Website Structure

This commit is contained in:
supalerk-ar66 2026-01-13 10:46:40 +07:00
parent 62812f2090
commit 71f0676a62
22365 changed files with 4265753 additions and 791 deletions

View file

@ -0,0 +1,75 @@
import { createReactivePlugin } from '../../utils/private.create/create.js'
const Plugin = createReactivePlugin({
isActive: false,
mode: false
}, {
__media: void 0,
set (val) {
if (__QUASAR_SSR_SERVER__) return
Plugin.mode = val
if (val === 'auto') {
if (Plugin.__media === void 0) {
Plugin.__media = window.matchMedia('(prefers-color-scheme: dark)')
Plugin.__updateMedia = () => { Plugin.set('auto') }
Plugin.__media.addListener(Plugin.__updateMedia)
}
val = Plugin.__media.matches
}
else if (Plugin.__media !== void 0) {
Plugin.__media.removeListener(Plugin.__updateMedia)
Plugin.__media = void 0
}
Plugin.isActive = val === true
document.body.classList.remove(`body--${ val === true ? 'light' : 'dark' }`)
document.body.classList.add(`body--${ val === true ? 'dark' : 'light' }`)
},
toggle () {
if (__QUASAR_SSR_SERVER__ !== true) {
Plugin.set(Plugin.isActive === false)
}
},
install ({ $q, ssrContext }) {
const dark = __QUASAR_SSR_CLIENT__
? document.body.classList.contains('body--dark')
: $q.config.dark
if (__QUASAR_SSR_SERVER__) {
this.isActive = dark === true
$q.dark = {
isActive: false,
mode: false,
set: val => {
ssrContext._meta.bodyClasses = ssrContext._meta.bodyClasses
.replace(' body--light', '')
.replace(' body--dark', '') + ` body--${ val === true ? 'dark' : 'light' }`
$q.dark.isActive = val === true
$q.dark.mode = val
},
toggle: () => {
$q.dark.set($q.dark.isActive === false)
}
}
$q.dark.set(dark)
return
}
$q.dark = this
if (this.__installed !== true) {
this.set(dark !== void 0 ? dark : false)
}
}
})
export default Plugin

View file

@ -0,0 +1,50 @@
{
"meta": {
"docsUrl": "https://v2.quasar.dev/quasar-plugins/dark"
},
"injection": "$q.dark",
"quasarConfOptions": {
"propName": "dark",
"type": [ "Boolean", "String" ],
"desc": "\"'auto'\" uses the OS/browser preference. \"true\" forces dark mode. \"false\" forces light mode.",
"values": [ "'auto'", "true", "false" ]
},
"props": {
"isActive": {
"type": "Boolean",
"desc": "Is Dark mode active?",
"reactive": true
},
"mode": {
"type": [ "Boolean", "String" ],
"desc": "Dark mode configuration (not status)",
"values": [ "'auto'", "true", "false" ],
"reactive": true
}
},
"methods": {
"set": {
"desc": "Set dark mode status",
"params": {
"status": {
"type": [ "Boolean", "String" ],
"desc": "Dark mode status",
"values": [ "true", "false", "'auto'" ],
"required": true
}
},
"returns": null
},
"toggle": {
"desc": "Toggle dark mode status",
"params": null,
"returns": null
}
}
}

View file

@ -0,0 +1,158 @@
import { describe, test, expect, vi } from 'vitest'
import { mount } from '@vue/test-utils'
import Dark from './Dark.js'
const mountPlugin = () => mount({ template: '<div />' })
describe('[Dark API]', () => {
describe('[Injection]', () => {
test('is injected into $q', () => {
const wrapper = mountPlugin()
expect(Dark).toMatchObject(wrapper.vm.$q.dark)
})
})
describe('[Props]', () => {
describe('[(prop)isActive]', () => {
test('is correct type', () => {
mountPlugin()
expect(Dark.isActive).toBeTypeOf('boolean')
})
test('is reactive', () => {
const { vm: { $q } } = mountPlugin()
expect(Dark.isActive).toBe(false)
expect($q.dark.isActive).toBe(false)
expect(
document.body.classList.contains('body--dark')
).toBe(false)
Dark.set(true)
expect(Dark.isActive).toBe(true)
expect($q.dark.isActive).toBe(true)
expect(
document.body.classList.contains('body--dark')
).toBe(true)
})
})
describe('[(prop)mode]', () => {
test('is correct type', () => {
mountPlugin()
expect([ 'auto', true, false ]).toContain(Dark.mode)
})
})
})
describe('[Methods]', () => {
describe('[(method)set]', () => {
test('should be callable', () => {
const { vm: { $q } } = mountPlugin()
expect(
Dark.set(true)
).toBeUndefined()
expect(Dark.isActive).toBe(true)
expect($q.dark.isActive).toBe(true)
expect(
document.body.classList.contains('body--dark')
).toBe(true)
expect(
Dark.set(false)
).toBeUndefined()
expect(Dark.isActive).toBe(false)
expect($q.dark.isActive).toBe(false)
expect(
document.body.classList.contains('body--dark')
).toBe(false)
})
test('should handle auto mode', () => {
const { vm: { $q } } = mountPlugin()
// jsdom hack
const media = {
matches: true,
addListener: vi.fn(),
removeListener: vi.fn()
}
window.matchMedia = vi.fn(() => media)
Dark.set('auto')
expect(Dark.mode).toBe('auto')
expect(media.addListener).toHaveBeenCalledTimes(1)
expect(media.removeListener).not.toHaveBeenCalled()
expect(Dark.isActive).toBe(true)
expect($q.dark.isActive).toBe(true)
expect(
document.body.classList.contains('body--dark')
).toBe(true)
media.matches = false
Dark.__updateMedia()
expect(media.addListener).toHaveBeenCalledTimes(1)
expect(media.removeListener).not.toHaveBeenCalled()
expect(Dark.isActive).toBe(false)
expect($q.dark.isActive).toBe(false)
expect(
document.body.classList.contains('body--dark')
).toBe(false)
Dark.set(true)
expect(Dark.mode).not.toBe('auto')
expect(media.addListener).toHaveBeenCalledTimes(1)
expect(media.removeListener).toHaveBeenCalledTimes(1)
expect(Dark.isActive).toBe(true)
expect($q.dark.isActive).toBe(true)
expect(
document.body.classList.contains('body--dark')
).toBe(true)
})
})
describe('[(method)toggle]', () => {
test('should be callable', () => {
const { vm: { $q } } = mountPlugin()
Dark.set(true)
expect(Dark.isActive).toBe(true)
expect($q.dark.isActive).toBe(true)
expect(
document.body.classList.contains('body--dark')
).toBe(true)
expect(
Dark.toggle()
).toBeUndefined()
expect(Dark.isActive).toBe(false)
expect($q.dark.isActive).toBe(false)
expect(
document.body.classList.contains('body--dark')
).toBe(false)
Dark.toggle()
expect(Dark.isActive).toBe(true)
expect($q.dark.isActive).toBe(true)
expect(
document.body.classList.contains('body--dark')
).toBe(true)
})
})
})
})