1
mirror of https://github.com/jakejarvis/dark-mode.git synced 2025-04-29 16:10:29 -04:00

Compare commits

..

27 Commits
0.6.2 ... main

Author SHA1 Message Date
0328cdb280
v0.10.0 2021-11-11 10:45:09 -05:00
57989cf25f switch to microbundle 2021-11-11 10:44:56 -05:00
c62cde5e91
fixes for eslint 8.0.0 2021-10-12 20:22:57 -04:00
ce472773c9
bring bundle config up-to-date with rollup template
https://github.com/jakejarvis/rollup-module-template
2021-10-09 16:49:25 -04:00
07ce4cab10
Release 0.9.1 2021-10-04 09:27:23 -04:00
9c9351398d
remove toggle || null (already checked for) 2021-10-04 09:26:15 -04:00
1c1ff4e186
Release 0.9.0 2021-10-04 09:25:46 -04:00
45d856cab3
add onUserToggle callback, move onInit and onChange up 2021-10-04 09:25:10 -04:00
fba5494cfe
Release 0.8.1 2021-09-09 17:56:35 -04:00
8670de8a30
types: HTMLElement -> Element | null 2021-09-09 17:55:23 -04:00
e5a76a03b3
Release 0.8.0 2021-09-09 17:49:07 -04:00
02f772dd46
Rename package from @jakejarvis/dark-mode to dark-mode-switcheroo 2021-09-09 17:48:20 -04:00
dependabot[bot]
5fc1bd80b3 📦 npm: Bump @babel/core from 7.15.0 to 7.15.5
Bumps [@babel/core](https://github.com/babel/babel/tree/HEAD/packages/babel-core) from 7.15.0 to 7.15.5.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.15.5/packages/babel-core)

---
updated-dependencies:
- dependency-name: "@babel/core"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-09-09 17:45:58 -04:00
dependabot[bot]
ba8cd84d66 📦 npm: Bump @babel/preset-env from 7.15.0 to 7.15.4
Bumps [@babel/preset-env](https://github.com/babel/babel/tree/HEAD/packages/babel-preset-env) from 7.15.0 to 7.15.4.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.15.4/packages/babel-preset-env)

---
updated-dependencies:
- dependency-name: "@babel/preset-env"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-09-09 17:43:21 -04:00
9d599b4675
Release 0.7.2 2021-08-31 10:44:39 -04:00
8f96d0bb83
use rollup-plugin-delete to clean dist folder on build 2021-08-31 10:30:56 -04:00
2fcad1a9e7
update eslint config to use @jakejarvis/eslint-config 2021-08-30 19:41:32 -04:00
20aaf287b2
Release 0.7.1 2021-08-23 09:15:31 -04:00
dependabot[bot]
a84de1b0e5 📦 npm: Bump rollup from 2.56.2 to 2.56.3
Bumps [rollup](https://github.com/rollup/rollup) from 2.56.2 to 2.56.3.
- [Release notes](https://github.com/rollup/rollup/releases)
- [Changelog](https://github.com/rollup/rollup/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rollup/rollup/compare/v2.56.2...v2.56.3)

---
updated-dependencies:
- dependency-name: rollup
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-08-23 09:14:48 -04:00
d00e3d54b2
add version number to banner comment 2021-08-23 09:11:27 -04:00
80153bce73
Release 0.7.0 2021-08-22 10:41:07 -04:00
fa128cb222
remove super-duper edge case testing of localStorage support
use the following methods externally to test on older browsers if needed:
- https://www.npmjs.com/package/storage-available
- https://www.npmjs.com/package/local-storage-fallback
- https://developer.mozilla.org/en-US/docs/Web/API/Web_Storage_API/Using_the_Web_Storage_API#testing_for_availability
2021-08-22 10:38:26 -04:00
dependabot[bot]
582e64ae13 📦 npm: Bump eslint-plugin-compat from 3.12.0 to 3.13.0
Bumps [eslint-plugin-compat](https://github.com/amilajack/eslint-plugin-compat) from 3.12.0 to 3.13.0.
- [Release notes](https://github.com/amilajack/eslint-plugin-compat/releases)
- [Changelog](https://github.com/amilajack/eslint-plugin-compat/blob/master/CHANGELOG.md)
- [Commits](https://github.com/amilajack/eslint-plugin-compat/compare/v3.12.0...v3.13.0)

---
updated-dependencies:
- dependency-name: eslint-plugin-compat
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-08-22 10:37:54 -04:00
eb6d058b5b
set "sideEffects": false 2021-08-16 23:06:22 -04:00
46ade562c4
Release 0.6.3 2021-08-11 09:48:05 -04:00
6ef857154b
publish via CI to NPM and GH packages 2021-08-11 09:47:30 -04:00
df981e17b3
add dependabot.yml 2021-08-11 09:39:52 -04:00
13 changed files with 2310 additions and 2078 deletions

17
.editorconfig Normal file
View File

@ -0,0 +1,17 @@
# http://editorconfig.org
# this file is the top-most editorconfig file
root = true
# all files
[*]
charset = utf-8
end_of_line = lf
indent_style = space
indent_size = 2
trim_trailing_whitespace = true
insert_final_newline = true
# site content
[*.md]
trim_trailing_whitespace = false

View File

@ -1,18 +1,16 @@
{ {
"extends": [ "extends": [
"eslint:recommended", "@jakejarvis/eslint-config",
"plugin:compat/recommended" "plugin:@typescript-eslint/recommended"
], ],
"plugins": [
"@typescript-eslint"
],
"parser": "@typescript-eslint/parser",
"env": { "env": {
"browser": true, "browser": true
"node": true
}, },
"parserOptions": { "ignorePatterns": [
"ecmaVersion": 2015, "dist/**"
"sourceType": "module" ]
},
"rules": {
"quotes": ["error", "double"],
"semi": ["error", "always"]
}
} }

2
.gitattributes vendored Normal file
View File

@ -0,0 +1,2 @@
# Set default behavior to automatically normalize line endings.
* text=auto eol=lf

10
.github/dependabot.yml vendored Normal file
View File

@ -0,0 +1,10 @@
version: 2
updates:
- package-ecosystem: "npm"
directory: "/"
versioning-strategy: increase
schedule:
interval: "daily"
commit-message:
prefix: "📦 npm:"

View File

@ -13,7 +13,7 @@ jobs:
- uses: actions/checkout@v2 - uses: actions/checkout@v2
- uses: actions/setup-node@v2 - uses: actions/setup-node@v2
with: with:
node-version: '14.x' node-version: 16.x
- run: yarn install --frozen-lockfile - run: yarn install --frozen-lockfile
- run: yarn lint - run: yarn lint
- run: yarn build - run: yarn build

20
.github/workflows/release.yml vendored Normal file
View File

@ -0,0 +1,20 @@
name: Release
on:
push:
tags:
- 'v*'
jobs:
npm:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
with:
node-version: 16.x
registry-url: https://registry.npmjs.org/
- run: yarn install --frozen-lockfile
- run: yarn publish
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}

View File

@ -1,10 +1,9 @@
# 🌓 Dark Mode Switcheroo™ # 🌓 Dark Mode Switcheroo™
[![CI](https://github.com/jakejarvis/dark-mode.js/actions/workflows/ci.yml/badge.svg)](https://github.com/jakejarvis/dark-mode.js/actions/workflows/ci.yml) [![CI](https://github.com/jakejarvis/dark-mode/actions/workflows/ci.yml/badge.svg)](https://github.com/jakejarvis/dark-mode/actions/workflows/ci.yml)
[![npm (scoped)](https://img.shields.io/npm/v/@jakejarvis/dark-mode)](https://www.npmjs.com/package/@jakejarvis/dark-mode) [![npm](https://img.shields.io/npm/v/dark-mode-switcheroo)](https://www.npmjs.com/package/dark-mode-switcheroo)
[![MIT License](https://img.shields.io/github/license/jakejarvis/dark-mode?color=violet)](LICENSE)
Very simple CSS dark/light mode toggler with saved preference via local storage & dynamic OS setting detection. Zero dependencies and only ~600 bytes gzipped! Very simple CSS dark/light mode toggler with saved preference via local storage & dynamic OS setting detection. Zero dependencies and [only ~500 bytes gzipped!](https://bundlephobia.com/package/dark-mode-switcheroo)
- [View the example.](https://jakejarvis.github.io/dark-mode/) - [View the example.](https://jakejarvis.github.io/dark-mode/)
- [Read the blog post.](https://jarv.is/notes/dark-mode/) - [Read the blog post.](https://jarv.is/notes/dark-mode/)
@ -21,6 +20,7 @@ Very simple CSS dark/light mode toggler with saved preference via local storage
- **`default`**: The initial `<body>` class hard-coded into the HTML template. (optional, default: `"light"`) - **`default`**: The initial `<body>` class hard-coded into the HTML template. (optional, default: `"light"`)
- **`storageKey`**: Name of the `localStorage` key holding the user's preference. (optional, default: `"dark_mode_pref"`) - **`storageKey`**: Name of the `localStorage` key holding the user's preference. (optional, default: `"dark_mode_pref"`)
- **`onInit([toggle])`**: Callback function executed at the end of initialization. The toggle above is passed in if set. (optional, default: `null`) - **`onInit([toggle])`**: Callback function executed at the end of initialization. The toggle above is passed in if set. (optional, default: `null`)
- **`onUserToggle([toggle])`**: Callback function executed when a user manually interacts with the toggle button. The toggle above (if set) is passed in. (optional, default: `null`)
- **`onChange([theme, toggle])`**: Callback function executed when theme is switched. The new theme and the toggle above (if set) are passed in. (optional, default: `null`) - **`onChange([theme, toggle])`**: Callback function executed when theme is switched. The new theme and the toggle above (if set) are passed in. (optional, default: `null`)
### Browser ### Browser
@ -28,7 +28,7 @@ Very simple CSS dark/light mode toggler with saved preference via local storage
```html ```html
<button class="dark-mode-toggle" style="visibility: hidden;">💡 Click to see the light... or not.</button> <button class="dark-mode-toggle" style="visibility: hidden;">💡 Click to see the light... or not.</button>
<script src="https://unpkg.com/@jakejarvis/dark-mode/dist/dark-mode.min.js"></script> <script src="https://unpkg.com/dark-mode-switcheroo/dist/dark-mode.min.js"></script>
<script> <script>
window.darkMode.init({ window.darkMode.init({
toggle: document.querySelector(".dark-mode-toggle"), toggle: document.querySelector(".dark-mode-toggle"),
@ -51,15 +51,15 @@ Very simple CSS dark/light mode toggler with saved preference via local storage
### Node ### Node
```bash ```bash
npm install @jakejarvis/dark-mode npm install dark-mode-switcheroo
# or... # or...
yarn add @jakejarvis/dark-mode yarn add dark-mode-switcheroo
``` ```
#### Module via `import` #### Module via `import`
```js ```js
import { init } from "@jakejarvis/dark-mode"; import { init } from "dark-mode-switcheroo";
init({ init({
// ...same as browser. // ...same as browser.
@ -69,7 +69,7 @@ init({
#### CommonJS via `require()` #### CommonJS via `require()`
```js ```js
const darkMode = require("@jakejarvis/dark-mode"); const darkMode = require("dark-mode-switcheroo");
darkMode.init({ darkMode.init({
// ...same as browser. // ...same as browser.

View File

@ -47,7 +47,7 @@
<p><a href="https://github.com/jakejarvis/dark-mode" target="_blank" rel="noopener">View the source code</a> or <a href="https://jarv.is/notes/dark-mode/" target="_blank" rel="noopener">read the post</a>.</p> <p><a href="https://github.com/jakejarvis/dark-mode" target="_blank" rel="noopener">View the source code</a> or <a href="https://jarv.is/notes/dark-mode/" target="_blank" rel="noopener">read the post</a>.</p>
<script src="../dist/dark-mode.min.js"></script> <!-- or use CDN: https://unpkg.com/@jakejarvis/dark-mode/dist/dark-mode.min.js --> <script src="../dist/dark-mode.min.js"></script> <!-- or use CDN: https://unpkg.com/dark-mode-switcheroo/dist/dark-mode.min.js -->
<script> <script>
window.darkMode.init({ window.darkMode.init({
toggle: document.querySelector(".dark-mode-toggle"), toggle: document.querySelector(".dark-mode-toggle"),

View File

@ -1,8 +1,9 @@
{ {
"name": "@jakejarvis/dark-mode", "name": "dark-mode-switcheroo",
"version": "0.6.2", "version": "0.10.0",
"description": "🌓 Simple CSS theme switching with saved preferences and automatic OS setting detection", "description": "🌓 Simple CSS theme switching with saved preferences and automatic OS setting detection",
"license": "MIT", "license": "MIT",
"homepage": "https://jrvs.io/darkmode",
"author": { "author": {
"name": "Jake Jarvis", "name": "Jake Jarvis",
"email": "jake@jarv.is", "email": "jake@jarv.is",
@ -16,36 +17,32 @@
"files": [ "files": [
"dist" "dist"
], ],
"main": "./dist/dark-mode.cjs.js", "source": "./src/dark-mode.ts",
"main": "./dist/dark-mode.cjs",
"module": "./dist/dark-mode.esm.js", "module": "./dist/dark-mode.esm.js",
"unpkg": "./dist/dark-mode.min.js", "unpkg": "./dist/dark-mode.min.js",
"types": "./dist/dark-mode.d.ts",
"exports": { "exports": {
"require": "./dist/dark-mode.cjs.js", "require": "./dist/dark-mode.cjs",
"import": "./dist/dark-mode.esm.js", "import": "./dist/dark-mode.esm.js",
"browser": "./dist/dark-mode.min.js" "browser": "./dist/dark-mode.min.js"
}, },
"types": "./dist/dark-mode.d.ts",
"scripts": { "scripts": {
"build": "rollup -c", "build": "microbundle --format cjs,esm,umd --name 'darkMode'",
"lint": "eslint src/**/*.js", "lint": "eslint .",
"prepublishOnly": "rm -rf dist && yarn build" "prepublishOnly": "yarn build"
}, },
"dependencies": {}, "dependencies": {},
"devDependencies": { "devDependencies": {
"@babel/core": "^7.15.0", "@jakejarvis/eslint-config": "*",
"@babel/preset-env": "^7.15.0", "@typescript-eslint/eslint-plugin": "^5.3.1",
"@rollup/plugin-babel": "^5.3.0", "@typescript-eslint/parser": "^5.3.1",
"@rollup/plugin-eslint": "^8.0.1", "eslint": "^8.2.0",
"@rollup/plugin-node-resolve": "^13.0.4", "microbundle": "^0.14.1",
"eslint": "^7.32.0", "typescript": "^4.4.4"
"eslint-plugin-compat": "^3.11.1",
"rollup": "^2.56.0",
"rollup-plugin-copy": "^3.4.0",
"rollup-plugin-filesize": "^9.1.1",
"rollup-plugin-terser": "^7.0.2"
}, },
"keywords": [ "keywords": [
"frontend", "front-end",
"dark mode", "dark mode",
"theme", "theme",
"appearance", "appearance",

View File

@ -1,87 +0,0 @@
import resolve from "@rollup/plugin-node-resolve";
import { babel } from "@rollup/plugin-babel";
import { terser } from "rollup-plugin-terser";
import eslint from "@rollup/plugin-eslint";
import filesize from "rollup-plugin-filesize";
import copy from "rollup-plugin-copy";
const banner = "/*! Dark Mode Switcheroo | MIT License | jrvs.io/darkmode */";
export default [
{
// universal (browser and node)
input: "src/index.js",
output: [
{
name: "darkMode",
file: "dist/dark-mode.js",
format: "umd",
exports: "named",
esModule: false,
banner: banner,
},
{
name: "darkMode",
file: "dist/dark-mode.min.js",
format: "umd",
exports: "named",
esModule: false,
plugins: [
terser({
output: {
preamble: banner,
},
}),
],
},
],
plugins: [
copy({
// clearly this isn't really typescript, so we need to manually copy the type definition file
targets: [
{
src: "src/index.d.ts",
dest: "dist",
rename: "dark-mode.d.ts",
},
],
}),
resolve(),
eslint(),
babel({
babelHelpers: "bundled",
presets: [["@babel/preset-env"]],
exclude: ["node_modules/**"],
}),
filesize(),
],
},
{
// modules
input: "src/index.js",
output: [
{
// ES6 module (import)
file: "dist/dark-mode.esm.js",
format: "esm",
exports: "named",
banner: banner,
},
{
// commonjs (require)
file: "dist/dark-mode.cjs.js",
format: "cjs",
exports: "named",
banner: banner,
},
],
plugins: [
resolve(),
babel({
babelHelpers: "bundled",
exclude: ["node_modules/**"],
}),
filesize(),
],
},
];

View File

@ -1,6 +1,12 @@
"use strict"; export function init(options: {
toggle?: Element | null;
const init = function (options) { classes?: { dark: string, light: string };
default?: string;
storageKey?: string;
onInit?: (toggle?: Element | null) => unknown;
onUserToggle?: (toggle?: Element | null) => unknown;
onChange?: (theme: string, toggle?: Element | null) => unknown;
}): void {
options = options || {}; options = options || {};
// use a specified element(s) to trigger swap when clicked // use a specified element(s) to trigger swap when clicked
@ -8,8 +14,7 @@ const init = function (options) {
// check for preset `dark_mode_pref` preference in local storage // check for preset `dark_mode_pref` preference in local storage
const storageKey = options.storageKey || "dark_mode_pref"; const storageKey = options.storageKey || "dark_mode_pref";
const storageAvailable = isStorageAvailable(); const pref = localStorage.getItem(storageKey);
const pref = storageAvailable ? localStorage.getItem(storageKey) : null;
// change CSS via these <body> classes: // change CSS via these <body> classes:
const dark = options.classes ? options.classes.dark : "dark"; const dark = options.classes ? options.classes.dark : "dark";
@ -22,25 +27,30 @@ const init = function (options) {
let active = defaultTheme === dark; let active = defaultTheme === dark;
// receives a class name and switches <body> to it // receives a class name and switches <body> to it
const activateTheme = function (theme, remember) { const activateTheme = function (theme: string, remember?: boolean) {
document.body.classList.remove(dark, light);
document.body.classList.add(theme);
active = theme === dark;
if (storageAvailable && !!remember) {
localStorage.setItem(storageKey, theme);
}
// optional onChange callback function passed as option // optional onChange callback function passed as option
if (typeof options.onChange === "function") { if (typeof options.onChange === "function") {
options.onChange(theme, toggle); options.onChange(theme, toggle);
} }
document.body.classList.remove(dark, light);
document.body.classList.add(theme);
active = theme === dark;
if (remember) {
localStorage.setItem(storageKey, theme);
}
}; };
// optional onInit callback function passed as option
if (typeof options.onInit === "function") {
options.onInit(toggle);
}
// user has never clicked the button, so go by their OS preference until/if they do so // user has never clicked the button, so go by their OS preference until/if they do so
if (!pref) { if (!pref) {
// returns media query selector syntax // returns media query selector syntax
const prefers = function (colorScheme) { const prefers = function (colorScheme: "dark" | "light") {
// https://drafts.csswg.org/mediaqueries-5/#prefers-color-scheme // https://drafts.csswg.org/mediaqueries-5/#prefers-color-scheme
return `(prefers-color-scheme: ${colorScheme})`; return `(prefers-color-scheme: ${colorScheme})`;
}; };
@ -78,6 +88,11 @@ const init = function (options) {
if (toggle !== null) { if (toggle !== null) {
// handle toggle click // handle toggle click
toggle.addEventListener("click", function () { toggle.addEventListener("click", function () {
// optional onUserToggle callback function passed as option
if (typeof options.onUserToggle === "function") {
options.onUserToggle(toggle);
}
// switch to the opposite theme & save preference in local storage // switch to the opposite theme & save preference in local storage
if (active) { if (active) {
activateTheme(light, true); activateTheme(light, true);
@ -86,25 +101,4 @@ const init = function (options) {
} }
}); });
} }
// optional onInit callback function passed as option
if (typeof options.onInit === "function") {
options.onInit(toggle);
} }
};
// recommended method (by MDN) to detect localStorage availability:
// https://developer.mozilla.org/en-US/docs/Web/API/Web_Storage_API/Using_the_Web_Storage_API#feature-detecting_localstorage
const isStorageAvailable = function () {
try {
var storage = window["localStorage"];
var x = "__storage_test__";
storage.setItem(x, x);
storage.removeItem(x);
return true;
} catch (e) {
return false;
}
};
export { init };

8
src/index.d.ts vendored
View File

@ -1,8 +0,0 @@
export function init(options?: {
toggle?: HTMLElement;
classes?: { dark: string, light: string };
default?: string;
storageKey?: string;
onInit?: (toggle?: HTMLElement) => unknown;
onChange?: (theme?: string, toggle?: HTMLElement) => unknown;
}): void;

4081
yarn.lock

File diff suppressed because it is too large Load Diff