diff --git a/.eslintrc.js b/.eslintrc.js
new file mode 100644
index 0000000..724f1bb
--- /dev/null
+++ b/.eslintrc.js
@@ -0,0 +1,6 @@
+/** @type {import("eslint").Linter.Config} */
+module.exports = {
+ env: {
+ es6: true
+ }
+}
diff --git a/.github/workflows/check-linter.yaml b/.github/workflows/check-linter.yaml
index d33ef55..0af1c09 100644
--- a/.github/workflows/check-linter.yaml
+++ b/.github/workflows/check-linter.yaml
@@ -6,8 +6,16 @@ jobs:
linter:
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v2
+ - uses: actions/checkout@v3
+ - uses: pnpm/action-setup@fe02b34f77f8bc703788d5817da081398fad5dd2 # pin@v4.0.0
+
+ - name: Install Nodejs
+ uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # pin@v4.0.2
+ with:
+ node-version: '18'
+ cache: 'pnpm'
+
- name: Install modules
- run: yarn
+ run: pnpm i
- name: Run Prettier ESLint check
- run: yarn lint
+ run: pnpm lint
diff --git a/.github/workflows/monorepo-package-release.yml b/.github/workflows/monorepo-package-release.yml
new file mode 100644
index 0000000..8d1a1ba
--- /dev/null
+++ b/.github/workflows/monorepo-package-release.yml
@@ -0,0 +1,125 @@
+name: Notification Manager package release
+
+on:
+ push:
+ tags:
+ - 'react-cookie-manager@[0-9]+.[0-9]+.[0-9]+'
+ - 'sveltekit-cookie-manager@[0-9]+.[0-9]+.[0-9]+'
+
+jobs:
+ publish-npm-package:
+ outputs:
+ library_dir: ${{ steps.detect_tag.outputs.library_dir }}
+ tag: ${{ github.ref_name }}
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v3
+ - uses: actions/setup-node@v3
+ with:
+ node-version: 16
+ registry-url: https://registry.npmjs.org/
+ - name: Detect tag and set variable
+ id: detect_tag
+ run: |
+ # Set the library name based on the tag
+ if [[ ${{ github.ref }} =~ ^refs/tags/(.*)-cookie-manager.* ]]; then
+ library_name=${BASH_REMATCH[1]}
+ echo "library_dir=$library_name" >> "$GITHUB_OUTPUT"
+ else
+ echo "Invalid tag"
+ exit 1
+ fi
+
+ - name: Publish package
+ # The package directory is the library name e.g "apps/sveltekit | apps/react"
+ run: |
+ cd cookie-manager/${{ steps.detect_tag.outputs.library_dir }} && \
+ pnpm i && \
+ pnpm package && \
+ cp ../../LICENSE ../../NOTICE . && \
+ npm publish --access=public
+ env:
+ NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
+
+ github_draft_release:
+ needs: publish-npm-package
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v3
+ - name: Prepare repository tags
+ run: |
+ # Fetch all tags
+ if git rev-parse --is-shallow-repository | grep -q 'true'; then
+ git fetch --prune --unshallow --tags -f
+ else
+ git fetch --prune --tags -f
+ fi
+ - name: Build changelog
+ id: build_changelog
+ run: |
+ echo "Building changelog..."
+
+ # Create a changelog file with a header:
+ echo "# What's Changed" > CHANGELOG.md
+
+ # Get the current tag from the workflow
+ current_tag="${{ needs.publish-npm-package.outputs.tag }}"
+
+ # Extract the tag type from the current tag
+ current_tag_type=$(echo "$current_tag" | awk -F'@' '{print $1}')
+
+ library_tags=$(git tag -l "$current_tag_type@*" --sort=-v:refname)
+
+ tag_array=()
+ while IFS= read -r line; do
+ tag_array+=("$line")
+ done <<< "$library_tags"
+
+ current_tag_index=-1
+ for i in "${!tag_array[@]}"; do
+ if [ "${tag_array[$i]}" == "$current_tag" ]; then
+ current_tag_index=$i
+ break
+ fi
+ done
+
+ if [ "$current_tag_index" -eq -1 ]; then
+ echo "Current tag $current_tag not found in the available tags."
+ exit 1
+ fi
+
+ if [ "$current_tag_index" -lt $((${#tag_array[@]} - 1)) ]; then
+ prev_tag="${tag_array[$((current_tag_index + 1))]}"
+ else
+ prev_tag=$(git rev-list --max-parents=0 HEAD)
+ fi
+
+ last_commit=$(git rev-list -n 1 "$prev_tag")
+
+ # Fill the changelog file with the commits since the last tag
+ # Set max tries to equal the maximum number of commits as protection
+ max_tries=$(git rev-list --count HEAD)
+ i=0
+ while [ "$(git rev-parse HEAD~$i)" != "$last_commit" ] && [ $i -lt $((max_tries-1)) ]; do
+ commit_message=$(git show -s --format=%s HEAD~$i)
+ echo "- $commit_message" >> CHANGELOG.md
+ i=$((i+1))
+ done
+
+ # Set the complete changelog URL
+ echo >> CHANGELOG.md
+ compare="${prev_tag}...${current_tag}"
+
+ echo "Appending full changelog URL to CHANGELOG.md..."
+ echo "**Full Changelog**: https://github.com/${{ github.repository }}/compare/${compare}" >> CHANGELOG.md
+
+ echo "Changelog built successfully."
+
+ - name: Create draft release
+ uses: softprops/action-gh-release@v1
+ with:
+ name: '@boxfish-studio/${{ github.ref_name }}'
+ tag_name: ${{ github.ref_name }}
+ body_path: CHANGELOG.md
+ draft: true
diff --git a/.github/workflows/package-release.yml b/.github/workflows/package-release.yml
deleted file mode 100644
index 5c2ac90..0000000
--- a/.github/workflows/package-release.yml
+++ /dev/null
@@ -1,81 +0,0 @@
-name: SvelteKit Cookie Manager Release
-
-on:
- push:
- tags:
- - 'v[0-9]+.[0-9]+.[0-9]+'
-
-jobs:
- publish-npm-package:
- runs-on: ubuntu-latest
- steps:
- - uses: actions/checkout@v3
- - uses: actions/setup-node@v3
- with:
- node-version: 16
- registry-url: https://registry.npmjs.org/
- - run: npm ci
- - run: npm run build
- - run: npm run package
- - run: cd package && npm publish --access=public
- env:
- NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
-
- github_draft_release:
- needs: publish-npm-package
- runs-on: ubuntu-latest
- steps:
- - name: Checkout
- uses: actions/checkout@v3
- - name: Prepare repository tags
- run: |
- if git rev-parse --is-shallow-repository | grep -q 'true'; then
- git fetch --prune --unshallow --tags -f
- else
- git fetch --prune --tags -f
- fi
- - name: Build changelog
- id: build_changelog
- run: |
- echo "Building changelog..."
-
- # Create a changelog file with a header:
- echo "# What's Changed" > CHANGELOG.md
- # Check repository tags and the last tagged commit
- n_tags=`git tag -l 'v*' --sort=-v:refname | wc -l`
- prev_tag=`git tag -l 'v*' --sort=-v:refname | sed '2q;d'`
- if [ $n_tags -eq 1 ]; then
- last_commit=`git rev-list --max-parents=0 HEAD`
- else
- last_commit=`git rev-list -n 1 $prev_tag`
- fi
-
- # Fill the changelog file with the commits since the last tag
- # Set max tries to equal the maximum number of commits as protection
- max_tries=`git rev-list --count HEAD`
- i=0
- while [ `git rev-parse HEAD~$i` != $last_commit ] && [ $i -lt $((max_tries-1)) ]
- do
- echo '- ' `git show -s --format=%s HEAD~$i` >> CHANGELOG.md
- i=$((i+1))
- done
-
- # Set the complete changelog url
- echo >> CHANGELOG.md
- compare=""
- if [ $n_tags -eq 1 ]; then
- compare=$last_commit
- else
- compare=$prev_tag
- fi
- compare="${compare}...`git tag -l 'v*' --sort=-v:refname | sed '1q;d'`"
- echo "**Full Changelog**: https://github.com/${{ github.repository }}/compare/${compare}" >> CHANGELOG.md
-
- echo "Changelog built successfully."
- - name: Create draft release
- uses: softprops/action-gh-release@v1
- with:
- name: SvelteKit Cookie Manager ${{ github.ref_name }}
- tag_name: ${{ github.ref_name }}
- body_path: CHANGELOG.md
- draft: true
diff --git a/.gitignore b/.gitignore
index e71d7f9..5aa13a5 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,9 +1,41 @@
-.DS_Store
+# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
+
+# Dependencies
node_modules
-/build
-/.svelte-kit
-/package
+.pnp
+.pnp.js
+
+# Local env files
.env
-.env.*
-!.env.example
+.env.local
+.env.development.local
+.env.test.local
+.env.production.local
+
+# Testing
+coverage
+
+# Turbo
+.turbo
+
+# Vercel
+.vercel
+
+# Build Outputs
+.next/
+out/
+build
+dist
+
+# Debug
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+
+# Misc
+.DS_Store
+*.pem
.eslintcache
+
+# Cookie Manager Package Specific
+cookie-manager/*/src/lib/cookie-core
diff --git a/.husky/pre-commit b/.husky/pre-commit
index abf1181..b7fbc57 100755
--- a/.husky/pre-commit
+++ b/.husky/pre-commit
@@ -1,4 +1,4 @@
#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"
-npx lint-staged --allow-empty
+pnpm exec lint-staged --allow-empty
diff --git a/.npmrc b/.npmrc
index b6f27f1..e69de29 100644
--- a/.npmrc
+++ b/.npmrc
@@ -1 +0,0 @@
-engine-strict=true
diff --git a/.prettierignore b/.prettierignore
new file mode 100644
index 0000000..3096115
--- /dev/null
+++ b/.prettierignore
@@ -0,0 +1,6 @@
+pnpm-lock.yaml
+yarn.lock
+node_modules
+dist
+.svelte-kit
+.turbo
diff --git a/.prettierrc b/.prettierrc
index b1dc1d6..4dd7a5f 100644
--- a/.prettierrc
+++ b/.prettierrc
@@ -3,5 +3,6 @@
"singleQuote": true,
"trailingComma": "none",
"printWidth": 100,
- "semi": false
+ "semi": false,
+ "plugins": ["prettier-plugin-svelte"]
}
diff --git a/.vscode/settings.json b/.vscode/settings.json
new file mode 100644
index 0000000..3a99786
--- /dev/null
+++ b/.vscode/settings.json
@@ -0,0 +1,7 @@
+{
+ "eslint.workingDirectories": [
+ {
+ "mode": "auto"
+ }
+ ]
+}
diff --git a/README.md b/README.md
index c79e7da..a761def 100644
--- a/README.md
+++ b/README.md
@@ -1,209 +1,6 @@
-# Sveltekit Cookie Manager 🍪
+# Cookie Manager Monorepo
-Sveltekit Cookie Manager is an easy-use Svelte package to help control the visitor's cookie consent.
+This is a monorepo for the Cookie Manager project. It contains the following packages:
-### Disclaimer
-
-Minimum required SvelteKit version: `1.0.0-next.581`.
-
-## About 📝
-
-**Sveltekit Cookie Manager** reduces the workload of creating and mantaining multiple cookie consents by centralizing them into this package. Enables cookie management of following services:
-
-- Google Analytics Universal.
-- Google Analytics 4.
-
-## Features ✨
-
-- Display a customizable popup to accept or reject cookies.
-- Create a cookie library showing:
- - Tables with details about site's necessary cookies and additional cookies: cookie name, provider name and url, cookie category, purpose, expiry and type.
- - Radio inputs (allow or reject all cookies) and a button to update preferences.
-
-## Installation 🧰
-
-```shell
-$ npm i @boxfish-studio/sveltekit-cookie-manager
-```
-
-or yarn
-
-```shell
-$ yarn add @boxfish-studio/sveltekit-cookie-manager
-```
-
-
-
-## How to use 📝
-
-### Show a popup
-
-Import the `CookieManager` component to your Svelte page and pass the configuration with your desired settings:
-
-```svelte
-
-
-
-```
-
-### Show the cookie library
-
-Import the `CookieLibrary` component to your svelte file and pass the configuration with your desired settings, as shown in the example below.
-
-You can also use the library without any configuration or you can pass a `theme` to the configuration:
-
-```svelte
-
-
-
-```
-
-### Using the internal store
-
-You can use the `servicesInitialized` writable to know whether the services are running or not.
-
-```ts
-import { servicesInitialized } from '@boxfish-studio/sveltekit-cookie-manager'
-import { get } from 'svelte/store'
-
-const isRunning = get(servicesInitialized)
-```
-
-## Configuration 🪛
-
-Custom configuration must be of type `SKCMConfiguration`. All available props are shown below:
-
-```ts
-type SKCMConfiguration = {
- disclaimer: {
- title?: string
- body?: string
- policyText?: string
- policyUrl?: string
- acceptButtonText?: string
- rejectButtonText?: string
- }
- services: {
- googleAnalyticsUniversalId?: string
- googleAnalytics4Id?: string
- adCookiesEnabled?: boolean
- customNecessaryCookies?: {
- name: string
- provider: string
- providerUrl: string
- purpose: string
- expiry: string
- type: string
- showDisclaimerIfMissing?: boolean
- }[]
- }
- theme: {
- primary?: string
- dark?: string
- medium?: string
- light?: string
- }
-}
-```
-
-### Disclaimer props
-
-| Name | Description | Default value |
-| ---------------- | --------------------------------- | -------------------------------------------------------- |
-| title | The title of the popup | "Cookie Preferences" |
-| body | Body message of the popup | "By using this site, you agree with our use of cookies." |
-| policyText | Text that links to Privacy Policy | "Read our Cookie Policy" |
-| policyUrl | Privacy Policy url | "/privacy-policy" |
-| acceptButtonText | Text shown in 'Accept' button | "Accept Additional Cookies" |
-| rejectButtonText | Text shown in 'Reject' button | "Reject Additional Cookies" |
-
-### Services props
-
-You must use `googleAnalyticsUniversalId` or `googleAnalytics4Id`.
-
-| Name | Description | Default value |
-| -------------------------- | ------------------------------------------------------------------------------------------------------------------------- | ------------- |
-| googleAnalyticsUniversalId | Your Google Analytics Universal key | |
-| googleAnalytics4Id | Your Google Analytics 4 key | |
-| adCookiesEnabled | Whether cookies with the category Advertising should be set in the browser and shown in the library | true |
-| customNecessaryCookies | Cookies that should be present in the Necessary Cookies table to inform the user their usage. To configure them see below | |
-
-### Custom necessary cookies
-
-You can configure extra cookies that will also appear in the Cookie library by specifying them in the `customNecessaryCookies` property.
-They accept the following options:
-
-| Name | Description | Default value | Required | Example |
-| ---------------------- | -------------------------------------------------------------------------- | ------------- | -------- | --------------------------- |
-| name | Name of the cookie | | Yes | Boxfish Cookie |
-| provider | Name of it's provider | | No | Boxfish |
-| providerUrl | URL of it's provider | | No | https://boxfish.studio |
-| purpose | Usage of the cookie | | Yes | "Stores the user's consent" |
-| expiry | Time that the cookie with remain in the user's browser since it's creation | | Yes | "30 days" |
-| type | Type of cookie | | Yes | "HTTP" |
-| showDisclamerIfMissing | Show the accept/reject popup if this cookie is missing | false | No | true |
-
-### Theme props
-
-A 4-colour palette has been predefined following a custom style guide. You may overwrite these values in your custom configuration variable.
-
-| Name | Description | Default value |
-| ------- | ----------------------------------------------------- | --------------- |
-| primary | Used in buttons backgrounds, anchors | #14cabf (teal) |
-| dark | Used in headings, body | #131f37 (black) |
-| medium | Used in table headings, table borders | #b0bfd9 (gray) |
-| light | Used in banner background colour, buttons text colour | #fff (white) |
-
-### Built with
-
-- Sveltekit.
-- Typescript.
-
-## Release Package
-
-`npm run package && cd package && npm publish --access=public`
-
-## License
-
-[Apache 2.0](./LICENSE) © [Boxfish Studio]
-
-[Boxfish Studio]: https://boxfish.studio
-
-
-
-
- Made with :heart: by Boxfish Studio.
-
-
+- [SvelteKit](./cookie-manager/sveltekit/).
+- [React](./cookie-manager/react/).
diff --git a/src/lib/app/constants.ts b/cookie-manager/core/constants.ts
similarity index 100%
rename from src/lib/app/constants.ts
rename to cookie-manager/core/constants.ts
diff --git a/src/lib/app/cookieLib.ts b/cookie-manager/core/cookieLib.ts
similarity index 100%
rename from src/lib/app/cookieLib.ts
rename to cookie-manager/core/cookieLib.ts
diff --git a/src/lib/app/enums.ts b/cookie-manager/core/enums.ts
similarity index 100%
rename from src/lib/app/enums.ts
rename to cookie-manager/core/enums.ts
diff --git a/src/lib/app/types.ts b/cookie-manager/core/types.ts
similarity index 96%
rename from src/lib/app/types.ts
rename to cookie-manager/core/types.ts
index 6d54db8..0cc6088 100644
--- a/src/lib/app/types.ts
+++ b/cookie-manager/core/types.ts
@@ -1,4 +1,4 @@
-import type { CookieCategory } from './'
+import type { CookieCategory } from './enums'
export enum SupportedService {
GoogleAnalyticsUniversal = 'googleAnalyticsUniversal',
diff --git a/cookie-manager/core/utils.ts b/cookie-manager/core/utils.ts
new file mode 100644
index 0000000..b2ae045
--- /dev/null
+++ b/cookie-manager/core/utils.ts
@@ -0,0 +1,37 @@
+import { DEFAULT_THEME_COLORS } from './constants'
+import type { Theme } from './types'
+
+/*
+ * General utils for managing cookies in Typescript.
+ * Source: https://gist.github.com/joduplessis/7b3b4340353760e945f972a69e855d11
+ */
+export function getCookie(name: string): string | undefined {
+ const value = '; ' + document.cookie
+ const parts = value.split('; ' + name + '=')
+
+ if (parts?.length == 2) {
+ return parts?.pop()?.split(';')?.shift() ?? undefined
+ }
+}
+export const setCookie = (name: string, val: string, expDays: number): void => {
+ const date = new Date()
+ const value = val
+ date.setTime(date.getTime() + expDays * 24 * 60 * 60 * 1000)
+ document.cookie = name + '=' + value + '; expires=' + date.toUTCString() + '; path=/'
+}
+// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
+export function deleteCookie(name: string) {
+ const date = new Date()
+ date.setTime(date.getTime() + -1 * 24 * 60 * 60 * 1000)
+ document.cookie = name + '=; expires=' + date.toUTCString() + '; path=/'
+}
+
+export const formatStyles = (theme: Theme): string =>
+ Object.entries(theme)
+ .map((colorVariable) => `--${colorVariable[0]}:${colorVariable[1]};`)
+ .join(' ')
+
+export const getInlineStyle = (theme: Theme = {}): string => {
+ const mergedTheme = { ...DEFAULT_THEME_COLORS, ...theme }
+ return formatStyles(mergedTheme)
+}
diff --git a/cookie-manager/react/.eslintignore b/cookie-manager/react/.eslintignore
new file mode 100644
index 0000000..cf64a52
--- /dev/null
+++ b/cookie-manager/react/.eslintignore
@@ -0,0 +1 @@
+.eslintrc.cjs
diff --git a/cookie-manager/react/.eslintrc.cjs b/cookie-manager/react/.eslintrc.cjs
new file mode 100644
index 0000000..71a6a4b
--- /dev/null
+++ b/cookie-manager/react/.eslintrc.cjs
@@ -0,0 +1,17 @@
+/** @type {import("eslint").Linter.Config} */
+module.exports = {
+ globals: {
+ React: true
+ },
+ root: true,
+ extends: ['@repo/eslint-config/index.js', 'plugin:react/recommended'],
+ parser: '@typescript-eslint/parser',
+ settings: {
+ react: {
+ version: 'detect'
+ }
+ },
+ parserOptions: {
+ project: true
+ }
+}
diff --git a/cookie-manager/react/.gitignore b/cookie-manager/react/.gitignore
new file mode 100644
index 0000000..e69de29
diff --git a/cookie-manager/react/.lintstagedrc.cjs b/cookie-manager/react/.lintstagedrc.cjs
new file mode 100644
index 0000000..fbd4eca
--- /dev/null
+++ b/cookie-manager/react/.lintstagedrc.cjs
@@ -0,0 +1 @@
+module.exports = require('@repo/lint-staged-config')
diff --git a/cookie-manager/react/README.md b/cookie-manager/react/README.md
new file mode 100644
index 0000000..e69de29
diff --git a/cookie-manager/react/index.html b/cookie-manager/react/index.html
new file mode 100644
index 0000000..ef80c79
--- /dev/null
+++ b/cookie-manager/react/index.html
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+ Vite + React + TS
+
+
+
+
+
+
diff --git a/cookie-manager/react/package.json b/cookie-manager/react/package.json
new file mode 100644
index 0000000..137fe30
--- /dev/null
+++ b/cookie-manager/react/package.json
@@ -0,0 +1,50 @@
+{
+ "name": "@boxfish-studio/react-cookie-manager",
+ "version": "0.0.0",
+ "private": true,
+ "type": "module",
+ "main": "./dist/index.umd.js",
+ "module": "./dist/index.es.js",
+ "types": "./dist/index.d.ts",
+ "files": [
+ "dist"
+ ],
+ "exports": {
+ ".": {
+ "import": "./dist/index.es.js",
+ "require": "./dist/index.umd.js",
+ "types": "./dist/index.d.ts"
+ },
+ "./dist/style.css": "./dist/style.css"
+ },
+ "scripts": {
+ "dev": "vite dev",
+ "build": "tsc -b && vite build",
+ "preview": "vite preview",
+ "lint": "eslint .",
+ "build:package": "tsc -d && cross-env BUILDING_PACKAGE=true vite build"
+ },
+ "dependencies": {
+ "cross-env": "^7.0.3",
+ "react": "^18.3.1",
+ "react-dom": "^18.3.1"
+ },
+ "devDependencies": {
+ "@repo/eslint-config": "workspace:*",
+ "@repo/lint-staged-config": "workspace:*",
+ "@repo/typescript-config": "workspace:*",
+ "@types/node": "^20.16.5",
+ "@types/react": "^18",
+ "@types/react-dom": "^18",
+ "@vitejs/plugin-react": "^4.3.1",
+ "@vitejs/plugin-react-swc": "^3.7.0",
+ "autoprefixer": "^10.4.20",
+ "eslint": "^8.57.1",
+ "postcss": "^8.4.47",
+ "tailwindcss": "^3.4.12",
+ "typescript": "^5.4.5",
+ "vite": "^4.4.11",
+ "vite-plugin-dts": "^3.9.1",
+ "vite-tsconfig-paths": "^4.2.1"
+ }
+}
diff --git a/cookie-manager/react/postcss.config.js b/cookie-manager/react/postcss.config.js
new file mode 100644
index 0000000..35237eb
--- /dev/null
+++ b/cookie-manager/react/postcss.config.js
@@ -0,0 +1,6 @@
+export default {
+ plugins: {
+ tailwindcss: {},
+ autoprefixer: {}
+ }
+}
diff --git a/cookie-manager/react/public/vite.svg b/cookie-manager/react/public/vite.svg
new file mode 100644
index 0000000..e7b8dfb
--- /dev/null
+++ b/cookie-manager/react/public/vite.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/cookie-manager/react/src/App.tsx b/cookie-manager/react/src/App.tsx
new file mode 100644
index 0000000..5f918da
--- /dev/null
+++ b/cookie-manager/react/src/App.tsx
@@ -0,0 +1,44 @@
+import { CookieLibrary, CookieManager } from '@components'
+import { SKCMConfiguration } from '@core/types'
+
+function App(): React.JSX.Element {
+ const configuration: SKCMConfiguration = {
+ disclaimer: {
+ title: 'Custom Title',
+ body: 'Custom Body'
+ },
+ services: {
+ googleAnalyticsUniversalId: 'UA-XXXXXXXXX',
+ googleAnalytics4Id: 'G-XXXXXXX',
+ adCookiesEnabled: true,
+ customNecessaryCookies: [
+ {
+ name: '1st Cookie Test',
+ provider: 'Boxfish',
+ providerUrl: 'boxfish.studio',
+ purpose: 'Stores the user´s preferences.',
+ expiry: '2 months',
+ type: 'HTTP',
+ showDisclaimerIfMissing: true
+ },
+ {
+ name: 'Cookie 2',
+ provider: 'Boxfish',
+ providerUrl: 'boxfish.studio',
+ purpose: 'Stores the user´s cookies consent state for the current domain',
+ expiry: '30 days',
+ type: 'HTTP',
+ showDisclaimerIfMissing: true
+ }
+ ]
+ }
+ }
+ return (
+ <>
+
+
+ >
+ )
+}
+
+export default App
diff --git a/cookie-manager/react/src/index.css b/cookie-manager/react/src/index.css
new file mode 100644
index 0000000..78e9b84
--- /dev/null
+++ b/cookie-manager/react/src/index.css
@@ -0,0 +1,70 @@
+:root {
+ font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif;
+ line-height: 1.5;
+ font-weight: 400;
+
+ color-scheme: light dark;
+ color: rgba(255, 255, 255, 0.87);
+ background-color: #242424;
+
+ font-synthesis: none;
+ text-rendering: optimizeLegibility;
+ -webkit-font-smoothing: antialiased;
+ -moz-osx-font-smoothing: grayscale;
+}
+
+a {
+ font-weight: 500;
+ color: #646cff;
+ text-decoration: inherit;
+}
+a:hover {
+ color: #535bf2;
+}
+
+body {
+ margin: 0;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ min-width: 320px;
+ min-height: 100vh;
+ max-width: 1200px;
+}
+
+h1 {
+ font-size: 3.2em;
+ line-height: 1.1;
+}
+
+button {
+ border-radius: 8px;
+ border: 1px solid transparent;
+ padding: 0.6em 1.2em;
+ font-size: 1em;
+ font-weight: 500;
+ font-family: inherit;
+ background-color: #1a1a1a;
+ cursor: pointer;
+ transition: border-color 0.25s;
+}
+button:hover {
+ border-color: #646cff;
+}
+button:focus,
+button:focus-visible {
+ outline: 4px auto -webkit-focus-ring-color;
+}
+
+@media (prefers-color-scheme: light) {
+ :root {
+ color: #213547;
+ background-color: #ffffff;
+ }
+ a:hover {
+ color: #747bff;
+ }
+ button {
+ background-color: #f9f9f9;
+ }
+}
diff --git a/cookie-manager/react/src/lib/app/types.ts b/cookie-manager/react/src/lib/app/types.ts
new file mode 100644
index 0000000..e69de29
diff --git a/cookie-manager/react/src/lib/components/CookieLibrary/CookieLibrary.tsx b/cookie-manager/react/src/lib/components/CookieLibrary/CookieLibrary.tsx
new file mode 100644
index 0000000..5b01f4b
--- /dev/null
+++ b/cookie-manager/react/src/lib/components/CookieLibrary/CookieLibrary.tsx
@@ -0,0 +1,13 @@
+import { SKCMConfiguration } from '@core/types'
+
+interface CookieLibraryProps {
+ configuration: SKCMConfiguration
+}
+
+export function CookieLibrary({ configuration }: CookieLibraryProps): React.JSX.Element {
+ return (
+
+
Library
+
+ )
+}
diff --git a/cookie-manager/react/src/lib/components/CookieLibrary/index.ts b/cookie-manager/react/src/lib/components/CookieLibrary/index.ts
new file mode 100644
index 0000000..299ce58
--- /dev/null
+++ b/cookie-manager/react/src/lib/components/CookieLibrary/index.ts
@@ -0,0 +1 @@
+export * from './CookieLibrary'
diff --git a/cookie-manager/react/src/lib/components/CookieManager.tsx b/cookie-manager/react/src/lib/components/CookieManager.tsx
new file mode 100644
index 0000000..d026b5d
--- /dev/null
+++ b/cookie-manager/react/src/lib/components/CookieManager.tsx
@@ -0,0 +1,8 @@
+import { SKCMConfiguration } from '@core/types'
+
+interface CookieManagerProps {
+ configuration: SKCMConfiguration
+}
+export function CookieManager({ configuration }: CookieManagerProps): React.JSX.Element {
+ return CookieManager
+}
diff --git a/cookie-manager/react/src/lib/components/index.ts b/cookie-manager/react/src/lib/components/index.ts
new file mode 100644
index 0000000..50537e3
--- /dev/null
+++ b/cookie-manager/react/src/lib/components/index.ts
@@ -0,0 +1,3 @@
+export * from './CookieLibrary'
+
+export * from './CookieManager'
diff --git a/cookie-manager/react/src/main.tsx b/cookie-manager/react/src/main.tsx
new file mode 100644
index 0000000..4b9e95a
--- /dev/null
+++ b/cookie-manager/react/src/main.tsx
@@ -0,0 +1,10 @@
+import { StrictMode } from 'react'
+import { createRoot } from 'react-dom/client'
+import App from './App.tsx'
+import './index.css'
+
+createRoot(document.getElementById('root') as HTMLElement).render(
+
+
+
+)
diff --git a/cookie-manager/react/src/vite-env.d.ts b/cookie-manager/react/src/vite-env.d.ts
new file mode 100644
index 0000000..14fa749
--- /dev/null
+++ b/cookie-manager/react/src/vite-env.d.ts
@@ -0,0 +1 @@
+// /
diff --git a/cookie-manager/react/tailwind.config.js b/cookie-manager/react/tailwind.config.js
new file mode 100644
index 0000000..82d87c3
--- /dev/null
+++ b/cookie-manager/react/tailwind.config.js
@@ -0,0 +1,8 @@
+/** @type {import('tailwindcss').Config} */
+export default {
+ content: ['./src/**/*.{js,ts,jsx,tsx}'],
+ theme: {
+ extend: {}
+ },
+ plugins: []
+}
diff --git a/cookie-manager/react/tsconfig.json b/cookie-manager/react/tsconfig.json
new file mode 100644
index 0000000..fe082e5
--- /dev/null
+++ b/cookie-manager/react/tsconfig.json
@@ -0,0 +1,15 @@
+{
+ "extends": "@repo/typescript-config/react.json",
+ "compilerOptions": {
+ "baseUrl": "./",
+ "allowImportingTsExtensions": true,
+ "paths": {
+ "@components": ["src/lib/components"],
+ "@components/*": ["src/lib/components/*"],
+ "@core": ["../core"],
+ "@core/*": ["../core/*"]
+ }
+ },
+ "include": ["src", "*.config.js", "*.config.ts"],
+ "exclude": ["node_modules"]
+}
diff --git a/cookie-manager/react/tsconfig.package.json b/cookie-manager/react/tsconfig.package.json
new file mode 100644
index 0000000..a4d64c2
--- /dev/null
+++ b/cookie-manager/react/tsconfig.package.json
@@ -0,0 +1,14 @@
+{
+ "extends": "@repo/typescript-config/react.json",
+ "compilerOptions": {
+ "baseUrl": "./",
+ "paths": {
+ "@components": ["src/lib/components"],
+ "@components/*": ["src/lib/components/*"],
+ "@core": ["src/lib/cookie-core"],
+ "@core/*": ["src/lib/cookie-core/*"]
+ }
+ },
+ "include": ["src"],
+ "exclude": ["node_modules"]
+}
diff --git a/cookie-manager/react/vite.config.ts b/cookie-manager/react/vite.config.ts
new file mode 100644
index 0000000..4812bff
--- /dev/null
+++ b/cookie-manager/react/vite.config.ts
@@ -0,0 +1,52 @@
+import { defineConfig } from 'vite'
+import react from '@vitejs/plugin-react-swc'
+import { resolve } from 'path'
+import dts from 'vite-plugin-dts'
+import tailwindcss from 'tailwindcss'
+import tsconfigPaths from 'vite-tsconfig-paths'
+
+const isPackageProduction = process.env.BUILDING_PACKAGE === 'true'
+
+const packageBuildConfig = {
+ lib: {
+ entry: resolve(__dirname, './src/lib/index.ts'),
+ name: '@boxfish-studio/react-cookie-manager',
+ fileName: (format) => `index.${format}.js`
+ },
+ rollupOptions: {
+ external: ['react', 'react-dom', 'tailwindcss'],
+ output: {
+ globals: {
+ react: 'React',
+ 'react-dom': 'ReactDOM',
+ tailwindcss: 'tailwindcss'
+ }
+ }
+ },
+ sourcemap: true,
+ emptyOutDir: true
+}
+const plugins = isPackageProduction
+ ? [
+ tsconfigPaths({
+ root: __dirname
+ }),
+ react(),
+ dts({ rollupTypes: true })
+ ]
+ : [
+ tsconfigPaths({
+ root: __dirname
+ }),
+ react()
+ ]
+
+export default defineConfig({
+ build: isPackageProduction ? packageBuildConfig : {},
+ plugins,
+ css: {
+ postcss: {
+ plugins: [tailwindcss]
+ }
+ }
+})
diff --git a/.env.example b/cookie-manager/sveltekit/.env.example
similarity index 100%
rename from .env.example
rename to cookie-manager/sveltekit/.env.example
diff --git a/cookie-manager/sveltekit/.eslintignore b/cookie-manager/sveltekit/.eslintignore
new file mode 100644
index 0000000..cf64a52
--- /dev/null
+++ b/cookie-manager/sveltekit/.eslintignore
@@ -0,0 +1 @@
+.eslintrc.cjs
diff --git a/cookie-manager/sveltekit/.eslintrc.cjs b/cookie-manager/sveltekit/.eslintrc.cjs
new file mode 100644
index 0000000..c59dca8
--- /dev/null
+++ b/cookie-manager/sveltekit/.eslintrc.cjs
@@ -0,0 +1,5 @@
+/** @type {import("eslint").Linter.Config} */
+module.exports = {
+ root: true,
+ extends: ['@repo/eslint-config/svelte.js']
+}
diff --git a/cookie-manager/sveltekit/.gitignore b/cookie-manager/sveltekit/.gitignore
new file mode 100644
index 0000000..e71d7f9
--- /dev/null
+++ b/cookie-manager/sveltekit/.gitignore
@@ -0,0 +1,9 @@
+.DS_Store
+node_modules
+/build
+/.svelte-kit
+/package
+.env
+.env.*
+!.env.example
+.eslintcache
diff --git a/cookie-manager/sveltekit/.lintstagedrc.cjs b/cookie-manager/sveltekit/.lintstagedrc.cjs
new file mode 100644
index 0000000..fbd4eca
--- /dev/null
+++ b/cookie-manager/sveltekit/.lintstagedrc.cjs
@@ -0,0 +1 @@
+module.exports = require('@repo/lint-staged-config')
diff --git a/cookie-manager/sveltekit/.npmrc b/cookie-manager/sveltekit/.npmrc
new file mode 100644
index 0000000..b6f27f1
--- /dev/null
+++ b/cookie-manager/sveltekit/.npmrc
@@ -0,0 +1 @@
+engine-strict=true
diff --git a/LICENSE b/cookie-manager/sveltekit/LICENSE
similarity index 100%
rename from LICENSE
rename to cookie-manager/sveltekit/LICENSE
diff --git a/NOTICE b/cookie-manager/sveltekit/NOTICE
similarity index 100%
rename from NOTICE
rename to cookie-manager/sveltekit/NOTICE
diff --git a/cookie-manager/sveltekit/README.md b/cookie-manager/sveltekit/README.md
new file mode 100644
index 0000000..c79e7da
--- /dev/null
+++ b/cookie-manager/sveltekit/README.md
@@ -0,0 +1,209 @@
+# Sveltekit Cookie Manager 🍪
+
+Sveltekit Cookie Manager is an easy-use Svelte package to help control the visitor's cookie consent.
+
+### Disclaimer
+
+Minimum required SvelteKit version: `1.0.0-next.581`.
+
+## About 📝
+
+**Sveltekit Cookie Manager** reduces the workload of creating and mantaining multiple cookie consents by centralizing them into this package. Enables cookie management of following services:
+
+- Google Analytics Universal.
+- Google Analytics 4.
+
+## Features ✨
+
+- Display a customizable popup to accept or reject cookies.
+- Create a cookie library showing:
+ - Tables with details about site's necessary cookies and additional cookies: cookie name, provider name and url, cookie category, purpose, expiry and type.
+ - Radio inputs (allow or reject all cookies) and a button to update preferences.
+
+## Installation 🧰
+
+```shell
+$ npm i @boxfish-studio/sveltekit-cookie-manager
+```
+
+or yarn
+
+```shell
+$ yarn add @boxfish-studio/sveltekit-cookie-manager
+```
+
+
+
+## How to use 📝
+
+### Show a popup
+
+Import the `CookieManager` component to your Svelte page and pass the configuration with your desired settings:
+
+```svelte
+
+
+
+```
+
+### Show the cookie library
+
+Import the `CookieLibrary` component to your svelte file and pass the configuration with your desired settings, as shown in the example below.
+
+You can also use the library without any configuration or you can pass a `theme` to the configuration:
+
+```svelte
+
+
+
+```
+
+### Using the internal store
+
+You can use the `servicesInitialized` writable to know whether the services are running or not.
+
+```ts
+import { servicesInitialized } from '@boxfish-studio/sveltekit-cookie-manager'
+import { get } from 'svelte/store'
+
+const isRunning = get(servicesInitialized)
+```
+
+## Configuration 🪛
+
+Custom configuration must be of type `SKCMConfiguration`. All available props are shown below:
+
+```ts
+type SKCMConfiguration = {
+ disclaimer: {
+ title?: string
+ body?: string
+ policyText?: string
+ policyUrl?: string
+ acceptButtonText?: string
+ rejectButtonText?: string
+ }
+ services: {
+ googleAnalyticsUniversalId?: string
+ googleAnalytics4Id?: string
+ adCookiesEnabled?: boolean
+ customNecessaryCookies?: {
+ name: string
+ provider: string
+ providerUrl: string
+ purpose: string
+ expiry: string
+ type: string
+ showDisclaimerIfMissing?: boolean
+ }[]
+ }
+ theme: {
+ primary?: string
+ dark?: string
+ medium?: string
+ light?: string
+ }
+}
+```
+
+### Disclaimer props
+
+| Name | Description | Default value |
+| ---------------- | --------------------------------- | -------------------------------------------------------- |
+| title | The title of the popup | "Cookie Preferences" |
+| body | Body message of the popup | "By using this site, you agree with our use of cookies." |
+| policyText | Text that links to Privacy Policy | "Read our Cookie Policy" |
+| policyUrl | Privacy Policy url | "/privacy-policy" |
+| acceptButtonText | Text shown in 'Accept' button | "Accept Additional Cookies" |
+| rejectButtonText | Text shown in 'Reject' button | "Reject Additional Cookies" |
+
+### Services props
+
+You must use `googleAnalyticsUniversalId` or `googleAnalytics4Id`.
+
+| Name | Description | Default value |
+| -------------------------- | ------------------------------------------------------------------------------------------------------------------------- | ------------- |
+| googleAnalyticsUniversalId | Your Google Analytics Universal key | |
+| googleAnalytics4Id | Your Google Analytics 4 key | |
+| adCookiesEnabled | Whether cookies with the category Advertising should be set in the browser and shown in the library | true |
+| customNecessaryCookies | Cookies that should be present in the Necessary Cookies table to inform the user their usage. To configure them see below | |
+
+### Custom necessary cookies
+
+You can configure extra cookies that will also appear in the Cookie library by specifying them in the `customNecessaryCookies` property.
+They accept the following options:
+
+| Name | Description | Default value | Required | Example |
+| ---------------------- | -------------------------------------------------------------------------- | ------------- | -------- | --------------------------- |
+| name | Name of the cookie | | Yes | Boxfish Cookie |
+| provider | Name of it's provider | | No | Boxfish |
+| providerUrl | URL of it's provider | | No | https://boxfish.studio |
+| purpose | Usage of the cookie | | Yes | "Stores the user's consent" |
+| expiry | Time that the cookie with remain in the user's browser since it's creation | | Yes | "30 days" |
+| type | Type of cookie | | Yes | "HTTP" |
+| showDisclamerIfMissing | Show the accept/reject popup if this cookie is missing | false | No | true |
+
+### Theme props
+
+A 4-colour palette has been predefined following a custom style guide. You may overwrite these values in your custom configuration variable.
+
+| Name | Description | Default value |
+| ------- | ----------------------------------------------------- | --------------- |
+| primary | Used in buttons backgrounds, anchors | #14cabf (teal) |
+| dark | Used in headings, body | #131f37 (black) |
+| medium | Used in table headings, table borders | #b0bfd9 (gray) |
+| light | Used in banner background colour, buttons text colour | #fff (white) |
+
+### Built with
+
+- Sveltekit.
+- Typescript.
+
+## Release Package
+
+`npm run package && cd package && npm publish --access=public`
+
+## License
+
+[Apache 2.0](./LICENSE) © [Boxfish Studio]
+
+[Boxfish Studio]: https://boxfish.studio
+
+
+
+
+ Made with :heart: by Boxfish Studio.
+
+
diff --git a/cookie-manager/sveltekit/package.json b/cookie-manager/sveltekit/package.json
new file mode 100644
index 0000000..175c103
--- /dev/null
+++ b/cookie-manager/sveltekit/package.json
@@ -0,0 +1,49 @@
+{
+ "name": "@boxfish-studio/sveltekit-cookie-manager",
+ "version": "1.0.3",
+ "author": "Boxfish Studio ",
+ "license": "Apache-2.0",
+ "repository": "github:boxfish-studio/sveltekit-cookie-manager",
+ "homepage": "https://github.com/boxfish-studio/sveltekit-cookie-manager",
+ "bugs": "https://github.com/boxfish-studio/sveltekit-cookie-manager/issues",
+ "scripts": {
+ "dev": "vite dev",
+ "build": "vite build",
+ "pre-package": "cp ../core ./src/lib/cookie-core -r",
+ "build:package": "pnpm pre-package && svelte-package",
+ "postpackage": "pnpm clean",
+ "clean": "rm -r ./package ./src/lib/cookie-core",
+ "package": "cross-env BUILDING_PACKAGE=true pnpm build:package",
+ "preview": "vite preview",
+ "check": "svelte-check --tsconfig ./tsconfig.json",
+ "check:watch": "svelte-check --tsconfig ./tsconfig.json --watch",
+ "lint": "prettier --check . && eslint .",
+ "format": "prettier --write .",
+ "prepare": "svelte-kit sync"
+ },
+ "dependencies": {
+ "sass": "^1.57.1",
+ "svelte": "^3.55.0"
+ },
+ "devDependencies": {
+ "@repo/lint-staged-config": "workspace:*",
+ "@repo/typescript-config": "workspace:*",
+ "@repo/eslint-config": "workspace:*",
+ "@sveltejs/adapter-auto": "1.0.0",
+ "@sveltejs/kit": "1.0.7",
+ "@sveltejs/package": "^1.0.2",
+ "@typescript-eslint/eslint-plugin": "^7.18.0",
+ "@typescript-eslint/parser": "^7.18.0",
+ "cross-env": "^7.0.3",
+ "eslint-config-prettier": "^9.1.0",
+ "prettier": "^3.2.5",
+ "prettier-plugin-svelte": "^3.2.6",
+ "svelte-check": "^3.0.2",
+ "svelte-eslint-parser": "^0.32.1",
+ "svelte-preprocess": "^5.0.0",
+ "tslib": "^2.4.1",
+ "typescript": "^5.4.5",
+ "vite": "^4.4.11"
+ },
+ "type": "module"
+}
diff --git a/src/app.d.ts b/cookie-manager/sveltekit/src/app.d.ts
similarity index 100%
rename from src/app.d.ts
rename to cookie-manager/sveltekit/src/app.d.ts
diff --git a/src/app.html b/cookie-manager/sveltekit/src/app.html
similarity index 93%
rename from src/app.html
rename to cookie-manager/sveltekit/src/app.html
index f454f12..9da5ac1 100644
--- a/src/app.html
+++ b/cookie-manager/sveltekit/src/app.html
@@ -1,4 +1,4 @@
-
+
diff --git a/cookie-manager/sveltekit/src/lib/app/index.ts b/cookie-manager/sveltekit/src/lib/app/index.ts
new file mode 100644
index 0000000..4d18ef3
--- /dev/null
+++ b/cookie-manager/sveltekit/src/lib/app/index.ts
@@ -0,0 +1,2 @@
+export * from './services'
+export * from './store'
diff --git a/src/lib/app/services.ts b/cookie-manager/sveltekit/src/lib/app/services.ts
similarity index 90%
rename from src/lib/app/services.ts
rename to cookie-manager/sveltekit/src/lib/app/services.ts
index d4c499c..268e63a 100644
--- a/src/lib/app/services.ts
+++ b/cookie-manager/sveltekit/src/lib/app/services.ts
@@ -1,9 +1,8 @@
-import { COOKIE_EXPIRATION_DAYS, GOOGLE_ANALYTICS_EXPIRATION_DAYS } from './constants'
+import { GOOGLE_ANALYTICS_EXPIRATION_DAYS } from '$core/constants'
import { browser } from '$app/environment'
import { get } from 'svelte/store'
-import { configuredServices, servicesInitialized } from './store'
-import { SupportedService } from './types'
-import { removeAdditionalCookies } from './utils'
+import { configuredServices, servicesInitialized, removeAdditionalCookies } from './store'
+import { SupportedService } from '$core/types'
export const initializeServices = (): void => {
if (!get(servicesInitialized)) {
diff --git a/src/lib/app/store.ts b/cookie-manager/sveltekit/src/lib/app/store.ts
similarity index 52%
rename from src/lib/app/store.ts
rename to cookie-manager/sveltekit/src/lib/app/store.ts
index bdfb208..50f9f40 100644
--- a/src/lib/app/store.ts
+++ b/cookie-manager/sveltekit/src/lib/app/store.ts
@@ -1,14 +1,14 @@
-import type { Readable, Writable } from 'svelte/store'
-import { derived, writable } from 'svelte/store'
+import { type Readable, type Writable, derived, get, writable } from 'svelte/store'
import {
GoogleOwnCookies,
SKCM_GA_GOOGLE_ANALYTICS_4_COOKIE,
SKCM_GA_GOOGLE_ANALYTICS_UNIVERSAL_COOKIE
-} from './cookieLib'
-import { CookieCategory } from './enums'
-import type { Service, ServiceCookie } from './types'
-import { SupportedService } from './types'
-import { getCookie } from './utils'
+} from '$core/cookieLib'
+import { CookieCategory } from '$core/enums'
+import type { Service, ServiceCookie } from '$core/types'
+import { SupportedService } from '$core/types'
+import { deleteCookie, getCookie, setCookie } from '$core/utils'
+import { COOKIE_EXPIRATION_DAYS } from '$core/constants'
export const showCookieDisclaimer: Writable = writable(false)
export const configuredServices: Writable = writable([])
@@ -63,3 +63,53 @@ export function initConfiguredServices(
configuredServices.set(_configuredServices)
necessaryCookies.set(_necessaryCookies)
}
+
+// Check user has all needed necessary cookies already set
+export const hasAllNeededNecessaryCookies = (): boolean => {
+ const neededCookies =
+ get(necessaryCookies)?.filter((cookie) => cookie?.showDisclaimerIfMissing) ?? []
+ for (let i = 0; i < neededCookies?.length; i++) {
+ if (!getCookie(neededCookies[i].name)?.length) {
+ return false
+ }
+ }
+ return true
+}
+
+export const submitNecessaryCookies = (value: 'true' | 'false'): void => {
+ const SKCM_NECESSARY_COOKIES: string[] = [
+ SKCM_GA_GOOGLE_ANALYTICS_UNIVERSAL_COOKIE?.name,
+ SKCM_GA_GOOGLE_ANALYTICS_4_COOKIE?.name
+ ]
+ // set cookies
+ const neededCookies =
+ get(necessaryCookies)?.filter(
+ (cookie) => cookie?.showDisclaimerIfMissing && SKCM_NECESSARY_COOKIES.includes(cookie?.name)
+ ) ?? []
+ for (let i = 0; i < neededCookies?.length; i++) {
+ setCookie(neededCookies[i]?.name, value, COOKIE_EXPIRATION_DAYS)
+ }
+ // enable services
+ const _configuredServices = get(configuredServices)?.map((service) => ({
+ ...service,
+ enabled: value === 'true'
+ }))
+ configuredServices.set(_configuredServices)
+}
+
+export const isServiceEnabled = (serviceType: SupportedService): boolean => {
+ const serviceConfig = get(configuredServices)?.find(({ type }) => type === serviceType)
+ return serviceConfig?.enabled
+}
+
+export const removeAdditionalCookies = (): void => {
+ const _necessaryCookies = get(necessaryCookies).map((cookie) => cookie.name)
+ document.cookie
+ ?.split('; ')
+ ?.map((cookie) => cookie.split('=')[0])
+ .forEach((cookie) => {
+ if (!_necessaryCookies.includes(cookie)) {
+ deleteCookie(cookie)
+ }
+ })
+}
diff --git a/src/lib/components/Button.svelte b/cookie-manager/sveltekit/src/lib/components/Button.svelte
similarity index 100%
rename from src/lib/components/Button.svelte
rename to cookie-manager/sveltekit/src/lib/components/Button.svelte
diff --git a/src/lib/components/CookieLibrary/AdditionalCookies.svelte b/cookie-manager/sveltekit/src/lib/components/CookieLibrary/AdditionalCookies.svelte
similarity index 100%
rename from src/lib/components/CookieLibrary/AdditionalCookies.svelte
rename to cookie-manager/sveltekit/src/lib/components/CookieLibrary/AdditionalCookies.svelte
diff --git a/src/lib/components/CookieLibrary/NecessaryCookies.svelte b/cookie-manager/sveltekit/src/lib/components/CookieLibrary/NecessaryCookies.svelte
similarity index 100%
rename from src/lib/components/CookieLibrary/NecessaryCookies.svelte
rename to cookie-manager/sveltekit/src/lib/components/CookieLibrary/NecessaryCookies.svelte
diff --git a/src/lib/components/CookieLibrary/cookies.json b/cookie-manager/sveltekit/src/lib/components/CookieLibrary/cookies.json
similarity index 100%
rename from src/lib/components/CookieLibrary/cookies.json
rename to cookie-manager/sveltekit/src/lib/components/CookieLibrary/cookies.json
diff --git a/src/lib/components/CookieLibrary/index.svelte b/cookie-manager/sveltekit/src/lib/components/CookieLibrary/index.svelte
similarity index 90%
rename from src/lib/components/CookieLibrary/index.svelte
rename to cookie-manager/sveltekit/src/lib/components/CookieLibrary/index.svelte
index 6f732b6..8a1b1df 100644
--- a/src/lib/components/CookieLibrary/index.svelte
+++ b/cookie-manager/sveltekit/src/lib/components/CookieLibrary/index.svelte
@@ -1,9 +1,9 @@