react-thailand-address-input 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,82 @@
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+
7
+ var _recompose = require('recompose');
8
+
9
+ var _react = require('react');
10
+
11
+ var _react2 = _interopRequireDefault(_react);
12
+
13
+ var _Typeahead = require('./Typeahead.component');
14
+
15
+ var _Typeahead2 = _interopRequireDefault(_Typeahead);
16
+
17
+ var _finder = require('./finder');
18
+
19
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
20
+
21
+ var AddressTypeaheadComponent = function AddressTypeaheadComponent(props) {
22
+ var searchStr = props.searchStr,
23
+ setSearchStr = props.setSearchStr,
24
+ fieldType = props.fieldType,
25
+ options = props.options,
26
+ className = props.className,
27
+ placeholder = props.placeholder,
28
+ maxVisible = props.maxVisible;
29
+
30
+ if (!fieldType) {
31
+ console.warn('No field type provide');
32
+ return _react2.default.createElement('div', null);
33
+ }
34
+ return _react2.default.createElement(_Typeahead2.default, {
35
+ displayOption: props.renderResult,
36
+ filterOption: fieldType,
37
+ className: className,
38
+ placeholder: placeholder,
39
+ options: options,
40
+ maxVisible: maxVisible,
41
+ value: searchStr,
42
+ onChange: function onChange(e) {
43
+ return setSearchStr(e.target.value);
44
+ },
45
+ onOptionSelected: function onOptionSelected(option) {
46
+ return props.onOptionSelected(option);
47
+ }
48
+ });
49
+ };
50
+
51
+ var AddressTypeahead = (0, _recompose.compose)((0, _recompose.withState)('searchStr', 'setSearchStr', function (_ref) {
52
+ var value = _ref.value;
53
+ return value;
54
+ }), (0, _recompose.lifecycle)({
55
+ componentWillReceiveProps: function componentWillReceiveProps(nextProps) {
56
+ if (nextProps.value !== this.props.value) {
57
+ this.props.setSearchStr(nextProps.value);
58
+ }
59
+ }
60
+ }), (0, _recompose.withProps)(function (_ref2) {
61
+ var searchStr = _ref2.searchStr,
62
+ fieldType = _ref2.fieldType;
63
+ return {
64
+ options: (0, _finder.resolveResultbyField)(fieldType, searchStr)
65
+ };
66
+ }), (0, _recompose.defaultProps)({
67
+ renderResult: function renderResult(data) {
68
+ return _react2.default.createElement(
69
+ 'span',
70
+ null,
71
+ data.d + ' \xBB ' + data.a + ' \xBB ' + data.p + ' \xBB ',
72
+ data.z || _react2.default.createElement(
73
+ 'li',
74
+ null,
75
+ 'ไม่มีรหัสไปรษณีย์'
76
+ )
77
+ );
78
+ },
79
+ value: ''
80
+ }))(AddressTypeaheadComponent);
81
+
82
+ exports.default = AddressTypeahead;
@@ -0,0 +1,66 @@
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+
7
+ var _react = require('react');
8
+
9
+ var _react2 = _interopRequireDefault(_react);
10
+
11
+ var _recompose = require('recompose');
12
+
13
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
14
+
15
+ var Typeahead = (0, _recompose.compose)((0, _recompose.defaultProps)({
16
+ onChange: function onChange() {},
17
+ option: [],
18
+ maxVisible: 10
19
+ }), (0, _recompose.withState)('open', 'setOpen', false))(function (props) {
20
+ return _react2.default.createElement(
21
+ 'div',
22
+ { className: 'typeahead typeahead-input-wrap' },
23
+ _react2.default.createElement('input', {
24
+ onBlur: function onBlur() {
25
+ return setTimeout(function () {
26
+ return props.setOpen(false);
27
+ }, 400);
28
+ },
29
+ onFocus: function onFocus() {
30
+ return props.setOpen(true);
31
+ },
32
+ type: 'text', value: props.value,
33
+ placeholder: props.placeholder,
34
+ onChange: props.onChange,
35
+ className: props.className
36
+ }),
37
+ props.options.length && props.value.length ? _react2.default.createElement('input', {
38
+ onChange: function onChange() {
39
+ return null;
40
+ },
41
+ value: props.options[0][props.filterOption],
42
+ type: 'text', className: 'typeahead-input-hint'
43
+ }) : null,
44
+ props.open && props.options.length && props.value.length ? _react2.default.createElement(
45
+ 'ul',
46
+ { className: 'typeahead-selector' },
47
+ props.options.filter(function (item, i) {
48
+ return i < props.maxVisible;
49
+ }).map(function (item, i) {
50
+ return _react2.default.createElement(
51
+ 'li',
52
+ {
53
+ key: i,
54
+ onClick: function onClick() {
55
+ props.onOptionSelected(item);
56
+ props.setOpen(false);
57
+ }
58
+ },
59
+ props.displayOption(item)
60
+ );
61
+ })
62
+ ) : null
63
+ );
64
+ });
65
+
66
+ exports.default = Typeahead;
package/dist/finder.js ADDED
@@ -0,0 +1,59 @@
1
+ 'use strict';
2
+
3
+ var JQL = require('jqljs');
4
+
5
+ var fieldsEnum = {
6
+ DISTRICT: 'd',
7
+ AMPHOE: 'a',
8
+ PROVINCE: 'p',
9
+ ZIPCODE: 'z'
10
+ };
11
+
12
+ /**
13
+ * From jquery.Thailand.js line 30 - 128
14
+ * Search result by FieldsType
15
+ */
16
+ var preprocess = function preprocess(data) {
17
+ if (!data[0].length) {
18
+ // non-compacted database
19
+ return data;
20
+ }
21
+ // compacted database in hierarchical form of:
22
+ // [["province",[["amphur",[["district",["zip"...]]...]]...]]...]
23
+ var expanded = [];
24
+ data.forEach(function (provinceEntry) {
25
+ var province = provinceEntry[0];
26
+ var amphurList = provinceEntry[1];
27
+ amphurList.forEach(function (amphurEntry) {
28
+ var amphur = amphurEntry[0];
29
+ var districtList = amphurEntry[1];
30
+ districtList.forEach(function (districtEntry) {
31
+ var district = districtEntry[0];
32
+ var zipCodeList = districtEntry[1];
33
+ zipCodeList.forEach(function (zipCode) {
34
+ expanded.push({
35
+ d: district,
36
+ a: amphur,
37
+ p: province,
38
+ z: zipCode
39
+ });
40
+ });
41
+ });
42
+ });
43
+ });
44
+ return expanded;
45
+ };
46
+ var DB = new JQL(preprocess(require('../data.json')));
47
+
48
+ var resolveResultbyField = function resolveResultbyField(type, searchStr) {
49
+ var possibles = [];
50
+ try {
51
+ possibles = DB.select('*').where(type).match('^' + searchStr).orderBy(type).fetch();
52
+ } catch (e) {
53
+ return [];
54
+ }
55
+ return possibles;
56
+ };
57
+
58
+ exports.resolveResultbyField = resolveResultbyField;
59
+ exports.fieldsEnum = fieldsEnum;
package/dist/index.js ADDED
@@ -0,0 +1,104 @@
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+
7
+ var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
8
+
9
+ var _react = require('react');
10
+
11
+ var _react2 = _interopRequireDefault(_react);
12
+
13
+ var _finder = require('./finder');
14
+
15
+ var _AddressTypeahead = require('./AddressTypeahead.component');
16
+
17
+ var _AddressTypeahead2 = _interopRequireDefault(_AddressTypeahead);
18
+
19
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
20
+
21
+ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
22
+
23
+ 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; }
24
+
25
+ function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
26
+
27
+ var AddressForm = function (_React$Component) {
28
+ _inherits(AddressForm, _React$Component);
29
+
30
+ function AddressForm(props) {
31
+ _classCallCheck(this, AddressForm);
32
+
33
+ var _this = _possibleConstructorReturn(this, (AddressForm.__proto__ || Object.getPrototypeOf(AddressForm)).call(this, props));
34
+
35
+ _this.state = {
36
+ addressObj: props.values
37
+ };
38
+ _this.setAddressObj = _this.setAddressObj.bind(_this);
39
+ return _this;
40
+ }
41
+
42
+ _createClass(AddressForm, [{
43
+ key: 'setAddressObj',
44
+ value: function setAddressObj(addressObj) {
45
+ this.setState({ addressObj: addressObj });
46
+ }
47
+ }, {
48
+ key: 'render',
49
+ value: function render() {
50
+ var _this2 = this;
51
+
52
+ var addressObj = this.state.addressObj;
53
+
54
+ return _react2.default.createElement(
55
+ 'div',
56
+ null,
57
+ Object.keys(_finder.fieldsEnum).map(function (key) {
58
+ var name = void 0;
59
+ switch (_finder.fieldsEnum[key]) {
60
+ case 'd':
61
+ name = 'ตำบล';break;
62
+ case 'a':
63
+ name = 'อำเภอ';break;
64
+ case 'p':
65
+ name = 'จังหวัด';break;
66
+ case 'z':
67
+ name = 'รหัสไปรษณีย์';break;
68
+ default:
69
+ name = '';break;
70
+ }
71
+ return _react2.default.createElement(
72
+ 'div',
73
+ { key: key, className: 'typeahead-address-container' },
74
+ _this2.props.showLabel ? _react2.default.createElement(
75
+ 'label',
76
+ { className: 'typeahead-address-label', htmlFor: 'district' },
77
+ name
78
+ ) : _react2.default.createElement('label', null),
79
+ _react2.default.createElement(_AddressTypeahead2.default, {
80
+ className: _this2.props.classNameInput,
81
+ placeholder: _this2.props.placeholder ? _this2.props.placeholder[_finder.fieldsEnum[key]] || '' : '',
82
+ renderResult: _this2.props.renderResult,
83
+ maxVisible: _this2.props.maxVisible,
84
+ onOptionSelected: function onOptionSelected(result) {
85
+ _this2.setAddressObj(result);
86
+ _this2.props.onAddressSelected(result);
87
+ },
88
+ value: addressObj ? addressObj[_finder.fieldsEnum[key]] : '',
89
+ fieldType: _finder.fieldsEnum[key]
90
+ })
91
+ );
92
+ })
93
+ );
94
+ }
95
+ }]);
96
+
97
+ return AddressForm;
98
+ }(_react2.default.Component);
99
+
100
+ AddressForm.defaultProps = {
101
+ maxVisible: 20
102
+ };
103
+
104
+ exports.default = AddressForm;
@@ -0,0 +1,49 @@
1
+ .typeahead-input-wrap {
2
+ position: relative;
3
+ width: 100%;
4
+ }
5
+ .typeahead input[type="text"], .typeahead-input-hint{
6
+ width: 100%;
7
+ box-sizing: border-box;
8
+ background: #fff;
9
+ color: #666;
10
+ border: 1px solid #e5e5e5;
11
+ padding: 8px 6px;
12
+ transition: 0.2s ease-in-out;
13
+ font-size: 16px;
14
+ transition-property: color, background-color, border;
15
+ }
16
+ .typeahead input[type="text"]:focus {
17
+ border-color: #1e87f0;
18
+ outline: none;
19
+ }
20
+
21
+ .typeahead-selector{
22
+ width: 100%;
23
+ border: 1px solid #eee;
24
+ border-top: none;
25
+ }
26
+ .typeahead ul {
27
+ padding: 0;
28
+ margin: 0;
29
+ }
30
+ .typeahead-selector li {
31
+ padding: 10px 5px;
32
+ background: #fff;
33
+ border-bottom: 1px solid #eee;
34
+ cursor: pointer;
35
+ }
36
+ .tt-cursor,
37
+ .typeahead-selector li:hover{
38
+ background: #f5f5f5;
39
+ }
40
+ .typeahead-input-hint {
41
+ opacity: 0.3 !important;
42
+ position: absolute;
43
+ width: 100%;
44
+ border: 1px solid rgba(0,0,0,0);
45
+ top:0;
46
+ left:0;
47
+ user-select: none;
48
+ pointer-events: none;
49
+ }
@@ -0,0 +1,38 @@
1
+ import React, { Component } from 'react';
2
+ import AddressForm from '../src/index';
3
+
4
+ class TestProps extends Component {
5
+ constructor(props) {
6
+ super(props);
7
+
8
+ this.onClick = this.onClick.bind(this);
9
+
10
+ this.state = {
11
+ address: { d: 'd', a: 'a', p: 'p', z: 123, }
12
+ }
13
+ }
14
+
15
+
16
+ onClick() {
17
+ const { address } = this.state;
18
+ address.d = "123666"
19
+ this.setState({
20
+ address: { }
21
+ })
22
+ }
23
+
24
+ render() {
25
+ const { address } = this.state;
26
+ return (
27
+ <div style={{ width: 400 }}>
28
+ <AddressForm
29
+ showLabel
30
+ maxVisible={40}
31
+ values={address}
32
+ />
33
+ <button onClick={this.onClick}>button</button>
34
+ </div>
35
+ );
36
+ }
37
+ }
38
+ export default TestProps;
@@ -0,0 +1,78 @@
1
+ import React from 'react';
2
+ import { storiesOf, action } from '@kadira/storybook';
3
+ import { withState } from 'recompose';
4
+ import AddressForm from '../src/index';
5
+
6
+ import '../src/styles.css';
7
+ import TestProps from './TestProps';
8
+
9
+ storiesOf('Component', module)
10
+ .add('montage', () => (
11
+ <div style={{ width: 350 }}>
12
+ <AddressForm onAddressSelected={action('onSelectedAdress')} />
13
+ <code>{'<AddressForm onAddressSelected={action(\'onSelectedAdress\')} />'}</code>
14
+ </div>
15
+ ))
16
+ .add('handle result', () => {
17
+ const WithStateComponent = withState('result', 'setResult', null)(({ result, setResult }) => (
18
+ <div style={{ width: 350 }}>
19
+ <div>
20
+ selected : {result ? `${result.p} ${result.a} ${result.d} ${result.z}` : null}
21
+ </div>
22
+ <AddressForm onAddressSelected={address => setResult(address)} />
23
+ </div>
24
+ ));
25
+ return (<div>
26
+ <WithStateComponent />
27
+ <code>
28
+ {`
29
+ <div style={{ width: 350 }}>
30
+ <div>
31
+ selected : {result ? \`\${result.p} \${result.a} \${result.d} \${result.z}\` : null}
32
+ </div>
33
+ <AddressForm onAddressSelected={address => setResult(address)} />
34
+ </div>
35
+ `}
36
+ </code>
37
+ </div>);
38
+ })
39
+ .add('custom render result', () => (
40
+ <TestProps />
41
+ ))
42
+ .add('custom initial', () => (
43
+ <div style={{ width: 350 }}>
44
+ <AddressForm
45
+ onAddressSelected={action('onSelectedAdress')}
46
+ values={{
47
+ d: "ฟากท่า", a: "ฟากท่า", p: "อุตรดิตถ์", z: 53161
48
+ }}
49
+ />
50
+ <code>{'<AddressForm onAddressSelected={action(\'onSelectedAdress\')} />'}</code>
51
+ </div>
52
+ ))
53
+ .add('show label', () => (
54
+ <div style={{ width: 350 }}>
55
+ <AddressForm
56
+ showLabel
57
+ onAddressSelected={action('onSelectedAdress')}
58
+ values={{
59
+ d: "ฟากท่า", a: "ฟากท่า", p: "อุตรดิตถ์", z: 53161
60
+ }}
61
+ />
62
+ <code>{'<AddressForm onAddressSelected={action(\'onSelectedAdress\')} />'}</code>
63
+ </div>
64
+ ))
65
+ .add('maxVisible', () => (
66
+ <div style={{ width: 350 }}>
67
+ <AddressForm
68
+ showLabel
69
+ maxVisible={40}
70
+ onAddressSelected={action('onSelectedAdress')}
71
+ values={{
72
+ d: "ฟากท่า", a: "ฟากท่า", p: "อุตรดิตถ์", z: 53160
73
+ }}
74
+ />
75
+ <code>{'<AddressForm onAddressSelected={action(\'onSelectedAdress\')} />'}</code>
76
+ </div>
77
+ ));
78
+
package/package.json ADDED
@@ -0,0 +1,68 @@
1
+ {
2
+ "name": "react-thailand-address-input",
3
+ "version": "1.1.0",
4
+ "main": "dist/index.js",
5
+ "repository": {
6
+ "url": "git@github.com:sangzn34/react-thailand-address-input.git",
7
+ "type": "git"
8
+ },
9
+ "scripts": {
10
+ "commit": "git-cz",
11
+ "release": "npm run build && standard-version",
12
+ "test": "jest",
13
+ "build": "babel src --out-dir dist --copy-files",
14
+ "webpack": "webpack",
15
+ "storybook": "start-storybook -p 9001 -c .storybook",
16
+ "export": "build-storybook -c .storybook -o .out"
17
+ },
18
+ "author": "Rungsikorn Rungsikavarnich <rungsikorn@me.com>",
19
+ "license": "MIT",
20
+ "devDependencies": {
21
+ "@kadira/storybook": "^2.35.3",
22
+ "babel-cli": "^6.24.1",
23
+ "babel-eslint": "^7.2.1",
24
+ "babel-loader": "^6.4.1",
25
+ "babel-plugin-transform-flow-strip-types": "^6.22.0",
26
+ "babel-preset-es2015": "^6.24.1",
27
+ "babel-preset-react": "^6.24.1",
28
+ "babili-webpack-plugin": "^0.0.11",
29
+ "commitizen": "^2.9.6",
30
+ "css-loader": "^0.28.0",
31
+ "cz-conventional-changelog": "^2.0.0",
32
+ "eslint": "^3.19.0",
33
+ "eslint-config-airbnb": "^14.1.0",
34
+ "eslint-config-clogii": "^1.0.1",
35
+ "eslint-plugin-flow-vars": "^0.5.0",
36
+ "eslint-plugin-flowtype": "^2.30.4",
37
+ "eslint-plugin-import": "^2.2.0",
38
+ "eslint-plugin-jsx-a11y": "^4.0.0",
39
+ "eslint-plugin-react": "^6.10.3",
40
+ "flow-remove-types": "^1.2.0",
41
+ "jest": "^19.0.2",
42
+ "json-loader": "^0.5.4",
43
+ "next": "^2.1.0",
44
+ "standard-version": "^4.0.0",
45
+ "style-loader": "^0.16.1",
46
+ "webpack": "^2.3.3",
47
+ "react": "15.4.0",
48
+ "react-dom": "15.5.3"
49
+ },
50
+ "config": {
51
+ "commitizen": {
52
+ "path": "./node_modules/cz-conventional-changelog"
53
+ }
54
+ },
55
+ "jest": {
56
+ "transform": {
57
+ "\\.js$": "./__test__/flow-type-strip.register.js"
58
+ }
59
+ },
60
+ "peerDependencies": {
61
+ "react": "15.4.0",
62
+ "react-dom": "15.5.3"
63
+ },
64
+ "dependencies": {
65
+ "jqljs": "^0.3.2",
66
+ "recompose": "0.23.0"
67
+ }
68
+ }