mirror of
				https://github.com/Mastermindzh/react-cookie-consent.git
				synced 2025-10-31 08:49:04 +01:00 
			
		
		
		
	Compare commits
	
		
			27 Commits
		
	
	
		
			7.3.1
			...
			7f5989a539
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 7f5989a539 | |||
| 123affe057 | |||
|  | c14e8274ad | ||
|  | 4a1ac1ed8f | ||
|  | 823cfb143f | ||
| a9612771f2 | |||
| 42184054c5 | |||
| 6a122704ac | |||
| 582a18bb4d | |||
| f83c3a7227 | |||
| 2a1973c008 | |||
| 38deb77dfd | |||
| a2fd789751 | |||
| 78411dcf57 | |||
| c544f19c41 | |||
| c6799ea446 | |||
| d7fce12ea4 | |||
|  | d05509bf04 | ||
|  | a7ce2de923 | ||
| d8993bead2 | |||
| ecb5f30a7c | |||
|  | d1c7252546 | ||
| 602a9bfe62 | |||
| c9a6e1f0ce | |||
|  | fefe28e288 | ||
|  | d63cb81fb7 | ||
| e96b4fe4c0 | 
							
								
								
									
										8
									
								
								.babelrc
									
									
									
									
									
								
							
							
						
						
									
										8
									
								
								.babelrc
									
									
									
									
									
								
							| @@ -1,8 +0,0 @@ | |||||||
| { |  | ||||||
|     "presets": ["@babel/preset-env"], |  | ||||||
|     "plugins": [ |  | ||||||
|       "@babel/plugin-proposal-object-rest-spread", |  | ||||||
|       "@babel/plugin-transform-react-jsx", |  | ||||||
|       "@babel/plugin-transform-object-assign" |  | ||||||
|     ] |  | ||||||
|   } |  | ||||||
							
								
								
									
										68
									
								
								.eslintrc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										68
									
								
								.eslintrc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,68 @@ | |||||||
|  | { | ||||||
|  |   "env": { | ||||||
|  |     "browser": true, | ||||||
|  |     "jest": true, | ||||||
|  |     "es6": true | ||||||
|  |   }, | ||||||
|  |   "plugins": ["import"], | ||||||
|  |   "extends": [ | ||||||
|  |     "react-app", | ||||||
|  |     "prettier/@typescript-eslint", | ||||||
|  |     "plugin:prettier/recommended", | ||||||
|  |     "eslint:recommended", | ||||||
|  |     "prettier" | ||||||
|  |   ], | ||||||
|  |   "parserOptions": { | ||||||
|  |     "ecmaVersion": 2020, | ||||||
|  |     "sourceType": "module" | ||||||
|  |   }, | ||||||
|  |   "rules": { | ||||||
|  |     "react/react-in-jsx-scope": "off", | ||||||
|  |     "no-console": [ | ||||||
|  |       "error", | ||||||
|  |       { | ||||||
|  |         "allow": ["debug", "error"] | ||||||
|  |       } | ||||||
|  |     ], | ||||||
|  |     "no-eval": "error", | ||||||
|  |     "import/first": "error", | ||||||
|  |     "camelcase": [ | ||||||
|  |       "error", | ||||||
|  |       { | ||||||
|  |         "ignoreImports": true, | ||||||
|  |         "ignoreDestructuring": true | ||||||
|  |       } | ||||||
|  |     ], | ||||||
|  |     "consistent-return": "warn", | ||||||
|  |     "constructor-super": "error", | ||||||
|  |     "curly": "error", | ||||||
|  |     "eol-last": "warn", | ||||||
|  |     "eqeqeq": ["error", "smart"], | ||||||
|  |     "import/order": 1, | ||||||
|  |     "new-parens": "error", | ||||||
|  |     "no-debugger": "error", | ||||||
|  |     "no-fallthrough": "off", | ||||||
|  |     "max-len": [ | ||||||
|  |       "warn", | ||||||
|  |       { | ||||||
|  |         "code": 120 | ||||||
|  |       } | ||||||
|  |     ], | ||||||
|  |     "no-shadow": [ | ||||||
|  |       "error", | ||||||
|  |       { | ||||||
|  |         "hoist": "all" | ||||||
|  |       } | ||||||
|  |     ], | ||||||
|  |     "no-trailing-spaces": "warn", | ||||||
|  |     "no-underscore-dangle": "error", | ||||||
|  |     "no-unsafe-finally": "error", | ||||||
|  |     "no-var": "error", | ||||||
|  |     "object-shorthand": "error", | ||||||
|  |     "one-var": ["error", "never"], | ||||||
|  |     "prefer-arrow/prefer-arrow-functions": "off", | ||||||
|  |     "prefer-const": "error", | ||||||
|  |     "radix": "off", | ||||||
|  |     "space-in-parens": ["off", "never"] | ||||||
|  |   } | ||||||
|  | } | ||||||
							
								
								
									
										17
									
								
								.github/stale.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								.github/stale.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,17 @@ | |||||||
|  | # Number of days of inactivity before an issue becomes stale | ||||||
|  | daysUntilStale: 30 | ||||||
|  | # Number of days of inactivity before a stale issue is closed | ||||||
|  | daysUntilClose: 7 | ||||||
|  | # Issues with these labels will never be considered stale | ||||||
|  | exemptLabels: | ||||||
|  |   - pinned | ||||||
|  |   - security | ||||||
|  | # Label to use when marking an issue as stale | ||||||
|  | staleLabel: wontfix | ||||||
|  | # Comment to post when marking an issue as stale. Set to `false` to disable | ||||||
|  | markComment: > | ||||||
|  |   This issue has been automatically marked as stale because it has not had | ||||||
|  |   recent activity. It will be closed if no further activity occurs. Thank you | ||||||
|  |   for your contributions. | ||||||
|  | # Comment to post when closing a stale issue. Set to `false` to disable | ||||||
|  | closeComment: false | ||||||
							
								
								
									
										20
									
								
								.github/workflows/gh-pages.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								.github/workflows/gh-pages.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,20 @@ | |||||||
|  | name: Build and Deploy storybook | ||||||
|  | on: [push] | ||||||
|  | permissions: | ||||||
|  |   contents: write | ||||||
|  | jobs: | ||||||
|  |   build-and-deploy: | ||||||
|  |     runs-on: ubuntu-latest | ||||||
|  |     steps: | ||||||
|  |       - name: Checkout 🛎️ | ||||||
|  |         uses: actions/checkout@v3 | ||||||
|  |  | ||||||
|  |       - name: Install and Build 🔧 | ||||||
|  |         run: | | ||||||
|  |           npm install | ||||||
|  |           npm run build-storybook | ||||||
|  |  | ||||||
|  |       - name: Deploy 🚀 | ||||||
|  |         uses: JamesIves/github-pages-deploy-action@v4 | ||||||
|  |         with: | ||||||
|  |           folder: storybook-static | ||||||
							
								
								
									
										32
									
								
								.github/workflows/main.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								.github/workflows/main.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,32 @@ | |||||||
|  | name: CI | ||||||
|  | on: [push] | ||||||
|  | jobs: | ||||||
|  |   build: | ||||||
|  |     name: Build, lint, and test on Node ${{ matrix.node }} and ${{ matrix.os }} | ||||||
|  |  | ||||||
|  |     runs-on: ${{ matrix.os }} | ||||||
|  |     strategy: | ||||||
|  |       matrix: | ||||||
|  |         node: ["10.x", "12.x", "14.x"] | ||||||
|  |         os: [ubuntu-latest, macOS-latest] | ||||||
|  |  | ||||||
|  |     steps: | ||||||
|  |       - name: Checkout repo | ||||||
|  |         uses: actions/checkout@v2 | ||||||
|  |  | ||||||
|  |       - name: Use Node ${{ matrix.node }} | ||||||
|  |         uses: actions/setup-node@v1 | ||||||
|  |         with: | ||||||
|  |           node-version: ${{ matrix.node }} | ||||||
|  |  | ||||||
|  |       - name: Install deps and build (with cache) | ||||||
|  |         uses: bahmutov/npm-install@v1 | ||||||
|  |  | ||||||
|  |       - name: Lint | ||||||
|  |         run: yarn lint | ||||||
|  |  | ||||||
|  |       - name: Test | ||||||
|  |         run: yarn test --ci --coverage --maxWorkers=2 | ||||||
|  |  | ||||||
|  |       - name: Build | ||||||
|  |         run: yarn build | ||||||
							
								
								
									
										12
									
								
								.github/workflows/size.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								.github/workflows/size.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,12 @@ | |||||||
|  | name: size | ||||||
|  | on: [pull_request] | ||||||
|  | jobs: | ||||||
|  |   size: | ||||||
|  |     runs-on: ubuntu-latest | ||||||
|  |     env: | ||||||
|  |       CI_JOB_NUMBER: 1 | ||||||
|  |     steps: | ||||||
|  |       - uses: actions/checkout@v1 | ||||||
|  |       - uses: andresz1/size-limit-action@v1 | ||||||
|  |         with: | ||||||
|  |           github_token: ${{ secrets.GITHUB_TOKEN }} | ||||||
							
								
								
									
										7
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										7
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| @@ -1,3 +1,6 @@ | |||||||
|  | *.log | ||||||
|  | .DS_Store | ||||||
|  | .cache | ||||||
|  | dist | ||||||
| node_modules | node_modules | ||||||
| build/index.js.LICENSE.txt | storybook-static | ||||||
| example/* |  | ||||||
|   | |||||||
							
								
								
									
										6
									
								
								.husky/pre-commit
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										6
									
								
								.husky/pre-commit
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,6 @@ | |||||||
|  | #!/usr/bin/env sh | ||||||
|  | . "$(dirname -- "$0")/_/husky.sh" | ||||||
|  |  | ||||||
|  | npm test | ||||||
|  | npm run lint | ||||||
|  | npm run build | ||||||
							
								
								
									
										10
									
								
								.storybook/main.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								.storybook/main.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,10 @@ | |||||||
|  | module.exports = { | ||||||
|  |   stories: ["../stories/**/*.stories.@(ts|tsx|js|jsx)"], | ||||||
|  |   addons: [ | ||||||
|  |     // '@storybook/addon-links', '@storybook/addon-essentials' | ||||||
|  |   ], | ||||||
|  |   // https://storybook.js.org/docs/react/configure/typescript#mainjs-configuration | ||||||
|  |   typescript: { | ||||||
|  |     check: true, // type-check stories during Storybook build | ||||||
|  |   }, | ||||||
|  | }; | ||||||
							
								
								
									
										5
									
								
								.storybook/preview.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								.storybook/preview.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,5 @@ | |||||||
|  | // https://storybook.js.org/docs/react/writing-stories/parameters#global-parameters | ||||||
|  | export const parameters = { | ||||||
|  |   // https://storybook.js.org/docs/react/essentials/actions#automatically-matching-args | ||||||
|  |   actions: { argTypesRegex: '^on.*' }, | ||||||
|  | }; | ||||||
							
								
								
									
										32
									
								
								CHANGELOG.md
									
									
									
									
									
								
							
							
						
						
									
										32
									
								
								CHANGELOG.md
									
									
									
									
									
								
							| @@ -5,6 +5,38 @@ All notable changes to this project will be documented in this file. | |||||||
