Skip to content
This repository was archived by the owner on May 15, 2022. It is now read-only.

Commit bbb689a

Browse files
Merge pull request #13 from rohan-deshpande/master
Better support for floats
2 parents 3bf9b23 + d1724d7 commit bbb689a

22 files changed

+199
-74
lines changed

README.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,8 @@ A number component for updating numeric values. Will render a slider if `min`, `
181181
* `max: number` - The maximum range for the number
182182
* `step: number` - The amount the number should increment each tick
183183
184+
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.
185+
184186
#### `DatPresets`
185187
186188
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.
@@ -195,7 +197,7 @@ Each item in this array will need to be in the format `{ 'presetName': ...data,
195197
196198
#### `DatSelect`
197199
198-
A select component for updating a value with one of the options supplied via the `options` prop. The original value from the `path` will always be added to the passed options array as the first item.
200+
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.
199201
200202
##### props
201203

build/react-dat-gui.css

Lines changed: 4 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

build/react-dat-gui.js

Lines changed: 37 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -4794,6 +4794,17 @@ function toNumber(value) {
47944794
return isNaN(float) ? 0 : float;
47954795
}
47964796

4797+
/**
4798+
* Polyfill for isInteger.
4799+
*
4800+
* @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/isInteger#Polyfill
4801+
* @param {number} value
4802+
* @return {bool}
4803+
*/
4804+
var isInteger = exports.isInteger = Number.isInteger || function (value) {
4805+
return typeof value === 'number' && isFinite(value) && Math.floor(value) === value;
4806+
};
4807+
47974808
/***/ }),
47984809
/* 53 */
47994810
/***/ (function(module, exports, __webpack_require__) {
@@ -6537,6 +6548,8 @@ var _react = __webpack_require__(0);
65376548

65386549
var _react2 = _interopRequireDefault(_react);
65396550

6551+
var _utils = __webpack_require__(52);
6552+
65406553
var _propTypes = __webpack_require__(2);
65416554

65426555
var _propTypes2 = _interopRequireDefault(_propTypes);
@@ -6557,8 +6570,6 @@ var _lodash5 = __webpack_require__(12);
65576570

65586571
var _lodash6 = _interopRequireDefault(_lodash5);
65596572

6560-
var _utils = __webpack_require__(52);
6561-
65626573
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
65636574

65646575
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
@@ -6639,6 +6650,8 @@ var DatNumber = function (_Component) {
66396650
hasMin = _ref2[0],
66406651
hasMax = _ref2[1],
66416652
hasStep = _ref2[2];
6653+
6654+
var decimalPlaces = hasStep && !(0, _utils.isInteger)(step) ? step.toString().split('.')[1].length : 0;
66426655
var isMin = false,
66436656
isMax = false;
66446657

@@ -6661,16 +6674,22 @@ var DatNumber = function (_Component) {
66616674
}
66626675
}
66636676

6664-
return value;
6677+
return value.toFixed(decimalPlaces);
66656678
}
6679+
6680+
/**
6681+
* @deprecated This has been deprecated for now and is no longer applied to the
6682+
* component onBlur.
6683+
*/
6684+
66666685
}, {
66676686
key: 'update',
66686687
value: function update() {
66696688
var value = this.state.value;
66706689

66716690

6672-
this.props._onUpdateValue && this.props._onUpdateValue(this.props.path, value);
6673-
this.props.onUpdate && this.props.onUpdate(value);
6691+
this.props._onUpdateValue && this.props._onUpdateValue(this.props.path, (0, _utils.toNumber)(value));
6692+
this.props.onUpdate && this.props.onUpdate((0, _utils.toNumber)(value));
66746693
}
66756694
}, {
66766695
key: 'renderSlider',
@@ -6697,12 +6716,14 @@ var DatNumber = function (_Component) {
66976716
max = _props3.max,
66986717
path = _props3.path,
66996718
label = _props3.label,
6700-
labelWidth = _props3.labelWidth;
6719+
labelWidth = _props3.labelWidth,
6720+
step = _props3.step,
6721+
disableSlider = _props3.disableSlider;
67016722

67026723
var labelText = (0, _lodash4.default)(label) ? label : path;
67036724
var hasSlider = (0, _lodash2.default)(min) && (0, _lodash2.default)(max);
67046725
var controlsWidth = 100 - labelWidth;
6705-
var inputWidth = hasSlider ? Math.round(controlsWidth / 3) : controlsWidth;
6726+
var inputWidth = hasSlider && disableSlider !== true ? Math.round(controlsWidth / 3) : controlsWidth;
67066727
var sliderWidth = controlsWidth - inputWidth;
67076728

67086729
return _react2.default.createElement(
@@ -6716,15 +6737,17 @@ var DatNumber = function (_Component) {
67166737
{ className: 'label-text', style: { width: labelWidth + '%' } },
67176738
labelText
67186739
),
6719-
hasSlider ? this.renderSlider(sliderWidth) : null,
6740+
hasSlider && disableSlider !== true ? this.renderSlider(sliderWidth) : null,
67206741
_react2.default.createElement('input', {
67216742
type: 'number',
6743+
step: step,
6744+
min: min,
6745+
max: max,
67226746
inputMode: 'numeric',
67236747
value: this.state.value,
67246748
style: { width: inputWidth + '%' },
67256749
onChange: this.handleChange,
6726-
onFocus: this.handleFocus,
6727-
onBlur: this.handleBlur
6750+
onFocus: this.handleFocus
67286751
})
67296752
)
67306753
);
@@ -6744,7 +6767,8 @@ DatNumber.propTypes = {
67446767
labelWidth: _propTypes2.default.number,
67456768
liveUpdate: _propTypes2.default.bool,
67466769
onUpdate: _propTypes2.default.func,
6747-
_onUpdateValue: _propTypes2.default.func
6770+
_onUpdateValue: _propTypes2.default.func,
6771+
disableSlider: _propTypes2.default.bool
67486772
};
67496773
exports.default = DatNumber;
67506774
module.exports = exports['default'];
@@ -6930,8 +6954,6 @@ var _lodash4 = _interopRequireDefault(_lodash3);
69306954

69316955
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
69326956

6933-
function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }
6934-
69356957
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
69366958

