Skip to content

Commit 52822ae

Browse files
committed
feat: first commit 🔥
0 parents  commit 52822ae

15 files changed

+7709
-0
lines changed

.gitignore

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
# Logs
2+
*.log
3+
npm-debug.log
4+
yarn-error.log
5+
6+
# Runtime data
7+
tmp
8+
build
9+
dist
10+
11+
# Dependency directory
12+
node_modules
13+
14+
# Jest
15+
.jest/

.npmignore

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# Logs
2+
*.log
3+
npm-debug.log
4+
yarn-error.log
5+
6+
# Runtime data
7+
tmp
8+
9+
# Dependency directory
10+
node_modules
11+
12+
# Example
13+
example

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
# React Native Number Please

babel.config.js

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
module.exports = {
2+
presets: ["module:metro-react-native-babel-preset"],
3+
plugins: [
4+
[
5+
"module-resolver",
6+
{
7+
root: ["./src"],
8+
extensions: [".js", ".ts", ".tsx", ".ios.js", ".android.js"],
9+
},
10+
],
11+
"@babel/plugin-transform-runtime",
12+
],
13+
env: {
14+
production: {
15+
plugins: ["transform-remove-console"],
16+
},
17+
},
18+
};

index.interface.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
"use strict";
2+
Object.defineProperty(exports, "__esModule", { value: true });

index.interface.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
export interface IDigits {
2+
id: string;
3+
label?: string;
4+
min: number;
5+
max: number;
6+
step?: number;
7+
}
8+
9+
export interface INumberPleaseProps {
10+
digits: IDigits[];
11+
values: object[];
12+
// format: any;
13+
onChange(value: any): any;
14+
divider?: any;
15+
pickerStyle?: {};
16+
itemStyle?: {};
17+
}

index.js

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
"use strict";
2+
var __assign = (this && this.__assign) || function () {
3+
__assign = Object.assign || function(t) {
4+
for (var s, i = 1, n = arguments.length; i < n; i++) {
5+
s = arguments[i];
6+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
7+
t[p] = s[p];
8+
}
9+
return t;
10+
};
11+
return __assign.apply(this, arguments);
12+
};
13+
var __rest = (this && this.__rest) || function (s, e) {
14+
var t = {};
15+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
16+
t[p] = s[p];
17+
if (s != null && typeof Object.getOwnPropertySymbols === "function")
18+
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
19+
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
20+
t[p[i]] = s[p[i]];
21+
}
22+
return t;
23+
};
24+
var __importDefault = (this && this.__importDefault) || function (mod) {
25+
return (mod && mod.__esModule) ? mod : { "default": mod };
26+
};
27+
Object.defineProperty(exports, "__esModule", { value: true });
28+
var react_1 = __importDefault(require("react"));
29+
var react_native_1 = require("react-native");
30+
var lodash_find_1 = __importDefault(require("lodash.find"));
31+
var lodash_findindex_1 = __importDefault(require("lodash.findindex"));
32+
var immer_1 = __importDefault(require("immer"));
33+
var range_1 = __importDefault(require("./src/utils/range"));
34+
var PickerFactory = function (_a) {
35+
var pickerProps = _a.pickerProps, selectedValue = _a.selectedValue, onChange = _a.onChange, pickerStyle = _a.pickerStyle, itemStyle = _a.itemStyle;
36+
var id = pickerProps.id, label = pickerProps.label, min = pickerProps.min, max = pickerProps.max;
37+
var numbers = range_1.default(min, max);
38+
return (react_1.default.createElement(react_native_1.Picker, { style: __assign({ height: "100%", width: 90 }, pickerStyle), selectedValue: selectedValue, onValueChange: function (value) { return onChange({ id: id, value: value }); }, itemStyle: itemStyle }, numbers.map(function (number, index) { return (react_1.default.createElement(react_native_1.Picker.Item, { key: id + "-" + number + "-" + index, value: number, label: number + " " + label })); })));
39+
};
40+
var NumberPlease = function (_a) {
41+
var digits = _a.digits, values = _a.values, onChange = _a.onChange, rest = __rest(_a, ["digits", "values", "onChange"]);
42+
var onChangeHandle = function (value) {
43+
var nextValues = immer_1.default(values, function (draft) {
44+
var index = lodash_findindex_1.default(draft, { id: value.id });
45+
draft[index] = value;
46+
});
47+
onChange(nextValues);
48+
};
49+
return (react_1.default.createElement(react_native_1.View, { style: styles.container }, digits.map(function (picker, index) {
50+
var value = lodash_find_1.default(values, { id: picker.id }).value;
51+
return (react_1.default.createElement(PickerFactory, __assign({ key: picker.id + "-picker-" + index, pickerProps: picker, selectedValue: value, onChange: onChangeHandle }, rest)));
52+
})));
53+
};
54+
var styles = react_native_1.StyleSheet.create({
55+
container: {
56+
flexDirection: "row",
57+
width: "100%",
58+
justifyContent: "center",
59+
alignItems: "center",
60+
},
61+
});
62+
exports.default = NumberPlease;

