@tanstack/devtools
Advanced tools
| // src/constants.ts | ||
| var PLUGIN_CONTAINER_ID = "plugin-container"; | ||
| var PLUGIN_TITLE_CONTAINER_ID = "plugin-title-container"; | ||
| export { PLUGIN_CONTAINER_ID, PLUGIN_TITLE_CONTAINER_ID }; |
| import { initialState } from './BNGI36V3.js'; | ||
| import { createComponent, delegateEvents } from 'solid-js/web'; | ||
| import { createContext, createEffect, createSignal, onCleanup, createMemo, useContext } from 'solid-js'; | ||
| import { createStore } from 'solid-js/store'; | ||
| // src/utils/storage.ts | ||
| var getStorageItem = (key) => localStorage.getItem(key); | ||
| var setStorageItem = (key, value) => { | ||
| try { | ||
| localStorage.setItem(key, value); | ||
| } catch (_e) { | ||
| return; | ||
| } | ||
| }; | ||
| var TANSTACK_DEVTOOLS = "tanstack_devtools"; | ||
| var TANSTACK_DEVTOOLS_STATE = "tanstack_devtools_state"; | ||
| var TANSTACK_DEVTOOLS_SETTINGS = "tanstack_devtools_settings"; | ||
| // src/utils/constants.ts | ||
| var MAX_ACTIVE_PLUGINS = 3; | ||
| // src/utils/get-default-active-plugins.ts | ||
| function getDefaultActivePlugins(plugins) { | ||
| if (plugins.length === 0) { | ||
| return []; | ||
| } | ||
| if (plugins.length === 1) { | ||
| return [plugins[0].id]; | ||
| } | ||
| return plugins.filter((plugin) => plugin.defaultOpen === true).slice(0, MAX_ACTIVE_PLUGINS).map((plugin) => plugin.id); | ||
| } | ||
| // src/utils/sanitize.ts | ||
| var tryParseJson = (json) => { | ||
| if (!json) return void 0; | ||
| try { | ||
| return JSON.parse(json); | ||
| } catch (_e) { | ||
| return void 0; | ||
| } | ||
| }; | ||
| var uppercaseFirstLetter = (value) => value.charAt(0).toUpperCase() + value.slice(1); | ||
| var getAllPermutations = (arr) => { | ||
| const res = []; | ||
| function permutate(arr2, start) { | ||
| if (start === arr2.length - 1) { | ||
| res.push([...arr2]); | ||
| return; | ||
| } | ||
| for (let i = start; i < arr2.length; i++) { | ||
| [arr2[start], arr2[i]] = [arr2[i], arr2[start]]; | ||
| permutate(arr2, start + 1); | ||
| [arr2[start], arr2[i]] = [arr2[i], arr2[start]]; | ||
| } | ||
| } | ||
| permutate(arr, 0); | ||
| return res; | ||
| }; | ||
| // src/context/devtools-context.tsx | ||
| var DevtoolsContext = createContext(); | ||
| var getSettings = () => { | ||
| const settingsString = getStorageItem(TANSTACK_DEVTOOLS_SETTINGS); | ||
| const settings = tryParseJson(settingsString); | ||
| return { | ||
| ...settings | ||
| }; | ||
| }; | ||
| var generatePluginId = (plugin, index) => { | ||
| if (plugin.id) { | ||
| return plugin.id; | ||
| } | ||
| if (typeof plugin.name === "string") { | ||
| return `${plugin.name.toLowerCase().replace(" ", "-")}-${index}`; | ||
| } | ||
| return index.toString(); | ||
| }; | ||
| function getStateFromLocalStorage(plugins) { | ||
| const existingStateString = getStorageItem(TANSTACK_DEVTOOLS_STATE); | ||
| const existingState = tryParseJson(existingStateString); | ||
| const pluginIds = plugins?.map((plugin, i) => generatePluginId(plugin, i)) || []; | ||
| if (existingState?.activePlugins) { | ||
| const originalLength = existingState.activePlugins.length; | ||
| existingState.activePlugins = existingState.activePlugins.filter((id) => pluginIds.includes(id)); | ||
| if (existingState.activePlugins.length !== originalLength) { | ||
| setStorageItem(TANSTACK_DEVTOOLS_STATE, JSON.stringify(existingState)); | ||
| } | ||
| } | ||
| return existingState; | ||
| } | ||
| var getExistingStateFromStorage = (config, plugins) => { | ||
| const existingState = getStateFromLocalStorage(plugins); | ||
| const settings = getSettings(); | ||
| const pluginsWithIds = plugins?.map((plugin, i) => { | ||
| const id = generatePluginId(plugin, i); | ||
| return { | ||
| ...plugin, | ||
| id | ||
| }; | ||
| }) || []; | ||
| let activePlugins = existingState?.activePlugins || []; | ||
| const shouldFillWithDefaultOpenPlugins = activePlugins.length === 0 && pluginsWithIds.length > 0; | ||
| if (shouldFillWithDefaultOpenPlugins) { | ||
| activePlugins = getDefaultActivePlugins(pluginsWithIds); | ||
| } | ||
| const state = { | ||
| ...initialState, | ||
| plugins: pluginsWithIds, | ||
| state: { | ||
| ...initialState.state, | ||
| ...existingState, | ||
| activePlugins | ||
| }, | ||
| settings: { | ||
| ...initialState.settings, | ||
| ...config, | ||
| ...settings | ||
| } | ||
| }; | ||
| return state; | ||
| }; | ||
| var DevtoolsProvider = (props) => { | ||
| const [store, setStore] = createStore(getExistingStateFromStorage(props.config, props.plugins)); | ||
| const updatePlugins = (newPlugins) => { | ||
| const pluginsWithIds = newPlugins.map((plugin, i) => { | ||
| const id = generatePluginId(plugin, i); | ||
| return { | ||
| ...plugin, | ||
| id | ||
| }; | ||
| }); | ||
| setStore("plugins", pluginsWithIds); | ||
| }; | ||
| createEffect(() => { | ||
| if (props.onSetPlugins) { | ||
| props.onSetPlugins(updatePlugins); | ||
| } | ||
| }); | ||
| const value = { | ||
| store, | ||
| setStore: (updater) => { | ||
| const newState = updater(store); | ||
| const { | ||
| settings, | ||
| state: internalState | ||
| } = newState; | ||
| setStorageItem(TANSTACK_DEVTOOLS_SETTINGS, JSON.stringify(settings)); | ||
| setStorageItem(TANSTACK_DEVTOOLS_STATE, JSON.stringify(internalState)); | ||
| setStore((prev) => ({ | ||
| ...prev, | ||
| ...newState | ||
| })); | ||
| } | ||
| }; | ||
| return createComponent(DevtoolsContext.Provider, { | ||
| value, | ||
| get children() { | ||
| return props.children; | ||
| } | ||
| }); | ||
| }; | ||
| var PiPContext = createContext(void 0); | ||
| var PiPProvider = (props) => { | ||
| const [pipWindow, setPipWindow] = createSignal(null); | ||
| const closePipWindow = () => { | ||
| const w = pipWindow(); | ||
| if (w != null) { | ||
| w.close(); | ||
| setPipWindow(null); | ||
| } | ||
| }; | ||
| const requestPipWindow = (settings) => { | ||
| if (pipWindow() != null) { | ||
| return; | ||
| } | ||
| const pip = window.open("", "TSDT-Devtools-Panel", `${settings},popup`); | ||
| if (!pip) { | ||
| throw new Error("Failed to open popup. Please allow popups for this site to view the devtools in picture-in-picture mode."); | ||
| } | ||
| if (import.meta.hot && typeof import.meta.hot.on === "function") { | ||
| import.meta.hot.on("vite:beforeUpdate", () => { | ||
| localStorage.setItem("pip_open", "false"); | ||
| closePipWindow(); | ||
| }); | ||
| } | ||
| window.addEventListener("beforeunload", () => { | ||
| localStorage.setItem("pip_open", "false"); | ||
| closePipWindow(); | ||
| }); | ||
| pip.document.head.innerHTML = ""; | ||
| pip.document.body.innerHTML = ""; | ||
| pip.document.title = "TanStack Devtools"; | ||
| pip.document.body.style.margin = "0"; | ||
| pip.addEventListener("pagehide", () => { | ||
| localStorage.setItem("pip_open", "false"); | ||
| closePipWindow(); | ||
| }); | ||
| [...document.styleSheets].forEach((styleSheet) => { | ||
| try { | ||
| const cssRules = [...styleSheet.cssRules].map((rule) => rule.cssText).join(""); | ||
| const style = document.createElement("style"); | ||
| const style_node = styleSheet.ownerNode; | ||
| let style_id = ""; | ||
| if (style_node && "id" in style_node) { | ||
| style_id = style_node.id; | ||
| } | ||
| if (style_id) { | ||
| style.setAttribute("id", style_id); | ||
| } | ||
| style.textContent = cssRules; | ||
| pip.document.head.appendChild(style); | ||
| } catch (e) { | ||
| const link = document.createElement("link"); | ||
| if (styleSheet.href == null) { | ||
| return; | ||
| } | ||
| link.rel = "stylesheet"; | ||
| link.type = styleSheet.type; | ||
| link.media = styleSheet.media.toString(); | ||
| link.href = styleSheet.href; | ||
| pip.document.head.appendChild(link); | ||
| } | ||
| }); | ||
| delegateEvents(["focusin", "focusout", "pointermove", "keydown", "pointerdown", "pointerup", "click", "mousedown", "input"], pip.document); | ||
| setPipWindow(pip); | ||
| }; | ||
| createEffect(() => { | ||
| const gooberStyles = document.querySelector("#_goober"); | ||
| const w = pipWindow(); | ||
| if (gooberStyles && w) { | ||
| const observer = new MutationObserver(() => { | ||
| const pip_style = w.document.querySelector("#_goober"); | ||
| if (pip_style) { | ||
| pip_style.textContent = gooberStyles.textContent; | ||
| } | ||
| }); | ||
| observer.observe(gooberStyles, { | ||
| childList: true, | ||
| // observe direct children | ||
| subtree: true, | ||
| // and lower descendants too | ||
| characterDataOldValue: true | ||
| // pass old data to callback | ||
| }); | ||
| onCleanup(() => { | ||
| observer.disconnect(); | ||
| }); | ||
| } | ||
| }); | ||
| const value = createMemo(() => ({ | ||
| pipWindow: pipWindow(), | ||
| requestPipWindow, | ||
| closePipWindow, | ||
| disabled: props.disabled ?? false | ||
| })); | ||
| return createComponent(PiPContext.Provider, { | ||
| value, | ||
| get children() { | ||
| return props.children; | ||
| } | ||
| }); | ||
| }; | ||
| var usePiPWindow = () => { | ||
| const context = createMemo(() => { | ||
| const ctx = useContext(PiPContext); | ||
| if (!ctx) { | ||
| throw new Error("usePiPWindow must be used within a PiPProvider"); | ||
| } | ||
| return ctx(); | ||
| }); | ||
| return context; | ||
| }; | ||
| export { DevtoolsContext, DevtoolsProvider, MAX_ACTIVE_PLUGINS, PiPProvider, TANSTACK_DEVTOOLS, getAllPermutations, uppercaseFirstLetter, usePiPWindow }; |
| // src/context/devtools-store.ts | ||
| var keyboardModifiers = [ | ||
| "Alt", | ||
| "Control", | ||
| "Meta", | ||
| "Shift", | ||
| "CtrlOrMeta" | ||
| ]; | ||
| var initialState = { | ||
| settings: { | ||
| defaultOpen: false, | ||
| hideUntilHover: false, | ||
| position: "bottom-right", | ||
| panelLocation: "bottom", | ||
| openHotkey: ["Control", "~"], | ||
| inspectHotkey: ["Shift", "Alt", "CtrlOrMeta"], | ||
| requireUrlFlag: false, | ||
| urlFlag: "tanstack-devtools", | ||
| theme: typeof window !== "undefined" && typeof window.matchMedia !== "undefined" && window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light", | ||
| triggerHidden: false, | ||
| customTrigger: void 0 | ||
| }, | ||
| state: { | ||
| activeTab: "plugins", | ||
| height: 400, | ||
| activePlugins: [], | ||
| persistOpen: false | ||
| } | ||
| }; | ||
| export { initialState, keyboardModifiers }; |
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
| import { DevtoolsProvider, PiPProvider } from '../chunk/AP5L3KAF.js'; | ||
| import '../chunk/BNGI36V3.js'; | ||
| import { render, createComponent, Portal } from 'solid-js/web'; | ||
| import { lazy } from 'solid-js'; | ||
| import { ClientEventBus } from '@tanstack/devtools-event-bus/client'; | ||
| function mountDevtools(options) { | ||
| const { | ||
| el, | ||
| plugins, | ||
| config, | ||
| eventBusConfig, | ||
| onSetPlugins | ||
| } = options; | ||
| const eventBus = new ClientEventBus(eventBusConfig); | ||
| eventBus.start(); | ||
| const Devtools = lazy(() => import('../devtools/NTZWLI2C.js')); | ||
| const dispose = render(() => createComponent(DevtoolsProvider, { | ||
| plugins, | ||
| config, | ||
| onSetPlugins, | ||
| get children() { | ||
| return createComponent(PiPProvider, { | ||
| get children() { | ||
| return createComponent(Portal, { | ||
| mount: el, | ||
| get children() { | ||
| return createComponent(Devtools, {}); | ||
| } | ||
| }); | ||
| } | ||
| }); | ||
| } | ||
| }), el); | ||
| return { | ||
| dispose, | ||
| eventBus | ||
| }; | ||
| } | ||
| export { mountDevtools }; |
| import { DevtoolsProvider, PiPProvider } from '../chunk/AP5L3KAF.js'; | ||
| import '../chunk/BNGI36V3.js'; | ||
| import { render, createComponent, Portal } from 'solid-js/web'; | ||
| import { lazy } from 'solid-js'; | ||
| import { ClientEventBus } from '@tanstack/devtools-event-bus/client'; | ||
| function mountDevtools(options) { | ||
| const { | ||
| el, | ||
| plugins, | ||
| config, | ||
| eventBusConfig, | ||
| onSetPlugins | ||
| } = options; | ||
| const eventBus = new ClientEventBus(eventBusConfig); | ||
| eventBus.start(); | ||
| const Devtools = lazy(() => import('../devtools/AHAZGWBE.js')); | ||
| const dispose = render(() => createComponent(DevtoolsProvider, { | ||
| plugins, | ||
| config, | ||
| onSetPlugins, | ||
| get children() { | ||
| return createComponent(PiPProvider, { | ||
| get children() { | ||
| return createComponent(Portal, { | ||
| mount: el, | ||
| get children() { | ||
| return createComponent(Devtools, {}); | ||
| } | ||
| }); | ||
| } | ||
| }); | ||
| } | ||
| }), el); | ||
| return { | ||
| dispose, | ||
| eventBus | ||
| }; | ||
| } | ||
| export { mountDevtools }; |
+126
| import { initialState } from './context/devtools-store' | ||
| import type { | ||
| TanStackDevtoolsConfig, | ||
| TanStackDevtoolsPlugin, | ||
| } from './context/devtools-context' | ||
| import type { ClientEventBusConfig } from '@tanstack/devtools-event-bus/client' | ||
| export interface TanStackDevtoolsInit { | ||
| /** | ||
| * Configuration for the devtools shell. These configuration options are used to set the | ||
| * initial state of the devtools when it is started for the first time. Afterwards, | ||
| * the settings are persisted in local storage and changed through the settings panel. | ||
| */ | ||
| config?: Partial<TanStackDevtoolsConfig> | ||
| /** | ||
| * Array of plugins to be used in the devtools. | ||
| * Each plugin has a `render` function that gives you the dom node to mount into | ||
| * | ||
| * Example: | ||
| * ```ts | ||
| * const devtools = new TanStackDevtoolsCore({ | ||
| * plugins: [ | ||
| * { | ||
| * id: "your-plugin-id", | ||
| * name: "Your Plugin", | ||
| * render: (el) => { | ||
| * // Your render logic here | ||
| * }, | ||
| * }, | ||
| * ], | ||
| * }) | ||
| * ``` | ||
| */ | ||
| plugins?: Array<TanStackDevtoolsPlugin> | ||
| eventBusConfig?: ClientEventBusConfig | ||
| } | ||
| export class TanStackDevtoolsCore { | ||
| #config: TanStackDevtoolsConfig = { | ||
| ...initialState.settings, | ||
| } | ||
| #plugins: Array<TanStackDevtoolsPlugin> = [] | ||
| #isMounted = false | ||
| #isMounting = false | ||
| #abortMount = false | ||
| #dispose?: () => void | ||
| #eventBus?: { stop: () => void } | ||
| #eventBusConfig: ClientEventBusConfig | undefined | ||
| #setPlugins?: (plugins: Array<TanStackDevtoolsPlugin>) => void | ||
| constructor(init: TanStackDevtoolsInit) { | ||
| this.#plugins = init.plugins || [] | ||
| this.#eventBusConfig = init.eventBusConfig | ||
| this.#config = { | ||
| ...this.#config, | ||
| ...init.config, | ||
| } | ||
| } | ||
| mount<T extends HTMLElement>(el: T) { | ||
| if (typeof document === 'undefined') return | ||
| if (this.#isMounted || this.#isMounting) { | ||
| throw new Error('Devtools is already mounted') | ||
| } | ||
| this.#isMounting = true | ||
| this.#abortMount = false | ||
| import('./mount-impl') | ||
| .then(({ mountDevtools }) => { | ||
| if (this.#abortMount) { | ||
| this.#isMounting = false | ||
| return | ||
| } | ||
| const result = mountDevtools({ | ||
| el, | ||
| plugins: this.#plugins, | ||
| config: this.#config, | ||
| eventBusConfig: this.#eventBusConfig, | ||
| onSetPlugins: (setPlugins) => { | ||
| this.#setPlugins = setPlugins | ||
| }, | ||
| }) | ||
| this.#dispose = result.dispose | ||
| this.#eventBus = result.eventBus | ||
| this.#isMounted = true | ||
| this.#isMounting = false | ||
| }) | ||
| .catch((err) => { | ||
| this.#isMounting = false | ||
| console.error('[TanStack Devtools] Failed to load:', err) | ||
| }) | ||
| } | ||
| unmount() { | ||
| if (!this.#isMounted && !this.#isMounting) { | ||
| throw new Error('Devtools is not mounted') | ||
| } | ||
| if (this.#isMounting) { | ||
| this.#abortMount = true | ||
| this.#isMounting = false | ||
| return | ||
| } | ||
| this.#eventBus?.stop() | ||
| this.#dispose?.() | ||
| this.#isMounted = false | ||
| } | ||
| setConfig(config: Partial<TanStackDevtoolsInit>) { | ||
| this.#config = { | ||
| ...this.#config, | ||
| ...config, | ||
| } | ||
| if (config.plugins) { | ||
| this.#plugins = config.plugins | ||
| // Update the reactive store if mounted | ||
| if (this.#isMounted && this.#setPlugins) { | ||
| this.#setPlugins(config.plugins) | ||
| } | ||
| } | ||
| } | ||
| } | ||
| export type { ClientEventBusConfig } |
| import { lazy } from 'solid-js' | ||
| import { Portal, render } from 'solid-js/web' | ||
| import { ClientEventBus } from '@tanstack/devtools-event-bus/client' | ||
| import { DevtoolsProvider } from './context/devtools-context' | ||
| import { PiPProvider } from './context/pip-context' | ||
| import type { | ||
| TanStackDevtoolsConfig, | ||
| TanStackDevtoolsPlugin, | ||
| } from './context/devtools-context' | ||
| import type { ClientEventBusConfig } from '@tanstack/devtools-event-bus/client' | ||
| interface MountOptions { | ||
| el: HTMLElement | ||
| plugins: Array<TanStackDevtoolsPlugin> | ||
| config: TanStackDevtoolsConfig | ||
| eventBusConfig?: ClientEventBusConfig | ||
| onSetPlugins: ( | ||
| setPlugins: (plugins: Array<TanStackDevtoolsPlugin>) => void, | ||
| ) => void | ||
| } | ||
| interface MountResult { | ||
| dispose: () => void | ||
| eventBus: { stop: () => void } | ||
| } | ||
| export function mountDevtools(options: MountOptions): MountResult { | ||
| const { el, plugins, config, eventBusConfig, onSetPlugins } = options | ||
| const eventBus = new ClientEventBus(eventBusConfig) | ||
| eventBus.start() | ||
| const Devtools = lazy(() => import('./devtools')) | ||
| const dispose = render( | ||
| () => ( | ||
| <DevtoolsProvider | ||
| plugins={plugins} | ||
| config={config} | ||
| onSetPlugins={onSetPlugins} | ||
| > | ||
| <PiPProvider> | ||
| <Portal mount={el}> | ||
| <Devtools /> | ||
| </Portal> | ||
| </PiPProvider> | ||
| </DevtoolsProvider> | ||
| ), | ||
| el, | ||
| ) | ||
| return { dispose, eventBus } | ||
| } |
+34
-38
@@ -1,7 +0,5 @@ | ||
| import { initialState, DevtoolsProvider, PiPProvider } from './chunk/ULTYUGME.js'; | ||
| export { PLUGIN_CONTAINER_ID, PLUGIN_TITLE_CONTAINER_ID } from './chunk/ULTYUGME.js'; | ||
| import { render, createComponent, Portal } from 'solid-js/web'; | ||
| import { lazy } from 'solid-js'; | ||
| import { ClientEventBus } from '@tanstack/devtools-event-bus/client'; | ||
| export { PLUGIN_CONTAINER_ID, PLUGIN_TITLE_CONTAINER_ID } from './chunk/A767CXXU.js'; | ||
| import { initialState } from './chunk/BNGI36V3.js'; | ||
| // src/core.ts | ||
| var TanStackDevtoolsCore = class { | ||
@@ -13,4 +11,5 @@ #config = { | ||
| #isMounted = false; | ||
| #isMounting = false; | ||
| #abortMount = false; | ||
| #dispose; | ||
| #Component; | ||
| #eventBus; | ||
@@ -28,43 +27,40 @@ #eventBusConfig; | ||
| mount(el) { | ||
| if (this.#isMounted) { | ||
| if (typeof document === "undefined") return; | ||
| if (this.#isMounted || this.#isMounting) { | ||
| throw new Error("Devtools is already mounted"); | ||
| } | ||
| const mountTo = el; | ||
| const dispose = render(() => { | ||
| const _self$ = this; | ||
| this.#Component = lazy(() => import('./devtools/LF5QLUHI.js')); | ||
| const Devtools = this.#Component; | ||
| this.#eventBus = new ClientEventBus(this.#eventBusConfig); | ||
| this.#eventBus.start(); | ||
| return createComponent(DevtoolsProvider, { | ||
| get plugins() { | ||
| return _self$.#plugins; | ||
| }, | ||
| get config() { | ||
| return _self$.#config; | ||
| }, | ||
| this.#isMounting = true; | ||
| this.#abortMount = false; | ||
| import('./mount-impl/E4RX7DUJ.js').then(({ mountDevtools }) => { | ||
| if (this.#abortMount) { | ||
| this.#isMounting = false; | ||
| return; | ||
| } | ||
| const result = mountDevtools({ | ||
| el, | ||
| plugins: this.#plugins, | ||
| config: this.#config, | ||
| eventBusConfig: this.#eventBusConfig, | ||
| onSetPlugins: (setPlugins) => { | ||
| _self$.#setPlugins = setPlugins; | ||
| }, | ||
| get children() { | ||
| return createComponent(PiPProvider, { | ||
| get children() { | ||
| return createComponent(Portal, { | ||
| mount: mountTo, | ||
| get children() { | ||
| return createComponent(Devtools, {}); | ||
| } | ||
| }); | ||
| } | ||
| }); | ||
| this.#setPlugins = setPlugins; | ||
| } | ||
| }); | ||
| }, mountTo); | ||
| this.#isMounted = true; | ||
| this.#dispose = dispose; | ||
| this.#dispose = result.dispose; | ||
| this.#eventBus = result.eventBus; | ||
| this.#isMounted = true; | ||
| this.#isMounting = false; | ||
| }).catch((err) => { | ||
| this.#isMounting = false; | ||
| console.error("[TanStack Devtools] Failed to load:", err); | ||
| }); | ||
| } | ||
| unmount() { | ||
| if (!this.#isMounted) { | ||
| if (!this.#isMounted && !this.#isMounting) { | ||
| throw new Error("Devtools is not mounted"); | ||
| } | ||
| if (this.#isMounting) { | ||
| this.#abortMount = true; | ||
| this.#isMounting = false; | ||
| return; | ||
| } | ||
| this.#eventBus?.stop(); | ||
@@ -71,0 +67,0 @@ this.#dispose?.(); |
+1
-1
@@ -0,4 +1,4 @@ | ||
| import * as solid_js from 'solid-js'; | ||
| import { ClientEventBusConfig } from '@tanstack/devtools-event-bus/client'; | ||
| export { ClientEventBusConfig } from '@tanstack/devtools-event-bus/client'; | ||
| import * as solid_js from 'solid-js'; | ||
@@ -5,0 +5,0 @@ declare const PLUGIN_CONTAINER_ID = "plugin-container"; |
+33
-38
@@ -1,7 +0,5 @@ | ||
| import { initialState, DevtoolsProvider, PiPProvider } from './chunk/ULTYUGME.js'; | ||
| export { PLUGIN_CONTAINER_ID, PLUGIN_TITLE_CONTAINER_ID } from './chunk/ULTYUGME.js'; | ||
| import { render, createComponent, Portal } from 'solid-js/web'; | ||
| import { lazy } from 'solid-js'; | ||
| import { ClientEventBus } from '@tanstack/devtools-event-bus/client'; | ||
| export { PLUGIN_CONTAINER_ID, PLUGIN_TITLE_CONTAINER_ID } from './chunk/A767CXXU.js'; | ||
| import { initialState } from './chunk/BNGI36V3.js'; | ||
| // src/core.ts | ||
| var TanStackDevtoolsCore = class { | ||
@@ -13,4 +11,5 @@ #config = { | ||
| #isMounted = false; | ||
| #isMounting = false; | ||
| #abortMount = false; | ||
| #dispose; | ||
| #Component; | ||
| #eventBus; | ||
@@ -28,43 +27,39 @@ #eventBusConfig; | ||
| mount(el) { | ||
| if (this.#isMounted) { | ||
| if (typeof document === "undefined") return; | ||
| if (this.#isMounted || this.#isMounting) { | ||
| throw new Error("Devtools is already mounted"); | ||
| } | ||
| const mountTo = el; | ||
| const dispose = render(() => { | ||
| const _self$ = this; | ||
| this.#Component = lazy(() => import('./devtools/LF5QLUHI.js')); | ||
| const Devtools = this.#Component; | ||
| this.#eventBus = new ClientEventBus(this.#eventBusConfig); | ||
| this.#eventBus.start(); | ||
| return createComponent(DevtoolsProvider, { | ||
| get plugins() { | ||
| return _self$.#plugins; | ||
| }, | ||
| get config() { | ||
| return _self$.#config; | ||
| }, | ||
| this.#isMounting = true; | ||
| this.#abortMount = false; | ||
| import('./mount-impl/E4RX7DUJ.js').then(({ mountDevtools }) => { | ||
| if (this.#abortMount) { | ||
| this.#isMounting = false; | ||
| return; | ||
| } | ||
| const result = mountDevtools({ | ||
| el, | ||
| plugins: this.#plugins, | ||
| config: this.#config, | ||
| eventBusConfig: this.#eventBusConfig, | ||
| onSetPlugins: (setPlugins) => { | ||
| _self$.#setPlugins = setPlugins; | ||
| }, | ||
| get children() { | ||
| return createComponent(PiPProvider, { | ||
| get children() { | ||
| return createComponent(Portal, { | ||
| mount: mountTo, | ||
| get children() { | ||
| return createComponent(Devtools, {}); | ||
| } | ||
| }); | ||
| } | ||
| }); | ||
| this.#setPlugins = setPlugins; | ||
| } | ||
| }); | ||
| }, mountTo); | ||
| this.#isMounted = true; | ||
| this.#dispose = dispose; | ||
| this.#dispose = result.dispose; | ||
| this.#eventBus = result.eventBus; | ||
| this.#isMounted = true; | ||
| this.#isMounting = false; | ||
| }).catch((err) => { | ||
| this.#isMounting = false; | ||
| }); | ||
| } | ||
| unmount() { | ||
| if (!this.#isMounted) { | ||
| if (!this.#isMounted && !this.#isMounting) { | ||
| throw new Error("Devtools is not mounted"); | ||
| } | ||
| if (this.#isMounting) { | ||
| this.#abortMount = true; | ||
| this.#isMounting = false; | ||
| return; | ||
| } | ||
| this.#eventBus?.stop(); | ||
@@ -71,0 +66,0 @@ this.#dispose?.(); |
+38
-8
@@ -1,7 +0,5 @@ | ||
| import { initialState } from './chunk/ULTYUGME.js'; | ||
| export { PLUGIN_CONTAINER_ID, PLUGIN_TITLE_CONTAINER_ID } from './chunk/ULTYUGME.js'; | ||
| import 'solid-js/web'; | ||
| import 'solid-js'; | ||
| import '@tanstack/devtools-event-bus/client'; | ||
| export { PLUGIN_CONTAINER_ID, PLUGIN_TITLE_CONTAINER_ID } from './chunk/A767CXXU.js'; | ||
| import { initialState } from './chunk/BNGI36V3.js'; | ||
| // src/core.ts | ||
| var TanStackDevtoolsCore = class { | ||
@@ -13,4 +11,5 @@ #config = { | ||
| #isMounted = false; | ||
| #isMounting = false; | ||
| #abortMount = false; | ||
| #dispose; | ||
| #Component; | ||
| #eventBus; | ||
@@ -28,8 +27,39 @@ #eventBusConfig; | ||
| mount(el) { | ||
| return; | ||
| if (typeof document === "undefined") return; | ||
| if (this.#isMounted || this.#isMounting) { | ||
| throw new Error("Devtools is already mounted"); | ||
| } | ||
| this.#isMounting = true; | ||
| this.#abortMount = false; | ||
| import('./mount-impl/22DJOLY6.js').then(({ mountDevtools }) => { | ||
| if (this.#abortMount) { | ||
| this.#isMounting = false; | ||
| return; | ||
| } | ||
| const result = mountDevtools({ | ||
| el, | ||
| plugins: this.#plugins, | ||
| config: this.#config, | ||
| eventBusConfig: this.#eventBusConfig, | ||
| onSetPlugins: (setPlugins) => { | ||
| this.#setPlugins = setPlugins; | ||
| } | ||
| }); | ||
| this.#dispose = result.dispose; | ||
| this.#eventBus = result.eventBus; | ||
| this.#isMounted = true; | ||
| this.#isMounting = false; | ||
| }).catch((err) => { | ||
| this.#isMounting = false; | ||
| }); | ||
| } | ||
| unmount() { | ||
| if (!this.#isMounted) { | ||
| if (!this.#isMounted && !this.#isMounting) { | ||
| throw new Error("Devtools is not mounted"); | ||
| } | ||
| if (this.#isMounting) { | ||
| this.#abortMount = true; | ||
| this.#isMounting = false; | ||
| return; | ||
| } | ||
| this.#eventBus?.stop(); | ||
@@ -36,0 +66,0 @@ this.#dispose?.(); |
+1
-1
| { | ||
| "name": "@tanstack/devtools", | ||
| "version": "0.10.10", | ||
| "version": "0.10.11", | ||
| "description": "TanStack Devtools is a set of tools for building advanced devtools for your application.", | ||
@@ -5,0 +5,0 @@ "author": "Tanner Linsley", |
| import { createComponent, delegateEvents } from 'solid-js/web'; | ||
| import { createContext, createSignal, createEffect, onCleanup, createMemo, useContext } from 'solid-js'; | ||
| import { createStore } from 'solid-js/store'; | ||
| // src/constants.ts | ||
| var PLUGIN_CONTAINER_ID = "plugin-container"; | ||
| var PLUGIN_TITLE_CONTAINER_ID = "plugin-title-container"; | ||
| // src/utils/storage.ts | ||
| var getStorageItem = (key) => localStorage.getItem(key); | ||
| var setStorageItem = (key, value) => { | ||
| try { | ||
| localStorage.setItem(key, value); | ||
| } catch (_e) { | ||
| return; | ||
| } | ||
| }; | ||
| var TANSTACK_DEVTOOLS = "tanstack_devtools"; | ||
| var TANSTACK_DEVTOOLS_STATE = "tanstack_devtools_state"; | ||
| var TANSTACK_DEVTOOLS_SETTINGS = "tanstack_devtools_settings"; | ||
| var PiPContext = createContext(void 0); | ||
| var PiPProvider = (props) => { | ||
| const [pipWindow, setPipWindow] = createSignal(null); | ||
| const closePipWindow = () => { | ||
| const w = pipWindow(); | ||
| if (w != null) { | ||
| w.close(); | ||
| setPipWindow(null); | ||
| } | ||
| }; | ||
| const requestPipWindow = (settings) => { | ||
| if (pipWindow() != null) { | ||
| return; | ||
| } | ||
| const pip = window.open("", "TSDT-Devtools-Panel", `${settings},popup`); | ||
| if (!pip) { | ||
| throw new Error("Failed to open popup. Please allow popups for this site to view the devtools in picture-in-picture mode."); | ||
| } | ||
| if (import.meta.hot && typeof import.meta.hot.on === "function") { | ||
| import.meta.hot.on("vite:beforeUpdate", () => { | ||
| localStorage.setItem("pip_open", "false"); | ||
| closePipWindow(); | ||
| }); | ||
| } | ||
| window.addEventListener("beforeunload", () => { | ||
| localStorage.setItem("pip_open", "false"); | ||
| closePipWindow(); | ||
| }); | ||
| pip.document.head.innerHTML = ""; | ||
| pip.document.body.innerHTML = ""; | ||
| pip.document.title = "TanStack Devtools"; | ||
| pip.document.body.style.margin = "0"; | ||
| pip.addEventListener("pagehide", () => { | ||
| localStorage.setItem("pip_open", "false"); | ||
| closePipWindow(); | ||
| }); | ||
| [...document.styleSheets].forEach((styleSheet) => { | ||
| try { | ||
| const cssRules = [...styleSheet.cssRules].map((rule) => rule.cssText).join(""); | ||
| const style = document.createElement("style"); | ||
| const style_node = styleSheet.ownerNode; | ||
| let style_id = ""; | ||
| if (style_node && "id" in style_node) { | ||
| style_id = style_node.id; | ||
| } | ||
| if (style_id) { | ||
| style.setAttribute("id", style_id); | ||
| } | ||
| style.textContent = cssRules; | ||
| pip.document.head.appendChild(style); | ||
| } catch (e) { | ||
| const link = document.createElement("link"); | ||
| if (styleSheet.href == null) { | ||
| return; | ||
| } | ||
| link.rel = "stylesheet"; | ||
| link.type = styleSheet.type; | ||
| link.media = styleSheet.media.toString(); | ||
| link.href = styleSheet.href; | ||
| pip.document.head.appendChild(link); | ||
| } | ||
| }); | ||
| delegateEvents(["focusin", "focusout", "pointermove", "keydown", "pointerdown", "pointerup", "click", "mousedown", "input"], pip.document); | ||
| setPipWindow(pip); | ||
| }; | ||
| createEffect(() => { | ||
| const gooberStyles = document.querySelector("#_goober"); | ||
| const w = pipWindow(); | ||
| if (gooberStyles && w) { | ||
| const observer = new MutationObserver(() => { | ||
| const pip_style = w.document.querySelector("#_goober"); | ||
| if (pip_style) { | ||
| pip_style.textContent = gooberStyles.textContent; | ||
| } | ||
| }); | ||
| observer.observe(gooberStyles, { | ||
| childList: true, | ||
| // observe direct children | ||
| subtree: true, | ||
| // and lower descendants too | ||
| characterDataOldValue: true | ||
| // pass old data to callback | ||
| }); | ||
| onCleanup(() => { | ||
| observer.disconnect(); | ||
| }); | ||
| } | ||
| }); | ||
| const value = createMemo(() => ({ | ||
| pipWindow: pipWindow(), | ||
| requestPipWindow, | ||
| closePipWindow, | ||
| disabled: props.disabled ?? false | ||
| })); | ||
| return createComponent(PiPContext.Provider, { | ||
| value, | ||
| get children() { | ||
| return props.children; | ||
| } | ||
| }); | ||
| }; | ||
| var usePiPWindow = () => { | ||
| const context = createMemo(() => { | ||
| const ctx = useContext(PiPContext); | ||
| if (!ctx) { | ||
| throw new Error("usePiPWindow must be used within a PiPProvider"); | ||
| } | ||
| return ctx(); | ||
| }); | ||
| return context; | ||
| }; | ||
| // src/utils/constants.ts | ||
| var MAX_ACTIVE_PLUGINS = 3; | ||
| // src/utils/sanitize.ts | ||
| var tryParseJson = (json) => { | ||
| if (!json) return void 0; | ||
| try { | ||
| return JSON.parse(json); | ||
| } catch (_e) { | ||
| return void 0; | ||
| } | ||
| }; | ||
| var uppercaseFirstLetter = (value) => value.charAt(0).toUpperCase() + value.slice(1); | ||
| var getAllPermutations = (arr) => { | ||
| const res = []; | ||
| function permutate(arr2, start) { | ||
| if (start === arr2.length - 1) { | ||
| res.push([...arr2]); | ||
| return; | ||
| } | ||
| for (let i = start; i < arr2.length; i++) { | ||
| [arr2[start], arr2[i]] = [arr2[i], arr2[start]]; | ||
| permutate(arr2, start + 1); | ||
| [arr2[start], arr2[i]] = [arr2[i], arr2[start]]; | ||
| } | ||
| } | ||
| permutate(arr, 0); | ||
| return res; | ||
| }; | ||
| // src/context/devtools-store.ts | ||
| var keyboardModifiers = [ | ||
| "Alt", | ||
| "Control", | ||
| "Meta", | ||
| "Shift", | ||
| "CtrlOrMeta" | ||
| ]; | ||
| var initialState = { | ||
| settings: { | ||
| defaultOpen: false, | ||
| hideUntilHover: false, | ||
| position: "bottom-right", | ||
| panelLocation: "bottom", | ||
| openHotkey: ["Control", "~"], | ||
| inspectHotkey: ["Shift", "Alt", "CtrlOrMeta"], | ||
| requireUrlFlag: false, | ||
| urlFlag: "tanstack-devtools", | ||
| theme: typeof window !== "undefined" && typeof window.matchMedia !== "undefined" && window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light", | ||
| triggerHidden: false, | ||
| customTrigger: void 0 | ||
| }, | ||
| state: { | ||
| activeTab: "plugins", | ||
| height: 400, | ||
| activePlugins: [], | ||
| persistOpen: false | ||
| } | ||
| }; | ||
| // src/utils/get-default-active-plugins.ts | ||
| function getDefaultActivePlugins(plugins) { | ||
| if (plugins.length === 0) { | ||
| return []; | ||
| } | ||
| if (plugins.length === 1) { | ||
| return [plugins[0].id]; | ||
| } | ||
| return plugins.filter((plugin) => plugin.defaultOpen === true).slice(0, MAX_ACTIVE_PLUGINS).map((plugin) => plugin.id); | ||
| } | ||
| // src/context/devtools-context.tsx | ||
| var DevtoolsContext = createContext(); | ||
| var getSettings = () => { | ||
| const settingsString = getStorageItem(TANSTACK_DEVTOOLS_SETTINGS); | ||
| const settings = tryParseJson(settingsString); | ||
| return { | ||
| ...settings | ||
| }; | ||
| }; | ||
| var generatePluginId = (plugin, index) => { | ||
| if (plugin.id) { | ||
| return plugin.id; | ||
| } | ||
| if (typeof plugin.name === "string") { | ||
| return `${plugin.name.toLowerCase().replace(" ", "-")}-${index}`; | ||
| } | ||
| return index.toString(); | ||
| }; | ||
| function getStateFromLocalStorage(plugins) { | ||
| const existingStateString = getStorageItem(TANSTACK_DEVTOOLS_STATE); | ||
| const existingState = tryParseJson(existingStateString); | ||
| const pluginIds = plugins?.map((plugin, i) => generatePluginId(plugin, i)) || []; | ||
| if (existingState?.activePlugins) { | ||
| const originalLength = existingState.activePlugins.length; | ||
| existingState.activePlugins = existingState.activePlugins.filter((id) => pluginIds.includes(id)); | ||
| if (existingState.activePlugins.length !== originalLength) { | ||
| setStorageItem(TANSTACK_DEVTOOLS_STATE, JSON.stringify(existingState)); | ||
| } | ||
| } | ||
| return existingState; | ||
| } | ||
| var getExistingStateFromStorage = (config, plugins) => { | ||
| const existingState = getStateFromLocalStorage(plugins); | ||
| const settings = getSettings(); | ||
| const pluginsWithIds = plugins?.map((plugin, i) => { | ||
| const id = generatePluginId(plugin, i); | ||
| return { | ||
| ...plugin, | ||
| id | ||
| }; | ||
| }) || []; | ||
| let activePlugins = existingState?.activePlugins || []; | ||
| const shouldFillWithDefaultOpenPlugins = activePlugins.length === 0 && pluginsWithIds.length > 0; | ||
| if (shouldFillWithDefaultOpenPlugins) { | ||
| activePlugins = getDefaultActivePlugins(pluginsWithIds); | ||
| } | ||
| const state = { | ||
| ...initialState, | ||
| plugins: pluginsWithIds, | ||
| state: { | ||
| ...initialState.state, | ||
| ...existingState, | ||
| activePlugins | ||
| }, | ||
| settings: { | ||
| ...initialState.settings, | ||
| ...config, | ||
| ...settings | ||
| } | ||
| }; | ||
| return state; | ||
| }; | ||
| var DevtoolsProvider = (props) => { | ||
| const [store, setStore] = createStore(getExistingStateFromStorage(props.config, props.plugins)); | ||
| const updatePlugins = (newPlugins) => { | ||
| const pluginsWithIds = newPlugins.map((plugin, i) => { | ||
| const id = generatePluginId(plugin, i); | ||
| return { | ||
| ...plugin, | ||
| id | ||
| }; | ||
| }); | ||
| setStore("plugins", pluginsWithIds); | ||
| }; | ||
| createEffect(() => { | ||
| if (props.onSetPlugins) { | ||
| props.onSetPlugins(updatePlugins); | ||
| } | ||
| }); | ||
| const value = { | ||
| store, | ||
| setStore: (updater) => { | ||
| const newState = updater(store); | ||
| const { | ||
| settings, | ||
| state: internalState | ||
| } = newState; | ||
| setStorageItem(TANSTACK_DEVTOOLS_SETTINGS, JSON.stringify(settings)); | ||
| setStorageItem(TANSTACK_DEVTOOLS_STATE, JSON.stringify(internalState)); | ||
| setStore((prev) => ({ | ||
| ...prev, | ||
| ...newState | ||
| })); | ||
| } | ||
| }; | ||
| return createComponent(DevtoolsContext.Provider, { | ||
| value, | ||
| get children() { | ||
| return props.children; | ||
| } | ||
| }); | ||
| }; | ||
| export { DevtoolsContext, DevtoolsProvider, MAX_ACTIVE_PLUGINS, PLUGIN_CONTAINER_ID, PLUGIN_TITLE_CONTAINER_ID, PiPProvider, TANSTACK_DEVTOOLS, getAllPermutations, initialState, keyboardModifiers, uppercaseFirstLetter, usePiPWindow }; |
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
-124
| import { lazy } from 'solid-js' | ||
| import { Portal, render } from 'solid-js/web' | ||
| import { ClientEventBus } from '@tanstack/devtools-event-bus/client' | ||
| import { DevtoolsProvider } from './context/devtools-context' | ||
| import { initialState } from './context/devtools-store' | ||
| import { PiPProvider } from './context/pip-context' | ||
| import type { ClientEventBusConfig } from '@tanstack/devtools-event-bus/client' | ||
| import type { | ||
| TanStackDevtoolsConfig, | ||
| TanStackDevtoolsPlugin, | ||
| } from './context/devtools-context' | ||
| export interface TanStackDevtoolsInit { | ||
| /** | ||
| * Configuration for the devtools shell. These configuration options are used to set the | ||
| * initial state of the devtools when it is started for the first time. Afterwards, | ||
| * the settings are persisted in local storage and changed through the settings panel. | ||
| */ | ||
| config?: Partial<TanStackDevtoolsConfig> | ||
| /** | ||
| * Array of plugins to be used in the devtools. | ||
| * Each plugin has a `render` function that gives you the dom node to mount into | ||
| * | ||
| * Example: | ||
| * ```ts | ||
| * const devtools = new TanStackDevtoolsCore({ | ||
| * plugins: [ | ||
| * { | ||
| * id: "your-plugin-id", | ||
| * name: "Your Plugin", | ||
| * render: (el) => { | ||
| * // Your render logic here | ||
| * }, | ||
| * }, | ||
| * ], | ||
| * }) | ||
| * ``` | ||
| */ | ||
| plugins?: Array<TanStackDevtoolsPlugin> | ||
| eventBusConfig?: ClientEventBusConfig | ||
| } | ||
| export class TanStackDevtoolsCore { | ||
| #config: TanStackDevtoolsConfig = { | ||
| ...initialState.settings, | ||
| } | ||
| #plugins: Array<TanStackDevtoolsPlugin> = [] | ||
| #isMounted = false | ||
| #dispose?: () => void | ||
| #Component: any | ||
| #eventBus: ClientEventBus | undefined | ||
| #eventBusConfig: ClientEventBusConfig | undefined | ||
| #setPlugins?: (plugins: Array<TanStackDevtoolsPlugin>) => void | ||
| constructor(init: TanStackDevtoolsInit) { | ||
| this.#plugins = init.plugins || [] | ||
| this.#eventBusConfig = init.eventBusConfig | ||
| this.#config = { | ||
| ...this.#config, | ||
| ...init.config, | ||
| } | ||
| } | ||
| mount<T extends HTMLElement>(el: T) { | ||
| // tsup-preset-solid statically replaces this variable during build, which eliminates this code from server bundle | ||
| // can be run outside of vite so we ignore the rule | ||
| // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition | ||
| if (import.meta?.env?.SSR) return | ||
| if (this.#isMounted) { | ||
| throw new Error('Devtools is already mounted') | ||
| } | ||
| const mountTo = el | ||
| const dispose = render(() => { | ||
| this.#Component = lazy(() => import('./devtools')) | ||
| const Devtools = this.#Component | ||
| this.#eventBus = new ClientEventBus(this.#eventBusConfig) | ||
| this.#eventBus.start() | ||
| return ( | ||
| <DevtoolsProvider | ||
| plugins={this.#plugins} | ||
| config={this.#config} | ||
| onSetPlugins={(setPlugins) => { | ||
| this.#setPlugins = setPlugins | ||
| }} | ||
| > | ||
| <PiPProvider> | ||
| <Portal mount={mountTo}> | ||
| <Devtools /> | ||
| </Portal> | ||
| </PiPProvider> | ||
| </DevtoolsProvider> | ||
| ) | ||
| }, mountTo) | ||
| this.#isMounted = true | ||
| this.#dispose = dispose | ||
| } | ||
| unmount() { | ||
| if (!this.#isMounted) { | ||
| throw new Error('Devtools is not mounted') | ||
| } | ||
| this.#eventBus?.stop() | ||
| this.#dispose?.() | ||
| this.#isMounted = false | ||
| } | ||
| setConfig(config: Partial<TanStackDevtoolsInit>) { | ||
| this.#config = { | ||
| ...this.#config, | ||
| ...config, | ||
| } | ||
| if (config.plugins) { | ||
| this.#plugins = config.plugins | ||
| // Update the reactive store if mounted | ||
| if (this.#isMounted && this.#setPlugins) { | ||
| this.#setPlugins(config.plugins) | ||
| } | ||
| } | ||
| } | ||
| } | ||
| export type { ClientEventBusConfig } |
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Network access
Supply chain riskThis module accesses the network.
Found 1 instance in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Network access
Supply chain riskThis module accesses the network.
Found 1 instance in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
555628
0.7%62
8.77%15626
0.98%