98 |
!this.shouldDisableOverlayClick() && this.toggleMenu()}
101 | style={this.getStyles('overlay')}
102 | />
103 |
108 |
109 |
110 | {React.Children.map(this.props.children, (item, index) => {
111 | if (item) {
112 | return React.cloneElement(item, {key: index});
113 | }
114 | })}
115 |
116 |
117 |
this.toggleMenu()}
119 | className={this.props.closeButtonClassName}
120 | closeClassName={this.props.closeClassName}
121 | />
122 |
123 |
this.toggleMenu()}
125 | className={this.props.menuButtonClassName}
126 | barClassName={this.props.menuBarClassName}
127 | />
128 |
129 | );
130 | }
131 | }
132 |
133 | Menu.propTypes = {
134 | bodyClassName: PropTypes.string,
135 | menuBarClassName: PropTypes.string,
136 | menuButtonClassName: PropTypes.string,
137 | closeButtonClassName: PropTypes.string,
138 | closeClassName: PropTypes.string,
139 | disableOverlayClick: PropTypes.oneOfType([PropTypes.bool, PropTypes.func]),
140 | id: PropTypes.string,
141 | isOpen: PropTypes.bool,
142 | itemListClassName: PropTypes.string,
143 | menuClassName: PropTypes.string,
144 | noOverlay: PropTypes.bool,
145 | onStateChange: PropTypes.func,
146 | right: PropTypes.bool,
147 | styles: PropTypes.object,
148 | width: PropTypes.oneOfType([PropTypes.number, PropTypes.string])
149 | };
150 |
151 | Menu.defaultProps = {
152 | bodyClassName: '',
153 | menuBarClassName: '',
154 | menuButtonClassName: '',
155 | className: '',
156 | closeButtonClassName: '',
157 | closeClassName: '',
158 | id: '',
159 | itemListClassName: '',
160 | menuClassName: '',
161 | noOverlay: false,
162 | onStateChange: () => {},
163 | overlayClassName: '',
164 | styles: {},
165 | width: 300
166 | };
167 |
--------------------------------------------------------------------------------
/src/components/menu/menuIcon.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 | import PropTypes from 'prop-types';
3 |
4 | export default class MenuIcon extends Component {
5 | constructor (props) {
6 | super(props);
7 | this.state = {
8 | hover: false
9 | };
10 | }
11 |
12 | getLineStyle(index) {
13 | return {
14 | position: 'absolute',
15 | height: '20%',
16 | left: 0,
17 | right: 0,
18 | top: 20 * (index * 2) + '%',
19 | opacity: this.state.hover ? 0.6 : 1
20 | };
21 | }
22 |
23 | render() {
24 | let icon;
25 | let buttonStyle = {
26 | backgroundColor: 'transparent',
27 | margin: 0,
28 | padding: 0,
29 | border: 'none',
30 | fontSize: 8,
31 | cursor: 'pointer'
32 | };
33 |
34 | if (this.props.customIcon) {
35 | let extraProps = {
36 | className: 'm-icon',
37 | style: {...{width: '100%', height: '100%'}, ...this.props.styles.mIcon}
38 | };
39 | icon = React.cloneElement(this.props.customIcon, extraProps);
40 | } else {
41 | icon = (
42 |
43 | {[0, 1, 2].map((bar) => (
44 |
49 | ))}
50 |
51 | );
52 | }
53 |
54 | return (
55 |
this.setState({hover: true})}
58 | onMouseOut={() => this.setState({hover: false})}
59 | className={`m-menu-button ${this.props.className}`}
60 | style={buttonStyle}
61 | >
62 | {icon}
63 |
64 | );
65 | }
66 | }
67 |
68 | MenuIcon.propTypes = {
69 | barClassName: PropTypes.string,
70 | styles: PropTypes.object
71 | };
72 |
73 | MenuIcon.defaultProps = {
74 | barClassName: '',
75 | className: '',
76 | styles: {}
77 | };
78 |
--------------------------------------------------------------------------------
/src/components/reset.css:
--------------------------------------------------------------------------------
1 | article,aside,details,figcaption,figure,footer,header,hgroup,main,nav,section,summary{display:block;}audio,canvas,video{display:inline-block;}audio:not([controls]){display:none;height:0;}[hidden]{display:none;}html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%;}body{margin:0;}a:focus{outline:thin dotted;}a:active,a:hover{outline:0;}h1{font-size:2em;margin:0.67em 0;}abbr[title]{border-bottom:1px dotted;}b,strong{font-weight:bold;}dfn{font-style:italic;}hr{-moz-box-sizing:content-box;box-sizing:content-box;height:0;}mark{background:#ff0;color:#000;}code,kbd,pre,samp{font-family:monospace,serif;font-size:1em;}pre{white-space:pre-wrap;}q{quotes:"\201C" "\201D" "\2018" "\2019";}small{font-size:80%;}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline;}sup{top:-0.5em;}sub{bottom:-0.25em;}img{border:0;}svg:not(:root){overflow:hidden;}figure{margin:0;}fieldset{border:1px solid #c0c0c0;margin:0 2px;padding:0.35em 0.625em 0.75em;}legend{border:0;padding:0;}button,input,select,textarea{font-family:inherit;font-size:100%;margin:0;}button,input{line-height:normal;}button,select{text-transform:none;}button,html input[type="button"],input[type="reset"],input[type="submit"]{-webkit-appearance:button;cursor:pointer;}button[disabled],html input[disabled]{cursor:default;}input[type="checkbox"],input[type="radio"]{box-sizing:border-box;padding:0;}input[type="search"]{-webkit-appearance:textfield;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box;}input[type="search"]::-webkit-search-cancel-button,input[type="search"]::-webkit-search-decoration{-webkit-appearance:none;}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0;}textarea{overflow:auto;vertical-align:top;}table{border-collapse:collapse;border-spacing:0;}
--------------------------------------------------------------------------------
/src/components/seo.js:
--------------------------------------------------------------------------------
1 | /**
2 | * SEO component that queries for data with
3 | * Gatsby's useStaticQuery React hook
4 | *
5 | * See: https://www.gatsbyjs.org/docs/use-static-query/
6 | */
7 |
8 | import React from "react"
9 | import PropTypes from "prop-types"
10 | import Helmet from "react-helmet"
11 | import { useStaticQuery, graphql } from "gatsby"
12 |
13 | function SEO({ description, lang, meta, keywords, title }) {
14 | const { site } = useStaticQuery(
15 | graphql`
16 | query {
17 | site {
18 | siteMetadata {
19 | title
20 | description
21 | author
22 | }
23 | }
24 | }
25 | `
26 | )
27 |
28 | const metaDescription = description || site.siteMetadata.description
29 |
30 | return (
31 |
0
73 | ? {
74 | name: `keywords`,
75 | content: keywords.join(`, `),
76 | }
77 | : []
78 | )
79 | .concat(meta)}
80 | />
81 | )
82 | }
83 |
84 | SEO.defaultProps = {
85 | lang: `en`,
86 | meta: [],
87 | keywords: [],
88 | description: ``,
89 | }
90 |
91 | SEO.propTypes = {
92 | description: PropTypes.string,
93 | lang: PropTypes.string,
94 | meta: PropTypes.arrayOf(PropTypes.object),
95 | keywords: PropTypes.arrayOf(PropTypes.string),
96 | title: PropTypes.string.isRequired,
97 | }
98 |
99 | export default SEO
100 |
--------------------------------------------------------------------------------
/src/components/signup-form.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | const SignupForm = (
4 |
5 |
Newsletter Sign Up
6 |
7 | Name
8 |
9 |
10 |
11 | Email
12 |
13 |
14 |
15 | Share with our partners?
16 |
17 |
18 | Submit
19 |
20 | )
21 | export default SignupForm
22 |
--------------------------------------------------------------------------------
/src/components/trip-planner/trip-planner.css:
--------------------------------------------------------------------------------
1 | #tripPlanner {
2 | background-color: #f2f2f2;
3 | box-shadow: 1px 1px 2px rgba(0,0,0,0.3);
4 | border: 1px solid black;
5 | color: #999;
6 | margin: 0 auto 1em;
7 | max-width: 800px;
8 | }
9 | #tripPlanner form > div {
10 | align-items: center;
11 | display: flex;
12 | padding: 1em;
13 | }
14 | #tripPlanner button {
15 | background-color: #f5f5f5;
16 | -webkit-appearance: none;
17 | height: 32px;
18 | width: 32px;
19 | }
20 | #tripPlanner .button-wrap.left {
21 | margin-right: 1em;
22 | }
23 | #tripPlanner .button-wrap.right {
24 | margin-left: 1em;
25 | margin-bottom: 1em;
26 | }
27 | #tripPlanner div.label.fit {
28 | flex-grow: 2;
29 | margin: 0;
30 | padding: 1em;
31 | width: 40%;
32 | }
33 | #tripPlanner div.label.fit input,
34 | #tripPlanner .button-wrap button {
35 | border: 1px solid #666;
36 | }
37 | #tripPlanner button.expand {
38 | background-color: #878c96;
39 | box-shadow: 1px 1px 2px rgba(0,0,0,0.3);
40 | border: none;
41 | color: #fff;
42 | }
43 | #tripPlanner div.label input {
44 | border: 0;
45 | height: 32px;
46 | padding: 0.25em;
47 | width: 100%;
48 | }
49 | #tripPlanner .inputGroup {
50 | border: 1px solid #666;
51 | display: flex;
52 | margin-bottom: 1em;
53 | margin-left: 4em;
54 | padding: 0;
55 | width: 39%;
56 | }
57 | #tripPlanner .select {
58 | border: 1px solid #666;
59 | background-color: white;
60 | height: 32px;
61 | margin-bottom: 1em;
62 | margin-left: 1em;
63 | width: 32%;
64 | }
65 | #tripPlanner .select select {
66 | border: none;
67 | height: 100%;
68 | width: 100%;
69 | }
70 | #tripPlanner .inputGroup div.label {
71 | flex-grow: 2;
72 | }
73 | #tripPlanner .inputGroup input {
74 | border: 0;
75 | height: 100%;
76 | text-align: center;
77 | }
78 | #tripPlanner .inputGroup button {
79 | border: 0;
80 | padding: 0.25em 0.5em;
81 | }
82 | #tripPlanner .button-wrap .submit {
83 | background-color: #b30000;
84 | box-shadow: 1px 1px 2px rgba(0,0,0,0.3);
85 | border: none;
86 | color: white;
87 | margin-left: 1.5em;
88 | width: 50px;
89 | }
--------------------------------------------------------------------------------
/src/components/trip-planner/trip-planner.js:
--------------------------------------------------------------------------------
1 | import React, { useState } from 'react'
2 |
3 | import './trip-planner.css'
4 | import { TripPlans } from './trip-plans'
5 |
6 | function TripPlanner() {
7 | const [state, setState] = useState({})
8 |
9 | const submitFn = ((event) => {
10 | event.preventDefault()
11 | let target = event.target
12 | setState({data: {
13 | tripName: target.tripName.value,
14 | areaName: target.areaName.value,
15 | date: target.date.value,
16 | type: target.type.value
17 | }})
18 | })
19 | return (
20 | <>
21 | Fill out the trip planner form to get started.
22 |
79 |
80 | >
81 | )
82 | }
83 | export default TripPlanner;
84 |
--------------------------------------------------------------------------------
/src/components/trip-planner/trip-plans.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 |
3 | export const TripPlans = ((props) => {
4 | let data = props.data
5 | return (
6 | <>
7 | {data !== undefined ?
8 |
9 | Event name: {data.tripName}
10 | Location: {data.areaName}
11 | Date: {data.date}
12 | Type: {data.type}
13 |
14 |
: null}
15 | >
16 | )
17 | })
18 |
--------------------------------------------------------------------------------
/src/data/friend-data.js:
--------------------------------------------------------------------------------
1 | export default [{
2 | name: 'Rainier McCheddarton',
3 | headshot: require('../images/rainier-headshot.jpg'),
4 | subtitle: 'Labradoodle, squeaker, cheese fan',
5 | bio: 'Doggo ipsum very hand that feed shibe heckin good boys and girls fat boi much ruin diet you are doing me the shock wrinkler length boy, I am bekom fat lotsa pats dat tungg tho shooberino.',
6 | twitterLink: 'http://twitter.com'
7 | },
8 | {
9 | name: 'Bagley Fluffpants',
10 | headshot: require('../images/bagley.jpg'),
11 | subtitle: 'Cheshire cat, supreme loaf',
12 | bio: "The door is opening! how exciting oh, it's you, meh drink water out of the faucet. Spend six hours per day washing, but still have a crusty butthole, so lies down or sit on human they not getting up ever, but lick human with sandpaper tongue.",
13 | twitterLink: 'http://twitter.com'
14 | },
15 | {
16 | name: 'Butterscotch',
17 | headshot: require('../images/mini-horse.jpg'),
18 | subtitle: 'My future mini horse',
19 | bio: "Kickin' cow his him boobtube damn moonshine skedaddled. Gal ain't havin' dirty tractor crazy tin. Hogjowls hold cain't hardware horse gospel tractor kinfolk, down.",
20 | twitterLink: 'http://twitter.com'
21 | }]
22 |
--------------------------------------------------------------------------------
/src/data/image-gallery.js:
--------------------------------------------------------------------------------
1 | export default ImageData = [{
2 | name: '',
3 | alt: ''
4 | },{
5 | name: '',
6 | alt: ''
7 | },{
8 | name: '',
9 | alt: ''
10 | },{
11 | name: '',
12 | alt: ''
13 | },{
14 | name: '',
15 | alt: ''
16 | },{
17 | name: '',
18 | alt: ''
19 | },{
20 | name: '',
21 | alt: ''
22 | },{
23 | name: '',
24 | alt: ''
25 | },{
26 | name: '',
27 | alt: ''
28 | }]
29 |
--------------------------------------------------------------------------------
/src/fonts/font-awesome-4.2.0/css/font-awesome.min.css:
--------------------------------------------------------------------------------
1 | /*!
2 | * Font Awesome 4.2.0 by @davegandy - http://fontawesome.io - @fontawesome
3 | * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License)
4 | */@font-face{font-family:'FontAwesome';src:url('../fonts/fontawesome-webfont.eot?v=4.2.0');src:url('../fonts/fontawesome-webfont.eot?#iefix&v=4.2.0') format('embedded-opentype'),url('../fonts/fontawesome-webfont.woff?v=4.2.0') format('woff'),url('../fonts/fontawesome-webfont.ttf?v=4.2.0') format('truetype'),url('../fonts/fontawesome-webfont.svg?v=4.2.0#fontawesomeregular') format('svg');font-weight:normal;font-style:normal}.fa{display:inline-block;font:normal normal normal 14px/1 FontAwesome;font-size:inherit;text-rendering:auto;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.fa-lg{font-size:1.33333333em;line-height:.75em;vertical-align:-15%}.fa-2x{font-size:2em}.fa-3x{font-size:3em}.fa-4x{font-size:4em}.fa-5x{font-size:5em}.fa-fw{width:1.28571429em;text-align:center}.fa-ul{padding-left:0;margin-left:2.14285714em;list-style-type:none}.fa-ul>li{position:relative}.fa-li{position:absolute;left:-2.14285714em;width:2.14285714em;top:.14285714em;text-align:center}.fa-li.fa-lg{left:-1.85714286em}.fa-border{padding:.2em .25em .15em;border:solid .08em #eee;border-radius:.1em}.pull-right{float:right}.pull-left{float:left}.fa.pull-left{margin-right:.3em}.fa.pull-right{margin-left:.3em}.fa-spin{-webkit-animation:fa-spin 2s infinite linear;animation:fa-spin 2s infinite linear}@-webkit-keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}@keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}.fa-rotate-90{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=1);-webkit-transform:rotate(90deg);-ms-transform:rotate(90deg);transform:rotate(90deg)}.fa-rotate-180{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=2);-webkit-transform:rotate(180deg);-ms-transform:rotate(180deg);transform:rotate(180deg)}.fa-rotate-270{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=3);-webkit-transform:rotate(270deg);-ms-transform:rotate(270deg);transform:rotate(270deg)}.fa-flip-horizontal{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1);-webkit-transform:scale(-1, 1);-ms-transform:scale(-1, 1);transform:scale(-1, 1)}.fa-flip-vertical{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1);-webkit-transform:scale(1, -1);-ms-transform:scale(1, -1);transform:scale(1, -1)}:root .fa-rotate-90,:root .fa-rotate-180,:root .fa-rotate-270,:root .fa-flip-horizontal,:root .fa-flip-vertical{filter:none}.fa-stack{position:relative;display:inline-block;width:2em;height:2em;line-height:2em;vertical-align:middle}.fa-stack-1x,.fa-stack-2x{position:absolute;left:0;width:100%;text-align:center}.fa-stack-1x{line-height:inherit}.fa-stack-2x{font-size:2em}.fa-inverse{color:#fff}.fa-glass:before{content:"\f000"}.fa-music:before{content:"\f001"}.fa-search:before{content:"\f002"}.fa-envelope-o:before{content:"\f003"}.fa-heart:before{content:"\f004"}.fa-star:before{content:"\f005"}.fa-star-o:before{content:"\f006"}.fa-user:before{content:"\f007"}.fa-film:before{content:"\f008"}.fa-th-large:before{content:"\f009"}.fa-th:before{content:"\f00a"}.fa-th-list:before{content:"\f00b"}.fa-check:before{content:"\f00c"}.fa-remove:before,.fa-close:before,.fa-times:before{content:"\f00d"}.fa-search-plus:before{content:"\f00e"}.fa-search-minus:before{content:"\f010"}.fa-power-off:before{content:"\f011"}.fa-signal:before{content:"\f012"}.fa-gear:before,.fa-cog:before{content:"\f013"}.fa-trash-o:before{content:"\f014"}.fa-home:before{content:"\f015"}.fa-file-o:before{content:"\f016"}.fa-clock-o:before{content:"\f017"}.fa-road:before{content:"\f018"}.fa-download:before{content:"\f019"}.fa-arrow-circle-o-down:before{content:"\f01a"}.fa-arrow-circle-o-up:before{content:"\f01b"}.fa-inbox:before{content:"\f01c"}.fa-play-circle-o:before{content:"\f01d"}.fa-rotate-right:before,.fa-repeat:before{content:"\f01e"}.fa-refresh:before{content:"\f021"}.fa-list-alt:before{content:"\f022"}.fa-lock:before{content:"\f023"}.fa-flag:before{content:"\f024"}.fa-headphones:before{content:"\f025"}.fa-volume-off:before{content:"\f026"}.fa-volume-down:before{content:"\f027"}.fa-volume-up:before{content:"\f028"}.fa-qrcode:before{content:"\f029"}.fa-barcode:before{content:"\f02a"}.fa-tag:before{content:"\f02b"}.fa-tags:before{content:"\f02c"}.fa-book:before{content:"\f02d"}.fa-bookmark:before{content:"\f02e"}.fa-print:before{content:"\f02f"}.fa-camera:before{content:"\f030"}.fa-font:before{content:"\f031"}.fa-bold:before{content:"\f032"}.fa-italic:before{content:"\f033"}.fa-text-height:before{content:"\f034"}.fa-text-width:before{content:"\f035"}.fa-align-left:before{content:"\f036"}.fa-align-center:before{content:"\f037"}.fa-align-right:before{content:"\f038"}.fa-align-justify:before{content:"\f039"}.fa-list:before{content:"\f03a"}.fa-dedent:before,.fa-outdent:before{content:"\f03b"}.fa-indent:before{content:"\f03c"}.fa-video-camera:before{content:"\f03d"}.fa-photo:before,.fa-image:before,.fa-picture-o:before{content:"\f03e"}.fa-pencil:before{content:"\f040"}.fa-map-marker:before{content:"\f041"}.fa-adjust:before{content:"\f042"}.fa-tint:before{content:"\f043"}.fa-edit:before,.fa-pencil-square-o:before{content:"\f044"}.fa-share-square-o:before{content:"\f045"}.fa-check-square-o:before{content:"\f046"}.fa-arrows:before{content:"\f047"}.fa-step-backward:before{content:"\f048"}.fa-fast-backward:before{content:"\f049"}.fa-backward:before{content:"\f04a"}.fa-play:before{content:"\f04b"}.fa-pause:before{content:"\f04c"}.fa-stop:before{content:"\f04d"}.fa-forward:before{content:"\f04e"}.fa-fast-forward:before{content:"\f050"}.fa-step-forward:before{content:"\f051"}.fa-eject:before{content:"\f052"}.fa-chevron-left:before{content:"\f053"}.fa-chevron-right:before{content:"\f054"}.fa-plus-circle:before{content:"\f055"}.fa-minus-circle:before{content:"\f056"}.fa-times-circle:before{content:"\f057"}.fa-check-circle:before{content:"\f058"}.fa-question-circle:before{content:"\f059"}.fa-info-circle:before{content:"\f05a"}.fa-crosshairs:before{content:"\f05b"}.fa-times-circle-o:before{content:"\f05c"}.fa-check-circle-o:before{content:"\f05d"}.fa-ban:before{content:"\f05e"}.fa-arrow-left:before{content:"\f060"}.fa-arrow-right:before{content:"\f061"}.fa-arrow-up:before{content:"\f062"}.fa-arrow-down:before{content:"\f063"}.fa-mail-forward:before,.fa-share:before{content:"\f064"}.fa-expand:before{content:"\f065"}.fa-compress:before{content:"\f066"}.fa-plus:before{content:"\f067"}.fa-minus:before{content:"\f068"}.fa-asterisk:before{content:"\f069"}.fa-exclamation-circle:before{content:"\f06a"}.fa-gift:before{content:"\f06b"}.fa-leaf:before{content:"\f06c"}.fa-fire:before{content:"\f06d"}.fa-eye:before{content:"\f06e"}.fa-eye-slash:before{content:"\f070"}.fa-warning:before,.fa-exclamation-triangle:before{content:"\f071"}.fa-plane:before{content:"\f072"}.fa-calendar:before{content:"\f073"}.fa-random:before{content:"\f074"}.fa-comment:before{content:"\f075"}.fa-magnet:before{content:"\f076"}.fa-chevron-up:before{content:"\f077"}.fa-chevron-down:before{content:"\f078"}.fa-retweet:before{content:"\f079"}.fa-shopping-cart:before{content:"\f07a"}.fa-folder:before{content:"\f07b"}.fa-folder-open:before{content:"\f07c"}.fa-arrows-v:before{content:"\f07d"}.fa-arrows-h:before{content:"\f07e"}.fa-bar-chart-o:before,.fa-bar-chart:before{content:"\f080"}.fa-twitter-square:before{content:"\f081"}.fa-facebook-square:before{content:"\f082"}.fa-camera-retro:before{content:"\f083"}.fa-key:before{content:"\f084"}.fa-gears:before,.fa-cogs:before{content:"\f085"}.fa-comments:before{content:"\f086"}.fa-thumbs-o-up:before{content:"\f087"}.fa-thumbs-o-down:before{content:"\f088"}.fa-star-half:before{content:"\f089"}.fa-heart-o:before{content:"\f08a"}.fa-sign-out:before{content:"\f08b"}.fa-linkedin-square:before{content:"\f08c"}.fa-thumb-tack:before{content:"\f08d"}.fa-external-link:before{content:"\f08e"}.fa-sign-in:before{content:"\f090"}.fa-trophy:before{content:"\f091"}.fa-github-square:before{content:"\f092"}.fa-upload:before{content:"\f093"}.fa-lemon-o:before{content:"\f094"}.fa-phone:before{content:"\f095"}.fa-square-o:before{content:"\f096"}.fa-bookmark-o:before{content:"\f097"}.fa-phone-square:before{content:"\f098"}.fa-twitter:before{content:"\f099"}.fa-facebook:before{content:"\f09a"}.fa-github:before{content:"\f09b"}.fa-unlock:before{content:"\f09c"}.fa-credit-card:before{content:"\f09d"}.fa-rss:before{content:"\f09e"}.fa-hdd-o:before{content:"\f0a0"}.fa-bullhorn:before{content:"\f0a1"}.fa-bell:before{content:"\f0f3"}.fa-certificate:before{content:"\f0a3"}.fa-hand-o-right:before{content:"\f0a4"}.fa-hand-o-left:before{content:"\f0a5"}.fa-hand-o-up:before{content:"\f0a6"}.fa-hand-o-down:before{content:"\f0a7"}.fa-arrow-circle-left:before{content:"\f0a8"}.fa-arrow-circle-right:before{content:"\f0a9"}.fa-arrow-circle-up:before{content:"\f0aa"}.fa-arrow-circle-down:before{content:"\f0ab"}.fa-globe:before{content:"\f0ac"}.fa-wrench:before{content:"\f0ad"}.fa-tasks:before{content:"\f0ae"}.fa-filter:before{content:"\f0b0"}.fa-briefcase:before{content:"\f0b1"}.fa-arrows-alt:before{content:"\f0b2"}.fa-group:before,.fa-users:before{content:"\f0c0"}.fa-chain:before,.fa-link:before{content:"\f0c1"}.fa-cloud:before{content:"\f0c2"}.fa-flask:before{content:"\f0c3"}.fa-cut:before,.fa-scissors:before{content:"\f0c4"}.fa-copy:before,.fa-files-o:before{content:"\f0c5"}.fa-paperclip:before{content:"\f0c6"}.fa-save:before,.fa-floppy-o:before{content:"\f0c7"}.fa-square:before{content:"\f0c8"}.fa-navicon:before,.fa-reorder:before,.fa-bars:before{content:"\f0c9"}.fa-list-ul:before{content:"\f0ca"}.fa-list-ol:before{content:"\f0cb"}.fa-strikethrough:before{content:"\f0cc"}.fa-underline:before{content:"\f0cd"}.fa-table:before{content:"\f0ce"}.fa-magic:before{content:"\f0d0"}.fa-truck:before{content:"\f0d1"}.fa-pinterest:before{content:"\f0d2"}.fa-pinterest-square:before{content:"\f0d3"}.fa-google-plus-square:before{content:"\f0d4"}.fa-google-plus:before{content:"\f0d5"}.fa-money:before{content:"\f0d6"}.fa-caret-down:before{content:"\f0d7"}.fa-caret-up:before{content:"\f0d8"}.fa-caret-left:before{content:"\f0d9"}.fa-caret-right:before{content:"\f0da"}.fa-columns:before{content:"\f0db"}.fa-unsorted:before,.fa-sort:before{content:"\f0dc"}.fa-sort-down:before,.fa-sort-desc:before{content:"\f0dd"}.fa-sort-up:before,.fa-sort-asc:before{content:"\f0de"}.fa-envelope:before{content:"\f0e0"}.fa-linkedin:before{content:"\f0e1"}.fa-rotate-left:before,.fa-undo:before{content:"\f0e2"}.fa-legal:before,.fa-gavel:before{content:"\f0e3"}.fa-dashboard:before,.fa-tachometer:before{content:"\f0e4"}.fa-comment-o:before{content:"\f0e5"}.fa-comments-o:before{content:"\f0e6"}.fa-flash:before,.fa-bolt:before{content:"\f0e7"}.fa-sitemap:before{content:"\f0e8"}.fa-umbrella:before{content:"\f0e9"}.fa-paste:before,.fa-clipboard:before{content:"\f0ea"}.fa-lightbulb-o:before{content:"\f0eb"}.fa-exchange:before{content:"\f0ec"}.fa-cloud-download:before{content:"\f0ed"}.fa-cloud-upload:before{content:"\f0ee"}.fa-user-md:before{content:"\f0f0"}.fa-stethoscope:before{content:"\f0f1"}.fa-suitcase:before{content:"\f0f2"}.fa-bell-o:before{content:"\f0a2"}.fa-coffee:before{content:"\f0f4"}.fa-cutlery:before{content:"\f0f5"}.fa-file-text-o:before{content:"\f0f6"}.fa-building-o:before{content:"\f0f7"}.fa-hospital-o:before{content:"\f0f8"}.fa-ambulance:before{content:"\f0f9"}.fa-medkit:before{content:"\f0fa"}.fa-fighter-jet:before{content:"\f0fb"}.fa-beer:before{content:"\f0fc"}.fa-h-square:before{content:"\f0fd"}.fa-plus-square:before{content:"\f0fe"}.fa-angle-double-left:before{content:"\f100"}.fa-angle-double-right:before{content:"\f101"}.fa-angle-double-up:before{content:"\f102"}.fa-angle-double-down:before{content:"\f103"}.fa-angle-left:before{content:"\f104"}.fa-angle-right:before{content:"\f105"}.fa-angle-up:before{content:"\f106"}.fa-angle-down:before{content:"\f107"}.fa-desktop:before{content:"\f108"}.fa-laptop:before{content:"\f109"}.fa-tablet:before{content:"\f10a"}.fa-mobile-phone:before,.fa-mobile:before{content:"\f10b"}.fa-circle-o:before{content:"\f10c"}.fa-quote-left:before{content:"\f10d"}.fa-quote-right:before{content:"\f10e"}.fa-spinner:before{content:"\f110"}.fa-circle:before{content:"\f111"}.fa-mail-reply:before,.fa-reply:before{content:"\f112"}.fa-github-alt:before{content:"\f113"}.fa-folder-o:before{content:"\f114"}.fa-folder-open-o:before{content:"\f115"}.fa-smile-o:before{content:"\f118"}.fa-frown-o:before{content:"\f119"}.fa-meh-o:before{content:"\f11a"}.fa-gamepad:before{content:"\f11b"}.fa-keyboard-o:before{content:"\f11c"}.fa-flag-o:before{content:"\f11d"}.fa-flag-checkered:before{content:"\f11e"}.fa-terminal:before{content:"\f120"}.fa-code:before{content:"\f121"}.fa-mail-reply-all:before,.fa-reply-all:before{content:"\f122"}.fa-star-half-empty:before,.fa-star-half-full:before,.fa-star-half-o:before{content:"\f123"}.fa-location-arrow:before{content:"\f124"}.fa-crop:before{content:"\f125"}.fa-code-fork:before{content:"\f126"}.fa-unlink:before,.fa-chain-broken:before{content:"\f127"}.fa-question:before{content:"\f128"}.fa-info:before{content:"\f129"}.fa-exclamation:before{content:"\f12a"}.fa-superscript:before{content:"\f12b"}.fa-subscript:before{content:"\f12c"}.fa-eraser:before{content:"\f12d"}.fa-puzzle-piece:before{content:"\f12e"}.fa-microphone:before{content:"\f130"}.fa-microphone-slash:before{content:"\f131"}.fa-shield:before{content:"\f132"}.fa-calendar-o:before{content:"\f133"}.fa-fire-extinguisher:before{content:"\f134"}.fa-rocket:before{content:"\f135"}.fa-maxcdn:before{content:"\f136"}.fa-chevron-circle-left:before{content:"\f137"}.fa-chevron-circle-right:before{content:"\f138"}.fa-chevron-circle-up:before{content:"\f139"}.fa-chevron-circle-down:before{content:"\f13a"}.fa-html5:before{content:"\f13b"}.fa-css3:before{content:"\f13c"}.fa-anchor:before{content:"\f13d"}.fa-unlock-alt:before{content:"\f13e"}.fa-bullseye:before{content:"\f140"}.fa-ellipsis-h:before{content:"\f141"}.fa-ellipsis-v:before{content:"\f142"}.fa-rss-square:before{content:"\f143"}.fa-play-circle:before{content:"\f144"}.fa-ticket:before{content:"\f145"}.fa-minus-square:before{content:"\f146"}.fa-minus-square-o:before{content:"\f147"}.fa-level-up:before{content:"\f148"}.fa-level-down:before{content:"\f149"}.fa-check-square:before{content:"\f14a"}.fa-pencil-square:before{content:"\f14b"}.fa-external-link-square:before{content:"\f14c"}.fa-share-square:before{content:"\f14d"}.fa-compass:before{content:"\f14e"}.fa-toggle-down:before,.fa-caret-square-o-down:before{content:"\f150"}.fa-toggle-up:before,.fa-caret-square-o-up:before{content:"\f151"}.fa-toggle-right:before,.fa-caret-square-o-right:before{content:"\f152"}.fa-euro:before,.fa-eur:before{content:"\f153"}.fa-gbp:before{content:"\f154"}.fa-dollar:before,.fa-usd:before{content:"\f155"}.fa-rupee:before,.fa-inr:before{content:"\f156"}.fa-cny:before,.fa-rmb:before,.fa-yen:before,.fa-jpy:before{content:"\f157"}.fa-ruble:before,.fa-rouble:before,.fa-rub:before{content:"\f158"}.fa-won:before,.fa-krw:before{content:"\f159"}.fa-bitcoin:before,.fa-btc:before{content:"\f15a"}.fa-file:before{content:"\f15b"}.fa-file-text:before{content:"\f15c"}.fa-sort-alpha-asc:before{content:"\f15d"}.fa-sort-alpha-desc:before{content:"\f15e"}.fa-sort-amount-asc:before{content:"\f160"}.fa-sort-amount-desc:before{content:"\f161"}.fa-sort-numeric-asc:before{content:"\f162"}.fa-sort-numeric-desc:before{content:"\f163"}.fa-thumbs-up:before{content:"\f164"}.fa-thumbs-down:before{content:"\f165"}.fa-youtube-square:before{content:"\f166"}.fa-youtube:before{content:"\f167"}.fa-xing:before{content:"\f168"}.fa-xing-square:before{content:"\f169"}.fa-youtube-play:before{content:"\f16a"}.fa-dropbox:before{content:"\f16b"}.fa-stack-overflow:before{content:"\f16c"}.fa-instagram:before{content:"\f16d"}.fa-flickr:before{content:"\f16e"}.fa-adn:before{content:"\f170"}.fa-bitbucket:before{content:"\f171"}.fa-bitbucket-square:before{content:"\f172"}.fa-tumblr:before{content:"\f173"}.fa-tumblr-square:before{content:"\f174"}.fa-long-arrow-down:before{content:"\f175"}.fa-long-arrow-up:before{content:"\f176"}.fa-long-arrow-left:before{content:"\f177"}.fa-long-arrow-right:before{content:"\f178"}.fa-apple:before{content:"\f179"}.fa-windows:before{content:"\f17a"}.fa-android:before{content:"\f17b"}.fa-linux:before{content:"\f17c"}.fa-dribbble:before{content:"\f17d"}.fa-skype:before{content:"\f17e"}.fa-foursquare:before{content:"\f180"}.fa-trello:before{content:"\f181"}.fa-female:before{content:"\f182"}.fa-male:before{content:"\f183"}.fa-gittip:before{content:"\f184"}.fa-sun-o:before{content:"\f185"}.fa-moon-o:before{content:"\f186"}.fa-archive:before{content:"\f187"}.fa-bug:before{content:"\f188"}.fa-vk:before{content:"\f189"}.fa-weibo:before{content:"\f18a"}.fa-renren:before{content:"\f18b"}.fa-pagelines:before{content:"\f18c"}.fa-stack-exchange:before{content:"\f18d"}.fa-arrow-circle-o-right:before{content:"\f18e"}.fa-arrow-circle-o-left:before{content:"\f190"}.fa-toggle-left:before,.fa-caret-square-o-left:before{content:"\f191"}.fa-dot-circle-o:before{content:"\f192"}.fa-wheelchair:before{content:"\f193"}.fa-vimeo-square:before{content:"\f194"}.fa-turkish-lira:before,.fa-try:before{content:"\f195"}.fa-plus-square-o:before{content:"\f196"}.fa-space-shuttle:before{content:"\f197"}.fa-slack:before{content:"\f198"}.fa-envelope-square:before{content:"\f199"}.fa-wordpress:before{content:"\f19a"}.fa-openid:before{content:"\f19b"}.fa-institution:before,.fa-bank:before,.fa-university:before{content:"\f19c"}.fa-mortar-board:before,.fa-graduation-cap:before{content:"\f19d"}.fa-yahoo:before{content:"\f19e"}.fa-google:before{content:"\f1a0"}.fa-reddit:before{content:"\f1a1"}.fa-reddit-square:before{content:"\f1a2"}.fa-stumbleupon-circle:before{content:"\f1a3"}.fa-stumbleupon:before{content:"\f1a4"}.fa-delicious:before{content:"\f1a5"}.fa-digg:before{content:"\f1a6"}.fa-pied-piper:before{content:"\f1a7"}.fa-pied-piper-alt:before{content:"\f1a8"}.fa-drupal:before{content:"\f1a9"}.fa-joomla:before{content:"\f1aa"}.fa-language:before{content:"\f1ab"}.fa-fax:before{content:"\f1ac"}.fa-building:before{content:"\f1ad"}.fa-child:before{content:"\f1ae"}.fa-paw:before{content:"\f1b0"}.fa-spoon:before{content:"\f1b1"}.fa-cube:before{content:"\f1b2"}.fa-cubes:before{content:"\f1b3"}.fa-behance:before{content:"\f1b4"}.fa-behance-square:before{content:"\f1b5"}.fa-steam:before{content:"\f1b6"}.fa-steam-square:before{content:"\f1b7"}.fa-recycle:before{content:"\f1b8"}.fa-automobile:before,.fa-car:before{content:"\f1b9"}.fa-cab:before,.fa-taxi:before{content:"\f1ba"}.fa-tree:before{content:"\f1bb"}.fa-spotify:before{content:"\f1bc"}.fa-deviantart:before{content:"\f1bd"}.fa-soundcloud:before{content:"\f1be"}.fa-database:before{content:"\f1c0"}.fa-file-pdf-o:before{content:"\f1c1"}.fa-file-word-o:before{content:"\f1c2"}.fa-file-excel-o:before{content:"\f1c3"}.fa-file-powerpoint-o:before{content:"\f1c4"}.fa-file-photo-o:before,.fa-file-picture-o:before,.fa-file-image-o:before{content:"\f1c5"}.fa-file-zip-o:before,.fa-file-archive-o:before{content:"\f1c6"}.fa-file-sound-o:before,.fa-file-audio-o:before{content:"\f1c7"}.fa-file-movie-o:before,.fa-file-video-o:before{content:"\f1c8"}.fa-file-code-o:before{content:"\f1c9"}.fa-vine:before{content:"\f1ca"}.fa-codepen:before{content:"\f1cb"}.fa-jsfiddle:before{content:"\f1cc"}.fa-life-bouy:before,.fa-life-buoy:before,.fa-life-saver:before,.fa-support:before,.fa-life-ring:before{content:"\f1cd"}.fa-circle-o-notch:before{content:"\f1ce"}.fa-ra:before,.fa-rebel:before{content:"\f1d0"}.fa-ge:before,.fa-empire:before{content:"\f1d1"}.fa-git-square:before{content:"\f1d2"}.fa-git:before{content:"\f1d3"}.fa-hacker-news:before{content:"\f1d4"}.fa-tencent-weibo:before{content:"\f1d5"}.fa-qq:before{content:"\f1d6"}.fa-wechat:before,.fa-weixin:before{content:"\f1d7"}.fa-send:before,.fa-paper-plane:before{content:"\f1d8"}.fa-send-o:before,.fa-paper-plane-o:before{content:"\f1d9"}.fa-history:before{content:"\f1da"}.fa-circle-thin:before{content:"\f1db"}.fa-header:before{content:"\f1dc"}.fa-paragraph:before{content:"\f1dd"}.fa-sliders:before{content:"\f1de"}.fa-share-alt:before{content:"\f1e0"}.fa-share-alt-square:before{content:"\f1e1"}.fa-bomb:before{content:"\f1e2"}.fa-soccer-ball-o:before,.fa-futbol-o:before{content:"\f1e3"}.fa-tty:before{content:"\f1e4"}.fa-binoculars:before{content:"\f1e5"}.fa-plug:before{content:"\f1e6"}.fa-slideshare:before{content:"\f1e7"}.fa-twitch:before{content:"\f1e8"}.fa-yelp:before{content:"\f1e9"}.fa-newspaper-o:before{content:"\f1ea"}.fa-wifi:before{content:"\f1eb"}.fa-calculator:before{content:"\f1ec"}.fa-paypal:before{content:"\f1ed"}.fa-google-wallet:before{content:"\f1ee"}.fa-cc-visa:before{content:"\f1f0"}.fa-cc-mastercard:before{content:"\f1f1"}.fa-cc-discover:before{content:"\f1f2"}.fa-cc-amex:before{content:"\f1f3"}.fa-cc-paypal:before{content:"\f1f4"}.fa-cc-stripe:before{content:"\f1f5"}.fa-bell-slash:before{content:"\f1f6"}.fa-bell-slash-o:before{content:"\f1f7"}.fa-trash:before{content:"\f1f8"}.fa-copyright:before{content:"\f1f9"}.fa-at:before{content:"\f1fa"}.fa-eyedropper:before{content:"\f1fb"}.fa-paint-brush:before{content:"\f1fc"}.fa-birthday-cake:before{content:"\f1fd"}.fa-area-chart:before{content:"\f1fe"}.fa-pie-chart:before{content:"\f200"}.fa-line-chart:before{content:"\f201"}.fa-lastfm:before{content:"\f202"}.fa-lastfm-square:before{content:"\f203"}.fa-toggle-off:before{content:"\f204"}.fa-toggle-on:before{content:"\f205"}.fa-bicycle:before{content:"\f206"}.fa-bus:before{content:"\f207"}.fa-ioxhost:before{content:"\f208"}.fa-angellist:before{content:"\f209"}.fa-cc:before{content:"\f20a"}.fa-shekel:before,.fa-sheqel:before,.fa-ils:before{content:"\f20b"}.fa-meanpath:before{content:"\f20c"}
--------------------------------------------------------------------------------
/src/fonts/font-awesome-4.2.0/fonts/fontawesome-webfont.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marcysutton/empathy-driven-development/b418b7b9028db42cb0db012f433a1a8e14face84/src/fonts/font-awesome-4.2.0/fonts/fontawesome-webfont.eot
--------------------------------------------------------------------------------
/src/fonts/font-awesome-4.2.0/fonts/fontawesome-webfont.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marcysutton/empathy-driven-development/b418b7b9028db42cb0db012f433a1a8e14face84/src/fonts/font-awesome-4.2.0/fonts/fontawesome-webfont.ttf
--------------------------------------------------------------------------------
/src/fonts/font-awesome-4.2.0/fonts/fontawesome-webfont.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marcysutton/empathy-driven-development/b418b7b9028db42cb0db012f433a1a8e14face84/src/fonts/font-awesome-4.2.0/fonts/fontawesome-webfont.woff
--------------------------------------------------------------------------------
/src/gallery/1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marcysutton/empathy-driven-development/b418b7b9028db42cb0db012f433a1a8e14face84/src/gallery/1.jpg
--------------------------------------------------------------------------------
/src/gallery/10.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marcysutton/empathy-driven-development/b418b7b9028db42cb0db012f433a1a8e14face84/src/gallery/10.jpg
--------------------------------------------------------------------------------
/src/gallery/2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marcysutton/empathy-driven-development/b418b7b9028db42cb0db012f433a1a8e14face84/src/gallery/2.jpg
--------------------------------------------------------------------------------
/src/gallery/3.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marcysutton/empathy-driven-development/b418b7b9028db42cb0db012f433a1a8e14face84/src/gallery/3.jpg
--------------------------------------------------------------------------------
/src/gallery/4.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marcysutton/empathy-driven-development/b418b7b9028db42cb0db012f433a1a8e14face84/src/gallery/4.jpg
--------------------------------------------------------------------------------
/src/gallery/5.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marcysutton/empathy-driven-development/b418b7b9028db42cb0db012f433a1a8e14face84/src/gallery/5.jpg
--------------------------------------------------------------------------------
/src/gallery/6.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marcysutton/empathy-driven-development/b418b7b9028db42cb0db012f433a1a8e14face84/src/gallery/6.jpg
--------------------------------------------------------------------------------
/src/gallery/7.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marcysutton/empathy-driven-development/b418b7b9028db42cb0db012f433a1a8e14face84/src/gallery/7.jpg
--------------------------------------------------------------------------------
/src/gallery/8.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marcysutton/empathy-driven-development/b418b7b9028db42cb0db012f433a1a8e14face84/src/gallery/8.jpg
--------------------------------------------------------------------------------
/src/gallery/9.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marcysutton/empathy-driven-development/b418b7b9028db42cb0db012f433a1a8e14face84/src/gallery/9.jpg
--------------------------------------------------------------------------------
/src/images/IMG_0663.JPG:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marcysutton/empathy-driven-development/b418b7b9028db42cb0db012f433a1a8e14face84/src/images/IMG_0663.JPG
--------------------------------------------------------------------------------
/src/images/bagley.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marcysutton/empathy-driven-development/b418b7b9028db42cb0db012f433a1a8e14face84/src/images/bagley.jpg
--------------------------------------------------------------------------------
/src/images/gatsby-astronaut.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marcysutton/empathy-driven-development/b418b7b9028db42cb0db012f433a1a8e14face84/src/images/gatsby-astronaut.png
--------------------------------------------------------------------------------
/src/images/gatsby-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marcysutton/empathy-driven-development/b418b7b9028db42cb0db012f433a1a8e14face84/src/images/gatsby-icon.png
--------------------------------------------------------------------------------
/src/images/kitten-mittens.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marcysutton/empathy-driven-development/b418b7b9028db42cb0db012f433a1a8e14face84/src/images/kitten-mittens.jpg
--------------------------------------------------------------------------------
/src/images/kuhtai.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marcysutton/empathy-driven-development/b418b7b9028db42cb0db012f433a1a8e14face84/src/images/kuhtai.jpg
--------------------------------------------------------------------------------
/src/images/lb.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marcysutton/empathy-driven-development/b418b7b9028db42cb0db012f433a1a8e14face84/src/images/lb.jpg
--------------------------------------------------------------------------------
/src/images/mini-horse.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marcysutton/empathy-driven-development/b418b7b9028db42cb0db012f433a1a8e14face84/src/images/mini-horse.jpg
--------------------------------------------------------------------------------
/src/images/mtbachelor.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marcysutton/empathy-driven-development/b418b7b9028db42cb0db012f433a1a8e14face84/src/images/mtbachelor.jpg
--------------------------------------------------------------------------------
/src/images/rainier-headshot.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marcysutton/empathy-driven-development/b418b7b9028db42cb0db012f433a1a8e14face84/src/images/rainier-headshot.jpg
--------------------------------------------------------------------------------
/src/images/rainier-large.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marcysutton/empathy-driven-development/b418b7b9028db42cb0db012f433a1a8e14face84/src/images/rainier-large.jpg
--------------------------------------------------------------------------------
/src/images/rainier-lowres.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marcysutton/empathy-driven-development/b418b7b9028db42cb0db012f433a1a8e14face84/src/images/rainier-lowres.jpg
--------------------------------------------------------------------------------
/src/images/white-blocks.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marcysutton/empathy-driven-development/b418b7b9028db42cb0db012f433a1a8e14face84/src/images/white-blocks.jpg
--------------------------------------------------------------------------------
/src/pages/404.js:
--------------------------------------------------------------------------------
1 | import React from "react"
2 |
3 | import Layout from "../components/layout"
4 | import SEO from "../components/seo"
5 |
6 | const NotFoundPage = () => (
7 |
8 |
9 | NOT FOUND
10 | You just hit a route that doesn't exist... the sadness.
11 |
12 | )
13 |
14 | export default NotFoundPage
15 |
--------------------------------------------------------------------------------
/src/pages/friends.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import CardFlip from '../components/card-flip/'
3 |
4 | import Layout from "../components/layout"
5 | import SEO from "../components/seo"
6 | import friends from "../data/friend-data"
7 |
8 | const FriendsPage = () => (
9 |
10 |
11 |
12 |
Which friends shall we bring?
13 |
21 |
28 |
35 |
36 |
37 | )
38 |
39 | export default FriendsPage
40 |
--------------------------------------------------------------------------------
/src/pages/gallery.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from "react"
2 | import { graphql } from "gatsby"
3 | import Layout from "../components/layout"
4 | import SEO from "../components/seo"
5 | import Carousel from "../components/carousel/carousel"
6 |
7 | const imageData = [
8 | 'Backpacking with Rainier the labradoodle',
9 | 'Camping with the dog at a wilderness lake',
10 | 'Carrying puppy Rainier on a mountain hike',
11 | 'Mt. Baker Wilderness at Chain Lakes',
12 | 'Skyline Lake reflection',
13 | 'Bagley the cat wants to go van camping',
14 | 'Sunny trail magic in the North Cascades',
15 | 'Snowy Iceberg the Adventure Van',
16 | 'Rainier in his snow suit in the Baker backcountry',
17 | 'My splitboard in the snow',
18 | ]
19 |
20 | class GalleryPage extends Component {
21 | render() {
22 | const data = this.props.data
23 |
24 | return (
25 |
26 |
27 | Inspiration
28 |
29 |
30 | )
31 | }
32 | }
33 |
34 | export const imageQuery = graphql`
35 | query {
36 | gallery: allFile(filter: { sourceInstanceName: { eq: "gallery" } }) {
37 | edges {
38 | node {
39 | name
40 | childImageSharp {
41 | fluid(maxWidth: 400, maxHeight: 400) {
42 | ...GatsbyImageSharpFluid
43 | }
44 | }
45 | }
46 | }
47 | }
48 | }
49 | `
50 |
51 | export default GalleryPage
52 |
--------------------------------------------------------------------------------
/src/pages/gearlist.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react'
2 | import Layout from "../components/layout"
3 |
4 | class GearList extends Component {
5 | render() {
6 | return (
7 |
8 | Gear Packing List
9 | It’s a bummer to forget a critical item when you’re headed to a cold snowy place.
10 | Here’s a handy checklist of things you might need.
11 |
12 |
13 |
All winter days
14 |
15 | Snow jacket
16 | Snow pants
17 | Base layers top & bottom
18 | Waterproof gloves
19 | Beanie
20 | Ski socks
21 | Ski boots
22 | Skis
23 | Poles
24 | Helmet
25 | Goggles
26 | Lunch
27 | Sunscreen
28 |
29 |
30 |
31 |
Backcountry days
32 |
33 | Avalanche beacon
34 | Probe
35 | Shovel
36 | Touring hat
37 | Glove liners
38 | Map
39 | Touring skis
40 | Touring boots
41 | Skins
42 | Backpack
43 | Water
44 | Sunglasses
45 |
46 |
47 |
48 |
49 | )
50 | }
51 | }
52 | export default GearList
53 |
--------------------------------------------------------------------------------
/src/pages/index.js:
--------------------------------------------------------------------------------
1 | import React from "react"
2 | import { useStaticQuery, graphql } from "gatsby"
3 | import Img from "gatsby-image"
4 |
5 | import TripPlanner from '../components/trip-planner/trip-planner';
6 | import Layout from "../components/layout"
7 | import SEO from "../components/seo"
8 |
9 | const IndexPage = (() => {
10 | const data = useStaticQuery(graphql`
11 | query {
12 | landingImage: file(relativePath: { eq: "kuhtai.jpg" }) {
13 | childImageSharp {
14 | fluid {
15 | ...GatsbyImageSharpFluid
16 | }
17 | }
18 | }
19 | }
20 | `)
21 | return (
22 |
23 |
24 |
25 |
30 |
31 |
32 |
33 | )
34 | })
35 |
36 | export default IndexPage
37 |
--------------------------------------------------------------------------------
/src/pages/login-form.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 |
3 | import LoginForm from '../components/login-form'
4 | import Layout from "../components/layout"
5 | import SEO from "../components/seo"
6 |
7 | let fields = [
8 | 'First name',
9 | 'Last name',
10 | 'Email'
11 | ]
12 | const LoginPage = () => (
13 |
14 |
15 |
19 |
20 | )
21 |
22 | export default LoginPage
23 |
--------------------------------------------------------------------------------
/src/registerServiceWorker.js:
--------------------------------------------------------------------------------
1 | // In production, we register a service worker to serve assets from local cache.
2 |
3 | // This lets the app load faster on subsequent visits in production, and gives
4 | // it offline capabilities. However, it also means that developers (and users)
5 | // will only see deployed updates on the "N+1" visit to a page, since previously
6 | // cached resources are updated in the background.
7 |
8 | // To learn more about the benefits of this model, read https://goo.gl/KwvDNy.
9 | // This link also includes instructions on opting out of this behavior.
10 |
11 | const isLocalhost = Boolean(
12 | window.location.hostname === 'localhost' ||
13 | // [::1] is the IPv6 localhost address.
14 | window.location.hostname === '[::1]' ||
15 | // 127.0.0.1/8 is considered localhost for IPv4.
16 | window.location.hostname.match(
17 | /^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/
18 | )
19 | );
20 |
21 | export default function register() {
22 | if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) {
23 | // The URL constructor is available in all browsers that support SW.
24 | const publicUrl = new URL(process.env.PUBLIC_URL, window.location);
25 | if (publicUrl.origin !== window.location.origin) {
26 | // Our service worker won't work if PUBLIC_URL is on a different origin
27 | // from what our page is served on. This might happen if a CDN is used to
28 | // serve assets; see https://github.com/facebookincubator/create-react-app/issues/2374
29 | return;
30 | }
31 |
32 | window.addEventListener('load', () => {
33 | const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`;
34 |
35 | if (isLocalhost) {
36 | // This is running on localhost. Lets check if a service worker still exists or not.
37 | checkValidServiceWorker(swUrl);
38 |
39 | // Add some additional logging to localhost, pointing developers to the
40 | // service worker/PWA documentation.
41 | navigator.serviceWorker.ready.then(() => {
42 | console.log(
43 | 'This web app is being served cache-first by a service ' +
44 | 'worker. To learn more, visit https://goo.gl/SC7cgQ'
45 | );
46 | });
47 | } else {
48 | // Is not local host. Just register service worker
49 | registerValidSW(swUrl);
50 | }
51 | });
52 | }
53 | }
54 |
55 | function registerValidSW(swUrl) {
56 | navigator.serviceWorker
57 | .register(swUrl)
58 | .then(registration => {
59 | registration.onupdatefound = () => {
60 | const installingWorker = registration.installing;
61 | installingWorker.onstatechange = () => {
62 | if (installingWorker.state === 'installed') {
63 | if (navigator.serviceWorker.controller) {
64 | // At this point, the old content will have been purged and
65 | // the fresh content will have been added to the cache.
66 | // It's the perfect time to display a "New content is
67 | // available; please refresh." message in your web app.
68 | console.log('New content is available; please refresh.');
69 | } else {
70 | // At this point, everything has been precached.
71 | // It's the perfect time to display a
72 | // "Content is cached for offline use." message.
73 | console.log('Content is cached for offline use.');
74 | }
75 | }
76 | };
77 | };
78 | })
79 | .catch(error => {
80 | console.error('Error during service worker registration:', error);
81 | });
82 | }
83 |
84 | function checkValidServiceWorker(swUrl) {
85 | // Check if the service worker can be found. If it can't reload the page.
86 | fetch(swUrl)
87 | .then(response => {
88 | // Ensure service worker exists, and that we really are getting a JS file.
89 | if (
90 | response.status === 404 ||
91 | response.headers.get('content-type').indexOf('javascript') === -1
92 | ) {
93 | // No service worker found. Probably a different app. Reload the page.
94 | navigator.serviceWorker.ready.then(registration => {
95 | registration.unregister().then(() => {
96 | window.location.reload();
97 | });
98 | });
99 | } else {
100 | // Service worker found. Proceed as normal.
101 | registerValidSW(swUrl);
102 | }
103 | })
104 | .catch(() => {
105 | console.log(
106 | 'No internet connection found. App is running in offline mode.'
107 | );
108 | });
109 | }
110 |
111 | export function unregister() {
112 | if ('serviceWorker' in navigator) {
113 | navigator.serviceWorker.ready.then(registration => {
114 | registration.unregister();
115 | });
116 | }
117 | }
118 |
--------------------------------------------------------------------------------
/static/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marcysutton/empathy-driven-development/b418b7b9028db42cb0db012f433a1a8e14face84/static/favicon.ico
--------------------------------------------------------------------------------
/static/favicon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marcysutton/empathy-driven-development/b418b7b9028db42cb0db012f433a1a8e14face84/static/favicon.png
--------------------------------------------------------------------------------
/static/scripts/inert.js:
--------------------------------------------------------------------------------
1 | (function (global, factory) {
2 | typeof exports === 'object' && typeof module !== 'undefined' ? factory() :
3 | typeof define === 'function' && define.amd ? define(factory) :
4 | (factory());
5 | }(this, (function () { 'use strict';
6 |
7 | /**
8 | * Determine if a DOM element matches a CSS selector
9 | *
10 | * @param {Element} elem
11 | * @param {String} selector
12 | * @return {Boolean}
13 | * @api public
14 | */
15 |
16 | function matches(elem, selector) {
17 | // Vendor-specific implementations of `Element.prototype.matches()`.
18 | var proto = window.Element.prototype;
19 | var nativeMatches = proto.matches ||
20 | proto.mozMatchesSelector ||
21 | proto.msMatchesSelector ||
22 | proto.oMatchesSelector ||
23 | proto.webkitMatchesSelector;
24 |
25 | if (!elem || elem.nodeType !== 1) {
26 | return false;
27 | }
28 |
29 | var parentElem = elem.parentNode;
30 |
31 | // use native 'matches'
32 | if (nativeMatches) {
33 | return nativeMatches.call(elem, selector);
34 | }
35 |
36 | // native support for `matches` is missing and a fallback is required
37 | var nodes = parentElem.querySelectorAll(selector);
38 | var len = nodes.length;
39 |
40 | for (var i = 0; i < len; i++) {
41 | if (nodes[i] === elem) {
42 | return true;
43 | }
44 | }
45 |
46 | return false;
47 | }
48 |
49 | /**
50 | * Expose `matches`
51 | */
52 |
53 | var index = matches;
54 |
55 | var classCallCheck = function (instance, Constructor) {
56 | if (!(instance instanceof Constructor)) {
57 | throw new TypeError("Cannot call a class as a function");
58 | }
59 | };
60 |
61 | var createClass = function () {
62 | function defineProperties(target, props) {
63 | for (var i = 0; i < props.length; i++) {
64 | var descriptor = props[i];
65 | descriptor.enumerable = descriptor.enumerable || false;
66 | descriptor.configurable = true;
67 | if ("value" in descriptor) descriptor.writable = true;
68 | Object.defineProperty(target, descriptor.key, descriptor);
69 | }
70 | }
71 |
72 | return function (Constructor, protoProps, staticProps) {
73 | if (protoProps) defineProperties(Constructor.prototype, protoProps);
74 | if (staticProps) defineProperties(Constructor, staticProps);
75 | return Constructor;
76 | };
77 | }();
78 |
79 | /**
80 | * This work is licensed under the W3C Software and Document License
81 | * (http://www.w3.org/Consortium/Legal/2015/copyright-software-and-document).
82 | */
83 |
84 | (function (document) {
85 | // Convenience function for converting NodeLists.
86 | /** @type {function(number,number):Array} */
87 | var slice = Array.prototype.slice;
88 |
89 | /** @type {string} */
90 | var _focusableElementsString = ['a[href]', 'area[href]', 'input:not([disabled])', 'select:not([disabled])', 'textarea:not([disabled])', 'button:not([disabled])', 'iframe', 'object', 'embed', '[contenteditable]'].join(',');
91 |
92 | /**
93 | * `InertRoot` manages a single inert subtree, i.e. a DOM subtree whose root element has an `inert`
94 | * attribute.
95 | *
96 | * Its main functions are:
97 | *
98 | * - to create and maintain a set of managed `InertNode`s, including when mutations occur in the
99 | * subtree. The `makeSubtreeUnfocusable()` method handles collecting `InertNode`s via registering
100 | * each focusable node in the subtree with the singleton `InertManager` which manages all known
101 | * focusable nodes within inert subtrees. `InertManager` ensures that a single `InertNode`
102 | * instance exists for each focusable node which has at least one inert root as an ancestor.
103 | *
104 | * - to notify all managed `InertNode`s when this subtree stops being inert (i.e. when the `inert`
105 | * attribute is removed from the root node). This is handled in the destructor, which calls the
106 | * `deregister` method on `InertManager` for each managed inert node.
107 | */
108 |
109 | var InertRoot = function () {
110 | /**
111 | * @param {Element} rootElement The Element at the root of the inert subtree.
112 | * @param {InertManager} inertManager The global singleton InertManager object.
113 | */
114 | function InertRoot(rootElement, inertManager) {
115 | classCallCheck(this, InertRoot);
116 |
117 | /** @type {InertManager} */
118 | this._inertManager = inertManager;
119 |
120 | /** @type {Element} */
121 | this._rootElement = rootElement;
122 |
123 | /**
124 | * @type {Set}
125 | * All managed focusable nodes in this InertRoot's subtree.
126 | */
127 | this._managedNodes = new Set([]);
128 |
129 | // Make the subtree hidden from assistive technology
130 | if (this._rootElement.hasAttribute('aria-hidden')) {
131 | this._savedAriaHidden = this._rootElement.getAttribute('aria-hidden');
132 | }
133 | this._rootElement.setAttribute('aria-hidden', 'true');
134 |
135 | // Make all focusable elements in the subtree unfocusable and add them to _managedNodes
136 | this._makeSubtreeUnfocusable(this._rootElement);
137 |
138 | // Watch for:
139 | // - any additions in the subtree: make them unfocusable too
140 | // - any removals from the subtree: remove them from this inert root's managed nodes
141 | // - attribute changes: if `tabindex` is added, or removed from an intrinsically focusable
142 | // element, make that node a managed node.
143 | this._observer = new MutationObserver(this._onMutation.bind(this));
144 | this._observer.observe(this._rootElement, { attributes: true, childList: true, subtree: true });
145 | }
146 |
147 | /**
148 | * Call this whenever this object is about to become obsolete. This unwinds all of the state
149 | * stored in this object and updates the state of all of the managed nodes.
150 | */
151 |
152 |
153 | createClass(InertRoot, [{
154 | key: 'destructor',
155 | value: function destructor() {
156 | this._observer.disconnect();
157 | this._observer = null;
158 |
159 | if (this._rootElement) {
160 | if (this.hasSavedAriaHidden) {
161 | this._rootElement.setAttribute('aria-hidden', this.savedAriaHidden);
162 | } else {
163 | this._rootElement.removeAttribute('aria-hidden');
164 | }
165 | }
166 | this._rootElement = null;
167 |
168 | var _iteratorNormalCompletion = true;
169 | var _didIteratorError = false;
170 | var _iteratorError = undefined;
171 |
172 | try {
173 | for (var _iterator = this._managedNodes[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
174 | var inertNode = _step.value;
175 |
176 | this._unmanageNode(inertNode.node);
177 | }
178 | } catch (err) {
179 | _didIteratorError = true;
180 | _iteratorError = err;
181 | } finally {
182 | try {
183 | if (!_iteratorNormalCompletion && _iterator.return) {
184 | _iterator.return();
185 | }
186 | } finally {
187 | if (_didIteratorError) {
188 | throw _iteratorError;
189 | }
190 | }
191 | }
192 |
193 | this._managedNodes = null;
194 |
195 | this._inertManager = null;
196 | }
197 |
198 | /**
199 | * @return {Set} A copy of this InertRoot's managed nodes set.
200 | */
201 |
202 | }, {
203 | key: '_makeSubtreeUnfocusable',
204 |
205 |
206 | /**
207 | * @param {Node} startNode
208 | */
209 | value: function _makeSubtreeUnfocusable(startNode) {
210 | var _this = this;
211 |
212 | composedTreeWalk(startNode, function (node) {
213 | return _this._visitNode(node);
214 | });
215 |
216 | var activeElement = document.activeElement;
217 | if (!contains(document.body, startNode)) {
218 | // startNode may be in shadow DOM, so find its nearest shadowRoot to get the activeElement.
219 | var node = startNode;
220 | var root = undefined;
221 | while (node) {
222 | if (node.nodeType === Node.DOCUMENT_FRAGMENT_NODE) {
223 | root = node;
224 | break;
225 | }
226 | node = node.parentNode;
227 | }
228 | if (root) {
229 | activeElement = root.activeElement;
230 | }
231 | }
232 | if (contains(startNode, activeElement)) {
233 | activeElement.blur();
234 | }
235 | }
236 |
237 | /**
238 | * @param {Node} node
239 | */
240 |
241 | }, {
242 | key: '_visitNode',
243 | value: function _visitNode(node) {
244 | if (node.nodeType !== Node.ELEMENT_NODE) {
245 | return;
246 | }
247 |
248 | // If a descendant inert root becomes un-inert, its descendants will still be inert because of
249 | // this inert root, so all of its managed nodes need to be adopted by this InertRoot.
250 | if (node !== this._rootElement && node.hasAttribute('inert')) {
251 | this._adoptInertRoot(node);
252 | }
253 |
254 | if (index(node, _focusableElementsString) || node.hasAttribute('tabindex')) {
255 | this._manageNode(node);
256 | }
257 | }
258 |
259 | /**
260 | * Register the given node with this InertRoot and with InertManager.
261 | * @param {Node} node
262 | */
263 |
264 | }, {
265 | key: '_manageNode',
266 | value: function _manageNode(node) {
267 | var inertNode = this._inertManager.register(node, this);
268 | this._managedNodes.add(inertNode);
269 | }
270 |
271 | /**
272 | * Unregister the given node with this InertRoot and with InertManager.
273 | * @param {Node} node
274 | */
275 |
276 | }, {
277 | key: '_unmanageNode',
278 | value: function _unmanageNode(node) {
279 | var inertNode = this._inertManager.deregister(node, this);
280 | if (inertNode) {
281 | this._managedNodes.delete(inertNode);
282 | }
283 | }
284 |
285 | /**
286 | * Unregister the entire subtree starting at `startNode`.
287 | * @param {Node} startNode
288 | */
289 |
290 | }, {
291 | key: '_unmanageSubtree',
292 | value: function _unmanageSubtree(startNode) {
293 | var _this2 = this;
294 |
295 | composedTreeWalk(startNode, function (node) {
296 | return _this2._unmanageNode(node);
297 | });
298 | }
299 |
300 | /**
301 | * If a descendant node is found with an `inert` attribute, adopt its managed nodes.
302 | * @param {Node} node
303 | */
304 |
305 | }, {
306 | key: '_adoptInertRoot',
307 | value: function _adoptInertRoot(node) {
308 | var inertSubroot = this._inertManager.getInertRoot(node);
309 |
310 | // During initialisation this inert root may not have been registered yet,
311 | // so register it now if need be.
312 | if (!inertSubroot) {
313 | this._inertManager.setInert(node, true);
314 | inertSubroot = this._inertManager.getInertRoot(node);
315 | }
316 |
317 | var _iteratorNormalCompletion2 = true;
318 | var _didIteratorError2 = false;
319 | var _iteratorError2 = undefined;
320 |
321 | try {
322 | for (var _iterator2 = inertSubroot.managedNodes[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) {
323 | var savedInertNode = _step2.value;
324 |
325 | this._manageNode(savedInertNode.node);
326 | }
327 | } catch (err) {
328 | _didIteratorError2 = true;
329 | _iteratorError2 = err;
330 | } finally {
331 | try {
332 | if (!_iteratorNormalCompletion2 && _iterator2.return) {
333 | _iterator2.return();
334 | }
335 | } finally {
336 | if (_didIteratorError2) {
337 | throw _iteratorError2;
338 | }
339 | }
340 | }
341 | }
342 |
343 | /**
344 | * Callback used when mutation observer detects subtree additions, removals, or attribute changes.
345 | * @param {MutationRecord} records
346 | * @param {MutationObserver} self
347 | */
348 |
349 | }, {
350 | key: '_onMutation',
351 | value: function _onMutation(records, self) {
352 | var _iteratorNormalCompletion3 = true;
353 | var _didIteratorError3 = false;
354 | var _iteratorError3 = undefined;
355 |
356 | try {
357 | for (var _iterator3 = records[Symbol.iterator](), _step3; !(_iteratorNormalCompletion3 = (_step3 = _iterator3.next()).done); _iteratorNormalCompletion3 = true) {
358 | var record = _step3.value;
359 |
360 | var target = record.target;
361 | if (record.type === 'childList') {
362 | // Manage added nodes
363 | var _iteratorNormalCompletion4 = true;
364 | var _didIteratorError4 = false;
365 | var _iteratorError4 = undefined;
366 |
367 | try {
368 | for (var _iterator4 = slice.call(record.addedNodes)[Symbol.iterator](), _step4; !(_iteratorNormalCompletion4 = (_step4 = _iterator4.next()).done); _iteratorNormalCompletion4 = true) {
369 | var node = _step4.value;
370 |
371 | this._makeSubtreeUnfocusable(node);
372 | }
373 |
374 | // Un-manage removed nodes
375 | } catch (err) {
376 | _didIteratorError4 = true;
377 | _iteratorError4 = err;
378 | } finally {
379 | try {
380 | if (!_iteratorNormalCompletion4 && _iterator4.return) {
381 | _iterator4.return();
382 | }
383 | } finally {
384 | if (_didIteratorError4) {
385 | throw _iteratorError4;
386 | }
387 | }
388 | }
389 |
390 | var _iteratorNormalCompletion5 = true;
391 | var _didIteratorError5 = false;
392 | var _iteratorError5 = undefined;
393 |
394 | try {
395 | for (var _iterator5 = slice.call(record.removedNodes)[Symbol.iterator](), _step5; !(_iteratorNormalCompletion5 = (_step5 = _iterator5.next()).done); _iteratorNormalCompletion5 = true) {
396 | var _node = _step5.value;
397 |
398 | this._unmanageSubtree(_node);
399 | }
400 | } catch (err) {
401 | _didIteratorError5 = true;
402 | _iteratorError5 = err;
403 | } finally {
404 | try {
405 | if (!_iteratorNormalCompletion5 && _iterator5.return) {
406 | _iterator5.return();
407 | }
408 | } finally {
409 | if (_didIteratorError5) {
410 | throw _iteratorError5;
411 | }
412 | }
413 | }
414 | } else if (record.type === 'attributes') {
415 | if (record.attributeName === 'tabindex') {
416 | // Re-initialise inert node if tabindex changes
417 | this._manageNode(target);
418 | } else if (target !== this._rootElement && record.attributeName === 'inert' && target.hasAttribute('inert')) {
419 | // If a new inert root is added, adopt its managed nodes and make sure it knows about the
420 | // already managed nodes from this inert subroot.
421 | this._adoptInertRoot(target);
422 | var inertSubroot = this._inertManager.getInertRoot(target);
423 | var _iteratorNormalCompletion6 = true;
424 | var _didIteratorError6 = false;
425 | var _iteratorError6 = undefined;
426 |
427 | try {
428 | for (var _iterator6 = this._managedNodes[Symbol.iterator](), _step6; !(_iteratorNormalCompletion6 = (_step6 = _iterator6.next()).done); _iteratorNormalCompletion6 = true) {
429 | var managedNode = _step6.value;
430 |
431 | if (contains(target, managedNode.node)) {
432 | inertSubroot._manageNode(managedNode.node);
433 | }
434 | }
435 | } catch (err) {
436 | _didIteratorError6 = true;
437 | _iteratorError6 = err;
438 | } finally {
439 | try {
440 | if (!_iteratorNormalCompletion6 && _iterator6.return) {
441 | _iterator6.return();
442 | }
443 | } finally {
444 | if (_didIteratorError6) {
445 | throw _iteratorError6;
446 | }
447 | }
448 | }
449 | }
450 | }
451 | }
452 | } catch (err) {
453 | _didIteratorError3 = true;
454 | _iteratorError3 = err;
455 | } finally {
456 | try {
457 | if (!_iteratorNormalCompletion3 && _iterator3.return) {
458 | _iterator3.return();
459 | }
460 | } finally {
461 | if (_didIteratorError3) {
462 | throw _iteratorError3;
463 | }
464 | }
465 | }
466 | }
467 | }, {
468 | key: 'managedNodes',
469 | get: function get$$1() {
470 | return new Set(this._managedNodes);
471 | }
472 |
473 | /** @return {boolean} */
474 |
475 | }, {
476 | key: 'hasSavedAriaHidden',
477 | get: function get$$1() {
478 | return '_savedAriaHidden' in this;
479 | }
480 |
481 | /** @param {string} ariaHidden */
482 |
483 | }, {
484 | key: 'savedAriaHidden',
485 | set: function set$$1(ariaHidden) {
486 | this._savedAriaHidden = ariaHidden;
487 | }
488 |
489 | /** @return {string} */
490 | ,
491 | get: function get$$1() {
492 | return this._savedAriaHidden;
493 | }
494 | }]);
495 | return InertRoot;
496 | }();
497 |
498 | /**
499 | * `InertNode` initialises and manages a single inert node.
500 | * A node is inert if it is a descendant of one or more inert root elements.
501 | *
502 | * On construction, `InertNode` saves the existing `tabindex` value for the node, if any, and
503 | * either removes the `tabindex` attribute or sets it to `-1`, depending on whether the element
504 | * is intrinsically focusable or not.
505 | *
506 | * `InertNode` maintains a set of `InertRoot`s which are descendants of this `InertNode`. When an
507 | * `InertRoot` is destroyed, and calls `InertManager.deregister()`, the `InertManager` notifies the
508 | * `InertNode` via `removeInertRoot()`, which in turn destroys the `InertNode` if no `InertRoot`s
509 | * remain in the set. On destruction, `InertNode` reinstates the stored `tabindex` if one exists,
510 | * or removes the `tabindex` attribute if the element is intrinsically focusable.
511 | */
512 |
513 |
514 | var InertNode = function () {
515 | /**
516 | * @param {Node} node A focusable element to be made inert.
517 | * @param {InertRoot} inertRoot The inert root element associated with this inert node.
518 | */
519 | function InertNode(node, inertRoot) {
520 | classCallCheck(this, InertNode);
521 |
522 | /** @type {Node} */
523 | this._node = node;
524 |
525 | /** @type {boolean} */
526 | this._overrodeFocusMethod = false;
527 |
528 | /**
529 | * @type {Set} The set of descendant inert roots.
530 | * If and only if this set becomes empty, this node is no longer inert.
531 | */
532 | this._inertRoots = new Set([inertRoot]);
533 |
534 | /** @type {boolean} */
535 | this._destroyed = false;
536 |
537 | // Save any prior tabindex info and make this node untabbable
538 | this.ensureUntabbable();
539 | }
540 |
541 | /**
542 | * Call this whenever this object is about to become obsolete.
543 | * This makes the managed node focusable again and deletes all of the previously stored state.
544 | */
545 |
546 |
547 | createClass(InertNode, [{
548 | key: 'destructor',
549 | value: function destructor() {
550 | this._throwIfDestroyed();
551 |
552 | if (this._node) {
553 | if (this.hasSavedTabIndex) {
554 | this._node.setAttribute('tabindex', this.savedTabIndex);
555 | } else {
556 | this._node.removeAttribute('tabindex');
557 | }
558 |
559 | // Use `delete` to restore native focus method.
560 | if (this._overrodeFocusMethod) {
561 | delete this._node.focus;
562 | }
563 | }
564 | this._node = null;
565 | this._inertRoots = null;
566 |
567 | this._destroyed = true;
568 | }
569 |
570 | /**
571 | * @type {boolean} Whether this object is obsolete because the managed node is no longer inert.
572 | * If the object has been destroyed, any attempt to access it will cause an exception.
573 | */
574 |
575 | }, {
576 | key: '_throwIfDestroyed',
577 |
578 |
579 | /**
580 | * Throw if user tries to access destroyed InertNode.
581 | */
582 | value: function _throwIfDestroyed() {
583 | if (this.destroyed) {
584 | throw new Error('Trying to access destroyed InertNode');
585 | }
586 | }
587 |
588 | /** @return {boolean} */
589 |
590 | }, {
591 | key: 'ensureUntabbable',
592 |
593 |
594 | /** Save the existing tabindex value and make the node untabbable and unfocusable */
595 | value: function ensureUntabbable() {
596 | var node = this.node;
597 | if (index(node, _focusableElementsString)) {
598 | if (node.tabIndex === -1 && this.hasSavedTabIndex) {
599 | return;
600 | }
601 |
602 | if (node.hasAttribute('tabindex')) {
603 | this._savedTabIndex = node.tabIndex;
604 | }
605 | node.setAttribute('tabindex', '-1');
606 | if (node.nodeType === Node.ELEMENT_NODE) {
607 | node.focus = function () {};
608 | this._overrodeFocusMethod = true;
609 | }
610 | } else if (node.hasAttribute('tabindex')) {
611 | this._savedTabIndex = node.tabIndex;
612 | node.removeAttribute('tabindex');
613 | }
614 | }
615 |
616 | /**
617 | * Add another inert root to this inert node's set of managing inert roots.
618 | * @param {InertRoot} inertRoot
619 | */
620 |
621 | }, {
622 | key: 'addInertRoot',
623 | value: function addInertRoot(inertRoot) {
624 | this._throwIfDestroyed();
625 | this._inertRoots.add(inertRoot);
626 | }
627 |
628 | /**
629 | * Remove the given inert root from this inert node's set of managing inert roots.
630 | * If the set of managing inert roots becomes empty, this node is no longer inert,
631 | * so the object should be destroyed.
632 | * @param {InertRoot} inertRoot
633 | */
634 |
635 | }, {
636 | key: 'removeInertRoot',
637 | value: function removeInertRoot(inertRoot) {
638 | this._throwIfDestroyed();
639 | this._inertRoots.delete(inertRoot);
640 | if (this._inertRoots.size === 0) {
641 | this.destructor();
642 | }
643 | }
644 | }, {
645 | key: 'destroyed',
646 | get: function get$$1() {
647 | return this._destroyed;
648 | }
649 | }, {
650 | key: 'hasSavedTabIndex',
651 | get: function get$$1() {
652 | return '_savedTabIndex' in this;
653 | }
654 |
655 | /** @return {Node} */
656 |
657 | }, {
658 | key: 'node',
659 | get: function get$$1() {
660 | this._throwIfDestroyed();
661 | return this._node;
662 | }
663 |
664 | /** @param {number} tabIndex */
665 |
666 | }, {
667 | key: 'savedTabIndex',
668 | set: function set$$1(tabIndex) {
669 | this._throwIfDestroyed();
670 | this._savedTabIndex = tabIndex;
671 | }
672 |
673 | /** @return {number} */
674 | ,
675 | get: function get$$1() {
676 | this._throwIfDestroyed();
677 | return this._savedTabIndex;
678 | }
679 | }]);
680 | return InertNode;
681 | }();
682 |
683 | /**
684 | * InertManager is a per-document singleton object which manages all inert roots and nodes.
685 | *
686 | * When an element becomes an inert root by having an `inert` attribute set and/or its `inert`
687 | * property set to `true`, the `setInert` method creates an `InertRoot` object for the element.
688 | * The `InertRoot` in turn registers itself as managing all of the element's focusable descendant
689 | * nodes via the `register()` method. The `InertManager` ensures that a single `InertNode` instance
690 | * is created for each such node, via the `_managedNodes` map.
691 | */
692 |
693 |
694 | var InertManager = function () {
695 | /**
696 | * @param {Document} document
697 | */
698 | function InertManager(document) {
699 | classCallCheck(this, InertManager);
700 |
701 | if (!document) {
702 | throw new Error('Missing required argument; InertManager needs to wrap a document.');
703 | }
704 |
705 | /** @type {Document} */
706 | this._document = document;
707 |
708 | /**
709 | * All managed nodes known to this InertManager. In a map to allow looking up by Node.
710 | * @type {Map}
711 | */
712 | this._managedNodes = new Map();
713 |
714 | /**
715 | * All inert roots known to this InertManager. In a map to allow looking up by Node.
716 | * @type {Map}
717 | */
718 | this._inertRoots = new Map();
719 |
720 | /**
721 | * Observer for mutations on `document.body`.
722 | * @type {MutationObserver}
723 | */
724 | this._observer = new MutationObserver(this._watchForInert.bind(this));
725 |
726 | // Add inert style.
727 | addInertStyle(document.head || document.body || document.documentElement);
728 |
729 | // Wait for document to be loaded.
730 | if (document.readyState === 'loading') {
731 | document.addEventListener('DOMContentLoaded', this._onDocumentLoaded.bind(this));
732 | } else {
733 | this._onDocumentLoaded();
734 | }
735 | }
736 |
737 | /**
738 | * Set whether the given element should be an inert root or not.
739 | * @param {Element} root
740 | * @param {boolean} inert
741 | */
742 |
743 |
744 | createClass(InertManager, [{
745 | key: 'setInert',
746 | value: function setInert(root, inert) {
747 | if (inert) {
748 | if (this._inertRoots.has(root)) {
749 | // element is already inert
750 | return;
751 | }
752 |
753 | var inertRoot = new InertRoot(root, this);
754 | root.setAttribute('inert', '');
755 | this._inertRoots.set(root, inertRoot);
756 | // If not contained in the document, it must be in a shadowRoot.
757 | // Ensure inert styles are added there.
758 | if (!contains(this._document.body, root)) {
759 | var parent = root.parentNode;
760 | while (parent) {
761 | if (parent.nodeType === 11) {
762 | addInertStyle(parent);
763 | }
764 | parent = parent.parentNode;
765 | }
766 | }
767 | } else {
768 | if (!this._inertRoots.has(root)) {
769 | // element is already non-inert
770 | return;
771 | }
772 |
773 | var _inertRoot = this._inertRoots.get(root);
774 | _inertRoot.destructor();
775 | this._inertRoots.delete(root);
776 | root.removeAttribute('inert');
777 | }
778 | }
779 |
780 | /**
781 | * Get the InertRoot object corresponding to the given inert root element, if any.
782 | * @param {Element} element
783 | * @return {InertRoot?}
784 | */
785 |
786 | }, {
787 | key: 'getInertRoot',
788 | value: function getInertRoot(element) {
789 | return this._inertRoots.get(element);
790 | }
791 |
792 | /**
793 | * Register the given InertRoot as managing the given node.
794 | * In the case where the node has a previously existing inert root, this inert root will
795 | * be added to its set of inert roots.
796 | * @param {Node} node
797 | * @param {InertRoot} inertRoot
798 | * @return {InertNode} inertNode
799 | */
800 |
801 | }, {
802 | key: 'register',
803 | value: function register(node, inertRoot) {
804 | var inertNode = this._managedNodes.get(node);
805 | if (inertNode !== undefined) {
806 | // node was already in an inert subtree
807 | inertNode.addInertRoot(inertRoot);
808 | // Update saved tabindex value if necessary
809 | inertNode.ensureUntabbable();
810 | } else {
811 | inertNode = new InertNode(node, inertRoot);
812 | }
813 |
814 | this._managedNodes.set(node, inertNode);
815 |
816 | return inertNode;
817 | }
818 |
819 | /**
820 | * De-register the given InertRoot as managing the given inert node.
821 | * Removes the inert root from the InertNode's set of managing inert roots, and remove the inert
822 | * node from the InertManager's set of managed nodes if it is destroyed.
823 | * If the node is not currently managed, this is essentially a no-op.
824 | * @param {Node} node
825 | * @param {InertRoot} inertRoot
826 | * @return {InertNode?} The potentially destroyed InertNode associated with this node, if any.
827 | */
828 |
829 | }, {
830 | key: 'deregister',
831 | value: function deregister(node, inertRoot) {
832 | var inertNode = this._managedNodes.get(node);
833 | if (!inertNode) {
834 | return null;
835 | }
836 |
837 | inertNode.removeInertRoot(inertRoot);
838 | if (inertNode.destroyed) {
839 | this._managedNodes.delete(node);
840 | }
841 |
842 | return inertNode;
843 | }
844 |
845 | /**
846 | * Callback used when document has finished loading.
847 | */
848 |
849 | }, {
850 | key: '_onDocumentLoaded',
851 | value: function _onDocumentLoaded() {
852 | // Find all inert roots in document and make them actually inert.
853 | var inertElements = slice.call(this._document.querySelectorAll('[inert]'));
854 | var _iteratorNormalCompletion7 = true;
855 | var _didIteratorError7 = false;
856 | var _iteratorError7 = undefined;
857 |
858 | try {
859 | for (var _iterator7 = inertElements[Symbol.iterator](), _step7; !(_iteratorNormalCompletion7 = (_step7 = _iterator7.next()).done); _iteratorNormalCompletion7 = true) {
860 | var inertElement = _step7.value;
861 |
862 | this.setInert(inertElement, true);
863 | }
864 |
865 | // Comment this out to use programmatic API only.
866 | } catch (err) {
867 | _didIteratorError7 = true;
868 | _iteratorError7 = err;
869 | } finally {
870 | try {
871 | if (!_iteratorNormalCompletion7 && _iterator7.return) {
872 | _iterator7.return();
873 | }
874 | } finally {
875 | if (_didIteratorError7) {
876 | throw _iteratorError7;
877 | }
878 | }
879 | }
880 |
881 | this._observer.observe(this._document.body, { attributes: true, subtree: true, childList: true });
882 | }
883 |
884 | /**
885 | * Callback used when mutation observer detects attribute changes.
886 | * @param {MutationRecord} records
887 | * @param {MutationObserver} self
888 | */
889 |
890 | }, {
891 | key: '_watchForInert',
892 | value: function _watchForInert(records, self) {
893 | var _iteratorNormalCompletion8 = true;
894 | var _didIteratorError8 = false;
895 | var _iteratorError8 = undefined;
896 |
897 | try {
898 | for (var _iterator8 = records[Symbol.iterator](), _step8; !(_iteratorNormalCompletion8 = (_step8 = _iterator8.next()).done); _iteratorNormalCompletion8 = true) {
899 | var record = _step8.value;
900 |
901 | switch (record.type) {
902 | case 'childList':
903 | var _iteratorNormalCompletion9 = true;
904 | var _didIteratorError9 = false;
905 | var _iteratorError9 = undefined;
906 |
907 | try {
908 | for (var _iterator9 = slice.call(record.addedNodes)[Symbol.iterator](), _step9; !(_iteratorNormalCompletion9 = (_step9 = _iterator9.next()).done); _iteratorNormalCompletion9 = true) {
909 | var node = _step9.value;
910 |
911 | if (node.nodeType !== Node.ELEMENT_NODE) {
912 | continue;
913 | }
914 | var inertElements = slice.call(node.querySelectorAll('[inert]'));
915 | if (index(node, '[inert]')) {
916 | inertElements.unshift(node);
917 | }
918 | var _iteratorNormalCompletion10 = true;
919 | var _didIteratorError10 = false;
920 | var _iteratorError10 = undefined;
921 |
922 | try {
923 | for (var _iterator10 = inertElements[Symbol.iterator](), _step10; !(_iteratorNormalCompletion10 = (_step10 = _iterator10.next()).done); _iteratorNormalCompletion10 = true) {
924 | var inertElement = _step10.value;
925 |
926 | this.setInert(inertElement, true);
927 | }
928 | } catch (err) {
929 | _didIteratorError10 = true;
930 | _iteratorError10 = err;
931 | } finally {
932 | try {
933 | if (!_iteratorNormalCompletion10 && _iterator10.return) {
934 | _iterator10.return();
935 | }
936 | } finally {
937 | if (_didIteratorError10) {
938 | throw _iteratorError10;
939 | }
940 | }
941 | }
942 | }
943 | } catch (err) {
944 | _didIteratorError9 = true;
945 | _iteratorError9 = err;
946 | } finally {
947 | try {
948 | if (!_iteratorNormalCompletion9 && _iterator9.return) {
949 | _iterator9.return();
950 | }
951 | } finally {
952 | if (_didIteratorError9) {
953 | throw _iteratorError9;
954 | }
955 | }
956 | }
957 |
958 | break;
959 | case 'attributes':
960 | if (record.attributeName !== 'inert') {
961 | continue;
962 | }
963 | var target = record.target;
964 | var inert = target.hasAttribute('inert');
965 | this.setInert(target, inert);
966 | break;
967 | }
968 | }
969 | } catch (err) {
970 | _didIteratorError8 = true;
971 | _iteratorError8 = err;
972 | } finally {
973 | try {
974 | if (!_iteratorNormalCompletion8 && _iterator8.return) {
975 | _iterator8.return();
976 | }
977 | } finally {
978 | if (_didIteratorError8) {
979 | throw _iteratorError8;
980 | }
981 | }
982 | }
983 | }
984 | }]);
985 | return InertManager;
986 | }();
987 |
988 | /**
989 | * Recursively walk the composed tree from |node|.
990 | * @param {Node} node
991 | * @param {(function (Element))=} callback Callback to be called for each element traversed,
992 | * before descending into child nodes.
993 | * @param {ShadowRoot=} shadowRootAncestor The nearest ShadowRoot ancestor, if any.
994 | */
995 |
996 |
997 | function composedTreeWalk(node, callback, shadowRootAncestor) {
998 | if (node.nodeType == Node.ELEMENT_NODE) {
999 | var element = /** @type {Element} */node;
1000 | if (callback) {
1001 | callback(element);
1002 | }
1003 |
1004 | // Descend into node:
1005 | // If it has a ShadowRoot, ignore all child elements - these will be picked
1006 | // up by the or elements. Descend straight into the
1007 | // ShadowRoot.
1008 | var shadowRoot = element.shadowRoot || element.webkitShadowRoot;
1009 | if (shadowRoot) {
1010 | composedTreeWalk(shadowRoot, callback, shadowRoot);
1011 | return;
1012 | }
1013 |
1014 | // If it is a element, descend into distributed elements - these
1015 | // are elements from outside the shadow root which are rendered inside the
1016 | // shadow DOM.
1017 | if (element.localName == 'content') {
1018 | var content = /** @type {HTMLContentElement} */element;
1019 | // Verifies if ShadowDom v0 is supported.
1020 | var distributedNodes = content.getDistributedNodes ? content.getDistributedNodes() : [];
1021 | for (var i = 0; i < distributedNodes.length; i++) {
1022 | composedTreeWalk(distributedNodes[i], callback, shadowRootAncestor);
1023 | }
1024 | return;
1025 | }
1026 |
1027 | // If it is a element, descend into assigned nodes - these
1028 | // are elements from outside the shadow root which are rendered inside the
1029 | // shadow DOM.
1030 | if (element.localName == 'slot') {
1031 | var slot = /** @type {HTMLSlotElement} */element;
1032 | // Verify if ShadowDom v1 is supported.
1033 | var _distributedNodes = slot.assignedNodes ? slot.assignedNodes({ flatten: true }) : [];
1034 | for (var _i = 0; _i < _distributedNodes.length; _i++) {
1035 | composedTreeWalk(_distributedNodes[_i], callback, shadowRootAncestor);
1036 | }
1037 | return;
1038 | }
1039 | }
1040 |
1041 | // If it is neither the parent of a ShadowRoot, a element, a
1042 | // element, nor a element recurse normally.
1043 | var child = node.firstChild;
1044 | while (child != null) {
1045 | composedTreeWalk(child, callback, shadowRootAncestor);
1046 | child = child.nextSibling;
1047 | }
1048 | }
1049 |
1050 | /**
1051 | * Adds a style element to the node containing the inert specific styles
1052 | * @param {Node} node
1053 | */
1054 | function addInertStyle(node) {
1055 | if (node.querySelector('style#inert-style')) {
1056 | return;
1057 | }
1058 | var style = document.createElement('style');
1059 | style.setAttribute('id', 'inert-style');
1060 | style.textContent = '\n' + '[inert] {\n' + ' pointer-events: none;\n' + ' cursor: default;\n' + '}\n' + '\n' + '[inert], [inert] * {\n' + ' user-select: none;\n' + ' -webkit-user-select: none;\n' + ' -moz-user-select: none;\n' + ' -ms-user-select: none;\n' + '}\n';
1061 | node.appendChild(style);
1062 | }
1063 |
1064 | /**
1065 | * `Node#contains()` polyfill.
1066 | *
1067 | * See: http://compatibility.shwups-cms.ch/en/polyfills/?&id=1
1068 | *
1069 | * @param {Node} node
1070 | * @param {Node} other
1071 | * @return {Boolean}
1072 | * @public
1073 | */
1074 | function contains(node, other) {
1075 | return other && (node === other || !!(node.compareDocumentPosition(other) & 16));
1076 | }
1077 |
1078 | var inertManager = new InertManager(document);
1079 |
1080 | Object.defineProperty(Element.prototype, 'inert', {
1081 | enumerable: true,
1082 | get: function get$$1() {
1083 | return this.hasAttribute('inert');
1084 | },
1085 | set: function set$$1(inert) {
1086 | inertManager.setInert(this, inert);
1087 | }
1088 | });
1089 | })(document);
1090 |
1091 | })));
1092 |
--------------------------------------------------------------------------------