Skip to content

Commit

Permalink
Merge pull request #8 from MailOnline/feat/various
Browse files Browse the repository at this point in the history
Feat/various
  • Loading branch information
streamich authored Jan 25, 2018
2 parents 61e4d98 + 4f91f47 commit d54c6ba
Show file tree
Hide file tree
Showing 35 changed files with 954 additions and 14 deletions.
23 changes: 23 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
language: node_js
os:
- linux
cache:
yarn: true
directories:
- ~/.npm
notifications:
email: false
node_js:
- '9'
- '8'
script:
- npm run test
- npm run build
matrix:
allow_failures: []
fast_finish: true
after_success:
- npm run semantic-release
branches:
except:
- /^v\d+\.\d+\.\d+$/
6 changes: 5 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
![libreact logo](./docs/libreact.png)

# libreact

[![][npm-badge]][npm-url] [![][travis-badge]][travis-url]
Expand Down Expand Up @@ -39,13 +41,15 @@ const MyComponent = mock();
- [`<NetworkSensor>`](./docs/NetworkSensor.md) and [`withNetwork()`](./docs/NetworkSensor.md#withnetwork)
- [`<LightSensor>`](./docs/LightSensor.md)
- [`<LocationSensor>`](./docs/LocationSensor.md)
- [`<OrientationSensor>`](./docs/OrientationSensor.md) and [`withOrientation()`](./docs/OrientationSensor.md#withorientation)
- [`<ScrollSensor>`](./docs/ScrollSensor.md)
- [`<SizeSensor>`](./docs/SizeSensor.md)
- `<ViewportSensor>`
- [`<ViewportSensor>`](./docs/ViewportSensor.md), `<ViewportScrollSensor>`, and `<ViewportObserverSensor>`
- [`<WidthSensor>`](./docs/WidthSensor.md)
- [`<WindowScrollSensor>`](./docs/WindowScrollSensor.md)
- [`<WindowSizeSensor>`](./docs/WindowSizeSensor.md)
- Generators
- [`<Alert>`](./docs/Alert.md)
- [`<Audio>`](./docs/Audio.md)
- [`<LocalStorage>`](./docs/LocalStorage.md)
- `<Redirect>`
Expand Down
16 changes: 16 additions & 0 deletions docs/Alert.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# `<Alert>`

Uses [`Window.alert()`](https://developer.mozilla.org/en-US/docs/Web/API/Window/alert) to display message ot a user.

## Usage

```jsx
import {Alert} from 'libreact/lib/Alert';

<Alert show text='Hello world' />
```

## Props

- `show` - boolean, optional, whether to show the alert.
- `text` - string, require, string message to display to the user.
2 changes: 1 addition & 1 deletion docs/LocalStorage.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import {LocalStorage} from 'libreact/lib/LocalStorage';
- `onMount` - optional, callback that receives stored data on component mount. Useful to persist and
re-hydrate form data, for example.

# Example
## Example

In the below example form inputs are stored in `localStorage` and re-hydrated when user
comes back and form renders for the first time.
Expand Down
45 changes: 45 additions & 0 deletions docs/OrientationSensor.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# `<OrientationSensor>`

Tracks screen orientation using [`orientationchange` event](https://developer.mozilla.org/en-US/docs/Web/Events/orientationchange).

## Usage

```jsx
import {OrientationSensor} from 'libreact/lib/OrientationSensor';

<OrientationSensor>(state) =>
<pre>{JSON.stringify(state, null, 4)}</pre>
</OrientationSensor>
```

## Props

None.

## State

Has signature

```ts
interface IOrientationSensorState {
angle: number;
type: string;
}
```

, where

- `angle` - screen rotation angle in degrees.
- `type` - is one of `portrait-primary`, `portrait-secondary`, `landscape-primary`, or `landscape-secondary`.


## `withOrientation()`

HOC that injects `orientation` object into your component.


```js
import {withOrientation} from 'libreact/lib/OrientationSensor';

const MyCompWithOrientation = withOrientation(MyComp);
```
36 changes: 36 additions & 0 deletions docs/Prompt.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# `<Prompt>`

Uses [`Window.prompt()`](https://developer.mozilla.org/en-US/docs/Web/API/Window/prompt) to get user input.

## Usage

Use it as a standalone compnent that returns result in `onResult` handler

```jsx
import {Prompt} from 'libreact/lib/Prompt';

<Prompt
show
message='Hello world'
default='hello back'
onResult={console.log}
/>
```

Or use it as a FaCC

```jsx
<Prompt
show
message='Hello world'
default='hello back'
onResult={console.log}
>{(result) => <div>{result}</div>}</Prompt>
```

## Props

- `show` - boolean, optional, whether to show the prompt modal.
- `message` - string, optional, string message to display to the user.
- `default` - string, optional, default text to pre-fill the user's response input.
- `onResult` - function, optional, function that receives prompt result string as a single argument.
52 changes: 52 additions & 0 deletions docs/ViewportSensor.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# `<ViewportSensor>`

Tracks if `children` are in viewport. Can be used as FaCC or a regular component.

Under-the-hood it uses `<ViewportObserverSensor>`, which in turn uses [`IntersectionObserver`](https://developer.mozilla.org/en-US/docs/Web/API/IntersectionObserver) API
to detect if your component is in viewport.

If `IntersectionObserver` API is not available it falls back and lazily downloads `<ViewportScrollSensor>`,
which uses document's scroll event to track if your component is in viewport.

## Usage

```jsx
import {ViewportSensor} from 'libreact/lib/ViewportSensor';

<ViewportSensor threshold={1} onChange={console.log}>{(state) =>
<pre>{JSON.stringify(state, null, 4)}</pre>
}</ViewportSensor>
```

## Props

Sensor's props have the following signature

```ts
interface IViewportSensorProps {
threshold?: number;
onChange?: (state: IViewportObserverSensorState) => void;
}
```

, where

- `threshold` - optional, number, percentage how much does your component have to intersect with viewport
to be considered visible. Defaults to `0`.
- `onChange` - optional, callback called when sensor changes its state, receives the state of the sensor as
a single argument.

## State

Sensor's state has the following signature

```ts
interface IViewportSensorState {
visible: boolean;
}
```

## `<ViewportScrollSensor>`

The `<ViewportScrollSensor>` has an additional prop `throttle`, which is a number in milliseconds specifying
how much to throttle document's `scroll` event.
11 changes: 11 additions & 0 deletions docs/getDisplayName.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# `getDisplayName()`

Returns display name of a React component.

```jsx
import getDisplayName from 'libreact/lib/util/getDisplayName';

const name = getDisplayName(MyComponent);
```

Accepts a single argument, which can be a stateful or stateless React component, or element. Returns a string.
Binary file added docs/libreact.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
8 changes: 5 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "libreact",
"version": "0.1.0",
"version": "0.2.0",
"description": "React standard library",
"main": "lib/index.js",
"keywords": [
Expand Down Expand Up @@ -55,7 +55,8 @@
"ts-loader": "3.2.0",
"ts-node": "4.1.0",
"typescript": "2.6.2",
"webpack": "3.10.0"
"webpack": "3.10.0",
"semantic-release": "^12.2.4"
},
"config": {
"commitizen": {
Expand All @@ -72,7 +73,8 @@
"test:watch": "jest --watch",
"storybook": "start-storybook -p 6007",
"build-storybook": "build-storybook",
"start": "npm run storybook"
"start": "npm run storybook",
"semantic-release": "semantic-release"
},
"jest": {
"moduleFileExtensions": [
Expand Down
11 changes: 11 additions & 0 deletions src/Alert/__story__/story.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import {createElement as h} from 'react';
import {storiesOf} from '@storybook/react';
import {action} from '@storybook/addon-actions';
import {linkTo} from '@storybook/addon-links';
import {Alert} from '..';
import ShowDocs from '../../../.storybook/ShowDocs'

storiesOf('Generators/Alert', module)
.add('Documentation', () => h(ShowDocs, {name: 'Alert'}))
.add('Basic example', () => <Alert show text='Hello world' />)
.add('Don\'t show', () => <Alert show={false} text='You shall not see this' />);
29 changes: 29 additions & 0 deletions src/Alert/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import {PureComponent} from 'react';
import {noop, isClient} from '../util';

export interface IAlertProps {
show?: boolean;
text?: string;
}

export class Alert extends PureComponent<IAlertProps, any> {
componentDidMount () {
this.alert();
}

componentDidUpdate () {
this.alert();
}

alert () {
const {show, text} = this.props;

if (show) {
alert(text);
}
}

render () {
return null;
}
}
1 change: 0 additions & 1 deletion src/LocationSensor/__tests__/index.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@ describe('<LocationSensor>', () => {
);
});


describe('re-renders on', () => {
const events = [
'pushstate',
Expand Down
22 changes: 22 additions & 0 deletions src/OrientationSensor/__story__/story.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import {createElement as h} from 'react';
import {storiesOf} from '@storybook/react';
import {action} from '@storybook/addon-actions';
import {linkTo} from '@storybook/addon-links';
import {OrientationSensor, withOrientation} from '..';
import ShowDocs from '../../../.storybook/ShowDocs'

const Print = ({orientation}) =>
<pre style={{fontFamily: 'monospace'}}>
{JSON.stringify(orientation, null, 4)}
</pre>;

const PrintOrientation = withOrientation(Print);

storiesOf('Sensors/OrientationSensor', module)
.add('Documentation', () => h(ShowDocs, {name: 'OrientationSensor'}))
.add('FaCC', () =>
<OrientationSensor>{(state) =>
<pre style={{fontFamily: 'monospace'}}>{JSON.stringify(state, null, 4)}</pre>
}</OrientationSensor>
)
.add('HOC', () => <PrintOrientation />);
64 changes: 64 additions & 0 deletions src/OrientationSensor/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import {Component} from 'react';
import {SyncSensor} from '../SyncSensor';
import {h, on, off, isClient} from '../util';

export interface IOrientationSensorProps {
children?: (state: IOrientationSensorState) => React.ReactElement<any>;
}

export interface IOrientationSensorState {
angle: number;
type: string;
}

const DEFAULT = {
angle: 0,
type: 'landscape-primary'
};

const addListener = (handler) => on(window, 'orientationchange', handler);
const removeListener = (handler) => off(window, 'orientationchange', handler);
const onEvent = () => {
const {orientation} = screen as any;

if (!orientation) {
return DEFAULT;
}

const {
angle,
type
} = orientation;

return {
angle,
type
};
};

const getInitialState = () => {
return isClient ? onEvent() : DEFAULT;
};

export class OrientationSensor extends Component<IOrientationSensorProps, any> {
initial = getInitialState();

render () {
return h(SyncSensor, {
children: this.props.children,
initial: this.initial,
addListener,
removeListener,
onEvent
});
}
}

export const withOrientation = (Comp) =>
(props) =>
h(OrientationSensor, null, (orientation) =>
h(Comp, {
...props,
orientation
})
);
Loading

0 comments on commit d54c6ba

Please sign in to comment.