@@ -61,6 +61,7 @@ export interface ThemePluginOptions<Z extends ThemeRecord = ThemeRecord> {
6161 default ?: ID
6262 palette ?: TokenCollection
6363 themes ?: Record < ID , Z >
64+ target ?: string | HTMLElement | null
6465}
6566
6667/**
@@ -246,24 +247,56 @@ export function createThemePlugin<
246247 Z extends ThemeTicket = ThemeTicket ,
247248 E extends ThemeContext < Z > = ThemeContext < Z > ,
248249> ( _options : ThemePluginOptions = { } ) {
249- const { adapter = new Vuetify0ThemeAdapter ( ) , palette = { } , themes = { } , ...options } = _options
250+ const { adapter = new Vuetify0ThemeAdapter ( ) , palette = { } , themes = { } , target , ...options } = _options
250251 const [ , provideThemeContext , themeContext ] = createTheme < Z , E > ( 'v0:theme' , { ...options , themes, palette } )
251252
252- function update ( colors : Record < string , Colors > ) {
253- adapter . update ( colors )
254- }
255-
256253 return createPlugin ( {
257254 namespace : 'v0:theme' ,
258255 provide : ( app : App ) => {
259256 provideThemeContext ( themeContext , app )
260257 } ,
261- setup : ( ) => {
258+ setup : ( app : App ) => {
262259 if ( IN_BROWSER ) {
263- const stop = watch ( themeContext . colors , update , { immediate : true , deep : true } )
264- onScopeDispose ( stop , true )
260+ const stopWatch = watch ( themeContext . colors , colors => {
261+ adapter . update ( colors )
262+ } , { immediate : true } )
263+
264+ onScopeDispose ( stopWatch , true )
265+
266+ if ( target === null ) return
267+
268+ const targetEl = target instanceof HTMLElement
269+ ? target
270+ : ( typeof target === 'string'
271+ ? document . querySelector ( target )
272+ : ( app . _container as HTMLElement | undefined ) || document . querySelector ( '#app' ) || document . body )
273+
274+ if ( ! targetEl ) return
275+
276+ let prevClass = ''
277+
278+ const stopClass = watch ( themeContext . selectedId , id => {
279+ if ( ! id ) return
280+
281+ const themeClass = `${ adapter . prefix } -theme--${ id } `
282+ if ( prevClass ) targetEl . classList . remove ( prevClass )
283+ targetEl . classList . add ( themeClass )
284+ prevClass = themeClass
285+ } , { immediate : true } )
286+
287+ onScopeDispose ( stopClass , true )
265288 } else {
266- update ( themeContext . colors . value )
289+ const head = app . _context ?. provides ?. usehead
290+ if ( head ?. push ) {
291+ const id = themeContext . selectedId . value
292+ head . push ( {
293+ htmlAttrs : { class : id ? `${ adapter . prefix } -theme--${ id } ` : '' } ,
294+ style : [ {
295+ innerHTML : adapter . generate ( themeContext . colors . value ) ,
296+ id : adapter . stylesheetId ,
297+ } ] ,
298+ } )
299+ }
267300 }
268301 } ,
269302 } )
0 commit comments