Full Code of buildo/react-cookie-banner for AI

master 79eb5aca6629 cached
27 files
45.0 KB
12.8k tokens
25 symbols
1 requests
Download .txt
Repository: buildo/react-cookie-banner
Branch: master
Commit: 79eb5aca6629
Files: 27
Total size: 45.0 KB

Directory structure:
gitextract_jyj6cf0v/

├── .gitignore
├── .hophoprc
├── .smooth-releaserc
├── CHANGELOG.md
├── LICENSE
├── README.md
├── ci/
│   ├── pipeline.yml
│   ├── test.sh
│   └── test.yml
├── examples/
│   ├── Examples.md
│   └── examples.scss
├── package.json
├── src/
│   ├── BannerContent.tsx
│   ├── CookieBanner.tsx
│   ├── CookieBannerUniversal.tsx
│   ├── README.md
│   ├── index.ts
│   └── styleUtils.ts
├── styleguide/
│   ├── index.html
│   └── setup.ts
├── styleguide.config.js
├── test/
│   ├── setup.js
│   └── tests/
│       ├── CookieBanner.test.tsx
│       └── __snapshots__/
│           └── CookieBanner.test.tsx.snap
├── tsconfig.json
├── typings/
│   └── react-cookie.d.ts
└── webpack.config.js

================================================
FILE CONTENTS
================================================

================================================
FILE: .gitignore
================================================
node_modules
coverage
npm-debug.log
lib
.vscode

================================================
FILE: .hophoprc
================================================
toggl: n
branchPrefix: n
branchSuffix: y

================================================
FILE: .smooth-releaserc
================================================
{
  "github": {
    "dataType": "pullRequests"
  },
  "tasks": {
    "npm-publish": true,
    "npm-version": true,
    "gh-release": true,
    "changelog": true
  }
}


================================================
FILE: CHANGELOG.md
================================================
#  Change Log