| The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), | ||||||
| and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). | and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). | ||||||
|  |  | ||||||
|  | ## [[8.0.1]((https://github.com/Mastermindzh/react-cookie-consent/releases/tag/8.0.1)] | ||||||
|  |  | ||||||
|  | ~~Second try of [np](https://github.com/sindresorhus/np)...~~ | ||||||
|  | Removed postinstall | ||||||
|  | np is not my thing.. reverted to old release strategy | ||||||
|  |  | ||||||
|  | ## [[8.0.0]((https://github.com/Mastermindzh/react-cookie-consent/releases/tag/8.0.0)] | ||||||
|  |  | ||||||
|  | - Switched to tsdx and Typescript | ||||||
|  | - Added storybook with examples from readme | ||||||
|  |  | ||||||
|  | ## [[7.6.0]](https://github.com/Mastermindzh/react-cookie-consent/releases/tag/7.6.0] | ||||||
|  |  | ||||||
|  | - Added `customButtonWrapperAttributes` prop which allows to add custom attributes to the button wrapper div | ||||||
|  |  | ||||||
|  | ## [[7.5.0]](https://github.com/Mastermindzh/react-cookie-consent/releases/tag/7.5.0) | ||||||
|  |  | ||||||
|  | - Added `customDeclineButtonProps` to add custom properties to the decline button | ||||||
|  |  | ||||||
|  | ## [[7.4.1]](https://github.com/Mastermindzh/react-cookie-consent/releases/tag/7.4.1) | ||||||
|  |  | ||||||
|  | - Small version error in package.json that actually didn't make it work with React 18 | ||||||
|  |  | ||||||
|  | ## [[7.4.0]](https://github.com/Mastermindzh/react-cookie-consent/releases/tag/7.4.0) | ||||||
|  |  | ||||||
|  | - Added support for React 18 | ||||||
|  | - Updated example and codebase to use React 18 | ||||||
|  |  | ||||||
|  | ## [[7.3.1]](https://github.com/Mastermindzh/react-cookie-consent/releases/tag/7.3.1) | ||||||
|  |  | ||||||
|  | - Added type annotations on public functions | ||||||
|  |  | ||||||
| ## [[7.3.0]](https://github.com/Mastermindzh/react-cookie-consent/releases/tag/7.3.0) | ## [[7.3.0]](https://github.com/Mastermindzh/react-cookie-consent/releases/tag/7.3.0) | ||||||
|  |  | ||||||
| - added `customButtonProps` that allows to use custom props with the button component. Specifically useful for library buttons components, for e.g. MUI Button. | - added `customButtonProps` that allows to use custom props with the button component. Specifically useful for library buttons components, for e.g. MUI Button. | ||||||
|   | |||||||
							
								
								
									
										102
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										102
									
								
								README.md
									
									
									
									
									
								
							| @@ -4,9 +4,7 @@ A small, simple and customizable cookie consent bar for use in React application | |||||||
|  |  | ||||||
| [](https://npmjs.org/package/react-cookie-consent) | [](https://npmjs.org/package/react-cookie-consent) | ||||||
|  |  | ||||||
| Demo: https://mastermindzh.github.io/react-cookie-consent/ | Demo (storybook): https://mastermindzh.github.io/react-cookie-consent/ | ||||||
|  |  | ||||||
| Example branch: https://github.com/Mastermindzh/react-cookie-consent/tree/example |  | ||||||
|  |  | ||||||
|       |       | ||||||
|  |  | ||||||
| @@ -137,53 +135,55 @@ That option would be interesting if you want to allow user to change their conse | |||||||
|  |  | ||||||
| ## Props | ## Props | ||||||
|  |  | ||||||
| | Prop                      |                    Type                     | Default value                        | Description                                                                                                                             | | | Prop                          |                    Type                     | Default value                        | Description                                                                                                                             | | ||||||
| | ------------------------- | :-----------------------------------------: | ------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------- | | | ----------------------------- | :-----------------------------------------: | ------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------- | | ||||||
| | location                  |      string, "top", "bottom" or "none"      | "bottom"                             | Syntactic sugar to easily enable you to place the bar at the top or the bottom of the browser window. Use "none" to disable.            | | | location                      |      string, "top", "bottom" or "none"      | "bottom"                             | Syntactic sugar to easily enable you to place the bar at the top or the bottom of the browser window. Use "none" to disable.            | | ||||||
| | visible                   | string, "show", "hidden" or "byCookieValue" | "byCookieValue"                      | Force the consent bar visibility. If "byCookieValue", visibility are defined by cookie consent existence.                               | | | visible                       | string, "show", "hidden" or "byCookieValue" | "byCookieValue"                      | Force the consent bar visibility. If "byCookieValue", visibility are defined by cookie consent existence.                               | | ||||||
| | children                  |          string or React component          |                                      | Content to appear inside the bar                                                                                                        | | | children                      |          string or React component          |                                      | Content to appear inside the bar                                                                                                        | | ||||||
| | disableStyles             |                   boolean                   | false                                | If enabled the component will have no default style. (you can still supply style through props)                                         | | | disableStyles                 |                   boolean                   | false                                | If enabled the component will have no default style. (you can still supply style through props)                                         | | ||||||
| | hideOnAccept              |                   boolean                   | true                                 | If disabled the component will not hide it self after the accept button has been clicked. You will need to hide yourself (see onAccept) | | | hideOnAccept                  |                   boolean                   | true                                 | If disabled the component will not hide it self after the accept button has been clicked. You will need to hide yourself (see onAccept) | | ||||||
| | buttonText                |          string or React component          | "I understand"                       | Text to appear on the button                                                                                                            | | | buttonText                    |          string or React component          | "I understand"                       | Text to appear on the button                                                                                                            | | ||||||
| | declineButtonText         |          string or React component          | "I decline"                          | Text to appear on the decline button                                                                                                    | | | declineButtonText             |          string or React component          | "I decline"                          | Text to appear on the decline button                                                                                                    | | ||||||
| | cookieName                |                   string                    | "CookieConsent"                      | Name of the cookie used to track whether the user has agreed.                                                                           | | | cookieName                    |                   string                    | "CookieConsent"                      | Name of the cookie used to track whether the user has agreed. Note that you also have to pass this to the `getCookieConsentValue` and `resetCookieConsentValue` functions as they default to "CookieConsent" as well.                                                                         | | ||||||
| | cookieValue               |         string or boolean or number         | true                                 | Value to be saved under the cookieName.                                                                                                 | | | cookieValue                   |         string or boolean or number         | true                                 | Value to be saved under the cookieName.                                                                                                 | | ||||||
| | declineCookieValue        |         string or boolean or number         | false                                | Value to be saved under the cookieName when declined.                                                                                   | | | declineCookieValue            |         string or boolean or number         | false                                | Value to be saved under the cookieName when declined.                                                                                   | | ||||||
| | setDeclineCookie          |                   boolean                   | true                                 | Whether to set a cookie when the user clicks "decline"                                                                                  | | | setDeclineCookie              |                   boolean                   | true                                 | Whether to set a cookie when the user clicks "decline"                                                                                  | | ||||||
| | onAccept                  |                  function                   | `() => {}`                           | Function to be called after the accept button has been clicked.                                                                         | | | onAccept                      |                  function                   | `() => {}`                           | Function to be called after the accept button has been clicked.                                                                         | | ||||||
| | onDecline                 |                  function                   | `() => {}`                           | Function to be called after the decline button has been clicked.                                                                        | | | onDecline                     |                  function                   | `() => {}`                           | Function to be called after the decline button has been clicked.                                                                        | | ||||||
| | debug                     |                   boolean                   | undefined                            | Bar will be drawn regardless of cookie for debugging purposes.                                                                          | | | debug                         |                   boolean                   | undefined                            | Bar will be drawn regardless of cookie for debugging purposes.                                                                          | | ||||||
| | expires                   |                   number                    | 365                                  | Number of days before the cookie expires.                                                                                               | | | expires                       |                   number                    | 365                                  | Number of days before the cookie expires.                                                                                               | | ||||||
| | extraCookieOptions        |                   object                    | `{}`                                 | Extra info (apart from expiry date) to add to the cookie                                                                                | | | extraCookieOptions            |                   object                    | `{}`                                 | Extra info (apart from expiry date) to add to the cookie                                                                                | | ||||||
| | overlay                   |                   boolean                   | false                                | Whether to show a page obscuring overlay or not.                                                                                        | | | overlay                       |                   boolean                   | false                                | Whether to show a page obscuring overlay or not.                                                                                        | | ||||||
| | containerClasses          |                   string                    | ""                                   | CSS classes to apply to the surrounding container                                                                                       | | | containerClasses              |                   string                    | ""                                   | CSS classes to apply to the surrounding container                                                                                       | | ||||||
| | buttonClasses             |                   string                    | ""                                   | CSS classes to apply to the button                                                                                                      | | | buttonClasses                 |                   string                    | ""                                   | CSS classes to apply to the button                                                                                                      | | ||||||
| | buttonWrapperClasses      |                   string                    | ""                                   | CSS classes to apply to the div wrapping the buttons                                                                                    | | | buttonWrapperClasses          |                   string                    | ""                                   | CSS classes to apply to the div wrapping the buttons                                                                                    | | ||||||
| | declineButtonClasses      |                   string                    | ""                                   | CSS classes to apply to the decline button                                                                                              | | | customButtonWrapperAttributes |   `React.HTMLAttributes<HTMLDivElement>`    | `{}`                                 | Allows you to set custom (data) attributes on the button wrapper div                                                                    | | ||||||
| | buttonId                  |                   string                    | ""                                   | Id to apply to the button                                                                                                               | | | declineButtonClasses          |                   string                    | ""                                   | CSS classes to apply to the decline button                                                                                              | | ||||||
| | declineButtonId           |                   string                    | ""                                   | Id to apply to the decline button                                                                                                       | | | buttonId                      |                   string                    | ""                                   | Id to apply to the button                                                                                                               | | ||||||
| | contentClasses            |                   string                    | ""                                   | CSS classes to apply to the content                                                                                                     | | | declineButtonId               |                   string                    | ""                                   | Id to apply to the decline button                                                                                                       | | ||||||
| | overlayClasses            |                   string                    | ""                                   | CSS classes to apply to the surrounding overlay                                                                                         | | | contentClasses                |                   string                    | ""                                   | CSS classes to apply to the content                                                                                                     | | ||||||
| | style                     |                   object                    | [look at source][style]              | React styling object for the bar.                                                                                                       | | | overlayClasses                |                   string                    | ""                                   | CSS classes to apply to the surrounding overlay                                                                                         | | ||||||
| | buttonStyle               |                   object                    | [look at source][buttonstyle]        | React styling object for the button.                                                                                                    | | | style                         |                   object                    | [look at source][style]              | React styling object for the bar.                                                                                                       | | ||||||
| | declineButtonStyle        |                   object                    | [look at source][declinebuttonstyle] | React styling object for the decline button.                                                                                            | | | buttonStyle                   |                   object                    | [look at source][buttonstyle]        | React styling object for the button.                                                                                                    | | ||||||
| | contentStyle              |                   object                    | [look at source][contentstyle]       | React styling object for the content.                                                                                                   | | | declineButtonStyle            |                   object                    | [look at source][declinebuttonstyle] | React styling object for the decline button.                                                                                            | | ||||||
| | overlayStyle              |                   object                    | [look at source][overlaystyle]       | React styling object for the overlay.                                                                                                   | | | contentStyle                  |                   object                    | [look at source][contentstyle]       | React styling object for the content.                                                                                                   | | ||||||
| | disableButtonStyles       |                   boolean                   | false                                | If enabled the button will have no default style. (you can still supply style through props)                                            | | | overlayStyle                  |                   object                    | [look at source][overlaystyle]       | React styling object for the overlay.                                                                                                   | | ||||||
| | enableDeclineButton       |                   boolean                   | false                                | If enabled the decline button will be rendered                                                                                          | | | disableButtonStyles           |                   boolean                   | false                                | If enabled the button will have no default style. (you can still supply style through props)                                            | | ||||||
| | flipButtons               |                   boolean                   | false                                | If enabled the accept and decline buttons will be flipped                                                                               | | | enableDeclineButton           |                   boolean                   | false                                | If enabled the decline button will be rendered                                                                                          | | ||||||
| | ButtonComponent           |               React component               | button                               | React Component to render as a button.                                                                                                  | | | flipButtons                   |                   boolean                   | false                                | If enabled the accept and decline buttons will be flipped                                                                               | | ||||||
| | sameSite                  |      string, "strict", "lax" or "none"      | none                                 | Cookies sameSite attribute value                                                                                                        | | | ButtonComponent               |               React component               | button                               | React Component to render as a button.                                                                                                  | | ||||||
| | cookieSecurity            |                  boolean ¡                  | undefined                            | Cookie security level. Defaults to true unless running on http.                                                                         | | | sameSite                      |      string, "strict", "lax" or "none"      | none                                 | Cookies sameSite attribute value                                                                                                        | | ||||||
| | ariaAcceptLabel           |                   string                    | Accept cookies                       | Aria label to set on the accept button                                                                                                  | | | cookieSecurity                |                   boolean                   | undefined                            | Cookie security level. Defaults to true unless running on http.                                                                         | | ||||||
| | ariaDeclineLabel          |                   string                    | Decline cookies                      | Aria label to set on the decline button                                                                                                 | | | ariaAcceptLabel               |                   string                    | Accept cookies                       | Aria label to set on the accept button                                                                                                  | | ||||||
| | acceptOnScroll            |                   boolean                   | false                                | Defines whether "accept" should be fired after the user scrolls a certain distance (see acceptOnScrollPercentage)                       | | | ariaDeclineLabel              |                   string                    | Decline cookies                      | Aria label to set on the decline button                                                                                                 | | ||||||
| | acceptOnScrollPercentage  |                   number                    | 25                                   | Percentage of the page height the user has to scroll to trigger the accept function if acceptOnScroll is enabled                        | | | acceptOnScroll                |                   boolean                   | false                                | Defines whether "accept" should be fired after the user scrolls a certain distance (see acceptOnScrollPercentage)                       | | ||||||
| | customContentAttributes   |                   object                    | `{}`                                 | Allows you to set custom (data) attributes on the content div                                                                           | | | acceptOnScrollPercentage      |                   number                    | 25                                   | Percentage of the page height the user has to scroll to trigger the accept function if acceptOnScroll is enabled                        | | ||||||
| | customContainerAttributes |                   object                    | `{}`                                 | Allows you to set custom (data) attributes on the container div                                                                         | | | customContentAttributes       |                   object                    | `{}`                                 | Allows you to set custom (data) attributes on the content div                                                                           | | ||||||
| | onOverlayClick            |                  function                   | `() => {}`                           | allows you to react to a click on the overlay                                                                                           | | | customContainerAttributes     |                   object                    | `{}`                                 | Allows you to set custom (data) attributes on the container div                                                                         | | ||||||
| | acceptOnOverlayClick      |                   boolean                   | false                                | Determines whether the cookies should be accepted after clicking on the overlay                                                         | | | onOverlayClick                |                  function                   | `() => {}`                           | allows you to react to a click on the overlay                                                                                           | | ||||||
| | customButtonProps         |                   object                    | `{}`                                 | Allows you to set custom props on the button component                                                                                  | | | acceptOnOverlayClick          |                   boolean                   | false                                | Determines whether the cookies should be accepted after clicking on the overlay                                                         | | ||||||
|  | | customButtonProps             |                   object                    | `{}`                                 | Allows you to set custom props on the button component                                                                                  | | ||||||
|  | | customDeclineButtonProps      |                   object                    | `{}`                                 | Allows you to set custom props on the decline button component                                                                          | | ||||||
|  |  | ||||||
| ## Debugging it | ## Debugging it | ||||||
|  |  | ||||||
| @@ -296,7 +296,7 @@ You can add more cookie options using the extraCookieOptions parameter like so: | |||||||
| <CookieConsent extraCookieOptions={{ domain: "myexample.com" }}>cookie bar</CookieConsent> | <CookieConsent extraCookieOptions={{ domain: "myexample.com" }}>cookie bar</CookieConsent> | ||||||
| ``` | ``` | ||||||
|  |  | ||||||
| #### Rainbows! | #### Rainbows | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										76
									
								
								build/index.d.ts
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										76
									
								
								build/index.d.ts
									
									
									
									
										vendored
									
									
								
							| @@ -1,76 +0,0 @@ | |||||||
| import * as React from "react"; |  | ||||||
| import Cookies from "js-cookie"; |  | ||||||
|  |  | ||||||
| export interface CookieConsentProps { |  | ||||||
|   location?: "top" | "bottom" | "none"; |  | ||||||
|   sameSite?: "strict" | "lax" | "none"; |  | ||||||
|   visible?: "hidden" | "show" | "byCookieValue"; |  | ||||||
|   cookieSecurity?: boolean; |  | ||||||
|   style?: object; |  | ||||||
|   buttonStyle?: object; |  | ||||||
|   declineButtonStyle?: object; |  | ||||||
|   contentStyle?: object; |  | ||||||
|   children?: React.ReactNode; |  | ||||||
|   disableStyles?: boolean; |  | ||||||
|   hideOnAccept?: boolean; |  | ||||||
|   hideOnDecline?: boolean; |  | ||||||
|   onAccept?: (acceptedByScrolling?: boolean) => void; |  | ||||||
|   onDecline?: Function; |  | ||||||
|   buttonText?: Function | React.ReactNode; |  | ||||||
|   declineButtonText?: Function | React.ReactNode; |  | ||||||
|   cookieName?: string; |  | ||||||
|   cookieValue?: string | boolean | number; |  | ||||||
|   declineCookieValue?: string | boolean | number; |  | ||||||
|   setDeclineCookie?: boolean; |  | ||||||
|   debug?: boolean; |  | ||||||
|   expires?: number; |  | ||||||
|   containerClasses?: string; |  | ||||||
|   contentClasses?: string; |  | ||||||
|   buttonWrapperClasses?: string; |  | ||||||
|   buttonClasses?: string; |  | ||||||
|   declineButtonClasses?: string; |  | ||||||
|   buttonId?: string; |  | ||||||
|   declineButtonId?: string; |  | ||||||
|   extraCookieOptions?: object; |  | ||||||
|   disableButtonStyles?: boolean; |  | ||||||
|   enableDeclineButton?: boolean; |  | ||||||
|   flipButtons?: boolean; |  | ||||||
|   ButtonComponent?: React.ElementType; |  | ||||||
|   overlay?: boolean; |  | ||||||
|   overlayClasses?: string; |  | ||||||
|   overlayStyle?: object; |  | ||||||
|   onOverlayClick?: () => void; |  | ||||||
|   acceptOnOverlayClick?: boolean; |  | ||||||
|   ariaAcceptLabel?: string; |  | ||||||
|   ariaDeclineLabel?: string; |  | ||||||
|   acceptOnScroll?: boolean; |  | ||||||
|   acceptOnScrollPercentage?: number; |  | ||||||
|   customContentAttributes?: object; |  | ||||||
|   customContainerAttributes?: object; |  | ||||||
|   customButtonProps?: object; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| export default class CookieConsent extends React.Component<CookieConsentProps, {}> {} |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * Returns the value of the consent cookie |  | ||||||
|  * Retrieves the regular value first and if not found the legacy one according |  | ||||||
|  * to: https://web.dev/samesite-cookie-recipes/#handling-incompatible-clients |  | ||||||
|  * @param {*} name optional name of the cookie |  | ||||||
|  */ |  | ||||||
| export function getCookieConsentValue(name?: string): string; |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * Reset the consent cookie |  | ||||||
|  * Remove the cookie on browser in order to allow user to change their consent |  | ||||||
|  * @param {*} name optional name of the cookie |  | ||||||
|  */ |  | ||||||
| export function resetCookieConsentValue(name?: string); |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * Get the legacy cookie name by the regular cookie name |  | ||||||
|  * @param {string} name of cookie to get |  | ||||||
|  */ |  | ||||||
| export function getLegacyCookieName(name: string); |  | ||||||
|  |  | ||||||
| export { Cookies }; |  | ||||||
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										1
									
								
								example
									
									
									
									
									
								
							
							
								
								
								
								
								
							
						
						
									
										1
									
								
								example
									
									
									
									
									
								
							 Submodule example deleted from bff8dd76c5
									
								
							
							
								
								
									
										45087
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										45087
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										139
									
								
								package.json
									
									
									
									
									
								
							
							
						
						
									
										139
									
								
								package.json
									
									
									
									
									
								
							| @@ -1,74 +1,103 @@ | |||||||
| { | { | ||||||
|   "name": "react-cookie-consent", |   "name": "react-cookie-consent", | ||||||
|   "author": { |   "version": "8.0.1", | ||||||
|     "name": "Rick van Lieshout", |  | ||||||
|     "email": "info@rickvanlieshout.com" |  | ||||||
|   }, |  | ||||||
|   "version": "7.3.0", |  | ||||||
|   "description": "A small, simple and customizable cookie consent bar for use in React applications.", |   "description": "A small, simple and customizable cookie consent bar for use in React applications.", | ||||||
|   "main": "build/index.js", |  | ||||||
|   "types": "build/index.d.ts", |  | ||||||
|   "dependencies": { |  | ||||||
|     "js-cookie": "^2.2.1", |  | ||||||
|     "prop-types": "^15.7.2" |  | ||||||
|   }, |  | ||||||
|   "peerDependencies": { |  | ||||||
|     "react": "^16.13.1 || ^17.0.0" |  | ||||||
|   }, |  | ||||||
|   "scripts": { |  | ||||||
|     "build": "webpack", |  | ||||||
|     "prettier": "prettier 'src/**/*.{js*,ts*,htm*,md,scss}' --write", |  | ||||||
|     "patch": "npm --no-git-tag-version version patch", |  | ||||||
|     "minor": "npm --no-git-tag-version version minor", |  | ||||||
|     "major": "npm --no-git-tag-version version major", |  | ||||||
|     "preversion": "grep \"\\[$npm_package_version\\]\" CHANGELOG.md > /dev/null || ( echo 'You need to add an entry in CHANGELOG.md for this version.' && false )", |  | ||||||
|     "release": "npm run build && git add -A && git tag $npm_package_version && git commit -m \"release $npm_package_version\" && git push && git push --tags && npm publish", |  | ||||||
|     "release-patch": "npm run patch && npm run release", |  | ||||||
|     "release-minor": "npm run minor && npm run release", |  | ||||||
|     "release-major": "npm run major && npm run release" |  | ||||||
|   }, |  | ||||||
|   "repository": { |  | ||||||
|     "type": "git", |  | ||||||
|     "url": "git+https://github.com/Mastermindzh/react-cookie-consent.git" |  | ||||||
|   }, |  | ||||||
|   "keywords": [ |   "keywords": [ | ||||||
|     "react", |     "react", | ||||||
|     "cookie", |     "cookie", | ||||||
|     "consent", |     "consent", | ||||||
|     "cookiebar" |     "cookiebar" | ||||||
|   ], |   ], | ||||||
|   "license": "MIT", |   "homepage": "https://github.com/Mastermindzh/react-cookie-consent#readme", | ||||||
|   "bugs": { |   "bugs": { | ||||||
|     "url": "https://github.com/Mastermindzh/react-cookie-consent/issues" |     "url": "https://github.com/Mastermindzh/react-cookie-consent/issues" | ||||||
|   }, |   }, | ||||||
|   "homepage": "https://github.com/Mastermindzh/react-cookie-consent#readme", |   "repository": { | ||||||
|   "devDependencies": { |     "type": "git", | ||||||
|     "@babel/cli": "^7.12.1", |     "url": "git+https://github.com/Mastermindzh/react-cookie-consent.git" | ||||||
|     "@babel/core": "^7.12.3", |  | ||||||
|     "@babel/plugin-proposal-object-rest-spread": "^7.12.1", |  | ||||||
|     "@babel/plugin-transform-object-assign": "^7.12.1", |  | ||||||
|     "@babel/plugin-transform-react-jsx": "^7.12.1", |  | ||||||
|     "@babel/preset-env": "^7.12.1", |  | ||||||
|     "@mastermindzh/prettier-config": "^1.0.0", |  | ||||||
|     "@types/js-cookie": "^2.2.6", |  | ||||||
|     "babel-loader": "^8.1.0", |  | ||||||
|     "copy-webpack-plugin": "^6.2.1", |  | ||||||
|     "husky": "^4.3.0", |  | ||||||
|     "lint-staged": "^10.5.1", |  | ||||||
|     "prettier": "^2.1.2", |  | ||||||
|     "react": "^16.13.1", |  | ||||||
|     "webpack": "^5.3.2", |  | ||||||
|     "webpack-cli": "^4.1.0" |  | ||||||
|   }, |   }, | ||||||
|   "prettier": "@mastermindzh/prettier-config", |   "license": "MIT", | ||||||
|   "husky": { |   "author": { | ||||||
|     "hooks": { |     "name": "Rick van Lieshout", | ||||||
|       "pre-commit": "lint-staged --allow-empty" |     "email": "info@rickvanlieshout.com" | ||||||
|     } |   }, | ||||||
|  |   "main": "dist/index.js", | ||||||
|  |   "module": "dist/react-cookie-consent.esm.js", | ||||||
|  |   "typings": "dist/index.d.ts", | ||||||
|  |   "files": [ | ||||||
|  |     "dist", | ||||||
|  |     "src" | ||||||
|  |   ], | ||||||
|  |   "scripts": { | ||||||
|  |     "analyze": "size-limit --why", | ||||||
|  |     "build": "tsdx build", | ||||||
|  |     "build-storybook": "build-storybook", | ||||||
|  |     "install-husky": "npx husky install", | ||||||
|  |     "lint": "tsdx lint", | ||||||
|  |     "major": "npm --no-git-tag-version version major", | ||||||
|  |     "minor": "npm --no-git-tag-version version minor", | ||||||
|  |     "organize": "npx format-package -w && npx sort-package-json", | ||||||
|  |     "patch": "npm --no-git-tag-version version patch", | ||||||
|  |     "prepare": "tsdx build", | ||||||
|  |     "prettier": "prettier 'src/**/*.{js*,ts*,htm*,md,scss}' --write", | ||||||
|  |     "publish": "npx np", | ||||||
|  |     "release": "npm run build && git add -A && git tag $npm_package_version && git commit -m \"release $npm_package_version\" && git push && git push --tags && npm publish", | ||||||
|  |     "release-major": "npm run major && npm run release", | ||||||
|  |     "release-minor": "npm run minor && npm run release", | ||||||
|  |     "release-patch": "npm run patch && npm run release", | ||||||
|  |     "size": "size-limit", | ||||||
|  |     "start": "tsdx watch", | ||||||
|  |     "storybook": "start-storybook -p 6006", | ||||||
|  |     "test": "tsdx test --passWithNoTests", | ||||||
|  |     "preversion": "grep \"\\[$npm_package_version\\]\" CHANGELOG.md > /dev/null || ( echo 'You need to add an entry in CHANGELOG.md for this version.' && false )" | ||||||
|   }, |   }, | ||||||
|   "lint-staged": { |   "lint-staged": { | ||||||
|     "*.{js*,ts*,htm*,md,scss}": [ |     "*.{js*,ts*,htm*,md,scss}": [ | ||||||
|       "prettier --write" |       "prettier --write" | ||||||
|     ] |     ] | ||||||
|   } |   }, | ||||||
|  |   "prettier": "@mastermindzh/prettier-config", | ||||||
|  |   "dependencies": { | ||||||
|  |     "js-cookie": "^2.2.1" | ||||||
|  |   }, | ||||||
|  |   "devDependencies": { | ||||||
|  |     "@emotion/react": "^11.9.3", | ||||||
|  |     "@emotion/styled": "^11.9.3", | ||||||
|  |     "@mastermindzh/prettier-config": "^1.0.0", | ||||||
|  |     "@mui/material": "^5.9.2", | ||||||
|  |     "@size-limit/preset-small-lib": "^7.0.8", | ||||||
|  |     "@storybook/addon-essentials": "^6.5.9", | ||||||
|  |     "@storybook/addons": "^6.5.9", | ||||||
|  |     "@storybook/react": "^6.5.9", | ||||||
|  |     "@types/js-cookie": "^2.2.6", | ||||||
|  |     "@types/react": "^18.0.15", | ||||||
|  |     "@types/react-dom": "^18.0.6", | ||||||
|  |     "babel-loader": "^8.2.5", | ||||||
|  |     "gh-pages": "^4.0.0", | ||||||
|  |     "husky": "^8.0.1", | ||||||
|  |     "prettier": "^2.6.2", | ||||||
|  |     "react": "^18.2.0", | ||||||
|  |     "react-dom": "^18.2.0", | ||||||
|  |     "react-is": "^18.2.0", | ||||||
|  |     "size-limit": "^7.0.8", | ||||||
|  |     "tsdx": "^0.14.1", | ||||||
|  |     "tslib": "^2.4.0", | ||||||
|  |     "typescript": "^3.9.10" | ||||||
|  |   }, | ||||||
|  |   "peerDependencies": { | ||||||
|  |     "react": ">=16" | ||||||
|  |   }, | ||||||
|  |   "engines": { | ||||||
|  |     "node": ">=10" | ||||||
|  |   }, | ||||||
|  |   "size-limit": [ | ||||||
|  |     { | ||||||
|  |       "path": "dist/react-cookie-consent.cjs.production.min.js", | ||||||
|  |       "limit": "10 KB" | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |       "path": "dist/react-cookie-consent.esm.js", | ||||||
|  |       "limit": "10 KB" | ||||||
|  |     } | ||||||
|  |   ] | ||||||
| } | } | ||||||
|   | |||||||
							
								
								
									
										115
									
								
								src/CookieConsent.props.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										115
									
								
								src/CookieConsent.props.tsx
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,115 @@ | |||||||
|  | import React, { FunctionComponent, ReactNode } from "react"; | ||||||
|  | import { | ||||||
|  |   defaultCookieConsentName, | ||||||
|  |   POSITION_OPTIONS, | ||||||
|  |   SAME_SITE_OPTIONS, | ||||||
|  |   VISIBILITY_OPTIONS, | ||||||
|  | } from "./models/constants"; | ||||||
|  |  | ||||||
|  | export interface CookieConsentProps { | ||||||
|  |   children?: ReactNode; | ||||||
|  |   style: React.CSSProperties; | ||||||
|  |   buttonStyle: React.CSSProperties; | ||||||
|  |   declineButtonStyle: React.CSSProperties; | ||||||
|  |   contentStyle: React.CSSProperties; | ||||||
|  |   disableStyles: boolean; | ||||||
|  |   hideOnAccept: boolean; | ||||||
|  |   hideOnDecline: boolean; | ||||||
|  |   onAccept: (acceptedByScrolling: boolean) => void; | ||||||
|  |   onDecline: () => void; | ||||||
|  |   buttonText: string | ReactNode | Function; | ||||||
|  |   declineButtonText: string | ReactNode | Function; | ||||||
|  |   cookieName: string; | ||||||
|  |   cookieValue: string | object; | ||||||
|  |   declineCookieValue: string | object; | ||||||
|  |   setDeclineCookie: boolean; | ||||||
|  |   debug: boolean; | ||||||
|  |   expires: number; | ||||||
|  |   containerClasses: string; | ||||||
|  |   contentClasses: string; | ||||||
|  |   buttonClasses: string; | ||||||
|  |   buttonWrapperClasses: string; | ||||||
|  |   declineButtonClasses: string; | ||||||
|  |   buttonId: string; | ||||||
|  |   declineButtonId: string; | ||||||
|  |   overlayClasses: string; | ||||||
|  |   ariaAcceptLabel: string; | ||||||
|  |   ariaDeclineLabel: string; | ||||||
|  |   disableButtonStyles: boolean; | ||||||
|  |   enableDeclineButton: boolean; | ||||||
|  |   flipButtons: boolean; | ||||||
|  |   cookieSecurity?: boolean; | ||||||
|  |   overlay: boolean; | ||||||
|  |   acceptOnOverlayClick: boolean; | ||||||
|  |   acceptOnScroll: boolean; | ||||||
|  |   acceptOnScrollPercentage: number; | ||||||
|  |   ButtonComponent: any; | ||||||
|  |   extraCookieOptions: Object; | ||||||
|  |   overlayStyle: Object; | ||||||
|  |   customContentAttributes: Object; | ||||||
|  |   customContainerAttributes: Object; | ||||||
|  |   customButtonProps: Object; | ||||||
|  |   customDeclineButtonProps: Object; | ||||||
|  |   customButtonWrapperAttributes: Object; | ||||||
|  |   onOverlayClick: () => void; | ||||||
|  |   // these should be enums | ||||||
|  |   location: string; | ||||||
|  |   visible: string; | ||||||
|  |   sameSite: "strict" | "Strict" | "lax" | "Lax" | "none" | "None" | undefined; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | const DefaultButtonComponent: FunctionComponent<{ children: ReactNode; [x: string]: any }> = ({ | ||||||
|  |   children, | ||||||
|  |   ...props | ||||||
|  | }) => { | ||||||
|  |   return <button {...props}>{children}</button>; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | export const defaultCookieConsentProps: CookieConsentProps = { | ||||||
|  |   disableStyles: false, | ||||||
|  |   hideOnAccept: true, | ||||||
|  |   hideOnDecline: true, | ||||||
|  |   location: POSITION_OPTIONS.BOTTOM, | ||||||
|  |   visible: VISIBILITY_OPTIONS.BY_COOKIE_VALUE, | ||||||
|  |   onAccept: (_acceptedByScrolling) => {}, | ||||||
|  |   onDecline: () => {}, | ||||||
|  |   cookieName: defaultCookieConsentName, | ||||||
|  |   cookieValue: "true", | ||||||
|  |   declineCookieValue: "false", | ||||||
|  |   setDeclineCookie: true, | ||||||
|  |   buttonText: "I understand", | ||||||
|  |   declineButtonText: "I decline", | ||||||
|  |   debug: false, | ||||||
|  |   expires: 365, | ||||||
|  |   containerClasses: "CookieConsent", | ||||||
|  |   contentClasses: "", | ||||||
|  |   buttonClasses: "", | ||||||
|  |   buttonWrapperClasses: "", | ||||||
|  |   declineButtonClasses: "", | ||||||
|  |   buttonId: "rcc-confirm-button", | ||||||
|  |   declineButtonId: "rcc-decline-button", | ||||||
|  |   extraCookieOptions: {}, | ||||||
|  |   disableButtonStyles: false, | ||||||
|  |   enableDeclineButton: false, | ||||||
|  |   flipButtons: false, | ||||||
|  |   sameSite: SAME_SITE_OPTIONS.LAX, | ||||||
|  |   ButtonComponent: DefaultButtonComponent, | ||||||
|  |   overlay: false, | ||||||
|  |   overlayClasses: "", | ||||||
|  |   onOverlayClick: () => {}, | ||||||
|  |   acceptOnOverlayClick: false, | ||||||
|  |   ariaAcceptLabel: "Accept cookies", | ||||||
|  |   ariaDeclineLabel: "Decline cookies", | ||||||
|  |   acceptOnScroll: false, | ||||||
|  |   acceptOnScrollPercentage: 25, | ||||||
|  |   customContentAttributes: {}, | ||||||
|  |   customContainerAttributes: {}, | ||||||
|  |   customButtonProps: {}, | ||||||
|  |   customDeclineButtonProps: {}, | ||||||
|  |   customButtonWrapperAttributes: {}, | ||||||
|  |   style: {}, | ||||||
|  |   buttonStyle: {}, | ||||||
|  |   declineButtonStyle: {}, | ||||||
|  |   contentStyle: {}, | ||||||
|  |   overlayStyle: {}, | ||||||
|  | }; | ||||||
							
								
								
									
										59
									
								
								src/CookieConsent.state.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										59
									
								
								src/CookieConsent.state.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,59 @@ | |||||||
|  | export interface CookieConsentState { | ||||||
|  |   visible: boolean; | ||||||
|  |   style: React.CSSProperties; | ||||||
|  |   buttonStyle: React.CSSProperties; | ||||||
|  |   declineButtonStyle: React.CSSProperties; | ||||||
|  |   contentStyle: React.CSSProperties; | ||||||
|  |   overlayStyle: React.CSSProperties; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | export const defaultState: CookieConsentState = { | ||||||
|  |   visible: false, | ||||||
|  |   style: { | ||||||
|  |     alignItems: "baseline", | ||||||
|  |     background: "#353535", | ||||||
|  |     color: "white", | ||||||
|  |     display: "flex", | ||||||
|  |     flexWrap: "wrap", | ||||||
|  |     justifyContent: "space-between", | ||||||
|  |     left: "0", | ||||||
|  |     position: "fixed", | ||||||
|  |     width: "100%", | ||||||
|  |     zIndex: "999", | ||||||
|  |   }, | ||||||
|  |   buttonStyle: { | ||||||
|  |     background: "#ffd42d", | ||||||
|  |     border: "0", | ||||||
|  |     borderRadius: "0px", | ||||||
|  |     boxShadow: "none", | ||||||
|  |     color: "black", | ||||||
|  |     cursor: "pointer", | ||||||
|  |     flex: "0 0 auto", | ||||||
|  |     padding: "5px 10px", | ||||||
|  |     margin: "15px", | ||||||
|  |   }, | ||||||
|  |   declineButtonStyle: { | ||||||
|  |     background: "#c12a2a", | ||||||
|  |     border: "0", | ||||||
|  |     borderRadius: "0px", | ||||||
|  |     boxShadow: "none", | ||||||
|  |     color: "#e5e5e5", | ||||||
|  |     cursor: "pointer", | ||||||
|  |     flex: "0 0 auto", | ||||||
|  |     padding: "5px 10px", | ||||||
|  |     margin: "15px", | ||||||
|  |   }, | ||||||
|  |   contentStyle: { | ||||||
|  |     flex: "1 0 300px", | ||||||
|  |     margin: "15px", | ||||||
|  |   }, | ||||||
|  |   overlayStyle: { | ||||||
|  |     position: "fixed", | ||||||
|  |     left: 0, | ||||||
|  |     top: 0, | ||||||
|  |     width: "100%", | ||||||
|  |     height: "100%", | ||||||
|  |     zIndex: "999", | ||||||
|  |     backgroundColor: "rgba(0,0,0,0.3)", | ||||||
|  |   }, | ||||||
|  | }; | ||||||
							
								
								
									
										301
									
								
								src/CookieConsent.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										301
									
								
								src/CookieConsent.tsx
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,301 @@ | |||||||
|  | import Cookies from "js-cookie"; | ||||||
|  | import React, { Component, CSSProperties } from "react"; | ||||||
|  | import { ConditionalWrapper } from "./components/ConditionalWrapper"; | ||||||
|  | import { CookieConsentProps, defaultCookieConsentProps } from "./CookieConsent.props"; | ||||||
|  | import { CookieConsentState, defaultState } from "./CookieConsent.state"; | ||||||
|  | import { POSITION_OPTIONS, SAME_SITE_OPTIONS, VISIBILITY_OPTIONS } from "./models/constants"; | ||||||
|  | import { getCookieConsentValue, getLegacyCookieName } from "./utilities"; | ||||||
|  |  | ||||||
|  | export class CookieConsent extends Component<CookieConsentProps, CookieConsentState> { | ||||||
|  |   public static defaultProps = defaultCookieConsentProps; | ||||||
|  |  | ||||||
|  |   state: CookieConsentState = defaultState; | ||||||
|  |  | ||||||
|  |   componentDidMount() { | ||||||
|  |     const { debug } = this.props; | ||||||
|  |  | ||||||
|  |     // if cookie undefined or debug | ||||||
|  |     if (this.getCookieValue() === undefined || debug) { | ||||||
|  |       this.setState({ visible: true }); | ||||||
|  |       // if acceptOnScroll is set to true and (cookie is undefined or debug is set to true), add a listener. | ||||||
|  |       if (this.props.acceptOnScroll) { | ||||||
|  |         window.addEventListener("scroll", this.handleScroll, { passive: true }); | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   componentWillUnmount() { | ||||||
|  |     // remove listener if still set | ||||||
|  |     this.removeScrollListener(); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   /** | ||||||
|  |    * Set a persistent accept cookie | ||||||
|  |    */ | ||||||
|  |   accept(acceptedByScrolling = false) { | ||||||
|  |     const { cookieName, cookieValue, hideOnAccept, onAccept } = this.props; | ||||||
|  |  | ||||||
|  |     this.setCookie(cookieName, cookieValue); | ||||||
|  |  | ||||||
|  |     onAccept(acceptedByScrolling ?? false); | ||||||
|  |  | ||||||
|  |     if (hideOnAccept) { | ||||||
|  |       this.setState({ visible: false }); | ||||||
|  |       this.removeScrollListener(); | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   /** | ||||||
|  |    * Handle a click on the overlay | ||||||
|  |    */ | ||||||
|  |   overlayClick() { | ||||||
|  |     const { acceptOnOverlayClick, onOverlayClick } = this.props; | ||||||
|  |     if (acceptOnOverlayClick) { | ||||||
|  |       this.accept(); | ||||||
|  |     } | ||||||
|  |     onOverlayClick(); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   /** | ||||||
|  |    * Set a persistent decline cookie | ||||||
|  |    */ | ||||||
|  |   decline() { | ||||||
|  |     const { cookieName, declineCookieValue, hideOnDecline, onDecline, setDeclineCookie } = | ||||||
|  |       this.props; | ||||||
|  |  | ||||||
|  |     if (setDeclineCookie) { | ||||||
|  |       this.setCookie(cookieName, declineCookieValue); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     onDecline(); | ||||||
|  |  | ||||||
|  |     if (hideOnDecline) { | ||||||
|  |       this.setState({ visible: false }); | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   /** | ||||||
|  |    * Function to set the consent cookie based on the provided variables | ||||||
|  |    * Sets two cookies to handle incompatible browsers, more details: | ||||||
|  |    * https://web.dev/samesite-cookie-recipes/#handling-incompatible-clients | ||||||
|  |    */ | ||||||
|  |   setCookie(cookieName: string, cookieValue: string | object) { | ||||||
|  |     const { extraCookieOptions, expires, sameSite } = this.props; | ||||||
|  |     let { cookieSecurity } = this.props; | ||||||
|  |  | ||||||
|  |     if (cookieSecurity === undefined) { | ||||||
|  |       cookieSecurity = window.location ? window.location.protocol === "https:" : true; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     const cookieOptions = { expires, ...extraCookieOptions, sameSite, secure: cookieSecurity }; | ||||||
|  |  | ||||||
|  |     // Fallback for older browsers where can not set SameSite=None, | ||||||
|  |     // SEE: https://web.dev/samesite-cookie-recipes/#handling-incompatible-clients | ||||||
|  |     if (sameSite === SAME_SITE_OPTIONS.NONE) { | ||||||
|  |       Cookies.set(getLegacyCookieName(cookieName), cookieValue, cookieOptions); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     // set the regular cookie | ||||||
|  |     Cookies.set(cookieName, cookieValue, cookieOptions); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   /** | ||||||
|  |    * Returns the value of the consent cookie | ||||||
|  |    * Retrieves the regular value first and if not found the legacy one according | ||||||
|  |    * to: https://web.dev/samesite-cookie-recipes/#handling-incompatible-clients | ||||||
|  |    */ | ||||||
|  |   getCookieValue() { | ||||||
|  |     const { cookieName } = this.props; | ||||||
|  |     return getCookieConsentValue(cookieName); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   /** | ||||||
|  |    * checks whether scroll has exceeded set amount and fire accept if so. | ||||||
|  |    */ | ||||||
|  |   handleScroll = () => { | ||||||
|  |     const { acceptOnScrollPercentage } = this.props; | ||||||
|  |  | ||||||
|  |     // (top / height) - height * 100 | ||||||
|  |     const rootNode = document.documentElement; | ||||||
|  |     const body = document.body; | ||||||
|  |     const top = "scrollTop"; | ||||||
|  |     const height = "scrollHeight"; | ||||||
|  |  | ||||||
|  |     const percentage = | ||||||
|  |       ((rootNode[top] || body[top]) / | ||||||
|  |         ((rootNode[height] || body[height]) - rootNode.clientHeight)) * | ||||||
|  |       100; | ||||||
|  |  | ||||||
|  |     if (percentage > acceptOnScrollPercentage) { | ||||||
|  |       this.accept(true); | ||||||
|  |     } | ||||||
|  |   }; | ||||||
|  |  | ||||||
|  |   removeScrollListener = () => { | ||||||
|  |     const { acceptOnScroll } = this.props; | ||||||
|  |     if (acceptOnScroll) { | ||||||
|  |       window.removeEventListener("scroll", this.handleScroll); | ||||||
|  |     } | ||||||
|  |   }; | ||||||
|  |  | ||||||
|  |   render() { | ||||||
|  |     // If the bar shouldn't be visible don't render anything. | ||||||
|  |     switch (this.props.visible) { | ||||||
|  |       case VISIBILITY_OPTIONS.HIDDEN: | ||||||
|  |         return null; | ||||||
|  |       case VISIBILITY_OPTIONS.BY_COOKIE_VALUE: | ||||||
|  |         if (!this.state.visible) { | ||||||
|  |           return null; | ||||||
|  |         } | ||||||
|  |         break; | ||||||
|  |       default: | ||||||
|  |         break; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     const { | ||||||
|  |       location, | ||||||
|  |       style, | ||||||
|  |       buttonStyle, | ||||||
|  |       declineButtonStyle, | ||||||
|  |       contentStyle, | ||||||
|  |       disableStyles, | ||||||
|  |       buttonText, | ||||||
|  |       declineButtonText, | ||||||
|  |       containerClasses, | ||||||
|  |       contentClasses, | ||||||
|  |       buttonClasses, | ||||||
|  |       buttonWrapperClasses, | ||||||
|  |       declineButtonClasses, | ||||||
|  |       buttonId, | ||||||
|  |       declineButtonId, | ||||||
|  |       disableButtonStyles, | ||||||
|  |       enableDeclineButton, | ||||||
|  |       flipButtons, | ||||||
|  |       ButtonComponent, | ||||||
|  |       overlay, | ||||||
|  |       overlayClasses, | ||||||
|  |       overlayStyle, | ||||||
|  |       ariaAcceptLabel, | ||||||
|  |       ariaDeclineLabel, | ||||||
|  |       customContainerAttributes, | ||||||
|  |       customContentAttributes, | ||||||
|  |       customButtonProps, | ||||||
|  |       customDeclineButtonProps, | ||||||
|  |       customButtonWrapperAttributes, | ||||||
|  |     } = this.props; | ||||||
|  |  | ||||||
|  |     let myStyle: CSSProperties = {}; | ||||||
|  |     let myButtonStyle: CSSProperties = {}; | ||||||
|  |     let myDeclineButtonStyle: CSSProperties = {}; | ||||||
|  |     let myContentStyle: CSSProperties = {}; | ||||||
|  |     let myOverlayStyle: CSSProperties = {}; | ||||||
|  |  | ||||||
|  |     if (disableStyles) { | ||||||
|  |       // if styles are disabled use the provided styles (or none) | ||||||
|  |       myStyle = Object.assign({}, style); | ||||||
|  |       myButtonStyle = Object.assign({}, buttonStyle); | ||||||
|  |       myDeclineButtonStyle = Object.assign({}, declineButtonStyle); | ||||||
|  |       myContentStyle = Object.assign({}, contentStyle); | ||||||
|  |       myOverlayStyle = Object.assign({}, overlayStyle); | ||||||
|  |     } else { | ||||||
|  |       // if styles aren't disabled merge them with the styles that are provided (or use default styles) | ||||||
|  |       myStyle = Object.assign({}, { ...this.state.style, ...style }); | ||||||
|  |       myContentStyle = Object.assign({}, { ...this.state.contentStyle, ...contentStyle }); | ||||||
|  |       myOverlayStyle = Object.assign({}, { ...this.state.overlayStyle, ...overlayStyle }); | ||||||
|  |  | ||||||
|  |       // switch to disable JUST the button styles | ||||||
|  |       if (disableButtonStyles) { | ||||||
|  |         myButtonStyle = Object.assign({}, buttonStyle); | ||||||
|  |         myDeclineButtonStyle = Object.assign({}, declineButtonStyle); | ||||||
|  |       } else { | ||||||
|  |         myButtonStyle = Object.assign({}, { ...this.state.buttonStyle, ...buttonStyle }); | ||||||
|  |         myDeclineButtonStyle = Object.assign( | ||||||
|  |           {}, | ||||||
|  |           { ...this.state.declineButtonStyle, ...declineButtonStyle } | ||||||
|  |         ); | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     // syntactic sugar to enable user to easily select top / bottom | ||||||
|  |     switch (location) { | ||||||
|  |       case POSITION_OPTIONS.TOP: | ||||||
|  |         myStyle.top = "0"; | ||||||
|  |         break; | ||||||
|  |  | ||||||
|  |       case POSITION_OPTIONS.BOTTOM: | ||||||
|  |         myStyle.bottom = "0"; | ||||||
|  |         break; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     const buttonsToRender = []; | ||||||
|  |  | ||||||
|  |     // add decline button | ||||||
|  |     enableDeclineButton && | ||||||
|  |       buttonsToRender.push( | ||||||
|  |         <ButtonComponent | ||||||
|  |           key="declineButton" | ||||||
|  |           style={myDeclineButtonStyle} | ||||||
|  |           className={declineButtonClasses} | ||||||
|  |           id={declineButtonId} | ||||||
|  |           aria-label={ariaDeclineLabel} | ||||||
|  |           onClick={() => { | ||||||
|  |             this.decline(); | ||||||
|  |           }} | ||||||
|  |           {...customDeclineButtonProps} | ||||||
|  |         > | ||||||
|  |           {declineButtonText} | ||||||
|  |         </ButtonComponent> | ||||||
|  |       ); | ||||||
|  |  | ||||||
|  |     // add accept button | ||||||
|  |     buttonsToRender.push( | ||||||
|  |       <ButtonComponent | ||||||
|  |         key="acceptButton" | ||||||
|  |         style={myButtonStyle} | ||||||
|  |         className={buttonClasses} | ||||||
|  |         id={buttonId} | ||||||
|  |         aria-label={ariaAcceptLabel} | ||||||
|  |         onClick={() => { | ||||||
|  |           this.accept(); | ||||||
|  |         }} | ||||||
|  |         {...customButtonProps} | ||||||
|  |       > | ||||||
|  |         {buttonText} | ||||||
|  |       </ButtonComponent> | ||||||
|  |     ); | ||||||
|  |  | ||||||
|  |     if (flipButtons) { | ||||||
|  |       buttonsToRender.reverse(); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     return ( | ||||||
|  |       <ConditionalWrapper | ||||||
|  |         condition={overlay} | ||||||
|  |         wrapper={(children) => ( | ||||||
|  |           <div | ||||||
|  |             style={myOverlayStyle} | ||||||
|  |             className={overlayClasses} | ||||||
|  |             onClick={() => { | ||||||
|  |               this.overlayClick(); | ||||||
|  |             }} | ||||||
|  |           > | ||||||
|  |             {children} | ||||||
|  |           </div> | ||||||
|  |         )} | ||||||
|  |       > | ||||||
|  |         <div className={`${containerClasses}`} style={myStyle} {...customContainerAttributes}> | ||||||
|  |           <div style={myContentStyle} className={contentClasses} {...customContentAttributes}> | ||||||
|  |             {this.props.children} | ||||||
|  |           </div> | ||||||
|  |           <div className={`${buttonWrapperClasses}`} {...customButtonWrapperAttributes}> | ||||||
|  |             {buttonsToRender.map((button) => { | ||||||
|  |               return button; | ||||||
|  |             })} | ||||||
|  |           </div> | ||||||
|  |         </div> | ||||||
|  |       </ConditionalWrapper> | ||||||
|  |     ); | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | export default CookieConsent; | ||||||
							
								
								
									
										18
									
								
								src/components/ConditionalWrapper.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								src/components/ConditionalWrapper.tsx
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,18 @@ | |||||||
|  | import { FunctionComponent, ReactNode } from "react"; | ||||||
|  |  | ||||||
|  | type Props = { | ||||||
|  |   condition: boolean; | ||||||
|  |   wrapper: (_: ReactNode) => any; | ||||||
|  |   children: ReactNode; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * A function to wrap elements with a "wrapper" on a condition | ||||||
|  |  * @param {object} wrappingOptions | ||||||
|  |  *  condition == boolean condition, when to wrap | ||||||
|  |  *  wrapper == style to wrap. e.g <div>{children}</div> | ||||||
|  |  *  children == react passes whatever is between tags as children. Don't supply this yourself. | ||||||
|  |  */ | ||||||
|  | export const ConditionalWrapper: FunctionComponent<Props> = ({ condition, wrapper, children }) => { | ||||||
|  |   return condition ? wrapper(children) : children; | ||||||
|  | }; | ||||||
							
								
								
									
										76
									
								
								src/index.d.ts
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										76
									
								
								src/index.d.ts
									
									
									
									
										vendored
									
									
								
							| @@ -1,76 +0,0 @@ | |||||||
| import * as React from "react"; |  | ||||||
| import Cookies from "js-cookie"; |  | ||||||
|  |  | ||||||
| export interface CookieConsentProps { |  | ||||||
|   location?: "top" | "bottom" | "none"; |  | ||||||
|   sameSite?: "strict" | "lax" | "none"; |  | ||||||
|   visible?: "hidden" | "show" | "byCookieValue"; |  | ||||||
|   cookieSecurity?: boolean; |  | ||||||
|   style?: object; |  | ||||||
|   buttonStyle?: object; |  | ||||||
|   declineButtonStyle?: object; |  | ||||||
|   contentStyle?: object; |  | ||||||
|   children?: React.ReactNode; |  | ||||||
|   disableStyles?: boolean; |  | ||||||
|   hideOnAccept?: boolean; |  | ||||||
|   hideOnDecline?: boolean; |  | ||||||
|   onAccept?: (acceptedByScrolling?: boolean) => void; |  | ||||||
|   onDecline?: Function; |  | ||||||
|   buttonText?: Function | React.ReactNode; |  | ||||||
|   declineButtonText?: Function | React.ReactNode; |  | ||||||
|   cookieName?: string; |  | ||||||
|   cookieValue?: string | boolean | number; |  | ||||||
|   declineCookieValue?: string | boolean | number; |  | ||||||
|   setDeclineCookie?: boolean; |  | ||||||
|   debug?: boolean; |  | ||||||
|   expires?: number; |  | ||||||
|   containerClasses?: string; |  | ||||||
|   contentClasses?: string; |  | ||||||
|   buttonWrapperClasses?: string; |  | ||||||
|   buttonClasses?: string; |  | ||||||
|   declineButtonClasses?: string; |  | ||||||
|   buttonId?: string; |  | ||||||
|   declineButtonId?: string; |  | ||||||
|   extraCookieOptions?: object; |  | ||||||
|   disableButtonStyles?: boolean; |  | ||||||
|   enableDeclineButton?: boolean; |  | ||||||
|   flipButtons?: boolean; |  | ||||||
|   ButtonComponent?: React.ElementType; |  | ||||||
|   overlay?: boolean; |  | ||||||
|   overlayClasses?: string; |  | ||||||
|   overlayStyle?: object; |  | ||||||
|   onOverlayClick?: () => void; |  | ||||||
|   acceptOnOverlayClick?: boolean; |  | ||||||
|   ariaAcceptLabel?: string; |  | ||||||
|   ariaDeclineLabel?: string; |  | ||||||
|   acceptOnScroll?: boolean; |  | ||||||
|   acceptOnScrollPercentage?: number; |  | ||||||
|   customContentAttributes?: object; |  | ||||||
|   customContainerAttributes?: object; |  | ||||||
|   customButtonProps?: object; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| export default class CookieConsent extends React.Component<CookieConsentProps, {}> {} |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * Returns the value of the consent cookie |  | ||||||
|  * Retrieves the regular value first and if not found the legacy one according |  | ||||||
|  * to: https://web.dev/samesite-cookie-recipes/#handling-incompatible-clients |  | ||||||
|  * @param {*} name optional name of the cookie |  | ||||||
|  */ |  | ||||||
| export function getCookieConsentValue(name?: string): string; |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * Reset the consent cookie |  | ||||||
|  * Remove the cookie on browser in order to allow user to change their consent |  | ||||||
|  * @param {*} name optional name of the cookie |  | ||||||
|  */ |  | ||||||
| export function resetCookieConsentValue(name?: string): void; |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * Get the legacy cookie name by the regular cookie name |  | ||||||
|  * @param {string} name of cookie to get |  | ||||||
|  */ |  | ||||||
| export function getLegacyCookieName(name: string): string; |  | ||||||
|  |  | ||||||
| export { Cookies }; |  | ||||||
							
								
								
									
										503
									
								
								src/index.js
									
									
									
									
									
								
							
							
						
						
									
										503
									
								
								src/index.js
									
									
									
									
									
								
							| @@ -1,503 +0,0 @@ | |||||||
| import React, { Component } from "react"; |  | ||||||
| import PropTypes from "prop-types"; |  | ||||||
| import Cookies from "js-cookie"; |  | ||||||
|  |  | ||||||
| export const OPTIONS = { |  | ||||||
|   TOP: "top", |  | ||||||
|   BOTTOM: "bottom", |  | ||||||
|   NONE: "none", |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| export const SAME_SITE_OPTIONS = { |  | ||||||
|   STRICT: "strict", |  | ||||||
|   LAX: "lax", |  | ||||||
|   NONE: "none", |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| export const VISIBLE_OPTIONS = { |  | ||||||
|   HIDDEN: "hidden", |  | ||||||
|   SHOW: "show", |  | ||||||
|   BY_COOKIE_VALUE: "byCookieValue", |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * Returns the value of the consent cookie |  | ||||||
|  * Retrieves the regular value first and if not found the legacy one according |  | ||||||
|  * to: https://web.dev/samesite-cookie-recipes/#handling-incompatible-clients |  | ||||||
|  * @param {*} name optional name of the cookie |  | ||||||
|  */ |  | ||||||
| export const getCookieConsentValue = (name = defaultCookieConsentName) => { |  | ||||||
|   let cookieValue = Cookies.get(name); |  | ||||||
|  |  | ||||||
|   // if the cookieValue is undefined check for the legacy cookie |  | ||||||
|   if (cookieValue === undefined) { |  | ||||||
|     cookieValue = Cookies.get(getLegacyCookieName(name)); |  | ||||||
|   } |  | ||||||
|   return cookieValue; |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * Reset the consent cookie |  | ||||||
|  * Remove the cookie on browser in order to allow user to change their consent |  | ||||||
|  * @param {*} name optional name of the cookie |  | ||||||
|  */ |  | ||||||
| export const resetCookieConsentValue = (name = defaultCookieConsentName) => { |  | ||||||
|   Cookies.remove(name); |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * Get the legacy cookie name by the regular cookie name |  | ||||||
|  * @param {string} name of cookie to get |  | ||||||
|  */ |  | ||||||
| const getLegacyCookieName = (name) => { |  | ||||||
|   return `${name}-legacy`; |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * Default name of the cookie which is set by CookieConsent |  | ||||||
|  */ |  | ||||||
| const defaultCookieConsentName = "CookieConsent"; |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * A function to wrap elements with a "wrapper" on a condition |  | ||||||
|  * @param {object} wrappingOptions |  | ||||||
|  *  condition == boolean condition, when to wrap |  | ||||||
|  *  wrapper == style to wrap. e.g <div>{children}</div> |  | ||||||
|  *  children == react passes whatever is between tags as children. Don't supply this yourself. |  | ||||||
|  */ |  | ||||||
| const ConditionalWrapper = ({ condition, wrapper, children }) => { |  | ||||||
|   return condition ? wrapper(children) : children; |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| class CookieConsent extends Component { |  | ||||||
|   constructor(props) { |  | ||||||
|     super(props); |  | ||||||
|  |  | ||||||
|     this.state = { |  | ||||||
|       visible: false, |  | ||||||
|       style: { |  | ||||||
|         alignItems: "baseline", |  | ||||||
|         background: "#353535", |  | ||||||
|         color: "white", |  | ||||||
|         display: "flex", |  | ||||||
|         flexWrap: "wrap", |  | ||||||
|         justifyContent: "space-between", |  | ||||||
|         left: "0", |  | ||||||
|         position: "fixed", |  | ||||||
|         width: "100%", |  | ||||||
|         zIndex: "999", |  | ||||||
|       }, |  | ||||||
|       buttonStyle: { |  | ||||||
|         background: "#ffd42d", |  | ||||||
|         border: "0", |  | ||||||
|         borderRadius: "0px", |  | ||||||
|         boxShadow: "none", |  | ||||||
|         color: "black", |  | ||||||
|         cursor: "pointer", |  | ||||||
|         flex: "0 0 auto", |  | ||||||
|         padding: "5px 10px", |  | ||||||
|         margin: "15px", |  | ||||||
|       }, |  | ||||||
|       declineButtonStyle: { |  | ||||||
|         background: "#c12a2a", |  | ||||||
|         border: "0", |  | ||||||
|         borderRadius: "0px", |  | ||||||
|         boxShadow: "none", |  | ||||||
|         color: "#e5e5e5", |  | ||||||
|         cursor: "pointer", |  | ||||||
|         flex: "0 0 auto", |  | ||||||
|         padding: "5px 10px", |  | ||||||
|         margin: "15px", |  | ||||||
|       }, |  | ||||||
|       contentStyle: { |  | ||||||
|         flex: "1 0 300px", |  | ||||||
|         margin: "15px", |  | ||||||
|       }, |  | ||||||
|       overlayStyle: { |  | ||||||
|         position: "fixed", |  | ||||||
|         left: 0, |  | ||||||
|         top: 0, |  | ||||||
|         width: "100%", |  | ||||||
|         height: "100%", |  | ||||||
|         zIndex: "999", |  | ||||||
|         backgroundColor: "rgba(0,0,0,0.3)", |  | ||||||
|       }, |  | ||||||
|     }; |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   componentDidMount() { |  | ||||||
|     const { debug } = this.props; |  | ||||||
|  |  | ||||||
|     // if cookie undefined or debug |  | ||||||
|     if (this.getCookieValue() === undefined || debug) { |  | ||||||
|       this.setState({ visible: true }); |  | ||||||
|       // if acceptOnScroll is set to true and (cookie is undefined or debug is set to true), add a listener. |  | ||||||
|       if (this.props.acceptOnScroll) { |  | ||||||
|         window.addEventListener("scroll", this.handleScroll, { passive: true }); |  | ||||||
|       } |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   componentWillUnmount() { |  | ||||||
|     // remove listener if still set |  | ||||||
|     this.removeScrollListener(); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   /** |  | ||||||
|    * Set a persistent accept cookie |  | ||||||
|    */ |  | ||||||
|   accept(acceptedByScrolling = false) { |  | ||||||
|     const { cookieName, cookieValue, hideOnAccept, onAccept } = this.props; |  | ||||||
|  |  | ||||||
|     this.setCookie(cookieName, cookieValue); |  | ||||||
|  |  | ||||||
|     onAccept(acceptedByScrolling ?? false); |  | ||||||
|  |  | ||||||
|     if (hideOnAccept) { |  | ||||||
|       this.setState({ visible: false }); |  | ||||||
|       this.removeScrollListener(); |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   /** |  | ||||||
|    * Handle a click on the overlay |  | ||||||
|    */ |  | ||||||
|   overlayClick() { |  | ||||||
|     const { acceptOnOverlayClick, onOverlayClick } = this.props; |  | ||||||
|     if (acceptOnOverlayClick) { |  | ||||||
|       this.accept(); |  | ||||||
|     } |  | ||||||
|     onOverlayClick(); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   /** |  | ||||||
|    * Set a persistent decline cookie |  | ||||||
|    */ |  | ||||||
|   decline() { |  | ||||||
|     const { cookieName, declineCookieValue, hideOnDecline, onDecline, setDeclineCookie } = |  | ||||||
|       this.props; |  | ||||||
|  |  | ||||||
|     if (setDeclineCookie) { |  | ||||||
|       this.setCookie(cookieName, declineCookieValue); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     onDecline(); |  | ||||||
|  |  | ||||||
|     if (hideOnDecline) { |  | ||||||
|       this.setState({ visible: false }); |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   /** |  | ||||||
|    * Function to set the consent cookie based on the provided variables |  | ||||||
|    * Sets two cookies to handle incompatible browsers, more details: |  | ||||||
|    * https://web.dev/samesite-cookie-recipes/#handling-incompatible-clients |  | ||||||
|    */ |  | ||||||
|   setCookie(cookieName, cookieValue) { |  | ||||||
|     const { extraCookieOptions, expires, sameSite } = this.props; |  | ||||||
|     let { cookieSecurity } = this.props; |  | ||||||
|  |  | ||||||
|     if (cookieSecurity === undefined) { |  | ||||||
|       cookieSecurity = location ? location.protocol === "https:" : true; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     let cookieOptions = { expires, ...extraCookieOptions, sameSite, secure: cookieSecurity }; |  | ||||||
|  |  | ||||||
|     // Fallback for older browsers where can not set SameSite=None, SEE: https://web.dev/samesite-cookie-recipes/#handling-incompatible-clients |  | ||||||
|     if (sameSite === SAME_SITE_OPTIONS.NONE) { |  | ||||||
|       Cookies.set(getLegacyCookieName(cookieName), cookieValue, cookieOptions); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     // set the regular cookie |  | ||||||
|     Cookies.set(cookieName, cookieValue, cookieOptions); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   /** |  | ||||||
|    * Returns the value of the consent cookie |  | ||||||
|    * Retrieves the regular value first and if not found the legacy one according |  | ||||||
|    * to: https://web.dev/samesite-cookie-recipes/#handling-incompatible-clients |  | ||||||
|    */ |  | ||||||
|   getCookieValue() { |  | ||||||
|     const { cookieName } = this.props; |  | ||||||
|     return getCookieConsentValue(cookieName); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   /** |  | ||||||
|    * checks whether scroll has exceeded set amount and fire accept if so. |  | ||||||
|    */ |  | ||||||
|   handleScroll = () => { |  | ||||||
|     const { acceptOnScrollPercentage } = this.props; |  | ||||||
|  |  | ||||||
|     // (top / height) - height * 100 |  | ||||||
|     let rootNode = document.documentElement, |  | ||||||
|       body = document.body, |  | ||||||
|       top = "scrollTop", |  | ||||||
|       height = "scrollHeight"; |  | ||||||
|  |  | ||||||
|     let percentage = |  | ||||||
|       ((rootNode[top] || body[top]) / |  | ||||||
|         ((rootNode[height] || body[height]) - rootNode.clientHeight)) * |  | ||||||
|       100; |  | ||||||
|  |  | ||||||
|     if (percentage > acceptOnScrollPercentage) { |  | ||||||
|       this.accept(true); |  | ||||||
|     } |  | ||||||
|   }; |  | ||||||
|  |  | ||||||
|   removeScrollListener = () => { |  | ||||||
|     const { acceptOnScroll } = this.props; |  | ||||||
|     if (acceptOnScroll) { |  | ||||||
|       window.removeEventListener("scroll", this.handleScroll); |  | ||||||
|     } |  | ||||||
|   }; |  | ||||||
|  |  | ||||||
|   render() { |  | ||||||
|     // If the bar shouldn't be visible don't render anything. |  | ||||||
|     switch (this.props.visible) { |  | ||||||
|       case VISIBLE_OPTIONS.HIDDEN: |  | ||||||
|         return null; |  | ||||||
|       case VISIBLE_OPTIONS.BY_COOKIE_VALUE: |  | ||||||
|         if (!this.state.visible) { |  | ||||||
|           return null; |  | ||||||
|         } |  | ||||||
|         break; |  | ||||||
|       default: |  | ||||||
|         break; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     const { |  | ||||||
|       location, |  | ||||||
|       style, |  | ||||||
|       buttonStyle, |  | ||||||
|       declineButtonStyle, |  | ||||||
|       contentStyle, |  | ||||||
|       disableStyles, |  | ||||||
|       buttonText, |  | ||||||
|       declineButtonText, |  | ||||||
|       containerClasses, |  | ||||||
|       contentClasses, |  | ||||||
|       buttonClasses, |  | ||||||
|       buttonWrapperClasses, |  | ||||||
|       declineButtonClasses, |  | ||||||
|       buttonId, |  | ||||||
|       declineButtonId, |  | ||||||
|       disableButtonStyles, |  | ||||||
|       enableDeclineButton, |  | ||||||
|       flipButtons, |  | ||||||
|       ButtonComponent, |  | ||||||
|       overlay, |  | ||||||
|       overlayClasses, |  | ||||||
|       overlayStyle, |  | ||||||
|       ariaAcceptLabel, |  | ||||||
|       ariaDeclineLabel, |  | ||||||
|       customContainerAttributes, |  | ||||||
|       customContentAttributes, |  | ||||||
|       customButtonProps, |  | ||||||
|     } = this.props; |  | ||||||
|  |  | ||||||
|     let myStyle = {}; |  | ||||||
|     let myButtonStyle = {}; |  | ||||||
|     let myDeclineButtonStyle = {}; |  | ||||||
|     let myContentStyle = {}; |  | ||||||
|     let myOverlayStyle = {}; |  | ||||||
|  |  | ||||||
|     if (disableStyles) { |  | ||||||
|       // if styles are disabled use the provided styles (or none) |  | ||||||
|       myStyle = Object.assign({}, style); |  | ||||||
|       myButtonStyle = Object.assign({}, buttonStyle); |  | ||||||
|       myDeclineButtonStyle = Object.assign({}, declineButtonStyle); |  | ||||||
|       myContentStyle = Object.assign({}, contentStyle); |  | ||||||
|       myOverlayStyle = Object.assign({}, overlayStyle); |  | ||||||
|     } else { |  | ||||||
|       // if styles aren't disabled merge them with the styles that are provided (or use default styles) |  | ||||||
|       myStyle = Object.assign({}, { ...this.state.style, ...style }); |  | ||||||
|       myContentStyle = Object.assign({}, { ...this.state.contentStyle, ...contentStyle }); |  | ||||||
|       myOverlayStyle = Object.assign({}, { ...this.state.overlayStyle, ...overlayStyle }); |  | ||||||
|  |  | ||||||
|       // switch to disable JUST the button styles |  | ||||||
|       if (disableButtonStyles) { |  | ||||||
|         myButtonStyle = Object.assign({}, buttonStyle); |  | ||||||
|         myDeclineButtonStyle = Object.assign({}, declineButtonStyle); |  | ||||||
|       } else { |  | ||||||
|         myButtonStyle = Object.assign({}, { ...this.state.buttonStyle, ...buttonStyle }); |  | ||||||
|         myDeclineButtonStyle = Object.assign( |  | ||||||
|           {}, |  | ||||||
|           { ...this.state.declineButtonStyle, ...declineButtonStyle } |  | ||||||
|         ); |  | ||||||
|       } |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     // syntactic sugar to enable user to easily select top / bottom |  | ||||||
|     switch (location) { |  | ||||||
|       case OPTIONS.TOP: |  | ||||||
|         myStyle.top = "0"; |  | ||||||
|         break; |  | ||||||
|  |  | ||||||
|       case OPTIONS.BOTTOM: |  | ||||||
|         myStyle.bottom = "0"; |  | ||||||
|         break; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     const buttonsToRender = []; |  | ||||||
|  |  | ||||||
|     // add decline button |  | ||||||
|     enableDeclineButton && |  | ||||||
|       buttonsToRender.push( |  | ||||||
|         <ButtonComponent |  | ||||||
|           key="declineButton" |  | ||||||
|           style={myDeclineButtonStyle} |  | ||||||
|           className={declineButtonClasses} |  | ||||||
|           id={declineButtonId} |  | ||||||
|           aria-label={ariaDeclineLabel} |  | ||||||
|           onClick={() => { |  | ||||||
|             this.decline(); |  | ||||||
|           }} |  | ||||||
|         > |  | ||||||
|           {declineButtonText} |  | ||||||
|         </ButtonComponent> |  | ||||||
|       ); |  | ||||||
|  |  | ||||||
|     // add accept button |  | ||||||
|     buttonsToRender.push( |  | ||||||
|       <ButtonComponent |  | ||||||
|         {...customButtonProps} |  | ||||||
|         key="acceptButton" |  | ||||||
|         style={myButtonStyle} |  | ||||||
|         className={buttonClasses} |  | ||||||
|         id={buttonId} |  | ||||||
|         aria-label={ariaAcceptLabel} |  | ||||||
|         onClick={() => { |  | ||||||
|           this.accept(); |  | ||||||
|         }} |  | ||||||
|       > |  | ||||||
|         {buttonText} |  | ||||||
|       </ButtonComponent> |  | ||||||
|     ); |  | ||||||
|  |  | ||||||
|     if (flipButtons) { |  | ||||||
|       buttonsToRender.reverse(); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     return ( |  | ||||||
|       <ConditionalWrapper |  | ||||||
|         condition={overlay} |  | ||||||
|         wrapper={(children) => ( |  | ||||||
|           <div |  | ||||||
|             style={myOverlayStyle} |  | ||||||
|             className={overlayClasses} |  | ||||||
|             onClick={() => { |  | ||||||
|               this.overlayClick(); |  | ||||||
|             }} |  | ||||||
|           > |  | ||||||
|             {children} |  | ||||||
|           </div> |  | ||||||
|         )} |  | ||||||
|       > |  | ||||||
|         <div className={`${containerClasses}`} style={myStyle} {...customContainerAttributes}> |  | ||||||
|           <div style={myContentStyle} className={contentClasses} {...customContentAttributes}> |  | ||||||
|             {this.props.children} |  | ||||||
|           </div> |  | ||||||
|           <div className={`${buttonWrapperClasses}`}> |  | ||||||
|             {buttonsToRender.map((button) => { |  | ||||||
|               return button; |  | ||||||
|             })} |  | ||||||
|           </div> |  | ||||||
|         </div> |  | ||||||
|       </ConditionalWrapper> |  | ||||||
|     ); |  | ||||||
|   } |  | ||||||
| } |  | ||||||
|  |  | ||||||
| CookieConsent.propTypes = { |  | ||||||
|   location: PropTypes.oneOf(Object.keys(OPTIONS).map((key) => OPTIONS[key])), |  | ||||||
|   visible: PropTypes.oneOf(Object.keys(VISIBLE_OPTIONS).map((key) => VISIBLE_OPTIONS[key])), |  | ||||||
|   sameSite: PropTypes.oneOf(Object.keys(SAME_SITE_OPTIONS).map((key) => SAME_SITE_OPTIONS[key])), |  | ||||||
|   style: PropTypes.object, |  | ||||||
|   buttonStyle: PropTypes.object, |  | ||||||
|   declineButtonStyle: PropTypes.object, |  | ||||||
|   contentStyle: PropTypes.object, |  | ||||||
|   children: PropTypes.any, // eslint-disable-line react/forbid-prop-types |  | ||||||
|   disableStyles: PropTypes.bool, |  | ||||||
|   hideOnAccept: PropTypes.bool, |  | ||||||
|   hideOnDecline: PropTypes.bool, |  | ||||||
|   onAccept: PropTypes.func, |  | ||||||
|   onDecline: PropTypes.func, |  | ||||||
|   buttonText: PropTypes.oneOfType([PropTypes.string, PropTypes.func, PropTypes.element]), |  | ||||||
|   declineButtonText: PropTypes.oneOfType([PropTypes.string, PropTypes.func, PropTypes.element]), |  | ||||||
|   cookieName: PropTypes.string, |  | ||||||
|   cookieValue: PropTypes.oneOfType([PropTypes.string, PropTypes.bool, PropTypes.number]), |  | ||||||
|   declineCookieValue: PropTypes.oneOfType([PropTypes.string, PropTypes.bool, PropTypes.number]), |  | ||||||
|   setDeclineCookie: PropTypes.bool, |  | ||||||
|   debug: PropTypes.bool, |  | ||||||
|   expires: PropTypes.number, |  | ||||||
|   containerClasses: PropTypes.string, |  | ||||||
|   contentClasses: PropTypes.string, |  | ||||||
|   buttonClasses: PropTypes.string, |  | ||||||
|   buttonWrapperClasses: PropTypes.string, |  | ||||||
|   declineButtonClasses: PropTypes.string, |  | ||||||
|   buttonId: PropTypes.string, |  | ||||||
|   declineButtonId: PropTypes.string, |  | ||||||
|   extraCookieOptions: PropTypes.object, |  | ||||||
|   disableButtonStyles: PropTypes.bool, |  | ||||||
|   enableDeclineButton: PropTypes.bool, |  | ||||||
|   flipButtons: PropTypes.bool, |  | ||||||
|   ButtonComponent: PropTypes.elementType, |  | ||||||
|   cookieSecurity: PropTypes.bool, |  | ||||||
|   overlay: PropTypes.bool, |  | ||||||
|   overlayClasses: PropTypes.string, |  | ||||||
|   overlayStyle: PropTypes.object, |  | ||||||
|   onOverlayClick: PropTypes.func, |  | ||||||
|   acceptOnOverlayClick: PropTypes.bool, |  | ||||||
|   ariaAcceptLabel: PropTypes.string, |  | ||||||
|   ariaDeclineLabel: PropTypes.string, |  | ||||||
|   acceptOnScroll: PropTypes.bool, |  | ||||||
|   acceptOnScrollPercentage: PropTypes.number, |  | ||||||
|   customContentAttributes: PropTypes.object, |  | ||||||
|   customContainerAttributes: PropTypes.object, |  | ||||||
|   customButtonProps: PropTypes.object, |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| CookieConsent.defaultProps = { |  | ||||||
|   disableStyles: false, |  | ||||||
|   hideOnAccept: true, |  | ||||||
|   hideOnDecline: true, |  | ||||||
|   location: OPTIONS.BOTTOM, |  | ||||||
|   visible: VISIBLE_OPTIONS.BY_COOKIE_VALUE, |  | ||||||
|   onAccept: () => {}, |  | ||||||
|   onDecline: () => {}, |  | ||||||
|   cookieName: defaultCookieConsentName, |  | ||||||
|   cookieValue: true, |  | ||||||
|   declineCookieValue: false, |  | ||||||
|   setDeclineCookie: true, |  | ||||||
|   buttonText: "I understand", |  | ||||||
|   declineButtonText: "I decline", |  | ||||||
|   debug: false, |  | ||||||
|   expires: 365, |  | ||||||
|   containerClasses: "CookieConsent", |  | ||||||
|   contentClasses: "", |  | ||||||
|   buttonClasses: "", |  | ||||||
|   buttonWrapperClasses: "", |  | ||||||
|   declineButtonClasses: "", |  | ||||||
|   buttonId: "rcc-confirm-button", |  | ||||||
|   declineButtonId: "rcc-decline-button", |  | ||||||
|   extraCookieOptions: {}, |  | ||||||
|   disableButtonStyles: false, |  | ||||||
|   enableDeclineButton: false, |  | ||||||
|   flipButtons: false, |  | ||||||
|   sameSite: SAME_SITE_OPTIONS.LAX, |  | ||||||
|   ButtonComponent: ({ children, ...props }) => <button {...props}>{children}</button>, |  | ||||||
|   overlay: false, |  | ||||||
|   overlayClasses: "", |  | ||||||
|   onOverlayClick: () => {}, |  | ||||||
|   acceptOnOverlayClick: false, |  | ||||||
|   ariaAcceptLabel: "Accept cookies", |  | ||||||
|   ariaDeclineLabel: "Decline cookies", |  | ||||||
|   acceptOnScroll: false, |  | ||||||
|   acceptOnScrollPercentage: 25, |  | ||||||
|   customContentAttributes: {}, |  | ||||||
|   customContainerAttributes: {}, |  | ||||||
|   customButtonProps: {}, |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| export default CookieConsent; |  | ||||||
| export { Cookies }; |  | ||||||
							
								
								
									
										11
									
								
								src/index.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								src/index.tsx
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,11 @@ | |||||||
|  | import Cookies from "js-cookie"; | ||||||
|  | import { ConditionalWrapper } from "./components/ConditionalWrapper"; | ||||||
|  | import { CookieConsent } from "./CookieConsent"; | ||||||
|  | import { POSITION_OPTIONS, VISIBILITY_OPTIONS } from "./models/constants"; | ||||||
|  |  | ||||||
|  | export * from "./models/constants"; | ||||||
|  | export * from "./utilities"; | ||||||
|  | export { Cookies, CookieConsent, ConditionalWrapper }; | ||||||
|  | // backwards compatibility exports | ||||||
|  | export { POSITION_OPTIONS as OPTIONS, VISIBILITY_OPTIONS as VISIBLE_OPTIONS }; | ||||||
|  | export default CookieConsent; | ||||||
							
								
								
									
										1
									
								
								src/models/constants/defaultCookieName.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								src/models/constants/defaultCookieName.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1 @@ | |||||||
|  | export const defaultCookieConsentName = "CookieConsent"; | ||||||
							
								
								
									
										4
									
								
								src/models/constants/index.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								src/models/constants/index.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,4 @@ | |||||||
|  | export * from "./positionOptions"; | ||||||
|  | export * from "./sameSiteOptions"; | ||||||
|  | export * from "./visibilityOptions"; | ||||||
|  | export * from "./defaultCookieName"; | ||||||
							
								
								
									
										5
									
								
								src/models/constants/positionOptions.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								src/models/constants/positionOptions.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,5 @@ | |||||||
|  | export const POSITION_OPTIONS = { | ||||||
|  |   TOP: "top", | ||||||
|  |   BOTTOM: "bottom", | ||||||
|  |   NONE: "none", | ||||||
|  | }; | ||||||
							
								
								
									
										5
									
								
								src/models/constants/sameSiteOptions.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								src/models/constants/sameSiteOptions.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,5 @@ | |||||||
|  | export enum SAME_SITE_OPTIONS { | ||||||
|  |   STRICT = "strict", | ||||||
|  |   LAX = "lax", | ||||||
|  |   NONE = "none", | ||||||
|  | } | ||||||
							
								
								
									
										5
									
								
								src/models/constants/visibilityOptions.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								src/models/constants/visibilityOptions.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,5 @@ | |||||||
|  | export const VISIBILITY_OPTIONS = { | ||||||
|  |   HIDDEN: "hidden", | ||||||
|  |   SHOW: "show", | ||||||
|  |   BY_COOKIE_VALUE: "byCookieValue", | ||||||
|  | }; | ||||||
							
								
								
									
										35
									
								
								src/utilities.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								src/utilities.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,35 @@ | |||||||
|  | import Cookies from "js-cookie"; | ||||||
|  | import { defaultCookieConsentName } from "./models/constants"; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Returns the value of the consent cookie | ||||||
|  |  * Retrieves the regular value first and if not found the legacy one according | ||||||
|  |  * to: https://web.dev/samesite-cookie-recipes/#handling-incompatible-clients | ||||||
|  |  * @param {*} name optional name of the cookie | ||||||
|  |  */ | ||||||
|  | export const getCookieConsentValue = (name = defaultCookieConsentName) => { | ||||||
|  |   const cookieValue = Cookies.get(name); | ||||||
|  |  | ||||||
|  |   // if the cookieValue is undefined check for the legacy cookie | ||||||
|  |   if (cookieValue === undefined) { | ||||||
|  |     return Cookies.get(getLegacyCookieName(name)); | ||||||
|  |   } | ||||||
|  |   return cookieValue; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Reset the consent cookie | ||||||
|  |  * Remove the cookie on browser in order to allow user to change their consent | ||||||
|  |  * @param {*} name optional name of the cookie | ||||||
|  |  */ | ||||||
|  | export const resetCookieConsentValue = (name = defaultCookieConsentName) => { | ||||||
|  |   Cookies.remove(name); | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Get the legacy cookie name by the regular cookie name | ||||||
|  |  * @param {string} name of cookie to get | ||||||
|  |  */ | ||||||
|  | export const getLegacyCookieName = (name: string) => { | ||||||
|  |   return `${name}-legacy`; | ||||||
|  | }; | ||||||
							
								
								
									
										11
									
								
								stories/defaults/intro.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								stories/defaults/intro.tsx
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,11 @@ | |||||||
|  | import { FunctionComponent } from "react"; | ||||||
|  |  | ||||||
|  | type Props = {}; | ||||||
|  |  | ||||||
|  | export const Intro: FunctionComponent<Props> = () => { | ||||||
|  |   return ( | ||||||
|  |     <h1> | ||||||
|  |       <p>Debug is turned on for all stories so that the bar always shows up</p> | ||||||
|  |     </h1> | ||||||
|  |   ); | ||||||
|  | }; | ||||||
							
								
								
									
										3
									
								
								stories/defaults/storyProps.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								stories/defaults/storyProps.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,3 @@ | |||||||
|  | import { CookieConsentProps, defaultCookieConsentProps } from "../../src/CookieConsent.props"; | ||||||
|  |  | ||||||
|  | export const defaultStoryProps: CookieConsentProps = { ...defaultCookieConsentProps, debug: true }; | ||||||
							
								
								
									
										13
									
								
								stories/defaults/template.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								stories/defaults/template.tsx
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,13 @@ | |||||||
|  | import { Story } from "@storybook/react"; | ||||||
|  | import CookieConsent from "../../src"; | ||||||
|  | import { Intro } from "./intro"; | ||||||
|  |  | ||||||
|  | export const DefaultTemplate: Story<any> = (args) => ( | ||||||
|  |   <> | ||||||
|  |     <Intro /> | ||||||
|  |     <CookieConsent {...args}> | ||||||
|  |       This website uses cookies to enhance the user experience. | ||||||
|  |       <span style={{ fontSize: "10px" }}>This bit of text is smaller :O</span> | ||||||
|  |     </CookieConsent> | ||||||
|  |   </> | ||||||
|  | ); | ||||||
							
								
								
									
										34
									
								
								stories/index.stories.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								stories/index.stories.tsx
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,34 @@ | |||||||
|  | import { Meta } from "@storybook/react"; | ||||||
|  | import { CookieConsent } from "../src"; | ||||||
|  | import { defaultStoryProps } from "./defaults/storyProps"; | ||||||
|  | import { DefaultTemplate } from "./defaults/template"; | ||||||
|  |  | ||||||
|  | const meta: Meta = { | ||||||
|  |   title: "CookieConsent", | ||||||
|  |   component: CookieConsent, | ||||||
|  |   argTypes: { | ||||||
|  |     children: { | ||||||
|  |       control: { | ||||||
|  |         type: "text", | ||||||
|  |       }, | ||||||
|  |     }, | ||||||
|  |   }, | ||||||
|  |   parameters: { | ||||||
|  |     controls: { expanded: true }, | ||||||
|  |   }, | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | export default meta; | ||||||
|  |  | ||||||
|  | export const Default = DefaultTemplate.bind({}); | ||||||
|  | Default.args = defaultStoryProps; | ||||||
|  |  | ||||||
|  | // stories | ||||||
|  | export * from "./stories/acceptOnScroll.story"; | ||||||
|  | export * from "./stories/additionalButtons.story"; | ||||||
|  | export * from "./stories/customStyling.story"; | ||||||
|  | export * from "./stories/flippedButtons.story"; | ||||||
|  | export * from "./stories/muiButtons.story"; | ||||||
|  | export * from "./stories/onAccept.story"; | ||||||
|  | export * from "./stories/overlay.story"; | ||||||
|  | export * from "./stories/rainbows.story"; | ||||||
							
								
								
									
										34
									
								
								stories/stories/acceptOnScroll.story.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								stories/stories/acceptOnScroll.story.tsx
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,34 @@ | |||||||
|  | import { Story } from "@storybook/react"; | ||||||
|  | import CookieConsent from "../../src"; | ||||||
|  | import { CookieConsentProps } from "../../src/CookieConsent.props"; | ||||||
|  | import { Intro } from "../defaults/intro"; | ||||||
|  | import { defaultStoryProps } from "../defaults/storyProps"; | ||||||
|  |  | ||||||
|  | const AcceptOnScrollTemplate: Story<any> = (args) => ( | ||||||
|  |   <> | ||||||
|  |     <Intro /> | ||||||
|  |     {Array.from(Array(25).keys()).map((_something) => ( | ||||||
|  |       <p> | ||||||
|  |         Lorem ipsum dolor sit, amet consectetur adipisicing elit. Voluptates ipsa sequi soluta | ||||||
|  |         mollitia illum, hic quaerat ipsum sint odit delectus magni neque sunt adipisci culpa harum | ||||||
|  |         aut distinctio quisquam ab! | ||||||
|  |       </p> | ||||||
|  |     ))} | ||||||
|  |  | ||||||
|  |     <CookieConsent {...args}> | ||||||
|  |       Scroll for {args.acceptOnScrollPercentage}% and the onAccept will trigger | ||||||
|  |     </CookieConsent> | ||||||
|  |   </> | ||||||
|  | ); | ||||||
|  |  | ||||||
|  | const AcceptOnScroll = AcceptOnScrollTemplate.bind({}); | ||||||
|  | AcceptOnScroll.args = { | ||||||
|  |   ...defaultStoryProps, | ||||||
|  |   onAccept: (acceptedByScrolling) => { | ||||||
|  |     alert(`ACCEPTED! By scrolling? ${JSON.stringify(acceptedByScrolling)}`); | ||||||
|  |   }, | ||||||
|  |   acceptOnScroll: true, | ||||||
|  |   acceptOnScrollPercentage: 25, | ||||||
|  | } as CookieConsentProps; | ||||||
|  |  | ||||||
|  | export { AcceptOnScroll }; | ||||||
							
								
								
									
										17
									
								
								stories/stories/additionalButtons.story.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								stories/stories/additionalButtons.story.tsx
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,17 @@ | |||||||
|  | import { Story } from "@storybook/react"; | ||||||
|  | import CookieConsent from "../../src"; | ||||||
|  | import { Intro } from "../defaults/intro"; | ||||||
|  | import { defaultStoryProps } from "../defaults/storyProps"; | ||||||
|  |  | ||||||
|  | const AdditionalButtonsTemplate: Story<any> = (args) => ( | ||||||
|  |   <> | ||||||
|  |     <Intro /> | ||||||
|  |     <CookieConsent {...args}> | ||||||
|  |       <button style={{ color: "gray" }}>I am a custom config button</button> | ||||||
|  |       <span style={{ fontSize: "10px" }}>This bit of text is smaller :O</span> | ||||||
|  |     </CookieConsent> | ||||||
|  |   </> | ||||||
|  | ); | ||||||
|  | const AdditionalButtons = AdditionalButtonsTemplate.bind({}); | ||||||
|  | AdditionalButtons.args = defaultStoryProps; | ||||||
|  | export { AdditionalButtons }; | ||||||
							
								
								
									
										12
									
								
								stories/stories/customStyling.story.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								stories/stories/customStyling.story.tsx
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,12 @@ | |||||||
|  | import { CookieConsentProps } from "../../src/CookieConsent.props"; | ||||||
|  | import { defaultStoryProps } from "../defaults/storyProps"; | ||||||
|  | import { DefaultTemplate } from "../defaults/template"; | ||||||
|  |  | ||||||
|  | const CustomStyling = DefaultTemplate.bind({}); | ||||||
|  | CustomStyling.args = { | ||||||
|  |   ...defaultStoryProps, | ||||||
|  |   style: { background: "red" }, | ||||||
|  |   buttonStyle: { fontWeight: "bold" }, | ||||||
|  | } as CookieConsentProps; | ||||||
|  |  | ||||||
|  | export { CustomStyling }; | ||||||
							
								
								
									
										12
									
								
								stories/stories/flippedButtons.story.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								stories/stories/flippedButtons.story.tsx
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,12 @@ | |||||||
|  | import { CookieConsentProps } from "../../src/CookieConsent.props"; | ||||||
|  | import { defaultStoryProps } from "../defaults/storyProps"; | ||||||
|  | import { DefaultTemplate } from "../defaults/template"; | ||||||
|  |  | ||||||
|  | const FlippedButtons = DefaultTemplate.bind({}); | ||||||
|  | FlippedButtons.args = { | ||||||
|  |   ...defaultStoryProps, | ||||||
|  |   flipButtons: true, | ||||||
|  |   enableDeclineButton: true, | ||||||
|  | } as CookieConsentProps; | ||||||
|  |  | ||||||
|  | export { FlippedButtons }; | ||||||
							
								
								
									
										14
									
								
								stories/stories/muiButtons.story.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								stories/stories/muiButtons.story.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,14 @@ | |||||||
|  | import { Button } from "@mui/material"; | ||||||
|  | import { CookieConsentProps } from "../../src/CookieConsent.props"; | ||||||
|  | import { defaultStoryProps } from "../defaults/storyProps"; | ||||||
|  | import { DefaultTemplate } from "../defaults/template"; | ||||||
|  |  | ||||||
|  | const CustomMuiButton = DefaultTemplate.bind({}); | ||||||
|  | CustomMuiButton.args = { | ||||||
|  |   ...defaultStoryProps, | ||||||
|  |   disableButtonStyles: true, | ||||||
|  |   ButtonComponent: Button, | ||||||
|  |   customButtonProps: { variant: "contained", style: { marginRight: "10px" } }, | ||||||
|  | } as CookieConsentProps; | ||||||
|  |  | ||||||
|  | export { CustomMuiButton }; | ||||||
							
								
								
									
										13
									
								
								stories/stories/onAccept.story.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								stories/stories/onAccept.story.tsx
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,13 @@ | |||||||
|  | import { CookieConsentProps } from "../../src/CookieConsent.props"; | ||||||
|  | import { defaultStoryProps } from "../defaults/storyProps"; | ||||||
|  | import { DefaultTemplate } from "../defaults/template"; | ||||||
|  |  | ||||||
|  | const CustomOnAccept = DefaultTemplate.bind({}); | ||||||
|  | CustomOnAccept.args = { | ||||||
|  |   ...defaultStoryProps, | ||||||
|  |   onAccept: (acceptedByScrolling) => { | ||||||
|  |     alert(`ACCEPTED! By scrolling? ${JSON.stringify(acceptedByScrolling)}`); | ||||||
|  |   }, | ||||||
|  | } as CookieConsentProps; | ||||||
|  |  | ||||||
|  | export { CustomOnAccept }; | ||||||
							
								
								
									
										11
									
								
								stories/stories/overlay.story.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								stories/stories/overlay.story.tsx
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,11 @@ | |||||||
|  | import { CookieConsentProps } from "../../src/CookieConsent.props"; | ||||||
|  | import { defaultStoryProps } from "../defaults/storyProps"; | ||||||
|  | import { DefaultTemplate } from "../defaults/template"; | ||||||
|  |  | ||||||
|  | const Overlay = DefaultTemplate.bind({}); | ||||||
|  | Overlay.args = { | ||||||
|  |   ...defaultStoryProps, | ||||||
|  |   overlay: true, | ||||||
|  | } as CookieConsentProps; | ||||||
|  |  | ||||||
|  | export { Overlay }; | ||||||
							
								
								
									
										22
									
								
								stories/stories/rainbows.story.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								stories/stories/rainbows.story.tsx
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,22 @@ | |||||||
|  | import { CookieConsentProps } from "../../src/CookieConsent.props"; | ||||||
|  | import { defaultStoryProps } from "../defaults/storyProps"; | ||||||
|  | import { DefaultTemplate } from "../defaults/template"; | ||||||
|  |  | ||||||
|  | const Rainbows = DefaultTemplate.bind({}); | ||||||
|  | Rainbows.args = { | ||||||
|  |   ...defaultStoryProps, | ||||||
|  |   buttonText: "OMG DOUBLE RAINBOW", | ||||||
|  |  | ||||||
|  |   style: { | ||||||
|  |     background: "linear-gradient(to right, orange , yellow, green, cyan, blue, violet)", | ||||||
|  |     textShadow: "2px 2px black", | ||||||
|  |   }, | ||||||
|  |   buttonStyle: { | ||||||
|  |     background: "linear-gradient(to left, orange , yellow, green, cyan, blue, violet)", | ||||||
|  |     color: "white", | ||||||
|  |     fontWeight: "bolder", | ||||||
|  |     textShadow: "2px 2px black", | ||||||
|  |   }, | ||||||
|  | } as CookieConsentProps; | ||||||
|  |  | ||||||
|  | export { Rainbows }; | ||||||
							
								
								
									
										35
									
								
								tsconfig.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								tsconfig.json
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,35 @@ | |||||||
|  | { | ||||||
|  |   // see https://www.typescriptlang.org/tsconfig to better understand tsconfigs | ||||||
|  |   "include": ["src", "types"], | ||||||
|  |   "compilerOptions": { | ||||||
|  |     "module": "esnext", | ||||||
|  |     "lib": ["dom", "esnext"], | ||||||
|  |     "importHelpers": true, | ||||||
|  |     // output .d.ts declaration files for consumers | ||||||
|  |     "declaration": true, | ||||||
|  |     // output .js.map sourcemap files for consumers | ||||||
|  |     "sourceMap": true, | ||||||
|  |     // match output dir to input dir. e.g. dist/index instead of dist/src/index | ||||||
|  |     "rootDir": "./src", | ||||||
|  |     // stricter type-checking for stronger correctness. Recommended by TS | ||||||
|  |     "strict": true, | ||||||
|  |     // linter checks for common issues | ||||||
|  |     "noImplicitReturns": true, | ||||||
|  |     "noFallthroughCasesInSwitch": true, | ||||||
|  |     // noUnused* overlap with @typescript-eslint/no-unused-vars, can disable if duplicative | ||||||
|  |     "noUnusedLocals": true, | ||||||
|  |     "noUnusedParameters": true, | ||||||
|  |     // use Node's module resolution algorithm, instead of the legacy TS one | ||||||
|  |     "moduleResolution": "node", | ||||||
|  |     // transpile JSX to React.createElement | ||||||
|  |     "jsx": "react", | ||||||
|  |     // interop between ESM and CJS modules. Recommended by TS | ||||||
|  |     "esModuleInterop": true, | ||||||
|  |     // significant perf increase by skipping checking .d.ts files, particularly those in node_modules. Recommended by TS | ||||||
|  |     "skipLibCheck": true, | ||||||
|  |     // error out if import and file system have a casing mismatch. Recommended by TS | ||||||
|  |     "forceConsistentCasingInFileNames": true, | ||||||
|  |     // `tsdx build` ignores this option, but it is commonly used when type-checking separately with `tsc` | ||||||
|  |     "noEmit": true, | ||||||
|  |   } | ||||||
|  | } | ||||||
| @@ -1,37 +0,0 @@ | |||||||
| var path = require("path"); |  | ||||||
| var CopyWebpackPlugin = require("copy-webpack-plugin"); |  | ||||||
|  |  | ||||||
| module.exports = { |  | ||||||
|   entry: "./src/index.js", |  | ||||||
|   output: { |  | ||||||
|     path: path.resolve(__dirname, "build"), |  | ||||||
|     filename: "index.js", |  | ||||||
|     library: { |  | ||||||
|       name: "ReactCookieConsent", |  | ||||||
|       type: "umd", |  | ||||||
|     }, |  | ||||||
|     environment: { |  | ||||||
|       arrowFunction: false, // the generated runtime-code should not use arrow functions |  | ||||||
|     }, |  | ||||||
|     globalObject: `typeof self !== 'undefined' ? self : this`, |  | ||||||
|   }, |  | ||||||
|   module: { |  | ||||||
|     rules: [ |  | ||||||
|       { |  | ||||||
|         test: /\.js$/, |  | ||||||
|         include: path.resolve(__dirname, "src"), |  | ||||||
|         exclude: /(node_modules|build)/, |  | ||||||
|         use: { |  | ||||||
|           loader: "babel-loader", |  | ||||||
|           options: { |  | ||||||
|             presets: ["@babel/preset-env"], |  | ||||||
|           }, |  | ||||||
|         }, |  | ||||||
|       }, |  | ||||||
|     ], |  | ||||||
|   }, |  | ||||||
|   externals: { |  | ||||||
|     react: "commonjs react", // this line is just to use the React dependency of our parent-testing-project instead of using our own React. |  | ||||||
|   }, |  | ||||||
|   plugins: [new CopyWebpackPlugin({ patterns: [{ from: "src/index.d.ts", to: "index.d.ts" }] })], |  | ||||||
| }; |  | ||||||
		Reference in New Issue
	
	Block a user