Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More →
Socket
Sign inDemoInstall
Socket

@nuxtjs/color-mode

Package Overview
Dependencies
Maintainers
4
Versions
47
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@nuxtjs/color-mode - npm Package Compare versions

Comparing version 1.1.1 to 2.0.0

11

CHANGELOG.md

@@ -5,2 +5,13 @@ # Changelog

## [2.0.0](https://github.com/nuxt-community/color-mode-module/compare/v1.1.1...v2.0.0) (2020-10-13)
### ⚠ BREAKING CHANGES
* Version 2 (#39)
### Features
* Version 2 ([#39](https://github.com/nuxt-community/color-mode-module/issues/39)) ([47664d7](https://github.com/nuxt-community/color-mode-module/commit/47664d76dc76a44ff270a6cd8569f512e5b004f3))
### [1.1.1](https://github.com/nuxt-community/color-mode-module/compare/v1.1.0...v1.1.1) (2020-09-15)

@@ -7,0 +18,0 @@

8

lib/module.js

@@ -16,9 +16,3 @@ import { resolve } from 'path'

classSuffix: '-mode',
cookie: {
key: 'nuxt-color-mode',
options: {
path: this.options.router.base,
sameSite: 'lax'
}
}
storageKey: 'nuxt-color-mode'
}

@@ -25,0 +19,0 @@ // defu(object, defaults)

@@ -10,4 +10,9 @@ // Add dark / light detection that runs before loading Nuxt.js

const preference = getCookie('<%= options.cookie.key %>') || '<%= options.preference %>'
const value = preference === 'system' ? getColorScheme() : preference
const preference = window.localStorage.getItem('<%= options.storageKey %>') || '<%= options.preference %>'
let value = preference === 'system' ? getColorScheme() : preference
// Applied forced color mode
const forcedColorMode = d.body.getAttribute('data-color-mode-forced')
if (forcedColorMode) {
value = forcedColorMode
}

@@ -24,18 +29,2 @@ addClass(value)

function getCookie (name) {
const nameEQ = name + '='
const cookies = d.cookie.split(';')
for (let i = 0; i < cookies.length; i++) {
let cookie = cookies[i]
while (cookie.charAt(0) === ' ') {
cookie = cookie.substring(1, cookie.length)
}
if (cookie.indexOf(nameEQ) === 0) {
return cookie.substring(nameEQ.length, cookie.length)
}
}
return null
}
function addClass (value) {

@@ -42,0 +31,0 @@ const className = '<%= options.classPrefix %>' + value + '<%= options.classSuffix %>'

@@ -1,1 +0,1 @@

!function(){"use strict";var e=window,s=document,t=s.documentElement,n=["dark","light"],o=function(e){for(var t=e+"=",n=s.cookie.split(";"),o=0;o<n.length;o++){for(var a=n[o];" "===a.charAt(0);)a=a.substring(1,a.length);if(0===a.indexOf(t))return a.substring(t.length,a.length)}return null}("<%= options.cookie.key %>")||"<%= options.preference %>",a="system"===o?c():o;function i(e){var s="<%= options.classPrefix %>"+e+"<%= options.classSuffix %>";t.classList?t.classList.add(s):t.className+=" "+s}function r(s){return e.matchMedia("(prefers-color-scheme"+s+")")}function c(){if(e.matchMedia&&"not all"!==r("").media)for(var s of n)if(r(":"+s).matches)return s;return"<%= options.fallback %>"}i(a),e["<%= options.globalName %>"]={preference:o,value:a,getColorScheme:c,addClass:i,removeClass:function(e){var s="<%= options.classPrefix %>"+e+"<%= options.classSuffix %>";t.classList?t.classList.remove(s):t.className=t.className.replace(new RegExp(s,"g"),"")}}}();
!function(){"use strict";var e=window,s=document,o=s.documentElement,a=["dark","light"],t=window.localStorage.getItem("<%= options.storageKey %>")||"<%= options.preference %>",c="system"===t?l():t,i=s.body.getAttribute("data-color-mode-forced");function r(e){var s="<%= options.classPrefix %>"+e+"<%= options.classSuffix %>";o.classList?o.classList.add(s):o.className+=" "+s}function n(s){return e.matchMedia("(prefers-color-scheme"+s+")")}function l(){if(e.matchMedia&&"not all"!==n("").media)for(var s of a)if(n(":"+s).matches)return s;return"<%= options.fallback %>"}i&&(c=i),r(c),e["<%= options.globalName %>"]={preference:t,value:c,getColorScheme:l,addClass:r,removeClass:function(e){var s="<%= options.classPrefix %>"+e+"<%= options.classSuffix %>";o.classList?o.classList.remove(s):o.className=o.className.replace(new RegExp(s,"g"),"")}}}();
import Vue from 'vue'
import { serialize } from 'cookie'
import colorSchemeComponent from './color-scheme'

@@ -7,5 +6,5 @@

const cookieKey = '<%= options.cookie.key %>'
const cookieOptions = JSON.parse('<%= JSON.stringify(options.cookie.options) %>')
const storageKey = '<%= options.storageKey %>'
const colorMode = window['<%= options.globalName %>']
const getForcedColorMode = route => route.matched[0] && route.matched[0].components.default.options.colorMode

@@ -19,5 +18,12 @@ export default function (ctx, inject) {

value: colorMode.value,
unknown: colorMode.preference === 'system'
unknown: false
}
const pageColorMode = getForcedColorMode(ctx.route)
if (pageColorMode) {
data.value = pageColorMode
data.forced = true
colorMode.addClass(pageColorMode)
}
}
// Get current page component
const $colorMode = new Vue({

@@ -27,2 +33,5 @@ data,

preference (preference) {
if (this.forced) {
return
}
if (preference === 'system') {

@@ -52,3 +61,3 @@ this.value = colorMode.getColorScheme()

_watchMedia () {
if (this._mediaWatcher || !window.matchMedia) {
if (this._darkWatcher || !window.matchMedia) {
return

@@ -59,3 +68,3 @@ }

this._darkWatcher.addListener((e) => {
if (this.preference === 'system') {
if (!this.forced && this.preference === 'system') {
this.value = colorMode.getColorScheme()

@@ -67,3 +76,3 @@ }

window.addEventListener('storage', (e) => {
if (e.key === cookieKey) {
if (e.key === storageKey) {
this.preference = e.newValue

@@ -74,9 +83,4 @@ }

_storePreference (preference) {
// Cookies for SSR
document.cookie = serialize(cookieKey, preference, cookieOptions)
// Local storage to sync with other tabs
if (window.localStorage) {
window.localStorage.setItem(cookieKey, preference)
}
window.localStorage.setItem(storageKey, preference)
}

@@ -86,10 +90,25 @@ }

if ($colorMode.unknown) {
window.onNuxtReady(() => {
window.onNuxtReady(() => {
if ($colorMode.unknown) {
$colorMode.preference = colorMode.preference
$colorMode.value = colorMode.value
$colorMode.unknown = false
}
ctx.app.router.beforeEach((route, from, next) => {
const forcedColorMode = getForcedColorMode(route)
if (forcedColorMode && forcedColorMode !== 'system') {
$colorMode.value = forcedColorMode
$colorMode.forced = true
} else {
if (forcedColorMode === 'system') {
console.warn('You cannot force the colorMode to system at the page level.')
}
$colorMode.forced = false
$colorMode.value = $colorMode.preference === 'system' ? colorMode.getColorScheme() : $colorMode.preference
}
next()
})
}
})
inject('colorMode', $colorMode)
}
import Vue from 'vue'
import { parse } from 'cookie'
import colorSchemeComponent from './color-scheme'
const cookieKey = '<%= options.cookie.key %>'

@@ -9,19 +7,24 @@ Vue.component('<%= options.componentName %>', colorSchemeComponent)

export default function (ctx, inject) {
let preference = '<%= options.preference %>'
const preference = '<%= options.preference %>'
// Try to read from cookies
if (ctx.req) {
// Check if cookie exist, otherwise TypeError: argument str must be a string
const cookies = parse(ctx.req.headers.cookie || '')
if (cookies[cookieKey]) {
preference = cookies[cookieKey]
}
}
const colorMode = {
preference,
value: preference,
unknown: process.static || !ctx.req || preference === 'system'
unknown: true,
forced: false
}
if (ctx.route.matched[0]) {
const pageColorMode = ctx.route.matched[0].components.default.options.colorMode
if (pageColorMode && pageColorMode !== 'system') {
colorMode.value = pageColorMode
colorMode.forced = true
ctx.app.head.bodyAttrs = ctx.app.head.bodyAttrs || {}
ctx.app.head.bodyAttrs['data-color-mode-forced'] = pageColorMode
} else if (pageColorMode === 'system') {
console.warn('You cannot force the colorMode to system at the page level.')
}
}
ctx.beforeNuxtRender(({ nuxtState }) => {

@@ -28,0 +31,0 @@ nuxtState.colorMode = colorMode

{
"name": "@nuxtjs/color-mode",
"version": "1.1.1",
"version": "2.0.0",
"description": "Dark and Light mode for NuxtJS with auto detection",

@@ -34,3 +34,3 @@ "repository": "nuxt-community/color-mode-module",

"@commitlint/config-conventional": "^9.1.2",
"@nuxt/types": "^2.14.5",
"@nuxt/types": "^2.14.6",
"@nuxtjs/eslint-config": "^3.1.0",

@@ -40,8 +40,8 @@ "@nuxtjs/module-test-utils": "^1.6.3",

"babel-eslint": "latest",
"babel-jest": "^26.3.0",
"eslint": "^7.9.0",
"babel-jest": "^26.5.2",
"eslint": "^7.10.0",
"husky": "latest",
"jest": "^26.4.2",
"nuxt": "^2.14.5",
"rollup": "^2.26.11",
"jest": "^26.5.2",
"nuxt": "^2.14.6",
"rollup": "^2.29.0",
"rollup-plugin-babel": "latest",

@@ -48,0 +48,0 @@ "rollup-plugin-terser": "^6.1.0",

@@ -0,1 +1,3 @@

[![@nuxtjs/color-mode](https://color-mode.nuxtjs.org/preview.png)](https://color-mode.nuxtjs.org)
# @nuxtjs/color-mode

@@ -16,3 +18,4 @@

[📖 Release Notes](./CHANGELOG.md)
- [✨ &nbsp;Release Notes](https://color-mode.nuxtjs.org/releases)
- [📖 &nbsp;Documentation](https://color-mode.nuxtjs.org)

@@ -22,172 +25,10 @@ ## Features

- Add `.${color}-mode` class to `<html>` for easy CSS theming
- Force a page to a specific color mode (perfect for incremental development)
- Works with any NuxtJS target (`static` or `server`) and rendering (`universal` and `spa`)
- Auto detect the system [color-mode](https://drafts.csswg.org/mediaqueries-5/#descdef-media-prefers-color-mode)
- Sync between tabs 🔄
- Sync dark mode across tabs and windows 🔄
- Supports IE9+ 👴
ℹī¸ &nbsp;This module is using a cookie to support server-side rendering, if your visitors are located in Europe, make sure to follow the [EU cookie directive](https://en.wikipedia.org/wiki/HTTP_cookie#EU_cookie_directive)
[📖 &nbsp;Read more](https://color-mode.nuxtjs.org)
## Setup
1. Add `@nuxtjs/color-mode` dependency to your project
```bash
yarn add --dev @nuxtjs/color-mode
# OR npm install --save-dev @nuxtjs/color-mode
```
2. Add `@nuxtjs/color-mode` to the `buildModules` section of your `nuxt.config.js`
```js
{
buildModules: [
// Simple usage
'@nuxtjs/color-mode'
]
}
```
ℹī¸ &nbsp;Use the `modules` property instead of `buildModules` if:
- you are using `ssr: false` and `nuxt start`, see [#25](https://github.com/nuxt-community/color-mode-module/issues/25#issuecomment-692567237)
- you are using `nuxt < 2.9.0`
3. Start theming your CSS with `.dark-mode` and `.light-mode` classes
## Usage
It injects `$colorMode` helper with:
- `preference`: Actual color-mode selected (can be `'system'`), update it to change the user preferred color mode
- `value`: Useful to know what color mode has been detected when `$colorMode === 'system'`, you should not update it
- `unknown`: Useful to know if during SSR or Generate, we need to render a placeholder
```vue
<template>
<div>
<h1>Color mode: {{ $colorMode.value }}</h1>
<select v-model="$colorMode.preference">
<option value="system">System</option>
<option value="light">Light</option>
<option value="dark">Dark</option>
<option value="sepia">Sepia</option>
</select>
</div>
</template>
<style>
body {
background-color: #fff;
color: rgba(0,0,0,0.8);
}
.dark-mode body {
background-color: #091a28;
color: #ebf4f1;
}
.sepia-mode body {
background-color: #f1e7d0;
color: #433422;
}
</style>
```
You can see a more advanced example in the [example/ directory](./example) or [play online on CodeSandBox](https://codesandbox.io/s/github/nuxt-community/color-mode-module/tree/master/?fontsize=14&hidenavigation=1&theme=dark&file=/example/pages/index.vue).
## Configuration
You can configure the module by providing the `colorMode` property in your `nuxt.config.js`, here are the default options:
```js
colorMode: {
preference: 'system', // default value of $colorMode.preference
fallback: 'light', // fallback value if not system preference found
hid: 'nuxt-color-mode-script',
globalName: '__NUXT_COLOR_MODE__',
componentName: 'ColorScheme',
classPrefix: '',
classSufix: '-mode',
cookie: {
key: 'nuxt-color-mode',
options: {
path: nuxt.options.router.base, // https://nuxtjs.org/api/configuration-router#base
sameSite: 'lax' // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie/SameSite
}
}
}
```
Notes:
- `'system'` is a special value, it will automatically detect the color mode based on the system preferences (see [prefers-color-mode spec](https://drafts.csswg.org/mediaqueries-5/#descdef-media-prefers-color-mode)). The value injected will be either `'light'` or `'dark'`. If `no-preference` is detected or the browser does not handle color-mode, it will set the `fallback` value.
- `cookie` are the options where to store the chosen color mode (to make it work universally), the `cookie.options` are available on the [cookie serialize options](https://www.npmjs.com/package/cookie#options-1) documentation. Each option will recursively overwrite the default property (by using [defu](https://github.com/nuxt-contrib/defu)).
## Caveats
If you are doing SSR (`nuxt start` or `nuxt generate`) and if `$colorMode.preference` is set to `'system'`, using `$colorMode` in your Vue template will lead to a flash. This is due to the fact that we cannot know the user preferences when pre-rendering the page since they are detected on client-side.
To avoid the flash, you have to guard any rendering path which depends on `$colorMode` with `$colorMode.unknown` to render a placeholder or use our `<ColorScheme>` component.
**Example:**
```vue
<template>
<ColorScheme placeholder="..." tag="span">
Color mode: <b>{{ $colorMode.preference }}</b>
<span v-if="$colorMode.preference === 'system'">(<i>{{ $colorMode.value }}</i> mode detected)</span>
</ColorScheme>
</template>
```
Props:
- `placeholder`: `String`
- `tag`: `String`, default: `'span'`
## TailwindCSS Dark Mode
### Tailwind v1.8+
Tailwind v1.8 introduced [dark mode support](https://github.com/tailwindlabs/tailwindcss/pull/2279), in order to work with @nuxtjs/color-mode, you need to set `dark: 'class'` in your `tailwind.config.js`:
```js
// tailwind.config.js
module.exports = {
experimental: {
darkModeVariant: true
},
dark: 'class'
}
```
Then in your `nuxt.config.js`, set the `classSuffix` option to an empty string:
```js
// nuxt.config.js
export default {
// ...
colorMode: {
classSuffix: ''
}
}
```
### Tailwindcss Dark Mode Plugin
You can easily integrate this module with [tailwindcss-dark-mode](https://github.com/ChanceArthur/tailwindcss-dark-mode) by just setting `darkSelector: '.dark-mode'`, see [changing the selector documentation](https://github.com/ChanceArthur/tailwindcss-dark-mode#changing-the-selector).
```js
// tailwind.config.js
module.exports = {
theme: {
darkSelector: '.dark-mode'
},
variants: {
backgroundColor: ["dark", "dark-hover", "dark-group-hover", "dark-even", "dark-odd"],
borderColor: ["dark", "dark-focus", "dark-focus-within"],
textColor: ["dark", "dark-hover", "dark-active"]
},
plugins: [
require('tailwindcss-dark-mode')()
]
}
```
Checkout a [live example on CodeSandBox](https://codesandbox.io/s/nuxt-dark-tailwindcss-17g2j?file=/pages/index.vue) as well as [@nuxtjs/tailwindcss](https://github.com/nuxt-community/tailwindcss-module) module.
## Contributing

@@ -197,3 +38,3 @@

[![Edit @nuxtjs/tailwindcss](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/github/nuxt-community/color-mode-module/tree/master/?fontsize=14&hidenavigation=1&theme=dark)
[![Edit @nuxtjs/color-mode](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/github/nuxt-community/color-mode-module/tree/master/?fontsize=14&hidenavigation=1&theme=dark)

@@ -200,0 +41,0 @@ Or locally:

@@ -1,18 +0,1 @@

export interface ColorModeCookieOptions {
/**
* Default: `nuxt-color-mode`
*/
key: string,
options: {
/**
* Default: `nuxt.options.router.base`
*/
path: string,
/**
* Default: `lax`
*/
sameSite: string
}
}
export interface ColorModeOptions {

@@ -47,3 +30,6 @@ /**

classSuffix: string,
cookie: ColorModeCookieOptions
/**
* Default: 'nuxt-color-mode'
*/
storageKey: string
}

@@ -54,3 +40,4 @@

value: string,
unknown: boolean
unknown: boolean,
forced: boolean
}
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡ī¸ by Socket Inc