├── .babelrc
├── .eslintrc
├── .gitignore
├── .npmignore
├── .scripts
├── get_gh_pages_url.js
├── mocha_runner.js
├── prepublish.sh
├── publish_storybook.sh
└── user
│ ├── prepublish.sh
│ └── pretest.js
├── .storybook
├── addons.js
├── config.js
├── user
│ └── modify_webpack_config.js
└── webpack.config.js
├── CHANGELOG.md
├── CONTRIBUTING.md
├── LICENSE
├── README.md
├── dist
├── KnobManager.js
├── KnobStore.js
├── components
│ ├── Panel.js
│ ├── PropField.js
│ ├── PropForm.js
│ ├── WrapStory.js
│ └── types
│ │ ├── Array.js
│ │ ├── Boolean.js
│ │ ├── Color.js
│ │ ├── Date
│ │ ├── index.js
│ │ └── styles.js
│ │ ├── Number.js
│ │ ├── Object.js
│ │ ├── Select.js
│ │ ├── Text.js
│ │ └── index.js
├── index.js
└── register.js
├── docs
├── demo.gif
├── demo.png
└── storybook-knobs-example.png
├── example
├── stories
│ └── index.js
└── typescript
│ └── index.tsx
├── package.json
├── register.js
├── src
├── KnobManager.js
├── KnobStore.js
├── components
│ ├── Panel.js
│ ├── PropField.js
│ ├── PropForm.js
│ ├── WrapStory.js
│ ├── tests
│ │ ├── Array.js
│ │ └── Panel.js
│ └── types
│ │ ├── Array.js
│ │ ├── Boolean.js
│ │ ├── Color.js
│ │ ├── Date
│ │ ├── index.js
│ │ └── styles.js
│ │ ├── Number.js
│ │ ├── Object.js
│ │ ├── Select.js
│ │ ├── Text.js
│ │ └── index.js
├── index.js
├── register.js
└── tests
│ ├── KnobManager.js
│ └── typescript.js
├── storybook-addon-knobs.d.ts
├── tsconfig.json
└── yarn.lock
/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": ["es2015", "stage-2", "react"]
3 | }
4 |
--------------------------------------------------------------------------------
/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "airbnb",
3 | "rules": {
4 | "arrow-body-style": 0,
5 | "prefer-arrow-callback": 0,
6 | "func-names": 0,
7 | "react/jsx-no-bind": 0,
8 | "react/jsx-uses-react": 1,
9 | "react/prefer-stateless-function": 0
10 | },
11 | "parserOptions": {
12 | "ecmaVersion": 6,
13 | "ecmaFeatures": {
14 | "experimentalObjectRestSpread": true
15 | }
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | *.log
3 | .idea
4 | .tern-port
--------------------------------------------------------------------------------
/.npmignore:
--------------------------------------------------------------------------------
1 | src
2 | .babelrc
3 |
--------------------------------------------------------------------------------
/.scripts/get_gh_pages_url.js:
--------------------------------------------------------------------------------
1 | // IMPORTANT
2 | // ---------
3 | // This is an auto generated file with React CDK.
4 | // Do not modify this file.
5 |
6 | const parse = require('git-url-parse');
7 | var ghUrl = process.argv[2];
8 | const parsedUrl = parse(ghUrl);
9 |
10 | const ghPagesUrl = 'https://' + parsedUrl.owner + '.github.io/' + parsedUrl.name;
11 | console.log(ghPagesUrl);
12 |
--------------------------------------------------------------------------------
/.scripts/mocha_runner.js:
--------------------------------------------------------------------------------
1 | // IMPORTANT
2 | // ---------
3 | // This is an auto generated file with React CDK.
4 | // Do not modify this file.
5 | // Use `.scripts/user/pretest.js instead`.
6 |
7 | require('babel-core/register');
8 | require('babel-polyfill');
9 |
10 | // Add jsdom support, which is required for enzyme.
11 | var jsdom = require('jsdom').jsdom;
12 |
13 | var exposedProperties = ['window', 'navigator', 'document'];
14 |
15 | global.document = jsdom('');
16 | global.window = document.defaultView;
17 | Object.keys(document.defaultView).forEach((property) => {
18 | if (typeof global[property] === 'undefined') {
19 | exposedProperties.push(property);
20 | global[property] = document.defaultView[property];
21 | }
22 | });
23 |
24 | global.navigator = {
25 | userAgent: 'node.js'
26 | };
27 |
28 | process.on('unhandledRejection', function (error) {
29 | console.error('Unhandled Promise Rejection:');
30 | console.error(error && error.stack || error);
31 | });
32 |
33 | require('./user/pretest.js');
34 |
--------------------------------------------------------------------------------
/.scripts/prepublish.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # IMPORTANT
4 | # ---------
5 | # This is an auto generated file with React CDK.
6 | # Do not modify this file.
7 | # Use `.scripts/user/prepublish.sh instead`.
8 |
9 | echo "=> Transpiling 'src' into ES5 ..."
10 | echo ""
11 | rm -rf ./dist
12 | ./node_modules/.bin/babel --ignore tests,stories --plugins "transform-runtime" ./src --out-dir ./dist
13 | echo ""
14 | echo "=> Transpiling completed."
15 |
16 | . .scripts/user/prepublish.sh
17 |
--------------------------------------------------------------------------------
/.scripts/publish_storybook.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # IMPORTANT
4 | # ---------
5 | # This is an auto generated file with React CDK.
6 | # Do not modify this file.
7 |
8 | set -e # exit with nonzero exit code if anything fails
9 |
10 | # get GIT url
11 |
12 | GIT_URL=`git config --get remote.origin.url`
13 | if [[ $GIT_URL == "" ]]; then
14 | echo "This project is not configured with a remote git repo".
15 | exit 1
16 | fi
17 |
18 | # clear and re-create the out directory
19 | rm -rf .out || exit 0;
20 | mkdir .out;
21 |
22 | # run our compile script, discussed above
23 | build-storybook -o .out
24 |
25 | # go to the out directory and create a *new* Git repo
26 | cd .out
27 | git init
28 |
29 | # inside this git repo we'll pretend to be a new user
30 | git config user.name "GH Pages Bot"
31 | git config user.email "hello@ghbot.com"
32 |
33 | # The first and only commit to this new Git repo contains all the
34 | # files present with the commit message "Deploy to GitHub Pages".
35 | git add .
36 | git commit -m "Deploy Storybook to GitHub Pages"
37 |
38 | # Force push from the current repo's master branch to the remote
39 | # repo's gh-pages branch. (All previous history on the gh-pages branch
40 | # will be lost, since we are overwriting it.) We redirect any output to
41 | # /dev/null to hide any sensitive credential data that might otherwise be exposed.
42 | git push --force --quiet $GIT_URL master:gh-pages > /dev/null 2>&1
43 | cd ..
44 | rm -rf .out
45 |
46 | echo ""
47 | echo "=> Storybook deployed to: `node .scripts/get_gh_pages_url.js $GIT_URL`"
48 |
--------------------------------------------------------------------------------
/.scripts/user/prepublish.sh:
--------------------------------------------------------------------------------
1 | # Use this file to your own code to run at NPM `prepublish` event.
2 |
--------------------------------------------------------------------------------
/.scripts/user/pretest.js:
--------------------------------------------------------------------------------
1 | // Use this file to setup any test utilities.
2 |
--------------------------------------------------------------------------------
/.storybook/addons.js:
--------------------------------------------------------------------------------
1 | import '../src/register';
2 | import '@kadira/storybook/addons'
3 |
--------------------------------------------------------------------------------
/.storybook/config.js:
--------------------------------------------------------------------------------
1 | // IMPORTANT
2 | // ---------
3 | // This is an auto generated file with React CDK.
4 | // Do not modify this file.
5 |
6 | import { configure } from '@kadira/storybook';
7 |
8 | function loadStories() {
9 | require('../example/stories');
10 | }
11 |
12 | configure(loadStories, module);
13 |
--------------------------------------------------------------------------------
/.storybook/user/modify_webpack_config.js:
--------------------------------------------------------------------------------
1 | module.exports = function (config) {
2 | // This is the default webpack config defined in the `../webpack.config.js`
3 | // modify as you need.
4 | };
5 |
--------------------------------------------------------------------------------
/.storybook/webpack.config.js:
--------------------------------------------------------------------------------
1 | // IMPORTANT
2 | // ---------
3 | // This is an auto generated file with React CDK.
4 | // Do not modify this file.
5 | // Use `.storybook/user/modify_webpack_config.js instead`.
6 |
7 | const path = require('path');
8 | const updateConfig = require('./user/modify_webpack_config');
9 |
10 | const config = {
11 | module: {
12 | loaders: [
13 | {
14 | test: /\.css?$/,
15 | loaders: ['style', 'raw'],
16 | include: path.resolve(__dirname, '../'),
17 | },
18 | ],
19 | },
20 | };
21 |
22 | updateConfig(config);
23 | module.exports = config;
24 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Changelog
2 |
3 | ### v1.7.1
4 | 01-December-2016
5 |
6 | Update style changes in the panel. [PR79](https://github.com/storybooks/storybook-addon-knobs/pull/79)
7 |
8 | ### v1.7.0
9 | 25-November-2016
10 |
11 | Modify number() to support a range slider as an input type for a knob.[PR77](https://github.com/storybooks/storybook-addon-knobs/pull/77)
12 |
13 | ### v1.6.0
14 | 19-November-2016
15 |
16 | Add Color as a type. [PR75](https://github.com/storybooks/storybook-addon-knobs/pull/75)
17 |
18 | ### v1.5.0
19 | 8-November-2016
20 |
21 | Add Array as a type. [PR70](https://github.com/storybooks/storybook-addon-knobs/pull/70).
22 |
23 | ### v1.4.1
24 | 27-October-2016
25 |
26 | Fix some issues related to typescript declaration. [PR69](Typescript declaration updates)
27 |
28 | ### v1.4.0
29 | 27-October-2016
30 |
31 | Add TypeScript support [PR65](https://github.com/kadirahq/storybook-addon-knobs/pull/65).
32 |
33 | ### v1.3.3
34 | 13-October-2016
35 |
36 | Fix issue where hot reloaded updates were not rendered [PR62](https://github.com/kadirahq/storybook-addon-knobs/pull/62).
37 |
38 | ### v1.3.2
39 | 13-October-2016
40 |
41 | Make the render function of WrapStory pure [PR61](https://github.com/kadirahq/storybook-addon-knobs/pull/61).
42 |
43 | ### v1.3.1
44 | 13-October-2016
45 |
46 | Show or hide knob from panel depending on whether it was called in the story or not [PR59](https://github.com/kadirahq/storybook-addon-knobs/pull/59).
47 |
48 | ### v1.3.0
49 | 05-October-2016
50 |
51 | Accept null values for the date type. [PR56](https://github.com/kadirahq/storybook-addon-knobs/pull/56).
52 |
53 | ### v1.2.3
54 | 28-September-2016
55 |
56 | Remove setting selected prop in options in Select knobs [PR47](https://github.com/kadirahq/storybook-addon-knobs/pull/47)
57 |
58 | ### v1.2.2
59 | 25-September-2016
60 |
61 | Fix copy-paste error [PR37](https://github.com/kadirahq/storybook-addon-knobs/pull/37)
62 | Remove
wrapper from WrapStory [PR42](https://github.com/kadirahq/storybook-addon-knobs/pull/42)
63 |
64 | ### v1.2.1
65 | 20-September-2016
66 |
67 | Support to use date type without a default value. [PR32](https://github.com/kadirahq/storybook-addon-knobs/pull/32)
68 |
69 | ### v1.2.0
70 | 19-September-2016
71 |
72 | Add a knob to get date from the user. [PR26](https://github.com/kadirahq/storybook-addon-knobs/pull/26)
73 |
74 | ### v1.1.0
75 | 11-September-2016
76 |
77 | Implement the select knob. [PR21](https://github.com/kadirahq/storybook-addon-knobs/pull/21)
78 |
79 | ### v1.0.1
80 | 09-September-2016
81 |
82 | Allow user to write JSON in the Object knob freely.
83 | Earlier, it's hard to add new fields without creating a JSON error.
84 |
85 | ### v1.0.0
86 | 09-September-2016
87 |
88 | Initial Release.
89 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # Contributing to Storybook Knobs
2 |
3 | We welcome your help to make this component better. This document will help to streamline the contributing process and save everyone's precious time.
4 |
5 | ## Development Setup
6 |
7 | This component has been setup with [React CDK](https://github.com/kadirahq/react-cdk). Refer [React CDK documentation](https://github.com/kadirahq/react-cdk)) to get started with the development.
8 |
9 | ## Setting Up
10 |
11 | You can start the built-in storybook and play with this addon. Do this for that:
12 |
13 | ```sh
14 | npm i
15 | npm run storybook
16 | ```
17 |
18 | Storybook lives inside the `example` directory and source code lives in `src` directory.
19 |
20 | ## Adding a new knob
21 |
22 | Adding a new knob is pretty easy. First you need to add the story side API to the `src/index.js`.
23 |
24 | Then you need to write the UI component to show/edit this knob inside `src/types` directory. Have a look at existing types for more information.
25 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2016 Kadira Inc.
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in
13 | all copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 | THE SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Storybook Addon Knobs
2 |
3 | This contents of this repo was moved to the [Storybook monorepo](https://github.com/storybooks/storybook/) and the NPM package name has been changed.
4 |
5 | - The old name of the package was: **@kadira/storybook-addon-knobs**
6 | - The new name of the package is: **@storybook/addon-knobs**
7 | - The location of the code is: https://github.com/storybooks/storybook/tree/master/addons/knobs
8 |
9 | The repo you're looking at now is out of date and no longer maintained.
10 |
--------------------------------------------------------------------------------
/dist/KnobManager.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | Object.defineProperty(exports, "__esModule", {
4 | value: true
5 | });
6 |
7 | var _extends2 = require('babel-runtime/helpers/extends');
8 |
9 | var _extends3 = _interopRequireDefault(_extends2);
10 |
11 | var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck');
12 |
13 | var _classCallCheck3 = _interopRequireDefault(_classCallCheck2);
14 |
15 | var _createClass2 = require('babel-runtime/helpers/createClass');
16 |
17 | var _createClass3 = _interopRequireDefault(_createClass2);
18 |
19 | var _react = require('react');
20 |
21 | var _react2 = _interopRequireDefault(_react);
22 |
23 | var _WrapStory = require('./components/WrapStory');
24 |
25 | var _WrapStory2 = _interopRequireDefault(_WrapStory);
26 |
27 | var _KnobStore = require('./KnobStore');
28 |
29 | var _KnobStore2 = _interopRequireDefault(_KnobStore);
30 |
31 | var _deepEqual = require('deep-equal');
32 |
33 | var _deepEqual2 = _interopRequireDefault(_deepEqual);
34 |
35 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
36 |
37 | // This is used by _mayCallChannel to determine how long to wait to before triggering a panel update
38 | var PANEL_UPDATE_INTERVAL = 400;
39 |
40 | var KnobManager = function () {
41 | function KnobManager() {
42 | (0, _classCallCheck3.default)(this, KnobManager);
43 |
44 | this.knobStore = null;
45 | this.knobStoreMap = {};
46 | }
47 |
48 | (0, _createClass3.default)(KnobManager, [{
49 | key: 'knob',
50 | value: function knob(name, options) {
51 | this._mayCallChannel();
52 |
53 | var knobStore = this.knobStore;
54 | var existingKnob = knobStore.get(name);
55 | // We need to return the value set by the knob editor via this.
56 | // But, if the user changes the code for the defaultValue we should set
57 | // that value instead.
58 | if (existingKnob && (0, _deepEqual2.default)(options.value, existingKnob.defaultValue)) {
59 | return existingKnob.value;
60 | }
61 |
62 | var defaultValue = options.value;
63 | var knobInfo = (0, _extends3.default)({}, options, {
64 | name: name,
65 | defaultValue: defaultValue
66 | });
67 |
68 | knobStore.set(name, knobInfo);
69 | return knobStore.get(name).value;
70 | }
71 | }, {
72 | key: 'wrapStory',
73 | value: function wrapStory(channel, storyFn, context) {
74 | this.channel = channel;
75 | var key = context.kind + ':::' + context.story;
76 | var knobStore = this.knobStoreMap[key];
77 |
78 | if (!knobStore) {
79 | knobStore = this.knobStoreMap[key] = new _KnobStore2.default();
80 | }
81 |
82 | this.knobStore = knobStore;
83 | knobStore.markAllUnused();
84 | var initialContent = storyFn(context);
85 | var props = { context: context, storyFn: storyFn, channel: channel, knobStore: knobStore, initialContent: initialContent };
86 | return _react2.default.createElement(_WrapStory2.default, props);
87 | }
88 | }, {
89 | key: '_mayCallChannel',
90 | value: function _mayCallChannel() {
91 | var _this = this;
92 |
93 | // Re rendering of the story may cause changes to the knobStore. Some new knobs maybe added and
94 | // Some knobs may go unused. So we need to update the panel accordingly. For example remove the
95 | // unused knobs from the panel. This function sends the `setKnobs` message to the channel
96 | // triggering a panel re-render.
97 |
98 | if (this.calling) {
99 | // If a call to channel has already registered ignore this call.
100 | // Once the previous call is completed all the changes to knobStore including the one that
101 | // triggered this, will be added to the panel.
102 | // This avoids emitting to the channel within very short periods of time.
103 | return;
104 | }
105 | this.calling = true;
106 |
107 | setTimeout(function () {
108 | _this.calling = false;
109 | // emit to the channel and trigger a panel re-render
110 | _this.channel.emit('addon:knobs:setKnobs', _this.knobStore.getAll());
111 | }, PANEL_UPDATE_INTERVAL);
112 | }
113 | }]);
114 | return KnobManager;
115 | }();
116 |
117 | exports.default = KnobManager;
--------------------------------------------------------------------------------
/dist/KnobStore.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | Object.defineProperty(exports, "__esModule", {
4 | value: true
5 | });
6 |
7 | var _keys = require("babel-runtime/core-js/object/keys");
8 |
9 | var _keys2 = _interopRequireDefault(_keys);
10 |
11 | var _classCallCheck2 = require("babel-runtime/helpers/classCallCheck");
12 |
13 | var _classCallCheck3 = _interopRequireDefault(_classCallCheck2);
14 |
15 | var _createClass2 = require("babel-runtime/helpers/createClass");
16 |
17 | var _createClass3 = _interopRequireDefault(_createClass2);
18 |
19 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
20 |
21 | var KnobStore = function () {
22 | function KnobStore() {
23 | (0, _classCallCheck3.default)(this, KnobStore);
24 |
25 | this.store = {};
26 | this.callbacks = [];
27 | }
28 |
29 | (0, _createClass3.default)(KnobStore, [{
30 | key: "has",
31 | value: function has(key) {
32 | return this.store[key] !== undefined;
33 | }
34 | }, {
35 | key: "set",
36 | value: function set(key, value) {
37 | this.store[key] = value;
38 | this.store[key].used = true;
39 | this.callbacks.forEach(function (cb) {
40 | return cb();
41 | });
42 | }
43 | }, {
44 | key: "get",
45 | value: function get(key) {
46 | var knob = this.store[key];
47 | if (knob) {
48 | knob.used = true;
49 | }
50 | return knob;
51 | }
52 | }, {
53 | key: "getAll",
54 | value: function getAll() {
55 | return this.store;
56 | }
57 | }, {
58 | key: "reset",
59 | value: function reset() {
60 | this.store = {};
61 | }
62 | }, {
63 | key: "markAllUnused",
64 | value: function markAllUnused() {
65 | var _this = this;
66 |
67 | (0, _keys2.default)(this.store).forEach(function (knobName) {
68 | _this.store[knobName].used = false;
69 | });
70 | }
71 | }, {
72 | key: "subscribe",
73 | value: function subscribe(cb) {
74 | this.callbacks.push(cb);
75 | }
76 | }, {
77 | key: "unsubscribe",
78 | value: function unsubscribe(cb) {
79 | var index = this.callbacks.indexOf(cb);
80 | this.callbacks.splice(index, 1);
81 | }
82 | }]);
83 | return KnobStore;
84 | }();
85 |
86 | exports.default = KnobStore;
--------------------------------------------------------------------------------
/dist/components/Panel.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | Object.defineProperty(exports, "__esModule", {
4 | value: true
5 | });
6 |
7 | var _extends2 = require('babel-runtime/helpers/extends');
8 |
9 | var _extends3 = _interopRequireDefault(_extends2);
10 |
11 | var _keys = require('babel-runtime/core-js/object/keys');
12 |
13 | var _keys2 = _interopRequireDefault(_keys);
14 |
15 | var _getPrototypeOf = require('babel-runtime/core-js/object/get-prototype-of');
16 |
17 | var _getPrototypeOf2 = _interopRequireDefault(_getPrototypeOf);
18 |
19 | var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck');
20 |
21 | var _classCallCheck3 = _interopRequireDefault(_classCallCheck2);
22 |
23 | var _createClass2 = require('babel-runtime/helpers/createClass');
24 |
25 | var _createClass3 = _interopRequireDefault(_createClass2);
26 |
27 | var _possibleConstructorReturn2 = require('babel-runtime/helpers/possibleConstructorReturn');
28 |
29 | var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2);
30 |
31 | var _inherits2 = require('babel-runtime/helpers/inherits');
32 |
33 | var _inherits3 = _interopRequireDefault(_inherits2);
34 |
35 | var _react = require('react');
36 |
37 | var _react2 = _interopRequireDefault(_react);
38 |
39 | var _PropForm = require('./PropForm');
40 |
41 | var _PropForm2 = _interopRequireDefault(_PropForm);
42 |
43 | var _types = require('./types');
44 |
45 | var _types2 = _interopRequireDefault(_types);
46 |
47 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
48 |
49 | var styles = {
50 | panelWrapper: {
51 | width: '100%'
52 | },
53 | panel: {
54 | padding: '5px',
55 | width: 'auto',
56 | position: 'relative'
57 | },
58 | noKnobs: {
59 | fontFamily: '\n -apple-system, ".SFNSText-Regular", "San Francisco", "Roboto",\n "Segoe UI", "Helvetica Neue", "Lucida Grande", sans-serif\n ',
60 | display: 'inline',
61 | width: '100%',
62 | textAlign: 'center',
63 | color: 'rgb(190, 190, 190)',
64 | padding: '10px'
65 | },
66 | resetButton: {
67 | position: 'absolute',
68 | bottom: 11,
69 | right: 10,
70 | border: 'none',
71 | borderTop: 'solid 1px rgba(0, 0, 0, 0.2)',
72 | borderLeft: 'solid 1px rgba(0, 0, 0, 0.2)',
73 | background: 'rgba(255, 255, 255, 0.5)',
74 | padding: '5px 10px',
75 | borderRadius: '4px 0 0 0',
76 | color: 'rgba(0, 0, 0, 0.5)',
77 | outline: 'none'
78 | }
79 | };
80 |
81 | var Panel = function (_React$Component) {
82 | (0, _inherits3.default)(Panel, _React$Component);
83 |
84 | function Panel(props) {
85 | (0, _classCallCheck3.default)(this, Panel);
86 |
87 | var _this = (0, _possibleConstructorReturn3.default)(this, (Panel.__proto__ || (0, _getPrototypeOf2.default)(Panel)).call(this, props));
88 |
89 | _this.handleChange = _this.handleChange.bind(_this);
90 | _this.setKnobs = _this.setKnobs.bind(_this);
91 | _this.reset = _this.reset.bind(_this);
92 |
93 | _this.state = { knobs: {} };
94 | _this.loadedFromUrl = false;
95 | _this.props.channel.on('addon:knobs:setKnobs', _this.setKnobs);
96 | return _this;
97 | }
98 |
99 | (0, _createClass3.default)(Panel, [{
100 | key: 'componentWillUnmount',
101 | value: function componentWillUnmount() {
102 | this.props.channel.removeListener('addon:knobs:setKnobs', this.setKnobs);
103 | }
104 | }, {
105 | key: 'setKnobs',
106 | value: function setKnobs(knobs) {
107 | var _this2 = this;
108 |
109 | var queryParams = {};
110 | var _props = this.props,
111 | api = _props.api,
112 | channel = _props.channel;
113 |
114 |
115 | (0, _keys2.default)(knobs).forEach(function (name) {
116 | var knob = knobs[name];
117 | // For the first time, get values from the URL and set them.
118 | if (!_this2.loadedFromUrl) {
119 | var urlValue = api.getQueryParam('knob-' + name);
120 |
121 | if (urlValue !== undefined) {
122 | // If the knob value present in url
123 | knob.value = _types2.default[knob.type].deserialize(urlValue);
124 | channel.emit('addon:knobs:knobChange', knob);
125 | }
126 | }
127 |
128 | queryParams['knob-' + name] = _types2.default[knob.type].serialize(knob.value);
129 | });
130 |
131 | this.loadedFromUrl = true;
132 | api.setQueryParams(queryParams);
133 | this.setState({ knobs: knobs });
134 | }
135 | }, {
136 | key: 'reset',
137 | value: function reset() {
138 | this.props.channel.emit('addon:knobs:reset');
139 | }
140 | }, {
141 | key: 'handleChange',
142 | value: function handleChange(changedKnob) {
143 | var _props2 = this.props,
144 | api = _props2.api,
145 | channel = _props2.channel;
146 | var knobs = this.state.knobs;
147 | var name = changedKnob.name,
148 | type = changedKnob.type,
149 | value = changedKnob.value;
150 |
151 | var newKnobs = (0, _extends3.default)({}, knobs);
152 | newKnobs[name] = (0, _extends3.default)({}, newKnobs[name], changedKnob);
153 |
154 | this.setState({ knobs: newKnobs });
155 |
156 | var queryParams = {};
157 | queryParams['knob-' + name] = _types2.default[type].serialize(value);
158 |
159 | api.setQueryParams(queryParams);
160 | channel.emit('addon:knobs:knobChange', changedKnob);
161 | }
162 | }, {
163 | key: 'render',
164 | value: function render() {
165 | var knobs = this.state.knobs;
166 |
167 | var knobsArray = (0, _keys2.default)(knobs).filter(function (key) {
168 | return knobs[key].used;
169 | }).map(function (key) {
170 | return knobs[key];
171 | });
172 |
173 | if (knobsArray.length === 0) {
174 | return _react2.default.createElement(
175 | 'div',
176 | { style: styles.noKnobs },
177 | 'NO KNOBS'
178 | );
179 | }
180 |
181 | return _react2.default.createElement(
182 | 'div',
183 | { style: styles.panelWrapper },
184 | _react2.default.createElement(
185 | 'div',
186 | { style: styles.panel },
187 | _react2.default.createElement(_PropForm2.default, { knobs: knobsArray, onFieldChange: this.handleChange })
188 | ),
189 | _react2.default.createElement(
190 | 'button',
191 | { style: styles.resetButton, onClick: this.reset },
192 | 'RESET'
193 | )
194 | );
195 | }
196 | }]);
197 | return Panel;
198 | }(_react2.default.Component);
199 |
200 | exports.default = Panel;
201 |
202 |
203 | Panel.propTypes = {
204 | channel: _react2.default.PropTypes.object,
205 | onReset: _react2.default.PropTypes.object,
206 | api: _react2.default.PropTypes.object
207 | };
--------------------------------------------------------------------------------
/dist/components/PropField.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | Object.defineProperty(exports, "__esModule", {
4 | value: true
5 | });
6 |
7 | var _getPrototypeOf = require('babel-runtime/core-js/object/get-prototype-of');
8 |
9 | var _getPrototypeOf2 = _interopRequireDefault(_getPrototypeOf);
10 |
11 | var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck');
12 |
13 | var _classCallCheck3 = _interopRequireDefault(_classCallCheck2);
14 |
15 | var _createClass2 = require('babel-runtime/helpers/createClass');
16 |
17 | var _createClass3 = _interopRequireDefault(_createClass2);
18 |
19 | var _possibleConstructorReturn2 = require('babel-runtime/helpers/possibleConstructorReturn');
20 |
21 | var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2);
22 |
23 | var _inherits2 = require('babel-runtime/helpers/inherits');
24 |
25 | var _inherits3 = _interopRequireDefault(_inherits2);
26 |
27 | var _extends2 = require('babel-runtime/helpers/extends');
28 |
29 | var _extends3 = _interopRequireDefault(_extends2);
30 |
31 | var _react = require('react');
32 |
33 | var _react2 = _interopRequireDefault(_react);
34 |
35 | var _types = require('./types');
36 |
37 | var _types2 = _interopRequireDefault(_types);
38 |
39 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
40 |
41 | var InvalidType = function InvalidType() {
42 | return _react2.default.createElement(
43 | 'span',
44 | null,
45 | 'Invalid Type'
46 | );
47 | };
48 |
49 | var stylesheet = {
50 | field: {
51 | display: 'table-row',
52 | padding: '5px'
53 | },
54 | label: {
55 | display: 'table-cell',
56 | boxSizing: 'border-box',
57 | verticalAlign: 'top',
58 | paddingRight: 5,
59 | paddingTop: 7,
60 | textAlign: 'right',
61 | width: 80,
62 | fontSize: 10,
63 | color: 'rgb(68, 68, 68)',
64 | textTransform: 'uppercase',
65 | fontWeight: 600
66 | }
67 | };
68 |
69 | stylesheet.textarea = (0, _extends3.default)({}, stylesheet.input, {
70 | height: '100px'
71 | });
72 |
73 | stylesheet.checkbox = (0, _extends3.default)({}, stylesheet.input, {
74 | width: 'auto'
75 | });
76 |
77 | var PropField = function (_React$Component) {
78 | (0, _inherits3.default)(PropField, _React$Component);
79 |
80 | function PropField(props) {
81 | (0, _classCallCheck3.default)(this, PropField);
82 |
83 | var _this = (0, _possibleConstructorReturn3.default)(this, (PropField.__proto__ || (0, _getPrototypeOf2.default)(PropField)).call(this, props));
84 |
85 | _this._onChange = _this.onChange.bind(_this);
86 | return _this;
87 | }
88 |
89 | (0, _createClass3.default)(PropField, [{
90 | key: 'onChange',
91 | value: function onChange(e) {
92 | this.props.onChange(e.target.value);
93 | }
94 | }, {
95 | key: 'render',
96 | value: function render() {
97 | var _props = this.props,
98 | onChange = _props.onChange,
99 | knob = _props.knob;
100 |
101 |
102 | var InputType = _types2.default[knob.type] || InvalidType;
103 |
104 | return _react2.default.createElement(
105 | 'div',
106 | { style: stylesheet.field },
107 | _react2.default.createElement(
108 | 'label',
109 | { htmlFor: knob.name, style: stylesheet.label },
110 | '' + knob.name
111 | ),
112 | _react2.default.createElement(InputType, {
113 | knob: knob,
114 | onChange: onChange
115 | })
116 | );
117 | }
118 | }]);
119 | return PropField;
120 | }(_react2.default.Component);
121 |
122 | exports.default = PropField;
123 |
124 |
125 | PropField.propTypes = {
126 | onChange: _react2.default.PropTypes.func.isRequired,
127 | knob: _react2.default.PropTypes.object
128 | };
--------------------------------------------------------------------------------
/dist/components/PropForm.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | Object.defineProperty(exports, "__esModule", {
4 | value: true
5 | });
6 |
7 | var _getPrototypeOf = require('babel-runtime/core-js/object/get-prototype-of');
8 |
9 | var _getPrototypeOf2 = _interopRequireDefault(_getPrototypeOf);
10 |
11 | var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck');
12 |
13 | var _classCallCheck3 = _interopRequireDefault(_classCallCheck2);
14 |
15 | var _createClass2 = require('babel-runtime/helpers/createClass');
16 |
17 | var _createClass3 = _interopRequireDefault(_createClass2);
18 |
19 | var _possibleConstructorReturn2 = require('babel-runtime/helpers/possibleConstructorReturn');
20 |
21 | var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2);
22 |
23 | var _inherits2 = require('babel-runtime/helpers/inherits');
24 |
25 | var _inherits3 = _interopRequireDefault(_inherits2);
26 |
27 | var _react = require('react');
28 |
29 | var _react2 = _interopRequireDefault(_react);
30 |
31 | var _PropField = require('./PropField');
32 |
33 | var _PropField2 = _interopRequireDefault(_PropField);
34 |
35 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
36 |
37 | var stylesheet = {
38 | propForm: {
39 | fontFamily: '\n -apple-system, ".SFNSText-Regular", "San Francisco", "Roboto",\n "Segoe UI", "Helvetica Neue", "Lucida Grande", sans-serif\n ',
40 | display: 'table',
41 | boxSizing: 'border-box',
42 | width: '100%',
43 | borderCollapse: 'separate',
44 | borderSpacing: '5px'
45 | }
46 | };
47 |
48 | var propForm = function (_React$Component) {
49 | (0, _inherits3.default)(propForm, _React$Component);
50 |
51 | function propForm() {
52 | (0, _classCallCheck3.default)(this, propForm);
53 |
54 | var _this = (0, _possibleConstructorReturn3.default)(this, (propForm.__proto__ || (0, _getPrototypeOf2.default)(propForm)).call(this));
55 |
56 | _this._onFieldChange = _this.onFieldChange.bind(_this);
57 | return _this;
58 | }
59 |
60 | (0, _createClass3.default)(propForm, [{
61 | key: 'onFieldChange',
62 | value: function onFieldChange(name, type, value) {
63 | var change = { name: name, type: type, value: value };
64 | this.props.onFieldChange(change);
65 | }
66 | }, {
67 | key: 'render',
68 | value: function render() {
69 | var _this2 = this;
70 |
71 | var knobs = this.props.knobs;
72 |
73 | return _react2.default.createElement(
74 | 'form',
75 | { style: stylesheet.propForm },
76 | knobs.map(function (knob) {
77 | return _react2.default.createElement(_PropField2.default, {
78 | key: knob.name,
79 | name: knob.name,
80 | type: knob.type,
81 | value: knob.value,
82 | knob: knob,
83 | onChange: _this2._onFieldChange.bind(null, knob.name, knob.type)
84 | });
85 | })
86 | );
87 | }
88 | }]);
89 | return propForm;
90 | }(_react2.default.Component);
91 |
92 | exports.default = propForm;
93 |
94 |
95 | propForm.displayName = 'propForm';
96 |
97 | propForm.propTypes = {
98 | knobs: _react2.default.PropTypes.array.isRequired,
99 | onFieldChange: _react2.default.PropTypes.func.isRequired
100 | };
--------------------------------------------------------------------------------
/dist/components/WrapStory.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | Object.defineProperty(exports, "__esModule", {
4 | value: true
5 | });
6 |
7 | var _getPrototypeOf = require('babel-runtime/core-js/object/get-prototype-of');
8 |
9 | var _getPrototypeOf2 = _interopRequireDefault(_getPrototypeOf);
10 |
11 | var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck');
12 |
13 | var _classCallCheck3 = _interopRequireDefault(_classCallCheck2);
14 |
15 | var _createClass2 = require('babel-runtime/helpers/createClass');
16 |
17 | var _createClass3 = _interopRequireDefault(_createClass2);
18 |
19 | var _possibleConstructorReturn2 = require('babel-runtime/helpers/possibleConstructorReturn');
20 |
21 | var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2);
22 |
23 | var _inherits2 = require('babel-runtime/helpers/inherits');
24 |
25 | var _inherits3 = _interopRequireDefault(_inherits2);
26 |
27 | var _react = require('react');
28 |
29 | var _react2 = _interopRequireDefault(_react);
30 |
31 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
32 |
33 | var WrapStory = function (_React$Component) {
34 | (0, _inherits3.default)(WrapStory, _React$Component);
35 |
36 | function WrapStory(props) {
37 | (0, _classCallCheck3.default)(this, WrapStory);
38 |
39 | var _this = (0, _possibleConstructorReturn3.default)(this, (WrapStory.__proto__ || (0, _getPrototypeOf2.default)(WrapStory)).call(this, props));
40 |
41 | _this.knobChanged = _this.knobChanged.bind(_this);
42 | _this.resetKnobs = _this.resetKnobs.bind(_this);
43 | _this.setPaneKnobs = _this.setPaneKnobs.bind(_this);
44 | _this._knobsAreReset = false;
45 | _this.state = { storyContent: _this.props.initialContent };
46 | return _this;
47 | }
48 |
49 | (0, _createClass3.default)(WrapStory, [{
50 | key: 'componentDidMount',
51 | value: function componentDidMount() {
52 | // Watch for changes in knob editor.
53 | this.props.channel.on('addon:knobs:knobChange', this.knobChanged);
54 | // Watch for the reset event and reset knobs.
55 | this.props.channel.on('addon:knobs:reset', this.resetKnobs);
56 | // Watch for any change in the knobStore and set the panel again for those
57 | // changes.
58 | this.props.knobStore.subscribe(this.setPaneKnobs);
59 | // Set knobs in the panel for the first time.
60 | this.setPaneKnobs();
61 | }
62 | }, {
63 | key: 'componentWillReceiveProps',
64 | value: function componentWillReceiveProps(props) {
65 | this.setState({ storyContent: props.initialContent });
66 | }
67 | }, {
68 | key: 'componentWillUnmount',
69 | value: function componentWillUnmount() {
70 | this.props.channel.removeListener('addon:knobs:knobChange', this.knobChanged);
71 | this.props.channel.removeListener('addon:knobs:reset', this.resetKnobs);
72 | this.props.knobStore.unsubscribe(this.setPaneKnobs);
73 | }
74 | }, {
75 | key: 'setPaneKnobs',
76 | value: function setPaneKnobs() {
77 | var _props = this.props,
78 | channel = _props.channel,
79 | knobStore = _props.knobStore;
80 |
81 | channel.emit('addon:knobs:setKnobs', knobStore.getAll());
82 | }
83 | }, {
84 | key: 'knobChanged',
85 | value: function knobChanged(change) {
86 | var name = change.name,
87 | value = change.value;
88 | var _props2 = this.props,
89 | knobStore = _props2.knobStore,
90 | storyFn = _props2.storyFn,
91 | context = _props2.context;
92 | // Update the related knob and it's value.
93 |
94 | var knobOptions = knobStore.get(name);
95 | knobOptions.value = value;
96 | knobStore.markAllUnused();
97 | this.setState({ storyContent: storyFn(context) });
98 | }
99 | }, {
100 | key: 'resetKnobs',
101 | value: function resetKnobs() {
102 | var _props3 = this.props,
103 | knobStore = _props3.knobStore,
104 | storyFn = _props3.storyFn,
105 | context = _props3.context;
106 |
107 | knobStore.reset();
108 | this.setState({ storyContent: storyFn(context) });
109 | this.setPaneKnobs();
110 | }
111 | }, {
112 | key: 'render',
113 | value: function render() {
114 | return this.state.storyContent;
115 | }
116 | }]);
117 | return WrapStory;
118 | }(_react2.default.Component);
119 |
120 | exports.default = WrapStory;
121 |
122 |
123 | WrapStory.propTypes = {
124 | context: _react2.default.PropTypes.object,
125 | storyFn: _react2.default.PropTypes.func,
126 | channel: _react2.default.PropTypes.object,
127 | knobStore: _react2.default.PropTypes.object,
128 | initialContent: _react2.default.PropTypes.object
129 | };
--------------------------------------------------------------------------------
/dist/components/types/Array.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | Object.defineProperty(exports, "__esModule", {
4 | value: true
5 | });
6 |
7 | var _getPrototypeOf = require('babel-runtime/core-js/object/get-prototype-of');
8 |
9 | var _getPrototypeOf2 = _interopRequireDefault(_getPrototypeOf);
10 |
11 | var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck');
12 |
13 | var _classCallCheck3 = _interopRequireDefault(_classCallCheck2);
14 |
15 | var _createClass2 = require('babel-runtime/helpers/createClass');
16 |
17 | var _createClass3 = _interopRequireDefault(_createClass2);
18 |
19 | var _possibleConstructorReturn2 = require('babel-runtime/helpers/possibleConstructorReturn');
20 |
21 | var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2);
22 |
23 | var _inherits2 = require('babel-runtime/helpers/inherits');
24 |
25 | var _inherits3 = _interopRequireDefault(_inherits2);
26 |
27 | var _react = require('react');
28 |
29 | var _react2 = _interopRequireDefault(_react);
30 |
31 | var _reactTextareaAutosize = require('react-textarea-autosize');
32 |
33 | var _reactTextareaAutosize2 = _interopRequireDefault(_reactTextareaAutosize);
34 |
35 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
36 |
37 | var styles = {
38 | display: 'table-cell',
39 | boxSizing: 'border-box',
40 | verticalAlign: 'middle',
41 | height: '26px',
42 | width: '100%',
43 | outline: 'none',
44 | border: '1px solid #f7f4f4',
45 | borderRadius: 2,
46 | fontSize: 11,
47 | padding: '5px',
48 | color: '#555'
49 | };
50 |
51 | var ArrayType = function (_React$Component) {
52 | (0, _inherits3.default)(ArrayType, _React$Component);
53 |
54 | function ArrayType() {
55 | (0, _classCallCheck3.default)(this, ArrayType);
56 | return (0, _possibleConstructorReturn3.default)(this, (ArrayType.__proto__ || (0, _getPrototypeOf2.default)(ArrayType)).apply(this, arguments));
57 | }
58 |
59 | (0, _createClass3.default)(ArrayType, [{
60 | key: 'render',
61 | value: function render() {
62 | var _props = this.props,
63 | knob = _props.knob,
64 | _onChange = _props.onChange;
65 |
66 | return _react2.default.createElement(_reactTextareaAutosize2.default, {
67 | id: knob.name,
68 | ref: 'input',
69 | style: styles,
70 | value: knob.value.join(knob.separator),
71 | onChange: function onChange(e) {
72 | return _onChange(e.target.value.split(knob.separator));
73 | }
74 | });
75 | }
76 | }]);
77 | return ArrayType;
78 | }(_react2.default.Component);
79 |
80 | ArrayType.propTypes = {
81 | knob: _react2.default.PropTypes.object,
82 | onChange: _react2.default.PropTypes.func
83 | };
84 |
85 | ArrayType.serialize = function (value) {
86 | return value;
87 | };
88 |
89 | ArrayType.deserialize = function (value) {
90 | return value;
91 | };
92 |
93 | exports.default = ArrayType;
--------------------------------------------------------------------------------
/dist/components/types/Boolean.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | Object.defineProperty(exports, "__esModule", {
4 | value: true
5 | });
6 |
7 | var _getPrototypeOf = require('babel-runtime/core-js/object/get-prototype-of');
8 |
9 | var _getPrototypeOf2 = _interopRequireDefault(_getPrototypeOf);
10 |
11 | var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck');
12 |
13 | var _classCallCheck3 = _interopRequireDefault(_classCallCheck2);
14 |
15 | var _createClass2 = require('babel-runtime/helpers/createClass');
16 |
17 | var _createClass3 = _interopRequireDefault(_createClass2);
18 |
19 | var _possibleConstructorReturn2 = require('babel-runtime/helpers/possibleConstructorReturn');
20 |
21 | var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2);
22 |
23 | var _inherits2 = require('babel-runtime/helpers/inherits');
24 |
25 | var _inherits3 = _interopRequireDefault(_inherits2);
26 |
27 | var _react = require('react');
28 |
29 | var _react2 = _interopRequireDefault(_react);
30 |
31 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
32 |
33 | var styles = {
34 | display: 'table-cell',
35 | boxSizing: 'border-box',
36 | verticalAlign: 'top',
37 | height: 21,
38 | outline: 'none',
39 | border: '1px solid #ececec',
40 | fontSize: '12px',
41 | color: '#555'
42 | };
43 |
44 | var BooleanType = function (_React$Component) {
45 | (0, _inherits3.default)(BooleanType, _React$Component);
46 |
47 | function BooleanType() {
48 | (0, _classCallCheck3.default)(this, BooleanType);
49 | return (0, _possibleConstructorReturn3.default)(this, (BooleanType.__proto__ || (0, _getPrototypeOf2.default)(BooleanType)).apply(this, arguments));
50 | }
51 |
52 | (0, _createClass3.default)(BooleanType, [{
53 | key: 'render',
54 | value: function render() {
55 | var _this2 = this;
56 |
57 | var _props = this.props,
58 | knob = _props.knob,
59 | _onChange = _props.onChange;
60 |
61 |
62 | return _react2.default.createElement('input', {
63 | id: knob.name,
64 | ref: 'input',
65 | style: styles,
66 | type: 'checkbox',
67 | onChange: function onChange() {
68 | return _onChange(_this2.refs.input.checked);
69 | },
70 | checked: knob.value
71 | });
72 | }
73 | }]);
74 | return BooleanType;
75 | }(_react2.default.Component);
76 |
77 | BooleanType.propTypes = {
78 | knob: _react2.default.PropTypes.object,
79 | onChange: _react2.default.PropTypes.func
80 | };
81 |
82 | BooleanType.serialize = function (value) {
83 | return String(value);
84 | };
85 |
86 | BooleanType.deserialize = function (value) {
87 | if (!value) return false;
88 | return value.trim() === 'true';
89 | };
90 |
91 | exports.default = BooleanType;
--------------------------------------------------------------------------------
/dist/components/types/Color.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | Object.defineProperty(exports, "__esModule", {
4 | value: true
5 | });
6 |
7 | var _getPrototypeOf = require('babel-runtime/core-js/object/get-prototype-of');
8 |
9 | var _getPrototypeOf2 = _interopRequireDefault(_getPrototypeOf);
10 |
11 | var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck');
12 |
13 | var _classCallCheck3 = _interopRequireDefault(_classCallCheck2);
14 |
15 | var _createClass2 = require('babel-runtime/helpers/createClass');
16 |
17 | var _createClass3 = _interopRequireDefault(_createClass2);
18 |
19 | var _possibleConstructorReturn2 = require('babel-runtime/helpers/possibleConstructorReturn');
20 |
21 | var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2);
22 |
23 | var _inherits2 = require('babel-runtime/helpers/inherits');
24 |
25 | var _inherits3 = _interopRequireDefault(_inherits2);
26 |
27 | var _react = require('react');
28 |
29 | var _react2 = _interopRequireDefault(_react);
30 |
31 | var _reactColor = require('react-color');
32 |
33 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
34 |
35 | var styles = {
36 | swatch: {
37 | background: '#fff',
38 | borderRadius: '1px',
39 | border: '1px solid rgb(247, 244, 244)',
40 | display: 'inline-block',
41 | cursor: 'pointer',
42 | width: '100%'
43 | },
44 | popover: {
45 | position: 'absolute',
46 | zIndex: '2'
47 | },
48 | cover: {
49 | position: 'fixed',
50 | top: '0px',
51 | right: '0px',
52 | bottom: '0px',
53 | left: '0px'
54 | }
55 | };
56 |
57 | var ColorType = function (_React$Component) {
58 | (0, _inherits3.default)(ColorType, _React$Component);
59 |
60 | function ColorType(props) {
61 | (0, _classCallCheck3.default)(this, ColorType);
62 |
63 | var _this = (0, _possibleConstructorReturn3.default)(this, (ColorType.__proto__ || (0, _getPrototypeOf2.default)(ColorType)).call(this, props));
64 |
65 | _this.handleClick = _this.handleClick.bind(_this);
66 | _this.onWindowMouseDown = _this.onWindowMouseDown.bind(_this);
67 | _this.state = {
68 | displayColorPicker: false
69 | };
70 | return _this;
71 | }
72 |
73 | (0, _createClass3.default)(ColorType, [{
74 | key: 'componentDidMount',
75 | value: function componentDidMount() {
76 | document.addEventListener('mousedown', this.onWindowMouseDown);
77 | }
78 | }, {
79 | key: 'componentWillUnmount',
80 | value: function componentWillUnmount() {
81 | document.removeEventListener('mousedown', this.onWindowMouseDown);
82 | }
83 | }, {
84 | key: 'onWindowMouseDown',
85 | value: function onWindowMouseDown(e) {
86 | if (!this.state.displayColorPicker) return;
87 | if (this.popover.contains(e.target)) return;
88 |
89 | this.setState({
90 | displayColorPicker: false
91 | });
92 | }
93 | }, {
94 | key: 'handleClick',
95 | value: function handleClick() {
96 | this.setState({
97 | displayColorPicker: !this.state.displayColorPicker
98 | });
99 | }
100 | }, {
101 | key: 'render',
102 | value: function render() {
103 | var _this2 = this;
104 |
105 | var _props = this.props,
106 | knob = _props.knob,
107 | _onChange = _props.onChange;
108 |
109 | var colorStyle = {
110 | width: 'auto',
111 | height: '20px',
112 | borderRadius: '2px',
113 | margin: 5,
114 | background: knob.value
115 | };
116 | return _react2.default.createElement(
117 | 'div',
118 | { id: knob.name },
119 | _react2.default.createElement(
120 | 'div',
121 | { style: styles.swatch, onClick: this.handleClick },
122 | _react2.default.createElement('div', { style: colorStyle })
123 | ),
124 | this.state.displayColorPicker ? _react2.default.createElement(
125 | 'div',
126 | { style: styles.popover, ref: function ref(e) {
127 | _this2.popover = e;
128 | } },
129 | _react2.default.createElement(_reactColor.SketchPicker, { color: knob.value, onChange: function onChange(color) {
130 | return _onChange(color.hex);
131 | } })
132 | ) : null
133 | );
134 | }
135 | }]);
136 | return ColorType;
137 | }(_react2.default.Component);
138 |
139 | ColorType.propTypes = {
140 | knob: _react2.default.PropTypes.object,
141 | onChange: _react2.default.PropTypes.func
142 | };
143 |
144 | ColorType.serialize = function (value) {
145 | return value;
146 | };
147 |
148 | ColorType.deserialize = function (value) {
149 | return value;
150 | };
151 |
152 | exports.default = ColorType;
--------------------------------------------------------------------------------
/dist/components/types/Date/index.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | Object.defineProperty(exports, "__esModule", {
4 | value: true
5 | });
6 |
7 | var _getPrototypeOf = require('babel-runtime/core-js/object/get-prototype-of');
8 |
9 | var _getPrototypeOf2 = _interopRequireDefault(_getPrototypeOf);
10 |
11 | var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck');
12 |
13 | var _classCallCheck3 = _interopRequireDefault(_classCallCheck2);
14 |
15 | var _createClass2 = require('babel-runtime/helpers/createClass');
16 |
17 | var _createClass3 = _interopRequireDefault(_createClass2);
18 |
19 | var _possibleConstructorReturn2 = require('babel-runtime/helpers/possibleConstructorReturn');
20 |
21 | var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2);
22 |
23 | var _inherits2 = require('babel-runtime/helpers/inherits');
24 |
25 | var _inherits3 = _interopRequireDefault(_inherits2);
26 |
27 | var _react = require('react');
28 |
29 | var _react2 = _interopRequireDefault(_react);
30 |
31 | var _reactDatetime = require('react-datetime');
32 |
33 | var _reactDatetime2 = _interopRequireDefault(_reactDatetime);
34 |
35 | var _insertCss = require('insert-css');
36 |
37 | var _insertCss2 = _interopRequireDefault(_insertCss);
38 |
39 | var _styles = require('./styles');
40 |
41 | var _styles2 = _interopRequireDefault(_styles);
42 |
43 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
44 |
45 | var customStyle = '\n .rdt input {\n outline: 0;\n width: 100%;\n border: 1px solid #f7f4f4;\n border-radius: 2px;\n font-size: 11px;\n padding: 5px;\n color: #555;\n display: table-cell;\n box-sizing: border-box;\n }\n';
46 |
47 | (0, _insertCss2.default)(_styles2.default);
48 | (0, _insertCss2.default)(customStyle);
49 |
50 | var DateType = function (_React$Component) {
51 | (0, _inherits3.default)(DateType, _React$Component);
52 |
53 | function DateType() {
54 | (0, _classCallCheck3.default)(this, DateType);
55 | return (0, _possibleConstructorReturn3.default)(this, (DateType.__proto__ || (0, _getPrototypeOf2.default)(DateType)).apply(this, arguments));
56 | }
57 |
58 | (0, _createClass3.default)(DateType, [{
59 | key: 'render',
60 | value: function render() {
61 | var _props = this.props,
62 | knob = _props.knob,
63 | _onChange = _props.onChange;
64 |
65 | return _react2.default.createElement(
66 | 'div',
67 | null,
68 | _react2.default.createElement(_reactDatetime2.default, {
69 | id: knob.name,
70 | value: knob.value ? new Date(knob.value) : null,
71 | type: 'date',
72 | onChange: function onChange(date) {
73 | return _onChange(date.valueOf());
74 | }
75 | })
76 | );
77 | }
78 | }]);
79 | return DateType;
80 | }(_react2.default.Component);
81 |
82 | DateType.propTypes = {
83 | knob: _react2.default.PropTypes.object,
84 | onChange: _react2.default.PropTypes.func
85 | };
86 |
87 | DateType.serialize = function (value) {
88 | return String(value);
89 | };
90 |
91 | DateType.deserialize = function (value) {
92 | return parseFloat(value);
93 | };
94 |
95 | exports.default = DateType;
--------------------------------------------------------------------------------
/dist/components/types/Date/styles.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | Object.defineProperty(exports, "__esModule", {
4 | value: true
5 | });
6 | exports.default = "\n .rdt {\n position: relative;\n }\n .rdtPicker {\n display: none;\n position: absolute;\n width: 200px;\n padding: 4px;\n margin-top: 1px;\n z-index: 99999 !important;\n background: #fff;\n box-shadow: 0 1px 3px rgba(0,0,0,.1);\n border: 1px solid #f9f9f9;\n }\n .rdtOpen .rdtPicker {\n display: block;\n }\n .rdtStatic .rdtPicker {\n box-shadow: none;\n position: static;\n }\n\n .rdtPicker .rdtTimeToggle {\n text-align: center;\n font-size:11px;\n }\n\n .rdtPicker table {\n width: 100%;\n margin: 0;\n }\n .rdtPicker td,\n .rdtPicker th {\n text-align: center;\n height: 28px;\n }\n .rdtPicker td {\n cursor: pointer;\n }\n .rdtPicker td.rdtDay:hover,\n .rdtPicker td.rdtHour:hover,\n .rdtPicker td.rdtMinute:hover,\n .rdtPicker td.rdtSecond:hover,\n .rdtPicker .rdtTimeToggle:hover {\n background: #eeeeee;\n cursor: pointer;\n }\n .rdtPicker td.rdtOld,\n .rdtPicker td.rdtNew {\n color: #999999;\n }\n .rdtPicker td.rdtToday {\n position: relative;\n }\n .rdtPicker td.rdtToday:before {\n content: '';\n display: inline-block;\n border-left: 7px solid transparent;\n border-bottom: 7px solid #428bca;\n border-top-color: rgba(0, 0, 0, 0.2);\n position: absolute;\n bottom: 4px;\n right: 4px;\n }\n .rdtPicker td.rdtActive,\n .rdtPicker td.rdtActive:hover {\n background-color: #428bca;\n color: #fff;\n text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n }\n .rdtPicker td.rdtActive.rdtToday:before {\n border-bottom-color: #fff;\n }\n .rdtPicker td.rdtDisabled,\n .rdtPicker td.rdtDisabled:hover {\n background: none;\n color: #999999;\n cursor: not-allowed;\n }\n\n .rdtPicker td span.rdtOld {\n color: #999999;\n }\n .rdtPicker td span.rdtDisabled,\n .rdtPicker td span.rdtDisabled:hover {\n background: none;\n color: #999999;\n cursor: not-allowed;\n }\n .rdtPicker th {\n border-bottom: 1px solid #f9f9f9;\n }\n .rdtPicker .dow {\n width: 14.2857%;\n font-size: 11px;\n border-bottom: none;\n }\n .rdtPicker th.rdtSwitch {\n width: 100px;\n font-size: 11px;\n }\n .rdtPicker th.rdtNext,\n .rdtPicker th.rdtPrev {\n font-size: 11px;\n vertical-align: top;\n }\n\n .rdtPrev span,\n .rdtNext span {\n display: block;\n -webkit-touch-callout: none; /* iOS Safari */\n -webkit-user-select: none; /* Chrome/Safari/Opera */\n -khtml-user-select: none; /* Konqueror */\n -moz-user-select: none; /* Firefox */\n -ms-user-select: none; /* Internet Explorer/Edge */\n user-select: none;\n }\n\n .rdtPicker th.rdtDisabled,\n .rdtPicker th.rdtDisabled:hover {\n background: none;\n color: #999999;\n cursor: not-allowed;\n }\n .rdtPicker thead tr:first-child th {\n cursor: pointer;\n }\n .rdtPicker thead tr:first-child th:hover {\n background: #eeeeee;\n }\n\n .rdtPicker tfoot {\n border-top: 1px solid #f9f9f9;\n }\n\n .rdtPicker button {\n border: none;\n background: none;\n cursor: pointer;\n }\n .rdtPicker button:hover {\n background-color: #eee;\n }\n\n .rdtPicker thead button {\n width: 100%;\n height: 100%;\n }\n\n td.rdtMonth,\n td.rdtYear {\n height: 50px;\n width: 25%;\n cursor: pointer;\n }\n td.rdtMonth:hover,\n td.rdtYear:hover {\n background: #eee;\n }\n\n td.rdtDay {\n font-size: 11px\n }\n\n .rdtCounters {\n display: inline-block;\n }\n\n .rdtCounters > div {\n float: left;\n }\n\n .rdtCounter {\n height: 100px;\n }\n\n .rdtCounter {\n width: 40px;\n }\n\n .rdtCounterSeparator {\n line-height: 100px;\n }\n\n .rdtCounter .rdtBtn {\n height: 40%;\n line-height: 40px;\n cursor: pointer;\n display: block;\n font-size: 11px;\n\n -webkit-touch-callout: none; /* iOS Safari */\n -webkit-user-select: none; /* Chrome/Safari/Opera */\n -khtml-user-select: none; /* Konqueror */\n -moz-user-select: none; /* Firefox */\n -ms-user-select: none; /* Internet Explorer/Edge */\n user-select: none;\n }\n .rdtCounter .rdtBtn:hover {\n background: #eee;\n }\n .rdtCounter .rdtCount {\n height: 20%;\n font-size: 11px;\n }\n\n .rdtMilli {\n vertical-align: middle;\n padding-left: 8px;\n width: 48px;\n }\n\n .rdtMilli input {\n width: 100%;\n font-size: 11px;\n margin-top: 37px;\n }\n";
--------------------------------------------------------------------------------
/dist/components/types/Number.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | Object.defineProperty(exports, "__esModule", {
4 | value: true
5 | });
6 |
7 | var _getPrototypeOf = require('babel-runtime/core-js/object/get-prototype-of');
8 |
9 | var _getPrototypeOf2 = _interopRequireDefault(_getPrototypeOf);
10 |
11 | var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck');
12 |
13 | var _classCallCheck3 = _interopRequireDefault(_classCallCheck2);
14 |
15 | var _createClass2 = require('babel-runtime/helpers/createClass');
16 |
17 | var _createClass3 = _interopRequireDefault(_createClass2);
18 |
19 | var _possibleConstructorReturn2 = require('babel-runtime/helpers/possibleConstructorReturn');
20 |
21 | var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2);
22 |
23 | var _inherits2 = require('babel-runtime/helpers/inherits');
24 |
25 | var _inherits3 = _interopRequireDefault(_inherits2);
26 |
27 | var _react = require('react');
28 |
29 | var _react2 = _interopRequireDefault(_react);
30 |
31 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
32 |
33 | var styles = {
34 | display: 'table-cell',
35 | boxSizing: 'border-box',
36 | verticalAlign: 'middle',
37 | height: '26px',
38 | width: '100%',
39 | outline: 'none',
40 | border: '1px solid #f7f4f4',
41 | borderRadius: 2,
42 | fontSize: 11,
43 | padding: '5px',
44 | color: '#444'
45 | };
46 |
47 | var NumberType = function (_React$Component) {
48 | (0, _inherits3.default)(NumberType, _React$Component);
49 |
50 | function NumberType(props) {
51 | (0, _classCallCheck3.default)(this, NumberType);
52 |
53 | var _this = (0, _possibleConstructorReturn3.default)(this, (NumberType.__proto__ || (0, _getPrototypeOf2.default)(NumberType)).call(this, props));
54 |
55 | _this.renderNormal = _this.renderNormal.bind(_this);
56 | _this.renderRange = _this.renderRange.bind(_this);
57 | return _this;
58 | }
59 |
60 | (0, _createClass3.default)(NumberType, [{
61 | key: 'renderNormal',
62 | value: function renderNormal() {
63 | var _this2 = this;
64 |
65 | var _props = this.props,
66 | knob = _props.knob,
67 | _onChange = _props.onChange;
68 |
69 |
70 | return _react2.default.createElement('input', {
71 | id: knob.name,
72 | ref: 'input',
73 | style: styles,
74 | value: knob.value,
75 | type: 'number',
76 | onChange: function onChange() {
77 | return _onChange(parseFloat(_this2.refs.input.value));
78 | }
79 | });
80 | }
81 | }, {
82 | key: 'renderRange',
83 | value: function renderRange() {
84 | var _this3 = this;
85 |
86 | var _props2 = this.props,
87 | knob = _props2.knob,
88 | _onChange2 = _props2.onChange;
89 |
90 |
91 | return _react2.default.createElement('input', {
92 | id: knob.name,
93 | ref: 'input',
94 | style: styles,
95 | value: knob.value,
96 | type: 'range',
97 | min: knob.min,
98 | max: knob.max,
99 | step: knob.step,
100 | onChange: function onChange() {
101 | return _onChange2(parseFloat(_this3.refs.input.value));
102 | }
103 | });
104 | }
105 | }, {
106 | key: 'render',
107 | value: function render() {
108 | var knob = this.props.knob;
109 |
110 |
111 | return knob.range ? this.renderRange() : this.renderNormal();
112 | }
113 | }]);
114 | return NumberType;
115 | }(_react2.default.Component);
116 |
117 | NumberType.propTypes = {
118 | knob: _react2.default.PropTypes.object,
119 | onChange: _react2.default.PropTypes.func
120 | };
121 |
122 | NumberType.serialize = function (value) {
123 | return String(value);
124 | };
125 |
126 | NumberType.deserialize = function (value) {
127 | return parseFloat(value);
128 | };
129 |
130 | exports.default = NumberType;
--------------------------------------------------------------------------------
/dist/components/types/Object.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | Object.defineProperty(exports, "__esModule", {
4 | value: true
5 | });
6 |
7 | var _extends2 = require('babel-runtime/helpers/extends');
8 |
9 | var _extends3 = _interopRequireDefault(_extends2);
10 |
11 | var _stringify = require('babel-runtime/core-js/json/stringify');
12 |
13 | var _stringify2 = _interopRequireDefault(_stringify);
14 |
15 | var _getPrototypeOf = require('babel-runtime/core-js/object/get-prototype-of');
16 |
17 | var _getPrototypeOf2 = _interopRequireDefault(_getPrototypeOf);
18 |
19 | var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck');
20 |
21 | var _classCallCheck3 = _interopRequireDefault(_classCallCheck2);
22 |
23 | var _createClass2 = require('babel-runtime/helpers/createClass');
24 |
25 | var _createClass3 = _interopRequireDefault(_createClass2);
26 |
27 | var _possibleConstructorReturn2 = require('babel-runtime/helpers/possibleConstructorReturn');
28 |
29 | var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2);
30 |
31 | var _inherits2 = require('babel-runtime/helpers/inherits');
32 |
33 | var _inherits3 = _interopRequireDefault(_inherits2);
34 |
35 | var _react = require('react');
36 |
37 | var _react2 = _interopRequireDefault(_react);
38 |
39 | var _reactTextareaAutosize = require('react-textarea-autosize');
40 |
41 | var _reactTextareaAutosize2 = _interopRequireDefault(_reactTextareaAutosize);
42 |
43 | var _deepEqual = require('deep-equal');
44 |
45 | var _deepEqual2 = _interopRequireDefault(_deepEqual);
46 |
47 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
48 |
49 | var styles = {
50 | display: 'table-cell',
51 | boxSizing: 'border-box',
52 | verticalAlign: 'middle',
53 | width: '100%',
54 | outline: 'none',
55 | border: '1px solid #f7f4f4',
56 | borderRadius: 2,
57 | fontSize: 11,
58 | padding: '5px',
59 | color: '#555',
60 | fontFamily: 'monospace'
61 | };
62 |
63 | var ObjectType = function (_React$Component) {
64 | (0, _inherits3.default)(ObjectType, _React$Component);
65 |
66 | function ObjectType() {
67 | var _ref;
68 |
69 | (0, _classCallCheck3.default)(this, ObjectType);
70 |
71 | for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {
72 | args[_key] = arguments[_key];
73 | }
74 |
75 | var _this = (0, _possibleConstructorReturn3.default)(this, (_ref = ObjectType.__proto__ || (0, _getPrototypeOf2.default)(ObjectType)).call.apply(_ref, [this].concat(args)));
76 |
77 | _this.state = {};
78 | return _this;
79 | }
80 |
81 | (0, _createClass3.default)(ObjectType, [{
82 | key: 'getJSONString',
83 | value: function getJSONString() {
84 | var _state = this.state,
85 | json = _state.json,
86 | jsonString = _state.jsonString;
87 | var knob = this.props.knob;
88 |
89 | // If there is an error in the JSON, we need to give that errored JSON.
90 |
91 | if (this.failed) return jsonString;
92 |
93 | // If the editor value and the knob value is the same, we need to return the
94 | // editor value as it allow user to add new fields to the JSON.
95 | if ((0, _deepEqual2.default)(json, knob.value)) return jsonString;
96 |
97 | // If the knob's value is different from the editor, it seems like
98 | // there's a outside change and we need to get that.
99 | return (0, _stringify2.default)(knob.value, null, 2);
100 | }
101 | }, {
102 | key: 'handleChange',
103 | value: function handleChange(e) {
104 | var onChange = this.props.onChange;
105 |
106 | var newState = {
107 | jsonString: e.target.value
108 | };
109 |
110 | try {
111 | newState.json = JSON.parse(e.target.value.trim());
112 | onChange(newState.json);
113 | this.failed = false;
114 | } catch (err) {
115 | this.failed = true;
116 | }
117 |
118 | this.setState(newState);
119 | }
120 | }, {
121 | key: 'render',
122 | value: function render() {
123 | var _this2 = this;
124 |
125 | var knob = this.props.knob;
126 |
127 | var jsonString = this.getJSONString();
128 | var extraStyle = {};
129 |
130 | if (this.failed) {
131 | extraStyle.border = '1px solid #fadddd';
132 | extraStyle.backgroundColor = '#fff5f5';
133 | }
134 |
135 | return _react2.default.createElement(_reactTextareaAutosize2.default, {
136 | id: knob.name,
137 | ref: 'input',
138 | style: (0, _extends3.default)({}, styles, extraStyle),
139 | value: jsonString,
140 | onChange: function onChange(e) {
141 | return _this2.handleChange(e);
142 | }
143 | });
144 | }
145 | }]);
146 | return ObjectType;
147 | }(_react2.default.Component);
148 |
149 | ObjectType.propTypes = {
150 | knob: _react2.default.PropTypes.object,
151 | onChange: _react2.default.PropTypes.func
152 | };
153 |
154 | ObjectType.serialize = function (object) {
155 | return (0, _stringify2.default)(object);
156 | };
157 |
158 | ObjectType.deserialize = function (value) {
159 | if (!value) return {};
160 | return JSON.parse(value);
161 | };
162 |
163 | exports.default = ObjectType;
--------------------------------------------------------------------------------
/dist/components/types/Select.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | Object.defineProperty(exports, "__esModule", {
4 | value: true
5 | });
6 |
7 | var _keys = require('babel-runtime/core-js/object/keys');
8 |
9 | var _keys2 = _interopRequireDefault(_keys);
10 |
11 | var _getPrototypeOf = require('babel-runtime/core-js/object/get-prototype-of');
12 |
13 | var _getPrototypeOf2 = _interopRequireDefault(_getPrototypeOf);
14 |
15 | var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck');
16 |
17 | var _classCallCheck3 = _interopRequireDefault(_classCallCheck2);
18 |
19 | var _createClass2 = require('babel-runtime/helpers/createClass');
20 |
21 | var _createClass3 = _interopRequireDefault(_createClass2);
22 |
23 | var _possibleConstructorReturn2 = require('babel-runtime/helpers/possibleConstructorReturn');
24 |
25 | var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2);
26 |
27 | var _inherits2 = require('babel-runtime/helpers/inherits');
28 |
29 | var _inherits3 = _interopRequireDefault(_inherits2);
30 |
31 | var _react = require('react');
32 |
33 | var _react2 = _interopRequireDefault(_react);
34 |
35 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
36 |
37 | var styles = {
38 | display: 'table-cell',
39 | boxSizing: 'border-box',
40 | verticalAlign: 'middle',
41 | height: '26px',
42 | width: '100%',
43 | outline: 'none',
44 | border: '1px solid #f7f4f4',
45 | borderRadius: 2,
46 | fontSize: 11,
47 | padding: '5px',
48 | color: '#555'
49 | };
50 |
51 | var SelectType = function (_React$Component) {
52 | (0, _inherits3.default)(SelectType, _React$Component);
53 |
54 | function SelectType() {
55 | (0, _classCallCheck3.default)(this, SelectType);
56 | return (0, _possibleConstructorReturn3.default)(this, (SelectType.__proto__ || (0, _getPrototypeOf2.default)(SelectType)).apply(this, arguments));
57 | }
58 |
59 | (0, _createClass3.default)(SelectType, [{
60 | key: '_makeOpt',
61 | value: function _makeOpt(key, val) {
62 | var opts = {
63 | key: key,
64 | value: key
65 | };
66 |
67 | return _react2.default.createElement(
68 | 'option',
69 | opts,
70 | val
71 | );
72 | }
73 | }, {
74 | key: '_options',
75 | value: function _options(values) {
76 | var _this2 = this;
77 |
78 | var data = [];
79 | if (Array.isArray(values)) {
80 | data = values.map(function (val) {
81 | return _this2._makeOpt(val, val);
82 | });
83 | } else {
84 | data = (0, _keys2.default)(values).map(function (key) {
85 | return _this2._makeOpt(key, values[key]);
86 | });
87 | }
88 |
89 | return data;
90 | }
91 | }, {
92 | key: 'render',
93 | value: function render() {
94 | var _props = this.props,
95 | knob = _props.knob,
96 | _onChange = _props.onChange;
97 |
98 |
99 | return _react2.default.createElement(
100 | 'select',
101 | {
102 | id: knob.name,
103 | ref: 'input',
104 | style: styles,
105 | value: knob.value,
106 | onChange: function onChange(e) {
107 | return _onChange(e.target.value);
108 | }
109 | },
110 | this._options(knob.options)
111 | );
112 | }
113 | }]);
114 | return SelectType;
115 | }(_react2.default.Component);
116 |
117 | SelectType.propTypes = {
118 | knob: _react2.default.PropTypes.object,
119 | onChange: _react2.default.PropTypes.func
120 | };
121 |
122 | SelectType.serialize = function (value) {
123 | return value;
124 | };
125 |
126 | SelectType.deserialize = function (value) {
127 | return value;
128 | };
129 |
130 | exports.default = SelectType;
--------------------------------------------------------------------------------
/dist/components/types/Text.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | Object.defineProperty(exports, "__esModule", {
4 | value: true
5 | });
6 |
7 | var _getPrototypeOf = require('babel-runtime/core-js/object/get-prototype-of');
8 |
9 | var _getPrototypeOf2 = _interopRequireDefault(_getPrototypeOf);
10 |
11 | var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck');
12 |
13 | var _classCallCheck3 = _interopRequireDefault(_classCallCheck2);
14 |
15 | var _createClass2 = require('babel-runtime/helpers/createClass');
16 |
17 | var _createClass3 = _interopRequireDefault(_createClass2);
18 |
19 | var _possibleConstructorReturn2 = require('babel-runtime/helpers/possibleConstructorReturn');
20 |
21 | var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2);
22 |
23 | var _inherits2 = require('babel-runtime/helpers/inherits');
24 |
25 | var _inherits3 = _interopRequireDefault(_inherits2);
26 |
27 | var _react = require('react');
28 |
29 | var _react2 = _interopRequireDefault(_react);
30 |
31 | var _reactTextareaAutosize = require('react-textarea-autosize');
32 |
33 | var _reactTextareaAutosize2 = _interopRequireDefault(_reactTextareaAutosize);
34 |
35 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
36 |
37 | var styles = {
38 | display: 'table-cell',
39 | boxSizing: 'border-box',
40 | verticalAlign: 'middle',
41 | height: '26px',
42 | width: '100%',
43 | outline: 'none',
44 | border: '1px solid #f7f4f4',
45 | borderRadius: 2,
46 | fontSize: 11,
47 | padding: '5px',
48 | color: '#555'
49 | };
50 |
51 | var TextType = function (_React$Component) {
52 | (0, _inherits3.default)(TextType, _React$Component);
53 |
54 | function TextType() {
55 | (0, _classCallCheck3.default)(this, TextType);
56 | return (0, _possibleConstructorReturn3.default)(this, (TextType.__proto__ || (0, _getPrototypeOf2.default)(TextType)).apply(this, arguments));
57 | }
58 |
59 | (0, _createClass3.default)(TextType, [{
60 | key: 'render',
61 | value: function render() {
62 | var _props = this.props,
63 | knob = _props.knob,
64 | _onChange = _props.onChange;
65 |
66 |
67 | return _react2.default.createElement(_reactTextareaAutosize2.default, {
68 | id: knob.name,
69 | ref: 'input',
70 | style: styles,
71 | value: knob.value,
72 | onChange: function onChange(e) {
73 | return _onChange(e.target.value);
74 | }
75 | });
76 | }
77 | }]);
78 | return TextType;
79 | }(_react2.default.Component);
80 |
81 | TextType.propTypes = {
82 | knob: _react2.default.PropTypes.object,
83 | onChange: _react2.default.PropTypes.func
84 | };
85 |
86 | TextType.serialize = function (value) {
87 | return value;
88 | };
89 |
90 | TextType.deserialize = function (value) {
91 | return value;
92 | };
93 |
94 | exports.default = TextType;
--------------------------------------------------------------------------------
/dist/components/types/index.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | Object.defineProperty(exports, "__esModule", {
4 | value: true
5 | });
6 |
7 | var _Text = require('./Text');
8 |
9 | var _Text2 = _interopRequireDefault(_Text);
10 |
11 | var _Number = require('./Number');
12 |
13 | var _Number2 = _interopRequireDefault(_Number);
14 |
15 | var _Color = require('./Color');
16 |
17 | var _Color2 = _interopRequireDefault(_Color);
18 |
19 | var _Boolean = require('./Boolean');
20 |
21 | var _Boolean2 = _interopRequireDefault(_Boolean);
22 |
23 | var _Object = require('./Object');
24 |
25 | var _Object2 = _interopRequireDefault(_Object);
26 |
27 | var _Select = require('./Select');
28 |
29 | var _Select2 = _interopRequireDefault(_Select);
30 |
31 | var _Array = require('./Array');
32 |
33 | var _Array2 = _interopRequireDefault(_Array);
34 |
35 | var _Date = require('./Date');
36 |
37 | var _Date2 = _interopRequireDefault(_Date);
38 |
39 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
40 |
41 | exports.default = {
42 | text: _Text2.default,
43 | number: _Number2.default,
44 | color: _Color2.default,
45 | boolean: _Boolean2.default,
46 | object: _Object2.default,
47 | select: _Select2.default,
48 | array: _Array2.default,
49 | date: _Date2.default
50 | };
--------------------------------------------------------------------------------
/dist/index.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | Object.defineProperty(exports, "__esModule", {
4 | value: true
5 | });
6 |
7 | var _extends2 = require('babel-runtime/helpers/extends');
8 |
9 | var _extends3 = _interopRequireDefault(_extends2);
10 |
11 | exports.knob = knob;
12 | exports.text = text;
13 | exports.boolean = boolean;
14 | exports.number = number;
15 | exports.color = color;
16 | exports.object = object;
17 | exports.select = select;
18 | exports.array = array;
19 | exports.date = date;
20 | exports.withKnobs = withKnobs;
21 |
22 | var _storybookAddons = require('@kadira/storybook-addons');
23 |
24 | var _storybookAddons2 = _interopRequireDefault(_storybookAddons);
25 |
26 | var _KnobManager = require('./KnobManager');
27 |
28 | var _KnobManager2 = _interopRequireDefault(_KnobManager);
29 |
30 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
31 |
32 | var manager = new _KnobManager2.default();
33 |
34 | function knob(name, options) {
35 | return manager.knob(name, options);
36 | }
37 |
38 | function text(name, value) {
39 | return manager.knob(name, { type: 'text', value: value });
40 | }
41 |
42 | function boolean(name, value) {
43 | return manager.knob(name, { type: 'boolean', value: value });
44 | }
45 |
46 | function number(name, value) {
47 | var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
48 |
49 | var defaults = {
50 | range: false,
51 | min: 0,
52 | max: 10,
53 | step: 1
54 | };
55 |
56 | var mergedOptions = (0, _extends3.default)({}, defaults, options);
57 |
58 | var finalOptions = (0, _extends3.default)({}, mergedOptions, {
59 | type: 'number',
60 | value: value
61 | });
62 |
63 | return manager.knob(name, finalOptions);
64 | }
65 |
66 | function color(name, value) {
67 | return manager.knob(name, { type: 'color', value: value });
68 | }
69 |
70 | function object(name, value) {
71 | return manager.knob(name, { type: 'object', value: value });
72 | }
73 |
74 | function select(name, options, value) {
75 | return manager.knob(name, { type: 'select', options: options, value: value });
76 | }
77 |
78 | function array(name, value) {
79 | var separator = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : ',';
80 |
81 | return manager.knob(name, { type: 'array', value: value, separator: separator });
82 | }
83 |
84 | function date(name) {
85 | var value = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : new Date();
86 |
87 | var proxyValue = value ? value.getTime() : null;
88 | return manager.knob(name, { type: 'date', value: proxyValue });
89 | }
90 |
91 | function withKnobs(storyFn, context) {
92 | var channel = _storybookAddons2.default.getChannel();
93 | return manager.wrapStory(channel, storyFn, context);
94 | }
--------------------------------------------------------------------------------
/dist/register.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var _react = require('react');
4 |
5 | var _react2 = _interopRequireDefault(_react);
6 |
7 | var _storybookAddons = require('@kadira/storybook-addons');
8 |
9 | var _storybookAddons2 = _interopRequireDefault(_storybookAddons);
10 |
11 | var _Panel = require('./components/Panel');
12 |
13 | var _Panel2 = _interopRequireDefault(_Panel);
14 |
15 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
16 |
17 | _storybookAddons2.default.register('kadirahq/storybook-addon-knobs', function (api) {
18 | var channel = _storybookAddons2.default.getChannel();
19 |
20 | _storybookAddons2.default.addPanel('kadirahq/storybook-addon-knobs', {
21 | title: 'Knobs',
22 | render: function render() {
23 | return _react2.default.createElement(_Panel2.default, { channel: channel, api: api, key: 'knobs-panel' });
24 | }
25 | });
26 | });
--------------------------------------------------------------------------------
/docs/demo.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/storybook-eol/storybook-addon-knobs/ab9d5913679fa59e9009f0f53bd21bed2cf999b2/docs/demo.gif
--------------------------------------------------------------------------------
/docs/demo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/storybook-eol/storybook-addon-knobs/ab9d5913679fa59e9009f0f53bd21bed2cf999b2/docs/demo.png
--------------------------------------------------------------------------------
/docs/storybook-knobs-example.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/storybook-eol/storybook-addon-knobs/ab9d5913679fa59e9009f0f53bd21bed2cf999b2/docs/storybook-knobs-example.png
--------------------------------------------------------------------------------
/example/stories/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { storiesOf } from '@kadira/storybook';
3 | import moment from 'moment';
4 | import {
5 | withKnobs,
6 | number,
7 | object,
8 | boolean,
9 | text,
10 | select,
11 | date,
12 | array,
13 | color,
14 | } from '../../src';
15 |
16 | const stories = storiesOf('Example of Knobs', module);
17 |
18 | stories.addDecorator(withKnobs);
19 |
20 | stories.add('simple example', () => (
21 |
22 | ));
23 |
24 | stories.add('with all knobs', () => {
25 | const name = text('Name', 'Tom Cary');
26 | const dob = date('DOB', new Date('January 20 1887'));
27 |
28 | const bold = boolean('Bold', false);
29 | const selectedColor = color('Color', 'black');
30 | const favoriteNumber = number('Favorite Number', 42);
31 | const comfortTemp = number('Comfort Temp', 72, {range:true, min: 60, max: 90, step: 1});
32 |
33 | const passions = array('Passions', ['Fishing', 'Skiing']);
34 |
35 | const customStyle = object('Style', {
36 | fontFamily: 'Arial',
37 | padding: 20,
38 | });
39 |
40 | const style = {
41 | ...customStyle,
42 | fontWeight: bold ? 800: 400,
43 | favoriteNumber: favoriteNumber,
44 | color: selectedColor,
45 | };
46 |
47 | return (
48 |
49 | I'm {name} and I was born on "{moment(dob).format("DD MMM YYYY")}"
50 | I like:
{passions.map((p, i) => - {p}
)}
51 |
My favorite number is {favoriteNumber}.
52 |
My most comfortable room temperature is {comfortTemp} degrees Fahrenheit.
53 |
54 | );
55 | })
56 |
57 | stories.add('dates Knob', () => {
58 | const today = date('today');
59 | const dob = date('DOB', null);
60 | const myDob = date('My DOB', new Date('July 07 1993'));
61 |
62 | return (
63 |
64 | -
65 |
Javascript Date default value, passes date value
66 |
67 | const myDob = date('My DOB', new Date('July 07 1993'));
68 | // I was born in: "{moment(myDob).format("DD MMM YYYY")}"
69 |
70 |
71 | -
72 |
undefined default value passes today's date
73 |
74 | const today = date('today');
75 | // Today's date is: "{moment(today).format("DD MMM YYYY")}"
76 |
77 |
78 | -
79 |
null default value passes null value
80 |
81 | const dob = date('DOB', null);
82 | // You were born in: "{dob? moment(dob).format("DD MMM YYYY"): 'Please select date.'}"
83 |
84 |
85 |
86 | )
87 | })
88 |
89 | stories.add('dynamic knobs', () => {
90 | const showOptional = select('Show optional', ['yes', 'no'], 'yes')
91 | return (
92 |
93 |
94 | {text('compulsary', 'I must be here')}
95 |
96 | { showOptional==='yes' ?
{text('optional', 'I can disapear')}
: null }
97 |
98 | )
99 | })
100 |
101 | stories.add('without any knob', () => (
102 |
103 | ));
104 |
--------------------------------------------------------------------------------
/example/typescript/index.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import { storiesOf } from '@kadira/storybook';
3 | import * as moment from 'moment';
4 | import {
5 | withKnobs,
6 | number,
7 | color,
8 | object,
9 | boolean,
10 | text,
11 | select,
12 | date
13 | } from '../../storybook-addon-knobs';
14 |
15 | const stories = storiesOf('Example of Knobs', module);
16 |
17 | stories.addDecorator(withKnobs);
18 |
19 | stories.add('simple example', () => (
20 |
21 | ));
22 |
23 | stories.add('with all knobs', () => {
24 | const name = text('Name', 'Tom Cary');
25 | const dob = date('DOB', new Date('January 20 1887'));
26 |
27 | const bold = boolean('Bold', false);
28 | const color = color('Color', 'black');
29 | const textDecoration = select('Decoration', {
30 | none: 'None',
31 | underline: 'Underline',
32 | "line-through": 'Line-Through'
33 | }, 'none');
34 |
35 | const customStyle = object('Style', {
36 | fontFamily: 'Arial',
37 | padding: 20,
38 | });
39 |
40 | const style = Object.assign({}, customStyle, {
41 | fontWeight: bold ? 800: 400,
42 | color,
43 | textDecoration
44 | });
45 |
46 | return (
47 |
48 | I'm {name} and I was born on "{moment(dob).format("DD MMM YYYY")}"
49 |
50 | );
51 | });
52 |
53 | stories.add('dates Knob', () => {
54 | const today = date('today');
55 | const dob = date('DOB', null);
56 | const myDob = date('My DOB', new Date('July 07 1993'));
57 |
58 | return (
59 |
60 | -
61 |
Javascript Date default value, passes date value
62 |
63 | const myDob = date('My DOB', new Date('July 07 1993'));
64 | // I was born in: "{moment(myDob).format("DD MMM YYYY")}"
65 |
66 |
67 | -
68 |
undefined default value passes today's date
69 |
70 | const today = date('today');
71 | // Today's date is: "{moment(today).format("DD MMM YYYY")}"
72 |
73 |
74 | -
75 |
null default value passes null value
76 |
77 | const dob = date('DOB', null);
78 | // You were born in: "{dob? moment(dob).format("DD MMM YYYY"): 'Please select date.'}"
79 |
80 |
81 |
82 | )
83 | });
84 |
85 | stories.add('dynamic knobs', () => {
86 | const showOptional = select('Show optional', ['yes', 'no'], 'yes')
87 | return (
88 |
89 |
90 | {text('compulsary', 'I must be here')}
91 |
92 | { showOptional==='yes' ?
{text('optional', 'I can disapear')}
: null }
93 |
94 | )
95 | });
96 |
97 | stories.add('without any knob', () => (
98 |
99 | ));
100 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@kadira/storybook-addon-knobs",
3 | "version": "1.7.1",
4 | "description": "React Storybook Addon Prop Editor Component",
5 | "repository": {
6 | "type": "git",
7 | "url": "https://github.com/kadirahq/react-storybook-addon-knobs.git"
8 | },
9 | "license": "MIT",
10 | "scripts": {
11 | "start": "./example/prepublish.sh",
12 | "prepublish": ". ./.scripts/prepublish.sh",
13 | "lint": "eslint src",
14 | "lintfix": "eslint src --fix",
15 | "testonly": "mocha --require .scripts/mocha_runner src/**/tests/**/*.js",
16 | "test": "npm run lint && npm run testonly",
17 | "test-watch": "npm run testonly -- --watch --watch-extensions js",
18 | "storybook": "start-storybook -p 9010",
19 | "publish-storybook": "bash .scripts/publish_storybook.sh"
20 | },
21 | "devDependencies": {
22 | "@kadira/storybook": "^2.1.0",
23 | "@types/mocha": "^2.2.32",
24 | "@types/node": "^6.0.46",
25 | "@types/react": "^0.14.42",
26 | "babel-cli": "^6.5.0",
27 | "babel-core": "^6.5.0",
28 | "babel-eslint": "^7.0.0",
29 | "babel-loader": "^6.2.4",
30 | "babel-plugin-transform-runtime": "^6.5.0",
31 | "babel-polyfill": "^6.5.0",
32 | "babel-preset-es2015": "^6.5.0",
33 | "babel-preset-react": "^6.5.0",
34 | "babel-preset-stage-2": "^6.5.0",
35 | "chai": "^3.5.0",
36 | "enzyme": "^2.2.0",
37 | "eslint": "^2.7.0",
38 | "eslint-config-airbnb": "^7.0.0",
39 | "eslint-plugin-babel": "^3.2.0",
40 | "eslint-plugin-jsx-a11y": "^0.6.2",
41 | "eslint-plugin-react": "^4.3.0",
42 | "git-url-parse": "^6.0.1",
43 | "jsdom": "^8.3.1",
44 | "mocha": "^3.1.0",
45 | "raw-loader": "^0.5.1",
46 | "react": "^15.3.2",
47 | "react-addons-test-utils": "^15.0.0",
48 | "react-dom": "^15.3.2",
49 | "sinon": "^1.17.3",
50 | "style-loader": "^0.13.1",
51 | "typescript": "^2.0.6",
52 | "typescript-definition-tester": "^0.0.5"
53 | },
54 | "peerDependencies": {
55 | "@kadira/storybook-addons": "^1.3.0",
56 | "react": "^0.14.7 || ^15.0.0",
57 | "react-dom": "^0.14.7 || ^15.0.0"
58 | },
59 | "dependencies": {
60 | "babel-runtime": "^6.5.0",
61 | "deep-equal": "^1.0.1",
62 | "insert-css": "^1.0.0",
63 | "moment": "^2.15.0",
64 | "react-color": "^2.4.3",
65 | "react-datetime": "^2.6.0",
66 | "react-textarea-autosize": "^4.0.5"
67 | },
68 | "main": "dist/index.js",
69 | "engines": {
70 | "npm": "^3.0.0"
71 | },
72 | "typings": "./storybook-addon-knobs.d.ts"
73 | }
74 |
--------------------------------------------------------------------------------
/register.js:
--------------------------------------------------------------------------------
1 | require('./dist/register');
2 |
--------------------------------------------------------------------------------
/src/KnobManager.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import WrapStory from './components/WrapStory';
3 | import KnobStore from './KnobStore';
4 | import deepEqual from 'deep-equal';
5 |
6 | // This is used by _mayCallChannel to determine how long to wait to before triggering a panel update
7 | const PANEL_UPDATE_INTERVAL = 400;
8 |
9 | export default class KnobManager {
10 | constructor() {
11 | this.knobStore = null;
12 | this.knobStoreMap = {};
13 | }
14 |
15 | knob(name, options) {
16 | this._mayCallChannel();
17 |
18 | const knobStore = this.knobStore;
19 | const existingKnob = knobStore.get(name);
20 | // We need to return the value set by the knob editor via this.
21 | // But, if the user changes the code for the defaultValue we should set
22 | // that value instead.
23 | if (existingKnob && deepEqual(options.value, existingKnob.defaultValue)) {
24 | return existingKnob.value;
25 | }
26 |
27 | const defaultValue = options.value;
28 | const knobInfo = {
29 | ...options,
30 | name,
31 | defaultValue,
32 | };
33 |
34 | knobStore.set(name, knobInfo);
35 | return knobStore.get(name).value;
36 | }
37 |
38 | wrapStory(channel, storyFn, context) {
39 | this.channel = channel;
40 | const key = `${context.kind}:::${context.story}`;
41 | let knobStore = this.knobStoreMap[key];
42 |
43 | if (!knobStore) {
44 | knobStore = this.knobStoreMap[key] = new KnobStore();
45 | }
46 |
47 | this.knobStore = knobStore;
48 | knobStore.markAllUnused();
49 | const initialContent = storyFn(context);
50 | const props = { context, storyFn, channel, knobStore, initialContent };
51 | return ();
52 | }
53 |
54 | _mayCallChannel() {
55 | // Re rendering of the story may cause changes to the knobStore. Some new knobs maybe added and
56 | // Some knobs may go unused. So we need to update the panel accordingly. For example remove the
57 | // unused knobs from the panel. This function sends the `setKnobs` message to the channel
58 | // triggering a panel re-render.
59 |
60 | if (this.calling) {
61 | // If a call to channel has already registered ignore this call.
62 | // Once the previous call is completed all the changes to knobStore including the one that
63 | // triggered this, will be added to the panel.
64 | // This avoids emitting to the channel within very short periods of time.
65 | return;
66 | }
67 | this.calling = true;
68 |
69 | setTimeout(() => {
70 | this.calling = false;
71 | // emit to the channel and trigger a panel re-render
72 | this.channel.emit('addon:knobs:setKnobs', this.knobStore.getAll());
73 | }, PANEL_UPDATE_INTERVAL);
74 | }
75 | }
76 |
--------------------------------------------------------------------------------
/src/KnobStore.js:
--------------------------------------------------------------------------------
1 | export default class KnobStore {
2 | constructor() {
3 | this.store = {};
4 | this.callbacks = [];
5 | }
6 |
7 | has(key) {
8 | return this.store[key] !== undefined;
9 | }
10 |
11 | set(key, value) {
12 | this.store[key] = value;
13 | this.store[key].used = true;
14 | this.callbacks.forEach(cb => cb());
15 | }
16 |
17 | get(key) {
18 | const knob = this.store[key];
19 | if (knob) {
20 | knob.used = true;
21 | }
22 | return knob;
23 | }
24 |
25 | getAll() {
26 | return this.store;
27 | }
28 |
29 | reset() {
30 | this.store = {};
31 | }
32 |
33 | markAllUnused() {
34 | Object.keys(this.store).forEach(knobName => {
35 | this.store[knobName].used = false;
36 | });
37 | }
38 |
39 | subscribe(cb) {
40 | this.callbacks.push(cb);
41 | }
42 |
43 | unsubscribe(cb) {
44 | const index = this.callbacks.indexOf(cb);
45 | this.callbacks.splice(index, 1);
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/src/components/Panel.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import PropForm from './PropForm';
3 | import Types from './types';
4 |
5 | const styles = {
6 | panelWrapper: {
7 | width: '100%',
8 | },
9 | panel: {
10 | padding: '5px',
11 | width: 'auto',
12 | position: 'relative',
13 | },
14 | noKnobs: {
15 | fontFamily: `
16 | -apple-system, ".SFNSText-Regular", "San Francisco", "Roboto",
17 | "Segoe UI", "Helvetica Neue", "Lucida Grande", sans-serif
18 | `,
19 | display: 'inline',
20 | width: '100%',
21 | textAlign: 'center',
22 | color: 'rgb(190, 190, 190)',
23 | padding: '10px',
24 | },
25 | resetButton: {
26 | position: 'absolute',
27 | bottom: 11,
28 | right: 10,
29 | border: 'none',
30 | borderTop: 'solid 1px rgba(0, 0, 0, 0.2)',
31 | borderLeft: 'solid 1px rgba(0, 0, 0, 0.2)',
32 | background: 'rgba(255, 255, 255, 0.5)',
33 | padding: '5px 10px',
34 | borderRadius: '4px 0 0 0',
35 | color: 'rgba(0, 0, 0, 0.5)',
36 | outline: 'none',
37 | },
38 | };
39 |
40 | export default class Panel extends React.Component {
41 | constructor(props) {
42 | super(props);
43 | this.handleChange = this.handleChange.bind(this);
44 | this.setKnobs = this.setKnobs.bind(this);
45 | this.reset = this.reset.bind(this);
46 |
47 | this.state = { knobs: {} };
48 | this.loadedFromUrl = false;
49 | this.props.channel.on('addon:knobs:setKnobs', this.setKnobs);
50 | }
51 |
52 | componentWillUnmount() {
53 | this.props.channel.removeListener('addon:knobs:setKnobs', this.setKnobs);
54 | }
55 |
56 | setKnobs(knobs) {
57 | const queryParams = {};
58 | const { api, channel } = this.props;
59 |
60 | Object.keys(knobs).forEach((name) => {
61 | const knob = knobs[name];
62 | // For the first time, get values from the URL and set them.
63 | if (!this.loadedFromUrl) {
64 | const urlValue = api.getQueryParam(`knob-${name}`);
65 |
66 | if (urlValue !== undefined) { // If the knob value present in url
67 | knob.value = Types[knob.type].deserialize(urlValue);
68 | channel.emit('addon:knobs:knobChange', knob);
69 | }
70 | }
71 |
72 | queryParams[`knob-${name}`] = Types[knob.type].serialize(knob.value);
73 | });
74 |
75 | this.loadedFromUrl = true;
76 | api.setQueryParams(queryParams);
77 | this.setState({ knobs });
78 | }
79 |
80 | reset() {
81 | this.props.channel.emit('addon:knobs:reset');
82 | }
83 |
84 | handleChange(changedKnob) {
85 | const { api, channel } = this.props;
86 | const { knobs } = this.state;
87 | const { name, type, value } = changedKnob;
88 | const newKnobs = { ...knobs };
89 | newKnobs[name] = {
90 | ...newKnobs[name],
91 | ...changedKnob,
92 | };
93 |
94 | this.setState({ knobs: newKnobs });
95 |
96 | const queryParams = {};
97 | queryParams[`knob-${name}`] = Types[type].serialize(value);
98 |
99 | api.setQueryParams(queryParams);
100 | channel.emit('addon:knobs:knobChange', changedKnob);
101 | }
102 |
103 | render() {
104 | const { knobs } = this.state;
105 | const knobsArray = Object.keys(knobs)
106 | .filter(key => (knobs[key].used))
107 | .map(key => (knobs[key]));
108 |
109 | if (knobsArray.length === 0) {
110 | return (
111 | NO KNOBS
112 | );
113 | }
114 |
115 | return (
116 |
122 | );
123 | }
124 | }
125 |
126 | Panel.propTypes = {
127 | channel: React.PropTypes.object,
128 | onReset: React.PropTypes.object,
129 | api: React.PropTypes.object,
130 | };
131 |
--------------------------------------------------------------------------------
/src/components/PropField.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import TypeMap from './types';
3 |
4 | const InvalidType = () => (Invalid Type);
5 |
6 | const stylesheet = {
7 | field: {
8 | display: 'table-row',
9 | padding: '5px',
10 | },
11 | label: {
12 | display: 'table-cell',
13 | boxSizing: 'border-box',
14 | verticalAlign: 'top',
15 | paddingRight: 5,
16 | paddingTop: 7,
17 | textAlign: 'right',
18 | width: 80,
19 | fontSize: 10,
20 | color: 'rgb(68, 68, 68)',
21 | fontWeight: 600,
22 | },
23 | };
24 |
25 | stylesheet.textarea = {
26 | ...stylesheet.input,
27 | height: '100px',
28 | };
29 |
30 | stylesheet.checkbox = {
31 | ...stylesheet.input,
32 | width: 'auto',
33 | };
34 |
35 | export default class PropField extends React.Component {
36 | constructor(props) {
37 | super(props);
38 | this._onChange = this.onChange.bind(this);
39 | }
40 |
41 | onChange(e) {
42 | this.props.onChange(e.target.value);
43 | }
44 |
45 | render() {
46 | const { onChange, knob } = this.props;
47 |
48 | let InputType = TypeMap[knob.type] || InvalidType;
49 |
50 | return (
51 |
52 |
55 |
59 |
60 | );
61 | }
62 | }
63 |
64 | PropField.propTypes = {
65 | onChange: React.PropTypes.func.isRequired,
66 | knob: React.PropTypes.object,
67 | };
68 |
--------------------------------------------------------------------------------
/src/components/PropForm.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | import PropField from './PropField';
4 |
5 | const stylesheet = {
6 | propForm: {
7 | fontFamily: `
8 | -apple-system, ".SFNSText-Regular", "San Francisco", "Roboto",
9 | "Segoe UI", "Helvetica Neue", "Lucida Grande", sans-serif
10 | `,
11 | display: 'table',
12 | boxSizing: 'border-box',
13 | width: '100%',
14 | borderCollapse: 'separate',
15 | borderSpacing: '5px',
16 | },
17 | };
18 |
19 | export default class propForm extends React.Component {
20 | constructor() {
21 | super();
22 | this._onFieldChange = this.onFieldChange.bind(this);
23 | }
24 |
25 | onFieldChange(name, type, value) {
26 | const change = { name, type, value };
27 | this.props.onFieldChange(change);
28 | }
29 |
30 | render() {
31 | const knobs = this.props.knobs;
32 |
33 | return (
34 |
46 | );
47 | }
48 | }
49 |
50 | propForm.displayName = 'propForm';
51 |
52 | propForm.propTypes = {
53 | knobs: React.PropTypes.array.isRequired,
54 | onFieldChange: React.PropTypes.func.isRequired,
55 | };
56 |
--------------------------------------------------------------------------------
/src/components/WrapStory.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | export default class WrapStory extends React.Component {
4 | constructor(props) {
5 | super(props);
6 | this.knobChanged = this.knobChanged.bind(this);
7 | this.resetKnobs = this.resetKnobs.bind(this);
8 | this.setPaneKnobs = this.setPaneKnobs.bind(this);
9 | this._knobsAreReset = false;
10 | this.state = { storyContent: this.props.initialContent };
11 | }
12 |
13 | componentDidMount() {
14 | // Watch for changes in knob editor.
15 | this.props.channel.on('addon:knobs:knobChange', this.knobChanged);
16 | // Watch for the reset event and reset knobs.
17 | this.props.channel.on('addon:knobs:reset', this.resetKnobs);
18 | // Watch for any change in the knobStore and set the panel again for those
19 | // changes.
20 | this.props.knobStore.subscribe(this.setPaneKnobs);
21 | // Set knobs in the panel for the first time.
22 | this.setPaneKnobs();
23 | }
24 |
25 | componentWillReceiveProps(props) {
26 | this.setState({ storyContent: props.initialContent });
27 | }
28 |
29 | componentWillUnmount() {
30 | this.props.channel.removeListener('addon:knobs:knobChange', this.knobChanged);
31 | this.props.channel.removeListener('addon:knobs:reset', this.resetKnobs);
32 | this.props.knobStore.unsubscribe(this.setPaneKnobs);
33 | }
34 |
35 | setPaneKnobs() {
36 | const { channel, knobStore } = this.props;
37 | channel.emit('addon:knobs:setKnobs', knobStore.getAll());
38 | }
39 |
40 | knobChanged(change) {
41 | const { name, value } = change;
42 | const { knobStore, storyFn, context } = this.props;
43 | // Update the related knob and it's value.
44 | const knobOptions = knobStore.get(name);
45 | knobOptions.value = value;
46 | knobStore.markAllUnused();
47 | this.setState({ storyContent: storyFn(context) });
48 | }
49 |
50 | resetKnobs() {
51 | const { knobStore, storyFn, context } = this.props;
52 | knobStore.reset();
53 | this.setState({ storyContent: storyFn(context) });
54 | this.setPaneKnobs();
55 | }
56 |
57 | render() {
58 | return this.state.storyContent;
59 | }
60 | }
61 |
62 | WrapStory.propTypes = {
63 | context: React.PropTypes.object,
64 | storyFn: React.PropTypes.func,
65 | channel: React.PropTypes.object,
66 | knobStore: React.PropTypes.object,
67 | initialContent: React.PropTypes.object,
68 | };
69 |
--------------------------------------------------------------------------------
/src/components/tests/Array.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { shallow } from 'enzyme';
3 | import Array from '../types/Array';
4 | import { expect } from 'chai';
5 | import sinon from 'sinon';
6 | const { describe, it } = global;
7 |
8 | describe('Array', () => {
9 | it('should subscribe to setKnobs event of channel', () => {
10 | const onChange = sinon.spy();
11 | const wrapper = shallow();
14 |
15 | wrapper.simulate('change', { target: { value: 'Fhishing,Skiing,Dancing' } });
16 | expect(onChange.calledWith(['Fhishing', 'Skiing', 'Dancing'])).to.equal(true);
17 | });
18 | });
19 |
--------------------------------------------------------------------------------
/src/components/tests/Panel.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { shallow } from 'enzyme';
3 | import Panel from '../Panel';
4 | import { expect } from 'chai';
5 | import sinon from 'sinon';
6 | const { describe, it } = global;
7 |
8 | describe('Panel', () => {
9 | it('should subscribe to setKnobs event of channel', () => {
10 | const testChannel = { on: sinon.spy() };
11 | shallow();
12 | expect(testChannel.on.calledWith('addon:knobs:setKnobs')).to.equal(true);
13 | });
14 |
15 | describe('setKnobs handler', () => {
16 | it('should read url params and set values for existing knobs', () => {
17 | const handlers = {};
18 |
19 | const testChannel = {
20 | on: (e, handler) => {
21 | handlers[e] = handler;
22 | },
23 | emit: sinon.spy(),
24 | };
25 |
26 | const testQueryParams = {
27 | 'knob-foo': 'test string',
28 | bar: 'some other string',
29 | };
30 |
31 | const testApi = {
32 | getQueryParam: key => {
33 | return testQueryParams[key];
34 | },
35 | setQueryParams: sinon.spy(),
36 | };
37 |
38 | shallow();
39 | const setKnobsHandler = handlers['addon:knobs:setKnobs'];
40 |
41 | const knobs = {
42 | foo: {
43 | name: 'foo',
44 | value: 'default string',
45 | type: 'text',
46 | },
47 | baz: {
48 | name: 'baz',
49 | value: 'another knob value',
50 | type: 'text',
51 | },
52 | };
53 |
54 | setKnobsHandler(knobs);
55 | const knobFromUrl = {
56 | name: 'foo',
57 | value: testQueryParams['knob-foo'],
58 | type: 'text',
59 | };
60 | const e = 'addon:knobs:knobChange';
61 | expect(testChannel.emit.calledWith(e, knobFromUrl)).to.equal(true);
62 | });
63 |
64 | it('should set query params when url params are already read', () => {
65 | const handlers = {};
66 |
67 | const testChannel = {
68 | on: (e, handler) => {
69 | handlers[e] = handler;
70 | },
71 | emit: sinon.spy(),
72 | };
73 |
74 | const testQueryParams = {
75 | 'knob-foo': 'test string',
76 | bar: 'some other string',
77 | };
78 |
79 | const testApi = {
80 | getQueryParam: key => {
81 | return testQueryParams[key];
82 | },
83 | setQueryParams: sinon.spy(),
84 | };
85 |
86 | const wrapper = shallow();
87 | const setKnobsHandler = handlers['addon:knobs:setKnobs'];
88 |
89 | const knobs = {
90 | foo: {
91 | name: 'foo',
92 | value: 'default string',
93 | type: 'text',
94 | },
95 | baz: {
96 | name: 'baz',
97 | value: 'another knob value',
98 | type: 'text',
99 | },
100 | };
101 |
102 | // Make it act like that url params are already checked
103 | wrapper.instance().loadedFromUrl = true;
104 |
105 | setKnobsHandler(knobs);
106 | const knobFromStory = {
107 | 'knob-foo': knobs.foo.value,
108 | 'knob-baz': knobs.baz.value,
109 | };
110 |
111 | expect(testApi.setQueryParams.calledWith(knobFromStory)).to.equal(true);
112 | });
113 | });
114 |
115 | describe('handleChange()', () => {
116 | it('should set queryParams and emit knobChange event', () => {
117 | const testChannel = {
118 | on: sinon.spy(),
119 | emit: sinon.spy(),
120 | };
121 |
122 | const testApi = {
123 | getQueryParam: sinon.spy(),
124 | setQueryParams: sinon.spy(),
125 | };
126 |
127 | const wrapper = shallow();
128 |
129 | const testChangedKnob = {
130 | name: 'foo',
131 | value: 'changed text',
132 | type: 'text',
133 | };
134 | wrapper.instance().handleChange(testChangedKnob);
135 | expect(testChannel.emit.calledWith(
136 | 'addon:knobs:knobChange', testChangedKnob)).to.equal(true);
137 |
138 | const paramsChange = { 'knob-foo': 'changed text' };
139 | expect(testApi.setQueryParams.calledWith(paramsChange)).to.equal(true);
140 | });
141 | });
142 | });
143 |
--------------------------------------------------------------------------------
/src/components/types/Array.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import Textarea from 'react-textarea-autosize';
3 |
4 | const styles = {
5 | display: 'table-cell',
6 | boxSizing: 'border-box',
7 | verticalAlign: 'middle',
8 | height: '26px',
9 | width: '100%',
10 | outline: 'none',
11 | border: '1px solid #f7f4f4',
12 | borderRadius: 2,
13 | fontSize: 11,
14 | padding: '5px',
15 | color: '#555',
16 | };
17 |
18 | class ArrayType extends React.Component {
19 | render() {
20 | const { knob, onChange } = this.props;
21 | return (
22 |