├── .gitignore ├── CNAME ├── README.md ├── favicon.png ├── fonts ├── DroidSerif-Bold.ttf ├── DroidSerif-BoldItalic.ttf ├── DroidSerif-Italic.ttf ├── DroidSerif.ttf ├── Montserrat-Bold.ttf └── Montserrat-Regular.ttf ├── ie.js ├── img ├── autumn.jpg ├── chevron-right.png ├── close-icon.svg ├── github.svg ├── icon-arrow-white.svg ├── icon-arrow.svg ├── icon.medium.svg ├── icon.twitter.svg ├── img.frank.png ├── img.frank@2x.png ├── ir_logo.png ├── ir_logo.svg ├── ir_logo@2x.png ├── jonmajor.png ├── logo-square.png ├── logo.png ├── logo@2x.png ├── long-arrow-right.svg ├── menu-icon.svg ├── newsletter-illustration.svg ├── purple-cloud.png ├── purple-cloud@2x.png ├── sponsor-demo.png └── voting.png ├── index.html ├── issues.html ├── issues ├── 2015 │ ├── 01-05-2015.html │ ├── 01-12-2015.html │ ├── 02-08-2015.html │ ├── 05-10-2015.html │ ├── 06-07-2015.html │ ├── 07-06-2015.html │ ├── 07-09-2015.html │ ├── 08-05-2015.html │ ├── 10-08-2015.html │ ├── 13-06-2015.html │ ├── 13-10-2015.html │ ├── 13-12-2015.html │ ├── 14-07-2015.html │ ├── 15-05-2015.html │ ├── 16-08-2015.html │ ├── 18-09-2015.html │ ├── 19-10-2015.html │ ├── 22-05-2015.html │ ├── 22-06-2015.html │ ├── 22-11-2015.html │ ├── 23-04-2015.html │ ├── 26-07-2015.html │ ├── 27-09-2015.html │ ├── 27-10-2015.html │ ├── 28-06-2015.html │ ├── 30-08-2015.html │ └── 31-05-2015.html ├── 2016 │ ├── 01-07-2016.html │ ├── 02-12-2016.html │ ├── 07-08-2016.html │ ├── 10-01-2016.html │ ├── 14-02-2016.html │ ├── 18-11-2016.html │ ├── 19-10-2016.html │ ├── 20-12-2016.html │ ├── 21-03-2016.html │ ├── 21-04-2016.html │ └── 22-01-2016.html ├── 2017 │ ├── 05-12-2017.html │ ├── 06-04-2017.html │ ├── 06-10-2017.html │ ├── 07-09-2017.html │ ├── 08-01-2017.html │ ├── 14-02-2017.html │ ├── 17-05-2017.html │ ├── 18-08-2017.html │ ├── 20-03-2017.html │ ├── 27-02-2017.html │ ├── 28-06-2017.html │ ├── 29-04-2017.html │ ├── 30-01-2017.html │ ├── 31-05-2017.html │ ├── 31-07-2017.html │ └── 31-10-2017.html ├── 2018 │ ├── 02-09-2018.html │ ├── 03-21-2018.html │ ├── 04-03-2018.html │ ├── 04-18-2018.html │ ├── 05-01-2018.html │ ├── 05-15-2018.html │ ├── 05-29-2018.html │ ├── 06-12-2018.html │ ├── 06-26-2018.html │ ├── 07-17-2018.html │ ├── 07-31-2018.html │ ├── 08-21-2018.html │ ├── 09-04-2018.html │ ├── 09-18-2018.html │ ├── 10-02-2018.html │ ├── 10-16-2018.html │ ├── 11-06-2018.html │ ├── 11-20-2018.html │ ├── 12-04-2018.html │ └── 12-18-2018.html ├── 2019 │ ├── 01-01-2019.html │ ├── 01-15-2019.html │ ├── 02-05-2019.html │ ├── 02-19-2019.html │ ├── 03-05-2019.html │ ├── 03-19-2019.html │ ├── 04-02-2019.html │ ├── 04-16-2019.html │ ├── 05-07-2019.html │ ├── 05-21-2019.html │ ├── 06-04-2019.html │ ├── 06-18-2019.html │ ├── 07-02-2019.html │ ├── 07-16-2019.html │ ├── 08-06-2019.html │ ├── 08-20-2019.html │ ├── 09-03-2019.html │ ├── 09-17-2019.html │ ├── 10-01-2019.html │ ├── 10-15-2019.html │ ├── 11-05-2019.html │ ├── 11-19-2019.html │ ├── 12-03-2019.html │ └── 12-17-2019.html ├── 2020 │ ├── 01-07-2020.html │ ├── 01-21-2020.html │ ├── 02-04-2020.html │ ├── 02-18-2020.html │ ├── 03-03-2020.html │ ├── 03-17-2020.html │ ├── 04-07-2020.html │ ├── 04-21-2020.html │ ├── 05-05-2020.html │ ├── 05-19-2020.html │ ├── 06-02-2020.html │ ├── 06-16-2020.html │ ├── 07-07-2020.html │ ├── 07-21-2020.html │ ├── 08-04-2020.html │ ├── 08-18-2020.html │ ├── 09-01-2020.html │ ├── 09-15-2020.html │ ├── 10-06-2020.html │ ├── 10-20-2020.html │ ├── 11-03-2020.html │ ├── 11-17-2020.html │ ├── 12-01-2020.html │ └── 12-15-2020.html ├── 2021 │ ├── 01-05-2021.html │ ├── 01-19-2021.html │ ├── 02-02-2021.html │ ├── 02-16-2021.html │ ├── 04-06-2021.html │ ├── 04-20-2021.html │ ├── 05-04-2021.html │ ├── 05-18-2021.html │ ├── 06-01-2021.html │ ├── 06-15-2021.html │ ├── 07-06-2021.html │ ├── 07-20-2021.html │ ├── 08-04-2021.html │ ├── 08-17-2021.html │ ├── 09-07-2021.html │ ├── 09-21-2021.html │ ├── 10-05-2021.html │ ├── 10-19-2021.html │ ├── 11-02-2021.html │ ├── 11-16-2021.html │ ├── 12-07-2021.html │ └── 12-28-2021.html ├── 2022 │ ├── 01-18-2022.html │ ├── 02-01-2022.html │ ├── 02-15-2022.html │ └── 03-01-2022.html └── newsletter.js ├── newsletter.css ├── newsletter.js ├── normalize.css ├── package.json ├── sponsor-package.pdf ├── sponsor.css ├── sponsor.html ├── sponsorPage.js ├── src └── sponsorPage.js ├── static.json ├── suggest-article.html └── yarn.lock /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | -------------------------------------------------------------------------------- /CNAME: -------------------------------------------------------------------------------- 1 | reactnative.cc -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # react-native-newsletter 2 | 3 | Free summary of React Native news, articles, libraries, apps, and 4 | more, published twice a month (or very nearly) ... curated by Jon Major Condon 5 | ([@jonmajorc](https://twitter.com/jonmajorc)). 6 | 7 | This repo is no longer actively maintained, but the newsletter itself is going strong! 8 | 9 | ## [Sign up here!](https://reactnativenewsletter.com/) 10 | 11 | ## [Past Issues](https://reactnativenewsletter.com/past-issues) 12 | -------------------------------------------------------------------------------- /favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReactNativeNews/react-native-newsletter/93016f62af32d97cc009f991d4f7c3c7155a4f26/favicon.png -------------------------------------------------------------------------------- /fonts/DroidSerif-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReactNativeNews/react-native-newsletter/93016f62af32d97cc009f991d4f7c3c7155a4f26/fonts/DroidSerif-Bold.ttf -------------------------------------------------------------------------------- /fonts/DroidSerif-BoldItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReactNativeNews/react-native-newsletter/93016f62af32d97cc009f991d4f7c3c7155a4f26/fonts/DroidSerif-BoldItalic.ttf -------------------------------------------------------------------------------- /fonts/DroidSerif-Italic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReactNativeNews/react-native-newsletter/93016f62af32d97cc009f991d4f7c3c7155a4f26/fonts/DroidSerif-Italic.ttf -------------------------------------------------------------------------------- /fonts/DroidSerif.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReactNativeNews/react-native-newsletter/93016f62af32d97cc009f991d4f7c3c7155a4f26/fonts/DroidSerif.ttf -------------------------------------------------------------------------------- /fonts/Montserrat-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReactNativeNews/react-native-newsletter/93016f62af32d97cc009f991d4f7c3c7155a4f26/fonts/Montserrat-Bold.ttf -------------------------------------------------------------------------------- /fonts/Montserrat-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReactNativeNews/react-native-newsletter/93016f62af32d97cc009f991d4f7c3c7155a4f26/fonts/Montserrat-Regular.ttf -------------------------------------------------------------------------------- /ie.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | // Patch IE's javascript support 3 | // https://stackoverflow.com/questions/2790001/fixing-javascript-array-functions-in-internet-explorer-indexof-foreach-etc 4 | 5 | // Add ECMA262-5 method binding if not supported natively 6 | // 7 | if (!('bind' in Function.prototype)) { 8 | Function.prototype.bind = function (owner) { 9 | var that = this; 10 | if (arguments.length <= 1) { 11 | return function () { 12 | return that.apply(owner, arguments); 13 | }; 14 | } else { 15 | var args = Array.prototype.slice.call(arguments, 1); 16 | return function () { 17 | return that.apply(owner, arguments.length === 0 ? args : args.concat(Array.prototype.slice.call(arguments))); 18 | }; 19 | } 20 | }; 21 | } 22 | 23 | // Add ECMA262-5 string trim if not supported natively 24 | // 25 | if (!('trim' in String.prototype)) { 26 | String.prototype.trim = function () { 27 | return this.replace(/^\s+/, '').replace(/\s+$/, ''); 28 | }; 29 | } 30 | 31 | // Add ECMA262-5 Array methods if not supported natively 32 | // 33 | if (!('indexOf' in Array.prototype)) { 34 | Array.prototype.indexOf = function (find, i /*opt*/) { 35 | if (i === undefined) i = 0; 36 | if (i < 0) i += this.length; 37 | if (i < 0) i = 0; 38 | for (var n = this.length; i < n; i++) 39 | if (i in this && this[i] === find) 40 | return i; 41 | return -1; 42 | }; 43 | } 44 | if (!('lastIndexOf' in Array.prototype)) { 45 | Array.prototype.lastIndexOf = function (find, i /*opt*/) { 46 | if (i === undefined) i = this.length - 1; 47 | if (i < 0) i += this.length; 48 | if (i > this.length - 1) i = this.length - 1; 49 | for (i++; i-- > 0;) /* i++ because from-argument is sadly inclusive */ 50 | if (i in this && this[i] === find) 51 | return i; 52 | return -1; 53 | }; 54 | } 55 | if (!('forEach' in Array.prototype)) { 56 | Array.prototype.forEach = function (action, that /*opt*/) { 57 | for (var i = 0, n = this.length; i < n; i++) 58 | if (i in this) 59 | action.call(that, this[i], i, this); 60 | }; 61 | } 62 | if (!('forEach' in NodeList.prototype)) { 63 | NodeList.prototype.forEach = function (action, that /*opt*/) { 64 | for (var i = 0, n = this.length; i < n; i++) 65 | if (i in this) 66 | action.call(that, this[i], i, this); 67 | }; 68 | } 69 | if (!('map' in Array.prototype)) { 70 | Array.prototype.map = function (mapper, that /*opt*/) { 71 | var other = new Array(this.length); 72 | for (var i = 0, n = this.length; i < n; i++) 73 | if (i in this) 74 | other[i] = mapper.call(that, this[i], i, this); 75 | return other; 76 | }; 77 | } 78 | if (!('filter' in Array.prototype)) { 79 | Array.prototype.filter = function (filter, that /*opt*/) { 80 | var other = [], v; 81 | for (var i = 0, n = this.length; i < n; i++) 82 | if (i in this && filter.call(that, v = this[i], i, this)) 83 | other.push(v); 84 | return other; 85 | }; 86 | } 87 | if (!('every' in Array.prototype)) { 88 | Array.prototype.every = function (tester, that /*opt*/) { 89 | for (var i = 0, n = this.length; i < n; i++) 90 | if (i in this && !tester.call(that, this[i], i, this)) 91 | return false; 92 | return true; 93 | }; 94 | } 95 | if (!('some' in Array.prototype)) { 96 | Array.prototype.some = function (tester, that /*opt*/) { 97 | for (var i = 0, n = this.length; i < n; i++) 98 | if (i in this && tester.call(that, this[i], i, this)) 99 | return true; 100 | return false; 101 | }; 102 | } -------------------------------------------------------------------------------- /img/autumn.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReactNativeNews/react-native-newsletter/93016f62af32d97cc009f991d4f7c3c7155a4f26/img/autumn.jpg -------------------------------------------------------------------------------- /img/chevron-right.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReactNativeNews/react-native-newsletter/93016f62af32d97cc009f991d4f7c3c7155a4f26/img/chevron-right.png -------------------------------------------------------------------------------- /img/close-icon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | times 5 | Created with Sketch. 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /img/github.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /img/icon-arrow-white.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | icon-arrow 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /img/icon-arrow.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | icon-arrow 4 | 5 | 6 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /img/icon.medium.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /img/icon.twitter.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /img/img.frank.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReactNativeNews/react-native-newsletter/93016f62af32d97cc009f991d4f7c3c7155a4f26/img/img.frank.png -------------------------------------------------------------------------------- /img/img.frank@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReactNativeNews/react-native-newsletter/93016f62af32d97cc009f991d4f7c3c7155a4f26/img/img.frank@2x.png -------------------------------------------------------------------------------- /img/ir_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReactNativeNews/react-native-newsletter/93016f62af32d97cc009f991d4f7c3c7155a4f26/img/ir_logo.png -------------------------------------------------------------------------------- /img/ir_logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | Infinite Red Logo Light 4 | Created with Sketch. 5 | 6 | 7 | 24 | 25 | -------------------------------------------------------------------------------- /img/ir_logo@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReactNativeNews/react-native-newsletter/93016f62af32d97cc009f991d4f7c3c7155a4f26/img/ir_logo@2x.png -------------------------------------------------------------------------------- /img/jonmajor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReactNativeNews/react-native-newsletter/93016f62af32d97cc009f991d4f7c3c7155a4f26/img/jonmajor.png -------------------------------------------------------------------------------- /img/logo-square.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReactNativeNews/react-native-newsletter/93016f62af32d97cc009f991d4f7c3c7155a4f26/img/logo-square.png -------------------------------------------------------------------------------- /img/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReactNativeNews/react-native-newsletter/93016f62af32d97cc009f991d4f7c3c7155a4f26/img/logo.png -------------------------------------------------------------------------------- /img/logo@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReactNativeNews/react-native-newsletter/93016f62af32d97cc009f991d4f7c3c7155a4f26/img/logo@2x.png -------------------------------------------------------------------------------- /img/long-arrow-right.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /img/menu-icon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | menu-icon 5 | Created with Sketch. 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /img/newsletter-illustration.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /img/purple-cloud.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReactNativeNews/react-native-newsletter/93016f62af32d97cc009f991d4f7c3c7155a4f26/img/purple-cloud.png -------------------------------------------------------------------------------- /img/purple-cloud@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReactNativeNews/react-native-newsletter/93016f62af32d97cc009f991d4f7c3c7155a4f26/img/purple-cloud@2x.png -------------------------------------------------------------------------------- /img/sponsor-demo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReactNativeNews/react-native-newsletter/93016f62af32d97cc009f991d4f7c3c7155a4f26/img/sponsor-demo.png -------------------------------------------------------------------------------- /img/voting.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReactNativeNews/react-native-newsletter/93016f62af32d97cc009f991d4f7c3c7155a4f26/img/voting.png -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 9 | 18 | 19 | 20 | 21 | 25 | 26 | React Native Newsletter 27 | 28 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 |
42 |
43 | 57 | 87 | 91 |
92 |
93 | 94 | 121 | 122 |
123 |
124 |

