@bsthun/tailwindcss-instant-dark-mode 1.0.0 → 1.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -3
- package/index.ts +3 -82
- package/package.json +1 -1
- package/util/instant.ts +81 -0
- package/util/toggledark.ts +40 -0
package/README.md
CHANGED
@@ -12,12 +12,11 @@ Adding new color class to tailwindcss, topup from original class with `-dark` pr
|
|
12
12
|
| `text-kmutt-800 dark:text-kmutt-200` | `text-kmutt-800-dark` |
|
13
13
|
| `hover:border-blue-300 dark:hover:border-blue-700` | `hover:border-blue-300-dark` |
|
14
14
|
|
15
|
-
Supported colors properties
|
15
|
+
#### Supported colors properties
|
16
16
|
- backgroundColor / `bg-`
|
17
17
|
- borderColor / `border-`
|
18
18
|
- color / `text-`
|
19
|
-
- ringColor / `
|
20
|
-
- divideColor / `ring-`
|
19
|
+
- ringColor / `ring-`
|
21
20
|
- divideColor / `divide-`
|
22
21
|
- placeholderColor / `placeholder-`
|
23
22
|
|
package/index.ts
CHANGED
@@ -1,83 +1,4 @@
|
|
1
|
-
import
|
1
|
+
import { initDarkMode, toggleDarkMode } from './util/toggledark'
|
2
|
+
import { tailwindcssInstantDarkMode } from './util/instant'
|
2
3
|
|
3
|
-
export
|
4
|
-
colorMap: Record<string, string> | null
|
5
|
-
}
|
6
|
-
|
7
|
-
export const tailwindcssInstantDarkMode = (config?: tailwindInstantDarkModeConfig) => {
|
8
|
-
// Helper to get the dark mode equivalent of a color
|
9
|
-
const getDarkEquivalent = (color: string) => {
|
10
|
-
// Map light colors to their dark equivalents
|
11
|
-
if (!config)
|
12
|
-
config = {
|
13
|
-
colorMap: null,
|
14
|
-
}
|
15
|
-
|
16
|
-
if (!config.colorMap) {
|
17
|
-
config.colorMap = {
|
18
|
-
'50': '900',
|
19
|
-
'100': '800',
|
20
|
-
'200': '700',
|
21
|
-
'300': '600',
|
22
|
-
'400': '500',
|
23
|
-
'500': '400',
|
24
|
-
'600': '300',
|
25
|
-
'700': '200',
|
26
|
-
'800': '100',
|
27
|
-
'900': '50',
|
28
|
-
}
|
29
|
-
}
|
30
|
-
|
31
|
-
// Extract color base and shade
|
32
|
-
const match = color.match(/^(.+)-(\d+)$/)
|
33
|
-
if (!match) return color
|
34
|
-
|
35
|
-
const [_, base, shade] = match
|
36
|
-
const darkShade = config.colorMap[shade]
|
37
|
-
|
38
|
-
return darkShade ? `${base}-${darkShade}` : color
|
39
|
-
}
|
40
|
-
|
41
|
-
return plugin(function ({ addComponents, theme }) {
|
42
|
-
// Get all color utilities from theme
|
43
|
-
const utilities = Object.entries(theme('colors') as Record<string, any>).reduce(
|
44
|
-
(acc: Record<string, any>, [colorName, colorValues]) => {
|
45
|
-
if (typeof colorValues === 'object') {
|
46
|
-
Object.entries(colorValues).forEach(([shade, colorValue]) => {
|
47
|
-
const properties = [
|
48
|
-
['backgroundColor', 'bg'],
|
49
|
-
['borderColor', 'border'],
|
50
|
-
['color', 'text'],
|
51
|
-
['ringColor', 'ring'],
|
52
|
-
['divideColor', 'divide'],
|
53
|
-
['placeholderColor', 'placeholder'],
|
54
|
-
] as const
|
55
|
-
|
56
|
-
properties.forEach(([prop, prefix]) => {
|
57
|
-
const className = `${prefix}-${colorName}-${shade}-dark`
|
58
|
-
|
59
|
-
const darkShadeKey = getDarkEquivalent(`${colorName}-${shade}`)
|
60
|
-
const [darkColorName, darkShade] = darkShadeKey.split('-')
|
61
|
-
|
62
|
-
const darkValue = theme('colors')?.[darkColorName]?.[darkShade]
|
63
|
-
|
64
|
-
if (colorValue && darkValue) {
|
65
|
-
acc[`.${className}`] = {
|
66
|
-
[prop]: colorValue,
|
67
|
-
'.dark &': {
|
68
|
-
[prop]: darkValue,
|
69
|
-
},
|
70
|
-
transition: 'color 0.2s, background-color 0.2s, border-color 0.2s',
|
71
|
-
}
|
72
|
-
}
|
73
|
-
})
|
74
|
-
})
|
75
|
-
}
|
76
|
-
return acc
|
77
|
-
},
|
78
|
-
{}
|
79
|
-
)
|
80
|
-
|
81
|
-
addComponents(utilities)
|
82
|
-
})
|
83
|
-
}
|
4
|
+
export { initDarkMode, toggleDarkMode, tailwindcssInstantDarkMode }
|
package/package.json
CHANGED
package/util/instant.ts
ADDED
@@ -0,0 +1,81 @@
|
|
1
|
+
import plugin from 'tailwindcss/plugin'
|
2
|
+
|
3
|
+
export type tailwindInstantDarkModeConfig = {
|
4
|
+
colorMap: Record<string, string> | null
|
5
|
+
}
|
6
|
+
|
7
|
+
export const tailwindcssInstantDarkMode = (config?: tailwindInstantDarkModeConfig) => {
|
8
|
+
const getDarkEquivalent = (color: string) => {
|
9
|
+
if (!config)
|
10
|
+
config = {
|
11
|
+
colorMap: null,
|
12
|
+
}
|
13
|
+
|
14
|
+
if (!config.colorMap) {
|
15
|
+
config.colorMap = {
|
16
|
+
'50': '950',
|
17
|
+
'100': '900',
|
18
|
+
'200': '800',
|
19
|
+
'300': '700',
|
20
|
+
'400': '600',
|
21
|
+
'500': '500',
|
22
|
+
'600': '400',
|
23
|
+
'700': '300',
|
24
|
+
'800': '200',
|
25
|
+
'900': '100',
|
26
|
+
'950': '50',
|
27
|
+
}
|
28
|
+
}
|
29
|
+
|
30
|
+
// Extract color base and shade
|
31
|
+
const match = color.match(/^(.+)-(\d+)$/)
|
32
|
+
if (!match) return color
|
33
|
+
|
34
|
+
const [_, base, shade] = match
|
35
|
+
const darkShade = config.colorMap[shade]
|
36
|
+
|
37
|
+
return darkShade ? `${base}-${darkShade}` : color
|
38
|
+
}
|
39
|
+
|
40
|
+
return plugin(function ({ addComponents, theme }) {
|
41
|
+
const utilities = Object.entries(theme('colors') as Record<string, any>).reduce(
|
42
|
+
(acc: Record<string, any>, [colorName, colorValues]) => {
|
43
|
+
if (typeof colorValues === 'object') {
|
44
|
+
Object.entries(colorValues).forEach(([shade, colorValue]) => {
|
45
|
+
const properties = [
|
46
|
+
['backgroundColor', 'bg'],
|
47
|
+
['borderColor', 'border'],
|
48
|
+
['color', 'text'],
|
49
|
+
['ringColor', 'ring'],
|
50
|
+
['divideColor', 'divide'],
|
51
|
+
['placeholderColor', 'placeholder'],
|
52
|
+
] as const
|
53
|
+
|
54
|
+
properties.forEach(([prop, prefix]) => {
|
55
|
+
const className = `${prefix}-${colorName}-${shade}-dark`
|
56
|
+
|
57
|
+
const darkShadeKey = getDarkEquivalent(`${colorName}-${shade}`)
|
58
|
+
const [darkColorName, darkShade] = darkShadeKey.split('-')
|
59
|
+
|
60
|
+
const darkValue = theme('colors')?.[darkColorName]?.[darkShade]
|
61
|
+
|
62
|
+
if (colorValue && darkValue) {
|
63
|
+
acc[`.${className}`] = {
|
64
|
+
[prop]: colorValue,
|
65
|
+
'.dark &': {
|
66
|
+
[prop]: darkValue,
|
67
|
+
},
|
68
|
+
transition: 'color 0.2s, background-color 0.2s, border-color 0.2s',
|
69
|
+
}
|
70
|
+
}
|
71
|
+
})
|
72
|
+
})
|
73
|
+
}
|
74
|
+
return acc
|
75
|
+
},
|
76
|
+
{}
|
77
|
+
)
|
78
|
+
|
79
|
+
addComponents(utilities)
|
80
|
+
})
|
81
|
+
}
|
@@ -0,0 +1,40 @@
|
|
1
|
+
const apply = (isDark: boolean) => {
|
2
|
+
const root = document.documentElement
|
3
|
+
if (isDark) {
|
4
|
+
root.classList.add('dark')
|
5
|
+
} else {
|
6
|
+
root.classList.remove('dark')
|
7
|
+
}
|
8
|
+
}
|
9
|
+
|
10
|
+
const initDarkMode = () => {
|
11
|
+
const userPref = localStorage.getItem('theme')
|
12
|
+
const systemPref = window.matchMedia('(prefers-color-scheme: dark)').matches
|
13
|
+
|
14
|
+
if (userPref === 'dark') {
|
15
|
+
apply(true)
|
16
|
+
} else if (userPref === 'light') {
|
17
|
+
apply(false)
|
18
|
+
} else {
|
19
|
+
apply(systemPref)
|
20
|
+
}
|
21
|
+
|
22
|
+
const systemPrefListener = window.matchMedia('(prefers-color-scheme: dark)')
|
23
|
+
systemPrefListener.addEventListener('change', (event) => {
|
24
|
+
apply(event.matches)
|
25
|
+
localStorage.setItem('theme', event.matches ? 'dark' : 'light')
|
26
|
+
})
|
27
|
+
}
|
28
|
+
|
29
|
+
const toggleDarkMode = () => {
|
30
|
+
const root = document.documentElement
|
31
|
+
if (root.classList.contains('dark')) {
|
32
|
+
root.classList.remove('dark')
|
33
|
+
localStorage.setItem('theme', 'light')
|
34
|
+
} else {
|
35
|
+
root.classList.add('dark')
|
36
|
+
localStorage.setItem('theme', 'dark')
|
37
|
+
}
|
38
|
+
}
|
39
|
+
|
40
|
+
export { initDarkMode, toggleDarkMode }
|