mirror of
https://github.com/zoriya/react-native-web.git
synced 2025-12-06 06:36:13 +00:00
New documentation site and examples app
Replaces the old storybook with static HTML documentation and an interactive examples app. The documentation is now easier to customize, easier to maintain, and faster to load. The interactive examples are a dedicated Next.js app that can be loaded and edited in codesandbox, as well as embedded in the documentation where needed.
This commit is contained in:
@@ -2,4 +2,4 @@ coverage
|
||||
dist
|
||||
node_modules
|
||||
packages/**/vendor/*
|
||||
packages/examples
|
||||
packages/examples/.next
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
<PROJECT_ROOT>/.*/__tests__/.*
|
||||
<PROJECT_ROOT>/packages/.*/dist/.*
|
||||
<PROJECT_ROOT>/packages/docs/.*
|
||||
<PROJECT_ROOT>/packages/examples/.*
|
||||
.*/node_modules/@emotion/css/*
|
||||
.*/node_modules/babel-plugin-transform-react-remove-prop-types/*
|
||||
|
||||
|
||||
19
.github/CONTRIBUTING.md
vendored
19
.github/CONTRIBUTING.md
vendored
@@ -70,16 +70,23 @@ yarn compile
|
||||
yarn compile --watch
|
||||
```
|
||||
|
||||
## Documentation and visual tests
|
||||
## Documentation
|
||||
|
||||
To run the interactive storybook:
|
||||
To run the documentation website:
|
||||
|
||||
```
|
||||
yarn docs
|
||||
yarn docs:dev
|
||||
```
|
||||
|
||||
When you're also making changes to the 'react-native-web' source files, run this
|
||||
command in another process:
|
||||
## Examples
|
||||
|
||||
To run the examples app:
|
||||
|
||||
```
|
||||
yarn examples:dev
|
||||
```
|
||||
|
||||
When you're also making changes to the 'react-native-web' source files, run this command in another process:
|
||||
|
||||
```
|
||||
yarn compile --watch
|
||||
@@ -90,7 +97,7 @@ yarn compile --watch
|
||||
To run the benchmarks locally:
|
||||
|
||||
```
|
||||
yarn benchmarks
|
||||
yarn benchmarks:dev
|
||||
open ./packages/benchmarks/dist/index.html
|
||||
```
|
||||
|
||||
|
||||
4
.gitignore
vendored
4
.gitignore
vendored
@@ -1,3 +1,5 @@
|
||||
.next
|
||||
build
|
||||
coverage
|
||||
node_modules
|
||||
dist
|
||||
node_modules
|
||||
|
||||
171
README.md
171
README.md
@@ -2,77 +2,15 @@
|
||||
|
||||
[![npm version][package-badge]][package-url] [![Build Status][ci-badge]][ci-url] [](https://reactjs.org/docs/how-to-contribute.html#your-first-pull-request)
|
||||
|
||||
**Compatibility: React Native >= 0.63**.
|
||||
|
||||
"React Native for Web" makes it possible to run [React
|
||||
Native][react-native-url] components and APIs on the web using React DOM.
|
||||
|
||||
* **High-quality web interfaces**: makes it easy to
|
||||
create [fast](https://github.com/necolas/react-native-web/blob/master/packages/benchmarks/README.md),
|
||||
adaptive web UIs in JavaScript. It provides native-quality interactions, support
|
||||
for multiple input modes (touch, mouse, keyboard), optimized vendor-prefixed
|
||||
styles, built-in support for RTL layout, built-in accessibility, and integrates
|
||||
with React Dev Tools.
|
||||
|
||||
* **Write once, render anywhere**: interoperates with existing React DOM
|
||||
components and is compatible with the majority of the React Native API. You can
|
||||
develop new components for native and web without rewriting existing code.
|
||||
React Native for Web can also render to HTML and critical CSS on the server
|
||||
using Node.js.
|
||||
|
||||
Who is using React Native for Web in production?
|
||||
[Twitter](https://mobile.twitter.com),
|
||||
[Expo](https://docs.expo.io/workflow/web/),
|
||||
[Major League Soccer](https://matchcenter.mlssoccer.com),
|
||||
[Flipkart](https://twitter.com/naqvitalha/status/969577892991549440),
|
||||
[Uber](https://www.youtube.com/watch?v=RV9rxrNIxnY),
|
||||
[The Times](https://github.com/newsuk/times-components),
|
||||
[DataCamp](https://www.datacamp.com/community/tech/porting-practice-to-web-part1).
|
||||
|
||||
Browser support: Chrome, Firefox, Edge, Safari 7+, IE 10+.
|
||||
|
||||
Components and APIs deprecated in React Native are not supported by React Native for Web.
|
||||
|
||||
## Quick start
|
||||
|
||||
The easiest way to get started is to edit this
|
||||
[CodeSandbox](https://codesandbox.io/s/q4qymyp2l6) template. You don’t need to
|
||||
install anything to try it out.
|
||||
"React Native for Web" makes it possible to run [React Native][react-native-url] components and APIs on the web using React DOM.
|
||||
|
||||
## Documentation
|
||||
|
||||
The [documentation app](https://necolas.github.com/react-native-web/docs) covers
|
||||
installation, configuration, APIs, and guides.
|
||||
The [documentation site](https://necolas.github.com/react-native-web/) covers installation, guides, and APIs.
|
||||
|
||||
The [React Native documentation][react-native-url] contains more information
|
||||
about the [Gesture Responder
|
||||
system](https://facebook.github.io/react-native/docs/gesture-responder-system.html),
|
||||
[animations](https://facebook.github.io/react-native/docs/animations.html), and
|
||||
other design details.
|
||||
## Example
|
||||
|
||||
## Libraries and integrations
|
||||
|
||||
List of React Native packages with known web compatibility:
|
||||
|
||||
* [React Native Directory](https://reactnative.directory/?web=true)
|
||||
|
||||
Examples of using React Native for Web with other web tools:
|
||||
|
||||
* [Docz](https://github.com/doczjs/docz/tree/master/examples/react-native)
|
||||
* [Gatsby](https://github.com/slorber/gatsby-plugin-react-native-web)
|
||||
* [Next.js](https://github.com/zeit/next.js/tree/master/examples/with-react-native-web)
|
||||
(and [example recipes](https://gist.github.com/necolas/f9034091723f1b279be86c7429eb0c96))
|
||||
* [Phenomic](https://github.com/phenomic/phenomic/tree/master/examples/react-native-web-app)
|
||||
* [Razzle](https://github.com/jaredpalmer/razzle/tree/master/examples/with-react-native-web)
|
||||
* [Storybook](https://github.com/necolas/react-native-web/tree/master/packages/docs/)
|
||||
* [Styleguidist](https://github.com/styleguidist/react-styleguidist/tree/master/examples/react-native)
|
||||
|
||||
## Examples
|
||||
|
||||
And here is a simple example to get you started. The documentation includes
|
||||
interactive examples and the [source
|
||||
code](https://github.com/necolas/react-native-web/blob/master/packages/docs) is
|
||||
also available.
|
||||
And here is a simple example to get you started. The example app includes interactive examples and the [source code](https://github.com/necolas/react-native-web/blob/master/packages/docs) is also available.
|
||||
|
||||
```js
|
||||
import React from 'react';
|
||||
@@ -99,116 +37,31 @@ AppRegistry.runApplication('App', { rootTag: document.getElementById('react-root
|
||||
|
||||
This example will render the `App` into a container on the page.
|
||||
|
||||
You'll notice that there is no reference to `react-dom`; the `App` component is
|
||||
defined using the platform-agnostic APIs and Components introduced by React
|
||||
Native. This allows the app to be rendered to web and native platforms.
|
||||
|
||||
## Compatibility with React Native
|
||||
|
||||
React Native v0.60
|
||||
|
||||
### Components
|
||||
|
||||
| Name | Status | Notes |
|
||||
| :----------------------- | :----- | :---- |
|
||||
| ActivityIndicator | ✓ | |
|
||||
| Button | ✓ | |
|
||||
| CheckBox | ✓ | |
|
||||
| FlatList | ✓ | |
|
||||
| Image | ✓ | Missing multiple sources ([#515](https://github.com/necolas/react-native-web/issues/515)) and HTTP headers ([#1019](https://github.com/necolas/react-native-web/issues/1019)). |
|
||||
| ImageBackground | ✓ | |
|
||||
| KeyboardAvoidingView | (✓) | Mock. No equivalent web APIs. |
|
||||
| Modal | ✓ | |
|
||||
| Picker | ✓ | |
|
||||
| Pressable | ✓ | |
|
||||
| RefreshControl | ✘ | Not started ([#1027](https://github.com/necolas/react-native-web/issues/1027)). |
|
||||
| SafeAreaView | ✓ | |
|
||||
| ScrollView | ✓ | Missing momentum scroll events ([#1021](https://github.com/necolas/react-native-web/issues/1021)). |
|
||||
| SectionList | ✓ | |
|
||||
| StatusBar | (✓) | Mock. No equivalent web APIs. |
|
||||
| Switch | ✓ | |
|
||||
| Text | ✓ | Missing `onLongPress` ([#1011](https://github.com/necolas/react-native-web/issues/1011)) support. |
|
||||
| TextInput | ✓ | Missing rich text features ([#1023](https://github.com/necolas/react-native-web/issues/1023)), and auto-expanding behaviour ([#795](https://github.com/necolas/react-native-web/issues/795)). |
|
||||
| Touchable | ✓ | Includes additional support for mouse and keyboard interactions. |
|
||||
| TouchableHighlight | ✓ | |
|
||||
| TouchableNativeFeedback | ✘ | Not started ([#1024](https://github.com/necolas/react-native-web/issues/1024)). |
|
||||
| TouchableOpacity | ✓ | |
|
||||
| TouchableWithoutFeedback | ✓ | |
|
||||
| View | ✓ | |
|
||||
| VirtualizedList | ✓ | |
|
||||
| YellowBox | (✓) | Mock. No YellowBox functionality. |
|
||||
|
||||
### Modules
|
||||
|
||||
| Name | Status | Notes |
|
||||
| :----------------------- | :----- | :---- |
|
||||
| AccessibilityInfo | (✓) | Mock. No equivalent web APIs. |
|
||||
| Alert | ✘ | Not started ([#1026](https://github.com/necolas/react-native-web/issues/1026)). |
|
||||
| Animated | ✓ | Missing `useNativeDriver` support. |
|
||||
| Appearance | ✓ | |
|
||||
| AppRegistry | ✓ | Includes additional support for server rendering with `getApplication`. |
|
||||
| AppState | ✓ | |
|
||||
| BackHandler | (✓) | Mock. No equivalent web APIs. |
|
||||
| Clipboard | ✓ | |
|
||||
| DeviceInfo | (✓) | Limited information. |
|
||||
| Dimensions | ✓ | |
|
||||
| Easing | ✓ | |
|
||||
| Geolocation | ✓ | |
|
||||
| I18nManager | ✓ | Includes additional support for runtime switch to RTL. |
|
||||
| InteractionManager | (✓) | |
|
||||
| Keyboard | (✓) | Mock. |
|
||||
| LayoutAnimation | (✓) | Missing translation to web animations. |
|
||||
| Linking | ✓ | |
|
||||
| NativeEventEmitter | ✓ | |
|
||||
| NativeMethodsMixin | ✓ | |
|
||||
| NativeModules | (✓) | Mocked. Missing ability to load native modules. |
|
||||
| PanResponder | ✓ | |
|
||||
| PixelRatio | ✓ | |
|
||||
| Platform | ✓ | |
|
||||
| Settings | ✘ | No equivalent web APIs. |
|
||||
| Share | ✓ | Only available over HTTPS. Read about the [Web Share API](https://wicg.github.io/web-share/). |
|
||||
| StyleSheet | ✓ | |
|
||||
| UIManager | ✓ | |
|
||||
| Vibration | ✓ | |
|
||||
| useColorScheme | ✓ | |
|
||||
| useWindowDimensions | ✓ | |
|
||||
You'll notice that there is no reference to `react-dom`; the `App` component is defined using the platform-agnostic APIs and Components introduced by React Native. This allows the app to be rendered to web and native platforms.
|
||||
|
||||
## Contributing
|
||||
|
||||
The main purpose of this repository is to help evolve React web and native
|
||||
development towards the platform-agnostic design of React Native, and in the
|
||||
process make it faster and easier to build high-quality experiences for the web
|
||||
with React. Development happens in the open on GitHub, and we are grateful for
|
||||
contributing bugfixes and improvements. Read below to learn how you can take
|
||||
part in improving React Native for Web.
|
||||
The main purpose of this repository is to help evolve React web and native development towards the platform-agnostic design of React Native, and in the process make it faster and easier to build high-quality experiences for the web with React. Development happens in the open on GitHub, and we are grateful for contributing bugfixes and improvements. Read below to learn how you can take part in improving React Native for Web.
|
||||
|
||||
### Code of conduct
|
||||
|
||||
Facebook has adopted a [Code of Conduct][code-of-conduct] that this project
|
||||
expects all participants to adhere to. Please read the full text so that you
|
||||
can understand what actions will and will not be tolerated.
|
||||
Facebook has adopted a [Code of Conduct][code-of-conduct] that this project expects all participants to adhere to. Please read the full text so that you can understand what actions will and will not be tolerated.
|
||||
|
||||
### Contributing guide
|
||||
|
||||
Read the [contributing guide][contributing-url] to learn about the
|
||||
development process, how to propose bugfixes and improvements, and how to build
|
||||
and test your changes to React Native for Web.
|
||||
Read the [contributing guide][contributing-url] to learn about the development process, how to propose bugfixes and improvements, and how to build and test your changes to React Native for Web.
|
||||
|
||||
### Good first issues
|
||||
|
||||
To help you get you familiar with the contribution process, there is a list of
|
||||
[good first issues][good-first-issue-url] that contain bugs which have a
|
||||
relatively limited scope. This is a great place to get started.
|
||||
To help you get you familiar with the contribution process, there is a list of [good first issues][good-first-issue-url] that contain bugs which have a relatively limited scope. This is a great place to get started.
|
||||
|
||||
## License
|
||||
|
||||
React Native for Web is [MIT licensed](./LICENSE). By contributing to React
|
||||
Native for Web, you agree that your contributions will be licensed under its
|
||||
MIT license.
|
||||
React Native for Web is [MIT licensed](./LICENSE). By contributing to React Native for Web, you agree that your contributions will be licensed under its MIT license.
|
||||
|
||||
[package-badge]: https://img.shields.io/npm/v/react-native-web.svg?style=flat
|
||||
[package-url]: https://yarnpkg.com/en/package/react-native-web
|
||||
[ci-badge]: https://github.com/necolas/react-native-web/workflows/test/badge.svg
|
||||
[package-url]: https://www.npmjs.com/package/react-native-web
|
||||
[ci-badge]: https://github.com/necolas/react-native-web/workflows/tests/badge.svg
|
||||
[ci-url]: https://github.com/necolas/react-native-web/actions
|
||||
[react-native-url]: https://facebook.github.io/react-native/
|
||||
[contributing-url]: https://github.com/necolas/react-native-web/blob/master/.github/CONTRIBUTING.md
|
||||
|
||||
14
package.json
14
package.json
@@ -7,10 +7,14 @@
|
||||
"compile": "npm-run-all clean -p \"compile:* -- {@}\" --",
|
||||
"compile:commonjs": "cd packages/react-native-web && cross-env BABEL_ENV=commonjs babel --root-mode upward src --out-dir dist/cjs --ignore \"**/__tests__\"",
|
||||
"compile:es": "cd packages/react-native-web && babel --root-mode upward src --out-dir dist --ignore \"**/__tests__\"",
|
||||
"benchmarks": "cd packages/benchmarks && yarn build",
|
||||
"benchmarks:release": "cd packages/benchmarks && yarn release",
|
||||
"docs": "cd packages/docs && yarn start",
|
||||
"docs:release": "cd packages/docs && yarn release",
|
||||
"benchmarks": "cd packages/benchmarks && yarn dev",
|
||||
"benchmarks:build": "cd packages/benchmarks && yarn build",
|
||||
"benchmarks:release": "yarn benchmarks:build && git checkout gh-pages && rm -rf ./docs/benchmarks && mv packages/benchmarks/dist ./docs/benchmarks && git add -A && git commit -m \"Deploy benchmarks\" && git push origin gh-pages && git checkout -",
|
||||
"docs": "cd packages/docs && yarn dev",
|
||||
"docs:build": "cd packages/docs && yarn build",
|
||||
"docs:release": "yarn docs:build && git checkout gh-pages && rm -rf ./docs && mv packages/docs/dist ./docs && git add ./docs && git commit -m \"Deploy documentation\" && git push origin gh-pages && git checkout -",
|
||||
"examples": "cd packages/examples && yarn dev",
|
||||
"examples:build": "cd packages/examples && yarn build",
|
||||
"flow": "flow",
|
||||
"fmt": "prettier --write \"**/*.js\"",
|
||||
"fmt:report": "prettier --check \"**/*.js\"",
|
||||
@@ -20,7 +24,7 @@
|
||||
"precommit": "lint-staged",
|
||||
"prerelease": "yarn test && yarn compile && yarn compile:commonjs",
|
||||
"release": "node ./scripts/release/publish.js",
|
||||
"postrelease": "yarn benchmarks:release && yarn docs:release",
|
||||
"postrelease": "yarn docs:release && yarn benchmarks:release && ",
|
||||
"test": "yarn flow && yarn lint:report && yarn jest --runInBand"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# benchmarks
|
||||
# Benchmarks
|
||||
|
||||
Try the [benchmarks app](https://necolas.github.io/react-native-web/benchmarks) online.
|
||||
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
"name": "benchmarks",
|
||||
"version": "0.14.13",
|
||||
"scripts": {
|
||||
"build": "mkdir -p dist && cp -f index.html dist/index.html && ./node_modules/.bin/webpack-cli --config ./webpack.config.js",
|
||||
"release": "NODE_ENV=production yarn build && git checkout gh-pages && rm -rf ../../benchmarks && mv dist ../../benchmarks && git add -A && git commit -m \"Benchmarks deploy\" && git push origin gh-pages && git checkout -"
|
||||
"dev": "mkdir -p dist && cp -f index.html dist/index.html && ./node_modules/.bin/webpack-cli --config ./webpack.config.js",
|
||||
"build": "NODE_ENV=production yarn dev"
|
||||
},
|
||||
"dependencies": {
|
||||
"aphrodite": "^2.4.0",
|
||||
|
||||
191
packages/docs/.eleventy.js
Normal file
191
packages/docs/.eleventy.js
Normal file
@@ -0,0 +1,191 @@
|
||||
'use strict';
|
||||
|
||||
const csso = require('csso');
|
||||
const eleventyNavigationPlugin = require('@11ty/eleventy-navigation');
|
||||
const eleventySvgContentsPlugin = require('eleventy-plugin-svg-contents');
|
||||
const eleventySyntaxHighlightPlugin = require('@11ty/eleventy-plugin-syntaxhighlight');
|
||||
const htmlmin = require('html-minifier');
|
||||
const markdown = require('markdown-it');
|
||||
const markdownAnchor = require('markdown-it-anchor');
|
||||
const markdownAttrs = require('markdown-it-attrs');
|
||||
const markdownContainer = require('markdown-it-container');
|
||||
const markdownEmoji = require('markdown-it-emoji');
|
||||
const markdownFootnote = require('markdown-it-footnote');
|
||||
const markdownTasks = require('markdown-it-task-lists');
|
||||
const twemoji = require('twemoji');
|
||||
const UglifyJS = require('uglify-es');
|
||||
|
||||
/**
|
||||
* Markdown plugin
|
||||
* Add classes to markdown elements by default
|
||||
*/
|
||||
function markdownitTagToClass(md, mapping = {}) {
|
||||
const toArray = a => (Array.isArray(a) ? a : [a]);
|
||||
const splitWithSpace = s => (s ? s.split(' ') : []);
|
||||
|
||||
function parseTokens(tokens) {
|
||||
tokens.forEach(token => {
|
||||
if (/(_open$|hr|image)/.test(token.type) && mapping[token.tag]) {
|
||||
const orig = splitWithSpace(token.attrGet('class'));
|
||||
const addition = toArray(mapping[token.tag]);
|
||||
token.attrSet('class', [...orig, ...addition].join(' '));
|
||||
}
|
||||
if (token.children) {
|
||||
parseTokens(token.children);
|
||||
}
|
||||
});
|
||||
}
|
||||
md.core.ruler.push('markdownit-tag-to-class', state => parseTokens(state.tokens));
|
||||
}
|
||||
|
||||
module.exports = function(eleventyConfig) {
|
||||
// Merge data instead of overriding
|
||||
// https://www.11ty.dev/docs/data-deep-merge/
|
||||
eleventyConfig.setDataDeepMerge(true);
|
||||
|
||||
// PLUGINS -----
|
||||
|
||||
// Eleventy Navigation https://www.11ty.dev/docs/plugins/navigation/
|
||||
eleventyConfig.addPlugin(eleventyNavigationPlugin);
|
||||
// Inline SVG files https://www.npmjs.com/package/eleventy-plugin-svg-contents
|
||||
eleventyConfig.addPlugin(eleventySvgContentsPlugin);
|
||||
// Syntax Highlighting https://www.11ty.dev/docs/plugins/syntaxhighlight/
|
||||
eleventyConfig.addPlugin(eleventySyntaxHighlightPlugin);
|
||||
|
||||
// TRANSFORMS -----
|
||||
|
||||
// Minify HTML output
|
||||
eleventyConfig.addTransform('htmlmin', function(content, outputPath) {
|
||||
if (typeof outputPath === 'string' && outputPath.includes('.html')) {
|
||||
return htmlmin.minify(content, {
|
||||
useShortDoctype: true,
|
||||
removeComments: true,
|
||||
collapseWhitespace: true
|
||||
});
|
||||
}
|
||||
return content;
|
||||
});
|
||||
|
||||
// FILTERS -----
|
||||
|
||||
// Date formatting (human readable)
|
||||
eleventyConfig.addFilter('readableDate', dateObj => {
|
||||
const options = { month: 'long', day: 'numeric', year: 'numeric' };
|
||||
return new Intl.DateTimeFormat('en-US', options).format(dateObj);
|
||||
});
|
||||
// Date formatting (machine readable)
|
||||
eleventyConfig.addFilter('machineDate', dateObj => {
|
||||
return dateObj.toISOString();
|
||||
});
|
||||
// Minify CSS
|
||||
eleventyConfig.addFilter('cssmin', function(code) {
|
||||
return csso.minify(code).css;
|
||||
});
|
||||
// Minify JS
|
||||
eleventyConfig.addFilter('jsmin', function(code) {
|
||||
const minified = UglifyJS.minify(code);
|
||||
if (minified.error) {
|
||||
console.log('UglifyJS error: ', minified.error);
|
||||
return code;
|
||||
}
|
||||
return minified.code;
|
||||
});
|
||||
|
||||
// SHORTCODES -----
|
||||
|
||||
eleventyConfig.addShortcode('version', function() {
|
||||
return String(Date.now());
|
||||
});
|
||||
|
||||
// PASSTHROUGH -----
|
||||
|
||||
eleventyConfig.addPassthroughCopy('src/static');
|
||||
|
||||
// COLLECTIONS -----
|
||||
|
||||
// Collection of items for navigation
|
||||
eleventyConfig.addCollection('nav', function(collection) {
|
||||
return collection
|
||||
.getAll()
|
||||
.filter(function(item) {
|
||||
return 'eleventyNavigation' in item.data;
|
||||
})
|
||||
.sort((a, b) => {
|
||||
const keyA = a.data.eleventyNavigation.key;
|
||||
const keyB = b.data.eleventyNavigation.key;
|
||||
if (keyA > keyB) {
|
||||
return 1;
|
||||
} else if (keyA < keyB) {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
});
|
||||
});
|
||||
|
||||
// MARKDOWN -----
|
||||
|
||||
const options = {
|
||||
html: true,
|
||||
breaks: true,
|
||||
linkify: true,
|
||||
typographer: true
|
||||
};
|
||||
|
||||
const markdownLib = markdown(options);
|
||||
|
||||
markdownLib
|
||||
// Customize markdown HTML
|
||||
// .use(markdownitTagToClass, {})
|
||||
// Automatically place anchors next to headings
|
||||
// https://github.com/valeriangalliat/markdown-it-anchor
|
||||
.use(markdownAnchor, {
|
||||
level: [2, 3],
|
||||
permalink: true,
|
||||
// permalinkClass: "direct-link",
|
||||
permalinkSymbol: '#'
|
||||
})
|
||||
// Syntax for adding attributes {.class decode=async}
|
||||
// https://github.com/arve0/markdown-it-attrs
|
||||
.use(markdownAttrs, {
|
||||
allowedAttributes: ['class', 'decode', 'height', 'lazy', 'width']
|
||||
})
|
||||
// Custom containers (::: name)
|
||||
// https://github.com/markdown-it/markdown-it-container
|
||||
.use(markdownContainer, 'callout')
|
||||
.use(markdownContainer, 'lead')
|
||||
.use(markdownContainer, 'warning')
|
||||
// Emoji replacement
|
||||
// https://github.com/markdown-it/markdown-it-emoji
|
||||
.use(markdownEmoji)
|
||||
// Add footnotes
|
||||
// https://github.com/markdown-it/markdown-it-footnote
|
||||
.use(markdownFootnote)
|
||||
// Render a task list
|
||||
// https://github.com/revin/markdown-it-task-lists
|
||||
.use(markdownTasks);
|
||||
|
||||
// Custom emoji renderer
|
||||
markdownLib.renderer.rules.emoji = function(token, idx) {
|
||||
return twemoji.parse(token[idx].content);
|
||||
};
|
||||
|
||||
eleventyConfig.setLibrary('md', markdownLib);
|
||||
|
||||
// ELEVENTY CONFIG -----
|
||||
|
||||
return {
|
||||
templateFormats: ['md', 'njk', 'html'],
|
||||
markdownTemplateEngine: 'njk',
|
||||
htmlTemplateEngine: 'njk',
|
||||
dataTemplateEngine: 'njk',
|
||||
passthroughFileCopy: true,
|
||||
dir: {
|
||||
input: './src',
|
||||
includes: 'includes',
|
||||
data: 'data',
|
||||
output: 'dist'
|
||||
},
|
||||
// Matches the GitHub Pages subdirectory of the site (necolas.github.io/react-native-web)
|
||||
pathPrefix: '/react-native-web/'
|
||||
};
|
||||
};
|
||||
3
packages/docs/README.md
Normal file
3
packages/docs/README.md
Normal file
@@ -0,0 +1,3 @@
|
||||
# Documentation website
|
||||
|
||||
Markdown pages and a static site generator.
|
||||
31
packages/docs/package.json
Normal file
31
packages/docs/package.json
Normal file
@@ -0,0 +1,31 @@
|
||||
{
|
||||
"private": true,
|
||||
"name": "docs",
|
||||
"version": "0.14.13",
|
||||
"description": "Documentation website for React Native for Web",
|
||||
"scripts": {
|
||||
"dev": "eleventy --serve",
|
||||
"build": "ELEVENTY_PRODUCTION=true eleventy",
|
||||
"debug": "DEBUG=* eleventy"
|
||||
},
|
||||
"homepage": "https://github.com/necolas/react-native-web",
|
||||
"devDependencies": {
|
||||
"@11ty/eleventy": "^0.11.1",
|
||||
"@11ty/eleventy-navigation": "^0.1.6",
|
||||
"@11ty/eleventy-plugin-syntaxhighlight": "^3.0.5",
|
||||
"csso": "^4.2.0",
|
||||
"eleventy-plugin-svg-contents": "^0.7.0",
|
||||
"eleventy-plugin-toc": "^1.1.0",
|
||||
"html-minifier": "^4.0.0",
|
||||
"markdown-it": "^12.0.4",
|
||||
"markdown-it-anchor": "^7.0.0",
|
||||
"markdown-it-attrs": "^4.0.0",
|
||||
"markdown-it-container": "^3.0.0",
|
||||
"markdown-it-emoji": "^2.0.0",
|
||||
"markdown-it-footnote": "^3.0.2",
|
||||
"markdown-it-for-inline": "^0.1.1",
|
||||
"markdown-it-task-lists": "^2.1.1",
|
||||
"twemoji": "*",
|
||||
"uglify-es": "^3.3.9"
|
||||
}
|
||||
}
|
||||
16
packages/docs/src/data/site.js
Normal file
16
packages/docs/src/data/site.js
Normal file
@@ -0,0 +1,16 @@
|
||||
const packageJson = require('../../package.json');
|
||||
|
||||
module.exports = {
|
||||
name: 'React Native for Web',
|
||||
description: '',
|
||||
footer: 'Copyright © Nicolas Gallagher and Facebook Inc.',
|
||||
url: 'https://necolas.github.io/react-native-web',
|
||||
githubUrl: 'https://github.com/necolas/react-native-web',
|
||||
githubBranch: 'master',
|
||||
packageName: 'react-native-web',
|
||||
packageUrl: 'https://www.npmjs.com/package/react-native-web',
|
||||
packageVersion: packageJson.version,
|
||||
|
||||
enableEditButton: true,
|
||||
enableGithubLink: true
|
||||
};
|
||||
530
packages/docs/src/includes/assets/inline.css
Normal file
530
packages/docs/src/includes/assets/inline.css
Normal file
@@ -0,0 +1,530 @@
|
||||
/**
|
||||
* Variables
|
||||
* --------------------------------------------------------
|
||||
*/
|
||||
|
||||
:root {
|
||||
--docs-spacing-1: 0.25rem;
|
||||
--docs-spacing-2: 0.5rem;
|
||||
--docs-spacing-3: 0.75rem;
|
||||
--docs-spacing-4: 1rem;
|
||||
--docs-spacing-5: 1.25rem;
|
||||
--docs-spacing-6: 1.5rem;
|
||||
--docs-spacing-8: 2rem;
|
||||
--docs-spacing-10: 2.5rem;
|
||||
--docs-spacing-12: 3rem;
|
||||
--docs-spacing-16: 4rem;
|
||||
--docs-spacing-20: 5rem;
|
||||
--docs-spacing-40: 10rem;
|
||||
--docs-spacing-60: 15rem;
|
||||
--docs-spacing-64: 16rem;
|
||||
--docs-spacing-72: 18rem;
|
||||
--docs-spacing-80: 20rem;
|
||||
|
||||
--docs-font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Helvetica, Arial, sans-serif;
|
||||
--docs-font-size: 14px;
|
||||
--docs-heading-size: 2em;
|
||||
--docs-line-height: 1.5;
|
||||
|
||||
--docs-ring-inset: var(--tw-empty,/*!*/ /*!*/);
|
||||
--docs-ring-offset-width: 0px;
|
||||
}
|
||||
|
||||
/* Widescreen */
|
||||
|
||||
@media (min-width: 1088px) {
|
||||
:root {
|
||||
--docs-font-size: 16px;
|
||||
--docs-heading-size: 2.25em;
|
||||
}
|
||||
}
|
||||
|
||||
/* Light theme */
|
||||
|
||||
@media all {
|
||||
:root {
|
||||
--docs-bg-color: #fff;
|
||||
--docs-border-color: #e5e5e5;
|
||||
--docs-border-color-faint: #e5e5e5;
|
||||
--docs-text-color: #333;
|
||||
--docs-text-color-faint: #6b7280;
|
||||
--docs-heading-color: #111;
|
||||
--docs-link-color: #1977f2;
|
||||
--docs-code-color: #111;
|
||||
--docs-callout-bg-color: #fff3cd;
|
||||
--docs-callout-border-color: #ffd402;
|
||||
--docs-theme-color: #1977f2;
|
||||
--docs-theme-color-faint: #1977f250;
|
||||
--docs-theme-color-faded: #1977f20f;
|
||||
|
||||
--docs-ring-color: rgba(59, 130, 246, 0.5);
|
||||
--docs-ring-offset-color: #fff;
|
||||
--docs-ring-offset-shadow: 0 0 #0000;
|
||||
--docs-ring-shadow: 0 0 #0000;
|
||||
|
||||
--docs-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
|
||||
}
|
||||
}
|
||||
|
||||
/* Dark theme */
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
:root {
|
||||
--docs-bg-color: #15202b;
|
||||
--docs-border-color: #26395a;
|
||||
--docs-border-color-faint: #26395a;
|
||||
--docs-text-color: #eee;
|
||||
--docs-text-color-faint: #aaa;
|
||||
--docs-heading-color: #fff;
|
||||
--docs-link-color: #60a6ff;
|
||||
--docs-code-color: #fff;
|
||||
--docs-callout-bg-color: #231f00;
|
||||
|
||||
--docs-ring-color: rgba(59, 130, 246, 0.5);
|
||||
--docs-ring-offset-color: #fff;
|
||||
--docs-ring-offset-shadow: 0 0 #0000;
|
||||
--docs-ring-shadow: 0 0 #0000;
|
||||
|
||||
--docs-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset
|
||||
* --------------------------------------------------------
|
||||
*/
|
||||
|
||||
html { font: var(--docs-font-size)/var(--docs-line-height) var(--docs-font-family); }
|
||||
body { background-color: var(--docs-bg-color, transparent); color: var(--docs-text-color, #333); margin: 0; }
|
||||
button, input { overflow: visible; }
|
||||
button, select { text-transform: none; }
|
||||
code, pre { font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; }
|
||||
hr { box-sizing: content-box; height: 0; overflow: visible; }
|
||||
img { border-style: none; }
|
||||
img, video, svg, iframe { display: block; }
|
||||
img, video { max-width: 100%; height: auto; }
|
||||
svg:not(:root){ overflow: hidden; }
|
||||
table { border-collapse: collapse; }
|
||||
:not(:focus-visible) { outline-width: 0; }
|
||||
a { color: var(--docs-link-color); text-decoration: underline; }
|
||||
h1, h2, h3, h4, h5, h6 { color: var(--docs-heading-color); }
|
||||
|
||||
/**
|
||||
* Core components
|
||||
* --------------------------------------------------------
|
||||
*/
|
||||
|
||||
.text {
|
||||
background-color: transparent;
|
||||
border: 0 solid black;
|
||||
box-sizing: border-box;
|
||||
color: var(--docs-text-color);
|
||||
display: inline;
|
||||
font-family: var(--docs-font-family);
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
text-decoration: none;
|
||||
white-space: pre-wrap;
|
||||
word-wrap: break-word;
|
||||
}
|
||||
|
||||
.view {
|
||||
align-items: stretch;
|
||||
background-color: transparent;
|
||||
border: 0 solid black;
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
flex-basis: auto;
|
||||
flex-direction: column;
|
||||
flex-shrink: 0;
|
||||
margin: 0;
|
||||
min-height: 0;
|
||||
min-width: 0;
|
||||
padding: 0;
|
||||
position: relative;
|
||||
text-decoration: none;
|
||||
z-index: 0;
|
||||
}
|
||||
|
||||
.emoji {
|
||||
height: 1.2em;
|
||||
margin: 0 0.075em !important;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
/**
|
||||
* Website components
|
||||
* --------------------------------------------------------
|
||||
*/
|
||||
|
||||
.container {
|
||||
max-width: 760px;
|
||||
}
|
||||
|
||||
.navigation {
|
||||
left: auto;
|
||||
right: 100%;
|
||||
}
|
||||
|
||||
.before-middot::before {
|
||||
display: inline-block;
|
||||
content: "";
|
||||
width: 3px;
|
||||
height: 3px;
|
||||
background-color: currentColor;
|
||||
border-radius: 9999px;
|
||||
margin: 0 7px 0 -10px;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.prop {
|
||||
margin-top: var(--docs-spacing-5);
|
||||
margin-bottom: var(--docs-spacing-5);
|
||||
}
|
||||
|
||||
.prop p {
|
||||
margin: 0 !important;
|
||||
}
|
||||
|
||||
.callout {
|
||||
background-color: var(--docs-callout-bg-color);
|
||||
border-bottom-right-radius: 0.5rem;
|
||||
border-top-right-radius: 0.5rem;
|
||||
border-left: 3px solid var(--docs-callout-border-color);
|
||||
margin: var(--docs-spacing-12) 0 var(--docs-spacing-4);
|
||||
padding: var(--docs-spacing-2) var(--docs-spacing-8);
|
||||
}
|
||||
|
||||
/**
|
||||
* Markdown content
|
||||
* --------------------------------------------------------
|
||||
*/
|
||||
|
||||
.markdown {
|
||||
line-height: 1.75;
|
||||
font-size: 1.125rem;
|
||||
word-wrap: break-word;
|
||||
}
|
||||
|
||||
.markdown a {
|
||||
color: var(--docs-link-color);
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.markdown h1 {
|
||||
font-weight: 800;
|
||||
font-size: var(--docs-heading-size);
|
||||
margin: 0 0 var(--docs-spacing-8);
|
||||
line-height: 1.1;
|
||||
}
|
||||
|
||||
.markdown h2 {
|
||||
font-weight: 700;
|
||||
font-size: 1.5em;
|
||||
margin: var(--docs-spacing-12) 0 var(--docs-spacing-6);
|
||||
line-height: 1.3;
|
||||
}
|
||||
|
||||
.markdown h2 + * {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.markdown h3 {
|
||||
font-weight: 600;
|
||||
font-size: 1.25em;
|
||||
margin: var(--docs-spacing-8) 0 var(--docs-spacing-3);
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.markdown h2,
|
||||
.markdown h3,
|
||||
.markdown h4 {
|
||||
scroll-margin-top: 1em;
|
||||
}
|
||||
|
||||
.markdown h1:hover .header-anchor,
|
||||
.markdown h2:hover .header-anchor,
|
||||
.markdown h3:hover .header-anchor {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.markdown .header-anchor {
|
||||
opacity: 0;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.markdown .lead {
|
||||
font-size: 1.25em;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.markdown hr {
|
||||
box-sizing: content-box;
|
||||
height: 0;
|
||||
overflow: visible;
|
||||
border: 0;
|
||||
border-top: 1px solid var(--docs-border-color-faint);
|
||||
margin: var(--docs-spacing-12) 0;
|
||||
}
|
||||
|
||||
.markdown hr + * {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.markdown table {
|
||||
border-collapse: collapse;
|
||||
text-indent: 0;
|
||||
border-color: inherit;
|
||||
width: 100%;
|
||||
table-layout: auto;
|
||||
text-align: left;
|
||||
margin-top: 2em;
|
||||
margin-bottom: 2em;
|
||||
font-size: 0.875em;
|
||||
line-height: 1.7;
|
||||
}
|
||||
|
||||
.markdown thead {
|
||||
font-weight: 600;
|
||||
border-bottom: 1px solid var(--docs-border-color);
|
||||
}
|
||||
|
||||
.markdown thead th {
|
||||
vertical-align: bottom;
|
||||
padding: 0 0.5em 0.5em;
|
||||
}
|
||||
|
||||
.markdown thead th:first-child {
|
||||
padding-left: 0;
|
||||
}
|
||||
|
||||
.markdown tbody tr {
|
||||
border-bottom: 1px solid var(--docs-border-color-faint);
|
||||
}
|
||||
|
||||
.markdown tbody td {
|
||||
vertical-align: top;
|
||||
padding: 0.5em;
|
||||
}
|
||||
|
||||
.markdown tbody td:first-child {
|
||||
padding-left: 0;
|
||||
}
|
||||
|
||||
.markdown code {
|
||||
color: var(--docs-code-color);
|
||||
font-weight: 600;
|
||||
font-size: 0.875em;
|
||||
}
|
||||
|
||||
.markdown p {
|
||||
margin: 1.25em 0;
|
||||
}
|
||||
|
||||
.markdown ol,
|
||||
.markdown ul {
|
||||
margin: 1.25em 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.markdown ol {
|
||||
margin-left: 1em;
|
||||
}
|
||||
|
||||
.markdown ul {
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
.markdown li {
|
||||
margin: 0.5em 0;
|
||||
}
|
||||
|
||||
.markdown ul > li {
|
||||
position: relative;
|
||||
padding-left: 1.75em;
|
||||
}
|
||||
|
||||
.markdown ul > li::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
background-color: currentColor;
|
||||
border-radius: 50%;
|
||||
width: 0.375em;
|
||||
height: 0.375em;
|
||||
top: calc(0.875em - 0.1875em);
|
||||
left: 0.25em;
|
||||
}
|
||||
|
||||
.markdown pre {
|
||||
max-width: 100%;
|
||||
color: black;
|
||||
tab-size: 2;
|
||||
overflow-x: auto;
|
||||
font-size: 1em;
|
||||
line-height: 1.7;
|
||||
margin: 1.5em 0;
|
||||
border-radius: 0.375rem;
|
||||
padding: 0.85em 1.15em;
|
||||
}
|
||||
|
||||
.markdown blockquote {
|
||||
font-weight: 500;
|
||||
font-style: italic;
|
||||
border-left-width: 0.25rem;
|
||||
border-left-color: #e5e7eb;
|
||||
quotes: "\201C""\201D""\2018""\2019";
|
||||
margin-top: 1.6em;
|
||||
margin-bottom: 1.6em;
|
||||
padding-left: 1em;
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility CSS
|
||||
* --------------------------------------------------------
|
||||
*/
|
||||
|
||||
.appearance-none { -webkit-appearance: none; -moz-appearance: none; appearance: none; }
|
||||
|
||||
.border { border-width: 1px; border-style: solid; }
|
||||
.border-none { border: none; }
|
||||
.border-top { border-top-width: 1px; border-top-style: solid; }
|
||||
.border-right { border-right-width: 1px; border-right-style: solid; }
|
||||
.border-left { border-left-width: 1px; border-left-style: solid; }
|
||||
.border-bottom { border-bottom-width: 1px; border-bottom-style: solid; }
|
||||
.border-left-3 { border-width: 3px; }
|
||||
|
||||
.block { display: block; }
|
||||
.hidden { display: none; }
|
||||
.inline { display: inline; }
|
||||
.inline-block { display: inline-block; }
|
||||
.inline-flex { display: inline-flex; }
|
||||
.flex { display: flex; }
|
||||
|
||||
.rounded { border-radius: var(--docs-spacing-1, 0.25rem); }
|
||||
.rounded-full { border-radius: 9999px; }
|
||||
|
||||
.cursor-pointer { cursor: pointer; }
|
||||
|
||||
.flex-row { flex-direction: row; }
|
||||
.flex-1 { flex: 1; }
|
||||
.flex-shrink { flex-shrink: 1; }
|
||||
.flex-wrap { flex-wrap: wrap; }
|
||||
.flex-nowrap { flex-wrap: nowrap; }
|
||||
.items-center { align-items: center; }
|
||||
.justify-center { justify-content: center; }
|
||||
|
||||
.font-bold { font-weight: bold; }
|
||||
.font-normal { font-weight: normal; }
|
||||
.font-mono { font-family: monospace, monospace; font-size: 1em; }
|
||||
.font-semibold { font-weight: 600; }
|
||||
|
||||
.h-12 { height: var(--docs-spacing-12); }
|
||||
.h-full { height: 100%; }
|
||||
.h-screen { height: 100vh; }
|
||||
|
||||
.list-none { list-style: none; }
|
||||
|
||||
.m-0 { margin: 0; }
|
||||
.mx-auto { margin-left: auto; margin-right: auto; }
|
||||
.my-2 { margin-top: var(--docs-spacing-2); margin-bottom: var(--docs-spacing-2); }
|
||||
.my-8 { margin-top: var(--docs-spacing-8); margin-bottom: var(--docs-spacing-8); }
|
||||
.ml-2 { margin-left: var(--docs-spacing-2); }
|
||||
.mt-2 { margin-top: var(--docs-spacing-2); }
|
||||
.mt-4 { margin-top: var(--docs-spacing-4); }
|
||||
.mt-6 { margin-top: var(--docs-spacing-6); }
|
||||
.mt-12 { margin-top: var(--docs-spacing-12); }
|
||||
.mr-2 { margin-right: var(--docs-spacing-2); }
|
||||
.mr-4 { margin-right: var(--docs-spacing-4); }
|
||||
.mb-2 { margin-bottom: var(--docs-spacing-2); }
|
||||
.mb-4 { margin-bottom: var(--docs-spacing-4); }
|
||||
.mb-8 { margin-bottom: var(--docs-spacing-8); }
|
||||
|
||||
.opacity-0 { opacity: 0; }
|
||||
.opacity-50 { opacity: 0.5; }
|
||||
.overflow-hidden { overflow: hidden; }
|
||||
.overflow-x-hidden { overflow-x: hidden; }
|
||||
.overflow-y-auto { overflow-y: auto; }
|
||||
|
||||
.p-6 { padding: var(--docs-spacing-6); }
|
||||
.px-1 { padding-left: var(--docs-spacing-1); padding-right: var(--docs-spacing-1); }
|
||||
.px-3 { padding-left: var(--docs-spacing-3); padding-right: var(--docs-spacing-3); }
|
||||
.px-4 { padding-left: var(--docs-spacing-4); padding-right: var(--docs-spacing-4); }
|
||||
.px-6 { padding-left: var(--docs-spacing-6); padding-right: var(--docs-spacing-6); }
|
||||
.py-1 { padding-top: var(--docs-spacing-1); padding-bottom: var(--docs-spacing-1); }
|
||||
.py-2 { padding-top: var(--docs-spacing-2); padding-bottom: var(--docs-spacing-2); }
|
||||
.py-3 { padding-top: var(--docs-spacing-3); padding-bottom: var(--docs-spacing-3); }
|
||||
.py-4 { padding-top: var(--docs-spacing-4); padding-bottom: var(--docs-spacing-4); }
|
||||
.pl-5 { padding-left: var(--docs-spacing-5); }
|
||||
.pt-1 { padding-top: var(--docs-spacing-1); }
|
||||
.pt-8 { padding-top: var(--docs-spacing-8); }
|
||||
.pt-12 { padding-top: var(--docs-spacing-12); }
|
||||
.pb-1 { padding-bottom: var(--docs-spacing-1); }
|
||||
|
||||
.absolute { position: absolute; }
|
||||
.relative { position: relative; }
|
||||
.sticky { position: sticky; }
|
||||
.fixed { position: fixed; }
|
||||
|
||||
.overflow-ellipsis { overflow: hidden; text-overflow: ellipsis; }
|
||||
|
||||
.text-uppercase { text-transform: uppercase; }
|
||||
.text-sm { font-size: 0.875rem; line-height: 1.25; }
|
||||
.text-xl { font-size: 1.25rem; line-height: 1.25; }
|
||||
.text-2xl { font-size: 2rem; line-height: 1.25; }
|
||||
.text-3xl { font-size: 3rem; line-height: 1.25; }
|
||||
|
||||
.w-auto { width: auto; }
|
||||
.w-40 { width: var(--docs-spacing-40); }
|
||||
.w-72 { width: var(--docs-spacing-72); }
|
||||
.w-full { width: 100%; }
|
||||
|
||||
.whitespace-nowrap { white-space: nowrap; }
|
||||
|
||||
.z-10 { z-index: 10; }
|
||||
.z-20 { z-index: 20; }
|
||||
|
||||
.fill-current { fill: currentColor; }
|
||||
.inset-y-0 { top: 0px; bottom: 0px; }
|
||||
.no-underline { text-decoration: none; }
|
||||
.ring-opacity-50 { --docs-ring-opacity: 0.5; }
|
||||
|
||||
/* Colors */
|
||||
|
||||
.bg-theme { background-color: var(--docs-bg-color); }
|
||||
.border-color-faint { border-color: var(--docs-border-color-faint); }
|
||||
.border-theme-faint { border-color: var(--docs-theme-color-faint); }
|
||||
.text-color { color: var(--docs-text-color); }
|
||||
.text-color-faint { color: var(--docs-text-color-faint); }
|
||||
.text-white { --docs-text-opacity: 1; color: rgba(255, 255, 255, var(--docs-text-opacity)); }
|
||||
|
||||
/* Interactions */
|
||||
|
||||
.hover\:opacity-100:hover { opacity: 1; }
|
||||
.hover\:text-color-inherit:hover { color: inherit; }
|
||||
|
||||
/**
|
||||
* Widescreen breakpoint
|
||||
* --------------------------------------------------------
|
||||
*/
|
||||
|
||||
@media (min-width: 1088px) {
|
||||
.container { max-width: 1400px; }
|
||||
.navigation { right: auto; }
|
||||
|
||||
.wide\:block { display: block; }
|
||||
.wide\:flex { display: flex; }
|
||||
.wide\:hidden { display: none; }
|
||||
|
||||
.wide\:flex-row { flex-direction: row; }
|
||||
|
||||
.wide\:sticky { position: sticky; }
|
||||
.wide\:opacity-0 { opacity: 0; }
|
||||
.wide\:opacity-1 { opacity: 1; }
|
||||
|
||||
.wide\:left-0 { left: 0; }
|
||||
.wide\:right-0 { right: 0; }
|
||||
.wide\:top-16 { top: var(--docs-spacing-16); }
|
||||
|
||||
.wide\:px-20 {padding-left: var(--docs-spacing-20); padding-right: var(--docs-spacing-20);}
|
||||
.wide\:px-40 {padding-left: var(--docs-spacing-40); padding-right: var(--docs-spacing-40);}
|
||||
}
|
||||
67
packages/docs/src/includes/assets/inline.js
Normal file
67
packages/docs/src/includes/assets/inline.js
Normal file
@@ -0,0 +1,67 @@
|
||||
/**
|
||||
* Navigation display
|
||||
*/
|
||||
function setupNavigationDrawer() {
|
||||
const navigation = document.getElementById('navigation');
|
||||
const closebtn = document.getElementById('close-nav');
|
||||
const showbtn = document.getElementById('show-nav');
|
||||
let navopen = false;
|
||||
|
||||
if (closebtn == null || showbtn == null || navigation == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// SHOW
|
||||
function showNavigation() {
|
||||
navigation.classList.remove('opacity-0');
|
||||
navigation.style.right = 'auto';
|
||||
showbtn.classList.add('hidden');
|
||||
closebtn.classList.remove('hidden');
|
||||
navopen = true;
|
||||
}
|
||||
showbtn.addEventListener('click', showNavigation);
|
||||
// CLOSE
|
||||
function closeNavigation() {
|
||||
navigation.classList.add('opacity-0');
|
||||
closebtn.classList.add('hidden');
|
||||
navigation.style.right = null;
|
||||
showbtn.classList.remove('hidden');
|
||||
navopen = false;
|
||||
}
|
||||
document.addEventListener('click', e => {
|
||||
if (navopen && !navigation.contains(e.target) && !showbtn.contains(e.target)) {
|
||||
closeNavigation();
|
||||
}
|
||||
});
|
||||
document.addEventListener('keydown', e => {
|
||||
if (navopen && e.key === 'Escape') {
|
||||
closeNavigation();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Preserve nav scroll position across page loads
|
||||
*/
|
||||
function setupNavigationScroll() {
|
||||
const scroller = document.getElementById('navigation-scroller');
|
||||
const navScrollPositionKey = 'navScrollPosition';
|
||||
|
||||
if (scroller == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
window.addEventListener('unload', function() {
|
||||
const navScrollPosition = scroller.scrollTop;
|
||||
localStorage.setItem(navScrollPositionKey, navScrollPosition);
|
||||
});
|
||||
const previousScrollPosition = localStorage.getItem(navScrollPositionKey);
|
||||
if (previousScrollPosition != null) {
|
||||
scroller.scrollTop = previousScrollPosition;
|
||||
}
|
||||
}
|
||||
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
setupNavigationDrawer();
|
||||
setupNavigationScroll();
|
||||
});
|
||||
1
packages/docs/src/includes/assets/svg/404.svg
Normal file
1
packages/docs/src/includes/assets/svg/404.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1120 778"><circle cx="212.592" cy="103" r="64" fill="#ff6584"/><path d="M523.976 343.122c0 151.011-89.774 203.739-200.515 203.739s-200.516-52.728-200.516-203.74S323.461 0 323.461 0s200.515 192.11 200.515 343.122z" fill="#f2f2f2"/><path fill="#3f3d56" d="M316.156 523.761l2.054-126.383 85.464-156.354-85.142 136.528.923-56.827 58.902-113.12-58.658 98.082 1.66-102.206 63.074-90.058-62.812 73.986L322.658 0l-6.52 248.096.536-10.235-64.127-98.157 63.099 117.804-5.975 114.146-.178-3.029-73.928-103.296 73.704 113.999-.747 14.275-.134.215.061 1.172-15.159 289.599h20.254l2.43-149.584 73.522-113.72-73.34 102.476z"/><path d="M1120.592 404.972c0 123.61-73.484 166.77-164.131 166.77s-164.132-43.16-164.132-166.77S956.461 124.11 956.461 124.11s164.131 157.252 164.131 280.862z" fill="#f2f2f2"/><path fill="#3f3d56" d="M950.482 552.833l1.68-103.45 69.957-127.983-69.693 111.754.756-46.515 48.214-92.595-48.014 80.285 1.359-83.66 51.628-73.717-51.415 60.562.85-153.404-5.337 203.078.439-8.377-52.492-80.347 51.65 96.429-4.891 93.434-.146-2.48-60.513-84.553 60.33 93.314-.612 11.685-.109.176.05.959-12.409 237.05h16.579l1.989-122.441 60.182-93.085-60.032 83.881z"/><ellipse cx="554.592" cy="680.479" rx="554.592" ry="28.034" fill="#3f3d56"/><ellipse cx="892.445" cy="726.797" rx="94.989" ry="4.802" fill="#3f3d56"/><ellipse cx="548.72" cy="773.114" rx="94.989" ry="4.802" fill="#3f3d56"/><ellipse cx="287.944" cy="734.279" rx="217.014" ry="10.97" fill="#3f3d56"/><circle cx="97.084" cy="566.27" r="79" fill="#2f2e41"/><path fill="#2f2e41" d="M60.355 627.841l23.999.283-.507 42.997-23.998-.283zM108.352 628.407l23.999.283-.507 42.997-23.998-.283z"/><ellipse cx="119.546" cy="732.616" rx="7.5" ry="20" transform="rotate(-89.325 68.811 722.182)" fill="#2f2e41"/><ellipse cx="167.554" cy="732.182" rx="7.5" ry="20" transform="rotate(-89.325 116.82 721.748)" fill="#2f2e41"/><circle cx="99.319" cy="546.295" r="27" fill="#fff"/><circle cx="99.319" cy="546.295" r="9" fill="#3f3d56"/><path d="M21.322 491.904c-6.042-28.64 14.688-57.265 46.3-63.933s62.139 11.143 68.18 39.783-14.978 38.93-46.59 45.6-61.848 7.191-67.89-21.45z" fill="#1977f2"/><path d="M217.592 610.342c0 55.076-32.74 74.306-73.13 74.306q-1.403 0-2.802-.03c-1.872-.041-3.725-.13-5.556-.255-36.452-2.58-64.772-22.8-64.772-74.021 0-53.008 67.739-119.896 72.827-124.846l.01-.01.293-.284s73.13 70.064 73.13 125.14z" fill="#1977f2"/><path d="M141.798 676.223l26.747-37.374-26.814 41.477-.071 4.291c-1.872-.04-3.725-.13-5.556-.254l2.882-55.102-.022-.428.049-.08.272-5.205-26.88-41.58 26.964 37.677.063 1.105 2.179-41.633-23.014-42.965 23.294 35.658 2.268-86.314.01-.294v.285l-.38 68.064 22.911-26.983-23.004 32.846-.606 37.276 21.391-35.774-21.48 41.259-.339 20.723 31.056-49.792-31.172 57.023z" fill="#3f3d56"/><circle cx="712.485" cy="565.415" r="79" fill="#2f2e41"/><path fill="#2f2e41" d="M696.287 635.256l22.94-7.05 12.633 41.102-22.941 7.05zM742.168 621.16l22.94-7.05 12.632 41.102-22.94 7.05z"/><ellipse cx="767.887" cy="732.003" rx="20" ry="7.5" transform="rotate(-17.083 544.826 833.656)" fill="#2f2e41"/><ellipse cx="813.475" cy="716.946" rx="20" ry="7.5" transform="rotate(-17.083 590.415 818.599)" fill="#2f2e41"/><circle cx="708.522" cy="545.71" r="27" fill="#fff"/><circle cx="708.522" cy="545.71" r="9" fill="#3f3d56"/><path d="M617.651 517.701c-14.49-25.433-3.478-59.016 24.595-75.01s62.575-8.34 77.065 17.094-2.39 41.643-30.463 57.636-56.707 25.713-71.197.28zM571.592 600.257c0 50.557-30.053 68.21-67.13 68.21q-1.288 0-2.572-.03a109.57 109.57 0 01-5.1-.232c-33.461-2.368-59.458-20.93-59.458-67.948 0-48.66 62.181-110.06 66.852-114.604l.008-.008c.18-.176.27-.261.27-.261s67.13 64.316 67.13 114.873z" fill="#1977f2"/><path d="M502.016 660.732l24.553-34.307-24.614 38.074-.065 3.939a109.57 109.57 0 01-5.1-.233l2.646-50.582-.02-.393.044-.073.25-4.777-24.676-38.169 24.753 34.586.058 1.014 2-38.217-21.125-39.44 21.382 32.732 2.082-79.233.008-.27v.262l-.347 62.48 21.03-24.77-21.116 30.152-.557 34.218 19.637-32.84-19.718 37.875-.311 19.022 28.507-45.706-28.614 52.345z" fill="#3f3d56"/><path d="M835.592 621.342c0 55.076-32.74 74.306-73.13 74.306q-1.403 0-2.802-.03c-1.872-.041-3.725-.13-5.556-.255-36.452-2.58-64.772-22.8-64.772-74.021 0-53.008 67.739-119.896 72.827-124.846l.01-.01.293-.284s73.13 70.064 73.13 125.14z" fill="#1977f2"/><path d="M759.798 687.223l26.747-37.374-26.814 41.477-.071 4.291c-1.872-.04-3.725-.13-5.556-.254l2.882-55.102-.022-.428.049-.08.272-5.205-26.88-41.58 26.965 37.677.062 1.105 2.179-41.633-23.014-42.965 23.294 35.658 2.268-86.314.01-.294v.285l-.38 68.064 22.911-26.983-23.004 32.846-.606 37.276 21.391-35.774-21.48 41.259-.339 20.723 31.056-49.792-31.172 57.023z" fill="#3f3d56"/><ellipse cx="721.517" cy="656.822" rx="12.4" ry="39.5" transform="rotate(-64.626 653.41 657.688)" fill="#2f2e41"/><ellipse cx="112.517" cy="651.822" rx="12.4" ry="39.5" transform="rotate(-68.158 47.55 650.645)" fill="#2f2e41"/></svg>
|
||||
|
After Width: | Height: | Size: 4.8 KiB |
3
packages/docs/src/includes/assets/svg/close.svg
Normal file
3
packages/docs/src/includes/assets/svg/close.svg
Normal file
@@ -0,0 +1,3 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 18 18" fill="currentColor" >
|
||||
<path d="M14.53 4.53l-1.06-1.06L9 7.94 4.53 3.47 3.47 4.53 7.94 9l-4.47 4.47 1.06 1.06L9 10.06l4.47 4.47 1.06-1.06L10.06 9z"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 218 B |
4
packages/docs/src/includes/assets/svg/documents.svg
Normal file
4
packages/docs/src/includes/assets/svg/documents.svg
Normal file
@@ -0,0 +1,4 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">
|
||||
<path d="M443.103 71.306H416.76V44.963a9.31 9.31 0 00-9.31-9.31h-26.342V9.31a9.31 9.31 0 00-9.31-9.31h-302.9a9.31 9.31 0 00-9.31 9.31v422.074a9.31 9.31 0 009.31 9.31H95.24v26.342a9.31 9.31 0 009.31 9.31h26.342v26.342a9.31 9.31 0 009.31 9.31h302.9a9.31 9.31 0 009.31-9.31V80.616a9.308 9.308 0 00-9.309-9.31zM78.208 422.074V18.621h284.279v403.453H78.208zm35.654 35.652v-17.032h257.935a9.31 9.31 0 009.31-9.31V54.274h17.033v403.453H113.862zm319.93 35.653H149.513v-17.032H407.45a9.31 9.31 0 009.31-9.31V89.927h17.032v403.452z"/>
|
||||
<path d="M271.292 95.592H169.404c-5.143 0-9.31 4.169-9.31 9.31s4.167 9.31 9.31 9.31h101.887c5.143 0 9.31-4.169 9.31-9.31s-4.166-9.31-9.309-9.31zM313.448 141.771h-186.2c-5.143 0-9.31 4.169-9.31 9.31s4.167 9.31 9.31 9.31h186.2a9.31 9.31 0 000-18.62zM313.448 187.948h-186.2c-5.143 0-9.31 4.169-9.31 9.31s4.167 9.31 9.31 9.31h186.2a9.31 9.31 0 000-18.62zM313.448 234.125h-186.2c-5.143 0-9.31 4.169-9.31 9.31s4.167 9.31 9.31 9.31h186.2a9.31 9.31 0 000-18.62zM313.448 280.303h-186.2c-5.143 0-9.31 4.169-9.31 9.31s4.167 9.31 9.31 9.31h186.2a9.31 9.31 0 000-18.62zM313.448 326.48h-186.2c-5.143 0-9.31 4.169-9.31 9.31s4.167 9.31 9.31 9.31h186.2a9.31 9.31 0 000-18.62z"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.2 KiB |
1
packages/docs/src/includes/assets/svg/github.svg
Normal file
1
packages/docs/src/includes/assets/svg/github.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" fill="currentColor"><path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/></svg>
|
||||
|
After Width: | Height: | Size: 811 B |
1
packages/docs/src/includes/assets/svg/logo.svg
Normal file
1
packages/docs/src/includes/assets/svg/logo.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 500 500" fill="currentColor"><path d="M367.6 192.9c-3.8-1.3-7.7-2.5-11.7-3.7.7-2.7 1.3-5.4 1.8-8 8.9-43.2 3.1-78-16.8-89.4-19-11-50.2.5-81.6 27.8-3 2.6-6.1 5.4-9.1 8.3-2-1.9-4-3.8-6-5.6-33-29.3-66-41.6-85.8-30.1-19 11-24.7 43.7-16.7 84.6.8 4 1.7 8 2.7 12.1-4.7 1.3-9.2 2.7-13.5 4.2-38.6 13.5-63.3 34.6-63.3 56.5 0 22.6 26.5 45.3 66.7 59.1 3.2 1.1 6.5 2.1 9.9 3.1-1.1 4.4-2.1 8.8-2.9 13-7.6 40.2-1.7 72.1 17.3 83.1 19.6 11.3 52.5-.3 84.5-28.3 2.5-2.2 5.1-4.6 7.6-7 3.3 3.2 6.6 6.2 9.9 9 31 26.7 61.7 37.5 80.6 26.5 19.6-11.3 25.9-45.6 17.7-87.4-.6-3.2-1.4-6.4-2.2-9.8 2.3-.7 4.6-1.4 6.8-2.1 41.8-13.9 69.1-36.3 69.1-59.2-.1-21.9-25.6-43.1-65-56.7zm-9.1 101.2c-2 .7-4 1.3-6.1 1.9-4.6-14.6-10.9-30.2-18.5-46.2 7.3-15.7 13.3-31 17.8-45.6 3.7 1.1 7.4 2.2 10.9 3.4 33.8 11.6 54.4 28.8 54.4 42.1-.1 14.1-22.3 32.4-58.5 44.4zm-15 29.7c3.7 18.5 4.2 35.1 1.8 48.2-2.2 11.7-6.5 19.5-12 22.7-11.5 6.7-36.1-2-62.6-24.8-3-2.6-6.1-5.4-9.2-8.4 10.3-11.2 20.6-24.3 30.6-38.8 17.6-1.6 34.3-4.1 49.4-7.6.8 2.9 1.5 5.8 2 8.7zm-151.6 69.7c-11.2 4-20.2 4.1-25.6 1-11.5-6.6-16.3-32.3-9.8-66.7.7-3.9 1.6-8 2.7-12.1 15 3.3 31.5 5.7 49.2 7.1 10.1 14.2 20.7 27.3 31.3 38.7-2.3 2.2-4.6 4.4-7 6.4-14.1 12.4-28.3 21.2-40.8 25.6zM139.3 294c-17.8-6.1-32.5-14-42.6-22.6-9.1-7.8-13.6-15.4-13.6-21.7 0-13.3 19.8-30.2 52.9-41.8 4-1.4 8.2-2.7 12.6-4 4.6 14.9 10.6 30.4 17.8 46.1-7.3 15.9-13.4 31.7-18 46.8-3.2-.9-6.2-1.8-9.1-2.8zm17.6-120.1c-6.9-35.1-2.3-61.5 9.2-68.1 12.2-7.1 39.2 3 67.7 28.3 1.8 1.6 3.6 3.3 5.5 5.1-10.6 11.4-21.1 24.4-31.1 38.5-17.2 1.6-33.6 4.1-48.7 7.6-1-4-1.8-7.8-2.6-11.4zm157.5 38.8c-3.6-6.2-7.3-12.3-11.1-18.3 11.6 1.5 22.8 3.4 33.3 5.8-3.1 10.1-7.1 20.6-11.7 31.4-3.3-6.1-6.8-12.5-10.5-18.9zm-64.2-62.5c7.2 7.8 14.4 16.5 21.5 25.9-7.1-.3-14.4-.5-21.7-.5-7.2 0-14.4.2-21.5.5 7.1-9.3 14.4-18 21.7-25.9zm-64.6 62.7c-3.6 6.3-7 12.6-10.3 18.9-4.5-10.8-8.4-21.4-11.6-31.6 10.4-2.3 21.5-4.2 33.1-5.7-3.9 5.9-7.6 12.1-11.2 18.4zm11.5 93.1c-12-1.3-23.2-3.1-33.6-5.4 3.2-10.4 7.2-21.2 11.8-32.2 3.3 6.3 6.7 12.6 10.3 18.9 3.7 6.4 7.5 12.6 11.5 18.7zm53.5 44.3c-7.4-8-14.8-16.8-22-26.3 7 .3 14.1.4 21.4.4 7.4 0 14.8-.2 22-.5-7.1 9.7-14.3 18.5-21.4 26.4zm74.4-82.5c4.9 11.1 9 21.9 12.3 32.1-10.6 2.4-22 4.4-34 5.8 3.8-6 7.5-12.2 11.2-18.6 3.7-6.4 7.2-12.8 10.5-19.3zm-24.1 11.6c-5.7 9.9-11.6 19.3-17.5 28.3-10.8.8-22 1.2-33.4 1.2-11.4 0-22.4-.4-33-1-6.2-9-12.2-18.5-17.8-28.3-5.7-9.8-10.9-19.6-15.6-29.4 4.7-9.8 9.9-19.7 15.5-29.4 5.6-9.8 11.6-19.2 17.7-28.2 10.9-.8 22-1.2 33.2-1.2 11.3 0 22.4.4 33.3 1.3 6 8.9 11.9 18.3 17.6 28.1 5.7 9.9 11 19.7 15.7 29.3-4.7 9.5-10 19.4-15.7 29.3zm32.2-174.1c12.2 7 17 35.5 9.3 72.8-.5 2.4-1 4.8-1.6 7.3-15.1-3.5-31.6-6.1-48.8-7.7-10-14.3-20.4-27.3-30.9-38.5 2.8-2.7 5.6-5.3 8.4-7.7 26.9-23.6 52.1-32.8 63.6-26.2zM250 217.1c18 0 32.6 14.6 32.6 32.6S268 282.3 250 282.3s-32.6-14.6-32.6-32.6 14.6-32.6 32.6-32.6z"/></svg>
|
||||
|
After Width: | Height: | Size: 2.8 KiB |
14
packages/docs/src/includes/fragments/footer.html
Normal file
14
packages/docs/src/includes/fragments/footer.html
Normal file
@@ -0,0 +1,14 @@
|
||||
<div class="view flex-row items-center mt-12 py-4 border-top border-color-faint">
|
||||
{% if site.enableGithubLink == 1 %}
|
||||
<a aria-label="Link to {{ site.name }} GitHub repository" class="inline-block mr-2 opacity-50 hover:opacity-100 text-color" style="width:20px;height:20px;vertical-align:middle;" rel="noopener noreferrer" href="{{ site.githubUrl}}" target="_blank">
|
||||
{{ '/src/includes/assets/svg/github.svg' | svgContents("w-full") | safe }}
|
||||
</a>
|
||||
{% endif %}
|
||||
|
||||
<div class="text text-sm text-color-faint">
|
||||
<a class="no-underline" href="/">{{ site.name }}</a> –
|
||||
{% if site.footer %}
|
||||
<span>{{ site.footer | safe }}</span>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
38
packages/docs/src/includes/fragments/macros.html
Normal file
38
packages/docs/src/includes/fragments/macros.html
Normal file
@@ -0,0 +1,38 @@
|
||||
{% macro button(text, href) %}
|
||||
<a href="{{ href }}" class="view inline-flex flex-row items-center py-3 px-6 border rounded text-xl text-white font-bold" style="background-color:var(--docs-theme-color); border-color:var(--docs-theme-color); color:white; text-decoration:none;">
|
||||
{{ text }}
|
||||
</a>
|
||||
{% endmacro %}
|
||||
|
||||
{% macro docbutton(text, href) %}
|
||||
<a href="{{ href | url }}" class="view inline-flex flex-row items-center py-3 px-6 border rounded text-xl text-white font-bold no-underline" style="background-color:var(--docs-theme-color); border-color:var(--docs-theme-color); color:white; text-decoration:">
|
||||
<span class="view mr-2" style="width:20px;">
|
||||
{{ '/src/includes/assets/svg/documents.svg' | svgContents("w-full fill-current") | safe }}
|
||||
</span>
|
||||
<span>{{ text }}</span>
|
||||
</a>
|
||||
{% endmacro %}
|
||||
|
||||
{% macro codebutton(text, href) %}
|
||||
<a href="{{ href }}" class="view inline-flex flex-row items-center py-3 px-6 border rounded text-xl no-underline font-mono text-color" style="border-color:currentColor;">
|
||||
<span aria-hidden="true" class="mr-2">$ </span>
|
||||
<span class="inline-block whitespace-nowrap overflow-ellipsis">{{ text }}</span>
|
||||
</a>
|
||||
{% endmacro %}
|
||||
|
||||
{% macro prop(name, type) %}
|
||||
<div class="prop border-left border-left-3 border-theme-faint pl-5 overflow-ellipsis">
|
||||
<span class="font-bold">{{ name }}</span>
|
||||
{%- if type != null -%}<span aria-hidden="true">:</span> <span class="whitespace-nowrap text-color-faint">{{ type }}</span>{%- endif %}
|
||||
{{ caller() }}
|
||||
</div>
|
||||
{% endmacro %}
|
||||
|
||||
{% macro codesandbox(path = '/') %}
|
||||
<iframe
|
||||
src="https://codesandbox.io/embed/github/necolas/react-native-web/tree/{{ site.packageVersion }}}}/packages/examples?codemirror=1&fontsize=12&hidedevtools=1&hidenavigation=1&initialpath=/{{ path }}&module=%2Fpages%2F{{ path }}%2Findex.js&theme=light"
|
||||
style="width:100%; height:500px; border:1px solid var(--docs-border-color); border-radius:4px; overflow:hidden;"
|
||||
title="React Native for Web: {{ path}} examples"
|
||||
sandbox="allow-forms allow-modals allow-popups allow-presentation allow-same-origin allow-scripts"
|
||||
></iframe>
|
||||
{% endmacro %}
|
||||
60
packages/docs/src/includes/fragments/nav.html
Normal file
60
packages/docs/src/includes/fragments/nav.html
Normal file
@@ -0,0 +1,60 @@
|
||||
{% set navPages = collections.nav | eleventyNavigation %}
|
||||
|
||||
<nav id="navigation-scroller" class="view overflow-x-hidden overflow-y-auto h-full p-6 pt-12">
|
||||
<h1 class="m-0 mb-4" style="font-size:1rem;">
|
||||
<a class="view no-underline group font-semibold" href="{{ '/' | url }}" style="color:var(--docs-theme-color)">
|
||||
<span class="view flex-row items-center overflow-x-hidden mb-1 text-xl">
|
||||
{{ site.name }}
|
||||
</span>
|
||||
<span>{{ site.packageName }}@{{ site.packageVersion }}</span>
|
||||
</a>
|
||||
</h1>
|
||||
|
||||
{% macro renderNavListItem(entry) -%}
|
||||
{% set itemClassName %}
|
||||
{% if entry.url == page.url %}
|
||||
font-semibold text-color-inherit
|
||||
{% else %}
|
||||
text-color-faint hover:text-color-inherit
|
||||
{% endif %}
|
||||
{% endset %}
|
||||
|
||||
{% set itemStyle %}
|
||||
{% if entry.url == page.url %}
|
||||
background-color:var(--docs-theme-color-faded); border-left:3px solid var(--docs-theme-color); margin-left:-13px; border-radius:0 0.25rem 0.25rem 0;
|
||||
{% endif %}
|
||||
{% endset %}
|
||||
|
||||
<li class="view item mb-2">
|
||||
{%- if entry.url != false -%}
|
||||
<a class="text block {{ itemClassName }}" href="{{ entry.url | url }}" style="padding:2px 10px; margin:-2px -10px;{{itemStyle}}">
|
||||
{{ entry.title }}
|
||||
{% if entry.label != null %}
|
||||
{% set labelColor -%}
|
||||
{%- if entry.label == 'Change' -%}
|
||||
#ff8300
|
||||
{%- else -%}
|
||||
#86b300
|
||||
{%- endif -%}
|
||||
{%- endset %}
|
||||
<span class="px-1 ml-2 inline-block border rounded text-uppercase text-sm" style="border-color:{{labelColor}}; color:{{labelColor}}; font-weight:normal">{{ entry.label }}</span>
|
||||
{% endif %}
|
||||
</a>
|
||||
{% else %}
|
||||
<span class="text block font-semibold text-uppercase text-sm">{{ entry.title }}</span>
|
||||
{% endif %}
|
||||
|
||||
{%- if entry.children.length -%}
|
||||
<ul class="view list-none mt-2 mb-4">
|
||||
{%- for child in entry.children %}{{ renderNavListItem(child) }}{% endfor -%}
|
||||
</ul>
|
||||
{%- endif -%}
|
||||
</li>
|
||||
{%- endmacro %}
|
||||
|
||||
<ul class="view list-none mt-6">
|
||||
{%- for entry in navPages %}
|
||||
{{ renderNavListItem(entry) }}
|
||||
{%- endfor -%}
|
||||
</ul>
|
||||
</nav>
|
||||
11
packages/docs/src/includes/layouts/404.html
Normal file
11
packages/docs/src/includes/layouts/404.html
Normal file
@@ -0,0 +1,11 @@
|
||||
---
|
||||
layout: layouts/shell.html
|
||||
section: page
|
||||
---
|
||||
|
||||
<article class="view items-center p-6 w-full">
|
||||
<h1 class="text-3xl">{{ title }}</h1>
|
||||
<div style="width:75%">
|
||||
{{ '/src/includes/assets/svg/404.svg' | svgContents("w-full") | safe }}
|
||||
</div>
|
||||
</article>
|
||||
61
packages/docs/src/includes/layouts/home.html
Normal file
61
packages/docs/src/includes/layouts/home.html
Normal file
@@ -0,0 +1,61 @@
|
||||
---
|
||||
layout: layouts/shell.html
|
||||
section: page
|
||||
---
|
||||
|
||||
{% import "fragments/macros.html" as macro with context %}
|
||||
|
||||
<main id="main" class="view flex-1">
|
||||
<div class="view w-full mt-12 px-6 wide:px-20">
|
||||
<div class="view w-full">
|
||||
<div class="view flex-1">
|
||||
<h1 class="view flex-row items-center font-bold">
|
||||
<span aria-hidden="true" rclass="block mr-2" style="width:50px;height:50px;margin-left:-6px;color:var(--docs-theme-color)">
|
||||
{{ '/src/includes/assets/svg/logo.svg' | svgContents("w-full") | safe }}
|
||||
</span>
|
||||
<span class="text" style="color:var(--docs-theme-color); font-size:1.75rem;">{{ site.name }}</span>
|
||||
</h1>
|
||||
<h2 class="text my-8 text-3xl">React Native Components and APIs on the Web</h2>
|
||||
<p class="text mb-8 text-2xl">{{ site.name }} is an accessible implementation of React Native's Components and APIs that is interoperable with React DOM.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="view flex-row flex-wrap">
|
||||
<div class="view my-2 mr-4">
|
||||
{{ macro.docbutton('Documentation', '/docs') }}
|
||||
</div>
|
||||
<div class="view flex-shrink my-2">
|
||||
{{ macro.codebutton('npm i react-native-web', site.packageUrl) }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="markdown mt-6">
|
||||
<ul style="font-size:1.25rem;">
|
||||
<li><strong>Accessible HTML</strong>. Support different devices and input modes, render semantic tags.</li>
|
||||
<li><strong>High-quality interactions</strong>. Support gestures and multiple input modes (touch, mouse, keyboard).</li>
|
||||
<li><strong>Reliable styles</strong>. Rely on scoped styles and automatic vendor-prefixing. Support RTL layouts.</li>
|
||||
<li><strong>Responsive containers</strong>. Respond to element resize events.</li>
|
||||
<li><strong>Incremental adoption</strong>. Interoperates with existing React DOM components. Bundle only what you use.</li>
|
||||
</ul>
|
||||
|
||||
<h2>Try it out!</h2>
|
||||
|
||||
<p>You can try {{ site.name }} from your browser using the <a href="https://codesandbox.io/s/react-native-q4qymyp2l6">official template on CodeSandbox</a>.</p>
|
||||
|
||||
<p>Fork the template and create your own app without leaving the browser.</p>
|
||||
|
||||
<iframe
|
||||
src="https://codesandbox.io/embed/react-native-q4qymyp2l6?codemirror=1&fontsize=12&hidedevtools=1&hidenavigation=1&theme=light"
|
||||
style="width:100%; height:500px; border:1px solid var(--docs-border-color); border-radius: 4px; overflow:hidden;"
|
||||
title="React Native for Web preview"
|
||||
sandbox="allow-forms allow-modals allow-popups allow-presentation allow-same-origin allow-scripts"
|
||||
></iframe>
|
||||
|
||||
<div class="callout">
|
||||
<p><strong>Did you know?</strong> React Native for Web is used in production web apps by <a href="https://twitter.com">Twitter</a>, <a href="https://twitter.com/naqvitalha/status/969577892991549440">Flipkart</a>, <a href="https://www.youtube.com/watch?v=RV9rxrNIxnY">Uber</a>, <a href="https://matchcenter.mlssoccer.com">Major League Soccer</a>, and many others. It also powers web support in multi-platform React projects such as <a href="https://expo.io">Expo</a>, <a href="https://reactnativeelements.com/">React Native Elements</a>, <a href="https://callstack.github.io/react-native-paper/using-on-the-web.html">React Native Paper</a>, and <a href="https://docs.nativebase.io/docs/GetStarted.html#Setup_with_Web">React Native Base</a>.
|
||||
</div>
|
||||
|
||||
<div style="height:2rem"><!-- spacer --></div>
|
||||
</div>
|
||||
{% include "fragments/footer.html" %}
|
||||
</div>
|
||||
</main>
|
||||
37
packages/docs/src/includes/layouts/page.html
Normal file
37
packages/docs/src/includes/layouts/page.html
Normal file
@@ -0,0 +1,37 @@
|
||||
---
|
||||
layout: layouts/shell.html
|
||||
section: page
|
||||
---
|
||||
|
||||
<div class="view fixed wide:hidden z-20" style="right:30px; bottom:30px;">
|
||||
<button id="show-nav" aria-label="Show navigation" class="view appearance-none rounded-full items-center justify-center text-white cursor-pointer" style="background-color:var(--docs-theme-color); width:4rem; height:4rem; padding:5px;">
|
||||
{{ '/src/includes/assets/svg/logo.svg' | svgContents("w-full fill-current") | safe }}
|
||||
</button>
|
||||
<button id="close-nav" aria-label="Close navigation" class="view appearance-none hidden rounded-full items-center justify-center text-white cursor-pointer" style="background-color:var(--docs-theme-color); width:4rem; height:4rem; padding:10px;">
|
||||
{{ '/src/includes/assets/svg/close.svg' | svgContents("w-full") | safe }}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="view flex-row flex-nowrap relative">
|
||||
<div id="navigation" class="navigation view fixed wide:sticky wide:left-0 z-10 opacity-0 wide:opacity-1 h-screen inset-y-0 w-72 border-right border-color-faint bg-theme">
|
||||
{% include "fragments/nav.html" %}
|
||||
</div>
|
||||
|
||||
<main id="main" class="view flex-1">
|
||||
<div class="view w-full mt-12 px-4 wide:px-20">
|
||||
<article class="markdown">
|
||||
<h1>{{ title }}</h1>
|
||||
{{ layoutContent | safe }}
|
||||
</article>
|
||||
|
||||
<div class="flex mt-4">
|
||||
<div class="inline-block w-auto text-sm pt-1 pb-1 mr-2 rounded text-color-faint">Updated <time datetime="{{ page.date | machineDate }}">{{ page.date | readableDate }}</time></div>
|
||||
{% if site.enableEditButton == true %}
|
||||
<a class="no-underline inline-block w-auto text-sm hover:bg-gray-200 py-1 px-3 rounded text-color-faint" href="{{ site.githubUrl }}/edit/{{ site.githubBranch }}/packages/www/{{ page.inputPath }}" target="_blank">Edit</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% include "fragments/footer.html" %}
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
34
packages/docs/src/includes/layouts/shell.html
Normal file
34
packages/docs/src/includes/layouts/shell.html
Normal file
@@ -0,0 +1,34 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
{%- set htmltitle -%}
|
||||
{%- if page.fileSlug === 'home' -%}
|
||||
{{- renderData.title or title -}}
|
||||
{%- else -%}
|
||||
{{- renderData.title or title }} // {{ site.name -}}
|
||||
{%- endif -%}
|
||||
{%- endset -%}
|
||||
<title>{{ htmltitle }}</title>
|
||||
<meta property="og:title" content="{{ htmltitle }}"/>
|
||||
<meta name="description" content="{{ metaDescription or renderData.metaDescription or site.description }}">
|
||||
<link rel="icon" href="{{ '/static/logo.svg' | url }}">
|
||||
{% set cssinline %}
|
||||
{% include "assets/inline.css" %}
|
||||
{% endset %}
|
||||
<style>{{ cssinline | cssmin | safe }}</style>
|
||||
<link rel="stylesheet" media="(prefers-color-scheme:light)" href="https://unpkg.com/prismjs@1.20.0/themes/prism.css">
|
||||
<link rel="stylesheet" media="(prefers-color-scheme:dark)" href="https://unpkg.com/prismjs@1.20.0/themes/prism-okaidia.css">
|
||||
{% set jsinline %}
|
||||
{% include "assets/inline.js" %}
|
||||
{% endset %}
|
||||
<script defer>{{ jsinline | jsmin | safe }}</script>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div id="app" class="container mx-auto">
|
||||
<div class="view">
|
||||
{{ layoutContent | safe }}
|
||||
</div>
|
||||
</div>
|
||||
5
packages/docs/src/pages/404.md
Normal file
5
packages/docs/src/pages/404.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
title: 404
|
||||
permalink: /404.html
|
||||
layout: layouts/404.html
|
||||
---
|
||||
9
packages/docs/src/pages/docs/apis/_.md
Normal file
9
packages/docs/src/pages/docs/apis/_.md
Normal file
@@ -0,0 +1,9 @@
|
||||
---
|
||||
title: APIs
|
||||
date: Last Modified
|
||||
permalink: false
|
||||
eleventyNavigation:
|
||||
key: APIs
|
||||
title: APIs
|
||||
order: 30
|
||||
---
|
||||
20
packages/docs/src/pages/docs/apis/animated.md
Normal file
20
packages/docs/src/pages/docs/apis/animated.md
Normal file
@@ -0,0 +1,20 @@
|
||||
---
|
||||
title: Animated
|
||||
date: Last Modified
|
||||
permalink: /docs/animated/index.html
|
||||
eleventyNavigation:
|
||||
key: Animated
|
||||
parent: APIs
|
||||
---
|
||||
|
||||
:::lead
|
||||
Animated focuses on declarative relationships between inputs and outputs, configurable transforms in between, and start/stop methods to control time-based animation execution.
|
||||
:::
|
||||
|
||||
This API is the same JavaScript implementation as found in React Native. Please refer to the React Native documentation below:
|
||||
|
||||
* [Animated](https://reactnative.dev/docs/animated)
|
||||
|
||||
:::callout
|
||||
**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/).
|
||||
:::
|
||||
74
packages/docs/src/pages/docs/apis/app-registry.md
Normal file
74
packages/docs/src/pages/docs/apis/app-registry.md
Normal file
@@ -0,0 +1,74 @@
|
||||
---
|
||||
title: AppRegistry
|
||||
date: Last Modified
|
||||
permalink: /docs/app-registry/index.html
|
||||
eleventyNavigation:
|
||||
key: AppRegistry
|
||||
parent: APIs
|
||||
---
|
||||
|
||||
{% import "fragments/macros.html" as macro with context %}
|
||||
|
||||
:::lead
|
||||
AppRegistry is the control point for registering, running, prerendering, and unmounting all apps.
|
||||
:::
|
||||
|
||||
App root components should register themselves with `AppRegistry.`registerComponent. Apps can be run by invoking `AppRegistry.runApplication`.
|
||||
|
||||
```js
|
||||
import { AppRegistry } from 'react-native';
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## API
|
||||
|
||||
### Static methods
|
||||
|
||||
{% call macro.prop('getAppKeys', '() => Array<string>') %}
|
||||
Returns an array of all registered app keys
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('getApplication', '(key: string, params: AppParams) => ({ element, getStyleElement })') %}
|
||||
A web-only method for server-side rendering to HTML and CSS. It returns an object containing the given application's `element` and `getStyleElement` function to get styles once the element is rendered.
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('registerComponent', '(key: string, getComponent: () => React.Element) => void') %}
|
||||
Register a component provider under the given `key`.
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('registerConfig', '(configs: Array<AppConfig>) => void') %}
|
||||
Register multiple applications.
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('unmountApplicationComponentAtRootTag', 'rootTag: HTMLElement') %}
|
||||
Called this function with the `rootTag` that was passed into `runApplication` in order to unmount it.
|
||||
{% endcall %}
|
||||
|
||||
### AppConfig
|
||||
|
||||
{% call macro.prop('appKey', 'string') %}
|
||||
The `key` under which the component is registered.
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('component', '() => React.Element') %}
|
||||
A function that returns a React element.
|
||||
{% endcall %}
|
||||
|
||||
### AppParams
|
||||
|
||||
{% call macro.prop('callback', '?() => void') %}
|
||||
Called when React rendering has finished.
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('hydrate', '?boolean') %}
|
||||
If the client should hydrate server-rendered HTML.
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('initialProps', '?Object') %}
|
||||
The initial props passed to the root component.
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('rootTag', 'HTMLElement') %}
|
||||
The native element into which the application is rendered.
|
||||
{% endcall %}
|
||||
51
packages/docs/src/pages/docs/apis/app-state.md
Normal file
51
packages/docs/src/pages/docs/apis/app-state.md
Normal file
@@ -0,0 +1,51 @@
|
||||
---
|
||||
title: AppState
|
||||
date: Last Modified
|
||||
permalink: /docs/app-state/index.html
|
||||
eleventyNavigation:
|
||||
key: AppState
|
||||
parent: APIs
|
||||
---
|
||||
|
||||
{% import "fragments/macros.html" as macro with context %}
|
||||
|
||||
:::lead
|
||||
AppState can tell you if the app is in the foreground or background, and notify you when the state changes.
|
||||
:::
|
||||
|
||||
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).
|
||||
|
||||
|
||||
```js
|
||||
import { AppState } from 'react-native';
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## API
|
||||
|
||||
### Static properties
|
||||
|
||||
{% call macro.prop('isAvailable', 'boolean') %}
|
||||
Whether the browser environment supports `AppState`.
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('currentState', '?("active" | "background")') %}
|
||||
Returns the current state of the app.
|
||||
{% endcall %}
|
||||
|
||||
### Static methods
|
||||
|
||||
{% call macro.prop('addEventListener', '(type: ?string, listener: (boolean) => void) => void') %}
|
||||
Add a listener to `AppState` changes. Listen to the `"change"` event type. The handler is called with the app state value.
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('removeEventListener', '(type: ?string, listener: (boolean) => void) => void') %}
|
||||
Remove a listener from `AppState` changes.
|
||||
{% endcall %}
|
||||
|
||||
---
|
||||
|
||||
## Examples
|
||||
|
||||
{{ macro.codesandbox('app-state') }}
|
||||
28
packages/docs/src/pages/docs/apis/appearance.md
Normal file
28
packages/docs/src/pages/docs/apis/appearance.md
Normal file
@@ -0,0 +1,28 @@
|
||||
---
|
||||
title: Appearance
|
||||
date: Last Modified
|
||||
permalink: /docs/appearance/index.html
|
||||
eleventyNavigation:
|
||||
key: Appearance
|
||||
parent: APIs
|
||||
---
|
||||
|
||||
{% import "fragments/macros.html" as macro with context %}
|
||||
|
||||
:::lead
|
||||
The Appearance module exposes information about the user's appearance preferences, such as their preferred color scheme (light or dark).
|
||||
:::
|
||||
|
||||
```js
|
||||
import { Appearance } from 'react-native';
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## API
|
||||
|
||||
### Static methods
|
||||
|
||||
{% call macro.prop('getColorScheme', '() => ("dark" | "light")') %}
|
||||
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.
|
||||
{% endcall %}
|
||||
42
packages/docs/src/pages/docs/apis/clipboard.md
Normal file
42
packages/docs/src/pages/docs/apis/clipboard.md
Normal file
@@ -0,0 +1,42 @@
|
||||
---
|
||||
title: Clipboard
|
||||
date: Last Modified
|
||||
permalink: /docs/clipboard/index.html
|
||||
eleventyNavigation:
|
||||
key: Clipboard
|
||||
parent: APIs
|
||||
---
|
||||
|
||||
{% import "fragments/macros.html" as macro with context %}
|
||||
|
||||
:::lead
|
||||
Clipboard gives you an interface for setting to the clipboard. (Getting clipboard content is not currently supported on web.)
|
||||
:::
|
||||
|
||||
```js
|
||||
import { Clipboard } from 'react-native';
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## API
|
||||
|
||||
### Static methods
|
||||
|
||||
{% call macro.prop('isAvailable', '() => boolean') %}
|
||||
Determines whether the browser environment supports Clipboard at all.
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('setString', '() => boolean') %}
|
||||
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.
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('getString', '() => Promise<"">') %}
|
||||
Not properly supported on Web. Returns a Promise of an empty string.
|
||||
{% endcall %}
|
||||
|
||||
---
|
||||
|
||||
## Examples
|
||||
|
||||
{{ macro.codesandbox('clipboard') }}
|
||||
58
packages/docs/src/pages/docs/apis/dimensions.md
Normal file
58
packages/docs/src/pages/docs/apis/dimensions.md
Normal file
@@ -0,0 +1,58 @@
|
||||
---
|
||||
title: Dimensions
|
||||
date: Last Modified
|
||||
permalink: /docs/dimensions/index.html
|
||||
eleventyNavigation:
|
||||
key: Dimensions
|
||||
parent: APIs
|
||||
---
|
||||
|
||||
{% import "fragments/macros.html" as macro with context %}
|
||||
|
||||
:::lead
|
||||
Respond to changes in the viewport dimensions.
|
||||
:::
|
||||
|
||||
Dimensions may change (e.g., due to device rotation) so any rendering logic or styles that depend on these constants should try to call this function on every render, rather than caching the value.
|
||||
|
||||
```js
|
||||
import { Dimensions } from 'react-native';
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## API
|
||||
|
||||
### Static methods
|
||||
|
||||
{% call macro.prop('get', '(string: "window" | "screen") => Dimension') %}
|
||||
Get a dimension (e.g., window or screen).
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('set', '(dimensions: { window: Dimension, screen: Dimension }) => void') %}
|
||||
This should only be called server-side with an estimate for initial dimensions to be used when pre-rendering pages on the server.
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('addEventListener', '(type: ?string, listener: (dimensions) => void) => void') %}
|
||||
Add a listener to `Dimensions` changes. Listen to the `"change"` event type. The handler is called with the dimensions state.
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('removeEventListener', '(type: ?string, listener: (dimensions) => void) => void') %}
|
||||
Remove a listener from `Dimensions` changes.
|
||||
{% endcall %}
|
||||
|
||||
### Dimension
|
||||
|
||||
{% call macro.prop('height', 'number') %}
|
||||
The height of the dimension.
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('width', 'number') %}
|
||||
The width of the dimension.
|
||||
{% endcall %}
|
||||
|
||||
---
|
||||
|
||||
## Examples
|
||||
|
||||
{{ macro.codesandbox('dimensions') }}
|
||||
63
packages/docs/src/pages/docs/apis/i18n-manager.md
Normal file
63
packages/docs/src/pages/docs/apis/i18n-manager.md
Normal file
@@ -0,0 +1,63 @@
|
||||
---
|
||||
title: I18nManager
|
||||
date: Last Modified
|
||||
permalink: /docs/i18n-manager/index.html
|
||||
eleventyNavigation:
|
||||
key: I18nManager
|
||||
parent: APIs
|
||||
label: "Change"
|
||||
---
|
||||
|
||||
{% import "fragments/macros.html" as macro with context %}
|
||||
|
||||
:::lead
|
||||
Control and query the layout and writing direction of the application.
|
||||
:::
|
||||
|
||||
```js
|
||||
import { I18nManager } from 'react-native';
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## API
|
||||
|
||||
### Static methods
|
||||
|
||||
{% call macro.prop('allowRTL', '(boolean) => void') %}
|
||||
Allow the application to display in RTL mode.
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('forceRTL', '(boolean) => void') %}
|
||||
Force the application to display in RTL mode.
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('getConstants', '() => I18nConstants') %}
|
||||
Determine how the application is handling bidi layout.
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('swapLeftAndRightInRTL', '(boolean) => void') %}
|
||||
Control whether the application swaps `left`/`right` styles in RTL mode. It is recommended that applications rely on `start`/`end` styles and disable automatic BiDi-flipping of `left`/`right` styles.
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('setPreferredLanguageRTL', '(boolean) => void') %}
|
||||
Set the application's preferred writing direction to RTL. You may need to infer the user's preferred locale on the server (from HTTP headers) and decide whether it's an RTL language. (Web-only)
|
||||
{% endcall %}
|
||||
|
||||
### I18nConstants
|
||||
|
||||
The object returned by `I18nManager.getConstants()`.
|
||||
|
||||
{% call macro.prop('isRTL', 'boolean = false') %}
|
||||
Whether the application is currently in RTL mode.
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('doLeftAndRightSwapInRTL', 'boolean = true') %}
|
||||
Whether the application swaps left/right styles in RTL mode.
|
||||
{% endcall %}
|
||||
|
||||
---
|
||||
|
||||
## Examples
|
||||
|
||||
{{ macro.codesandbox('i18n-manager') }}
|
||||
43
packages/docs/src/pages/docs/apis/linking.md
Normal file
43
packages/docs/src/pages/docs/apis/linking.md
Normal file
@@ -0,0 +1,43 @@
|
||||
---
|
||||
title: Linking
|
||||
date: Last Modified
|
||||
permalink: /docs/linking/index.html
|
||||
eleventyNavigation:
|
||||
key: Linking
|
||||
parent: APIs
|
||||
label: "Change"
|
||||
---
|
||||
|
||||
{% import "fragments/macros.html" as macro with context %}
|
||||
|
||||
:::lead
|
||||
Linking gives you a general interface for securely opening external URLs from JavaScript.
|
||||
:::
|
||||
|
||||
```js
|
||||
import { Linking } from 'react-native';
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## API
|
||||
|
||||
### Static methods
|
||||
|
||||
{% call macro.prop('canOpenURL', '(url) => Promise<boolean>') %}
|
||||
Returns a `Promise` that resolves to a boolean indicating whether the app can open the URL.
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('getInitialURL', '() => Promise<string>') %}
|
||||
Returns a `Promise` that resolves to the string of the URL that initially loaded the app.
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('openURL', '(url) => Promise<>') %}
|
||||
Try to open the given url in a secure fashion. The method returns a Promise object. If the url opens, the promise is resolved. If not, the promise is rejected.
|
||||
{% endcall %}
|
||||
|
||||
---
|
||||
|
||||
## Examples
|
||||
|
||||
{{ macro.codesandbox('linking') }}
|
||||
24
packages/docs/src/pages/docs/apis/pan-responder.md
Normal file
24
packages/docs/src/pages/docs/apis/pan-responder.md
Normal file
@@ -0,0 +1,24 @@
|
||||
---
|
||||
title: PanResponder
|
||||
date: Last Modified
|
||||
permalink: /docs/pan-responder/index.html
|
||||
eleventyNavigation:
|
||||
key: PanResponder
|
||||
parent: APIs
|
||||
---
|
||||
|
||||
{% import "fragments/macros.html" as macro with context %}
|
||||
|
||||
:::lead
|
||||
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.
|
||||
:::
|
||||
|
||||
Please refer to the React Native documentation below:
|
||||
|
||||
* [PanResponder](https://reactnative.dev/docs/panresponder)
|
||||
|
||||
---
|
||||
|
||||
## Examples
|
||||
|
||||
{{ macro.codesandbox('pan-responder') }}
|
||||
40
packages/docs/src/pages/docs/apis/pixel-ratio.md
Normal file
40
packages/docs/src/pages/docs/apis/pixel-ratio.md
Normal file
@@ -0,0 +1,40 @@
|
||||
---
|
||||
title: PixelRatio
|
||||
date: Last Modified
|
||||
permalink: /docs/pixel-ratio/index.html
|
||||
eleventyNavigation:
|
||||
key: PixelRatio
|
||||
parent: APIs
|
||||
---
|
||||
|
||||
{% import "fragments/macros.html" as macro with context %}
|
||||
|
||||
:::lead
|
||||
`PixelRatio` class gives access to the device pixel density.
|
||||
:::
|
||||
|
||||
```js
|
||||
import { PixelRatio } from 'react-native';
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## API
|
||||
|
||||
### Static methods
|
||||
|
||||
{% call macro.prop('get', '() => number') %}
|
||||
Returns the device pixel density as a number.
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('getFontScale', '() => number') %}
|
||||
On web this returns the device pixel ratio as a number.
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('getPixelSizeForLayoutSize', '(number) => number') %}
|
||||
Converts a layout size (dp) to pixel size (px). Guaranteed to return an integer number.
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('roundToNearestPixel', '(number) => number') %}
|
||||
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.
|
||||
{% endcall %}
|
||||
36
packages/docs/src/pages/docs/apis/platform.md
Normal file
36
packages/docs/src/pages/docs/apis/platform.md
Normal file
@@ -0,0 +1,36 @@
|
||||
---
|
||||
title: Platform
|
||||
date: Last Modified
|
||||
permalink: /docs/platform/index.html
|
||||
eleventyNavigation:
|
||||
key: Platform
|
||||
parent: APIs
|
||||
---
|
||||
|
||||
{% import "fragments/macros.html" as macro with context %}
|
||||
|
||||
:::lead
|
||||
Detect what is the platform in which the app is running.
|
||||
:::
|
||||
|
||||
This piece of functionality can be useful when only small parts of a component are platform specific.
|
||||
|
||||
```js
|
||||
import { Platform } from 'react-native';
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## API
|
||||
|
||||
### Static properties
|
||||
|
||||
{% call macro.prop('OS', '"web"') %}
|
||||
This value will be `"web"` when running in a Web browser.
|
||||
{% endcall %}
|
||||
|
||||
### Static methods
|
||||
|
||||
{% call macro.prop('select', '(config) => any') %}
|
||||
Takes an object containing `Platform.OS` values as keys and returns the value for the platform you are currently running on.
|
||||
{% endcall %}
|
||||
56
packages/docs/src/pages/docs/apis/style-sheet.md
Normal file
56
packages/docs/src/pages/docs/apis/style-sheet.md
Normal file
@@ -0,0 +1,56 @@
|
||||
---
|
||||
title: StyleSheet
|
||||
date: Last Modified
|
||||
permalink: /docs/style-sheet/index.html
|
||||
eleventyNavigation:
|
||||
key: StyleSheet
|
||||
parent: APIs
|
||||
---
|
||||
|
||||
{% import "fragments/macros.html" as macro with context %}
|
||||
|
||||
:::lead
|
||||
Work with strict styles that provide deterministic rendering and automatically adapt to localized writing direction.
|
||||
:::
|
||||
|
||||
The StyleSheet abstraction converts predefined styles to (vendor-prefixed) CSS without requiring a compile-time step. Styles that cannot be resolved outside of the render loop (e.g., dynamic positioning) are usually applied as inline styles.
|
||||
|
||||
```js
|
||||
import { StyleSheet } from 'react-native';
|
||||
```
|
||||
|
||||
::: callout
|
||||
**Did you know?** StyleSheet automatically merges styles and produces "utility" CSS for lightweight, reliable, and performant styling. Read more in the [styling]({{ '/docs/styling' | url }}) guide.
|
||||
:::
|
||||
|
||||
---
|
||||
|
||||
## API
|
||||
|
||||
### Static properties
|
||||
|
||||
{% call macro.prop('absoluteFill', '?number') %}
|
||||
A very common pattern is to create overlays with position absolute and zero positioning, so `absoluteFill` can be used for convenience and to reduce duplication of these repeated styles.
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('absoluteFillObject', '?Object') %}
|
||||
Sometimes you may want `absoluteFill` but with a couple tweaks - `absoluteFillObject` can be used to create a customized entry in a StyleSheet.
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('hairlineWidth', '?Object') %}
|
||||
Equal to 1px. This is not implemented using screen density as browsers may round sub-pixel values down to `0`, causing the line not to be rendered.
|
||||
{% endcall %}
|
||||
|
||||
### Static methods
|
||||
|
||||
{% call macro.prop('compose', '(style1, style2) => Style') %}
|
||||
Combines two styles such that the last style overrides properties of the first style. If either style is falsy, the other one is returned without allocating an array, saving allocations and maintaining reference equality.
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('create', '({ [key]: ruleset }) => ({ [key]: number })') %}
|
||||
Define style objects. Each key of the object passed to `create` must define a style object. These values are opaque and should not be introspected.
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('flatten', '(styles: Style) => Object') %}
|
||||
Lookup a style object by ID or flatten an array of styles into a single style object.
|
||||
{% endcall %}
|
||||
34
packages/docs/src/pages/docs/apis/vibration.md
Normal file
34
packages/docs/src/pages/docs/apis/vibration.md
Normal file
@@ -0,0 +1,34 @@
|
||||
---
|
||||
title: Vibration
|
||||
date: Last Modified
|
||||
permalink: /docs/vibration/index.html
|
||||
eleventyNavigation:
|
||||
key: Vibration
|
||||
parent: APIs
|
||||
---
|
||||
|
||||
{% import "fragments/macros.html" as macro with context %}
|
||||
|
||||
:::lead
|
||||
Vibration is described as a pattern of on-off pulses, which may be of varying lengths.
|
||||
:::
|
||||
|
||||
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()`.
|
||||
|
||||
```js
|
||||
import { Vibration } from 'react-native';
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## API
|
||||
|
||||
### Static methods
|
||||
|
||||
{% call macro.prop('cancel', '() => void') %}
|
||||
Stop the vibration
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('vibrate', '(number | Array<number>) => void') %}
|
||||
Start the vibration pattern
|
||||
{% endcall %}
|
||||
9
packages/docs/src/pages/docs/appendix/_.md
Normal file
9
packages/docs/src/pages/docs/appendix/_.md
Normal file
@@ -0,0 +1,9 @@
|
||||
---
|
||||
title: Appendix
|
||||
date: Last Modified
|
||||
permalink: false
|
||||
eleventyNavigation:
|
||||
key: Appendix
|
||||
title: Appendix
|
||||
order: 90
|
||||
---
|
||||
24
packages/docs/src/pages/docs/appendix/about-project.md
Normal file
24
packages/docs/src/pages/docs/appendix/about-project.md
Normal file
@@ -0,0 +1,24 @@
|
||||
---
|
||||
title: About the project
|
||||
date: Last Modified
|
||||
permalink: /docs/about-project/index.html
|
||||
description:
|
||||
eleventyNavigation:
|
||||
key: About the project
|
||||
parent: Appendix
|
||||
order: 2
|
||||
---
|
||||
|
||||
:::lead
|
||||
{{ site.name }}'s origins, evolution, and development.
|
||||
:::
|
||||
|
||||
{{ site.name }} was started in 2015 by [Nicolas Gallagher](http://nicolasgallagher.com) during the development of [Twitter's Progressive Web App](https://blog.twitter.com/engineering/en_us/topics/open-source/2017/how-we-built-twitter-lite.html). It has evolved from a framework inspired by React Native into a mature and pragmatic compatibility layer between React DOM and React Native.
|
||||
|
||||
{{ site.name }} is currently used in production Web apps by companies including [Twitter](https://twitter.com), [Flipkart](https://twitter.com/naqvitalha/status/969577892991549440), [Uber](https://www.youtube.com/watch?v=RV9rxrNIxnY), and [Major League Soccer](https://matchcenter.mlssoccer.com). Software engineers from Facebook, Twitter, and Expo continue to contribute design and patches to the project.
|
||||
|
||||
Developing a Web compatibility layer for React Native involves balancing the needs of high-quality Web apps with the value of React Native API compatibility. There are instances where parts of the React Native API are co-opted to infer information that is necessary or beneficial to products running in Web browsers. Other times there are use cases that are not accomodated by the APIs provided; even when that information cannot be pragmatically incorporated into the existing React Native API design constraints, it still helps to inform which API changes are needed over the long term.
|
||||
|
||||
The evolution of React Native now involves developers who work on React Native for Android, iOS, Web, Windows, and macOS. We aim to help designers and developers with shared, platform-agnostic React APIs that reduce time to market for high-quality, multi-platform products.
|
||||
|
||||
Please browse the [source code]({{ site.githubUrl }}) and consider contributing your experience to the project.
|
||||
102
packages/docs/src/pages/docs/appendix/unstable-apis.md
Normal file
102
packages/docs/src/pages/docs/appendix/unstable-apis.md
Normal file
@@ -0,0 +1,102 @@
|
||||
---
|
||||
title: Unstable APIs
|
||||
date: Last Modified
|
||||
permalink: /docs/unstable-apis/index.html
|
||||
description:
|
||||
eleventyNavigation:
|
||||
key: Unstable APIs
|
||||
parent: Appendix
|
||||
order: 1
|
||||
---
|
||||
|
||||
:::lead
|
||||
The following APIs are unstable and subject to breaking changes. Use at your own risk.
|
||||
:::
|
||||
|
||||
## Use with existing React DOM components
|
||||
|
||||
React Native for Web exports a web-specific module called `unstable_createElement`, which can be used to wrap React DOM components. This allows you to use React Native's accessibility and style optimizations. Since this is a web-specific export it should always be imported from the `react-native-web` package.
|
||||
|
||||
In the example below, `Video` will now accept common React Native props such as `accessibilityLabel`, `accessible`, `style`, and even the Responder event props.
|
||||
|
||||
```js
|
||||
import { unstable_createElement } from 'react-native-web';
|
||||
const Video = (props) => unstable_createElement('video', props);
|
||||
```
|
||||
|
||||
This also works with composite components defined in your existing component gallery or dependencies ([live example](https://www.webpackbin.com/bins/-KiTSGFw3fB9Szg7quLI)).
|
||||
|
||||
```js
|
||||
import RaisedButton from 'material-ui/RaisedButton';
|
||||
import { unstable_createElement } from 'react-native-web';
|
||||
import { StyleSheet } from 'react-native';
|
||||
|
||||
const CustomButton = (props) => unstable_createElement(RaisedButton, {
|
||||
...props,
|
||||
style: [ styles.button, props.style ]
|
||||
});
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
button: {
|
||||
padding: 20
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
And `unstable_createElement` can be used as drop-in replacement for `React.createElement`:
|
||||
|
||||
```jsx
|
||||
/* @jsx unstable_createElement */
|
||||
import { unstable_createElement } from 'react-native-web';
|
||||
const Video = (props) => <video {...props} style={[ { marginVertical: 10 }, props.style ]} />
|
||||
```
|
||||
|
||||
Remember that React Native styles are not the same as React DOM styles, and care needs to be taken not to pass React DOM styles into your React Native wrapped components.
|
||||
|
||||
## Use as a library framework
|
||||
|
||||
The React Native (for Web) building blocks can be used to create higher-level components and abstractions. In the example below, a `styled` function provides an API inspired by styled-components ([live example](https://www.webpackbin.com/bins/-KjT9ziwv4O7FDZdvsnX)).
|
||||
|
||||
```jsx
|
||||
import { unstable_createElement } from 'react-native-web';
|
||||
import { StyleSheet } from 'react-native';
|
||||
|
||||
/**
|
||||
* styled API
|
||||
*/
|
||||
const styled = (Component, styler) => {
|
||||
const isDOMComponent = typeof Component === 'string';
|
||||
|
||||
class Styled extends React.Component {
|
||||
static contextTypes = {
|
||||
getTheme: React.PropTypes.func
|
||||
};
|
||||
|
||||
render() {
|
||||
const theme = this.context.getTheme && this.context.getTheme();
|
||||
const localProps = { ...this.props, theme };
|
||||
const nextProps = { ...this.props }
|
||||
const style = typeof styler === 'function' ? styler(localProps) : styler;
|
||||
nextProps.style = [ style, this.props.style ];
|
||||
|
||||
return (
|
||||
isDOMComponent
|
||||
? unstable_createElement(Component, nextProps)
|
||||
: <Component {...nextProps} />
|
||||
);
|
||||
}
|
||||
}
|
||||
return Styled;
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
alignItems: 'center',
|
||||
backgroundColor: '#2196F3',
|
||||
flex: 1,
|
||||
justifyContent: 'center'
|
||||
}
|
||||
});
|
||||
|
||||
const StyledView = styled(View, styles.container);
|
||||
```
|
||||
9
packages/docs/src/pages/docs/components/_.md
Normal file
9
packages/docs/src/pages/docs/components/_.md
Normal file
@@ -0,0 +1,9 @@
|
||||
---
|
||||
title: Components
|
||||
date: Last Modified
|
||||
permalink: false
|
||||
eleventyNavigation:
|
||||
key: Components
|
||||
title: Components
|
||||
order: 20
|
||||
---
|
||||
@@ -0,0 +1,52 @@
|
||||
---
|
||||
title: ActivityIndicator
|
||||
date: Last Modified
|
||||
permalink: /docs/activity-indicator/index.html
|
||||
eleventyNavigation:
|
||||
key: ActivityIndicator
|
||||
parent: Components
|
||||
---
|
||||
|
||||
{% import "fragments/macros.html" as macro with context %}
|
||||
|
||||
:::lead
|
||||
Displays a customizable activity indicator.
|
||||
:::
|
||||
|
||||
```jsx
|
||||
import { ActivityIndicator } from 'react-native';
|
||||
|
||||
<ActivityIndicator {...props} />;
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## API
|
||||
|
||||
### Props
|
||||
|
||||
{% call macro.prop('...ViewProps', '?ViewProps') %}
|
||||
All the props supported by [View]({{ '/docs/view' | url }}).
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('animating', '?boolean') %}
|
||||
Default `true`. Set whether the activity indicator is animating.
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('color', '?string') %}
|
||||
Default `"#1976D2"`. Set the color of the activity indicator.
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('hidesWhenStopped', '?boolean') %}
|
||||
Default `true`. Set whether the activity indicator is hidden when not animating.
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('size', '?("small" | "large" | number)') %}
|
||||
Default `"small"`. Set the size of the activity indicator.
|
||||
{% endcall %}
|
||||
|
||||
---
|
||||
|
||||
## Examples
|
||||
|
||||
{{ macro.codesandbox('activity-indicator') }}
|
||||
58
packages/docs/src/pages/docs/components/button.md
Normal file
58
packages/docs/src/pages/docs/components/button.md
Normal file
@@ -0,0 +1,58 @@
|
||||
---
|
||||
title: Button
|
||||
date: Last Modified
|
||||
permalink: /docs/button/index.html
|
||||
eleventyNavigation:
|
||||
key: Button
|
||||
parent: Components
|
||||
---
|
||||
|
||||
{% import "fragments/macros.html" as macro with context %}
|
||||
|
||||
:::lead
|
||||
A basic button component. Supports a minimal level of customization.
|
||||
:::
|
||||
|
||||
You can also build a custom button using `Pressable`.
|
||||
|
||||
```jsx
|
||||
import { Button } from 'react-native';
|
||||
|
||||
<Button {...props} />;
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## API
|
||||
|
||||
### Props
|
||||
|
||||
{% call macro.prop('accessibilityLabel', '?string') %}
|
||||
Equivalent to [aria-label](https://www.w3.org/TR/wai-aria-1.2/#aria-label).
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('color', '?string') %}
|
||||
Default `"#2196F3"`. Set the background color of the button.
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('disabled', '?boolean') %}
|
||||
Prevent all interactions with the button.
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('onPress', '?(e: ClickEvent) => void') %}
|
||||
Called when the button is pressed by a pointer or keyboard.
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('testID', '?string') %}
|
||||
Set the test selector label (via `data-testid`).
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('title', 'string') %}
|
||||
Set the text content of the button.
|
||||
{% endcall %}
|
||||
|
||||
---
|
||||
|
||||
## Examples
|
||||
|
||||
{{ macro.codesandbox('button') }}
|
||||
60
packages/docs/src/pages/docs/components/checkbox.md
Normal file
60
packages/docs/src/pages/docs/components/checkbox.md
Normal file
@@ -0,0 +1,60 @@
|
||||
---
|
||||
title: CheckBox
|
||||
date: Last Modified
|
||||
permalink: /docs/checkbox/index.html
|
||||
eleventyNavigation:
|
||||
key: CheckBox
|
||||
parent: Components
|
||||
---
|
||||
|
||||
{% import "fragments/macros.html" as macro with context %}
|
||||
|
||||
:::lead
|
||||
An accessible checkbox component with customizable appearance.
|
||||
:::
|
||||
|
||||
`CheckBox` is a controlled component. The `onValueChange` callback should be used to update the `value` prop to reflect user actions. If the `value` prop is not updated, the component will continue to render the supplied `value` prop instead of the expected result of any user actions.
|
||||
|
||||
```jsx
|
||||
import { CheckBox } from 'react-native-web';
|
||||
|
||||
<CheckBox {...props} />;
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## API
|
||||
|
||||
### Props
|
||||
|
||||
{% call macro.prop('...ViewProps', '?ViewProps') %}
|
||||
All the props supported by [View]({{ '/docs/view' | url }}).
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('color', '?string = "#AAB8C2"') %}
|
||||
Set the background color of the checkbox.
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('disabled', '?boolean') %}
|
||||
Prevent all interactions with the checkbox.
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('onChange', '?(e: ChangeEvent) => void') %}
|
||||
Called when the state of the native checkbox changes.
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('onValueChange', '?(value: boolean | "mixed") => void') %}
|
||||
Called when the state of the native checkbox changes.
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('value', '?(boolean | "mixed") = false') %}
|
||||
Set the value of the checkbox.
|
||||
{% endcall %}
|
||||
|
||||
---
|
||||
|
||||
## Examples
|
||||
|
||||
Note that the size of the checkbox can be controlled by changing the `height` and `width` style properties.
|
||||
|
||||
{{ macro.codesandbox('checkbox') }}
|
||||
42
packages/docs/src/pages/docs/components/image-background.md
Normal file
42
packages/docs/src/pages/docs/components/image-background.md
Normal file
@@ -0,0 +1,42 @@
|
||||
---
|
||||
title: ImageBackground
|
||||
date: Last Modified
|
||||
permalink: /docs/image-background/index.html
|
||||
eleventyNavigation:
|
||||
key: ImageBackground
|
||||
parent: Components
|
||||
---
|
||||
|
||||
{% import "fragments/macros.html" as macro with context %}
|
||||
|
||||
:::lead
|
||||
An image component with support for child content.
|
||||
:::
|
||||
|
||||
```jsx
|
||||
import { ImageBackground } from 'react-native';
|
||||
|
||||
<ImageBackground {...props}>{children}</ImageBackground>;
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## API
|
||||
|
||||
### Props
|
||||
|
||||
{% call macro.prop('...ImageProps', '?ImageProps') %}
|
||||
All the props supported by [Image]({{ '/docs/image' | url }}).
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('children', '?any') %}
|
||||
Content to display over the image.
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('imageStyle', '?Style') %}
|
||||
Styles to forward to the image component.
|
||||
{% endcall %}
|
||||
|
||||
## Examples
|
||||
|
||||
{{ macro.codesandbox('image-background') }}
|
||||
104
packages/docs/src/pages/docs/components/image.md
Normal file
104
packages/docs/src/pages/docs/components/image.md
Normal file
@@ -0,0 +1,104 @@
|
||||
---
|
||||
title: Image
|
||||
date: Last Modified
|
||||
permalink: /docs/image/index.html
|
||||
eleventyNavigation:
|
||||
key: Image
|
||||
parent: Components
|
||||
---
|
||||
|
||||
{% import "fragments/macros.html" as macro with context %}
|
||||
|
||||
:::lead
|
||||
An accessible and responsive image component.
|
||||
:::
|
||||
|
||||
This component renders images with flexbox layout and `cover` object-fit (rather than `stretch`) by default.
|
||||
|
||||
```jsx
|
||||
import { Image } from 'react-native';
|
||||
|
||||
<Image {...props} />;
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## API
|
||||
|
||||
### Props
|
||||
|
||||
{% call macro.prop('...ViewProps', '?ViewProps') %}
|
||||
All the props supported by [View]({{ '/docs/view' | url }}).
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('blurRadius', '?number') %}
|
||||
The radius of the blur filter added to the image
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('defaultSource', '?Source') %}
|
||||
A static image to display while loading the image source.
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('draggable', '?boolean = false') %}
|
||||
Set whether the image can be dragged with native browser behavior. (Web-only)
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('onError', '?({ nativeEvent: { error } }) => void') %}
|
||||
Called when the image fails to load.
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('onLoad', '?({ nativeEvent: LoadEvent ) => void') %}
|
||||
Called when the image successfully loads.
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('onLoadEnd', '?() => void') %}
|
||||
Called when image loading ends.
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('onLoadStart', '?() => void') %}
|
||||
Called when the image loading starts.
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('resizeMode', '?("center" | "cover" | "contain" | "none" | "stretch") = "cover"') %}
|
||||
The image source. The string can be a path to an external resource or a base64 encoded resource.
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('source', '?(string | Source)') %}
|
||||
The image source. The string can be a path to an external resource or a base64 encoded resource.
|
||||
{% endcall %}
|
||||
|
||||
#### Source
|
||||
|
||||
{% call macro.prop('height', '?number') %}
|
||||
Set the styles of the view.
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('uri', '?string') %}
|
||||
Set the styles of the view.
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('width', '?number') %}
|
||||
Set the styles of the view.
|
||||
{% endcall %}
|
||||
|
||||
### Statics
|
||||
|
||||
{% call macro.prop('getSize', '?(url: string, complete, failure) => void') %}
|
||||
Download an image and measure the width and height (in pixels) prior to displaying it. This method can fail if the image cannot be found, or fails to download.
|
||||
Complete callback: `(width: number, height: number) => void`.
|
||||
Failure callback: `() => void`.
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('prefetch', '?(url: string) => Promise') %}
|
||||
Prefetches a remote image for later use by downloading it. Once an image has been prefetched it is assumed to be in native browser caches and available for immediate rendering.
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('queryCache', '?(urls: Array<string>) => Promise') %}
|
||||
Performs cache interrogation. Returns a mapping from URL to cache status: "disk", "memory", "disk/memory". If a requested URL is not in the mapping, it means it's not in the cache.
|
||||
{% endcall %}
|
||||
|
||||
---
|
||||
|
||||
## Examples
|
||||
|
||||
{{ macro.codesandbox('image') }}
|
||||
30
packages/docs/src/pages/docs/components/lists.md
Normal file
30
packages/docs/src/pages/docs/components/lists.md
Normal file
@@ -0,0 +1,30 @@
|
||||
---
|
||||
title: Lists
|
||||
date: Last Modified
|
||||
permalink: /docs/lists/index.html
|
||||
eleventyNavigation:
|
||||
key: Lists
|
||||
parent: Components
|
||||
---
|
||||
|
||||
{% import "fragments/macros.html" as macro with context %}
|
||||
|
||||
:::lead
|
||||
Basic support for FlatList, SectionList, and VirtualizedList.
|
||||
:::
|
||||
|
||||
These components are the same JavaScript implementations as those found in React Native. Please refer to the React Native documentation below:
|
||||
|
||||
* [FlatList](https://reactnative.dev/docs/flatlist)
|
||||
* [SectionList](https://reactnative.dev/docs/sectionlist)
|
||||
* [VirtualizedList](https://reactnative.dev/docs/virtualizedlist)
|
||||
|
||||
:::callout
|
||||
**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).
|
||||
:::
|
||||
|
||||
---
|
||||
|
||||
## Examples
|
||||
|
||||
{{ macro.codesandbox('lists') }}
|
||||
61
packages/docs/src/pages/docs/components/modal.md
Normal file
61
packages/docs/src/pages/docs/components/modal.md
Normal file
@@ -0,0 +1,61 @@
|
||||
---
|
||||
title: Modal
|
||||
date: Last Modified
|
||||
permalink: /docs/modal/index.html
|
||||
eleventyNavigation:
|
||||
key: Modal
|
||||
parent: Components
|
||||
label: "New"
|
||||
---
|
||||
|
||||
{% import "fragments/macros.html" as macro with context %}
|
||||
|
||||
:::lead
|
||||
A basic way to present content above an enclosing view. Modals may be nested within other Modals.
|
||||
:::
|
||||
|
||||
```jsx
|
||||
import { Modal } from 'react-native';
|
||||
|
||||
<Modal {...props}>{children}</Modal>;
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## API
|
||||
|
||||
### Props
|
||||
|
||||
{% call macro.prop('animationType', '?("fade" | "none" | "slide")') %}
|
||||
Default is `"none"`. This can be used to add an animation to the modal being opened or closed.
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('children', '?any') %}
|
||||
The children of a `Modal` element will be hidden or shown depending on the modal visibility.
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('onDismiss', '?() => void') %}
|
||||
Called after the modal has been dismissed and is no longer visible.
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('onRequestClose', '?() => void') %}
|
||||
Called when the user is attempting to close the modal like when they hit `Escape`. Only the top-most Modal responds to hitting `Escape`.
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('onShow', '?() => void') %}
|
||||
Called after the modal has been shown and may be visible.
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('transparent', '?boolean = false') %}
|
||||
Determines if the modal is rendered with a transparent backdrop or a white backdrop
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('visible', '?boolean = true') %}
|
||||
Determines if the modal and its content is rendered.
|
||||
{% endcall %}
|
||||
|
||||
---
|
||||
|
||||
## Examples
|
||||
|
||||
{{ macro.codesandbox('modal') }}
|
||||
70
packages/docs/src/pages/docs/components/picker.md
Normal file
70
packages/docs/src/pages/docs/components/picker.md
Normal file
@@ -0,0 +1,70 @@
|
||||
---
|
||||
title: Picker
|
||||
date: Last Modified
|
||||
permalink: /docs/picker/index.html
|
||||
eleventyNavigation:
|
||||
key: Picker
|
||||
parent: Components
|
||||
---
|
||||
|
||||
{% import "fragments/macros.html" as macro with context %}
|
||||
|
||||
:::lead
|
||||
Renders the native `<select>` component
|
||||
:::
|
||||
|
||||
```jsx
|
||||
import { Picker } from 'react-native';
|
||||
|
||||
<Picker {...props}>
|
||||
<Picker.Item />
|
||||
</Picker>;
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## API
|
||||
|
||||
### Props
|
||||
|
||||
{% call macro.prop('...ViewProps', '?ViewProps') %}
|
||||
All the props supported by [View]({{ '/docs/view' | url }}).
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('children', '?(...Picker.Item)') %}
|
||||
The items to display in the picker must be of type `Picker.Item`.
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('enabled', '?boolean = true') %}
|
||||
Determines if the picker will be disabled, i.e., the user will not be able to make a selection.
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('onValueChange', '?(value, index) => void') %}
|
||||
Callback for when an item is selected. This is called with the value and index prop of the item that was selected.
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('selectedValue', '?string') %}
|
||||
Select the item with the matching value.
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('style', '?{ ...ViewProps.style, color: ?string }') %}
|
||||
Supported style properties.
|
||||
{% endcall %}
|
||||
|
||||
### Picker.Item
|
||||
|
||||
{% call macro.prop('color', '?string') %}
|
||||
Color of the item label. (Limited by browser support.)
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('label', '?string') %}
|
||||
Text to display for this item.
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('testID', '?string') %}
|
||||
Used to locate this view in end-to-end tests.
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('value', '?(number | string)') %}
|
||||
The value to be passed to the picker's `onValueChange` callback when this item is selected.
|
||||
{% endcall %}
|
||||
111
packages/docs/src/pages/docs/components/pressable.md
Normal file
111
packages/docs/src/pages/docs/components/pressable.md
Normal file
@@ -0,0 +1,111 @@
|
||||
---
|
||||
title: Pressable
|
||||
date: Last Modified
|
||||
permalink: /docs/pressable/index.html
|
||||
eleventyNavigation:
|
||||
key: Pressable
|
||||
parent: Components
|
||||
label: "New"
|
||||
---
|
||||
|
||||
{% import "fragments/macros.html" as macro with context %}
|
||||
|
||||
:::lead
|
||||
Pressable is a component that can detect various parts of press interactions on any of its defined children.
|
||||
:::
|
||||
|
||||
`Pressable` responds to touch, mouse, and keyboard interactions. The interaction state of the view is exposed to the `children` and `style` props which accept a callback as their value. The `hover` state is only activated by mouse interactions.
|
||||
|
||||
```jsx
|
||||
import { Pressable } from 'react-native';
|
||||
|
||||
<Pressable {...props}>{children}</Pressable>;
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## API
|
||||
|
||||
### Props
|
||||
|
||||
{% call macro.prop('...ViewProps', '?ViewProps') %}
|
||||
All the props supported by [View]({{ '/docs/view' | url }}).
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('children', '?(any | (state: InteractionState) => any)') %}
|
||||
The children of the view. Supports computing children as a function of interaction state.
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('delayLongPress', '?number = 500') %}
|
||||
How long to delay calling `onLongPress` after `onPressIn` is called.
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('delayPressIn', '?number = 0') %}
|
||||
How long to delay calling `onPressIn` after an interaction begins.
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('delayPressOut', '?number = 0') %}
|
||||
How long to delay calling `onPressOut` after an interaction ends.
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('disabled', '?boolean') %}
|
||||
Disables all pointer interactions with the element.
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('onHoverIn', '?(e: MouseEvent) => void') %}
|
||||
Called when the pointer starts hovering over the element. Touch interactions have no effect.
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('onHoverOut', '?(e: MouseEvent) => void') %}
|
||||
Called when the pointer stops hovering over the element. Touch interactions have no effect.
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('onLongPress', '?() => void') %}
|
||||
Called when the pointer is held down for as long as the value of `delayLongPress`.
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('onPress', '?(e: MouseEvent) => void') %}
|
||||
Called when the pointer is released without first being cancelled (e.g. by a scroll that steals the responder lock). Equivalent to the `click` DOM event.
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('onPressIn', '?(e: ResponderEvent) => void') %}
|
||||
Called when the pointer starts interacting with the element after `delayPressIn` ms.
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('onPressOut', '?(e: ResponderEvent) => void') %}
|
||||
Called when the pointer stops interacting with the element after `delayPressOut` ms.
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('style', '?(Style | (state: InteractionState) => Style)') %}
|
||||
The style of the view. Supports computing style as a function of interaction state.
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('testOnly_hovered', '?boolean') %}
|
||||
Used only for documentation or testing (e.g. snapshot testing).
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('testOnly_pressed', '?boolean') %}
|
||||
Used only for documentation or testing (e.g. snapshot testing).
|
||||
{% endcall %}
|
||||
|
||||
### InteractionState
|
||||
|
||||
The state object passed to function values of `children` and `state` reflects the current state of the user interaction with the view.
|
||||
|
||||
{% call macro.prop('focused', 'boolean') %}
|
||||
Whether the view is currently focused.
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('hovered', 'boolean') %}
|
||||
Whether the view is being hovered over by a mouse.
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('pressed', 'boolean') %}
|
||||
Whether the view is being pressed by a pointer or keyboard interaction key.
|
||||
{% endcall %}
|
||||
|
||||
---
|
||||
|
||||
## Examples
|
||||
|
||||
{{ macro.codesandbox('pressable') }}
|
||||
54
packages/docs/src/pages/docs/components/progress-bar.md
Normal file
54
packages/docs/src/pages/docs/components/progress-bar.md
Normal file
@@ -0,0 +1,54 @@
|
||||
---
|
||||
title: ProgressBar
|
||||
date: Last Modified
|
||||
permalink: /docs/progress-bar/index.html
|
||||
eleventyNavigation:
|
||||
key: ProgressBar
|
||||
parent: Components
|
||||
---
|
||||
|
||||
{% import "fragments/macros.html" as macro with context %}
|
||||
|
||||
:::lead
|
||||
Display an activity progress bar.
|
||||
:::
|
||||
|
||||
```jsx
|
||||
import { ProgressBar } from 'react-native';
|
||||
|
||||
<ProgressBar {...props} />;
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## API
|
||||
|
||||
### Props
|
||||
|
||||
{% call macro.prop('...ViewProps', '?ViewProps') %}
|
||||
All the props supported by [View]({{ '/docs/view' | url }}).
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('color', '?string = "#1976D2"') %}
|
||||
Set the background color of the button.
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('indeterminate', '?boolean = false') %}
|
||||
Whether the progress bar will show indeterminate progress.
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('progress', '?number = 0') %}
|
||||
The progress value between `0` and `1`.
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('trackColor', '?string = "transparent"') %}
|
||||
Customize the color of the track bar.
|
||||
{% endcall %}
|
||||
|
||||
---
|
||||
|
||||
## Examples
|
||||
|
||||
Custom sizes can be created using style properties.
|
||||
|
||||
{{ macro.codesandbox('progress-bar') }}
|
||||
117
packages/docs/src/pages/docs/components/scoll-view.md
Normal file
117
packages/docs/src/pages/docs/components/scoll-view.md
Normal file
@@ -0,0 +1,117 @@
|
||||
---
|
||||
title: ScrollView
|
||||
date: Last Modified
|
||||
permalink: /docs/scroll-view/index.html
|
||||
eleventyNavigation:
|
||||
key: ScrollView
|
||||
parent: Components
|
||||
---
|
||||
|
||||
{% import "fragments/macros.html" as macro with context %}
|
||||
|
||||
:::lead
|
||||
A scrollable view that provides integration with the pointer-locking responder system.
|
||||
:::
|
||||
|
||||
ScrollView must have a bounded height: either set the height of the view directly (discouraged) or make sure all parent views have bounded height (e.g., apply `{ flex: 1}` down the view stack).
|
||||
|
||||
```jsx
|
||||
import { ScrollView } from 'react-native';
|
||||
|
||||
<ScrollView {...props}>{children}</ScrollView>;
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## API
|
||||
|
||||
### Props
|
||||
|
||||
{% call macro.prop('...ViewProps', '?ViewProps') %}
|
||||
All the props supported by [View]({{ '/docs/view' | url }}).
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('contentContainerStyle', '?Style') %}
|
||||
These styles will be applied to the scroll view content container which wraps all of the child views.
|
||||
{% endcall %}
|
||||
|
||||
|
||||
{% call macro.prop('disableScrollViewPanResponder', '?boolean = false') %}
|
||||
When `true`, the default `PanResponder` on the `ScrollView` is disabled, and full control over pointers inside the `ScrollView` is left to its child components. This is meant to be used when native "snap-to" scrolling behavior is needed.
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('horizontal', '?boolean = false') %}
|
||||
When `true`, the scroll view's children are arranged horizontally in a row instead of vertically in a column.
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('keyboardDismissMode', '?("none" | "on-drag")') %}
|
||||
Determines whether the keyboard gets dismissed in response to a scroll drag.
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('onContentSizeChange', '?(width: number, height: number) => void') %}
|
||||
Called when scrollable content view of the ScrollView changes.
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('onScroll', '?(e: ScrollEvent) => void') %}
|
||||
Called during scrolling. The frequency of the events can be controlled using the `scrollEventThrottle` prop.
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('pagingEnabled', '?boolean = false') %}
|
||||
When `true`, the scroll view snaps to individual items in the list when scrolling.
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('scrollEnabled', '?boolean = true') %}
|
||||
When `false`, the content does not scroll.
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('scrollEventThrottle', '?number = 0') %}
|
||||
This controls how often the scroll event will be fired while scrolling (as a time interval in ms). A lower number yields better accuracy for code that is tracking the scroll position, but can lead to scroll performance problems. The default value is `0`, which means the scroll event will be sent only once each time the view is scrolled.
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('stickyHeaderIndices', '?Array<number>') %}
|
||||
An array of child indices determining which children get docked to the top of the screen when scrolling. For example, passing `stickyHeaderIndices={0}` will cause the first child to be fixed to the top of the scroll view. This property is not supported in conjunction with the `horizontal` prop.
|
||||
{% endcall %}
|
||||
|
||||
### ScrollEvent
|
||||
|
||||
The `nativeEvent` on the event passed to `onScroll` is a custom object of information related to the layout of the ScrollView.
|
||||
|
||||
{% call macro.prop('contentOffset', '{ x: number, y: number}') %}
|
||||
How far the scroll view is scrolled along each axis.
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('contentSize', '{ height: number, width: number}') %}
|
||||
The size of the scrollable content area.
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('layoutMeasurement', '{ height: number, width: number}') %}
|
||||
The `border-box` height and width of the scroll view.
|
||||
{% endcall %}
|
||||
|
||||
### Instant methods
|
||||
|
||||
{% call macro.prop('getInnerViewNode', '() => void') %}
|
||||
Returns a reference to the underlying content container DOM node within the `ScrollView`.
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('getScrollableNode', '() => void') %}
|
||||
Returns a reference to the underlying scrollable DOM node.
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('getScrollResponder', '() => void') %}
|
||||
Returns a reference to the underlying scroll responder, which supports operations like `scrollTo()`. All `ScrollView`-like components should implement this method so that they can be composed while providing access to the underlying scroll responder's methods.
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('scrollTo', '(options?: { x: number, y: number, animated: boolean }) => void') %}
|
||||
Scrolls to a given `x`, `y` offset (animation depends on browser support for scroll-behavior).
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('scrollToEnd', '(options?: { animated: boolean }) => void') %}
|
||||
Scrolls to the end of the scroll view.
|
||||
{% endcall %}
|
||||
|
||||
---
|
||||
|
||||
## Examples
|
||||
|
||||
{{ macro.codesandbox('scroll-view') }}
|
||||
68
packages/docs/src/pages/docs/components/switch.md
Normal file
68
packages/docs/src/pages/docs/components/switch.md
Normal file
@@ -0,0 +1,68 @@
|
||||
---
|
||||
title: Switch
|
||||
date: Last Modified
|
||||
permalink: /docs/switch/index.html
|
||||
eleventyNavigation:
|
||||
key: Switch
|
||||
parent: Components
|
||||
---
|
||||
|
||||
{% import "fragments/macros.html" as macro with context %}
|
||||
|
||||
:::lead
|
||||
A controlled component that renders a boolean input.
|
||||
:::
|
||||
|
||||
`Switch` requires an onValueChange callback that updates the value prop in order for the component to reflect user actions. If the value prop is not updated, the component will continue to render the supplied value prop instead of the expected result of any user actions.
|
||||
|
||||
```jsx
|
||||
import { Switch } from 'react-native';
|
||||
|
||||
<Switch {...props} />;
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## API
|
||||
|
||||
### Props
|
||||
|
||||
{% call macro.prop('...ViewProps', '?ViewProps') %}
|
||||
All the props supported by [View]({{ '/docs/view' | url }}).
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('activeThumbColor', '?string = "#009688"') %}
|
||||
The color of the thumb grip when the switch is turned on. (Web-only)
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('activeTrackColor', '?string = "#A3D3CF"') %}
|
||||
The color of the track when the switch is turned on. (Web-only)
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('disabled', '?boolean') %}
|
||||
Disables interactions with the element. If `true`, the user won't be able to interact with the switch.
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('onValueChange', '?(boolean) => void') %}
|
||||
Invoked with the new value when the value changes.
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('thumbColor', '?string = "#FAFAFA"') %}
|
||||
The color of the thumb grip when the switch is turned off.
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('trackColor', '?string => "#939393"') %}
|
||||
The color of the track when the switch is turned off.
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('value', '?boolean = false') %}
|
||||
The value of the switch. If `true` the switch will be turned on.
|
||||
{% endcall %}
|
||||
|
||||
---
|
||||
|
||||
## Examples
|
||||
|
||||
Custom sizes can be created using styles.
|
||||
|
||||
{{ macro.codesandbox('switch') }}
|
||||
206
packages/docs/src/pages/docs/components/text-input.md
Normal file
206
packages/docs/src/pages/docs/components/text-input.md
Normal file
@@ -0,0 +1,206 @@
|
||||
---
|
||||
title: TextInput
|
||||
date: Last Modified
|
||||
permalink: /docs/text-input/index.html
|
||||
eleventyNavigation:
|
||||
key: TextInput
|
||||
parent: Components
|
||||
---
|
||||
|
||||
{% import "fragments/macros.html" as macro with context %}
|
||||
|
||||
:::lead
|
||||
Accessible single- and multi-line text input via a keyboard.
|
||||
:::
|
||||
|
||||
Supports features such as auto-complete, auto-focus, placeholder text, and event callbacks. Note: some props are exclusive to or excluded from `multiline`.
|
||||
|
||||
```jsx
|
||||
import { TextInput } from 'react-native-web';
|
||||
|
||||
<TextInput {...props} />;
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## API
|
||||
|
||||
### Props
|
||||
|
||||
{% call macro.prop('...AccessibilityProps') %}
|
||||
The [accessibility props]({{ '/docs/accessibility' | url }}).
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('...ClickProps') %}
|
||||
The [click props]({{ '/docs/interactions' | url }}).
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('...FocusProps') %}
|
||||
The [focus props]({{ '/docs/interactions' | url }}).
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('autoCapitalize', '?string') %}
|
||||
Equivalent to [HTMLElement.autocapitalize](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/autocapitalize).
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('autoComplete', '?string') %}
|
||||
Equivalent to [HTMLElement.autocomplete](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/autocomplete).
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('autoCorrect', '?("on" | "off")') %}
|
||||
A string indicating whether or not auto-correct behavior is on or off. Safari only.
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('autoFocus', '?boolean = false') %}
|
||||
If `true`, focuses the input on mount. Only the first form element in a document with auto-focus is focused.
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('blurOnSubmit', '?boolean') %}
|
||||
If `true`, the text field will blur when submitted. The default value is `true` for single-line fields and `false` for multiline fields. Note, for multiline fields setting `blurOnSubmit` to `true` means that pressing return will blur the field and trigger the `onSubmitEditing` event instead of inserting a newline into the field.
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('clearTextOnFocus', '?boolean = false') %}
|
||||
If `true`, clears the text field automatically when focused.
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('dataSet', '?Object') %}
|
||||
Equivalent to [HTMLElement.dataset](https://developer.mozilla.org/en-US/docs/Web/API/HTMLOrForeignElement/dataset).
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('defaultValue', '?string') %}
|
||||
The initial value of the input. Useful for simple use-cases where you don't want to deal with listening to events and updating the value prop to keep the controlled state in sync.
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('direction', '?("auto" | "ltr" | "rtl") = "auto"') %}
|
||||
Equivalent to [HTMLElement.dir](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/dir)
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('disabled', '?boolean = false') %}
|
||||
Equivalent to [HTMLElement.disabled](https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/disabled)
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('editable', '?boolean = true') %}
|
||||
Equivalent to [HTMLElement.readonly](https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/readonly)
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('keyboardType', '?string') %}
|
||||
Hints at the type of data that might be entered by the user while editing the element or its contents. Equivalent to [HTMLElement.inputMode](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/inputmode). Safari iOS requires an ancestral <form action> element to display the search keyboard. (Not available when multiline is true.)
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('lang', '?string') %}
|
||||
Equivalent to [HTMLElement.lang](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/lang).
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('maxLength', '?string') %}
|
||||
Equivalent to [HTMLElement.maxlength](https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/maxlength).
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('multiline', '?boolean = false') %}
|
||||
If `true`, the text input can be multiple lines.
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('nativeID', '?string') %}
|
||||
Equivalent to [HTMLElement.id](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/id).
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('numberOfLines', '?number = 1') %}
|
||||
Sets the number of lines for a multiline input. (Requires `multiline` to be `true`.)
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('onChange', '?(e: ChangeEvent) => void') %}
|
||||
Equivalent to the React DOM `ChangeEvent`.
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('onChangeText', '?(text: string) => void') %}
|
||||
Called when the text content of the input changes.
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('onContentSizeChange', '?({ nativeEvent: { contentSize: { width, height } } }) => void') %}
|
||||
Callback that is called when the text input's content size changes.
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('onKeyPress', '?(e: KeyboardEvent) => void') %}
|
||||
Equivalent to the [onKeyDown prop]({{ '/docs/interactions' | url }}).
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('onLayout', '?({ nativeEvent: { layout: { x, y, width, height } } }) => void') %}
|
||||
This is invoked when a component is mounted and when its layout changes. `x` and `y` are the offsets from the parent node.
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('onScroll', '?(e: ScrollEvent) => void') %}
|
||||
Called during scrolling.
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('onSelectionChange', '?({ nativeEvent: { selection: { start, end } } }) => void') %}
|
||||
Callback that is called when the text input's selection changes.
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('onSubmitEditing', '?() => void') %}
|
||||
Callback that is called when the keyboard's submit button is pressed. When `multiline={true}`, this is only called if `blurOnSubmit={true}`.
|
||||
{% endcall %}
|
||||
|
||||
|
||||
|
||||
{% call macro.prop('placeholder', '?boolean') %}
|
||||
Text that appears in the form control when it has no value set.
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('placeholderTextColor', '?string') %}
|
||||
Equivalent to defining `::placeholder { color }` via a CSS property.
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('required', '?boolean') %}
|
||||
Equivalent to [HTMLElement.required](https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/required)
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('returnKeyType', '?string') %}
|
||||
Specifies what action label (or icon) to present for the enter key on virtual keyboards. Equivalent to [HTMLElement.enterkeyhint](https://html.spec.whatwg.org/multipage/interaction.html#input-modalities:-the-enterkeyhint-attribute)
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('secureTextEntry', '?boolean = false') %}
|
||||
Set to `true` for passwords and other sensitive data. Equivalent to HTMLInputElement ["password" `type`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/password). (Not available when `multiline` is `true`.)
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('selectTextOnFocus', '?boolean = false') %}
|
||||
If `true`, all text will automatically be selected on focus.
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('spellCheck', '?boolean') %}
|
||||
Equivalent to [HTMLElement.spellcheck](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/spellcheck)
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('style', '?Style') %}
|
||||
Set the styles of the view. `TextInput` supports typographic styles in addition to those of `View`.
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('testID', '?string') %}
|
||||
Set the test selector label (via `data-testid`).
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('value', '?string') %}
|
||||
The value of the input when using it as a controlled component.
|
||||
{% endcall %}
|
||||
|
||||
### Instance methods
|
||||
|
||||
{% call macro.prop('blur', '() => void') %}
|
||||
Blur the underlying DOM input.
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('clear', '() => void') %}
|
||||
Clear the text from the underlying DOM input.
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('focus', '() => void') %}
|
||||
Focus the underlying DOM input.
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('isFocused', '() => boolean') %}
|
||||
Returns `true` if the input is currently focused; `false` otherwise.
|
||||
{% endcall %}
|
||||
|
||||
---
|
||||
|
||||
## Examples
|
||||
|
||||
{{ macro.codesandbox('text-input') }}
|
||||
111
packages/docs/src/pages/docs/components/text.md
Normal file
111
packages/docs/src/pages/docs/components/text.md
Normal file
@@ -0,0 +1,111 @@
|
||||
---
|
||||
title: Text
|
||||
date: Last Modified
|
||||
permalink: /docs/text/index.html
|
||||
eleventyNavigation:
|
||||
key: Text
|
||||
parent: Components
|
||||
label: "Change"
|
||||
---
|
||||
|
||||
{% import "fragments/macros.html" as macro with context %}
|
||||
|
||||
:::lead
|
||||
The fundamental text primitive. `Text` inherits typographic styles from ancestor `Text` elements.
|
||||
:::
|
||||
|
||||
`Text` has built in accessibility controls, enforces inline layout by default, provides limited inheritance of text styles, and supports `View` as children. It inherits typographic styles from ancestor `Text` elements (as long as the chain of text elements is not interrupted by a `View`). By default, text is rendered using the native platform’s algorithm to determine the directionality of the content language.
|
||||
|
||||
```jsx
|
||||
import { Text } from 'react-native';
|
||||
|
||||
<Text {...props}>{children}</Text>;
|
||||
```
|
||||
|
||||
::: callout
|
||||
**Did you know?** Text styling in {{ site.name }} has stricter rules than it does on the web. Read the [Styling]({{ '/docs/styling' | url }}) guide to learn more.
|
||||
:::
|
||||
|
||||
---
|
||||
|
||||
## API
|
||||
|
||||
### Props
|
||||
|
||||
{% call macro.prop('...AccessibilityProps') %}
|
||||
The [accessibility props]({{ '/docs/accessibility' | url }}).
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('...ClickProps') %}
|
||||
The [click props]({{ '/docs/interactions' | url }}).
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('...FocusProps') %}
|
||||
The [focus props]({{ '/docs/interactions' | url }}).
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('...KeyboardProps') %}
|
||||
The [keyboard props]({{ '/docs/interactions' | url }}).
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('...ResponderProps') %}
|
||||
The [responder props]({{ '/docs/interactions' | url }}).
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('children', 'any') %}
|
||||
The children of a `Text` element can be strings as well as other elements like `<View />` and `<Image />`. Nested text components will inherit the typographic styles of their parents.
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('dataSet', '?Object') %}
|
||||
Equivalent to [HTMLElement.dataset](https://developer.mozilla.org/en-US/docs/Web/API/HTMLOrForeignElement/dataset).
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('dir', '?("auto" | "ltr" | "rtl") = "auto"') %}
|
||||
Equivalent to [HTMLElement.dir](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/dir). The default value of `"auto"` is not set on *nested* text elements.
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('focusable', '?boolean') %}
|
||||
Set whether the view can receive keyboard focus.
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('href', '?string') %}
|
||||
If `href` is defined, the view is rendered as an anchor tag pointing to this URL.
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('hrefAttrs', '?Object') %}
|
||||
If `href` is defined, this prop defines related attributes to include on the anchor (e.g., `download`, `rel`, `target`) which may modify its behavior.
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('lang', '?string') %}
|
||||
Equivalent to [HTMLElement.lang](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/lang).
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('nativeID', '?string') %}
|
||||
Equivalent to [HTMLElement.id](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/id).
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('numberOfLines', '?number') %}
|
||||
Truncates the text with an ellipsis after this many lines.
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('onLayout', '?({ nativeEvent: { layout: { x, y, width, height } } }) => void') %}
|
||||
This is invoked when a component is mounted and when its layout changes. `x` and `y` are the offsets from the parent node.
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('selectable', '?boolean = true') %}
|
||||
When `false`, the text is not selectable.
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('style', '?Style') %}
|
||||
Set the styles of the text. `Text` supports typographic styles in addition to those of `View`.
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('testID', '?string') %}
|
||||
Set the test selector label (via `data-testid`).
|
||||
{% endcall %}
|
||||
|
||||
---
|
||||
|
||||
## Examples
|
||||
|
||||
{{ macro.codesandbox('text') }}
|
||||
25
packages/docs/src/pages/docs/components/touchables.md
Normal file
25
packages/docs/src/pages/docs/components/touchables.md
Normal file
@@ -0,0 +1,25 @@
|
||||
---
|
||||
title: Touchables
|
||||
date: Last Modified
|
||||
permalink: /docs/touchables/index.html
|
||||
eleventyNavigation:
|
||||
key: Touchables
|
||||
parent: Components
|
||||
---
|
||||
|
||||
|
||||
{% import "fragments/macros.html" as macro with context %}
|
||||
|
||||
:::lead
|
||||
Components for making views respond to touch, mouse, and keyboard on web.
|
||||
:::
|
||||
|
||||
Please refer to the React Native documentation below:
|
||||
|
||||
* [TouchableHighlight](https://reactnative.dev/docs/touchablehighlight)
|
||||
* [TouchableOpacity](https://reactnative.dev/docs/touchableopacity)
|
||||
* [TouchableWithoutFeedback](https://reactnative.dev/docs/touchablewithoutfeedback)
|
||||
|
||||
:::callout
|
||||
**Did you know?** The [Pressable]({{ '/docs/pressable' }}) component is a more accessible, flexible, and future-proof way to handle tap and click interactions with React Native.
|
||||
:::
|
||||
105
packages/docs/src/pages/docs/components/view.md
Normal file
105
packages/docs/src/pages/docs/components/view.md
Normal file
@@ -0,0 +1,105 @@
|
||||
---
|
||||
title: View
|
||||
date: Last Modified
|
||||
permalink: /docs/view/index.html
|
||||
eleventyNavigation:
|
||||
key: View
|
||||
parent: Components
|
||||
label: "Change"
|
||||
---
|
||||
|
||||
{% import "fragments/macros.html" as macro with context %}
|
||||
|
||||
:::lead
|
||||
The fundamental layout primitive.
|
||||
:::
|
||||
|
||||
View uses a flexbox column layout by default. Every instance of `View` uses relative positioning by default and the `zIndex` can only be used to control the relative Z-axis stacking of siblings within their parent.
|
||||
|
||||
Raw text nodes are **not** allowed as children of View. A View nested within a Text will render inline without altering its display or that of its children.
|
||||
|
||||
```jsx
|
||||
import { View } from 'react-native';
|
||||
|
||||
<View {...props}>{children}</View>;
|
||||
```
|
||||
|
||||
:::callout
|
||||
**Did you know?** `View` elements do not support text content or text styles. Style properties like `fontFamily` are only supported on `Text` and `TextInput` elements.
|
||||
:::
|
||||
|
||||
---
|
||||
|
||||
## API
|
||||
|
||||
### Props
|
||||
|
||||
{% call macro.prop('...AccessibilityProps') %}
|
||||
The [accessibility props]({{ '/docs/accessibility' | url }}).
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('...ClickProps') %}
|
||||
The [click props]({{ '/docs/interactions' | url }}).
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('...FocusProps') %}
|
||||
The [focus props]({{ '/docs/interactions' | url }}).
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('...KeyboardProps') %}
|
||||
The [keyboard props]({{ '/docs/interactions' | url }}).
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('...ResponderProps') %}
|
||||
The [responder props]({{ '/docs/interactions' | url }}).
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('children', 'any') %}
|
||||
The children of a `View` element can be other elements and must *not* include strings (or components that render down to strings).
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('dataSet', '?Object') %}
|
||||
Equivalent to [HTMLElement.dataset](https://developer.mozilla.org/en-US/docs/Web/API/HTMLOrForeignElement/dataset).
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('dir', '?("ltr" | "rtl")') %}
|
||||
Equivalent to [HTMLElement.dir](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/dir)
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('focusable', '?boolean') %}
|
||||
Set whether the view can receive keyboard focus.
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('href', '?string') %}
|
||||
If `href` is defined, the view is rendered as an anchor tag pointing to this URL.
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('hrefAttrs', '?Object') %}
|
||||
If `href` is defined, this prop defines related attributes to include on the anchor (e.g., `download`, `rel`, `target`) which may modify its behavior.
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('nativeID', '?string') %}
|
||||
Equivalent to [HTMLElement.id](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/id).
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('onLayout', '?({ nativeEvent: { layout: { x, y, width, height } } }) => void') %}
|
||||
This is invoked when a component is mounted and when its layout changes. `x` and `y` are the offsets from the parent node.
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('pointerEvents', '?("all" | "none" | "box-only" | "box-none")') %}
|
||||
Equivalent to [CSS pointer-events](https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events) with 2 additional values. A value of `"box-none"` preserves pointer events on the element's children; `"box-only"` disables pointer events on the element's children.
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('style', '?Style') %}
|
||||
Set the styles of the view.
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('testID', '?string') %}
|
||||
Set the test selector label (via `data-testid`).
|
||||
{% endcall %}
|
||||
|
||||
---
|
||||
|
||||
## Examples
|
||||
|
||||
{{ macro.codesandbox('view') }}
|
||||
9
packages/docs/src/pages/docs/concepts/_.md
Normal file
9
packages/docs/src/pages/docs/concepts/_.md
Normal file
@@ -0,0 +1,9 @@
|
||||
---
|
||||
title: Main concepts
|
||||
date: Last Modified
|
||||
permalink: false
|
||||
eleventyNavigation:
|
||||
key: Concepts
|
||||
title: Main concepts
|
||||
order: 10
|
||||
---
|
||||
292
packages/docs/src/pages/docs/concepts/accessibility.md
Normal file
292
packages/docs/src/pages/docs/concepts/accessibility.md
Normal file
@@ -0,0 +1,292 @@
|
||||
---
|
||||
title: Accessibility
|
||||
date: Last Modified
|
||||
permalink: /docs/accessibility/index.html
|
||||
eleventyNavigation:
|
||||
key: Accessibility
|
||||
parent: Concepts
|
||||
label: "Change"
|
||||
---
|
||||
|
||||
{% import "fragments/macros.html" as macro with context %}
|
||||
|
||||
:::lead
|
||||
Familiar web accessibility APIs in a platform-agnostic form.
|
||||
:::
|
||||
|
||||
Accessibility in {{ site.name }} combines several separate web APIs into a cohesive system. Assistive technologies (e.g., VoiceOver, TalkBack screen readers) derive useful information about the structure, purpose, and interactivity of web apps from their [HTML elements][html-accessibility-url], attributes, and [ARIA in HTML][aria-in-html-url].
|
||||
|
||||
---
|
||||
|
||||
## Accessibility Props API
|
||||
|
||||
{{ site.name }} includes APIs for making accessible apps. The most common and well supported accessibility features of the Web are exposed as platform-agnostic `accessibility*` props.
|
||||
|
||||
{% call macro.prop('accessibilityActiveDescendant', '?string') %}
|
||||
Equivalent to [aria-activedescendant](https://www.w3.org/TR/wai-aria-1.2/#aria-activedescendant).
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('accessibilityAtomic', '?boolean') %}
|
||||
Equivalent to [aria-atomic](https://www.w3.org/TR/wai-aria-1.2/#aria-atomic).
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('accessibilityAutoComplete', '?string') %}
|
||||
Equivalent to [aria-autocomplete](https://www.w3.org/TR/wai-aria-1.2/#aria-autocomplete).
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('accessibilityBusy', '?boolean') %}
|
||||
Equivalent to [aria-busy](https://www.w3.org/TR/wai-aria-1.2/#aria-busy).
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('accessibilityChecked', '?(boolean | "mixed")') %}
|
||||
Equivalent to [aria-checked](https://www.w3.org/TR/wai-aria-1.2/#aria-checked).
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('accessibilityColumnCount', '?number') %}
|
||||
Equivalent to [aria-colcount](https://www.w3.org/TR/wai-aria-1.2/#aria-colcount).
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('accessibilityColumnIndex', '?number') %}
|
||||
Equivalent to [aria-colindex](https://www.w3.org/TR/wai-aria-1.2/#aria-colindex).
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('accessibilityColumnSpan', '?number') %}
|
||||
Equivalent to [aria-colspan](https://www.w3.org/TR/wai-aria-1.2/#aria-colspan).
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('accessibilityControls', '?string') %}
|
||||
Equivalent to [aria-controls](https://www.w3.org/TR/wai-aria-1.2/#aria-controls).
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('accessibilityDescribedBy', '?string') %}
|
||||
Equivalent to [aria-describedby](https://www.w3.org/TR/wai-aria-1.2/#aria-describedby).
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('accessibilityDetails', '?string') %}
|
||||
Equivalent to [aria-details](https://www.w3.org/TR/wai-aria-1.2/#aria-details).
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('accessibilityDisabled', '?boolean') %}
|
||||
Equivalent to [aria-disabled](https://www.w3.org/TR/wai-aria-1.2/#aria-disabled).
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('accessibilityErrorMessage', '?string') %}
|
||||
Equivalent to [aria-errormessage](https://www.w3.org/TR/wai-aria-1.2/#aria-errormessage).
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('accessibilityExpanded', '?boolean') %}
|
||||
Equivalent to [aria-expanded](https://www.w3.org/TR/wai-aria-1.2/#aria-expanded).
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('accessibilityFlowTo', '?string') %}
|
||||
Equivalent to [aria-flowto](https://www.w3.org/TR/wai-aria-1.2/#aria-flowto).
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('accessibilityHasPopup', '?string') %}
|
||||
Equivalent to [aria-haspopup](https://www.w3.org/TR/wai-aria-1.2/#aria-haspopup).
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('accessibilityHidden', '?boolean') %}
|
||||
Equivalent to [aria-hidden](https://www.w3.org/TR/wai-aria-1.2/#aria-hidden).
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('accessibilityInvalid', '?boolean') %}
|
||||
Equivalent to [aria-invalid](https://www.w3.org/TR/wai-aria-1.2/#aria-invalid).
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('accessibilityKeyShortcuts', '?Array<string>') %}
|
||||
Equivalent to [aria-keyshortcuts](https://www.w3.org/TR/wai-aria-1.2/#aria-keyshortcuts).
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('accessibilityLabel', '?string') %}
|
||||
Equivalent to [aria-label](https://www.w3.org/TR/wai-aria-1.2/#aria-label).
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('accessibilityLabelledBy', '?string') %}
|
||||
Equivalent to [aria-labelledby](https://www.w3.org/TR/wai-aria-1.2/#aria-labelledby).
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('accessibilityLiveRegion', '?("assertive" | "off" | "polite")') %}
|
||||
Equivalent to [aria-live](https://www.w3.org/TR/wai-aria-1.2/#aria-live).
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('accessibilityModal', '?boolean') %}
|
||||
Equivalent to [aria-modal](https://www.w3.org/TR/wai-aria-1.2/#aria-modal).
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('accessibilityMultiline', '?boolean') %}
|
||||
Equivalent to [aria-multiline](https://www.w3.org/TR/wai-aria-1.2/#aria-multiline).
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('accessibilityMultiSelectable', '?boolean') %}
|
||||
Equivalent to [aria-multiselectable](https://www.w3.org/TR/wai-aria-1.2/#aria-multiselectable).
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('accessibilityOrientation', '?("horizontal" | "vertical")') %}
|
||||
Equivalent to [aria-orientation](https://www.w3.org/TR/wai-aria-1.2/#aria-orientation).
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('accessibilityOwns', '?string') %}
|
||||
Equivalent to [aria-owns](https://www.w3.org/TR/wai-aria-1.2/#aria-owns).
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('accessibilityPlaceholder', '?string') %}
|
||||
Equivalent to [aria-placeholder](https://www.w3.org/TR/wai-aria-1.2/#aria-placeholder).
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('accessibilityPosInSet', '?number') %}
|
||||
Equivalent to [aria-posinset](https://www.w3.org/TR/wai-aria-1.2/#aria-posinset).
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('accessibilityPressed', '?boolean') %}
|
||||
Equivalent to [aria-pressed](https://www.w3.org/TR/wai-aria-1.2/#aria-pressed).
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('accessibilityReadOnly', '?boolean') %}
|
||||
Equivalent to [aria-readonly](https://www.w3.org/TR/wai-aria-1.2/#aria-readonly).
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('accessibilityRequired', '?boolean') %}
|
||||
Equivalent to [aria-required](https://www.w3.org/TR/wai-aria-1.2/#aria-required).
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('accessibilityRole', '?boolean') %}
|
||||
Equivalent to [role](https://www.w3.org/TR/wai-aria-1.2/#role_definitions).
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('accessibilityRoleDescription', '?string') %}
|
||||
Equivalent to [aria-roledescription](https://www.w3.org/TR/wai-aria-1.2/#aria-roledescription).
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('accessibilityRowCount', '?number') %}
|
||||
Equivalent to [aria-rowcount](https://www.w3.org/TR/wai-aria-1.2/#aria-rowcount).
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('accessibilityRowIndex', '?number') %}
|
||||
Equivalent to [aria-rowindex](https://www.w3.org/TR/wai-aria-1.2/#aria-rowindex).
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('accessibilityRowSpan', '?number') %}
|
||||
Equivalent to [aria-rowspan](https://www.w3.org/TR/wai-aria-1.2/#aria-rowspan).
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('accessibilitySelected', '?boolean') %}
|
||||
Equivalent to [aria-selected](https://www.w3.org/TR/wai-aria-1.2/#aria-selected).
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('accessibilitySetSize', '?number') %}
|
||||
Equivalent to [aria-setsize](https://www.w3.org/TR/wai-aria-1.2/#aria-setsize).
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('accessibilitySort', '?("ascending" | "descending" | "none" | "other")') %}
|
||||
Equivalent to [aria-sort](https://www.w3.org/TR/wai-aria-1.2/#aria-sort).
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('accessibilityValueMax', '?number') %}
|
||||
Equivalent to [aria-valuemax](https://www.w3.org/TR/wai-aria-1.2/#aria-valuemax).
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('accessibilityValueMin', '?number') %}
|
||||
Equivalent to [aria-valuemin](https://www.w3.org/TR/wai-aria-1.2/#aria-valuemin).
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('accessibilityValueNow', '?number') %}
|
||||
Equivalent to [aria-valuenow](https://www.w3.org/TR/wai-aria-1.2/#aria-valuenow).
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('accessibilityValueText', '?string') %}
|
||||
Equivalent to [aria-valuetext](https://www.w3.org/TR/wai-aria-1.2/#aria-valuetext).
|
||||
{% endcall %}
|
||||
|
||||
---
|
||||
|
||||
## Accessibility patterns
|
||||
|
||||
### Links
|
||||
|
||||
The `Text` and `View` components can be rendered as links. If the `href` prop is set, the element will render `<a>` tags without altering the presentation of the element.
|
||||
|
||||
```jsx
|
||||
<Text href="/" />
|
||||
// <a href="/" ></a>
|
||||
```
|
||||
|
||||
The `hrefAttrs` prop sets link-related attributes.
|
||||
|
||||
```jsx
|
||||
const hrefAttrs = { download: true, rel: "nofollow", target: "blank" };
|
||||
|
||||
<Text
|
||||
href="/document.pdf"
|
||||
hrefAttrs={hrefAttrs}
|
||||
/>
|
||||
// <a download href="/document.pdf" rel="nofollow" target="_blank"></a>
|
||||
```
|
||||
|
||||
### Keyboard focus
|
||||
|
||||
The `focusable` prop determines whether a component is user-focusable and appears in the keyboard tab flow. This prop should be used instead of the `accessible` prop found in React Native for Android/iOS, which is not implemented by React Native for Web/Windows/macOS.
|
||||
|
||||
```jsx
|
||||
<View focusable={true} />
|
||||
// <div tabindex="0"></div>
|
||||
|
||||
<Text focusable={false} href="/" />
|
||||
// <a href="/" tabindex="-1"></a>
|
||||
```
|
||||
|
||||
:::callout
|
||||
**Did you know?** Any element (including elements not in the keybaord tab flow) can be programmatically focused from its ref: `viewRef.current.focus()`.
|
||||
:::
|
||||
|
||||
### Accessible HTML
|
||||
|
||||
{{ site.name }} components express semantics exclusively via the `accessibility*` props which are equivalent to `aria-*` attributes. For example, `accessibilityRole` is equivalent to the HTML `role` attribute, `accessibilityLabel` is equivalent to `aria-label`, etc. (Additional compatibility with React Native accessibility props is also included.)
|
||||
|
||||
```jsx
|
||||
<View
|
||||
accessibilityLabel="..."
|
||||
accessibilityPressed={false}
|
||||
accessibilityRole="menuitem"
|
||||
nativeID="abc"
|
||||
/>
|
||||
/*
|
||||
<div
|
||||
aria-label="..."
|
||||
aria-pressed="false"
|
||||
id="abc"
|
||||
role="menuitem"
|
||||
/>
|
||||
*/
|
||||
```
|
||||
|
||||
### Semantic HTML
|
||||
|
||||
The value of the `accessibilityRole` prop is used to infer an [analogous HTML element][html-aria-url] where appropriate. This is done to rely on well-supported native mechanisms for encoding semantics and accessibility information.
|
||||
|
||||
```jsx
|
||||
<View accessibilityRole="article">
|
||||
<Text accessibilityRole="paragraph">This is an article</Text>
|
||||
</View>
|
||||
/*
|
||||
<article>
|
||||
<div role="paragraph">This is an article</div>
|
||||
</article>
|
||||
*/
|
||||
```
|
||||
|
||||
The `"paragraph"` role isn't mapped to a `<p>` tag because it's an HTML conformance error to include block-level children within the element; both `Text` and `View` support block-level children.
|
||||
|
||||
If the `"heading"` role is combined with an `accessibilityLevel`, the equivalent HTML heading element is rendered. Otherwise, it is rendered as `<h2>`.
|
||||
|
||||
```jsx
|
||||
<Text accessibilityRole="heading" /> /* <h2> */
|
||||
<Text accessibilityRole="heading" accessibilityLevel={1} /> /* <h1> */
|
||||
```
|
||||
|
||||
Note: Avoid changing `accessibilityRole` values over time or after user actions. Generally, accessibility APIs do not provide a means of notifying assistive technologies if a `role` changes.
|
||||
|
||||
|
||||
[aria-in-html-url]: https://w3c.github.io/aria-in-html/
|
||||
[html-accessibility-url]: http://www.html5accessibility.com/
|
||||
[html-aria-url]: http://www.w3.org/TR/html-aria/
|
||||
234
packages/docs/src/pages/docs/concepts/interactions.md
Normal file
234
packages/docs/src/pages/docs/concepts/interactions.md
Normal file
@@ -0,0 +1,234 @@
|
||||
---
|
||||
title: Interactions
|
||||
date: Last Modified
|
||||
permalink: /docs/interactions/index.html
|
||||
eleventyNavigation:
|
||||
key: Interactions
|
||||
parent: Concepts
|
||||
---
|
||||
|
||||
{% import "fragments/macros.html" as macro with context %}
|
||||
|
||||
:::lead
|
||||
Interactions and gestures for the web.
|
||||
:::
|
||||
|
||||
{{ site.name }} extends the interaction modes available in React Native to account for mouse, touch, and keyboard use. The Responder System is available for more advanced gesture recognition.
|
||||
|
||||
---
|
||||
|
||||
## Click Props API
|
||||
|
||||
Click interactions are available on supporting elements. These events are React DOM synthetic mouse events. The `click` events may be dispatched by the browser following user interactions with a pointer (mouse or touch) as well as a keyboard.
|
||||
|
||||
In cases where a native `click` is not dispatched following a valid keyboard interaction (due to the native semantics of the host element), it will be emulated by React Native for Web. This helps to improve the accessibility of elements for all forms of interaction hardware.
|
||||
|
||||
{% call macro.prop('onClick', '?(event: MouseEvent) => void') %}
|
||||
Called when the element is clicked.
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('onClickCapture', '?(event: MouseEvent) => void') %}
|
||||
Called when the element is clicked. (Capture phase.)
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('onContextMenu', '?(event: MouseEvent) => void') %}
|
||||
Called when a native context menu is displayed. This may be in response to mouse, touch, or mouse+keyboard interaction.
|
||||
{% endcall %}
|
||||
|
||||
---
|
||||
|
||||
## Focus Props API
|
||||
|
||||
Focus interactions are available on supporting elements. The focus events are React DOM synthetic focus events. These events are also fired in response to focus being programmatically moved.
|
||||
|
||||
{% call macro.prop('onBlur', '?(event: FocusEvent) => void') %}
|
||||
Called when the element loses focus.
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('onFocus', '?(event: FocusEvent) => void') %}
|
||||
Called when the element receives focus.
|
||||
{% endcall %}
|
||||
|
||||
---
|
||||
|
||||
## Keyboard Props API
|
||||
|
||||
Keyboard interactions are available on supporting elements. The keyboard events are React DOM synthetic keyboard events.
|
||||
|
||||
{% call macro.prop('onKeyDown', '?(event: KeyboardEvent) => void') %}
|
||||
Called when a key is pressed down.
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('onKeyDownCapture', '?(event: KeyboardEvent) => void') %}
|
||||
Called when a key is pressed down. (Capture phase.)
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('onKeyUp', '?(event: KeyboardEvent) => void') %}
|
||||
Called when a key is released.
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('onKeyUpCapture', '?(event: KeyboardEvent) => void') %}
|
||||
Called when a key is released. (Capture phase.)
|
||||
{% endcall %}
|
||||
|
||||
---
|
||||
|
||||
## Responder Props API
|
||||
|
||||
"Responder" interactions are available on supporting elements. The Responder System allows views and gesture recognizers to opt-in to negotiating over a single, global “interaction lock”. For a view to become the “responder” means that pointer interactions are exclusive to that view and none other. A view can negotiate to become the “responder” without requiring knowledge of other views. A more specialized API for working with multi-pointer gestures is available by using the [PanResponder]({{ '/docs/pan-responder' | url }}) module.
|
||||
|
||||
A view can become the "responder" after the following native events: `scroll`, `touchstart`, `touchmove`, `mousedown`, `mousemove`. If nothing is already the "responder", the event propagates to (capture) and from (bubble) the event target until a view returns `true` for `on*SetResponder(Capture)`. If a view is *currently* the responder, the negotiation event propagates to (capture) and from (bubble) the lowest common ancestor of the event target and the current responder. Then negotiation happens between the current responder and the view that wants to become the responder.
|
||||
|
||||
NOTE: For historical reasons (originating from React Native), mouse interactions are represented as a single `touch`.
|
||||
|
||||
### Negotiation props
|
||||
|
||||
A view can become the responder by using the negotiation callbacks. During the capture phase the deepest node is called last. During the bubble phase the deepest node is called first. The capture phase should be used when a view wants to prevent a descendant from becoming the responder. The first view to return `true` from any of the `on*ShouldSetResponderCapture` / `on*ShouldSetResponder` callbacks will either become the responder or enter into negotiation with the existing responder.
|
||||
|
||||
N.B. If `stopPropagation` is called on the event for any of the negotiation callbakcs, it only stops further negotiation within the Responder System. It will not stop the propagation of the native event (which has already bubbled to the `document` by this time.)
|
||||
|
||||
{% call macro.prop('onStartShouldSetResponder', '?(event: ResponderEvent) => boolean') %}
|
||||
On `pointerdown`, should this view attempt to become the responder? If the view is not the responder, this callback may be called for every pointer start on the view.
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('onStartShouldSetResponderCapture', '?(event: ResponderEvent) => boolean') %}
|
||||
On `pointerdown`, should this view attempt to become the responder during the capture phase? If the view is not the responder, this callback may be called for every pointer start on the view.
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('onMoveShouldSetResponder', '?(event: ResponderEvent) => boolean') %}
|
||||
On `pointermove` for an active pointer, should this view attempt to become the responder? If the view is not the responder, this callback may be called for every pointer move on the view.
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('onMoveShouldSetResponderCapture', '?(event: ResponderEvent) => boolean') %}
|
||||
On `pointermove` for an active pointer, should this view attempt to become the responder during the capture phase? If the view is not the responder, this callback may be called for every pointer move on the view.
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('onScrollShouldSetResponder', '?(event: ResponderEvent) => boolean') %}
|
||||
On `scroll`, should this view attempt to become the responder? If the view is not the responder, this callback may be called for every scroll of the view.
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('onScrollShouldSetResponderCapture', '?(event: ResponderEvent) => boolean') %}
|
||||
On `scroll`, should this view attempt to become the responder during the capture phase? If the view is not the responder, this callback may be called for every scroll of the view.
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('onResponderTerminationRequest', '?(event: ResponderEvent) => boolean') %}
|
||||
The view is the responder, but another view now wants to become the responder. Should this view release the responder? Returning `true` allows the responder to be released.
|
||||
{% endcall %}
|
||||
|
||||
### Transfer props
|
||||
|
||||
If a view returns `true` for a negotiation callback then it will either become the responder (if none exists) or be involved in the responder transfer. The following callbacks are called only for the views involved in the responder transfer (i.e., no bubbling.)
|
||||
|
||||
{% call macro.prop('onResponderGrant', '?(event: ResponderEvent) => void') %}
|
||||
The view is granted the responder and is now responding to pointer events. The lifecycle callbacks will be called for this view. This is the point at which you should provide visual feedback for users that the interaction has begun.
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('onResponderReject', '?(event: ResponderEvent) => void') %}
|
||||
The view was not granted the responder. It was rejected because another view is already the responder and will not release it.
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('onResponderTerminate', '?(event: ResponderEvent) => void') %}
|
||||
The responder has been taken from this view. It may have been taken by another view after a call to `onResponderTerminationRequest`, or it might have been taken by the browser without asking (e.g., window blur, document scroll, context menu open). This is the point at which you should provide visual feedback for users that the interaction has been cancelled.
|
||||
{% endcall %}
|
||||
|
||||
### Lifecycle props
|
||||
|
||||
If a view is the responder, the following callbacks will be called only for this view (i.e., no bubbling.) These callbacks are *always* bookended by `onResponderGrant` (before) and either `onResponderRelease` or `onResponderTerminate` (after).
|
||||
|
||||
{% call macro.prop('onResponderStart', '?(event: ResponderEvent) => void') %}
|
||||
A pointer down event occured on the screen. The responder is notified of all start events, even if the pointer target is not this view (i.e., additional pointers are being used). Therefore, this callback may be called multiple times while the view is the responder.
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('onResponderMove', '?(event: ResponderEvent) => void') %}
|
||||
A pointer move event occured on the screen. The responder is notified of all move events, even if the pointer target is not this view (i.e., additional pointers are being used). Therefore, this callback may be called multiple times while the view is the responder.
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('onResponderEnd', '?(event: ResponderEvent) => void') %}
|
||||
A pointer up event occured on the screen. The responder is notified of all end events, even if the pointer target is not this view (i.e., additional pointers are being used). Therefore, this callback may be called multiple times while the view is the responder.
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('onResponderRelease', '?(event: ResponderEvent) => void') %}
|
||||
As soon as there are no more pointers that *started* inside descendants of the responder, this callback is called on the responder and the interaction lock is released. This is the point at which you should provide visual feedback for users that the interaction is over.
|
||||
{% endcall %}
|
||||
|
||||
### ResponderEvent
|
||||
|
||||
Every callback is called with a `ResponderEvent` event. Data dervied from the native events, e.g., the native `target` and pointer coordinates, can be used to determine the return value of the negotiation callbacks, etc.
|
||||
|
||||
{% call macro.prop('currentTarget', 'EventTarget') %}
|
||||
The DOM element acting as the responder view.
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('defaultPrevented', 'boolean') %}
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('eventPhase', 'number') %}
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('isDefaultPrevented', '() => boolean') %}
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('isPropagationStopped', '() => boolean') %}
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('isTrusted', 'boolean') %}
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('nativeEvent', 'TouchEvent') %}
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('target', 'EventTarget') %}
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('timeStamp', 'number') %}
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('touchHistory', 'TouchHistory') %}
|
||||
An object containing information about the history of touches.
|
||||
{% endcall %}
|
||||
|
||||
#### TouchHistory
|
||||
|
||||
{% call macro.prop('indexOfSingleActiveTouch', 'number') %}
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('mostRecentTimeStamp', 'number') %}
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('numberActiveTouches', 'number') %}
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('touchBank', 'TouchBank') %}
|
||||
{% endcall %}
|
||||
|
||||
#### TouchBank
|
||||
|
||||
{% call macro.prop('currentPageX', 'number') %}
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('currentPageY', 'number') %}
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('currentTimeStamp', 'number') %}
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('previousPageX', 'number') %}
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('previousPageY', 'number') %}
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('previousTimeStamp', 'number') %}
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('startPageX', 'number') %}
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('startPageY', 'number') %}
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('startTimeStamp', 'number') %}
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('touchActive', 'number') %}
|
||||
{% endcall %}
|
||||
65
packages/docs/src/pages/docs/concepts/localization.md
Normal file
65
packages/docs/src/pages/docs/concepts/localization.md
Normal file
@@ -0,0 +1,65 @@
|
||||
---
|
||||
title: Localization
|
||||
date: Last Modified
|
||||
permalink: /docs/localization/index.html
|
||||
eleventyNavigation:
|
||||
key: Localization
|
||||
parent: Concepts
|
||||
---
|
||||
|
||||
{% import "fragments/macros.html" as macro with context %}
|
||||
|
||||
:::lead
|
||||
Localized layout is largely automatic if you follow this guide.
|
||||
:::
|
||||
|
||||
{{ site.name }} provides several mechanisms to automatically flip application layout to match the writing direction of the primary language.
|
||||
|
||||
## Localized component layout
|
||||
|
||||
To automatically flip the layout of a flexbox or grid container, set the `dir` prop on `View`, `Text`, or `TextInput` components to desired writing direction (e.g., `"rtl"`). By default, the native writing direction is set to `"auto"` for `Text` and `TextInput` elements. This uses the browser's built-in writing direction algorithm to detect whether the text should be displayed left-to-right or right-to-left.
|
||||
|
||||
You can also set the `lang` prop on `Text` or `TextInput` to provide browsers with information about the language of the text.
|
||||
|
||||
```jsx
|
||||
const style = { alignItems: 'flex-start' };
|
||||
return (
|
||||
<View dir="rtl" style={style}>
|
||||
<Text lang="ar">...</Text>
|
||||
</View>
|
||||
);
|
||||
```
|
||||
|
||||
The non-standard [direction-independent style properties]({{ '/docs/styling/#non-standard-properties' | url }}) should also be used as much as possible. {{ site.name }} will automatically flip the direction of these properties when the application is re-rendered after using `I18nManager` to enable RTL mode.
|
||||
|
||||
```jsx
|
||||
// "start" is "left" for LTR and "right" for RTL
|
||||
const style = { paddingStart: 10, marginStart: 10 };
|
||||
return (
|
||||
<View style={style} />
|
||||
);
|
||||
```
|
||||
|
||||
The `I18nManager` API can also be used to help with more fine-grained control of layout, e.g., flipping images or transforms.
|
||||
|
||||
```jsx
|
||||
const { isRTL } = I18nManager.getConstants();
|
||||
const transform = { [{ scaleX: isRTL ? -1 : 1 }] };
|
||||
|
||||
<Image source={'forward.svg'} style={transform} />
|
||||
<Image source={isRTL ? 'back.svg' : 'forward.svg'} />
|
||||
```
|
||||
|
||||
## Localized application layout
|
||||
|
||||
The application will automatically display as RTL if rendered *after* setting the direction to RTL.
|
||||
|
||||
```js
|
||||
// Either force RTL (e.g., for unit tests)
|
||||
I18nManager.forceRTL(true);
|
||||
|
||||
// Or set RTL if you know the language is RTL
|
||||
I18nManager.setPreferredLanguageRTL(true);
|
||||
```
|
||||
|
||||
Once the application is rendered in RTL mode, it will flip all the direction-independent styles and ensure that the `isRTL` constant is `true`.
|
||||
94
packages/docs/src/pages/docs/concepts/rendering.md
Normal file
94
packages/docs/src/pages/docs/concepts/rendering.md
Normal file
@@ -0,0 +1,94 @@
|
||||
---
|
||||
title: Rendering
|
||||
date: Last Modified
|
||||
permalink: /docs/rendering/index.html
|
||||
eleventyNavigation:
|
||||
key: Rendering
|
||||
parent: Concepts
|
||||
---
|
||||
|
||||
:::lead
|
||||
Client and server rendering with {{ site.name }}.
|
||||
:::
|
||||
|
||||
React Native for Web can be used for multi-platform and web-only applications. It can incrementally adopted by existing React Web apps and integrated with existing React Native apps. Preact is also supported.
|
||||
|
||||
{{ site.name }} components interoperate with React DOM components. They can be incrementally introduced at any point in an application's component tree. One thing to be aware of is that external CSS applied to *all* tags in a document may interfere with the default rendering of some {{ site.name }} components.
|
||||
|
||||
---
|
||||
|
||||
## Client API
|
||||
|
||||
Render apps using [AppRegistry]({{ '/docs/app-registry' | url }}):
|
||||
|
||||
```js
|
||||
// index.web.js
|
||||
|
||||
import { AppRegistry } from 'react-native';
|
||||
import App from './src/App';
|
||||
|
||||
// register the app
|
||||
AppRegistry.registerComponent('App', () => App);
|
||||
|
||||
AppRegistry.runApplication('App', {
|
||||
initialProps: {},
|
||||
rootTag: document.getElementById('root')
|
||||
});
|
||||
```
|
||||
|
||||
Or render individual components:
|
||||
|
||||
```js
|
||||
import { render } from 'react-native';
|
||||
import Header from './src/Header';
|
||||
|
||||
render(<Header />, document.getElementById('header'))
|
||||
```
|
||||
|
||||
You might need to adjust the styles of the HTML document's root elements for your app to fill the viewport.
|
||||
|
||||
```html
|
||||
<html style="height:100%">
|
||||
<body style="height:100%">
|
||||
<div id="root" style="display:flex;height:100%"></div>
|
||||
```
|
||||
|
||||
:::callout
|
||||
**Warning!** Although components in can be rendered by calling `ReactDOM.render` directly, this will not set the global context React Native provides to components when using the `AppRegistry` API.
|
||||
:::
|
||||
|
||||
---
|
||||
|
||||
## Server API
|
||||
|
||||
Server-side rendering to HTML is supported using `AppRegistry`:
|
||||
|
||||
```js
|
||||
import App from './src/App';
|
||||
import ReactDOMServer from 'react-dom/server';
|
||||
import { AppRegistry } from 'react-native-web';
|
||||
|
||||
// register the app
|
||||
AppRegistry.registerComponent('App', () => App);
|
||||
|
||||
// prerender the app
|
||||
const { element, getStyleElement } = AppRegistry.getApplication('App', { initialProps });
|
||||
// first the element
|
||||
const html = ReactDOMServer.renderToString(element);
|
||||
// then the styles (optionally include a nonce if your CSP policy requires it)
|
||||
const css = ReactDOMServer.renderToStaticMarkup(getStyleElement({ nonce }));
|
||||
|
||||
// example HTML document string
|
||||
const document = `
|
||||
<!DOCTYPE html>
|
||||
<html style="height:100%">
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
${css}
|
||||
<body style="height:100%; overflow-y:hidden">
|
||||
<div id="root" style="display:flex; height: 100%">
|
||||
${html}
|
||||
</div>
|
||||
<script nonce="${nonce}" src="${bundlePath}"></script>
|
||||
`
|
||||
```
|
||||
356
packages/docs/src/pages/docs/concepts/styling.md
Normal file
356
packages/docs/src/pages/docs/concepts/styling.md
Normal file
@@ -0,0 +1,356 @@
|
||||
---
|
||||
title: Styling
|
||||
date: Last Modified
|
||||
permalink: /docs/styling/index.html
|
||||
eleventyNavigation:
|
||||
key: Styling
|
||||
parent: Concepts
|
||||
---
|
||||
|
||||
{% import "fragments/macros.html" as macro with context %}
|
||||
|
||||
:::lead
|
||||
{{ site.name }} relies on authoring styles in JavaScript and produces optimized CSS.
|
||||
:::
|
||||
|
||||
Style declarations are authored in JavaScript and applied to elements using the `style` prop. {{ site.name }} includes a very small CSS reset that only removes unwanted User Agent styles beyond the reach of React components. All other styles are scoped to components and implemented as "utility" CSS that deduplicates styles and provides reliable rendering.
|
||||
|
||||
```jsx
|
||||
const style = { flex: 1, opacity: 0 };
|
||||
const Component = () => <View style={style} />;
|
||||
```
|
||||
|
||||
Style performance is improved when styles are defined outside of components using the `StyleSheet` API. This creates opaque references to the styles that cannot be directly accessed unless first passed to `StyleSheet.flatten`.
|
||||
|
||||
```jsx
|
||||
const styles = StyleSheet.create({ root: { flex: 1, opacity: 0 } });
|
||||
const Component = () => <View style={styles.root} />;
|
||||
```
|
||||
|
||||
All the React Native components accept a `style` property. The value can be a registered object, a plain object, or an array of objects. The array syntax will merge styles from left-to-right as normal JavaScript objects, and can be used to conditionally apply styles:
|
||||
|
||||
```jsx
|
||||
<View style={[ styles.element, isActive && styles.active ]} />
|
||||
```
|
||||
|
||||
To let other components customize the style of a component's children you can expose a prop so styles can be explicitly passed into the component.
|
||||
|
||||
```jsx
|
||||
function List(props) {
|
||||
return (
|
||||
<View style={props.style}>
|
||||
{elements.map((element) =>
|
||||
<View style={[ styles.element, props.elementStyle ]} />
|
||||
)}
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
||||
function App() {
|
||||
return (
|
||||
<List
|
||||
elementStyle={styles.listElement}
|
||||
style={styles.list}
|
||||
/>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
You have greater control over how styles are composed when compared to using class names. For example, you may choose to accept a limited subset of style props in the component's API, and control the order and conditions of their merging.
|
||||
|
||||
---
|
||||
|
||||
## Styles API
|
||||
|
||||
{{ site.name }} supports all *long-form* CSS properties. There is no direct support for `@`-rules, selectors, pseudo-selectors, and pseudo-elements, equivalents of which are demonstrated in the [styling patterns](#styling-patterns) section below.
|
||||
|
||||
### Short-form properties
|
||||
|
||||
The only supported short-form CSS properties accept only a *single* value.
|
||||
|
||||
{% call macro.prop('borderColor', '?string') %}
|
||||
Accepts only a single value that is applied to all sides.
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('borderRadius', '?(number | string)') %}
|
||||
Accepts only a single value that is applied to all sides.
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('borderStyle', '?string') %}
|
||||
Accepts only a single value that is applied to all sides.
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('borderWidth', '?(number | string)') %}
|
||||
Accepts only a single value that is applied to all sides.
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('flex', '?number') %}
|
||||
Accepts only positive integers, `0`, or `-1`.
|
||||
The value of `-1` is non-standard and equivalent to setting `flowGrow:0` and `flexShrink:1`.
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('margin', '?(number | string)') %}
|
||||
Accepts only a single value that is applied to all sides.
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('overflow', '?("auto" | "hidden" | "visible")') %}
|
||||
Accepts only a single value that is applied to both axes.
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('overscrollBehavior', '?("auto" | "contain" | "none")') %}
|
||||
Accepts only a single value that is applied to both axes.
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('padding', '?(number | string)') %}
|
||||
Accepts only a single value that is applied to all sides.
|
||||
{% endcall %}
|
||||
|
||||
### Non-standard properties
|
||||
|
||||
{{ site.name }} includes compatibility with the following non-standard React Native properties and values.
|
||||
|
||||
{% call macro.prop('animationKeyframes', '?Object') %}
|
||||
A web-only CSS extension for defining keyframes. The value is an object representing a [CSS keyframes definition](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Animations/Using_CSS_animations). For example: `{ '0%': { opacity: 1 } }`.
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('borderEndColor', '?string') %}
|
||||
Equivalent to [border-inline-end-color](https://developer.mozilla.org/en-US/docs/Web/CSS/border-inline-end-color).
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('borderEndStyle', '?string') %}
|
||||
Equivalent to [border-inline-end-style](https://developer.mozilla.org/en-US/docs/Web/CSS/border-inline-end-style).
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('borderEndWidth', '?(string | number)') %}
|
||||
Equivalent to [border-inline-end-width](https://developer.mozilla.org/en-US/docs/Web/CSS/border-inline-end-width).
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('borderStartColor', '?string') %}
|
||||
Equivalent to [border-inline-start-color](https://developer.mozilla.org/en-US/docs/Web/CSS/border-inline-start-color).
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('borderStartStyle', '?string') %}
|
||||
Equivalent to [border-inline-start-style](https://developer.mozilla.org/en-US/docs/Web/CSS/border-inline-start-style).
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('borderStartWidth', '?(string | number)') %}
|
||||
Equivalent to [border-inline-start-width](https://developer.mozilla.org/en-US/docs/Web/CSS/border-inline-start-width).
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('borderBottomEndRadius', '?(string | number)') %}
|
||||
Equivalent to [border-end-end-radius](https://developer.mozilla.org/en-US/docs/Web/CSS/border-end-end-radius).
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('borderBottomStartRadius', '?(string | number)') %}
|
||||
Equivalent to [border-end-start-radius](https://developer.mozilla.org/en-US/docs/Web/CSS/border-end-start-radius).
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('borderTopEndRadius', '?(string | number)') %}
|
||||
Equivalent to [border-start-end-radius](https://developer.mozilla.org/en-US/docs/Web/CSS/border-start-end-radius).
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('borderTopStartRadius', '?(string | number)') %}
|
||||
Equivalent to [border-start-start-radius](https://developer.mozilla.org/en-US/docs/Web/CSS/border-start-start-radius).
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('end', '?(string | number)') %}
|
||||
Defines the logical inline end position of an element. Equivalent to `right` for `ltr` writing direction.
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('marginHorizontal', '?(number | string)') %}
|
||||
Equivalent to [margin-inline](https://developer.mozilla.org/en-US/docs/Web/CSS/margin-inline). Accepts only a single value.
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('marginVertical', '?(number | string)') %}
|
||||
Equivalent to [margin-block](https://developer.mozilla.org/en-US/docs/Web/CSS/margin-block).
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('marginEnd', '?(string | number)') %}
|
||||
Equivalent to [margin-inline-end](https://developer.mozilla.org/en-US/docs/Web/CSS/margin-inline-end).
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('marginStart', '?(string | number)') %}
|
||||
Equivalent to [margin-inline-start](https://developer.mozilla.org/en-US/docs/Web/CSS/margin-inline-start).
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('paddingHorizontal', '?(number | string)') %}
|
||||
Equivalent to [padding-inline](https://developer.mozilla.org/en-US/docs/Web/CSS/padding-inline). Accepts only a single value.
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('paddingVertical', '?(number | string)') %}
|
||||
Equivalent to [padding-block](https://developer.mozilla.org/en-US/docs/Web/CSS/padding-block). Accepts only a single value.
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('paddingEnd', '?(string | number)') %}
|
||||
Equivalent to [padding-inline-end](https://developer.mozilla.org/en-US/docs/Web/CSS/padding-inline-end).
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('paddingStart', '?(string | number)') %}
|
||||
Equivalent to [padding-inline-start](https://developer.mozilla.org/en-US/docs/Web/CSS/padding-inline-start).
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('shadowColor', '?string') %}
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('shadowOffset', '?(string | number)') %}
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('shadowOpacity', '?number') %}
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('shadowRadius', '?(string | number)') %}
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('start', '?(string | number)') %}
|
||||
Defines the logical inline end position of an element. Equivalent to `left` for `ltr` writing direction.
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('textAlign', '?string') %}
|
||||
Includes support for non-standard `"start"` and `"end"` values for localization support.
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('textAlignVertical', '?string') %}
|
||||
Equivalent to [vertical-align](https://developer.mozilla.org/en-US/docs/Web/CSS/vertical-align).
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('textShadowColor', '?string') %}
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('textShadowOffset', '?(string | number)') %}
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('textShadowRadius', '?(string | number)') %}
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('transform', '?Array<Object>') %}
|
||||
Implements React Native's [JavaScript syntax for transforms](https://reactnative.dev/docs/transforms#reference).
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('writingDirection', '?("auto" | "ltr" | "rtl")') %}
|
||||
Equivalent to [direction](https://developer.mozilla.org/en-US/docs/Web/CSS/direction).
|
||||
{% endcall %}
|
||||
|
||||
---
|
||||
|
||||
## Text style inheritance
|
||||
|
||||
Web developers will be used to setting "global" font styles that are applied to the entire document, taking advantage of inherited CSS properties.
|
||||
|
||||
```css
|
||||
html {
|
||||
font-family: Arial, sans-serif;
|
||||
font-size: 16px;
|
||||
color: #333;
|
||||
}
|
||||
```
|
||||
|
||||
However, this approach is problematic for component-based systems, as the rendering of a component may be affected by text styles unexpectedly inherited from its ancestors. {{ site.name }} adopts the same inheritance restrictions found in React Native: all text nodes **must** be contained by a `Text` component and cannot be rendered directly within a `View`; and text style inheritance is only available within `Text` subtrees.
|
||||
|
||||
```jsx
|
||||
// BAD
|
||||
<View>Some text</View>
|
||||
// GOOD
|
||||
<View><Text>Some text</Text></View>
|
||||
```
|
||||
|
||||
The consequence of this is that default text styles cannot be set on `View` for an entire subtree. Although this may seem limiting, it ensures that different design systems can co-exist on the same page and text styles are always encapsulated. The recommended way to use consistent text styles across your application is to create a custom text component (e.g., `AppText`) that implements those styles and forms the basis of further app-specific text customization.
|
||||
|
||||
```jsx
|
||||
<View>
|
||||
<AppHeaderText>App header text</AppHeaderText>
|
||||
<AppText>App default text</AppText>
|
||||
</View>
|
||||
```
|
||||
|
||||
This still allows for text style inheritance within the `Text` subtree.
|
||||
|
||||
```jsx
|
||||
const bold = { fontWeight: 'bold' }
|
||||
const red = { color: 'red' }
|
||||
|
||||
<Text style={bold}>
|
||||
I am bold
|
||||
<Text style={red}>and red</Text>
|
||||
</Text>
|
||||
```
|
||||
|
||||
This approach means that components are designed with isolation in mind. You should be able to drop a component anywhere in your application, trusting that as long as the props are the same, it will *look and behave* the same way. Text properties that could inherit from outside of the props would break this isolation.
|
||||
|
||||
---
|
||||
|
||||
## Styling patterns
|
||||
|
||||
The styling system in React Native is a way of defining the styles your application requires; it does not concern itself with _where_ or _when_ those styles are applied to elements. As a result, there is no dedicted Media Query or pseudo-class API built into the styling system. Instead, the state of the application should be derived from the equivalent JavaScript APIs that have the benefit of not being limited to modifying only styles.
|
||||
|
||||
### Responsive layouts
|
||||
|
||||
Media Queries may not be most appropriate for component-based designs, as adapting to the dimensions of a container is often preferred. This can be done with the `onLayout` prop found on all the core components. If you do choose to use Media Queries, using them in JavaScript via the `matchMedia` DOM API has the benefit of allowing you to swap out entire components, not just styles.
|
||||
|
||||
### Interaction states
|
||||
|
||||
Interactions such as hover, focus, and press should be implemented using events (e.g., `onFocus`). Components like `Pressable` expose interaction state in a ready-to-use form.
|
||||
|
||||
### Debugging
|
||||
|
||||
React Dev Tools supports inspecting and editing of React Native styles. It's recommended that you rely more on React Dev Tools and live/hot-reloading rather than inspecting and editing the DOM directly.
|
||||
|
||||
---
|
||||
|
||||
## How it works
|
||||
|
||||
Style resolution is deterministic and slightly different from CSS. In the following HTML/CSS example, the `.margin` selector is defined last in the CSS and takes precedence over the previous rules, resulting in a margin of `0,0,0,0`.
|
||||
|
||||
```html
|
||||
<style>
|
||||
.marginTop { margin-top: 10px; }
|
||||
.marginBottom { margin-bottom: 20px; }
|
||||
.margin { margin: 0; }
|
||||
</style>
|
||||
|
||||
<div class="marginTop marginBottom margin"></div>
|
||||
```
|
||||
|
||||
But in {{ site.name }} the most *precise* style property takes precedence, resulting in margins of `10,0,20,0`.
|
||||
|
||||
```jsx
|
||||
const style = [
|
||||
{ marginTop: 10 },
|
||||
{ marginBottom: 20 },
|
||||
{ margin: 0 }
|
||||
];
|
||||
|
||||
const Box = () => <View style={style} />
|
||||
```
|
||||
|
||||
{{ site.name }} transforms styles objects into CSS and inline styles. Any styles defined using `StyleSheet.create` will ultimately be rendered using CSS class names. Each rule is broken down into declarations, properties are expanded to their long-form, and the resulting key-value pairs are mapped to unique "atomic CSS" class names.
|
||||
|
||||
Input:
|
||||
|
||||
```jsx
|
||||
const Box = () => <View style={styles.box} />
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
box: {
|
||||
margin: 0
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
Output:
|
||||
|
||||
```html
|
||||
<style>
|
||||
.rn-1mnahxq { margin-top: 0px; }
|
||||
.rn-61z16t { margin-right: 0px; }
|
||||
.rn-p1pxzi { margin-bottom: 0px; }
|
||||
.rn-11wrixw { margin-left: 0px; }
|
||||
</style>
|
||||
|
||||
<div class="r-156q2ks r-61z16t r-p1pxzi r-11wrixw"></div>
|
||||
```
|
||||
|
||||
This ensures that CSS order doesn't impact rendering and CSS rules are efficiently deduplicated. Rather than the total CSS growing in proportion to the number of *rules*, it grows in proportion to the number of *unique declarations*. As a result, the DOM style sheet is only written to when new unique declarations are defined and it is usually small enough to be pre-rendered and inlined.
|
||||
|
||||
Class names are deterministic, which means that the resulting CSS and HTML is consistent across builds – important for large apps using code-splitting and deploying incremental updates.
|
||||
|
||||
At runtime registered styles are resolved to DOM style props and memoized. Any dynamic styles that contain declarations previously registered as static styles can also be converted to CSS class names. Otherwise, they render as inline styles.
|
||||
9
packages/docs/src/pages/docs/getting-started/_.md
Normal file
9
packages/docs/src/pages/docs/getting-started/_.md
Normal file
@@ -0,0 +1,9 @@
|
||||
---
|
||||
title: Getting started
|
||||
date: Last Modified
|
||||
permalink: false
|
||||
eleventyNavigation:
|
||||
key: Start
|
||||
title: Getting started
|
||||
order: 0
|
||||
---
|
||||
@@ -0,0 +1,57 @@
|
||||
---
|
||||
title: Browser compatibility
|
||||
date: Last Modified
|
||||
permalink: /docs/browser-compatibility/index.html
|
||||
eleventyNavigation:
|
||||
key: Browser compatibility
|
||||
parent: Start
|
||||
order: 3
|
||||
---
|
||||
|
||||
:::lead
|
||||
Understanding {{ site.name }} browser compatibility.
|
||||
:::
|
||||
|
||||
{{ site.name }} is designed and tested for recent mobile and desktop browsers, for touch and mouse and keyboard interactions.
|
||||
|
||||
The browsers with known support include:
|
||||
|
||||
* Chrome 60+
|
||||
* Safari 10+ / iOS Safari 10+
|
||||
* Edge 12+
|
||||
* Firefox ESR+
|
||||
* Internet Explorer 11
|
||||
* Opera
|
||||
|
||||
If specific exports have a different browser support expectation, it will be documented with that export.
|
||||
|
||||
---
|
||||
|
||||
## JavaScript
|
||||
|
||||
Your application may need to polyfill `Promise`, `Object.assign`, `Array.from`, and [`ResizeObserver`](https://github.com/que-etc/resize-observer-polyfill) as necessary for your desired browser support.
|
||||
|
||||
---
|
||||
|
||||
## CSS
|
||||
|
||||
Most CSS properties and values are supported. Vendor prefixes are automatically provided where necessary. For example, if you use the following style:
|
||||
|
||||
```js
|
||||
const style = {
|
||||
userSelect: 'none'
|
||||
}
|
||||
```
|
||||
|
||||
The resulting CSS is:
|
||||
|
||||
```css
|
||||
.r-userSelect-24jds {
|
||||
-webkit-user-select: none;
|
||||
user-select: none;
|
||||
}
|
||||
```
|
||||
|
||||
Certain CSS properties are not supported across all browsers, but are polyfilled by {{ site.name }}.
|
||||
|
||||
(N.B. Safari prior to version 10.1 can suffer from extremely [poor flexbox performance](https://bugs.webkit.org/show_bug.cgi?id=150445). The recommended way to work around this issue (as used on mobile.twitter.com) is to set `display:block` on Views in your element hierarchy that you know don't need flexbox layout.)
|
||||
22
packages/docs/src/pages/docs/getting-started/help.md
Normal file
22
packages/docs/src/pages/docs/getting-started/help.md
Normal file
@@ -0,0 +1,22 @@
|
||||
---
|
||||
title: Help
|
||||
date: Last Modified
|
||||
permalink: /docs/help/index.html
|
||||
description:
|
||||
eleventyNavigation:
|
||||
key: Help
|
||||
parent: Start
|
||||
order: 5
|
||||
---
|
||||
|
||||
:::lead
|
||||
Questions? Looking for help? These are the best places to look first.
|
||||
:::
|
||||
|
||||
## Discussions
|
||||
|
||||
[{{ site.name }} Discussions on GitHub]({{ site.githubUrl }}/discussions) is the place for general questions, discussions, and ideas.
|
||||
|
||||
## Issues
|
||||
|
||||
[{{ site.name }} Issues on GitHub]({{ site.githubUrl }}/issues) is the place for reporting and resolving issues with {{ site.name }}.
|
||||
61
packages/docs/src/pages/docs/getting-started/installation.md
Normal file
61
packages/docs/src/pages/docs/getting-started/installation.md
Normal file
@@ -0,0 +1,61 @@
|
||||
---
|
||||
title: Installation
|
||||
date: Last Modified
|
||||
permalink: /docs/installation/index.html
|
||||
eleventyNavigation:
|
||||
key: Installation
|
||||
parent: Start
|
||||
order: 1
|
||||
---
|
||||
|
||||
:::lead
|
||||
An overview of how to install and use {{ site.name }}.
|
||||
:::
|
||||
|
||||
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.
|
||||
|
||||
```shell
|
||||
npm install react-dom {{ site.packageName }}
|
||||
```
|
||||
|
||||
The Babel plugin is recommended for build-time optimizations.
|
||||
|
||||
```shell
|
||||
npm install --save-dev babel-plugin-react-native-web
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Quickstart
|
||||
|
||||
### Expo
|
||||
|
||||
[Expo](https://expo.io) is a framework and a platform for universal React applications. [Expo for Web](https://docs.expo.io/workflow/web/) uses React Native for Web, provides dozens of additional cross-platform APIs, includes web build optimizations, and is compatibile with the broder React Native ecosystem.
|
||||
|
||||
```shell
|
||||
npx expo-cli init my-app
|
||||
cd my-app
|
||||
npm install react-dom react-native-web
|
||||
npx expo-cli start
|
||||
```
|
||||
|
||||
### Create React App
|
||||
|
||||
[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.
|
||||
|
||||
```shell
|
||||
npx create-react-app my-app
|
||||
cd my-app
|
||||
npm install react-native-web
|
||||
npm start
|
||||
```
|
||||
|
||||
### Integrations
|
||||
|
||||
Visit the [React Native Directory](https://reactnative.directory/?web=true) to find React Native packages with known web support. Popular web frameworks maintain example integrations.
|
||||
|
||||
* [Docz](https://github.com/doczjs/docz/tree/master/examples/react-native)
|
||||
* [Gatsby](https://github.com/slorber/gatsby-plugin-react-native-web)
|
||||
* [Next.js](https://github.com/zeit/next.js/tree/master/examples/with-react-native-web) (and [example recipes](https://gist.github.com/necolas/f9034091723f1b279be86c7429eb0c96))
|
||||
* [Razzle](https://github.com/jaredpalmer/razzle/tree/master/examples/with-react-native-web)
|
||||
* [Styleguidist](https://github.com/styleguidist/react-styleguidist/tree/master/examples/react-native)
|
||||
39
packages/docs/src/pages/docs/getting-started/introduction.md
Normal file
39
packages/docs/src/pages/docs/getting-started/introduction.md
Normal file
@@ -0,0 +1,39 @@
|
||||
---
|
||||
title: Introduction to React Native for Web
|
||||
date: Last Modified
|
||||
permalink: /docs/index.html
|
||||
eleventyNavigation:
|
||||
key: Introduction
|
||||
parent: Start
|
||||
order: 0
|
||||
---
|
||||
|
||||
{% import "fragments/macros.html" as macro with context %}
|
||||
|
||||
:::lead
|
||||
React Native for Web is a compatibility layer between React DOM and React Native. It can be used in new and existing apps, web-only and multi-platform apps.
|
||||
:::
|
||||
|
||||
{{ site.name }} uses React DOM to accurately render React Native compatible JavaScript code in a web browser. This brings several powerful abstractions to web developers include a simple [styles in JavaScript API]({{ '/docs/stylesheet' | url }}), built-in [layout localization]({{ '/docs/localization' | url }}), and a [high-level gesture system]({{ '/docs/interactions/#responder-props-api' | url}}).
|
||||
|
||||
## Modern React
|
||||
|
||||
{{ site.name }} is made with modern React APIs including function components and hooks. It builds upon React DOM, making it straight-forward for React DOM apps to incrementally adopt the framework (as was done by Twitter and Flipkart.) The project aims to provide broad compatibility with React alternatives, but will continue to evolve with React as APIs like Concurrent Mode and Server Components are introduced.
|
||||
|
||||
## Modern Web
|
||||
|
||||
{{ site.name }} makes direct use of native DOM APIs to implement specific features. As the Web platform improves, so does {{ site.name }}. Although certains APIs in the project have remained unchanged since inception, the implementations have become smaller and faster by migrating to new DOM APIs as they became broadly available in browsers.
|
||||
|
||||
## Components
|
||||
|
||||
{{ site.name }} provides all the core components you'd expect from React Native. You will mostly work with `View`, `Image`, `Text`, `TextInput`, and `ScrollView`. The core components include props for working with interactions, including the advanced gesture [responder system]({{ '/docs/interactions' | url }}). Each component's documentation contains live and editable examples to try out.
|
||||
|
||||
React Native for Web exports many different modules to support a variety of use cases. Your application can use as many or as few of these modules as needed. The babel plugin will help you to only bundle the modules that you are using.
|
||||
|
||||
## Styles
|
||||
|
||||
{{ site.name }} components use JavaScript to author styles which are converted to native CSS. The design of this styling system avoids *all* the [problems with CSS at scale](https://speakerdeck.com/vjeux/react-css-in-js) and produces highly optimized CSS without the need to learn a domain-specific styling language and without the need for specialized tooling that parses markup to remove unused styles.
|
||||
|
||||
## Reliable and tested
|
||||
|
||||
{{ site.name }} is thoroughly unit and production tested. Significant changes are first published as canary releases to limit regressions and gather feedback from partners. Pull requests record changes to the compressed file size of each module in the library.
|
||||
247
packages/docs/src/pages/docs/getting-started/multi-platform.md
Normal file
247
packages/docs/src/pages/docs/getting-started/multi-platform.md
Normal file
@@ -0,0 +1,247 @@
|
||||
---
|
||||
title: Multi-platform setup
|
||||
date: Last Modified
|
||||
permalink: /docs/multi-platform/index.html
|
||||
eleventyNavigation:
|
||||
key: Multi-platform
|
||||
parent: Start
|
||||
order: 2
|
||||
---
|
||||
|
||||
:::lead
|
||||
An overview of how to integrate React Native for Web into an existing React Native codebase.
|
||||
:::
|
||||
|
||||
If you are interested in making a multi-platform app it is strongly recommended that you use Expo (or learn from the source code for the Web integration). Expo includes [web support](https://docs.expo.io/versions/v35.0.0/guides/running-in-the-browser/) and takes care of all the configuration work required.
|
||||
|
||||
If you have an existing application, this guide will surface the areas that require attention and customization before most web bundlers can consume the non-standard JavaScript in packages produced by the React Native ecosystem. Additionally, 3rd party React Native packages with web support are listed in the [React Native Directory](https://reactnative.directory/?web=true).
|
||||
|
||||
---
|
||||
|
||||
## Package aliasing
|
||||
|
||||
### Bundler
|
||||
|
||||
Configure your module bundler to alias the package to `react-native`. For example, modify your [webpack](https://github.com/webpack/webpack) configuration as follows:
|
||||
|
||||
```js
|
||||
// webpack.config.js
|
||||
module.exports = {
|
||||
// ...the rest of your config
|
||||
|
||||
resolve: {
|
||||
alias: {
|
||||
'react-native$': 'react-native-web'
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Compiler
|
||||
|
||||
[Babel](https://babeljs.io/) supports module aliasing using [babel-plugin-module-resolver](https://www.npmjs.com/package/babel-plugin-module-resolver)
|
||||
|
||||
```js
|
||||
{
|
||||
"plugins": [
|
||||
["module-resolver", {
|
||||
"alias": {
|
||||
"^react-native$": "react-native-web"
|
||||
}
|
||||
}]
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### Jest
|
||||
|
||||
[Jest](https://facebook.github.io/jest/) can be configured using the provided preset. This will map `react-native` to `react-native-web` and provide appropriate mocks. Please refer to the Jest documentation for more information.
|
||||
|
||||
```js
|
||||
{
|
||||
"preset": "react-native-web"
|
||||
}
|
||||
```
|
||||
|
||||
### Flow
|
||||
|
||||
[Flow](https://flow.org) can be configured to understand the aliased module. You may also need to include a custom libdef ([example](https://gist.github.com/paularmstrong/f60b40d16fc83e1e8e532d483336f9bb)) in your config.
|
||||
|
||||
```yml
|
||||
[options]
|
||||
module.name_mapper='^react-native$' -> 'react-native-web'
|
||||
```
|
||||
|
||||
### Node.js
|
||||
|
||||
Node.js can alias `react-native` to `react-native-web` using [`module-alias`](https://www.npmjs.com/package/module-alias). This is useful if you want to pre-render the app (e.g., server-side rendering or build-time rendering).
|
||||
|
||||
```js
|
||||
// Install the `module-alias` package as a dependency first
|
||||
const moduleAlias = require("module-alias");
|
||||
moduleAlias.addAliases({
|
||||
"react-native": require.resolve("react-native-web"),
|
||||
});
|
||||
moduleAlias();
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Root element
|
||||
|
||||
Full-screen React Native apps may require the following styles inlined in the HTML document shell. ([Example](https://codesandbox.io/s/52x1871vjl?file=/public/index.html:352-644).)
|
||||
|
||||
```css
|
||||
/* These styles make the body full-height */
|
||||
html, body { height: 100%; }
|
||||
/* These styles disable body scrolling if you are using <ScrollView> */
|
||||
body { overflow: hidden; }
|
||||
/* These styles make the root element full-height */
|
||||
#root { display:flex; height:100%; }
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Web-specific code
|
||||
|
||||
Minor platform differences can use the `Platform` module.
|
||||
|
||||
```js
|
||||
import { Platform } from 'react-native';
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
height: (Platform.OS === 'web') ? 200 : 100,
|
||||
});
|
||||
```
|
||||
|
||||
More significant platform differences should use platform-specific files (see the webpack configuration below for resolving `*.web.js` files):
|
||||
|
||||
For example, with the following files in your project:
|
||||
|
||||
```shell
|
||||
MyComponent.android.js
|
||||
MyComponent.ios.js
|
||||
MyComponent.web.js
|
||||
```
|
||||
|
||||
And the following import:
|
||||
|
||||
```js
|
||||
import MyComponent from './MyComponent';
|
||||
```
|
||||
|
||||
React Native will automatically import the correct variant for each specific target platform.
|
||||
|
||||
---
|
||||
|
||||
## Compiling and Bundling
|
||||
|
||||
What follows is only an _example_ of a basic way to package a Web app using [webpack](https://webpack.js.org) and [Babel](https://babeljs.io/). ([Metro](https://github.com/facebook/metro) is the React Native bundler with [undocumented web support](https://github.com/necolas/react-native-web/issues/1257#issuecomment-541443684).)
|
||||
|
||||
Install webpack-related dependencies, for example:
|
||||
|
||||
```shell
|
||||
npm install --save-dev babel-loader url-loader webpack webpack-cli webpack-dev-server
|
||||
```
|
||||
|
||||
React Native's Babel preset rewrites ES modules to CommonJS modules, preventing bundlers from automatically performing "tree-shaking" to remove unused modules from your web app build. To help with this, you can install the following Babel plugin:
|
||||
|
||||
```shell
|
||||
npm install --save-dev babel-plugin-react-native-web
|
||||
```
|
||||
|
||||
Create a `web/webpack.config.js` file:
|
||||
|
||||
```js
|
||||
// web/webpack.config.js
|
||||
|
||||
const path = require('path');
|
||||
const webpack = require('webpack');
|
||||
|
||||
const appDirectory = path.resolve(__dirname, '../');
|
||||
|
||||
// This is needed for webpack to compile JavaScript.
|
||||
// Many OSS React Native packages are not compiled to ES5 before being
|
||||
// published. If you depend on uncompiled packages they may cause webpack build
|
||||
// errors. To fix this webpack can be configured to compile to the necessary
|
||||
// `node_module`.
|
||||
const babelLoaderConfiguration = {
|
||||
test: /\.js$/,
|
||||
// Add every directory that needs to be compiled by Babel during the build.
|
||||
include: [
|
||||
path.resolve(appDirectory, 'index.web.js'),
|
||||
path.resolve(appDirectory, 'src'),
|
||||
path.resolve(appDirectory, 'node_modules/react-native-uncompiled')
|
||||
],
|
||||
use: {
|
||||
loader: 'babel-loader',
|
||||
options: {
|
||||
cacheDirectory: true,
|
||||
// The 'metro-react-native-babel-preset' preset is recommended to match React Native's packager
|
||||
presets: ['module:metro-react-native-babel-preset'],
|
||||
// Re-write paths to import only the modules needed by the app
|
||||
plugins: ['react-native-web']
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// This is needed for webpack to import static images in JavaScript files.
|
||||
const imageLoaderConfiguration = {
|
||||
test: /\.(gif|jpe?g|png|svg)$/,
|
||||
use: {
|
||||
loader: 'url-loader',
|
||||
options: {
|
||||
name: '[name].[ext]'
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
entry: [
|
||||
// load any web API polyfills
|
||||
// path.resolve(appDirectory, 'polyfills-web.js'),
|
||||
// your web-specific entry file
|
||||
path.resolve(appDirectory, 'index.web.js')
|
||||
],
|
||||
|
||||
// configures where the build ends up
|
||||
output: {
|
||||
filename: 'bundle.web.js',
|
||||
path: path.resolve(appDirectory, 'dist')
|
||||
},
|
||||
|
||||
// ...the rest of your config
|
||||
|
||||
module: {
|
||||
rules: [
|
||||
babelLoaderConfiguration,
|
||||
imageLoaderConfiguration
|
||||
]
|
||||
},
|
||||
|
||||
resolve: {
|
||||
// This will only alias the exact import "react-native"
|
||||
alias: {
|
||||
'react-native$': 'react-native-web'
|
||||
},
|
||||
// If you're working on a multi-platform React Native app, web-specific
|
||||
// module implementations should be written in files using the extension
|
||||
// `.web.js`.
|
||||
extensions: [ '.web.js', '.js' ]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
To run in development from the root of your application:
|
||||
|
||||
```shell
|
||||
./node_modules/.bin/webpack-dev-server -d --config ./web/webpack.config.js --inline --hot --colors
|
||||
```
|
||||
|
||||
To build for production:
|
||||
|
||||
```shell
|
||||
./node_modules/.bin/webpack -p --config ./web/webpack.config.js
|
||||
```
|
||||
|
||||
Please refer to the Webpack documentation for more information on configuration.
|
||||
@@ -0,0 +1,83 @@
|
||||
---
|
||||
title: React Native compatibility
|
||||
date: Last Modified
|
||||
permalink: /docs/react-native-compatibility/index.html
|
||||
eleventyNavigation:
|
||||
key: React Native compatibility
|
||||
parent: Start
|
||||
order: 4
|
||||
---
|
||||
|
||||
:::lead
|
||||
React Native for Web provides compatibility with the vast majority of React Native's JavaScript API. Features deprecated in React Native should be considered *unsupported* in React Native for Web.
|
||||
:::
|
||||
|
||||
**Best used with React Native >= 0.63**.
|
||||
|
||||
Visit the [React Native Directory](https://reactnative.directory/?web=true) to find React Native packages with known web support.
|
||||
|
||||
## Components
|
||||
|
||||
| Name | Status | Notes |
|
||||
| :----------------------- | :----- | :---- |
|
||||
| ActivityIndicator | ✓ | |
|
||||
| Button | ✓ | |
|
||||
| CheckBox | ✓ | |
|
||||
| FlatList | ✓ | |
|
||||
| Image | ✓ | Missing multiple sources ([#515](https://github.com/necolas/react-native-web/issues/515)) and HTTP headers ([#1019](https://github.com/necolas/react-native-web/issues/1019)). |
|
||||
| ImageBackground | ✓ | |
|
||||
| KeyboardAvoidingView | (✓) | Mock. No equivalent web APIs. |
|
||||
| Modal | ✓ | |
|
||||
| Picker | ✓ | |
|
||||
| Pressable | ✓ | |
|
||||
| RefreshControl | ✘ | Not started ([#1027](https://github.com/necolas/react-native-web/issues/1027)). |
|
||||
| SafeAreaView | ✓ | |
|
||||
| ScrollView | ✓ | Missing momentum scroll events ([#1021](https://github.com/necolas/react-native-web/issues/1021)). |
|
||||
| SectionList | ✓ | |
|
||||
| StatusBar | (✓) | Mock. No equivalent web APIs. |
|
||||
| Switch | ✓ | |
|
||||
| Text | ✓ | Missing `onLongPress` ([#1011](https://github.com/necolas/react-native-web/issues/1011)) support. |
|
||||
| TextInput | ✓ | Missing rich text features ([#1023](https://github.com/necolas/react-native-web/issues/1023)), and auto-expanding behaviour ([#795](https://github.com/necolas/react-native-web/issues/795)). |
|
||||
| Touchable | ✓ | Includes additional support for mouse and keyboard interactions. |
|
||||
| TouchableHighlight | ✓ | |
|
||||
| TouchableNativeFeedback | ✘ | Not started ([#1024](https://github.com/necolas/react-native-web/issues/1024)). |
|
||||
| TouchableOpacity | ✓ | |
|
||||
| TouchableWithoutFeedback | ✓ | |
|
||||
| View | ✓ | |
|
||||
| VirtualizedList | ✓ | |
|
||||
| YellowBox | (✓) | Mock. No YellowBox functionality. |
|
||||
|
||||
## APIs
|
||||
|
||||
| Name | Status | Notes |
|
||||
| :----------------------- | :----- | :---- |
|
||||
| AccessibilityInfo | (✓) | Mock. No equivalent web APIs. |
|
||||
| Alert | ✘ | Not started ([#1026](https://github.com/necolas/react-native-web/issues/1026)). |
|
||||
| Animated | ✓ | Missing `useNativeDriver` support. |
|
||||
| Appearance | ✓ | |
|
||||
| AppRegistry | ✓ | Includes additional support for server rendering with `getApplication`. |
|
||||
| AppState | ✓ | |
|
||||
| BackHandler | (✓) | Mock. No equivalent web APIs. |
|
||||
| Clipboard | ✓ | |
|
||||
| DeviceInfo | (✓) | Limited information. |
|
||||
| Dimensions | ✓ | |
|
||||
| Easing | ✓ | |
|
||||
| Geolocation | ✓ | |
|
||||
| I18nManager | ✓ | Includes additional support for runtime switch to RTL. |
|
||||
| InteractionManager | (✓) | |
|
||||
| Keyboard | (✓) | Mock. |
|
||||
| LayoutAnimation | (✓) | Missing translation to web animations. |
|
||||
| Linking | ✓ | |
|
||||
| NativeEventEmitter | ✓ | |
|
||||
| NativeMethodsMixin | ✓ | |
|
||||
| NativeModules | (✓) | Mocked. Missing ability to load native modules. |
|
||||
| PanResponder | ✓ | |
|
||||
| PixelRatio | ✓ | |
|
||||
| Platform | ✓ | |
|
||||
| Settings | ✘ | No equivalent web APIs. |
|
||||
| Share | ✓ | Only available over HTTPS. Read about the [Web Share API](https://wicg.github.io/web-share/). |
|
||||
| StyleSheet | ✓ | |
|
||||
| UIManager | ✓ | |
|
||||
| Vibration | ✓ | |
|
||||
| useColorScheme | ✓ | |
|
||||
| useWindowDimensions | ✓ | |
|
||||
9
packages/docs/src/pages/docs/hooks/_.md
Normal file
9
packages/docs/src/pages/docs/hooks/_.md
Normal file
@@ -0,0 +1,9 @@
|
||||
---
|
||||
title: Hooks
|
||||
date: Last Modified
|
||||
permalink: false
|
||||
eleventyNavigation:
|
||||
key: Hooks
|
||||
title: Hooks
|
||||
order: 40
|
||||
---
|
||||
33
packages/docs/src/pages/docs/hooks/use-color-scheme.md
Normal file
33
packages/docs/src/pages/docs/hooks/use-color-scheme.md
Normal file
@@ -0,0 +1,33 @@
|
||||
---
|
||||
title: useColorScheme
|
||||
date: Last Modified
|
||||
permalink: /docs/use-color-scheme/index.html
|
||||
eleventyNavigation:
|
||||
key: useColorScheme
|
||||
parent: Hooks
|
||||
---
|
||||
|
||||
{% import "fragments/macros.html" as macro with context %}
|
||||
|
||||
:::lead
|
||||
The `useColorScheme` React hook provides and subscribes to color scheme updates from the `Appearance` module.
|
||||
:::
|
||||
|
||||
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).
|
||||
|
||||
```js
|
||||
import { useColorScheme } from 'react-native';
|
||||
const colorScheme = useColorScheme();
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## API
|
||||
|
||||
### Return value
|
||||
|
||||
`useColorScheme` returns the color scheme value.
|
||||
|
||||
{% call macro.prop('colorScheme', '"dark" | "light" | null') %}
|
||||
A string representing the color scheme.
|
||||
{% endcall %}
|
||||
41
packages/docs/src/pages/docs/hooks/use-window-dimensions.md
Normal file
41
packages/docs/src/pages/docs/hooks/use-window-dimensions.md
Normal file
@@ -0,0 +1,41 @@
|
||||
---
|
||||
title: useWindowDimensions
|
||||
date: Last Modified
|
||||
permalink: /docs/use-window-dimensions/index.html
|
||||
eleventyNavigation:
|
||||
key: useWindowDimensions
|
||||
parent: Hooks
|
||||
---
|
||||
|
||||
{% import "fragments/macros.html" as macro with context %}
|
||||
|
||||
:::lead
|
||||
The `useWindowDimensions` React hook provides and subscribes to window size changes from the `Dimensions` module.
|
||||
:::
|
||||
|
||||
`useWindowDimensions` automatically updates `width` and `height` values when viewport size changes.
|
||||
|
||||
```js
|
||||
import { useWindowDimensions } from 'react-native';
|
||||
const { height, scale, width } = useWindowDimensions();
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## API
|
||||
|
||||
### Return value
|
||||
|
||||
`useWindowDimensions` returns the `window` dimension object.
|
||||
|
||||
{% call macro.prop('height', 'number') %}
|
||||
The height in pixels of the app viewport.
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('scale', 'number') %}
|
||||
The pixel ratio of the device your app is running on.
|
||||
{% endcall %}
|
||||
|
||||
{% call macro.prop('width', 'number') %}
|
||||
The width in pixels of the app viewport.
|
||||
{% endcall %}
|
||||
6
packages/docs/src/pages/home.md
Normal file
6
packages/docs/src/pages/home.md
Normal file
@@ -0,0 +1,6 @@
|
||||
---
|
||||
title: React Native for Web
|
||||
date: Last Modified
|
||||
permalink: /
|
||||
layout: layouts/home.html
|
||||
---
|
||||
3
packages/docs/src/pages/pages.json
Normal file
3
packages/docs/src/pages/pages.json
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"layout": "layouts/page.html"
|
||||
}
|
||||
1
packages/docs/src/static/logo.svg
Normal file
1
packages/docs/src/static/logo.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg width="32" height="32" fill="#1977f2" xmlns="http://www.w3.org/2000/svg"><path d="M26.31 10.978a21.425 21.425 0 00-1.03-.325c.058-.237.112-.472.16-.702.78-3.785.27-6.835-1.472-7.839-1.669-.962-4.4.041-7.156 2.441-.265.23-.531.475-.797.731-.177-.17-.354-.333-.53-.49-2.89-2.565-5.787-3.647-7.526-2.64-1.668.966-2.162 3.832-1.46 7.42.068.346.147.7.237 1.06-.41.116-.806.24-1.184.372C2.164 12.187 0 14.038 0 15.959c0 1.983 2.323 3.972 5.851 5.178.279.095.568.185.866.27-.097.39-.181.77-.252 1.143-.669 3.525-.146 6.324 1.517 7.283 1.718.99 4.602-.028 7.41-2.482.221-.194.444-.4.667-.615.29.278.578.542.865.789 2.72 2.34 5.406 3.285 7.067 2.323 1.717-.993 2.275-4 1.55-7.658a18.09 18.09 0 00-.191-.856c.202-.06.4-.121.595-.186 3.668-1.215 6.055-3.18 6.055-5.19 0-1.927-2.233-3.79-5.69-4.98zm-.795 8.873c-.175.058-.355.114-.538.168a32.06 32.06 0 00-1.62-4.054 32.047 32.047 0 001.557-3.995c.328.095.645.195.951.3 2.962 1.02 4.768 2.527 4.768 3.689 0 1.236-1.95 2.842-5.118 3.892zM24.2 22.455c.32 1.618.365 3.08.153 4.224-.19 1.027-.574 1.712-1.047 1.986-1.009.584-3.165-.175-5.491-2.176-.267-.23-.535-.475-.805-.734a32.098 32.098 0 002.682-3.406 31.897 31.897 0 004.334-.668c.066.264.123.522.174.774zm-13.292 6.11c-.985.347-1.77.357-2.244.084-1.01-.582-1.429-2.83-.856-5.844.065-.346.143-.7.233-1.063 1.31.29 2.762.499 4.312.625a33.288 33.288 0 002.747 3.393c-.204.197-.407.385-.61.562-1.24 1.085-2.485 1.855-3.582 2.242zm-4.615-8.722c-1.56-.533-2.85-1.226-3.733-1.983-.793-.68-1.194-1.354-1.194-1.901 0-1.166 1.737-2.652 4.635-3.662.351-.123.72-.238 1.101-.347a32.77 32.77 0 001.56 4.042 33.3 33.3 0 00-1.58 4.099c-.272-.079-.536-.16-.79-.248zM7.84 9.311c-.602-3.073-.202-5.392.803-5.974 1.07-.62 3.438.264 5.933 2.48.16.141.32.29.48.443a32.757 32.757 0 00-2.726 3.373c-1.505.14-2.946.364-4.27.664a20.04 20.04 0 01-.22-.986zm13.803 3.408a43.506 43.506 0 00-.973-1.6c1.021.13 2 .3 2.918.51-.276.884-.62 1.808-1.024 2.756a47.536 47.536 0 00-.92-1.666zm-5.629-5.482a29.21 29.21 0 011.883 2.273 40.252 40.252 0 00-3.782 0 30.151 30.151 0 011.9-2.273zm-5.665 5.492a40.383 40.383 0 00-.903 1.655 30.172 30.172 0 01-1.017-2.77 30.81 30.81 0 012.901-.497 40.233 40.233 0 00-.98 1.612zm1.01 8.169a29.106 29.106 0 01-2.949-.474c.283-.913.63-1.86 1.037-2.825a40.513 40.513 0 001.912 3.3zm4.693 3.879a30.679 30.679 0 01-1.925-2.305A47.86 47.86 0 0016 22.51c.652 0 1.297-.015 1.932-.043a29.079 29.079 0 01-1.879 2.31zm6.525-7.227a29.01 29.01 0 011.074 2.814c-.927.212-1.93.383-2.985.51.333-.527.66-1.07.983-1.629a43.5 43.5 0 00.928-1.695zm-2.112 1.012c-.5.867-1.014 1.695-1.536 2.477-.95.068-1.93.103-2.93.103-.996 0-1.964-.031-2.897-.092a38.382 38.382 0 01-2.93-5.059 38.453 38.453 0 012.913-5.05 38.486 38.486 0 015.833 0c.53.783 1.046 1.606 1.542 2.463.502.867.963 1.726 1.38 2.568a41.219 41.219 0 01-1.375 2.59zm2.82-15.265c1.071.618 1.488 3.11.815 6.378-.043.208-.092.42-.144.636a32.752 32.752 0 00-4.279-.676 32.114 32.114 0 00-2.705-3.376c.246-.236.492-.462.736-.675 2.363-2.056 4.57-2.868 5.577-2.287zM16 13.1a2.858 2.858 0 110 5.715 2.858 2.858 0 010-5.715z"/></svg>
|
||||
|
After Width: | Height: | Size: 3.0 KiB |
9
packages/examples/.babelrc
Normal file
9
packages/examples/.babelrc
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"presets": [
|
||||
"next/babel",
|
||||
"@babel/preset-flow"
|
||||
],
|
||||
"plugins": [
|
||||
[ "react-native-web", { "commonjs": true } ]
|
||||
]
|
||||
}
|
||||
3
packages/examples/README.md
Normal file
3
packages/examples/README.md
Normal file
@@ -0,0 +1,3 @@
|
||||
# Example app
|
||||
|
||||
Next.js pages and React Native components. Provides interactive examples for the documentation website.
|
||||
11
packages/examples/next.config.js
Normal file
11
packages/examples/next.config.js
Normal file
@@ -0,0 +1,11 @@
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
const pages = fs.readdirSync(path.resolve(__dirname, 'pages'), { withFileTypes: true })
|
||||
.filter((dirent) => dirent.isDirectory())
|
||||
.map((dirent) => dirent.name);
|
||||
|
||||
module.exports = {
|
||||
outDir: 'dist',
|
||||
env: { pages }
|
||||
};
|
||||
22
packages/examples/package.json
Normal file
22
packages/examples/package.json
Normal file
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"private": true,
|
||||
"name": "examples",
|
||||
"version": "0.14.13",
|
||||
"scripts": {
|
||||
"dev": "next",
|
||||
"build": "next build",
|
||||
"start": "next start"
|
||||
},
|
||||
"dependencies": {
|
||||
"next": "^10.0.6",
|
||||
"react": "^17.0.1",
|
||||
"react-dom": "^17.0.1",
|
||||
"react-native-web": "0.14.13"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.12.10",
|
||||
"@babel/preset-flow": "^7.8.3",
|
||||
"babel-plugin-react-native-web": "0.14.13"
|
||||
},
|
||||
"license": "MIT"
|
||||
}
|
||||
48
packages/examples/pages/activity-indicator/index.js
Normal file
48
packages/examples/pages/activity-indicator/index.js
Normal file
@@ -0,0 +1,48 @@
|
||||
import { ActivityIndicator, StyleSheet, View } from 'react-native';
|
||||
import React from 'react';
|
||||
import Example from '../../shared/example';
|
||||
|
||||
export default function ActivityIndicatorPage() {
|
||||
const [animating,setAnimating] = React.useState(true);
|
||||
|
||||
React.useEffect(() => {
|
||||
const interval = setInterval(() => {
|
||||
setAnimating(!animating);
|
||||
}, 2000);
|
||||
return () => {
|
||||
clearInterval(interval);
|
||||
};
|
||||
}, [animating]);
|
||||
|
||||
return (
|
||||
<Example title="ActivityIndicator">
|
||||
<View style={styles.row}>
|
||||
<ActivityIndicator style={styles.item} />
|
||||
<ActivityIndicator animating={false} hidesWhenStopped={false} style={styles.item} />
|
||||
<ActivityIndicator animating={animating} hidesWhenStopped={false} style={styles.item} />
|
||||
</View>
|
||||
<View style={styles.row}>
|
||||
<ActivityIndicator color="#1DA1F2" size="small" style={styles.item} />
|
||||
<ActivityIndicator color="#17BF63" size={20} style={styles.item} />
|
||||
</View>
|
||||
<View style={styles.row}>
|
||||
<ActivityIndicator color="#FFAD1F" size="large" style={styles.item} />
|
||||
<ActivityIndicator color="#F45D22" size={36} style={styles.item} />
|
||||
</View>
|
||||
<View style={styles.row}>
|
||||
<ActivityIndicator color="#794BC4" size={60} style={styles.item} />
|
||||
</View>
|
||||
</Example>
|
||||
);
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
row: {
|
||||
alignItems: 'center',
|
||||
flexDirection: 'row',
|
||||
marginVertical: 20
|
||||
},
|
||||
item: {
|
||||
paddingHorizontal: 10
|
||||
}
|
||||
});
|
||||
33
packages/examples/pages/app-state/index.js
Normal file
33
packages/examples/pages/app-state/index.js
Normal file
@@ -0,0 +1,33 @@
|
||||
import React from 'react';
|
||||
import { AppState, Text } from 'react-native';
|
||||
import Example from '../../shared/example';
|
||||
|
||||
export default function AppStatePage() {
|
||||
const [state, setState] = React.useState({
|
||||
active: 0,
|
||||
background: 0,
|
||||
currentState: AppState.currentState
|
||||
});
|
||||
|
||||
React.useEffect(() => {
|
||||
const handleChange = (nextState) => {
|
||||
setState((previousState) => ({
|
||||
...previousState,
|
||||
[nextState]: previousState[nextState] + 1
|
||||
}));
|
||||
};
|
||||
|
||||
AppState.addEventListener('change', handleChange);
|
||||
return () => {
|
||||
AppState.removeEventListener('change', handleChange);
|
||||
};
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<Example title="AppState">
|
||||
<Text>AppState.currentState: <Text style={{ fontWeight:'bold'}}>{state.currentState}</Text></Text>
|
||||
<Text>Active count: {state.active}</Text>
|
||||
<Text>Background count: {state.background}</Text>
|
||||
</Example>
|
||||
);
|
||||
}
|
||||
36
packages/examples/pages/button/index.js
Normal file
36
packages/examples/pages/button/index.js
Normal file
@@ -0,0 +1,36 @@
|
||||
import React from 'react';
|
||||
import { Button, StyleSheet, View } from 'react-native';
|
||||
import Example from '../../shared/example';
|
||||
|
||||
const emptyFunction = () => {};
|
||||
|
||||
function Divider() {
|
||||
return <View style={styles.divider} />
|
||||
}
|
||||
|
||||
export default function ButtonPage() {
|
||||
const disabledOnPress = () => {
|
||||
console.error('Disabled button should not trigger onPress!');
|
||||
};
|
||||
|
||||
return (
|
||||
<Example title="Button">
|
||||
<Divider />
|
||||
<Button onPress={emptyFunction} title="Button" />
|
||||
<Divider />
|
||||
<Button color="#17BF63" onPress={emptyFunction} title="Button" />
|
||||
<Divider />
|
||||
<Button color="#794BC4" onPress={emptyFunction} title="Button" />
|
||||
<Divider />
|
||||
<Button color="#E0245E" onPress={emptyFunction} title="Button" />
|
||||
<Divider />
|
||||
<Button disabled onPress={disabledOnPress} title="Disabled button" />
|
||||
</Example>
|
||||
);
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
divider: {
|
||||
height: '1rem'
|
||||
}
|
||||
});
|
||||
62
packages/examples/pages/checkbox/index.js
Normal file
62
packages/examples/pages/checkbox/index.js
Normal file
@@ -0,0 +1,62 @@
|
||||
import { CheckBox, StyleSheet, View } from 'react-native';
|
||||
import React from 'react';
|
||||
import Example from '../../shared/example';
|
||||
|
||||
function Divider() {
|
||||
return <View style={styles.divider} />
|
||||
}
|
||||
|
||||
export default function CheckboxPage() {
|
||||
const [checked,setChecked] = React.useState(true);
|
||||
|
||||
React.useEffect(() => {
|
||||
const interval = setInterval(() => {
|
||||
setChecked(!checked);
|
||||
}, 2500);
|
||||
return () => {
|
||||
clearInterval(interval);
|
||||
};
|
||||
}, [checked]);
|
||||
|
||||
return (
|
||||
<Example title="CheckBox">
|
||||
<View style={styles.row}>
|
||||
<CheckBox disabled style={styles.item} value={false} />
|
||||
<Divider />
|
||||
<CheckBox disabled style={styles.item} value={true} />
|
||||
</View>
|
||||
<View style={styles.row}>
|
||||
<CheckBox value={false} />
|
||||
<Divider />
|
||||
<CheckBox value={true} />
|
||||
</View>
|
||||
<View style={styles.row}>
|
||||
<CheckBox color="#1DA1F2" value={true} />
|
||||
<Divider />
|
||||
<CheckBox color="#17BF63" value={true} />
|
||||
<Divider />
|
||||
<CheckBox color="#FFAD1F" value={true} />
|
||||
<Divider />
|
||||
<CheckBox color="#F45D22" value={true} />
|
||||
<Divider />
|
||||
<CheckBox color="#794BC4" value={true} />
|
||||
<Divider />
|
||||
<CheckBox color="#E0245E" value={true} />
|
||||
</View>
|
||||
<View style={styles.row}>
|
||||
<CheckBox color="#1DA1F2" style={{ height: 32, width: 32 }} value={checked} />
|
||||
</View>
|
||||
</Example>
|
||||
);
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
row: {
|
||||
alignItems: 'center',
|
||||
flexDirection: 'row',
|
||||
marginVertical: 20
|
||||
},
|
||||
divider: {
|
||||
width: 10
|
||||
}
|
||||
});
|
||||
36
packages/examples/pages/clipboard/index.js
Normal file
36
packages/examples/pages/clipboard/index.js
Normal file
@@ -0,0 +1,36 @@
|
||||
import { Button, Clipboard, StyleSheet, TextInput, View } from 'react-native';
|
||||
import React from 'react';
|
||||
import Example from '../../shared/example';
|
||||
|
||||
export default function ClipboardPage() {
|
||||
const setString = () => {
|
||||
const success = Clipboard.setString('This text was copied to the clipboard by React Native');
|
||||
console.log(`Clipboard.setString success? ${success}`);
|
||||
};
|
||||
|
||||
return (
|
||||
<Example title="Clipboard"w>
|
||||
<View style={styles.buttonBox}>
|
||||
<Button onPress={setString} title="Copy to clipboard" />
|
||||
</View>
|
||||
<TextInput
|
||||
multiline={true}
|
||||
placeholder={'Try pasting here afterwards'}
|
||||
style={styles.textInput}
|
||||
/>
|
||||
</Example>
|
||||
);
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
buttonBox: {
|
||||
maxWidth: 300
|
||||
},
|
||||
textInput: {
|
||||
borderColor: '#AAB8C2',
|
||||
borderWidth: 1,
|
||||
height: 50,
|
||||
marginTop: 20,
|
||||
padding: 5
|
||||
}
|
||||
});
|
||||
29
packages/examples/pages/dimensions/index.js
Normal file
29
packages/examples/pages/dimensions/index.js
Normal file
@@ -0,0 +1,29 @@
|
||||
import React from 'react';
|
||||
import { Dimensions, Text } from 'react-native';
|
||||
import Example from '../../shared/example';
|
||||
|
||||
export default function DimensionsPage() {
|
||||
const [screenDims, setScreen] = React.useState(Dimensions.get('screen'));
|
||||
const [windowDims, setWindow] = React.useState(Dimensions.get('window'));
|
||||
|
||||
React.useEffect(() => {
|
||||
const handleChange = ({ screen, window: win }) => {
|
||||
setScreen(screen)
|
||||
setWindow(win);
|
||||
}
|
||||
|
||||
Dimensions.addEventListener('change', handleChange);
|
||||
return () => {
|
||||
Dimensions.removeEventListener('change', handleChange);
|
||||
}
|
||||
}, [setScreen, setWindow]);
|
||||
|
||||
return (
|
||||
<Example title="Dimensions">
|
||||
<Text style={{ marginBottom: '1em' }} suppressHydrationWarnings={true}>
|
||||
window: {JSON.stringify(windowDims, null, 2)}
|
||||
</Text>
|
||||
<Text suppressHydrationWarnings={true}>screen: {JSON.stringify(screenDims, null, 2)}</Text>
|
||||
</Example>
|
||||
);
|
||||
}
|
||||
603
packages/examples/pages/i18n-manager/index.js
Normal file
603
packages/examples/pages/i18n-manager/index.js
Normal file
@@ -0,0 +1,603 @@
|
||||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*
|
||||
* @noflow
|
||||
*/
|
||||
|
||||
/* eslint-disable no-use-before-define */
|
||||
|
||||
import React from 'react';
|
||||
import {
|
||||
Button,
|
||||
I18nManager,
|
||||
Image,
|
||||
PixelRatio,
|
||||
Platform,
|
||||
ScrollView,
|
||||
StyleSheet,
|
||||
Text,
|
||||
Switch,
|
||||
View
|
||||
} from 'react-native';
|
||||
import Example from '../../shared/example';
|
||||
|
||||
const SCALE = PixelRatio.get();
|
||||
const IMAGE_DIMENSION = 100 * SCALE;
|
||||
const IMAGE_SIZE = [IMAGE_DIMENSION, IMAGE_DIMENSION];
|
||||
const iconSource =
|
||||
'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0nMjAwJyBoZWlnaHQ9JzIwMCcgZmlsbD0iIzAwMDAwMCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgdmVyc2lvbj0iMS4xIiB4PSIwcHgiIHk9IjBweCIgdmlld0JveD0iMCAwIDEwMCAxMDAiIGVuYWJsZS1iYWNrZ3JvdW5kPSJuZXcgMCAwIDEwMCAxMDAiIHhtbDpzcGFjZT0icHJlc2VydmUiPjxnPjxwYXRoIGQ9Ik0yNS44NjcsNDguODUzQzMyLjgwNiw1MC4xNzYsNDYuNDYsNTIuNSw2MS4yMTUsNTIuNWgwLjAwNWM5LjcxLDAsMTguNDAxLTEuMDU3LDI1LjkzOC0yLjkxMyAgIGMwLjE1OS0wLjA0NiwwLjM1LTAuMTM1LDAuNTY1LTAuMTg3YzAuMjgyLTAuMDcyLDAuNTY1LTAuMTY0LDAuODQ0LTAuMjM4YzMuMTg0LTAuOTY0LDIuNTc3LTMuMDUxLDIuMTk5LTMuODUyICAgYy00LjE2Ni03LjcxOS0xNS4wODYtMjMuNDE1LTM1LjAyOC0yMy40MTVjLTIyLjE2OSwwLTMwLjI2MiwxMC42MzUtMzMuMTQsMTkuNTg5QzIyLjU0NSw0Mi4zMzMsMjIuNDA3LDQ3LjEzNSwyNS44NjcsNDguODUzeiAgICBNMjguNjc2LDM4LjAzMmMwLjAxMy0wLjAzNiwwLjYxNC0xLjYyNiwxLjkyMy0xLjAwOGMxLjEzMywwLjUzNSwwLjk2MSwxLjU2MywwLjg4NywxLjg1Yy0wLjAwNywwLjAyNC0wLjAxNCwwLjA0OC0wLjAyMSwwLjA3MyAgIGMwLDAuMDAxLTAuMDAxLDAuMDA0LTAuMDAxLDAuMDA0bDAsMGMtMC4yNDksMC45MjktMC40MDQsMi4wODYtMC4wMTcsMi44NmMwLjE2LDAuMzE5LDAuNDkyLDAuNzY4LDEuNTQyLDAuOTg3bDAuMzY2LDAuMDc3ICAgYzIwLjgxNiw0LjM2LDM2LDIuOTMzLDQ1LjY3OCwwLjYyNmwtMC4wMDQsMC4wMDJjMCwwLDAuMDA1LTAuMDAyLDAuMDA3LTAuMDAzYzAuMjEyLTAuMDUsMC40MjEtMC4xMDEsMC42MjgtMC4xNTIgICBjMC41MDktMC4wNSwxLjE3MywwLjA3OCwxLjM5OSwxYzAuMzUxLDEuNDI0LTAuOTczLDEuODk1LTEuMjE3LDEuOTY5Yy01LjMyNSwxLjI3OS0xMi4yNjYsMi4zMDYtMjAuODM1LDIuMzA3ICAgYy03LjUwNSwwLTE2LjI1NS0wLjc4Ny0yNi4yNTctMi44ODJsLTAuMzY0LTAuMDc3Yy0yLjEyLTAuNDQyLTMuMTExLTEuNjMzLTMuNTY5LTIuNTU1QzI3Ljk4NSw0MS40MjEsMjguMjgxLDM5LjQxNiwyOC42NzYsMzguMDMyICAgeiI+PC9wYXRoPjxjaXJjbGUgY3g9IjEwLjQ5MyIgY3k9IjIzLjQ1NSIgcj0iMC42MTkiPjwvY2lyY2xlPjxwYXRoIGQ9Ik0yLjA4LDI4LjMwOGMwLjY3Ni0wLjE3OCwwLjk4My0wLjM1MiwxLjE3NC0wLjVDNC42OSwyNi42OSw2LjUsMjcuNDgzLDcuNSwyOC4zNTd2MC4wMDJjMCwwLDEuNzExLDEuMjM1LDAuNzM3LDIuMjAyICAgYy0wLjk3NCwwLjk2NS0yLjMxOSwwLjAwNi0yLjMxOSwwLjAwNmwwLjAzNSwwLjAxNmMtMC4zMjctMC4yMDMtMC42LTAuNTYxLTAuNzgtMC41ODRjLTAuMzcsMC4yNi0wLjg3NiwwLjUtMS40NzYsMC41SDMuNyAgIGMwLDAtMS4zNDUsMC43MDksMC4xNzgsMS42NTJjMC4wMDEsMC4wMDEsMC4wMDIsMC4wNzIsMC4wMDQsMC4wNzNjMy45MzksMi4zNDIsOC4yNzEsNS43MDEsOC4yNzEsOC44OCAgIGMwLDAuNjkxLDAuMiwxNy4wNDIsMTcuNjI2LDI0LjczOWwwLjk2NywwLjQ0MmwtMC4xLDEuMDU5Yy0wLjQyMSw0LjM5LDEuMTQ1LDEwLjE5MSwxMC45OTMsMTIuODg4bDAuMTEzLDAuMDM4ICAgYzAuMDY3LDAuMDIzLDYuNzMyLDIuNDI5LDEwLjkwNywyLjQyOWMxLjU4NCwwLDIuMTU1LTAuMzUyLDIuMjQzLTAuNTYxYzAuMDg1LTAuMjAyLDAuNjEyLTIuMTY0LTYuMzMyLTkuMzg3bDAuMDAyLTAuMTgzICAgYzAsMC0yLjQ3Ny0zLjA3LDEuNTMzLTMuMDdjMC4wMSwwLDAuMDE5LDAsMC4wMjksMGMxLjI4NSwwLDIuNjA4LDAuMjE1LDMuOTgsMC4xODRjNC43NzEtMC4xMTcsOS4zMTYtMC40MjUsMTMuNTA2LTEuMDk2ICAgbDAuNDc0LTAuMDI4bDAuNjY4LDAuMTU4YzkuNjUxLDQuOTQ4LDE2LjczOCw3LjcxNiwxOS43MzgsNy43MTZ2MC4wMDZjMCwwLDAuMTY0LDAuMDExLDAuMjMsMC4wMDQgICBjLTAuMTg5LTAuNzIzLTIuMjMtMi44LTcuMjMtOS4wNzl2MC4wMjFjMCwwLTEuNTEyLTEuNjU4LDAuNzk3LTIuNjUzYzAuMDYzLTAuMDI2LDAuMDA4LDAuMDIzLDAuMDYtMC4wMDEgICBjOC42MzktMy41MDksMTMuNTAxLTguMjA0LDE1LjQxMS0xMS43NzVjMS4xNDUtMi4xMjksMC4yMDYtMi43ODQtMC42NTktMi45NzZjLTAuMzE3LTAuMDM4LTAuNjM0LTAuMDYyLTAuOTEyLTAuMDYyICAgYy0wLjIwNSwwLTAuMzc5LDAuMDEtMC41MjgsMC4wMjdsLTMuMTQzLDEuMjE0QzgzLjczMiw1My45MjYsNzMuMjE4LDU1LjUsNjEuMjIsNTUuNWMtMC4wMDIsMC0wLjAwNSwwLTAuMDA1LDAgICBjLTE1LjEyOCwwLTI5LjEwMS0yLjQzMi0zNi4wODMtMy43NzFsLTAuMTczLTAuMTExbC0wLjE2LTAuMTI2Yy01Ljg1OC0yLjY4MS01LjEzNy0xMC4yMDItNS4xMDMtMTAuNTE5bDAuMDYtMC4zICAgYzAuODk1LTIuODM4LDIuNDY3LTYuMzUyLDUuMjEzLTkuNzE5Yy0xLjgwOC0xLjM2OS00LjU5LTQuMTg4LTQuNDMtOC40OTRjMC4wNDYtMS4yNDQtMC40ODYtMi41MDgtMS40OTgtMy41NTkgICBjLTEuNDk4LTEuNTU1LTMuNzg1LTIuNDQ2LTYuMjc0LTIuNDQ2Yy0xLjc3LDAtMy41NTMsMC40NDItNS4yOTMsMS4zMTRjLTQuMDYxLDIuMDM1LTQuODU1LDQuNzM2LTUuNjkyLDcuNTk2ICAgYy0wLjEzNiwwLjQ2OC0wLjI4NCwwLjkzOS0wLjQzOCwxLjQxYy0wLjAwNiwwLjAxOS0wLjAyMiwwLjAzNS0wLjAyOCwwLjA1NkMwLjgzMywyOC40MjMsMS42OTEsMjguMzksMi4wOCwyOC4zMDh6IE0xMC40OTMsMTkuOTA4ICAgYzEuOTU2LDAsMy41NDgsMS41OTEsMy41NDgsMy41NDdjMCwxLjk1Ny0xLjU5MiwzLjU0OC0zLjU0OCwzLjU0OGMtMS45NTcsMC0zLjU0OC0xLjU5Mi0zLjU0OC0zLjU0OCAgIEM2Ljk0NCwyMS40OTksOC41MzYsMTkuOTA4LDEwLjQ5MywxOS45MDh6Ij48L3BhdGg+PC9nPjwvc3ZnPg==';
|
||||
|
||||
function ListItem(props) {
|
||||
return (
|
||||
<View style={styles.row}>
|
||||
<View style={styles.column1}>
|
||||
<Image source={props.imageSource} style={styles.icon} />
|
||||
</View>
|
||||
<View style={styles.column2}>
|
||||
<View style={styles.textBox}>
|
||||
<Text>Text Text Text</Text>
|
||||
</View>
|
||||
</View>
|
||||
<View style={styles.column3}>
|
||||
<Button onPress={() => {}} style={styles.smallButton} title="Button" />
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
||||
function TextAlignmentExample(props) {
|
||||
return (
|
||||
<Block description={props.description} title={props.title}>
|
||||
<View>
|
||||
<Text style={props.style}>Left-to-Right language text alignment.</Text>
|
||||
<Text style={props.style}>
|
||||
{'\u0645\u0646 \u0627\u0644\u064A\u0645\u064A\u0646 ' +
|
||||
'\u0625\u0644\u0649 \u0627\u0644\u064A\u0633\u0627\u0631 ' +
|
||||
'\u0627\u0644\u0644\u063A\u0629 \u062F\u0648\u0646 ' +
|
||||
'\u0645\u062D\u0627\u0630\u0627\u0629 \u0627\u0644\u0646\u0635'}
|
||||
</Text>
|
||||
<Text style={props.style}>
|
||||
{'\u05DE\u05D9\u05DE\u05D9\u05DF \u05DC\u05E9\u05DE\u05D0\u05DC ' +
|
||||
'\u05D4\u05E9\u05E4\u05D4 \u05D1\u05DC\u05D9 ' +
|
||||
'\u05D9\u05D9\u05E9\u05D5\u05E8 \u05D8\u05E7\u05E1\u05D8'}
|
||||
</Text>
|
||||
</View>
|
||||
</Block>
|
||||
);
|
||||
}
|
||||
|
||||
function withRTLState(Component) {
|
||||
return class extends React.Component {
|
||||
constructor(...args) {
|
||||
super(...args);
|
||||
this.state = {
|
||||
isRTL: false
|
||||
};
|
||||
}
|
||||
|
||||
render() {
|
||||
const isRTL = Platform === 'ios' ? this.state.isRTL : I18nManager.isRTL;
|
||||
const setRTL = isRTL => this.setState({ isRTL: isRTL });
|
||||
return <Component isRTL={isRTL} setRTL={setRTL} />;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
const RTLToggler = ({ isRTL, setRTL }) => {
|
||||
if (Platform.OS !== 'ios') {
|
||||
return <Text style={styles.rtlToggler}>{isRTL ? 'RTL' : 'LTR'}</Text>;
|
||||
}
|
||||
|
||||
const toggleRTL = () => setRTL(!isRTL);
|
||||
return (
|
||||
<Button
|
||||
accessibilityLabel="Change layout direction"
|
||||
color="gray"
|
||||
onPress={toggleRTL}
|
||||
title={isRTL ? 'RTL' : 'LTR'}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
const PaddingExample = withRTLState(({ isRTL, setRTL }) => {
|
||||
const color = 'teal';
|
||||
|
||||
return (
|
||||
<Block title={'padding{Start,End}'}>
|
||||
<Text style={styles.bold}>Styles</Text>
|
||||
<Text>paddingStart: 50,</Text>
|
||||
<Text>paddingEnd: 10</Text>
|
||||
<Text />
|
||||
<Text style={styles.bold}>Demo: </Text>
|
||||
<Text>The {color} is padding.</Text>
|
||||
<View
|
||||
style={{
|
||||
backgroundColor: color,
|
||||
paddingStart: 50,
|
||||
paddingEnd: 10,
|
||||
borderWidth: 1,
|
||||
borderColor: color,
|
||||
direction: isRTL ? 'rtl' : 'ltr'
|
||||
}}
|
||||
>
|
||||
<View
|
||||
style={{
|
||||
backgroundColor: 'white',
|
||||
paddingTop: 5,
|
||||
paddingBottom: 5,
|
||||
borderLeftWidth: 1,
|
||||
borderRightWidth: 1,
|
||||
borderColor: 'gray'
|
||||
}}
|
||||
>
|
||||
<RTLToggler isRTL={isRTL} setRTL={setRTL} />
|
||||
</View>
|
||||
</View>
|
||||
</Block>
|
||||
);
|
||||
});
|
||||
|
||||
const MarginExample = withRTLState(({ isRTL, setRTL }) => {
|
||||
return (
|
||||
<Block title={'margin{Start,End}'}>
|
||||
<Text style={styles.bold}>Styles</Text>
|
||||
<Text>marginStart: 50,</Text>
|
||||
<Text>marginEnd: 10</Text>
|
||||
<Text />
|
||||
<Text style={styles.bold}>Demo: </Text>
|
||||
<Text>The green is margin.</Text>
|
||||
<View
|
||||
style={{
|
||||
backgroundColor: 'green',
|
||||
borderWidth: 1,
|
||||
borderColor: 'green',
|
||||
direction: isRTL ? 'rtl' : 'ltr'
|
||||
}}
|
||||
>
|
||||
<View
|
||||
style={{
|
||||
backgroundColor: 'white',
|
||||
paddingTop: 5,
|
||||
paddingBottom: 5,
|
||||
marginStart: 50,
|
||||
marginEnd: 10,
|
||||
borderLeftWidth: 1,
|
||||
borderRightWidth: 1,
|
||||
borderColor: 'gray'
|
||||
}}
|
||||
>
|
||||
<RTLToggler isRTL={isRTL} setRTL={setRTL} />
|
||||
</View>
|
||||
</View>
|
||||
</Block>
|
||||
);
|
||||
});
|
||||
|
||||
const PositionExample = withRTLState(({ isRTL, setRTL }) => {
|
||||
return (
|
||||
<Block title={'position: "start" | "end"'}>
|
||||
<Text style={styles.bold}>Styles</Text>
|
||||
<Text>start: 50</Text>
|
||||
<Text />
|
||||
<Text style={styles.bold}>Demo: </Text>
|
||||
<Text>The orange is position.</Text>
|
||||
<View
|
||||
style={{
|
||||
backgroundColor: 'orange',
|
||||
borderWidth: 1,
|
||||
borderColor: 'orange',
|
||||
direction: isRTL ? 'rtl' : 'ltr'
|
||||
}}
|
||||
>
|
||||
<View
|
||||
style={{
|
||||
backgroundColor: 'white',
|
||||
start: 50,
|
||||
borderColor: 'gray'
|
||||
}}
|
||||
>
|
||||
<RTLToggler isRTL={isRTL} setRTL={setRTL} />
|
||||
</View>
|
||||
</View>
|
||||
<Text />
|
||||
<Text style={styles.bold}>Styles</Text>
|
||||
<Text>end: 50</Text>
|
||||
<Text />
|
||||
<Text style={styles.bold}>Demo: </Text>
|
||||
<Text>The orange is position.</Text>
|
||||
<View
|
||||
style={{
|
||||
backgroundColor: 'orange',
|
||||
borderWidth: 1,
|
||||
borderColor: 'orange',
|
||||
direction: isRTL ? 'rtl' : 'ltr'
|
||||
}}
|
||||
>
|
||||
<View
|
||||
style={{
|
||||
backgroundColor: 'white',
|
||||
end: 50,
|
||||
borderColor: 'gray'
|
||||
}}
|
||||
>
|
||||
<RTLToggler isRTL={isRTL} setRTL={setRTL} />
|
||||
</View>
|
||||
</View>
|
||||
</Block>
|
||||
);
|
||||
});
|
||||
|
||||
const BorderWidthExample = withRTLState(({ isRTL, setRTL }) => {
|
||||
return (
|
||||
<Block title={'border{Start,End}Width'}>
|
||||
<Text style={styles.bold}>Styles</Text>
|
||||
<Text>borderStartWidth: 10,</Text>
|
||||
<Text>borderEndWidth: 50</Text>
|
||||
<Text />
|
||||
<Text style={styles.bold}>Demo: </Text>
|
||||
<View style={{ direction: isRTL ? 'rtl' : 'ltr' }}>
|
||||
<View
|
||||
style={{
|
||||
borderStartWidth: 10,
|
||||
borderEndWidth: 50
|
||||
}}
|
||||
>
|
||||
<View>
|
||||
<RTLToggler isRTL={isRTL} setRTL={setRTL} />
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
</Block>
|
||||
);
|
||||
});
|
||||
|
||||
const BorderColorExample = withRTLState(({ isRTL, setRTL }) => {
|
||||
return (
|
||||
<Block title={'border{Start,End}Color'}>
|
||||
<Text style={styles.bold}>Styles</Text>
|
||||
<Text>borderStartColor: 'red',</Text>
|
||||
<Text>borderEndColor: 'green',</Text>
|
||||
<Text />
|
||||
<Text style={styles.bold}>Demo: </Text>
|
||||
<View style={{ direction: isRTL ? 'rtl' : 'ltr' }}>
|
||||
<View
|
||||
style={{
|
||||
borderStartColor: 'red',
|
||||
borderEndColor: 'green',
|
||||
borderLeftWidth: 20,
|
||||
borderRightWidth: 20,
|
||||
padding: 10
|
||||
}}
|
||||
>
|
||||
<View>
|
||||
<RTLToggler isRTL={isRTL} setRTL={setRTL} />
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
</Block>
|
||||
);
|
||||
});
|
||||
|
||||
const BorderRadiiExample = withRTLState(({ isRTL, setRTL }) => {
|
||||
return (
|
||||
<Block title={'border{Top,Bottom}{Start,End}Radius'}>
|
||||
<Text style={styles.bold}>Styles</Text>
|
||||
<Text>borderTopStartRadius: 10,</Text>
|
||||
<Text>borderTopEndRadius: 20,</Text>
|
||||
<Text>borderBottomStartRadius: 30,</Text>
|
||||
<Text>borderBottomEndRadius: 40</Text>
|
||||
<Text />
|
||||
<Text style={styles.bold}>Demo: </Text>
|
||||
<View style={{ direction: isRTL ? 'rtl' : 'ltr' }}>
|
||||
<View
|
||||
style={{
|
||||
borderWidth: 10,
|
||||
borderTopStartRadius: 10,
|
||||
borderTopEndRadius: 20,
|
||||
borderBottomStartRadius: 30,
|
||||
borderBottomEndRadius: 40,
|
||||
padding: 10
|
||||
}}
|
||||
>
|
||||
<View>
|
||||
<RTLToggler isRTL={isRTL} setRTL={setRTL} />
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
</Block>
|
||||
);
|
||||
});
|
||||
|
||||
function Block(props) {
|
||||
let description;
|
||||
if (props.description) {
|
||||
description = <Text style={blockStyles.descriptionText}>{props.description}</Text>;
|
||||
}
|
||||
|
||||
return (
|
||||
<View style={blockStyles.container}>
|
||||
<View style={blockStyles.titleContainer}>
|
||||
<Text style={blockStyles.titleText}>{props.title}</Text>
|
||||
{description}
|
||||
</View>
|
||||
<View style={blockStyles.children}>{props.children}</View>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
||||
const blockStyles = StyleSheet.create({
|
||||
container: {
|
||||
borderRadius: 3,
|
||||
borderWidth: 0.5,
|
||||
borderColor: '#d6d7da',
|
||||
backgroundColor: '#ffffff',
|
||||
margin: 10,
|
||||
marginVertical: 5,
|
||||
overflow: 'hidden'
|
||||
},
|
||||
titleContainer: {
|
||||
borderBottomWidth: 0.5,
|
||||
borderTopLeftRadius: 3,
|
||||
borderTopRightRadius: 2.5,
|
||||
borderBottomColor: '#d6d7da',
|
||||
backgroundColor: '#f6f7f8',
|
||||
paddingHorizontal: 10,
|
||||
paddingVertical: 10
|
||||
},
|
||||
titleText: {
|
||||
fontSize: 16,
|
||||
fontWeight: '500'
|
||||
},
|
||||
descriptionText: {
|
||||
fontSize: 14
|
||||
},
|
||||
disclosure: {
|
||||
position: 'absolute',
|
||||
top: 0,
|
||||
right: 0,
|
||||
padding: 10
|
||||
},
|
||||
disclosureIcon: {
|
||||
width: 12,
|
||||
height: 8
|
||||
},
|
||||
children: {
|
||||
margin: 10
|
||||
}
|
||||
});
|
||||
|
||||
class LayoutRTLExample extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
const { doLeftAndRightSwapInRTL, isRTL } = I18nManager;
|
||||
|
||||
this.state = {
|
||||
toggleStatus: {},
|
||||
isRTL,
|
||||
doLeftAndRightSwapInRTL,
|
||||
containerWidth: 0
|
||||
};
|
||||
|
||||
this._onDirectionChange = this._onDirectionChange.bind(this);
|
||||
this._onSwapChange = this._onSwapChange.bind(this);
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<ScrollView
|
||||
style={[
|
||||
styles.container,
|
||||
// `direction` property is not supported on Android.
|
||||
Platform.OS !== 'android' ? { direction: this.state.isRTL ? 'rtl' : 'ltr' } : null
|
||||
]}
|
||||
>
|
||||
|
||||
<Block title={'Current layout direction'}>
|
||||
<View style={styles.directionBox}>
|
||||
<Text style={styles.directionText}>
|
||||
{this.state.isRTL ? 'Right-to-Left' : 'Left-to-Right'}
|
||||
</Text>
|
||||
</View>
|
||||
</Block>
|
||||
<Block title={'Quickly test RTL layout'}>
|
||||
<View style={[styles.flexDirectionRow, styles.switchRow]}>
|
||||
<Text style={{ fontWeight: 'bold' }}>forceRTL</Text>
|
||||
<View>
|
||||
<Switch onValueChange={this._onDirectionChange} value={this.state.isRTL} />
|
||||
</View>
|
||||
</View>
|
||||
<View style={[styles.flexDirectionRow, styles.switchRow]}>
|
||||
<Text style={{ fontWeight: 'bold' }}>swapLeftAndRightInRTL</Text>
|
||||
<View>
|
||||
<Switch
|
||||
onValueChange={this._onSwapChange}
|
||||
value={this.state.doLeftAndRightSwapInRTL}
|
||||
/>
|
||||
</View>
|
||||
</View>
|
||||
</Block>
|
||||
<TextAlignmentExample
|
||||
description={'Depends on the text content.'}
|
||||
style={styles.fontSizeSmall}
|
||||
title={'Default text alignment'}
|
||||
/>
|
||||
<TextAlignmentExample
|
||||
style={[styles.fontSizeSmall, styles.textAlignLeft]}
|
||||
title={'textAlign: "left"'}
|
||||
/>
|
||||
<TextAlignmentExample
|
||||
style={[styles.fontSizeSmall, styles.textAlignRight]}
|
||||
title={'textAlign: "right"'}
|
||||
/>
|
||||
<TextAlignmentExample
|
||||
style={[styles.fontSizeSmall, styles.textAlignStart]}
|
||||
title={'textAlign: "start"'}
|
||||
/>
|
||||
<TextAlignmentExample
|
||||
style={[styles.fontSizeSmall, styles.textAlignEnd]}
|
||||
title={'textAlign: "end"'}
|
||||
/>
|
||||
<PaddingExample />
|
||||
<MarginExample />
|
||||
<PositionExample />
|
||||
<BorderColorExample />
|
||||
<BorderWidthExample />
|
||||
<BorderRadiiExample />
|
||||
|
||||
<Block title={'A simple list-item layout'}>
|
||||
<View style={styles.list}>
|
||||
<ListItem imageSource={{ uri: 'https://picsum.photos/130/130?image=222' }} />
|
||||
<ListItem imageSource={{ uri: 'https://picsum.photos/130/130?image=250' }} />
|
||||
</View>
|
||||
</Block>
|
||||
|
||||
<Block title={'Working with icons'}>
|
||||
<View style={[styles.flexDirectionRow, { justifyContent: 'space-around' }]}>
|
||||
<View style={{ alignItems: 'center' }}>
|
||||
<Image source={iconSource} style={styles.image} />
|
||||
<Text style={styles.fontSizeSmall}>No RTL flip</Text>
|
||||
</View>
|
||||
<View style={{ alignItems: 'center' }}>
|
||||
<Image
|
||||
source={iconSource}
|
||||
style={[styles.image, { transform: [{ scaleX: this.state.isRTL ? -1 : 1 }] }]}
|
||||
/>
|
||||
<Text style={styles.fontSizeSmall}>RTL flip</Text>
|
||||
</View>
|
||||
</View>
|
||||
</Block>
|
||||
|
||||
</ScrollView>
|
||||
);
|
||||
}
|
||||
|
||||
_onDirectionChange() {
|
||||
I18nManager.forceRTL(!this.state.isRTL);
|
||||
this.setState({ isRTL: !this.state.isRTL });
|
||||
}
|
||||
|
||||
_onSwapChange() {
|
||||
I18nManager.swapLeftAndRightInRTL(!this.state.doLeftAndRightSwapInRTL);
|
||||
this.setState({
|
||||
doLeftAndRightSwapInRTL: !this.state.doLeftAndRightSwapInRTL
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
width: '100%'
|
||||
},
|
||||
directionBox: {
|
||||
flex: 1,
|
||||
backgroundColor: '#f8f8f8',
|
||||
borderWidth: 0.5,
|
||||
borderColor: 'black'
|
||||
},
|
||||
directionText: {
|
||||
padding: 10,
|
||||
fontSize: 16,
|
||||
textAlign: 'center',
|
||||
fontWeight: 'bold'
|
||||
},
|
||||
switchRow: {
|
||||
alignItems: 'center',
|
||||
justifyContent: 'space-between',
|
||||
paddingVertical: 5
|
||||
},
|
||||
list: {
|
||||
height: 120,
|
||||
marginBottom: 5,
|
||||
borderTopWidth: 0.5,
|
||||
borderLeftWidth: 0.5,
|
||||
borderRightWidth: 0.5,
|
||||
borderColor: '#e5e5e5'
|
||||
},
|
||||
row: {
|
||||
height: 60,
|
||||
flexDirection: 'row',
|
||||
borderBottomWidth: 0.5,
|
||||
borderColor: '#e5e5e5'
|
||||
},
|
||||
column1: {
|
||||
width: 60,
|
||||
padding: 6
|
||||
},
|
||||
column2: {
|
||||
flex: 1,
|
||||
padding: 6
|
||||
},
|
||||
column3: {
|
||||
justifyContent: 'center',
|
||||
padding: 6
|
||||
},
|
||||
icon: {
|
||||
width: 48,
|
||||
height: 48,
|
||||
borderWidth: 0.5,
|
||||
borderColor: '#e5e5e5'
|
||||
},
|
||||
image: {
|
||||
width: 48,
|
||||
height: 48
|
||||
},
|
||||
img: {
|
||||
width: IMAGE_SIZE[0] / SCALE,
|
||||
height: IMAGE_SIZE[1] / SCALE
|
||||
},
|
||||
view: {
|
||||
flex: 1
|
||||
},
|
||||
block: {
|
||||
padding: 10,
|
||||
alignItems: 'center'
|
||||
},
|
||||
smallButton: {
|
||||
height: 24,
|
||||
width: 64
|
||||
},
|
||||
fontSizeSmall: {
|
||||
fontSize: 14
|
||||
},
|
||||
fontSizeExtraSmall: {
|
||||
fontSize: 12
|
||||
},
|
||||
textAlignLeft: {
|
||||
textAlign: 'left'
|
||||
},
|
||||
textAlignRight: {
|
||||
textAlign: 'right'
|
||||
},
|
||||
textAlignStart: {
|
||||
textAlign: 'start'
|
||||
},
|
||||
textAlignEnd: {
|
||||
textAlign: 'end'
|
||||
},
|
||||
flexDirectionRow: {
|
||||
flexDirection: 'row'
|
||||
},
|
||||
bold: {
|
||||
fontWeight: 'bold'
|
||||
},
|
||||
rtlToggler: {
|
||||
color: 'gray',
|
||||
padding: 8,
|
||||
textAlign: 'center',
|
||||
fontWeight: '500'
|
||||
}
|
||||
});
|
||||
|
||||
export default function I18nManagerPage() {
|
||||
return (
|
||||
<Example title="I18nManager">
|
||||
<LayoutRTLExample />
|
||||
</Example>
|
||||
);
|
||||
}
|
||||
32
packages/examples/pages/image-background/index.js
Normal file
32
packages/examples/pages/image-background/index.js
Normal file
@@ -0,0 +1,32 @@
|
||||
import React from 'react';
|
||||
import { ImageBackground, StyleSheet, Text } from 'react-native';
|
||||
import Example from '../../shared/example';
|
||||
|
||||
const source = 'https://images.unsplash.com/photo-1481595357459-84468f6eeaac?dpr=1&auto=format&fit=crop&w=376&h=251&q=60&cs=tinysrgb';
|
||||
|
||||
export default function ImageBackgroundPage() {
|
||||
return (
|
||||
<Example title="ImageBackground">
|
||||
<ImageBackground source={source} style={styles.image}>
|
||||
<Text style={styles.text}>Child content</Text>
|
||||
</ImageBackground>
|
||||
</Example>
|
||||
);
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
image: {
|
||||
width: 300,
|
||||
height: 200,
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
marginTop: '1.5rem'
|
||||
},
|
||||
text: {
|
||||
color: 'white',
|
||||
fontWeight: 'bold',
|
||||
fontSize: 18,
|
||||
position: 'relative',
|
||||
top: 50
|
||||
}
|
||||
});
|
||||
129
packages/examples/pages/image/index.js
Normal file
129
packages/examples/pages/image/index.js
Normal file
@@ -0,0 +1,129 @@
|
||||
import { Image, StyleSheet, Text, View } from 'react-native';
|
||||
import React from 'react';
|
||||
import Example from '../../shared/example';
|
||||
|
||||
const placeholder = '/image/placeholder.svg';
|
||||
const source = 'https://images.unsplash.com/photo-1481595357459-84468f6eeaac?dpr=1&auto=format&fit=crop&w=376&h=251&q=60&cs=tinysrgb';
|
||||
const agif = 'http://38.media.tumblr.com/9e9bd08c6e2d10561dd1fb4197df4c4e/tumblr_mfqekpMktw1rn90umo1_500.gif';
|
||||
const pjpeg = 'http://pooyak.com/p/progjpeg/jpegload.cgi?o=1';
|
||||
const resizesource = '/image/smallflower.jpg';
|
||||
const dataBase64Png = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEsAAABLCAQAAACSR7JhAAADtUlEQVR4Ac3YA2Bj6QLH0XPT1Fzbtm29tW3btm3bfLZtv7e2ObZnms7d8Uw098tuetPzrxv8wiISrtVudrG2JXQZ4VOv+qUfmqCGGl1mqLhoA52oZlb0mrjsnhKpgeUNEs91Z0pd1kvihA3ULGVHiQO2narKSHKkEMulm9VgUyE60s1aWoMQUbpZOWE+kaqs4eLEjdIlZTcFZB0ndc1+lhB1lZrIuk5P2aib1NBpZaL+JaOGIt0ls47SKzLC7CqrlGF6RZ09HGoNy1lYl2aRSWL5GuzqWU1KafRdoRp0iOQEiDzgZPnG6DbldcomadViflnl/cL93tOoVbsOLVM2jylvdWjXolWX1hmfZbGR/wjypDjFLSZIRov09BgYmtUqPQPlQrPapecLgTIy0jMgPKtTeob2zWtrGH3xvjUkPCtNg/tm1rjwrMa+mdUkPd3hWbH0jArPGiU9ufCsNNWFZ40wpwn+62/66R2RUtoso1OB34tnLOcy7YB1fUdc9e0q3yru8PGM773vXsuZ5YIZX+5xmHwHGVvlrGPN6ZSiP1smOsMMde40wKv2VmwPPVXNut4sVpUreZiLBHi0qln/VQeI/LTMYXpsJtFiclUN+5HVZazim+Ky+7sAvxWnvjXrJFneVtLWLyPJu9K3cXLWeOlbMTlrIelbMDlrLenrjEQOtIF+fuI9xRp9ZBFp6+b6WT8RrxEpdK64BuvHgDk+vUy+b5hYk6zfyfs051gRoNO1usU12WWRWL73/MMEy9pMi9qIrR4ZpV16Rrvduxazmy1FSvuFXRkqTnE7m2kdb5U8xGjLw/spRr1uTov4uOgQE+0N/DvFrG/Jt7i/FzwxbA9kDanhf2w+t4V97G8lrT7wc08aA2QNUkuTfW/KimT01wdlfK4yEw030VfT0RtZbzjeMprNq8m8tnSTASrTLti64oBNdpmMQm0eEwvfPwRbUBywG5TzjPCsdwk3IeAXjQblLCoXnDVeoAz6SfJNk5TTzytCNZk/POtTSV40NwOFWzw86wNJRpubpXsn60NJFlHeqlYRbslqZm2jnEZ3qcSKgm0kTli3zZVS7y/iivZTweYXJ26Y+RTbV1zh3hYkgyFGSTKPfRVbRqWWVReaxYeSLarYv1Qqsmh1s95S7G+eEWK0f3jYKTbV6bOwepjfhtafsvUsqrQvrGC8YhmnO9cSCk3yuY984F1vesdHYhWJ5FvASlacshUsajFt2mUM9pqzvKGcyNJW0arTKN1GGGzQlH0tXwLDgQTurS8eIQAAAABJRU5ErkJggg==';
|
||||
const dataBase64Svg = 'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0nMjAwJyBoZWlnaHQ9JzIwMCcgZmlsbD0iIzAwMDAwMCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgdmVyc2lvbj0iMS4xIiB4PSIwcHgiIHk9IjBweCIgdmlld0JveD0iMCAwIDEwMCAxMDAiIGVuYWJsZS1iYWNrZ3JvdW5kPSJuZXcgMCAwIDEwMCAxMDAiIHhtbDpzcGFjZT0icHJlc2VydmUiPjxnPjxwYXRoIGQ9Ik0yNS44NjcsNDguODUzQzMyLjgwNiw1MC4xNzYsNDYuNDYsNTIuNSw2MS4yMTUsNTIuNWgwLjAwNWM5LjcxLDAsMTguNDAxLTEuMDU3LDI1LjkzOC0yLjkxMyAgIGMwLjE1OS0wLjA0NiwwLjM1LTAuMTM1LDAuNTY1LTAuMTg3YzAuMjgyLTAuMDcyLDAuNTY1LTAuMTY0LDAuODQ0LTAuMjM4YzMuMTg0LTAuOTY0LDIuNTc3LTMuMDUxLDIuMTk5LTMuODUyICAgYy00LjE2Ni03LjcxOS0xNS4wODYtMjMuNDE1LTM1LjAyOC0yMy40MTVjLTIyLjE2OSwwLTMwLjI2MiwxMC42MzUtMzMuMTQsMTkuNTg5QzIyLjU0NSw0Mi4zMzMsMjIuNDA3LDQ3LjEzNSwyNS44NjcsNDguODUzeiAgICBNMjguNjc2LDM4LjAzMmMwLjAxMy0wLjAzNiwwLjYxNC0xLjYyNiwxLjkyMy0xLjAwOGMxLjEzMywwLjUzNSwwLjk2MSwxLjU2MywwLjg4NywxLjg1Yy0wLjAwNywwLjAyNC0wLjAxNCwwLjA0OC0wLjAyMSwwLjA3MyAgIGMwLDAuMDAxLTAuMDAxLDAuMDA0LTAuMDAxLDAuMDA0bDAsMGMtMC4yNDksMC45MjktMC40MDQsMi4wODYtMC4wMTcsMi44NmMwLjE2LDAuMzE5LDAuNDkyLDAuNzY4LDEuNTQyLDAuOTg3bDAuMzY2LDAuMDc3ICAgYzIwLjgxNiw0LjM2LDM2LDIuOTMzLDQ1LjY3OCwwLjYyNmwtMC4wMDQsMC4wMDJjMCwwLDAuMDA1LTAuMDAyLDAuMDA3LTAuMDAzYzAuMjEyLTAuMDUsMC40MjEtMC4xMDEsMC42MjgtMC4xNTIgICBjMC41MDktMC4wNSwxLjE3MywwLjA3OCwxLjM5OSwxYzAuMzUxLDEuNDI0LTAuOTczLDEuODk1LTEuMjE3LDEuOTY5Yy01LjMyNSwxLjI3OS0xMi4yNjYsMi4zMDYtMjAuODM1LDIuMzA3ICAgYy03LjUwNSwwLTE2LjI1NS0wLjc4Ny0yNi4yNTctMi44ODJsLTAuMzY0LTAuMDc3Yy0yLjEyLTAuNDQyLTMuMTExLTEuNjMzLTMuNTY5LTIuNTU1QzI3Ljk4NSw0MS40MjEsMjguMjgxLDM5LjQxNiwyOC42NzYsMzguMDMyICAgeiI+PC9wYXRoPjxjaXJjbGUgY3g9IjEwLjQ5MyIgY3k9IjIzLjQ1NSIgcj0iMC42MTkiPjwvY2lyY2xlPjxwYXRoIGQ9Ik0yLjA4LDI4LjMwOGMwLjY3Ni0wLjE3OCwwLjk4My0wLjM1MiwxLjE3NC0wLjVDNC42OSwyNi42OSw2LjUsMjcuNDgzLDcuNSwyOC4zNTd2MC4wMDJjMCwwLDEuNzExLDEuMjM1LDAuNzM3LDIuMjAyICAgYy0wLjk3NCwwLjk2NS0yLjMxOSwwLjAwNi0yLjMxOSwwLjAwNmwwLjAzNSwwLjAxNmMtMC4zMjctMC4yMDMtMC42LTAuNTYxLTAuNzgtMC41ODRjLTAuMzcsMC4yNi0wLjg3NiwwLjUtMS40NzYsMC41SDMuNyAgIGMwLDAtMS4zNDUsMC43MDksMC4xNzgsMS42NTJjMC4wMDEsMC4wMDEsMC4wMDIsMC4wNzIsMC4wMDQsMC4wNzNjMy45MzksMi4zNDIsOC4yNzEsNS43MDEsOC4yNzEsOC44OCAgIGMwLDAuNjkxLDAuMiwxNy4wNDIsMTcuNjI2LDI0LjczOWwwLjk2NywwLjQ0MmwtMC4xLDEuMDU5Yy0wLjQyMSw0LjM5LDEuMTQ1LDEwLjE5MSwxMC45OTMsMTIuODg4bDAuMTEzLDAuMDM4ICAgYzAuMDY3LDAuMDIzLDYuNzMyLDIuNDI5LDEwLjkwNywyLjQyOWMxLjU4NCwwLDIuMTU1LTAuMzUyLDIuMjQzLTAuNTYxYzAuMDg1LTAuMjAyLDAuNjEyLTIuMTY0LTYuMzMyLTkuMzg3bDAuMDAyLTAuMTgzICAgYzAsMC0yLjQ3Ny0zLjA3LDEuNTMzLTMuMDdjMC4wMSwwLDAuMDE5LDAsMC4wMjksMGMxLjI4NSwwLDIuNjA4LDAuMjE1LDMuOTgsMC4xODRjNC43NzEtMC4xMTcsOS4zMTYtMC40MjUsMTMuNTA2LTEuMDk2ICAgbDAuNDc0LTAuMDI4bDAuNjY4LDAuMTU4YzkuNjUxLDQuOTQ4LDE2LjczOCw3LjcxNiwxOS43MzgsNy43MTZ2MC4wMDZjMCwwLDAuMTY0LDAuMDExLDAuMjMsMC4wMDQgICBjLTAuMTg5LTAuNzIzLTIuMjMtMi44LTcuMjMtOS4wNzl2MC4wMjFjMCwwLTEuNTEyLTEuNjU4LDAuNzk3LTIuNjUzYzAuMDYzLTAuMDI2LDAuMDA4LDAuMDIzLDAuMDYtMC4wMDEgICBjOC42MzktMy41MDksMTMuNTAxLTguMjA0LDE1LjQxMS0xMS43NzVjMS4xNDUtMi4xMjksMC4yMDYtMi43ODQtMC42NTktMi45NzZjLTAuMzE3LTAuMDM4LTAuNjM0LTAuMDYyLTAuOTEyLTAuMDYyICAgYy0wLjIwNSwwLTAuMzc5LDAuMDEtMC41MjgsMC4wMjdsLTMuMTQzLDEuMjE0QzgzLjczMiw1My45MjYsNzMuMjE4LDU1LjUsNjEuMjIsNTUuNWMtMC4wMDIsMC0wLjAwNSwwLTAuMDA1LDAgICBjLTE1LjEyOCwwLTI5LjEwMS0yLjQzMi0zNi4wODMtMy43NzFsLTAuMTczLTAuMTExbC0wLjE2LTAuMTI2Yy01Ljg1OC0yLjY4MS01LjEzNy0xMC4yMDItNS4xMDMtMTAuNTE5bDAuMDYtMC4zICAgYzAuODk1LTIuODM4LDIuNDY3LTYuMzUyLDUuMjEzLTkuNzE5Yy0xLjgwOC0xLjM2OS00LjU5LTQuMTg4LTQuNDMtOC40OTRjMC4wNDYtMS4yNDQtMC40ODYtMi41MDgtMS40OTgtMy41NTkgICBjLTEuNDk4LTEuNTU1LTMuNzg1LTIuNDQ2LTYuMjc0LTIuNDQ2Yy0xLjc3LDAtMy41NTMsMC40NDItNS4yOTMsMS4zMTRjLTQuMDYxLDIuMDM1LTQuODU1LDQuNzM2LTUuNjkyLDcuNTk2ICAgYy0wLjEzNiwwLjQ2OC0wLjI4NCwwLjkzOS0wLjQzOCwxLjQxYy0wLjAwNiwwLjAxOS0wLjAyMiwwLjAzNS0wLjAyOCwwLjA1NkMwLjgzMywyOC40MjMsMS42OTEsMjguMzksMi4wOCwyOC4zMDh6IE0xMC40OTMsMTkuOTA4ICAgYzEuOTU2LDAsMy41NDgsMS41OTEsMy41NDgsMy41NDdjMCwxLjk1Ny0xLjU5MiwzLjU0OC0zLjU0OCwzLjU0OGMtMS45NTcsMC0zLjU0OC0xLjU5Mi0zLjU0OC0zLjU0OCAgIEM2Ljk0NCwyMS40OTksOC41MzYsMTkuOTA4LDEwLjQ5MywxOS45MDh6Ij48L3BhdGg+PC9nPjwvc3ZnPg==';
|
||||
const dataSvg = 'data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 841.9 595.3"><g fill="#61DAFB"><path d="M666.3 296.5c0-32.5-40.7-63.3-103.1-82.4 14.4-63.6 8-114.2-20.2-130.4-6.5-3.8-14.1-5.6-22.4-5.6v22.3c4.6 0 8.3.9 11.4 2.6 13.6 7.8 19.5 37.5 14.9 75.7-1.1 9.4-2.9 19.3-5.1 29.4-19.6-4.8-41-8.5-63.5-10.9-13.5-18.5-27.5-35.3-41.6-50 32.6-30.3 63.2-46.9 84-46.9V78c-27.5 0-63.5 19.6-99.9 53.6-36.4-33.8-72.4-53.2-99.9-53.2v22.3c20.7 0 51.4 16.5 84 46.6-14 14.7-28 31.4-41.3 49.9-22.6 2.4-44 6.1-63.6 11-2.3-10-4-19.7-5.2-29-4.7-38.2 1.1-67.9 14.6-75.8 3-1.8 6.9-2.6 11.5-2.6V78.5c-8.4 0-16 1.8-22.6 5.6-28.1 16.2-34.4 66.7-19.9 130.1-62.2 19.2-102.7 49.9-102.7 82.3 0 32.5 40.7 63.3 103.1 82.4-14.4 63.6-8 114.2 20.2 130.4 6.5 3.8 14.1 5.6 22.5 5.6 27.5 0 63.5-19.6 99.9-53.6 36.4 33.8 72.4 53.2 99.9 53.2 8.4 0 16-1.8 22.6-5.6 28.1-16.2 34.4-66.7 19.9-130.1 62-19.1 102.5-49.9 102.5-82.3zm-130.2-66.7c-3.7 12.9-8.3 26.2-13.5 39.5-4.1-8-8.4-16-13.1-24-4.6-8-9.5-15.8-14.4-23.4 14.2 2.1 27.9 4.7 41 7.9zm-45.8 106.5c-7.8 13.5-15.8 26.3-24.1 38.2-14.9 1.3-30 2-45.2 2-15.1 0-30.2-.7-45-1.9-8.3-11.9-16.4-24.6-24.2-38-7.6-13.1-14.5-26.4-20.8-39.8 6.2-13.4 13.2-26.8 20.7-39.9 7.8-13.5 15.8-26.3 24.1-38.2 14.9-1.3 30-2 45.2-2 15.1 0 30.2.7 45 1.9 8.3 11.9 16.4 24.6 24.2 38 7.6 13.1 14.5 26.4 20.8 39.8-6.3 13.4-13.2 26.8-20.7 39.9zm32.3-13c5.4 13.4 10 26.8 13.8 39.8-13.1 3.2-26.9 5.9-41.2 8 4.9-7.7 9.8-15.6 14.4-23.7 4.6-8 8.9-16.1 13-24.1zM421.2 430c-9.3-9.6-18.6-20.3-27.8-32 9 .4 18.2.7 27.5.7 9.4 0 18.7-.2 27.8-.7-9 11.7-18.3 22.4-27.5 32zm-74.4-58.9c-14.2-2.1-27.9-4.7-41-7.9 3.7-12.9 8.3-26.2 13.5-39.5 4.1 8 8.4 16 13.1 24 4.7 8 9.5 15.8 14.4 23.4zM420.7 163c9.3 9.6 18.6 20.3 27.8 32-9-.4-18.2-.7-27.5-.7-9.4 0-18.7.2-27.8.7 9-11.7 18.3-22.4 27.5-32zm-74 58.9c-4.9 7.7-9.8 15.6-14.4 23.7-4.6 8-8.9 16-13 24-5.4-13.4-10-26.8-13.8-39.8 13.1-3.1 26.9-5.8 41.2-7.9zm-90.5 125.2c-35.4-15.1-58.3-34.9-58.3-50.6 0-15.7 22.9-35.6 58.3-50.6 8.6-3.7 18-7 27.7-10.1 5.7 19.6 13.2 40 22.5 60.9-9.2 20.8-16.6 41.1-22.2 60.6-9.9-3.1-19.3-6.5-28-10.2zM310 490c-13.6-7.8-19.5-37.5-14.9-75.7 1.1-9.4 2.9-19.3 5.1-29.4 19.6 4.8 41 8.5 63.5 10.9 13.5 18.5 27.5 35.3 41.6 50-32.6 30.3-63.2 46.9-84 46.9-4.5-.1-8.3-1-11.3-2.7zm237.2-76.2c4.7 38.2-1.1 67.9-14.6 75.8-3 1.8-6.9 2.6-11.5 2.6-20.7 0-51.4-16.5-84-46.6 14-14.7 28-31.4 41.3-49.9 22.6-2.4 44-6.1 63.6-11 2.3 10.1 4.1 19.8 5.2 29.1zm38.5-66.7c-8.6 3.7-18 7-27.7 10.1-5.7-19.6-13.2-40-22.5-60.9 9.2-20.8 16.6-41.1 22.2-60.6 9.9 3.1 19.3 6.5 28.1 10.2 35.4 15.1 58.3 34.9 58.3 50.6-.1 15.7-23 35.6-58.4 50.6zM320.8 78.4z"/><circle cx="420.9" cy="296.5" r="45.7"/><path d="M520.5 78.1z"/></g></svg>';
|
||||
|
||||
function Divider() {
|
||||
return <View style={styles.divider} />
|
||||
}
|
||||
|
||||
export default function ImagePage() {
|
||||
return (
|
||||
<Example title="Image">
|
||||
<Divider />
|
||||
<Image defaultSource={placeholder} style={styles.base} />
|
||||
<Divider />
|
||||
<Image
|
||||
defaultSource={placeholder}
|
||||
onError={() => { console.log('error') }}
|
||||
onLoad={() => { console.log('load') }}
|
||||
onLoadEnd={() => { console.log('load-end') }}
|
||||
onLoadStart={() => { console.log('load-start') }}
|
||||
source={source}
|
||||
style={styles.base}
|
||||
/>
|
||||
<Divider />
|
||||
<View style={styles.row}>
|
||||
<View style={styles.column}>
|
||||
<Text style={styles.text}>Static image</Text>
|
||||
<Image source={'/image/ladybug.jpg'} style={styles.image} />
|
||||
</View>
|
||||
<View style={styles.column}>
|
||||
<Text style={styles.text}>Progressive JPEG</Text>
|
||||
<Image source={pjpeg} style={styles.image} />
|
||||
</View>
|
||||
</View>
|
||||
<Divider />
|
||||
<View style={styles.row}>
|
||||
<View style={styles.column}>
|
||||
<Text style={styles.text}>Animated GIF</Text>
|
||||
<Image source={agif} style={styles.image} />
|
||||
</View>
|
||||
<View style={styles.column}>
|
||||
<Text style={styles.text}>PNG (base64)</Text>
|
||||
<Image source={dataBase64Png} style={styles.image} />
|
||||
</View>
|
||||
</View>
|
||||
<Divider />
|
||||
<View style={styles.row}>
|
||||
<View style={styles.column}>
|
||||
<Text style={styles.text}>SVG (base64)</Text>
|
||||
<Image source={dataBase64Svg} style={styles.image} />
|
||||
</View>
|
||||
<View style={styles.column}>
|
||||
<Text style={styles.text}>SVG (inline data)</Text>
|
||||
<Image source={dataSvg} style={styles.image} />
|
||||
</View>
|
||||
</View>
|
||||
<Divider />
|
||||
<View style={styles.row}>
|
||||
<View style={styles.column}>
|
||||
<Text style={[styles.text]}>Center</Text>
|
||||
<Image resizeMode="center" source={resizesource} style={styles.resizeMode} />
|
||||
</View>
|
||||
<View style={styles.column}>
|
||||
<Text style={[styles.text]}>Contain</Text>
|
||||
<Image resizeMode="contain" source={resizesource} style={styles.resizeMode} />
|
||||
</View>
|
||||
</View>
|
||||
<Divider />
|
||||
<View style={styles.row}>
|
||||
<View style={styles.column}>
|
||||
<Text style={[styles.text]}>Cover</Text>
|
||||
<Image resizeMode="cover" source={resizesource} style={styles.resizeMode} />
|
||||
</View>
|
||||
<View style={styles.column}>
|
||||
<Text style={[styles.text]}>Stretch</Text>
|
||||
<Image resizeMode="stretch" source={resizesource} style={styles.resizeMode} />
|
||||
</View>
|
||||
</View>
|
||||
</Example>
|
||||
);
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
base: {
|
||||
height: 200,
|
||||
width: 300
|
||||
},
|
||||
divider: {
|
||||
height: '1rem'
|
||||
},
|
||||
row: {
|
||||
flexDirection: 'row',
|
||||
flexWrap: 'wrap',
|
||||
justifyContent: 'space-between'
|
||||
},
|
||||
column: {
|
||||
marginBottom: '1rem',
|
||||
marginHorizontal: '1rem'
|
||||
},
|
||||
text: {
|
||||
marginBottom: '0.5rem',
|
||||
textAlign: 'center'
|
||||
},
|
||||
image: {
|
||||
borderColor: 'black',
|
||||
borderWidth: 0.5,
|
||||
height: 120,
|
||||
width: 120,
|
||||
resizeMode: 'cover'
|
||||
},
|
||||
resizeMode: {
|
||||
borderColor: 'black',
|
||||
borderWidth: 0.5,
|
||||
height: 120,
|
||||
width: 120
|
||||
},
|
||||
leftMargin: {
|
||||
marginLeft: 10
|
||||
}
|
||||
});
|
||||
82
packages/examples/pages/index.js
Normal file
82
packages/examples/pages/index.js
Normal file
@@ -0,0 +1,82 @@
|
||||
import NextLink from 'next/link';
|
||||
import React from 'react';
|
||||
import { Image, StyleSheet, Text, View } from 'react-native';
|
||||
|
||||
const logoUri =
|
||||
'data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 841.9 595.3"><g fill="#1977f2"><path d="M666.3 296.5c0-32.5-40.7-63.3-103.1-82.4 14.4-63.6 8-114.2-20.2-130.4-6.5-3.8-14.1-5.6-22.4-5.6v22.3c4.6 0 8.3.9 11.4 2.6 13.6 7.8 19.5 37.5 14.9 75.7-1.1 9.4-2.9 19.3-5.1 29.4-19.6-4.8-41-8.5-63.5-10.9-13.5-18.5-27.5-35.3-41.6-50 32.6-30.3 63.2-46.9 84-46.9V78c-27.5 0-63.5 19.6-99.9 53.6-36.4-33.8-72.4-53.2-99.9-53.2v22.3c20.7 0 51.4 16.5 84 46.6-14 14.7-28 31.4-41.3 49.9-22.6 2.4-44 6.1-63.6 11-2.3-10-4-19.7-5.2-29-4.7-38.2 1.1-67.9 14.6-75.8 3-1.8 6.9-2.6 11.5-2.6V78.5c-8.4 0-16 1.8-22.6 5.6-28.1 16.2-34.4 66.7-19.9 130.1-62.2 19.2-102.7 49.9-102.7 82.3 0 32.5 40.7 63.3 103.1 82.4-14.4 63.6-8 114.2 20.2 130.4 6.5 3.8 14.1 5.6 22.5 5.6 27.5 0 63.5-19.6 99.9-53.6 36.4 33.8 72.4 53.2 99.9 53.2 8.4 0 16-1.8 22.6-5.6 28.1-16.2 34.4-66.7 19.9-130.1 62-19.1 102.5-49.9 102.5-82.3zm-130.2-66.7c-3.7 12.9-8.3 26.2-13.5 39.5-4.1-8-8.4-16-13.1-24-4.6-8-9.5-15.8-14.4-23.4 14.2 2.1 27.9 4.7 41 7.9zm-45.8 106.5c-7.8 13.5-15.8 26.3-24.1 38.2-14.9 1.3-30 2-45.2 2-15.1 0-30.2-.7-45-1.9-8.3-11.9-16.4-24.6-24.2-38-7.6-13.1-14.5-26.4-20.8-39.8 6.2-13.4 13.2-26.8 20.7-39.9 7.8-13.5 15.8-26.3 24.1-38.2 14.9-1.3 30-2 45.2-2 15.1 0 30.2.7 45 1.9 8.3 11.9 16.4 24.6 24.2 38 7.6 13.1 14.5 26.4 20.8 39.8-6.3 13.4-13.2 26.8-20.7 39.9zm32.3-13c5.4 13.4 10 26.8 13.8 39.8-13.1 3.2-26.9 5.9-41.2 8 4.9-7.7 9.8-15.6 14.4-23.7 4.6-8 8.9-16.1 13-24.1zM421.2 430c-9.3-9.6-18.6-20.3-27.8-32 9 .4 18.2.7 27.5.7 9.4 0 18.7-.2 27.8-.7-9 11.7-18.3 22.4-27.5 32zm-74.4-58.9c-14.2-2.1-27.9-4.7-41-7.9 3.7-12.9 8.3-26.2 13.5-39.5 4.1 8 8.4 16 13.1 24 4.7 8 9.5 15.8 14.4 23.4zM420.7 163c9.3 9.6 18.6 20.3 27.8 32-9-.4-18.2-.7-27.5-.7-9.4 0-18.7.2-27.8.7 9-11.7 18.3-22.4 27.5-32zm-74 58.9c-4.9 7.7-9.8 15.6-14.4 23.7-4.6 8-8.9 16-13 24-5.4-13.4-10-26.8-13.8-39.8 13.1-3.1 26.9-5.8 41.2-7.9zm-90.5 125.2c-35.4-15.1-58.3-34.9-58.3-50.6 0-15.7 22.9-35.6 58.3-50.6 8.6-3.7 18-7 27.7-10.1 5.7 19.6 13.2 40 22.5 60.9-9.2 20.8-16.6 41.1-22.2 60.6-9.9-3.1-19.3-6.5-28-10.2zM310 490c-13.6-7.8-19.5-37.5-14.9-75.7 1.1-9.4 2.9-19.3 5.1-29.4 19.6 4.8 41 8.5 63.5 10.9 13.5 18.5 27.5 35.3 41.6 50-32.6 30.3-63.2 46.9-84 46.9-4.5-.1-8.3-1-11.3-2.7zm237.2-76.2c4.7 38.2-1.1 67.9-14.6 75.8-3 1.8-6.9 2.6-11.5 2.6-20.7 0-51.4-16.5-84-46.6 14-14.7 28-31.4 41.3-49.9 22.6-2.4 44-6.1 63.6-11 2.3 10.1 4.1 19.8 5.2 29.1zm38.5-66.7c-8.6 3.7-18 7-27.7 10.1-5.7-19.6-13.2-40-22.5-60.9 9.2-20.8 16.6-41.1 22.2-60.6 9.9 3.1 19.3 6.5 28.1 10.2 35.4 15.1 58.3 34.9 58.3 50.6-.1 15.7-23 35.6-58.4 50.6zM320.8 78.4z" /><circle cx="420.9" cy="296.5" r="45.7" /><path d="M520.5 78.1z" /></g></svg>';
|
||||
|
||||
function Link(props) {
|
||||
return (
|
||||
<NextLink href={props.href}>
|
||||
<Text
|
||||
{...props}
|
||||
accessibilityRole="link"
|
||||
style={StyleSheet.compose(styles.link, props.style)}
|
||||
/>
|
||||
</NextLink>
|
||||
);
|
||||
}
|
||||
|
||||
export default function IndexPage() {
|
||||
return (
|
||||
<View style={styles.app}>
|
||||
<View style={styles.header}>
|
||||
<Image
|
||||
accessibilityLabel="React logo"
|
||||
resizeMode="contain"
|
||||
source={{ uri: logoUri }}
|
||||
style={styles.logo}
|
||||
/>
|
||||
<Text style={styles.title}>React Native for Web</Text>
|
||||
</View>
|
||||
<Text style={styles.text}>
|
||||
<Link href="https://github.com/necolas/react-native-web">React Native for Web</Link> example app built with Next.js
|
||||
</Text>
|
||||
|
||||
<View accessibilityRole="list">
|
||||
{process.env.pages.map((name) => (
|
||||
<View accessibilityRole="listitem" key={name} style={styles.listitem}>
|
||||
<Link href={'/' + name} style={styles.pageLink}>{name}</Link>
|
||||
</View>
|
||||
))}
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
app: {
|
||||
marginHorizontal: 'auto',
|
||||
maxWidth: 500,
|
||||
padding: 20
|
||||
},
|
||||
logo: {
|
||||
height: 80
|
||||
},
|
||||
header: {
|
||||
padding: 20
|
||||
},
|
||||
title: {
|
||||
fontWeight: 'bold',
|
||||
fontSize: '1.5rem',
|
||||
marginTop: '1em',
|
||||
textAlign: 'center'
|
||||
},
|
||||
text: {
|
||||
lineHeight: '1.5em',
|
||||
fontSize: '1.125rem',
|
||||
marginVertical: '1em',
|
||||
textAlign: 'center'
|
||||
},
|
||||
link: {
|
||||
color: '#1977f2'
|
||||
},
|
||||
listitem: {
|
||||
marginVertical: '0.5rem',
|
||||
textAlign: 'center'
|
||||
},
|
||||
pageLink: {
|
||||
fontSize: '1.25rem',
|
||||
fontWeight: 'bold'
|
||||
}
|
||||
});
|
||||
41
packages/examples/pages/linking/index.js
Normal file
41
packages/examples/pages/linking/index.js
Normal file
@@ -0,0 +1,41 @@
|
||||
import { Linking, StyleSheet, Text } from 'react-native';
|
||||
import React, { PureComponent } from 'react';
|
||||
import Example from '../../shared/example';
|
||||
|
||||
const url = 'https://mathiasbynens.github.io/rel-noopener/malicious.html';
|
||||
|
||||
export default class LinkingPage extends PureComponent {
|
||||
handlePress() {
|
||||
Linking.canOpenURL(url).then(supported => {
|
||||
return Linking.openURL(url);
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<Example title="Linking">
|
||||
<Text onPress={this.handlePress} style={styles.text}>
|
||||
Linking.openURL
|
||||
</Text>
|
||||
<Text
|
||||
accessibilityRole="link"
|
||||
href="https://mathiasbynens.github.io/rel-noopener/malicious.html"
|
||||
style={styles.text}
|
||||
target="_blank"
|
||||
>
|
||||
target="_blank"
|
||||
</Text>
|
||||
</Example>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
text: {
|
||||
borderRadius: 5,
|
||||
borderStyle: 'solid',
|
||||
borderWidth: 1,
|
||||
marginVertical: 10,
|
||||
padding: 10
|
||||
}
|
||||
});
|
||||
462
packages/examples/pages/lists/index.js
Normal file
462
packages/examples/pages/lists/index.js
Normal file
@@ -0,0 +1,462 @@
|
||||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @noflow
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
import * as React from 'react';
|
||||
import { Animated, FlatList, Image, StyleSheet, Switch, TouchableHighlight, Text, TextInput, View } from 'react-native';
|
||||
import Example from '../../shared/example';
|
||||
|
||||
type Item = { title: string, text: string, key: string, pressed: boolean, noImage?: ?boolean };
|
||||
|
||||
const AnimatedFlatList = Animated.createAnimatedComponent(FlatList);
|
||||
|
||||
const HEADER = { height: 30, width: 100 };
|
||||
const SEPARATOR_HEIGHT = StyleSheet.hairlineWidth;
|
||||
const HORIZ_WIDTH = 200;
|
||||
const ITEM_HEIGHT = 72;
|
||||
const VIEWABILITY_CONFIG = {
|
||||
minimumViewTime: 3000,
|
||||
viewAreaCoveragePercentThreshold: 100,
|
||||
waitForInteraction: true
|
||||
};
|
||||
const THUMB_URLS = [
|
||||
'./lists/like.png',
|
||||
'./lists/dislike.png',
|
||||
'./lists/call.png',
|
||||
'./lists/fist.png',
|
||||
'./lists/bandaged.png',
|
||||
'./lists/flowers.png',
|
||||
'./lists/heart.png',
|
||||
'./lists/liking.png',
|
||||
'./lists/party.png',
|
||||
'./lists/poke.png',
|
||||
'./lists/superlike.png',
|
||||
'./lists/victory.png'
|
||||
];
|
||||
const LOREM_IPSUM =
|
||||
'Lorem ipsum dolor sit amet, ius ad pertinax oportere accommodare, an vix ' +
|
||||
'civibus corrumpit referrentur. Te nam case ludus inciderint, te mea facilisi adipiscing. Sea id ' +
|
||||
'integre luptatum. In tota sale consequuntur nec. Erat ocurreret mei ei. Eu paulo sapientem ' +
|
||||
'vulputate est, vel an accusam intellegam interesset. Nam eu stet pericula reprimique, ea vim illud ' +
|
||||
'modus, putant invidunt reprehendunt ne qui.';
|
||||
|
||||
function genItemData(count: number, start: number = 0): Array<Item> {
|
||||
const dataBlob = [];
|
||||
for (let ii = start; ii < count + start; ii++) {
|
||||
const itemHash = Math.abs(hashCode('Item ' + ii));
|
||||
dataBlob.push({
|
||||
title: 'Item ' + ii,
|
||||
text: LOREM_IPSUM.substr(0, (itemHash % 301) + 20),
|
||||
key: String(ii),
|
||||
pressed: false
|
||||
});
|
||||
}
|
||||
return dataBlob;
|
||||
}
|
||||
|
||||
class ItemComponent extends React.PureComponent<{
|
||||
fixedHeight?: ?boolean,
|
||||
horizontal?: ?boolean,
|
||||
item: Item,
|
||||
onPress: (key: string) => void,
|
||||
onShowUnderlay?: () => void,
|
||||
onHideUnderlay?: () => void
|
||||
}> {
|
||||
_onPress = () => {
|
||||
this.props.onPress(this.props.item.key);
|
||||
};
|
||||
render() {
|
||||
const { fixedHeight, horizontal, item } = this.props;
|
||||
const itemHash = Math.abs(hashCode(item.title));
|
||||
const imgSource = THUMB_URLS[itemHash % THUMB_URLS.length];
|
||||
return (
|
||||
<TouchableHighlight
|
||||
onHideUnderlay={this.props.onHideUnderlay}
|
||||
onPress={this._onPress}
|
||||
onShowUnderlay={this.props.onShowUnderlay}
|
||||
style={horizontal ? styles.horizItem : styles.item}
|
||||
tvParallaxProperties={{
|
||||
pressMagnification: 1.1
|
||||
}}
|
||||
>
|
||||
<View
|
||||
style={[
|
||||
styles.row,
|
||||
horizontal && { width: HORIZ_WIDTH },
|
||||
fixedHeight && { height: ITEM_HEIGHT }
|
||||
]}
|
||||
>
|
||||
{!item.noImage && <Image source={imgSource} style={styles.thumb} />}
|
||||
<Text numberOfLines={horizontal || fixedHeight ? 3 : undefined} style={styles.text}>
|
||||
{item.title} - {item.text}
|
||||
</Text>
|
||||
</View>
|
||||
</TouchableHighlight>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class FooterComponent extends React.PureComponent<{}> {
|
||||
render() {
|
||||
return (
|
||||
<View style={styles.headerFooterContainer}>
|
||||
<SeparatorComponent />
|
||||
<View style={styles.headerFooter}>
|
||||
<Text>LIST FOOTER</Text>
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class HeaderComponent extends React.PureComponent<{}> {
|
||||
render() {
|
||||
return (
|
||||
<View style={styles.headerFooterContainer}>
|
||||
<View style={styles.headerFooter}>
|
||||
<Text>LIST HEADER</Text>
|
||||
</View>
|
||||
<SeparatorComponent />
|
||||
</View>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class SeparatorComponent extends React.PureComponent<{}> {
|
||||
render() {
|
||||
return <View style={styles.separator} />;
|
||||
}
|
||||
}
|
||||
|
||||
class ItemSeparatorComponent extends React.PureComponent<{}> {
|
||||
render() {
|
||||
const style = this.props.highlighted
|
||||
? [styles.itemSeparator, { marginLeft: 0, backgroundColor: 'rgb(217, 217, 217)' }]
|
||||
: styles.itemSeparator;
|
||||
return <View style={style} />;
|
||||
}
|
||||
}
|
||||
|
||||
class Spindicator extends React.PureComponent<{}> {
|
||||
render() {
|
||||
return (
|
||||
<Animated.View
|
||||
style={[
|
||||
styles.spindicator,
|
||||
{
|
||||
transform: [
|
||||
{
|
||||
rotate: this.props.value.interpolate({
|
||||
inputRange: [0, 5000],
|
||||
outputRange: ['0deg', '360deg'],
|
||||
extrapolate: 'extend'
|
||||
})
|
||||
}
|
||||
]
|
||||
}
|
||||
]}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function hashCode(str: string): number {
|
||||
let hash = 15;
|
||||
for (let ii = str.length - 1; ii >= 0; ii--) {
|
||||
hash = (hash << 5) - hash + str.charCodeAt(ii);
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
|
||||
function getItemLayout(data: any, index: number, horizontal?: boolean) {
|
||||
const [length, separator, header] = horizontal
|
||||
? [HORIZ_WIDTH, 0, HEADER.width]
|
||||
: [ITEM_HEIGHT, SEPARATOR_HEIGHT, HEADER.height];
|
||||
return { length, offset: (length + separator) * index + header, index };
|
||||
}
|
||||
|
||||
function pressItem(context: Object, key: string) {
|
||||
const index = Number(key);
|
||||
const pressed = !context.state.data[index].pressed;
|
||||
context.setState(state => {
|
||||
const newData = [...state.data];
|
||||
newData[index] = {
|
||||
...state.data[index],
|
||||
pressed,
|
||||
title: 'Item ' + key + (pressed ? ' (pressed)' : '')
|
||||
};
|
||||
return { data: newData };
|
||||
});
|
||||
}
|
||||
|
||||
function renderSmallSwitchOption(context: Object, key: string) {
|
||||
return (
|
||||
<View style={styles.option}>
|
||||
<Text>{key}:</Text>
|
||||
<Switch
|
||||
onValueChange={value => context.setState({ [key]: value })}
|
||||
style={styles.smallSwitch}
|
||||
value={context.state[key]}
|
||||
/>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
||||
function PlainInput(props: Object) {
|
||||
return (
|
||||
<TextInput
|
||||
autoCapitalize="none"
|
||||
autoCorrect={false}
|
||||
clearButtonMode="always"
|
||||
style={styles.searchTextInput}
|
||||
underlineColorAndroid="transparent"
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
class SingleColumnExample extends React.PureComponent {
|
||||
static title = '<FlatList>';
|
||||
static description = 'Performant, scrollable list of data.';
|
||||
|
||||
state = {
|
||||
data: genItemData(100),
|
||||
debug: false,
|
||||
horizontal: false,
|
||||
inverted: false,
|
||||
filterText: '',
|
||||
fixedHeight: true,
|
||||
logViewable: false,
|
||||
virtualized: true
|
||||
};
|
||||
|
||||
_onChangeFilterText = filterText => {
|
||||
this.setState({ filterText });
|
||||
};
|
||||
|
||||
_onChangeScrollToIndex = text => {
|
||||
this._listRef.getNode().scrollToIndex({ viewPosition: 0.5, index: Number(text) });
|
||||
};
|
||||
|
||||
_scrollPos = new Animated.Value(0);
|
||||
_scrollSinkX = Animated.event([{ nativeEvent: { contentOffset: { x: this._scrollPos } } }], {
|
||||
useNativeDriver: true
|
||||
});
|
||||
_scrollSinkY = Animated.event([{ nativeEvent: { contentOffset: { y: this._scrollPos } } }], {
|
||||
useNativeDriver: true
|
||||
});
|
||||
|
||||
componentDidUpdate() {
|
||||
this._listRef.getNode().recordInteraction(); // e.g. flipping logViewable switch
|
||||
}
|
||||
|
||||
render() {
|
||||
const filterRegex = new RegExp(String(this.state.filterText), 'i');
|
||||
const filter = item => filterRegex.test(item.text) || filterRegex.test(item.title);
|
||||
const filteredData = this.state.data.filter(filter);
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
<View style={styles.searchRow}>
|
||||
<View style={styles.options}>
|
||||
<PlainInput
|
||||
onChangeText={this._onChangeFilterText}
|
||||
placeholder="Search..."
|
||||
value={this.state.filterText}
|
||||
/>
|
||||
<PlainInput onChangeText={this._onChangeScrollToIndex} placeholder="scrollToIndex..." />
|
||||
</View>
|
||||
<View style={styles.options}>
|
||||
{renderSmallSwitchOption(this, 'virtualized')}
|
||||
{renderSmallSwitchOption(this, 'horizontal')}
|
||||
{renderSmallSwitchOption(this, 'fixedHeight')}
|
||||
{renderSmallSwitchOption(this, 'logViewable')}
|
||||
{renderSmallSwitchOption(this, 'inverted')}
|
||||
{renderSmallSwitchOption(this, 'debug')}
|
||||
<Spindicator value={this._scrollPos} />
|
||||
</View>
|
||||
</View>
|
||||
<SeparatorComponent />
|
||||
<AnimatedFlatList
|
||||
ItemSeparatorComponent={ItemSeparatorComponent}
|
||||
ListFooterComponent={FooterComponent}
|
||||
ListHeaderComponent={<HeaderComponent />}
|
||||
contentContainerStyle={styles.list}
|
||||
data={filteredData}
|
||||
debug={this.state.debug}
|
||||
disableVirtualization={!this.state.virtualized}
|
||||
getItemLayout={this.state.fixedHeight ? this._getItemLayout : undefined}
|
||||
horizontal={this.state.horizontal}
|
||||
inverted={this.state.inverted}
|
||||
key={(this.state.horizontal ? 'h' : 'v') + (this.state.fixedHeight ? 'f' : 'd')}
|
||||
keyboardDismissMode="on-drag"
|
||||
keyboardShouldPersistTaps="always"
|
||||
legacyImplementation={false}
|
||||
numColumns={1}
|
||||
onEndReached={this._onEndReached}
|
||||
onRefresh={this._onRefresh}
|
||||
onScroll={this.state.horizontal ? this._scrollSinkX : this._scrollSinkY}
|
||||
onViewableItemsChanged={this._onViewableItemsChanged}
|
||||
ref={this._captureRef}
|
||||
refreshing={false}
|
||||
renderItem={this._renderItemComponent}
|
||||
viewabilityConfig={VIEWABILITY_CONFIG}
|
||||
/>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
_captureRef = ref => {
|
||||
this._listRef = ref;
|
||||
};
|
||||
_getItemLayout = (data: any, index: number) => {
|
||||
return getItemLayout(data, index, this.state.horizontal);
|
||||
};
|
||||
_onEndReached = () => {
|
||||
if (this.state.data.length >= 1000) {
|
||||
return;
|
||||
}
|
||||
this.setState(state => ({
|
||||
data: state.data.concat(genItemData(100, state.data.length))
|
||||
}));
|
||||
};
|
||||
_onRefresh = () => console.log('onRefresh: nothing to refresh :P');
|
||||
_renderItemComponent = ({ item, separators }) => {
|
||||
return (
|
||||
<ItemComponent
|
||||
fixedHeight={this.state.fixedHeight}
|
||||
horizontal={this.state.horizontal}
|
||||
item={item}
|
||||
onHideUnderlay={separators.unhighlight}
|
||||
onPress={this._pressItem}
|
||||
onShowUnderlay={separators.highlight}
|
||||
/>
|
||||
);
|
||||
};
|
||||
// This is called when items change viewability by scrolling into or out of
|
||||
// the viewable area.
|
||||
_onViewableItemsChanged = (info: {
|
||||
changed: Array<{
|
||||
key: string,
|
||||
isViewable: boolean,
|
||||
item: any,
|
||||
index: ?number,
|
||||
section?: any
|
||||
}>
|
||||
}) => {
|
||||
// Impressions can be logged here
|
||||
if (this.state.logViewable) {
|
||||
console.log('onViewableItemsChanged: ', info.changed.map(v => ({ ...v, item: '...' })));
|
||||
}
|
||||
};
|
||||
_pressItem = (key: string) => {
|
||||
this._listRef.getNode().recordInteraction();
|
||||
pressItem(this, key);
|
||||
};
|
||||
_listRef: AnimatedFlatList;
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
backgroundColor: 'rgb(239, 239, 244)',
|
||||
flex: 1
|
||||
},
|
||||
list: {
|
||||
backgroundColor: 'white'
|
||||
},
|
||||
options: {
|
||||
flexDirection: 'row',
|
||||
flexWrap: 'wrap',
|
||||
alignItems: 'center'
|
||||
},
|
||||
searchRow: {
|
||||
padding: 10
|
||||
},
|
||||
headerFooter: {
|
||||
...HEADER,
|
||||
alignSelf: 'center',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center'
|
||||
},
|
||||
headerFooterContainer: {
|
||||
backgroundColor: 'rgb(239, 239, 244)'
|
||||
},
|
||||
horizItem: {
|
||||
alignSelf: 'flex-start' // Necessary for touch highlight
|
||||
},
|
||||
item: {
|
||||
flex: 1
|
||||
},
|
||||
itemSeparator: {
|
||||
height: SEPARATOR_HEIGHT,
|
||||
backgroundColor: 'rgb(200, 199, 204)',
|
||||
marginLeft: 60
|
||||
},
|
||||
option: {
|
||||
flexDirection: 'row',
|
||||
padding: 8,
|
||||
paddingLeft: 0,
|
||||
alignItems: 'center'
|
||||
},
|
||||
row: {
|
||||
flexDirection: 'row',
|
||||
padding: 10,
|
||||
backgroundColor: 'white'
|
||||
},
|
||||
searchTextInput: {
|
||||
backgroundColor: 'white',
|
||||
borderColor: '#cccccc',
|
||||
borderRadius: 3,
|
||||
borderWidth: 1,
|
||||
paddingLeft: 8,
|
||||
paddingVertical: 0,
|
||||
height: 26,
|
||||
fontSize: 14,
|
||||
flexGrow: 1
|
||||
},
|
||||
separator: {
|
||||
height: SEPARATOR_HEIGHT,
|
||||
backgroundColor: 'rgb(200, 199, 204)'
|
||||
},
|
||||
smallSwitch: {
|
||||
top: 1,
|
||||
margin: -6,
|
||||
transform: [{ scale: 0.7 }]
|
||||
},
|
||||
stacked: {
|
||||
alignItems: 'center',
|
||||
backgroundColor: 'white',
|
||||
padding: 10
|
||||
},
|
||||
thumb: {
|
||||
width: 50,
|
||||
height: 50,
|
||||
left: -5
|
||||
},
|
||||
spindicator: {
|
||||
marginLeft: 'auto',
|
||||
marginTop: 8,
|
||||
width: 2,
|
||||
height: 16,
|
||||
backgroundColor: 'darkgray'
|
||||
},
|
||||
stackedText: {
|
||||
padding: 4,
|
||||
fontSize: 18
|
||||
},
|
||||
text: {
|
||||
flex: 1
|
||||
}
|
||||
});
|
||||
|
||||
export default function ListsPage() {
|
||||
return (
|
||||
<Example title="Lists">
|
||||
<SingleColumnExample />
|
||||
</Example>
|
||||
);
|
||||
}
|
||||
140
packages/examples/pages/modal/index.js
Normal file
140
packages/examples/pages/modal/index.js
Normal file
@@ -0,0 +1,140 @@
|
||||
import React, { useState, useMemo } from 'react';
|
||||
import { Modal, View, Text, Button, StyleSheet } from 'react-native';
|
||||
import Example from '../../shared/example';
|
||||
|
||||
function Gap() {
|
||||
return <View style={styles.gap} />;
|
||||
}
|
||||
|
||||
function AnimatedModal({ animationType }) {
|
||||
const [isVisible, setIsVisible] = useState(false);
|
||||
|
||||
return (
|
||||
<>
|
||||
<Button onPress={() => setIsVisible(true)} title={`Animation '${animationType}'`} />
|
||||
<Modal
|
||||
animationType={animationType}
|
||||
onRequestClose={() => setIsVisible(false)}
|
||||
visible={isVisible}
|
||||
>
|
||||
<View style={styles.container}>
|
||||
<Text>Modal with "animationType" of "{animationType}"</Text>
|
||||
<Gap />
|
||||
<Button onPress={() => setIsVisible(false)} title={'Close Modal'} />
|
||||
</View>
|
||||
</Modal>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
function AnimatedModalStack() {
|
||||
return (
|
||||
<>
|
||||
<AnimatedModal animationType={'none'} />
|
||||
<Gap />
|
||||
<AnimatedModal animationType={'slide'} />
|
||||
<Gap />
|
||||
<AnimatedModal animationType={'fade'} />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
const WIGGLE_ROOM = 128;
|
||||
|
||||
function Modalception({ depth = 1 }) {
|
||||
const [isVisible, setIsVisible] = useState(false);
|
||||
|
||||
const offset = useMemo(() => {
|
||||
return {
|
||||
top: Math.random() * WIGGLE_ROOM - WIGGLE_ROOM / 2,
|
||||
left: Math.random() * WIGGLE_ROOM - WIGGLE_ROOM / 2
|
||||
};
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<>
|
||||
<Button onPress={() => setIsVisible(true)} title={'Open modal'} />
|
||||
<Modal onRequestClose={() => setIsVisible(false)} transparent visible={isVisible}>
|
||||
<View style={[styles.containeralt, offset]}>
|
||||
<Text>This is in Modal {depth}</Text>
|
||||
<Gap />
|
||||
{isVisible ? <Modalception depth={depth + 1} /> : null}
|
||||
<Gap />
|
||||
<Button color="red" onPress={() => setIsVisible(false)} title={'Close'} />
|
||||
</View>
|
||||
</Modal>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
function SimpleModal() {
|
||||
const [isVisible, setIsVisible] = useState(false);
|
||||
|
||||
return (
|
||||
<>
|
||||
<Button onPress={() => setIsVisible(true)} title={'Simple modal'} />
|
||||
<Modal onRequestClose={() => setIsVisible(false)} visible={isVisible}>
|
||||
<View style={styles.container}>
|
||||
<Text>Hello, World!</Text>
|
||||
<Gap />
|
||||
<Button onPress={() => setIsVisible(false)} title={'Close'} />
|
||||
</View>
|
||||
</Modal>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
function TransparentModal() {
|
||||
const [isVisible, setIsVisible] = useState(false);
|
||||
|
||||
return (
|
||||
<>
|
||||
<Button onPress={() => setIsVisible(true)} title={'Transparent modal'} />
|
||||
<Modal onRequestClose={() => setIsVisible(false)} transparent visible={isVisible}>
|
||||
<View style={styles.containeralt}>
|
||||
<Text style={{ textAlign: 'center' }}>Modal with "transparent" value</Text>
|
||||
<Gap />
|
||||
<Button onPress={() => setIsVisible(false)} title={'Close'} />
|
||||
</View>
|
||||
</Modal>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
alignItems: 'center',
|
||||
flex: 1,
|
||||
justifyContent: 'center'
|
||||
},
|
||||
containeralt: {
|
||||
alignItems: 'center',
|
||||
backgroundColor: 'white',
|
||||
borderColor: '#eee',
|
||||
borderRadius: 10,
|
||||
borderWidth: 1,
|
||||
justifyContent: 'center',
|
||||
height: 300,
|
||||
margin: 'auto',
|
||||
padding: 30,
|
||||
width: 300
|
||||
},
|
||||
gap: {
|
||||
height: 10
|
||||
}
|
||||
});
|
||||
|
||||
export default function ModalPage() {
|
||||
return (
|
||||
<Example title="Modal">
|
||||
<Gap />
|
||||
<SimpleModal />
|
||||
<Gap />
|
||||
<TransparentModal />
|
||||
<Gap />
|
||||
<AnimatedModalStack />
|
||||
<Gap />
|
||||
<Modalception />
|
||||
</Example>
|
||||
);
|
||||
}
|
||||
165
packages/examples/pages/pan-responder/index.js
Normal file
165
packages/examples/pages/pan-responder/index.js
Normal file
@@ -0,0 +1,165 @@
|
||||
/**
|
||||
* @flow
|
||||
*/
|
||||
import React from 'react';
|
||||
import { PanResponder, StyleSheet, View } from 'react-native';
|
||||
import Example from '../../shared/example';
|
||||
|
||||
const CIRCLE_SIZE = 80;
|
||||
|
||||
class DraggableCircle extends React.PureComponent {
|
||||
_panResponder = {};
|
||||
_previousLeft = 0;
|
||||
_previousTop = 0;
|
||||
_circleStyles = {};
|
||||
circle = null;
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
this._panResponder = PanResponder.create({
|
||||
onStartShouldSetPanResponder: this._handleStartShouldSetPanResponder,
|
||||
onMoveShouldSetPanResponder: this._handleMoveShouldSetPanResponder,
|
||||
onPanResponderGrant: this._handlePanResponderGrant,
|
||||
onPanResponderMove: this._handlePanResponderMove,
|
||||
onPanResponderRelease: this._handlePanResponderEnd,
|
||||
onPanResponderTerminate: this._handlePanResponderEnd
|
||||
});
|
||||
this._previousLeft = 20;
|
||||
this._previousTop = 84;
|
||||
this._circleStyles = {
|
||||
style: {
|
||||
left: this._previousLeft,
|
||||
top: this._previousTop,
|
||||
backgroundColor: 'green'
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this._updateNativeStyles();
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
<View ref={this._setCircleRef} style={styles.circle} {...this._panResponder.panHandlers} />
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
||||
_setCircleRef = circle => {
|
||||
this.circle = circle;
|
||||
};
|
||||
|
||||
_highlight() {
|
||||
this._circleStyles.style.backgroundColor = 'blue';
|
||||
this._updateNativeStyles();
|
||||
}
|
||||
|
||||
_unHighlight() {
|
||||
this._circleStyles.style.backgroundColor = 'green';
|
||||
this._updateNativeStyles();
|
||||
}
|
||||
|
||||
_updateNativeStyles() {
|
||||
this.circle && this.circle.setNativeProps(this._circleStyles);
|
||||
}
|
||||
|
||||
_handleStartShouldSetPanResponder = (e: Object, gestureState: Object): boolean => {
|
||||
// Should we become active when the user presses down on the circle?
|
||||
return true;
|
||||
};
|
||||
|
||||
_handleMoveShouldSetPanResponder = (e: Object, gestureState: Object): boolean => {
|
||||
// Should we become active when the user moves a touch over the circle?
|
||||
return true;
|
||||
};
|
||||
|
||||
_handlePanResponderGrant = (e: Object, gestureState: Object) => {
|
||||
this._highlight();
|
||||
};
|
||||
|
||||
_handlePanResponderMove = (e: Object, gestureState: Object) => {
|
||||
this._circleStyles.style.left = this._previousLeft + gestureState.dx;
|
||||
this._circleStyles.style.top = this._previousTop + gestureState.dy;
|
||||
this._updateNativeStyles();
|
||||
};
|
||||
|
||||
_handlePanResponderEnd = (e: Object, gestureState: Object) => {
|
||||
this._unHighlight();
|
||||
this._previousLeft += gestureState.dx;
|
||||
this._previousTop += gestureState.dy;
|
||||
};
|
||||
}
|
||||
|
||||
class LocationXY extends React.Component {
|
||||
constructor() {
|
||||
super();
|
||||
this.state = { translateX: 0 };
|
||||
this.panResponder = PanResponder.create({
|
||||
onStartShouldSetPanResponder: () => true,
|
||||
onStartShouldSetPanResponderCapture: () => true,
|
||||
onPanResponderMove: this._handlePanResponderMove,
|
||||
onPanResponderTerminationRequest: () => true
|
||||
});
|
||||
}
|
||||
|
||||
_handlePanResponderMove = (e, gestureState) => {
|
||||
console.log(e.nativeEvent.locationX, e.nativeEvent.locationY);
|
||||
this.setState(state => ({
|
||||
...state,
|
||||
translateX: gestureState.dx
|
||||
}));
|
||||
};
|
||||
|
||||
render() {
|
||||
const transform = { transform: [{ translateX: this.state.translateX }] };
|
||||
return (
|
||||
<View style={styles.box}>
|
||||
<View style={styles.outer} {...this.panResponder.panHandlers}>
|
||||
<View style={[styles.inner, transform]} />
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
circle: {
|
||||
width: CIRCLE_SIZE,
|
||||
height: CIRCLE_SIZE,
|
||||
borderRadius: CIRCLE_SIZE / 2,
|
||||
position: 'absolute',
|
||||
left: 0,
|
||||
top: 0,
|
||||
touchAction: 'none'
|
||||
},
|
||||
container: {
|
||||
alignSelf: 'stretch',
|
||||
minHeight: 300,
|
||||
paddingTop: 64
|
||||
},
|
||||
box: {
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center'
|
||||
},
|
||||
outer: {
|
||||
width: 250,
|
||||
height: 50,
|
||||
backgroundColor: 'skyblue'
|
||||
},
|
||||
inner: {
|
||||
width: 30,
|
||||
height: 30,
|
||||
backgroundColor: 'lightblue'
|
||||
}
|
||||
});
|
||||
|
||||
export default function PanResponderPage() {
|
||||
return (
|
||||
<Example title="PanResponder">
|
||||
<DraggableCircle />
|
||||
<LocationXY />
|
||||
</Example>
|
||||
);
|
||||
}
|
||||
99
packages/examples/pages/pressable/index.js
Normal file
99
packages/examples/pages/pressable/index.js
Normal file
@@ -0,0 +1,99 @@
|
||||
import React from 'react';
|
||||
import { Button, ScrollView, StyleSheet, View, Text, Pressable } from 'react-native';
|
||||
import Example from '../../shared/example';
|
||||
|
||||
export default function PressablePage() {
|
||||
const [eventLog, updateEventLog] = React.useState([]);
|
||||
const [disabled, setDisabled] = React.useState(false);
|
||||
const [delay, setDelay] = React.useState(0);
|
||||
|
||||
const handleEvent = eventName => {
|
||||
return () => {
|
||||
const limit = 10;
|
||||
updateEventLog(state => {
|
||||
const nextState = state.slice(0, limit - 1);
|
||||
nextState.unshift(eventName);
|
||||
return nextState;
|
||||
});
|
||||
};
|
||||
};
|
||||
|
||||
return (
|
||||
<Example title="Pressable">
|
||||
<View style={styles.container}>
|
||||
<Pressable
|
||||
accessibilityRole="button"
|
||||
delayLongPress="750"
|
||||
delayPressIn={delay}
|
||||
delayPressOut={delay}
|
||||
disabled={disabled}
|
||||
onHoverIn={handleEvent('onHoverIn')}
|
||||
onHoverOut={handleEvent('onHoverOut')}
|
||||
onLongPress={handleEvent('onLongPress - 750ms delay')}
|
||||
onPress={handleEvent(`onPress - ${delay}ms delay`)}
|
||||
onPressIn={handleEvent(`onPressIn - ${delay}ms delay`)}
|
||||
onPressOut={handleEvent(`oPressOut - ${delay}ms delay`)}
|
||||
style={(state) => ([
|
||||
styles.pressable,
|
||||
!disabled && state.focused && styles.focused,
|
||||
!disabled && state.hovered && styles.hovered,
|
||||
!disabled && state.pressed && styles.pressed,
|
||||
disabled && styles.disabled
|
||||
])}
|
||||
>
|
||||
<Text>Pressable</Text>
|
||||
</Pressable>
|
||||
|
||||
<View style={styles.buttons}>
|
||||
<Button onPress={() => setDisabled(state => !state)} title={disabled ? 'Enable' : 'Disable'} />
|
||||
<View style={{ width: '1rem' }} />
|
||||
<Button onPress={() => setDelay(state => state === 0 ? 350 : 0)} title={delay === 0 ? 'Add delay' : 'Remove delay'} />
|
||||
</View>
|
||||
|
||||
<ScrollView style={styles.eventLogBox}>
|
||||
{eventLog.map((e, i) => (
|
||||
<Text key={i}>{e}</Text>
|
||||
))}
|
||||
</ScrollView>
|
||||
</View>
|
||||
</Example>
|
||||
);
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
maxWidth: 500,
|
||||
padding: '1rem',
|
||||
width: '100%',
|
||||
},
|
||||
pressable: {
|
||||
borderRadius: 5,
|
||||
padding: 10,
|
||||
borderWidth: 1,
|
||||
outlineWidth: 0,
|
||||
backgroundColor: '#fff'
|
||||
},
|
||||
hovered: {
|
||||
backgroundColor: '#ddd'
|
||||
},
|
||||
focused: {
|
||||
boxShadow: '0px 0px 0px 1px blue'
|
||||
},
|
||||
pressed: {
|
||||
backgroundColor: 'lightblue'
|
||||
},
|
||||
disabled: {
|
||||
opacity: 0.5
|
||||
},
|
||||
buttons: {
|
||||
flexDirection: 'row',
|
||||
marginVertical: '1rem'
|
||||
},
|
||||
eventLogBox: {
|
||||
padding: 10,
|
||||
height: 120,
|
||||
borderWidth: StyleSheet.hairlineWidth,
|
||||
borderColor: '#f0f0f0',
|
||||
backgroundColor: '#f9f9f9'
|
||||
}
|
||||
});
|
||||
50
packages/examples/pages/progress-bar/index.js
Normal file
50
packages/examples/pages/progress-bar/index.js
Normal file
@@ -0,0 +1,50 @@
|
||||
import React from 'react';
|
||||
import { ProgressBar, StyleSheet, View } from 'react-native';
|
||||
import Example from '../../shared/example';
|
||||
|
||||
function Divider() {
|
||||
return <View style={styles.divider} />;
|
||||
}
|
||||
|
||||
export default function ProgressBarPage() {
|
||||
return (
|
||||
<Example title="ProgressBar">
|
||||
<View style={styles.container}>
|
||||
<Divider />
|
||||
<ProgressBar indeterminate trackColor="#D1E3F6" />
|
||||
<Divider />
|
||||
<ProgressBar color="#1DA1F2" progress={0.2} />
|
||||
<Divider />
|
||||
<ProgressBar color="#17BF63" progress={0.4} />
|
||||
<Divider />
|
||||
<ProgressBar color="#F45D22" progress={0.6} />
|
||||
<Divider />
|
||||
<ProgressBar color="#794BC4" progress={0.8} />
|
||||
<Divider />
|
||||
<ProgressBar color="#E0245E" progress={1} />
|
||||
<Divider />
|
||||
<ProgressBar color="rgb(23, 191, 99)" progress={0.1} trackColor="rgba(23, 191, 99, 0.3)" />
|
||||
<Divider />
|
||||
<ProgressBar color="rgb(244, 93, 34)" progress={0.2} trackColor="rgba(244, 93, 34, 0.3)" />
|
||||
<Divider />
|
||||
<ProgressBar color="rgb(121, 75, 196)" progress={0.3} trackColor="rgba(121, 75, 196, 0.3)" />
|
||||
<Divider />
|
||||
<ProgressBar color="#1DA1F2" progress={0.33} style={styles.custom} trackColor="#D1E3F6" />
|
||||
</View>
|
||||
</Example>
|
||||
);
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
alignSelf: 'stretch',
|
||||
padding: '1rem'
|
||||
},
|
||||
divider: {
|
||||
height: '1rem'
|
||||
},
|
||||
custom: {
|
||||
borderRadius: 10,
|
||||
height: 20
|
||||
}
|
||||
});
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user