A curated, fun to read newsletter all about React Native

125 | 126 |

127 | Free bi-weekly summary of React Native news, articles, libraries, 128 | apps, and more! 129 |

130 | 131 | 156 |
157 | 158 |
159 |
160 | 161 | 185 |
186 |
187 | 188 | 189 | -------------------------------------------------------------------------------- /issues.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 9 | 18 | 19 | 20 | 21 | 25 | 26 | React Native Newsletter 27 | 28 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 |
41 |
42 | 56 | 92 | 93 | 97 |
98 |
99 | 123 | 124 |
125 |
126 |
130 | 131 |
    132 |

    Current Issue

    133 | 134 |
  • 135 | #148 March 01 141 |
  • 142 |
143 | 144 | 145 |
    152 | 153 | 155 | 156 | 159 | 160 |
    161 |
    162 |

    2022

    163 | 180 |
    181 |
    182 |

    2021

    183 | 295 |
    296 |
    297 |

    2020

    298 | 420 |
    421 | 422 |
    423 |

    2019

    424 | 546 |
    547 | 548 |
    549 |

    2018

    550 | 652 |
    653 |
    654 |
    655 |
    656 |

    2017

    657 | 739 |
    740 | 741 |
    742 |

    2016

    743 | 800 |
    801 | 802 |
    803 |

    2015

    804 | 941 |
    942 |
    943 | 944 |
    945 |
    946 |
    947 |
    948 | 949 | 973 |
    974 |
    975 | 976 | 977 | -------------------------------------------------------------------------------- /issues/2015/14-07-2015.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | React Native Newsletter 7 | 8 | 9 | 10 |
    11 | 12 | 13 | 550 | 551 |
    14 | 15 | 16 | 17 | 48 | 49 | 50 | 51 | 52 | 53 | 68 | 69 | 70 | 71 | 72 | 73 | 85 | 86 | 87 | 88 | 89 | 90 | 487 | 488 | 489 | 490 | 491 | 492 | 514 | 515 | 516 | 517 | 518 | 519 | 520 | 521 | 522 | 523 | 524 | 525 | 541 | 542 | 543 | 544 | 545 | 546 | 547 |
    18 |
    19 | 20 | 21 | 22 | 43 | 44 |
    23 | 24 | 25 | 26 | 29 | 30 |
    27 |

    Issue #12

    28 |
    31 | 32 | 33 | 34 | 35 | 40 | 41 |
    36 |

    37 | 38 |

    39 |
    42 |
    45 | 46 |
    47 |
    54 | 55 | 56 | 65 | 66 |
    57 | 58 | 59 | 62 | 63 |
    60 | Logo for React Native Newsletter 61 |
    64 |
    67 |
    74 | 75 | 76 | 77 | 81 | 82 |
    78 |

    Special San Francisco edition! Well special for me anyways because I live in Vancouver, Canada, but I am in San Francisco helping out some A1 folks (I learned the term "A1" yesterday and had to UrbanDictionary it) on a React Native project. Also special because it's coming out a Tuesday, wow! A late edition! And shorter than usual! Fancy.

    79 | 80 |
    83 | 84 |
    91 | 92 | 93 | 94 | 95 | 96 | 105 | 106 |
    97 | 98 | 99 | 102 | 103 |
    100 |

    Top News

    101 |
    104 |
    107 | 108 | 109 | 110 | 111 | 112 | 159 | 160 |
    113 | 114 | 115 | 116 | 127 | 128 | 129 |
    117 | React Native 0.8.0-rc released 118 |
    119 | 120 | React Native 0.8.0-rc released 121 | 122 |

    Notable new features: the long-awaited animation API, text-decoration styles for Text elements and remote image loading events. This animation API, wow. You have to try it. Check out my Tinder card demo using the Animated API, and @sahrens' talk at React Europe for an in depth look at the API.

    123 | 124 |

    This release boasts performance improvements: a switch to io.js, a faster version of the babel transformer, and optimizations by @a2 around removing layout-only View nodes.

    125 |
    126 |
    130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 |
    139 | 140 | 141 | 142 | 143 | 152 | 153 | 154 |
    144 | Docs for "Animated" are up 145 |
    146 | 147 | Docs for "Animated" are up 148 | 149 |

    I know I'm really milking this one, but I can't emphasize enough how fantastic I think this library is. Click through to read the docs!

    150 |
    151 |
    155 | 156 | 157 | 158 |
    161 | 162 | 163 | 164 | 211 | 212 |
    165 | 166 | 167 | 168 | 179 | 180 | 181 |
    169 | Joshua Sierles - React Native playground lightning talk at react-europe 2015 - YouTube 170 |
    171 | 172 | Joshua Sierles - React Native playground lightning talk at react-europe 2015 - YouTube 173 | 174 |

    "Soon after React Native's release, I started working on this tool to help share and test React Native apps: the React Native Playground (https://rnplay.org)"

    175 | 176 |

    A great demo of React Native Playground, well played @jsierles.

    177 |
    178 |
    182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 |
    191 | 192 | 193 | 194 | 195 | 204 | 205 | 206 |
    196 | All ReactEurope presentations up on YouTube 197 |
    198 | 199 | All ReactEurope presentations up on YouTube 200 | 201 |

    Watch, learn, be happy. A big :clap: for all of the presenters, thank you for sharing your knowledge with us!

    202 |
    203 |
    207 | 208 | 209 | 210 |
    213 | 214 | 215 | 216 | 217 | 218 | 227 | 228 |
    219 | 220 | 221 | 224 | 225 |
    222 |

    Highlights from Issues and Pull Requests

    223 |
    226 |
    229 | 230 | 231 | 232 | 233 | 234 | 279 | 280 |
    235 | 236 | 237 | 238 | 247 | 248 | 249 |
    239 | Add Image progress examples to UIExplorer 240 |
    241 | 242 | Add Image progress examples to UIExplorer 243 | 244 |

    @unknownexception spent a good amount of time pushing his Image loading progress events that were included in the 0.8.0-rc release, and followed that up promptly with some examples for UIExplorer to ensure that people know how to use it.

    245 |
    246 |
    250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 |
    259 | 260 | 261 | 262 | 263 | 272 | 273 | 274 |
    264 | Expose rotate x, y, z transforms by @chirag04 265 |
    266 | 267 | Expose rotate x, y, z transforms by @chirag04 268 | 269 |

    This pull request is one in a series that adds support for 3d transforms to style. Very cool stuff when used in conjunction with the Animated api especially. Thanks @chirag04!

    270 |
    271 |
    275 | 276 | 277 | 278 |
    281 | 282 | 283 | 284 | 307 | 308 |
    285 | 286 | 287 | 288 | 299 | 300 | 301 |
    289 | App Extension support by @yusefnapora 290 |
    291 | 292 | App Extension support by @yusefnapora 293 | 294 |

    This adds workarounds for the code that was preventing React from compiling when linked against an iOS App Extension target. Some iOS APIs are unavailable to App Extensions, and Xcode's static analysis will catch attempts to use methods that have been flagged as unavailable.

    295 | 296 |

    Learn more about app extensions.

    297 |
    298 |
    302 | 303 | 304 | 305 | 306 |
    309 | 310 | 311 | 312 | 313 | 314 | 323 | 324 |
    315 | 316 | 317 | 320 | 321 |
    318 |

    Highlights from the community

    319 |
    322 |
    325 | 326 | 327 | 328 | 329 | 330 | 379 | 380 |
    331 | 332 | 333 | 334 | 347 | 348 | 349 |
    335 | react-router has a React Native branch 336 |
    337 | 338 | react-router has a React Native branch 339 | 340 |

    @tylermcginnis33 there's a branch, soon as 1.0 ships we'll make it happen, it kinda works right now iirc

    341 | 342 |

    Currently, this branch aims to incorporate navigation history. It will be interesting to see how it integrates with Navigator - which works great but could be even more powerful if it were declarative.

    343 | 344 |

    Check out the branch.

    345 |
    346 |
    350 | 351 | 352 | 353 | 354 | 355 | 356 | 357 | 358 |
    359 | 360 | 361 | 362 | 363 | 372 | 373 | 374 |
    364 | Exploring Dynamic Layout in Sketch 365 |
    366 | 367 | Exploring Dynamic Layout in Sketch 368 | 369 |

    An interesting experiment that uses React Native's css-layout library to prototype interfaces in Sketch. Seems like a good middle ground between developers and designers, and a good way to get more familiar with React Native's subset of supported CSS declarations.

    370 |
    371 |
    375 | 376 | 377 | 378 |
    381 | 382 | 383 | 384 | 431 | 432 |
    385 | 386 | 387 | 388 | 397 | 398 | 399 |
    389 | syrusakbary/react-native-refresher 390 |
    391 | 392 | syrusakbary/react-native-refresher 393 | 394 |

    If the demo gifs are any indication, this looks to be the best pull-to-refresh library out there at the moment. Animations look smooth and it has a clean API, so check it out!

    395 |
    396 |
    400 | 401 | 402 | 403 | 404 | 405 | 406 | 407 | 408 |
    409 | 410 | 411 | 412 | 413 | 424 | 425 | 426 |
    414 | johanneslumpe/react-native-gesture-recognizers 415 |
    416 | 417 | johanneslumpe/react-native-gesture-recognizers 418 | 419 |

    Library built on last week's blog post about gesture recognition in React Native - it's implemented using ES7 decorators, which are basically like macros that wrap a component in some other component to layer on functionality. Think onions. But components. Component-onions. Maybe that's why the syntax is @decoratorName. @ is pretty onion-like.

    420 | 421 |

    So yeah, onions aside, check it out if you need custom gesture recognition like pinch, or are interested to see how a decorator-based API can work in React Native. Also johanneslumpe is just a cool human being, so respect.

    422 |
    423 |
    427 | 428 | 429 | 430 |
    433 | 434 | 435 | 436 | 481 | 482 |
    437 | 438 | 439 | 440 | 449 | 450 | 451 |
    441 | exponentjs/react-native-scrollable-decorator 442 |
    443 | 444 | exponentjs/react-native-scrollable-decorator 445 | 446 |

    Speaking of onions/decorators, check this other decorator library from the fine exponent duo of @ide and @ccheever. With a @scrollable dusted on top of your component declaration, your component is given the same external api (eg: scrollTo) as a ScrollView.

    447 |
    448 |
    452 | 453 | 454 | 455 | 456 | 457 | 458 | 459 | 460 |
    461 | 462 | 463 | 464 | 465 | 474 | 475 | 476 |
    466 | nulrich/RCTAutoComplete 467 |
    468 | 469 | nulrich/RCTAutoComplete 470 | 471 |

    The only thing better than completing something is autocompleting something. PSA: try to stay away from using RCT for your module prefixes. I get it, I'm a hypocrite because in react-native-video I use RCTVideo. Or am I? Kind of but not so much because this was actually

    472 |
    473 |
    477 | 478 | 479 | 480 |
    483 | 484 | 485 | 486 |
    493 | 494 | 495 | 511 | 512 |
    496 |

    That's 500 | it for now! Ping me on Twitter @notbrent 501 | if you have anything that you would like 502 | me to share next week. 503 |
    504 |
    505 | If you're reading 506 | this on the web, you can subscribe to 507 | get this delivered weekly to your email here!

    509 | 510 |
    513 |
    526 | 527 | 528 | 538 | 539 |
    529 |

    530 | 531 | Goodbits 532 | 533 |

    534 |

    535 | Collect and curate content easily for brilliant newsletters. Try Goodbits for free! 536 |

    537 |
    540 |
    548 | 549 |
    552 | 607 |
    608 | 609 | 610 | 611 | 612 | 613 | 614 | -------------------------------------------------------------------------------- /issues/newsletter.js: -------------------------------------------------------------------------------- 1 | $(function() { 2 | $('a').attr('target', '_blank'); 3 | var $headerImage = $('[alt="Logo for React Native Newsletter"]'); 4 | $headerImage.click(function() { 5 | window.location.href = 'http://reactnative.cc'; 6 | }); 7 | 8 | $headerImage.css('cursor', 'pointer'); 9 | }); 10 | -------------------------------------------------------------------------------- /newsletter.css: -------------------------------------------------------------------------------- 1 | /** 2 | * Fonts 3 | */ 4 | @font-face { 5 | font-family: 'Droid Serif'; 6 | src: url('/fonts/DroidSerif.ttf'); 7 | font-style: normal; 8 | } 9 | 10 | @font-face { 11 | font-family: 'Droid Serif'; 12 | src: url('/fonts/DroidSerif-Italic.ttf'); 13 | font-style: italic; 14 | } 15 | 16 | @font-face { 17 | font-family: 'Montserrat'; 18 | src: url('/fonts/Montserrat-Regular.ttf'); 19 | } 20 | 21 | /** 22 | * Typography 23 | */ 24 | 25 | /** 26 | * Icons 27 | */ 28 | 29 | .icon { 30 | display: inline-block; 31 | width: 18px; 32 | height: 16px; 33 | background-repeat: no-repeat; 34 | } 35 | 36 | .icon.twitter { 37 | background-image: url(/img/icon.twitter.svg); 38 | } 39 | 40 | .icon.medium { 41 | background-image: url(/img/icon.medium.svg); 42 | } 43 | 44 | .icon.github { 45 | background-image: url(/img/github.svg); 46 | } 47 | 48 | .icon.arrow-right { 49 | background-image: url(/img/icon-arrow.svg); 50 | margin-top: 2px 51 | } 52 | 53 | /** 54 | * Forms 55 | */ 56 | 57 | input { 58 | -webkit-appearance: none; 59 | color: #8f7e94; 60 | font-size: 15px; 61 | text-align: left; 62 | width: 393px; 63 | outline: none; 64 | background-color: white; 65 | border-radius: 32.5px; 66 | width: 300px; 67 | padding: 19px 30px 19px 30px; 68 | border: 2px solid #fff; 69 | display: block; 70 | margin-top: 23px; 71 | } 72 | 73 | .input-field { 74 | display: flex; 75 | flex-flow: row wrap; 76 | } 77 | 78 | .captcha-field { 79 | display: flex; 80 | align-self: center; 81 | padding-top: 100px; 82 | padding-left: 5px; 83 | } 84 | 85 | .input-field span { 86 | display: none; 87 | font-size: 13px; 88 | font-family: 'Droid Serif', serif; 89 | font-style: italic; 90 | line-height: 35px; 91 | text-align: left; 92 | } 93 | 94 | .input-field .addon { 95 | width: 50px; 96 | height: 61px; 97 | border-top-right-radius: 32.5px; 98 | border-bottom-right-radius: 32.5px; 99 | background-color: #fff; 100 | background-image: url(/img/long-arrow-right.svg); 101 | background-repeat: no-repeat; 102 | background-position: right 20px center; 103 | border-top: 2px solid #fff; 104 | border-right: 2px solid #fff; 105 | border-bottom: 2px solid #fff; 106 | border-left: none; 107 | outline: none; 108 | } 109 | 110 | .input-field .addon:hover { 111 | cursor: pointer; 112 | } 113 | 114 | .input-field.error .addon { 115 | border-color: #e73536; 116 | } 117 | 118 | .input-field.error input { 119 | border-color: #e73536; 120 | } 121 | 122 | .input-field.error span { 123 | display: block; 124 | color: #e73536; 125 | margin-left: 30px; 126 | width: 100%; 127 | } 128 | 129 | .email-input { 130 | margin-top: 71px; 131 | } 132 | 133 | .email-input input { 134 | margin-top: 0; 135 | border-right: none; 136 | border-top-right-radius: 0%; 137 | border-bottom-right-radius: 0%; 138 | width: 280px; 139 | } 140 | 141 | /** 142 | * Styles 143 | */ 144 | 145 | html, 146 | body { 147 | background: linear-gradient( 148 | 143.43deg, 149 | #1f0232 0%, 150 | rgba(100, 11, 86, 0.99) 100% 151 | ); 152 | min-height: 100%; 153 | min-width: 100%; 154 | height: auto; 155 | } 156 | 157 | body { 158 | font-family: 'Montserrat', sans-serif; 159 | color: #fff; 160 | } 161 | 162 | h1 { 163 | font-size: 46px; 164 | font-weight: bold; 165 | line-height: 56px; 166 | margin-bottom: 23px; 167 | letter-spacing: 1px; 168 | } 169 | 170 | h2 { 171 | font-size: 20px; 172 | font-style: italic; 173 | font-weight: normal; 174 | line-height: 35px; 175 | } 176 | 177 | h2, 178 | p { 179 | color: #caabcb; 180 | font-family: 'Droid Serif', serif; 181 | } 182 | 183 | ul { 184 | list-style-type: none; 185 | padding: 0; 186 | } 187 | 188 | ul li { 189 | display: inline-block; 190 | } 191 | 192 | .container { 193 | background-image: url(/img/purple-cloud.png); 194 | background-position: bottom right; 195 | background-repeat: no-repeat; 196 | background-size: 60% 100%; 197 | min-height: 1000px; 198 | } 199 | 200 | main { 201 | display: block; 202 | position: relative; 203 | margin: 0 auto; 204 | z-index: 999; 205 | min-height: calc(100vh - 60px); 206 | display: grid; 207 | padding: 30px; 208 | max-width: 1440px; 209 | grid-template-columns: 1fr; 210 | grid-template-rows: 56px 1fr 87px; 211 | grid-template-areas: 'top' 'mid' 'bot'; 212 | } 213 | 214 | header { 215 | grid-area: top; 216 | } 217 | 218 | .banner { 219 | background-color: #783460; 220 | padding: 20px 30px; 221 | display: flex; 222 | align-items: center; 223 | justify-content: space-between; 224 | } 225 | 226 | .banner h1 { 227 | font-size: 16px; 228 | line-height: 20px; 229 | margin: 0; 230 | } 231 | 232 | .banner-about { 233 | max-width: 670px; 234 | margin-right: 16px; 235 | } 236 | 237 | .banner-about span, .banner-about a, .banner a { 238 | font-weight: normal; 239 | color: #fff; 240 | font-size: 13px; 241 | line-height: 19px; 242 | } 243 | 244 | .banner-about span.about { 245 | margin-top: 5px; 246 | display: inline-block; 247 | } 248 | 249 | .banner-about span.about, .banner-about a { 250 | color: #fff; 251 | font-size: 13px; 252 | } 253 | 254 | .banner .banner-cta { 255 | display: flex; 256 | width: 224px; 257 | height: 60px; 258 | align-items: center; 259 | justify-content: center; 260 | padding:0 16px; 261 | color: #783460; 262 | background-color: #fff; 263 | text-decoration: none; 264 | } 265 | 266 | .banner .banner-cta .cta { 267 | font-size: 16px; 268 | font-weight: 600; 269 | margin-right: 16px 270 | } 271 | 272 | 273 | nav.desktop, 274 | nav.mobile { 275 | padding: 0 30px; 276 | display: flex; 277 | align-items: center; 278 | justify-content: space-between; 279 | } 280 | 281 | nav a { 282 | color: #928699; 283 | font-size: 13px; 284 | line-height: 16px; 285 | text-decoration: none; 286 | margin-right: 30px; 287 | } 288 | 289 | nav a:hover { 290 | color: #b6abbd; 291 | } 292 | 293 | nav a#logo { 294 | display: block; 295 | width: 56px; 296 | height: 56px; 297 | background-image: url('/img/logo.png'); 298 | background-repeat: no-repeat; 299 | background-size: cover; 300 | } 301 | 302 | nav.mobile a#logo { 303 | width: 48px; 304 | height: 48px; 305 | } 306 | 307 | nav a#open-menu { 308 | display: block; 309 | width: 35px; 310 | height: 35px; 311 | background-image: url('/img/menu-icon.svg'); 312 | background-repeat: no-repeat; 313 | margin: 0; 314 | } 315 | 316 | nav.desktop ul, 317 | nav.mobile ul { 318 | display: flex; 319 | align-items: center; 320 | } 321 | 322 | nav.desktop .social { 323 | align-self: right; 324 | } 325 | 326 | nav.desktop .social li { 327 | margin-right: 20px; 328 | } 329 | 330 | nav.desktop .social li a { 331 | margin: 0; 332 | } 333 | 334 | nav.mobile { 335 | display: none; 336 | } 337 | 338 | nav.menu { 339 | position: absolute; 340 | visibility: hidden; 341 | opacity: 0; 342 | background-color: #2d0838; 343 | top: 0; 344 | left: 0; 345 | height: calc(100vh - 60px); 346 | width: 100%; 347 | z-index: 0; 348 | display: grid; 349 | grid-template-rows: 30px 70% 55px; 350 | grid-template-columns: 1fr; 351 | padding: 30px 0; 352 | transition-property: opacity, visibility; 353 | transition-duration: 0.25s; 354 | transition-timing-function: ease-in-out; 355 | } 356 | 357 | nav.menu.open { 358 | visibility: visible; 359 | opacity: 1; 360 | z-index: 0; 361 | } 362 | 363 | nav.menu .close-wrapper { 364 | display: flex; 365 | align-items: flex-end; 366 | justify-content: flex-end; 367 | } 368 | 369 | nav.menu .close-wrapper .close { 370 | align-self: right; 371 | display: block; 372 | background-image: url('/img/close-icon.svg'); 373 | background-repeat: no-repeat; 374 | width: 30px; 375 | height: 30px; 376 | } 377 | 378 | nav.menu ul { 379 | padding: 0 30px; 380 | } 381 | 382 | nav.menu li { 383 | margin-top: 40px; 384 | display: block; 385 | } 386 | 387 | nav.menu li a { 388 | color: #fff; 389 | font-size: 26px; 390 | line-height: 32px; 391 | } 392 | 393 | nav.menu ul.social li { 394 | display: inline; 395 | } 396 | 397 | nav.menu ul.social li a { 398 | height: 25px; 399 | width: 30px; 400 | background-size: cover; 401 | } 402 | 403 | /** 404 | * Suggest An Article 405 | */ 406 | 407 | .suggest-article { 408 | position: fixed; 409 | visibility: hidden; 410 | opacity: 0; 411 | z-index: 1001; 412 | top: 0; 413 | left: 0; 414 | width: 100%; 415 | min-height: 100vh; 416 | background-color: #2d0838; 417 | display: grid; 418 | grid-template-rows: 127px 1fr; 419 | grid-template-columns: 1fr; 420 | text-align: center; 421 | transition-property: opacity, visibility; 422 | transition-duration: 0.25s; 423 | transition-timing-function: ease-in-out; 424 | } 425 | 426 | .suggest-article.open { 427 | visibility: visible; 428 | opacity: 1; 429 | } 430 | 431 | .suggest-article .close-wrapper { 432 | display: flex; 433 | align-items: flex-end; 434 | justify-content: flex-end; 435 | padding: 40px 72px; 436 | } 437 | 438 | .suggest-article .close-wrapper a.close { 439 | color: #fff; 440 | font-size: 14px; 441 | text-decoration: none; 442 | background-image: url('/img/close-icon.svg'); 443 | background-repeat: no-repeat; 444 | background-position: top right; 445 | background-size: 16px 16px; 446 | padding-right: 25px; 447 | } 448 | 449 | .suggest-article h1, 450 | .suggest-article h2 { 451 | width: 85%; 452 | margin-left: auto; 453 | margin-right: auto; 454 | } 455 | 456 | .suggest-article form { 457 | width: 390px; 458 | margin: 55px auto; 459 | } 460 | 461 | .suggest-article input { 462 | margin-left: auto; 463 | margin-right: auto; 464 | } 465 | 466 | .suggest-article button { 467 | margin-top: 55px; 468 | background-image: url('/img/chevron-right.png'); 469 | background-repeat: no-repeat; 470 | background-size: 25px 25px; 471 | background-position: center center; 472 | border: none; 473 | width: 48px; 474 | height: 48px; 475 | background-color: #e73536; 476 | border-radius: 50%; 477 | } 478 | 479 | /** 480 | * Content 481 | */ 482 | 483 | .content { 484 | -ms-grid-columns: 1fr 1fr; 485 | -ms-grid-rows: minmax(min-content, calc(100vh - 250px)); 486 | grid-area: mid; 487 | grid-template-areas: 'left right'; 488 | grid-template-columns: 1fr 1fr; 489 | grid-template-rows: 1fr; 490 | min-height: 900px; 491 | height: 100%; 492 | } 493 | 494 | .hideable { 495 | display: none !important; 496 | } 497 | 498 | .content #splash { 499 | padding-top: 163px; 500 | padding-left: 65px; 501 | } 502 | 503 | .content #splash h1 { 504 | width: 579px; 505 | } 506 | 507 | .content #splash h2 { 508 | width: 509px; 509 | } 510 | 511 | .content #illustration { 512 | -ms-grid-column: 2; 513 | grid-area: right; 514 | background-image: url(/img/newsletter-illustration.svg); 515 | background-repeat: no-repeat; 516 | background-position: center 66px; 517 | padding: 30px; 518 | height: 725px; 519 | } 520 | 521 | .past-issues-container { 522 | width: 100%; 523 | display: flex; 524 | align-items: left; 525 | justify-content: space-around; 526 | margin-bottom: 30px; 527 | } 528 | 529 | .past-issues-header { 530 | width: 100%; 531 | display: flex; 532 | flex-flow: row wrap; 533 | align-items: left; 534 | justify-content: left; 535 | margin-bottom: 30px; 536 | } 537 | 538 | .recent-past-issues { 539 | display: grid; 540 | grid-template-columns: auto auto auto auto auto; 541 | padding-bottom: 4em; 542 | padding-left: 1em; 543 | } 544 | 545 | .recent-past-issues a { 546 | font-size: 18px; 547 | padding: 4px; 548 | font-size: 22px; 549 | text-align: left; 550 | color: #928699; 551 | text-decoration: none; 552 | } 553 | 554 | .recent-past-issues a:hover { 555 | color: #fff; 556 | } 557 | 558 | .past-issues { 559 | min-width: 200px; 560 | /* width: 33%; */ 561 | } 562 | 563 | .past-issues li { 564 | display: block; 565 | font-size: 18px; 566 | } 567 | 568 | .past-issues li a { 569 | color: #928699; 570 | text-decoration: none; 571 | } 572 | 573 | .past-issues-header li a { 574 | color: #928699; 575 | text-decoration: none; 576 | margin: 8px; 577 | display: block; 578 | font-size: 22px; 579 | } 580 | 581 | .past-issues li a:hover { 582 | color: #fff; 583 | } 584 | 585 | /** 586 | * Footer 587 | */ 588 | footer { 589 | grid-area: bot; 590 | } 591 | 592 | footer .bio h1, 593 | footer .bio p { 594 | margin: 0; 595 | padding: 0; 596 | line-height: 1em; 597 | font-size: 14px; 598 | align-self: left; 599 | } 600 | 601 | footer .bio h1 { 602 | line-height: 35px; 603 | } 604 | 605 | footer .bio p { 606 | line-height: 20px; 607 | } 608 | 609 | footer .bio .photo { 610 | flex: 1; 611 | height: 87px; 612 | width: 52px; 613 | align-self: left; 614 | background-image: url(/img/jonmajor.png); 615 | background-repeat: no-repeat; 616 | background-size: contain; 617 | margin-right: 24px; 618 | float: left; 619 | } 620 | 621 | footer .bio .details { 622 | float: left; 623 | } 624 | 625 | footer .sponsor { 626 | float: right; 627 | width: 120px; 628 | height: 74px; 629 | } 630 | 631 | footer .sponsor h1 { 632 | font-size: 12px; 633 | font-weight: normal; 634 | letter-spacing: 2px; 635 | text-transform: uppercase; 636 | line-height: 1em; 637 | margin-bottom: 16px; 638 | } 639 | 640 | footer .sponsor .logo { 641 | display: block; 642 | height: 50px; 643 | width: 99px; 644 | background-image: url(/img/ir_logo.svg); 645 | background-repeat: no-repeat; 646 | margin: 0 auto; 647 | } 648 | 649 | footer .social li { 650 | margin-right: 15px; 651 | } 652 | 653 | /** 654 | * Mobile overrides 655 | */ 656 | @media screen and (max-width: 1229px) { 657 | .content { 658 | grid-template-columns: 1fr; 659 | } 660 | 661 | .content #illustration { 662 | display: none; 663 | } 664 | } 665 | 666 | @media screen and (max-width: 730px) { 667 | main { 668 | grid-template-rows: 56px 1fr 300px; 669 | } 670 | 671 | .container { 672 | background: none; 673 | } 674 | 675 | .suggest-article { 676 | position: absolute; 677 | grid-template-rows: 90px 1fr; 678 | height: 1115px; 679 | } 680 | 681 | .suggest-article .close-wrapper { 682 | padding: 30px; 683 | } 684 | 685 | .suggest-article .close-wrapper a.close { 686 | display: block; 687 | font-size: 0; 688 | height: 30px; 689 | width: 30px; 690 | background-size: 30px 30px; 691 | padding: 0; 692 | } 693 | 694 | .suggest-article form { 695 | width: 315px; 696 | } 697 | 698 | .suggest-article input { 699 | width: 250px; 700 | } 701 | 702 | .content { 703 | min-height: 750px; 704 | width: 100%; 705 | display: block; 706 | grid-template-columns: none; 707 | grid-template-rows: none; 708 | } 709 | 710 | .content #splash { 711 | padding-top: 50px; 712 | padding-left: 0; 713 | } 714 | 715 | .content #splash h1, 716 | .content #splash h2 { 717 | width: auto; 718 | } 719 | 720 | .email-input input { 721 | max-width: 250px; 722 | width: calc(100% - 115px); 723 | } 724 | 725 | footer { 726 | clear: both; 727 | } 728 | 729 | footer .bio h1 { 730 | line-height: 3.5em; 731 | } 732 | 733 | footer .bio p { 734 | font-size: 13px; 735 | } 736 | 737 | footer .bio .photo { 738 | display: block; 739 | float: none; 740 | height: 52px; 741 | } 742 | 743 | footer .bio .details { 744 | display: block; 745 | float: none; 746 | } 747 | 748 | footer .bio .social { 749 | padding: 0; 750 | margin-top: 20px; 751 | } 752 | 753 | footer .sponsor-wrap { 754 | display: flex; 755 | align-items: center; 756 | justify-content: center; 757 | float: none; 758 | margin-top: 50pt; 759 | } 760 | } 761 | 762 | @media screen and (max-width: 700px) { 763 | nav.desktop { 764 | display: none; 765 | } 766 | 767 | nav.mobile { 768 | display: flex; 769 | } 770 | 771 | .banner { 772 | flex-direction: column; 773 | align-items: flex-start; 774 | padding: 40px 30px 30px; 775 | margin-bottom: 24px; 776 | } 777 | 778 | .banner-about { 779 | max-width: 355px; 780 | margin-bottom: 30px; 781 | } 782 | 783 | .banner h1 { 784 | font-size: 20px; 785 | } 786 | } 787 | 788 | @media screen and (max-width: 414px) { 789 | .content #splash { 790 | padding: 0; 791 | } 792 | } 793 | -------------------------------------------------------------------------------- /newsletter.js: -------------------------------------------------------------------------------- 1 | // See https://stackoverflow.com/questions/46155/how-can-you-validate-an-email-address-in-javascript 2 | function validateEmail (email) { 3 | var re = /^(([^<>()[\]\\.,:\s@\"]+(\.[^<>()[\]\\.,:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/ 4 | return re.test(email) 5 | } 6 | 7 | function enableScroll () { 8 | ['html', 'body'].forEach(function (selector) { 9 | document.querySelector(selector).style = '' 10 | }) 11 | } 12 | 13 | function disableScroll () { 14 | ['html', 'body'].forEach(function (selector) { 15 | document.querySelector(selector).style = 'position: fixed; height: 100vh; overflow: hidden;' 16 | }) 17 | } 18 | 19 | function displayError (element) { 20 | element.classList.add('error') 21 | } 22 | 23 | function hideError (element) { 24 | element.classList.remove('error') 25 | } 26 | 27 | window.onload = function () { 28 | // Subscribe Form 29 | var subscribeForm = document.querySelector('.subscribe-form form') 30 | var emailWrapper = document.querySelector('.email-input') 31 | var emailInput = document.querySelector('.email-input input') 32 | 33 | if (subscribeForm !== null) { 34 | subscribeForm.addEventListener('submit', function (event) { 35 | event.preventDefault() 36 | 37 | if (validateEmail(emailInput.value)) { 38 | emailWrapper.className = 'input-field email-input' 39 | subscribeForm.submit() 40 | } else { 41 | emailWrapper.className = 'input-field email-input error' 42 | } 43 | }) 44 | } 45 | 46 | // Mobile navigation 47 | var openNav = document.querySelector('#open-menu') 48 | var closeNav = document.querySelector('nav.menu .close') 49 | var menu = document.querySelector('nav.menu') 50 | var content = document.querySelector(`section.content`) 51 | 52 | openNav.addEventListener('click', function (event) { 53 | event.preventDefault() 54 | window.scrollTo(0, 0) 55 | menu.classList.add('open') 56 | content.classList.add('hideable') 57 | disableScroll() 58 | }) 59 | 60 | closeNav.addEventListener('click', function (event) { 61 | event.preventDefault() 62 | menu.classList.remove('open') 63 | content.classList.remove('hideable') 64 | enableScroll() 65 | }) 66 | 67 | // Suggest an Article Modal 68 | var openSuggest = document.querySelectorAll('.open-suggest-article') 69 | var closeSuggest = document.querySelector('.suggest-article .close') 70 | var suggest = document.querySelector('.suggest-article') 71 | 72 | openSuggest.forEach(function (element) { 73 | element.addEventListener('click', function (event) { 74 | event.preventDefault() 75 | suggest.classList.add('open') 76 | enableScroll() 77 | }) 78 | }) 79 | 80 | closeSuggest.addEventListener('click', function (event) { 81 | event.preventDefault() 82 | window.scrollTo(0, 0) 83 | suggest.classList.remove('open') 84 | 85 | if (menu.classList.contains('open')) { 86 | disableScroll() 87 | } else { 88 | enableScroll() 89 | } 90 | }) 91 | 92 | // Suggest an Article Form 93 | var suggestForm = document.querySelector('.suggest-article form') 94 | var suggestName = document.querySelector('.suggest-article input[name="name"]') 95 | var suggestEmail = document.querySelector('.suggest-article input[name="email"]') 96 | var suggestUrl = document.querySelector('.suggest-article input[name="url"]') 97 | 98 | suggestForm.addEventListener('submit', function (event) { 99 | event.preventDefault() 100 | var errors = [] 101 | 102 | if (suggestName.value.length === 0) { 103 | displayError(suggestName.parentElement) 104 | errors = errors.concat('name') 105 | } else { 106 | hideError(suggestName.parentElement) 107 | } 108 | 109 | if (!validateEmail(suggestEmail.value)) { 110 | displayError(suggestEmail.parentElement) 111 | errors = errors.concat('email') 112 | } else { 113 | hideError(suggestEmail.parentElement) 114 | } 115 | 116 | if (suggestUrl.value.length < 5) { 117 | displayError(suggestUrl.parentElement) 118 | errors = errors.concat('url') 119 | } else { 120 | hideError(suggestUrl.parentElement) 121 | } 122 | 123 | if (errors.length === 0) { 124 | suggestForm.submit() 125 | } 126 | }) 127 | } 128 | 129 | -------------------------------------------------------------------------------- /normalize.css: -------------------------------------------------------------------------------- 1 | /*! normalize.css v7.0.0 | MIT License | github.com/necolas/normalize.css */ 2 | 3 | /* Document 4 | ========================================================================== */ 5 | 6 | /** 7 | * 1. Correct the line height in all browsers. 8 | * 2. Prevent adjustments of font size after orientation changes in 9 | * IE on Windows Phone and in iOS. 10 | */ 11 | 12 | html { 13 | line-height: 1.15; /* 1 */ 14 | -ms-text-size-adjust: 100%; /* 2 */ 15 | -webkit-text-size-adjust: 100%; /* 2 */ 16 | } 17 | 18 | /* Sections 19 | ========================================================================== */ 20 | 21 | /** 22 | * Remove the margin in all browsers (opinionated). 23 | */ 24 | 25 | body { 26 | margin: 0; 27 | } 28 | 29 | /** 30 | * Add the correct display in IE 9-. 31 | */ 32 | 33 | article, 34 | aside, 35 | footer, 36 | header, 37 | nav, 38 | section { 39 | display: block; 40 | } 41 | 42 | /** 43 | * Correct the font size and margin on `h1` elements within `section` and 44 | * `article` contexts in Chrome, Firefox, and Safari. 45 | */ 46 | 47 | h1 { 48 | font-size: 2em; 49 | margin: 0.67em 0; 50 | } 51 | 52 | /* Grouping content 53 | ========================================================================== */ 54 | 55 | /** 56 | * Add the correct display in IE 9-. 57 | * 1. Add the correct display in IE. 58 | */ 59 | 60 | figcaption, 61 | figure, 62 | main { 63 | /* 1 */ 64 | display: block; 65 | } 66 | 67 | /** 68 | * Add the correct margin in IE 8. 69 | */ 70 | 71 | figure { 72 | margin: 1em 40px; 73 | } 74 | 75 | /** 76 | * 1. Add the correct box sizing in Firefox. 77 | * 2. Show the overflow in Edge and IE. 78 | */ 79 | 80 | hr { 81 | box-sizing: content-box; /* 1 */ 82 | height: 0; /* 1 */ 83 | overflow: visible; /* 2 */ 84 | } 85 | 86 | /** 87 | * 1. Correct the inheritance and scaling of font size in all browsers. 88 | * 2. Correct the odd `em` font sizing in all browsers. 89 | */ 90 | 91 | pre { 92 | font-family: monospace, monospace; /* 1 */ 93 | font-size: 1em; /* 2 */ 94 | } 95 | 96 | /* Text-level semantics 97 | ========================================================================== */ 98 | 99 | /** 100 | * 1. Remove the gray background on active links in IE 10. 101 | * 2. Remove gaps in links underline in iOS 8+ and Safari 8+. 102 | */ 103 | 104 | a { 105 | background-color: transparent; /* 1 */ 106 | -webkit-text-decoration-skip: objects; /* 2 */ 107 | } 108 | 109 | /** 110 | * 1. Remove the bottom border in Chrome 57- and Firefox 39-. 111 | * 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari. 112 | */ 113 | 114 | abbr[title] { 115 | border-bottom: none; /* 1 */ 116 | text-decoration: underline; /* 2 */ 117 | text-decoration: underline dotted; /* 2 */ 118 | } 119 | 120 | /** 121 | * Prevent the duplicate application of `bolder` by the next rule in Safari 6. 122 | */ 123 | 124 | b, 125 | strong { 126 | font-weight: inherit; 127 | } 128 | 129 | /** 130 | * Add the correct font weight in Chrome, Edge, and Safari. 131 | */ 132 | 133 | b, 134 | strong { 135 | font-weight: bolder; 136 | } 137 | 138 | /** 139 | * 1. Correct the inheritance and scaling of font size in all browsers. 140 | * 2. Correct the odd `em` font sizing in all browsers. 141 | */ 142 | 143 | code, 144 | kbd, 145 | samp { 146 | font-family: monospace, monospace; /* 1 */ 147 | font-size: 1em; /* 2 */ 148 | } 149 | 150 | /** 151 | * Add the correct font style in Android 4.3-. 152 | */ 153 | 154 | dfn { 155 | font-style: italic; 156 | } 157 | 158 | /** 159 | * Add the correct background and color in IE 9-. 160 | */ 161 | 162 | mark { 163 | background-color: #ff0; 164 | color: #000; 165 | } 166 | 167 | /** 168 | * Add the correct font size in all browsers. 169 | */ 170 | 171 | small { 172 | font-size: 80%; 173 | } 174 | 175 | /** 176 | * Prevent `sub` and `sup` elements from affecting the line height in 177 | * all browsers. 178 | */ 179 | 180 | sub, 181 | sup { 182 | font-size: 75%; 183 | line-height: 0; 184 | position: relative; 185 | vertical-align: baseline; 186 | } 187 | 188 | sub { 189 | bottom: -0.25em; 190 | } 191 | 192 | sup { 193 | top: -0.5em; 194 | } 195 | 196 | /* Embedded content 197 | ========================================================================== */ 198 | 199 | /** 200 | * Add the correct display in IE 9-. 201 | */ 202 | 203 | audio, 204 | video { 205 | display: inline-block; 206 | } 207 | 208 | /** 209 | * Add the correct display in iOS 4-7. 210 | */ 211 | 212 | audio:not([controls]) { 213 | display: none; 214 | height: 0; 215 | } 216 | 217 | /** 218 | * Remove the border on images inside links in IE 10-. 219 | */ 220 | 221 | img { 222 | border-style: none; 223 | } 224 | 225 | /** 226 | * Hide the overflow in IE. 227 | */ 228 | 229 | svg:not(:root) { 230 | overflow: hidden; 231 | } 232 | 233 | /* Forms 234 | ========================================================================== */ 235 | 236 | /** 237 | * 1. Change the font styles in all browsers (opinionated). 238 | * 2. Remove the margin in Firefox and Safari. 239 | */ 240 | 241 | button, 242 | input, 243 | optgroup, 244 | select, 245 | textarea { 246 | font-family: sans-serif; /* 1 */ 247 | font-size: 100%; /* 1 */ 248 | line-height: 1.15; /* 1 */ 249 | margin: 0; /* 2 */ 250 | } 251 | 252 | /** 253 | * Show the overflow in IE. 254 | * 1. Show the overflow in Edge. 255 | */ 256 | 257 | button, 258 | input { 259 | /* 1 */ 260 | overflow: visible; 261 | } 262 | 263 | /** 264 | * Remove the inheritance of text transform in Edge, Firefox, and IE. 265 | * 1. Remove the inheritance of text transform in Firefox. 266 | */ 267 | 268 | button, 269 | select { 270 | /* 1 */ 271 | text-transform: none; 272 | } 273 | 274 | /** 275 | * 1. Prevent a WebKit bug where (2) destroys native `audio` and `video` 276 | * controls in Android 4. 277 | * 2. Correct the inability to style clickable types in iOS and Safari. 278 | */ 279 | 280 | button, 281 | html [type="button"], /* 1 */ 282 | [type="reset"], 283 | [type="submit"] { 284 | -webkit-appearance: button; /* 2 */ 285 | } 286 | 287 | /** 288 | * Remove the inner border and padding in Firefox. 289 | */ 290 | 291 | button::-moz-focus-inner, 292 | [type="button"]::-moz-focus-inner, 293 | [type="reset"]::-moz-focus-inner, 294 | [type="submit"]::-moz-focus-inner { 295 | border-style: none; 296 | padding: 0; 297 | } 298 | 299 | /** 300 | * Restore the focus styles unset by the previous rule. 301 | */ 302 | 303 | button:-moz-focusring, 304 | [type="button"]:-moz-focusring, 305 | [type="reset"]:-moz-focusring, 306 | [type="submit"]:-moz-focusring { 307 | outline: 1px dotted ButtonText; 308 | } 309 | 310 | /** 311 | * Correct the padding in Firefox. 312 | */ 313 | 314 | fieldset { 315 | padding: 0.35em 0.75em 0.625em; 316 | } 317 | 318 | /** 319 | * 1. Correct the text wrapping in Edge and IE. 320 | * 2. Correct the color inheritance from `fieldset` elements in IE. 321 | * 3. Remove the padding so developers are not caught out when they zero out 322 | * `fieldset` elements in all browsers. 323 | */ 324 | 325 | legend { 326 | box-sizing: border-box; /* 1 */ 327 | color: inherit; /* 2 */ 328 | display: table; /* 1 */ 329 | max-width: 100%; /* 1 */ 330 | padding: 0; /* 3 */ 331 | white-space: normal; /* 1 */ 332 | } 333 | 334 | /** 335 | * 1. Add the correct display in IE 9-. 336 | * 2. Add the correct vertical alignment in Chrome, Firefox, and Opera. 337 | */ 338 | 339 | progress { 340 | display: inline-block; /* 1 */ 341 | vertical-align: baseline; /* 2 */ 342 | } 343 | 344 | /** 345 | * Remove the default vertical scrollbar in IE. 346 | */ 347 | 348 | textarea { 349 | overflow: auto; 350 | } 351 | 352 | /** 353 | * 1. Add the correct box sizing in IE 10-. 354 | * 2. Remove the padding in IE 10-. 355 | */ 356 | 357 | [type="checkbox"], 358 | [type="radio"] { 359 | box-sizing: border-box; /* 1 */ 360 | padding: 0; /* 2 */ 361 | } 362 | 363 | /** 364 | * Correct the cursor style of increment and decrement buttons in Chrome. 365 | */ 366 | 367 | [type="number"]::-webkit-inner-spin-button, 368 | [type="number"]::-webkit-outer-spin-button { 369 | height: auto; 370 | } 371 | 372 | /** 373 | * 1. Correct the odd appearance in Chrome and Safari. 374 | * 2. Correct the outline style in Safari. 375 | */ 376 | 377 | [type="search"] { 378 | -webkit-appearance: textfield; /* 1 */ 379 | outline-offset: -2px; /* 2 */ 380 | } 381 | 382 | /** 383 | * Remove the inner padding and cancel buttons in Chrome and Safari on macOS. 384 | */ 385 | 386 | [type="search"]::-webkit-search-cancel-button, 387 | [type="search"]::-webkit-search-decoration { 388 | -webkit-appearance: none; 389 | } 390 | 391 | /** 392 | * 1. Correct the inability to style clickable types in iOS and Safari. 393 | * 2. Change font properties to `inherit` in Safari. 394 | */ 395 | 396 | ::-webkit-file-upload-button { 397 | -webkit-appearance: button; /* 1 */ 398 | font: inherit; /* 2 */ 399 | } 400 | 401 | /* Interactive 402 | ========================================================================== */ 403 | 404 | /* 405 | * Add the correct display in IE 9-. 406 | * 1. Add the correct display in Edge, IE, and Firefox. 407 | */ 408 | 409 | details, /* 1 */ 410 | menu { 411 | display: block; 412 | } 413 | 414 | /* 415 | * Add the correct display in all browsers. 416 | */ 417 | 418 | summary { 419 | display: list-item; 420 | } 421 | 422 | /* Scripting 423 | ========================================================================== */ 424 | 425 | /** 426 | * Add the correct display in IE 9-. 427 | */ 428 | 429 | canvas { 430 | display: inline-block; 431 | } 432 | 433 | /** 434 | * Add the correct display in IE. 435 | */ 436 | 437 | template { 438 | display: none; 439 | } 440 | 441 | /* Hidden 442 | ========================================================================== */ 443 | 444 | /** 445 | * Add the correct display in IE 10-. 446 | */ 447 | 448 | [hidden] { 449 | display: none; 450 | } 451 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-native-newsletter", 3 | "version": "1.0.0", 4 | "description": "Free bi-weekly summary of React Native news, articles, issues & pull requests, libraries and apps curated by Jon Major Condon ([@jonmajorc](https://twitter.com/jonmajorc)).", 5 | "main": "ie.js", 6 | "dependencies": { 7 | "babel-cli": "^6.26.0", 8 | "babel-preset-react-app": "^3.1.2" 9 | }, 10 | "devDependencies": {}, 11 | "scripts": { 12 | "test": "echo \"Error: no test specified\" && exit 1" 13 | }, 14 | "repository": { 15 | "type": "git", 16 | "url": "git+https://github.com/ReactNativeNews/react-native-newsletter.git" 17 | }, 18 | "keywords": [], 19 | "author": "", 20 | "license": "ISC", 21 | "bugs": { 22 | "url": "https://github.com/ReactNativeNews/react-native-newsletter/issues" 23 | }, 24 | "homepage": "https://github.com/ReactNativeNews/react-native-newsletter#readme" 25 | } 26 | -------------------------------------------------------------------------------- /sponsor-package.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReactNativeNews/react-native-newsletter/93016f62af32d97cc009f991d4f7c3c7155a4f26/sponsor-package.pdf -------------------------------------------------------------------------------- /sponsor.css: -------------------------------------------------------------------------------- 1 | /** 2 | * Fonts 3 | */ 4 | @font-face { 5 | font-family: 'Droid Serif'; 6 | src: url('/fonts/DroidSerif.ttf'); 7 | font-style: normal; 8 | } 9 | 10 | @font-face { 11 | font-family: 'Droid Serif'; 12 | src: url('/fonts/DroidSerif-Italic.ttf'); 13 | font-style: italic; 14 | } 15 | 16 | @font-face { 17 | font-family: 'Montserrat'; 18 | src: url('/fonts/Montserrat-Regular.ttf'); 19 | } 20 | 21 | /** 22 | * Typography 23 | */ 24 | 25 | /** 26 | * Icons 27 | */ 28 | 29 | .icon { 30 | display: inline-block; 31 | width: 18px; 32 | height: 16px; 33 | background-repeat: no-repeat; 34 | } 35 | 36 | .icon.twitter { 37 | background-image: url(/img/icon.twitter.svg); 38 | } 39 | 40 | .icon.medium { 41 | background-image: url(/img/icon.medium.svg); 42 | } 43 | 44 | .icon.github { 45 | background-image: url(/img/github.svg); 46 | } 47 | 48 | .icon.arrow-right { 49 | background-image: url(/img/icon-arrow.svg); 50 | margin-top: 2px; 51 | } 52 | 53 | .icon.arrow-right-white { 54 | background-image: url(/img/icon-arrow-white.svg); 55 | } 56 | 57 | /** 58 | * Forms 59 | */ 60 | 61 | input { 62 | -webkit-appearance: none; 63 | color: #8f7e94; 64 | font-size: 15px; 65 | text-align: left; 66 | width: 393px; 67 | outline: none; 68 | background-color: white; 69 | border-radius: 32.5px; 70 | width: 300px; 71 | padding: 19px 30px 19px 30px; 72 | border: 2px solid #fff; 73 | display: block; 74 | margin-top: 23px; 75 | } 76 | 77 | .input-field { 78 | display: flex; 79 | flex-flow: row wrap; 80 | } 81 | 82 | .captcha-field { 83 | display: flex; 84 | align-self: center; 85 | padding-top: 100px; 86 | padding-left: 5px; 87 | } 88 | 89 | .input-field span { 90 | display: none; 91 | font-size: 13px; 92 | font-family: 'Droid Serif', serif; 93 | font-style: italic; 94 | line-height: 35px; 95 | text-align: left; 96 | } 97 | 98 | .input-field .addon { 99 | width: 50px; 100 | height: 61px; 101 | border-top-right-radius: 32.5px; 102 | border-bottom-right-radius: 32.5px; 103 | background-color: #fff; 104 | background-image: url(/img/long-arrow-right.svg); 105 | background-repeat: no-repeat; 106 | background-position: right 20px center; 107 | border-top: 2px solid #fff; 108 | border-right: 2px solid #fff; 109 | border-bottom: 2px solid #fff; 110 | border-left: none; 111 | outline: none; 112 | } 113 | 114 | .input-field .addon:hover { 115 | cursor: pointer; 116 | } 117 | 118 | .input-field.error .addon { 119 | border-color: #e73536; 120 | } 121 | 122 | .input-field.error input { 123 | border-color: #e73536; 124 | } 125 | 126 | .input-field.error span { 127 | display: block; 128 | color: #e73536; 129 | margin-left: 30px; 130 | width: 100%; 131 | } 132 | 133 | .email-input { 134 | margin-top: 71px; 135 | } 136 | 137 | .email-input input { 138 | margin-top: 0; 139 | border-right: none; 140 | border-top-right-radius: 0%; 141 | border-bottom-right-radius: 0%; 142 | width: 280px; 143 | } 144 | 145 | /** 146 | * Styles 147 | */ 148 | 149 | html, 150 | body { 151 | background: linear-gradient( 152 | 143.43deg, 153 | #1f0232 0%, 154 | rgba(100, 11, 86, 0.99) 100% 155 | ); 156 | min-height: 100%; 157 | min-width: 100%; 158 | height: auto; 159 | } 160 | 161 | body { 162 | font-family: 'Montserrat', sans-serif; 163 | color: #fff; 164 | margin: 0; 165 | } 166 | 167 | h1 { 168 | font-size: 46px; 169 | font-weight: bold; 170 | line-height: 56px; 171 | margin-bottom: 23px; 172 | } 173 | 174 | h2 { 175 | font-size: 30px; 176 | /* font-style: italic; */ 177 | font-weight: normal; 178 | line-height: 35px; 179 | } 180 | 181 | h5 { 182 | color: red; 183 | } 184 | 185 | p { 186 | color: #caabcb; 187 | font-family: 'Droid Serif', serif; 188 | margin: 0 10em 2em 10em; 189 | font-size: 18px; 190 | text-align: center; 191 | line-height: 1.6; 192 | } 193 | 194 | article ul { 195 | margin: 0 10em 2em 10em; 196 | } 197 | 198 | article ul li { 199 | color: #caabcb; 200 | font-family: 'Droid Serif', serif; 201 | font-size: 18px; 202 | line-height: 3.5; 203 | } 204 | article img { 205 | width: 1000px; 206 | } 207 | 208 | .rates-container { 209 | margin: auto; 210 | margin-bottom: 50px; 211 | width: 50%; 212 | flex: 1; 213 | display: flex; 214 | padding: 20px; 215 | background-color: white; 216 | } 217 | 218 | .rate { 219 | width: 33.33%; 220 | } 221 | 222 | .rate-title { 223 | color: #d14435; 224 | text-align: center; 225 | font-size: 46px; 226 | font-weight: bold; 227 | } 228 | 229 | .rate-subtitle { 230 | text-align: center; 231 | width: 100%; 232 | color: #d14435; 233 | font-size: 14px; 234 | font-weight: bold; 235 | } 236 | 237 | .required-info-header { 238 | background-color: #992020; 239 | font-size: 100px; 240 | } 241 | 242 | .required-info-container { 243 | margin: auto; 244 | margin-bottom: 5em; 245 | width: 50%; 246 | display: flex; 247 | flex-direction: column; 248 | align-items: center; 249 | padding: 20px; 250 | background-color: white; 251 | } 252 | 253 | .required-info-container ul { 254 | background-color: #2d0838; 255 | width: 80%; 256 | padding: 1em 0 1em 4em; 257 | } 258 | 259 | .required-info-container h3 { 260 | display: flex; 261 | align-self: center; 262 | color: #d14435; 263 | font-size: 20px; 264 | margin-bottom: 30px; 265 | text-decoration: underline; 266 | } 267 | 268 | .center-wrapper { 269 | margin: auto; 270 | margin-bottom: 1em; 271 | display: flex; 272 | flex-direction: column; 273 | align-items: center; 274 | } 275 | 276 | .sponsor-image { 277 | width: 60%; 278 | height: 100%; 279 | margin-bottom: 5em; 280 | } 281 | 282 | .root a:link { 283 | color: #d14435; 284 | } 285 | .root a:visited { 286 | color: #2d0838; 287 | text-decoration: underline; 288 | cursor: auto; 289 | } 290 | 291 | .container { 292 | background-image: url(/img/purple-cloud.png); 293 | background-position: bottom right; 294 | background-repeat: no-repeat; 295 | background-size: 60% 100%; 296 | min-height: 1000px; 297 | } 298 | 299 | main { 300 | display: block; 301 | position: relative; 302 | margin: 0 auto; 303 | z-index: 999; 304 | min-height: calc(100vh - 60px); 305 | display: grid; 306 | padding: 30px; 307 | max-width: 1440px; 308 | grid-template-columns: 1fr; 309 | grid-template-rows: 56px 1fr 87px; 310 | grid-template-areas: 'top' 'mid' 'bot'; 311 | } 312 | 313 | header { 314 | grid-area: top; 315 | } 316 | 317 | .banner { 318 | background-color: #783460; 319 | padding: 20px 30px; 320 | display: flex; 321 | align-items: center; 322 | justify-content: space-between; 323 | } 324 | 325 | .banner h1 { 326 | font-size: 16px; 327 | line-height: 20px; 328 | margin: 0; 329 | } 330 | 331 | .banner-about { 332 | max-width: 670px; 333 | margin-right: 16px; 334 | } 335 | 336 | .banner-about span, .banner-about a, .banner a { 337 | font-weight: normal; 338 | color: #fff; 339 | font-size: 13px; 340 | line-height: 19px; 341 | } 342 | 343 | .banner-about span.about { 344 | margin-top: 5px; 345 | display: inline-block; 346 | } 347 | 348 | .banner-about span.about, .banner-about a { 349 | color: #fff; 350 | font-size: 13px; 351 | } 352 | 353 | .banner .banner-cta { 354 | display: flex; 355 | width: 224px; 356 | height: 60px; 357 | align-items: center; 358 | justify-content: center; 359 | padding:0 16px; 360 | color: #783460; 361 | background-color: #fff; 362 | text-decoration: none; 363 | } 364 | 365 | .banner .banner-cta .cta { 366 | font-size: 16px; 367 | font-weight: 600; 368 | margin-right: 16px 369 | } 370 | 371 | nav.desktop, 372 | nav.mobile { 373 | padding: 0 30px; 374 | display: flex; 375 | align-items: center; 376 | justify-content: space-between; 377 | } 378 | 379 | nav a { 380 | color: #928699; 381 | font-size: 13px; 382 | line-height: 16px; 383 | text-decoration: none; 384 | margin-right: 30px; 385 | } 386 | 387 | nav a:hover { 388 | color: #b6abbd; 389 | } 390 | 391 | nav a#logo { 392 | display: block; 393 | width: 56px; 394 | height: 56px; 395 | background-image: url('/img/logo.png'); 396 | background-repeat: no-repeat; 397 | background-size: cover; 398 | } 399 | 400 | nav.mobile a#logo { 401 | width: 48px; 402 | height: 48px; 403 | } 404 | 405 | nav a#open-menu { 406 | display: block; 407 | width: 35px; 408 | height: 35px; 409 | background-image: url('/img/menu-icon.svg'); 410 | background-repeat: no-repeat; 411 | margin: 0; 412 | } 413 | 414 | nav.desktop ul, 415 | nav.mobile ul { 416 | display: flex; 417 | align-items: center; 418 | } 419 | 420 | nav.desktop .social { 421 | align-self: right; 422 | } 423 | 424 | nav.desktop .social li { 425 | margin-right: 20px; 426 | } 427 | 428 | nav.desktop .social li a { 429 | margin: 0; 430 | } 431 | 432 | nav.mobile { 433 | display: none; 434 | } 435 | nav ul { 436 | list-style-type: none; 437 | padding: 0; 438 | } 439 | 440 | nav li { 441 | display: inline-block; 442 | } 443 | 444 | nav.menu { 445 | position: absolute; 446 | visibility: hidden; 447 | opacity: 0; 448 | background-color: #2d0838; 449 | top: 0; 450 | left: 0; 451 | height: calc(100vh - 60px); 452 | width: 100%; 453 | z-index: 0; 454 | display: grid; 455 | grid-template-rows: 30px 70% 55px; 456 | grid-template-columns: 1fr; 457 | padding: 30px 0; 458 | transition-property: opacity, visibility; 459 | transition-duration: 0.25s; 460 | transition-timing-function: ease-in-out; 461 | } 462 | 463 | nav.menu.open { 464 | visibility: visible; 465 | opacity: 1; 466 | z-index: 0; 467 | } 468 | 469 | nav.menu .close-wrapper { 470 | display: flex; 471 | align-items: flex-end; 472 | justify-content: flex-end; 473 | } 474 | 475 | nav.menu .close-wrapper .close { 476 | display: block; 477 | background-image: url('/img/close-icon.svg'); 478 | background-repeat: no-repeat; 479 | width: 30px; 480 | height: 30px; 481 | } 482 | 483 | nav.menu ul { 484 | padding: 0 30px; 485 | } 486 | 487 | nav.menu li { 488 | margin-top: 40px; 489 | display: block; 490 | } 491 | 492 | nav.menu li a { 493 | color: #fff; 494 | font-size: 26px; 495 | line-height: 32px; 496 | } 497 | 498 | nav.menu ul.social li { 499 | display: inline; 500 | } 501 | 502 | nav.menu ul.social li a { 503 | height: 25px; 504 | width: 30px; 505 | background-size: cover; 506 | } 507 | 508 | /** 509 | * New Site Message 510 | */ 511 | 512 | section.new-site-message { 513 | display: flex; 514 | flex-direction: column; 515 | justify-content: flex-start; 516 | max-width: 563px; 517 | } 518 | 519 | section.new-site-message h1 { 520 | font-size: 32px; 521 | line-height: 1.18; 522 | margin: 0 0 24px 0; 523 | width: 410px 524 | } 525 | 526 | section.new-site-message p { 527 | text-align: left; 528 | color: #fff; 529 | font-family: 'Montserrat'; 530 | margin: 0 0 16px 0; 531 | font-size: 16px; 532 | line-height: 1.5; 533 | } 534 | 535 | section.new-site-message p a { 536 | color: #fff; 537 | } 538 | 539 | section.new-site-message p.new-site-cta a { 540 | margin-top: 38px; 541 | color: #fff; 542 | text-decoration: none; 543 | display: flex; 544 | align-items: center; 545 | } 546 | 547 | p a .new-site-cta-message { 548 | margin-left: 10px; 549 | text-decoration: underline; 550 | font-weight: bold !important; 551 | } 552 | 553 | /** 554 | * Suggest An Article 555 | */ 556 | 557 | .suggest-article { 558 | position: fixed; 559 | visibility: hidden; 560 | opacity: 0; 561 | z-index: 1001; 562 | top: 0; 563 | left: 0; 564 | width: 100%; 565 | min-height: 100vh; 566 | background-color: #2d0838; 567 | display: grid; 568 | grid-template-rows: 127px 1fr; 569 | grid-template-columns: 1fr; 570 | text-align: center; 571 | transition-property: opacity, visibility; 572 | transition-duration: 0.25s; 573 | transition-timing-function: ease-in-out; 574 | } 575 | 576 | .suggest-article.open { 577 | visibility: visible; 578 | opacity: 1; 579 | } 580 | 581 | .suggest-article .close-wrapper { 582 | display: flex; 583 | align-items: flex-end; 584 | justify-content: flex-end; 585 | padding: 40px 72px; 586 | } 587 | 588 | .suggest-article .close-wrapper a.close { 589 | color: #fff; 590 | font-size: 14px; 591 | text-decoration: none; 592 | background-image: url('/img/close-icon.svg'); 593 | background-repeat: no-repeat; 594 | background-position: top right; 595 | background-size: 16px 16px; 596 | padding-right: 25px; 597 | } 598 | 599 | .suggest-article h1, 600 | .suggest-article h2 { 601 | width: 85%; 602 | margin-left: auto; 603 | margin-right: auto; 604 | } 605 | 606 | .suggest-article form { 607 | width: 390px; 608 | margin: 55px auto; 609 | } 610 | 611 | .suggest-article input { 612 | margin-left: auto; 613 | margin-right: auto; 614 | } 615 | 616 | .suggest-article button { 617 | margin-top: 55px; 618 | background-image: url('/img/chevron-right.png'); 619 | background-repeat: no-repeat; 620 | background-size: 25px 25px; 621 | background-position: center center; 622 | border: none; 623 | width: 48px; 624 | height: 48px; 625 | background-color: #e73536; 626 | border-radius: 50%; 627 | } 628 | 629 | /** 630 | * Content 631 | */ 632 | 633 | .content { 634 | -ms-grid-columns: 1fr 1fr; 635 | -ms-grid-rows: minmax(min-content, calc(100vh - 250px)); 636 | grid-area: mid; 637 | display: flex; 638 | justify-content: center; 639 | } 640 | 641 | .content #splash { 642 | padding-top: 163px; 643 | padding-left: 65px; 644 | } 645 | 646 | .content #splash h1 { 647 | width: 579px; 648 | } 649 | 650 | .content #splash h2 { 651 | width: 509px; 652 | } 653 | 654 | .content #illustration { 655 | -ms-grid-column: 2; 656 | grid-area: right; 657 | background-image: url(/img/newsletter-illustration.svg); 658 | background-repeat: no-repeat; 659 | background-position: center 66px; 660 | padding: 30px; 661 | height: 725px; 662 | } 663 | 664 | .past-issues-container { 665 | width: 100%; 666 | display: flex; 667 | align-items: left; 668 | justify-content: space-around; 669 | margin-bottom: 30px; 670 | } 671 | 672 | .past-issues-header { 673 | width: 100%; 674 | display: flex; 675 | flex-flow: row wrap; 676 | align-items: left; 677 | justify-content: left; 678 | margin-bottom: 30px; 679 | } 680 | 681 | .past-issues { 682 | min-width: 200px; 683 | /* width: 33%; */ 684 | } 685 | 686 | .past-issues li { 687 | display: block; 688 | font-size: 18px; 689 | } 690 | 691 | .past-issues li a { 692 | color: #928699; 693 | text-decoration: none; 694 | } 695 | 696 | .past-issues-header li a { 697 | color: #928699; 698 | text-decoration: none; 699 | margin: 8px; 700 | display: block; 701 | font-size: 22px; 702 | } 703 | 704 | .past-issues li a:hover { 705 | color: #fff; 706 | } 707 | 708 | /** 709 | * Footer 710 | */ 711 | 712 | footer { 713 | grid-area: bot; 714 | } 715 | 716 | footer .bio h1 { 717 | margin: 0; 718 | padding: 0; 719 | line-height: 1em; 720 | font-size: 14px; 721 | align-self: left; 722 | } 723 | 724 | footer .bio p { 725 | margin: 15px 0 0 0; 726 | padding: 0; 727 | line-height: 1em; 728 | font-size: 14px; 729 | align-self: left; 730 | /* right: 20px; */ 731 | /* background-color: #992020; */ 732 | } 733 | 734 | footer .bio .photo { 735 | flex: 1; 736 | height: 87px; 737 | width: 52px; 738 | align-self: left; 739 | background-image: url(/img/jonmajor.png); 740 | background-repeat: no-repeat; 741 | background-size: contain; 742 | margin-right: 24px; 743 | float: left; 744 | } 745 | 746 | footer .bio .details { 747 | float: left; 748 | } 749 | 750 | footer .sponsor { 751 | float: right; 752 | width: 120px; 753 | height: 74px; 754 | } 755 | 756 | footer .sponsor h1 { 757 | font-size: 12px; 758 | font-weight: normal; 759 | letter-spacing: 2px; 760 | text-transform: uppercase; 761 | line-height: 1em; 762 | margin-bottom: 16px; 763 | } 764 | 765 | footer .sponsor p { 766 | font-size: 12px; 767 | font-weight: normal; 768 | letter-spacing: 2px; 769 | text-transform: uppercase; 770 | line-height: 1em; 771 | margin-bottom: 16px; 772 | } 773 | 774 | footer .sponsor .logo { 775 | display: block; 776 | height: 50px; 777 | width: 99px; 778 | background-image: url(/img/ir_logo.svg); 779 | background-repeat: no-repeat; 780 | margin: 0 auto; 781 | } 782 | 783 | footer .social li { 784 | margin-right: 15px; 785 | } 786 | 787 | /** 788 | * Mobile overrides 789 | */ 790 | @media screen and (max-width: 1229px) { 791 | .content { 792 | grid-template-columns: 1fr; 793 | } 794 | 795 | .content #illustration { 796 | display: none; 797 | } 798 | } 799 | 800 | @media screen and (max-width: 730px) { 801 | main { 802 | grid-template-rows: 56px 1fr 300px; 803 | } 804 | 805 | .container { 806 | background: none; 807 | } 808 | 809 | .suggest-article { 810 | position: absolute; 811 | grid-template-rows: 90px 1fr; 812 | height: 1115px; 813 | } 814 | 815 | .suggest-article .close-wrapper { 816 | padding: 30px; 817 | } 818 | 819 | .suggest-article .close-wrapper a.close { 820 | display: block; 821 | font-size: 0; 822 | height: 30px; 823 | width: 30px; 824 | background-size: 30px 30px; 825 | padding: 0; 826 | } 827 | 828 | .suggest-article form { 829 | width: 315px; 830 | } 831 | 832 | .suggest-article input { 833 | width: 250px; 834 | } 835 | 836 | .content { 837 | min-height: 750px; 838 | width: 100%; 839 | display: block; 840 | grid-template-columns: none; 841 | grid-template-rows: none; 842 | } 843 | 844 | .content #splash { 845 | padding-top: 50px; 846 | padding-left: 0; 847 | } 848 | 849 | .content #splash h1, 850 | .content #splash h2 { 851 | width: auto; 852 | } 853 | 854 | .email-input input { 855 | max-width: 250px; 856 | width: calc(100% - 115px); 857 | } 858 | 859 | footer { 860 | clear: both; 861 | } 862 | 863 | footer .bio h1 { 864 | line-height: 3.5em; 865 | } 866 | 867 | footer .bio .photo { 868 | display: block; 869 | float: none; 870 | height: 52px; 871 | } 872 | 873 | footer .bio .social { 874 | padding: 0; 875 | margin-top: 20px; 876 | display: flex; 877 | flex-direction: row; 878 | background-color: #992020; 879 | } 880 | 881 | footer .sponsor-wrap { 882 | display: flex; 883 | align-items: center; 884 | justify-content: center; 885 | float: none; 886 | margin-top: 50pt; 887 | } 888 | } 889 | 890 | @media screen and (max-width: 700px) { 891 | nav.desktop { 892 | display: none; 893 | } 894 | 895 | nav.mobile { 896 | display: flex; 897 | } 898 | 899 | .banner { 900 | flex-direction: column; 901 | align-items: flex-start; 902 | padding: 40px 30px 30px; 903 | margin-bottom: 24px; 904 | } 905 | 906 | .banner-about { 907 | max-width: 355px; 908 | margin-bottom: 30px; 909 | } 910 | 911 | .banner h1 { 912 | font-size: 20px; 913 | } 914 | } 915 | 916 | @media screen and (max-width: 414px) { 917 | .content #splash { 918 | padding: 0; 919 | } 920 | } 921 | -------------------------------------------------------------------------------- /sponsor.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 9 | 18 | 19 | 20 | 24 | 25 | React Native Newsletter 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 |
    37 |
    38 | 52 | 78 | 79 | 83 |
    84 |
    85 | 109 | 110 |
    111 |
    112 |

    You can find this page on our new site

    113 |

    Many of our pages have moved! Article suggestions have moved to a new website.

    114 |
    115 |
    116 | 117 | 141 |
    142 |
    143 | 147 | 151 | 152 | 153 | 154 | 155 | -------------------------------------------------------------------------------- /sponsorPage.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | function SponsorPage() { 4 | function renderStats() { 5 | return React.createElement( 6 | "div", 7 | { "class": "rates-container" }, 8 | React.createElement( 9 | "div", 10 | { "class": "rate" }, 11 | React.createElement( 12 | "div", 13 | { "class": "rate-title" }, 14 | "11.5+ k" 15 | ), 16 | React.createElement( 17 | "div", 18 | { "class": "rate-subtitle" }, 19 | "SUBSCRIBERS" 20 | ) 21 | ), 22 | React.createElement( 23 | "div", 24 | { "class": "rate" }, 25 | React.createElement( 26 | "div", 27 | { "class": "rate-title" }, 28 | "30%" 29 | ), 30 | React.createElement( 31 | "div", 32 | { "class": "rate-subtitle" }, 33 | "OPEN RATE" 34 | ) 35 | ), 36 | React.createElement( 37 | "div", 38 | { "class": "rate" }, 39 | React.createElement( 40 | "div", 41 | { "class": "rate-title" }, 42 | "10%" 43 | ), 44 | React.createElement( 45 | "div", 46 | { "class": "rate-subtitle" }, 47 | "CLICK THRU RATE" 48 | ) 49 | ) 50 | ); 51 | } 52 | 53 | function renderRequiredInfo() { 54 | return React.createElement( 55 | "div", 56 | { "class": "required-info-container" }, 57 | React.createElement( 58 | "h3", 59 | null, 60 | "Sponsorship Required Information & Assets" 61 | ), 62 | React.createElement( 63 | "ul", 64 | null, 65 | React.createElement( 66 | "li", 67 | null, 68 | "1 Image (1200x900px, png or jpg)" 69 | ), 70 | React.createElement( 71 | "li", 72 | null, 73 | "Title (20 words max)" 74 | ), 75 | React.createElement( 76 | "li", 77 | null, 78 | "Description (75 words max)" 79 | ), 80 | React.createElement( 81 | "li", 82 | null, 83 | "URL Link (will link on image and title)" 84 | ), 85 | React.createElement( 86 | "li", 87 | null, 88 | "Content should be tasteful and appropriate" 89 | ), 90 | React.createElement( 91 | "li", 92 | null, 93 | "Provide all information one week before sponsored issue date" 94 | ) 95 | ) 96 | ); 97 | } 98 | 99 | return React.createElement( 100 | "div", 101 | { "class": "root" }, 102 | React.createElement( 103 | "div", 104 | { "class": "center-wrapper" }, 105 | React.createElement( 106 | "h2", 107 | null, 108 | "Why sponsor the React Native Newsletter?" 109 | ) 110 | ), 111 | React.createElement( 112 | "p", 113 | null, 114 | "Sponsoring the newsletter not only gets your company in front of many high quality React Native developers, but it also helps support the continuing curation and editing of the newsletter." 115 | ), 116 | renderStats(), 117 | React.createElement( 118 | "ul", 119 | null, 120 | React.createElement( 121 | "li", 122 | null, 123 | "There are four sponsorships available per issue available on a first-come, first-serve basis." 124 | ), 125 | React.createElement( 126 | "li", 127 | null, 128 | "Sponsorships are $250/issue and must be paid for in-full upfront - credit cards and PayPal are payment options." 129 | ), 130 | React.createElement( 131 | "li", 132 | null, 133 | "Sponsorships do not have to be consecutive." 134 | ), 135 | React.createElement( 136 | "li", 137 | null, 138 | "Desired dates must be listed at time of purchase and approved by Infinite Red." 139 | ) 140 | ), 141 | React.createElement("br", null), 142 | React.createElement( 143 | "div", 144 | { "class": "center-wrapper" }, 145 | React.createElement( 146 | "h2", 147 | null, 148 | "Example Sponsorship" 149 | ), 150 | React.createElement("img", { "class": "sponsor-image", src: "../img/sponsor-demo.png" }) 151 | ), 152 | React.createElement( 153 | "div", 154 | { "class": "center-wrapper" }, 155 | React.createElement( 156 | "h2", 157 | null, 158 | "Complete this Form to Sponsor the Newsletter" 159 | ) 160 | ), 161 | React.createElement( 162 | "div", 163 | { "class": "center-wrapper" }, 164 | React.createElement( 165 | "iframe", 166 | { 167 | src: "https://docs.google.com/forms/d/e/1FAIpQLScqz4Wpdkd2hpNsA2isEnGNR311XNEh1HAmPzUXL99BDBzv2Q/viewform?embedded=true", 168 | width: "640", 169 | height: "1000", 170 | frameborder: "0", 171 | marginheight: "0", 172 | marginwidth: "0" 173 | }, 174 | "Loading\u2026" 175 | ) 176 | ), 177 | React.createElement("div", { style: { height: 50 } }) 178 | ); 179 | } 180 | var domContainer = document.querySelector("#sponsor_page_content"); 181 | ReactDOM.render(React.createElement(SponsorPage, null), domContainer); -------------------------------------------------------------------------------- /src/sponsorPage.js: -------------------------------------------------------------------------------- 1 | "use strict" 2 | 3 | function SponsorPage() { 4 | function renderStats() { 5 | return ( 6 |
    7 |
    8 |
    11.5+ k
    9 |
    SUBSCRIBERS
    10 |
    11 |
    12 |
    30%
    13 |
    OPEN RATE
    14 |
    15 |
    16 |
    10%
    17 |
    CLICK THRU RATE
    18 |
    19 |
    20 | ) 21 | } 22 | 23 | function renderRequiredInfo() { 24 | return ( 25 |
    26 |

    Sponsorship Required Information & Assets

    27 | 35 |
    36 | ) 37 | } 38 | 39 | return ( 40 |
    41 |
    42 |

    Why sponsor the React Native Newsletter?

    43 |
    44 |

    45 | Sponsoring the newsletter not only gets your company in front of many high quality React Native developers, but it also helps 46 | support the continuing curation and editing of the newsletter. 47 |

    48 | {renderStats()} 49 | 55 |
    56 |
    57 |

    Example Sponsorship

    58 | 59 |
    60 | {/* {renderRequiredInfo()} */} 61 |
    62 |

    Complete this Form to Sponsor the Newsletter

    63 |
    64 |
    65 | 75 |
    76 |
    77 | {/*

    78 | Email us with any questions or to inquire 79 | about a sponsorship. 80 |

    */} 81 |
    82 | ) 83 | } 84 | let domContainer = document.querySelector("#sponsor_page_content") 85 | ReactDOM.render(, domContainer) 86 | -------------------------------------------------------------------------------- /static.json: -------------------------------------------------------------------------------- 1 | { 2 | "root": "." 3 | } -------------------------------------------------------------------------------- /suggest-article.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 9 | 18 | 19 | 20 | 24 | 25 | React Native Newsletter 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 |
    38 |
    39 | 53 | 85 | 86 | 90 |
    91 |
    92 | 93 | 117 | 118 | 119 |
    120 |
    121 |

    You can find this page on our new site

    122 |

    Many of our pages have moved! Article suggestions have moved to a new website.

    123 |

    Please check out ReactNativeNewsletter.com for more.

    124 |

    125 | 126 | 127 | Take me to the new site 128 | 129 |

    130 |
    131 |
    132 | 133 |
    134 |
    135 |
    136 |
    137 |

    Jon Major Condon, Editor-in-Chief

    138 |

    Jon Major specializes in React Native at Infinite Red.

    139 |
    140 |
    141 | 142 | 148 |
    149 |
    150 |
    151 | 155 | 159 | 160 | 161 | 162 | 163 | --------------------------------------------------------------------------------