]> git.wincent.com - hextrapolate.git/blob - src/Field.react.js
4cd7d470daceadb0e0ffb0b118f8fcc3ffcbf51f
[hextrapolate.git] / src / Field.react.js
1 /**
2  * Copyright 2015-present Greg Hurrell. All rights reserved.
3  * Licensed under the terms of the MIT license.
4  *
5  * @flow
6  */
7
8 'use strict';
9
10 import React from 'react';
11 import convert from './convert';
12
13 const DIGITS = '0123456789abcdef';
14
15 /**
16  * Convert from canonical (hexadecimal) value to `base`.
17  */
18 function fromValue(value: string, base: number): string {
19   if (value === null) {
20     return '';
21   }
22   if (base === 16) {
23     return value;
24   }
25   return convert(value, 16, base);
26 }
27
28 /**
29  * Convert from `base` value to canonical (hexadecimal) value.
30  */
31 function toValue(value: string, base: number): ?string {
32   if (value === '') {
33     return null;
34   }
35   if (base === 16) {
36     return value;
37   }
38   return convert(value, base, 16);
39 }
40
41 export default class Field extends React.Component {
42   static propTypes = {
43     base: React.PropTypes.number,
44     onValueChange: React.PropTypes.func.required,
45     value: React.PropTypes.string.required,
46   };
47   static defaultProps = {
48     base: 10,
49   };
50
51   constructor(props) {
52     super(props);
53     if (props.base < 2 || props.base > DIGITS.length) {
54       throw new Error(
55         `base prop must be between 2..${DIGITS.length}`
56       );
57     }
58   }
59
60   _isValid(value: string): boolean {
61     const validator = new RegExp(
62       `^[${DIGITS.slice(0, this.props.base)}]*$`
63     );
64     return validator.test(value.trim().toLowerCase());
65   }
66
67   _onChange = event => {
68     const value = event.currentTarget.value;
69     if (this._isValid(value)) {
70       this.props.onValueChange(toValue(value, this.props.base));
71     }
72   }
73
74   render() {
75     return (
76       <input
77         className="hextrapolate-input"
78         onChange={this._onChange}
79         type="text"
80         value={fromValue(this.props.value, this.props.base)}
81       />
82     );
83   }
84 }