## [v4.1.0](https://github.com/buildo/react-cookie-banner/tree/v4.1.0) (2019-12-11)
[Full Changelog](https://github.com/buildo/react-cookie-banner/compare/v4.0.0...v4.1.0)

#### New features:

- Leverage componentDidUpdate hook instead of componentWillReceiveProps [#67](https://github.com/buildo/react-cookie-banner/pull/67)
- Fixing build after migration to Concourse [#64](https://github.com/buildo/react-cookie-banner/pull/64)
- Migrating from drone to concourse [#63](https://github.com/buildo/react-cookie-banner/pull/63)
- Updated link prop documentation [#57](https://github.com/buildo/react-cookie-banner/pull/57)

## [v4.0.0](https://github.com/buildo/react-cookie-banner/tree/v4.0.0) (2018-05-04)
[Full Changelog](https://github.com/buildo/react-cookie-banner/compare/v3.0.0...v4.0.0)

#### New features:

- Clarify usage of onAccept-callback in documentation [#53](https://github.com/buildo/react-cookie-banner/pull/53)
- #35: support `Link` from react-router-dom (button-close not rendered anymore when using custom children) (closes #35) [#52](https://github.com/buildo/react-cookie-banner/pull/52)
- Add Click To Dismiss [#51](https://github.com/buildo/react-cookie-banner/pull/51)

## [v3.0.0](https://github.com/buildo/react-cookie-banner/tree/v3.0.0) (2017-12-12)
[Full Changelog](https://github.com/buildo/react-cookie-banner/compare/v2.0.0...v3.0.0)

#### Breaking:

- Accessibility improvements: Button elements & a rel attributes [#43](https://github.com/buildo/react-cookie-banner/pull/43)

## [v2.0.0](https://github.com/buildo/react-cookie-banner/tree/v2.0.0) (2017-12-12)
[Full Changelog](https://github.com/buildo/react-cookie-banner/compare/v1.0.1...v2.0.0)

#### New features:

- #41: Server side rendering issues (closes #41) [#42](https://github.com/buildo/react-cookie-banner/pull/42)

## [v1.0.1](https://github.com/buildo/react-cookie-banner/tree/v1.0.1) (2017-12-04)
[Full Changelog](https://github.com/buildo/react-cookie-banner/compare/v1.0.0...v1.0.1)

#### Fixes (bugs & defects):

- #39: import in v1.0.0 is broken (closes #39) [#40](https://github.com/buildo/react-cookie-banner/pull/40)

## [v1.0.0](https://github.com/buildo/react-cookie-banner/tree/v1.0.0) (2017-12-03)
[Full Changelog](https://github.com/buildo/react-cookie-banner/compare/v0.0.18...v1.0.0)

#### Breaking:

- #37: Refactor in TypeScript! (closes #37) [#38](https://github.com/buildo/react-cookie-banner/pull/38)

#### New features:

- Adding import to react-components showroom example [#36](https://github.com/buildo/react-cookie-banner/pull/36)

## [v0.0.18](https://github.com/buildo/react-cookie-banner/tree/v0.0.18) (2017-05-03)
[Full Changelog](https://github.com/buildo/react-cookie-banner/compare/v0.0.17...v0.0.18)

#### New features:

- Add a 'cookiePath' property [#34](https://github.com/buildo/react-cookie-banner/pull/34)
- #29: Template and cookie logic should live in different components (closes #29) [#30](https://github.com/buildo/react-cookie-banner/pull/30)

#### Fixes (bugs & defects):

- #31: React15 throws warning for unknown prop (closes #31) [#32](https://github.com/buildo/react-cookie-banner/pull/32)

## [v0.0.17](https://github.com/buildo/react-cookie-banner/tree/v0.0.17) (2016-10-13)
[Full Changelog](https://github.com/buildo/react-cookie-banner/compare/v0.0.16...v0.0.17)

#### New features:

- #26: Use eslint-config-buildo (closes #26) [#27](https://github.com/buildo/react-cookie-banner/pull/27)
- Custom component can receive onAccept prop using a children function [#25](https://github.com/buildo/react-cookie-banner/pull/25)

## [v0.0.16](https://github.com/buildo/react-cookie-banner/tree/v0.0.16) (2016-10-05)
[Full Changelog](https://github.com/buildo/react-cookie-banner/compare/v0.0.15...v0.0.16)

#### New features:

- #23: Cookie expiration date (closes #23) [#24](https://github.com/buildo/react-cookie-banner/pull/24)
- #21: Renew example (closes #21) [#22](https://github.com/buildo/react-cookie-banner/pull/22)

## [v0.0.15](https://github.com/buildo/react-cookie-banner/tree/v0.0.15) (2016-09-14)
[Full Changelog](https://github.com/buildo/react-cookie-banner/compare/v0.0.14...v0.0.15)

## [v0.0.14](https://github.com/buildo/react-cookie-banner/tree/v0.0.14) (2016-08-10)
[Full Changelog](https://github.com/buildo/react-cookie-banner/compare/v0.0.13...v0.0.14)

## [v0.0.13](https://github.com/buildo/react-cookie-banner/tree/v0.0.13) (2016-08-10)
[Full Changelog](https://github.com/buildo/react-cookie-banner/compare/v0.0.12...v0.0.13)

#### Fixes (bugs & defects):

- Replace `mousewheel` event with `scroll` [#20](https://github.com/buildo/react-cookie-banner/pull/20)

#### New features:

- #16: if dismissOnScroll at false, the click on the close button do not close the banner (closes #16) [#17](https://github.com/buildo/react-cookie-banner/pull/17)

## [v0.0.12](https://github.com/buildo/react-cookie-banner/tree/v0.0.12) (2016-05-31)
[Full Changelog](https://github.com/buildo/react-cookie-banner/compare/v0.0.11...v0.0.12)

#### New features:

- add target to the cookie-link [#14](https://github.com/buildo/react-cookie-banner/pull/14)

## [v0.0.11](https://github.com/buildo/react-cookie-banner/tree/v0.0.11) (2015-12-11)
[Full Changelog](https://github.com/buildo/react-cookie-banner/compare/v0.0.10...v0.0.11)

## [v0.0.10](https://github.com/buildo/react-cookie-banner/tree/v0.0.10) (2015-10-14)
[Full Changelog](https://github.com/buildo/react-cookie-banner/compare/v0.0.9...v0.0.10)

#### New features:

- #9: code clean (closes #9) [#10](https://github.com/buildo/react-cookie-banner/pull/10)
- Allow custom styles [#8](https://github.com/buildo/react-cookie-banner/pull/8)
- #3: Remove .gitkeep from src and tests (closes #3) [#7](https://github.com/buildo/react-cookie-banner/pull/7)

## [v0.0.9](https://github.com/buildo/react-cookie-banner/tree/v0.0.9) (2015-07-14)
[Full Changelog](https://github.com/buildo/react-cookie-banner/compare/v0.0.8...v0.0.9)

#### Fixes (bugs & defects):

- #5: Is not safe for universal rendering [#6](https://github.com/buildo/react-cookie-banner/pull/6)

## [v0.0.8](https://github.com/buildo/react-cookie-banner/tree/v0.0.8) (2015-07-03)
[Full Changelog](https://github.com/buildo/react-cookie-banner/compare/v0.0.7...v0.0.8)

#### New features:

- dismissOnScroll should take an optional Y threshold (default: 0) [#4](https://github.com/buildo/react-cookie-banner/pull/4)

## [v0.0.7](https://github.com/buildo/react-cookie-banner/tree/v0.0.7) (2015-06-30)
[Full Changelog](https://github.com/buildo/react-cookie-banner/compare/v0.0.6...v0.0.7)

## [v0.0.6](https://github.com/buildo/react-cookie-banner/tree/v0.0.6) (2015-06-29)
[Full Changelog](https://github.com/buildo/react-cookie-banner/compare/v0.0.5...v0.0.6)

## [v0.0.5](https://github.com/buildo/react-cookie-banner/tree/v0.0.5) (2015-06-25)
[Full Changelog](https://github.com/buildo/react-cookie-banner/compare/v0.0.4...v0.0.5)

## [v0.0.4](https://github.com/buildo/react-cookie-banner/tree/v0.0.4) (2015-06-19)
[Full Changelog](https://github.com/buildo/react-cookie-banner/compare/v0.0.3...v0.0.4)

## [v0.0.3](https://github.com/buildo/react-cookie-banner/tree/v0.0.3) (2015-06-14)
[Full Changelog](https://github.com/buildo/react-cookie-banner/compare/v0.0.2...v0.0.3)

## [v0.0.2](https://github.com/buildo/react-cookie-banner/tree/v0.0.2) (2015-06-12)
[Full Changelog](https://github.com/buildo/react-cookie-banner/compare/v0.0.1...v0.0.2)

## [v0.0.1](https://github.com/buildo/react-cookie-banner/tree/v0.0.1) (2015-06-12)


================================================
FILE: LICENSE
================================================
The MIT License (MIT)

Copyright (c) 2015 buildo

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.



================================================
FILE: README.md
================================================
[![Build Status](https://drone.our.buildo.io/api/badges/buildo/react-cookie-banner/status.svg)](https://drone.our.buildo.io/buildo/react-cookie-banner) ![](https://img.shields.io/npm/v/react-cookie-banner.svg)

# React Cookie Banner

A cookie banner for React that can be dismissed with a simple scroll. Because [fuck the Cookie Law](http://nocookielaw.com/) that's why.

(If you *really* want to annoy your users you can disable this feature but this is strongly discouraged!).

```jsx
import CookieBanner from 'react-cookie-banner';

React.renderComponent(
  <div>
    <CookieBanner
      message="Yes, we use cookies. If you don't like it change website, we won't miss you!"
      onAccept={() => {}}
      cookie="user-has-accepted-cookies" />
  </div>,
  document.body
);
```

[Live Examples](http://react-components.buildo.io/#cookiebanner)

## Install
```
npm install --save react-cookie-banner
```

or using `yarn`:

```
yarn add react-cookie-banner
```

## API
You can see `CookieBanner`'s props in its own [README.md](https://github.com/buildo/react-cookie-banner/blob/master/src/README.md)

## Style
`react-cookie-banner` comes with a nice default style made using inline-style.

Of course, you can customize it as you like in several ways.

Based on how many changes you want to apply, you can style `react-cookie-banner` as follows:

### You like the original style and you wish to make only a few modifications
Why spending hours on the CSS when you have such a nice default style? :)

In this case you can:

#### 1) Override the predefined inline-styles
In this example we change the message font-size and make the banner slightly transparent with the `styles` prop:

```jsx
<CookieBanner
  styles={{
    banner: { backgroundColor: 'rgba(60, 60, 60, 0.8)' },
    message: { fontWeight: 400 }
  }}
  message='...'
/>
```

See [`src/styleUtils.ts`](https://github.com/buildo/react-cookie-banner/blob/master/src/styleUtils.ts) for a complete list of overridable style objects.

#### 2) Beat it with good old CSS (or SASS)

The banner is structured as follows:

```jsx
<div className={this.props.className + ' react-cookie-banner'}
  <span className='cookie-message'>
    {this.props.message}
    <a className='cookie-link'>
      Learn more
    </a>
  </span>
  <button className='button-close'>
    Got it
  </button>
</div>
```

You can style every part of it using the appropriate `className`:

```sass
.your-class-name.react-cookie-banner {
  background-color: rgba(60, 60, 60, 0.8);

  .cookie-message {
    font-weight: 400;
  }
}
```

### You need to heavily adapt the style to your application
Your creative designer wants to change the style of the cookie banner completely?
Don't worry, we got your covered!

If you need to re-style it, you can:

#### 1) Disable the default style and use your CSS

You may disable the default style by simply setting the prop `disableStyle` to `true`:

```jsx
<CookieBanner disableStyle={true} />
```

Now you can re-style the cookie banner completely using your own CSS.

#### 2) Use your own cookie banner!
Don't like the layout either?
You can use your own custom cookie banner component by passing it as `children` and still let `react-cookie-banner` handle the hassle of managing `cookies` for you :)

```jsx
<CookieBanner>
  {(onAccept) => (
    <MyCustomCookieBanner {...myCustomProps} onAccept={onAccept} /> {/* rendered directly without any <div> wrapper */}
  )}
</CookieBanner>
```

## Cookies manipulation
`react-cookie-banner` uses **`universal-cookie`** to manipulate cookies.

You can import the `Cookies` class and use it as follows:

```js
import { Cookies } from 'react-cookie-banner'

const cookies = new Cookies(/* Your cookie header, on browsers defaults to document.cookie */)

// simple set
cookie.set('test', 'a')
// complex set - cookie(name, value, ttl, path, domain, secure)
cookie.set('test', 'a', {
  expires: new Date(2020-05-04)
  path: '/api',
  domain: '*.example.com',
  secure: true
})
// get
cookies.get('test')
// destroy
cookies.remove('test', '', -1)
```

Please refer to [universal-cookie](https://github.com/reactivestack/cookies/tree/master/packages/universal-cookie#api---cookies-class) repo for more documentation.

## Server side rendering (aka Universal)
`react-cookie-banner` supports SSR thanks to `react-cookie`.
If you want to support SSR, you should use the `CookieProvider` from `react-cookie` and the `CookieBannerUniversal` wrapper:

```jsx
import { Cookies, CookiesProvider, CookieBannerUniversal } from 'react-cookie-banner'

const cookies = new Cookies(/* Your cookie header, on browsers defaults to document.cookie */)

<CookiesProvider cookies={cookies}>
  <CookieBannerUniversal />
</CookiesProvider>
```



================================================
FILE: ci/pipeline.yml
================================================
resource_types:
  - name: pull-request
    type: docker-image
    source:
      repository: teliaoss/github-pr-resource

resources:
  - name: master
    type: git
    icon: github-circle
    source:
      uri: git@github.com:buildo/react-cookie-banner
      branch: master
      private_key: ((private-key))

  - name: pr
    type: pull-request
    source:
      repository: buildo/react-cookie-banner
      access_token: ((github-token))

jobs:
  - name: pr-test
    plan:
      - get: react-cookie-banner
        resource: pr
        trigger: true
        version: every
      - put: pr
        params:
          path: react-cookie-banner
          status: pending
          context: concourse
      - do:
          - task: test
            file: react-cookie-banner/ci/test.yml
            attempts: 2
        on_success:
          put: pr
          params:
            path: react-cookie-banner
            status: success
            context: concourse
        on_failure:
          put: pr
          params:
            path: react-cookie-banner
            status: failure
            context: concourse

  - name: test
    plan:
      - get: react-cookie-banner
        resource: master
        trigger: true
      - do:
          - task: test
            file: react-cookie-banner/ci/test.yml
            attempts: 2


================================================
FILE: ci/test.sh
================================================
#!/bin/sh

set -e

yarn install --no-progress
yarn typecheck
yarn test


================================================
FILE: ci/test.yml
================================================
platform: linux

image_resource:
  type: docker-image
  source:
    repository: node
    tag: 8-slim

inputs:
  - name: react-cookie-banner

caches:
  - path: react-cookie-banner/node_modules

run:
  path: ci/test.sh
  dir: react-cookie-banner


================================================
FILE: examples/Examples.md
================================================
### Examples

```js
initialState = { dismissOnScroll: true, dismissOnClick: false }

// reset cookies on first render
!state.accepted && cookies.get('accepts-cookies') && cookies.remove('accepts-cookies')

const styles = {
  banner: {
    fontFamily: 'Source Sans Pro',
    height: 57,
    background: 'rgba(52, 64, 81, 0.88) url(/cookie.png) 20px 50% no-repeat',
    backgroundSize: '30px 30px',
    backgroundColor: '',
    fontSize: '15px',
    fontWeight: 600
  },
  button: {
    border: '1px solid white',
    borderRadius: 4,
    width: 66,
    height: 32,
    lineHeight: '32px',
    background: 'transparent',
    color: 'white',
    fontSize: '14px',
    fontWeight: 600,
    opacity: 1,
    right: 20,
    marginTop: -18
  },
  message: {
    display: 'block',
    padding: '9px 67px',
    lineHeight: 1.3,
    textAlign: 'left',
    marginRight: 244,
    color: 'white'
  },
  link: {
    textDecoration: 'none',
    fontWeight: 'bold'
  }
}

const message = "Buildo uses cookies to guarantee users the employment of its site features, offering a better purchasing experience. By continuing to browse the site you're agreeing to our use of cookies."

function toggleDismissOnScroll() {
  setState({ dismissOnScroll: !state.dismissOnScroll })
}

function toggleDismissOnClick() {
  setState({ dismissOnClick: !state.dismissOnClick })
}

function resetCookies() {
  cookies.remove('accepts-cookies')
  setState({ accepted: false })
}

<div>
  <p>
    accepts-cookies: {cookies.get('accepts-cookies') || 'false'}
  </p>

  <button onClick={toggleDismissOnScroll}>
    {`${state.dismissOnScroll ? 'Disable' : 'Activate'} dismissOnScroll`}
  </button>

  <button onClick={toggleDismissOnClick} style={{ marginLeft: 20 }}>
    {`${state.dismissOnClick ? 'Disable' : 'Activate'} dismissOnClick`}
  </button>

  <button onClick={resetCookies} style={{ marginLeft: 20 }}>
    Reset Cookies
  </button>

  <CookieBanner
    styles={styles}
    message={message}
    link={<a href='http://nocookielaw.com/'>More information on our use of cookies</a>}
    buttonMessage='Close'
    dismissOnScroll={state.dismissOnScroll}
    dismissOnClick={state.dismissOnClick}
    onAccept={() => setState({ accepted: true })}
  />
</div>
```

#### Server side rendering
You can pass your own `cookies` instance to `CookiesProvider` to support SSR:

```js static
// import { Cookies, CookiesProvider, CookieBannerUniversal } from 'react-cookie-banner';

const cookies = new Cookies(/* Your cookie header, on browsers defaults to document.cookie */);

<CookiesProvider cookies={cookies}>
  <CookieBannerUniversal />
</CookiesProvider>
```


================================================
FILE: examples/examples.scss
================================================
.react-cookie-banner {
  position: fixed !important;
  bottom: 0 !important;
  left: 0 !important;
  width: 100% !important;
  z-index: 999 !important;
  font-family: 'Source Sans Pro'
}


================================================
FILE: package.json
================================================
{
  "name": "react-cookie-banner",
  "version": "4.1.0",
  "description": "React Cookie banner which can be automatically dismissed with a scroll. Because fuck The Cookie Law, that's why.",
  "main": "lib",
  "typings": "lib",
  "files": [
    "lib",
    "src",
    "examples",
    "styleguide",
    "typings"
  ],
  "scripts": {
    "test": "jest",
    "build": "rm -rf lib && mkdir lib && tsc",
    "preversion": "npm run test",
    "prepublish": "npm run build",
    "start": "styleguidist server",
    "typecheck": "tsc --noEmit",
    "release-version": "smooth-release"
  },
  "repository": {
    "type": "git",
    "url": "https://github.com/buildo/react-cookie-banner.git"
  },
  "keywords": [
    "react",
    "react-component",
    "cookie",
    "cookies",
    "banner",
    "eu",
    "law"
  ],
  "author": "Francesco Cioria <francesco@buildo.io>",
  "license": "ISC",
  "bugs": {
    "url": "https://github.com/buildo/react-cookie-banner/issues"
  },
  "homepage": "https://github.com/buildo/react-cookie-banner",
  "dependencies": {
    "classnames": "2.2.5",
    "lodash.omit": "^4.5.0",
    "react-addons-clone-with-props": "^0.14.8",
    "react-cookie": "^2.1.2"
  },
  "devDependencies": {
    "@types/classnames": "^2.2.3",
    "@types/enzyme": "2.8.6",
    "@types/jest": "^22",
    "@types/lodash.omit": "^4.5.3",
    "@types/node": "9.6.4",
    "@types/prop-types": "^15.5.2",
    "@types/react": "^16.3.10",
    "babel-loader": "^7.1.2",
    "babel-preset-buildo": "^0.1.1",
    "css-loader": "^0.28.5",
    "enzyme": "^3.2.0",
    "enzyme-adapter-react-16": "^1.1.0",
    "file-loader": "^1.1.5",
    "jest": "^22",
    "node-sass": "^4.8.3",
    "progress-bar-webpack-plugin": "^1.10.0",
    "raw-loader": "^0.5.1",
    "react": "^16",
    "react-docgen-typescript": "^1.1.0",
    "react-dom": "^16",
    "react-styleguidist": "^6.0.33",
    "react-test-renderer": "^16.2.0",
    "sass-loader": "^6.0.6",
    "smooth-release": "^8.0.4",
    "ts-jest": "^22",
    "ts-loader": "^2.3.3",
    "typescript": "^2.8.1",
    "webpack": "3.5.5"
  },
  "peerDependencies": {
    "react": ">= 0.12.x"
  },
  "jest": {
    "setupFiles": [
      "<rootDir>/test/setup.js"
    ],
    "transform": {
      "^.+\\.tsx?$": "<rootDir>/node_modules/ts-jest/preprocessor.js"
    },
    "testRegex": "(.*[.](test))[.](tsx?)$",
    "moduleFileExtensions": [
      "js",
      "ts",
      "tsx"
    ],
    "testURL": "http://localhost/"
  }
}


================================================
FILE: src/BannerContent.tsx
================================================
import * as React from 'react';
import * as PropTypes from 'prop-types';
import omit = require('lodash.omit');
import * as cx from 'classnames';
import * as styleUtils from './styleUtils';

export type Props = {
  /** message written inside default cookie banner */
  message?: string,
  /** called when user accepts cookies */
  onAccept: () => void,
  /** JSX element to link to your cookie-policy page */
  link?: JSX.Element,
  /** message written inside the button of the default cookie banner */
  buttonMessage?: string,
  /** className passed to close-icon */
  closeIcon?: string,
  /** pass `true` if you want to disable default style */
  disableStyle?: boolean,
  /** object with custom styles used to overwrite default ones */
  styles?: object,
  className?: string,
  /** pass `true` if you want to dismiss by clicking anywhere on the banner */
  dismissOnClick?: boolean
}

export const propTypes = {
  message: PropTypes.string,
  onAccept: PropTypes.func.isRequired,
  link: PropTypes.element,
  buttonMessage: PropTypes.string,
  closeIcon: PropTypes.string,
  disableStyle: PropTypes.bool,
  styles: PropTypes.object,
  className: PropTypes.string,
  dismissOnClick: PropTypes.bool
};


/**
 * React Cookie banner template
 */
export default class BannerContent extends React.Component<Props> {

  static propTypes = propTypes

  getStyle = (style: 'message' | 'banner' | 'link' | 'button' | 'icon') => {
    const { disableStyle, styles = {} } = this.props;
    if (!disableStyle) {
      // apply custom styles if available
      return { ...styleUtils.getStyle(style), ...styles[style] };
    }
  }

  templateCloseIcon = (className: string, onClick: () => void, style: React.CSSProperties ) => (
    <button {...{ onClick, style }}>
      <i {...{ className }} />
    </button>
  )

  templateCloseButton = (buttonMessage: string, onClick: () => void, style: React.CSSProperties) => (
    <button className='button-close' {...{ onClick, style }}>
      {buttonMessage}
    </button>
  )

  templateLink = (link: JSX.Element, style: React.CSSProperties) => (
    React.cloneElement(link, link.props.style ? undefined : { style })
  )

  render() {
    const {
      getStyle,
      props: {
        onAccept, className, message,
        closeIcon, link, buttonMessage = 'Got it',
        ..._wrapperProps
      }
    } = this;

    const cookieMessageStyle = getStyle('message');
    const wrapperProps = {
      ...omit(_wrapperProps, Object.keys(propTypes)),
      className: cx('react-cookie-banner', className),
      style: getStyle('banner')
    };

    return (
      <div {...wrapperProps} onClick={this.bannerClicked}>
        <span className='cookie-message' style={cookieMessageStyle}>
          {message}
          {link && this.templateLink(link, getStyle('link'))}
        </span>
        {!closeIcon && this.templateCloseButton(buttonMessage, onAccept, getStyle('button'))}
        {!!closeIcon && this.templateCloseIcon(closeIcon, onAccept, getStyle('icon'))}
      </div>
    );
  }

  bannerClicked = () => {
    if (this.props.dismissOnClick) {
      this.props.onAccept();
    }
  }

}


================================================
FILE: src/CookieBanner.tsx
================================================
import * as React from 'react';
import * as PropTypes from 'prop-types';
import omit = require('lodash.omit');
import { Cookies } from 'react-cookie';
import BannerContent, { propTypes as BannerContentPropTypes, Props as BannerContentProps } from './BannerContent';

export type CookieBannerRequiredProps = {
  /** custom component rendered if user has not accepted cookies */
  children?: any,
  /** called when user accepts cookies */
  onAccept?: (o: { cookie: string }) => void,
  /** instance of Cookies class to be used in server-side-rendering */
  cookies?: Cookies,
  /** cookie-key used to save user's decision about you cookie-policy */
  cookie?: string,
  /** used to set the cookie expiration */
  cookieExpiration?: number | {
    years?: number,
    days?: number,
    hours?: number
  },
  /** used to set the cookie path */
  cookiePath?: string,
  /** whether the cookie banner should be dismissed on scroll or not */
  dismissOnScroll?: boolean,
  /** amount of pixel the user need to scroll to dismiss the cookie banner */
  dismissOnScrollThreshold?: number
}

export type CookieBannerDefaultProps = {
  onAccept: () => void,
  dismissOnScroll: boolean,
  cookies: Cookies,
  cookie: string,
  cookieExpiration: { years: number },
  buttonMessage: string,
  dismissOnScrollThreshold: number,
  styles: object
}

export type CookieBannerProps = BannerContentProps & CookieBannerRequiredProps & Partial<CookieBannerDefaultProps>;

export namespace CookieBanner {
  export type Props = CookieBannerProps;
}

type CookieBannerDefaultedProps = CookieBannerRequiredProps & CookieBannerDefaultProps;

export type State = {
  listeningScroll: boolean
}

/**
 * React Cookie banner dismissable with just a scroll!
 */
export default class CookieBanner extends React.Component<CookieBanner.Props, State> {

  static propTypes = {
    ...BannerContentPropTypes,
    children: PropTypes.oneOfType([
      PropTypes.node,
      PropTypes.func
    ]),
    onAccept: PropTypes.func,
    cookies: PropTypes.instanceOf(Cookies),
    cookie: PropTypes.string,
    cookieExpiration: PropTypes.oneOfType([
      PropTypes.number,
      PropTypes.shape({
        years: PropTypes.number,
        days: PropTypes.number,
        hours: PropTypes.number
      })
    ]),
    cookiePath: PropTypes.string,
    dismissOnScroll: PropTypes.bool,
    dismissOnScrollThreshold: PropTypes.number
  }

  static defaultProps = {
    onAccept: () => {},
    dismissOnScroll: true,
    cookies: new Cookies(),
    cookie: 'accepts-cookies',
    cookieExpiration: { years: 1 },
    buttonMessage: 'Got it',
    dismissOnScrollThreshold: 0,
    styles: {}
  };

  state = { listeningScroll: false }

  componentDidMount() {
    this.addOnScrollListener();
  }

  addOnScrollListener = (props?: CookieBanner.Props) => {
    const _props = props || this.props;
    if (!this.state.listeningScroll && !this.hasAcceptedCookies() && _props.dismissOnScroll) {
      if ((window as any).attachEvent) {
        // Internet Explorer
        (window as any).attachEvent('onscroll', this.onScroll);
      } else if (window.addEventListener) {
        window.addEventListener('scroll', this.onScroll, false);
      }
      this.setState({ listeningScroll: true });
    }
  }

  removeOnScrollListener = () => {
    if (this.state.listeningScroll) {
      if ((window as any).detachEvent) {
        // Internet Explorer
        (window as any).detachEvent('onscroll', this.onScroll);
      } else if (window.removeEventListener) {
        window.removeEventListener('scroll', this.onScroll, false);
      }
      this.setState({ listeningScroll: false });
    }
  }

  onScroll = () => {
    // tacit agreement buahaha! (evil laugh)
    const { dismissOnScrollThreshold } = this.props as CookieBannerDefaultedProps;
    if (window.pageYOffset > dismissOnScrollThreshold) {
      this.onAccept();
    }
  }

  getSecondsSinceExpiration = (cookieExpiration: CookieBannerRequiredProps['cookieExpiration']) => {
    if (typeof cookieExpiration === 'number') {
      return cookieExpiration;
    }

    const SECONDS_IN_YEAR = 31536000;
    const SECONDS_IN_DAY = 86400;
    const SECONDS_IN_HOUR = 3600;

    const _cookieExpiration = {
      years: 0, days: 0, hours: 0,
      ...cookieExpiration
    };

    const { years, days, hours } = _cookieExpiration;

    return (years * SECONDS_IN_YEAR) + (days * SECONDS_IN_DAY) + (hours * SECONDS_IN_HOUR);
  }

  onAccept = () => {
    const { cookies, cookie, cookieExpiration, cookiePath: path, onAccept } = this.props as CookieBannerDefaultedProps;

    cookies.set(cookie, true, {
      path,
      expires: new Date(Date.now() + (this.getSecondsSinceExpiration(cookieExpiration) * 1000))
    });

    onAccept({ cookie });

    if (this.state.listeningScroll) {
      this.removeOnScrollListener();
    } else {
      this.forceUpdate();
    }
  }

  hasAcceptedCookies() {
    const { cookies, cookie } = this.props as CookieBannerDefaultedProps;
    return cookies.get(cookie);
  }

  templateChildren(children: CookieBanner.Props['children'], onAccept: CookieBannerDefaultProps['onAccept']) {
    if (typeof children === 'function') {
      return children(onAccept);
    }
    return children;
  }

  render() {
    const {
      onAccept,
      props: {
        message, link, buttonMessage, closeIcon,
        disableStyle, styles, className, children, dismissOnClick, ...props
      }
    } = this;

    const hasAcceptedCookies = this.hasAcceptedCookies();
    const bannerContentProps = {
      ...omit(props, Object.keys(CookieBanner.propTypes)),
      message, onAccept, link, buttonMessage,
      closeIcon, disableStyle, styles, className, dismissOnClick,
    };

    if (hasAcceptedCookies) {
      return null;
    }

    return children ?
      this.templateChildren(children, onAccept) :
      <BannerContent {...bannerContentProps} />;
  }

  componentDidUpdate() {
    const { props } = this;

    if (props.dismissOnScroll) {
      this.addOnScrollListener(props);
    } else {
      this.removeOnScrollListener();
    }
  }

  componentWillUnmount() {
    this.removeOnScrollListener();
  }

}


================================================
FILE: src/CookieBannerUniversal.tsx
================================================
import * as React from 'react';
import { withCookies } from 'react-cookie';
import CookieBanner, { CookieBannerProps } from './CookieBanner';

export default withCookies<CookieBannerProps>(CookieBanner) as React.ComponentClass<CookieBannerProps>;


================================================
FILE: src/README.md
================================================
# CookieBanner

React Cookie banner dismissable with just a scroll!

## Props
|Name|Type|Default|Description|
|----|----|-------|-----------|
| **children** | <code>union(ReactChildren &#124; Function)</code> |  | *optional*. Custom component rendered if user has not accepted cookies |
| **message** | <code>String</code> |  | *optional*. Message written inside default cookie banner |
| **onAccept** | <code>Function</code> | <code>"onAccept"</code> | *optional*. Called when user accepts cookies |
| **link** | <code>JSX.Element</code> |  | *optional*. JSX element to link to your cookie-policy page |
| **buttonMessage** | <code>String</code> | <code>"Got it"</code> | *optional*. Message written inside the button of the default cookie banner |
| **cookie** | <code>String</code> | <code>"accepts-cookies"</code> | *optional*. Cookie-key used to save user's decision about you cookie-policy |
| **cookieExpiration** | <code>union(Integer &#124; {years: ?Number, days: ?Number, hours: ?Number})</code> | <code>{   "years": 1 }</code> | *optional*. Used to set the cookie expiration |
| **cookiePath** | <code>String</code> |  | *optional*. Used to set the cookie path |
| **dismissOnScroll** | <code>Boolean</code> | <code>true</code> | *optional*. Whether the cookie banner should be dismissed on scroll or not |
| **dismissOnScrollThreshold** | <code>Number</code> | <code>0</code> | *optional*.   amount of pixel the user need to scroll to dismiss the cookie banner |
| **closeIcon** | <code>String</code> |  | *optional*. ClassName passed to close-icon |
| **disableStyle** | <code>Boolean</code> |  | *optional*. Pass `true` if you want to disable default style |
| **styles** | <code>Object</code> | <code>{}</code> | *optional*. Object with custom styles used to overwrite default ones |
| **className** | <code>String</code> |  | *optional*. Additional `className` for wrapper element |

================================================
FILE: src/index.ts
================================================
import CookieBanner from './CookieBanner';
import CookieBannerUniversal from './CookieBannerUniversal';
import BannerContent from './BannerContent';

export default CookieBanner;
export { Cookies, CookiesProvider } from 'react-cookie';
export { BannerContent, CookieBannerUniversal }


================================================
FILE: src/styleUtils.ts
================================================

const styles = {
  icon: {
    background: 'none',
    border: 'none',
    boxShadow: 'none',
    padding: '0',
    position: 'absolute',
    fontSize: '1em',
    top: '50%',
    marginTop: '-0.5em',
    right: '1em',
    color: 'white',
    cursor: 'pointer'
  },

  link: {
    color: '#F0F0F0',
    textDecoration: 'underline',
    marginLeft: '10px'
  },

  button: {
    position: 'absolute',
    top: '50%',
    right: '35px',
    lineHeight: '24px',
    marginTop: '-12px',
    padding: '0 8px',
    backgroundColor: 'rgba(255, 255, 255, 0.6)',
    border: 'none',
    borderRadius: '3px',
    boxShadow: 'none',
    fontSize: '12px',
    fontWeight: '500',
    color: '#242424',
    cursor: 'pointer'
  },

  message: {
    lineHeight: '45px',
    fontWeight: 500,
    color: '#F0F0F0'
  },

  banner: {
    position: 'relative',
    textAlign: 'center',
    backgroundColor: '#484848',
    width: '100%',
    height: '45px',
    zIndex: '10000'
  }
};

const getStyle = (style: 'message' | 'banner' | 'link' | 'button' | 'icon') => styles[style];

export { getStyle };


================================================
FILE: styleguide/index.html
================================================
<!doctype html>
<html>
	<head>
		<meta charset="utf-8">
		<link href='https://fonts.googleapis.com/css?family=Source+Sans+Pro:300,400,600,700' rel='stylesheet' type='text/css'>
    <link rel="stylesheet" href="https://i.icomoon.io/public/5ba04e2a5e/Showroom/style.css">
		<meta name="viewport" content="width=device-width, initial-scale=1.0">
	</head>
	<body>
		<div id="app"></div>
	</body>
</html>


================================================
FILE: styleguide/setup.ts
================================================
import { Cookies, CookiesProvider } from 'react-cookie';
import { CookieBannerUniversal } from '../src';

import '../examples/examples.scss';
import '../examples/cookie.png';

(global as any).cookies = new Cookies();
(global as any).CookiesProvider = CookiesProvider;
(global as any).Cookies = Cookies;
(global as any).CookieBannerUniversal = CookieBannerUniversal;


================================================
FILE: styleguide.config.js
================================================
const path = require('path');

module.exports = {
  // build
  serverPort: 8080,

  require: [
    // "global" setup + sass imports
    path.resolve(__dirname, 'styleguide/setup.ts')
  ],

  // content
  title: 'react-cookie-banner',
  // assetsDir: 'styleguide/assets',
  template: 'styleguide/index.html',
  propsParser: require('react-docgen-typescript').parse, // detect docs using TS information
  sections: [{
    name: 'CookieBanner',
    components: () => [path.resolve(__dirname, 'src/CookieBanner.tsx')]
  }],
  showCode: true,
  showUsage: false, // show props by default
  getExampleFilename() {
    return path.resolve(__dirname, 'examples/Examples.md');
  }
};


================================================
FILE: test/setup.js
================================================
global.requestAnimationFrame = (callback) => {
  setTimeout(callback, 0);
};

const Enzyme = require('enzyme');
const Adapter = require('enzyme-adapter-react-16');

Enzyme.configure({ adapter: new Adapter() });


================================================
FILE: test/tests/CookieBanner.test.tsx
================================================
import { execSync } from 'child_process';
import * as fs from 'fs';
import * as path from 'path';
import * as React from 'react';
import { shallow, mount } from 'enzyme';

import CookieBanner from '../../src';
import { getStyle } from '../../src/styleUtils';

function resetCookies() {
  const cookies = document.cookie.split(';');

  cookies.forEach(cookie => {
    const eqPos = cookie.indexOf('=');
    const name = eqPos > -1 ? cookie.substr(0, eqPos) : cookie;
    document.cookie = `${name}=;expires=Thu, 01 Jan 1970 00:00:00 GMT`;
  });
};

beforeEach(resetCookies);

describe('secondsSinceExpiration', () => {
  const { getSecondsSinceExpiration } = new CookieBanner({ onAccept: () => {} });

  it('should return "cookieExpiration" if it is an integer', () => {
    expect(getSecondsSinceExpiration(12345)).toBe(12345);
  });

  it('should transform "years", "days" and "hours" into seconds', () => {
    expect(getSecondsSinceExpiration({ years: 1, days: 10, hours: 5 })).toBe(32418000);
  });

  it('should handle missing "years", "days" or "hours"', () => {
    expect(getSecondsSinceExpiration({ days: 10 })).toBe(864000);
    expect(getSecondsSinceExpiration({})).toBe(0);
  });

});

describe('CookieBanner', () => {

  it('should be displayed if no cookies are set', () => {
    const component = shallow(
      <CookieBanner message='cookie message' onAccept={() => {}} />
    );
    expect(component).toMatchSnapshot();
  });

  it('should be displayed with correct default styles', () => {
    const component = mount(
      <CookieBanner message='cookie message' link={<a />} onAccept={() => {}} />
    );

    expect(component.find('.cookie-message').prop('style')).toEqual(getStyle('message'));
    expect(component.find('.button-close').prop('style')).toEqual(getStyle('button'));
    expect(component.find('a').prop('style')).toEqual(getStyle('link'));

    const componentWithIcon = mount(
      <CookieBanner closeIcon='icon' onAccept={() => {}} />
    );

    expect(componentWithIcon.find('.icon').length).toBe(1);
    expect(componentWithIcon.find('button').prop('style')).toEqual(getStyle('icon'));
  });

  it('should hide on click', () => {
    const component = mount(
      <CookieBanner message='cookie message' onAccept={() => {}} />
    );

    expect(component.find('.react-cookie-banner')).toHaveLength(1);
    component.find('.button-close').simulate('click');
    expect(component.find('.react-cookie-banner')).toHaveLength(0);
  });

  it('should hide on click when dismissOnScroll is false', () => {
    const component = mount(
      <CookieBanner message='cookie message' onAccept={() => {}} dismissOnScroll={false} />
    );

    expect(component.find('.react-cookie-banner')).toHaveLength(1);
    component.find('.button-close').simulate('click');
    expect(component.find('.react-cookie-banner')).toHaveLength(0);
  });

  it('should be displayed with correct message', () => {
    const component = mount(
      <CookieBanner message='cookie message' onAccept={() => {}} />
    );

    expect(component.find('.cookie-message').text()).toBe('cookie message');
  });

  it('should be displayed with correct link element', () => {
    const children = 'children!'
    const component = mount(
      <CookieBanner link={<a className='cookie-link'>{children}</a>} onAccept={() => {}} />
    );

    const cookieBanner = component.find('.cookie-link');
    expect(cookieBanner.text()).toBe(children);
  });

  it('should not overwrite link\'s style props, if present', () => {
    const style = { color: 'red' }
    const component = mount(
      <CookieBanner link={<a style={style} className='cookie-link' />} onAccept={() => {}} />
    );

    const cookieBanner = component.find('.cookie-link');
    expect(cookieBanner.prop('style')).toEqual(style);
  });

  it('should be displayed with correct link element', () => {
    const children = 'children!'
    const component = mount(
      <CookieBanner link={<a className='cookie-link'>{children}</a>} onAccept={() => {}} />
    );

    expect(component.find('.cookie-link').text()).toBe(children);
  });

  it('should be replaced with custom child component', () => {
    const MyComponent = () => (
      <div className='my-component' />
    );

    const component = mount(
      <CookieBanner message='cookie message' onAccept={() => {}}>
        <MyComponent />
      </CookieBanner>
    );

    expect(component.find('.my-component')).toHaveLength(1);
  });

  it('should be replaced with custom child component using function', () => {
    const MyOtherComponent = ({ onAccept }) => (
      <div className='my-other-component' onClick={onAccept} />
    );

    const customTrigger = onAccept => <MyOtherComponent onAccept={onAccept} />;

    const component = mount(
      <CookieBanner onAccept={() => {}}>
        {customTrigger}
      </CookieBanner>
    );

    expect(component.find('.my-other-component')).toHaveLength(1);
  });

});

describe('build', () => {

  it('build script generates every needed file', () => {
    execSync('npm run build')
    expect(fs.readdirSync(path.resolve(__dirname, '../../lib'))).toMatchSnapshot()
  })

})


================================================
FILE: test/tests/__snapshots__/CookieBanner.test.tsx.snap
================================================
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`CookieBanner should be displayed if no cookies are set 1`] = `
ShallowWrapper {
  Symbol(enzyme.__root__): [Circular],
  Symbol(enzyme.__unrendered__): <CookieBanner
    buttonMessage="Got it"
    cookie="accepts-cookies"
    cookieExpiration={
      Object {
        "years": 1,
      }
    }
    cookies={
      Cookies {
        "HAS_DOCUMENT_COOKIE": true,
        "changeListeners": Array [],
        "cookies": Object {},
        "hooks": undefined,
      }
    }
    dismissOnScroll={true}
    dismissOnScrollThreshold={0}
    message="cookie message"
    onAccept={[Function]}
    styles={Object {}}
  />,
  Symbol(enzyme.__renderer__): Object {
    "batchedUpdates": [Function],
    "checkPropTypes": [Function],
    "getNode": [Function],
    "render": [Function],
    "simulateError": [Function],
    "simulateEvent": [Function],
    "unmount": [Function],
  },
  Symbol(enzyme.__node__): Object {
    "instance": null,
    "key": undefined,
    "nodeType": "class",
    "props": Object {
      "buttonMessage": "Got it",
      "className": undefined,
      "closeIcon": undefined,
      "disableStyle": undefined,
      "dismissOnClick": undefined,
      "link": undefined,
      "message": "cookie message",
      "onAccept": [Function],
      "styles": Object {},
    },
    "ref": null,
    "rendered": null,
    "type": [Function],
  },
  Symbol(enzyme.__nodes__): Array [
    Object {
      "instance": null,
      "key": undefined,
      "nodeType": "class",
      "props": Object {
        "buttonMessage": "Got it",
        "className": undefined,
        "closeIcon": undefined,
        "disableStyle": undefined,
        "dismissOnClick": undefined,
        "link": undefined,
        "message": "cookie message",
        "onAccept": [Function],
        "styles": Object {},
      },
      "ref": null,
      "rendered": null,
      "type": [Function],
    },
  ],
  Symbol(enzyme.__options__): Object {
    "adapter": ReactSixteenAdapter {
      "options": Object {
        "enableComponentDidUpdateOnSetState": true,
        "legacyContextMode": "parent",
        "lifecycles": Object {
          "componentDidUpdate": Object {
            "onSetState": true,
          },
          "getChildContext": Object {
            "calledByRenderer": false,
          },
          "getDerivedStateFromError": true,
          "getDerivedStateFromProps": Object {
            "hasShouldComponentUpdateBug": false,
          },
          "getSnapshotBeforeUpdate": true,
          "setState": Object {
            "skipsComponentDidUpdateOnNullish": true,
          },
        },
      },
    },
    Symbol(enzyme.__providerValues__): undefined,
  },
  Symbol(enzyme.__providerValues__): Map {},
  Symbol(enzyme.__childContext__): null,
}
`;

exports[`build build script generates every needed file 1`] = `
Array [
  "BannerContent.d.ts",
  "BannerContent.js",
  "CookieBanner.d.ts",
  "CookieBanner.js",
  "CookieBannerUniversal.d.ts",
  "CookieBannerUniversal.js",
  "index.d.ts",
  "index.js",
  "styleUtils.d.ts",
  "styleUtils.js",
]
`;


================================================
FILE: tsconfig.json
================================================
{
  "compilerOptions": {
    "target": "ES3",
    "module": "commonjs",
    "declaration": true,
    "allowSyntheticDefaultImports": false,
    "allowJs": false,
    "experimentalDecorators": true,
    "outDir": "./lib",
    "baseUrl": ".",
    "noImplicitAny": true,
    "suppressImplicitAnyIndexErrors": true,
    "noUnusedLocals": true,
    "noUnusedParameters": true,
    "strictNullChecks": true,
    "sourceMap": false,
    "alwaysStrict": true,
    "jsx": "react",
    "lib": [
      "dom", "es6"
    ]
  },
  "include": [
    "src/*",
    "typings"
  ]
}


================================================
FILE: typings/react-cookie.d.ts
================================================
// react-cookies typings are in WIP... copied the following from https://github.com/reactivestack/cookies/issues/107

declare module 'react-cookie' {
  import { Component, ComponentClass } from 'react';

  export type Cookie = string;

  export class CookiesProvider extends Component<{},{}>{}

  export function withCookies<T>(Component: ComponentClass): ComponentClass<T>;

  export interface ReactCookieGetOptions{
    doNotParse?: boolean;
  }

  export interface ReactCookieGetAllOptions{
    doNotParse?: boolean;
  }

  export interface ReactCookieSetOptions{
    path?: string;
    expires?: Date;
    maxAge?: number;
    domain?: string;
    secure?: boolean;
    httpOnly?: boolean;
  }

  export interface ReactCookieRemoveOptions{
    path?: string;
    expires?: Date;
    maxAge?: number;
    domain?: string;
    secure?: boolean;
    httpOnly?: boolean;
  }

  export class Cookies {
    get: (key: string, options?: ReactCookieGetOptions) => Cookie | undefined;
    getAll: (options?: ReactCookieGetAllOptions) => Cookie[];
    set(name: string, value: any, options?: ReactCookieSetOptions): void;
    remove(name: string, options?: ReactCookieRemoveOptions): void;
  }
}


================================================
FILE: webpack.config.js
================================================
const path = require('path');
const ProgressBarPlugin = require('progress-bar-webpack-plugin');

module.exports = {
  resolve: {
    extensions: ['.js', '.jsx', '.ts', '.tsx', '.json']
  },
  plugins: [
    new ProgressBarPlugin()
  ],
  module: {
    rules: [
      {
        test: /\.[jt]sx?$/,
        include: [
          path.resolve(__dirname, 'src'),
          path.resolve(__dirname, 'styleguide')
        ],
        use: [
          {
            loader: 'babel-loader',
            options: {
              presets: [['buildo', { env: 'react' }]]
            }
          },
          {
            loader: 'ts-loader',
            options: {
              configFile: require('path').resolve(__dirname, 'tsconfig.json')
            }
          }
        ]
      },
      {
        test: /\.css$/,
        loader: [
          'style-loader',
          { loader: 'css-loader', options: { modules: true } }
        ]
      },
      {
        test: /\.scss$/,
        use: ['style-loader', 'css-loader', 'sass-loader']
      },
      {
        test: /\.(png|jpg|gif)$/,
        loader: 'file-loader',
        options: {
          name: '[name].[ext]'
        }
      }
    ]
  }
};
Download .txt
gitextract_jyj6cf0v/

├── .gitignore
├── .hophoprc
├── .smooth-releaserc
├── CHANGELOG.md
├── LICENSE
├── README.md
├── ci/
│   ├── pipeline.yml
│   ├── test.sh
│   └── test.yml
├── examples/
│   ├── Examples.md
│   └── examples.scss
├── package.json
├── src/
│   ├── BannerContent.tsx
│   ├── CookieBanner.tsx
│   ├── CookieBannerUniversal.tsx
│   ├── README.md
│   ├── index.ts
│   └── styleUtils.ts
├── styleguide/
│   ├── index.html
│   └── setup.ts
├── styleguide.config.js
├── test/
│   ├── setup.js
│   └── tests/
│       ├── CookieBanner.test.tsx
│       └── __snapshots__/
│           └── CookieBanner.test.tsx.snap
├── tsconfig.json
├── typings/
│   └── react-cookie.d.ts
└── webpack.config.js
Download .txt
SYMBOL INDEX (25 symbols across 5 files)

FILE: src/BannerContent.tsx
  type Props (line 7) | type Props = {
  class BannerContent (line 43) | class BannerContent extends React.Component<Props> {
    method render (line 71) | render() {

FILE: src/CookieBanner.tsx
  type CookieBannerRequiredProps (line 7) | type CookieBannerRequiredProps = {
  type CookieBannerDefaultProps (line 30) | type CookieBannerDefaultProps = {
  type CookieBannerProps (line 41) | type CookieBannerProps = BannerContentProps & CookieBannerRequiredProps ...
  type Props (line 44) | type Props = CookieBannerProps;
  type CookieBannerDefaultedProps (line 47) | type CookieBannerDefaultedProps = CookieBannerRequiredProps & CookieBann...
  type State (line 49) | type State = {
  class CookieBanner (line 56) | class CookieBanner extends React.Component<CookieBanner.Props, State> {
    method componentDidMount (line 93) | componentDidMount() {
    method hasAcceptedCookies (line 166) | hasAcceptedCookies() {
    method templateChildren (line 171) | templateChildren(children: CookieBanner.Props['children'], onAccept: C...
    method render (line 178) | render() {
    method componentDidUpdate (line 203) | componentDidUpdate() {
    method componentWillUnmount (line 213) | componentWillUnmount() {

FILE: styleguide.config.js
  method getExampleFilename (line 23) | getExampleFilename() {

FILE: test/tests/CookieBanner.test.tsx
  function resetCookies (line 10) | function resetCookies() {

FILE: typings/react-cookie.d.ts
  type Cookie (line 6) | type Cookie = string;
  class CookiesProvider (line 8) | class CookiesProvider extends Component<{},{}>{}
  type ReactCookieGetOptions (line 12) | interface ReactCookieGetOptions{
  type ReactCookieGetAllOptions (line 16) | interface ReactCookieGetAllOptions{
  type ReactCookieSetOptions (line 20) | interface ReactCookieSetOptions{
  type ReactCookieRemoveOptions (line 29) | interface ReactCookieRemoveOptions{
  class Cookies (line 38) | class Cookies {
Condensed preview — 27 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (49K chars).
[
  {
    "path": ".gitignore",
    "chars": 47,
    "preview": "node_modules\ncoverage\nnpm-debug.log\nlib\n.vscode"
  },
  {
    "path": ".hophoprc",
    "chars": 40,
    "preview": "toggl: n\nbranchPrefix: n\nbranchSuffix: y"
  },
  {
    "path": ".smooth-releaserc",
    "chars": 167,
    "preview": "{\n  \"github\": {\n    \"dataType\": \"pullRequests\"\n  },\n  \"tasks\": {\n    \"npm-publish\": true,\n    \"npm-version\": true,\n    \""
  },
  {
    "path": "CHANGELOG.md",
    "chars": 7541,
    "preview": "#  Change Log\n\n\n\n## [v4.1.0](https://github.com/buildo/react-cookie-banner/tree/v4.1.0) (2019-12-11)\n[Full Changelog](ht"
  },
  {
    "path": "LICENSE",
    "chars": 1074,
    "preview": "The MIT License (MIT)\n\nCopyright (c) 2015 buildo\n\nPermission is hereby granted, free of charge, to any person obtaining "
  },
  {
    "path": "README.md",
    "chars": 4722,
    "preview": "[![Build Status](https://drone.our.buildo.io/api/badges/buildo/react-cookie-banner/status.svg)](https://drone.our.buildo"
  },
  {
    "path": "ci/pipeline.yml",
    "chars": 1326,
    "preview": "resource_types:\n  - name: pull-request\n    type: docker-image\n    source:\n      repository: teliaoss/github-pr-resource\n"
  },
  {
    "path": "ci/test.sh",
    "chars": 71,
    "preview": "#!/bin/sh\n\nset -e\n\nyarn install --no-progress\nyarn typecheck\nyarn test\n"
  },
  {
    "path": "ci/test.yml",
    "chars": 244,
    "preview": "platform: linux\n\nimage_resource:\n  type: docker-image\n  source:\n    repository: node\n    tag: 8-slim\n\ninputs:\n  - name: "
  },
  {
    "path": "examples/Examples.md",
    "chars": 2625,
    "preview": "### Examples\n\n```js\ninitialState = { dismissOnScroll: true, dismissOnClick: false }\n\n// reset cookies on first render\n!s"
  },
  {
    "path": "examples/examples.scss",
    "chars": 187,
    "preview": ".react-cookie-banner {\n  position: fixed !important;\n  bottom: 0 !important;\n  left: 0 !important;\n  width: 100% !import"
  },
  {
    "path": "package.json",
    "chars": 2444,
    "preview": "{\n  \"name\": \"react-cookie-banner\",\n  \"version\": \"4.1.0\",\n  \"description\": \"React Cookie banner which can be automaticall"
  },
  {
    "path": "src/BannerContent.tsx",
    "chars": 3129,
    "preview": "import * as React from 'react';\nimport * as PropTypes from 'prop-types';\nimport omit = require('lodash.omit');\nimport * "
  },
  {
    "path": "src/CookieBanner.tsx",
    "chars": 6136,
    "preview": "import * as React from 'react';\nimport * as PropTypes from 'prop-types';\nimport omit = require('lodash.omit');\nimport { "
  },
  {
    "path": "src/CookieBannerUniversal.tsx",
    "chars": 247,
    "preview": "import * as React from 'react';\nimport { withCookies } from 'react-cookie';\nimport CookieBanner, { CookieBannerProps } f"
  },
  {
    "path": "src/README.md",
    "chars": 1898,
    "preview": "# CookieBanner\n\nReact Cookie banner dismissable with just a scroll!\n\n## Props\n|Name|Type|Default|Description|\n|----|----"
  },
  {
    "path": "src/index.ts",
    "chars": 284,
    "preview": "import CookieBanner from './CookieBanner';\nimport CookieBannerUniversal from './CookieBannerUniversal';\nimport BannerCon"
  },
  {
    "path": "src/styleUtils.ts",
    "chars": 1079,
    "preview": "\nconst styles = {\n  icon: {\n    background: 'none',\n    border: 'none',\n    boxShadow: 'none',\n    padding: '0',\n    pos"
  },
  {
    "path": "styleguide/index.html",
    "chars": 400,
    "preview": "<!doctype html>\n<html>\n\t<head>\n\t\t<meta charset=\"utf-8\">\n\t\t<link href='https://fonts.googleapis.com/css?family=Source+San"
  },
  {
    "path": "styleguide/setup.ts",
    "chars": 366,
    "preview": "import { Cookies, CookiesProvider } from 'react-cookie';\nimport { CookieBannerUniversal } from '../src';\n\nimport '../exa"
  },
  {
    "path": "styleguide.config.js",
    "chars": 675,
    "preview": "const path = require('path');\n\nmodule.exports = {\n  // build\n  serverPort: 8080,\n\n  require: [\n    // \"global\" setup + s"
  },
  {
    "path": "test/setup.js",
    "chars": 211,
    "preview": "global.requestAnimationFrame = (callback) => {\n  setTimeout(callback, 0);\n};\n\nconst Enzyme = require('enzyme');\nconst Ad"
  },
  {
    "path": "test/tests/CookieBanner.test.tsx",
    "chars": 5150,
    "preview": "import { execSync } from 'child_process';\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport * as React from"
  },
  {
    "path": "test/tests/__snapshots__/CookieBanner.test.tsx.snap",
    "chars": 3108,
    "preview": "// Jest Snapshot v1, https://goo.gl/fbAQLP\n\nexports[`CookieBanner should be displayed if no cookies are set 1`] = `\nShal"
  },
  {
    "path": "tsconfig.json",
    "chars": 563,
    "preview": "{\n  \"compilerOptions\": {\n    \"target\": \"ES3\",\n    \"module\": \"commonjs\",\n    \"declaration\": true,\n    \"allowSyntheticDefa"
  },
  {
    "path": "typings/react-cookie.d.ts",
    "chars": 1190,
    "preview": "// react-cookies typings are in WIP... copied the following from https://github.com/reactivestack/cookies/issues/107\n\nde"
  },
  {
    "path": "webpack.config.js",
    "chars": 1188,
    "preview": "const path = require('path');\nconst ProgressBarPlugin = require('progress-bar-webpack-plugin');\n\nmodule.exports = {\n  re"
  }
]

About this extraction

This page contains the full source code of the buildo/react-cookie-banner GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 27 files (45.0 KB), approximately 12.8k tokens, and a symbol index with 25 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!