├── .prettierignore ├── example ├── next.config.js ├── pages │ ├── _app.js │ └── index.js ├── package.json └── components │ ├── Stats.js │ └── ReactDatGui.js ├── src ├── components │ ├── Picker │ │ ├── Pointer.js │ │ ├── PointerCircle.js │ │ ├── Fields.js │ │ └── index.js │ ├── utils.js │ ├── DatButton.js │ ├── DatFolder.js │ ├── DatBoolean.js │ ├── DatSelect.js │ ├── DatPresets.js │ ├── DatString.js │ ├── Slider.js │ ├── DatColor.js │ └── DatNumber.js ├── style │ ├── _select.scss │ ├── _string.scss │ ├── dat.scss │ ├── _presets.scss │ ├── _button.scss │ ├── _boolean.scss │ ├── _folder.scss │ ├── _number.scss │ ├── _vars.scss │ ├── _main.scss │ └── _color.scss ├── __tests__ │ └── DatGUI.test.js └── index.js ├── .stylelintrc.js ├── .prettierrc.js ├── .travis.yml ├── .babelrc.js ├── .editorconfig ├── jest.config.js ├── .eslintrc.js ├── LICENSE ├── rollup.config.js ├── .gitignore ├── index.d.ts ├── dist ├── index.d.ts ├── index.css ├── index.es.js └── index.es.js.map ├── CONTRIBUTING.md ├── package.json ├── CHANGELOG.md └── README.md /.prettierignore: -------------------------------------------------------------------------------- 1 | node_modules/** 2 | example/node_modules/** -------------------------------------------------------------------------------- /example/next.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | assetPrefix: process.env.NODE_ENV === 'production' ? '/react-dat-gui' : '' 3 | }; 4 | -------------------------------------------------------------------------------- /src/components/Picker/Pointer.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | const Pointer = () =>
; 4 | 5 | export default Pointer; 6 | -------------------------------------------------------------------------------- /src/components/Picker/PointerCircle.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | const PointerCircle = () =>
; 4 | 5 | export default PointerCircle; 6 | -------------------------------------------------------------------------------- /src/style/_select.scss: -------------------------------------------------------------------------------- 1 | .react-dat-gui .cr.select { 2 | border-left: $border-left-size solid $select-color; 3 | 4 | label { 5 | padding: 6px 2px 6px 8px; 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /example/pages/_app.js: -------------------------------------------------------------------------------- 1 | import 'react-dat-gui/dist/index.css'; 2 | 3 | function MyApp({ Component, pageProps }) { 4 | return ; 5 | } 6 | 7 | export default MyApp; 8 | -------------------------------------------------------------------------------- /.stylelintrc.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Configure Stylelint 3 | * 4 | * @see https://github.com/stylelint/stylelint-config-recommended 5 | */ 6 | module.exports = { 7 | extends: ['stylelint-config-recommended'] 8 | }; 9 | -------------------------------------------------------------------------------- /.prettierrc.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Configure Prettier 3 | * 4 | * https://prettier.io/docs/en/configuration.html#basic-configuration 5 | */ 6 | module.exports = { 7 | singleQuote: true, 8 | semi: true 9 | }; 10 | -------------------------------------------------------------------------------- /src/style/_string.scss: -------------------------------------------------------------------------------- 1 | .react-dat-gui .cr.string { 2 | border-left: $border-left-size solid $string-color; 3 | 4 | input[type='text'] { 5 | color: $string-color; 6 | padding: 2px 5px; 7 | width: 100%; 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/style/dat.scss: -------------------------------------------------------------------------------- 1 | @import 'vars'; 2 | @import 'main'; 3 | @import 'boolean'; 4 | @import 'button'; 5 | @import 'folder'; 6 | @import 'number'; 7 | @import 'string'; 8 | @import 'select'; 9 | @import 'color'; 10 | @import 'presets'; 11 | -------------------------------------------------------------------------------- /src/style/_presets.scss: -------------------------------------------------------------------------------- 1 | .react-dat-gui .cr.presets { 2 | border-left: $border-left-size solid $presets-color; 3 | 4 | label { 5 | padding: 6px 2px 6px 8px; 6 | 7 | select { 8 | width: 100%; 9 | } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/__tests__/DatGUI.test.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { render } from '@testing-library/react'; 3 | import DatGUI from '../index'; 4 | 5 | test('Renders without errors', () => { 6 | render( null} />); 7 | }); 8 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - 'node' 4 | install: npm install 5 | script: 6 | - npm run lint 7 | - npm run test 8 | branches: 9 | - master 10 | - develop 11 | - /^feature.*$/ 12 | notifications: 13 | email: false 14 | cache: 15 | npm: true 16 | -------------------------------------------------------------------------------- /src/style/_button.scss: -------------------------------------------------------------------------------- 1 | .react-dat-gui .cr.button { 2 | border-left: $border-left-size solid $button-color; 3 | 4 | &:hover { 5 | background: #111; 6 | } 7 | 8 | .label-text { 9 | display: block; 10 | width: 100%; 11 | padding: 6px 2px 6px 8px; 12 | cursor: pointer; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/style/_boolean.scss: -------------------------------------------------------------------------------- 1 | .react-dat-gui .cr.boolean { 2 | position: relative; 3 | border-left: $border-left-size solid $boolean-color; 4 | 5 | label { 6 | cursor: pointer; 7 | } 8 | 9 | .label-text { 10 | display: block; 11 | padding: 5px 0; 12 | } 13 | 14 | .checkbox-container { 15 | width: 100%; 16 | } 17 | 18 | input[type='checkbox'] { 19 | margin: 0; 20 | vertical-align: middle; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /.babelrc.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Configure Babel for Rollup 3 | * 4 | * @see https://babeljs.io/docs/en/options 5 | */ 6 | module.exports = { 7 | presets: ['@babel/env', '@babel/react'], 8 | plugins: [ 9 | ['@babel/plugin-proposal-class-properties'], 10 | ['@babel/plugin-proposal-object-rest-spread'], 11 | ['transform-react-remove-prop-types', { removeImport: true }], 12 | ['@babel/plugin-transform-runtime', { regenerator: false }] 13 | ] 14 | }; 15 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig is awesome: http://EditorConfig.org 2 | 3 | # top-most EditorConfig file 4 | root = true 5 | 6 | # Unix-style newlines with a newline ending every file 7 | [*] 8 | end_of_line = lf 9 | insert_final_newline = true 10 | 11 | [*.json] 12 | indent_style = space 13 | indent_size = 2 14 | 15 | [*.js] 16 | indent_size = 2 17 | indent_style = space 18 | 19 | [*.md] 20 | indent_size = 2 21 | indent_style = space 22 | 23 | [*.scss] 24 | indent_size = 2 25 | indent_style = space 26 | -------------------------------------------------------------------------------- /src/style/_folder.scss: -------------------------------------------------------------------------------- 1 | .react-dat-gui li.folder { 2 | display: block; 3 | padding: 0; 4 | 5 | .title { 6 | font-weight: bold; 7 | user-select: none; 8 | display: block; 9 | cursor: pointer; 10 | padding: 5px 5px 5px 16px; 11 | background: $folder-open; 12 | } 13 | 14 | ul { 15 | margin-left: $nest-margin; 16 | width: calc(100% - #{$nest-margin}); 17 | } 18 | 19 | &.closed { 20 | .title { 21 | background: $folder-closed; 22 | } 23 | 24 | ul { 25 | display: none; 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/style/_number.scss: -------------------------------------------------------------------------------- 1 | .react-dat-gui .cr.number { 2 | border-left: $border-left-size solid $number-color; 3 | 4 | input[type='text'], 5 | input[type='number'] { 6 | color: $number-color; 7 | height: $number-height; 8 | } 9 | 10 | .slider { 11 | display: block; 12 | position: relative; 13 | border: 3px solid $background-color; 14 | border-right-width: 1px; 15 | background-color: $input-color; 16 | background-image: linear-gradient(90deg, $number-color, $number-color); 17 | background-size: 0% 100%; 18 | background-repeat: no-repeat; 19 | cursor: ew-resize; 20 | height: $number-height; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /jest.config.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Configure Jest as the test runner for @testing-library 3 | * 4 | * @see https://jestjs.io/docs/en/configuration 5 | * @see https://testing-library.com/docs/react-testing-library/setup 6 | */ 7 | module.exports = { 8 | setupFilesAfterEnv: [ 9 | '@testing-library/jest-dom/extend-expect', 10 | 'babel-polyfill' 11 | ], 12 | collectCoverage: true, 13 | coveragePathIgnorePatterns: ['/node_modules/', '/__tests__/'], 14 | testMatch: ['**/__tests__/**/*.(spec|test).[jt]s?(x)'], 15 | // https://jestjs.io/docs/en/webpack.html#mocking-css-modules 16 | moduleNameMapper: { 17 | '\\.(scss)$': 'identity-obj-proxy' 18 | } 19 | }; 20 | -------------------------------------------------------------------------------- /example/pages/index.js: -------------------------------------------------------------------------------- 1 | import Head from 'next/head'; 2 | import ReactDatGui from '../components/ReactDatGui'; 3 | 4 | const Page = () => ( 5 | <> 6 | 7 | 8 | 9 | 10 | 22 | 23 | 24 | ); 25 | 26 | export default Page; 27 | -------------------------------------------------------------------------------- /src/components/utils.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-restricted-globals */ 2 | export function toNumber(value) { 3 | const float = parseFloat(value); 4 | return isNaN(float) ? 0 : float; 5 | } 6 | 7 | /** 8 | * Polyfill for isInteger. 9 | * 10 | * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/isInteger#Polyfill 11 | * @param {number} value 12 | * @return {bool} 13 | */ 14 | export const isInteger = 15 | Number.isInteger || 16 | // eslint-disable-next-line func-names 17 | function(value) { 18 | return ( 19 | typeof value === 'number' && 20 | isFinite(value) && 21 | Math.floor(value) === value 22 | ); 23 | }; 24 | -------------------------------------------------------------------------------- /src/components/DatButton.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import PropTypes from 'prop-types'; 3 | import cx from 'classnames'; 4 | 5 | const DatButton = ({ label, onClick, className, style }) => ( 6 |
  • 7 | 14 | {label} 15 | 16 |
  • 17 | ); 18 | 19 | DatButton.propTypes = { 20 | className: PropTypes.string, 21 | style: PropTypes.object, 22 | label: PropTypes.string, 23 | onClick: PropTypes.func.isRequired 24 | }; 25 | 26 | DatButton.defaultProps = { 27 | className: null, 28 | style: null, 29 | label: null 30 | }; 31 | 32 | export default DatButton; 33 | -------------------------------------------------------------------------------- /example/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-dat-gui-example", 3 | "homepage": "https://claus.github.io/react-dat-gui", 4 | "version": "0.1.0", 5 | "private": true, 6 | "browserslist": [ 7 | ">0.2%", 8 | "not dead", 9 | "not ie <= 11", 10 | "not op_mini all" 11 | ], 12 | "dependencies": { 13 | "next": "^10.1.1", 14 | "prop-types": "^15.7.2", 15 | "react": "file:../node_modules/react", 16 | "react-dat-gui": "file:..", 17 | "react-dom": "file:../node_modules/react-dom" 18 | }, 19 | "scripts": { 20 | "dev": "next", 21 | "start": "next start", 22 | "build": "next build", 23 | "export": "npm run clean && next build && next export", 24 | "clean": "shx rm -rf out", 25 | "deploy": "npm run export && shx touch out/.nojekyll && gh-pages -t -d out && npm run clean" 26 | }, 27 | "devDependencies": { 28 | "gh-pages": "^3.1.0", 29 | "shx": "^0.3.3" 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/style/_vars.scss: -------------------------------------------------------------------------------- 1 | $background-color: #1a1a1a; 2 | 3 | $hover-lighten: 5%; 4 | $border-lighten: 5%; 5 | $active-lighten: 10%; 6 | 7 | $number-color: #2fa1d6; 8 | $boolean-color: #806787; 9 | $string-color: #1ed36f; 10 | $button-color: #e61d5f; 11 | $save-row-color: #dad5cb; 12 | $select-color: #f4d450; 13 | $presets-color: #dad5cb; 14 | 15 | $border-color: lighten($background-color, $border-lighten); 16 | $input-color: lighten($background-color, 8.5%); 17 | $input-border: 3px solid $background-color; 18 | $input-padding: 2px 5px; 19 | 20 | $border-left-size: 5px; 21 | 22 | $folder-closed: #000 23 | url(data:image/gif;base64,R0lGODlhBQAFAJEAAP////Pz8////////yH5BAEAAAIALAAAAAAFAAUAAAIIlGIWqMCbWAEAOw==) 24 | 6px 48% no-repeat; 25 | $folder-open: #000 26 | url(data:image/gif;base64,R0lGODlhBQAFAJEAAP////Pz8////////yH5BAEAAAIALAAAAAAFAAUAAAIIlI+hKgFxoCgAOw==) 27 | 6px 48% no-repeat; 28 | 29 | $nest-margin: 4px; 30 | $number-height: 25px; 31 | -------------------------------------------------------------------------------- /src/components/Picker/Fields.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import PropTypes from 'prop-types'; 3 | import { EditableInput } from 'react-color/lib/components/common'; 4 | import color from 'react-color/lib/helpers/color'; 5 | 6 | export default class Fields extends Component { 7 | static propTypes = { 8 | hex: PropTypes.string.isRequired, 9 | onChange: PropTypes.func.isRequired 10 | }; 11 | 12 | handleChange = (value, e) => { 13 | const { onChange } = this.props; 14 | 15 | if (color.isValidHex(value)) 16 | onChange( 17 | { 18 | hex: value, 19 | source: 'hex' 20 | }, 21 | e 22 | ); 23 | }; 24 | 25 | render() { 26 | const { hex } = this.props; 27 | 28 | return ( 29 |
    30 |
    31 |
    32 | 33 |
    34 |
    35 |
    36 | ); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Configure ESLint 3 | * 4 | * @see https://eslint.org/docs/user-guide/configuring 5 | */ 6 | module.exports = { 7 | parser: 'babel-eslint', 8 | env: { 9 | browser: true, 10 | es6: true, 11 | jest: true 12 | }, 13 | extends: ['airbnb', 'prettier', 'prettier/react', 'plugin:import/warnings'], 14 | plugins: ['prettier', 'jsx-a11y', 'import'], 15 | globals: { 16 | document: true, 17 | window: true 18 | }, 19 | parserOptions: { 20 | sourceType: 'module' 21 | }, 22 | rules: { 23 | 'react/forbid-prop-types': 0, 24 | 'react/jsx-filename-extension': 0, 25 | 'react/react-in-jsx-scope': 0, 26 | 'class-methods-use-this': 0, 27 | 'no-unused-expressions': ['error', { allowTaggedTemplates: true }], 28 | 'react/no-unused-prop-types': 0, 29 | 'consistent-return': 0, 30 | 'jsx-a11y/anchor-is-valid': 0, 31 | 'jsx-a11y/label-has-associated-control': 0, 32 | 'prettier/prettier': 'error', 33 | 'react/destructuring-assignment': 0, 34 | 'react/static-property-placement': 0, 35 | 'react/jsx-props-no-spreading': 0 36 | } 37 | }; 38 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2017 Claus Wahlers, Rohan Deshpande 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 all 13 | 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 THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /example/components/Stats.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import PropTypes from 'prop-types'; 3 | 4 | const Stats = ({ data }) => ( 5 |
    6 |

    7 | react-dat-gui 8 |

    9 |

    Use the controls and watch your changes happen in real time!

    10 |
    11 |
    12 | String value: {data.string} 13 |
    14 |
    15 | Slider value: {data.minMaxNumber} 16 |
    17 |
    18 | Number value: {data.number} 19 |
    20 |
    21 | Checkbox value: {data.boolean.toString()} 22 |
    23 |
    24 | Select value: {data.select} 25 |
    26 |
    27 | Picked color:{' '} 28 |
    36 |
    37 |
    38 | Click the button for a random number: {data.random} 39 |
    40 |
    41 | Nested string value: {data.nested.string} 42 |
    43 |
    44 |
    45 | ); 46 | 47 | Stats.propTypes = { 48 | data: PropTypes.object.isRequired 49 | }; 50 | 51 | export default Stats; 52 | -------------------------------------------------------------------------------- /rollup.config.js: -------------------------------------------------------------------------------- 1 | import path from 'path'; 2 | import babel from '@rollup/plugin-babel'; 3 | import commonjs from '@rollup/plugin-commonjs'; 4 | import resolve from '@rollup/plugin-node-resolve'; 5 | import filesize from 'rollup-plugin-filesize'; 6 | import postcss from 'rollup-plugin-postcss'; 7 | import autoprefixer from 'autoprefixer'; 8 | import cssnano from 'cssnano'; 9 | import copy from 'rollup-plugin-copy'; 10 | import pkg from './package.json'; 11 | 12 | const root = process.platform === 'win32' ? path.resolve('/') : '/'; 13 | 14 | /** 15 | * Rollup config for building the react-dat-gui library 16 | * 17 | * @see https://rollupjs.org/guide/en/#using-config-files 18 | */ 19 | export default { 20 | input: './src/index.js', 21 | output: [ 22 | { 23 | file: pkg.main, 24 | format: 'cjs', 25 | sourcemap: true, 26 | exports: 'named', 27 | }, 28 | { 29 | file: pkg.module, 30 | format: 'es', 31 | sourcemap: true, 32 | } 33 | ], 34 | external: id => 35 | !id.startsWith('.') && !id.startsWith(root) && !id.includes('style-inject'), 36 | plugins: [ 37 | postcss({ plugins: [autoprefixer, cssnano], extract: pkg.style }), 38 | babel({ 39 | exclude: 'node_modules/**', 40 | babelHelpers: 'runtime' 41 | }), 42 | resolve(), 43 | commonjs({ 44 | include: 'node_modules/**' 45 | }), 46 | filesize(), 47 | copy({ 48 | targets: [{ src: './index.d.ts', dest: 'dist' }] 49 | }) 50 | ] 51 | }; 52 | -------------------------------------------------------------------------------- /src/components/Picker/index.js: -------------------------------------------------------------------------------- 1 | import { ColorWrap, Hue, Saturation } from 'react-color/lib/components/common'; 2 | import PropTypes from 'prop-types'; 3 | import React from 'react'; 4 | import Fields from './Fields'; 5 | import Pointer from './Pointer'; 6 | import PointerCircle from './PointerCircle'; 7 | 8 | const Picker = ({ onChange, hsl, hsv, hex, className = '' }) => { 9 | return ( 10 |
    11 |
    12 | 19 |
    20 |
    21 |
    22 |
    23 |
    24 | 30 |
    31 |
    32 |
    33 | 34 |
    35 |
    36 | ); 37 | }; 38 | 39 | Picker.propTypes = { 40 | onChange: PropTypes.func.isRequired, 41 | hsl: PropTypes.string, 42 | hsv: PropTypes.string, 43 | hex: PropTypes.string, 44 | className: PropTypes.string, 45 | disableAlpha: PropTypes.bool 46 | }; 47 | 48 | Picker.defaultProps = { 49 | hsl: null, 50 | hsv: null, 51 | hex: null, 52 | className: null, 53 | disableAlpha: false 54 | }; 55 | 56 | export default ColorWrap(Picker); 57 | -------------------------------------------------------------------------------- /src/components/DatFolder.js: -------------------------------------------------------------------------------- 1 | import React, { Component, cloneElement } from 'react'; 2 | import PropTypes from 'prop-types'; 3 | import cx from 'classnames'; 4 | 5 | export default class DatFolder extends Component { 6 | static propTypes = { 7 | className: PropTypes.string, 8 | style: PropTypes.object, 9 | title: PropTypes.string, 10 | closed: PropTypes.bool, 11 | children: PropTypes.element.isRequired 12 | }; 13 | 14 | static defaultProps = { 15 | className: null, 16 | style: null, 17 | title: 'Folder', 18 | closed: true 19 | }; 20 | 21 | constructor(props) { 22 | super(props); 23 | this.state = { closed: props.closed }; 24 | } 25 | 26 | handleClick = () => 27 | this.setState(prevState => ({ closed: !prevState.closed })); 28 | 29 | renderChildren() { 30 | // Disable this rule to take title out of the props so nested folders can have unique titles. 31 | // eslint-disable-next-line no-unused-vars 32 | const { children, title, ...rest } = this.props; 33 | 34 | return React.Children.map(children, child => 35 | cloneElement(child, { ...rest }) 36 | ); 37 | } 38 | 39 | render() { 40 | const { closed } = this.state; 41 | const { title, className, style } = this.props; 42 | 43 | return ( 44 |
  • 45 |
    46 |
    53 | {title} 54 |
    55 |
      {this.renderChildren()}
    56 |
    57 |
  • 58 | ); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Build ... 2 | node_modules 3 | npm-debug.log 4 | tmp 5 | 6 | # Next 7 | 8 | .next 9 | 10 | # Created by https://www.gitignore.io 11 | 12 | ### OSX ### 13 | .DS_Store 14 | .AppleDouble 15 | .LSOverride 16 | 17 | # Icon must end with two \r 18 | Icon 19 | 20 | 21 | # Thumbnails 22 | ._* 23 | 24 | # Files that might appear in the root of a volume 25 | .DocumentRevisions-V100 26 | .fseventsd 27 | .Spotlight-V100 28 | .TemporaryItems 29 | .Trashes 30 | .VolumeIcon.icns 31 | 32 | # Directories potentially created on remote AFP share 33 | .AppleDB 34 | .AppleDesktop 35 | Network Trash Folder 36 | Temporary Items 37 | .apdisk 38 | 39 | 40 | ### Vim ### 41 | [._]*.s[a-w][a-z] 42 | [._]s[a-w][a-z] 43 | *.un~ 44 | Session.vim 45 | .netrwhist 46 | *~ 47 | 48 | 49 | ### SublimeText ### 50 | # cache files for sublime text 51 | *.tmlanguage.cache 52 | *.tmPreferences.cache 53 | *.stTheme.cache 54 | 55 | # workspace files are user-specific 56 | *.sublime-workspace 57 | 58 | # project files should be checked into the repository, unless a significant 59 | # proportion of contributors will probably not be using SublimeText 60 | # *.sublime-project 61 | 62 | # sftp configuration file 63 | sftp-config.json 64 | 65 | 66 | ### Node ### 67 | # Logs 68 | logs 69 | *.log 70 | 71 | # Runtime data 72 | pids 73 | *.pid 74 | *.seed 75 | 76 | # Directory for instrumented libs generated by jscoverage/JSCover 77 | lib-cov 78 | 79 | # Coverage directory used by tools like istanbul 80 | coverage 81 | 82 | # node-waf configuration 83 | .lock-wscript 84 | 85 | # Compiled binary addons (http://nodejs.org/api/addons.html) 86 | 87 | # Dependency directory 88 | # https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git 89 | node_modules 90 | 91 | 92 | ### Linux ### 93 | *~ 94 | 95 | # KDE directory preferences 96 | .directory 97 | 98 | # Linux trash folder which might appear on any partition or disk 99 | .Trash-* 100 | -------------------------------------------------------------------------------- /src/components/DatBoolean.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import PropTypes from 'prop-types'; 3 | import isString from 'lodash.isstring'; 4 | import result from 'lodash.result'; 5 | import cx from 'classnames'; 6 | 7 | export default class DatBoolean extends Component { 8 | static propTypes = { 9 | className: PropTypes.string, 10 | style: PropTypes.object, 11 | data: PropTypes.object.isRequired, 12 | path: PropTypes.string, 13 | label: PropTypes.string, 14 | labelWidth: PropTypes.string.isRequired, 15 | _onUpdateValue: PropTypes.func.isRequired 16 | }; 17 | 18 | static defaultProps = { 19 | className: null, 20 | style: null, 21 | path: null, 22 | label: null 23 | }; 24 | 25 | constructor(props) { 26 | super(props); 27 | 28 | this.state = { 29 | value: null 30 | }; 31 | } 32 | 33 | static getDerivedStateFromProps(nextProps, prevState) { 34 | const nextValue = result(nextProps.data, nextProps.path); 35 | 36 | if (prevState.value === nextValue) return null; 37 | 38 | return { 39 | value: nextValue 40 | }; 41 | } 42 | 43 | handleChange = event => { 44 | const value = event.target.checked; 45 | const { _onUpdateValue, path } = this.props; 46 | 47 | _onUpdateValue(path, value); 48 | }; 49 | 50 | render() { 51 | const { path, label, labelWidth, className, style } = this.props; 52 | const labelText = isString(label) ? label : path; 53 | 54 | return ( 55 |
  • 56 | 71 |
  • 72 | ); 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /src/style/_main.scss: -------------------------------------------------------------------------------- 1 | .react-dat-gui { 2 | position: fixed; 3 | right: 16px; 4 | top: 0; 5 | width: 280px; 6 | font-size: 12px; 7 | font-family: 'Lucida Grande', sans-serif; 8 | 9 | box-sizing: border-box; 10 | -webkit-font-smoothing: antialiased; 11 | -moz-osx-font-smoothing: grayscale; 12 | -webkit-tap-highlight-color: transparent; 13 | 14 | *, 15 | *:before, 16 | *:after { 17 | box-sizing: inherit; 18 | } 19 | 20 | .dg { 21 | margin: 0; 22 | padding: 0; 23 | color: #eee; 24 | overflow: hidden; 25 | 26 | ul { 27 | list-style: none; 28 | margin: 0; 29 | padding: 0; 30 | width: 100%; 31 | clear: both; 32 | } 33 | 34 | &.main { 35 | &::-webkit-scrollbar { 36 | width: 5px; 37 | background: $background-color; 38 | } 39 | 40 | &::-webkit-scrollbar-corner { 41 | height: 0; 42 | display: none; 43 | } 44 | 45 | &::-webkit-scrollbar-thumb { 46 | border-radius: 5px; 47 | background: lighten($background-color, 30%); 48 | } 49 | } 50 | } 51 | 52 | .cr { 53 | display: block; 54 | background-color: $background-color; 55 | user-select: none; 56 | 57 | &:not(:last-child) { 58 | border-bottom: 1px solid $border-color; 59 | } 60 | 61 | label { 62 | display: flex; 63 | align-items: center; 64 | justify-content: flex-start; 65 | width: 100%; 66 | padding: 1px 2px 1px 8px; 67 | } 68 | 69 | .label-text { 70 | width: 40%; 71 | min-width: 0; 72 | white-space: nowrap; 73 | overflow: hidden; 74 | text-overflow: ellipsis; 75 | user-select: none; 76 | } 77 | 78 | input[type='text'], 79 | input[type='number'] { 80 | background: $input-color; 81 | border: 3px solid $background-color; 82 | border-radius: 0; 83 | margin: 0; 84 | outline: none; 85 | font-size: inherit; 86 | 87 | &:hover { 88 | background: lighten($input-color, $hover-lighten); 89 | } 90 | 91 | &:focus { 92 | background: lighten($input-color, $active-lighten); 93 | color: #fff; 94 | } 95 | 96 | &::-ms-clear { 97 | display: none; 98 | } 99 | } 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import React, { Component, cloneElement } from 'react'; 2 | import PropTypes from 'prop-types'; 3 | import cloneDeep from 'lodash.clonedeep'; 4 | import cx from 'classnames'; 5 | import isUndefined from 'lodash.isundefined'; 6 | import set from 'lodash.set'; 7 | import './style/dat.scss'; 8 | 9 | export default class DatGui extends Component { 10 | static propTypes = { 11 | data: PropTypes.object.isRequired, 12 | children: PropTypes.node.isRequired, 13 | onUpdate: PropTypes.func.isRequired, 14 | liveUpdate: PropTypes.bool, 15 | labelWidth: PropTypes.string, 16 | className: PropTypes.string, 17 | style: PropTypes.object 18 | }; 19 | 20 | static defaultProps = { 21 | liveUpdate: true, 22 | className: null, 23 | style: null, 24 | labelWidth: '40%' 25 | }; 26 | 27 | handleUpdateValue = (path, value) => { 28 | const { data, onUpdate } = this.props; 29 | const dataUpdated = set(cloneDeep(data), path, value); 30 | 31 | onUpdate(dataUpdated); 32 | }; 33 | 34 | renderChildren() { 35 | const { children, data } = this.props; 36 | 37 | return React.Children.toArray(children).map((child, i) => { 38 | const liveUpdate = isUndefined(child.props.liveUpdate) 39 | ? this.props.liveUpdate 40 | : child.props.liveUpdate; 41 | const labelWidth = isUndefined(child.props.labelWidth) 42 | ? this.props.labelWidth 43 | : child.props.labelWidth; 44 | 45 | return cloneElement(child, { 46 | key: i, 47 | data, 48 | liveUpdate, 49 | labelWidth, 50 | _onUpdateValue: this.handleUpdateValue 51 | }); 52 | }); 53 | } 54 | 55 | render() { 56 | const { style, className } = this.props; 57 | const classNames = cx('react-dat-gui', className); 58 | 59 | return ( 60 |
    61 |
      {this.renderChildren()}
    62 |
    63 | ); 64 | } 65 | } 66 | 67 | export { default as DatString } from './components/DatString'; 68 | export { default as DatNumber } from './components/DatNumber'; 69 | export { default as DatBoolean } from './components/DatBoolean'; 70 | export { default as DatButton } from './components/DatButton'; 71 | export { default as DatFolder } from './components/DatFolder'; 72 | export { default as DatSelect } from './components/DatSelect'; 73 | export { default as DatColor } from './components/DatColor'; 74 | export { default as DatPresets } from './components/DatPresets'; 75 | -------------------------------------------------------------------------------- /src/components/DatSelect.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import PropTypes from 'prop-types'; 3 | import isString from 'lodash.isstring'; 4 | import result from 'lodash.result'; 5 | import cx from 'classnames'; 6 | 7 | export default class DatSelect extends Component { 8 | static propTypes = { 9 | className: PropTypes.string, 10 | style: PropTypes.object, 11 | data: PropTypes.object.isRequired, 12 | path: PropTypes.string, 13 | label: PropTypes.string, 14 | options: PropTypes.array.isRequired, 15 | optionLabels: PropTypes.array, 16 | labelWidth: PropTypes.string.isRequired, 17 | liveUpdate: PropTypes.bool.isRequired, 18 | onUpdate: PropTypes.func, 19 | _onUpdateValue: PropTypes.func.isRequired 20 | }; 21 | 22 | static defaultProps = { 23 | className: null, 24 | style: null, 25 | path: null, 26 | label: null, 27 | optionLabels: null, 28 | onUpdate: () => null 29 | }; 30 | 31 | constructor() { 32 | super(); 33 | this.state = { 34 | value: null, 35 | options: null 36 | }; 37 | } 38 | 39 | static getDerivedStateFromProps(nextProps) { 40 | const nextValue = result(nextProps.data, nextProps.path); 41 | 42 | return { 43 | value: nextValue, 44 | options: nextProps.options 45 | }; 46 | } 47 | 48 | handleChange = event => { 49 | const { value } = event.target; 50 | const { liveUpdate, _onUpdateValue, onUpdate, path } = this.props; 51 | _onUpdateValue(path, value); 52 | if (liveUpdate) onUpdate(value); 53 | }; 54 | 55 | render() { 56 | const { 57 | path, 58 | label, 59 | labelWidth, 60 | optionLabels, 61 | className, 62 | style 63 | } = this.props; 64 | const { value, options } = this.state; 65 | const labelText = isString(label) ? label : path; 66 | 67 | return ( 68 |
  • 69 | 86 |
  • 87 | ); 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /src/components/DatPresets.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import PropTypes from 'prop-types'; 3 | import cloneDeep from 'lodash.clonedeep'; 4 | import isString from 'lodash.isstring'; 5 | import cx from 'classnames'; 6 | 7 | const DEFAULT_PRESET_KEY = 'Default'; 8 | 9 | export default class DatPresets extends Component { 10 | static propTypes = { 11 | className: PropTypes.string, 12 | style: PropTypes.object, 13 | data: PropTypes.object.isRequired, 14 | path: PropTypes.string, 15 | label: PropTypes.string.isRequired, 16 | options: PropTypes.array.isRequired, 17 | labelWidth: PropTypes.string.isRequired, 18 | liveUpdate: PropTypes.bool.isRequired, 19 | onUpdate: PropTypes.func.isRequired 20 | }; 21 | 22 | static defaultProps = { 23 | className: null, 24 | style: null, 25 | path: null 26 | }; 27 | 28 | constructor() { 29 | super(); 30 | this.state = { 31 | defaultPreset: null, 32 | options: null 33 | }; 34 | } 35 | 36 | static getDerivedStateFromProps(nextProps, prevState) { 37 | const nextValue = cloneDeep(nextProps.data); 38 | const defaultPreset = prevState.defaultPreset 39 | ? prevState.defaultPreset 40 | : nextValue; 41 | 42 | return { 43 | defaultPreset, 44 | options: [ 45 | { [DEFAULT_PRESET_KEY]: defaultPreset }, 46 | ...nextProps.options.filter(preset => { 47 | return Object.keys(preset)[0] !== DEFAULT_PRESET_KEY; 48 | }) 49 | ] 50 | }; 51 | } 52 | 53 | handleChange = event => { 54 | const value = JSON.parse(event.target.value); 55 | const { liveUpdate, onUpdate } = this.props; 56 | 57 | if (liveUpdate) onUpdate(value); 58 | }; 59 | 60 | render() { 61 | const { path, label, labelWidth, className, style } = this.props; 62 | const { options } = this.state; 63 | const labelText = isString(label) ? label : path; 64 | 65 | return ( 66 |
  • 67 | 86 |
  • 87 | ); 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /src/style/_color.scss: -------------------------------------------------------------------------------- 1 | .react-dat-gui .cr.color { 2 | border-left: $border-left-size solid $background-color; 3 | 4 | .swatch { 5 | text-align: center; 6 | font-weight: bold; 7 | color: white; 8 | text-shadow: rgba(0, 0, 0, 0.7) 0px 1px 1px; 9 | padding: $input-padding; 10 | border: $input-border; 11 | cursor: pointer; 12 | } 13 | 14 | .popover { 15 | position: absolute; 16 | z-index: 2; 17 | right: 5px; 18 | } 19 | 20 | .cover { 21 | position: fixed; 22 | top: 0px; 23 | right: 0px; 24 | bottom: 0px; 25 | left: 0px; 26 | } 27 | 28 | .picker { 29 | background: #fff; 30 | box-shadow: 0 0 2px rgba(0, 0, 0, 0.3), 0 4px 8px rgba(0, 0, 0, 0.3); 31 | box-sizing: initial; 32 | width: auto; 33 | font-family: Menlo, sans-serif; 34 | margin-top: -3px; 35 | 36 | .body { 37 | padding: 0px; 38 | 39 | .controls { 40 | display: flex; 41 | 42 | .toggles { 43 | flex: 1; 44 | 45 | .hue-wrap { 46 | height: 10px; 47 | position: relative; 48 | } 49 | } 50 | } 51 | } 52 | 53 | .saturation-wrap { 54 | width: 100%; 55 | padding-bottom: 55%; 56 | position: relative; 57 | overflow: hidden; 58 | } 59 | } 60 | 61 | .fields-wrap { 62 | display: flex; 63 | 64 | .fields { 65 | flex: 1; 66 | display: flex; 67 | margin-left: -6px; 68 | 69 | .field { 70 | padding-left: 6px; 71 | width: 100%; 72 | 73 | input { 74 | font-size: 11px; 75 | color: #333; 76 | border-radius: 2px; 77 | border: none; 78 | box-shadow: inset 0 0 0 1px #dadada; 79 | height: 21px; 80 | text-align: center; 81 | 82 | &:focus { 83 | outline: none; 84 | } 85 | } 86 | 87 | label { 88 | text-transform: uppercase; 89 | font-size: 11px; 90 | line-height: 11px; 91 | color: #969696; 92 | text-align: center; 93 | display: block; 94 | margin-top: 12px; 95 | } 96 | } 97 | } 98 | } 99 | 100 | .pointer { 101 | width: 12px; 102 | height: 12px; 103 | border-radius: 6px; 104 | transform: translate(-6px, -1px); 105 | background-color: rgb(248, 248, 248); 106 | box-shadow: 0 1px 4px 0 rgba(0, 0, 0, 0.37); 107 | position: absolute; 108 | z-index: 3; 109 | } 110 | 111 | .pointer-circle { 112 | width: 12px; 113 | height: 12px; 114 | border-radius: 6px; 115 | box-shadow: inset 0 0 0 1px #fff; 116 | transform: translate(-6px, -6px); 117 | } 118 | } 119 | -------------------------------------------------------------------------------- /src/components/DatString.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import PropTypes from 'prop-types'; 3 | import isString from 'lodash.isstring'; 4 | import result from 'lodash.result'; 5 | import cx from 'classnames'; 6 | 7 | export default class DatString extends Component { 8 | static propTypes = { 9 | className: PropTypes.string, 10 | style: PropTypes.object, 11 | data: PropTypes.object.isRequired, 12 | path: PropTypes.string, 13 | label: PropTypes.string, 14 | labelWidth: PropTypes.string.isRequired, 15 | liveUpdate: PropTypes.bool.isRequired, 16 | onUpdate: PropTypes.func, 17 | _onUpdateValue: PropTypes.func.isRequired 18 | }; 19 | 20 | static defaultProps = { 21 | className: null, 22 | style: null, 23 | path: null, 24 | label: null, 25 | onUpdate: () => null 26 | }; 27 | 28 | constructor() { 29 | super(); 30 | this.state = { 31 | value: null 32 | }; 33 | } 34 | 35 | static getDerivedStateFromProps(nextProps, prevState) { 36 | const nextValue = result(nextProps.data, nextProps.path); 37 | 38 | if (prevState.value === nextValue) return null; 39 | 40 | return { 41 | value: nextValue 42 | }; 43 | } 44 | 45 | handleChange = event => { 46 | const { value } = event.target; 47 | const { liveUpdate } = this.props; 48 | 49 | if (liveUpdate) this.update(value); 50 | }; 51 | 52 | handleFocus = () => { 53 | document.addEventListener('keydown', this.handleKeyDown); 54 | }; 55 | 56 | handleBlur = () => { 57 | document.removeEventListener('keydown', this.handleKeyDown); 58 | window.getSelection().removeAllRanges(); 59 | 60 | const { liveUpdate } = this.props; 61 | if (!liveUpdate) this.update(); 62 | }; 63 | 64 | handleKeyDown = event => { 65 | const key = event.keyCode || event.which; 66 | const { liveUpdate } = this.props; 67 | 68 | if (key === 13 && !liveUpdate) this.update(); 69 | }; 70 | 71 | update(value) { 72 | const { _onUpdateValue, onUpdate, path } = this.props; 73 | _onUpdateValue(path, value); 74 | onUpdate(value); 75 | } 76 | 77 | render() { 78 | const { path, label, labelWidth, className, style } = this.props; 79 | const labelText = isString(label) ? label : path; 80 | 81 | return ( 82 |
  • 83 | 96 |
  • 97 | ); 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /index.d.ts: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | 3 | export interface DatGuiProps { 4 | /** 5 | * The data your dat.GUI controller will mutate 6 | */ 7 | data: any; 8 | /** 9 | * The method which will be called whenever an update is handled by the controller 10 | */ 11 | onUpdate: (data: any) => any; 12 | /** 13 | * The dat.GUI components that make up the controller 14 | */ 15 | children: any; 16 | /** 17 | * Determines if live updates should occur, defaults to true 18 | */ 19 | liveUpdate?: boolean; 20 | /** 21 | * The width of the labels in pixels, defaults to 40 22 | */ 23 | labelWidth?: number; 24 | /** 25 | * The class name to set on the DatGui div 26 | */ 27 | className?: string; 28 | /** 29 | * The style object to set on the DatGui div 30 | */ 31 | style?: React.CSSProperties; 32 | } 33 | 34 | /** 35 | * A React reimplementation of Google's dat.GUI controller library. 36 | * 37 | * @see https://github.com/claus/react-dat-gui 38 | */ 39 | export default class DatGui extends React.Component {} 40 | 41 | export class DatUnchangableFieldProps { 42 | label?: string; 43 | } 44 | 45 | export class DatChangableFieldProps extends DatUnchangableFieldProps { 46 | path: string; 47 | } 48 | 49 | export interface DatButtonProps extends DatUnchangableFieldProps { 50 | onClick: (e: React.MouseEvent) => any; 51 | } 52 | 53 | export class DatButton extends React.Component {} 54 | 55 | export interface DatFolderProps extends DatUnchangableFieldProps { 56 | title: string; 57 | closed: boolean; 58 | children: any; 59 | } 60 | 61 | export class DatFolder extends React.Component {} 62 | 63 | export interface DatPresetsProps extends DatUnchangableFieldProps { 64 | onUpdate: (data: any) => any; 65 | options: { 66 | presetName?: string; 67 | data?: any; // Initial data 68 | preset: any; // Your preset 69 | }; 70 | } 71 | 72 | export class DatPresets extends React.Component {} 73 | 74 | export interface DatBooleanProps extends DatChangableFieldProps {} 75 | 76 | export class DatBoolean extends React.Component {} 77 | 78 | export interface DatColorProps extends DatChangableFieldProps { 79 | [reactColorProp: string]: any; 80 | } 81 | 82 | export class DatColor extends React.Component {} 83 | 84 | export interface DatNumberProps extends DatChangableFieldProps { 85 | min: number; 86 | max: number; 87 | step: number; 88 | } 89 | 90 | export class DatNumber extends React.Component {} 91 | 92 | export interface DatSelectProps extends DatChangableFieldProps { 93 | options: any[]; 94 | } 95 | 96 | export class DatSelect extends React.Component {} 97 | 98 | export interface DatStringProps extends DatChangableFieldProps {} 99 | 100 | export class DatString extends React.Component {} 101 | -------------------------------------------------------------------------------- /dist/index.d.ts: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | 3 | export interface DatGuiProps { 4 | /** 5 | * The data your dat.GUI controller will mutate 6 | */ 7 | data: any; 8 | /** 9 | * The method which will be called whenever an update is handled by the controller 10 | */ 11 | onUpdate: (data: any) => any; 12 | /** 13 | * The dat.GUI components that make up the controller 14 | */ 15 | children: any; 16 | /** 17 | * Determines if live updates should occur, defaults to true 18 | */ 19 | liveUpdate?: boolean; 20 | /** 21 | * The width of the labels in pixels, defaults to 40 22 | */ 23 | labelWidth?: number; 24 | /** 25 | * The class name to set on the DatGui div 26 | */ 27 | className?: string; 28 | /** 29 | * The style object to set on the DatGui div 30 | */ 31 | style?: React.CSSProperties; 32 | } 33 | 34 | /** 35 | * A React reimplementation of Google's dat.GUI controller library. 36 | * 37 | * @see https://github.com/claus/react-dat-gui 38 | */ 39 | export default class DatGui extends React.Component {} 40 | 41 | export class DatUnchangableFieldProps { 42 | label?: string; 43 | } 44 | 45 | export class DatChangableFieldProps extends DatUnchangableFieldProps { 46 | path: string; 47 | } 48 | 49 | export interface DatButtonProps extends DatUnchangableFieldProps { 50 | onClick: (e: React.MouseEvent) => any; 51 | } 52 | 53 | export class DatButton extends React.Component {} 54 | 55 | export interface DatFolderProps extends DatUnchangableFieldProps { 56 | title: string; 57 | closed: boolean; 58 | children: any; 59 | } 60 | 61 | export class DatFolder extends React.Component {} 62 | 63 | export interface DatPresetsProps extends DatUnchangableFieldProps { 64 | onUpdate: (data: any) => any; 65 | options: { 66 | presetName?: string; 67 | data?: any; // Initial data 68 | preset: any; // Your preset 69 | }; 70 | } 71 | 72 | export class DatPresets extends React.Component {} 73 | 74 | export interface DatBooleanProps extends DatChangableFieldProps {} 75 | 76 | export class DatBoolean extends React.Component {} 77 | 78 | export interface DatColorProps extends DatChangableFieldProps { 79 | [reactColorProp: string]: any; 80 | } 81 | 82 | export class DatColor extends React.Component {} 83 | 84 | export interface DatNumberProps extends DatChangableFieldProps { 85 | min: number; 86 | max: number; 87 | step: number; 88 | } 89 | 90 | export class DatNumber extends React.Component {} 91 | 92 | export interface DatSelectProps extends DatChangableFieldProps { 93 | options: any[]; 94 | } 95 | 96 | export class DatSelect extends React.Component {} 97 | 98 | export interface DatStringProps extends DatChangableFieldProps {} 99 | 100 | export class DatString extends React.Component {} 101 | -------------------------------------------------------------------------------- /src/components/Slider.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable jsx-a11y/click-events-have-key-events */ 2 | /* eslint-disable jsx-a11y/control-has-associated-label */ 3 | import React, { Component } from 'react'; 4 | import PropTypes from 'prop-types'; 5 | import clamp from 'lodash.clamp'; 6 | import cx from 'classnames'; 7 | import { toNumber } from './utils'; 8 | 9 | export default class Slider extends Component { 10 | static propTypes = { 11 | className: PropTypes.string, 12 | style: PropTypes.object, 13 | value: PropTypes.oneOfType([PropTypes.number, PropTypes.string]), 14 | min: PropTypes.number, 15 | max: PropTypes.number, 16 | width: PropTypes.number, 17 | onUpdate: PropTypes.func.isRequired 18 | }; 19 | 20 | static defaultProps = { 21 | className: null, 22 | style: null, 23 | value: null, 24 | min: null, 25 | max: null, 26 | width: null 27 | }; 28 | 29 | constructor() { 30 | super(); 31 | this.state = { value: null }; 32 | this.sliderRef = React.createRef(); 33 | } 34 | 35 | static getDerivedStateFromProps(nextProps, prevState) { 36 | const nextValue = toNumber(nextProps.value); 37 | 38 | if (prevState.value === nextValue) return null; 39 | 40 | return { 41 | value: nextValue 42 | }; 43 | } 44 | 45 | handleMouseDown = event => { 46 | this.update(event.pageX); 47 | 48 | window.addEventListener('mousemove', this.handleMouseMove); 49 | window.addEventListener('mouseup', this.handleMouseUp); 50 | }; 51 | 52 | handleMouseMove = event => { 53 | this.update(event.pageX); 54 | 55 | event.preventDefault(); 56 | }; 57 | 58 | handleMouseUp = event => { 59 | this.update(event.pageX, false); 60 | 61 | window.removeEventListener('mousemove', this.handleMouseMove); 62 | window.removeEventListener('mouseup', this.handleMouseUp); 63 | }; 64 | 65 | handleClick = event => { 66 | // do not focus input field on slider click 67 | event.preventDefault(); 68 | }; 69 | 70 | update(pageX, isLive = true) { 71 | const { min, max, onUpdate } = this.props; 72 | const rect = this.sliderRef.current.getBoundingClientRect(); 73 | const x = pageX - rect.left; 74 | const w = rect.right - rect.left; 75 | const value = min + clamp(x / w, 0, 1) * (max - min); 76 | 77 | this.setState({ value }, () => { 78 | onUpdate(value, isLive); 79 | }); 80 | } 81 | 82 | render() { 83 | const { min, max, width, className, style } = this.props; 84 | const { value } = this.state; 85 | const widthBackground = clamp(((value - min) * 100) / (max - min), 0, 100); 86 | const sliderStyles = { 87 | width: `${width}%`, 88 | backgroundSize: `${widthBackground}% 100%`, 89 | ...style 90 | }; 91 | 92 | return ( 93 | 105 | ); 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /src/components/DatColor.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import PropTypes from 'prop-types'; 3 | import isString from 'lodash.isstring'; 4 | import result from 'lodash.result'; 5 | import cx from 'classnames'; 6 | import ColorPicker from './Picker'; 7 | 8 | export default class DatColor extends Component { 9 | static propTypes = { 10 | className: PropTypes.string, 11 | style: PropTypes.object, 12 | data: PropTypes.object.isRequired, 13 | path: PropTypes.string, 14 | label: PropTypes.string, 15 | labelWidth: PropTypes.string.isRequired, 16 | _onUpdateValue: PropTypes.func.isRequired 17 | }; 18 | 19 | static defaultProps = { 20 | className: null, 21 | style: null, 22 | path: null, 23 | label: null 24 | }; 25 | 26 | constructor() { 27 | super(); 28 | 29 | this.state = { 30 | value: null, 31 | displayColorPicker: false 32 | }; 33 | } 34 | 35 | static getDerivedStateFromProps(nextProps, prevState) { 36 | const nextValue = result(nextProps.data, nextProps.path); 37 | 38 | return { 39 | ...prevState, 40 | value: nextValue 41 | }; 42 | } 43 | 44 | handleClickColorPicker = () => 45 | this.setState(prevState => ({ 46 | ...prevState, 47 | displayColorPicker: !prevState.displayColorPicker 48 | })); 49 | 50 | handleCloseColorPicker = () => 51 | this.setState({ 52 | displayColorPicker: false 53 | }); 54 | 55 | handleChangeColor = color => { 56 | const value = isString(color) ? color : color.hex; 57 | const { _onUpdateValue, path } = this.props; 58 | 59 | _onUpdateValue(path, value); 60 | }; 61 | 62 | renderPicker() { 63 | const { value, displayColorPicker } = this.state; 64 | 65 | return !displayColorPicker ? null : ( 66 |
    67 | {/* eslint-disable-next-line jsx-a11y/control-has-associated-label */} 68 |
    75 | 76 |
    77 | ); 78 | } 79 | 80 | render() { 81 | const { path, label, labelWidth, className, style } = this.props; 82 | const { value } = this.state; 83 | const labelText = isString(label) ? label : path; 84 | 85 | return ( 86 |
  • 90 | 112 |
  • 113 | ); 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | When contributing to this repository, please first discuss the change you wish to make via creating an issue before making a change. 4 | 5 | Please note we have a code of conduct, please follow it in all your interactions with the project. 6 | 7 | ## Pull Request Process 8 | 9 | 1. This repository follows the [`git-flow`](https://www.atlassian.com/git/tutorials/comparing-workflows/gitflow-workflow) workflow 10 | 2. After you have made your issue, please create a feature branch off `develop` on your fork and name it in a descriptive way for example `feature/describes-my-feature` 11 | 3. After you have done this, please raise a PR to the `develop` branch, this will ensure that CI runs on your branch before it can be merged 12 | 4. After your PR has been merged, the library maintainers will cut a release and your change will be made available in a patch, minor or major release shortly 13 | 14 | ## Code of Conduct 15 | 16 | ### Our Pledge 17 | 18 | In the interest of fostering an open and welcoming environment, we as 19 | contributors and maintainers pledge to making participation in our project and 20 | our community a harassment-free experience for everyone, regardless of age, body 21 | size, disability, ethnicity, gender identity and expression, level of experience, 22 | nationality, personal appearance, race, religion, or sexual identity and 23 | orientation. 24 | 25 | ### Our Standards 26 | 27 | Examples of behavior that contributes to creating a positive environment 28 | include: 29 | 30 | * Using welcoming and inclusive language 31 | * Being respectful of differing viewpoints and experiences 32 | * Gracefully accepting constructive criticism 33 | * Focusing on what is best for the community 34 | * Showing empathy towards other community members 35 | 36 | Examples of unacceptable behavior by participants include: 37 | 38 | * The use of sexualized language or imagery and unwelcome sexual attention or 39 | advances 40 | * Trolling, insulting/derogatory comments, and personal or political attacks 41 | * Public or private harassment 42 | * Publishing others' private information, such as a physical or electronic 43 | address, without explicit permission 44 | * Other conduct which could reasonably be considered inappropriate in a 45 | professional setting 46 | 47 | ### Our Responsibilities 48 | 49 | Project maintainers are responsible for clarifying the standards of acceptable 50 | behavior and are expected to take appropriate and fair corrective action in 51 | response to any instances of unacceptable behavior. 52 | 53 | Project maintainers have the right and responsibility to remove, edit, or 54 | reject comments, commits, code, wiki edits, issues, and other contributions 55 | that are not aligned to this Code of Conduct, or to ban temporarily or 56 | permanently any contributor for other behaviors that they deem inappropriate, 57 | threatening, offensive, or harmful. 58 | 59 | ### Scope 60 | 61 | This Code of Conduct applies both within project spaces and in public spaces 62 | when an individual is representing the project or its community. Examples of 63 | representing a project or community include using an official project e-mail 64 | address, posting via an official social media account, or acting as an appointed 65 | representative at an online or offline event. Representation of a project may be 66 | further defined and clarified by project maintainers. 67 | 68 | ### Attribution 69 | 70 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, 71 | available at [http://contributor-covenant.org/version/1/4][version] 72 | 73 | [homepage]: http://contributor-covenant.org 74 | [version]: http://contributor-covenant.org/version/1/4/ -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-dat-gui", 3 | "version": "4.1.1", 4 | "description": "dat.GUI reimagined for React", 5 | "main": "dist/index.cjs.js", 6 | "exports": "./dist/index.cjs.js", 7 | "module": "dist/index.es.js", 8 | "jsnext:main": "dist/index.es.js", 9 | "style": "dist/index.css", 10 | "types": "dist/index.d.ts", 11 | "author": "Claus Wahlers (https://github.com/claus)", 12 | "contributors": [ 13 | { 14 | "name": "Claus Wahlers", 15 | "email": "claus@codeazur.com.br", 16 | "url": "https://github.com/claus" 17 | }, 18 | { 19 | "name": "Rohan Deshpande", 20 | "email": "rohan@creativelifeform.com", 21 | "url": "https://github.com/rohan-deshpande" 22 | }, 23 | { 24 | "name": "Tim Ellenberger", 25 | "email": "timellenberger@gmail.com", 26 | "url": "https://github.com/tim-soft" 27 | } 28 | ], 29 | "license": "MIT", 30 | "keywords": [ 31 | "react", 32 | "dat.gui" 33 | ], 34 | "repository": { 35 | "type": "git", 36 | "url": "git@github.com:claus/react-dat-gui.git" 37 | }, 38 | "bugs": { 39 | "url": "https://github.com/claus/react-dat-gui/issues" 40 | }, 41 | "homepage": "https://claus.github.io/react-dat-gui/", 42 | "files": [ 43 | "dist" 44 | ], 45 | "scripts": { 46 | "build": "rollup -c", 47 | "dev": "rollup -c -w", 48 | "test": "jest", 49 | "test:watch": "jest --watch", 50 | "lint": "eslint src", 51 | "lint:fix": "eslint src --fix", 52 | "deploy": "cd example && npm run deploy" 53 | }, 54 | "dependencies": { 55 | "classnames": "2.2.6", 56 | "lodash.clamp": "^4.0.3", 57 | "lodash.clonedeep": "^4.5.0", 58 | "lodash.isfinite": "^3.3.2", 59 | "lodash.isstring": "^4.0.1", 60 | "lodash.isundefined": "^3.0.1", 61 | "lodash.result": "^4.5.2", 62 | "lodash.set": "^4.3.2", 63 | "react-color": "^2.19.3", 64 | "sass": "^1.32.8" 65 | }, 66 | "devDependencies": { 67 | "@babel/core": "^7.13.14", 68 | "@babel/helper-plugin-test-runner": "^7.13.10", 69 | "@babel/plugin-proposal-class-properties": "^7.13.0", 70 | "@babel/plugin-proposal-object-rest-spread": "^7.13.8", 71 | "@babel/plugin-transform-runtime": "^7.13.10", 72 | "@babel/preset-env": "^7.13.12", 73 | "@babel/preset-react": "^7.13.13", 74 | "@babel/runtime": "^7.13.10", 75 | "@rollup/plugin-babel": "^5.3.0", 76 | "@rollup/plugin-commonjs": "^18.0.0", 77 | "@rollup/plugin-node-resolve": "^11.2.1", 78 | "@testing-library/jest-dom": "^5.11.10", 79 | "@testing-library/react": "^11.2.5", 80 | "autoprefixer": "^10.2.5", 81 | "babel-eslint": "10.0.3", 82 | "babel-plugin-transform-react-remove-prop-types": "^0.4.24", 83 | "babel-polyfill": "^6.26.0", 84 | "cssnano": "^4.1.10", 85 | "eslint": "^7.23.0", 86 | "eslint-config-airbnb": "^18.2.1", 87 | "eslint-config-prettier": "^8.1.0", 88 | "eslint-plugin-import": "^2.22.1", 89 | "eslint-plugin-jsx-a11y": "^6.4.1", 90 | "eslint-plugin-prettier": "^3.3.1", 91 | "eslint-plugin-react": "^7.23.1", 92 | "eslint-plugin-react-hooks": "^4.2.0", 93 | "identity-obj-proxy": "^3.0.0", 94 | "jest": "^26.6.3", 95 | "postcss": "^8.2.8", 96 | "prettier": "^2.2.1", 97 | "prop-types": "^15.7.2", 98 | "react": "^17.0.0", 99 | "react-dom": "^17.0.0", 100 | "rollup": "^2.44.0", 101 | "rollup-plugin-copy": "^3.4.0", 102 | "rollup-plugin-filesize": "^9.1.1", 103 | "rollup-plugin-postcss": "^4.0.0", 104 | "rollup-plugin-scss": "^2.6.1", 105 | "stylelint": "^13.12.0", 106 | "stylelint-config-recommended": "^4.0.0" 107 | }, 108 | "peerDependencies": { 109 | "prop-types": "^15.7.2", 110 | "react": ">=16.0.0", 111 | "react-dom": ">=16.0.0" 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /example/components/ReactDatGui.js: -------------------------------------------------------------------------------- 1 | import DatGui, { 2 | DatBoolean, 3 | DatButton, 4 | DatColor, 5 | DatFolder, 6 | DatNumber, 7 | DatPresets, 8 | DatSelect, 9 | DatString 10 | } from 'react-dat-gui'; 11 | import React, { Component } from 'react'; 12 | 13 | import Stats from './Stats'; 14 | 15 | /** 16 | * Demonstrates presets that extend the default preset (initial state) 17 | * as well as presets which extend the current state 18 | */ 19 | class DatGUI extends Component { 20 | constructor() { 21 | super(); 22 | 23 | const initialState = { 24 | string: 'Hello World', 25 | minMaxNumber: 66, 26 | number: 80, 27 | boolean: true, 28 | select: 'one', 29 | color: '#2FA1D6', 30 | random: 0, 31 | nested: { 32 | string: 'Nested Hello World' 33 | } 34 | }; 35 | 36 | this.state = { 37 | data: initialState, 38 | defaultData: initialState 39 | }; 40 | } 41 | 42 | // Update random number for current state 43 | handleButtonClick = () => 44 | this.setState(prevState => ({ 45 | data: { ...prevState.data, random: Math.random() } 46 | })); 47 | 48 | // Update current state with changes from controls 49 | handleUpdate = newData => 50 | this.setState(prevState => ({ 51 | data: { ...prevState.data, ...newData } 52 | })); 53 | 54 | render() { 55 | const { data, defaultData } = this.state; 56 | const presets = [ 57 | // Preset A doesn't extend any other presets 58 | { 59 | A: { 60 | string: 'Preset A', 61 | minMaxNumber: 33, 62 | number: 40, 63 | boolean: false, 64 | select: 'one', 65 | color: '#e61d5f', 66 | random: Math.random(), 67 | nested: { 68 | string: 'Nested Preset A' 69 | } 70 | } 71 | }, 72 | { 73 | B: { 74 | string: 'Preset B', 75 | minMaxNumber: 12, 76 | number: 68, 77 | boolean: true, 78 | select: 'three', 79 | color: '#2FD654', 80 | random: Math.random(), 81 | nested: { 82 | string: 'Nested Preset B' 83 | } 84 | } 85 | }, 86 | // Preset C extends the default preset 87 | { 'C (extends Default)': { ...defaultData, string: 'Preset C' } }, 88 | // Preset D extends the current state 89 | { 'D (extends current state)': { ...data, string: 'Preset D' } } 90 | ]; 91 | 92 | return ( 93 |
    94 | 95 | 96 | 101 | 102 | 109 | 110 | 111 | 112 | 117 | 118 | 119 | 120 | 127 | 128 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 |
    144 | ); 145 | } 146 | } 147 | 148 | export default DatGUI; 149 | -------------------------------------------------------------------------------- /src/components/DatNumber.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-param-reassign */ 2 | import React, { Component } from 'react'; 3 | import PropTypes from 'prop-types'; 4 | import isFinite from 'lodash.isfinite'; 5 | import isString from 'lodash.isstring'; 6 | import result from 'lodash.result'; 7 | import cx from 'classnames'; 8 | import Slider from './Slider'; 9 | import { isInteger, toNumber } from './utils'; 10 | 11 | const applyConstraints = ({ value, min, max, step }) => { 12 | const [hasMin, hasMax, hasStep] = [ 13 | isFinite(min), 14 | isFinite(max), 15 | isFinite(step) 16 | ]; 17 | const decimalPlaces = 18 | hasStep && !isInteger(step) ? step.toString().split('.')[1].length : 0; 19 | let [isMin, isMax] = [false, false]; 20 | 21 | value = toNumber(value); 22 | 23 | if (hasMin && value <= min) { 24 | value = min; 25 | isMin = true; 26 | } 27 | 28 | if (hasMax && value >= max) { 29 | value = max; 30 | isMax = true; 31 | } 32 | 33 | if (!isMin && !isMax) { 34 | if (hasStep && step !== 0) { 35 | value = Math.round(value / step) * step; 36 | } 37 | } 38 | 39 | return value.toFixed(decimalPlaces); 40 | }; 41 | 42 | export default class DatNumber extends Component { 43 | static propTypes = { 44 | className: PropTypes.string, 45 | style: PropTypes.object, 46 | min: PropTypes.number, 47 | max: PropTypes.number, 48 | step: PropTypes.number, 49 | data: PropTypes.object.isRequired, 50 | path: PropTypes.string, 51 | label: PropTypes.string, 52 | labelWidth: PropTypes.string.isRequired, 53 | _onUpdateValue: PropTypes.func.isRequired, 54 | disableSlider: PropTypes.bool 55 | }; 56 | 57 | static defaultProps = { 58 | className: null, 59 | style: null, 60 | min: null, 61 | max: null, 62 | step: null, 63 | path: null, 64 | label: null, 65 | disableSlider: null 66 | }; 67 | 68 | constructor() { 69 | super(); 70 | this.state = { value: null }; 71 | } 72 | 73 | static getDerivedStateFromProps(nextProps) { 74 | const { min, max, step } = nextProps; 75 | const nextValue = applyConstraints({ 76 | value: result(nextProps.data, nextProps.path), 77 | min, 78 | max, 79 | step 80 | }); 81 | 82 | return { 83 | value: nextValue 84 | }; 85 | } 86 | 87 | handleChange = event => { 88 | const { value } = event.target; 89 | this.update(value); 90 | }; 91 | 92 | handleSliderUpdate = value => { 93 | const { min, max, step } = this.props; 94 | 95 | this.update(applyConstraints({ value, min, max, step })); 96 | }; 97 | 98 | update = value => { 99 | const { _onUpdateValue, path } = this.props; 100 | 101 | _onUpdateValue(path, toNumber(value)); 102 | }; 103 | 104 | renderSlider(width) { 105 | const { min, max } = this.props; 106 | const { value } = this.state; 107 | 108 | return ( 109 | 116 | ); 117 | } 118 | 119 | render() { 120 | const { 121 | min, 122 | max, 123 | path, 124 | label, 125 | labelWidth, 126 | step, 127 | disableSlider, 128 | className, 129 | style 130 | } = this.props; 131 | const labelText = isString(label) ? label : path; 132 | const hasSlider = isFinite(min) && isFinite(max); 133 | const controlsWidth = 100; 134 | const inputWidth = 135 | hasSlider && disableSlider !== true 136 | ? Math.round(controlsWidth / 3) 137 | : controlsWidth; 138 | const sliderWidth = controlsWidth - inputWidth; 139 | 140 | return ( 141 |
  • 142 | 164 |
  • 165 | ); 166 | } 167 | } 168 | -------------------------------------------------------------------------------- /dist/index.css: -------------------------------------------------------------------------------- 1 | .react-dat-gui{position:fixed;right:16px;top:0;width:280px;font-size:12px;font-family:Lucida Grande,sans-serif;box-sizing:border-box;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;-webkit-tap-highlight-color:transparent}.react-dat-gui *,.react-dat-gui :after,.react-dat-gui :before{box-sizing:inherit}.react-dat-gui .dg{margin:0;padding:0;color:#eee;overflow:hidden}.react-dat-gui .dg ul{list-style:none;margin:0;padding:0;width:100%;clear:both}.react-dat-gui .dg.main::-webkit-scrollbar{width:5px;background:#1a1a1a}.react-dat-gui .dg.main::-webkit-scrollbar-corner{height:0;display:none}.react-dat-gui .dg.main::-webkit-scrollbar-thumb{border-radius:5px;background:#676767}.react-dat-gui .cr{display:block;background-color:#1a1a1a;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.react-dat-gui .cr:not(:last-child){border-bottom:1px solid #272727}.react-dat-gui .cr label{display:flex;align-items:center;justify-content:flex-start;width:100%;padding:1px 2px 1px 8px}.react-dat-gui .cr .label-text{width:40%;min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.react-dat-gui .cr input[type=number],.react-dat-gui .cr input[type=text]{background:#303030;border:3px solid #1a1a1a;border-radius:0;margin:0;outline:none;font-size:inherit}.react-dat-gui .cr input[type=number]:hover,.react-dat-gui .cr input[type=text]:hover{background:#3c3c3c}.react-dat-gui .cr input[type=number]:focus,.react-dat-gui .cr input[type=text]:focus{background:#494949;color:#fff}.react-dat-gui .cr input[type=number]::-ms-clear,.react-dat-gui .cr input[type=text]::-ms-clear{display:none}.react-dat-gui .cr.boolean{position:relative;border-left:5px solid #806787}.react-dat-gui .cr.boolean label{cursor:pointer}.react-dat-gui .cr.boolean .label-text{display:block;padding:5px 0}.react-dat-gui .cr.boolean .checkbox-container{width:100%}.react-dat-gui .cr.boolean input[type=checkbox]{margin:0;vertical-align:middle}.react-dat-gui .cr.button{border-left:5px solid #e61d5f}.react-dat-gui .cr.button:hover{background:#111}.react-dat-gui .cr.button .label-text{display:block;width:100%;padding:6px 2px 6px 8px;cursor:pointer}.react-dat-gui li.folder{display:block;padding:0}.react-dat-gui li.folder .title{font-weight:700;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;display:block;cursor:pointer;padding:5px 5px 5px 16px;background:#000 url(data:image/gif;base64,R0lGODlhBQAFAJEAAP////Pz8////////yH5BAEAAAIALAAAAAAFAAUAAAIIlI+hKgFxoCgAOw==) 6px 48% no-repeat}.react-dat-gui li.folder ul{margin-left:4px;width:calc(100% - 4px)}.react-dat-gui li.folder.closed .title{background:#000 url(data:image/gif;base64,R0lGODlhBQAFAJEAAP////Pz8////////yH5BAEAAAIALAAAAAAFAAUAAAIIlGIWqMCbWAEAOw==) 6px 48% no-repeat}.react-dat-gui li.folder.closed ul{display:none}.react-dat-gui .cr.number{border-left:5px solid #2fa1d6}.react-dat-gui .cr.number input[type=number],.react-dat-gui .cr.number input[type=text]{color:#2fa1d6;height:25px}.react-dat-gui .cr.number .slider{display:block;position:relative;border:3px solid #1a1a1a;border-right-width:1px;background-color:#303030;background-image:linear-gradient(90deg,#2fa1d6,#2fa1d6);background-size:0 100%;background-repeat:no-repeat;cursor:ew-resize;height:25px}.react-dat-gui .cr.string{border-left:5px solid #1ed36f}.react-dat-gui .cr.string input[type=text]{color:#1ed36f;padding:2px 5px;width:100%}.react-dat-gui .cr.select{border-left:5px solid #f4d450}.react-dat-gui .cr.select label{padding:6px 2px 6px 8px}.react-dat-gui .cr.color{border-left:5px solid #1a1a1a}.react-dat-gui .cr.color .swatch{text-align:center;font-weight:700;color:#fff;text-shadow:rgba(0,0,0,.7) 0 1px 1px;padding:2px 5px;border:3px solid #1a1a1a;cursor:pointer}.react-dat-gui .cr.color .popover{position:absolute;z-index:2;right:5px}.react-dat-gui .cr.color .cover{position:fixed;top:0;right:0;bottom:0;left:0}.react-dat-gui .cr.color .picker{background:#fff;box-shadow:0 0 2px rgba(0,0,0,.3),0 4px 8px rgba(0,0,0,.3);box-sizing:initial;width:auto;font-family:Menlo,sans-serif;margin-top:-3px}.react-dat-gui .cr.color .picker .body{padding:0}.react-dat-gui .cr.color .picker .body .controls{display:flex}.react-dat-gui .cr.color .picker .body .controls .toggles{flex:1}.react-dat-gui .cr.color .picker .body .controls .toggles .hue-wrap{height:10px;position:relative}.react-dat-gui .cr.color .picker .saturation-wrap{width:100%;padding-bottom:55%;position:relative;overflow:hidden}.react-dat-gui .cr.color .fields-wrap{display:flex}.react-dat-gui .cr.color .fields-wrap .fields{flex:1;display:flex;margin-left:-6px}.react-dat-gui .cr.color .fields-wrap .fields .field{padding-left:6px;width:100%}.react-dat-gui .cr.color .fields-wrap .fields .field input{font-size:11px;color:#333;border-radius:2px;border:none;box-shadow:inset 0 0 0 1px #dadada;height:21px;text-align:center}.react-dat-gui .cr.color .fields-wrap .fields .field input:focus{outline:none}.react-dat-gui .cr.color .fields-wrap .fields .field label{text-transform:uppercase;font-size:11px;line-height:11px;color:#969696;text-align:center;display:block;margin-top:12px}.react-dat-gui .cr.color .pointer{width:12px;height:12px;border-radius:6px;transform:translate(-6px,-1px);background-color:#f8f8f8;box-shadow:0 1px 4px 0 rgba(0,0,0,.37);position:absolute;z-index:3}.react-dat-gui .cr.color .pointer-circle{width:12px;height:12px;border-radius:6px;box-shadow:inset 0 0 0 1px #fff;transform:translate(-6px,-6px)}.react-dat-gui .cr.presets{border-left:5px solid #dad5cb}.react-dat-gui .cr.presets label{padding:6px 2px 6px 8px}.react-dat-gui .cr.presets label select{width:100%} -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | ## (2020-03-15) `v4.0.1` 4 | 5 | Thanks to [@anselanza](https://github.com/anselanza) for their work to getting typescript types into the `dist` folder 🎉 ! 6 | 7 | ### Resolves 8 | 9 | * [#47](https://github.com/claus/react-dat-gui/issues/47) 10 | 11 | ## (2019-09-01) `v4.0.0` 12 | 13 | Special thanks to [@tim-soft](https://github.com/tim-soft) for this awesome [PR](https://github.com/claus/react-dat-gui/pull/33)! 14 | 15 | ### Added 16 | 17 | - Testing framework via `jest` and `testing-library/react` 18 | - CI integration with Travis 19 | 20 | ### Changed 21 | 22 | - Switched deprecated `componentWillReceiveProps` to `getDerivedStateFromProps` 23 | - All linting packages updated 24 | - Example now uses `nextjs` and links to root modules for better dev experience 25 | - Bundling now done with `rollup` 26 | 27 | ### Fixed 28 | 29 | - Default preset is stored separately so that it can be reapplied after changing to other presets 30 | - All built-in react-dat-gui components now accept className and style props 31 | - All built-in react-dat-gui components can now have a labelWidth prop which can override the container prop and in any valid CSS units 32 | - Automatically include styles, no longer require importing external stylesheet 33 | - Add linting and precommit scripts that run prettier, eslint and stylelint over the codebase 34 | 35 | ## (2019-04-02) `v3.0.0` 36 | 37 | ### Changed 38 | 39 | - Move `react`, `react-dom` and `prop-types` to peer deps [@tim-soft](https://github.com/tim-soft) 40 | 41 | ## (2019-03-01) `v2.2.0` 42 | 43 | ### Fixed 44 | 45 | - Coding example in README [@avin](https://github.com/avin) 46 | - `DatFolder` now passes props to children correctly once again [@rdrgn](https://github.com/rdrgn) 47 | 48 | ## (2019-01-02) `v2.0.1` 49 | 50 | ### Added 51 | 52 | - `TypeScript` definitions 53 | - Better support for floats 54 | 55 | ## (2019-01-02) `v2.0.0` 56 | 57 | ### Added 58 | 59 | - `DatFolder` now accepts a `closed` boolean prop to determine if the folder should be closed or open by default 60 | 61 | ### Changed 62 | 63 | - React v16.0.0 is now required as a peer dependency 64 | - README updated with more docs, included a note about the React v16 peer dependency 65 | 66 | ## (2017-12-09) `v1.0.3` 67 | 68 | ### Added 69 | 70 | - Section on React version to README 71 | - Point regarding animations for `DatFolder` to Roadmap 72 | - License section to README 73 | 74 | ## (2017-10-09) `v1.0.2` 75 | 76 | ### Changed 77 | 78 | - Minor code formatting updates 79 | - Installation guidelines 80 | 81 | ## (2017-10-09) `v1.0.1` 82 | 83 | ### Changed 84 | 85 | - ES7 property initializers are now used to set initial state in all components rather than `componentWillMount` 86 | 87 | ## (2017-10-09) `v1.0.0` 88 | 89 | ### Added 90 | 91 | - A lot of documentation to the README 92 | - Deploy script to `./example` app which deploys to github pages 93 | 94 | ### Changed 95 | 96 | - Changed default export from `Dat` to `DatGui` 97 | 98 | ## (2017-10-08) `v0.0.21` 99 | 100 | ### Changed 101 | 102 | - Removed custom check box styling from `DatBoolean` component 103 | - Ensured sliders are the same height as number inputs 104 | - Minor style changes for consistency 105 | 106 | ## (2017-10-08) `v0.0.20` 107 | 108 | ### Changed 109 | 110 | - Housekeeping in preparation for `v1.0.0` 111 | 112 | ## (2017-10-06) `v0.0.19` 113 | 114 | ### Added 115 | 116 | - `DatPresets` component - this allows you to set presets for your DatGUI component and switch between them easily 117 | 118 | ### Changed 119 | 120 | - Removed final reference to `reactcss`, this can be completely removed from dependencies now 121 | - Removed unnecessary arrow functions in some `setState` callbacks 122 | - Fixed bug where `DatNumber` input updates weren't updating sliders 123 | 124 | ## (2017-10-05) `v0.0.18` 125 | 126 | ### Added 127 | 128 | - `DatColor` component - this allows color pickers, powered by `react-color` to be rendered for mutating colors 129 | - Added `example:promote` script for pushing development code up from `example/src/dev` into `src` 130 | 131 | ### Changed 132 | 133 | - Example updated with `DatColor` included 134 | 135 | ## (2017-10-04) `v0.0.17` 136 | 137 | ### Added 138 | 139 | - `DatSelect` component 140 | 141 | ### Changed 142 | 143 | - Example updated with `DatSelect` included 144 | 145 | ## (2017-10-03) `v0.0.16` 146 | 147 | ### Added 148 | 149 | - Support for nested folders via `DatFolder` 150 | 151 | ### Changed 152 | 153 | - Example `App.js` has been updated to include a nested folder example 154 | 155 | ## (2017-10-02) `v0.0.15` 156 | 157 | ### Changed 158 | 159 | - SCSS is now broken up into partials which align with the various components 160 | 161 | ### Added 162 | 163 | - Added `DatFolder` component 164 | - Added this to the example 165 | 166 | ## (2017-10-02) `v0.0.14` 167 | 168 | ### Changed 169 | 170 | - Updated component files to use `.js` file extension rather than `.jsx` 171 | - Removed `examples` directory and created single `example` directory which is now powered by `create-react-app` 172 | - Rewrote `webpack.config.js` so that it is compatible with Webpack v2 173 | - Updated a bunch of dependencies in `package.json` 174 | - Separated out `Slider` component from `DatNumber` and also added `utils` file 175 | - Switched all event handlers in components to ES7 syntax 176 | - Some code formatting 177 | - Changed `build` directory to `dist` 178 | 179 | ### Added 180 | 181 | - `example` directory 182 | - `src/components/Slider.js` 183 | - `src/components/utils.js` 184 | - `src/style` directory 185 | - `.editorconfig` file 186 | - `.eslintrc.json` file 187 | - `.babelrc` file 188 | - `scripts` directory 189 | - A number of `npm` scripts to `package.json` 190 | - This change log! 191 | 192 | ### Removed 193 | 194 | - The build no longer creates minified files, can add these back if required but I think it's better for the user to perform this step in their own build pipeline 195 | - ES5 examples, don't think many people are coding with React and ES5 nowadays 196 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # React dat.GUI 2 | 3 | [![npm](https://img.shields.io/npm/v/react-dat-gui?style=flat-square)](https://www.npmjs.com/package/react-dat-gui) 4 | [![Travis (.org)](https://img.shields.io/travis/claus/react-dat-gui?style=flat-square)](https://travis-ci.org/claus/react-dat-gui) 5 | [![npm bundle size](https://img.shields.io/bundlephobia/minzip/react-dat-gui?style=flat-square)](https://bundlephobia.com/result?p=react-dat-gui) 6 | [![GitHub](https://img.shields.io/github/license/claus/react-dat-gui?style=flat-square)](https://github.com/claus/react-dat-gui/blob/master/LICENSE) 7 | 8 | **This project is not maintained. I am not really using it myself and currently have no bandwidth to take care of it. If anyone would like to fork and run with it, i would be more than happy to drop a link here. Also feel free to check out [Leva](https://github.com/pmndrs/leva), which looks like a decent alternative.** 9 | 10 | react-dat-gui is a fully[\*](#whats-missing) featured React port of Google's esteemed [dat.GUI](https://workshop.chromeexperiments.com/examples/gui/#1--Basic-Usage) controller library. It comes packed with all of the core components you will need to cleanly integrate dat.GUIs into your React app. 11 | 12 |

    13 | 14 | 15 | 16 |
    17 | Demo 18 |     19 | Codesandbox 20 |

    21 | 22 | The dat.GUI library is designed for easily updating and interacting with objects in real time. It is used extensively in canvas and WebGL rendering demos/apps for libraries such as [three.js](http://threejs.org) and is also commonly used in browser based editing software. 23 | 24 | ## Contents 25 | 26 | - [Basic Usage](#installation) 27 | - [Docs](#docs) 28 | - [Local Development](#local-development) 29 | - [What's missing](#whats-missing) 30 | - [Roadmap](#roadmap) 31 | 32 | ## Installation 33 | 34 | ``` 35 | npm install react-dat-gui --save 36 | ``` 37 | 38 | ## Basic Usage 39 | 40 | react-dat-gui has a wrapper component `` and several control components that can be used to add functionality to the controller. 41 | 42 | ```jsx 43 | import React from 'react'; 44 | import DatGui, { DatBoolean, DatColor, DatNumber, DatString } from 'react-dat-gui'; 45 | 46 | class App extends React.Component { 47 | state = { 48 | data: { 49 | package: 'react-dat-gui', 50 | power: 9000, 51 | isAwesome: true, 52 | feelsLike: '#2FA1D6', 53 | } 54 | } 55 | 56 | // Update current state with changes from controls 57 | handleUpdate = newData => 58 | this.setState(prevState => ({ 59 | data: { ...prevState.data, ...newData } 60 | })); 61 | 62 | render() { 63 | const { data } = this.state; 64 | 65 | return ( 66 | 67 | 68 | 69 | 70 | 71 | 72 | ) 73 | } 74 | ``` 75 | 76 | ## Docs 77 | 78 | ### `` 79 | 80 | This is the main container component for your GUI and is the default export from the package. 81 | 82 | #### required 83 | 84 | | prop | Description | Type | 85 | | -------- | ------------------------------------------------------------------------------- | -------- | 86 | | data | The data your dat.GUI controller will mutate | object | 87 | | onUpdate | The method which will be called whenever an update is handled by the controller | function | 88 | | children | The dat.GUI components that make up the controller | array | 89 | 90 | #### optional 91 | 92 | | prop | Description | Type | Default | 93 | | ---------- | ---------------------------------------------- | ------- | ------- | 94 | | liveUpdate | Determines if live updates should occur | boolean | true | 95 | | labelWidth | The width of the labels in any valid CSS units | string | "40%" | 96 | | className | The class name to set on the `DatGui` div | string | null | 97 | | style | The style object to set on the `DatGui` div | object | null | 98 | 99 | ### Control Components 100 | 101 | `react-dat-gui` comes with eight built-in control components which can be used by rendering them as direct children of ``. 102 | 103 | - [DatBoolean](#datboolean) 104 | - [DatButton](#datbutton) 105 | - [DatColor](#datcolor) 106 | - [DatFolder](#datfolder) 107 | - [DatPresets](#datpresets) 108 | - [DatSelect](#datselect) 109 | - [DatString](#datstring) 110 | 111 | Custom control components can also be used so long as they implement the required props. 112 | 113 | #### Common props 114 | 115 | All child components of `` receive the following props implicitly, these are useful when building custom control components. See the built-in control components in [src/components](src/components) for examples of how to implement your own controls. 116 | 117 | | prop | Description | Type | 118 | | --------------- | ------------------------------------------------------------------------------------------------------------------------------------ | ------- | 119 | | data | The data your dat.GUI controller will mutate, the same object from ` | object | 120 | | labelWidth | The width of the control name label | string | 121 | | liveUpdate | Determines if live updates should occur | boolean | 122 | | \_onUpdateValue | A callback function for `, call this method to update dat.Gui state from your control. | function | 123 | 124 | Below are docs for the required and optional props you can pass to each built-in control component. 125 | 126 | ##### required 127 | 128 | - `path: string` - the path to the value within the `data` object which the component will control, eg., considering your object was `{ foo: 'bar' }`: `` or `{ foo: { bar: 'string' } }`: `` for nested values. 129 | - Note, this prop is not required for the following components 130 | - `DatButton` 131 | - `DatFolder` 132 | - `DatPresets` 133 | 134 | ##### optional 135 | 136 | - `className: string` - A CSS class name 137 | - `style: object` - A style object for inline styles 138 | - `label: string` - The label for the controller eg., `` 139 | - `labelWidth: string` - The width of the labels in any valid CSS units, overrides `` 140 | 141 | #### `DatBoolean` 142 | 143 | Used for controlling boolean values. Renders a checkbox input element. 144 | 145 | #### `DatButton` 146 | 147 | Can be used for performing any kind of function. Simply pass an `onClick` prop to the component and it will fire whenever the rendered element is clicked. 148 | 149 | ##### props 150 | 151 | ###### required 152 | 153 | - `onClick :func` - the function to perform with the rendered element is clicked 154 | 155 | #### `DatColor` 156 | 157 | Uses [`react-color`](https://github.com/casesandberg/react-color/) to render a color picker component that will control color values. 158 | 159 | #### `DatFolder` 160 | 161 | Component which wraps other components to render them within an expandable/collapsable nested folder. 162 | 163 | ##### props 164 | 165 | ###### required 166 | 167 | - `title: string` - The folder title eg., `` 168 | - `children: array` - The child components to render 169 | 170 | ###### optional 171 | 172 | - `closed: boolean` - Whether the initial state of the folder is closed, defaults to `true` 173 | 174 | #### `DatNumber` 175 | 176 | A number component for updating numeric values. Will render a slider if `min`, `max` and `step` props are supplied. 177 | 178 | ##### props 179 | 180 | ###### optional 181 | 182 | - `min: number` - The minimum range for the number 183 | - `max: number` - The maximum range for the number 184 | - `step: number` - The amount the number should increment each tick 185 | 186 | If your `step` prop is a float, `DatNumber` will ensure that your number field steps to the correct number of decimal places to align with the step that you've set. 187 | 188 | #### `DatPresets` 189 | 190 | Presets for the object which your `DatGui` is controlling can be supplied to this component as items in its `options` prop. A select field will be rendered which will allow you to easily switch between the presets. 191 | 192 | Each item in this array will need to be in the format `{ 'presetName': ...data, ...preset }` where `...data` is your initial data and `...preset` is your preset. 193 | 194 | ##### props 195 | 196 | ###### required 197 | 198 | - `options: array` - An array of objects, each in the format `{ 'presetName': ...data, ...preset }` 199 | 200 | #### `DatSelect` 201 | 202 | A select component for updating a value with one of the options supplied via the `options` prop. The initial selected value will be taken from the mapped `path` prop. 203 | 204 | ##### props 205 | 206 | ###### required 207 | 208 | - `options: array` - A simple array of options to select from eg., `` 209 | 210 | #### `DatString` 211 | 212 | A simple text input component that can be used to mutate strings. 213 | 214 | ## Local Development 215 | 216 | Clone the repo 217 | 218 | ```bash 219 | git clone https://github.com/claus/react-dat-gui.git react-dat-gui 220 | cd react-dat-gui 221 | ``` 222 | 223 | In order to see your changes to `react-dat-gui` the best way is to develop on the package and the example simultaneously. To do this, follow these steps. 224 | 225 | ### 1. Setup symlinks and install dependencies 226 | 227 | ```bash 228 | npm install 229 | cd example 230 | npm install 231 | ``` 232 | 233 | ### 2. Run the library in development mode 234 | 235 | ```bash 236 | cd .. 237 | npm run dev 238 | ``` 239 | 240 | ### 3. Run the example app in development mode (in second terminal window) 241 | 242 | ```bash 243 | cd example 244 | npm run dev 245 | ``` 246 | 247 | After the example has compiled, it should be available for viewing at [http://localhost:3000](http://localhost:3000). Changes to the library code should now hot reload in the example app 248 | 249 | ## Scripts 250 | 251 | | Script | Description | 252 | | ------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------- | 253 | | `build` | Builds the library for production into `/dist` | 254 | | `start` | Starts the library in development mode with hot module reloading | 255 | | `test` | Runs unit testing suite powered by [Jest](https://github.com/facebook/jest) and [testing-library](https://github.com/testing-library/react-testing-library) | 256 | | `lint` | Runs linting over entire codebase with `prettier`, `eslint` and `stylelint` | 257 | | `lint-js` | Lints only javascript files | 258 | | `lint-styles` | Lints only stylesheet files | 259 | | `fix` | Runs linting over entire codebase with `prettier`, `eslint` and `stylelint` and applies any available automatic fixes | 260 | | `fix-js` | Lints only javascript files and applies any available automatic fixes | 261 | | `fix-styles` | Lints only stylesheet files and applies any available automatic fixes | 262 | | `deploy` | Compiles and deploys a static build of `/example` next.js app to gh-pages | 263 | 264 | ## What's missing 265 | 266 | There are still a few features from the original implementation missing from this package. These are mainly related to saving and loading data as well as local storage. Animations for folder expanding/collapsing is also not currently implemented, but shouldn't be too hard to do. 267 | 268 | For the first, I think the fact that this is now an NPM module sort of goes against it handling this sort of stuff. Google's original concept was basically a plug and play controller that could do everything if you just slam it into the browser and pass it an object. However, in module form, it's expected that you'll most likely be integrating this with an existing application. In that case, you'll probably have pretty specific needs around how you would like to save/load data into your GUI and so it's been left out for now. 269 | 270 | Local storage however is in the roadmap and will probably be done very soon. 271 | 272 | ## Roadmap 273 | 274 | - Loading and storing both default and preset data via `localStorage` 275 | - Animations for `DatFolder` expanding/collapsing 276 | - Time travel with undo/redo buttons 277 | - ~~Better support for floating point `DatNumber`s (rounding etc.)~~ ✅ 278 | 279 | ## License 280 | 281 | [MIT](https://opensource.org/licenses/MIT) 282 | -------------------------------------------------------------------------------- /dist/index.es.js: -------------------------------------------------------------------------------- 1 | import _classCallCheck from '@babel/runtime/helpers/classCallCheck'; 2 | import _createClass from '@babel/runtime/helpers/createClass'; 3 | import _assertThisInitialized from '@babel/runtime/helpers/assertThisInitialized'; 4 | import _inherits from '@babel/runtime/helpers/inherits'; 5 | import _possibleConstructorReturn from '@babel/runtime/helpers/possibleConstructorReturn'; 6 | import _getPrototypeOf from '@babel/runtime/helpers/getPrototypeOf'; 7 | import _defineProperty from '@babel/runtime/helpers/defineProperty'; 8 | import React, { Component, cloneElement } from 'react'; 9 | import cloneDeep from 'lodash.clonedeep'; 10 | import cx from 'classnames'; 11 | import isUndefined from 'lodash.isundefined'; 12 | import set from 'lodash.set'; 13 | import isString from 'lodash.isstring'; 14 | import result from 'lodash.result'; 15 | import isFinite$1 from 'lodash.isfinite'; 16 | import clamp from 'lodash.clamp'; 17 | import _objectWithoutProperties from '@babel/runtime/helpers/objectWithoutProperties'; 18 | import { EditableInput, ColorWrap, Saturation, Hue } from 'react-color/lib/components/common'; 19 | import color from 'react-color/lib/helpers/color'; 20 | import _toConsumableArray from '@babel/runtime/helpers/toConsumableArray'; 21 | 22 | function _createSuper$9(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct$9(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; } 23 | 24 | function _isNativeReflectConstruct$9() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } } 25 | 26 | var DatString = /*#__PURE__*/function (_Component) { 27 | _inherits(DatString, _Component); 28 | 29 | var _super = _createSuper$9(DatString); 30 | 31 | function DatString() { 32 | var _this; 33 | 34 | _classCallCheck(this, DatString); 35 | 36 | _this = _super.call(this); 37 | 38 | _defineProperty(_assertThisInitialized(_this), "handleChange", function (event) { 39 | var value = event.target.value; 40 | var liveUpdate = _this.props.liveUpdate; 41 | if (liveUpdate) _this.update(value); 42 | }); 43 | 44 | _defineProperty(_assertThisInitialized(_this), "handleFocus", function () { 45 | document.addEventListener('keydown', _this.handleKeyDown); 46 | }); 47 | 48 | _defineProperty(_assertThisInitialized(_this), "handleBlur", function () { 49 | document.removeEventListener('keydown', _this.handleKeyDown); 50 | window.getSelection().removeAllRanges(); 51 | var liveUpdate = _this.props.liveUpdate; 52 | if (!liveUpdate) _this.update(); 53 | }); 54 | 55 | _defineProperty(_assertThisInitialized(_this), "handleKeyDown", function (event) { 56 | var key = event.keyCode || event.which; 57 | var liveUpdate = _this.props.liveUpdate; 58 | if (key === 13 && !liveUpdate) _this.update(); 59 | }); 60 | 61 | _this.state = { 62 | value: null 63 | }; 64 | return _this; 65 | } 66 | 67 | _createClass(DatString, [{ 68 | key: "update", 69 | value: function update(value) { 70 | var _this$props = this.props, 71 | _onUpdateValue = _this$props._onUpdateValue, 72 | onUpdate = _this$props.onUpdate, 73 | path = _this$props.path; 74 | 75 | _onUpdateValue(path, value); 76 | 77 | onUpdate(value); 78 | } 79 | }, { 80 | key: "render", 81 | value: function render() { 82 | var _this$props2 = this.props, 83 | path = _this$props2.path, 84 | label = _this$props2.label, 85 | labelWidth = _this$props2.labelWidth, 86 | className = _this$props2.className, 87 | style = _this$props2.style; 88 | var labelText = isString(label) ? label : path; 89 | return /*#__PURE__*/React.createElement("li", { 90 | className: cx('cr', 'string', className), 91 | style: style 92 | }, /*#__PURE__*/React.createElement("label", null, /*#__PURE__*/React.createElement("span", { 93 | className: "label-text", 94 | style: { 95 | width: labelWidth 96 | } 97 | }, labelText), /*#__PURE__*/React.createElement("input", { 98 | style: { 99 | width: "calc(100% - ".concat(labelWidth, ")") 100 | }, 101 | type: "text", 102 | value: this.state.value, 103 | onChange: this.handleChange, 104 | onFocus: this.handleFocus, 105 | onBlur: this.handleBlur 106 | }))); 107 | } 108 | }], [{ 109 | key: "getDerivedStateFromProps", 110 | value: function getDerivedStateFromProps(nextProps, prevState) { 111 | var nextValue = result(nextProps.data, nextProps.path); 112 | if (prevState.value === nextValue) return null; 113 | return { 114 | value: nextValue 115 | }; 116 | } 117 | }]); 118 | 119 | return DatString; 120 | }(Component); 121 | 122 | _defineProperty(DatString, "defaultProps", { 123 | className: null, 124 | style: null, 125 | path: null, 126 | label: null, 127 | onUpdate: function onUpdate() { 128 | return null; 129 | } 130 | }); 131 | 132 | /* eslint-disable no-restricted-globals */ 133 | function toNumber(value) { 134 | var _float = parseFloat(value); 135 | 136 | return isNaN(_float) ? 0 : _float; 137 | } 138 | /** 139 | * Polyfill for isInteger. 140 | * 141 | * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/isInteger#Polyfill 142 | * @param {number} value 143 | * @return {bool} 144 | */ 145 | 146 | var isInteger = Number.isInteger || // eslint-disable-next-line func-names 147 | function (value) { 148 | return typeof value === 'number' && isFinite(value) && Math.floor(value) === value; 149 | }; 150 | 151 | function ownKeys$2(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; } 152 | 153 | function _objectSpread$2(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys$2(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys$2(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } 154 | 155 | function _createSuper$8(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct$8(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; } 156 | 157 | function _isNativeReflectConstruct$8() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } } 158 | 159 | var Slider = /*#__PURE__*/function (_Component) { 160 | _inherits(Slider, _Component); 161 | 162 | var _super = _createSuper$8(Slider); 163 | 164 | function Slider() { 165 | var _this; 166 | 167 | _classCallCheck(this, Slider); 168 | 169 | _this = _super.call(this); 170 | 171 | _defineProperty(_assertThisInitialized(_this), "handleMouseDown", function (event) { 172 | _this.update(event.pageX); 173 | 174 | window.addEventListener('mousemove', _this.handleMouseMove); 175 | window.addEventListener('mouseup', _this.handleMouseUp); 176 | }); 177 | 178 | _defineProperty(_assertThisInitialized(_this), "handleMouseMove", function (event) { 179 | _this.update(event.pageX); 180 | 181 | event.preventDefault(); 182 | }); 183 | 184 | _defineProperty(_assertThisInitialized(_this), "handleMouseUp", function (event) { 185 | _this.update(event.pageX, false); 186 | 187 | window.removeEventListener('mousemove', _this.handleMouseMove); 188 | window.removeEventListener('mouseup', _this.handleMouseUp); 189 | }); 190 | 191 | _defineProperty(_assertThisInitialized(_this), "handleClick", function (event) { 192 | // do not focus input field on slider click 193 | event.preventDefault(); 194 | }); 195 | 196 | _this.state = { 197 | value: null 198 | }; 199 | _this.sliderRef = /*#__PURE__*/React.createRef(); 200 | return _this; 201 | } 202 | 203 | _createClass(Slider, [{ 204 | key: "update", 205 | value: function update(pageX) { 206 | var isLive = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true; 207 | var _this$props = this.props, 208 | min = _this$props.min, 209 | max = _this$props.max, 210 | onUpdate = _this$props.onUpdate; 211 | var rect = this.sliderRef.current.getBoundingClientRect(); 212 | var x = pageX - rect.left; 213 | var w = rect.right - rect.left; 214 | var value = min + clamp(x / w, 0, 1) * (max - min); 215 | this.setState({ 216 | value: value 217 | }, function () { 218 | onUpdate(value, isLive); 219 | }); 220 | } 221 | }, { 222 | key: "render", 223 | value: function render() { 224 | var _this$props2 = this.props, 225 | min = _this$props2.min, 226 | max = _this$props2.max, 227 | width = _this$props2.width, 228 | className = _this$props2.className, 229 | style = _this$props2.style; 230 | var value = this.state.value; 231 | var widthBackground = clamp((value - min) * 100 / (max - min), 0, 100); 232 | 233 | var sliderStyles = _objectSpread$2({ 234 | width: "".concat(width, "%"), 235 | backgroundSize: "".concat(widthBackground, "% 100%") 236 | }, style); 237 | 238 | return /*#__PURE__*/React.createElement("span", { 239 | ref: this.sliderRef, 240 | className: cx('slider', className), 241 | style: sliderStyles, 242 | onClick: this.handleClick, 243 | onMouseDown: this.handleMouseDown, 244 | role: "slider", 245 | tabIndex: 0, 246 | "aria-valuenow": value, 247 | "aria-valuemin": min, 248 | "aria-valuemax": max 249 | }); 250 | } 251 | }], [{ 252 | key: "getDerivedStateFromProps", 253 | value: function getDerivedStateFromProps(nextProps, prevState) { 254 | var nextValue = toNumber(nextProps.value); 255 | if (prevState.value === nextValue) return null; 256 | return { 257 | value: nextValue 258 | }; 259 | } 260 | }]); 261 | 262 | return Slider; 263 | }(Component); 264 | 265 | _defineProperty(Slider, "defaultProps", { 266 | className: null, 267 | style: null, 268 | value: null, 269 | min: null, 270 | max: null, 271 | width: null 272 | }); 273 | 274 | function _createSuper$7(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct$7(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; } 275 | 276 | function _isNativeReflectConstruct$7() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } } 277 | 278 | var applyConstraints = function applyConstraints(_ref) { 279 | var value = _ref.value, 280 | min = _ref.min, 281 | max = _ref.max, 282 | step = _ref.step; 283 | var _ref2 = [isFinite$1(min), isFinite$1(max), isFinite$1(step)], 284 | hasMin = _ref2[0], 285 | hasMax = _ref2[1], 286 | hasStep = _ref2[2]; 287 | var decimalPlaces = hasStep && !isInteger(step) ? step.toString().split('.')[1].length : 0; 288 | var isMin = false, 289 | isMax = false; 290 | value = toNumber(value); 291 | 292 | if (hasMin && value <= min) { 293 | value = min; 294 | isMin = true; 295 | } 296 | 297 | if (hasMax && value >= max) { 298 | value = max; 299 | isMax = true; 300 | } 301 | 302 | if (!isMin && !isMax) { 303 | if (hasStep && step !== 0) { 304 | value = Math.round(value / step) * step; 305 | } 306 | } 307 | 308 | return value.toFixed(decimalPlaces); 309 | }; 310 | 311 | var DatNumber = /*#__PURE__*/function (_Component) { 312 | _inherits(DatNumber, _Component); 313 | 314 | var _super = _createSuper$7(DatNumber); 315 | 316 | function DatNumber() { 317 | var _this; 318 | 319 | _classCallCheck(this, DatNumber); 320 | 321 | _this = _super.call(this); 322 | 323 | _defineProperty(_assertThisInitialized(_this), "handleChange", function (event) { 324 | var value = event.target.value; 325 | 326 | _this.update(value); 327 | }); 328 | 329 | _defineProperty(_assertThisInitialized(_this), "handleSliderUpdate", function (value) { 330 | var _this$props = _this.props, 331 | min = _this$props.min, 332 | max = _this$props.max, 333 | step = _this$props.step; 334 | 335 | _this.update(applyConstraints({ 336 | value: value, 337 | min: min, 338 | max: max, 339 | step: step 340 | })); 341 | }); 342 | 343 | _defineProperty(_assertThisInitialized(_this), "update", function (value) { 344 | var _this$props2 = _this.props, 345 | _onUpdateValue = _this$props2._onUpdateValue, 346 | path = _this$props2.path; 347 | 348 | _onUpdateValue(path, toNumber(value)); 349 | }); 350 | 351 | _this.state = { 352 | value: null 353 | }; 354 | return _this; 355 | } 356 | 357 | _createClass(DatNumber, [{ 358 | key: "renderSlider", 359 | value: function renderSlider(width) { 360 | var _this$props3 = this.props, 361 | min = _this$props3.min, 362 | max = _this$props3.max; 363 | var value = this.state.value; 364 | return /*#__PURE__*/React.createElement(Slider, { 365 | value: value, 366 | min: min, 367 | max: max, 368 | width: width, 369 | onUpdate: this.handleSliderUpdate 370 | }); 371 | } 372 | }, { 373 | key: "render", 374 | value: function render() { 375 | var _this$props4 = this.props, 376 | min = _this$props4.min, 377 | max = _this$props4.max, 378 | path = _this$props4.path, 379 | label = _this$props4.label, 380 | labelWidth = _this$props4.labelWidth, 381 | step = _this$props4.step, 382 | disableSlider = _this$props4.disableSlider, 383 | className = _this$props4.className, 384 | style = _this$props4.style; 385 | var labelText = isString(label) ? label : path; 386 | var hasSlider = isFinite$1(min) && isFinite$1(max); 387 | var controlsWidth = 100; 388 | var inputWidth = hasSlider && disableSlider !== true ? Math.round(controlsWidth / 3) : controlsWidth; 389 | var sliderWidth = controlsWidth - inputWidth; 390 | return /*#__PURE__*/React.createElement("li", { 391 | className: cx('cr', 'number', className), 392 | style: style 393 | }, /*#__PURE__*/React.createElement("label", null, /*#__PURE__*/React.createElement("span", { 394 | className: "label-text", 395 | style: { 396 | width: labelWidth 397 | } 398 | }, labelText), /*#__PURE__*/React.createElement("span", { 399 | style: { 400 | display: 'inherit', 401 | width: "calc(100% - ".concat(labelWidth, ")") 402 | } 403 | }, hasSlider && disableSlider !== true ? this.renderSlider(sliderWidth) : null, /*#__PURE__*/React.createElement("input", { 404 | type: "number", 405 | step: step, 406 | min: min, 407 | max: max, 408 | inputMode: "numeric", 409 | value: this.state.value, 410 | style: { 411 | width: "".concat(inputWidth, "%") 412 | }, 413 | onChange: this.handleChange 414 | })))); 415 | } 416 | }], [{ 417 | key: "getDerivedStateFromProps", 418 | value: function getDerivedStateFromProps(nextProps) { 419 | var min = nextProps.min, 420 | max = nextProps.max, 421 | step = nextProps.step; 422 | var nextValue = applyConstraints({ 423 | value: result(nextProps.data, nextProps.path), 424 | min: min, 425 | max: max, 426 | step: step 427 | }); 428 | return { 429 | value: nextValue 430 | }; 431 | } 432 | }]); 433 | 434 | return DatNumber; 435 | }(Component); 436 | 437 | _defineProperty(DatNumber, "defaultProps", { 438 | className: null, 439 | style: null, 440 | min: null, 441 | max: null, 442 | step: null, 443 | path: null, 444 | label: null, 445 | disableSlider: null 446 | }); 447 | 448 | function _createSuper$6(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct$6(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; } 449 | 450 | function _isNativeReflectConstruct$6() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } } 451 | 452 | var DatBoolean = /*#__PURE__*/function (_Component) { 453 | _inherits(DatBoolean, _Component); 454 | 455 | var _super = _createSuper$6(DatBoolean); 456 | 457 | function DatBoolean(props) { 458 | var _this; 459 | 460 | _classCallCheck(this, DatBoolean); 461 | 462 | _this = _super.call(this, props); 463 | 464 | _defineProperty(_assertThisInitialized(_this), "handleChange", function (event) { 465 | var value = event.target.checked; 466 | var _this$props = _this.props, 467 | _onUpdateValue = _this$props._onUpdateValue, 468 | path = _this$props.path; 469 | 470 | _onUpdateValue(path, value); 471 | }); 472 | 473 | _this.state = { 474 | value: null 475 | }; 476 | return _this; 477 | } 478 | 479 | _createClass(DatBoolean, [{ 480 | key: "render", 481 | value: function render() { 482 | var _this$props2 = this.props, 483 | path = _this$props2.path, 484 | label = _this$props2.label, 485 | labelWidth = _this$props2.labelWidth, 486 | className = _this$props2.className, 487 | style = _this$props2.style; 488 | var labelText = isString(label) ? label : path; 489 | return /*#__PURE__*/React.createElement("li", { 490 | className: cx('cr', 'boolean', className), 491 | style: style 492 | }, /*#__PURE__*/React.createElement("label", null, /*#__PURE__*/React.createElement("span", { 493 | className: "label-text", 494 | style: { 495 | width: labelWidth 496 | } 497 | }, labelText), /*#__PURE__*/React.createElement("span", { 498 | className: "checkbox-container", 499 | style: { 500 | width: "calc(100% - ".concat(labelWidth, ")") 501 | } 502 | }, /*#__PURE__*/React.createElement("input", { 503 | type: "checkbox", 504 | checked: this.state.value, 505 | onChange: this.handleChange 506 | })))); 507 | } 508 | }], [{ 509 | key: "getDerivedStateFromProps", 510 | value: function getDerivedStateFromProps(nextProps, prevState) { 511 | var nextValue = result(nextProps.data, nextProps.path); 512 | if (prevState.value === nextValue) return null; 513 | return { 514 | value: nextValue 515 | }; 516 | } 517 | }]); 518 | 519 | return DatBoolean; 520 | }(Component); 521 | 522 | _defineProperty(DatBoolean, "defaultProps", { 523 | className: null, 524 | style: null, 525 | path: null, 526 | label: null 527 | }); 528 | 529 | var DatButton = function DatButton(_ref) { 530 | var label = _ref.label, 531 | onClick = _ref.onClick, 532 | className = _ref.className, 533 | style = _ref.style; 534 | return /*#__PURE__*/React.createElement("li", { 535 | className: cx('cr', 'button', className), 536 | style: style 537 | }, /*#__PURE__*/React.createElement("span", { 538 | className: "label-text", 539 | onClick: onClick, 540 | onKeyPress: onClick, 541 | role: "button", 542 | tabIndex: 0 543 | }, label)); 544 | }; 545 | 546 | DatButton.defaultProps = { 547 | className: null, 548 | style: null, 549 | label: null 550 | }; 551 | 552 | function ownKeys$1(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; } 553 | 554 | function _objectSpread$1(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys$1(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys$1(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } 555 | 556 | function _createSuper$5(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct$5(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; } 557 | 558 | function _isNativeReflectConstruct$5() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } } 559 | 560 | var DatFolder = /*#__PURE__*/function (_Component) { 561 | _inherits(DatFolder, _Component); 562 | 563 | var _super = _createSuper$5(DatFolder); 564 | 565 | function DatFolder(props) { 566 | var _this; 567 | 568 | _classCallCheck(this, DatFolder); 569 | 570 | _this = _super.call(this, props); 571 | 572 | _defineProperty(_assertThisInitialized(_this), "handleClick", function () { 573 | return _this.setState(function (prevState) { 574 | return { 575 | closed: !prevState.closed 576 | }; 577 | }); 578 | }); 579 | 580 | _this.state = { 581 | closed: props.closed 582 | }; 583 | return _this; 584 | } 585 | 586 | _createClass(DatFolder, [{ 587 | key: "renderChildren", 588 | value: function renderChildren() { 589 | // Disable this rule to take title out of the props so nested folders can have unique titles. 590 | // eslint-disable-next-line no-unused-vars 591 | var _this$props = this.props, 592 | children = _this$props.children; 593 | _this$props.title; 594 | var rest = _objectWithoutProperties(_this$props, ["children", "title"]); 595 | 596 | return React.Children.map(children, function (child) { 597 | return /*#__PURE__*/cloneElement(child, _objectSpread$1({}, rest)); 598 | }); 599 | } 600 | }, { 601 | key: "render", 602 | value: function render() { 603 | var closed = this.state.closed; 604 | var _this$props2 = this.props, 605 | title = _this$props2.title, 606 | className = _this$props2.className, 607 | style = _this$props2.style; 608 | return /*#__PURE__*/React.createElement("li", { 609 | className: cx('folder', { 610 | closed: closed 611 | }, className), 612 | style: style 613 | }, /*#__PURE__*/React.createElement("div", { 614 | className: "dg" 615 | }, /*#__PURE__*/React.createElement("div", { 616 | className: "title", 617 | onClick: this.handleClick, 618 | onKeyPress: this.handleClick, 619 | role: "button", 620 | tabIndex: 0 621 | }, title), /*#__PURE__*/React.createElement("ul", null, this.renderChildren()))); 622 | } 623 | }]); 624 | 625 | return DatFolder; 626 | }(Component); 627 | 628 | _defineProperty(DatFolder, "defaultProps", { 629 | className: null, 630 | style: null, 631 | title: 'Folder', 632 | closed: true 633 | }); 634 | 635 | function _createSuper$4(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct$4(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; } 636 | 637 | function _isNativeReflectConstruct$4() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } } 638 | 639 | var DatSelect = /*#__PURE__*/function (_Component) { 640 | _inherits(DatSelect, _Component); 641 | 642 | var _super = _createSuper$4(DatSelect); 643 | 644 | function DatSelect() { 645 | var _this; 646 | 647 | _classCallCheck(this, DatSelect); 648 | 649 | _this = _super.call(this); 650 | 651 | _defineProperty(_assertThisInitialized(_this), "handleChange", function (event) { 652 | var value = event.target.value; 653 | var _this$props = _this.props, 654 | liveUpdate = _this$props.liveUpdate, 655 | _onUpdateValue = _this$props._onUpdateValue, 656 | onUpdate = _this$props.onUpdate, 657 | path = _this$props.path; 658 | 659 | _onUpdateValue(path, value); 660 | 661 | if (liveUpdate) onUpdate(value); 662 | }); 663 | 664 | _this.state = { 665 | value: null, 666 | options: null 667 | }; 668 | return _this; 669 | } 670 | 671 | _createClass(DatSelect, [{ 672 | key: "render", 673 | value: function render() { 674 | var _this$props2 = this.props, 675 | path = _this$props2.path, 676 | label = _this$props2.label, 677 | labelWidth = _this$props2.labelWidth, 678 | optionLabels = _this$props2.optionLabels, 679 | className = _this$props2.className, 680 | style = _this$props2.style; 681 | var _this$state = this.state, 682 | value = _this$state.value, 683 | options = _this$state.options; 684 | var labelText = isString(label) ? label : path; 685 | return /*#__PURE__*/React.createElement("li", { 686 | className: cx('cr', 'select', className), 687 | style: style 688 | }, /*#__PURE__*/React.createElement("label", null, /*#__PURE__*/React.createElement("span", { 689 | className: "label-text", 690 | style: { 691 | width: labelWidth 692 | } 693 | }, labelText), /*#__PURE__*/React.createElement("select", { 694 | value: value, 695 | onChange: this.handleChange, 696 | style: { 697 | width: "calc(100% - ".concat(labelWidth, ")") 698 | } 699 | }, options.map(function (item, index) { 700 | return ( 701 | /*#__PURE__*/ 702 | // eslint-disable-next-line react/no-array-index-key 703 | React.createElement("option", { 704 | key: index, 705 | value: item 706 | }, optionLabels ? optionLabels[index] : item) 707 | ); 708 | })))); 709 | } 710 | }], [{ 711 | key: "getDerivedStateFromProps", 712 | value: function getDerivedStateFromProps(nextProps) { 713 | var nextValue = result(nextProps.data, nextProps.path); 714 | return { 715 | value: nextValue, 716 | options: nextProps.options 717 | }; 718 | } 719 | }]); 720 | 721 | return DatSelect; 722 | }(Component); 723 | 724 | _defineProperty(DatSelect, "defaultProps", { 725 | className: null, 726 | style: null, 727 | path: null, 728 | label: null, 729 | optionLabels: null, 730 | onUpdate: function onUpdate() { 731 | return null; 732 | } 733 | }); 734 | 735 | function _createSuper$3(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct$3(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; } 736 | 737 | function _isNativeReflectConstruct$3() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } } 738 | 739 | var Fields = /*#__PURE__*/function (_Component) { 740 | _inherits(Fields, _Component); 741 | 742 | var _super = _createSuper$3(Fields); 743 | 744 | function Fields() { 745 | var _this; 746 | 747 | _classCallCheck(this, Fields); 748 | 749 | for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { 750 | args[_key] = arguments[_key]; 751 | } 752 | 753 | _this = _super.call.apply(_super, [this].concat(args)); 754 | 755 | _defineProperty(_assertThisInitialized(_this), "handleChange", function (value, e) { 756 | var onChange = _this.props.onChange; 757 | if (color.isValidHex(value)) onChange({ 758 | hex: value, 759 | source: 'hex' 760 | }, e); 761 | }); 762 | 763 | return _this; 764 | } 765 | 766 | _createClass(Fields, [{ 767 | key: "render", 768 | value: function render() { 769 | var hex = this.props.hex; 770 | return /*#__PURE__*/React.createElement("div", { 771 | className: "flexbox-fix fields-wrap" 772 | }, /*#__PURE__*/React.createElement("div", { 773 | className: "flexbox-fix fields" 774 | }, /*#__PURE__*/React.createElement("div", { 775 | className: "field" 776 | }, /*#__PURE__*/React.createElement(EditableInput, { 777 | value: hex, 778 | onChange: this.handleChange 779 | })))); 780 | } 781 | }]); 782 | 783 | return Fields; 784 | }(Component); 785 | 786 | var Pointer = function Pointer() { 787 | return /*#__PURE__*/React.createElement("div", { 788 | className: "pointer" 789 | }); 790 | }; 791 | 792 | var PointerCircle = function PointerCircle() { 793 | return /*#__PURE__*/React.createElement("div", { 794 | className: "pointer-circle" 795 | }); 796 | }; 797 | 798 | var Picker = function Picker(_ref) { 799 | var onChange = _ref.onChange, 800 | hsl = _ref.hsl, 801 | hsv = _ref.hsv, 802 | hex = _ref.hex, 803 | _ref$className = _ref.className, 804 | className = _ref$className === void 0 ? '' : _ref$className; 805 | return /*#__PURE__*/React.createElement("div", { 806 | className: "picker ".concat(className) 807 | }, /*#__PURE__*/React.createElement("div", { 808 | className: "saturation-wrap" 809 | }, /*#__PURE__*/React.createElement(Saturation, { 810 | className: "saturation", 811 | hsl: hsl, 812 | hsv: hsv, 813 | pointer: PointerCircle, 814 | onChange: onChange 815 | })), /*#__PURE__*/React.createElement("div", { 816 | className: "body" 817 | }, /*#__PURE__*/React.createElement("div", { 818 | className: "controls" 819 | }, /*#__PURE__*/React.createElement("div", { 820 | className: "toggles" 821 | }, /*#__PURE__*/React.createElement("div", { 822 | className: "hue-wrap" 823 | }, /*#__PURE__*/React.createElement(Hue, { 824 | className: "hue", 825 | hsl: hsl, 826 | pointer: Pointer, 827 | onChange: onChange 828 | })))), /*#__PURE__*/React.createElement(Fields, { 829 | hex: hex, 830 | onChange: onChange 831 | }))); 832 | }; 833 | 834 | Picker.defaultProps = { 835 | hsl: null, 836 | hsv: null, 837 | hex: null, 838 | className: null, 839 | disableAlpha: false 840 | }; 841 | var ColorPicker = ColorWrap(Picker); 842 | 843 | function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; } 844 | 845 | function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } 846 | 847 | function _createSuper$2(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct$2(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; } 848 | 849 | function _isNativeReflectConstruct$2() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } } 850 | 851 | var DatColor = /*#__PURE__*/function (_Component) { 852 | _inherits(DatColor, _Component); 853 | 854 | var _super = _createSuper$2(DatColor); 855 | 856 | function DatColor() { 857 | var _this; 858 | 859 | _classCallCheck(this, DatColor); 860 | 861 | _this = _super.call(this); 862 | 863 | _defineProperty(_assertThisInitialized(_this), "handleClickColorPicker", function () { 864 | return _this.setState(function (prevState) { 865 | return _objectSpread(_objectSpread({}, prevState), {}, { 866 | displayColorPicker: !prevState.displayColorPicker 867 | }); 868 | }); 869 | }); 870 | 871 | _defineProperty(_assertThisInitialized(_this), "handleCloseColorPicker", function () { 872 | return _this.setState({ 873 | displayColorPicker: false 874 | }); 875 | }); 876 | 877 | _defineProperty(_assertThisInitialized(_this), "handleChangeColor", function (color) { 878 | var value = isString(color) ? color : color.hex; 879 | var _this$props = _this.props, 880 | _onUpdateValue = _this$props._onUpdateValue, 881 | path = _this$props.path; 882 | 883 | _onUpdateValue(path, value); 884 | }); 885 | 886 | _this.state = { 887 | value: null, 888 | displayColorPicker: false 889 | }; 890 | return _this; 891 | } 892 | 893 | _createClass(DatColor, [{ 894 | key: "renderPicker", 895 | value: function renderPicker() { 896 | var _this$state = this.state, 897 | value = _this$state.value, 898 | displayColorPicker = _this$state.displayColorPicker; 899 | return !displayColorPicker ? null : /*#__PURE__*/React.createElement("div", { 900 | className: "popover" 901 | }, /*#__PURE__*/React.createElement("div", { 902 | className: "cover", 903 | onClick: this.handleCloseColorPicker, 904 | onKeyPress: this.handleCloseColorPicker, 905 | role: "button", 906 | tabIndex: 0 907 | }), /*#__PURE__*/React.createElement(ColorPicker, { 908 | color: value, 909 | onChange: this.handleChangeColor 910 | })); 911 | } 912 | }, { 913 | key: "render", 914 | value: function render() { 915 | var _this$props2 = this.props, 916 | path = _this$props2.path, 917 | label = _this$props2.label, 918 | labelWidth = _this$props2.labelWidth, 919 | className = _this$props2.className, 920 | style = _this$props2.style; 921 | var value = this.state.value; 922 | var labelText = isString(label) ? label : path; 923 | return /*#__PURE__*/React.createElement("li", { 924 | className: cx('cr', 'color', className), 925 | style: _objectSpread({ 926 | borderLeftColor: "".concat(value) 927 | }, style) 928 | }, /*#__PURE__*/React.createElement("label", null, /*#__PURE__*/React.createElement("span", { 929 | className: "label-text", 930 | style: { 931 | width: labelWidth 932 | } 933 | }, labelText), /*#__PURE__*/React.createElement("div", { 934 | style: { 935 | backgroundColor: value, 936 | width: "calc(100% - ".concat(labelWidth, ")") 937 | } 938 | }, /*#__PURE__*/React.createElement("div", { 939 | className: "swatch", 940 | onClick: this.handleClickColorPicker, 941 | onKeyPress: this.handleClickColorPicker, 942 | role: "button", 943 | tabIndex: 0 944 | }, value), this.renderPicker()))); 945 | } 946 | }], [{ 947 | key: "getDerivedStateFromProps", 948 | value: function getDerivedStateFromProps(nextProps, prevState) { 949 | var nextValue = result(nextProps.data, nextProps.path); 950 | return _objectSpread(_objectSpread({}, prevState), {}, { 951 | value: nextValue 952 | }); 953 | } 954 | }]); 955 | 956 | return DatColor; 957 | }(Component); 958 | 959 | _defineProperty(DatColor, "defaultProps", { 960 | className: null, 961 | style: null, 962 | path: null, 963 | label: null 964 | }); 965 | 966 | function _createSuper$1(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct$1(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; } 967 | 968 | function _isNativeReflectConstruct$1() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } } 969 | var DEFAULT_PRESET_KEY = 'Default'; 970 | 971 | var DatPresets = /*#__PURE__*/function (_Component) { 972 | _inherits(DatPresets, _Component); 973 | 974 | var _super = _createSuper$1(DatPresets); 975 | 976 | function DatPresets() { 977 | var _this; 978 | 979 | _classCallCheck(this, DatPresets); 980 | 981 | _this = _super.call(this); 982 | 983 | _defineProperty(_assertThisInitialized(_this), "handleChange", function (event) { 984 | var value = JSON.parse(event.target.value); 985 | var _this$props = _this.props, 986 | liveUpdate = _this$props.liveUpdate, 987 | onUpdate = _this$props.onUpdate; 988 | if (liveUpdate) onUpdate(value); 989 | }); 990 | 991 | _this.state = { 992 | defaultPreset: null, 993 | options: null 994 | }; 995 | return _this; 996 | } 997 | 998 | _createClass(DatPresets, [{ 999 | key: "render", 1000 | value: function render() { 1001 | var _this$props2 = this.props, 1002 | path = _this$props2.path, 1003 | label = _this$props2.label, 1004 | labelWidth = _this$props2.labelWidth, 1005 | className = _this$props2.className, 1006 | style = _this$props2.style; 1007 | var options = this.state.options; 1008 | var labelText = isString(label) ? label : path; 1009 | return /*#__PURE__*/React.createElement("li", { 1010 | className: cx('cr', 'presets', className), 1011 | style: style 1012 | }, /*#__PURE__*/React.createElement("label", null, /*#__PURE__*/React.createElement("span", { 1013 | className: "label-text", 1014 | style: { 1015 | width: labelWidth 1016 | } 1017 | }, labelText), /*#__PURE__*/React.createElement("select", { 1018 | onChange: this.handleChange, 1019 | style: { 1020 | width: "calc(100% - ".concat(labelWidth, ")") 1021 | } 1022 | }, options.map(function (preset) { 1023 | return Object.keys(preset).map(function (key) { 1024 | return /*#__PURE__*/React.createElement("option", { 1025 | key: key, 1026 | value: JSON.stringify(preset[key]) 1027 | }, key); 1028 | }); 1029 | })))); 1030 | } 1031 | }], [{ 1032 | key: "getDerivedStateFromProps", 1033 | value: function getDerivedStateFromProps(nextProps, prevState) { 1034 | var nextValue = cloneDeep(nextProps.data); 1035 | var defaultPreset = prevState.defaultPreset ? prevState.defaultPreset : nextValue; 1036 | return { 1037 | defaultPreset: defaultPreset, 1038 | options: [_defineProperty({}, DEFAULT_PRESET_KEY, defaultPreset)].concat(_toConsumableArray(nextProps.options.filter(function (preset) { 1039 | return Object.keys(preset)[0] !== DEFAULT_PRESET_KEY; 1040 | }))) 1041 | }; 1042 | } 1043 | }]); 1044 | 1045 | return DatPresets; 1046 | }(Component); 1047 | 1048 | _defineProperty(DatPresets, "defaultProps", { 1049 | className: null, 1050 | style: null, 1051 | path: null 1052 | }); 1053 | 1054 | function _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; } 1055 | 1056 | function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } } 1057 | 1058 | var DatGui = /*#__PURE__*/function (_Component) { 1059 | _inherits(DatGui, _Component); 1060 | 1061 | var _super = _createSuper(DatGui); 1062 | 1063 | function DatGui() { 1064 | var _this; 1065 | 1066 | _classCallCheck(this, DatGui); 1067 | 1068 | for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { 1069 | args[_key] = arguments[_key]; 1070 | } 1071 | 1072 | _this = _super.call.apply(_super, [this].concat(args)); 1073 | 1074 | _defineProperty(_assertThisInitialized(_this), "handleUpdateValue", function (path, value) { 1075 | var _this$props = _this.props, 1076 | data = _this$props.data, 1077 | onUpdate = _this$props.onUpdate; 1078 | var dataUpdated = set(cloneDeep(data), path, value); 1079 | onUpdate(dataUpdated); 1080 | }); 1081 | 1082 | return _this; 1083 | } 1084 | 1085 | _createClass(DatGui, [{ 1086 | key: "renderChildren", 1087 | value: function renderChildren() { 1088 | var _this2 = this; 1089 | 1090 | var _this$props2 = this.props, 1091 | children = _this$props2.children, 1092 | data = _this$props2.data; 1093 | return React.Children.toArray(children).map(function (child, i) { 1094 | var liveUpdate = isUndefined(child.props.liveUpdate) ? _this2.props.liveUpdate : child.props.liveUpdate; 1095 | var labelWidth = isUndefined(child.props.labelWidth) ? _this2.props.labelWidth : child.props.labelWidth; 1096 | return /*#__PURE__*/cloneElement(child, { 1097 | key: i, 1098 | data: data, 1099 | liveUpdate: liveUpdate, 1100 | labelWidth: labelWidth, 1101 | _onUpdateValue: _this2.handleUpdateValue 1102 | }); 1103 | }); 1104 | } 1105 | }, { 1106 | key: "render", 1107 | value: function render() { 1108 | var _this$props3 = this.props, 1109 | style = _this$props3.style, 1110 | className = _this$props3.className; 1111 | var classNames = cx('react-dat-gui', className); 1112 | return /*#__PURE__*/React.createElement("div", { 1113 | className: classNames, 1114 | style: style 1115 | }, /*#__PURE__*/React.createElement("ul", { 1116 | className: "dg main" 1117 | }, this.renderChildren())); 1118 | } 1119 | }]); 1120 | 1121 | return DatGui; 1122 | }(Component); 1123 | 1124 | _defineProperty(DatGui, "defaultProps", { 1125 | liveUpdate: true, 1126 | className: null, 1127 | style: null, 1128 | labelWidth: '40%' 1129 | }); 1130 | 1131 | export default DatGui; 1132 | export { DatBoolean, DatButton, DatColor, DatFolder, DatNumber, DatPresets, DatSelect, DatString }; 1133 | //# sourceMappingURL=index.es.js.map 1134 | -------------------------------------------------------------------------------- /dist/index.es.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"index.es.js","sources":["../src/components/DatString.js","../src/components/utils.js","../src/components/Slider.js","../src/components/DatNumber.js","../src/components/DatBoolean.js","../src/components/DatButton.js","../src/components/DatFolder.js","../src/components/DatSelect.js","../src/components/Picker/Fields.js","../src/components/Picker/Pointer.js","../src/components/Picker/PointerCircle.js","../src/components/Picker/index.js","../src/components/DatColor.js","../src/components/DatPresets.js","../src/index.js"],"sourcesContent":["import React, { Component } from 'react';\nimport PropTypes from 'prop-types';\nimport isString from 'lodash.isstring';\nimport result from 'lodash.result';\nimport cx from 'classnames';\n\nexport default class DatString extends Component {\n static propTypes = {\n className: PropTypes.string,\n style: PropTypes.object,\n data: PropTypes.object.isRequired,\n path: PropTypes.string,\n label: PropTypes.string,\n labelWidth: PropTypes.string.isRequired,\n liveUpdate: PropTypes.bool.isRequired,\n onUpdate: PropTypes.func,\n _onUpdateValue: PropTypes.func.isRequired\n };\n\n static defaultProps = {\n className: null,\n style: null,\n path: null,\n label: null,\n onUpdate: () => null\n };\n\n constructor() {\n super();\n this.state = {\n value: null\n };\n }\n\n static getDerivedStateFromProps(nextProps, prevState) {\n const nextValue = result(nextProps.data, nextProps.path);\n\n if (prevState.value === nextValue) return null;\n\n return {\n value: nextValue\n };\n }\n\n handleChange = event => {\n const { value } = event.target;\n const { liveUpdate } = this.props;\n\n if (liveUpdate) this.update(value);\n };\n\n handleFocus = () => {\n document.addEventListener('keydown', this.handleKeyDown);\n };\n\n handleBlur = () => {\n document.removeEventListener('keydown', this.handleKeyDown);\n window.getSelection().removeAllRanges();\n\n const { liveUpdate } = this.props;\n if (!liveUpdate) this.update();\n };\n\n handleKeyDown = event => {\n const key = event.keyCode || event.which;\n const { liveUpdate } = this.props;\n\n if (key === 13 && !liveUpdate) this.update();\n };\n\n update(value) {\n const { _onUpdateValue, onUpdate, path } = this.props;\n _onUpdateValue(path, value);\n onUpdate(value);\n }\n\n render() {\n const { path, label, labelWidth, className, style } = this.props;\n const labelText = isString(label) ? label : path;\n\n return (\n
  • \n \n
  • \n );\n }\n}\n","/* eslint-disable no-restricted-globals */\nexport function toNumber(value) {\n const float = parseFloat(value);\n return isNaN(float) ? 0 : float;\n}\n\n/**\n * Polyfill for isInteger.\n *\n * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/isInteger#Polyfill\n * @param {number} value\n * @return {bool}\n */\nexport const isInteger =\n Number.isInteger ||\n // eslint-disable-next-line func-names\n function(value) {\n return (\n typeof value === 'number' &&\n isFinite(value) &&\n Math.floor(value) === value\n );\n };\n","/* eslint-disable jsx-a11y/click-events-have-key-events */\n/* eslint-disable jsx-a11y/control-has-associated-label */\nimport React, { Component } from 'react';\nimport PropTypes from 'prop-types';\nimport clamp from 'lodash.clamp';\nimport cx from 'classnames';\nimport { toNumber } from './utils';\n\nexport default class Slider extends Component {\n static propTypes = {\n className: PropTypes.string,\n style: PropTypes.object,\n value: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),\n min: PropTypes.number,\n max: PropTypes.number,\n width: PropTypes.number,\n onUpdate: PropTypes.func.isRequired\n };\n\n static defaultProps = {\n className: null,\n style: null,\n value: null,\n min: null,\n max: null,\n width: null\n };\n\n constructor() {\n super();\n this.state = { value: null };\n this.sliderRef = React.createRef();\n }\n\n static getDerivedStateFromProps(nextProps, prevState) {\n const nextValue = toNumber(nextProps.value);\n\n if (prevState.value === nextValue) return null;\n\n return {\n value: nextValue\n };\n }\n\n handleMouseDown = event => {\n this.update(event.pageX);\n\n window.addEventListener('mousemove', this.handleMouseMove);\n window.addEventListener('mouseup', this.handleMouseUp);\n };\n\n handleMouseMove = event => {\n this.update(event.pageX);\n\n event.preventDefault();\n };\n\n handleMouseUp = event => {\n this.update(event.pageX, false);\n\n window.removeEventListener('mousemove', this.handleMouseMove);\n window.removeEventListener('mouseup', this.handleMouseUp);\n };\n\n handleClick = event => {\n // do not focus input field on slider click\n event.preventDefault();\n };\n\n update(pageX, isLive = true) {\n const { min, max, onUpdate } = this.props;\n const rect = this.sliderRef.current.getBoundingClientRect();\n const x = pageX - rect.left;\n const w = rect.right - rect.left;\n const value = min + clamp(x / w, 0, 1) * (max - min);\n\n this.setState({ value }, () => {\n onUpdate(value, isLive);\n });\n }\n\n render() {\n const { min, max, width, className, style } = this.props;\n const { value } = this.state;\n const widthBackground = clamp(((value - min) * 100) / (max - min), 0, 100);\n const sliderStyles = {\n width: `${width}%`,\n backgroundSize: `${widthBackground}% 100%`,\n ...style\n };\n\n return (\n \n );\n }\n}\n","/* eslint-disable no-param-reassign */\nimport React, { Component } from 'react';\nimport PropTypes from 'prop-types';\nimport isFinite from 'lodash.isfinite';\nimport isString from 'lodash.isstring';\nimport result from 'lodash.result';\nimport cx from 'classnames';\nimport Slider from './Slider';\nimport { isInteger, toNumber } from './utils';\n\nconst applyConstraints = ({ value, min, max, step }) => {\n const [hasMin, hasMax, hasStep] = [\n isFinite(min),\n isFinite(max),\n isFinite(step)\n ];\n const decimalPlaces =\n hasStep && !isInteger(step) ? step.toString().split('.')[1].length : 0;\n let [isMin, isMax] = [false, false];\n\n value = toNumber(value);\n\n if (hasMin && value <= min) {\n value = min;\n isMin = true;\n }\n\n if (hasMax && value >= max) {\n value = max;\n isMax = true;\n }\n\n if (!isMin && !isMax) {\n if (hasStep && step !== 0) {\n value = Math.round(value / step) * step;\n }\n }\n\n return value.toFixed(decimalPlaces);\n};\n\nexport default class DatNumber extends Component {\n static propTypes = {\n className: PropTypes.string,\n style: PropTypes.object,\n min: PropTypes.number,\n max: PropTypes.number,\n step: PropTypes.number,\n data: PropTypes.object.isRequired,\n path: PropTypes.string,\n label: PropTypes.string,\n labelWidth: PropTypes.string.isRequired,\n _onUpdateValue: PropTypes.func.isRequired,\n disableSlider: PropTypes.bool\n };\n\n static defaultProps = {\n className: null,\n style: null,\n min: null,\n max: null,\n step: null,\n path: null,\n label: null,\n disableSlider: null\n };\n\n constructor() {\n super();\n this.state = { value: null };\n }\n\n static getDerivedStateFromProps(nextProps) {\n const { min, max, step } = nextProps;\n const nextValue = applyConstraints({\n value: result(nextProps.data, nextProps.path),\n min,\n max,\n step\n });\n\n return {\n value: nextValue\n };\n }\n\n handleChange = event => {\n const { value } = event.target;\n this.update(value);\n };\n\n handleSliderUpdate = value => {\n const { min, max, step } = this.props;\n\n this.update(applyConstraints({ value, min, max, step }));\n };\n\n update = value => {\n const { _onUpdateValue, path } = this.props;\n\n _onUpdateValue(path, toNumber(value));\n };\n\n renderSlider(width) {\n const { min, max } = this.props;\n const { value } = this.state;\n\n return (\n \n );\n }\n\n render() {\n const {\n min,\n max,\n path,\n label,\n labelWidth,\n step,\n disableSlider,\n className,\n style\n } = this.props;\n const labelText = isString(label) ? label : path;\n const hasSlider = isFinite(min) && isFinite(max);\n const controlsWidth = 100;\n const inputWidth =\n hasSlider && disableSlider !== true\n ? Math.round(controlsWidth / 3)\n : controlsWidth;\n const sliderWidth = controlsWidth - inputWidth;\n\n return (\n
  • \n \n
  • \n );\n }\n}\n","import React, { Component } from 'react';\nimport PropTypes from 'prop-types';\nimport isString from 'lodash.isstring';\nimport result from 'lodash.result';\nimport cx from 'classnames';\n\nexport default class DatBoolean extends Component {\n static propTypes = {\n className: PropTypes.string,\n style: PropTypes.object,\n data: PropTypes.object.isRequired,\n path: PropTypes.string,\n label: PropTypes.string,\n labelWidth: PropTypes.string.isRequired,\n _onUpdateValue: PropTypes.func.isRequired\n };\n\n static defaultProps = {\n className: null,\n style: null,\n path: null,\n label: null\n };\n\n constructor(props) {\n super(props);\n\n this.state = {\n value: null\n };\n }\n\n static getDerivedStateFromProps(nextProps, prevState) {\n const nextValue = result(nextProps.data, nextProps.path);\n\n if (prevState.value === nextValue) return null;\n\n return {\n value: nextValue\n };\n }\n\n handleChange = event => {\n const value = event.target.checked;\n const { _onUpdateValue, path } = this.props;\n\n _onUpdateValue(path, value);\n };\n\n render() {\n const { path, label, labelWidth, className, style } = this.props;\n const labelText = isString(label) ? label : path;\n\n return (\n
  • \n \n
  • \n );\n }\n}\n","import React from 'react';\nimport PropTypes from 'prop-types';\nimport cx from 'classnames';\n\nconst DatButton = ({ label, onClick, className, style }) => (\n
  • \n \n {label}\n \n
  • \n);\n\nDatButton.propTypes = {\n className: PropTypes.string,\n style: PropTypes.object,\n label: PropTypes.string,\n onClick: PropTypes.func.isRequired\n};\n\nDatButton.defaultProps = {\n className: null,\n style: null,\n label: null\n};\n\nexport default DatButton;\n","import React, { Component, cloneElement } from 'react';\nimport PropTypes from 'prop-types';\nimport cx from 'classnames';\n\nexport default class DatFolder extends Component {\n static propTypes = {\n className: PropTypes.string,\n style: PropTypes.object,\n title: PropTypes.string,\n closed: PropTypes.bool,\n children: PropTypes.element.isRequired\n };\n\n static defaultProps = {\n className: null,\n style: null,\n title: 'Folder',\n closed: true\n };\n\n constructor(props) {\n super(props);\n this.state = { closed: props.closed };\n }\n\n handleClick = () =>\n this.setState(prevState => ({ closed: !prevState.closed }));\n\n renderChildren() {\n // Disable this rule to take title out of the props so nested folders can have unique titles.\n // eslint-disable-next-line no-unused-vars\n const { children, title, ...rest } = this.props;\n\n return React.Children.map(children, child =>\n cloneElement(child, { ...rest })\n );\n }\n\n render() {\n const { closed } = this.state;\n const { title, className, style } = this.props;\n\n return (\n
  • \n
    \n \n {title}\n
    \n
      {this.renderChildren()}
    \n
  • \n \n );\n }\n}\n","import React, { Component } from 'react';\nimport PropTypes from 'prop-types';\nimport isString from 'lodash.isstring';\nimport result from 'lodash.result';\nimport cx from 'classnames';\n\nexport default class DatSelect extends Component {\n static propTypes = {\n className: PropTypes.string,\n style: PropTypes.object,\n data: PropTypes.object.isRequired,\n path: PropTypes.string,\n label: PropTypes.string,\n options: PropTypes.array.isRequired,\n optionLabels: PropTypes.array,\n labelWidth: PropTypes.string.isRequired,\n liveUpdate: PropTypes.bool.isRequired,\n onUpdate: PropTypes.func,\n _onUpdateValue: PropTypes.func.isRequired\n };\n\n static defaultProps = {\n className: null,\n style: null,\n path: null,\n label: null,\n optionLabels: null,\n onUpdate: () => null\n };\n\n constructor() {\n super();\n this.state = {\n value: null,\n options: null\n };\n }\n\n static getDerivedStateFromProps(nextProps) {\n const nextValue = result(nextProps.data, nextProps.path);\n\n return {\n value: nextValue,\n options: nextProps.options\n };\n }\n\n handleChange = event => {\n const { value } = event.target;\n const { liveUpdate, _onUpdateValue, onUpdate, path } = this.props;\n _onUpdateValue(path, value);\n if (liveUpdate) onUpdate(value);\n };\n\n render() {\n const {\n path,\n label,\n labelWidth,\n optionLabels,\n className,\n style\n } = this.props;\n const { value, options } = this.state;\n const labelText = isString(label) ? label : path;\n\n return (\n
  • \n \n
  • \n );\n }\n}\n","import React, { Component } from 'react';\nimport PropTypes from 'prop-types';\nimport { EditableInput } from 'react-color/lib/components/common';\nimport color from 'react-color/lib/helpers/color';\n\nexport default class Fields extends Component {\n static propTypes = {\n hex: PropTypes.string.isRequired,\n onChange: PropTypes.func.isRequired\n };\n\n handleChange = (value, e) => {\n const { onChange } = this.props;\n\n if (color.isValidHex(value))\n onChange(\n {\n hex: value,\n source: 'hex'\n },\n e\n );\n };\n\n render() {\n const { hex } = this.props;\n\n return (\n
    \n
    \n
    \n \n
    \n
    \n
    \n );\n }\n}\n","import React from 'react';\n\nconst Pointer = () =>
    ;\n\nexport default Pointer;\n","import React from 'react';\n\nconst PointerCircle = () =>
    ;\n\nexport default PointerCircle;\n","import { ColorWrap, Hue, Saturation } from 'react-color/lib/components/common';\nimport PropTypes from 'prop-types';\nimport React from 'react';\nimport Fields from './Fields';\nimport Pointer from './Pointer';\nimport PointerCircle from './PointerCircle';\n\nconst Picker = ({ onChange, hsl, hsv, hex, className = '' }) => {\n return (\n
    \n
    \n \n
    \n
    \n
    \n
    \n
    \n \n
    \n
    \n
    \n \n
    \n
    \n );\n};\n\nPicker.propTypes = {\n onChange: PropTypes.func.isRequired,\n hsl: PropTypes.string,\n hsv: PropTypes.string,\n hex: PropTypes.string,\n className: PropTypes.string,\n disableAlpha: PropTypes.bool\n};\n\nPicker.defaultProps = {\n hsl: null,\n hsv: null,\n hex: null,\n className: null,\n disableAlpha: false\n};\n\nexport default ColorWrap(Picker);\n","import React, { Component } from 'react';\nimport PropTypes from 'prop-types';\nimport isString from 'lodash.isstring';\nimport result from 'lodash.result';\nimport cx from 'classnames';\nimport ColorPicker from './Picker';\n\nexport default class DatColor extends Component {\n static propTypes = {\n className: PropTypes.string,\n style: PropTypes.object,\n data: PropTypes.object.isRequired,\n path: PropTypes.string,\n label: PropTypes.string,\n labelWidth: PropTypes.string.isRequired,\n _onUpdateValue: PropTypes.func.isRequired\n };\n\n static defaultProps = {\n className: null,\n style: null,\n path: null,\n label: null\n };\n\n constructor() {\n super();\n\n this.state = {\n value: null,\n displayColorPicker: false\n };\n }\n\n static getDerivedStateFromProps(nextProps, prevState) {\n const nextValue = result(nextProps.data, nextProps.path);\n\n return {\n ...prevState,\n value: nextValue\n };\n }\n\n handleClickColorPicker = () =>\n this.setState(prevState => ({\n ...prevState,\n displayColorPicker: !prevState.displayColorPicker\n }));\n\n handleCloseColorPicker = () =>\n this.setState({\n displayColorPicker: false\n });\n\n handleChangeColor = color => {\n const value = isString(color) ? color : color.hex;\n const { _onUpdateValue, path } = this.props;\n\n _onUpdateValue(path, value);\n };\n\n renderPicker() {\n const { value, displayColorPicker } = this.state;\n\n return !displayColorPicker ? null : (\n
    \n {/* eslint-disable-next-line jsx-a11y/control-has-associated-label */}\n \n \n
    \n );\n }\n\n render() {\n const { path, label, labelWidth, className, style } = this.props;\n const { value } = this.state;\n const labelText = isString(label) ? label : path;\n\n return (\n \n
    \n {this.renderPicker()}\n
    \n \n \n );\n }\n}\n","import React, { Component } from 'react';\nimport PropTypes from 'prop-types';\nimport cloneDeep from 'lodash.clonedeep';\nimport isString from 'lodash.isstring';\nimport cx from 'classnames';\n\nconst DEFAULT_PRESET_KEY = 'Default';\n\nexport default class DatPresets extends Component {\n static propTypes = {\n className: PropTypes.string,\n style: PropTypes.object,\n data: PropTypes.object.isRequired,\n path: PropTypes.string,\n label: PropTypes.string.isRequired,\n options: PropTypes.array.isRequired,\n labelWidth: PropTypes.string.isRequired,\n liveUpdate: PropTypes.bool.isRequired,\n onUpdate: PropTypes.func.isRequired\n };\n\n static defaultProps = {\n className: null,\n style: null,\n path: null\n };\n\n constructor() {\n super();\n this.state = {\n defaultPreset: null,\n options: null\n };\n }\n\n static getDerivedStateFromProps(nextProps, prevState) {\n const nextValue = cloneDeep(nextProps.data);\n const defaultPreset = prevState.defaultPreset\n ? prevState.defaultPreset\n : nextValue;\n\n return {\n defaultPreset,\n options: [\n { [DEFAULT_PRESET_KEY]: defaultPreset },\n ...nextProps.options.filter(preset => {\n return Object.keys(preset)[0] !== DEFAULT_PRESET_KEY;\n })\n ]\n };\n }\n\n handleChange = event => {\n const value = JSON.parse(event.target.value);\n const { liveUpdate, onUpdate } = this.props;\n\n if (liveUpdate) onUpdate(value);\n };\n\n render() {\n const { path, label, labelWidth, className, style } = this.props;\n const { options } = this.state;\n const labelText = isString(label) ? label : path;\n\n return (\n
  • \n \n
  • \n );\n }\n}\n","import React, { Component, cloneElement } from 'react';\nimport PropTypes from 'prop-types';\nimport cloneDeep from 'lodash.clonedeep';\nimport cx from 'classnames';\nimport isUndefined from 'lodash.isundefined';\nimport set from 'lodash.set';\nimport './style/dat.scss';\n\nexport default class DatGui extends Component {\n static propTypes = {\n data: PropTypes.object.isRequired,\n children: PropTypes.node.isRequired,\n onUpdate: PropTypes.func.isRequired,\n liveUpdate: PropTypes.bool,\n labelWidth: PropTypes.string,\n className: PropTypes.string,\n style: PropTypes.object\n };\n\n static defaultProps = {\n liveUpdate: true,\n className: null,\n style: null,\n labelWidth: '40%'\n };\n\n handleUpdateValue = (path, value) => {\n const { data, onUpdate } = this.props;\n const dataUpdated = set(cloneDeep(data), path, value);\n\n onUpdate(dataUpdated);\n };\n\n renderChildren() {\n const { children, data } = this.props;\n\n return React.Children.toArray(children).map((child, i) => {\n const liveUpdate = isUndefined(child.props.liveUpdate)\n ? this.props.liveUpdate\n : child.props.liveUpdate;\n const labelWidth = isUndefined(child.props.labelWidth)\n ? this.props.labelWidth\n : child.props.labelWidth;\n\n return cloneElement(child, {\n key: i,\n data,\n liveUpdate,\n labelWidth,\n _onUpdateValue: this.handleUpdateValue\n });\n });\n }\n\n render() {\n const { style, className } = this.props;\n const classNames = cx('react-dat-gui', className);\n\n return (\n
    \n
      {this.renderChildren()}
    \n
    \n );\n }\n}\n\nexport { default as DatString } from './components/DatString';\nexport { default as DatNumber } from './components/DatNumber';\nexport { default as DatBoolean } from './components/DatBoolean';\nexport { default as DatButton } from './components/DatButton';\nexport { default as DatFolder } from './components/DatFolder';\nexport { default as DatSelect } from './components/DatSelect';\nexport { default as DatColor } from './components/DatColor';\nexport { default as DatPresets } from './components/DatPresets';\n"],"names":["DatString","event","value","target","liveUpdate","props","update","document","addEventListener","handleKeyDown","removeEventListener","window","getSelection","removeAllRanges","key","keyCode","which","state","_onUpdateValue","onUpdate","path","label","labelWidth","className","style","labelText","isString","cx","width","handleChange","handleFocus","handleBlur","nextProps","prevState","nextValue","result","data","Component","toNumber","float","parseFloat","isNaN","isInteger","Number","isFinite","Math","floor","Slider","pageX","handleMouseMove","handleMouseUp","preventDefault","sliderRef","React","createRef","isLive","min","max","rect","current","getBoundingClientRect","x","left","w","right","clamp","setState","widthBackground","sliderStyles","backgroundSize","handleClick","handleMouseDown","applyConstraints","step","hasMin","hasMax","hasStep","decimalPlaces","toString","split","length","isMin","isMax","round","toFixed","DatNumber","handleSliderUpdate","disableSlider","hasSlider","controlsWidth","inputWidth","sliderWidth","display","renderSlider","DatBoolean","checked","DatButton","onClick","defaultProps","DatFolder","closed","children","title","rest","Children","map","child","cloneElement","renderChildren","DatSelect","options","optionLabels","item","index","Fields","e","onChange","color","isValidHex","hex","source","Pointer","PointerCircle","Picker","hsl","hsv","disableAlpha","ColorWrap","DatColor","displayColorPicker","handleCloseColorPicker","handleChangeColor","borderLeftColor","backgroundColor","handleClickColorPicker","renderPicker","DEFAULT_PRESET_KEY","DatPresets","JSON","parse","defaultPreset","preset","Object","keys","stringify","cloneDeep","filter","DatGui","dataUpdated","set","toArray","i","isUndefined","handleUpdateValue","classNames"],"mappings":"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"} --------------------------------------------------------------------------------