Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,11 @@ import { defineCustomElement } from 'vue'
import css from '../.generated/css'
import Component from './DockStandalone.vue'

const forcedColorModeCss = `
:host([data-vite-devtools-color-mode='dark']) {
color-scheme: dark;
}
:host([data-vite-devtools-color-mode='light']) {
color-scheme: light;
}
`

export const DockStandalone = defineCustomElement(
Component,
{
shadowRoot: true,
styles: [css, forcedColorModeCss],
styles: [css],
},
) as VueElementConstructor<{
context: DocksContext
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ watch(
)

const groupedEntries = computed(() => {
if (isDockPopupEntryVisible())
if (isDockPopupEntryVisible('standalone'))
return context.docks.groupedEntries

return filterPopupDockEntry(context.docks.groupedEntries)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,33 +1,30 @@
import type { DocksContext } from '@vitejs/devtools-kit/client'
import { afterAll, beforeEach, describe, expect, it, vi } from 'vitest'
import { setDocksOverflowPanel, useDocksOverflowPanel } from '../floating-tooltip'
import { closeDockPopup, filterPopupDockEntry, isDockPopupEntryVisible, isDockPopupSupported, isRunningInDockPopupWindow, openDockPopup, setDockStandaloneLoaderForTest, useDockPopupWindow, useIsDockPopupOpen } from '../popup'
import { closeDockPopup, filterPopupDockEntry, isDockPopupEntryVisible, isDockPopupSupported, openDockPopup, setDockStandaloneLoaderForTest, useDockPopupWindow, useIsDockPopupOpen } from '../popup'

const {
DockStandaloneElementMock,
dockStandaloneCtorCalls,
dockElementRemoveMock,
dockElementSetAttributeMock,
} = vi.hoisted(() => {
const dockElementRemoveMock = vi.fn()
const dockElementSetAttributeMock = vi.fn()
const dockStandaloneCtorCalls: Array<{ context: DocksContext }> = []
class DockStandaloneElementMock {
context: DocksContext
remove: () => void
setAttribute: (name: string, value: string) => void
style: Record<string, string>
constructor({ context }: { context: DocksContext }) {
this.context = context
this.remove = dockElementRemoveMock
this.setAttribute = dockElementSetAttributeMock
this.style = {}
dockStandaloneCtorCalls.push({ context })
}
}
return {
DockStandaloneElementMock: DockStandaloneElementMock as unknown as new (props: { context: DocksContext }) => HTMLElement,
dockStandaloneCtorCalls,
dockElementRemoveMock,
dockElementSetAttributeMock,
}
})

Expand Down Expand Up @@ -135,7 +132,6 @@ describe('dock popup state', () => {
setDockStandaloneLoaderForTest(async () => DockStandaloneElementMock)
dockStandaloneCtorCalls.length = 0
dockElementRemoveMock.mockClear()
dockElementSetAttributeMock.mockClear()
;(globalThis as { window?: any }).window = {
innerWidth: 1200,
innerHeight: 800,
Expand All @@ -149,7 +145,7 @@ describe('dock popup state', () => {

it('returns null when the API is unavailable', async () => {
expect(isDockPopupSupported()).toBe(false)
expect(isDockPopupEntryVisible()).toBe(false)
expect(isDockPopupEntryVisible('embedded')).toBe(false)
const popup = await openDockPopup(createMockContext())
expect(popup).toBeNull()
expect(useIsDockPopupOpen().value).toBe(false)
Expand All @@ -160,21 +156,15 @@ describe('dock popup state', () => {
const requestWindow = vi.fn().mockResolvedValue(popup)
;(window as Window & { documentPictureInPicture?: unknown }).documentPictureInPicture = { requestWindow }

expect(isDockPopupEntryVisible()).toBe(true)
expect(isDockPopupEntryVisible('embedded')).toBe(true)
await openDockPopup(createMockContext())
expect(isDockPopupEntryVisible()).toBe(false)
expect(isDockPopupEntryVisible('embedded')).toBe(false)
})

it('hides popup entry when running inside popup window', () => {
;(window as Window & { documentPictureInPicture?: unknown }).documentPictureInPicture = { requestWindow: vi.fn() }
;(window as Window & { document?: unknown }).document = {
documentElement: {
hasAttribute: vi.fn((name: string) => name === 'data-vite-devtools-popup-window'),
},
} as any

expect(isRunningInDockPopupWindow()).toBe(true)
expect(isDockPopupEntryVisible()).toBe(false)
expect(isDockPopupEntryVisible('standalone')).toBe(false)
})

it('filters popup entry from grouped entries', () => {
Expand Down Expand Up @@ -220,7 +210,6 @@ describe('dock popup state', () => {
expect(appRoot).toBeTruthy()
expect(appRoot.id).toBe('vite-devtools-popup-root')
expect(appRoot.appended).toHaveLength(1)
expect(dockElementSetAttributeMock).toHaveBeenCalledWith('data-vite-devtools-color-mode', 'light')
})

it('hides dock overflow panel when opening popup', async () => {
Expand Down
4 changes: 2 additions & 2 deletions packages/core/src/client/webcomponents/state/context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ export async function createDocksContext(

// If the action is in a popup, delegate to the main frame
if (entry.type === 'action') {
const delegated = await triggerMainFrameDockAction(entry.id)
const delegated = await triggerMainFrameDockAction(clientType, entry.id)
if (delegated != null)
return false
}
Expand Down Expand Up @@ -135,7 +135,7 @@ export async function createDocksContext(
clientType,
})

registerMainFrameDockActionHandler(async (id) => {
registerMainFrameDockActionHandler(clientType, async (id) => {
const entry = dockEntries.value.find(e => e.id === id)
if (!entry || entry.type !== 'action')
return false
Expand Down
20 changes: 6 additions & 14 deletions packages/core/src/client/webcomponents/state/popup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ const PANEL_MAX_SIZE = 100
const POPUP_MIN_WIDTH = 320
const POPUP_MIN_HEIGHT = 240
const POPUP_DOCK_ID = '~popup'
const POPUP_WINDOW_ATTRIBUTE = 'data-vite-devtools-popup-window'
const MAIN_FRAME_ACTION_HANDLER_KEY = '__VITE_DEVTOOLS_TRIGGER_DOCK_ACTION__'

const popupWindow = shallowRef<Window | null>(null)
Expand Down Expand Up @@ -81,9 +80,7 @@ function resolveColorMode(): ColorMode {
}

function applyPopupColorMode(popup: Window, mode: ColorMode) {
popup.document.documentElement?.setAttribute('data-vite-devtools-color-mode', mode)
popup.document.documentElement?.style.setProperty('color-scheme', mode)
popupDockElement?.setAttribute('data-vite-devtools-color-mode', mode)
}

function setupPopupColorModeSync(popup: Window): () => void {
Expand Down Expand Up @@ -177,7 +174,6 @@ async function mountStandaloneApp(context: DocksContext, popup: Window) {
].join('\n')

popup.document.title = 'Vite DevTools'
popup.document.documentElement?.setAttribute(POPUP_WINDOW_ATTRIBUTE, '')
popup.document.head?.appendChild(baseStyle)
popup.document.body.textContent = ''

Expand All @@ -194,30 +190,26 @@ export function isDockPopupSupported(): boolean {
return !!getDocumentPictureInPicture()?.requestWindow
}

export function isRunningInDockPopupWindow(): boolean {
if (typeof window === 'undefined')
return false
return !!window.document?.documentElement?.hasAttribute?.(POPUP_WINDOW_ATTRIBUTE)
}

export function registerMainFrameDockActionHandler(
clientType: 'embedded' | 'standalone',
handler: MainFrameDockActionHandler,
) {
if (typeof window === 'undefined') {
return
}
if (isRunningInDockPopupWindow()) {
if (clientType === 'standalone') {
return
}
;(window as Window & { [MAIN_FRAME_ACTION_HANDLER_KEY]?: MainFrameDockActionHandler })[MAIN_FRAME_ACTION_HANDLER_KEY] = handler
}

export async function triggerMainFrameDockAction(
clientType: 'embedded' | 'standalone',
entryId: string,
): Promise<boolean | undefined> {
if (typeof window === 'undefined')
return undefined
if (!isRunningInDockPopupWindow())
if (clientType !== 'standalone')
return undefined

try {
Expand All @@ -234,8 +226,8 @@ export async function triggerMainFrameDockAction(
}
}

export function isDockPopupEntryVisible(): boolean {
return isDockPopupSupported() && !isPopupOpen.value && !isRunningInDockPopupWindow()
export function isDockPopupEntryVisible(clientType: 'embedded' | 'standalone'): boolean {
return isDockPopupSupported() && !isPopupOpen.value && clientType !== 'standalone'
}

export function filterPopupDockEntry(
Expand Down
Loading