69376959
function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
@@ -6953,8 +6975,8 @@ var DatSelect = function (_Component) {
69536975
}
69546976

69556977
return _ret = (_temp = (_this = _possibleConstructorReturn(this, (_ref = DatSelect.__proto__ || Object.getPrototypeOf(DatSelect)).call.apply(_ref, [this].concat(args))), _this), _this.state = {
6956-
value: '',
6957-
options: [_this.getValue()].concat(_toConsumableArray(_this.props.options))
6978+
value: _this.getValue(),
6979+
options: _this.props.options
69586980
}, _this.handleChange = function (event) {
69596981
var value = event.target.value;
69606982

build/react-dat-gui.js.map

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dev/src/App.js

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ class App extends Component {
1919
minMaxNumber: 66,
2020
number: 80,
2121
boolean: true,
22-
select: 'one',
22+
select: 'three',
2323
color: '#2FA1D6',
2424
random: Math.random(),
2525
nested: {
@@ -49,6 +49,7 @@ class App extends Component {
4949
string: 'Preset A',
5050
minMaxNumber: 33,
5151
number: 40,
52+
float: 0.001,
5253
boolean: false,
5354
select: 'one',
5455
color: '#e61d5f',
@@ -81,6 +82,12 @@ class App extends Component {
8182
<div>
8283
<b>Number value:</b> {data.number}
8384
</div>
85+
<div>
86+
<b>Number value is a string:</b> {(typeof data.number === 'string') ? 'true' : 'false'}
87+
</div>
88+
<div>
89+
<b>Float value:</b> {data.float}
90+
</div>
8491
<div>
8592
<b>Checkbox value:</b> {(data.boolean) ? 'true' : 'false'}
8693
</div>
@@ -102,6 +109,9 @@ class App extends Component {
102109
<DatString path="string" label="String" />
103110
<DatNumber path="minMaxNumber" label="Number" min={0} max={100} step={1} />
104111
<DatNumber path="number" label="Number" />
112+
<DatNumber path="float" label="Float" min={0} max={100} step={0.001} />
113+
<DatNumber path="float" label="Another Float" min={0} max={100} step={0.01} />
114+
<DatNumber path="float" label="Min Max No Slider" min={0} max={100} step={0.01} disableSlider={true} />
105115
<DatBoolean path="boolean" label="Boolean" />
106116
<DatButton label="Button" onClick={this.handleClick} />
107117
<DatSelect label="Select" path='select' options={['two', 'three', 'four']}/>

dev/src/react-dat-gui/components/DatNumber.js

Lines changed: 48 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
import React, { Component } from 'react';
2+
import { isInteger, toNumber } from './utils';
23

34
import PropTypes from 'prop-types';
45
import Slider from './Slider';
56
import isFinite from 'lodash.isfinite';
67
import isString from 'lodash.isstring';
78
import result from 'lodash.result';
8-
import { toNumber } from './utils';
99

1010
export default class DatNumber extends Component {
1111
static propTypes = {
@@ -19,11 +19,12 @@ export default class DatNumber extends Component {
1919
liveUpdate: PropTypes.bool,
2020
onUpdate: PropTypes.func,
2121
_onUpdateValue: PropTypes.func,
22+
disableSlider: PropTypes.bool
2223
};
2324

2425
state = {
25-
value: this.getValue(),
26-
}
26+
value: this.getValue()
27+
};
2728

2829
componentWillReceiveProps(nextProps) {
2930
this.setState({
@@ -37,8 +38,14 @@ export default class DatNumber extends Component {
3738

3839
applyConstraints(value) {
3940
const { min, max, step } = this.props;
40-
const [ hasMin, hasMax, hasStep ] = [ isFinite(min), isFinite(max), isFinite(step) ];
41-
let [ isMin, isMax ] = [ false, false ];
41+
const [hasMin, hasMax, hasStep] = [
42+
isFinite(min),
43+
isFinite(max),
44+
isFinite(step)
45+
];
46+
const decimalPlaces =
47+
hasStep && !isInteger(step) ? step.toString().split('.')[1].length : 0;
48+
let [isMin, isMax] = [false, false];
4249

4350
value = toNumber(value);
4451

@@ -58,25 +65,29 @@ export default class DatNumber extends Component {
5865
}
5966
}
6067

61-
return value;
68+
return value.toFixed(decimalPlaces);
6269
}
6370

6471
handleChange = event => {
6572
this.setState({ value: event.target.value }, this.update);
66-
}
73+
};
6774

6875
handleFocus = () => {
6976
document.addEventListener('keydown', this.handleKeyDown);
70-
}
77+
};
7178

79+
/**
80+
* @deprecated This has been deprecated for now and is no longer applied to the
81+
* component onBlur.
82+
*/
7283
handleBlur = event => {
7384
const value = this.applyConstraints(event.target.value);
7485

7586
document.removeEventListener('keydown', this.handleKeyDown);
7687
window.getSelection().removeAllRanges();
7788

7889
this.setState({ value }, this.update);
79-
}
90+
};
8091

8192
handleKeyDown = event => {
8293
const key = event.keyCode || event.which;
@@ -86,24 +97,25 @@ export default class DatNumber extends Component {
8697

8798
this.setState({ value }, this.update);
8899
}
89-
}
100+
};
90101

91102
handleSliderUpdate = (value, isLive) => {
92103
const constrained = this.applyConstraints(value);
93-
const shouldUpdate = (!isLive || this.props.liveUpdate);
104+
const shouldUpdate = !isLive || this.props.liveUpdate;
94105

95106
this.setState({ value: constrained }, () => {
96107
if (shouldUpdate) {
97108
this.update();
98109
}
99110
});
100-
}
111+
};
101112

102113
update() {
103114
const { value } = this.state;
104115

105-
this.props._onUpdateValue && this.props._onUpdateValue(this.props.path, value);
106-
this.props.onUpdate && this.props.onUpdate(value);
116+
this.props._onUpdateValue &&
117+
this.props._onUpdateValue(this.props.path, toNumber(value));
118+
this.props.onUpdate && this.props.onUpdate(toNumber(value));
107119
}
108120

109121
renderSlider(width) {
@@ -122,26 +134,43 @@ export default class DatNumber extends Component {
122134
}
123135

124136
render() {
125-
const { min, max, path, label, labelWidth } = this.props;
137+
const {
138+
min,
139+
max,
140+
path,
141+
label,
142+
labelWidth,
143+
step,
144+
disableSlider
145+
} = this.props;
126146
const labelText = isString(label) ? label : path;
127147
const hasSlider = isFinite(min) && isFinite(max);
128148
const controlsWidth = 100 - labelWidth;
129-
const inputWidth = hasSlider ? Math.round(controlsWidth / 3) : controlsWidth;
149+
const inputWidth =
150+
hasSlider && disableSlider !== true
151+
? Math.round(controlsWidth / 3)
152+
: controlsWidth;
130153
const sliderWidth = controlsWidth - inputWidth;
131154

132155
return (
133156
<li className="cr number">
134157
<label>
135-
<span className="label-text" style={{ width: `${labelWidth}%` }}>{labelText}</span>
136-
{hasSlider ? this.renderSlider(sliderWidth) : null}
158+
<span className="label-text" style={{ width: `${labelWidth}%` }}>
159+
{labelText}
160+
</span>
161+
{hasSlider && disableSlider !== true
162+
? this.renderSlider(sliderWidth)
163+
: null}
137164
<input
138165
type="number"
166+
step={step}
167+
min={min}
168+
max={max}
139169
inputMode="numeric"
140170
value={this.state.value}
141171
style={{ width: `${inputWidth}%` }}
142172
onChange={this.handleChange}
143173
onFocus={this.handleFocus}
144-
onBlur={this.handleBlur}
145174
/>
146175
</label>
147176
</li>

dev/src/react-dat-gui/components/DatSelect.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@ export default class DatSelect extends Component {
1717
};
1818

1919
state = {
20-
value: '',
21-
options: [this.getValue(), ...this.props.options],
20+
value: this.getValue(),
21+
options: this.props.options,
2222
}
2323

2424
componentWillReceiveProps(nextProps) {

0 commit comments

Comments
 (0)