import { render } from 'solid-js/web' import { createSignal, lazy } from 'solid-js' import { setupStyleSheet } from './utils' import type { QueryClient, onlineManager as TOnlineManager, } from '@tanstack/query-core' import type { DevtoolsComponentType } from './Devtools' import type { DevtoolsButtonPosition, DevtoolsErrorType, DevtoolsPosition, QueryDevtoolsProps, Theme, } from './contexts/types' import type { Signal } from 'solid-js' /** * The options for `TanstackQueryDevtools`, which mounts the floating devtools. */ export interface TanstackQueryDevtoolsConfig extends QueryDevtoolsProps { /** * Use this to pass a nonce to the style tag that is added to the document head. This is useful if * you are using a Content Security Policy (CSP) nonce to allow inline styles. */ styleNonce?: string /** * Use this to pass a shadow DOM target to the devtools so that the styles will be applied * within the shadow DOM instead of within the head tag in the light DOM. */ shadowDOMTarget?: ShadowRoot } class TanstackQueryDevtools { #client: Signal #onlineManager: typeof TOnlineManager #queryFlavor: string #version: string #isMounted = false #styleNonce?: string #shadowDOMTarget?: ShadowRoot #buttonPosition: Signal #position: Signal #initialIsOpen: Signal #errorTypes: Signal | undefined> #hideDisabledQueries: Signal #Component: DevtoolsComponentType | undefined #theme: Signal #dispose?: () => void constructor(config: TanstackQueryDevtoolsConfig) { const { client, queryFlavor, version, onlineManager, buttonPosition, position, initialIsOpen, errorTypes, styleNonce, shadowDOMTarget, hideDisabledQueries, theme, } = config this.#client = createSignal(client) this.#queryFlavor = queryFlavor this.#version = version this.#onlineManager = onlineManager this.#styleNonce = styleNonce this.#shadowDOMTarget = shadowDOMTarget this.#buttonPosition = createSignal(buttonPosition) this.#position = createSignal(position) this.#initialIsOpen = createSignal(initialIsOpen) this.#errorTypes = createSignal(errorTypes) this.#hideDisabledQueries = createSignal(hideDisabledQueries) this.#theme = createSignal(theme) } setButtonPosition(position: DevtoolsButtonPosition) { this.#buttonPosition[1](position) } setPosition(position: DevtoolsPosition) { this.#position[1](position) } setInitialIsOpen(isOpen: boolean) { this.#initialIsOpen[1](isOpen) } setErrorTypes(errorTypes: Array) { this.#errorTypes[1](errorTypes) } setClient(client: QueryClient) { this.#client[1](client) } setTheme(theme?: Theme) { this.#theme[1](theme) } mount(el: T) { if (this.#isMounted) { throw new Error('Devtools is already mounted') } const dispose = render(() => { const [btnPosition] = this.#buttonPosition const [pos] = this.#position const [isOpen] = this.#initialIsOpen const [errors] = this.#errorTypes const [hideDisabledQueries] = this.#hideDisabledQueries const [queryClient] = this.#client const [theme] = this.#theme let Devtools: DevtoolsComponentType if (this.#Component) { Devtools = this.#Component } else { Devtools = lazy(() => import('./DevtoolsComponent')) this.#Component = Devtools } setupStyleSheet(this.#styleNonce, this.#shadowDOMTarget) return ( ) }, el) this.#isMounted = true this.#dispose = dispose } unmount() { if (!this.#isMounted) { throw new Error('Devtools is not mounted') } this.#dispose?.() this.#isMounted = false } } export { TanstackQueryDevtools }