-
-
Notifications
You must be signed in to change notification settings - Fork 9.4k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #6594 from ForbesLindesay/ondevice-actions
Ondevice actions
- Loading branch information
Showing
13 changed files
with
382 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
# Storybook Actions Addon for react-native | ||
|
||
Storybook Actions Addon allows you to log events/actions inside stories in [Storybook](https://storybook.js.org). | ||
|
||
[Framework Support](https://github.com/storybooks/storybook/blob/master/ADDONS_SUPPORT.md) | ||
|
||
**This addon is a wrapper for addon [@storybook/addon-actions](https://github.com/storybooks/storybook/blob/master/addons/actions). | ||
Refer to its documentation to understand how to use actions** | ||
|
||
## Installation | ||
|
||
```sh | ||
yarn add -D @storybook/addon-ondevice-actions @storybook/addon-actions | ||
``` | ||
|
||
## Configuration | ||
|
||
Create a file called `rn-addons.js` in your storybook config. | ||
|
||
Add following content to it: | ||
|
||
```js | ||
import '@storybook/addon-ondevice-actions/register'; | ||
``` | ||
|
||
Then import `rn-addons.js` next to your `getStorybookUI` call. | ||
|
||
```js | ||
import './rn-addons'; | ||
``` | ||
|
||
See [@storybook/addon-actions](https://github.com/storybooks/storybook/blob/master/addons/actions) to learn how to write stories with actions and the [crna-kitchen-sink app](../../examples-native/crna-kitchen-sink) for more examples. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
{ | ||
"name": "@storybook/addon-ondevice-actions", | ||
"version": "5.1.0-alpha.37", | ||
"description": "Action Logger addon for react-native storybook", | ||
"keywords": [ | ||
"storybook" | ||
], | ||
"homepage": "https://github.com/storybooks/storybook/tree/master/addons/actions", | ||
"bugs": { | ||
"url": "https://github.com/storybooks/storybook/issues" | ||
}, | ||
"repository": { | ||
"type": "git", | ||
"url": "https://github.com/storybooks/storybook.git" | ||
}, | ||
"license": "MIT", | ||
"main": "dist/index.js", | ||
"scripts": { | ||
"prepare": "node ../../scripts/prepare.js" | ||
}, | ||
"dependencies": { | ||
"@storybook/addons": "5.1.0-alpha.37", | ||
"@storybook/core-events": "5.1.0-alpha.37", | ||
"core-js": "^2.5.7", | ||
"fast-deep-equal": "^2.0.1" | ||
}, | ||
"devDependencies": { | ||
"@storybook/addon-actions": "5.1.0-alpha.37" | ||
}, | ||
"peerDependencies": { | ||
"@storybook/addon-actions": "*", | ||
"react": "*", | ||
"react-native": "*" | ||
}, | ||
"publishConfig": { | ||
"access": "public" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
require('./dist').register(); |
173 changes: 173 additions & 0 deletions
173
addons/ondevice-actions/src/components/ActionLogger/Inspect.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,173 @@ | ||
import React from 'react'; | ||
import { Button, View, Text } from 'react-native'; | ||
|
||
const theme = { | ||
OBJECT_PREVIEW_ARRAY_MAX_PROPERTIES: 10, | ||
OBJECT_PREVIEW_OBJECT_MAX_PROPERTIES: 5, | ||
OBJECT_NAME_COLOR: 'rgb(136, 19, 145)', | ||
OBJECT_VALUE_NULL_COLOR: 'rgb(128, 128, 128)', | ||
OBJECT_VALUE_UNDEFINED_COLOR: 'rgb(128, 128, 128)', | ||
OBJECT_VALUE_REGEXP_COLOR: 'rgb(196, 26, 22)', | ||
OBJECT_VALUE_STRING_COLOR: 'rgb(196, 26, 22)', | ||
OBJECT_VALUE_SYMBOL_COLOR: 'rgb(196, 26, 22)', | ||
OBJECT_VALUE_NUMBER_COLOR: 'rgb(28, 0, 207)', | ||
OBJECT_VALUE_BOOLEAN_COLOR: 'rgb(28, 0, 207)', | ||
OBJECT_VALUE_FUNCTION_PREFIX_COLOR: 'rgb(13, 34, 170)', | ||
|
||
ARROW_COLOR: '#6e6e6e', | ||
ARROW_MARGIN_RIGHT: 3, | ||
ARROW_FONT_SIZE: 12, | ||
ARROW_ANIMATION_DURATION: '0', | ||
}; | ||
|
||
class Inspect extends React.Component<{ name?: string; value: any }, { expanded: boolean }> { | ||
state = { expanded: false }; | ||
render() { | ||
const { name, value } = this.props; | ||
const { expanded } = this.state; | ||
const toggle = ( | ||
<View style={{ width: 40, height: 40 }}> | ||
{name && | ||
((Array.isArray(value) && value.length) || | ||
(value && | ||
typeof value === 'object' && | ||
!Array.isArray(value) && | ||
Object.keys(value).length)) ? ( | ||
<Button | ||
onPress={() => this.setState(s => ({ expanded: !s.expanded }))} | ||
title={!expanded ? '▶' : '▼'} | ||
/> | ||
) : null} | ||
</View> | ||
); | ||
|
||
const nameComponent = name ? ( | ||
<Text style={{ color: theme.OBJECT_NAME_COLOR }}>{name}</Text> | ||
) : null; | ||
|
||
if (Array.isArray(value)) { | ||
if (name) { | ||
return ( | ||
<> | ||
<View style={{ flexDirection: 'row', alignItems: 'center' }}> | ||
{toggle} | ||
{nameComponent} | ||
<Text>{': ' + (value.length === 0 ? '[]' : expanded ? '[' : '[...]')}</Text> | ||
</View> | ||
{expanded ? ( | ||
<View style={{ marginLeft: 40 }}> | ||
{value.map((v, i) => ( | ||
<View key={i} style={{ marginLeft: 40 }}> | ||
<Inspect value={v} /> | ||
</View> | ||
))} | ||
<View style={{ marginLeft: 20 }}> | ||
<Text>{']'}</Text> | ||
</View> | ||
</View> | ||
) : null} | ||
</> | ||
); | ||
} | ||
return ( | ||
<View> | ||
<Text>{'['}</Text> | ||
{value.map((v, i) => ( | ||
<View key={i} style={{ marginLeft: 20 }}> | ||
<Inspect value={v} /> | ||
</View> | ||
))} | ||
<Text>{']'}</Text> | ||
</View> | ||
); | ||
} | ||
if (value && typeof value === 'object' && !(value instanceof RegExp)) { | ||
if (name) { | ||
return ( | ||
<> | ||
<View style={{ flexDirection: 'row', alignItems: 'center' }}> | ||
{toggle} | ||
{nameComponent} | ||
<Text> | ||
{': ' + (Object.keys(value).length === 0 ? '{}' : expanded ? '{' : '{...}')} | ||
</Text> | ||
</View> | ||
{expanded ? ( | ||
<View style={{ marginLeft: 40 }}> | ||
{Object.entries(value).map(([key, v]) => ( | ||
<View key={key}> | ||
<Inspect name={key} value={v} /> | ||
</View> | ||
))} | ||
<View style={{ marginLeft: 20 }}> | ||
<Text>{'}'}</Text> | ||
</View> | ||
</View> | ||
) : null} | ||
</> | ||
); | ||
} | ||
return ( | ||
<View> | ||
<Text>{'{'}</Text> | ||
{Object.entries(value).map(([key, v]) => ( | ||
<View key={key}> | ||
<Inspect name={key} value={v} /> | ||
</View> | ||
))} | ||
<Text>{'}'}</Text> | ||
</View> | ||
); | ||
} | ||
if (name) { | ||
return ( | ||
<View style={{ flexDirection: 'row', alignItems: 'center' }}> | ||
{toggle} | ||
{nameComponent} | ||
<Text>{': '}</Text> | ||
<Value value={value} /> | ||
</View> | ||
); | ||
} | ||
return ( | ||
<View> | ||
<Value value={value} /> | ||
</View> | ||
); | ||
} | ||
} | ||
|
||
function Value({ value }: { value: any }) { | ||
if (value === null) { | ||
return <Text style={{ color: theme.OBJECT_VALUE_NULL_COLOR }}>null</Text>; | ||
} | ||
if (value === undefined) { | ||
return <Text style={{ color: theme.OBJECT_VALUE_UNDEFINED_COLOR }}>undefined</Text>; | ||
} | ||
if (value instanceof RegExp) { | ||
return ( | ||
<Text style={{ color: theme.OBJECT_VALUE_REGEXP_COLOR }}> | ||
{'/' + value.source + '/' + value.flags} | ||
</Text> | ||
); | ||
} | ||
switch (typeof value) { | ||
case 'string': | ||
return ( | ||
<Text style={{ color: theme.OBJECT_VALUE_STRING_COLOR }}>{JSON.stringify(value)}</Text> | ||
); | ||
case 'number': | ||
return ( | ||
<Text style={{ color: theme.OBJECT_VALUE_NUMBER_COLOR }}>{JSON.stringify(value)}</Text> | ||
); | ||
case 'boolean': | ||
return ( | ||
<Text style={{ color: theme.OBJECT_VALUE_BOOLEAN_COLOR }}>{JSON.stringify(value)}</Text> | ||
); | ||
case 'function': | ||
return <Text style={{ color: theme.OBJECT_VALUE_FUNCTION_PREFIX_COLOR }}>[Function]</Text>; | ||
} | ||
return <Text>{JSON.stringify(value)}</Text>; | ||
} | ||
|
||
export default Inspect; |
31 changes: 31 additions & 0 deletions
31
addons/ondevice-actions/src/components/ActionLogger/index.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
import React from 'react'; | ||
import { Button, View, Text, ScrollView } from 'react-native'; | ||
import { ActionDisplay } from '@storybook/addon-actions'; | ||
import Inspect from './Inspect'; | ||
|
||
interface ActionLoggerProps { | ||
actions: ActionDisplay[]; | ||
onClear: () => void; | ||
} | ||
|
||
export const ActionLogger = ({ actions, onClear }: ActionLoggerProps) => ( | ||
<ScrollView> | ||
<ScrollView horizontal> | ||
<View> | ||
{actions.map((action: ActionDisplay) => ( | ||
<View key={action.id} style={{ flexDirection: 'row' }}> | ||
<View>{action.count > 1 ? <Text>{action.count}</Text> : null}</View> | ||
<View style={{ flexGrow: 1 }}> | ||
<Inspect name={action.data.name} value={action.data.args || action.data} /> | ||
</View> | ||
</View> | ||
))} | ||
</View> | ||
</ScrollView> | ||
<View> | ||
<Button onPress={onClear} title="CLEAR" /> | ||
</View> | ||
</ScrollView> | ||
); | ||
|
||
export default ActionLogger; |
79 changes: 79 additions & 0 deletions
79
addons/ondevice-actions/src/containers/ActionLogger/index.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
import React, { Component } from 'react'; | ||
import deepEqual from 'fast-deep-equal'; | ||
|
||
import { addons } from '@storybook/addons'; | ||
import { STORY_RENDERED } from '@storybook/core-events'; | ||
import { ActionDisplay, EVENT_ID } from '@storybook/addon-actions'; | ||
|
||
import { ActionLogger as ActionLoggerComponent } from '../../components/ActionLogger'; | ||
|
||
interface ActionLoggerProps { | ||
active: boolean; | ||
} | ||
|
||
interface ActionLoggerState { | ||
actions: ActionDisplay[]; | ||
} | ||
|
||
const safeDeepEqual = (a: any, b: any): boolean => { | ||
try { | ||
return deepEqual(a, b); | ||
} catch (e) { | ||
return false; | ||
} | ||
}; | ||
|
||
export default class ActionLogger extends Component<ActionLoggerProps, ActionLoggerState> { | ||
private channel = addons.getChannel(); | ||
|
||
constructor(props: ActionLoggerProps) { | ||
super(props); | ||
|
||
this.state = { actions: [] }; | ||
} | ||
|
||
componentDidMount() { | ||
this.channel.addListener(EVENT_ID, this.addAction); | ||
this.channel.addListener(STORY_RENDERED, this.handleStoryChange); | ||
} | ||
|
||
componentWillUnmount() { | ||
this.channel.removeListener(STORY_RENDERED, this.handleStoryChange); | ||
this.channel.removeListener(EVENT_ID, this.addAction); | ||
} | ||
|
||
handleStoryChange = () => { | ||
const { actions } = this.state; | ||
if (actions.length > 0 && actions[0].options.clearOnStoryChange) { | ||
this.clearActions(); | ||
} | ||
}; | ||
|
||
addAction = (action: ActionDisplay) => { | ||
this.setState((prevState: ActionLoggerState) => { | ||
const actions = [...prevState.actions]; | ||
const previous = actions.length && actions[0]; | ||
if (previous && safeDeepEqual(previous.data, action.data)) { | ||
previous.count++; // eslint-disable-line | ||
} else { | ||
action.count = 1; // eslint-disable-line | ||
actions.unshift(action); | ||
} | ||
return { actions: actions.slice(0, action.options.limit) }; | ||
}); | ||
}; | ||
|
||
clearActions = () => { | ||
this.setState({ actions: [] }); | ||
}; | ||
|
||
render() { | ||
const { actions = [] } = this.state; | ||
const { active } = this.props; | ||
const props = { | ||
actions, | ||
onClear: this.clearActions, | ||
}; | ||
return active ? <ActionLoggerComponent {...props} /> : null; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
import React from 'react'; | ||
import addons from '@storybook/addons'; | ||
import { ADDON_ID, PANEL_ID } from '@storybook/addon-actions'; | ||
import ActionLogger from './containers/ActionLogger'; | ||
|
||
export function register() { | ||
addons.register(ADDON_ID, () => { | ||
addons.addPanel(PANEL_ID, { | ||
title: 'Actions', | ||
render: ({ active, key }) => <ActionLogger key={key} active={active} />, | ||
}); | ||
}); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
{ | ||
"extends": "../../tsconfig.json", | ||
"compilerOptions": { | ||
"rootDir": "./src" | ||
}, | ||
"include": ["src/**/*"], | ||
"exclude": ["src/__tests__/**/*"] | ||
} |
Oops, something went wrong.
c726632
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Successfully aliased the URL https://monorepo-6g054of2v.now.sh to the following aliases.