mirror of
https://github.com/reduxjs/redux-devtools.git
synced 2024-12-04 15:33:53 +03:00
Use prettier
This commit is contained in:
parent
458f9019aa
commit
6907c48147
File diff suppressed because one or more lines are too long
|
@ -6,3 +6,4 @@ umd
|
||||||
build
|
build
|
||||||
coverage
|
coverage
|
||||||
node_modules
|
node_modules
|
||||||
|
__snapshots__
|
||||||
|
|
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -7,3 +7,4 @@ umd
|
||||||
build
|
build
|
||||||
coverage
|
coverage
|
||||||
.idea
|
.idea
|
||||||
|
.eslintcache
|
||||||
|
|
|
@ -8,5 +8,5 @@ cache:
|
||||||
- "node_modules"
|
- "node_modules"
|
||||||
script:
|
script:
|
||||||
- yarn build:all
|
- yarn build:all
|
||||||
- yarn lint
|
- yarn lint:all
|
||||||
- yarn test
|
- yarn test
|
||||||
|
|
|
@ -11,4 +11,3 @@ Project maintainers have the right and responsibility to remove, edit, or reject
|
||||||
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by opening an issue or contacting one or more of the project maintainers.
|
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by opening an issue or contacting one or more of the project maintainers.
|
||||||
|
|
||||||
This Code of Conduct is adapted from the [Contributor Covenant](http://contributor-covenant.org), version 1.0.0, available at [http://contributor-covenant.org/version/1/0/0/](http://contributor-covenant.org/version/1/0/0/)
|
This Code of Conduct is adapted from the [Contributor Covenant](http://contributor-covenant.org), version 1.0.0, available at [http://contributor-covenant.org/version/1/0/0/](http://contributor-covenant.org/version/1/0/0/)
|
||||||
|
|
||||||
|
|
|
@ -15,6 +15,7 @@ By default, the websocket server is running on `ws://localhost:8000/socketcluste
|
||||||
The client driver provides a way to connect to the server via websockets (see the docs for the selected client).
|
The client driver provides a way to connect to the server via websockets (see the docs for the selected client).
|
||||||
|
|
||||||
##### JavaScript
|
##### JavaScript
|
||||||
|
|
||||||
```js
|
```js
|
||||||
var socket = socketCluster.connect({
|
var socket = socketCluster.connect({
|
||||||
hostname: 'localhost',
|
hostname: 'localhost',
|
||||||
|
@ -23,6 +24,7 @@ var socket = socketCluster.connect({
|
||||||
```
|
```
|
||||||
|
|
||||||
##### Python
|
##### Python
|
||||||
|
|
||||||
```py
|
```py
|
||||||
socket = Socketcluster.socket("ws://localhost:8000/socketcluster/")
|
socket = Socketcluster.socket("ws://localhost:8000/socketcluster/")
|
||||||
socket.connect()
|
socket.connect()
|
||||||
|
@ -35,6 +37,7 @@ socket.connect()
|
||||||
SocketCluster client handles reconnecting for you, but you still might want to know when the connection is established, or when it failed to connect.
|
SocketCluster client handles reconnecting for you, but you still might want to know when the connection is established, or when it failed to connect.
|
||||||
|
|
||||||
##### JavaScript
|
##### JavaScript
|
||||||
|
|
||||||
```js
|
```js
|
||||||
socket.on('connect', status => {
|
socket.on('connect', status => {
|
||||||
// Here will come the next step
|
// Here will come the next step
|
||||||
|
@ -48,6 +51,7 @@ socket.on('error', error => {
|
||||||
```
|
```
|
||||||
|
|
||||||
##### Python
|
##### Python
|
||||||
|
|
||||||
```py
|
```py
|
||||||
def onconnect(socket):
|
def onconnect(socket):
|
||||||
// Here will call the next step
|
// Here will call the next step
|
||||||
|
@ -66,9 +70,13 @@ socket.setBasicListener(onconnect, ondisconnect, onConnectError)
|
||||||
We're not providing an authorizing mechanism yet. All you have to do is to emit a `login` event, and you'll get a `channelName` you should subscribe for, and watch for messages and events. Make sure to pass the `master` event, otherwise it should be a monitor, not a client app.
|
We're not providing an authorizing mechanism yet. All you have to do is to emit a `login` event, and you'll get a `channelName` you should subscribe for, and watch for messages and events. Make sure to pass the `master` event, otherwise it should be a monitor, not a client app.
|
||||||
|
|
||||||
##### JavaScript
|
##### JavaScript
|
||||||
|
|
||||||
```js
|
```js
|
||||||
socket.emit('login', 'master', (error, channelName) => {
|
socket.emit('login', 'master', (error, channelName) => {
|
||||||
if (error) { console.log(error); return; }
|
if (error) {
|
||||||
|
console.log(error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
channel = socket.subscribe(channelName);
|
channel = socket.subscribe(channelName);
|
||||||
channel.watch(handleMessages);
|
channel.watch(handleMessages);
|
||||||
socket.on(channelName, handleMessages);
|
socket.on(channelName, handleMessages);
|
||||||
|
@ -80,6 +88,7 @@ function handleMessages(message) {
|
||||||
```
|
```
|
||||||
|
|
||||||
##### Python
|
##### Python
|
||||||
|
|
||||||
```py
|
```py
|
||||||
socket.emitack("login", "master", login)
|
socket.emitack("login", "master", login)
|
||||||
|
|
||||||
|
@ -99,6 +108,7 @@ You could just emit the `login` event, and omit subscribing (and point `5` bello
|
||||||
To send your data to the monitor use `log` or `log-noid` channel. The latter will add the socket id to the message from the server side (useful when the message was sent before the connection was established).
|
To send your data to the monitor use `log` or `log-noid` channel. The latter will add the socket id to the message from the server side (useful when the message was sent before the connection was established).
|
||||||
|
|
||||||
The message object includes the following:
|
The message object includes the following:
|
||||||
|
|
||||||
- `type` - usually should be `ACTION`. If you want to indicate that we're starting a new log (clear all actions emitted before and add `@@INIT`), use `INIT`. In case you have a lifted state similar to one provided by [`redux-devtools-instrument`](https://github.com/zalmoxisus/redux-devtools-instrument), use `STATE`.
|
- `type` - usually should be `ACTION`. If you want to indicate that we're starting a new log (clear all actions emitted before and add `@@INIT`), use `INIT`. In case you have a lifted state similar to one provided by [`redux-devtools-instrument`](https://github.com/zalmoxisus/redux-devtools-instrument), use `STATE`.
|
||||||
- `action` - the action object. It is recommended to lift it in another object, and add `timestamp` to show when the action was fired off: `{ timestamp: Date.now(), action: { type: 'SOME_ACTION' } }`.
|
- `action` - the action object. It is recommended to lift it in another object, and add `timestamp` to show when the action was fired off: `{ timestamp: Date.now(), action: { type: 'SOME_ACTION' } }`.
|
||||||
- `payload` - usually the state or lifted state object.
|
- `payload` - usually the state or lifted state object.
|
||||||
|
@ -107,6 +117,7 @@ The message object includes the following:
|
||||||
- `id` - socket connection id, which should be either `socket.id` or should not provided and use `log-noid` channel.
|
- `id` - socket connection id, which should be either `socket.id` or should not provided and use `log-noid` channel.
|
||||||
|
|
||||||
##### JavaScript
|
##### JavaScript
|
||||||
|
|
||||||
```js
|
```js
|
||||||
const message = {
|
const message = {
|
||||||
type: 'ACTION',
|
type: 'ACTION',
|
||||||
|
@ -120,6 +131,7 @@ socket.emit(socket.id ? 'log' : 'log-noid', message);
|
||||||
```
|
```
|
||||||
|
|
||||||
##### Python
|
##### Python
|
||||||
|
|
||||||
```py
|
```py
|
||||||
class Message:
|
class Message:
|
||||||
def __init__(self, action, state):
|
def __init__(self, action, state):
|
||||||
|
@ -133,6 +145,7 @@ socket.emit(socket.id if "log" else "log-noid", Message(action, state));
|
||||||
#### 5. Listening for monitor events
|
#### 5. Listening for monitor events
|
||||||
|
|
||||||
When a monitor action is emitted, you'll get an event on the subscribed function. The argument object includes a `type` key, which can be:
|
When a monitor action is emitted, you'll get an event on the subscribed function. The argument object includes a `type` key, which can be:
|
||||||
|
|
||||||
- `DISPATCH` - a monitor action dispatched on Redux DevTools monitor, like `{ type: 'DISPATCH', payload: { type: 'JUMP_TO_STATE', 'index': 2 }`. See [`redux-devtools-instrument`](https://github.com/zalmoxisus/redux-devtools-instrument/blob/master/src/instrument.js) for details. Additionally to that API, you'll get also a stringified `state` object when needed. So, for example, for time travelling (`JUMP_TO_STATE`) you can just parse and set the state (see the example). Usually implementing this type of actions would be enough.
|
- `DISPATCH` - a monitor action dispatched on Redux DevTools monitor, like `{ type: 'DISPATCH', payload: { type: 'JUMP_TO_STATE', 'index': 2 }`. See [`redux-devtools-instrument`](https://github.com/zalmoxisus/redux-devtools-instrument/blob/master/src/instrument.js) for details. Additionally to that API, you'll get also a stringified `state` object when needed. So, for example, for time travelling (`JUMP_TO_STATE`) you can just parse and set the state (see the example). Usually implementing this type of actions would be enough.
|
||||||
- `ACTION` - the user requested to dispatch an action remotely like `{ type: 'ACTION', action: '{ type: \'INCREMENT_COUNTER\' }' }`. The `action` can be either a stringified javascript object which should be evalled or a function which arguments should be evalled like [here](https://github.com/zalmoxisus/remotedev-utils/blob/master/src/index.js#L62-L70).
|
- `ACTION` - the user requested to dispatch an action remotely like `{ type: 'ACTION', action: '{ type: \'INCREMENT_COUNTER\' }' }`. The `action` can be either a stringified javascript object which should be evalled or a function which arguments should be evalled like [here](https://github.com/zalmoxisus/remotedev-utils/blob/master/src/index.js#L62-L70).
|
||||||
- `START` - a monitor was opened. You could handle this event in order not to do extra tasks when the app is not monitored.
|
- `START` - a monitor was opened. You could handle this event in order not to do extra tasks when the app is not monitored.
|
||||||
|
@ -141,6 +154,7 @@ When a monitor action is emitted, you'll get an event on the subscribed function
|
||||||
See [`mobx-remotedev`](https://github.com/zalmoxisus/mobx-remotedev/blob/master/src/monitorActions.js) for an example of implementation without [`redux-devtools-instrument`](https://github.com/zalmoxisus/redux-devtools-instrument/blob/master/src/instrument.js).
|
See [`mobx-remotedev`](https://github.com/zalmoxisus/mobx-remotedev/blob/master/src/monitorActions.js) for an example of implementation without [`redux-devtools-instrument`](https://github.com/zalmoxisus/redux-devtools-instrument/blob/master/src/instrument.js).
|
||||||
|
|
||||||
##### JavaScript
|
##### JavaScript
|
||||||
|
|
||||||
```js
|
```js
|
||||||
function handleMessages(message) {
|
function handleMessages(message) {
|
||||||
if (message.type === 'DISPATCH' && message.payload.type === 'JUMP_TO_STATE') {
|
if (message.type === 'DISPATCH' && message.payload.type === 'JUMP_TO_STATE') {
|
||||||
|
@ -150,6 +164,7 @@ function handleMessages(message) {
|
||||||
```
|
```
|
||||||
|
|
||||||
##### Python
|
##### Python
|
||||||
|
|
||||||
```py
|
```py
|
||||||
def handleMessages(key, message):
|
def handleMessages(key, message):
|
||||||
if message.type === "DISPATCH" and message.payload.type === "JUMP_TO_STATE":
|
if message.type === "DISPATCH" and message.payload.type === "JUMP_TO_STATE":
|
||||||
|
|
|
@ -46,10 +46,12 @@ const DevTools = createDevTools(
|
||||||
// Consult their repositories to learn about those props.
|
// Consult their repositories to learn about those props.
|
||||||
// Here, we put LogMonitor inside a DockMonitor.
|
// Here, we put LogMonitor inside a DockMonitor.
|
||||||
// Note: DockMonitor is visible by default.
|
// Note: DockMonitor is visible by default.
|
||||||
<DockMonitor toggleVisibilityKey='ctrl-h'
|
<DockMonitor
|
||||||
changePositionKey='ctrl-q'
|
toggleVisibilityKey="ctrl-h"
|
||||||
defaultIsVisible={true}>
|
changePositionKey="ctrl-q"
|
||||||
<LogMonitor theme='tomorrow' />
|
defaultIsVisible={true}
|
||||||
|
>
|
||||||
|
<LogMonitor theme="tomorrow" />
|
||||||
</DockMonitor>
|
</DockMonitor>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -60,9 +62,7 @@ Note that you can use `LogMonitor` directly without wrapping it in `DockMonitor`
|
||||||
|
|
||||||
```js
|
```js
|
||||||
// If you'd rather not use docking UI, use <LogMonitor> directly
|
// If you'd rather not use docking UI, use <LogMonitor> directly
|
||||||
const DevTools = createDevTools(
|
const DevTools = createDevTools(<LogMonitor theme="solarized" />);
|
||||||
<LogMonitor theme='solarized' />
|
|
||||||
);
|
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Use `DevTools.instrument()` Store Enhancer
|
#### Use `DevTools.instrument()` Store Enhancer
|
||||||
|
@ -75,7 +75,7 @@ The easiest way to apply several store enhancers in a row is to use the [`compos
|
||||||
|
|
||||||
You can add additional options to it: `DevTools.instrument({ maxAge: 50, shouldCatchErrors: true })`. See [`redux-devtools-instrument`'s API](https://github.com/reduxjs/redux-devtools/tree/master/packages/redux-devtools-instrument#api) for more details.
|
You can add additional options to it: `DevTools.instrument({ maxAge: 50, shouldCatchErrors: true })`. See [`redux-devtools-instrument`'s API](https://github.com/reduxjs/redux-devtools/tree/master/packages/redux-devtools-instrument#api) for more details.
|
||||||
|
|
||||||
It’s important that you should add `DevTools.instrument()` *after* `applyMiddleware` in your `compose()` function arguments. This is because `applyMiddleware` is potentially asynchronous, but `DevTools.instrument()` expects all actions to be plain objects rather than actions interpreted by asynchronous middleware such as [redux-promise](https://github.com/acdlite/redux-promise) or [redux-thunk](https://github.com/gaearon/redux-thunk). So make sure `applyMiddleware()` goes first in the `compose()` call, and `DevTools.instrument()` goes after it.
|
It’s important that you should add `DevTools.instrument()` _after_ `applyMiddleware` in your `compose()` function arguments. This is because `applyMiddleware` is potentially asynchronous, but `DevTools.instrument()` expects all actions to be plain objects rather than actions interpreted by asynchronous middleware such as [redux-promise](https://github.com/acdlite/redux-promise) or [redux-thunk](https://github.com/gaearon/redux-thunk). So make sure `applyMiddleware()` goes first in the `compose()` call, and `DevTools.instrument()` goes after it.
|
||||||
|
|
||||||
##### `store/configureStore.js`
|
##### `store/configureStore.js`
|
||||||
|
|
||||||
|
@ -99,7 +99,9 @@ export default function configureStore(initialState) {
|
||||||
// Hot reload reducers (requires Webpack or Browserify HMR to be enabled)
|
// Hot reload reducers (requires Webpack or Browserify HMR to be enabled)
|
||||||
if (module.hot) {
|
if (module.hot) {
|
||||||
module.hot.accept('../reducers', () =>
|
module.hot.accept('../reducers', () =>
|
||||||
store.replaceReducer(require('../reducers')/*.default if you use Babel 6+ */)
|
store.replaceReducer(
|
||||||
|
require('../reducers') /*.default if you use Babel 6+ */
|
||||||
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -126,7 +128,7 @@ function getDebugSessionKey() {
|
||||||
// You can write custom logic here!
|
// You can write custom logic here!
|
||||||
// By default we try to read the key from ?debug_session=<key> in the address bar
|
// By default we try to read the key from ?debug_session=<key> in the address bar
|
||||||
const matches = window.location.href.match(/[?&]debug_session=([^&#]+)\b/);
|
const matches = window.location.href.match(/[?&]debug_session=([^&#]+)\b/);
|
||||||
return (matches && matches.length > 0)? matches[1] : null;
|
return matches && matches.length > 0 ? matches[1] : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function configureStore(initialState) {
|
export default function configureStore(initialState) {
|
||||||
|
@ -181,7 +183,7 @@ export default function configureStore(initialState) {
|
||||||
// Note: only Redux >= 3.1.0 supports passing enhancer as third argument.
|
// Note: only Redux >= 3.1.0 supports passing enhancer as third argument.
|
||||||
// See https://github.com/rackt/redux/releases/tag/v3.1.0
|
// See https://github.com/rackt/redux/releases/tag/v3.1.0
|
||||||
return createStore(rootReducer, initialState, enhancer);
|
return createStore(rootReducer, initialState, enhancer);
|
||||||
};
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
##### `store/configureStore.dev.js`
|
##### `store/configureStore.dev.js`
|
||||||
|
@ -205,7 +207,7 @@ function getDebugSessionKey() {
|
||||||
// You can write custom logic here!
|
// You can write custom logic here!
|
||||||
// By default we try to read the key from ?debug_session=<key> in the address bar
|
// By default we try to read the key from ?debug_session=<key> in the address bar
|
||||||
const matches = window.location.href.match(/[?&]debug_session=([^&]+)\b/);
|
const matches = window.location.href.match(/[?&]debug_session=([^&]+)\b/);
|
||||||
return (matches && matches.length > 0)? matches[1] : null;
|
return matches && matches.length > 0 ? matches[1] : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function configureStore(initialState) {
|
export default function configureStore(initialState) {
|
||||||
|
@ -216,7 +218,9 @@ export default function configureStore(initialState) {
|
||||||
// Hot reload reducers (requires Webpack or Browserify HMR to be enabled)
|
// Hot reload reducers (requires Webpack or Browserify HMR to be enabled)
|
||||||
if (module.hot) {
|
if (module.hot) {
|
||||||
module.hot.accept('../reducers', () =>
|
module.hot.accept('../reducers', () =>
|
||||||
store.replaceReducer(require('../reducers')/*.default if you use Babel 6+ */)
|
store.replaceReducer(
|
||||||
|
require('../reducers') /*.default if you use Babel 6+ */
|
||||||
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -346,7 +350,11 @@ import { render } from 'react-dom';
|
||||||
import DevTools from './containers/DevTools';
|
import DevTools from './containers/DevTools';
|
||||||
|
|
||||||
export default function showDevTools(store) {
|
export default function showDevTools(store) {
|
||||||
const popup = window.open(null, 'Redux DevTools', 'menubar=no,location=no,resizable=yes,scrollbars=no,status=no');
|
const popup = window.open(
|
||||||
|
null,
|
||||||
|
'Redux DevTools',
|
||||||
|
'menubar=no,location=no,resizable=yes,scrollbars=no,status=no'
|
||||||
|
);
|
||||||
// Reload in case it already exists
|
// Reload in case it already exists
|
||||||
popup.location.reload();
|
popup.location.reload();
|
||||||
|
|
||||||
|
@ -366,11 +374,11 @@ Note that there are no useful props you can pass to the `DevTools` component oth
|
||||||
|
|
||||||
### Gotchas
|
### Gotchas
|
||||||
|
|
||||||
* **Your reducers have to be pure and free of side effects to work correctly with DevTools.** For example, even generating a random ID in reducer makes it impure and non-deterministic. Instead, do this in action creators.
|
- **Your reducers have to be pure and free of side effects to work correctly with DevTools.** For example, even generating a random ID in reducer makes it impure and non-deterministic. Instead, do this in action creators.
|
||||||
|
|
||||||
* **Make sure to only apply `DevTools.instrument()` and render `<DevTools>` in development!** In production, this will be terribly slow because actions just accumulate forever. As described above, you need to use conditional `require`s and use `DefinePlugin` (Webpack) or `loose-envify` (Browserify) together with Uglify to remove the dead code. Here is [an example](https://github.com/erikras/react-redux-universal-hot-example/) that adds Redux DevTools handling the production case correctly.
|
- **Make sure to only apply `DevTools.instrument()` and render `<DevTools>` in development!** In production, this will be terribly slow because actions just accumulate forever. As described above, you need to use conditional `require`s and use `DefinePlugin` (Webpack) or `loose-envify` (Browserify) together with Uglify to remove the dead code. Here is [an example](https://github.com/erikras/react-redux-universal-hot-example/) that adds Redux DevTools handling the production case correctly.
|
||||||
|
|
||||||
* **It is important that `DevTools.instrument()` store enhancer should be added to your middleware stack *after* `applyMiddleware` in the `compose`d functions, as `applyMiddleware` is potentially asynchronous.** Otherwise, DevTools won’t see the raw actions emitted by asynchronous middleware such as [redux-promise](https://github.com/acdlite/redux-promise) or [redux-thunk](https://github.com/gaearon/redux-thunk).
|
- **It is important that `DevTools.instrument()` store enhancer should be added to your middleware stack _after_ `applyMiddleware` in the `compose`d functions, as `applyMiddleware` is potentially asynchronous.** Otherwise, DevTools won’t see the raw actions emitted by asynchronous middleware such as [redux-promise](https://github.com/acdlite/redux-promise) or [redux-thunk](https://github.com/gaearon/redux-thunk).
|
||||||
|
|
||||||
### What Next?
|
### What Next?
|
||||||
|
|
||||||
|
|
|
@ -8,9 +8,5 @@
|
||||||
"allowBranch": "master"
|
"allowBranch": "master"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"ignoreChanges": [
|
"ignoreChanges": ["**/test/**", "**/examples/**", "**/*.md"]
|
||||||
"**/test/**",
|
|
||||||
"**/examples/**",
|
|
||||||
"**/*.md"
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
|
|
17
package.json
17
package.json
|
@ -9,7 +9,8 @@
|
||||||
"eslint-plugin-react": "7.12.3",
|
"eslint-plugin-react": "7.12.3",
|
||||||
"jest": "^23.6.0",
|
"jest": "^23.6.0",
|
||||||
"lerna": "3.9.0",
|
"lerna": "3.9.0",
|
||||||
"pre-commit": "^1.1.3"
|
"lint-staged": "^8.1.0",
|
||||||
|
"prettier": "^1.15.3"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"lerna": "lerna",
|
"lerna": "lerna",
|
||||||
|
@ -21,13 +22,23 @@
|
||||||
"lint": "eslint '**/*.{js,jsx}' --cache",
|
"lint": "eslint '**/*.{js,jsx}' --cache",
|
||||||
"lint:fix": "eslint '**/*.{js,jsx}' --fix --cache",
|
"lint:fix": "eslint '**/*.{js,jsx}' --fix --cache",
|
||||||
"lint:all": "eslint '**/*.{js,jsx}'",
|
"lint:all": "eslint '**/*.{js,jsx}'",
|
||||||
|
"prettify": "prettier '**/*.{js,jsx,json,css,html,md}' --ignore-path .eslintignore --single-quote --write",
|
||||||
|
"precommit": "lint-staged",
|
||||||
"test": "jest --onlyChanged",
|
"test": "jest --onlyChanged",
|
||||||
"test:all": "jest"
|
"test:all": "jest"
|
||||||
},
|
},
|
||||||
"workspaces": [
|
"workspaces": [
|
||||||
"packages/*"
|
"packages/*"
|
||||||
],
|
],
|
||||||
"pre-commit": [
|
"lint-staged": {
|
||||||
"lint"
|
"*.{js,jsx}": [
|
||||||
|
"prettier --single-quote --write",
|
||||||
|
"yarn lint:fix",
|
||||||
|
"git add"
|
||||||
|
],
|
||||||
|
"*.{json,css,html,md}": [
|
||||||
|
"prettier --single-quote --write",
|
||||||
|
"git add"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
d3tooltip
|
# d3tooltip
|
||||||
=========================
|
|
||||||
|
|
||||||
This tooltip aims for a minimal yet highly configurable API. It has a long way to go, but the essentials are there.
|
This tooltip aims for a minimal yet highly configurable API. It has a long way to go, but the essentials are there.
|
||||||
It was created by [@romseguy](https://github.com/romseguy) and merged from [`romseguy/d3tooltip`](https://github.com/romseguy/d3tooltip).
|
It was created by [@romseguy](https://github.com/romseguy) and merged from [`romseguy/d3tooltip`](https://github.com/romseguy/d3tooltip).
|
||||||
|
@ -47,9 +46,9 @@ vis.selectAll('circle').data(someData).enter()
|
||||||
|
|
||||||
## API
|
## API
|
||||||
|
|
||||||
Option | Type | Default | Description
|
| Option | Type | Default | Description |
|
||||||
--------------------------|--------------|---------------------|--------------------------------------------------------------
|
| -------- | ----------- | ------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||||
`root` | DOM.Element | `body` | The tooltip will be added as a child of that element. You can also use a D3 [selection](https://github.com/mbostock/d3/wiki/Selections#d3_select)
|
| `root` | DOM.Element | `body` | The tooltip will be added as a child of that element. You can also use a D3 [selection](https://github.com/mbostock/d3/wiki/Selections#d3_select) |
|
||||||
`left` | Number | `undefined` | Sets the tooltip `x` absolute position instead of the mouse `x` position, relative to the `root` element
|
| `left` | Number | `undefined` | Sets the tooltip `x` absolute position instead of the mouse `x` position, relative to the `root` element |
|
||||||
`top` | Number | `undefined` | Sets the tooltip `y` absolute position instead of the mouse `y` position, relative to the `root` element
|
| `top` | Number | `undefined` | Sets the tooltip `y` absolute position instead of the mouse `y` position, relative to the `root` element |
|
||||||
`offset` | Object | `{left: 0, top: 0}` | Sets the distance, starting from the cursor position, until the tooltip is rendered. **Warning**: only applicable if you don't provide a `left` or `top` option
|
| `offset` | Object | `{left: 0, top: 0}` | Sets the distance, starting from the cursor position, until the tooltip is rendered. **Warning**: only applicable if you don't provide a `left` or `top` option |
|
||||||
|
|
18
packages/d3tooltip/src/index.js
vendored
18
packages/d3tooltip/src/index.js
vendored
|
@ -10,14 +10,9 @@ const defaultOptions = {
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function tooltip(d3, className = 'tooltip', options = {}) {
|
export default function tooltip(d3, className = 'tooltip', options = {}) {
|
||||||
const {
|
const { left, top, offset, root } = { ...defaultOptions, ...options };
|
||||||
left,
|
|
||||||
top,
|
|
||||||
offset,
|
|
||||||
root
|
|
||||||
} = {...defaultOptions, ...options};
|
|
||||||
|
|
||||||
let attrs = {'class': className};
|
let attrs = { class: className };
|
||||||
let text = () => '';
|
let text = () => '';
|
||||||
let styles = {};
|
let styles = {};
|
||||||
|
|
||||||
|
@ -33,7 +28,8 @@ export default function tooltip(d3, className = 'tooltip', options = {}) {
|
||||||
|
|
||||||
anchor.selectAll(`div.${className}`).remove();
|
anchor.selectAll(`div.${className}`).remove();
|
||||||
|
|
||||||
el = anchor.append('div')
|
el = anchor
|
||||||
|
.append('div')
|
||||||
.attr(prependClass(className)(attrs))
|
.attr(prependClass(className)(attrs))
|
||||||
.style({
|
.style({
|
||||||
position: 'absolute',
|
position: 'absolute',
|
||||||
|
@ -49,12 +45,10 @@ export default function tooltip(d3, className = 'tooltip', options = {}) {
|
||||||
let [mouseX, mouseY] = d3.mouse(rootNode);
|
let [mouseX, mouseY] = d3.mouse(rootNode);
|
||||||
let [x, y] = [left || mouseX + offset.left, top || mouseY - offset.top];
|
let [x, y] = [left || mouseX + offset.left, top || mouseY - offset.top];
|
||||||
|
|
||||||
el
|
el.style({
|
||||||
.style({
|
|
||||||
left: x + 'px',
|
left: x + 'px',
|
||||||
top: y + 'px'
|
top: y + 'px'
|
||||||
})
|
}).html(() => text(node));
|
||||||
.html(() => text(node));
|
|
||||||
},
|
},
|
||||||
|
|
||||||
'mouseout.tip': () => el.remove()
|
'mouseout.tip': () => el.remove()
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
|
|
||||||
module.exports = (env = {}) => (
|
module.exports = (env = {}) => ({
|
||||||
{
|
|
||||||
mode: 'production',
|
mode: 'production',
|
||||||
entry: {
|
entry: {
|
||||||
app: ['./src/index.js']
|
app: ['./src/index.js']
|
||||||
|
@ -27,5 +26,4 @@ module.exports = (env = {}) => (
|
||||||
performance: {
|
performance: {
|
||||||
hints: false
|
hints: false
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
);
|
|
||||||
|
|
|
@ -7,5 +7,6 @@ const parse = require('git-url-parse');
|
||||||
var ghUrl = process.argv[2];
|
var ghUrl = process.argv[2];
|
||||||
const parsedUrl = parse(ghUrl);
|
const parsedUrl = parse(ghUrl);
|
||||||
|
|
||||||
const ghPagesUrl = 'https://' + parsedUrl.owner + '.github.io/' + parsedUrl.name;
|
const ghPagesUrl =
|
||||||
|
'https://' + parsedUrl.owner + '.github.io/' + parsedUrl.name;
|
||||||
console.log(ghPagesUrl);
|
console.log(ghPagesUrl);
|
||||||
|
|
|
@ -14,7 +14,7 @@ var exposedProperties = ['window', 'navigator', 'document'];
|
||||||
|
|
||||||
global.document = jsdom('');
|
global.document = jsdom('');
|
||||||
global.window = document.defaultView;
|
global.window = document.defaultView;
|
||||||
Object.keys(document.defaultView).forEach((property) => {
|
Object.keys(document.defaultView).forEach(property => {
|
||||||
if (typeof global[property] === 'undefined') {
|
if (typeof global[property] === 'undefined') {
|
||||||
exposedProperties.push(property);
|
exposedProperties.push(property);
|
||||||
global[property] = document.defaultView[property];
|
global[property] = document.defaultView[property];
|
||||||
|
@ -27,7 +27,7 @@ global.navigator = {
|
||||||
|
|
||||||
process.on('unhandledRejection', function(error) {
|
process.on('unhandledRejection', function(error) {
|
||||||
console.error('Unhandled Promise Rejection:');
|
console.error('Unhandled Promise Rejection:');
|
||||||
console.error(error && error.stack || error);
|
console.error((error && error.stack) || error);
|
||||||
});
|
});
|
||||||
|
|
||||||
require('./user/pretest.js');
|
require('./user/pretest.js');
|
||||||
|
|
|
@ -5,7 +5,8 @@ import { withKnobs } from '@storybook/addon-knobs';
|
||||||
import { withTheme } from './themeAddon/theme';
|
import { withTheme } from './themeAddon/theme';
|
||||||
import '../src/presets.js';
|
import '../src/presets.js';
|
||||||
|
|
||||||
addDecorator(withOptions({
|
addDecorator(
|
||||||
|
withOptions({
|
||||||
name: 'DevUI',
|
name: 'DevUI',
|
||||||
url: 'https://github.com/reduxjs/redux-devtools/tree/master/packages/devui',
|
url: 'https://github.com/reduxjs/redux-devtools/tree/master/packages/devui',
|
||||||
goFullScreen: false,
|
goFullScreen: false,
|
||||||
|
@ -13,7 +14,8 @@ addDecorator(withOptions({
|
||||||
showAddonPanel: true,
|
showAddonPanel: true,
|
||||||
showSearchBox: false,
|
showSearchBox: false,
|
||||||
addonPanelInRight: true
|
addonPanelInRight: true
|
||||||
}));
|
})
|
||||||
|
);
|
||||||
|
|
||||||
addDecorator(withTheme);
|
addDecorator(withTheme);
|
||||||
addDecorator(withKnobs);
|
addDecorator(withKnobs);
|
||||||
|
|
|
@ -11,10 +11,11 @@
|
||||||
min-height: 400px;
|
min-height: 400px;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
font-family: "Helvetica Neue", "Lucida Grande", sans-serif;
|
font-family: 'Helvetica Neue', 'Lucida Grande', sans-serif;
|
||||||
font-size: 11px;
|
font-size: 11px;
|
||||||
}
|
}
|
||||||
#root, #root > div {
|
#root,
|
||||||
|
#root > div {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
#root > div > div {
|
#root > div > div {
|
||||||
|
|
|
@ -7,10 +7,7 @@ addons.register(ADDON_ID, api => {
|
||||||
const channel = addons.getChannel();
|
const channel = addons.getChannel();
|
||||||
addons.addPanel(PANEL_ID, {
|
addons.addPanel(PANEL_ID, {
|
||||||
title: 'Theme',
|
title: 'Theme',
|
||||||
render: ({ active }) => (
|
render: ({ active }) =>
|
||||||
active ?
|
active ? <Panel channel={channel} api={api} /> : null
|
||||||
<Panel channel={channel} api={api} />
|
|
||||||
: null
|
|
||||||
)
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -4,7 +4,8 @@
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
src: local('Source Code Pro'), local('SourceCodePro-Regular'),
|
src: local('Source Code Pro'), local('SourceCodePro-Regular'),
|
||||||
url('./source-code-pro-v6-latin/source-code-pro-v6-latin-regular.woff2') format('woff2');
|
url('./source-code-pro-v6-latin/source-code-pro-v6-latin-regular.woff2')
|
||||||
|
format('woff2');
|
||||||
}
|
}
|
||||||
/* source-sans-pro-regular - latin */
|
/* source-sans-pro-regular - latin */
|
||||||
@font-face {
|
@font-face {
|
||||||
|
@ -12,7 +13,8 @@
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
src: local('Source Sans Pro'), local('SourceSansPro-Regular'),
|
src: local('Source Sans Pro'), local('SourceSansPro-Regular'),
|
||||||
url('./source-sans-pro-v9-latin/source-sans-pro-v9-latin-regular.woff2') format('woff2');
|
url('./source-sans-pro-v9-latin/source-sans-pro-v9-latin-regular.woff2')
|
||||||
|
format('woff2');
|
||||||
}
|
}
|
||||||
/* source-sans-pro-600 - latin */
|
/* source-sans-pro-600 - latin */
|
||||||
@font-face {
|
@font-face {
|
||||||
|
@ -20,7 +22,8 @@
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
src: local('Source Sans Pro Semibold'), local('SourceSansPro-Semibold'),
|
src: local('Source Sans Pro Semibold'), local('SourceSansPro-Semibold'),
|
||||||
url('./source-sans-pro-v9-latin/source-sans-pro-v9-latin-600.woff2') format('woff2');
|
url('./source-sans-pro-v9-latin/source-sans-pro-v9-latin-600.woff2')
|
||||||
|
format('woff2');
|
||||||
}
|
}
|
||||||
|
|
||||||
/* roboto-regular - latin */
|
/* roboto-regular - latin */
|
||||||
|
@ -37,7 +40,8 @@
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
src: local('Roboto Mono'), local('RobotoMono-Regular'),
|
src: local('Roboto Mono'), local('RobotoMono-Regular'),
|
||||||
url('./roboto-mono-v4-latin/roboto-mono-v4-latin-regular.woff2') format('woff2');
|
url('./roboto-mono-v4-latin/roboto-mono-v4-latin-regular.woff2')
|
||||||
|
format('woff2');
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Generated with https://google-webfonts-helper.herokuapp.com */
|
/* Generated with https://google-webfonts-helper.herokuapp.com */
|
||||||
|
|
|
@ -1,15 +1,16 @@
|
||||||
{
|
{
|
||||||
"name": "devui",
|
"name": "devui",
|
||||||
"version": "1.0.0-3",
|
"version": "1.0.0-3",
|
||||||
"description":
|
"description": "Reusable React components for building DevTools monitors and apps.",
|
||||||
"Reusable React components for building DevTools monitors and apps.",
|
"files": [
|
||||||
"files": ["lib", "fonts"],
|
"lib",
|
||||||
|
"fonts"
|
||||||
|
],
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/reduxjs/redux-devtools.git"
|
"url": "https://github.com/reduxjs/redux-devtools.git"
|
||||||
},
|
},
|
||||||
"author":
|
"author": "Mihail Diordiev <zalmoxisus@gmail.com> (https://github.com/zalmoxisus)",
|
||||||
"Mihail Diordiev <zalmoxisus@gmail.com> (https://github.com/zalmoxisus)",
|
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "npm run storybook",
|
"start": "npm run storybook",
|
||||||
|
|
|
@ -10,13 +10,15 @@ const CommonWrapper = createStyledComponent(commonStyle);
|
||||||
|
|
||||||
export default class Button extends Component {
|
export default class Button extends Component {
|
||||||
shouldComponentUpdate(nextProps) {
|
shouldComponentUpdate(nextProps) {
|
||||||
return nextProps.children !== this.props.children ||
|
return (
|
||||||
|
nextProps.children !== this.props.children ||
|
||||||
nextProps.disabled !== this.props.disabled ||
|
nextProps.disabled !== this.props.disabled ||
|
||||||
nextProps.mark !== this.props.mark ||
|
nextProps.mark !== this.props.mark ||
|
||||||
nextProps.size !== this.props.size ||
|
nextProps.size !== this.props.size ||
|
||||||
nextProps.primary !== this.props.primary ||
|
nextProps.primary !== this.props.primary ||
|
||||||
nextProps.tooltipPosition !== this.props.tooltipPosition ||
|
nextProps.tooltipPosition !== this.props.tooltipPosition ||
|
||||||
nextProps.title !== this.props.title;
|
nextProps.title !== this.props.title
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
onMouseUp = e => {
|
onMouseUp = e => {
|
||||||
|
@ -56,15 +58,32 @@ export default class Button extends Component {
|
||||||
Button.propTypes = {
|
Button.propTypes = {
|
||||||
children: PropTypes.any.isRequired,
|
children: PropTypes.any.isRequired,
|
||||||
title: PropTypes.string,
|
title: PropTypes.string,
|
||||||
tooltipPosition: PropTypes.oneOf(['top', 'bottom', 'left', 'right',
|
tooltipPosition: PropTypes.oneOf([
|
||||||
'bottom-left', 'bottom-right', 'top-left', 'top-right']),
|
'top',
|
||||||
|
'bottom',
|
||||||
|
'left',
|
||||||
|
'right',
|
||||||
|
'bottom-left',
|
||||||
|
'bottom-right',
|
||||||
|
'top-left',
|
||||||
|
'top-right'
|
||||||
|
]),
|
||||||
onClick: PropTypes.func,
|
onClick: PropTypes.func,
|
||||||
type: PropTypes.string,
|
type: PropTypes.string,
|
||||||
disabled: PropTypes.bool,
|
disabled: PropTypes.bool,
|
||||||
primary: PropTypes.bool,
|
primary: PropTypes.bool,
|
||||||
size: PropTypes.oneOf(['big', 'normal', 'small']),
|
size: PropTypes.oneOf(['big', 'normal', 'small']),
|
||||||
mark: PropTypes.oneOf([false, 'base08', 'base09', 'base0A', 'base0B',
|
mark: PropTypes.oneOf([
|
||||||
'base0C', 'base0D', 'base0E', 'base0F']),
|
false,
|
||||||
|
'base08',
|
||||||
|
'base09',
|
||||||
|
'base0A',
|
||||||
|
'base0B',
|
||||||
|
'base0C',
|
||||||
|
'base0D',
|
||||||
|
'base0E',
|
||||||
|
'base0F'
|
||||||
|
]),
|
||||||
theme: PropTypes.object
|
theme: PropTypes.object
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -16,16 +16,20 @@ export const Container = styled.div`
|
||||||
|
|
||||||
storiesOf('Button', module)
|
storiesOf('Button', module)
|
||||||
.addDecorator(withKnobs)
|
.addDecorator(withKnobs)
|
||||||
.add(
|
.add('default', () => (
|
||||||
'default',
|
|
||||||
() => (
|
|
||||||
<Container>
|
<Container>
|
||||||
<Button
|
<Button
|
||||||
title={text('Title', 'Hello Tooltip! \\a And from new line hello!')}
|
title={text('Title', 'Hello Tooltip! \\a And from new line hello!')}
|
||||||
tooltipPosition={
|
tooltipPosition={select('tooltipPosition', [
|
||||||
select('tooltipPosition', ['top', 'bottom', 'left', 'right',
|
'top',
|
||||||
'bottom-left', 'bottom-right', 'top-left', 'top-right'])
|
'bottom',
|
||||||
}
|
'left',
|
||||||
|
'right',
|
||||||
|
'bottom-left',
|
||||||
|
'bottom-right',
|
||||||
|
'top-left',
|
||||||
|
'top-right'
|
||||||
|
])}
|
||||||
primary={boolean('primary', true)}
|
primary={boolean('primary', true)}
|
||||||
size={select('size', ['big', 'normal', 'small'], 'normal')}
|
size={select('size', ['big', 'normal', 'small'], 'normal')}
|
||||||
disabled={boolean('Disabled', false)}
|
disabled={boolean('Disabled', false)}
|
||||||
|
@ -34,20 +38,35 @@ storiesOf('Button', module)
|
||||||
{text('Label', 'Hello Button')}
|
{text('Label', 'Hello Button')}
|
||||||
</Button>
|
</Button>
|
||||||
</Container>
|
</Container>
|
||||||
)
|
))
|
||||||
)
|
.add('mark', () => (
|
||||||
.add(
|
|
||||||
'mark',
|
|
||||||
() => (
|
|
||||||
<Container>
|
<Container>
|
||||||
<Button
|
<Button
|
||||||
mark={select('mark', ['base08', 'base09', 'base0A', 'base0B',
|
mark={select(
|
||||||
'base0C', 'base0D', 'base0E', 'base0F'], 'base08')}
|
'mark',
|
||||||
|
[
|
||||||
|
'base08',
|
||||||
|
'base09',
|
||||||
|
'base0A',
|
||||||
|
'base0B',
|
||||||
|
'base0C',
|
||||||
|
'base0D',
|
||||||
|
'base0E',
|
||||||
|
'base0F'
|
||||||
|
],
|
||||||
|
'base08'
|
||||||
|
)}
|
||||||
title={text('Title', 'Hello Tooltip')}
|
title={text('Title', 'Hello Tooltip')}
|
||||||
tooltipPosition={
|
tooltipPosition={select('tooltipPosition', [
|
||||||
select('tooltipPosition', ['top', 'bottom', 'left', 'right',
|
'top',
|
||||||
'bottom-left', 'bottom-right', 'top-left', 'top-right'])
|
'bottom',
|
||||||
}
|
'left',
|
||||||
|
'right',
|
||||||
|
'bottom-left',
|
||||||
|
'bottom-right',
|
||||||
|
'top-left',
|
||||||
|
'top-right'
|
||||||
|
])}
|
||||||
size={select('size', ['big', 'normal', 'small'], 'normal')}
|
size={select('size', ['big', 'normal', 'small'], 'normal')}
|
||||||
disabled={boolean('Disabled', false)}
|
disabled={boolean('Disabled', false)}
|
||||||
onClick={action('button clicked')}
|
onClick={action('button clicked')}
|
||||||
|
@ -55,5 +74,4 @@ storiesOf('Button', module)
|
||||||
<MdFiberManualRecord />
|
<MdFiberManualRecord />
|
||||||
</Button>
|
</Button>
|
||||||
</Container>
|
</Container>
|
||||||
)
|
));
|
||||||
);
|
|
||||||
|
|
|
@ -2,7 +2,7 @@ import { css } from 'styled-components';
|
||||||
import { fadeIn } from '../../utils/animations';
|
import { fadeIn } from '../../utils/animations';
|
||||||
import colorEffect from '../../utils/color';
|
import colorEffect from '../../utils/color';
|
||||||
|
|
||||||
const both = (tooltipPosition) => {
|
const both = tooltipPosition => {
|
||||||
switch (tooltipPosition) {
|
switch (tooltipPosition) {
|
||||||
case 'bottom':
|
case 'bottom':
|
||||||
return `
|
return `
|
||||||
|
@ -46,7 +46,7 @@ const both = (tooltipPosition) => {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const before = (tooltipPosition) => {
|
const before = tooltipPosition => {
|
||||||
switch (tooltipPosition) {
|
switch (tooltipPosition) {
|
||||||
case 'bottom-left':
|
case 'bottom-left':
|
||||||
return `
|
return `
|
||||||
|
@ -110,12 +110,13 @@ const after = (tooltipPosition, color) => {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const getDirection = (tooltipPosition) => {
|
const getDirection = tooltipPosition => {
|
||||||
return (tooltipPosition.indexOf('-') > 0) ?
|
return tooltipPosition.indexOf('-') > 0
|
||||||
tooltipPosition.substring(0, tooltipPosition.indexOf('-')) : tooltipPosition;
|
? tooltipPosition.substring(0, tooltipPosition.indexOf('-'))
|
||||||
|
: tooltipPosition;
|
||||||
};
|
};
|
||||||
|
|
||||||
const getSize = (size) => {
|
const getSize = size => {
|
||||||
switch (size) {
|
switch (size) {
|
||||||
case 'big':
|
case 'big':
|
||||||
return 'min-height: 34px; padding: 2px 12px;';
|
return 'min-height: 34px; padding: 2px 12px;';
|
||||||
|
@ -144,8 +145,13 @@ export const commonStyle = ({ theme, mark, size }) => css`
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
${mark && `
|
${mark &&
|
||||||
background-color: ${colorEffect(theme[mark], 'fade', theme.light ? 0.92 : 0.82)};
|
`
|
||||||
|
background-color: ${colorEffect(
|
||||||
|
theme[mark],
|
||||||
|
'fade',
|
||||||
|
theme.light ? 0.92 : 0.82
|
||||||
|
)};
|
||||||
|
|
||||||
> svg {
|
> svg {
|
||||||
color: ${theme[mark]};
|
color: ${theme[mark]};
|
||||||
|
@ -158,7 +164,13 @@ export const commonStyle = ({ theme, mark, size }) => css`
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export const tooltipStyle = ({ theme, tooltipTitle, tooltipPosition, mark, size }) => css`
|
export const tooltipStyle = ({
|
||||||
|
theme,
|
||||||
|
tooltipTitle,
|
||||||
|
tooltipPosition,
|
||||||
|
mark,
|
||||||
|
size
|
||||||
|
}) => css`
|
||||||
${commonStyle({ theme, mark, size })}
|
${commonStyle({ theme, mark, size })}
|
||||||
|
|
||||||
&:before {
|
&:before {
|
||||||
|
@ -170,7 +182,9 @@ export const tooltipStyle = ({ theme, tooltipTitle, tooltipPosition, mark, size
|
||||||
border-radius: 3px;
|
border-radius: 3px;
|
||||||
background: ${theme.base01};
|
background: ${theme.base01};
|
||||||
border: 1px solid ${theme.base02};
|
border: 1px solid ${theme.base02};
|
||||||
box-shadow: 1px 1px 2px -1px ${theme.base02}, 1px 1px 2px 0px ${theme.base02};
|
box-shadow: 1px 1px 2px -1px ${theme.base02}, 1px 1px 2px 0px ${
|
||||||
|
theme.base02
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
&:after,
|
&:after,
|
||||||
|
@ -194,7 +208,8 @@ export const tooltipStyle = ({ theme, tooltipTitle, tooltipPosition, mark, size
|
||||||
${theme.type === 'material' ? `animation: ${fadeIn} 500ms;` : ''}
|
${theme.type === 'material' ? `animation: ${fadeIn} 500ms;` : ''}
|
||||||
}
|
}
|
||||||
|
|
||||||
${theme.type !== 'material' && `
|
${theme.type !== 'material' &&
|
||||||
|
`
|
||||||
&:after {
|
&:after {
|
||||||
content: "";
|
content: "";
|
||||||
border-style: solid;
|
border-style: solid;
|
||||||
|
|
|
@ -11,21 +11,30 @@ export const style = ({ theme, primary, disabled }) => css`
|
||||||
margin: auto 0;
|
margin: auto 0;
|
||||||
border: 1px solid ${theme.base02};
|
border: 1px solid ${theme.base02};
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
${primary ? `
|
${
|
||||||
|
primary
|
||||||
|
? `
|
||||||
background-color: ${theme.base05};
|
background-color: ${theme.base05};
|
||||||
color: ${theme.base00};
|
color: ${theme.base00};
|
||||||
` : `
|
`
|
||||||
|
: `
|
||||||
background-color: ${theme.base01};
|
background-color: ${theme.base01};
|
||||||
color: ${theme.base05};
|
color: ${theme.base05};
|
||||||
`}
|
`
|
||||||
${disabled ? `
|
}
|
||||||
|
${
|
||||||
|
disabled
|
||||||
|
? `
|
||||||
cursor: not-allowed;
|
cursor: not-allowed;
|
||||||
opacity: 0.6;
|
opacity: 0.6;
|
||||||
` : `
|
`
|
||||||
|
: `
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
`}
|
`
|
||||||
|
}
|
||||||
|
|
||||||
${!disabled && `
|
${!disabled &&
|
||||||
|
`
|
||||||
&:hover,
|
&:hover,
|
||||||
&:focus {
|
&:focus {
|
||||||
background-color: ${primary ? theme.base07 : theme.base02};
|
background-color: ${primary ? theme.base07 : theme.base02};
|
||||||
|
|
|
@ -13,20 +13,24 @@ export const style = ({ theme, primary, disabled }) => css`
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
margin: auto 0;
|
margin: auto 0;
|
||||||
background-color: ${primary ? theme.base05 : theme.base01};
|
background-color: ${primary ? theme.base05 : theme.base01};
|
||||||
${disabled ? `
|
${disabled
|
||||||
|
? `
|
||||||
cursor: not-allowed;
|
cursor: not-allowed;
|
||||||
color: ${theme.base04};
|
color: ${theme.base04};
|
||||||
opacity: 0.6;
|
opacity: 0.6;
|
||||||
` : `
|
`
|
||||||
|
: `
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
color: ${primary ? theme.base00 : theme.base05};
|
color: ${primary ? theme.base00 : theme.base05};
|
||||||
`}
|
`}
|
||||||
${!disabled ? `
|
${!disabled
|
||||||
|
? `
|
||||||
box-shadow:
|
box-shadow:
|
||||||
0 2px 2px 0 ${theme.base03},
|
0 2px 2px 0 ${theme.base03},
|
||||||
0 3px 1px -2px ${theme.base02},
|
0 3px 1px -2px ${theme.base02},
|
||||||
0 1px 5px 0 ${theme.base02};
|
0 1px 5px 0 ${theme.base02};
|
||||||
` : ''}
|
`
|
||||||
|
: ''}
|
||||||
|
|
||||||
|
|
||||||
&:hover, &:focus:not(:active) {
|
&:hover, &:focus:not(:active) {
|
||||||
|
|
|
@ -10,12 +10,20 @@ export const MainContainerWrapper = styled.div`
|
||||||
color: ${props => props.theme.base07};
|
color: ${props => props.theme.base07};
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
|
|
||||||
div, input, textarea, keygen, select, button {
|
div,
|
||||||
|
input,
|
||||||
|
textarea,
|
||||||
|
keygen,
|
||||||
|
select,
|
||||||
|
button {
|
||||||
font-family: ${props => props.theme.fontFamily || 'monaco, monospace'};
|
font-family: ${props => props.theme.fontFamily || 'monaco, monospace'};
|
||||||
}
|
}
|
||||||
|
|
||||||
.CodeMirror div, pre, .monitor-LogMonitor * {
|
.CodeMirror div,
|
||||||
font-family: ${props => props.theme.codeFontFamily || props.theme.fontFamily || 'monospace'};
|
pre,
|
||||||
|
.monitor-LogMonitor * {
|
||||||
|
font-family: ${props =>
|
||||||
|
props.theme.codeFontFamily || props.theme.fontFamily || 'monospace'};
|
||||||
}
|
}
|
||||||
|
|
||||||
.monitor {
|
.monitor {
|
||||||
|
|
|
@ -12,8 +12,10 @@ export default class ContextMenu extends Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillReceiveProps(nextProps) {
|
componentWillReceiveProps(nextProps) {
|
||||||
if (nextProps.items !== this.props.items ||
|
if (
|
||||||
nextProps.visible !== this.props.visible) {
|
nextProps.items !== this.props.items ||
|
||||||
|
nextProps.visible !== this.props.visible
|
||||||
|
) {
|
||||||
this.updateItems(nextProps.items);
|
this.updateItems(nextProps.items);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -32,7 +34,7 @@ export default class ContextMenu extends Component {
|
||||||
e.target.blur();
|
e.target.blur();
|
||||||
};
|
};
|
||||||
|
|
||||||
onClick = (e) => {
|
onClick = e => {
|
||||||
this.props.onClick(e.target.value);
|
this.props.onClick(e.target.value);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -78,7 +80,7 @@ export default class ContextMenu extends Component {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
menuRef = (c) => {
|
menuRef = c => {
|
||||||
this.menu = c;
|
this.menu = c;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -16,9 +16,7 @@ export const Container = styled.div`
|
||||||
|
|
||||||
storiesOf('ContextMenu', module)
|
storiesOf('ContextMenu', module)
|
||||||
.addDecorator(withKnobs)
|
.addDecorator(withKnobs)
|
||||||
.add(
|
.add('default', () => (
|
||||||
'default',
|
|
||||||
() => (
|
|
||||||
<Container>
|
<Container>
|
||||||
<ContextMenu
|
<ContextMenu
|
||||||
visible
|
visible
|
||||||
|
@ -28,5 +26,4 @@ storiesOf('ContextMenu', module)
|
||||||
items={items}
|
items={items}
|
||||||
/>
|
/>
|
||||||
</Container>
|
</Container>
|
||||||
)
|
));
|
||||||
);
|
|
||||||
|
|
|
@ -1,11 +1,13 @@
|
||||||
import { css } from 'styled-components';
|
import { css } from 'styled-components';
|
||||||
|
|
||||||
export default ({ theme, left, top, visible }) => css`
|
export default ({ theme, left, top, visible }) => css`
|
||||||
${visible ? `
|
${visible
|
||||||
|
? `
|
||||||
visibility: visible;
|
visibility: visible;
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
transition: opacity 0.2s linear;
|
transition: opacity 0.2s linear;
|
||||||
` : `
|
`
|
||||||
|
: `
|
||||||
visibility: hidden;
|
visibility: hidden;
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
transition: visibility 0s 0.2s, opacity 0.2s linear;
|
transition: visibility 0s 0.2s, opacity 0.2s linear;
|
||||||
|
|
|
@ -59,40 +59,40 @@ export default class Dialog extends (PureComponent || Component) {
|
||||||
{children}
|
{children}
|
||||||
{schema && (
|
{schema && (
|
||||||
<Form {...rest}>
|
<Form {...rest}>
|
||||||
{!noFooter &&
|
{!noFooter && (
|
||||||
(
|
|
||||||
<input
|
<input
|
||||||
type="submit"
|
type="submit"
|
||||||
ref={this.getFormButtonRef}
|
ref={this.getFormButtonRef}
|
||||||
className="mc-dialog--hidden"
|
className="mc-dialog--hidden"
|
||||||
/>
|
/>
|
||||||
)
|
)}
|
||||||
}
|
|
||||||
</Form>
|
</Form>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
{
|
{!noFooter &&
|
||||||
!noFooter &&
|
(actions ? (
|
||||||
(actions ?
|
|
||||||
<div className="mc-dialog--footer">
|
<div className="mc-dialog--footer">
|
||||||
{submitText ?
|
{submitText
|
||||||
[...actions,
|
? [
|
||||||
<Button key="default-submit" primary onClick={this.onSubmit}>
|
...actions,
|
||||||
|
<Button
|
||||||
|
key="default-submit"
|
||||||
|
primary
|
||||||
|
onClick={this.onSubmit}
|
||||||
|
>
|
||||||
{submitText}
|
{submitText}
|
||||||
</Button>
|
</Button>
|
||||||
]
|
]
|
||||||
: actions
|
: actions}
|
||||||
}
|
|
||||||
</div>
|
</div>
|
||||||
:
|
) : (
|
||||||
<div className="mc-dialog--footer">
|
<div className="mc-dialog--footer">
|
||||||
<Button onClick={onDismiss}>Cancel</Button>
|
<Button onClick={onDismiss}>Cancel</Button>
|
||||||
<Button primary onClick={this.onSubmit}>
|
<Button primary onClick={this.onSubmit}>
|
||||||
{submitText || 'Submit'}
|
{submitText || 'Submit'}
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
)
|
))}
|
||||||
}
|
|
||||||
</div>
|
</div>
|
||||||
</DialogWrapper>
|
</DialogWrapper>
|
||||||
);
|
);
|
||||||
|
|
|
@ -7,9 +7,7 @@ import { schema, uiSchema, formData } from '../../Form/stories/schema';
|
||||||
|
|
||||||
storiesOf('Dialog', module)
|
storiesOf('Dialog', module)
|
||||||
.addDecorator(withKnobs)
|
.addDecorator(withKnobs)
|
||||||
.add(
|
.add('default', () => (
|
||||||
'default',
|
|
||||||
() => (
|
|
||||||
<Dialog
|
<Dialog
|
||||||
title={text('title', 'Dialog Title')}
|
title={text('title', 'Dialog Title')}
|
||||||
submitText={text('submitText', 'Submit!')}
|
submitText={text('submitText', 'Submit!')}
|
||||||
|
@ -23,11 +21,8 @@ storiesOf('Dialog', module)
|
||||||
>
|
>
|
||||||
{text('children', 'Hello Dialog!')}
|
{text('children', 'Hello Dialog!')}
|
||||||
</Dialog>
|
</Dialog>
|
||||||
)
|
))
|
||||||
)
|
.add('with form', () => (
|
||||||
.add(
|
|
||||||
'with form',
|
|
||||||
() => (
|
|
||||||
<Dialog
|
<Dialog
|
||||||
open={boolean('open', true)}
|
open={boolean('open', true)}
|
||||||
noHeader={boolean('noHeader', false)}
|
noHeader={boolean('noHeader', false)}
|
||||||
|
@ -41,5 +36,4 @@ storiesOf('Dialog', module)
|
||||||
onSubmit={action('form submitted')}
|
onSubmit={action('form submitted')}
|
||||||
onDismiss={action('dialog dismissed')}
|
onDismiss={action('dialog dismissed')}
|
||||||
/>
|
/>
|
||||||
)
|
));
|
||||||
);
|
|
||||||
|
|
|
@ -36,10 +36,8 @@ export const style = ({ theme, open, fullWidth }) => css`
|
||||||
border: 1px outset ${theme.base01};
|
border: 1px outset ${theme.base01};
|
||||||
border-radius: 2px;
|
border-radius: 2px;
|
||||||
background-color: ${theme.base00};
|
background-color: ${theme.base00};
|
||||||
box-shadow:
|
box-shadow: 0 9px 46px 8px rgba(0, 0, 0, 0.14),
|
||||||
0 9px 46px 8px rgba(0, 0, 0, 0.14),
|
0 11px 15px -7px rgba(0, 0, 0, 0.12), 0 24px 38px 3px rgba(0, 0, 0, 0.2);
|
||||||
0 11px 15px -7px rgba(0, 0, 0, 0.12),
|
|
||||||
0 24px 38px 3px rgba(0, 0, 0, 0.2);
|
|
||||||
|
|
||||||
> div.mc-dialog--header {
|
> div.mc-dialog--header {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
@ -77,14 +75,22 @@ export const style = ({ theme, open, fullWidth }) => css`
|
||||||
> form {
|
> form {
|
||||||
padding: 0;
|
padding: 0;
|
||||||
|
|
||||||
> .form-group { margin-bottom: 0; }
|
> .form-group {
|
||||||
|
margin-bottom: 0;
|
||||||
> div > fieldset {
|
|
||||||
legend { display: none; }
|
|
||||||
#root__description { margin-top: 0; }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.mc-dialog--hidden { display: none; }
|
> div > fieldset {
|
||||||
|
legend {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
#root__description {
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.mc-dialog--hidden {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -35,10 +35,8 @@ export const style = ({ theme, open, fullWidth }) => css`
|
||||||
margin-bottom: 16px;
|
margin-bottom: 16px;
|
||||||
border: none;
|
border: none;
|
||||||
background-color: ${theme.base00};
|
background-color: ${theme.base00};
|
||||||
box-shadow:
|
box-shadow: 0 9px 46px 8px rgba(0, 0, 0, 0.14),
|
||||||
0 9px 46px 8px rgba(0, 0, 0, 0.14),
|
0 11px 15px -7px rgba(0, 0, 0, 0.12), 0 24px 38px 3px rgba(0, 0, 0, 0.2);
|
||||||
0 11px 15px -7px rgba(0, 0, 0, 0.12),
|
|
||||||
0 24px 38px 3px rgba(0, 0, 0, 0.2);
|
|
||||||
|
|
||||||
> div.mc-dialog--header {
|
> div.mc-dialog--header {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
@ -74,14 +72,22 @@ export const style = ({ theme, open, fullWidth }) => css`
|
||||||
> form {
|
> form {
|
||||||
padding: 0;
|
padding: 0;
|
||||||
|
|
||||||
> .form-group { margin-bottom: 0; }
|
> .form-group {
|
||||||
|
margin-bottom: 0;
|
||||||
> div > fieldset {
|
|
||||||
legend { display: none; }
|
|
||||||
#root__description { margin-top: 0; }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.mc-dialog--hidden { display: none; }
|
> div > fieldset {
|
||||||
|
legend {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
#root__description {
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.mc-dialog--hidden {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,15 +4,13 @@ import styled from 'styled-components';
|
||||||
import CodeMirror from 'codemirror';
|
import CodeMirror from 'codemirror';
|
||||||
import { defaultStyle, themedStyle } from './styles';
|
import { defaultStyle, themedStyle } from './styles';
|
||||||
|
|
||||||
const EditorContainer = styled.div('',
|
const EditorContainer = styled.div('', ({ theme }) =>
|
||||||
({ theme }) => (theme.scheme === 'default' && theme.light ? defaultStyle : themedStyle(theme))
|
theme.scheme === 'default' && theme.light ? defaultStyle : themedStyle(theme)
|
||||||
);
|
);
|
||||||
|
|
||||||
export default class Editor extends Component {
|
export default class Editor extends Component {
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
this.cm = CodeMirror( // eslint-disable-line new-cap
|
this.cm = CodeMirror(this.node, {
|
||||||
this.node,
|
|
||||||
{
|
|
||||||
value: this.props.value,
|
value: this.props.value,
|
||||||
mode: this.props.mode,
|
mode: this.props.mode,
|
||||||
lineNumbers: this.props.lineNumbers,
|
lineNumbers: this.props.lineNumbers,
|
||||||
|
@ -21,11 +19,12 @@ export default class Editor extends Component {
|
||||||
autofocus: this.props.autofocus,
|
autofocus: this.props.autofocus,
|
||||||
foldGutter: this.props.foldGutter,
|
foldGutter: this.props.foldGutter,
|
||||||
gutters: ['CodeMirror-linenumbers', 'CodeMirror-foldgutter']
|
gutters: ['CodeMirror-linenumbers', 'CodeMirror-foldgutter']
|
||||||
}
|
});
|
||||||
);
|
|
||||||
|
|
||||||
if (this.props.onChange) {
|
if (this.props.onChange) {
|
||||||
this.cm.on('change', (doc, change) => { this.props.onChange(doc.getValue(), change); });
|
this.cm.on('change', (doc, change) => {
|
||||||
|
this.props.onChange(doc.getValue(), change);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -34,7 +34,9 @@ export default class WithTabs extends Component {
|
||||||
}
|
}
|
||||||
]}
|
]}
|
||||||
selected={this.state.selected}
|
selected={this.state.selected}
|
||||||
onClick={selected => { this.setState({ selected }); }}
|
onClick={selected => {
|
||||||
|
this.setState({ selected });
|
||||||
|
}}
|
||||||
align={select('align', ['left', 'right', 'center'], 'left')}
|
align={select('align', ['left', 'right', 'center'], 'left')}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|
|
@ -30,11 +30,6 @@ storiesOf('Editor', module)
|
||||||
),
|
),
|
||||||
{ info: 'Based on [CodeMirror](http://codemirror.net/).' }
|
{ info: 'Based on [CodeMirror](http://codemirror.net/).' }
|
||||||
)
|
)
|
||||||
.add(
|
.add('with tabs', () => (
|
||||||
'with tabs',
|
<WithTabs lineNumbers={boolean('lineNumbers', true)} />
|
||||||
() => (
|
));
|
||||||
<WithTabs
|
|
||||||
lineNumbers={boolean('lineNumbers', true)}
|
|
||||||
/>
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
|
@ -19,37 +19,79 @@ export const themedStyle = theme => css`
|
||||||
background-color: ${theme.base00};
|
background-color: ${theme.base00};
|
||||||
color: ${theme.base04};
|
color: ${theme.base04};
|
||||||
|
|
||||||
.cm-header { color: ${theme.base05}; }
|
.cm-header {
|
||||||
.cm-quote { color: ${theme.base09}; }
|
color: ${theme.base05};
|
||||||
|
}
|
||||||
|
.cm-quote {
|
||||||
|
color: ${theme.base09};
|
||||||
|
}
|
||||||
|
|
||||||
.cm-keyword { color: ${theme.base0F}; }
|
.cm-keyword {
|
||||||
.cm-atom { color: ${theme.base0F}; }
|
color: ${theme.base0F};
|
||||||
.cm-number { color: ${theme.base0F}; }
|
}
|
||||||
.cm-def { color: ${theme.base0D}; }
|
.cm-atom {
|
||||||
|
color: ${theme.base0F};
|
||||||
|
}
|
||||||
|
.cm-number {
|
||||||
|
color: ${theme.base0F};
|
||||||
|
}
|
||||||
|
.cm-def {
|
||||||
|
color: ${theme.base0D};
|
||||||
|
}
|
||||||
|
|
||||||
.cm-variable { color: ${theme.base05}; }
|
.cm-variable {
|
||||||
.cm-variable-2 { color: ${theme.base0A}; }
|
color: ${theme.base05};
|
||||||
.cm-variable-3 { color: ${theme.base0E}; }
|
}
|
||||||
|
.cm-variable-2 {
|
||||||
|
color: ${theme.base0A};
|
||||||
|
}
|
||||||
|
.cm-variable-3 {
|
||||||
|
color: ${theme.base0E};
|
||||||
|
}
|
||||||
|
|
||||||
.cm-property { color: ${theme.base0C}; }
|
.cm-property {
|
||||||
.cm-operator { color: ${theme.base0E}; }
|
color: ${theme.base0C};
|
||||||
|
}
|
||||||
|
.cm-operator {
|
||||||
|
color: ${theme.base0E};
|
||||||
|
}
|
||||||
|
|
||||||
.cm-comment {
|
.cm-comment {
|
||||||
color: ${theme.base05};
|
color: ${theme.base05};
|
||||||
font-style: italic;
|
font-style: italic;
|
||||||
}
|
}
|
||||||
|
|
||||||
.cm-string { color: ${theme.base0B}; }
|
.cm-string {
|
||||||
.cm-string-2 { color: ${theme.base0A}; }
|
color: ${theme.base0B};
|
||||||
|
}
|
||||||
|
.cm-string-2 {
|
||||||
|
color: ${theme.base0A};
|
||||||
|
}
|
||||||
|
|
||||||
.cm-meta { color: ${theme.base0B}; }
|
.cm-meta {
|
||||||
.cm-qualifier { color: ${theme.base0A}; }
|
color: ${theme.base0B};
|
||||||
.cm-builtin { color: ${theme.base0F}; }
|
}
|
||||||
.cm-bracket { color: ${theme.base09}; }
|
.cm-qualifier {
|
||||||
.CodeMirror-matchingbracket { color: ${theme.base0B}; }
|
color: ${theme.base0A};
|
||||||
.CodeMirror-nonmatchingbracket { color: ${theme.base08}; }
|
}
|
||||||
.cm-tag { color: ${theme.base02}; }
|
.cm-builtin {
|
||||||
.cm-attribute { color: ${theme.base0C}; }
|
color: ${theme.base0F};
|
||||||
|
}
|
||||||
|
.cm-bracket {
|
||||||
|
color: ${theme.base09};
|
||||||
|
}
|
||||||
|
.CodeMirror-matchingbracket {
|
||||||
|
color: ${theme.base0B};
|
||||||
|
}
|
||||||
|
.CodeMirror-nonmatchingbracket {
|
||||||
|
color: ${theme.base08};
|
||||||
|
}
|
||||||
|
.cm-tag {
|
||||||
|
color: ${theme.base02};
|
||||||
|
}
|
||||||
|
.cm-attribute {
|
||||||
|
color: ${theme.base0C};
|
||||||
|
}
|
||||||
|
|
||||||
.cm-hr {
|
.cm-hr {
|
||||||
color: transparent;
|
color: transparent;
|
||||||
|
@ -62,7 +104,9 @@ export const themedStyle = theme => css`
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
.cm-special { color: ${theme.base0E}; }
|
.cm-special {
|
||||||
|
color: ${theme.base0E};
|
||||||
|
}
|
||||||
|
|
||||||
.cm-em {
|
.cm-em {
|
||||||
color: #999;
|
color: #999;
|
||||||
|
@ -70,7 +114,9 @@ export const themedStyle = theme => css`
|
||||||
text-decoration-style: dotted;
|
text-decoration-style: dotted;
|
||||||
}
|
}
|
||||||
|
|
||||||
.cm-strong { color: ${theme.base01}; }
|
.cm-strong {
|
||||||
|
color: ${theme.base01};
|
||||||
|
}
|
||||||
|
|
||||||
.cm-error,
|
.cm-error,
|
||||||
.cm-invalidchar {
|
.cm-invalidchar {
|
||||||
|
@ -78,7 +124,9 @@ export const themedStyle = theme => css`
|
||||||
border-bottom: 1px dotted ${theme.base08};
|
border-bottom: 1px dotted ${theme.base08};
|
||||||
}
|
}
|
||||||
|
|
||||||
div.CodeMirror-selected { background: ${theme.base01}; }
|
div.CodeMirror-selected {
|
||||||
|
background: ${theme.base01};
|
||||||
|
}
|
||||||
|
|
||||||
.CodeMirror-line::selection,
|
.CodeMirror-line::selection,
|
||||||
.CodeMirror-line > span::selection,
|
.CodeMirror-line > span::selection,
|
||||||
|
@ -106,17 +154,27 @@ export const themedStyle = theme => css`
|
||||||
padding: 0 5px;
|
padding: 0 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.CodeMirror-guttermarker-subtle { color: ${theme.base05}; }
|
.CodeMirror-guttermarker-subtle {
|
||||||
.CodeMirror-guttermarker { color: ${theme.base09}; }
|
color: ${theme.base05};
|
||||||
|
}
|
||||||
|
.CodeMirror-guttermarker {
|
||||||
|
color: ${theme.base09};
|
||||||
|
}
|
||||||
|
|
||||||
.CodeMirror-gutter .CodeMirror-gutter-text {
|
.CodeMirror-gutter .CodeMirror-gutter-text {
|
||||||
color: ${theme.base05};
|
color: ${theme.base05};
|
||||||
}
|
}
|
||||||
|
|
||||||
.CodeMirror-cursor { border-left: 1px solid #819090; }
|
.CodeMirror-cursor {
|
||||||
|
border-left: 1px solid #819090;
|
||||||
|
}
|
||||||
|
|
||||||
.cm-fat-cursor .CodeMirror-cursor { background: ${theme.base02}; }
|
.cm-fat-cursor .CodeMirror-cursor {
|
||||||
.cm-animate-fat-cursor { background-color: ${theme.base02}; }
|
background: ${theme.base02};
|
||||||
|
}
|
||||||
|
.cm-animate-fat-cursor {
|
||||||
|
background-color: ${theme.base02};
|
||||||
|
}
|
||||||
|
|
||||||
.CodeMirror-activeline-background {
|
.CodeMirror-activeline-background {
|
||||||
background: ${theme.base07};
|
background: ${theme.base07};
|
||||||
|
|
|
@ -10,16 +10,30 @@ const FormContainer = createStyledComponent(styles, JSONSchemaForm);
|
||||||
|
|
||||||
export default class Form extends (PureComponent || Component) {
|
export default class Form extends (PureComponent || Component) {
|
||||||
render() {
|
render() {
|
||||||
const { widgets, children, submitText, primaryButton, noSubmit, ...rest } = this.props;
|
const {
|
||||||
|
widgets,
|
||||||
|
children,
|
||||||
|
submitText,
|
||||||
|
primaryButton,
|
||||||
|
noSubmit,
|
||||||
|
...rest
|
||||||
|
} = this.props;
|
||||||
return (
|
return (
|
||||||
<FormContainer {...rest} widgets={{ ...customWidgets, ...widgets }}>
|
<FormContainer {...rest} widgets={{ ...customWidgets, ...widgets }}>
|
||||||
{
|
{noSubmit ? (
|
||||||
noSubmit ? <noscript /> :
|
<noscript />
|
||||||
children ||
|
) : (
|
||||||
<Button size="big" primary={primaryButton} theme={rest.theme} type="submit">
|
children || (
|
||||||
|
<Button
|
||||||
|
size="big"
|
||||||
|
primary={primaryButton}
|
||||||
|
theme={rest.theme}
|
||||||
|
type="submit"
|
||||||
|
>
|
||||||
{submitText || 'Submit'}
|
{submitText || 'Submit'}
|
||||||
</Button>
|
</Button>
|
||||||
}
|
)
|
||||||
|
)}
|
||||||
</FormContainer>
|
</FormContainer>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -33,5 +47,7 @@ Form.propTypes = {
|
||||||
schema: PropTypes.object.isRequired,
|
schema: PropTypes.object.isRequired,
|
||||||
uiSchema: PropTypes.object,
|
uiSchema: PropTypes.object,
|
||||||
formData: PropTypes.any,
|
formData: PropTypes.any,
|
||||||
widgets: PropTypes.objectOf(PropTypes.oneOfType([PropTypes.func, PropTypes.object]))
|
widgets: PropTypes.objectOf(
|
||||||
|
PropTypes.oneOfType([PropTypes.func, PropTypes.object])
|
||||||
|
)
|
||||||
};
|
};
|
||||||
|
|
|
@ -19,8 +19,9 @@ storiesOf('Form', module)
|
||||||
onSubmit={action('form submitted')}
|
onSubmit={action('form submitted')}
|
||||||
/>
|
/>
|
||||||
),
|
),
|
||||||
{ info:
|
{
|
||||||
'Wrapper around [`react-jsonschema-form`](https://github.com/mozilla-services/react-jsonschema-form)'
|
info:
|
||||||
+ ' with custom widgets.'
|
'Wrapper around [`react-jsonschema-form`](https://github.com/mozilla-services/react-jsonschema-form)' +
|
||||||
|
' with custom widgets.'
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
|
@ -27,31 +27,19 @@ module.exports = {
|
||||||
title: 'A multiple choices list',
|
title: 'A multiple choices list',
|
||||||
items: {
|
items: {
|
||||||
type: 'string',
|
type: 'string',
|
||||||
enum: [
|
enum: ['foo', 'bar', 'fuzz']
|
||||||
'foo',
|
|
||||||
'bar',
|
|
||||||
'fuzz'
|
|
||||||
]
|
|
||||||
},
|
},
|
||||||
uniqueItems: true
|
uniqueItems: true
|
||||||
},
|
},
|
||||||
numberEnum: {
|
numberEnum: {
|
||||||
type: 'number',
|
type: 'number',
|
||||||
title: 'Number enum',
|
title: 'Number enum',
|
||||||
enum: [
|
enum: [1, 2, 3]
|
||||||
1,
|
|
||||||
2,
|
|
||||||
3
|
|
||||||
]
|
|
||||||
},
|
},
|
||||||
numberEnumRadio: {
|
numberEnumRadio: {
|
||||||
type: 'number',
|
type: 'number',
|
||||||
title: 'Number enum',
|
title: 'Number enum',
|
||||||
enum: [
|
enum: [1, 2, 3]
|
||||||
1,
|
|
||||||
2,
|
|
||||||
3
|
|
||||||
]
|
|
||||||
},
|
},
|
||||||
integerRange: {
|
integerRange: {
|
||||||
title: 'Integer range',
|
title: 'Integer range',
|
||||||
|
|
|
@ -87,10 +87,10 @@ textarea.form-control {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
.radio input[type="radio"],
|
.radio input[type='radio'],
|
||||||
.radio-inline input[type="radio"],
|
.radio-inline input[type='radio'],
|
||||||
.checkbox input[type="checkbox"],
|
.checkbox input[type='checkbox'],
|
||||||
.checkbox-inline input[type="checkbox"] {
|
.checkbox-inline input[type='checkbox'] {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
margin-left: -20px;
|
margin-left: -20px;
|
||||||
margin-top: 4px \\9;
|
margin-top: 4px \\9;
|
||||||
|
@ -125,20 +125,20 @@ textarea.form-control {
|
||||||
padding-left: 25px;
|
padding-left: 25px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.radio input[type="radio"],
|
.radio input[type='radio'],
|
||||||
.radio-inline input[type="radio"],
|
.radio-inline input[type='radio'],
|
||||||
.checkbox input[type="radio"],
|
.checkbox input[type='radio'],
|
||||||
.checkbox-inline input[type="radio"],
|
.checkbox-inline input[type='radio'],
|
||||||
.radio input[type="checkbox"],
|
.radio input[type='checkbox'],
|
||||||
.radio-inline input[type="checkbox"],
|
.radio-inline input[type='checkbox'],
|
||||||
.checkbox input[type="checkbox"],
|
.checkbox input[type='checkbox'],
|
||||||
.checkbox-inline input[type="checkbox"] {
|
.checkbox-inline input[type='checkbox'] {
|
||||||
margin-left: -25px;
|
margin-left: -25px;
|
||||||
}
|
}
|
||||||
|
|
||||||
input[type="radio"],
|
input[type='radio'],
|
||||||
.radio input[type="radio"],
|
.radio input[type='radio'],
|
||||||
.radio-inline input[type="radio"] {
|
.radio-inline input[type='radio'] {
|
||||||
position: relative;
|
position: relative;
|
||||||
margin-top: 6px;
|
margin-top: 6px;
|
||||||
margin-right: 4px;
|
margin-right: 4px;
|
||||||
|
@ -149,19 +149,19 @@ input[type="radio"],
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
input[type="radio"]:focus,
|
input[type='radio']:focus,
|
||||||
.radio input[type="radio"]:focus,
|
.radio input[type='radio']:focus,
|
||||||
.radio-inline input[type="radio"]:focus {
|
.radio-inline input[type='radio']:focus {
|
||||||
outline: none;
|
outline: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
input[type="radio"]:before,
|
input[type='radio']:before,
|
||||||
.radio input[type="radio"]:before,
|
.radio input[type='radio']:before,
|
||||||
.radio-inline input[type="radio"]:before,
|
.radio-inline input[type='radio']:before,
|
||||||
input[type="radio"]:after,
|
input[type='radio']:after,
|
||||||
.radio input[type="radio"]:after,
|
.radio input[type='radio']:after,
|
||||||
.radio-inline input[type="radio"]:after {
|
.radio-inline input[type='radio']:after {
|
||||||
content: "";
|
content: '';
|
||||||
display: block;
|
display: block;
|
||||||
width: 18px;
|
width: 18px;
|
||||||
height: 18px;
|
height: 18px;
|
||||||
|
@ -170,9 +170,9 @@ input[type="radio"]:after,
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
}
|
}
|
||||||
|
|
||||||
input[type="radio"]:before,
|
input[type='radio']:before,
|
||||||
.radio input[type="radio"]:before,
|
.radio input[type='radio']:before,
|
||||||
.radio-inline input[type="radio"]:before {
|
.radio-inline input[type='radio']:before {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
left: 0;
|
left: 0;
|
||||||
top: -3px;
|
top: -3px;
|
||||||
|
@ -180,44 +180,44 @@ input[type="radio"]:before,
|
||||||
transform: scale(0);
|
transform: scale(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
input[type="radio"]:after,
|
input[type='radio']:after,
|
||||||
.radio input[type="radio"]:after,
|
.radio input[type='radio']:after,
|
||||||
.radio-inline input[type="radio"]:after {
|
.radio-inline input[type='radio']:after {
|
||||||
position: relative;
|
position: relative;
|
||||||
top: -3px;
|
top: -3px;
|
||||||
border: 2px solid ${theme.base03};
|
border: 2px solid ${theme.base03};
|
||||||
}
|
}
|
||||||
|
|
||||||
input[type="radio"]:checked:before,
|
input[type='radio']:checked:before,
|
||||||
.radio input[type="radio"]:checked:before,
|
.radio input[type='radio']:checked:before,
|
||||||
.radio-inline input[type="radio"]:checked:before {
|
.radio-inline input[type='radio']:checked:before {
|
||||||
transform: scale(0.5);
|
transform: scale(0.5);
|
||||||
}
|
}
|
||||||
|
|
||||||
input[type="radio"]:disabled:checked:before,
|
input[type='radio']:disabled:checked:before,
|
||||||
.radio input[type="radio"]:disabled:checked:before,
|
.radio input[type='radio']:disabled:checked:before,
|
||||||
.radio-inline input[type="radio"]:disabled:checked:before {
|
.radio-inline input[type='radio']:disabled:checked:before {
|
||||||
background-color: ${theme.base03};
|
background-color: ${theme.base03};
|
||||||
}
|
}
|
||||||
|
|
||||||
input[type="radio"]:checked:after,
|
input[type='radio']:checked:after,
|
||||||
.radio input[type="radio"]:checked:after,
|
.radio input[type='radio']:checked:after,
|
||||||
.radio-inline input[type="radio"]:checked:after {
|
.radio-inline input[type='radio']:checked:after {
|
||||||
border-color: ${theme.base0D};
|
border-color: ${theme.base0D};
|
||||||
}
|
}
|
||||||
|
|
||||||
input[type="radio"]:disabled:after,
|
input[type='radio']:disabled:after,
|
||||||
.radio input[type="radio"]:disabled:after,
|
.radio input[type='radio']:disabled:after,
|
||||||
.radio-inline input[type="radio"]:disabled:after,
|
.radio-inline input[type='radio']:disabled:after,
|
||||||
input[type="radio"]:disabled:checked:after,
|
input[type='radio']:disabled:checked:after,
|
||||||
.radio input[type="radio"]:disabled:checked:after,
|
.radio input[type='radio']:disabled:checked:after,
|
||||||
.radio-inline input[type="radio"]:disabled:checked:after {
|
.radio-inline input[type='radio']:disabled:checked:after {
|
||||||
border-color: ${theme.base03};
|
border-color: ${theme.base03};
|
||||||
}
|
}
|
||||||
|
|
||||||
input[type="checkbox"],
|
input[type='checkbox'],
|
||||||
.checkbox input[type="checkbox"],
|
.checkbox input[type='checkbox'],
|
||||||
.checkbox-inline input[type="checkbox"] {
|
.checkbox-inline input[type='checkbox'] {
|
||||||
position: relative;
|
position: relative;
|
||||||
border: none;
|
border: none;
|
||||||
margin-bottom: -4px;
|
margin-bottom: -4px;
|
||||||
|
@ -225,22 +225,22 @@ input[type="checkbox"],
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
input[type="checkbox"]:focus,
|
input[type='checkbox']:focus,
|
||||||
.checkbox input[type="checkbox"]:focus,
|
.checkbox input[type='checkbox']:focus,
|
||||||
.checkbox-inline input[type="checkbox"]:focus {
|
.checkbox-inline input[type='checkbox']:focus {
|
||||||
outline: none;
|
outline: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
input[type="checkbox"]:focus:after,
|
input[type='checkbox']:focus:after,
|
||||||
.checkbox input[type="checkbox"]:focus:after,
|
.checkbox input[type='checkbox']:focus:after,
|
||||||
.checkbox-inline input[type="checkbox"]:focus:after {
|
.checkbox-inline input[type='checkbox']:focus:after {
|
||||||
border-color: ${theme.base0D};
|
border-color: ${theme.base0D};
|
||||||
}
|
}
|
||||||
|
|
||||||
input[type="checkbox"]:after,
|
input[type='checkbox']:after,
|
||||||
.checkbox input[type="checkbox"]:after,
|
.checkbox input[type='checkbox']:after,
|
||||||
.checkbox-inline input[type="checkbox"]:after {
|
.checkbox-inline input[type='checkbox']:after {
|
||||||
content: "";
|
content: '';
|
||||||
display: block;
|
display: block;
|
||||||
width: 18px;
|
width: 18px;
|
||||||
height: 18px;
|
height: 18px;
|
||||||
|
@ -252,10 +252,10 @@ input[type="checkbox"]:after,
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
}
|
}
|
||||||
|
|
||||||
input[type="checkbox"]:checked:before,
|
input[type='checkbox']:checked:before,
|
||||||
.checkbox input[type="checkbox"]:checked:before,
|
.checkbox input[type='checkbox']:checked:before,
|
||||||
.checkbox-inline input[type="checkbox"]:checked:before {
|
.checkbox-inline input[type='checkbox']:checked:before {
|
||||||
content: "";
|
content: '';
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0;
|
top: 0;
|
||||||
left: 6px;
|
left: 6px;
|
||||||
|
@ -269,32 +269,32 @@ input[type="checkbox"]:checked:before,
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
}
|
}
|
||||||
|
|
||||||
input[type="checkbox"]:checked:after,
|
input[type='checkbox']:checked:after,
|
||||||
.checkbox input[type="checkbox"]:checked:after,
|
.checkbox input[type='checkbox']:checked:after,
|
||||||
.checkbox-inline input[type="checkbox"]:checked:after {
|
.checkbox-inline input[type='checkbox']:checked:after {
|
||||||
background-color: ${theme.base0D};
|
background-color: ${theme.base0D};
|
||||||
border-color: ${theme.base0D};
|
border-color: ${theme.base0D};
|
||||||
}
|
}
|
||||||
|
|
||||||
input[type="checkbox"]:disabled:after,
|
input[type='checkbox']:disabled:after,
|
||||||
.checkbox input[type="checkbox"]:disabled:after,
|
.checkbox input[type='checkbox']:disabled:after,
|
||||||
.checkbox-inline input[type="checkbox"]:disabled:after {
|
.checkbox-inline input[type='checkbox']:disabled:after {
|
||||||
border-color: ${theme.base03};
|
border-color: ${theme.base03};
|
||||||
}
|
}
|
||||||
|
|
||||||
input[type="checkbox"]:disabled:checked:after,
|
input[type='checkbox']:disabled:checked:after,
|
||||||
.checkbox input[type="checkbox"]:disabled:checked:after,
|
.checkbox input[type='checkbox']:disabled:checked:after,
|
||||||
.checkbox-inline input[type="checkbox"]:disabled:checked:after {
|
.checkbox-inline input[type='checkbox']:disabled:checked:after {
|
||||||
background-color: ${theme.base03};
|
background-color: ${theme.base03};
|
||||||
border-color: transparent;
|
border-color: transparent;
|
||||||
}
|
}
|
||||||
|
|
||||||
input[type="radio"][disabled],
|
input[type='radio'][disabled],
|
||||||
input[type="checkbox"][disabled],
|
input[type='checkbox'][disabled],
|
||||||
input[type="radio"].disabled,
|
input[type='radio'].disabled,
|
||||||
input[type="checkbox"].disabled,
|
input[type='checkbox'].disabled,
|
||||||
fieldset[disabled] input[type="radio"],
|
fieldset[disabled] input[type='radio'],
|
||||||
fieldset[disabled] input[type="checkbox"] {
|
fieldset[disabled] input[type='checkbox'] {
|
||||||
cursor: not-allowed;
|
cursor: not-allowed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,9 @@ const SelectWidget = ({ options, multi, ...rest }) => (
|
||||||
);
|
);
|
||||||
|
|
||||||
const RangeWidget = ({
|
const RangeWidget = ({
|
||||||
schema, readonly, autofocus,
|
schema,
|
||||||
|
readonly,
|
||||||
|
autofocus,
|
||||||
label, // eslint-disable-line
|
label, // eslint-disable-line
|
||||||
options, // eslint-disable-line
|
options, // eslint-disable-line
|
||||||
formContext, // eslint-disable-line
|
formContext, // eslint-disable-line
|
||||||
|
|
|
@ -11,16 +11,22 @@ const NotificationWrapper = createStyledComponent(styles);
|
||||||
|
|
||||||
export default class Notification extends Component {
|
export default class Notification extends Component {
|
||||||
shouldComponentUpdate(nextProps) {
|
shouldComponentUpdate(nextProps) {
|
||||||
return nextProps.children !== this.props.children ||
|
return (
|
||||||
nextProps.type !== this.props.type;
|
nextProps.children !== this.props.children ||
|
||||||
|
nextProps.type !== this.props.type
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
getIcon = () => {
|
getIcon = () => {
|
||||||
switch (this.props.type) {
|
switch (this.props.type) {
|
||||||
case 'warning': return <WarningIcon />;
|
case 'warning':
|
||||||
case 'error': return <ErrorIcon />;
|
return <WarningIcon />;
|
||||||
case 'success': return <SuccessIcon />;
|
case 'error':
|
||||||
default: return null;
|
return <ErrorIcon />;
|
||||||
|
case 'success':
|
||||||
|
return <SuccessIcon />;
|
||||||
|
default:
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -29,9 +35,11 @@ export default class Notification extends Component {
|
||||||
<NotificationWrapper type={this.props.type} theme={this.props.theme}>
|
<NotificationWrapper type={this.props.type} theme={this.props.theme}>
|
||||||
{this.getIcon()}
|
{this.getIcon()}
|
||||||
<span>{this.props.children}</span>
|
<span>{this.props.children}</span>
|
||||||
{this.props.onClose &&
|
{this.props.onClose && (
|
||||||
<button onClick={this.props.onClose}><CloseIcon /></button>
|
<button onClick={this.props.onClose}>
|
||||||
}
|
<CloseIcon />
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
</NotificationWrapper>
|
</NotificationWrapper>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,18 +15,17 @@ export const Container = styled.div`
|
||||||
|
|
||||||
storiesOf('Notification', module)
|
storiesOf('Notification', module)
|
||||||
.addDecorator(withKnobs)
|
.addDecorator(withKnobs)
|
||||||
.add(
|
.add('default', () => (
|
||||||
'default',
|
|
||||||
() => (
|
|
||||||
<Container>
|
<Container>
|
||||||
<Notification
|
<Notification
|
||||||
type={
|
type={select(
|
||||||
select('type', ['info', 'success', 'warning', 'error'], 'warning')
|
'type',
|
||||||
}
|
['info', 'success', 'warning', 'error'],
|
||||||
|
'warning'
|
||||||
|
)}
|
||||||
onClose={action('notification closed')}
|
onClose={action('notification closed')}
|
||||||
>
|
>
|
||||||
{text('Message', 'Hello Notification')}
|
{text('Message', 'Hello Notification')}
|
||||||
</Notification>
|
</Notification>
|
||||||
</Container>
|
</Container>
|
||||||
)
|
));
|
||||||
);
|
|
||||||
|
|
|
@ -49,7 +49,8 @@ export default ({ theme, type }) => css`
|
||||||
opacity: 0.8;
|
opacity: 0.8;
|
||||||
}
|
}
|
||||||
|
|
||||||
& > button:hover, & > button:active {
|
& > button:hover,
|
||||||
|
& > button:active {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,8 +7,10 @@ const SegmentedWrapper = createStyledComponent(styles);
|
||||||
|
|
||||||
export default class SegmentedControl extends Component {
|
export default class SegmentedControl extends Component {
|
||||||
shouldComponentUpdate(nextProps) {
|
shouldComponentUpdate(nextProps) {
|
||||||
return nextProps.disabled !== this.props.disabled ||
|
return (
|
||||||
nextProps.selected !== this.props.selected;
|
nextProps.disabled !== this.props.disabled ||
|
||||||
|
nextProps.selected !== this.props.selected
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
onClick = e => {
|
onClick = e => {
|
||||||
|
|
|
@ -15,9 +15,7 @@ export const Container = styled.div`
|
||||||
|
|
||||||
storiesOf('SegmentedControl', module)
|
storiesOf('SegmentedControl', module)
|
||||||
.addDecorator(withKnobs)
|
.addDecorator(withKnobs)
|
||||||
.add(
|
.add('default', () => (
|
||||||
'default',
|
|
||||||
() => (
|
|
||||||
<Container>
|
<Container>
|
||||||
<SegmentedControl
|
<SegmentedControl
|
||||||
values={['Button1', 'Button2', 'Button3']}
|
values={['Button1', 'Button2', 'Button3']}
|
||||||
|
@ -26,5 +24,4 @@ storiesOf('SegmentedControl', module)
|
||||||
disabled={boolean('Disabled', false)}
|
disabled={boolean('Disabled', false)}
|
||||||
/>
|
/>
|
||||||
</Container>
|
</Container>
|
||||||
)
|
));
|
||||||
);
|
|
||||||
|
|
|
@ -5,7 +5,8 @@ export default ({ theme, disabled }) => css`
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
|
|
||||||
> [data-selected], > [data-selected]:hover {
|
> [data-selected],
|
||||||
|
> [data-selected]:hover {
|
||||||
background-color: ${theme.base04};
|
background-color: ${theme.base04};
|
||||||
color: ${theme.base00};
|
color: ${theme.base00};
|
||||||
}
|
}
|
||||||
|
@ -19,10 +20,12 @@ export default ({ theme, disabled }) => css`
|
||||||
border: 1px solid ${color(theme.base03, 'alpha', 0.4)};
|
border: 1px solid ${color(theme.base03, 'alpha', 0.4)};
|
||||||
border-left-width: 0;
|
border-left-width: 0;
|
||||||
padding: 5px 10px;
|
padding: 5px 10px;
|
||||||
${disabled ? `
|
${disabled
|
||||||
|
? `
|
||||||
cursor: not-allowed;
|
cursor: not-allowed;
|
||||||
opacity: 0.6;
|
opacity: 0.6;
|
||||||
` : `
|
`
|
||||||
|
: `
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
color: ${theme.base05};
|
color: ${theme.base05};
|
||||||
background-color: ${theme.base01};
|
background-color: ${theme.base01};
|
||||||
|
|
|
@ -26,4 +26,9 @@ Select.propTypes = {
|
||||||
openOuterUp: PropTypes.bool // value to control the opening direction
|
openOuterUp: PropTypes.bool // value to control the opening direction
|
||||||
};
|
};
|
||||||
|
|
||||||
Select.defaultProps = { autosize: true, clearable: false, simpleValue: true, menuMaxHeight: 200 };
|
Select.defaultProps = {
|
||||||
|
autosize: true,
|
||||||
|
clearable: false,
|
||||||
|
simpleValue: true,
|
||||||
|
menuMaxHeight: 200
|
||||||
|
};
|
||||||
|
|
|
@ -39,8 +39,9 @@ storiesOf('Select', module)
|
||||||
/>
|
/>
|
||||||
</Container>
|
</Container>
|
||||||
),
|
),
|
||||||
{ info:
|
{
|
||||||
'Wrapper around [React Select](https://github.com/JedWatson/react-select) with themes '
|
info:
|
||||||
+ 'and new props like `openOuterUp` and `menuMaxHeight`.'
|
'Wrapper around [React Select](https://github.com/JedWatson/react-select) with themes ' +
|
||||||
|
'and new props like `openOuterUp` and `menuMaxHeight`.'
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
|
@ -59,10 +59,9 @@ export default ({ theme, openOuterUp, menuMaxHeight }) => css`
|
||||||
}
|
}
|
||||||
|
|
||||||
&.is-open > .Select-control {
|
&.is-open > .Select-control {
|
||||||
border-radius: ${openOuterUp ?
|
border-radius: ${openOuterUp
|
||||||
`0 0 ${theme.inputBorderRadius}px ${theme.inputBorderRadius}px` :
|
? `0 0 ${theme.inputBorderRadius}px ${theme.inputBorderRadius}px`
|
||||||
`${theme.inputBorderRadius}px ${theme.inputBorderRadius}px 0 0`
|
: `${theme.inputBorderRadius}px ${theme.inputBorderRadius}px 0 0`};
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
&.is-searchable {
|
&.is-searchable {
|
||||||
|
@ -212,9 +211,7 @@ export default ({ theme, openOuterUp, menuMaxHeight }) => css`
|
||||||
.Select-arrow {
|
.Select-arrow {
|
||||||
border-color: ${theme.base03} transparent transparent;
|
border-color: ${theme.base03} transparent transparent;
|
||||||
border-style: solid;
|
border-style: solid;
|
||||||
border-width:
|
border-width: ${theme.selectArrowWidth}px ${theme.selectArrowWidth}px
|
||||||
${theme.selectArrowWidth}px
|
|
||||||
${theme.selectArrowWidth}px
|
|
||||||
${theme.selectArrowWidth / 2}px;
|
${theme.selectArrowWidth / 2}px;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
height: 0;
|
height: 0;
|
||||||
|
@ -317,7 +314,8 @@ export default ({ theme, openOuterUp, menuMaxHeight }) => css`
|
||||||
border-bottom-right-radius: ${theme.inputBorderRadius}px;
|
border-bottom-right-radius: ${theme.inputBorderRadius}px;
|
||||||
border-top-right-radius: ${theme.inputBorderRadius}px;
|
border-top-right-radius: ${theme.inputBorderRadius}px;
|
||||||
cursor: default;
|
cursor: default;
|
||||||
padding: ${Math.floor(theme.inputPadding / 4)}px ${Math.floor(theme.inputPadding / 2)}px;
|
padding: ${Math.floor(theme.inputPadding / 4)}px
|
||||||
|
${Math.floor(theme.inputPadding / 2)}px;
|
||||||
}
|
}
|
||||||
|
|
||||||
a.Select-value-label {
|
a.Select-value-label {
|
||||||
|
|
|
@ -9,12 +9,14 @@ const ContainerWithValue = createStyledComponent(containerStyle);
|
||||||
|
|
||||||
export default class Slider extends Component {
|
export default class Slider extends Component {
|
||||||
shouldComponentUpdate(nextProps) {
|
shouldComponentUpdate(nextProps) {
|
||||||
return nextProps.label !== this.props.label ||
|
return (
|
||||||
|
nextProps.label !== this.props.label ||
|
||||||
nextProps.value !== this.props.value ||
|
nextProps.value !== this.props.value ||
|
||||||
nextProps.max !== this.props.max ||
|
nextProps.max !== this.props.max ||
|
||||||
nextProps.min !== this.props.min ||
|
nextProps.min !== this.props.min ||
|
||||||
nextProps.withValue !== this.props.withValue ||
|
nextProps.withValue !== this.props.withValue ||
|
||||||
nextProps.disabled !== this.props.disabled;
|
nextProps.disabled !== this.props.disabled
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
onChange = e => {
|
onChange = e => {
|
||||||
|
@ -25,7 +27,7 @@ export default class Slider extends Component {
|
||||||
const { label, sublabel, withValue, theme, ...rest } = this.props;
|
const { label, sublabel, withValue, theme, ...rest } = this.props;
|
||||||
const { value, max, min, disabled } = rest;
|
const { value, max, min, disabled } = rest;
|
||||||
const absMax = max - min;
|
const absMax = max - min;
|
||||||
const percent = (value - min) / absMax * 100;
|
const percent = ((value - min) / absMax) * 100;
|
||||||
const slider = <input {...rest} onChange={this.onChange} type="range" />;
|
const slider = <input {...rest} onChange={this.onChange} type="range" />;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -35,13 +37,19 @@ export default class Slider extends Component {
|
||||||
withLabel={!!label}
|
withLabel={!!label}
|
||||||
theme={theme}
|
theme={theme}
|
||||||
>
|
>
|
||||||
{label && <label>{label} {sublabel && <span>{sublabel}</span>}</label>}
|
{label && (
|
||||||
{!withValue ? slider :
|
<label>
|
||||||
|
{label} {sublabel && <span>{sublabel}</span>}
|
||||||
|
</label>
|
||||||
|
)}
|
||||||
|
{!withValue ? (
|
||||||
|
slider
|
||||||
|
) : (
|
||||||
<ContainerWithValue theme={theme}>
|
<ContainerWithValue theme={theme}>
|
||||||
{slider}
|
{slider}
|
||||||
<div>{value}</div>
|
<div>{value}</div>
|
||||||
</ContainerWithValue>
|
</ContainerWithValue>
|
||||||
}
|
)}
|
||||||
</SliderWrapper>
|
</SliderWrapper>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,9 +15,7 @@ export const Container = styled.div`
|
||||||
|
|
||||||
storiesOf('Slider', module)
|
storiesOf('Slider', module)
|
||||||
.addDecorator(withKnobs)
|
.addDecorator(withKnobs)
|
||||||
.add(
|
.add('default', () => (
|
||||||
'default',
|
|
||||||
() => (
|
|
||||||
<Container>
|
<Container>
|
||||||
<Slider
|
<Slider
|
||||||
value={number('value', 0)}
|
value={number('value', 0)}
|
||||||
|
@ -30,5 +28,4 @@ storiesOf('Slider', module)
|
||||||
onChange={action('slider changed')}
|
onChange={action('slider changed')}
|
||||||
/>
|
/>
|
||||||
</Container>
|
</Container>
|
||||||
)
|
));
|
||||||
);
|
|
||||||
|
|
|
@ -42,21 +42,32 @@ export const style = ({ theme, percent, disabled, withLabel }) => css`
|
||||||
border-radius: 0.8em/1.1em;
|
border-radius: 0.8em/1.1em;
|
||||||
font-size: 1em;
|
font-size: 1em;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
background: linear-gradient(${theme.base02}, ${theme.base00}) padding-box, 50% 50% border-box;
|
background: linear-gradient(${theme.base02}, ${
|
||||||
|
theme.base00
|
||||||
|
}) padding-box, 50% 50% border-box;
|
||||||
background-size: 100% 100%;
|
background-size: 100% 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
${prefixSelectors('input', ['webkit-slider-runnable-track', 'moz-range-track', 'ms-track'], `{
|
${prefixSelectors(
|
||||||
|
'input',
|
||||||
|
['webkit-slider-runnable-track', 'moz-range-track', 'ms-track'],
|
||||||
|
`{
|
||||||
position: relative;
|
position: relative;
|
||||||
height: 0.8em;
|
height: 0.8em;
|
||||||
border-radius: 0.5em;
|
border-radius: 0.5em;
|
||||||
box-shadow: 0 0 .125em ${theme.base04};
|
box-shadow: 0 0 .125em ${theme.base04};
|
||||||
background: linear-gradient(${theme.base01}, ${theme.base02} 40%, ${theme.base01})
|
background: linear-gradient(${theme.base01}, ${theme.base02} 40%, ${
|
||||||
|
theme.base01
|
||||||
|
})
|
||||||
no-repeat ${theme.base00};
|
no-repeat ${theme.base00};
|
||||||
background-size: ${percent}% 100%;
|
background-size: ${percent}% 100%;
|
||||||
}`)}
|
}`
|
||||||
|
)}
|
||||||
|
|
||||||
${prefixSelectors('input', ['webkit-slider-thumb', 'moz-range-thumb', 'ms-thumb'], `{
|
${prefixSelectors(
|
||||||
|
'input',
|
||||||
|
['webkit-slider-thumb', 'moz-range-thumb', 'ms-thumb'],
|
||||||
|
`{
|
||||||
position: relative;
|
position: relative;
|
||||||
appearance: none;
|
appearance: none;
|
||||||
cursor: ew-resize;
|
cursor: ew-resize;
|
||||||
|
@ -68,13 +79,16 @@ export const style = ({ theme, percent, disabled, withLabel }) => css`
|
||||||
height: 1.5em;
|
height: 1.5em;
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}`)}
|
}`
|
||||||
|
)}
|
||||||
|
|
||||||
${prefixSelectors('input:focus:not(:active)',
|
${prefixSelectors(
|
||||||
|
'input:focus:not(:active)',
|
||||||
['webkit-slider-thumb', 'moz-range-thumb', 'ms-thumb'],
|
['webkit-slider-thumb', 'moz-range-thumb', 'ms-thumb'],
|
||||||
`{
|
`{
|
||||||
box-shadow: 0 0 1px 2px ${theme.base0D};
|
box-shadow: 0 0 1px 2px ${theme.base0D};
|
||||||
}`)}
|
}`
|
||||||
|
)}
|
||||||
|
|
||||||
input::-moz-focus-outer {
|
input::-moz-focus-outer {
|
||||||
border: 0;
|
border: 0;
|
||||||
|
|
|
@ -19,7 +19,9 @@ export const style = ({ theme, percent, disabled, withLabel }) => css`
|
||||||
width: 100%;
|
width: 100%;
|
||||||
color: ${theme.base06};
|
color: ${theme.base06};
|
||||||
|
|
||||||
> span { color: ${theme.base04}; }
|
> span {
|
||||||
|
color: ${theme.base04};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
input {
|
input {
|
||||||
|
@ -32,8 +34,12 @@ export const style = ({ theme, percent, disabled, withLabel }) => css`
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
color: inherit;
|
color: inherit;
|
||||||
background-color: ${theme.base02};
|
background-color: ${theme.base02};
|
||||||
background-image:
|
background-image: linear-gradient(
|
||||||
linear-gradient(90deg, currentcolor, currentcolor ${percent}%, transparent ${percent}%);
|
90deg,
|
||||||
|
currentcolor,
|
||||||
|
currentcolor ${percent}%,
|
||||||
|
transparent ${percent}%
|
||||||
|
);
|
||||||
background-clip: content-box;
|
background-clip: content-box;
|
||||||
height: 0.5em;
|
height: 0.5em;
|
||||||
border-radius: 999px;
|
border-radius: 999px;
|
||||||
|
@ -41,7 +47,10 @@ export const style = ({ theme, percent, disabled, withLabel }) => css`
|
||||||
font-size: 1em;
|
font-size: 1em;
|
||||||
}
|
}
|
||||||
|
|
||||||
${prefixSelectors('input', ['webkit-slider-thumb', 'moz-range-thumb', 'ms-thumb'], `{
|
${prefixSelectors(
|
||||||
|
'input',
|
||||||
|
['webkit-slider-thumb', 'moz-range-thumb', 'ms-thumb'],
|
||||||
|
`{
|
||||||
width: 1.5em;
|
width: 1.5em;
|
||||||
height: 1.5em;
|
height: 1.5em;
|
||||||
background-image: none;
|
background-image: none;
|
||||||
|
@ -53,14 +62,17 @@ export const style = ({ theme, percent, disabled, withLabel }) => css`
|
||||||
border 0.18s ${animationCurve},
|
border 0.18s ${animationCurve},
|
||||||
box-shadow 0.18s ${animationCurve},
|
box-shadow 0.18s ${animationCurve},
|
||||||
background 0.28s ${animationCurve};
|
background 0.28s ${animationCurve};
|
||||||
}`)}
|
}`
|
||||||
|
)}
|
||||||
|
|
||||||
${prefixSelectors('input:focus:not(:active)',
|
${prefixSelectors(
|
||||||
|
'input:focus:not(:active)',
|
||||||
['webkit-slider-thumb', 'moz-range-thumb', 'ms-thumb'],
|
['webkit-slider-thumb', 'moz-range-thumb', 'ms-thumb'],
|
||||||
`{
|
`{
|
||||||
box-shadow: 0 0 0 8px ${color(theme.base0D, 'alpha', 0.5)};
|
box-shadow: 0 0 0 8px ${color(theme.base0D, 'alpha', 0.5)};
|
||||||
transform: scale(1.2);
|
transform: scale(1.2);
|
||||||
}`)}
|
}`
|
||||||
|
)}
|
||||||
|
|
||||||
input::-moz-focus-outer {
|
input::-moz-focus-outer {
|
||||||
border: 0;
|
border: 0;
|
||||||
|
|
|
@ -75,7 +75,9 @@ export default class Tabs extends Component {
|
||||||
return (
|
return (
|
||||||
<TabsContainer position={this.props.position}>
|
<TabsContainer position={this.props.position}>
|
||||||
{tabsHeader}
|
{tabsHeader}
|
||||||
<div><this.SelectedComponent {...(this.selector && this.selector())} /></div>
|
<div>
|
||||||
|
<this.SelectedComponent {...this.selector && this.selector()} />
|
||||||
|
</div>
|
||||||
</TabsContainer>
|
</TabsContainer>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,9 +22,11 @@ export default class TabsHeader extends Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillReceiveProps(nextProps) {
|
componentWillReceiveProps(nextProps) {
|
||||||
if (nextProps.tabs !== this.props.tabs ||
|
if (
|
||||||
|
nextProps.tabs !== this.props.tabs ||
|
||||||
nextProps.selected !== this.props.selected ||
|
nextProps.selected !== this.props.selected ||
|
||||||
nextProps.collapsible !== this.props.collapsible) {
|
nextProps.collapsible !== this.props.collapsible
|
||||||
|
) {
|
||||||
this.setState({ hiddenTabs: [], visibleTabs: nextProps.tabs.slice() });
|
this.setState({ hiddenTabs: [], visibleTabs: nextProps.tabs.slice() });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -47,7 +49,9 @@ export default class TabsHeader extends Component {
|
||||||
if (this.iconWidth === 0) {
|
if (this.iconWidth === 0) {
|
||||||
const tabButtons = this.tabsRef.children;
|
const tabButtons = this.tabsRef.children;
|
||||||
if (this.tabsRef.children[tabButtons.length - 1].value === 'expandIcon') {
|
if (this.tabsRef.children[tabButtons.length - 1].value === 'expandIcon') {
|
||||||
this.iconWidth = tabButtons[tabButtons.length - 1].getBoundingClientRect().width;
|
this.iconWidth = tabButtons[
|
||||||
|
tabButtons.length - 1
|
||||||
|
].getBoundingClientRect().width;
|
||||||
shouldCollapse = true;
|
shouldCollapse = true;
|
||||||
}
|
}
|
||||||
} else if (this.state.hiddenTabs.length === 0) {
|
} else if (this.state.hiddenTabs.length === 0) {
|
||||||
|
@ -96,7 +100,8 @@ export default class TabsHeader extends Component {
|
||||||
|
|
||||||
if (tabsRefRight >= tabsWrapperRight - this.iconWidth) {
|
if (tabsRefRight >= tabsWrapperRight - this.iconWidth) {
|
||||||
if (
|
if (
|
||||||
this.props.position === 'right' && hiddenTabs.length > 0 &&
|
this.props.position === 'right' &&
|
||||||
|
hiddenTabs.length > 0 &&
|
||||||
tabsRef.getBoundingClientRect().width + this.hiddenTabsWidth[0] <
|
tabsRef.getBoundingClientRect().width + this.hiddenTabsWidth[0] <
|
||||||
tabsWrapperRef.getBoundingClientRect().width
|
tabsWrapperRef.getBoundingClientRect().width
|
||||||
) {
|
) {
|
||||||
|
@ -111,12 +116,16 @@ export default class TabsHeader extends Component {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
while (
|
while (
|
||||||
i > 0 && tabButtons[i] &&
|
i > 0 &&
|
||||||
tabButtons[i].getBoundingClientRect().right >= tabsWrapperRight - this.iconWidth
|
tabButtons[i] &&
|
||||||
|
tabButtons[i].getBoundingClientRect().right >=
|
||||||
|
tabsWrapperRight - this.iconWidth
|
||||||
) {
|
) {
|
||||||
if (tabButtons[i].value !== selected) {
|
if (tabButtons[i].value !== selected) {
|
||||||
hiddenTabs.unshift(...visibleTabs.splice(i, 1));
|
hiddenTabs.unshift(...visibleTabs.splice(i, 1));
|
||||||
this.hiddenTabsWidth.unshift(tabButtons[i].getBoundingClientRect().width);
|
this.hiddenTabsWidth.unshift(
|
||||||
|
tabButtons[i].getBoundingClientRect().width
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
tabsWrapperRight -= tabButtons[i].getBoundingClientRect().width;
|
tabsWrapperRight -= tabButtons[i].getBoundingClientRect().width;
|
||||||
}
|
}
|
||||||
|
@ -125,9 +134,10 @@ export default class TabsHeader extends Component {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
while (
|
while (
|
||||||
i < tabs.length - 1 && tabButtons[i] &&
|
i < tabs.length - 1 &&
|
||||||
tabButtons[i].getBoundingClientRect().right +
|
tabButtons[i] &&
|
||||||
this.hiddenTabsWidth[0] < tabsWrapperRight - this.iconWidth
|
tabButtons[i].getBoundingClientRect().right + this.hiddenTabsWidth[0] <
|
||||||
|
tabsWrapperRight - this.iconWidth
|
||||||
) {
|
) {
|
||||||
hiddenTab = hiddenTabs.shift();
|
hiddenTab = hiddenTabs.shift();
|
||||||
visibleTabs.splice(Number(hiddenTab.key), 0, hiddenTab);
|
visibleTabs.splice(Number(hiddenTab.key), 0, hiddenTab);
|
||||||
|
@ -150,7 +160,7 @@ export default class TabsHeader extends Component {
|
||||||
this.tabsRef = node;
|
this.tabsRef = node;
|
||||||
};
|
};
|
||||||
|
|
||||||
expandMenu = (e) => {
|
expandMenu = e => {
|
||||||
const rect = e.currentTarget.children[0].getBoundingClientRect();
|
const rect = e.currentTarget.children[0].getBoundingClientRect();
|
||||||
this.setState({
|
this.setState({
|
||||||
contextMenu: {
|
contextMenu: {
|
||||||
|
@ -171,11 +181,14 @@ export default class TabsHeader extends Component {
|
||||||
>
|
>
|
||||||
<div ref={this.getTabsRef}>
|
<div ref={this.getTabsRef}>
|
||||||
{visibleTabs}
|
{visibleTabs}
|
||||||
{this.props.collapsible && visibleTabs.length < this.props.items.length &&
|
{this.props.collapsible &&
|
||||||
<button onClick={this.expandMenu} value="expandIcon"><CollapseIcon /></button>
|
visibleTabs.length < this.props.items.length && (
|
||||||
}
|
<button onClick={this.expandMenu} value="expandIcon">
|
||||||
|
<CollapseIcon />
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
{this.props.collapsible && contextMenu &&
|
{this.props.collapsible && contextMenu && (
|
||||||
<ContextMenu
|
<ContextMenu
|
||||||
items={hiddenTabs}
|
items={hiddenTabs}
|
||||||
onClick={this.props.onClick}
|
onClick={this.props.onClick}
|
||||||
|
@ -183,7 +196,7 @@ export default class TabsHeader extends Component {
|
||||||
y={contextMenu.top}
|
y={contextMenu.top}
|
||||||
visible={this.state.subMenuOpened}
|
visible={this.state.subMenuOpened}
|
||||||
/>
|
/>
|
||||||
}
|
)}
|
||||||
</TabsWrapper>
|
</TabsWrapper>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -198,4 +211,3 @@ TabsHeader.propTypes = {
|
||||||
collapsible: PropTypes.bool,
|
collapsible: PropTypes.bool,
|
||||||
selected: PropTypes.string
|
selected: PropTypes.string
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -38,4 +38,5 @@ export const tabs = [
|
||||||
];
|
];
|
||||||
|
|
||||||
export const simple10Tabs = [];
|
export const simple10Tabs = [];
|
||||||
for (let i = 1; i <= 10; i++) simple10Tabs.push({ name: `Tab${i}`, value: `${i}` });
|
for (let i = 1; i <= 10; i++)
|
||||||
|
simple10Tabs.push({ name: `Tab${i}`, value: `${i}` });
|
||||||
|
|
|
@ -16,22 +16,19 @@ const Container = styled.div`
|
||||||
|
|
||||||
storiesOf('Tabs', module)
|
storiesOf('Tabs', module)
|
||||||
.addDecorator(withKnobs)
|
.addDecorator(withKnobs)
|
||||||
.add(
|
.add('default', () => (
|
||||||
'default',
|
<Container>
|
||||||
() => (
|
<Tabs
|
||||||
<Container><Tabs
|
|
||||||
tabs={simple10Tabs}
|
tabs={simple10Tabs}
|
||||||
selected={text('selected', '2')}
|
selected={text('selected', '2')}
|
||||||
main={boolean('main', true)}
|
main={boolean('main', true)}
|
||||||
onClick={action('tab selected')}
|
onClick={action('tab selected')}
|
||||||
collapsible={boolean('collapsible', true)}
|
collapsible={boolean('collapsible', true)}
|
||||||
position={select('position', ['left', 'right', 'center'], 'left')}
|
position={select('position', ['left', 'right', 'center'], 'left')}
|
||||||
/></Container>
|
/>
|
||||||
)
|
</Container>
|
||||||
)
|
))
|
||||||
.add(
|
.add('with content', () => (
|
||||||
'with content',
|
|
||||||
() => (
|
|
||||||
<Tabs
|
<Tabs
|
||||||
tabs={tabs}
|
tabs={tabs}
|
||||||
selected={text('selected', 'Tab2')}
|
selected={text('selected', 'Tab2')}
|
||||||
|
@ -40,5 +37,4 @@ storiesOf('Tabs', module)
|
||||||
collapsible={boolean('collapsible', false)}
|
collapsible={boolean('collapsible', false)}
|
||||||
position={select('position', ['left', 'right', 'center'], 'left')}
|
position={select('position', ['left', 'right', 'center'], 'left')}
|
||||||
/>
|
/>
|
||||||
)
|
));
|
||||||
);
|
|
||||||
|
|
|
@ -11,10 +11,14 @@ export const TabsContainer = styled.div`
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
|
||||||
> div > div:first-child {
|
> div > div:first-child {
|
||||||
${props => props.position !== 'left' && `
|
${props =>
|
||||||
|
props.position !== 'left' &&
|
||||||
|
`
|
||||||
margin-left: auto !important;
|
margin-left: auto !important;
|
||||||
`}
|
`}
|
||||||
${props => props.position === 'center' && `
|
${props =>
|
||||||
|
props.position === 'center' &&
|
||||||
|
`
|
||||||
margin-right: auto !important;
|
margin-right: auto !important;
|
||||||
`}
|
`}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,8 @@ export const style = ({ theme, main }) => css`
|
||||||
background-color: ${theme.base01};
|
background-color: ${theme.base01};
|
||||||
width: 100%;
|
width: 100%;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
${!main && `
|
${!main &&
|
||||||
|
`
|
||||||
border-top: 1px solid ${theme.base01};
|
border-top: 1px solid ${theme.base01};
|
||||||
border-bottom: 1px solid ${theme.base02};
|
border-bottom: 1px solid ${theme.base02};
|
||||||
`}
|
`}
|
||||||
|
@ -39,9 +40,10 @@ export const style = ({ theme, main }) => css`
|
||||||
}
|
}
|
||||||
|
|
||||||
> [data-selected] {
|
> [data-selected] {
|
||||||
${main ?
|
${
|
||||||
`border-bottom: 2px solid ${theme.base0D};` :
|
main
|
||||||
`
|
? `border-bottom: 2px solid ${theme.base0D};`
|
||||||
|
: `
|
||||||
background-color: ${theme.base00};
|
background-color: ${theme.base00};
|
||||||
border: 1px solid ${theme.base02};
|
border: 1px solid ${theme.base02};
|
||||||
border-bottom: 1px solid ${theme.base00};
|
border-bottom: 1px solid ${theme.base00};
|
||||||
|
|
|
@ -8,7 +8,8 @@ export const style = ({ theme, main }) => css`
|
||||||
background-color: ${theme.base01};
|
background-color: ${theme.base01};
|
||||||
width: 100%;
|
width: 100%;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
${!main && `
|
${!main &&
|
||||||
|
`
|
||||||
border-top: 1px solid ${theme.base01};
|
border-top: 1px solid ${theme.base01};
|
||||||
border-bottom: 1px solid ${theme.base02};
|
border-bottom: 1px solid ${theme.base02};
|
||||||
`}
|
`}
|
||||||
|
|
|
@ -2,12 +2,27 @@ import React from 'react';
|
||||||
import { storiesOf } from '@storybook/react';
|
import { storiesOf } from '@storybook/react';
|
||||||
import { action } from '@storybook/addon-actions';
|
import { action } from '@storybook/addon-actions';
|
||||||
import styled from 'styled-components';
|
import styled from 'styled-components';
|
||||||
import { withKnobs, text, number, boolean, select } from '@storybook/addon-knobs';
|
import {
|
||||||
|
withKnobs,
|
||||||
|
text,
|
||||||
|
number,
|
||||||
|
boolean,
|
||||||
|
select
|
||||||
|
} from '@storybook/addon-knobs';
|
||||||
import PlayIcon from 'react-icons/lib/md/play-arrow';
|
import PlayIcon from 'react-icons/lib/md/play-arrow';
|
||||||
import RecordIcon from 'react-icons/lib/md/fiber-manual-record';
|
import RecordIcon from 'react-icons/lib/md/fiber-manual-record';
|
||||||
import LeftIcon from 'react-icons/lib/md/keyboard-arrow-left';
|
import LeftIcon from 'react-icons/lib/md/keyboard-arrow-left';
|
||||||
import RightIcon from 'react-icons/lib/md/keyboard-arrow-right';
|
import RightIcon from 'react-icons/lib/md/keyboard-arrow-right';
|
||||||
import { Toolbar, Divider, Spacer, Button, Select, Slider, SegmentedControl, Tabs } from '../../';
|
import {
|
||||||
|
Toolbar,
|
||||||
|
Divider,
|
||||||
|
Spacer,
|
||||||
|
Button,
|
||||||
|
Select,
|
||||||
|
Slider,
|
||||||
|
SegmentedControl,
|
||||||
|
Tabs
|
||||||
|
} from '../../';
|
||||||
import { options } from '../../Select/stories/options';
|
import { options } from '../../Select/stories/options';
|
||||||
import { simple10Tabs } from '../../Tabs/stories/data';
|
import { simple10Tabs } from '../../Tabs/stories/data';
|
||||||
|
|
||||||
|
@ -26,17 +41,21 @@ export const SliderContainer = styled.div`
|
||||||
|
|
||||||
storiesOf('Toolbar', module)
|
storiesOf('Toolbar', module)
|
||||||
.addDecorator(withKnobs)
|
.addDecorator(withKnobs)
|
||||||
.add(
|
.add('default', () => (
|
||||||
'default',
|
|
||||||
() => (
|
|
||||||
<Container>
|
<Container>
|
||||||
<Toolbar borderPosition={select('borderPosition', ['top', 'bottom'])}>
|
<Toolbar borderPosition={select('borderPosition', ['top', 'bottom'])}>
|
||||||
<Button
|
<Button
|
||||||
title={text('Title', 'Hello Tooltip')}
|
title={text('Title', 'Hello Tooltip')}
|
||||||
tooltipPosition={
|
tooltipPosition={select('tooltipPosition', [
|
||||||
select('tooltipPosition', ['top', 'bottom', 'left', 'right',
|
'top',
|
||||||
'bottom-left', 'bottom-right', 'top-left', 'top-right'])
|
'bottom',
|
||||||
}
|
'left',
|
||||||
|
'right',
|
||||||
|
'bottom-left',
|
||||||
|
'bottom-right',
|
||||||
|
'top-left',
|
||||||
|
'top-right'
|
||||||
|
])}
|
||||||
disabled={boolean('Disabled', false)}
|
disabled={boolean('Disabled', false)}
|
||||||
onClick={action('button clicked')}
|
onClick={action('button clicked')}
|
||||||
>
|
>
|
||||||
|
@ -45,10 +64,16 @@ storiesOf('Toolbar', module)
|
||||||
<Divider />
|
<Divider />
|
||||||
<Button
|
<Button
|
||||||
title={text('Title', 'Hello Tooltip')}
|
title={text('Title', 'Hello Tooltip')}
|
||||||
tooltipPosition={
|
tooltipPosition={select('tooltipPosition', [
|
||||||
select('tooltipPosition', ['top', 'bottom', 'left', 'right',
|
'top',
|
||||||
'bottom-left', 'bottom-right', 'top-left', 'top-right'])
|
'bottom',
|
||||||
}
|
'left',
|
||||||
|
'right',
|
||||||
|
'bottom-left',
|
||||||
|
'bottom-right',
|
||||||
|
'top-left',
|
||||||
|
'top-right'
|
||||||
|
])}
|
||||||
disabled={boolean('Disabled', false)}
|
disabled={boolean('Disabled', false)}
|
||||||
onClick={action('button clicked')}
|
onClick={action('button clicked')}
|
||||||
>
|
>
|
||||||
|
@ -59,19 +84,22 @@ storiesOf('Toolbar', module)
|
||||||
<Select options={options} />
|
<Select options={options} />
|
||||||
</Toolbar>
|
</Toolbar>
|
||||||
</Container>
|
</Container>
|
||||||
)
|
))
|
||||||
)
|
.add('tabs', () => (
|
||||||
.add(
|
|
||||||
'tabs',
|
|
||||||
() => (
|
|
||||||
<Container>
|
<Container>
|
||||||
<Toolbar>
|
<Toolbar>
|
||||||
<Button
|
<Button
|
||||||
title={text('Title', 'Hello Tooltip')}
|
title={text('Title', 'Hello Tooltip')}
|
||||||
tooltipPosition={
|
tooltipPosition={select('tooltipPosition', [
|
||||||
select('tooltipPosition', ['top', 'bottom', 'left', 'right',
|
'top',
|
||||||
'bottom-left', 'bottom-right', 'top-left', 'top-right'])
|
'bottom',
|
||||||
}
|
'left',
|
||||||
|
'right',
|
||||||
|
'bottom-left',
|
||||||
|
'bottom-right',
|
||||||
|
'top-left',
|
||||||
|
'top-right'
|
||||||
|
])}
|
||||||
disabled={boolean('Disabled', false)}
|
disabled={boolean('Disabled', false)}
|
||||||
onClick={action('button clicked')}
|
onClick={action('button clicked')}
|
||||||
>
|
>
|
||||||
|
@ -87,10 +115,16 @@ storiesOf('Toolbar', module)
|
||||||
/>
|
/>
|
||||||
<Button
|
<Button
|
||||||
title={text('Title', 'Hello Tooltip')}
|
title={text('Title', 'Hello Tooltip')}
|
||||||
tooltipPosition={
|
tooltipPosition={select('tooltipPosition', [
|
||||||
select('tooltipPosition', ['top', 'bottom', 'left', 'right',
|
'top',
|
||||||
'bottom-left', 'bottom-right', 'top-left', 'top-right'])
|
'bottom',
|
||||||
}
|
'left',
|
||||||
|
'right',
|
||||||
|
'bottom-left',
|
||||||
|
'bottom-right',
|
||||||
|
'top-left',
|
||||||
|
'top-right'
|
||||||
|
])}
|
||||||
disabled={boolean('Disabled', false)}
|
disabled={boolean('Disabled', false)}
|
||||||
onClick={action('button clicked')}
|
onClick={action('button clicked')}
|
||||||
>
|
>
|
||||||
|
@ -98,20 +132,23 @@ storiesOf('Toolbar', module)
|
||||||
</Button>
|
</Button>
|
||||||
</Toolbar>
|
</Toolbar>
|
||||||
</Container>
|
</Container>
|
||||||
)
|
))
|
||||||
)
|
.add('with slider', () => (
|
||||||
.add(
|
|
||||||
'with slider',
|
|
||||||
() => (
|
|
||||||
<Container>
|
<Container>
|
||||||
<SliderContainer>
|
<SliderContainer>
|
||||||
<Toolbar noBorder fullHeight compact>
|
<Toolbar noBorder fullHeight compact>
|
||||||
<Button
|
<Button
|
||||||
title={text('play title', 'Play')}
|
title={text('play title', 'Play')}
|
||||||
tooltipPosition={
|
tooltipPosition={select('tooltipPosition', [
|
||||||
select('tooltipPosition', ['top', 'bottom', 'left', 'right',
|
'top',
|
||||||
'bottom-left', 'bottom-right', 'top-left', 'top-right'])
|
'bottom',
|
||||||
}
|
'left',
|
||||||
|
'right',
|
||||||
|
'bottom-left',
|
||||||
|
'bottom-right',
|
||||||
|
'top-left',
|
||||||
|
'top-right'
|
||||||
|
])}
|
||||||
onClick={action('button clicked')}
|
onClick={action('button clicked')}
|
||||||
>
|
>
|
||||||
<PlayIcon />
|
<PlayIcon />
|
||||||
|
@ -126,10 +163,16 @@ storiesOf('Toolbar', module)
|
||||||
/>
|
/>
|
||||||
<Button
|
<Button
|
||||||
title="Previous state"
|
title="Previous state"
|
||||||
tooltipPosition={
|
tooltipPosition={select('tooltipPosition', [
|
||||||
select('tooltipPosition', ['top', 'bottom', 'left', 'right',
|
'top',
|
||||||
'bottom-left', 'bottom-right', 'top-left', 'top-right'])
|
'bottom',
|
||||||
}
|
'left',
|
||||||
|
'right',
|
||||||
|
'bottom-left',
|
||||||
|
'bottom-right',
|
||||||
|
'top-left',
|
||||||
|
'top-right'
|
||||||
|
])}
|
||||||
disabled
|
disabled
|
||||||
onClick={action('previous state clicked')}
|
onClick={action('previous state clicked')}
|
||||||
>
|
>
|
||||||
|
@ -137,10 +180,16 @@ storiesOf('Toolbar', module)
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
title="Next state"
|
title="Next state"
|
||||||
tooltipPosition={
|
tooltipPosition={select('tooltipPosition', [
|
||||||
select('tooltipPosition', ['top', 'bottom', 'left', 'right',
|
'top',
|
||||||
'bottom-left', 'bottom-right', 'top-left', 'top-right'])
|
'bottom',
|
||||||
}
|
'left',
|
||||||
|
'right',
|
||||||
|
'bottom-left',
|
||||||
|
'bottom-right',
|
||||||
|
'top-left',
|
||||||
|
'top-right'
|
||||||
|
])}
|
||||||
onClick={action('next state clicked')}
|
onClick={action('next state clicked')}
|
||||||
>
|
>
|
||||||
<RightIcon />
|
<RightIcon />
|
||||||
|
@ -153,5 +202,4 @@ storiesOf('Toolbar', module)
|
||||||
</Toolbar>
|
</Toolbar>
|
||||||
</SliderContainer>
|
</SliderContainer>
|
||||||
</Container>
|
</Container>
|
||||||
)
|
));
|
||||||
);
|
|
||||||
|
|
|
@ -14,8 +14,7 @@ const Toolbar = styled.div`
|
||||||
text-align: center;
|
text-align: center;
|
||||||
position: relative;
|
position: relative;
|
||||||
${({ borderPosition, theme }) =>
|
${({ borderPosition, theme }) =>
|
||||||
borderPosition && `border-${borderPosition}: 1px solid ${theme.base02};`
|
borderPosition && `border-${borderPosition}: 1px solid ${theme.base02};`}
|
||||||
}
|
|
||||||
|
|
||||||
& > div {
|
& > div {
|
||||||
margin: auto ${props => (props.noBorder ? '0' : '1px;')};
|
margin: auto ${props => (props.noBorder ? '0' : '1px;')};
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
export default (colors) => ({
|
export default colors => ({
|
||||||
...colors,
|
...colors,
|
||||||
fontFamily: "'Source Sans Pro', sans-serif",
|
fontFamily: "'Source Sans Pro', sans-serif",
|
||||||
codeFontFamily: "'Source Code Pro', monospace",
|
codeFontFamily: "'Source Code Pro', monospace",
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
export default (colors) => ({
|
export default colors => ({
|
||||||
fontFamily: "'Roboto', sans-serif",
|
fontFamily: "'Roboto', sans-serif",
|
||||||
codeFontFamily: "'Roboto Mono', monospace",
|
codeFontFamily: "'Roboto Mono', monospace",
|
||||||
inputPadding: 5,
|
inputPadding: 5,
|
||||||
|
|
|
@ -36,7 +36,9 @@ export const ripple = theme => `
|
||||||
top: 0;
|
top: 0;
|
||||||
left: 0;
|
left: 0;
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
background-image: radial-gradient(circle, ${theme.base07} 11%, transparent 11%);
|
background-image: radial-gradient(circle, ${
|
||||||
|
theme.base07
|
||||||
|
} 11%, transparent 11%);
|
||||||
background-repeat: no-repeat;
|
background-repeat: no-repeat;
|
||||||
background-position: 50%;
|
background-position: 50%;
|
||||||
transform: scale(10, 10);
|
transform: scale(10, 10);
|
||||||
|
|
|
@ -7,6 +7,10 @@ import Color from 'color';
|
||||||
effect('#000000', 'alpha', 0.5);
|
effect('#000000', 'alpha', 0.5);
|
||||||
*/
|
*/
|
||||||
|
|
||||||
export default (color, effect, val) => new Color(color)[effect](val).hsl().string();
|
export default (color, effect, val) =>
|
||||||
|
new Color(color)
|
||||||
|
[effect](val)
|
||||||
|
.hsl()
|
||||||
|
.string();
|
||||||
|
|
||||||
// TODO: memoize it
|
// TODO: memoize it
|
||||||
|
|
|
@ -1,17 +1,19 @@
|
||||||
import styled from 'styled-components';
|
import styled from 'styled-components';
|
||||||
import getDefaultTheme from '../themes/default';
|
import getDefaultTheme from '../themes/default';
|
||||||
|
|
||||||
const getStyle = (styles, type) => (
|
const getStyle = (styles, type) =>
|
||||||
typeof styles === 'object' ? styles[type] || styles.default : styles
|
typeof styles === 'object' ? styles[type] || styles.default : styles;
|
||||||
);
|
|
||||||
|
|
||||||
export default (styles, component) =>
|
export default (styles, component) =>
|
||||||
styled(component || 'div')`${
|
styled(component || 'div')`
|
||||||
props => (
|
${props =>
|
||||||
props.theme.type ? getStyle(styles, props.theme.type) :
|
props.theme.type
|
||||||
// used outside of container (theme provider)
|
? getStyle(styles, props.theme.type)
|
||||||
getStyle(styles, 'default')({ ...props, theme: getDefaultTheme(props.theme) })
|
: // used outside of container (theme provider)
|
||||||
)
|
getStyle(styles, 'default')({
|
||||||
}`;
|
...props,
|
||||||
|
theme: getDefaultTheme(props.theme)
|
||||||
|
})}
|
||||||
|
`;
|
||||||
|
|
||||||
// TODO: memoize it?
|
// TODO: memoize it?
|
||||||
|
|
|
@ -5,7 +5,10 @@ import * as additionalSchemes from '../colorSchemes';
|
||||||
import invertColors from '../utils/invertColors';
|
import invertColors from '../utils/invertColors';
|
||||||
|
|
||||||
export const schemes = { ...baseSchemes, ...additionalSchemes };
|
export const schemes = { ...baseSchemes, ...additionalSchemes };
|
||||||
export const listSchemes = () => Object.keys(schemes).slice(1).sort(); // remove `__esModule`
|
export const listSchemes = () =>
|
||||||
|
Object.keys(schemes)
|
||||||
|
.slice(1)
|
||||||
|
.sort(); // remove `__esModule`
|
||||||
export const listThemes = () => Object.keys(themes);
|
export const listThemes = () => Object.keys(themes);
|
||||||
|
|
||||||
export const getTheme = ({ theme: type, scheme, light }) => {
|
export const getTheme = ({ theme: type, scheme, light }) => {
|
||||||
|
|
|
@ -6,7 +6,9 @@ import { Container } from '../src';
|
||||||
describe('Container', function() {
|
describe('Container', function() {
|
||||||
it('renders correctly', () => {
|
it('renders correctly', () => {
|
||||||
const wrapper = render(
|
const wrapper = render(
|
||||||
<Container themeData={{ theme: 'default', scheme: 'default', invert: false }}>
|
<Container
|
||||||
|
themeData={{ theme: 'default', scheme: 'default', invert: false }}
|
||||||
|
>
|
||||||
Text
|
Text
|
||||||
</Container>
|
</Container>
|
||||||
);
|
);
|
||||||
|
|
|
@ -7,26 +7,20 @@ import { items } from '../src/ContextMenu/stories/data';
|
||||||
describe('ContextMenu', function() {
|
describe('ContextMenu', function() {
|
||||||
it('renders correctly', () => {
|
it('renders correctly', () => {
|
||||||
const wrapper = render(
|
const wrapper = render(
|
||||||
<ContextMenu
|
<ContextMenu items={items} onClick={() => {}} x={100} y={100} />
|
||||||
items={items}
|
|
||||||
onClick={() => {}}
|
|
||||||
x={100}
|
|
||||||
y={100}
|
|
||||||
/>
|
|
||||||
);
|
);
|
||||||
expect(renderToJson(wrapper)).toMatchSnapshot();
|
expect(renderToJson(wrapper)).toMatchSnapshot();
|
||||||
});
|
});
|
||||||
it('should handle the click event', () => {
|
it('should handle the click event', () => {
|
||||||
const onClick = jest.fn();
|
const onClick = jest.fn();
|
||||||
const wrapper = mount(
|
const wrapper = mount(
|
||||||
<ContextMenu
|
<ContextMenu items={items} onClick={onClick} x={100} y={100} />
|
||||||
items={items}
|
);
|
||||||
onClick={onClick}
|
|
||||||
x={100}
|
|
||||||
y={100}
|
|
||||||
/>);
|
|
||||||
|
|
||||||
wrapper.find('button').first().simulate('click');
|
wrapper
|
||||||
|
.find('button')
|
||||||
|
.first()
|
||||||
|
.simulate('click');
|
||||||
expect(onClick).toBeCalled();
|
expect(onClick).toBeCalled();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -11,11 +11,7 @@ describe('Dialog', function () {
|
||||||
|
|
||||||
it('renders with props', () => {
|
it('renders with props', () => {
|
||||||
const wrapper = render(
|
const wrapper = render(
|
||||||
<Dialog
|
<Dialog title="Dialog Title" open fullWidth>
|
||||||
title="Dialog Title"
|
|
||||||
open
|
|
||||||
fullWidth
|
|
||||||
>
|
|
||||||
Hello Dialog!
|
Hello Dialog!
|
||||||
</Dialog>
|
</Dialog>
|
||||||
);
|
);
|
||||||
|
@ -31,7 +27,10 @@ describe('Dialog', function () {
|
||||||
const onDismiss = jest.fn();
|
const onDismiss = jest.fn();
|
||||||
const wrapper = mount(<Dialog open onDismiss={onDismiss} />);
|
const wrapper = mount(<Dialog open onDismiss={onDismiss} />);
|
||||||
|
|
||||||
wrapper.find('button').first().simulate('click');
|
wrapper
|
||||||
|
.find('button')
|
||||||
|
.first()
|
||||||
|
.simulate('click');
|
||||||
expect(onDismiss).toBeCalled();
|
expect(onDismiss).toBeCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -39,7 +38,10 @@ describe('Dialog', function () {
|
||||||
const onSubmit = jest.fn();
|
const onSubmit = jest.fn();
|
||||||
const wrapper = mount(<Dialog open onSubmit={onSubmit} />);
|
const wrapper = mount(<Dialog open onSubmit={onSubmit} />);
|
||||||
|
|
||||||
wrapper.find('button').last().simulate('click');
|
wrapper
|
||||||
|
.find('button')
|
||||||
|
.last()
|
||||||
|
.simulate('click');
|
||||||
expect(onSubmit).toBeCalled();
|
expect(onSubmit).toBeCalled();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -7,11 +7,8 @@ import { schema, uiSchema, formData } from '../src/Form/stories/schema';
|
||||||
describe('Form', function() {
|
describe('Form', function() {
|
||||||
it('renders correctly', () => {
|
it('renders correctly', () => {
|
||||||
const wrapper = shallow(
|
const wrapper = shallow(
|
||||||
<Form
|
<Form formData={formData} schema={schema} uiSchema={uiSchema} />
|
||||||
formData={formData}
|
);
|
||||||
schema={schema}
|
|
||||||
uiSchema={uiSchema}
|
|
||||||
/>);
|
|
||||||
expect(shallowToJson(wrapper)).toMatchSnapshot();
|
expect(shallowToJson(wrapper)).toMatchSnapshot();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -23,18 +20,15 @@ describe('Form', function () {
|
||||||
formData={formData}
|
formData={formData}
|
||||||
schema={schema}
|
schema={schema}
|
||||||
uiSchema={uiSchema}
|
uiSchema={uiSchema}
|
||||||
/>);
|
/>
|
||||||
|
);
|
||||||
expect(shallowToJson(wrapper)).toMatchSnapshot();
|
expect(shallowToJson(wrapper)).toMatchSnapshot();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('renders with no button', () => {
|
it('renders with no button', () => {
|
||||||
const wrapper = shallow(
|
const wrapper = shallow(
|
||||||
<Form
|
<Form formData={formData} schema={schema} uiSchema={uiSchema} noSubmit />
|
||||||
formData={formData}
|
);
|
||||||
schema={schema}
|
|
||||||
uiSchema={uiSchema}
|
|
||||||
noSubmit
|
|
||||||
/>);
|
|
||||||
expect(shallowToJson(wrapper)).toMatchSnapshot();
|
expect(shallowToJson(wrapper)).toMatchSnapshot();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -11,14 +11,18 @@ describe('Notification', function () {
|
||||||
|
|
||||||
it('renders with props', () => {
|
it('renders with props', () => {
|
||||||
const wrapper = render(
|
const wrapper = render(
|
||||||
<Notification type="error" onClose={() => {}}>Message</Notification>
|
<Notification type="error" onClose={() => {}}>
|
||||||
|
Message
|
||||||
|
</Notification>
|
||||||
);
|
);
|
||||||
expect(renderToJson(wrapper)).toMatchSnapshot();
|
expect(renderToJson(wrapper)).toMatchSnapshot();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should handle the click event', () => {
|
it('should handle the click event', () => {
|
||||||
const onClose = jest.fn();
|
const onClose = jest.fn();
|
||||||
const wrapper = mount(<Notification onClose={onClose}>Message</Notification>);
|
const wrapper = mount(
|
||||||
|
<Notification onClose={onClose}>Message</Notification>
|
||||||
|
);
|
||||||
|
|
||||||
wrapper.find('button').simulate('click');
|
wrapper.find('button').simulate('click');
|
||||||
expect(onClose).toBeCalled();
|
expect(onClose).toBeCalled();
|
||||||
|
|
|
@ -17,7 +17,8 @@ describe('SegmentedControl', function () {
|
||||||
});
|
});
|
||||||
it('should handle the click event', () => {
|
it('should handle the click event', () => {
|
||||||
const onClick = jest.fn();
|
const onClick = jest.fn();
|
||||||
const wrapper = mount(<SegmentedControl
|
const wrapper = mount(
|
||||||
|
<SegmentedControl
|
||||||
values={['Button1', 'Button2', 'Button3']}
|
values={['Button1', 'Button2', 'Button3']}
|
||||||
selected="Button1"
|
selected="Button1"
|
||||||
disabled={false}
|
disabled={false}
|
||||||
|
@ -25,7 +26,10 @@ describe('SegmentedControl', function () {
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|
||||||
wrapper.find('button').first().simulate('click');
|
wrapper
|
||||||
|
.find('button')
|
||||||
|
.first()
|
||||||
|
.simulate('click');
|
||||||
expect(onClick).toBeCalled();
|
expect(onClick).toBeCalled();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -12,22 +12,14 @@ describe('Tabs', function () {
|
||||||
|
|
||||||
it('renders with props', () => {
|
it('renders with props', () => {
|
||||||
const wrapper = render(
|
const wrapper = render(
|
||||||
<Tabs
|
<Tabs tabs={tabs} onClick={() => {}} selected="Tab2" />
|
||||||
tabs={tabs}
|
|
||||||
onClick={() => {}}
|
|
||||||
selected="Tab2"
|
|
||||||
/>
|
|
||||||
);
|
);
|
||||||
expect(renderToJson(wrapper)).toMatchSnapshot();
|
expect(renderToJson(wrapper)).toMatchSnapshot();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('renders tabs without inner components', () => {
|
it('renders tabs without inner components', () => {
|
||||||
const wrapper = render(
|
const wrapper = render(
|
||||||
<Tabs
|
<Tabs tabs={simple10Tabs} onClick={() => {}} selected="5" />
|
||||||
tabs={simple10Tabs}
|
|
||||||
onClick={() => {}}
|
|
||||||
selected="5"
|
|
||||||
/>
|
|
||||||
);
|
);
|
||||||
expect(renderToJson(wrapper)).toMatchSnapshot();
|
expect(renderToJson(wrapper)).toMatchSnapshot();
|
||||||
});
|
});
|
||||||
|
@ -36,7 +28,10 @@ describe('Tabs', function () {
|
||||||
const onClick = jest.fn();
|
const onClick = jest.fn();
|
||||||
const wrapper = mount(<Tabs tabs={tabs} onClick={onClick} />);
|
const wrapper = mount(<Tabs tabs={tabs} onClick={onClick} />);
|
||||||
|
|
||||||
wrapper.find('button').first().simulate('click');
|
wrapper
|
||||||
|
.find('button')
|
||||||
|
.first()
|
||||||
|
.simulate('click');
|
||||||
expect(onClick).toBeCalled();
|
expect(onClick).toBeCalled();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -17,9 +17,7 @@ describe('Toolbar', function () {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('renders with props', () => {
|
it('renders with props', () => {
|
||||||
const wrapper = render(
|
const wrapper = render(<Toolbar borderPosition="top" />);
|
||||||
<Toolbar borderPosition="top" />
|
|
||||||
);
|
|
||||||
expect(renderToJson(wrapper)).toMatchSnapshot();
|
expect(renderToJson(wrapper)).toMatchSnapshot();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -2,10 +2,10 @@
|
||||||
|
|
||||||
exports[`Button renders correctly 1`] = `
|
exports[`Button renders correctly 1`] = `
|
||||||
<div
|
<div
|
||||||
class="sc-ifAKCX jTewnV"
|
class="sc-ifAKCX evScRP"
|
||||||
>
|
>
|
||||||
<button
|
<button
|
||||||
class="sc-htpNat fWcQZ"
|
class="sc-htpNat ldLqpm"
|
||||||
>
|
>
|
||||||
Text
|
Text
|
||||||
</button>
|
</button>
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
exports[`Container renders correctly 1`] = `
|
exports[`Container renders correctly 1`] = `
|
||||||
<div
|
<div
|
||||||
class="sc-bdVaJa dRsjcb"
|
class="sc-bdVaJa ODaHo"
|
||||||
>
|
>
|
||||||
Text
|
Text
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
exports[`ContextMenu renders correctly 1`] = `
|
exports[`ContextMenu renders correctly 1`] = `
|
||||||
<div
|
<div
|
||||||
class="sc-EHOje dIpPFG"
|
class="sc-EHOje cfLLnh"
|
||||||
>
|
>
|
||||||
<button
|
<button
|
||||||
value="Menu Item 1"
|
value="Menu Item 1"
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
exports[`Dialog renders correctly 1`] = `
|
exports[`Dialog renders correctly 1`] = `
|
||||||
<div
|
<div
|
||||||
class="sc-iwsKbI fOBkrR"
|
class="sc-iwsKbI islPis"
|
||||||
>
|
>
|
||||||
<div />
|
<div />
|
||||||
<div>
|
<div>
|
||||||
|
@ -21,19 +21,19 @@ exports[`Dialog renders correctly 1`] = `
|
||||||
class="mc-dialog--footer"
|
class="mc-dialog--footer"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
class="sc-ifAKCX jTewnV"
|
class="sc-ifAKCX evScRP"
|
||||||
>
|
>
|
||||||
<button
|
<button
|
||||||
class="sc-htpNat fWcQZ"
|
class="sc-htpNat ldLqpm"
|
||||||
>
|
>
|
||||||
Cancel
|
Cancel
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
class="sc-ifAKCX jTewnV"
|
class="sc-ifAKCX evScRP"
|
||||||
>
|
>
|
||||||
<button
|
<button
|
||||||
class="sc-htpNat iMkoYt"
|
class="sc-htpNat cvNnmn"
|
||||||
>
|
>
|
||||||
Submit
|
Submit
|
||||||
</button>
|
</button>
|
||||||
|
@ -45,7 +45,7 @@ exports[`Dialog renders correctly 1`] = `
|
||||||
|
|
||||||
exports[`Dialog renders modal 1`] = `
|
exports[`Dialog renders modal 1`] = `
|
||||||
<div
|
<div
|
||||||
class="sc-iwsKbI fOBkrR"
|
class="sc-iwsKbI islPis"
|
||||||
>
|
>
|
||||||
<div />
|
<div />
|
||||||
<div>
|
<div>
|
||||||
|
@ -61,19 +61,19 @@ exports[`Dialog renders modal 1`] = `
|
||||||
class="mc-dialog--footer"
|
class="mc-dialog--footer"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
class="sc-ifAKCX jTewnV"
|
class="sc-ifAKCX evScRP"
|
||||||
>
|
>
|
||||||
<button
|
<button
|
||||||
class="sc-htpNat fWcQZ"
|
class="sc-htpNat ldLqpm"
|
||||||
>
|
>
|
||||||
Cancel
|
Cancel
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
class="sc-ifAKCX jTewnV"
|
class="sc-ifAKCX evScRP"
|
||||||
>
|
>
|
||||||
<button
|
<button
|
||||||
class="sc-htpNat iMkoYt"
|
class="sc-htpNat cvNnmn"
|
||||||
>
|
>
|
||||||
Submit
|
Submit
|
||||||
</button>
|
</button>
|
||||||
|
@ -85,7 +85,7 @@ exports[`Dialog renders modal 1`] = `
|
||||||
|
|
||||||
exports[`Dialog renders with props 1`] = `
|
exports[`Dialog renders with props 1`] = `
|
||||||
<div
|
<div
|
||||||
class="sc-iwsKbI fpUYbC"
|
class="sc-iwsKbI hRSLqU"
|
||||||
open=""
|
open=""
|
||||||
>
|
>
|
||||||
<div />
|
<div />
|
||||||
|
@ -109,19 +109,19 @@ exports[`Dialog renders with props 1`] = `
|
||||||
class="mc-dialog--footer"
|
class="mc-dialog--footer"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
class="sc-ifAKCX jTewnV"
|
class="sc-ifAKCX evScRP"
|
||||||
>
|
>
|
||||||
<button
|
<button
|
||||||
class="sc-htpNat fWcQZ"
|
class="sc-htpNat ldLqpm"
|
||||||
>
|
>
|
||||||
Cancel
|
Cancel
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
class="sc-ifAKCX jTewnV"
|
class="sc-ifAKCX evScRP"
|
||||||
>
|
>
|
||||||
<button
|
<button
|
||||||
class="sc-htpNat iMkoYt"
|
class="sc-htpNat cvNnmn"
|
||||||
>
|
>
|
||||||
Submit
|
Submit
|
||||||
</button>
|
</button>
|
||||||
|
|
|
@ -14,7 +14,7 @@ exports[`Editor renders correctly 1`] = `
|
||||||
innerRef={[Function]}
|
innerRef={[Function]}
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
className="sc-gZMcBi eROHUl"
|
className="sc-gZMcBi bFOJgt"
|
||||||
/>
|
/>
|
||||||
</styled.div>
|
</styled.div>
|
||||||
</Editor>
|
</Editor>
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
exports[`Notification renders correctly 1`] = `
|
exports[`Notification renders correctly 1`] = `
|
||||||
<div
|
<div
|
||||||
class="sc-fjdhpX fmuodm"
|
class="sc-fjdhpX gcvrGp"
|
||||||
type="info"
|
type="info"
|
||||||
>
|
>
|
||||||
<span>
|
<span>
|
||||||
|
@ -13,7 +13,7 @@ exports[`Notification renders correctly 1`] = `
|
||||||
|
|
||||||
exports[`Notification renders with props 1`] = `
|
exports[`Notification renders with props 1`] = `
|
||||||
<div
|
<div
|
||||||
class="sc-fjdhpX fmuodm"
|
class="sc-fjdhpX gcvrGp"
|
||||||
type="error"
|
type="error"
|
||||||
>
|
>
|
||||||
<svg
|
<svg
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
exports[`SegmentedControl renders correctly 1`] = `
|
exports[`SegmentedControl renders correctly 1`] = `
|
||||||
<div
|
<div
|
||||||
class="sc-jTzLTM jHNWjD"
|
class="sc-jTzLTM bwMlok"
|
||||||
>
|
>
|
||||||
<button
|
<button
|
||||||
data-selected="true"
|
data-selected="true"
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
exports[`Select renders correctly 1`] = `
|
exports[`Select renders correctly 1`] = `
|
||||||
<div
|
<div
|
||||||
class="Select sc-bZQynM lpCNM is-searchable Select--single"
|
class="Select sc-bZQynM eKUTFA is-searchable Select--single"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
class="Select-control"
|
class="Select-control"
|
||||||
|
@ -47,7 +47,7 @@ exports[`Select renders correctly 1`] = `
|
||||||
|
|
||||||
exports[`Select renders with props 1`] = `
|
exports[`Select renders with props 1`] = `
|
||||||
<div
|
<div
|
||||||
class="Select sc-bZQynM dVPEwd has-value is-clearable is-disabled is-loading Select--multi"
|
class="Select sc-bZQynM lbesTc has-value is-clearable is-disabled is-loading Select--multi"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
class="Select-control"
|
class="Select-control"
|
||||||
|
@ -155,7 +155,7 @@ exports[`Select should select another option 1`] = `
|
||||||
autosize={true}
|
autosize={true}
|
||||||
backspaceRemoves={true}
|
backspaceRemoves={true}
|
||||||
backspaceToRemoveMessage="Press backspace to remove {label}"
|
backspaceToRemoveMessage="Press backspace to remove {label}"
|
||||||
className="sc-bZQynM lpCNM"
|
className="sc-bZQynM eKUTFA"
|
||||||
clearAllText="Clear all"
|
clearAllText="Clear all"
|
||||||
clearRenderer={[Function]}
|
clearRenderer={[Function]}
|
||||||
clearValueText="Clear value"
|
clearValueText="Clear value"
|
||||||
|
@ -215,7 +215,7 @@ exports[`Select should select another option 1`] = `
|
||||||
valueKey="value"
|
valueKey="value"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
className="Select sc-bZQynM lpCNM is-open is-searchable Select--single"
|
className="Select sc-bZQynM eKUTFA is-open is-searchable Select--single"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
className="Select-control"
|
className="Select-control"
|
||||||
|
@ -404,7 +404,7 @@ exports[`Select shouldn't find any results 1`] = `
|
||||||
autosize={true}
|
autosize={true}
|
||||||
backspaceRemoves={true}
|
backspaceRemoves={true}
|
||||||
backspaceToRemoveMessage="Press backspace to remove {label}"
|
backspaceToRemoveMessage="Press backspace to remove {label}"
|
||||||
className="sc-bZQynM lpCNM"
|
className="sc-bZQynM eKUTFA"
|
||||||
clearAllText="Clear all"
|
clearAllText="Clear all"
|
||||||
clearRenderer={[Function]}
|
clearRenderer={[Function]}
|
||||||
clearValueText="Clear value"
|
clearValueText="Clear value"
|
||||||
|
@ -464,7 +464,7 @@ exports[`Select shouldn't find any results 1`] = `
|
||||||
valueKey="value"
|
valueKey="value"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
className="Select sc-bZQynM lpCNM is-open is-searchable Select--single"
|
className="Select sc-bZQynM eKUTFA is-open is-searchable Select--single"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
className="Select-control"
|
className="Select-control"
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
exports[`Slider renders correctly 1`] = `
|
exports[`Slider renders correctly 1`] = `
|
||||||
<div
|
<div
|
||||||
class="sc-gzVnrw gTqmBD"
|
class="sc-gzVnrw hKBSWW"
|
||||||
>
|
>
|
||||||
<input
|
<input
|
||||||
max="100"
|
max="100"
|
||||||
|
@ -15,7 +15,7 @@ exports[`Slider renders correctly 1`] = `
|
||||||
|
|
||||||
exports[`Slider renders with props 1`] = `
|
exports[`Slider renders with props 1`] = `
|
||||||
<div
|
<div
|
||||||
class="sc-gzVnrw csqRof"
|
class="sc-gzVnrw gnJNaZ"
|
||||||
disabled=""
|
disabled=""
|
||||||
>
|
>
|
||||||
<label>
|
<label>
|
||||||
|
|
|
@ -5,7 +5,7 @@ exports[`Tabs renders correctly 1`] = `
|
||||||
class="sc-VigVT fmiisu"
|
class="sc-VigVT fmiisu"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
class="sc-gqjmRU gEvsQs"
|
class="sc-gqjmRU kpDKzc"
|
||||||
>
|
>
|
||||||
<div>
|
<div>
|
||||||
<button
|
<button
|
||||||
|
@ -33,7 +33,7 @@ exports[`Tabs renders tabs without inner components 1`] = `
|
||||||
class="sc-VigVT fmiisu"
|
class="sc-VigVT fmiisu"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
class="sc-gqjmRU gEvsQs"
|
class="sc-gqjmRU kpDKzc"
|
||||||
>
|
>
|
||||||
<div>
|
<div>
|
||||||
<button
|
<button
|
||||||
|
@ -97,7 +97,7 @@ exports[`Tabs renders with props 1`] = `
|
||||||
class="sc-VigVT fmiisu"
|
class="sc-VigVT fmiisu"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
class="sc-gqjmRU gEvsQs"
|
class="sc-gqjmRU kpDKzc"
|
||||||
>
|
>
|
||||||
<div>
|
<div>
|
||||||
<button
|
<button
|
||||||
|
|
|
@ -5,10 +5,10 @@ exports[`Toolbar renders correctly 1`] = `
|
||||||
class="sc-jzJRlG bBrbNn"
|
class="sc-jzJRlG bBrbNn"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
class="sc-ifAKCX jTewnV"
|
class="sc-ifAKCX evScRP"
|
||||||
>
|
>
|
||||||
<button
|
<button
|
||||||
class="sc-htpNat fWcQZ"
|
class="sc-htpNat ldLqpm"
|
||||||
>
|
>
|
||||||
1
|
1
|
||||||
</button>
|
</button>
|
||||||
|
@ -20,10 +20,10 @@ exports[`Toolbar renders correctly 1`] = `
|
||||||
class="sc-kAzzGY lcEaIs"
|
class="sc-kAzzGY lcEaIs"
|
||||||
/>
|
/>
|
||||||
<div
|
<div
|
||||||
class="sc-ifAKCX jTewnV"
|
class="sc-ifAKCX evScRP"
|
||||||
>
|
>
|
||||||
<button
|
<button
|
||||||
class="sc-htpNat fWcQZ"
|
class="sc-htpNat ldLqpm"
|
||||||
>
|
>
|
||||||
2
|
2
|
||||||
</button>
|
</button>
|
||||||
|
|
|
@ -5,15 +5,16 @@ The following opinions must be taken into account since the primary use case of
|
||||||
- Objects and arrays deeply nested within collections are not converted into a tree structure. See `someNestedObject` and `someNestedArray` in the [output](https://github.com/romseguy/map2tree#output) below, or the [corresponding test](https://github.com/romseguy/map2tree/blob/master/test/map2tree.js#L140).
|
- Objects and arrays deeply nested within collections are not converted into a tree structure. See `someNestedObject` and `someNestedArray` in the [output](https://github.com/romseguy/map2tree#output) below, or the [corresponding test](https://github.com/romseguy/map2tree/blob/master/test/map2tree.js#L140).
|
||||||
- Provides support for [Immutable.js](https://github.com/facebook/immutable-js) data structures (only List and Map though).
|
- Provides support for [Immutable.js](https://github.com/facebook/immutable-js) data structures (only List and Map though).
|
||||||
|
|
||||||
|
|
||||||
# Usage
|
# Usage
|
||||||
|
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
map2tree(someMap, options = {
|
map2tree(
|
||||||
|
someMap,
|
||||||
|
(options = {
|
||||||
key: 'state', // the name you want for as the root node of the output tree
|
key: 'state', // the name you want for as the root node of the output tree
|
||||||
pushMethod: 'push' // use 'unshift' to change the order children nodes are added
|
pushMethod: 'push' // use 'unshift' to change the order children nodes are added
|
||||||
})
|
})
|
||||||
|
);
|
||||||
```
|
```
|
||||||
|
|
||||||
# Input
|
# Input
|
||||||
|
|
|
@ -19,16 +19,24 @@ function visit(parent, visitFn, childrenFn) {
|
||||||
function getNode(tree, key) {
|
function getNode(tree, key) {
|
||||||
let node = null;
|
let node = null;
|
||||||
|
|
||||||
visit(tree, d => {
|
visit(
|
||||||
|
tree,
|
||||||
|
d => {
|
||||||
if (d.name === key) {
|
if (d.name === key) {
|
||||||
node = d;
|
node = d;
|
||||||
}
|
}
|
||||||
}, d => d.children);
|
},
|
||||||
|
d => d.children
|
||||||
|
);
|
||||||
|
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function map2tree(root, options = {}, tree = {name: options.key || 'state', children: []}) {
|
export default function map2tree(
|
||||||
|
root,
|
||||||
|
options = {},
|
||||||
|
tree = { name: options.key || 'state', children: [] }
|
||||||
|
) {
|
||||||
if (!isPlainObject(root) && root && !root.toJS) {
|
if (!isPlainObject(root) && root && !root.toJS) {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
@ -41,7 +49,10 @@ export default function map2tree(root, options = {}, tree = {name: options.key |
|
||||||
}
|
}
|
||||||
|
|
||||||
mapValues(root && root.toJS ? root.toJS() : root, (maybeImmutable, key) => {
|
mapValues(root && root.toJS ? root.toJS() : root, (maybeImmutable, key) => {
|
||||||
const value = maybeImmutable && maybeImmutable.toJS ? maybeImmutable.toJS() : maybeImmutable;
|
const value =
|
||||||
|
maybeImmutable && maybeImmutable.toJS
|
||||||
|
? maybeImmutable.toJS()
|
||||||
|
: maybeImmutable;
|
||||||
let newNode = { name: key };
|
let newNode = { name: key };
|
||||||
|
|
||||||
if (isArray(value)) {
|
if (isArray(value)) {
|
||||||
|
|
|
@ -16,9 +16,7 @@ describe('# shallow map', () => {
|
||||||
|
|
||||||
const expected = {
|
const expected = {
|
||||||
name: 'state',
|
name: 'state',
|
||||||
children: [
|
children: [{ name: 'a', value: null }]
|
||||||
{name: 'a', value: null}
|
|
||||||
]
|
|
||||||
};
|
};
|
||||||
|
|
||||||
expect(map2tree(map)).toEqual(expected);
|
expect(map2tree(map)).toEqual(expected);
|
||||||
|
@ -33,10 +31,7 @@ describe('# shallow map', () => {
|
||||||
|
|
||||||
const expected = {
|
const expected = {
|
||||||
name: 'state',
|
name: 'state',
|
||||||
children: [
|
children: [{ name: 'a', value: 'foo' }, { name: 'b', value: 'bar' }]
|
||||||
{name: 'a', value: 'foo'},
|
|
||||||
{name: 'b', value: 'bar'}
|
|
||||||
]
|
|
||||||
};
|
};
|
||||||
|
|
||||||
expect(map2tree(map)).toEqual(expected);
|
expect(map2tree(map)).toEqual(expected);
|
||||||
|
@ -50,9 +45,7 @@ describe('# shallow map', () => {
|
||||||
|
|
||||||
const expected = {
|
const expected = {
|
||||||
name: 'state',
|
name: 'state',
|
||||||
children: [
|
children: [{ name: 'a', children: [{ name: 'aa', value: 'foo' }] }]
|
||||||
{name: 'a', children: [{name: 'aa', value: 'foo'}]}
|
|
||||||
]
|
|
||||||
};
|
};
|
||||||
|
|
||||||
expect(map2tree(map)).toEqual(expected);
|
expect(map2tree(map)).toEqual(expected);
|
||||||
|
@ -67,12 +60,15 @@ describe('# shallow map', () => {
|
||||||
const expected = {
|
const expected = {
|
||||||
name: 'state',
|
name: 'state',
|
||||||
children: [
|
children: [
|
||||||
{name: 'a', children: [{name: 'aa', value: 'foo'}, {name: 'ab', value: 'bar'}]}
|
{
|
||||||
|
name: 'a',
|
||||||
|
children: [{ name: 'aa', value: 'foo' }, { name: 'ab', value: 'bar' }]
|
||||||
|
}
|
||||||
]
|
]
|
||||||
};
|
};
|
||||||
|
|
||||||
expect(map2tree(map)).toEqual(expected);
|
expect(map2tree(map)).toEqual(expected);
|
||||||
})
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('# deep map', () => {
|
describe('# deep map', () => {
|
||||||
|
@ -113,9 +109,7 @@ describe('# deep map', () => {
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
name: 'aa',
|
name: 'aa',
|
||||||
children: [
|
children: [{ name: 'aaa', value: 'foo' }]
|
||||||
{name: 'aaa', value: 'foo'}
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
@ -129,21 +123,18 @@ describe('# deep map', () => {
|
||||||
|
|
||||||
describe('# array map', () => {
|
describe('# array map', () => {
|
||||||
const map = {
|
const map = {
|
||||||
a: [
|
a: [1, 2]
|
||||||
1,
|
|
||||||
2
|
|
||||||
]
|
|
||||||
};
|
};
|
||||||
|
|
||||||
test('## push', () => {
|
test('## push', () => {
|
||||||
const expected = {
|
const expected = {
|
||||||
name: 'state',
|
name: 'state',
|
||||||
children: [{
|
|
||||||
name: 'a',
|
|
||||||
children: [
|
children: [
|
||||||
{name: 'a[0]', value: 1},
|
{
|
||||||
{name: 'a[1]', value: 2}]
|
name: 'a',
|
||||||
}]
|
children: [{ name: 'a[0]', value: 1 }, { name: 'a[1]', value: 2 }]
|
||||||
|
}
|
||||||
|
]
|
||||||
};
|
};
|
||||||
|
|
||||||
expect(map2tree(map)).toEqual(expected);
|
expect(map2tree(map)).toEqual(expected);
|
||||||
|
@ -154,13 +145,12 @@ describe('# array map', () => {
|
||||||
const options = { pushMethod: 'unshift' };
|
const options = { pushMethod: 'unshift' };
|
||||||
const expected = {
|
const expected = {
|
||||||
name: 'state',
|
name: 'state',
|
||||||
children: [{
|
|
||||||
name: 'a',
|
|
||||||
children: [
|
children: [
|
||||||
{name: 'a[1]', value: 2},
|
{
|
||||||
{name: 'a[0]', value: 1}
|
name: 'a',
|
||||||
|
children: [{ name: 'a[1]', value: 2 }, { name: 'a[0]', value: 1 }]
|
||||||
|
}
|
||||||
]
|
]
|
||||||
}]
|
|
||||||
};
|
};
|
||||||
|
|
||||||
expect(map2tree(map, options)).toEqual(expected);
|
expect(map2tree(map, options)).toEqual(expected);
|
||||||
|
@ -169,33 +159,28 @@ describe('# array map', () => {
|
||||||
|
|
||||||
test('## null', () => {
|
test('## null', () => {
|
||||||
const map = {
|
const map = {
|
||||||
a: [
|
a: [null]
|
||||||
null
|
|
||||||
]
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const expected = {
|
const expected = {
|
||||||
name: 'state',
|
name: 'state',
|
||||||
children: [{
|
|
||||||
name: 'a',
|
|
||||||
children: [
|
children: [
|
||||||
{name: 'a[0]', value: null}
|
{
|
||||||
|
name: 'a',
|
||||||
|
children: [{ name: 'a[0]', value: null }]
|
||||||
|
}
|
||||||
]
|
]
|
||||||
}]
|
|
||||||
};
|
};
|
||||||
|
|
||||||
expect(map2tree(map)).toEqual(expected);
|
expect(map2tree(map)).toEqual(expected);
|
||||||
expect(map2tree(immutable.fromJS(map))).toEqual(expected);
|
expect(map2tree(immutable.fromJS(map))).toEqual(expected);
|
||||||
})
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('# collection map', () => {
|
describe('# collection map', () => {
|
||||||
test('## value', () => {
|
test('## value', () => {
|
||||||
const map = {
|
const map = {
|
||||||
a: [
|
a: [{ aa: 1 }, { aa: 2 }]
|
||||||
{aa: 1},
|
|
||||||
{aa: 2}
|
|
||||||
]
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const expected = {
|
const expected = {
|
||||||
|
@ -217,9 +202,7 @@ describe('# collection map', () => {
|
||||||
|
|
||||||
test('## object', () => {
|
test('## object', () => {
|
||||||
const map = {
|
const map = {
|
||||||
a: [
|
a: [{ aa: { aaa: 'foo' } }]
|
||||||
{aa: {aaa: 'foo'}}
|
|
||||||
]
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const expected = {
|
const expected = {
|
||||||
|
@ -227,14 +210,12 @@ describe('# collection map', () => {
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
name: 'a',
|
name: 'a',
|
||||||
children: [
|
children: [{ name: 'a[0]', object: { aa: { aaa: 'foo' } } }]
|
||||||
{name: 'a[0]', object: {aa: {aaa: 'foo'}}}
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
};
|
};
|
||||||
|
|
||||||
expect(map2tree(map)).toEqual(expected);
|
expect(map2tree(map)).toEqual(expected);
|
||||||
expect(map2tree(immutable.fromJS(map))).toEqual(expected);
|
expect(map2tree(immutable.fromJS(map))).toEqual(expected);
|
||||||
})
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
|
|
||||||
module.exports = (env = {}) => (
|
module.exports = (env = {}) => ({
|
||||||
{
|
|
||||||
mode: 'production',
|
mode: 'production',
|
||||||
entry: {
|
entry: {
|
||||||
app: ['./src/index.js']
|
app: ['./src/index.js']
|
||||||
|
@ -27,5 +26,4 @@ module.exports = (env = {}) => (
|
||||||
performance: {
|
performance: {
|
||||||
hints: false
|
hints: false
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
);
|
|
||||||
|
|
|
@ -2,7 +2,6 @@ The MIT License (MIT)
|
||||||
|
|
||||||
Copyright (c) 2015 Shusaku Uesugi, (c) 2016-present Alexander Kuznetsov
|
Copyright (c) 2015 Shusaku Uesugi, (c) 2016-present Alexander Kuznetsov
|
||||||
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
in the Software without restriction, including without limitation the rights
|
in the Software without restriction, including without limitation the rights
|
||||||
|
|
|
@ -33,6 +33,7 @@ Check out [examples](examples) directory for more details.
|
||||||
### Theming
|
### Theming
|
||||||
|
|
||||||
This component now uses [react-base16-styling](https://github.com/alexkuz/react-base16-styling) module, which allows to customize component via `theme` property, which can be the following:
|
This component now uses [react-base16-styling](https://github.com/alexkuz/react-base16-styling) module, which allows to customize component via `theme` property, which can be the following:
|
||||||
|
|
||||||
- [base16](http://chriskempson.github.io/base16) theme data. [The example theme data can be found here](https://github.com/gaearon/redux-devtools/tree/75322b15ee7ba03fddf10ac3399881e302848874/src/react/themes).
|
- [base16](http://chriskempson.github.io/base16) theme data. [The example theme data can be found here](https://github.com/gaearon/redux-devtools/tree/75322b15ee7ba03fddf10ac3399881e302848874/src/react/themes).
|
||||||
- object that contains style objects, strings (that treated as classnames) or functions. A function is used to extend its first argument `{ style, className }` and should return an object with the same structure. Other arguments depend on particular context (and should be described here). See [createStylingFromTheme.js](https://github.com/alexkuz/react-json-tree/blob/feature-refactor-styling/src/createStylingFromTheme.js) for the list of styling object keys. Also, this object can extend `base16` theme via `extend` property.
|
- object that contains style objects, strings (that treated as classnames) or functions. A function is used to extend its first argument `{ style, className }` and should return an object with the same structure. Other arguments depend on particular context (and should be described here). See [createStylingFromTheme.js](https://github.com/alexkuz/react-json-tree/blob/feature-refactor-styling/src/createStylingFromTheme.js) for the list of styling object keys. Also, this object can extend `base16` theme via `extend` property.
|
||||||
|
|
||||||
|
@ -62,8 +63,7 @@ const theme = {
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<JSONTree data={data} theme={theme} invertTheme={false} />
|
<JSONTree data={data} theme={theme} invertTheme={false} />
|
||||||
</div>
|
</div>;
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Result (Monokai theme, dark background):
|
#### Result (Monokai theme, dark background):
|
||||||
|
@ -74,7 +74,9 @@ const theme = {
|
||||||
|
|
||||||
```jsx
|
```jsx
|
||||||
<div>
|
<div>
|
||||||
<JSONTree data={data} theme={{
|
<JSONTree
|
||||||
|
data={data}
|
||||||
|
theme={{
|
||||||
extend: theme,
|
extend: theme,
|
||||||
// underline keys for literal values
|
// underline keys for literal values
|
||||||
valueLabel: {
|
valueLabel: {
|
||||||
|
@ -88,7 +90,8 @@ const theme = {
|
||||||
textTransform: expanded ? 'uppercase' : style.textTransform
|
textTransform: expanded ? 'uppercase' : style.textTransform
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}} />
|
}}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
react-hot-boilerplate
|
# react-hot-boilerplate
|
||||||
=====================
|
|
||||||
|
|
||||||
The minimal dev environment to enable live-editing React components.
|
The minimal dev environment to enable live-editing React components.
|
||||||
|
|
||||||
|
@ -32,16 +31,16 @@ This boilerplate is purposefully simple to show the minimal configuration for Re
|
||||||
|
|
||||||
### Dependencies
|
### Dependencies
|
||||||
|
|
||||||
* React
|
- React
|
||||||
* Webpack
|
- Webpack
|
||||||
* [webpack-dev-server](https://github.com/webpack/webpack-dev-server)
|
- [webpack-dev-server](https://github.com/webpack/webpack-dev-server)
|
||||||
* [babel-loader](https://github.com/babel/babel-loader)
|
- [babel-loader](https://github.com/babel/babel-loader)
|
||||||
* [react-hot-loader](https://github.com/gaearon/react-hot-loader)
|
- [react-hot-loader](https://github.com/gaearon/react-hot-loader)
|
||||||
|
|
||||||
### Resources
|
### Resources
|
||||||
|
|
||||||
* [Demo video](http://vimeo.com/100010922)
|
- [Demo video](http://vimeo.com/100010922)
|
||||||
* [react-hot-loader on Github](https://github.com/gaearon/react-hot-loader)
|
- [react-hot-loader on Github](https://github.com/gaearon/react-hot-loader)
|
||||||
* [Integrating JSX live reload into your workflow](http://gaearon.github.io/react-hot-loader/getstarted/)
|
- [Integrating JSX live reload into your workflow](http://gaearon.github.io/react-hot-loader/getstarted/)
|
||||||
* [Troubleshooting guide](https://github.com/gaearon/react-hot-loader/blob/master/docs/Troubleshooting.md)
|
- [Troubleshooting guide](https://github.com/gaearon/react-hot-loader/blob/master/docs/Troubleshooting.md)
|
||||||
* Ping dan_abramov on Twitter or #reactjs IRC
|
- Ping dan_abramov on Twitter or #reactjs IRC
|
||||||
|
|
|
@ -10,8 +10,7 @@
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id='root'>
|
<div id="root"></div>
|
||||||
</div>
|
|
||||||
<script src="/static/bundle.js"></script>
|
<script src="/static/bundle.js"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
@ -23,7 +23,8 @@ module.exports = {
|
||||||
}),
|
}),
|
||||||
new webpack.HotModuleReplacementPlugin(),
|
new webpack.HotModuleReplacementPlugin(),
|
||||||
new webpack.NoEmitOnErrorsPlugin(),
|
new webpack.NoEmitOnErrorsPlugin(),
|
||||||
isProduction && new webpack.optimize.UglifyJsPlugin({
|
isProduction &&
|
||||||
|
new webpack.optimize.UglifyJsPlugin({
|
||||||
compress: { warnings: false },
|
compress: { warnings: false },
|
||||||
output: { comments: false },
|
output: { comments: false },
|
||||||
sourceMap: true
|
sourceMap: true
|
||||||
|
@ -33,19 +34,22 @@ module.exports = {
|
||||||
alias: {
|
alias: {
|
||||||
'react-json-tree/lib': path.join(__dirname, '..', 'src'),
|
'react-json-tree/lib': path.join(__dirname, '..', 'src'),
|
||||||
'react-json-tree': path.join(__dirname, '..', 'src'),
|
'react-json-tree': path.join(__dirname, '..', 'src'),
|
||||||
'react': path.join(__dirname, 'node_modules', 'react')
|
react: path.join(__dirname, 'node_modules', 'react')
|
||||||
},
|
},
|
||||||
extensions: ['.js']
|
extensions: ['.js']
|
||||||
},
|
},
|
||||||
module: {
|
module: {
|
||||||
loaders: [{
|
loaders: [
|
||||||
|
{
|
||||||
test: /\.js$/,
|
test: /\.js$/,
|
||||||
loaders: ['babel-loader'].filter(Boolean),
|
loaders: ['babel-loader'].filter(Boolean),
|
||||||
include: path.join(__dirname, 'src')
|
include: path.join(__dirname, 'src')
|
||||||
}, {
|
},
|
||||||
|
{
|
||||||
test: /\.js$/,
|
test: /\.js$/,
|
||||||
loaders: ['babel-loader'].filter(Boolean),
|
loaders: ['babel-loader'].filter(Boolean),
|
||||||
include: path.join(__dirname, '..', 'src')
|
include: path.join(__dirname, '..', 'src')
|
||||||
}]
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -22,7 +22,10 @@
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/reduxjs/redux-devtools.git"
|
"url": "https://github.com/reduxjs/redux-devtools.git"
|
||||||
},
|
},
|
||||||
"keywords": ["react", "json viewer"],
|
"keywords": [
|
||||||
|
"react",
|
||||||
|
"json viewer"
|
||||||
|
],
|
||||||
"author": "Shu Uesugi <shu@chibicode.com> (http://github.com/chibicode)",
|
"author": "Shu Uesugi <shu@chibicode.com> (http://github.com/chibicode)",
|
||||||
"contributors": [
|
"contributors": [
|
||||||
"Alexander Kuznetsov <alexkuz@gmail.com> (http://kuzya.org/)",
|
"Alexander Kuznetsov <alexkuz@gmail.com> (http://kuzya.org/)",
|
||||||
|
|
5
packages/react-json-tree/src/JSONNode.js
vendored
5
packages/react-json-tree/src/JSONNode.js
vendored
|
@ -86,7 +86,10 @@ const JSONNode = ({
|
||||||
return <JSONValueNode {...simpleNodeProps} />;
|
return <JSONValueNode {...simpleNodeProps} />;
|
||||||
default:
|
default:
|
||||||
return (
|
return (
|
||||||
<JSONValueNode {...simpleNodeProps} valueGetter={() => `<${nodeType}>`} />
|
<JSONValueNode
|
||||||
|
{...simpleNodeProps}
|
||||||
|
valueGetter={() => `<${nodeType}>`}
|
||||||
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
3
packages/react-json-tree/src/index.js
vendored
3
packages/react-json-tree/src/index.js
vendored
|
@ -117,8 +117,7 @@ export default class JSONTree extends React.Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
shouldComponentUpdate(nextProps) {
|
shouldComponentUpdate(nextProps) {
|
||||||
return !!Object.keys(nextProps).find(
|
return !!Object.keys(nextProps).find(k =>
|
||||||
k =>
|
|
||||||
k === 'keyPath'
|
k === 'keyPath'
|
||||||
? nextProps[k].join('/') !== this.props[k].join('/')
|
? nextProps[k].join('/') !== this.props[k].join('/')
|
||||||
: nextProps[k] !== this.props[k]
|
: nextProps[k] !== this.props[k]
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user