From 4e046273e2108d3ab51781cb825143159639cbb1 Mon Sep 17 00:00:00 2001 From: Alvin Lim Date: Thu, 28 Mar 2019 09:56:01 +0700 Subject: [PATCH] docs(pwa-example): add example for pwa ported google pwa example to work with maleo re #152 --- example/pwa/README.md | 3 + example/pwa/_document.jsx | 34 ++ example/pwa/_wrap.jsx | 17 + example/pwa/images/clear.png | Bin 0 -> 1321 bytes .../pwa/images/cloudy-scattered-showers.png | Bin 0 -> 2031 bytes example/pwa/images/cloudy.png | Bin 0 -> 1778 bytes example/pwa/images/cloudy_s_sunny.png | Bin 0 -> 2696 bytes example/pwa/images/fog.png | Bin 0 -> 3912 bytes example/pwa/images/ic_add_white_24px.svg | 4 + example/pwa/images/ic_refresh_white_24px.svg | 4 + example/pwa/images/icons/icon-128x128.png | Bin 0 -> 1201 bytes example/pwa/images/icons/icon-144x144.png | Bin 0 -> 5438 bytes example/pwa/images/icons/icon-152x152.png | Bin 0 -> 5763 bytes example/pwa/images/icons/icon-192x192.png | Bin 0 -> 1961 bytes example/pwa/images/icons/icon-256x256.png | Bin 0 -> 2696 bytes example/pwa/images/icons/icon-32x32.png | Bin 0 -> 365 bytes example/pwa/images/partly-cloudy.png | Bin 0 -> 2064 bytes example/pwa/images/rain.png | Bin 0 -> 1538 bytes example/pwa/images/scattered-showers.png | Bin 0 -> 1916 bytes example/pwa/images/sleet.png | Bin 0 -> 1357 bytes example/pwa/images/snow.png | Bin 0 -> 2206 bytes example/pwa/images/thunderstorm.png | Bin 0 -> 2529 bytes example/pwa/images/wind.png | Bin 0 -> 1474 bytes example/pwa/maleo.config.js | 9 + example/pwa/manifest.json | 35 ++ example/pwa/package.json | 17 + example/pwa/routes.json | 6 + example/pwa/server.js | 72 ++++ example/pwa/src/Cards.jsx | 140 ++++++ example/pwa/src/Dialog.jsx | 39 ++ example/pwa/src/Loading.jsx | 14 + example/pwa/src/RootComponent.jsx | 196 +++++++++ example/pwa/src/style.css | 406 ++++++++++++++++++ example/pwa/sw.js | 87 ++++ 34 files changed, 1083 insertions(+) create mode 100644 example/pwa/README.md create mode 100644 example/pwa/_document.jsx create mode 100644 example/pwa/_wrap.jsx create mode 100755 example/pwa/images/clear.png create mode 100755 example/pwa/images/cloudy-scattered-showers.png create mode 100755 example/pwa/images/cloudy.png create mode 100755 example/pwa/images/cloudy_s_sunny.png create mode 100755 example/pwa/images/fog.png create mode 100755 example/pwa/images/ic_add_white_24px.svg create mode 100755 example/pwa/images/ic_refresh_white_24px.svg create mode 100755 example/pwa/images/icons/icon-128x128.png create mode 100755 example/pwa/images/icons/icon-144x144.png create mode 100755 example/pwa/images/icons/icon-152x152.png create mode 100755 example/pwa/images/icons/icon-192x192.png create mode 100755 example/pwa/images/icons/icon-256x256.png create mode 100755 example/pwa/images/icons/icon-32x32.png create mode 100755 example/pwa/images/partly-cloudy.png create mode 100755 example/pwa/images/rain.png create mode 100755 example/pwa/images/scattered-showers.png create mode 100755 example/pwa/images/sleet.png create mode 100755 example/pwa/images/snow.png create mode 100755 example/pwa/images/thunderstorm.png create mode 100755 example/pwa/images/wind.png create mode 100644 example/pwa/maleo.config.js create mode 100644 example/pwa/manifest.json create mode 100644 example/pwa/package.json create mode 100644 example/pwa/routes.json create mode 100644 example/pwa/server.js create mode 100644 example/pwa/src/Cards.jsx create mode 100644 example/pwa/src/Dialog.jsx create mode 100644 example/pwa/src/Loading.jsx create mode 100644 example/pwa/src/RootComponent.jsx create mode 100644 example/pwa/src/style.css create mode 100644 example/pwa/sw.js diff --git a/example/pwa/README.md b/example/pwa/README.md new file mode 100644 index 00000000..a1b22655 --- /dev/null +++ b/example/pwa/README.md @@ -0,0 +1,3 @@ +# Maleo Progressive Web Application Example + +This example is ported from [Google's PWA Tutorial](https://developers.google.com/web/fundamentals/codelabs/your-first-pwapp/) to work with Maleo diff --git a/example/pwa/_document.jsx b/example/pwa/_document.jsx new file mode 100644 index 00000000..ecee6f8e --- /dev/null +++ b/example/pwa/_document.jsx @@ -0,0 +1,34 @@ +import React from 'react'; +import { default as Document, Header, Scripts, Main } from '@airy/maleo/document'; + +export default class CustomDocument extends Document { + render() { + return ( + +
+ + + + + + + Weather PWA + + {/* Safari */} + + + + + + {/* Windows */} + + +
+ +
+ + + + ); + } +} diff --git a/example/pwa/_wrap.jsx b/example/pwa/_wrap.jsx new file mode 100644 index 00000000..49b37881 --- /dev/null +++ b/example/pwa/_wrap.jsx @@ -0,0 +1,17 @@ +import React from 'react'; +import Wrap from '@airy/maleo/wrap'; +import pageWithStyles from '@airy/maleo-css-plugin/pageWithStyles'; + +@pageWithStyles +export default class extends Wrap { + static getInitialProps = () => { + // Register Service Worker on client + if (typeof window !== 'undefined') { + if ('serviceWorker' in navigator) { + navigator.serviceWorker.register('./sw').then(function() { + console.log('Service Worker Registered'); + }); + } + } + }; +} diff --git a/example/pwa/images/clear.png b/example/pwa/images/clear.png new file mode 100755 index 0000000000000000000000000000000000000000..28e292954290f964d6fcb90a8c5482f64a640cbc GIT binary patch literal 1321 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

# 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 literal 0 HcmV?d00001 diff --git a/example/pwa/images/ic_add_white_24px.svg b/example/pwa/images/ic_add_white_24px.svg new file mode 100755 index 00000000..012e1849 --- /dev/null +++ b/example/pwa/images/ic_add_white_24px.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/example/pwa/images/ic_refresh_white_24px.svg b/example/pwa/images/ic_refresh_white_24px.svg new file mode 100755 index 00000000..7a8d303e --- /dev/null +++ b/example/pwa/images/ic_refresh_white_24px.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/example/pwa/images/icons/icon-128x128.png b/example/pwa/images/icons/icon-128x128.png new file mode 100755 index 0000000000000000000000000000000000000000..de286f2dd85ed0b9558665d567f694fdce10ebc9 GIT binary patch literal 1201 zcmeAS@N?(olHy`uVBq!ia0vp^4Is?H1|$#LC7uRSEX7WqAsj$Z!;#Vf4nJ za0`JjtCPjfmEe;$l2R`Y6*kH6_uB<+D>H_ua zx%Z0_4>bH-vDEqM%`-i3wZ30mfA!LxHCxR)#P_kVJn(j4AQp0XGw7aw|33fS3fZ}b z`!1Y*|2g`Ie*n{t1hu|PiE2%DtrM@Sax4g85Z~hywe@e)@z=&I0cs80Q6Ezuv`^t! z;KJ~7*IULb91nIfuy6UJ$jVfq)xdr3eA~%;Vs!!s{26ZvH~n8A8=0A6^kq-cb&JLj z%?6eO^E?#i-_-f@+s(VqaW%u)lT0%LrcZsvGC}W#)?%lI+TcB5ifj94y7e+m@nWr* z9iY^3fAfEhHfEL`Z9I&R#1^Kj)8HHr}1h5hqQmO3XS=y*)x<5JU_6!vE=9Z zrpaHP-F&>3;nFK#g~soBf8TFqP|x{1Z_}OG+&+_)mWq%d=@yS{He%HkBeog`opIg?? z$@u!cnaN)5Q0!WUQ@j5qseD+u*jn*}v)ufdSt1K~HGcf`TwAx!{KQob1<8HN>Zxmc z&Y%CZ)~oK?+q-X1A30Oyw9vI-@AeAmNUvqwcGi`aZrjqBqWW3(f7AHkpT*0x#ZD#G zr7h`TowNNPne$Qq9?d%-&Uj{`=XCul)y+#nVvg0kw%mE1spj&l&HRMFDBgF7pTx687-S3wqSPFSD_nuPhCFReXBFlxuSoFclSR(#}EH?1)T*K z%;pIDn7X%Nrq>Iba6x5Hxz#yR$N%-SNYM4ctls4cbW+X?{G#o+3g8zA{1ufhzprM?dXR>)xSb zRm8bNZ(e)7#KF&c&HL&lnF|k2Z(yk5FVdQ&MBb@ E03WaJs{jB1 literal 0 HcmV?d00001 diff --git a/example/pwa/images/icons/icon-144x144.png b/example/pwa/images/icons/icon-144x144.png new file mode 100755 index 0000000000000000000000000000000000000000..3e919f8c801f94e23765533ac5d3d5aea74ccb77 GIT binary patch literal 5438 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 R{}ZBQ(1$Rc8ZFzm{{yO;G=%^F literal 0 HcmV?d00001 diff --git a/example/pwa/images/icons/icon-152x152.png b/example/pwa/images/icons/icon-152x152.png new file mode 100755 index 0000000000000000000000000000000000000000..6ef1f8f0b9eca5d3213183c6b4e0067c5a43d720 GIT binary patch literal 5763 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

# zd6}l^JYokv(e>S8SIK99Ruysy|)|mxDzm;zA{zh03wQJJsaTHW6mo`N8j>WG=I**K+JM_(&*e^HMR|> zX)k<)wfk`?xWk#ZocIMeq=~G}ghKVpm~ZAr6?_yN#v1XaMBDHWKRVC(TH9z z*S z1HvbVc^>NnC1!Cs8eZr#0P1~osNND{|vzEmEtpmc&Ln^O`p~7alRYT`dn>`c6g*epXhr$;a} zM~R&&^l+B>F0z5KaW_l-yKe#vin(Hp@yRaSO{G4Xi&$2y^AlM2?AY=+MKQ*<`tYE} zhpzh57e8{&KBCh!ea6q-9*xTdp172spZRW9)jz#Iih`OKE^7P`E#N%EdbUlLWyJ!9 zt91(wH11u0Z63>-fCKBeRD5ilnH1C%3PjhH&($&bdUjUBzZnejj5#Zo-LqcUaN3Cd zMM|^Ft+T5WoGs>eRDNgtC^^4c{f>f?J@+a5L_rOvdffu%lBOmDBLS~>!0=-5boFyt I=akR{0D{nkY5)KL literal 0 HcmV?d00001 diff --git a/example/pwa/images/partly-cloudy.png b/example/pwa/images/partly-cloudy.png new file mode 100755 index 0000000000000000000000000000000000000000..2e217848aa8751ab0ae02453d71beb14361bf70e GIT binary patch literal 2064 zcmcJQ*H@G27RKLvNobis1cV423{9Fw6w!ddgeFDA&;$&SNI!rYk%8b)J|QY91B4ln zS<(hj%0Y=END)cY!;A<>P-#kuQHn&WASI9tXU(55>+FmDd-lcN&(*W`b&7{GRzX7n z0DyIMar6QJu`Llm4!Mn(I)9&SL{Qv)oVF>IN{5Gsr5~dHf1Q{gFtzPOi1+gF1^|a6 z5X{WTWD12&XE0zmH@B>e!{PDxe1TwLA<`Jn1whu))zQv}`EGVJ=2kfgCqws3Pj@j@ zP%y$tq@^QoYd||V~)t>>6=p72Au~M z1~w$S??Q~kzB|b~ZbePC@8emyxZQDqR<}S~wb74`JJts@5zDb#=Zl`K0!~Jq7QUme z#0J*Puh3nLzzPf|reAChL(BkIWi6Bj7^&39T!IpSI56*+@D+w&)T#ITBvKGz;GjC@ z4(dWXRU=~*fv7GF)9S&K#r;xup}}325j2PiPWzgDwqGVa0iy^O;sdQ#p=p*|C>s|OCZBx|hSZPe1pS9y*2GSNj^NHx6l zGm^EGBX|4z+kB+zxBr5)N8EjM%?8zF6z;v*)?m@05rqj!+EE3P%u`P!e9^q8w05P3 z?dI9bIu+4sNX=}OOEr%gtKq|wOaY^?Ilo%AH;SiM6HzG|aBv=DuD!l4#)EeBM* zzN434@k%}*q1(n5?!W1gdZHg8yrg4<-Gzzhxh^b|EM*_7&d_gQtdg69`gn zBW<#Xh6?|c14wyhGY9DFkur!c6cA=Xj}fEO|3L*AvOw1Px-A_5rdzx`REAd~gw*Vx`3n6`6l9}^K6ynJRVQ|3umQEkQcHM+uuGQHH!6uJ z&5UkJR)t?QBHsoP_%`y^Q07V#*F&bdT`oZnJW^@kTJGl;%Uc7NDp36==#zaKPU1!9 zeH)xYJNG;k*zi&{;6kQappr~x6{1)YqJIC!8K|$BLV^QF^?P*DIs%!i#Hn zy>k8F2^|1w2eoR53}MInc4h~fSB%;7@;vR^Ouer$f@yf!-SSC*B&kYor}cXwI#k@> zHF;n4zQv>>2GI6Usw10B8)J&8ilFrDT+{sE>dg2-+xUUi{F%mqeMq>&Li|H3mo##3 z{`0Nr_mWc+(6fpM=Dor}$w|`5h~|aJ3nK3kef4FaohbI(zh{lI+%`~jP%C@sloPd` z7@U`uf~^m>Ly>7p#xd`>tzP4fR5p@7=n!q2{AjsXEo4KCcsq{lu}LeSiWM!v;-SKY zM^Za=e2N2WnN??;)wvSwkc-TX$XG$suGMVKHofynWXU}y2Vu{3ev1{kDGAKu!5>F3 z>5>BfV`B(X>DjZN5ieSK>=Y2MEqXJmQuz`c+lVE;yOImRQ88c2E07~Q<8)h$HQ0MD zcPkyS1W_ehetLxB-N4m8a5P#u?kZ5FI{41st`C54-=&*ita_ATI?hM)!(bAWHLkf) zj2s@{7l-f<-Ji8LLeXq4Qtw7}`)6}1yhHxXRANU90;S30A2s(})ym=qUKc?4UzBO* za_lVLnyw2WJb^)*bvoX1!$5^Ren+q*xb(23+`?2FE`gNxTSl9_|F{5_m78l;-fVjO zRxq?Z;HFE`ueFL2x3Zy)s)w}@`ae}XP+gj=Wsn>ZzCtxBL9qSi=N~)2^8KFIUj0RSVni}8hGNmG!IJKV7<;KSTO|@L zU%z${J@lf+fli}Zx;aPff@T*FC5b2UTQXlhuY57pE^{#IJBBYi zX~Ek|O=^*;y^3DznjVpq4GmW+5*+^Z1FIEv)Z7a;QGf02QgebbdwKF0_|$6Rn$#ai z!COF;Z~ff5Y}ID>MoBM#@lnA@vTR4G+`^XL&#fMpv1tAiF$RPpSUR)ZE~M?@fAYPy dcbU)EcJFDAx*8?U-2J~(u1+3~_wDKFe*ri5k7NJ< literal 0 HcmV?d00001 diff --git a/example/pwa/images/rain.png b/example/pwa/images/rain.png new file mode 100755 index 0000000000000000000000000000000000000000..d335d2777e43450942a2fb5a54e9a07d874140de GIT binary patch literal 1538 zcmZ`(X;4#F82#>hSrAM}1w~E3xD>HE5;a;F7{Kdik!zH`1a-}&bLxc3~8`FU~7 zCz}HR$H!Z;5&)Sf0yEqMn=S?gnqZYo8o0!SMx$|gd9&&Kw|*gh9{OkOU-Gx>i`E-2 z$~3L!$FKAY0O0Y2LXn6dWF#qTh znSVr%jwgRXS``lMtpBJv*(~iGoTyHSQum;iE=G;AHn%;q=Gt^XW&~h73K+t#QJ04J zf)g7;7WgN2CHh#6SJ~RP-4lx!f^uz@@#TEw9W?pSr`4MSMD&_mOYrvO;k4jQP>#l% zimkd^a=j9{j_Aub%o(dHA=lXlj3dfOMW-EWElSxph%XB^CoFGNSeuQ}m5vr-2(>W# zvGi1`YMp_ujAV;!k}IRxPIngEj-~3844P;mk2-c6iK19ep2FK<)Y5Q+GW|!Gjq(1- zUCV=Gwh(l9C7iMq`dXxcXk~BpNOwi4JF6t0hmodhm0u7WqDr>8pQ^JWbMUKW?fvr7 zYlo7b`kR5a=F*hf_SRYBY#!oZW``{M?U#pv)oFd?R*cwvKhzCuk5nYg%wkV`0J;Ye z7-@x^!hEvX$}Fj>0V6$12b=-UGtBWP9rzx!x%}vNTSWFK`qdwl_G8-U-$_Zis}8OXmTKzJT*J_;S(QB ztW^eVIRi@_()%J{LSbFw7#PqBHr+yg=h0PxD;j&fdKeA#AUAhu7mzECP&gd|^v=x2 zSazgLlG=y2BCdmk9#76;=!QeD+Uf$$fg1|}^Wab%7IY9%2^itg9nDrovxzcW+L}pj zVpHl79j%f@Ctvq)JC{5>-#Y4+fBl&lmYOzOQypO>aIjKJPZB>U4opyub zMC!Lh2yh|RZp0q7+u49akDh*k$>*5SkKbiA_Kp3))jnxvjKo}g+&T)CReEq$Y+l$T_x69}KZ0w88nEKxjLGZ}( z+-5@U?Egs#j{1bqrXicBmoh{%8MM28Fz;GZzGKaCfKQo&Np7yiuJtCa9}KAP=i6<} zaHV^Py^d!-^;T4%lWwCUbW+pf46&C$7h@P#&Bm|*9O$8{IG0@qoV~1dKRv(LF#oeS zgHEs7W)*!|u3(^8aeehK($97?c|ly*p1j#Qfit9Y9L!Z3^eqZpq!Lo~ENh0gnc51z zd>NOB!VjXz7-AL_aU7VcVzdVa7O8kt2kR)3wNa+0%a<_-1?~%lvBVg7#Bl&s88V=w z->clIx2yq{wu9<`7QWVo*ny{DU0Vo$FmSrqG6Ek))>&^Q zV~ASsguDJOUiH>_H#B(i?UFLurs^6)y7l|BRl$n0`P1Jo{Lpi=U9I;%VYc2FE&&L= zQkC{$-gTQ4^{j3|xy3ZcSDsgj&i;CBk}B_iqwMPe_m?V@r((u<%ka5{hc%|e1)n8; KlFOdt?mq$V%ZHBu literal 0 HcmV?d00001 diff --git a/example/pwa/images/scattered-showers.png b/example/pwa/images/scattered-showers.png new file mode 100755 index 0000000000000000000000000000000000000000..b2235ffb2e6ad287ffc55e333e665068bac66e43 GIT binary patch literal 1916 zcmbtVX;f1O7QT-_5(t5?6cK@hMV1aiia-HTB2Wvm1*F4PB*0i>0S76vspLU*KrILr z1gQrfLx)Bdr631%D0v_wD66s)ksxYZPy(_Tf@E?|f6Rg}Pm-#bq)wtqt|cz-FePsbInyVH}oCslfA zn%bvITo4p>>i|OgzoD;*9yS?v_U~>8XLWi!Zc3);xf@qk^%#aM>eBdY!BDf`Uf5m$3q2W4%&& z9bu2ici<#!$o$?dcp5R2&!VH3Eqpr>#@OkzFOZyaZA^oYa9yGGI<}KlefHu5rLJ-} zt?g*^Fkxhm39EAJ&ln-k@qAYZ7}}!K1C@cwh4B{mxM13EfvB?Xk+7e^+o8%!89uQ@ z)#&I~goe*Qb0YE6k&p@KGeDayIO^)R2OU!v)uW1?_5Za_Y;67oj`LUow~O|l9hDP9vk~YwGs#`awQP~LRP!h$K^3_OJ6c}qDxI<2jEN&QTvkWQ9uB-S zJ}4Bfcx-*1NQQqz;4_pIM~I zRcb-V#LkZX)fpE`DXga9q46uV{yg;Dyaw&l^QtEZL-nb4iAsIbNZDQobSw)sVeKSm zHK|Ev)mcqryMt2a)D?~N7$vmb?n?RK@@9hfJx0(q%hxzp}z}6Cvh$G0Ucwmn>jqCl{}zVnUSpXH?4NK z_$4lPzYO}#V}0e;bXJy;{LPeaN#KI;jZ8-w`u|WIEsScntv8RZldr7>(!e~oCTmk~ zIU}9awi>)5TUeMe0dHcLQ2w3dm)dTzgMfr!&Vgb>(Yi@&11N9l*ox;@HOC-i+nk-~ zHc#Nd#+p?ia@43sor-Q|pV2{oYT|HVIWWPH@MyD(=nSigB7M=SAsB;{U1SE|`!JQ@ zZQ*+w{&d4l9Yz+15cGjG+X~8}I_T)6y_FhN1; zxoZTg_WZaD?!e)Ny|17EJ0C09p{GU>Nx?IxZ|xBxY3o^fe9Wae(#jbXZ`Zqu@neN& zOku)|uPr_Y*}+vh*LX>%d7 zr^aU3!CrbA-wo>LfQ$ke=OZ?W*|#X1BRV5d;42hq5GFEc9-z$nPl)z_Yr82$!nYYd wo>L%5+k(x-Fa1U@rTc&E{AiE``-*vA-;~>*+g`Gwcxd4BMS$0J4^GZM0YM#23jhEB literal 0 HcmV?d00001 diff --git a/example/pwa/images/sleet.png b/example/pwa/images/sleet.png new file mode 100755 index 0000000000000000000000000000000000000000..99fb835e4ecb5e8961433612602c474026c6578b GIT binary patch literal 1357 zcmaKse@s(X6vxk_rTnmz7YmBkDlnLeAXRW~MCe0c$PZhT3WzY?m?BeIsuET}%HxOH z!Bhe$K~x?AGgJ_qqGk?lM8NT5v|60SIG;m6TVMq&0|dIVCB!U?=a2LK+1ANw6a`k2>@0>Tl}{JAVx&MoMx2$HBlm?goK5P0*q=f7`EP18{^+RNB_ismhW%Q zAH9F^ROd{Z@wvsx+XdkOC~9xd!@_V}Ocapya=Ai5>2y`KE3*OUXM_BGMUtMO=R2dH z@oY?~8~0OmBtF=-*RW>Dk9Jh*88s&E+L<*R7oyza&d(j#3??W6bbCO|vH!!h7nUS6 z4&UAzr}vEc@#EDPzjne=s|td!$0rR5Wujg<-_mRMd;?RLGzo+&eKn}E53f611WhL& ztEc)wU>JMhv5}!js_(cQZSvZxrsyW;fvFu=V;1_tQf_{$%0^~EMQ3i$l0jqE9W0WM z4Q%7rU+O_rjJnr7$RbHX4F}iN^1FGc1vd0MMD1rpq4r-jLac1++Le7sGDfDyPnMtg+gIUp~ma@swO%?8J+}ezEFKO40Q|u8R zp$rtqudL{Qc`#Vk`PLkebonn`RcjXD0i&*$onZGvpJE!%J|u>pt%LC8a3IzJyx2sq zV4sArRnuD>fjPRz6@lttavi)oIG1Ww6vTc3TJ~uQTs&ZrI+n_?_T>@J6AtA-%6T#X zk{=;AlA%mUZUr|kxU9h9=<;FaV~|u8v#=AKyrA-BSSQ1DPp}owcE{c3nX^3O zk3K3~h`FtD_wyp8?)9^ea|pgX*Re7jdA(lC_qI$kscukA357?eL3J#?$b@_~RRqN` znU-Ls29Mn|W`Py?y_n$aro}jL$O#t8!H*pvSoaZ6Oqrt+K!RwgcP_%K z{zQuc?%%0w<4_SBprf0ORg5R{iEC-ZsS*n=ct$T2!&44Sq+fipob+R-zGDm`R}=l^ zw)i)6YIYZHE#7YmksFDIB~W<|LOnnsfW%cf$;1vXNK1!q8{!NLoPS<`7qi4gEKsr? zz>Y3FiokWMS<&lD&h+Urc433Z9)4SiYj?#DL(+k~DM)++mC4}DC9jndw|hqbwz`=` zEG8~GfZIT!>bFw=n4sr0*gbR@iQtqFVdMA|9PZUI^LRae#oAPOrNv6(`MNO=H1kwmIRN`pE zBzsCp2@#fqH$a7yp^aslo;B}YfF`=cj2!y3BfeTQL!j+1U%~0z`MMu;=$vnl(9n@T zvLju4`e>+LlNVUi(}$pcjTQ#ZL=26BEIp&sJ7wsQne0fGveEFYp`B|#Y8x>Sb#o4! z6O51#YGnOAo&z@S%NzUX$}~Txv|Qa+ZoWsFSeof_Zt_ynY;#zD>yycnrqc3fCD$Da n-&n7mZ;Kd%_zw>ff}Cco(+GyKTW__-K?Xqq0{^R<@$A0=DCs>3 literal 0 HcmV?d00001 diff --git a/example/pwa/images/snow.png b/example/pwa/images/snow.png new file mode 100755 index 0000000000000000000000000000000000000000..e7efe06e89893a43870e560834ac491b81f97073 GIT binary patch literal 2206 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 HDB1FNMXD=2 literal 0 HcmV?d00001 diff --git a/example/pwa/images/wind.png b/example/pwa/images/wind.png new file mode 100755 index 0000000000000000000000000000000000000000..98ea71f47001874f133e71ab9392b9384816e29f GIT binary patch literal 1474 zcmb7EZ!}bS82;Tmu9=MScZS4fDoH9cimBMur6EPr9F5L|HKVdw?Utk1snBJ!4q37N zlVYZSV+qY>Ws@1VP+OEaA`|&nSW;%pC}Ei$`)NPym!1#r^PKm*&wHLP@0-cxY@wJe zG64Wkwg$380Due<0wjWg4wUhE24Zo8dHx30>-8@`6Q#1Dl?JEfkr2*K04(TClq-zG zawRfc*{8{D3!4Q1aox)H<%v4qcXuZi(k&2S>Fc_sYW;0_%ySQ7+kL{~{ofoeEL&aY z(kHXj1sz>ySogWu4u-~dbw$OLmz(G>7Q-H=^s!B<_P4-GUs;}9ZqoN*T0WUFG6C9r zIwOh^q1OBRDlfpQ>ymDR&^P7GRuEHAzg?c&;4o_#)Mph`CF1CQ0Gt2%djz zCCf?!n9|b=+Oj}!<+;0v3b2vb?Z7?Nmxd0|?vKFC&2;53%p9W$dB(~?vAGT=9ZKD1 zhsKfl(IE6=YOWo&JAQ}pU8pwaWYZj(x<-IgaH|X`UV+)8vKYV7)ss5p6);^uUm~De z(Um5Q7uDMl}l2BF$h?NTl;}0d6XEYHu(!YC-AG zENjl6wi=jJdR6z#yj6#kfknsmY65t(!~#Zre{1`lSAEqUd+VhRob-R%-(lmatH z2d3A*RWBYOt3a?ieP5yu2?hnKA8T)vWxX3D^8s)3PpVHG1qPw(8XrxxRgH@jef{8$ zeRmI9RO@Q<)Rv0K&gdFD)6b3b6%sn?Ig|Fj^?}Gqz%`SE1x4zs&hGnH59{@@Eazrh zDnaIdOCQVknV0!RqS?G8Uw1IsFnW4`oCQ(e>3beOM5f>rFd9Ckq6_dbOVK*Jg}nCs zgfz9uBIfF%W1fAa(2g%d&v*1k+sy=r zJ6${6pWe~RpKA|I0KN*;4$Wt9jV*@AMHJ3wyx3cfW3M;8hWc|1)Y zYLP5wzwxBhf)Y)n0)5n^G-RC~)qJZ!yR;kr@1{P{(V^E_;nD;4t9*>OYy7i%&P2o9 z3cMi6L%koIPYXpmd>kdKB1q+8Gj5GSQDsha5l|d|Cn(J$b4^ei3o@E)!cI&(5q2|i zVbW7S*Gr_?^^VF7G)@YMEjL9f_xRtc|0^@_C6Xt-#OQ(JUHuZWaaWir?RIM>`nMa^ zw@AId2GZ`{g;%b-I!qAcYca38*131wn8loo8_uD`I83068<$bB z6q~$eAK?vgz|weX;KoydeP0T4=$v1(*H3j1osRl4t;e`JC}W&dLNqOui>xf| g(D3=+`uT|OIyC6^V(&q9NcOyWt3QWb;U`S{2MI}Pwg3PC literal 0 HcmV?d00001 diff --git a/example/pwa/maleo.config.js b/example/pwa/maleo.config.js new file mode 100644 index 00000000..a8b285da --- /dev/null +++ b/example/pwa/maleo.config.js @@ -0,0 +1,9 @@ +const cssPlugin = require('@airy/maleo-css-plugin'); + +module.exports = cssPlugin({ + enableISL: true, + cssLoader: { + modules: true, + camelCase: true, + }, +}); diff --git a/example/pwa/manifest.json b/example/pwa/manifest.json new file mode 100644 index 00000000..3fcf5b11 --- /dev/null +++ b/example/pwa/manifest.json @@ -0,0 +1,35 @@ +{ + "name": "Weather", + "short_name": "Weather", + "icons": [ + { + "src": "images/icons/icon-128x128.png", + "sizes": "128x128", + "type": "image/png" + }, + { + "src": "images/icons/icon-144x144.png", + "sizes": "144x144", + "type": "image/png" + }, + { + "src": "images/icons/icon-152x152.png", + "sizes": "152x152", + "type": "image/png" + }, + { + "src": "images/icons/icon-192x192.png", + "sizes": "192x192", + "type": "image/png" + }, + { + "src": "images/icons/icon-256x256.png", + "sizes": "256x256", + "type": "image/png" + } + ], + "start_url": "/", + "display": "standalone", + "background_color": "#3E4EB8", + "theme_color": "#2F3BA2" +} \ No newline at end of file diff --git a/example/pwa/package.json b/example/pwa/package.json new file mode 100644 index 00000000..0a78e420 --- /dev/null +++ b/example/pwa/package.json @@ -0,0 +1,17 @@ +{ + "name": "pwa", + "version": "1.0.0", + "main": "index.js", + "license": "MIT", + "scripts": { + "dev": "maleo dev", + "build": "export NODE_ENV=production && maleo build", + "start": "export NODE_ENV=production && node .maleo/server.js" + }, + "dependencies": { + "@airy/maleo": "latest", + "@airy/maleo-css-plugin": "^0.1.6", + "classnames": "^2.2.6", + "react": "^16.8.5" + } +} diff --git a/example/pwa/routes.json b/example/pwa/routes.json new file mode 100644 index 00000000..0e5ca739 --- /dev/null +++ b/example/pwa/routes.json @@ -0,0 +1,6 @@ +[ + { + "path": "/", + "page": "./src/RootComponent" + } +] \ No newline at end of file diff --git a/example/pwa/server.js b/example/pwa/server.js new file mode 100644 index 00000000..bbfcadca --- /dev/null +++ b/example/pwa/server.js @@ -0,0 +1,72 @@ +import { Server } from '@airy/maleo/server'; +import path from 'path'; +import express from 'express'; + +const PORT = process.env.PORT || 3000; + +const maleoServer = Server.init({ + port: PORT, +}); + +// register static image folder +maleoServer.applyExpressMiddleware('/images', express.static('./images')); +// register path /sw to return service worker file +maleoServer.applyExpressMiddleware('/sw', (req, res, next) => { + res.sendFile(path.resolve('.', 'sw.js')); +}); +maleoServer.applyExpressMiddleware('/manifest.json', (req, res, next) => { + res.sendFile(path.resolve('.', 'manifest.json')); +}); +maleoServer.faviconHandler = (req, res) => { + res.sendFile(path.resolve('.', 'images', 'icons', 'icon-32x32.png')); +}; + +// example for client fetching data +maleoServer.applyExpressMiddleware('/api/forecast', (req, res) => { + setTimeout(() => { + res.send({ + query: { + created: Date.parse(new Date()), + result: { + key: '2459115', + label: 'New York, NY', + created: '2016-07-22T01:00:00Z', + channel: { + astronomy: { + sunrise: '5:43 am', + sunset: '8:21 pm', + }, + item: { + condition: { + text: 'Windy', + date: 'Thu, 21 Jul 2016 09:00 PM EDT', + temp: 56, + code: 24, + }, + forecast: [ + { code: 44, high: 86, low: 70 }, + { code: 44, high: 94, low: 73 }, + { code: 4, high: 95, low: 78 }, + { code: 24, high: 75, low: 89 }, + { code: 24, high: 89, low: 77 }, + { code: 44, high: 92, low: 79 }, + { code: 44, high: 89, low: 77 }, + ], + }, + atmosphere: { + humidity: 56, + }, + wind: { + speed: 25, + direction: 195, + }, + }, + }, + }, + }); + }, 2000); +}); + +maleoServer.run(() => { + console.log('Custom Server running on port:', PORT); +}); diff --git a/example/pwa/src/Cards.jsx b/example/pwa/src/Cards.jsx new file mode 100644 index 00000000..efb97308 --- /dev/null +++ b/example/pwa/src/Cards.jsx @@ -0,0 +1,140 @@ +import React from 'react'; +import cn from 'classnames'; +import withStyles from '@airy/maleo-css-plugin/withStyles'; + +import style from './style.css'; + +const daysOfWeek = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']; + +function Cards({ visibleCards }) { + const today = new Date().getDay(); + + return ( +

+ {Object.keys(visibleCards).map((card) => { + const { + channel: { + astronomy: { sunrise, sunset }, + atmosphere: { humidity }, + item: { condition, forecast }, + wind, + }, + created, + key, + label, + } = visibleCards[card]; + + return ( +
+
+
+
+
{condition.date}
+
{condition.text}
+
+
+
+
+ {Math.round(condition.temp)} + °F +
+
+
+
{Math.round(humidity)}%
+
+ {Math.round(wind.speed)} + mph + {wind.direction}° +
+
{sunrise}
+
{sunset}
+
+
+
+ {forecast.map((fc, i) => ( +
+
{daysOfWeek[(i + today) % 7]}
+
+
+ {Math.round(fc.high)}° +
+
+
+ {Math.round(fc.low)}° +
+
+ ))} +
+
+ ); + })} +
+ ); +} + +function getIconClass(weatherCode, style) { + weatherCode = parseInt(weatherCode); + switch (weatherCode) { + case 25: // cold + case 32: // sunny + case 33: // fair (night) + case 34: // fair (day) + case 36: // hot + case 3200: // not available + return style.clearDay; + case 0: // tornado + case 1: // tropical storm + case 2: // hurricane + case 6: // mixed rain and sleet + case 8: // freezing drizzle + case 9: // drizzle + case 10: // freezing rain + case 11: // showers + case 12: // showers + case 17: // hail + case 35: // mixed rain and hail + case 40: // scattered showers + return style.rain; + case 3: // severe thunderstorms + case 4: // thunderstorms + case 37: // isolated thunderstorms + case 38: // scattered thunderstorms + case 39: // scattered thunderstorms (not a typo) + case 45: // thundershowers + case 47: // isolated thundershowers + return style.thunderstorms; + case 5: // mixed rain and snow + case 7: // mixed snow and sleet + case 13: // snow flurries + case 14: // light snow showers + case 16: // snow + case 18: // sleet + case 41: // heavy snow + case 42: // scattered snow showers + case 43: // heavy snow + case 46: // snow showers + return style.snow; + case 15: // blowing snow + case 19: // dust + case 20: // foggy + case 21: // haze + case 22: // smoky + return style.fog; + case 24: // windy + case 23: // blustery + return style.windy; + case 26: // cloudy + case 27: // mostly cloudy (night) + case 28: // mostly cloudy (day) + case 31: // clear (night) + return style.cloudy; + case 29: // partly cloudy (night) + case 30: // partly cloudy (day) + case 44: // partly cloudy + return style.partlyCloudyDay; + default: + return ''; + } +} + +export default withStyles(style)(Cards); diff --git a/example/pwa/src/Dialog.jsx b/example/pwa/src/Dialog.jsx new file mode 100644 index 00000000..6829fc35 --- /dev/null +++ b/example/pwa/src/Dialog.jsx @@ -0,0 +1,39 @@ +import React from 'react'; +import withStyles from '@airy/maleo-css-plugin/withStyles'; + +import style from './style.css'; + +export function Dialog({ toggleAddDialog, addCity, selectedCity, changeSelectedCity, cities }) { + return ( +
+
+
Add new city
+
+ +
+
+ + +
+
+
+ ); +} + +export default withStyles(style)(Dialog); diff --git a/example/pwa/src/Loading.jsx b/example/pwa/src/Loading.jsx new file mode 100644 index 00000000..fbca6f8a --- /dev/null +++ b/example/pwa/src/Loading.jsx @@ -0,0 +1,14 @@ +import React from 'react'; +import withStyles from '@airy/maleo-css-plugin/withStyles'; + +import style from './style.css'; + +export default withStyles(style)(function() { + return ( +
+ + + +
+ ); +}); diff --git a/example/pwa/src/RootComponent.jsx b/example/pwa/src/RootComponent.jsx new file mode 100644 index 00000000..64e97d47 --- /dev/null +++ b/example/pwa/src/RootComponent.jsx @@ -0,0 +1,196 @@ +import React from 'react'; +import withStyles from '@airy/maleo-css-plugin/withStyles'; +import Dynamic from '@airy/maleo/dynamic'; + +import style from './style.css'; + +const Cards = Dynamic({ + loader: () => import(/* webpackChunkName:"Cards" */ './Cards'), +}); + +const Dialog = Dynamic({ + loader: () => import(/* webpackChunkName:"Dialog" */ './Dialog'), +}); + +const Loading = Dynamic({ + loader: () => import(/* webpackChunkName:"Loading" */ './Loading'), +}); + +const cities = [ + { value: 2357536, city: 'Austin, TX' }, + { value: 2367105, city: 'Boston, MA' }, + { value: 2379574, city: 'Chicago, IL' }, + { value: 2459115, city: 'New York, NY' }, + { value: 2475687, city: 'Portland, OR' }, + { value: 2487956, city: 'San Francisco, CA' }, + { value: 2490383, city: 'Seattle, WA' }, +]; + +@withStyles(style) +export default class RootComponent extends React.Component { + state = { + isLoading: true, + showDialogContainer: false, + visibleCards: {}, + selectedCities: [], + selectedCity: cities[0].value, + }; + + componentDidMount() { + this.getForecast(); + } + + getForecast = async (key, label) => { + this.setState({ isLoading: true }); + const response = await fetch('/api/forecast'); + + // const response = await axios.get(url); + if (response.status === 200) { + const { query } = await response.json(); + + this.updateForecastCard(query.result); + } + }; + + updateForecasts = () => { + console.log('Update Forecast'); + }; + + toggleAddDialog = (visible = false) => { + this.setState({ + showDialogContainer: visible, + }); + }; + + updateForecastCard = (data) => { + const dataLastUpdated = new Date(data.created); + + const { visibleCards } = this.state; + if (!visibleCards[data.key]) { + this.setState({ + visibleCards: { + ...visibleCards, + [data.key]: data, + }, + isLoading: false, + }); + } + }; + + changeSelectedCity = (e) => { + this.setState({ + selectedCity: e.target.value, + }); + }; + + addCity = () => { + const { selectedCity } = this.state; + const selected = cities.find((c) => c.value === selectedCity); + + this.getForecast(selected.value, selected.city); + this.toggleAddDialog(false); + }; + + getIconClass = (weatherCode) => { + weatherCode = parseInt(weatherCode); + switch (weatherCode) { + case 25: // cold + case 32: // sunny + case 33: // fair (night) + case 34: // fair (day) + case 36: // hot + case 3200: // not available + return style.clearDay; + case 0: // tornado + case 1: // tropical storm + case 2: // hurricane + case 6: // mixed rain and sleet + case 8: // freezing drizzle + case 9: // drizzle + case 10: // freezing rain + case 11: // showers + case 12: // showers + case 17: // hail + case 35: // mixed rain and hail + case 40: // scattered showers + return style.rain; + case 3: // severe thunderstorms + case 4: // thunderstorms + case 37: // isolated thunderstorms + case 38: // scattered thunderstorms + case 39: // scattered thunderstorms (not a typo) + case 45: // thundershowers + case 47: // isolated thundershowers + return style.thunderstorms; + case 5: // mixed rain and snow + case 7: // mixed snow and sleet + case 13: // snow flurries + case 14: // light snow showers + case 16: // snow + case 18: // sleet + case 41: // heavy snow + case 42: // scattered snow showers + case 43: // heavy snow + case 46: // snow showers + return style.snow; + case 15: // blowing snow + case 19: // dust + case 20: // foggy + case 21: // haze + case 22: // smoky + return style.fog; + case 24: // windy + case 23: // blustery + return style.windy; + case 26: // cloudy + case 27: // mostly cloudy (night) + case 28: // mostly cloudy (day) + case 31: // clear (night) + return style.cloudy; + case 29: // partly cloudy (night) + case 30: // partly cloudy (day) + case 44: // partly cloudy + return style.partlyCloudyDay; + default: + return ''; + } + }; + + render() { + const { isLoading, showDialogContainer, visibleCards, selectedCity } = this.state; + + return ( +
+
+

Weather PWA

+
+ + {showDialogContainer && ( + + )} + + {!!Object.keys(visibleCards).length && } + + {isLoading && } +
+ ); + } +} diff --git a/example/pwa/src/style.css b/example/pwa/src/style.css new file mode 100644 index 00000000..609383a2 --- /dev/null +++ b/example/pwa/src/style.css @@ -0,0 +1,406 @@ +/* + * Copyright 2016 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +* { + box-sizing: border-box; } + +html, body { + padding: 0; + margin: 0; + height: 100%; + width: 100%; + font-family: 'Helvetica', 'Verdana', sans-serif; + font-weight: 400; + font-display: optional; + color: #444; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; } + +html { + overflow: hidden; } + +body { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + z-index: -100; + display: flex; + -webkit-box-orient: vertical; + -webkit-box-direction: normal; + -webkit-flex-direction: column; + -ms-flex-direction: column; + flex-direction: column; + -webkit-flex-wrap: nowrap; + -ms-flex-wrap: nowrap; + flex-wrap: nowrap; + -webkit-box-pack: start; + -webkit-justify-content: flex-start; + -ms-flex-pack: start; + justify-content: flex-start; + -webkit-box-align: stretch; + -webkit-align-items: stretch; + -ms-flex-align: stretch; + align-items: stretch; + -webkit-align-content: stretch; + -ms-flex-line-pack: stretch; + align-content: stretch; + background: #ececec; } + +.header { + width: 100%; + height: 56px; + color: #FFF; + background: #3F51B5; + position: fixed; + font-size: 20px; + box-shadow: 0 4px 5px 0 rgba(0, 0, 0, 0.14), 0 2px 9px 1px rgba(0, 0, 0, 0.12), 0 4px 2px -2px rgba(0, 0, 0, 0.2); + padding: 16px 16px 0 16px; + will-change: transform; + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-box-orient: horizontal; + -webkit-box-direction: normal; + -webkit-flex-direction: row; + -ms-flex-direction: row; + flex-direction: row; + -webkit-flex-wrap: nowrap; + -ms-flex-wrap: nowrap; + flex-wrap: nowrap; + -webkit-box-pack: start; + -webkit-justify-content: flex-start; + -ms-flex-pack: start; + justify-content: flex-start; + -webkit-box-align: stretch; + -webkit-align-items: stretch; + -ms-flex-align: stretch; + align-items: stretch; + -webkit-align-content: center; + -ms-flex-line-pack: center; + align-content: center; + -webkit-transition: -webkit-transform 0.233s cubic-bezier(0, 0, 0.21, 1) 0.1s; + transition: -webkit-transform 0.233s cubic-bezier(0, 0, 0.21, 1) 0.1s; + transition: transform 0.233s cubic-bezier(0, 0, 0.21, 1) 0.1s; + transition: transform 0.233s cubic-bezier(0, 0, 0.21, 1) 0.1s, -webkit-transform 0.233s cubic-bezier(0, 0, 0.21, 1) 0.1s; + z-index: 1000; } + .header .headerButton { + width: 24px; + height: 24px; + margin-right: 16px; + text-indent: -30000px; + overflow: hidden; + opacity: 0.54; + -webkit-transition: opacity 0.333s cubic-bezier(0, 0, 0.21, 1); + transition: opacity 0.333s cubic-bezier(0, 0, 0.21, 1); + border: none; + outline: none; + cursor: pointer; } + .header #butRefresh { + background: url(/images/ic_refresh_white_24px.svg) center center no-repeat; } + .header #butAdd { + background: url(/images/ic_add_white_24px.svg) center center no-repeat; } + +.header__title { + font-weight: 400; + font-size: 20px; + margin: 0; + -webkit-box-flex: 1; + -webkit-flex: 1; + -ms-flex: 1; + flex: 1; } + +.loader { + left: 50%; + top: 50%; + position: fixed; + -webkit-transform: translate(-50%, -50%); + transform: translate(-50%, -50%); } + .loader #spinner { + box-sizing: border-box; + stroke: #673AB7; + stroke-width: 3px; + -webkit-transform-origin: 50%; + transform-origin: 50%; + -webkit-animation: line 1.6s cubic-bezier(0.4, 0, 0.2, 1) infinite, rotate 1.6s linear infinite; + animation: line 1.6s cubic-bezier(0.4, 0, 0.2, 1) infinite, rotate 1.6s linear infinite; } + +@-webkit-keyframes rotate { + from { + -webkit-transform: rotate(0); + transform: rotate(0); } + to { + -webkit-transform: rotate(450deg); + transform: rotate(450deg); } } + +@keyframes rotate { + from { + -webkit-transform: rotate(0); + transform: rotate(0); } + to { + -webkit-transform: rotate(450deg); + transform: rotate(450deg); } } + +@-webkit-keyframes line { + 0% { + stroke-dasharray: 2, 85.964; + -webkit-transform: rotate(0); + transform: rotate(0); } + 50% { + stroke-dasharray: 65.973, 21.9911; + stroke-dashoffset: 0; } + 100% { + stroke-dasharray: 2, 85.964; + stroke-dashoffset: -65.973; + -webkit-transform: rotate(90deg); + transform: rotate(90deg); } } + +@keyframes line { + 0% { + stroke-dasharray: 2, 85.964; + -webkit-transform: rotate(0); + transform: rotate(0); } + 50% { + stroke-dasharray: 65.973, 21.9911; + stroke-dashoffset: 0; } + 100% { + stroke-dasharray: 2, 85.964; + stroke-dashoffset: -65.973; + -webkit-transform: rotate(90deg); + transform: rotate(90deg); } } + +.main { + padding-top: 60px; + -webkit-box-flex: 1; + -webkit-flex: 1; + -ms-flex: 1; + flex: 1; + overflow-x: hidden; + overflow-y: auto; + -webkit-overflow-scrolling: touch; } + +.dialog-container { + background: rgba(0, 0, 0, 0.57); + z-index: 100; + position: fixed; + left: 0; + top: 0; + width: 100%; + height: 100%; + will-change: opacity; + -webkit-transition: opacity 0.333s cubic-bezier(0, 0, 0.21, 1); + transition: opacity 0.333s cubic-bezier(0, 0, 0.21, 1); } + +.dialog-container--visible { + opacity: 1; + pointer-events: auto; } + +.dialog { + background: #FFF; + border-radius: 2px; + box-shadow: 0 0 14px rgba(0, 0, 0, 0.24), 0 14px 28px rgba(0, 0, 0, 0.48); + min-width: 280px; + position: absolute; + left: 50%; + top: 50%; + -webkit-transform: translate(-50%, -50%) translateY(30px); + transform: translate(-50%, -50%) translateY(30px); + -webkit-transition: -webkit-transform 0.333s cubic-bezier(0, 0, 0.21, 1) 0.05s; + transition: -webkit-transform 0.333s cubic-bezier(0, 0, 0.21, 1) 0.05s; + transition: transform 0.333s cubic-bezier(0, 0, 0.21, 1) 0.05s; + transition: transform 0.333s cubic-bezier(0, 0, 0.21, 1) 0.05s, -webkit-transform 0.333s cubic-bezier(0, 0, 0.21, 1) 0.05s; } + +.dialog > div { + padding-left: 24px; + padding-right: 24px; } + +.dialog-title { + padding-top: 20px; + font-size: 1.25em; } + +.dialog-body { + padding-top: 20px; + padding-bottom: 24px; } + .dialog-body select { + width: 100%; + font-size: 2em; } + +.dialog-buttons { + padding: 8px !important; + float: right; } + +.card { + padding: 16px; + position: relative; + box-sizing: border-box; + background: #fff; + border-radius: 2px; + margin: 16px; + box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.14), 0 3px 1px -2px rgba(0, 0, 0, 0.2), 0 1px 5px 0 rgba(0, 0, 0, 0.12); } + +.weather-forecast .location { + font-size: 1.75em; } + +.weather-forecast .date, .weather-forecast .description { + font-size: 1.25em; } + +.weather-forecast .current { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; } + .weather-forecast .current .icon { + width: 128px; + height: 128px; } + .weather-forecast .current .visual { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + font-size: 4em; } + .weather-forecast .current .visual .scale { + font-size: 0.5em; + vertical-align: super; } + .weather-forecast .current .visual, .weather-forecast .current .description { + -webkit-box-flex: 1; + -webkit-flex-grow: 1; + -ms-flex-positive: 1; + flex-grow: 1; } + .weather-forecast .current .sunset:before { + content: "Sunset: "; + color: #888; } + .weather-forecast .current .wind:before { + content: "Wind: "; + color: #888; } + .weather-forecast .current .sunrise:before { + content: "Sunrise: "; + color: #888; } + .weather-forecast .current .humidity:before { + content: "Humidity: "; + color: #888; } + .weather-forecast .current .pollen:before { + content: "Pollen Count: "; + color: #888; } + .weather-forecast .current .pcount:before { + content: "Pollen "; + color: #888; } + +.weather-forecast .future { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; } + .weather-forecast .future .oneday { + -webkit-box-flex: 1; + -webkit-flex-grow: 1; + -ms-flex-positive: 1; + flex-grow: 1; + text-align: center; } + .weather-forecast .future .oneday .icon { + width: 64px; + height: 64px; + margin-left: auto; + margin-right: auto; } + .weather-forecast .future .oneday .temp-high, .weather-forecast .future .oneday .temp-low { + display: inline-block; } + .weather-forecast .future .oneday .temp-low { + color: #888; } + +.weather-forecast .icon { + background-repeat: no-repeat; + background-size: contain; } + .weather-forecast .icon.clear-day { + background-image: url("/images/clear.png"); } + .weather-forecast .icon.clear-night { + background-image: url("/images/clear.png"); } + .weather-forecast .icon.rain { + background-image: url("/images/rain.png"); } + .weather-forecast .icon.snow { + background-image: url("/images/snow.png"); } + .weather-forecast .icon.sleet { + background-image: url("/images/sleet.png"); } + .weather-forecast .icon.windy { + background-image: url("/images/wind.png"); } + .weather-forecast .icon.fog { + background-image: url("/images/fog.png"); } + .weather-forecast .icon.cloudy { + background-image: url("/images/cloudy.png"); } + .weather-forecast .icon.partly-cloudy-day { + background-image: url("/images/partly-cloudy.png"); } + .weather-forecast .icon.partly-cloudy-night { + background-image: url("/images/partly-cloudy.png"); } + .weather-forecast .icon.thunderstorms { + background-image: url("/images/thunderstorm.png"); } + +@media (max-width: 450px) { + .weather-forecast .date, .weather-forecast .description { + font-size: 0.9em; } + .weather-forecast .current .icon { + width: 96px; + height: 96px; } + .weather-forecast .current .visual { + font-size: 3em; } + .weather-forecast .future .oneday .icon { + width: 32px; + height: 32px; } } + +.mdl-button { + background: transparent; + border: none; + border-radius: 2px; + color: black; + position: relative; + height: 36px; + margin: 0; + min-width: 64px; + padding: 0 16px; + display: inline-block; + font-family: "Roboto", "Helvetica", "Arial", sans-serif; + font-size: 14px; + font-weight: 500; + text-transform: uppercase; + line-height: 1; + letter-spacing: 0; + overflow: hidden; + will-change: box-shadow; + -webkit-transition: box-shadow 0.2s cubic-bezier(0.4, 0, 1, 1), background-color 0.2s cubic-bezier(0.4, 0, 0.2, 1), color 0.2s cubic-bezier(0.4, 0, 0.2, 1); + transition: box-shadow 0.2s cubic-bezier(0.4, 0, 1, 1), background-color 0.2s cubic-bezier(0.4, 0, 0.2, 1), color 0.2s cubic-bezier(0.4, 0, 0.2, 1); + outline: none; + cursor: pointer; + text-decoration: none; + text-align: center; + line-height: 36px; + vertical-align: middle; } + .mdl-button::-moz-focus-inner { + border: 0; } + .mdl-button:hover { + background-color: rgba(158, 158, 158, 0.2); } + .mdl-button:focus:not(:active) { + background-color: rgba(0, 0, 0, 0.12); } + .mdl-button:active { + background-color: rgba(158, 158, 158, 0.4); } + .mdl-button.mdl-button--colored { + color: #3f51b5; } + .mdl-button.mdl-button--colored:focus:not(:active) { + background-color: rgba(0, 0, 0, 0.12); } + +.mdl-button--primary.mdl-button--primary { + color: #3f51b5; } + .mdl-button--primary.mdl-button--primary .mdl-ripple { + background: white; } + .mdl-button--primary.mdl-button--primary.mdl-button--raised, .mdl-button--primary.mdl-button--primary.mdl-button--fab { + color: white; + background-color: #3f51b5; } \ No newline at end of file diff --git a/example/pwa/sw.js b/example/pwa/sw.js new file mode 100644 index 00000000..ba98da05 --- /dev/null +++ b/example/pwa/sw.js @@ -0,0 +1,87 @@ +var cacheName = 'weatherPWA-assets-4'; +var dataCacheName = 'weatherPWA-data-4'; +var filesToCache = [ + '/', + '/favicon', + '/images/icons/icon-32x32.png', + '/images/icons/icon-128x128.png', + '/images/icons/icon-144x144.png', + '/images/icons/icon-152x152.png', + '/images/icons/icon-192x192.png', + '/images/icons/icon-256x256.png', + '/images/clear.png', + '/images/cloudy-scattered-showers.png', + '/images/cloudy.png', + '/images/fog.png', + '/images/ic_add_white_24px.svg', + '/images/ic_refresh_white_24px.svg', + '/images/partly-cloudy.png', + '/images/rain.png', + '/images/scattered-showers.png', + '/images/sleet.png', + '/images/snow.png', + '/images/thunderstorm.png', + '/images/wind.png', +]; + +self.addEventListener('install', function(e) { + console.log('[ServiceWorker] Install'); + + e.waitUntil( + caches.open(cacheName).then(function(cache) { + console.log('[ServiceWorker] Caching app shell'); + return cache.addAll(filesToCache); + }), + ); +}); + +self.addEventListener('activate', function(e) { + e.waitUntil( + caches.keys().then(function(keyList) { + return Promise.all( + keyList.map(function(key) { + if (key !== cacheName) { + console.log('[ServiceWorker] Removing old cache', key); + return caches.delete(key); + } + }), + ); + }), + ); + + return self.clients.claim(); +}); + +self.addEventListener('fetch', function(e) { + e.respondWith( + caches.match(e.request).then(function(response) { + return response || cacheStrategy(e); + }), + ); +}); + +// Caches all Maleo's bundled assets required for the page to run +function cacheStrategy(e) { + const asset = e.request.url.match(/\/_assets\/(.+)/); + if (asset) { + return caches.open(cacheName).then(function(cache) { + return fetch(e.request).then(function(response) { + cache.put(e.request.url, response.clone()); + return response; + }); + }); + } + + var url = '/api/forecast'; + if (e.request.url.indexOf(url) > -1) { + // Cache then network + return caches.open(dataCacheName).then(function(cache) { + return fetch(e.request).then(function(response) { + cache.put(e.request.url, response.clone()); + return response; + }); + }); + } + + return fetch(e.request); +}