diff --git a/README.md b/README.md
index 118fcd7e..c248f94f 100644
--- a/README.md
+++ b/README.md
@@ -1,57 +1,34 @@
# react-web-sdk
-**Experimental / API proof of concept**
+**Experimental / Proof of concept**
-Components for building web applications and SDKs. Based on `react-native`'s
-components.
+A component-based React SDK for building and styling web applications and SDKs.
+Inspired by `react-native`.
-1. Styles are plain JavaScript objects.
-2. Styles are passed to a component's `style` prop.
-3. Non-dynamic styles rely on static CSS classes.
-4. Dynamic styles are written as inline styles on the DOM node.
+This library provides:
-Each Component defines `StylePropTypes` and filters out any style properties
-that are not part of its style API. For example, `View` does not support any
-typographic properties. You must use `Text` to wrap and style any text strings.
+* An initial implementation of the `react-native` components `Image`, `Text`,
+ and `View`.
+* An initial implementation of defining explicit and default `style` propTypes.
+* A proof of concept implementation for converting inline `style` definitions
+ to CSS classes.
-### Implementation notes
-
-The current implementation uses a prebuilt CSS library – 200+ single-purpose,
-obfuscated selectors. It provides a large number of common, knowable styles
-needed to build apps. This makes the foundational CSS fixed (~5KB gzipped) and
-highly cachable. Inline styles are used for anything the CSS library doesn't
-provide, but their use is significantly reduced.
-
-A better implementation would generate the CSS library from the declarations
-defined in the source code, replace static variables (use webpack's
-`DefinePlugin`?), and only use inline-styles for dynamic, instance-specific
+This proof of concept uses a ~3KB (gzipped) precomputed CSS bundle; a complete
+implementation is likely to produce a slightly larger CSS file and fewer inline
styles.
-What about media queries? Perhaps rely on `mediaMatch` and re-render when the
-`style` prop needs to change; works better with DOM-related changes that need
-to happen at breakpoints. And that would avoid the need for any additional
-CSS. Alternatively, rely on something similar to `react-style`'s approach and
-duplicate the single-purpose classes within static CSS media queries.
+Other React styling strategies:
+[react-native](https://facebook.github.io/react-native/),
+[react-style](https://github.com/js-next/react-style),
+[jsxstyle](https://github.com/petehunt/jsxstyle),
+[react-inline](https://github.com/martinandert/react-inline), and
+[react-free-style](https://github.com/blakeembrey/react-free-style/)
-### Example
+### 1. Write styles using plain JavaScript objects
+
+Use JavaScript to write style definitions in React components:
```js
-import React from 'react';
-import {Image, Text, View} from 'react-web-sdk';
-
-class Example extends React.Component {
- render() {
- return (
-
-
- 0.5 && style.text) }}>
- Example component
-
-
- );
- }
-}
-
const style = {
common: {
backgroundColor: 'white',
@@ -68,10 +45,131 @@ const style = {
fontWeight: '300'
}
};
-
-export default Example;
```
+### 2. Set styles using the `style` attribute
+
+The `style` attribute is a simple API for creating element-scoped styles.
+
+```js
+...
+
+
+ ...
+...
+```
+
+The current implementation uses a precomputed CSS library of known and common
+declarations – 200+ single-declaration rules, with obfuscated selectors. This
+handles a signficant portion of possible declarations. But it falls through to
+inline styles significantly more often than an better implementation using
+static analysis to generate the CSS library at build time.
+
+### 4. Use inline styles for dynamic values
+
+Inline styles are used for values that cannot be resolved at build time.
+
+```js
+ 0.5 ? 'red' : 'black')}}>...
+```
+
+### 5. Add `style` prop types
+
+Each Component defines `StylePropTypes` and filters out any style properties
+that are not part of its style API. For example, `View` does not support any
+typographic properties.
+
+See the section below on `StylePropTypes`.
+
+### Media Queries?
+
+We can use `mediaMatch` to orchestrate both style and DOM changes. The
+component can be re-rendered when the styles change. This also avoids the need
+for additional CSS. Adding media queries as keys on the `style` object (like
+`react-style` does) might be a good, or it might not be. I'd prefer a solution
+that accomodates both style and DOM changes, rather than one or the other.
+Perhaps `this.context` or a higher-order component that passes viewport data to
+components via `props`.
+
---
## Components
@@ -93,37 +191,26 @@ All other props are transferred directly to the `element`.
#### Examples
```js
-import {Component, getOtherProps, pickProps} from 'react-web-sdk';
+import {Component, pickProps} from 'react-web-sdk';
import React, {PropTypes} from 'react';
-const ExampleStylePropTypes = {
- opacity: PropTypes.number
-};
-
-const ExampleStyleDefaultProps = {
- opacity: 1
-};
+const ExampleStylePropTypes = { opacity: PropTypes.number };
+const ExampleStyleDefaultProps = { opacity: 1 };
class Example extends React.Component {
static propTypes = {
- anExampleProp: PropTypes.number,
- someExampleProp: PropTypes.string,
style: PropTypes.shape(ExampleStylePropTypes)
}
- static defaultProps = {
- style: ExampleStyleDefaultProps
- }
-
render() {
- const other = getOtherProps(this);
+ // only apply supported styles
const supportedStyle = pickProps(this.props.style, ExampleStylePropTypes);
+ // merge with default styles
const style = { ...ExampleStyleDefaultProps, ...supportedStyle }
return (
@@ -141,10 +228,10 @@ TODO
All other props are transferred directly to the `element`.
-+ `alt`: `string`
++ `accessibilityLabel`: `string`
+ `async`: `bool` (TODO)
+ `className`: `string`
-+ `src`: `string`
++ `source`: `string`
+ `style`: `ImageStylePropTypes`
#### ImageStylePropTypes
@@ -154,6 +241,47 @@ All other props are transferred directly to the `element`.
+ `LayoutPropTypes`
+ `opacity`: `string`
+#### Examples
+
+```js
+import {Image, StylePropTypes} from 'react-web-sdk';
+import React, {PropTypes} from 'react';
+
+const AvatarStylePropTypes = {
+ ...StylePropTypes.BorderThemePropTypes
+};
+
+const AvatarStyleDefaultProps = {
+ borderColor: 'white',
+ borderWidth: '5px'
+};
+
+class Avatar extends React.Component {
+ static propTypes = {
+ size: PropTypes.oneOf(['small', 'normal', 'large']),
+ style: PropTypes.shape(AvatarStylePropTypes),
+ user: PropTypes.object
+ }
+
+ static defaultProps = {
+ size: 'normal'
+ }
+
+ render() {
+ const supportedStyle = pickProps(this.props.style, AvatarStylePropTypes);
+ const style = { ...AvatarStyleDefaultProps, ...supportedStyle }
+
+ return (
+
+ );
+ }
+}
+```
+
### `Text`
@@ -172,6 +300,61 @@ All other props are transferred directly to the `element`.
+ ViewStylePropTypes
+ TypographicPropTypes
+#### Examples
+
+```js
+import {StylePropTypes, Text} from 'react-web-sdk';
+import React, {PropTypes} from 'react';
+
+class PrettyText extends React.Component {
+ static propTypes = {
+ color: PropTypes.oneOf(['white', 'gray', 'red']),
+ size: PropTypes.oneOf(['small', 'normal', 'large']),
+ weight: PropTypes.oneOf(['light', 'normal', 'bold'])
+ }
+
+ static defaultProps = {
+ color: 'gray',
+ size: 'normal',
+ weight: 'normal'
+ }
+
+ render() {
+ const { color, size, style, weight, ...other } = this.props;
+
+ return (
+
+ );
+ }
+}
+
+const localStyle = {
+ color: {
+ white: { color: 'white' },
+ gray: { color: 'gray' },
+ red: { color: 'red' }
+ },
+ size: {
+ small: { fontSize: '0.85rem', padding: '0.5rem' },
+ normal: { fontSize: '1rem', padding: '0.75rem' },
+ large: { fontSize: '1.5rem', padding: '1rem' }
+ },
+ weight: {
+ light: { fontWeight: '300' },
+ normal: { fontWeight: '400' },
+ bold: { fontWeight: '700' }
+ }
+}
+```
+
### `View`
diff --git a/index.js b/index.js
index 500f1e52..454a592e 100644
--- a/index.js
+++ b/index.js
@@ -1,4 +1,5 @@
import {getOtherProps, omitProps, pickProps} from './lib/filterObjectProps';
+import StylePropTypes from './lib/StylePropTypes';
import Component from './lib/components/Component';
import Image from './lib/components/Image';
import Text from './lib/components/Text';
@@ -7,6 +8,7 @@ import View from './lib/components/View';
export default {
getOtherProps,
pickProps,
+ StylePropTypes,
Component,
Image,
Text,