index.tsx

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
import React, { FC } from "react";
2+
import { View, Picker, StyleSheet } from "react-native";
3+
import find from "lodash.find";
4+
import findIndex from "lodash.findindex";
5+
import produce from "immer";
6+
import range from "./src/utils/range";
7+
import { INumberPleaseProps } from "./index.interface";
8+
9+
const PickerFactory: FC<any> = ({
10+
pickerProps,
11+
selectedValue,
12+
onChange,
13+
pickerStyle,
14+
itemStyle,
15+
}: any) => {
16+
const { id, label, min, max } = pickerProps;
17+
const numbers = range(min, max);
18+
19+
return (
20+
<Picker
21+
style={{ height: "100%", width: 90, ...pickerStyle }}
22+
selectedValue={selectedValue}
23+
onValueChange={(value: any) => onChange({ id, value })}
24+
itemStyle={itemStyle}
25+
>
26+
{numbers.map((number, index) => (
27+
<Picker.Item
28+
key={`${id}-${number}-${index}`}
29+
value={number}
30+
label={`${number} ${label}`}
31+
/>
32+
))}
33+
</Picker>
34+
);
35+
};
36+
37+
const NumberPlease: FC<INumberPleaseProps> = ({
38+
digits,
39+
values,
40+
onChange,
41+
...rest
42+
}: any) => {
43+
const onChangeHandle = (value: any) => {
44+
const nextValues = produce(values, (draft: any) => {
45+
const index = findIndex(draft, { id: value.id });
46+
draft[index] = value;
47+
});
48+
49+
onChange(nextValues);
50+
};
51+
52+
return (
53+
<View style={styles.container}>
54+
{digits.map((picker: any, index: any) => {
55+
const { value }: any = find(values, { id: picker.id });
56+
return (
57+
<PickerFactory
58+
key={`${picker.id}-picker-${index}`}
59+
pickerProps={picker}
60+
selectedValue={value}
61+
onChange={onChangeHandle}
62+
{...rest}
63+
/>
64+
);
65+
})}
66+
</View>
67+
);
68+
};
69+
70+
const styles = StyleSheet.create({
71+
container: {
72+
flexDirection: "row",
73+
width: "100%",
74+
justifyContent: "center",
75+
alignItems: "center",
76+
},
77+
});
78+
79+
export default NumberPlease;

jest.config.js

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
module.exports = {
2+
preset: "react-native",
3+
moduleFileExtensions: ["ts", "tsx", "js", "jsx", "json"],
4+
testRegex: "(/__tests__/.*|(\\.|/)(test|spec))\\.(js|ts)x?$",
5+
transform: {
6+
"^.+\\.(js|tsx?)$":
7+
"<rootDir>/node_modules/react-native/jest/preprocessor.js",
8+
},
9+
testPathIgnorePatterns: ["\\.snap$", "<rootDir>/node_modules/"],
10+
cacheDirectory: ".jest/cache",
11+
transformIgnorePatterns: [
12+
"node_modules/(?!(react-native|react-navigation|react-navigation-tabs|react-navigation-redux-helpers|react-native-safari-view|react-native-linear-gradient|react-native-blur|react-native-animatable|react-native-wkwebview-reborn|react-native-safe-area-view|react-native-popup-menu|redux-persist)/)",
13+
],
14+
setupFiles: ["./__mocks__/react-native.js"],
15+
};

