diff --git a/.gitignore b/.gitignore
index 00cbbdf..c1a4f7d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -57,3 +57,5 @@ typings/
# dotenv environment variables file
.env
+example/bundle.js
+example/bundle.js.map
\ No newline at end of file
diff --git a/.npmignore b/.npmignore
new file mode 100644
index 0000000..b68090e
--- /dev/null
+++ b/.npmignore
@@ -0,0 +1,2 @@
+example/
+docs/
\ No newline at end of file
diff --git a/README.md b/README.md
index 4f79efe..44bb56c 100644
--- a/README.md
+++ b/README.md
@@ -1,2 +1,111 @@
# react-giphy-selector
-A search modal for picking the perfect giphy.
+A search and select React.JS component for picking the perfect giphy.
+
+![Example selector](./docs/example_1.gif)
+
+> This component is highly-customizable and only provides basic styling out-of-box. The example above includes simple customization to a few elements. You can view this example in `/example/src`.
+
+## Table of Contents
+
+- [Installation](#installation)
+- [Usage](#usage)
+
+## Installation
+
+You just install `react-giphy-selector` the good ole' fashion way through NPM:
+
+```
+npm install --save react-giphy-selector
+```
+
+## Usage
+
+This package exports the `Selector` React component and then two helper `enums`:
+
+```js
+import {Selector, ResultSort, Rating} from "react-giphy-selector";
+
+```
+
+- [Selector](#selector)
+- [Rating](#rating)
+- [ResultSort](#resultSort)
+
+### Selector
+
+The selector component contains all of the search, display, and selection logic. The only required properties are `apiKey` and `onGifSelected`.
+
+```jsx
+
+```
+
+That said, there are a bunch of props that allow you to make this component your own. Note: the `?` included at the end of a property name denotes it as optional.
+
+- `apiKey: string`: [Your Giphy Project API Key](https://developers.giphy.com/).
+- `onGifSelected?: (gifObject: IGifObject) => void`: The function to fire when a gif search result has been selected. The `IGifObject` represents the full [GIF Object](https://developers.giphy.com/docs/#gif-object) returned via the Giphy API.
+- `rating?: Rating`: The maximum rating you want to allow in your search results. Use the exported [Rating](#rating) enum for help. Default: `Rating.G`.
+- `sort?: ResultSort`: The sort order of the search results. Use the helper enum [ResultSort](#resultsort). Default: `ResultSort.Relevant`.
+- `limit?: number`: The number of results to return. Default: `20`.
+- `suggestions?: string[]`: An array containing one-click searches to make it easy for your user. Will not show suggestions section if none are passed. Default: `[]`.
+- `queryInputPlaceholder?: string`: The placeholder text for the search bar text input. Default `'Enter search text'`.
+- `resultColumns?: number`: The number of columns to divide the search results into. Default: `3`.
+- `showGiphyMark?: boolean`: Indicates whether to show the "powered by Giphy" mark in the selector. This is required when [using a Giphy Production API Key](https://developers.giphy.com/docs/#production-key). Default: `true`.
+
+#### Styling your Selector
+
+There are a bunch of `props` to help you customize the style of the the selector. Both the `className` and the `style` methods are available. `react-giphy-selector` is very intentionally unopinionated about how exactly each section of the selector should look. Instead, the package offers a lot of customization and flexibility through the props below.
+
+The images below will help you understand the nomenclature of the components:
+
+![Diagram of component nomenclature for query form, suggestions, and footer](./docs/components_1.png)
+![Diagram of component nomenclature for search results](./docs/components_2.png)
+
+Here are all the props available for styling the component:
+
+- `queryFormClassName?: string`: Additional `className` for the query form section of the component. You can find the default style applied in `src/components/QueryForm.css`.
+- `queryFormInputClassName?: string`: Additional `className` for the text input in the query form. You can find the default style applied in `src/components/QueryForm.css`.
+- `queryFormSubmitClassName?: string`: Additional `className` for the submit button in the query form. You can find the default style applied in `src/components/QueryForm.css`.
+- `queryFormStyle?: object`: A style object to add to the query form style. You can find the default style applied in `src/components/QueryForm.css`.
+- `queryFormInputStyle?: object`: A style object to add to the text input in the query form. You can find the default style applied in `src/components/QueryForm.css`.
+- `queryFormSubmitStyle?: object`: A style object to add to the submit button in the query form. You can find the default style applied in `src/components/QueryForm.css`.
+- `queryFormSubmitContent?: string or Component`: You can pass in a `string` or your own component to render inside the submit button in the query form. This allows you to pass in things like custom icons. Default: `'Search'`.
+- `searchResultsClassName?: string`: Additional `className` for the search results component. You can find the default style in `src/components/SearchResults.css`.
+- `searchResultsStyle?: object`: A style object to the add to the search results container. You can find the default style in `src/components/SearchResults.css`.
+- `searchResultClassName?: string`: Additional `className` to add to a search result. Search results are `a` elements. You can find the default style in `src/components/SearchResult.css`.
+- `searchResultStyle?: object`: A style object to add to a search result. Search results are `a` elements. You can find the default style in `src/components/SearchResult.css`.
+- `suggestionsClassName?: string`: Additional `className` to add to the suggestions container. You can find the default style in `src/components/Suggestions.css`.
+- `suggestionsStyle?: object`: A style object to add to the suggestions container. You can find the default style in `src/components/Suggestions.css`.
+- `suggestionClassName?: string`: Additional `className` to add to a suggestion. This is an `a` element. You can find the default style in `src/components/Suggestion.css`.
+- `suggestionStyle?: object`: A style object to add to a suggestion. This is an `a` element. You can find the default style in `src/components/Suggestion.css`.
+- `loaderClassName?: string`: Additional `className` to add to the loader container. You can find the default style in `src/components/Selector.css`.
+- `loaderStyle?: object`: A style object to add to the loader container. You can find the default style in `src/components/Selector.css`.
+- `loaderContent?: string or Component`: You can pass in a `string` or customer component to display when results are loading. Default `'Loading'...`.
+- `searchErrorClassName?: string`: Additional `className` to add to the error message shown on broken searches. You can find the default style in `src/components/Selector.css`.
+- `searchErrorStyle?: object`: A style object to add to the error message shown on broken searches. You can find the default style in `src/components/Selector.css`.
+- `footerClassName?: string`: Additional `className` to add to footer of selector. You can find the default style in `src/components/Selector.css`.
+- `footerStyle?: object`: A style object to add to footer of selector. You can find the default style in `src/components/Selector.css`.
+
+If you have a cool style you'd like to share, please [make an issue](https://github.com/tshaddix/react-giphy-selector/issues).
+
+### Rating
+
+The `Rating` enum contains all the possible ratings you can limit searches to:
+
+```js
+Rating.Y
+Rating.G
+Rating.PG
+Rating.PG13
+Rating.R
+```
+
+### ResultSort
+
+The `ResultSort` enum contains the different sort methods supported by the Giphy API.
+
+```js
+ResultSort.Recent // ordered by most recent
+ResultSort.Relevant // ordered by relevance
+```
\ No newline at end of file
diff --git a/docs/components_1.png b/docs/components_1.png
new file mode 100644
index 0000000..1f4aa48
Binary files /dev/null and b/docs/components_1.png differ
diff --git a/docs/components_2.png b/docs/components_2.png
new file mode 100644
index 0000000..41cc4f3
Binary files /dev/null and b/docs/components_2.png differ
diff --git a/docs/example_1.gif b/docs/example_1.gif
new file mode 100644
index 0000000..c0592f3
Binary files /dev/null and b/docs/example_1.gif differ
diff --git a/example/example.html b/example/example.html
new file mode 100644
index 0000000..4e7953b
--- /dev/null
+++ b/example/example.html
@@ -0,0 +1,13 @@
+
+
+
+
+ React Giphy Selector - Example
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/example/src/example.css b/example/src/example.css
new file mode 100644
index 0000000..6420ff1
--- /dev/null
+++ b/example/src/example.css
@@ -0,0 +1,39 @@
+.customQueryFormSubmit {
+ background: #0097cf;
+ color: #fff;
+ border: 0;
+ padding: 10px 20px;
+ font-size: 16px;
+ font-weight: bold;
+}
+
+.customQueryFormInput {
+ padding-left: 10px;
+ padding-right: 10px;
+ border: 1px solid #e0e0e0;
+ border-right: 0;
+ box-shadow: none;
+}
+
+.customSearchResults {
+ max-height: 400px;
+ margin-top: 10px;
+ margin-bottom: 10px;
+}
+
+/********************************
+CSS classes for example fake modal
+********************************/
+
+body {
+ background: #333;
+ font-family: sans-serif;
+}
+
+.modal {
+ max-width: 600px;
+ margin: 60px auto;
+ background: #fff;
+ padding: 20px;
+ border-bottom: 5px solid #111;
+}
\ No newline at end of file
diff --git a/example/src/example.tsx b/example/src/example.tsx
new file mode 100644
index 0000000..8d9541b
--- /dev/null
+++ b/example/src/example.tsx
@@ -0,0 +1,98 @@
+import { Selector, Rating } from "../../lib";
+import * as React from "react";
+import * as ReactDOM from "react-dom";
+
+const customStyle = require("./example.css");
+
+// feel free to change these :)
+const suggestions = [
+ "watching",
+ "quiz",
+ "stop it",
+ "nice one",
+ "learning",
+ "reading",
+ "working"
+];
+
+interface IExampleProps {
+ suggestions: string[];
+}
+
+interface IExampleState {
+ apiKey: string;
+ isKeySubmitted: boolean;
+}
+
+class ExampleApp extends React.Component {
+ state: IExampleState;
+
+ constructor(props: IExampleProps) {
+ super(props);
+
+ this.state = {
+ apiKey: "",
+ isKeySubmitted: false
+ };
+
+ this.onKeyChange = this.onKeyChange.bind(this);
+ this.onKeySubmit = this.onKeySubmit.bind(this);
+ this.onGifSelected = this.onGifSelected.bind(this);
+ }
+
+ public onKeyChange(event: any): void {
+ this.setState({ apiKey: event.target.value });
+ }
+
+ public onKeySubmit(event: any): void {
+ event.preventDefault();
+
+ this.setState({
+ isKeySubmitted: true
+ });
+ }
+
+ public onGifSelected(gifObject: any): void {
+ alert(`You selected a gif! id: ${gifObject.id}`);
+ }
+
+ public render(): JSX.Element {
+ const { apiKey, isKeySubmitted } = this.state;
+ const { suggestions } = this.props;
+
+ if (!isKeySubmitted) {
+ return (
+
+ );
+ }
+
+ return (
+
+
+
+ );
+ }
+}
+
+ReactDOM.render(
+ ,
+ document.getElementById("example")
+);
diff --git a/example/webpack.config.js b/example/webpack.config.js
new file mode 100644
index 0000000..d63b8c4
--- /dev/null
+++ b/example/webpack.config.js
@@ -0,0 +1,30 @@
+module.exports = {
+ entry: "./example/src/example.tsx",
+ output: {
+ filename: "bundle.js",
+ path: __dirname
+ },
+
+ // Enable sourcemaps for debugging webpack's output.
+ devtool: "source-map",
+
+ resolve: {
+ // Add '.ts' and '.tsx' as resolvable extensions.
+ extensions: [".ts", ".tsx", ".js", ".json"]
+ },
+
+ module: {
+ rules: [
+ // All files with a '.ts' or '.tsx' extension will be handled by 'awesome-typescript-loader'.
+ { test: /\.tsx?$/, loader: "awesome-typescript-loader" },
+
+ // All output '.js' files will have any sourcemaps re-processed by 'source-map-loader'.
+ { enforce: "pre", test: /\.js$/, loader: "source-map-loader" },
+
+ {
+ test: /\.css$/,
+ loader: ["style-loader", "css-loader?sourceMap&modules"]
+ }
+ ]
+ }
+};
\ No newline at end of file
diff --git a/index.d.ts b/index.d.ts
new file mode 100644
index 0000000..fbc5b27
--- /dev/null
+++ b/index.d.ts
@@ -0,0 +1,2 @@
+export {Rating, ResultSort, IGifImage, IGifObject} from './src/types';
+export {Selector, ISelectorProps} from './src/components/Selector';
\ No newline at end of file
diff --git a/lib/index.js b/lib/index.js
new file mode 100644
index 0000000..0cd9be8
--- /dev/null
+++ b/lib/index.js
@@ -0,0 +1,23013 @@
+(function webpackUniversalModuleDefinition(root, factory) {
+ if(typeof exports === 'object' && typeof module === 'object')
+ module.exports = factory();
+ else if(typeof define === 'function' && define.amd)
+ define([], factory);
+ else if(typeof exports === 'object')
+ exports["ReactGiphySelector"] = factory();
+ else
+ root["ReactGiphySelector"] = factory();
+})(typeof self !== 'undefined' ? self : this, function() {
+return /******/ (function(modules) { // webpackBootstrap
+/******/ // The module cache
+/******/ var installedModules = {};
+/******/
+/******/ // The require function
+/******/ function __webpack_require__(moduleId) {
+/******/
+/******/ // Check if module is in cache
+/******/ if(installedModules[moduleId]) {
+/******/ return installedModules[moduleId].exports;
+/******/ }
+/******/ // Create a new module (and put it into the cache)
+/******/ var module = installedModules[moduleId] = {
+/******/ i: moduleId,
+/******/ l: false,
+/******/ exports: {}
+/******/ };
+/******/
+/******/ // Execute the module function
+/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
+/******/
+/******/ // Flag the module as loaded
+/******/ module.l = true;
+/******/
+/******/ // Return the exports of the module
+/******/ return module.exports;
+/******/ }
+/******/
+/******/
+/******/ // expose the modules object (__webpack_modules__)
+/******/ __webpack_require__.m = modules;
+/******/
+/******/ // expose the module cache
+/******/ __webpack_require__.c = installedModules;
+/******/
+/******/ // define getter function for harmony exports
+/******/ __webpack_require__.d = function(exports, name, getter) {
+/******/ if(!__webpack_require__.o(exports, name)) {
+/******/ Object.defineProperty(exports, name, {
+/******/ configurable: false,
+/******/ enumerable: true,
+/******/ get: getter
+/******/ });
+/******/ }
+/******/ };
+/******/
+/******/ // getDefaultExport function for compatibility with non-harmony modules
+/******/ __webpack_require__.n = function(module) {
+/******/ var getter = module && module.__esModule ?
+/******/ function getDefault() { return module['default']; } :
+/******/ function getModuleExports() { return module; };
+/******/ __webpack_require__.d(getter, 'a', getter);
+/******/ return getter;
+/******/ };
+/******/
+/******/ // Object.prototype.hasOwnProperty.call
+/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
+/******/
+/******/ // __webpack_public_path__
+/******/ __webpack_require__.p = "";
+/******/
+/******/ // Load entry module and return exports
+/******/ return __webpack_require__(__webpack_require__.s = 14);
+/******/ })
+/************************************************************************/
+/******/ ([
+/* 0 */
+/***/ (function(module, exports) {
+
+// shim for using process in browser
+var process = module.exports = {};
+
+// cached from whatever global is present so that test runners that stub it
+// don't break things. But we need to wrap it in a try catch in case it is
+// wrapped in strict mode code which doesn't define any globals. It's inside a
+// function because try/catches deoptimize in certain engines.
+
+var cachedSetTimeout;
+var cachedClearTimeout;
+
+function defaultSetTimout() {
+ throw new Error('setTimeout has not been defined');
+}
+function defaultClearTimeout () {
+ throw new Error('clearTimeout has not been defined');
+}
+(function () {
+ try {
+ if (typeof setTimeout === 'function') {
+ cachedSetTimeout = setTimeout;
+ } else {
+ cachedSetTimeout = defaultSetTimout;
+ }
+ } catch (e) {
+ cachedSetTimeout = defaultSetTimout;
+ }
+ try {
+ if (typeof clearTimeout === 'function') {
+ cachedClearTimeout = clearTimeout;
+ } else {
+ cachedClearTimeout = defaultClearTimeout;
+ }
+ } catch (e) {
+ cachedClearTimeout = defaultClearTimeout;
+ }
+} ())
+function runTimeout(fun) {
+ if (cachedSetTimeout === setTimeout) {
+ //normal enviroments in sane situations
+ return setTimeout(fun, 0);
+ }
+ // if setTimeout wasn't available but was latter defined
+ if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) {
+ cachedSetTimeout = setTimeout;
+ return setTimeout(fun, 0);
+ }
+ try {
+ // when when somebody has screwed with setTimeout but no I.E. maddness
+ return cachedSetTimeout(fun, 0);
+ } catch(e){
+ try {
+ // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally
+ return cachedSetTimeout.call(null, fun, 0);
+ } catch(e){
+ // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error
+ return cachedSetTimeout.call(this, fun, 0);
+ }
+ }
+
+
+}
+function runClearTimeout(marker) {
+ if (cachedClearTimeout === clearTimeout) {
+ //normal enviroments in sane situations
+ return clearTimeout(marker);
+ }
+ // if clearTimeout wasn't available but was latter defined
+ if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) {
+ cachedClearTimeout = clearTimeout;
+ return clearTimeout(marker);
+ }
+ try {
+ // when when somebody has screwed with setTimeout but no I.E. maddness
+ return cachedClearTimeout(marker);
+ } catch (e){
+ try {
+ // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally
+ return cachedClearTimeout.call(null, marker);
+ } catch (e){
+ // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error.
+ // Some versions of I.E. have different rules for clearTimeout vs setTimeout
+ return cachedClearTimeout.call(this, marker);
+ }
+ }
+
+
+
+}
+var queue = [];
+var draining = false;
+var currentQueue;
+var queueIndex = -1;
+
+function cleanUpNextTick() {
+ if (!draining || !currentQueue) {
+ return;
+ }
+ draining = false;
+ if (currentQueue.length) {
+ queue = currentQueue.concat(queue);
+ } else {
+ queueIndex = -1;
+ }
+ if (queue.length) {
+ drainQueue();
+ }
+}
+
+function drainQueue() {
+ if (draining) {
+ return;
+ }
+ var timeout = runTimeout(cleanUpNextTick);
+ draining = true;
+
+ var len = queue.length;
+ while(len) {
+ currentQueue = queue;
+ queue = [];
+ while (++queueIndex < len) {
+ if (currentQueue) {
+ currentQueue[queueIndex].run();
+ }
+ }
+ queueIndex = -1;
+ len = queue.length;
+ }
+ currentQueue = null;
+ draining = false;
+ runClearTimeout(timeout);
+}
+
+process.nextTick = function (fun) {
+ var args = new Array(arguments.length - 1);
+ if (arguments.length > 1) {
+ for (var i = 1; i < arguments.length; i++) {
+ args[i - 1] = arguments[i];
+ }
+ }
+ queue.push(new Item(fun, args));
+ if (queue.length === 1 && !draining) {
+ runTimeout(drainQueue);
+ }
+};
+
+// v8 likes predictible objects
+function Item(fun, array) {
+ this.fun = fun;
+ this.array = array;
+}
+Item.prototype.run = function () {
+ this.fun.apply(null, this.array);
+};
+process.title = 'browser';
+process.browser = true;
+process.env = {};
+process.argv = [];
+process.version = ''; // empty string to avoid regexp issues
+process.versions = {};
+
+function noop() {}
+
+process.on = noop;
+process.addListener = noop;
+process.once = noop;
+process.off = noop;
+process.removeListener = noop;
+process.removeAllListeners = noop;
+process.emit = noop;
+process.prependListener = noop;
+process.prependOnceListener = noop;
+
+process.listeners = function (name) { return [] }
+
+process.binding = function (name) {
+ throw new Error('process.binding is not supported');
+};
+
+process.cwd = function () { return '/' };
+process.chdir = function (dir) {
+ throw new Error('process.chdir is not supported');
+};
+process.umask = function() { return 0; };
+
+
+/***/ }),
+/* 1 */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+/* WEBPACK VAR INJECTION */(function(process) {
+
+if (process.env.NODE_ENV === 'production') {
+ module.exports = __webpack_require__(16);
+} else {
+ module.exports = __webpack_require__(17);
+}
+
+/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(0)))
+
+/***/ }),
+/* 2 */
+/***/ (function(module, exports, __webpack_require__) {
+
+var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;/*!
+ Copyright (c) 2016 Jed Watson.
+ Licensed under the MIT License (MIT), see
+ http://jedwatson.github.io/classnames
+*/
+/* global define */
+
+(function () {
+ 'use strict';
+
+ var hasOwn = {}.hasOwnProperty;
+
+ function classNames () {
+ var classes = [];
+
+ for (var i = 0; i < arguments.length; i++) {
+ var arg = arguments[i];
+ if (!arg) continue;
+
+ var argType = typeof arg;
+
+ if (argType === 'string' || argType === 'number') {
+ classes.push(arg);
+ } else if (Array.isArray(arg)) {
+ classes.push(classNames.apply(null, arg));
+ } else if (argType === 'object') {
+ for (var key in arg) {
+ if (hasOwn.call(arg, key) && arg[key]) {
+ classes.push(key);
+ }
+ }
+ }
+ }
+
+ return classes.join(' ');
+ }
+
+ if (typeof module !== 'undefined' && module.exports) {
+ module.exports = classNames;
+ } else if (true) {
+ // register as 'classnames', consistent with npm package name
+ !(__WEBPACK_AMD_DEFINE_ARRAY__ = [], __WEBPACK_AMD_DEFINE_RESULT__ = (function () {
+ return classNames;
+ }).apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__),
+ __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
+ } else {
+ window.classNames = classNames;
+ }
+}());
+
+
+/***/ }),
+/* 3 */
+/***/ (function(module, exports) {
+
+/*
+ MIT License http://www.opensource.org/licenses/mit-license.php
+ Author Tobias Koppers @sokra
+*/
+// css base code, injected by the css-loader
+module.exports = function(useSourceMap) {
+ var list = [];
+
+ // return the list of modules as css string
+ list.toString = function toString() {
+ return this.map(function (item) {
+ var content = cssWithMappingToString(item, useSourceMap);
+ if(item[2]) {
+ return "@media " + item[2] + "{" + content + "}";
+ } else {
+ return content;
+ }
+ }).join("");
+ };
+
+ // import a list of modules into the list
+ list.i = function(modules, mediaQuery) {
+ if(typeof modules === "string")
+ modules = [[null, modules, ""]];
+ var alreadyImportedModules = {};
+ for(var i = 0; i < this.length; i++) {
+ var id = this[i][0];
+ if(typeof id === "number")
+ alreadyImportedModules[id] = true;
+ }
+ for(i = 0; i < modules.length; i++) {
+ var item = modules[i];
+ // skip already imported module
+ // this implementation is not 100% perfect for weird media query combinations
+ // when a module is imported multiple times with different media queries.
+ // I hope this will never occur (Hey this way we have smaller bundles)
+ if(typeof item[0] !== "number" || !alreadyImportedModules[item[0]]) {
+ if(mediaQuery && !item[2]) {
+ item[2] = mediaQuery;
+ } else if(mediaQuery) {
+ item[2] = "(" + item[2] + ") and (" + mediaQuery + ")";
+ }
+ list.push(item);
+ }
+ }
+ };
+ return list;
+};
+
+function cssWithMappingToString(item, useSourceMap) {
+ var content = item[1] || '';
+ var cssMapping = item[3];
+ if (!cssMapping) {
+ return content;
+ }
+
+ if (useSourceMap && typeof btoa === 'function') {
+ var sourceMapping = toComment(cssMapping);
+ var sourceURLs = cssMapping.sources.map(function (source) {
+ return '/*# sourceURL=' + cssMapping.sourceRoot + source + ' */'
+ });
+
+ return [content].concat(sourceURLs).concat([sourceMapping]).join('\n');
+ }
+
+ return [content].join('\n');
+}
+
+// Adapted from convert-source-map (MIT)
+function toComment(sourceMap) {
+ // eslint-disable-next-line no-undef
+ var base64 = btoa(unescape(encodeURIComponent(JSON.stringify(sourceMap))));
+ var data = 'sourceMappingURL=data:application/json;charset=utf-8;base64,' + base64;
+
+ return '/*# ' + data + ' */';
+}
+
+
+/***/ }),
+/* 4 */
+/***/ (function(module, exports, __webpack_require__) {
+
+/*
+ MIT License http://www.opensource.org/licenses/mit-license.php
+ Author Tobias Koppers @sokra
+*/
+
+var stylesInDom = {};
+
+var memoize = function (fn) {
+ var memo;
+
+ return function () {
+ if (typeof memo === "undefined") memo = fn.apply(this, arguments);
+ return memo;
+ };
+};
+
+var isOldIE = memoize(function () {
+ // Test for IE <= 9 as proposed by Browserhacks
+ // @see http://browserhacks.com/#hack-e71d8692f65334173fee715c222cb805
+ // Tests for existence of standard globals is to allow style-loader
+ // to operate correctly into non-standard environments
+ // @see https://github.com/webpack-contrib/style-loader/issues/177
+ return window && document && document.all && !window.atob;
+});
+
+var getElement = (function (fn) {
+ var memo = {};
+
+ return function(selector) {
+ if (typeof memo[selector] === "undefined") {
+ var styleTarget = fn.call(this, selector);
+ // Special case to return head of iframe instead of iframe itself
+ if (styleTarget instanceof window.HTMLIFrameElement) {
+ try {
+ // This will throw an exception if access to iframe is blocked
+ // due to cross-origin restrictions
+ styleTarget = styleTarget.contentDocument.head;
+ } catch(e) {
+ styleTarget = null;
+ }
+ }
+ memo[selector] = styleTarget;
+ }
+ return memo[selector]
+ };
+})(function (target) {
+ return document.querySelector(target)
+});
+
+var singleton = null;
+var singletonCounter = 0;
+var stylesInsertedAtTop = [];
+
+var fixUrls = __webpack_require__(39);
+
+module.exports = function(list, options) {
+ if (typeof DEBUG !== "undefined" && DEBUG) {
+ if (typeof document !== "object") throw new Error("The style-loader cannot be used in a non-browser environment");
+ }
+
+ options = options || {};
+
+ options.attrs = typeof options.attrs === "object" ? options.attrs : {};
+
+ // Force single-tag solution on IE6-9, which has a hard limit on the # of