From 2958ca11ecad9a44461ef7090d32c208d1fe2623 Mon Sep 17 00:00:00 2001 From: Tales Pereira Date: Sat, 11 Apr 2020 03:54:02 -0300 Subject: [PATCH 01/14] add deps + command --- package.json | 13 +++- yarn.lock | 163 +++++++++++++++++++++++++++++++++++++++++++-------- 2 files changed, 150 insertions(+), 26 deletions(-) diff --git a/package.json b/package.json index 608a43c..f017554 100644 --- a/package.json +++ b/package.json @@ -9,14 +9,21 @@ ], "homepage": "http://expo-ui-kit.com/", "description": "Expo.io UI Kit for React-Native", - "main": "index.js", + "main": "dist/index.js", + "types": "dist/index.d.ts", "author": "React-UI-Kit (https://react-ui-kit.com)", "license": "MIT", "scripts": { + "build": "tsc", "lint": "eslint src", "test": "jest" }, "devDependencies": { + "@types/enzyme": "^3.10.5", + "@types/enzyme-adapter-react-16": "^1.0.6", + "@types/jest": "^25.2.1", + "@types/react": "^16.9.34", + "@types/react-test-renderer": "^16.9.2", "enzyme": "^3.10.0", "enzyme-adapter-react-16": "^1.14.0", "eslint": "^6.5.0", @@ -28,9 +35,13 @@ "react-native": "https://github.com/expo/react-native/archive/sdk-37.0.1.tar.gz", "react-native-testing-library": "^1.13.0", "react-test-renderer": "^16.13.1", + "ts-jest": "^25.3.1", "typescript": "^3.8.3" }, "eslintConfig": { "extends": "universe/native" + }, + "dependencies": { + "@types/react-native": "^0.62.2" } } diff --git a/yarn.lock b/yarn.lock index 1b469b5..8d174c6 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1153,11 +1153,33 @@ dependencies: "@babel/types" "^7.3.0" +"@types/cheerio@*": + version "0.22.17" + resolved "https://registry.yarnpkg.com/@types/cheerio/-/cheerio-0.22.17.tgz#e54f71c3135f71ebc16c8dc62edad533872c9e72" + integrity sha512-izlm+hbqWN9csuB9GSMfCnAyd3/57XZi3rfz1B0C4QBGVMp+9xQ7+9KYnep+ySfUrCWql4lGzkLf0XmprXcz9g== + dependencies: + "@types/node" "*" + "@types/color-name@^1.1.1": version "1.1.1" resolved "https://registry.yarnpkg.com/@types/color-name/-/color-name-1.1.1.tgz#1c1261bbeaa10a8055bbc5d8ab84b7b2afc846a0" integrity sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ== +"@types/enzyme-adapter-react-16@^1.0.6": + version "1.0.6" + resolved "https://registry.yarnpkg.com/@types/enzyme-adapter-react-16/-/enzyme-adapter-react-16-1.0.6.tgz#8aca7ae2fd6c7137d869b6616e696d21bb8b0cec" + integrity sha512-VonDkZ15jzqDWL8mPFIQnnLtjwebuL9YnDkqeCDYnB4IVgwUm0mwKkqhrxLL6mb05xm7qqa3IE95m8CZE9imCg== + dependencies: + "@types/enzyme" "*" + +"@types/enzyme@*", "@types/enzyme@^3.10.5": + version "3.10.5" + resolved "https://registry.yarnpkg.com/@types/enzyme/-/enzyme-3.10.5.tgz#fe7eeba3550369eed20e7fb565bfb74eec44f1f0" + integrity sha512-R+phe509UuUYy9Tk0YlSbipRpfVtIzb/9BHn5pTEtjJTF5LXvUjrIQcZvNyANNEyFrd2YGs196PniNT1fgvOQA== + dependencies: + "@types/cheerio" "*" + "@types/react" "*" + "@types/eslint-visitor-keys@^1.0.0": version "1.0.0" resolved "https://registry.yarnpkg.com/@types/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz#1ee30d79544ca84d68d4b3cdb0af4f205663dd2d" @@ -1183,6 +1205,14 @@ "@types/istanbul-lib-coverage" "*" "@types/istanbul-lib-report" "*" +"@types/jest@^25.2.1": + version "25.2.1" + resolved "https://registry.yarnpkg.com/@types/jest/-/jest-25.2.1.tgz#9544cd438607955381c1bdbdb97767a249297db5" + integrity sha512-msra1bCaAeEdkSyA0CZ6gW1ukMIvZ5YoJkdXw/qhQdsuuDlFTcEUrUw8CLCPt2rVRUfXlClVvK2gvPs9IokZaA== + dependencies: + jest-diff "^25.2.1" + pretty-format "^25.2.1" + "@types/json-schema@^7.0.3": version "7.0.4" resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.4.tgz#38fd73ddfd9b55abb1e1b2ed578cb55bd7b7d339" @@ -1198,6 +1228,33 @@ resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-1.19.1.tgz#33509849f8e679e4add158959fdb086440e9553f" integrity sha512-5qOlnZscTn4xxM5MeGXAMOsIOIKIbh9e85zJWfBRVPlRMEVawzoPhINYbRGkBZCI8LxvBe7tJCdWiarA99OZfQ== +"@types/prop-types@*": + version "15.7.3" + resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.3.tgz#2ab0d5da2e5815f94b0b9d4b95d1e5f243ab2ca7" + integrity sha512-KfRL3PuHmqQLOG+2tGpRO26Ctg+Cq1E01D2DMriKEATHgWLfeNDmq9e29Q9WIky0dQ3NPkd1mzYH8Lm936Z9qw== + +"@types/react-native@^0.62.2": + version "0.62.2" + resolved "https://registry.yarnpkg.com/@types/react-native/-/react-native-0.62.2.tgz#f3e150f308c27089cefbcbfa3eb6cc14db279b2f" + integrity sha512-oIUIbqZNN9vRnGKWHYbTVp/GyTqdaM5mfy1s4zsi6BYvHAaFOPZ32IrhIHno/A5XOv4wuGfE7g5fliDk/H0+/Q== + dependencies: + "@types/react" "*" + +"@types/react-test-renderer@^16.9.2": + version "16.9.2" + resolved "https://registry.yarnpkg.com/@types/react-test-renderer/-/react-test-renderer-16.9.2.tgz#e1c408831e8183e5ad748fdece02214a7c2ab6c5" + integrity sha512-4eJr1JFLIAlWhzDkBCkhrOIWOvOxcCAfQh+jiKg7l/nNZcCIL2MHl2dZhogIFKyHzedVWHaVP1Yydq/Ruu4agw== + dependencies: + "@types/react" "*" + +"@types/react@*", "@types/react@^16.9.34": + version "16.9.34" + resolved "https://registry.yarnpkg.com/@types/react/-/react-16.9.34.tgz#f7d5e331c468f53affed17a8a4d488cd44ea9349" + integrity sha512-8AJlYMOfPe1KGLKyHpflCg5z46n0b5DbRfqDksxBLBTUpB75ypDBAO9eCUcjNwE6LCUslwTz00yyG/X9gaVtow== + dependencies: + "@types/prop-types" "*" + csstype "^2.2.0" + "@types/stack-utils@^1.0.1": version "1.0.1" resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-1.0.1.tgz#0a851d3bd96498fa25c33ab7278ed3bd65f06c3e" @@ -1831,6 +1888,13 @@ browser-resolve@^1.11.3: dependencies: resolve "1.1.7" +bs-logger@0.x: + version "0.2.6" + resolved "https://registry.yarnpkg.com/bs-logger/-/bs-logger-0.2.6.tgz#eb7d365307a72cf974cc6cda76b68354ad336bd8" + integrity sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog== + dependencies: + fast-json-stable-stringify "2.x" + bser@2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/bser/-/bser-2.1.1.tgz#e6787da20ece9d07998533cfd9de6f5c38f4bc05" @@ -1843,7 +1907,7 @@ buffer-crc32@^0.2.13: resolved "https://registry.yarnpkg.com/buffer-crc32/-/buffer-crc32-0.2.13.tgz#0d333e3f00eac50aa1454abd30ef8c2a5d9a7242" integrity sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI= -buffer-from@^1.0.0: +buffer-from@1.x, buffer-from@^1.0.0: version "1.1.1" resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef" integrity sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A== @@ -2176,9 +2240,9 @@ copy-descriptor@^0.1.0: integrity sha1-Z29us8OZl8LuGsOpJP1hJHSPV40= core-js-pure@^3.0.0: - version "3.6.4" - resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.6.4.tgz#4bf1ba866e25814f149d4e9aaa08c36173506e3a" - integrity sha512-epIhRLkXdgv32xIUFaaAry2wdxZYBi6bgM7cB136dzzXXa+dFyRLTZeLUJxnd8ShrmyVXBub63n2NHo2JAt8Cw== + version "3.6.5" + resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.6.5.tgz#c79e75f5e38dbc85a662d91eea52b8256d53b813" + integrity sha512-lacdXOimsiD0QyNf9BC/mxivNJ/ybBGJXQFKzRekp1WTHoVUWsUHEn+2T8GJAzzIhyOuXA+gOxCVN3l+5PLPUA== core-js@^1.0.0: version "1.2.7" @@ -2275,6 +2339,11 @@ cssstyle@^2.0.0: dependencies: cssom "~0.3.6" +csstype@^2.2.0: + version "2.6.10" + resolved "https://registry.yarnpkg.com/csstype/-/csstype-2.6.10.tgz#e63af50e66d7c266edb6b32909cfd0aabe03928b" + integrity sha512-D34BqZU4cIlMCY93rZHbrq9pjTAQJ3U8S8rfBqjwHxkGPThWFjzZDQpgMJY0QViLxth6ZKYiwFBo14RdN44U/w== + dashdash@^1.12.0: version "1.14.1" resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0" @@ -3053,7 +3122,7 @@ fast-diff@^1.1.2: resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.2.0.tgz#73ee11982d86caaf7959828d519cfe927fac5f03" integrity sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w== -fast-json-stable-stringify@^2.0.0: +fast-json-stable-stringify@2.x, fast-json-stable-stringify@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== @@ -4006,7 +4075,7 @@ jest-config@^25.3.0: pretty-format "^25.3.0" realpath-native "^2.0.0" -jest-diff@^25.3.0: +jest-diff@^25.2.1, jest-diff@^25.3.0: version "25.3.0" resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-25.3.0.tgz#0d7d6f5d6171e5dacde9e05be47b3615e147c26f" integrity sha512-vyvs6RPoVdiwARwY4kqFWd4PirPLm2dmmkNzKqo38uZOzJvLee87yzDjIZLmY1SjM3XR5DwsUH+cdQ12vgqi1w== @@ -4496,6 +4565,13 @@ json-stringify-safe@~5.0.1: resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" integrity sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus= +json5@2.x: + version "2.1.3" + resolved "https://registry.yarnpkg.com/json5/-/json5-2.1.3.tgz#c9b0f7fa9233bfe5807fe66fcf3a5617ed597d43" + integrity sha512-KXPvOm8K9IJKFM0bmdn8QXh7udDh1g/giieX0NLCaMnb4hEiVFqnop2ImTXCc5e0/oHz3LTqmHGtExn5hfMkOA== + dependencies: + minimist "^1.2.5" + json5@^2.1.0: version "2.1.1" resolved "https://registry.yarnpkg.com/json5/-/json5-2.1.1.tgz#81b6cb04e9ba496f1c7005d07b4368a2638f90b6" @@ -4656,6 +4732,11 @@ lodash.isequal@^4.5.0: resolved "https://registry.yarnpkg.com/lodash.isequal/-/lodash.isequal-4.5.0.tgz#415c4478f2bcc30120c22ce10ed3226f7d3e18e0" integrity sha1-QVxEePK8wwEgwizhDtMib30+GOA= +lodash.memoize@4.x: + version "4.1.2" + resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe" + integrity sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4= + lodash.sortby@^4.7.0: version "4.7.0" resolved "https://registry.yarnpkg.com/lodash.sortby/-/lodash.sortby-4.7.0.tgz#edd14c824e2cc9c1e0b0a1b42bb5210516a42438" @@ -4724,6 +4805,11 @@ make-dir@^3.0.0: dependencies: semver "^6.0.0" +make-error@1.x: + version "1.3.6" + resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2" + integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw== + makeerror@1.0.x: version "1.0.11" resolved "https://registry.yarnpkg.com/makeerror/-/makeerror-1.0.11.tgz#e01a5c9109f2af79660e4e8b9587790184f5a96c" @@ -4996,6 +5082,14 @@ metro@^0.56.0, metro@^0.56.4: xpipe "^1.0.5" yargs "^9.0.0" +micromatch@4.x, micromatch@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.2.tgz#4fcb0999bf9fbc2fcbdd212f6d629b9a56c39259" + integrity sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q== + dependencies: + braces "^3.0.1" + picomatch "^2.0.5" + micromatch@^3.1.10, micromatch@^3.1.4: version "3.1.10" resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-3.1.10.tgz#70859bc95c9840952f359a068a3fc49f9ecfac23" @@ -5015,14 +5109,6 @@ micromatch@^3.1.10, micromatch@^3.1.4: snapdragon "^0.8.1" to-regex "^3.0.2" -micromatch@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.2.tgz#4fcb0999bf9fbc2fcbdd212f6d629b9a56c39259" - integrity sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q== - dependencies: - braces "^3.0.1" - picomatch "^2.0.5" - mime-db@1.43.0, "mime-db@>= 1.43.0 < 2": version "1.43.0" resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.43.0.tgz#0a12e0502650e473d735535050e7c8f4eb4fae58" @@ -5084,6 +5170,11 @@ minimist@^1.1.1, minimist@^1.2.0: resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284" integrity sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ= +minimist@^1.2.5: + version "1.2.5" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602" + integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw== + mixin-deep@^1.2.0: version "1.3.2" resolved "https://registry.yarnpkg.com/mixin-deep/-/mixin-deep-1.3.2.tgz#1120b43dc359a785dce65b55b82e257ccf479566" @@ -5092,6 +5183,11 @@ mixin-deep@^1.2.0: for-in "^1.0.2" is-extendable "^1.0.1" +mkdirp@1.x: + version "1.0.4" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" + integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== + mkdirp@^0.5.1: version "0.5.1" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" @@ -5747,7 +5843,7 @@ pretty-format@^25.1.0: ansi-styles "^4.0.0" react-is "^16.12.0" -pretty-format@^25.3.0: +pretty-format@^25.2.1, pretty-format@^25.3.0: version "25.3.0" resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-25.3.0.tgz#d0a4f988ff4a6cd350342fdabbb809aeb4d49ad5" integrity sha512-wToHwF8bkQknIcFkBqNfKu4+UZqnrLn/Vr+wwKQwwvPzkBfDDKp/qIabFqdgtoi5PEnM8LFByVsOrHoa3SpTVA== @@ -6188,7 +6284,7 @@ resolve@1.1.7: resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.1.7.tgz#203114d82ad2c5ed9e8e0411b3932875e889e97b" integrity sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs= -resolve@^1.10.0, resolve@^1.12.0, resolve@^1.13.1, resolve@^1.15.1, resolve@^1.3.2, resolve@^1.5.0, resolve@^1.8.1: +resolve@1.x, resolve@^1.10.0, resolve@^1.12.0, resolve@^1.13.1, resolve@^1.15.1, resolve@^1.3.2, resolve@^1.5.0, resolve@^1.8.1: version "1.15.1" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.15.1.tgz#27bdcdeffeaf2d6244b95bb0f9f4b4653451f3e8" integrity sha512-84oo6ZTtoTUpjgNEr5SJyzQhzL72gaRodsSfyxC/AXRvwu0Yse9H8eF9IpGo7b8YetZhlI6v7ZQ6bKBFV/6S7w== @@ -6366,7 +6462,7 @@ scheduler@^0.19.1: resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== -semver@^6.0.0, semver@^6.1.2, semver@^6.3.0: +semver@6.x, semver@^6.0.0, semver@^6.1.2, semver@^6.3.0: version "6.3.0" resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== @@ -7019,6 +7115,23 @@ tr46@^1.0.1: dependencies: punycode "^2.1.0" +ts-jest@^25.3.1: + version "25.3.1" + resolved "https://registry.yarnpkg.com/ts-jest/-/ts-jest-25.3.1.tgz#58e2ed3506e4e4487c0b9b532846a5cade9656ba" + integrity sha512-O53FtKguoMUByalAJW+NWEv7c4tus5ckmhfa7/V0jBb2z8v5rDSLFC1Ate7wLknYPC1euuhY6eJjQq4FtOZrkg== + dependencies: + bs-logger "0.x" + buffer-from "1.x" + fast-json-stable-stringify "2.x" + json5 "2.x" + lodash.memoize "4.x" + make-error "1.x" + micromatch "4.x" + mkdirp "1.x" + resolve "1.x" + semver "6.x" + yargs-parser "18.x" + tslib@^1.8.1, tslib@^1.9.0: version "1.11.0" resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.11.0.tgz#f1f3528301621a53220d58373ae510ff747a66bc" @@ -7456,18 +7569,18 @@ yallist@^2.1.2: resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52" integrity sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI= -yargs-parser@^11.1.1: - version "11.1.1" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-11.1.1.tgz#879a0865973bca9f6bab5cbdf3b1c67ec7d3bcf4" - integrity sha512-C6kB/WJDiaxONLJQnF8ccx9SEeoTTLek8RVbaOIsrAUS8VrBEXfmeSnCZxygc+XC2sNMBIwOOnfcxiynjHsVSQ== +yargs-parser@18.x, yargs-parser@^18.1.1: + version "18.1.2" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-18.1.2.tgz#2f482bea2136dbde0861683abea7756d30b504f1" + integrity sha512-hlIPNR3IzC1YuL1c2UwwDKpXlNFBqD1Fswwh1khz5+d8Cq/8yc/Mn0i+rQXduu8hcrFKvO7Eryk+09NecTQAAQ== dependencies: camelcase "^5.0.0" decamelize "^1.2.0" -yargs-parser@^18.1.1: - version "18.1.2" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-18.1.2.tgz#2f482bea2136dbde0861683abea7756d30b504f1" - integrity sha512-hlIPNR3IzC1YuL1c2UwwDKpXlNFBqD1Fswwh1khz5+d8Cq/8yc/Mn0i+rQXduu8hcrFKvO7Eryk+09NecTQAAQ== +yargs-parser@^11.1.1: + version "11.1.1" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-11.1.1.tgz#879a0865973bca9f6bab5cbdf3b1c67ec7d3bcf4" + integrity sha512-C6kB/WJDiaxONLJQnF8ccx9SEeoTTLek8RVbaOIsrAUS8VrBEXfmeSnCZxygc+XC2sNMBIwOOnfcxiynjHsVSQ== dependencies: camelcase "^5.0.0" decamelize "^1.2.0" From f90e21d4ad9335e1853f700eda4cd2d6bc31f214 Mon Sep 17 00:00:00 2001 From: Tales Pereira Date: Sat, 11 Apr 2020 03:54:26 -0300 Subject: [PATCH 02/14] add directory --- .gitignore | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 5310536..312780a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ node_modules coverage -yarn.lock \ No newline at end of file +yarn.lock +dist \ No newline at end of file From 35e1a0d97f39db134b1955298179a5b884273d8c Mon Sep 17 00:00:00 2001 From: Tales Pereira Date: Sat, 11 Apr 2020 03:54:51 -0300 Subject: [PATCH 03/14] setup typescript --- .npmignore | 2 ++ jest.config.js | 13 ++++++--- tsconfig.jest.json | 7 +++++ tsconfig.json | 66 ++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 85 insertions(+), 3 deletions(-) create mode 100644 .npmignore create mode 100644 tsconfig.jest.json create mode 100644 tsconfig.json diff --git a/.npmignore b/.npmignore new file mode 100644 index 0000000..3e00276 --- /dev/null +++ b/.npmignore @@ -0,0 +1,2 @@ +tsconfig.json +src \ No newline at end of file diff --git a/jest.config.js b/jest.config.js index 15fff00..166301a 100644 --- a/jest.config.js +++ b/jest.config.js @@ -7,9 +7,16 @@ module.exports = { coveragePathIgnorePatterns: ["node_modules", "src/utils"], moduleDirectories: ["node_modules"], transform: { - "^.+\\.js$": "/node_modules/react-native/jest/preprocessor.js" + "^.+\\.js$": "/node_modules/react-native/jest/preprocessor.js", + "\\.(ts|tsx)$": "ts-jest" }, setupFiles: ["/jest.setup.js"], - moduleFileExtensions: ["js", "jsx"], - transformIgnorePatterns: [] + moduleFileExtensions: ["js", "jsx", "ts", "tsx"], + transformIgnorePatterns: [], + globals: { + "ts-jest": { + tsConfig: "tsconfig.jest.json" + } + }, + testPathIgnorePatterns: ["dist/"] }; diff --git a/tsconfig.jest.json b/tsconfig.jest.json new file mode 100644 index 0000000..ba7894c --- /dev/null +++ b/tsconfig.jest.json @@ -0,0 +1,7 @@ +{ + "extends": "./tsconfig", + "compilerOptions": { + "jsx": "react", + "module": "commonjs" + } +} diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..7bc8b36 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,66 @@ +{ + "compilerOptions": { + /* Basic Options */ + // "incremental": true, /* Enable incremental compilation */ + "target": "es5" /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */, + "module": "commonjs" /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */, + // "lib": [], /* Specify library files to be included in the compilation. */ + "allowJs": true /* Allow javascript files to be compiled. */, + // "checkJs": true, /* Report errors in .js files. */ + "jsx": "preserve" /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */, + "declaration": true /* Generates corresponding '.d.ts' file. */, + // "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */ + // "sourceMap": true, /* Generates corresponding '.map' file. */ + // "outFile": "./", /* Concatenate and emit output to single file. */ + "outDir": "./dist" /* Redirect output structure to the directory. */, + // "rootDir": "./", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */ + // "composite": true, /* Enable project compilation */ + // "tsBuildInfoFile": "./", /* Specify file to store incremental compilation information */ + // "removeComments": true, /* Do not emit comments to output. */ + // "noEmit": true, /* Do not emit outputs. */ + // "importHelpers": true, /* Import emit helpers from 'tslib'. */ + // "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */ + // "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */ + + /* Strict Type-Checking Options */ + "strict": false /* Enable all strict type-checking options. */, + // "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */ + // "strictNullChecks": true, /* Enable strict null checks. */ + // "strictFunctionTypes": true, /* Enable strict checking of function types. */ + // "strictBindCallApply": true, /* Enable strict 'bind', 'call', and 'apply' methods on functions. */ + // "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */ + // "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */ + // "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */ + + /* Additional Checks */ + // "noUnusedLocals": true, /* Report errors on unused locals. */ + // "noUnusedParameters": true, /* Report errors on unused parameters. */ + // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ + // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ + + /* Module Resolution Options */ + // "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */ + // "baseUrl": "./", /* Base directory to resolve non-absolute module names. */ + // "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */ + // "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */ + // "typeRoots": [], /* List of folders to include type definitions from. */ + // "types": [], /* Type declaration files to be included in compilation. */ + // "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */ + "esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */, + // "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */ + // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ + + /* Source Map Options */ + // "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */ + // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ + // "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */ + // "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */ + + /* Experimental Options */ + // "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */ + // "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */ + + /* Advanced Options */ + "forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */ + } +} From a34fa408393f16b0bcff551ce54d8e0f8cd8118a Mon Sep 17 00:00:00 2001 From: Tales Pereira Date: Sat, 11 Apr 2020 05:13:14 -0300 Subject: [PATCH 04/14] remove js files --- index.js | 5 - src/Block.js | 369 ------------------------ src/Button.js | 251 ---------------- src/Card.js | 105 ------- src/Input.js | 182 ------------ src/Text.js | 292 ------------------- src/__tests__/Block.test.js | 525 ---------------------------------- src/__tests__/Button.test.js | 392 ------------------------- src/__tests__/Card.test.js | 36 --- src/__tests__/Input.test.js | 254 ---------------- src/__tests__/Text.test.js | 434 ---------------------------- src/__tests__/helpers.test.js | 53 ---- src/index.js | 7 - src/theme.js | 64 ----- src/utils/helpers.js | 296 ------------------- src/utils/index.js | 13 - src/utils/rgba.js | 79 ----- 17 files changed, 3357 deletions(-) delete mode 100644 index.js delete mode 100644 src/Block.js delete mode 100644 src/Button.js delete mode 100644 src/Card.js delete mode 100644 src/Input.js delete mode 100644 src/Text.js delete mode 100644 src/__tests__/Block.test.js delete mode 100644 src/__tests__/Button.test.js delete mode 100644 src/__tests__/Card.test.js delete mode 100644 src/__tests__/Input.test.js delete mode 100644 src/__tests__/Text.test.js delete mode 100644 src/__tests__/helpers.test.js delete mode 100644 src/index.js delete mode 100644 src/theme.js delete mode 100644 src/utils/helpers.js delete mode 100644 src/utils/index.js delete mode 100644 src/utils/rgba.js diff --git a/index.js b/index.js deleted file mode 100644 index 0af7056..0000000 --- a/index.js +++ /dev/null @@ -1,5 +0,0 @@ -import { Block, Card, Button, Text, Input } from "./src"; -import * as Utils from "./src/utils"; -import * as theme from "./src/theme"; - -module.exports = { Block, Card, Button, Text, Input, Utils, theme }; diff --git a/src/Block.js b/src/Block.js deleted file mode 100644 index 2378b0a..0000000 --- a/src/Block.js +++ /dev/null @@ -1,369 +0,0 @@ -import React from "react"; -import { - Animated, - SafeAreaView, - ScrollView, - StyleSheet, - View -} from "react-native"; -import expoTheme from "./theme"; -import { getSpacing, mergeTheme, parseSpacing } from "./utils"; - -/** - * https://facebook.github.io/react-native/docs/view - * https://facebook.github.io/react-native/docs/flexbox - * - * Usage: - * - default Block has flex: 1 - * - * components - * - disable flex - * flex: 0 - * - * - flex for half of the size - * flex: 0.5 - * - * - row will render flexDirection: row - * - * text 1 - * text 2 - * - * - * - vertical centering the content - * - * text 1 - * text 2 - * - * * - * - horizontal centering the content - * - * text 1 - * text 2 - * - * - * - vertical & horizontal centering the content - * - * text 1 - * text 2 - * - * - * Colors - * - will render backgroundColor using predefined colors from theme.js COLORS array - * - predefined colors: primary, secondary, tertiary, black, white, gray, error, warning, success, info - * - * backgroundColor: COLORS.primary - * backgroundColor: COLORS.secondary - * - * - custom color using hex color - * backgroundColor: #DDDDDD - * - * Arrange content using justifyContent - * https://facebook.github.io/react-native/docs/layout-props#justifycontent - * - space between the content - * - * 1st text - * 2nd text - * - * - * - space evenly the content - * - * 1st text - * 2nd text - * - * - * - space around the content - * - * 1st text - * 2nd text - * - * - * Border radius - * - round the corners using borderRadius: 6 - * - * 1st text - * 2nd text - * - * - * Border radius - * - round the corners using borderRadius: 6 - * - * 1st text - * 2nd text - * - * - * Wrap content using flexWrap - * by default flexWrap: 'nowrap' - * https://facebook.github.io/react-native/docs/flexbox#flex-wrap - * - * - flexWrap: 'wrap' - * - * 1st text - * 2nd text - * 3rd text - * - * - * For animations animate props can be use to render Animated.View component - * - animated will render Animated.View - * - * animated view - * - * - * For safe area views, safe props can be use to render SafeAreaView component - * - safe will render SafeAreaView - * - * safe area view - * - */ - -const Block = props => { - const getSpacings = type => { - const { - margin, - marginTop, - marginRight, - marginBottom, - marginLeft, - marginVertical, - marginHorizontal, - padding, - paddingTop, - paddingRight, - paddingBottom, - paddingLeft, - paddingVertical, - paddingHorizontal, - theme - } = props; - const { SIZES } = mergeTheme(expoTheme, theme); - - if (type === "margin") { - return [ - margin && getSpacing(type, margin, SIZES.base), - marginTop && parseSpacing("marginTop", marginTop, SIZES.base), - marginRight && parseSpacing("marginRight", marginRight, SIZES.base), - marginBottom && parseSpacing("marginBottom", marginBottom, SIZES.base), - marginLeft && parseSpacing("marginLeft", marginLeft, SIZES.base), - marginVertical && - parseSpacing("marginVertical", marginVertical, SIZES.base), - marginHorizontal && - parseSpacing("marginHorizontal", marginHorizontal, SIZES.base) - ]; - } - - if (type === "padding") { - return [ - padding && getSpacing(type, padding, SIZES.base), - paddingTop && parseSpacing("paddingTop", paddingTop, SIZES.base), - paddingRight && parseSpacing("paddingRight", paddingRight, SIZES.base), - paddingBottom && - parseSpacing("paddingBottom", paddingBottom, SIZES.base), - paddingLeft && parseSpacing("paddingLeft", paddingLeft, SIZES.base), - paddingVertical && - parseSpacing("paddingVertical", paddingVertical, SIZES.base), - paddingHorizontal && - parseSpacing("paddingHorizontal", paddingHorizontal, SIZES.base) - ]; - } - }; - - const { - width, - height, - flex, - noflex, - row, - column, - center, - middle, - left, - right, - top, - bottom, - card, - shadow, - elevation, - // colors - color, - primary, - secondary, - tertiary, - black, - white, - gray, - error, - warning, - success, - info, - // positioning - space, - radius, - wrap, - animated, - theme, - safe, - style, - children, - scroll, - ...rest - } = props; - - const excludeProps = [ - "margin", - "marginTop", - "marginRight", - "marginBottom", - "marginLeft", - "marginVertical", - "marginHorizontal", - "padding", - "paddingTop", - "paddingRight", - "paddingBottom", - "paddingLeft", - "paddingVertical", - "paddingHorizontal" - ]; - - const extraProps = Object.keys(props).reduce((prop, key) => { - if (!excludeProps.includes(`${key}`)) { - prop[key] = props[key]; - } - return prop; - }, {}); - - const { SIZES, COLORS } = mergeTheme(expoTheme, theme); - const marginSpacing = getSpacings("margin"); - const paddingSpacing = getSpacings("padding"); - - const blockStyles = StyleSheet.flatten([ - styles.block, - flex && { flex: flex === true ? 1 : flex }, - (!flex || noflex) && { flex: 0 }, - row && styles.row, - column && styles.column, - center && styles.center, - middle && styles.middle, - left && styles.left, - right && styles.right, - top && styles.top, - bottom && styles.bottom, - marginSpacing, - paddingSpacing, - wrap && styles.wrap, - shadow && { - elevation, - shadowColor: COLORS.black, - shadowOffset: { width: 0, height: elevation - 1 }, - shadowOpacity: 0.1, - shadowRadius: elevation - }, - space && { justifyContent: `space-${space}` }, - card && { borderRadius: SIZES.border }, - radius && { borderRadius: radius }, - // color shortcuts - primary && { backgroundColor: COLORS.primary }, - secondary && { backgroundColor: COLORS.secondary }, - tertiary && { backgroundColor: COLORS.tertiary }, - black && { backgroundColor: COLORS.black }, - white && { backgroundColor: COLORS.white }, - gray && { backgroundColor: COLORS.gray }, - error && { backgroundColor: COLORS.error }, - warning && { backgroundColor: COLORS.warning }, - success && { backgroundColor: COLORS.success }, - info && { backgroundColor: COLORS.info }, - color && { backgroundColor: color }, // custom backgroundColor - row && { flex: 0 }, - width && { width }, - height && { height }, - style // rewrite predefined styles - ]); - - if (scroll) { - return ( - - {children} - - ); - } - - if (animated) { - return ( - - {children} - - ); - } - - if (safe) { - return ( - - {children} - - ); - } - - return ( - - {children} - - ); -}; - -Block.defaultProps = { - flex: true, - row: false, - column: false, - center: false, - middle: false, - left: false, - right: false, - top: false, - bottom: false, - card: false, - shadow: null, - elevation: 3, - color: null, - space: null, - margin: null, - padding: null, - radius: null, - wrap: false, - animated: false, - safe: false, - scroll: false, - style: {}, - theme: {} -}; - -export default Block; - -export const styles = StyleSheet.create({ - block: { - flex: 1 - }, - row: { - flexDirection: "row" - }, - column: { - flexDirection: "column" - }, - center: { - alignItems: "center" - }, - middle: { - justifyContent: "center" - }, - left: { - justifyContent: "flex-start" - }, - right: { - justifyContent: "flex-end" - }, - top: { - justifyContent: "flex-start" - }, - bottom: { - justifyContent: "flex-end" - }, - wrap: { flexWrap: "wrap" } -}); diff --git a/src/Button.js b/src/Button.js deleted file mode 100644 index 750f5e4..0000000 --- a/src/Button.js +++ /dev/null @@ -1,251 +0,0 @@ -import React from "react"; -import { - StyleSheet, - TouchableHighlight, - TouchableNativeFeedback, - TouchableOpacity, - TouchableWithoutFeedback -} from "react-native"; -import expoTheme from "./theme"; -import { getSpacing, mergeTheme, parseSpacing, rgba } from "./utils"; - -/** - * https://facebook.github.io/react-native/docs/touchableopacity - * https://facebook.github.io/react-native/docs/touchablehighlight - * https://facebook.github.io/react-native/docs/touchablenativefeedback - * https://facebook.github.io/react-native/docs/touchablewithoutfeedback - * - * Default render an instance of TouchableOpacity - * - * - TouchableHighlight - * - * - * - TouchableNativeFeedback - * - * - * - TouchableWithoutFeedback - * - * - * Colors - * - will render backgroundColor using predefined colors from theme.js COLORS array - * - predefined colors: primary, secondary, tertiary, black, white, gray, error, warning, success, info - * - * - * - * - * - custom color using hex color - * - * - * Set activeOpacity using opacity prop - * default activeOpacity=0.8 - * - * - * Outlined and add borderColor equal with backgroundColor - * - * - * Disabling the button - * - * - * - * Add flex to button style - * - * - * - * Add height to button style - * - * - */ - -function Button(props) { - const getSpacings = (type) => { - const { - margin, - marginTop, - marginRight, - marginBottom, - marginLeft, - marginVertical, - marginHorizontal, - padding, - paddingTop, - paddingRight, - paddingBottom, - paddingLeft, - paddingVertical, - paddingHorizontal, - theme - } = props; - const { SIZES } = mergeTheme(expoTheme, theme); - - if (type === "margin") { - return [ - margin && getSpacing(type, margin, SIZES.base), - marginTop && parseSpacing("marginTop", marginTop, SIZES.base), - marginRight && parseSpacing("marginRight", marginRight, SIZES.base), - marginBottom && parseSpacing("marginBottom", marginBottom, SIZES.base), - marginLeft && parseSpacing("marginLeft", marginLeft, SIZES.base), - marginVertical && - parseSpacing("marginVertical", marginVertical, SIZES.base), - marginHorizontal && - parseSpacing("marginHorizontal", marginHorizontal, SIZES.base) - ]; - } - - if (type === "padding") { - return [ - padding && getSpacing(type, padding, SIZES.base), - paddingTop && parseSpacing("paddingTop", paddingTop, SIZES.base), - paddingRight && parseSpacing("paddingRight", paddingRight, SIZES.base), - paddingBottom && - parseSpacing("paddingBottom", paddingBottom, SIZES.base), - paddingLeft && parseSpacing("paddingLeft", paddingLeft, SIZES.base), - paddingVertical && - parseSpacing("paddingVertical", paddingVertical, SIZES.base), - paddingHorizontal && - parseSpacing("paddingHorizontal", paddingHorizontal, SIZES.base) - ]; - } - }; - - const { - disabled, - opacity, - outlined, - flex, - height, - borderWidth, - // colors - color, - transparent, - primary, - secondary, - tertiary, - black, - white, - gray, - error, - warning, - success, - info, - borderColor, - // support for touchables - highlight, - nativeFeedback, - withoutFeedback, - theme, - style, - children, - ...rest - } = props; - - const excludeProps = [ - "margin", - "marginTop", - "marginRight", - "marginBottom", - "marginLeft", - "marginVertical", - "marginHorizontal", - "padding", - "paddingTop", - "paddingRight", - "paddingBottom", - "paddingLeft", - "paddingVertical", - "paddingHorizontal" - ]; - const extraProps = Object.keys(props).reduce((prop, key) => { - if (!excludeProps.includes(`${key}`)) { - prop[key] = props[key]; - } - return prop; - }, {}); - - const { SIZES, COLORS } = mergeTheme({ ...expoTheme }, theme); - const marginSpacing = getSpacings("margin"); - const paddingSpacing = getSpacings("padding"); - - const buttonStyles = StyleSheet.flatten([ - { - height: SIZES.base * 5.5, - borderRadius: SIZES.radius, - backgroundColor: color || COLORS.primary, - justifyContent: "center" - }, - transparent && { backgroundColor: "transparent" }, - primary && { backgroundColor: COLORS.primary }, - secondary && { backgroundColor: COLORS.secondary }, - tertiary && { backgroundColor: COLORS.tertiary }, - black && { backgroundColor: COLORS.black }, - white && { backgroundColor: COLORS.white }, - gray && { backgroundColor: COLORS.gray }, - error && { backgroundColor: COLORS.error }, - warning && { backgroundColor: COLORS.warning }, - success && { backgroundColor: COLORS.success }, - info && { backgroundColor: COLORS.info }, - color && { backgroundColor: color }, // custom backgroundColor - flex && { flex }, // flex width - height && { height }, // custom height - borderWidth && { borderWidth }, - borderColor && { borderColor }, - marginSpacing, - paddingSpacing, - style - ]); - - const backgroundColor = StyleSheet.flatten(buttonStyles).backgroundColor; - - if (disabled) { - buttonStyles.backgroundColor = rgba(backgroundColor, 0.5); - } - - if (outlined) { - buttonStyles.borderWidth = 1; - buttonStyles.borderColor = backgroundColor; - buttonStyles.backgroundColor = "transparent"; - } - - const ButtonType = highlight - ? TouchableHighlight - : nativeFeedback - ? TouchableNativeFeedback - : withoutFeedback - ? TouchableWithoutFeedback - : TouchableOpacity; - - return ( - - {children} - - ); -} - -Button.defaultProps = { - color: null, - disabled: false, - opacity: 0.8, - outlined: false, - margin: null, - padding: null, - flex: 0, - height: false, - transparent: false, - primary: false, - secondary: false, - tertiary: false, - black: false, - white: false, - gray: false, - error: false, - warning: false, - success: false, - info: false, - theme: {}, - style: {} -}; - -export default Button; diff --git a/src/Card.js b/src/Card.js deleted file mode 100644 index a00ecb6..0000000 --- a/src/Card.js +++ /dev/null @@ -1,105 +0,0 @@ -import React from "react"; -import { StyleSheet } from "react-native"; -import Block from "./Block"; -import expoTheme from "./theme"; -import { mergeTheme, rgba } from "./utils"; - -/** - * https://facebook.github.io/react-native/docs/view - * https://facebook.github.io/react-native/docs/flexbox - * - * Using Block component with predefined props: color, radius and padding - * - * default card - * - * - * Border radius using radius props - * - * - * radius={8} - * - * - * Padding using padding props - * default padding={SIZES.base} - * - * - * padding={12} - * - * - * Set shadow using shadow props - * default shadow with color black and elevation - * shadowOffset is calculated using elevation - 1 - * shadowRadius is equal with elevation value - * - * - * shadow - * - * - * - * shadow elevation={2} - * - * - * Set borderColor using outlined prop - * default borderWidth: 1 and borderColor: rgba(COLORS.black, 0.16) with alpha 0.16 - * - * - * outlined - * - * - */ - -const Card = props => { - const { - color, - radius, - padding, - shadow, - elevation, - outlined, - theme, - style, - children, - ...rest - } = props; - - const { SIZES, COLORS } = mergeTheme({ ...expoTheme }, theme); - - const cardStyles = StyleSheet.flatten([ - shadow && { - elevation, - shadowColor: COLORS.black, - shadowOffset: { width: 0, height: elevation - 1 }, - shadowOpacity: 0.1, - shadowRadius: elevation - }, - outlined && { - borderWidth: 1, - borderColor: rgba(COLORS.black, 0.16) - }, - style - ]); - - return ( - - {children} - - ); -}; - -Card.defaultProps = { - color: null, - radius: null, - padding: null, - shadow: false, - elevation: 3, - outlined: false, - theme: {}, - style: {} -}; - -export default Card; diff --git a/src/Input.js b/src/Input.js deleted file mode 100644 index c143bd0..0000000 --- a/src/Input.js +++ /dev/null @@ -1,182 +0,0 @@ -import React, { useReducer } from "react"; -import { StyleSheet, TextInput } from "react-native"; - -import expoTheme from "./theme"; -import { mergeTheme, rgba } from "./utils"; - -/** - * https://facebook.github.io/react-native/docs/textinput - * - * Validation - * onValidation return a single boolean or object with boolean values - * pattern using regex string for validating the value - * - * single pattern to validate the value - * console.log(isValid)} - * /> - * - * multiple pattern to validate the value - * console.log(isValid)} - * /> - * - * Border color using color prop - * - * - * Pass ref from props using internalRef reference - * this.c} /> - */ - -export const INITIAL_STATE = { - value: null, - focused: false, - blurred: false -}; - -export const change = (value) => { - return { type: "change", payload: { value } }; -}; -export const focus = () => { - return { type: "focus" }; -}; -export const blur = () => { - return { type: "blur" }; -}; - -export const reducer = (state, action) => { - switch (action.type) { - case "change": - return { ...state, value: action.payload.value }; - case "focus": - return { ...state, focused: true, blurred: false }; - case "blur": - return { ...state, focused: false, blurred: true }; - default: - return state; - } -}; - -const Input = (props) => { - const [state, dispatch] = useReducer(reducer, INITIAL_STATE); - - const handleValidation = (value) => { - const { pattern } = props; - if (!pattern) return true; - - // string pattern, one validation rule - if (typeof pattern === "string") { - const condition = new RegExp(pattern, "g"); - return condition.test(value); - } - - // array patterns, multiple validation rules - if (typeof pattern === "object") { - const conditions = pattern.map((rule) => new RegExp(rule, "g")); - return conditions.map((condition) => condition.test(value)); - } - }; - - const handleChange = (value) => { - const { onChangeText, onValidation } = props; - const isValid = handleValidation(value); - dispatch(change(value)); - onValidation && onValidation(isValid); - onChangeText && onChangeText(value); - }; - - const handleFocus = (event) => { - const { onFocus } = props; - dispatch(focus()); - onFocus && onFocus(event); - }; - - const handleBlur = (event) => { - const { onBlur } = props; - dispatch(blur()); - onBlur && onBlur(event); - }; - - const handleTextType = (type) => { - return type === "email" - ? "emailAddress" - : type === "phone" - ? "telephoneNumber" - : type; - }; - - const { - autoCorrect, - autoCapitalize, - placeholder, - children, - color, - borderWidth, - borderColor, - type, - style, - theme, - internalRef, - onFocus, - onBlur, - onChangeText, - ...rest - } = props; - const { SIZES, COLORS } = mergeTheme({ ...expoTheme }, theme); - - const textStyles = StyleSheet.flatten([ - { - borderWidth: 1, - height: SIZES.base * 5.5, - borderRadius: SIZES.radius, - borderColor: rgba(color || COLORS.primary, 0.4), - paddingHorizontal: SIZES.base, - fontSize: SIZES.font - }, - borderWidth && { borderWidth }, - borderColor && { borderColor }, - style - ]); - const textType = handleTextType(type); - - const internalProps = { - style: textStyles, - autoCorrect, - autoCapitalize, - placeholder, - textContentType: textType, - value: state.value, - onFocus: handleFocus, - onBlur: handleBlur, - onChangeText: handleChange - }; - - return ( - - {children} - - ); -}; - -Input.defaultProps = { - pattern: null, - onFocus: null, - onBlur: null, - onChange: null, - onValidation: null, - placeholder: null, - autoCorrect: false, - autoCapitalize: "none", - color: null, - internalRef: null, - theme: {}, - style: {} -}; - -export default Input; diff --git a/src/Text.js b/src/Text.js deleted file mode 100644 index c1ea8fc..0000000 --- a/src/Text.js +++ /dev/null @@ -1,292 +0,0 @@ -import React from "react"; -import { Animated, StyleSheet, Text } from "react-native"; -import expoTheme from "./theme"; -import { getSpacing, mergeTheme, parseSpacing } from "./utils"; - -/** - * Usage: - * fontSize predefined by theme.js - * - fontSize of 34 from FONTS.h1 - * - fontSize of 24 from FONTS.h2 - * - fontSize of 20 from FONTS.h3 - * - fontSize of 18 from FONTS.title - * - fontSize of 14 from FONTS.subtitle - * - fontSize of 12 from FONTS.caption - * - fontSize of 10 from FONTS.small - * fontSize defined by user - * - fontSize of 20 - * - * margin & padding - * - set margin 4 to: top, right, bottom & left - * - set margin 6 to: top, right, bottom & left - * - margin + Top | Bottom | Left | Right | Vertical | Horizontal - * - padding + Top | Bottom | Left | Right | Vertical | Horizontal - * - * text styling - * - textTransform: capitalize, lowercase, uppercase - * - fontWeight from WEIGHTS.regular - * - fontWeight from WEIGHTS.bold - * - fontWeight from WEIGHTS.semibold - * - fontWeight from WEIGHTS.medium - * - fontWeight from WEIGHTS.light - * - fontWeight from user input - * - * text colors - * - color from COLORS.primary - * - color from COLORS.secondary - * - color from COLORS.tertiary - * - color from COLORS.black - * - color from COLORS.white - * - color from COLORS.gray - * - color from COLORS.info - * - color from COLORS.success - * - color from COLORS.warning - * - color from COLORS.error - * - color from user input - * - * custom theme using the src/theme.js data structure - * - create a custom theme by defining: const customTheme.js - * - with the following structure to rewrite any value - * { - * COLORS: { - * primary: "cyan" or "#8A00D4", - * secondary: "fucsia" or "#D527B7", - * tertiary: "yellow" or "#FFC46B" - * }, - * SIZES: { - * font: 15, - * h1: 28 - * title: 17 - * } - * } - * - include the custom theme to the component props - * primary using new color: #8A00D4 - * - * animating text can be used using the "animated" props - * - will render Animated.Text - */ - -const Typography = props => { - const getSpacings = type => { - const { - margin, - marginTop, - marginRight, - marginBottom, - marginLeft, - marginVertical, - marginHorizontal, - padding, - paddingTop, - paddingRight, - paddingBottom, - paddingLeft, - paddingVertical, - paddingHorizontal, - theme - } = props; - const { SIZES } = mergeTheme(expoTheme, theme); - - if (type === "margin") { - return [ - margin && getSpacing(type, margin, SIZES.base), - marginTop && parseSpacing("marginTop", marginTop, SIZES.base), - marginRight && parseSpacing("marginRight", marginRight, SIZES.base), - marginBottom && parseSpacing("marginBottom", marginBottom, SIZES.base), - marginLeft && parseSpacing("marginLeft", marginLeft, SIZES.base), - marginVertical && - parseSpacing("marginVertical", marginVertical, SIZES.base), - marginHorizontal && - parseSpacing("marginHorizontal", marginHorizontal, SIZES.base) - ]; - } - - if (type === "padding") { - return [ - padding && getSpacing(type, padding, SIZES.base), - paddingTop && parseSpacing("paddingTop", paddingTop, SIZES.base), - paddingRight && parseSpacing("paddingRight", paddingRight, SIZES.base), - paddingBottom && - parseSpacing("paddingBottom", paddingBottom, SIZES.base), - paddingLeft && parseSpacing("paddingLeft", paddingLeft, SIZES.base), - paddingVertical && - parseSpacing("paddingVertical", paddingVertical, SIZES.base), - paddingHorizontal && - parseSpacing("paddingHorizontal", paddingHorizontal, SIZES.base) - ]; - } - }; - - const { - // fonts & sizes - h1, - h2, - h3, - title, - subtitle, - caption, - small, - size, - // styling - transform, - regular, - bold, - semibold, - medium, - weight, - light, - center, - right, - spacing, // letter-spacing - height, // line-height - // colors - color, - primary, - secondary, - tertiary, - black, - white, - gray, - error, - warning, - success, - info, - animated, - theme, - style, - children, - ...rest - } = props; - - const excludeProps = [ - "margin", - "marginTop", - "marginRight", - "marginBottom", - "marginLeft", - "marginVertical", - "marginHorizontal", - "padding", - "paddingTop", - "paddingRight", - "paddingBottom", - "paddingLeft", - "paddingVertical", - "paddingHorizontal" - ]; - const extraProps = Object.keys(props).reduce((prop, key) => { - if (!excludeProps.includes(`${key}`)) { - prop[key] = props[key]; - } - return prop; - }, {}); - - const { SIZES, COLORS, FONTS, WEIGHTS } = mergeTheme({ ...expoTheme }, theme); - - const marginSpacing = getSpacings("margin"); - const paddingSpacing = getSpacings("padding"); - - const textStyles = StyleSheet.flatten([ - { - fontWeight: WEIGHTS.regular, - fontSize: SIZES.font, - color: COLORS.font - }, - h1 && FONTS.h1, - h2 && FONTS.h2, - h3 && FONTS.h3, - title && FONTS.title, - subtitle && FONTS.subtitle, - caption && FONTS.caption, - small && FONTS.small, - size && { fontSize: size }, - marginSpacing, - paddingSpacing, - transform && { textTransform: transform }, - height && { lineHeight: height }, - spacing && { letterSpacing: spacing }, - weight && { fontWeight: weight }, - regular && { fontWeight: WEIGHTS.regular }, - bold && { fontWeight: WEIGHTS.bold }, - semibold && { fontWeight: WEIGHTS.semibold }, - medium && { fontWeight: WEIGHTS.medium }, - light && { fontWeight: WEIGHTS.light }, - center && styles.center, - right && styles.right, - // color shortcuts - primary && { color: COLORS.primary }, - secondary && { color: COLORS.secondary }, - tertiary && { color: COLORS.tertiary }, - black && { color: COLORS.black }, - white && { color: COLORS.white }, - gray && { color: COLORS.gray }, - error && { color: COLORS.error }, - warning && { color: COLORS.warning }, - success && { color: COLORS.success }, - info && { color: COLORS.info }, - color && { color }, - style // rewrite predefined styles - ]); - - if (animated) { - return ( - - {children} - - ); - } - - return ( - - {children} - - ); -}; - -Typography.defaultProps = { - // fonts & sizes - h1: false, - h2: false, - h3: false, - title: false, - subtitle: false, - caption: false, - small: false, - size: null, - margin: null, - padding: null, - // styling - transform: null, - regular: false, - bold: false, - semibold: false, - medium: false, - weight: false, - light: false, - center: false, - right: false, - spacing: null, // letter-spacing - height: null, // line-height - // colors - color: null, - primary: false, - secondary: false, - tertiary: false, - black: false, - white: false, - gray: false, - error: false, - warning: false, - success: false, - info: false, - theme: {}, - style: {} -}; - -export default Typography; - -const styles = StyleSheet.create({ - // positioning - center: { textAlign: "center" }, - right: { textAlign: "right" } -}); diff --git a/src/__tests__/Block.test.js b/src/__tests__/Block.test.js deleted file mode 100644 index 263b51b..0000000 --- a/src/__tests__/Block.test.js +++ /dev/null @@ -1,525 +0,0 @@ -import { shallow } from "enzyme"; -import React from "react"; -import { StyleSheet } from "react-native"; -import renderer from "react-test-renderer"; -import Block from "../Block"; -import { SIZES } from "../theme"; - -const customTheme = { - COLORS: { - primary: "red" - } -}; - -describe("", () => { - it("render default", () => { - const component = renderer.create().toJSON(); - const style = StyleSheet.flatten(component.props.style); - expect(style.flex).toEqual(1); - }); - - it("testing flex, flex={0.5}, flex={false}", () => { - const component = shallow(flex); - let style = StyleSheet.flatten(component.props().style); - expect(style.flex).toEqual(1); - - component.setProps({ flex: 0.5 }); - style = StyleSheet.flatten(component.props().style); - expect(style.flex).toEqual(0.5); - - component.setProps({ flex: true }); - style = StyleSheet.flatten(component.props().style); - expect(style.flex).toEqual(1); - - component.setProps({ flex: 0 }); - style = StyleSheet.flatten(component.props().style); - expect(style.flex).toEqual(0); - }); - - it("testing flexDirection, row & column", () => { - const component = shallow(flexDirection); - - let style = StyleSheet.flatten(component.props().style); - expect(style.flexDirection).toEqual("row"); - - component.setProps({ column: true }); - style = StyleSheet.flatten(component.props().style); - expect(style.flexDirection).toEqual("column"); - }); - - it("center", () => { - const component = renderer.create().toJSON(); - const style = StyleSheet.flatten(component.props.style); - expect(style.alignItems).toEqual("center"); - }); - - it("middle", () => { - const component = renderer.create().toJSON(); - const style = StyleSheet.flatten(component.props.style); - expect(style.justifyContent).toEqual("center"); - }); - - it("left", () => { - const component = renderer.create().toJSON(); - const style = StyleSheet.flatten(component.props.style); - expect(style.justifyContent).toEqual("flex-start"); - }); - - it("right", () => { - const component = renderer.create().toJSON(); - const style = StyleSheet.flatten(component.props.style); - expect(style.justifyContent).toEqual("flex-end"); - }); - - it("top", () => { - const component = renderer.create().toJSON(); - const style = StyleSheet.flatten(component.props.style); - expect(style.justifyContent).toEqual("flex-start"); - }); - - it("bottom", () => { - const component = renderer.create().toJSON(); - const style = StyleSheet.flatten(component.props.style); - expect(style.justifyContent).toEqual("flex-end"); - }); - - it("wrap", () => { - const component = renderer.create().toJSON(); - const style = StyleSheet.flatten(component.props.style); - expect(style.flexWrap).toEqual("wrap"); - }); - - it("padding={4}", () => { - const block = renderer.create(); - - const component = block.toJSON(); - const instance = block.root; - - const style = StyleSheet.flatten(component.props.style); - expect(instance.props.padding).toEqual(4); - expect(style).toEqual({ - flex: 1, - paddingBottom: 4, - paddingLeft: 4, - paddingRight: 4, - paddingTop: 4 - }); - }); - - it("padding={[2, 4]}", () => { - const block = renderer.create(); - - const component = block.toJSON(); - const instance = block.root; - - const style = StyleSheet.flatten(component.props.style); - expect(instance.props.padding).toEqual([2, 4]); - expect(style).toEqual({ - flex: 1, - paddingBottom: 2, - paddingLeft: 4, - paddingRight: 4, - paddingTop: 2 - }); - }); - - it("padding={[1, 2, 3, 4]}", () => { - const block = renderer.create(); - - const component = block.toJSON(); - const instance = block.root; - - const style = StyleSheet.flatten(component.props.style); - expect(instance.props.padding).toEqual([1, 2, 3, 4]); - expect(style).toEqual({ - flex: 1, - paddingBottom: 3, - paddingLeft: 4, - paddingRight: 2, - paddingTop: 1 - }); - }); - - it("paddingTop={6}, paddingRight={5}, paddingBottom={4}, paddingLeft={3}", () => { - const block = renderer.create( - - ); - - const component = block.toJSON(); - const instance = block.root; - - const style = StyleSheet.flatten(component.props.style); - expect(instance.props.paddingTop).toEqual(6); - expect(instance.props.paddingRight).toEqual(5); - expect(instance.props.paddingBottom).toEqual(4); - expect(instance.props.paddingLeft).toEqual(3); - expect(style).toEqual({ - flex: 1, - paddingLeft: 3, - paddingBottom: 4, - paddingRight: 5, - paddingTop: 6 - }); - }); - - it("paddingTop='2x', paddingRight='3x', paddingBottom='4x', paddingLeft='5x'", () => { - const block = renderer.create( - - ); - - const component = block.toJSON(); - const instance = block.root; - - const style = StyleSheet.flatten(component.props.style); - expect(instance.props.paddingTop).toEqual("2x"); - expect(instance.props.paddingRight).toEqual("3x"); - expect(instance.props.paddingBottom).toEqual("4x"); - expect(instance.props.paddingLeft).toEqual("5x"); - expect(style).toEqual({ - flex: 1, - paddingLeft: 40, - paddingBottom: 32, - paddingRight: 24, - paddingTop: 16 - }); - }); - - it("paddingHorizontal={6}, paddingVertical={8}", () => { - const block = renderer.create( - - ); - - const component = block.toJSON(); - const instance = block.root; - - const style = StyleSheet.flatten(component.props.style); - expect(instance.props.paddingHorizontal).toEqual(6); - expect(instance.props.paddingVertical).toEqual(8); - expect(style).toEqual({ - flex: 1, - paddingVertical: 8, - paddingHorizontal: 6 - }); - }); - - it("paddingHorizontal='2x', paddingVertical='0.5x'", () => { - const block = renderer.create( - - ); - - const component = block.toJSON(); - const instance = block.root; - - const style = StyleSheet.flatten(component.props.style); - expect(instance.props.paddingHorizontal).toEqual("2x"); - expect(instance.props.paddingVertical).toEqual("0.5x"); - expect(style).toEqual({ - flex: 1, - paddingVertical: 4, - paddingHorizontal: 16 - }); - }); - - it("margin={6}", () => { - const block = renderer.create(); - - const component = block.toJSON(); - const instance = block.root; - - const style = StyleSheet.flatten(component.props.style); - expect(instance.props.margin).toEqual(6); - expect(style).toEqual({ - flex: 1, - marginBottom: 6, - marginLeft: 6, - marginRight: 6, - marginTop: 6 - }); - }); - - it("margin={[2, 4]}", () => { - const block = renderer.create(); - - const component = block.toJSON(); - const instance = block.root; - - const style = StyleSheet.flatten(component.props.style); - expect(instance.props.margin).toEqual([2, 4]); - expect(style).toEqual({ - flex: 1, - marginBottom: 2, - marginLeft: 4, - marginRight: 4, - marginTop: 2 - }); - }); - - it("margin={[1, 2, 3, 4]}", () => { - const block = renderer.create(); - - const component = block.toJSON(); - const instance = block.root; - - const style = StyleSheet.flatten(component.props.style); - expect(instance.props.margin).toEqual([1, 2, 3, 4]); - expect(style).toEqual({ - flex: 1, - marginBottom: 3, - marginLeft: 4, - marginRight: 2, - marginTop: 1 - }); - }); - - it("marginTop={6}, marginRight={5}, marginBottom={4}, marginLeft={3}", () => { - const block = renderer.create( - - ); - - const component = block.toJSON(); - const instance = block.root; - - const style = StyleSheet.flatten(component.props.style); - expect(instance.props.marginTop).toEqual(6); - expect(instance.props.marginRight).toEqual(5); - expect(instance.props.marginBottom).toEqual(4); - expect(instance.props.marginLeft).toEqual(3); - expect(style).toEqual({ - flex: 1, - marginLeft: 3, - marginBottom: 4, - marginRight: 5, - marginTop: 6 - }); - }); - - it("marginTop='2x', marginRight='3x', marginBottom='4x', marginLeft='5x'", () => { - const block = renderer.create( - - ); - - const component = block.toJSON(); - const instance = block.root; - - const style = StyleSheet.flatten(component.props.style); - expect(instance.props.marginTop).toEqual("2x"); - expect(instance.props.marginRight).toEqual("3x"); - expect(instance.props.marginBottom).toEqual("4x"); - expect(instance.props.marginLeft).toEqual("5x"); - expect(style).toEqual({ - flex: 1, - marginLeft: 40, - marginBottom: 32, - marginRight: 24, - marginTop: 16 - }); - }); - - it("marginHorizontal={6}, marginVertical={8}", () => { - const block = renderer.create( - - ); - - const component = block.toJSON(); - const instance = block.root; - - const style = StyleSheet.flatten(component.props.style); - expect(instance.props.marginHorizontal).toEqual(6); - expect(instance.props.marginVertical).toEqual(8); - expect(style).toEqual({ - flex: 1, - marginVertical: 8, - marginHorizontal: 6 - }); - }); - - it("marginHorizontal='2x', marginVertical='0.5x'", () => { - const block = renderer.create( - - ); - - const component = block.toJSON(); - const instance = block.root; - - const style = StyleSheet.flatten(component.props.style); - expect(instance.props.marginHorizontal).toEqual("2x"); - expect(instance.props.marginVertical).toEqual("0.5x"); - expect(style).toEqual({ - flex: 1, - marginVertical: 4, - marginHorizontal: 16 - }); - }); - - it("animated", () => { - const component = shallow(); - const block = renderer.create(); - - const instance = block.root; - - expect(instance.props.animated).toEqual(true); - expect(component.name()).toEqual("AnimatedComponent"); - }); - - it("safe", () => { - const component = shallow(); - const block = renderer.create(); - - const instance = block.root; - - expect(instance.props.safe).toEqual(true); - expect(component.name()).toEqual("SafeAreaView"); - }); - - it("shadow", () => { - const block = renderer.create(); - - const component = block.toJSON(); - const instance = block.root; - - const style = StyleSheet.flatten(component.props.style); - - expect(instance.props.shadow).toEqual(true); - expect(style.elevation).toEqual(3); - expect(style.shadowColor).toEqual("#000020"); - expect(style.shadowOffset).toEqual({ width: 0, height: 2 }); - expect(style.shadowOpacity).toEqual(0.1); - expect(style.shadowRadius).toEqual(3); - }); - - it('space="between"', () => { - const block = renderer.create(); - - const component = block.toJSON(); - const instance = block.root; - - const style = StyleSheet.flatten(component.props.style); - expect(instance.props.space).toEqual("between"); - expect(style.justifyContent).toEqual("space-between"); - }); - - it("card", () => { - const block = renderer.create(); - - const component = block.toJSON(); - const instance = block.root; - - const style = StyleSheet.flatten(component.props.style); - expect(instance.props.card).toEqual(true); - expect(style.borderRadius).toEqual(SIZES.border); - }); - - it("radius={4}", () => { - const block = renderer.create(); - - const component = block.toJSON(); - const instance = block.root; - - const style = StyleSheet.flatten(component.props.style); - expect(instance.props.radius).toEqual(4); - expect(style.borderRadius).toEqual(4); - }); - - it("colors: primary, secondary, tertiary, black, white, gray, alert, warning, success, info, color", () => { - const component = shallow(block color); - let style = StyleSheet.flatten(component.props().style); - expect(style.backgroundColor).toEqual(undefined); - - component.setProps({ primary: true }); - style = StyleSheet.flatten(component.props().style); - expect(style.backgroundColor).toEqual("#4630EB"); - - component.setProps({ secondary: true }); - style = StyleSheet.flatten(component.props().style); - expect(style.backgroundColor).toEqual("#A3A1F7"); - - component.setProps({ tertiary: true }); - style = StyleSheet.flatten(component.props().style); - expect(style.backgroundColor).toEqual("#FFE358"); - - component.setProps({ black: true }); - style = StyleSheet.flatten(component.props().style); - expect(style.backgroundColor).toEqual("#000020"); - - component.setProps({ white: true }); - style = StyleSheet.flatten(component.props().style); - expect(style.backgroundColor).toEqual("#FFFFFF"); - - component.setProps({ gray: true }); - style = StyleSheet.flatten(component.props().style); - expect(style.backgroundColor).toEqual("#535453"); - - component.setProps({ error: true }); - style = StyleSheet.flatten(component.props().style); - expect(style.backgroundColor).toEqual("#DC3545"); - - component.setProps({ warning: true }); - style = StyleSheet.flatten(component.props().style); - expect(style.backgroundColor).toEqual("#FFE358"); - - component.setProps({ success: true }); - style = StyleSheet.flatten(component.props().style); - expect(style.backgroundColor).toEqual("#4CD964"); - - component.setProps({ info: true }); - style = StyleSheet.flatten(component.props().style); - expect(style.backgroundColor).toEqual("#4DA1FF"); - - component.setProps({ color: "#88B04B" }); - style = StyleSheet.flatten(component.props().style); - expect(style.backgroundColor).toEqual("#88B04B"); - }); - - it("custom theme for primary color", () => { - const block = renderer.create( - - custom theme color - - ); - - const component = block.toJSON(); - const instance = block.root; - - expect(instance.props.theme).toEqual(customTheme); - - let style = StyleSheet.flatten(component.props.style); - - expect(style.backgroundColor).toEqual("red"); - }); - - it("render ScrollView component", () => { - const component = shallow(); - - expect(component.props().scroll).toEqual(true); - expect(component.name()).toEqual("ScrollViewMock"); - }); - - it("width={100}", () => { - const component = shallow(); - const style = StyleSheet.flatten(component.props().style); - - expect(style.width).toEqual(100); - }); - - it("height={100}", () => { - const component = shallow(); - const style = StyleSheet.flatten(component.props().style); - - expect(style.height).toEqual(100); - }); -}); diff --git a/src/__tests__/Button.test.js b/src/__tests__/Button.test.js deleted file mode 100644 index dce5f76..0000000 --- a/src/__tests__/Button.test.js +++ /dev/null @@ -1,392 +0,0 @@ -import { shallow } from "enzyme"; -import React from "react"; -import { StyleSheet } from "react-native"; -import renderer from "react-test-renderer"; - -import Button from "../Button"; -import Text from "../Text"; -import { SIZES } from "../theme"; -import { rgba } from "../utils"; - -describe(" - ); - - expect(component.props().highlight).toEqual(true); - expect(component.name()).toEqual("TouchableHighlight"); - }); - - it("ButtonType: withoutFeedback", () => { - const component = shallow( - - ); - - expect(component.props().withoutFeedback).toEqual(true); - expect(component.name()).toEqual("TouchableWithoutFeedback"); - }); - - it("onPress", () => { - const onPress = jest.fn(); - const component = shallow( + * + * - TouchableNativeFeedback + * + * + * - TouchableWithoutFeedback + * + * + * Colors + * - will render backgroundColor using predefined colors from theme.js COLORS array + * - predefined colors: primary, secondary, tertiary, black, white, gray, error, warning, success, info + * + * + * + * + * - custom color using hex color + * + * + * Set activeOpacity using opacity prop + * default activeOpacity=0.8 + * + * + * Outlined and add borderColor equal with backgroundColor + * + * + * Disabling the button + * + * + * + * Add flex to button style + * + * + * + * Add height to button style + * + * + */ + +const Button: React.FC = (props) => { + const getSpacings = (type: "margin" | "padding") => { + const { + margin, + marginTop, + marginRight, + marginBottom, + marginLeft, + marginVertical, + marginHorizontal, + padding, + paddingTop, + paddingRight, + paddingBottom, + paddingLeft, + paddingVertical, + paddingHorizontal, + theme + } = props; + const { SIZES } = mergeTheme(expoTheme, theme); + + if (type === "margin") { + return [ + margin && getSpacing(type, margin, SIZES.base), + marginTop && parseSpacing("marginTop", marginTop, SIZES.base), + marginRight && parseSpacing("marginRight", marginRight, SIZES.base), + marginBottom && parseSpacing("marginBottom", marginBottom, SIZES.base), + marginLeft && parseSpacing("marginLeft", marginLeft, SIZES.base), + marginVertical && + parseSpacing("marginVertical", marginVertical, SIZES.base), + marginHorizontal && + parseSpacing("marginHorizontal", marginHorizontal, SIZES.base) + ]; + } + + if (type === "padding") { + return [ + padding && getSpacing(type, padding, SIZES.base), + paddingTop && parseSpacing("paddingTop", paddingTop, SIZES.base), + paddingRight && parseSpacing("paddingRight", paddingRight, SIZES.base), + paddingBottom && + parseSpacing("paddingBottom", paddingBottom, SIZES.base), + paddingLeft && parseSpacing("paddingLeft", paddingLeft, SIZES.base), + paddingVertical && + parseSpacing("paddingVertical", paddingVertical, SIZES.base), + paddingHorizontal && + parseSpacing("paddingHorizontal", paddingHorizontal, SIZES.base) + ]; + } + }; + const { + disabled, + opacity, + outlined, + flex, + height, + // colors + color, + transparent, + primary, + secondary, + tertiary, + black, + white, + gray, + error, + warning, + success, + info, + // support for touchables + highlight, + nativeFeedback, + withoutFeedback, + theme, + style, + children + } = props; + + const excludeProps = [ + "margin", + "marginTop", + "marginRight", + "marginBottom", + "marginLeft", + "marginVertical", + "marginHorizontal", + "padding", + "paddingTop", + "paddingRight", + "paddingBottom", + "paddingLeft", + "paddingVertical", + "paddingHorizontal" + ]; + const extraProps = Object.keys(props).reduce>( + (prop, key) => { + if (!excludeProps.includes(`${key}`)) { + prop[key] = props[key]; + } + return prop; + }, + {} + ); + + const { SIZES, COLORS } = mergeTheme({ ...expoTheme }, theme); + const marginSpacing = getSpacings("margin"); + const paddingSpacing = getSpacings("padding"); + + const buttonStyles = StyleSheet.flatten([ + { + height: SIZES.base * 5.5, + borderRadius: SIZES.radius, + backgroundColor: COLORS.primary, + justifyContent: "center" + }, + transparent && { backgroundColor: "transparent" }, + primary && { backgroundColor: COLORS.primary }, + secondary && { backgroundColor: COLORS.secondary }, + tertiary && { backgroundColor: COLORS.tertiary }, + black && { backgroundColor: COLORS.black }, + white && { backgroundColor: COLORS.white }, + gray && { backgroundColor: COLORS.gray }, + error && { backgroundColor: COLORS.error }, + warning && { backgroundColor: COLORS.warning }, + success && { backgroundColor: COLORS.success }, + info && { backgroundColor: COLORS.info }, + color && { backgroundColor: color }, // custom backgroundColor + flex && { flex }, // flex width + height && { height }, // custom height + marginSpacing, + paddingSpacing, + style + ]); + + if (disabled) { + const backgroundColor = StyleSheet.flatten(buttonStyles).backgroundColor; + buttonStyles.backgroundColor = rgba(backgroundColor, 0.5); + } + + if (outlined) { + const backgroundColor = StyleSheet.flatten(buttonStyles).backgroundColor; + buttonStyles.borderWidth = 1; + buttonStyles.borderColor = backgroundColor; + buttonStyles.backgroundColor = "transparent"; + } + if (highlight) { + return ( + + {children} + + ); + } + if (nativeFeedback) { + return ( + + {children} + + ); + } + if (withoutFeedback) { + return ( + + {children} + + ); + } + + return ( + + {children} + + ); +}; + +Button.defaultProps = { + color: null, + disabled: false, + opacity: 0.8, + outlined: false, + margin: null, + padding: null, + flex: 0, + transparent: false, + primary: false, + secondary: false, + tertiary: false, + black: false, + white: false, + gray: false, + error: false, + warning: false, + success: false, + info: false, + theme: {}, + style: {} +}; + +export default Button; diff --git a/src/Card.tsx b/src/Card.tsx new file mode 100644 index 0000000..f0c7c77 --- /dev/null +++ b/src/Card.tsx @@ -0,0 +1,106 @@ +import React from "react"; +import { StyleSheet } from "react-native"; +import Block from "./Block"; +import expoTheme from "./theme"; +import { CardProps } from "./types"; +import { mergeTheme, rgba } from "./utils/index"; + +/** + * https://facebook.github.io/react-native/docs/view + * https://facebook.github.io/react-native/docs/flexbox + * + * Using Block component with predefined props: color, radius and padding + * + * default card + * + * + * Border radius using radius props + * + * + * radius={8} + * + * + * Padding using padding props + * default padding={SIZES.base} + * + * + * padding={12} + * + * + * Set shadow using shadow props + * default shadow with color black and elevation + * shadowOffset is calculated using elevation - 1 + * shadowRadius is equal with elevation value + * + * + * shadow + * + * + * + * shadow elevation={2} + * + * + * Set borderColor using outlined prop + * default borderWidth: 1 and borderColor: rgba(COLORS.black, 0.16) with alpha 0.16 + * + * + * outlined + * + * + */ + +const Card: React.FC = (props) => { + const { + color, + radius, + padding, + shadow, + elevation, + outlined, + theme, + style, + children, + ...rest + } = props; + + const { SIZES, COLORS } = mergeTheme({ ...expoTheme }, theme); + + const cardStyles = StyleSheet.flatten([ + shadow && { + elevation, + shadowColor: COLORS.black, + shadowOffset: { width: 0, height: elevation - 1 }, + shadowOpacity: 0.1, + shadowRadius: elevation + }, + outlined && { + borderWidth: 1, + borderColor: rgba(COLORS.black, 0.16) + }, + style + ]); + + return ( + + {children} + + ); +}; + +Card.defaultProps = { + color: null, + radius: null, + padding: null, + shadow: false, + elevation: 3, + outlined: false, + theme: {}, + style: {} +}; + +export default Card; diff --git a/src/Input.tsx b/src/Input.tsx new file mode 100644 index 0000000..a07f530 --- /dev/null +++ b/src/Input.tsx @@ -0,0 +1,178 @@ +import React, { useReducer } from "react"; +import { StyleSheet, TextInput } from "react-native"; +import expoTheme from "./theme"; +import { InputAction, InputProps, InputState } from "./types"; +import { mergeTheme, rgba } from "./utils/index"; + +/** + * https://facebook.github.io/react-native/docs/textinput + * + * Validation + * onValidation return a single boolean or object with boolean values + * pattern using regex string for validating the value + * + * single pattern to validate the value + * console.log(isValid)} + * /> + * + * multiple pattern to validate the value + * console.log(isValid)} + * /> + * + * Border color using color prop + * + * + * Pass ref from props using internalRef reference + * this.c} /> + */ + +export const INITIAL_STATE: InputState = { + value: null, + focused: false, + blurred: false +}; + +export const change = (value: any) => { + return { type: "change", payload: { value } }; +}; +export const focus = () => { + return { type: "focus" }; +}; +export const blur = () => { + return { type: "blur" }; +}; + +export const reducer = (state: InputState, action: InputAction) => { + switch (action.type) { + case "change": + return { ...state, value: action.payload.value }; + case "focus": + return { ...state, focused: true, blurred: false }; + case "blur": + return { ...state, focused: false, blurred: true }; + default: + return state; + } +}; + +const Input: React.FC = (props) => { + const [state, dispatch] = useReducer(reducer, INITIAL_STATE); + + const handleValidation = (value) => { + const { pattern } = props; + if (!pattern) return true; + + // string pattern, one validation rule + if (typeof pattern === "string") { + const condition = new RegExp(pattern, "g"); + return condition.test(value); + } + + // array patterns, multiple validation rules + if (typeof pattern === "object") { + const conditions = pattern.map((rule) => new RegExp(rule, "g")); + return conditions.map((condition) => condition.test(value)); + } + }; + + const handleChange = (value) => { + const { onChangeText, onValidation } = props; + const isValid = handleValidation(value); + dispatch(change(value)); + onValidation && onValidation(isValid); + onChangeText && onChangeText(value); + }; + + const handleFocus = (event) => { + const { onFocus } = props; + dispatch(focus()); + onFocus && onFocus(event); + }; + + const handleBlur = (event) => { + const { onBlur } = props; + dispatch(blur()); + onBlur && onBlur(event); + }; + + const handleTextType = (type) => { + return type === "email" + ? "emailAddress" + : type === "phone" + ? "telephoneNumber" + : type; + }; + + const { + autoCorrect, + autoCapitalize, + placeholder, + children, + color, + type, + style, + theme, + internalRef, + onFocus, + onBlur, + onChangeText, + ...rest + } = props; + const { SIZES, COLORS } = mergeTheme({ ...expoTheme }, theme); + + const textStyles = StyleSheet.flatten([ + { + borderWidth: 1, + height: SIZES.base * 5.5, + borderRadius: SIZES.radius, + borderColor: rgba(color || COLORS.primary, 0.4), + paddingHorizontal: SIZES.base, + fontSize: SIZES.font + }, + style + ]); + const textType = handleTextType(type); + + const internalProps = { + style: textStyles, + autoCorrect, + autoCapitalize, + placeholder, + textContentType: textType, + value: state.value, + onFocus: handleFocus, + onBlur: handleBlur, + onChangeText: handleChange + }; + + return ( + + {children} + + ); +}; + +Input.defaultProps = { + pattern: null, + onFocus: null, + onBlur: null, + onChangeText: null, + onValidation: null, + placeholder: null, + autoCorrect: false, + autoCapitalize: "none", + color: null, + internalRef: null, + theme: {}, + style: {} +}; + +export default Input; diff --git a/src/Text.tsx b/src/Text.tsx new file mode 100644 index 0000000..4757001 --- /dev/null +++ b/src/Text.tsx @@ -0,0 +1,297 @@ +import React from "react"; +import { Animated, StyleSheet, Text } from "react-native"; +import { ExtraProps } from "./global"; +import expoTheme from "./theme"; +import { TextProps } from "./types"; +import { getSpacing, mergeTheme, parseSpacing } from "./utils/index"; + +/** + * Usage: + * fontSize predefined by theme.js + * - fontSize of 34 from FONTS.h1 + * - fontSize of 24 from FONTS.h2 + * - fontSize of 20 from FONTS.h3 + * - fontSize of 18 from FONTS.title + * - fontSize of 14 from FONTS.subtitle + * - fontSize of 12 from FONTS.caption + * - fontSize of 10 from FONTS.small + * fontSize defined by user + * - fontSize of 20 + * + * margin & padding + * - set margin 4 to: top, right, bottom & left + * - set margin 6 to: top, right, bottom & left + * - margin + Top | Bottom | Left | Right | Vertical | Horizontal + * - padding + Top | Bottom | Left | Right | Vertical | Horizontal + * + * text styling + * - textTransform: capitalize, lowercase, uppercase + * - fontWeight from WEIGHTS.regular + * - fontWeight from WEIGHTS.bold + * - fontWeight from WEIGHTS.semibold + * - fontWeight from WEIGHTS.medium + * - fontWeight from WEIGHTS.light + * - fontWeight from user input + * + * text colors + * - color from COLORS.primary + * - color from COLORS.secondary + * - color from COLORS.tertiary + * - color from COLORS.black + * - color from COLORS.white + * - color from COLORS.gray + * - color from COLORS.info + * - color from COLORS.success + * - color from COLORS.warning + * - color from COLORS.error + * - color from user input + * + * custom theme using the src/theme.js data structure + * - create a custom theme by defining: const customTheme.js + * - with the following structure to rewrite any value + * { + * COLORS: { + * primary: "cyan" or "#8A00D4", + * secondary: "fucsia" or "#D527B7", + * tertiary: "yellow" or "#FFC46B" + * }, + * SIZES: { + * font: 15, + * h1: 28 + * title: 17 + * } + * } + * - include the custom theme to the component props + * primary using new color: #8A00D4 + * + * animating text can be used using the "animated" props + * - will render Animated.Text + */ + +const Typography: React.FC = (props) => { + const getSpacings = (type) => { + const { + margin, + marginTop, + marginRight, + marginBottom, + marginLeft, + marginVertical, + marginHorizontal, + padding, + paddingTop, + paddingRight, + paddingBottom, + paddingLeft, + paddingVertical, + paddingHorizontal, + theme + } = props; + const { SIZES } = mergeTheme(expoTheme, theme); + + if (type === "margin") { + return [ + margin && getSpacing(type, margin, SIZES.base), + marginTop && parseSpacing("marginTop", marginTop, SIZES.base), + marginRight && parseSpacing("marginRight", marginRight, SIZES.base), + marginBottom && parseSpacing("marginBottom", marginBottom, SIZES.base), + marginLeft && parseSpacing("marginLeft", marginLeft, SIZES.base), + marginVertical && + parseSpacing("marginVertical", marginVertical, SIZES.base), + marginHorizontal && + parseSpacing("marginHorizontal", marginHorizontal, SIZES.base) + ]; + } + + if (type === "padding") { + return [ + padding && getSpacing(type, padding, SIZES.base), + paddingTop && parseSpacing("paddingTop", paddingTop, SIZES.base), + paddingRight && parseSpacing("paddingRight", paddingRight, SIZES.base), + paddingBottom && + parseSpacing("paddingBottom", paddingBottom, SIZES.base), + paddingLeft && parseSpacing("paddingLeft", paddingLeft, SIZES.base), + paddingVertical && + parseSpacing("paddingVertical", paddingVertical, SIZES.base), + paddingHorizontal && + parseSpacing("paddingHorizontal", paddingHorizontal, SIZES.base) + ]; + } + }; + + const { + // fonts & sizes + h1, + h2, + h3, + title, + subtitle, + caption, + small, + size, + // styling + transform, + regular, + bold, + semibold, + medium, + weight, + light, + center, + right, + spacing, // letter-spacing + height, // line-height + // colors + color, + primary, + secondary, + tertiary, + black, + white, + gray, + error, + warning, + success, + info, + animated, + theme, + style, + children, + ...rest + } = props; + + const excludeProps = [ + "margin", + "marginTop", + "marginRight", + "marginBottom", + "marginLeft", + "marginVertical", + "marginHorizontal", + "padding", + "paddingTop", + "paddingRight", + "paddingBottom", + "paddingLeft", + "paddingVertical", + "paddingHorizontal" + ]; + const extraProps = Object.keys(props).reduce>( + (prop, key) => { + if (!excludeProps.includes(`${key}`)) { + prop[key] = props[key]; + } + return prop; + }, + {} + ); + + const { SIZES, COLORS, FONTS, WEIGHTS } = mergeTheme({ ...expoTheme }, theme); + + const marginSpacing = getSpacings("margin"); + const paddingSpacing = getSpacings("padding"); + + const textStyles = StyleSheet.flatten([ + { + fontWeight: WEIGHTS.regular, + fontSize: SIZES.font, + color: COLORS.font + }, + h1 && FONTS.h1, + h2 && FONTS.h2, + h3 && FONTS.h3, + title && FONTS.title, + subtitle && FONTS.subtitle, + caption && FONTS.caption, + small && FONTS.small, + size && { fontSize: size }, + marginSpacing, + paddingSpacing, + transform && { textTransform: transform }, + height && { lineHeight: height }, + spacing && { letterSpacing: spacing }, + weight && { fontWeight: weight }, + regular && { fontWeight: WEIGHTS.regular }, + bold && { fontWeight: WEIGHTS.bold }, + semibold && { fontWeight: WEIGHTS.semibold }, + medium && { fontWeight: WEIGHTS.medium }, + light && { fontWeight: WEIGHTS.light }, + center && styles.center, + right && styles.right, + // color shortcuts + primary && { color: COLORS.primary }, + secondary && { color: COLORS.secondary }, + tertiary && { color: COLORS.tertiary }, + black && { color: COLORS.black }, + white && { color: COLORS.white }, + gray && { color: COLORS.gray }, + error && { color: COLORS.error }, + warning && { color: COLORS.warning }, + success && { color: COLORS.success }, + info && { color: COLORS.info }, + color && { color }, + style // rewrite predefined styles + ]); + + if (animated) { + return ( + + {children} + + ); + } + + return ( + + {children} + + ); +}; + +Typography.defaultProps = { + // fonts & sizes + h1: false, + h2: false, + h3: false, + title: false, + subtitle: false, + caption: false, + small: false, + size: null, + margin: null, + padding: null, + // styling + transform: null, + regular: false, + bold: false, + semibold: false, + medium: false, + weight: false, + light: false, + center: false, + right: false, + spacing: null, // letter-spacing + height: null, // line-height + // colors + color: null, + primary: false, + secondary: false, + tertiary: false, + black: false, + white: false, + gray: false, + error: false, + warning: false, + success: false, + info: false, + theme: {}, + style: {} +}; + +export default Typography; + +const styles = StyleSheet.create({ + // positioning + center: { textAlign: "center" }, + right: { textAlign: "right" } +}); diff --git a/src/__tests__/Block.test.tsx b/src/__tests__/Block.test.tsx new file mode 100644 index 0000000..b67c1c5 --- /dev/null +++ b/src/__tests__/Block.test.tsx @@ -0,0 +1,526 @@ +import { shallow } from "enzyme"; +import React from "react"; +import { StyleSheet } from "react-native"; +import renderer from "react-test-renderer"; +import Block from "../Block"; +import { SIZES } from "../theme"; + +const customTheme = { + COLORS: { + primary: "red" + } +}; + +describe("", () => { + it("render default", () => { + const component = renderer.create().toJSON(); + const style = StyleSheet.flatten(component.props.style); + expect(style.flex).toEqual(1); + }); + + it("testing flex, flex={0.5}, flex={false}", () => { + const component = shallow(flex); + let style = StyleSheet.flatten(component.props().style); + expect(style.flex).toEqual(1); + + component.setProps({ flex: 0.5 }); + style = StyleSheet.flatten(component.props().style); + expect(style.flex).toEqual(0.5); + + component.setProps({ flex: true }); + style = StyleSheet.flatten(component.props().style); + expect(style.flex).toEqual(1); + + component.setProps({ flex: 0 }); + style = StyleSheet.flatten(component.props().style); + expect(style.flex).toEqual(0); + }); + + it("testing flexDirection, row & column", () => { + const component = shallow(flexDirection); + + let style = StyleSheet.flatten(component.props().style); + expect(style.flexDirection).toEqual("row"); + + component.setProps({ column: true }); + style = StyleSheet.flatten(component.props().style); + expect(style.flexDirection).toEqual("column"); + }); + + it("center", () => { + const component = renderer.create().toJSON(); + const style = StyleSheet.flatten(component.props.style); + expect(style.alignItems).toEqual("center"); + }); + + it("middle", () => { + const component = renderer.create().toJSON(); + const style = StyleSheet.flatten(component.props.style); + expect(style.justifyContent).toEqual("center"); + }); + + it("left", () => { + const component = renderer.create().toJSON(); + const style = StyleSheet.flatten(component.props.style); + expect(style.justifyContent).toEqual("flex-start"); + }); + + it("right", () => { + const component = renderer.create().toJSON(); + const style = StyleSheet.flatten(component.props.style); + expect(style.justifyContent).toEqual("flex-end"); + }); + + it("top", () => { + const component = renderer.create().toJSON(); + const style = StyleSheet.flatten(component.props.style); + expect(style.justifyContent).toEqual("flex-start"); + }); + + it("bottom", () => { + const component = renderer.create().toJSON(); + const style = StyleSheet.flatten(component.props.style); + expect(style.justifyContent).toEqual("flex-end"); + }); + + it("wrap", () => { + const component = renderer.create().toJSON(); + const style = StyleSheet.flatten(component.props.style); + expect(style.flexWrap).toEqual("wrap"); + }); + + it("padding={4}", () => { + const block = renderer.create(); + + const component = block.toJSON(); + const instance = block.root; + + const style = StyleSheet.flatten(component.props.style); + expect(instance.props.padding).toEqual(4); + expect(style).toEqual({ + flex: 1, + paddingBottom: 4, + paddingLeft: 4, + paddingRight: 4, + paddingTop: 4 + }); + }); + + it("padding={[2, 4]}", () => { + const block = renderer.create(); + + const component = block.toJSON(); + const instance = block.root; + + const style = StyleSheet.flatten(component.props.style); + expect(instance.props.padding).toEqual([2, 4]); + expect(style).toEqual({ + flex: 1, + paddingBottom: 2, + paddingLeft: 4, + paddingRight: 4, + paddingTop: 2 + }); + }); + + it("padding={[1, 2, 3, 4]}", () => { + const block = renderer.create(); + + const component = block.toJSON(); + const instance = block.root; + + const style = StyleSheet.flatten(component.props.style); + expect(instance.props.padding).toEqual([1, 2, 3, 4]); + expect(style).toEqual({ + flex: 1, + paddingBottom: 3, + paddingLeft: 4, + paddingRight: 2, + paddingTop: 1 + }); + }); + + it("paddingTop={6}, paddingRight={5}, paddingBottom={4}, paddingLeft={3}", () => { + const block = renderer.create( + + ); + + const component = block.toJSON(); + const instance = block.root; + + const style = StyleSheet.flatten(component.props.style); + expect(instance.props.paddingTop).toEqual(6); + expect(instance.props.paddingRight).toEqual(5); + expect(instance.props.paddingBottom).toEqual(4); + expect(instance.props.paddingLeft).toEqual(3); + expect(style).toEqual({ + flex: 1, + paddingLeft: 3, + paddingBottom: 4, + paddingRight: 5, + paddingTop: 6 + }); + }); + + it("paddingTop='2x', paddingRight='3x', paddingBottom='4x', paddingLeft='5x'", () => { + const block = renderer.create( + + ); + + const component = block.toJSON(); + const instance = block.root; + + const style = StyleSheet.flatten(component.props.style); + expect(instance.props.paddingTop).toEqual("2x"); + expect(instance.props.paddingRight).toEqual("3x"); + expect(instance.props.paddingBottom).toEqual("4x"); + expect(instance.props.paddingLeft).toEqual("5x"); + expect(style).toEqual({ + flex: 1, + paddingLeft: 40, + paddingBottom: 32, + paddingRight: 24, + paddingTop: 16 + }); + }); + + it("paddingHorizontal={6}, paddingVertical={8}", () => { + const block = renderer.create( + + ); + + const component = block.toJSON(); + const instance = block.root; + + const style = StyleSheet.flatten(component.props.style); + expect(instance.props.paddingHorizontal).toEqual(6); + expect(instance.props.paddingVertical).toEqual(8); + expect(style).toEqual({ + flex: 1, + paddingVertical: 8, + paddingHorizontal: 6 + }); + }); + + it("paddingHorizontal='2x', paddingVertical='0.5x'", () => { + const block = renderer.create( + + ); + + const component = block.toJSON(); + const instance = block.root; + + const style = StyleSheet.flatten(component.props.style); + expect(instance.props.paddingHorizontal).toEqual("2x"); + expect(instance.props.paddingVertical).toEqual("0.5x"); + expect(style).toEqual({ + flex: 1, + paddingVertical: 4, + paddingHorizontal: 16 + }); + }); + + it("margin={6}", () => { + const block = renderer.create(); + + const component = block.toJSON(); + const instance = block.root; + + const style = StyleSheet.flatten(component.props.style); + expect(instance.props.margin).toEqual(6); + expect(style).toEqual({ + flex: 1, + marginBottom: 6, + marginLeft: 6, + marginRight: 6, + marginTop: 6 + }); + }); + + it("margin={[2, 4]}", () => { + const block = renderer.create(); + + const component = block.toJSON(); + const instance = block.root; + + const style = StyleSheet.flatten(component.props.style); + expect(instance.props.margin).toEqual([2, 4]); + expect(style).toEqual({ + flex: 1, + marginBottom: 2, + marginLeft: 4, + marginRight: 4, + marginTop: 2 + }); + }); + + it("margin={[1, 2, 3, 4]}", () => { + const block = renderer.create(); + + const component = block.toJSON(); + const instance = block.root; + + const style = StyleSheet.flatten(component.props.style); + expect(instance.props.margin).toEqual([1, 2, 3, 4]); + expect(style).toEqual({ + flex: 1, + marginBottom: 3, + marginLeft: 4, + marginRight: 2, + marginTop: 1 + }); + }); + + it("marginTop={6}, marginRight={5}, marginBottom={4}, marginLeft={3}", () => { + const block = renderer.create( + + ); + + const component = block.toJSON(); + const instance = block.root; + + const style = StyleSheet.flatten(component.props.style); + expect(instance.props.marginTop).toEqual(6); + expect(instance.props.marginRight).toEqual(5); + expect(instance.props.marginBottom).toEqual(4); + expect(instance.props.marginLeft).toEqual(3); + expect(style).toEqual({ + flex: 1, + marginLeft: 3, + marginBottom: 4, + marginRight: 5, + marginTop: 6 + }); + }); + + it("marginTop='2x', marginRight='3x', marginBottom='4x', marginLeft='5x'", () => { + const block = renderer.create( + + ); + + const component = block.toJSON(); + const instance = block.root; + + const style = StyleSheet.flatten(component.props.style); + expect(instance.props.marginTop).toEqual("2x"); + expect(instance.props.marginRight).toEqual("3x"); + expect(instance.props.marginBottom).toEqual("4x"); + expect(instance.props.marginLeft).toEqual("5x"); + expect(style).toEqual({ + flex: 1, + marginLeft: 40, + marginBottom: 32, + marginRight: 24, + marginTop: 16 + }); + }); + + it("marginHorizontal={6}, marginVertical={8}", () => { + const block = renderer.create( + + ); + + const component = block.toJSON(); + const instance = block.root; + + const style = StyleSheet.flatten(component.props.style); + expect(instance.props.marginHorizontal).toEqual(6); + expect(instance.props.marginVertical).toEqual(8); + expect(style).toEqual({ + flex: 1, + marginVertical: 8, + marginHorizontal: 6 + }); + }); + + it("marginHorizontal='2x', marginVertical='0.5x'", () => { + const block = renderer.create( + + ); + + const component = block.toJSON(); + const instance = block.root; + + const style = StyleSheet.flatten(component.props.style); + expect(instance.props.marginHorizontal).toEqual("2x"); + expect(instance.props.marginVertical).toEqual("0.5x"); + expect(style).toEqual({ + flex: 1, + marginVertical: 4, + marginHorizontal: 16 + }); + }); + + it("animated", () => { + const component = shallow(); + const block = renderer.create(); + + const instance = block.root; + + expect(instance.props.animated).toEqual(true); + expect(component.name()).toEqual("AnimatedComponent"); + }); + + it("safe", () => { + const component = shallow(); + const block = renderer.create(); + + const instance = block.root; + + expect(instance.props.safe).toEqual(true); + expect(component.name()).toEqual("SafeAreaView"); + }); + + it("shadow", () => { + const block = renderer.create(); + + const component = block.toJSON(); + const instance = block.root; + + const style = StyleSheet.flatten(component.props.style); + + expect(instance.props.shadow).toEqual(true); + expect(style.elevation).toEqual(3); + expect(style.shadowColor).toEqual("#000020"); + expect(style.shadowOffset).toEqual({ width: 0, height: 2 }); + expect(style.shadowOpacity).toEqual(0.1); + expect(style.shadowRadius).toEqual(3); + }); + + it('space="between"', () => { + const block = renderer.create(); + + const component = block.toJSON(); + const instance = block.root; + + const style = StyleSheet.flatten(component.props.style); + expect(instance.props.space).toEqual("between"); + expect(style.justifyContent).toEqual("space-between"); + }); + + it("card", () => { + const block = renderer.create(); + + const component = block.toJSON(); + const instance = block.root; + + const style = StyleSheet.flatten(component.props.style); + expect(instance.props.card).toEqual(true); + //!TODO: border value + expect(style.borderRadius).toEqual(SIZES.height); + }); + + it("radius={4}", () => { + const block = renderer.create(); + + const component = block.toJSON(); + const instance = block.root; + + const style = StyleSheet.flatten(component.props.style); + expect(instance.props.radius).toEqual(4); + expect(style.borderRadius).toEqual(4); + }); + + it("colors: primary, secondary, tertiary, black, white, gray, alert, warning, success, info, color", () => { + const component = shallow(block color); + let style = StyleSheet.flatten(component.props().style); + expect(style.backgroundColor).toEqual(undefined); + + component.setProps({ primary: true }); + style = StyleSheet.flatten(component.props().style); + expect(style.backgroundColor).toEqual("#4630EB"); + + component.setProps({ secondary: true }); + style = StyleSheet.flatten(component.props().style); + expect(style.backgroundColor).toEqual("#A3A1F7"); + + component.setProps({ tertiary: true }); + style = StyleSheet.flatten(component.props().style); + expect(style.backgroundColor).toEqual("#FFE358"); + + component.setProps({ black: true }); + style = StyleSheet.flatten(component.props().style); + expect(style.backgroundColor).toEqual("#000020"); + + component.setProps({ white: true }); + style = StyleSheet.flatten(component.props().style); + expect(style.backgroundColor).toEqual("#FFFFFF"); + + component.setProps({ gray: true }); + style = StyleSheet.flatten(component.props().style); + expect(style.backgroundColor).toEqual("#535453"); + + component.setProps({ error: true }); + style = StyleSheet.flatten(component.props().style); + expect(style.backgroundColor).toEqual("#DC3545"); + + component.setProps({ warning: true }); + style = StyleSheet.flatten(component.props().style); + expect(style.backgroundColor).toEqual("#FFE358"); + + component.setProps({ success: true }); + style = StyleSheet.flatten(component.props().style); + expect(style.backgroundColor).toEqual("#4CD964"); + + component.setProps({ info: true }); + style = StyleSheet.flatten(component.props().style); + expect(style.backgroundColor).toEqual("#4DA1FF"); + + component.setProps({ color: "#88B04B" }); + style = StyleSheet.flatten(component.props().style); + expect(style.backgroundColor).toEqual("#88B04B"); + }); + + it("custom theme for primary color", () => { + const block = renderer.create( + + custom theme color + + ); + + const component = block.toJSON(); + const instance = block.root; + + expect(instance.props.theme).toEqual(customTheme); + + const style = StyleSheet.flatten(component.props.style); + + expect(style.backgroundColor).toEqual("red"); + }); + + it("render ScrollView component", () => { + const component = shallow(); + + expect(component.props().scroll).toEqual(true); + expect(component.name()).toEqual("ScrollViewMock"); + }); + + it("width={100}", () => { + const component = shallow(); + const style = StyleSheet.flatten(component.props().style); + + expect(style.width).toEqual(100); + }); + + it("height={100}", () => { + const component = shallow(); + const style = StyleSheet.flatten(component.props().style); + + expect(style.height).toEqual(100); + }); +}); diff --git a/src/__tests__/Button.test.tsx b/src/__tests__/Button.test.tsx new file mode 100644 index 0000000..d2aa94c --- /dev/null +++ b/src/__tests__/Button.test.tsx @@ -0,0 +1,370 @@ +import { shallow } from "enzyme"; +import React from "react"; +import { StyleSheet } from "react-native"; +import renderer from "react-test-renderer"; +import Button from "../Button"; +import Text from "../Text"; +import { SIZES } from "../theme"; +import { ButtonProps } from "../types"; +import { rgba } from "../utils"; + +describe(" + ); + + expect(component.props().highlight).toEqual(true); + expect(component.name()).toEqual("TouchableHighlight"); + }); + + it("ButtonType: withoutFeedback", () => { + const component = shallow( + + ); + + expect(component.props().withoutFeedback).toEqual(true); + expect(component.name()).toEqual("TouchableWithoutFeedback"); + }); + + it("onPress", () => { + const onPress = jest.fn(); + const component = shallow( ); + const buttonType = shallow( + + + + ); + expect(component.props().highlight).toEqual(true); - expect(component.name()).toEqual("TouchableHighlight"); + expect(buttonType.name()).toEqual("TouchableHighlight"); }); it("ButtonType: withoutFeedback", () => { @@ -356,9 +372,14 @@ describe(" ); + const buttonType = shallow( + + + + ); expect(component.props().withoutFeedback).toEqual(true); - expect(component.name()).toEqual("TouchableWithoutFeedback"); + expect(buttonType.name()).toEqual("TouchableWithoutFeedback"); }); it("onPress", () => { @@ -367,4 +388,26 @@ describe(" diff --git a/src/__tests__/Card.test.tsx b/src/__tests__/Card.test.js similarity index 100% rename from src/__tests__/Card.test.tsx rename to src/__tests__/Card.test.js diff --git a/src/__tests__/Input.test.tsx b/src/__tests__/Input.test.js similarity index 100% rename from src/__tests__/Input.test.tsx rename to src/__tests__/Input.test.js diff --git a/src/__tests__/Text.test.tsx b/src/__tests__/Text.test.js similarity index 99% rename from src/__tests__/Text.test.tsx rename to src/__tests__/Text.test.js index 97d9e04..3c7e34b 100644 --- a/src/__tests__/Text.test.tsx +++ b/src/__tests__/Text.test.js @@ -303,13 +303,13 @@ describe("", () => { it('transform="uppercase"', () => { const component = shallow(uppercase); - let style = StyleSheet.flatten(component.props().style); + const style = StyleSheet.flatten(component.props().style); expect(style.textTransform).toEqual("uppercase"); }); it("lineHeight using height={32}", () => { const component = shallow(lineHeight 32); - let style = StyleSheet.flatten(component.props().style); + const style = StyleSheet.flatten(component.props().style); expect(style.lineHeight).toEqual(32); }); diff --git a/src/__tests__/helpers.test.tsx b/src/__tests__/helpers.test.js similarity index 100% rename from src/__tests__/helpers.test.tsx rename to src/__tests__/helpers.test.js diff --git a/src/types/types.ts b/src/index.d.ts similarity index 74% rename from src/types/types.ts rename to src/index.d.ts index 9b2774f..c161660 100644 --- a/src/types/types.ts +++ b/src/index.d.ts @@ -1,7 +1,4 @@ -/** - * Component Types - */ - +import React from "react"; import { NativeSyntheticEvent, TextInputFocusEventData, @@ -187,3 +184,70 @@ export interface CardProps extends CardOptions, ThemeProps { } export interface InputProps extends InputOptions, ThemeProps {} + +export declare const Block: React.FC; +export declare const styles: { + block: { + flex: number; + }; + row: { + flexDirection: "row"; + }; + column: { + flexDirection: "column"; + }; + center: { + alignItems: "center"; + }; + middle: { + justifyContent: "center"; + }; + left: { + justifyContent: "flex-start"; + }; + right: { + justifyContent: "flex-end"; + }; + top: { + justifyContent: "flex-start"; + }; + bottom: { + justifyContent: "flex-end"; + }; + wrap: { + flexWrap: "wrap"; + }; +}; +export declare const RenderButton: ({ + Touchable, + children, + ...props +}: RenderButtonProps) => JSX.Element; +export declare const Button: React.FC< + ButtonProps & TouchableWithoutFeedbackProps & TouchableNativeFeedbackProps +>; + +export declare const Card: React.FC; + +export declare const INITIAL_STATE: InputState; +export declare const change: ( + value: any +) => { + type: string; + payload: { + value: any; + }; +}; +export declare const focus: () => { + type: string; +}; +export declare const blur: () => { + type: string; +}; +export declare const reducer: ( + state: InputState, + action: InputAction +) => InputState; +export declare const Input: React.FC; + +export declare const Typography: React.FC; diff --git a/src/index.tsx b/src/index.js similarity index 100% rename from src/index.tsx rename to src/index.js diff --git a/src/theme.ts b/src/theme.js similarity index 86% rename from src/theme.ts rename to src/theme.js index 2a59628..d913701 100644 --- a/src/theme.ts +++ b/src/theme.js @@ -1,10 +1,8 @@ import { Dimensions } from "react-native"; -import { Colors, Fonts, Sizes, Weights } from "./global"; - const { width, height } = Dimensions.get("window"); -export const COLORS: Colors = { +export const COLORS = { // default font color font: "#000000", @@ -25,7 +23,7 @@ export const COLORS: Colors = { info: "#4DA1FF" }; -export const SIZES: Sizes = { +export const SIZES = { // global sizes base: 8, font: 16, @@ -46,7 +44,7 @@ export const SIZES: Sizes = { height }; -export const FONTS: Fonts = { +export const FONTS = { h1: { fontSize: SIZES.h1, letterSpacing: 0.15 }, h2: { fontSize: SIZES.h2, letterSpacing: 0 }, h3: { fontSize: SIZES.h3, letterSpacing: 0.15 }, @@ -56,7 +54,7 @@ export const FONTS: Fonts = { small: { fontSize: SIZES.small, letterSpacing: 1.5 } }; -export const WEIGHTS: Weights = { +export const WEIGHTS = { regular: "normal", bold: "bold", semibold: "500", diff --git a/src/utils/helpers.ts b/src/utils/helpers.js similarity index 97% rename from src/utils/helpers.ts rename to src/utils/helpers.js index 693a6b8..ee9236b 100644 --- a/src/utils/helpers.ts +++ b/src/utils/helpers.js @@ -16,8 +16,6 @@ * const marginSpacing = spacing("margin", "0.5x", 12); // multiply 0.5 * 10 => margin 6 */ -import { CustomTheme, DefaultTheme } from "../global"; - export const spacing = (type, value, defaultValue = 1) => { // accept only 2 types: margin & padding const accepted = ["margin", "padding"]; @@ -194,10 +192,7 @@ export const getMargins = (value, defaultValue = 1) => { } }; -export const getPaddings = ( - value: "number" | "object" | "string", - defaultValue = 1 -) => { +export const getPaddings = (value, defaultValue = 1) => { if (typeof value === "number") { return { paddingTop: value, @@ -289,7 +284,7 @@ export const getPaddings = ( * COLORS.secondary will return value "green" */ -export const mergeTheme = (theme: DefaultTheme, extra: CustomTheme) => { +export const mergeTheme = (theme, extra) => { const { COLORS, SIZES, FONTS, WEIGHTS, ...REST } = extra; return { COLORS: { ...theme.COLORS, ...COLORS }, diff --git a/src/utils/index.ts b/src/utils/index.js similarity index 100% rename from src/utils/index.ts rename to src/utils/index.js diff --git a/src/utils/rgba.ts b/src/utils/rgba.js similarity index 77% rename from src/utils/rgba.ts rename to src/utils/rgba.js index 81d4e21..4892e9a 100644 --- a/src/utils/rgba.ts +++ b/src/utils/rgba.js @@ -2,12 +2,9 @@ // NPM: https://www.npmjs.com/package/hex-to-rgba // GitHub: https://github.com/misund/hex-to-rgba -import { RGBA } from "../global"; +const removeHash = (hex) => (hex.charAt(0) === "#" ? hex.slice(1) : hex); -const removeHash = (hex: string): string => - hex.charAt(0) === "#" ? hex.slice(1) : hex; - -const parseHex = (nakedHex: string): RGBA => { +const parseHex = (nakedHex) => { const isShort = nakedHex.length === 3 || nakedHex.length === 4; const twoDigitHexR = isShort @@ -34,18 +31,18 @@ const parseHex = (nakedHex: string): RGBA => { }; }; -const hexToDecimal = (hex: string) => parseInt(hex, 16); +const hexToDecimal = (hex) => parseInt(hex, 16); -const hexesToDecimals = ({ r, g, b, a }: RGBA): RGBA => ({ +const hexesToDecimals = ({ r, g, b, a }) => ({ r: hexToDecimal(r), g: hexToDecimal(g), b: hexToDecimal(b), a: +(hexToDecimal(a) / 255).toFixed(2) }); -const isNumeric = (n: any) => !isNaN(parseFloat(n)) && isFinite(n); // eslint-disable-line no-restricted-globals, max-len +const isNumeric = (n) => !isNaN(parseFloat(n)) && isFinite(n); // eslint-disable-line no-restricted-globals, max-len -const formatRgb = (decimalObject: RGBA, parameterA?: number) => { +const formatRgb = (decimalObject, parameterA) => { const { r, g, b, a: parsedA } = decimalObject; const a = isNumeric(parameterA) ? parameterA : parsedA; @@ -61,7 +58,7 @@ const formatRgb = (decimalObject: RGBA, parameterA?: number) => { * @param a - An alpha value to apply. (optional) ('0.5', '0.25') * @return An rgb or rgba value. ('rgb(11, 22, 33)'. 'rgba(11, 22, 33, 0.5)') */ -const hexToRgba = (hex: string, a?: number) => { +const hexToRgba = (hex, a) => { const hashlessHex = removeHash(hex); const hexObject = parseHex(hashlessHex); const decimalObject = hexesToDecimals(hexObject); From 6092e49362e86abeff271c2dfe9c09f6dcf9124d Mon Sep 17 00:00:00 2001 From: Tales Pereira Date: Wed, 22 Apr 2020 14:40:37 -0300 Subject: [PATCH 14/14] naming instance --- src/Button.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Button.js b/src/Button.js index ec1318e..5d2196c 100644 --- a/src/Button.js +++ b/src/Button.js @@ -56,7 +56,7 @@ import { getSpacing, mergeTheme, parseSpacing, rgba } from "./utils/index"; * */ -export const RenderButton = ({ +export const ButtonInstance = ({ Touchable = TouchableOpacity, children, ...props @@ -209,7 +209,7 @@ const Button = (props) => { buttonStyles.backgroundColor = "transparent"; } - const touch = highlight + const Touchable = highlight ? TouchableHighlight : nativeFeedback ? TouchableNativeFeedback @@ -218,10 +218,10 @@ const Button = (props) => { : TouchableOpacity; return ( -