]> git.wincent.com - hextrapolate.git/blob - src/App.js
3f7ccd6bce537d4cffaec2fae5570d5aa967db20
[hextrapolate.git] / src / App.js
1 /**
2  * Copyright 2003-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 DIGITS from './DIGITS';
11 import DynamicField from './DynamicField.react';
12 import Field from './Field.react';
13 import Label from './Label.react';
14 import React from 'react';
15 import Size from './Size.react';
16 import type Value from './Field.react';
17 import convert from './convert';
18 import debounce from 'simple-debounce';
19
20 import './App.css';
21
22 const SERIALIZATION_BASE = DIGITS.length;
23
24 const replaceHistoryState = debounce(
25   value => window.history.replaceState(
26     {},
27     '',
28     '#' + convert(value.value, value.base, SERIALIZATION_BASE)
29   ),
30   500
31 );
32
33 function getInitialValue() {
34   // Extract value from URL fragment, if present.
35   const value = window.location.hash.replace(/^#/, '');
36   const validator = new RegExp(`^[${DIGITS}]+$`);
37   if (!validator.test(value)) {
38     return null;
39   } else {
40     return {
41       base: SERIALIZATION_BASE,
42       value,
43     };
44   }
45 }
46
47 export default class App extends React.Component {
48   constructor(props) {
49     super(props);
50     this.state = {
51       value: getInitialValue(),
52     };
53   }
54
55   _onValueChange = (value: Value) => {
56     this.setState({value});
57     replaceHistoryState(value);
58   }
59
60   componentDidMount() {
61     this._firstInput.focus();
62   }
63
64   render() {
65     const {value} = this.state;
66
67     return (
68       <div className="hextrapolate">
69         <h1>
70           Hextrapolate &mdash; <Size value={value} />
71         </h1>
72         <Label text="Hexadecimal">
73           <Field
74             base={16}
75             onValueChange={this._onValueChange}
76             ref={ref => this._firstInput = ref}
77             value={value}
78           />
79         </Label>
80         <Label text="Decimal">
81           <Field
82             onValueChange={this._onValueChange}
83             value={value}
84           />
85         </Label>
86         <Label text="Octal">
87           <Field
88             base={8}
89             onValueChange={this._onValueChange}
90             value={value}
91           />
92         </Label>
93         <Label text="Binary">
94           <Field
95             base={2}
96             onValueChange={this._onValueChange}
97             value={value}
98           />
99         </Label>
100         <DynamicField
101           initialBase={32}
102           value={value}
103           onValueChange={this._onValueChange}
104         />
105         <DynamicField
106           initialBase={36}
107           value={value}
108           onValueChange={this._onValueChange}
109         />
110         <footer className="hextrapolate-footer">
111           <a href="mailto:greg@hurrell.net">Contact</a>
112           {' | '}
113           <a href="https://github.com/wincent/hextrapolate">Source</a>
114         </footer>
115       </div>
116     );
117   }
118 }