package.json

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
{
2+
"name": "react-native-number-please",
3+
"version": "1.0.2",
4+
"description": "React Native number picker",
5+
"main": "dist/index.js",
6+
"types": "dist/index.d.ts",
7+
"files": [
8+
"./dist"
9+
],
10+
"scripts": {
11+
"build": "tsc",
12+
"test": "echo \"Error: no test specified\" && exit 1"
13+
},
14+
"repository": {
15+
"type": "git",
16+
"url": "git+https://github.com/thebiltheory/react-native-number-please.git"
17+
},
18+
"keywords": [
19+
"react-native",
20+
"number",
21+
"picker",
22+
"digit",
23+
"dropdown"
24+
],
25+
"author": "Bil Benhamou <bil@thebiltheory.com>",
26+
"license": "MIT",
27+
"bugs": {
28+
"url": "https://github.com/thebiltheory/react-native-number-please/issues"
29+
},
30+
"homepage": "https://github.com/thebiltheory/react-native-number-please#readme",
31+
"peerDependencies": {
32+
"react": "*",
33+
"react-native": "*"
34+
},
35+
"devDependencies": {
36+
"@types/jest": "^25.2.1",
37+
"@types/lodash.find": "^4.6.6",
38+
"@types/lodash.findindex": "^4.6.6",
39+
"@types/react": "^16.9.32",
40+
"@types/react-native": "^0.62.2",
41+
"@types/react-test-renderer": "^16.9.2",
42+
"microbundle": "^0.11.0",
43+
"prettier": "^2.0.4",
44+
"react": "^16.13.1",
45+
"react-addons-test-utils": "^15.6.2",
46+
"react-native": "^0.62.1",
47+
"react-native-typescript-transformer": "^1.2.13",
48+
"ts-jest": "^25.3.1",
49+
"typescript": "^3.8.3"
50+
},
51+
"dependencies": {
52+
"immer": "^6.0.3",
53+
"lodash.find": "^4.6.0",
54+
"lodash.findindex": "^4.6.0"
55+
},
56+
"jest": {
57+
"preset": "react-native",
58+
"moduleFileExtensions": [
59+
"ts",
60+
"tsx",
61+
"js"
62+
],
63+
"transform": {
64+
"^.+\\.(js)$": "<rootDir>/node_modules/babel-jest",
65+
"\\.(ts|tsx)$": "<rootDir>/node_modules/ts-jest/preprocessor.js"
66+
},
67+
"testRegex": "(/__tests__/.*|\\.(test|spec))\\.(ts|tsx|js)$",
68+
"testPathIgnorePatterns": [
69+
"\\.snap$",
70+
"<rootDir>/node_modules/"
71+
],
72+
"cacheDirectory": ".jest/cache"
73+
}
74+
}

rn-cli.config.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
module.exports = {
2+
getTransformModulePath() {
3+
return require.resolve("react-native-typescript-transformer");
4+
},
5+
getSourceExts() {
6+
return ["ts", "tsx"];
7+
},
8+
};

src/utils/range.js

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
"use strict";
2+
Object.defineProperty(exports, "__esModule", { value: true });
3+
function range(start, end, step) {
4+
if (step === void 0) { step = 1; }
5+
// Test that the first 3 arguments are finite numbers.
6+
// Using Array.prototype.every() and Number.isFinite().
7+
var allNumbers = [start, end, step].every(Number.isFinite);
8+
// Throw an error if any of the first 3 arguments is not a finite number.
9+
if (!allNumbers) {
10+
throw new TypeError("range() expects only finite numbers as arguments.");
11+
}
12+
// Ensure the step is always a positive number.
13+
if (step <= 0) {
14+
throw new Error("step must be a number greater than 0.");
15+
}
16+
// When the start number is greater than the end number,
17+
// modify the step for decrementing instead of incrementing.
18+
if (start > end) {
19+
step = -step;
20+
}
21+
// Determine the length of the array to be returned.
22+
// The length is incremented by 1 after Math.floor().
23+
// This ensures that the end number is listed if it falls within the range.
24+
var length = Math.floor(Math.abs((end - start) / step)) + 1;
25+
// Fill up a new array with the range numbers
26+
// using Array.from() with a mapping function.
27+
// Finally, return the new array.
28+
return Array.from(Array(length), function (x, index) { return start + index * step; });
29+
}
30+
exports.default = range;

src/utils/range.ts

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
export default function range(start: number, end: number, step = 1) {
2+
// Test that the first 3 arguments are finite numbers.
3+
// Using Array.prototype.every() and Number.isFinite().
4+
const allNumbers = [start, end, step].every(Number.isFinite);
5+
6+
// Throw an error if any of the first 3 arguments is not a finite number.
7+
if (!allNumbers) {
8+
throw new TypeError("range() expects only finite numbers as arguments.");
9+
}
10+
11+
// Ensure the step is always a positive number.
12+
if (step <= 0) {
13+
throw new Error("step must be a number greater than 0.");
14+
}
15+
16+
// When the start number is greater than the end number,
17+
// modify the step for decrementing instead of incrementing.
18+
if (start > end) {
19+
step = -step;
20+
}
21+
22+
// Determine the length of the array to be returned.
23+
// The length is incremented by 1 after Math.floor().
24+
// This ensures that the end number is listed if it falls within the range.
25+
const length = Math.floor(Math.abs((end - start) / step)) + 1;
26+
27+
// Fill up a new array with the range numbers
28+
// using Array.from() with a mapping function.
29+
// Finally, return the new array.
30+
return Array.from(Array(length), (x, index) => start + index * step);
31+
}

0 commit comments

Comments
 (0)