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
15 changes: 8 additions & 7 deletions docs/pages/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,15 @@ const { data } = await useAsyncData('landing', () => {
queryContent('/').findOne(),
])
})
const [getStarted, page] = data.value

const [getStarted, page] = data.value! || []

const intervalId = ref()
const currentStep = ref(0)
const projectsSectionVisible = ref(false)
const nuxtProjectsSection = ref(null)

const { data: module } = await useFetch<{
const { data: mod } = await useFetch<{
stats: {
downloads: number
stars: number
Expand Down Expand Up @@ -216,9 +217,9 @@ watch(projectsSectionVisible, () => {
</template>

<template #links>
<UAvatarGroup :max="13" size="md" class="flex-wrap lg:self-start [&_span:first-child]:text-xs">
<UAvatarGroup v-if="mod" :max="13" size="md" class="flex-wrap lg:self-start [&_span:first-child]:text-xs">
<UTooltip
v-for="(contributor, idx) of module.contributors" :key="idx" :text="contributor.username"
v-for="(contributor, idx) of mod.contributors" :key="idx" :text="contributor.username"
class="rounded-full" :ui="{ background: 'bg-gray-50 dark:bg-gray-800/50' }"
:popper="{ offsetDistance: 16 }"
>
Expand All @@ -241,12 +242,12 @@ watch(projectsSectionVisible, () => {
</p>
</template>

<div class="flex flex-col items-center justify-center gap-8 sm:flex-row lg:gap-16">
<div v-if="mod" class="flex flex-col items-center justify-center gap-8 sm:flex-row lg:gap-16">
<NuxtLink class="group text-center" to="https://npmjs.org/package/@nuxt/devtools" target="_blank">
<p
class="group-hover:text-primary-500 dark:group-hover:text-primary-400 text-6xl font-semibold text-gray-900 dark:text-white"
>
{{ formatNumber(module.stats.downloads) }}+
{{ formatNumber(mod.stats.downloads) }}+
</p>
<p>Monthly Downloads</p>
</NuxtLink>
Expand All @@ -255,7 +256,7 @@ watch(projectsSectionVisible, () => {
<p
class="group-hover:text-primary-500 dark:group-hover:text-primary-400 text-6xl font-semibold text-gray-900 dark:text-white"
>
{{ formatNumber(module.stats.stars) }}+
{{ formatNumber(mod.stats.stars) }}+
</p>
<p>Stars</p>
</NuxtLink>
Expand Down
1 change: 1 addition & 0 deletions packages/devtools-kit/src/_types/options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,7 @@ export interface NuxtDevToolsOptions {
scale: number
showExperimentalFeatures: boolean
showHelpButtons: boolean
showPanel: boolean | null
sidebarExpanded: boolean
sidebarScrollable: boolean
}
Expand Down
18 changes: 15 additions & 3 deletions packages/devtools/client/pages/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,16 @@ definePageMeta({
})

const telemetry = ref(true)
const enableFloatPanel = ref(true)

const {
showPanel,
} = useDevToolsUIOptions()

function visit() {
telemetryEnabled.value = telemetry.value
if (showPanel.value == null && enableFloatPanel.value)
showPanel.value = true
isFirstVisit.value = false
}
</script>
Expand All @@ -34,9 +41,14 @@ function visit() {
</NButton>

<div absolute bottom-0 left-0 right-0 p4>
<NCheckbox v-model="telemetry">
<span op50>Send anonymous statistics, help us improving DevTools</span>
</NCheckbox>
<div flex="~ col gap-2" mxa w-max>
<NCheckbox v-if="showPanel == null" v-model="enableFloatPanel" n="green6">
<span op50>Show floating panel from now on</span>
</NCheckbox>
<NCheckbox v-model="telemetry" n="green6">
<span op50>Send anonymous statistics, help us improving DevTools</span>
</NCheckbox>
</div>
</div>
</NPanelGrids>
</template>
12 changes: 8 additions & 4 deletions packages/devtools/client/pages/settings.vue
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ definePageMeta({

const {
interactionCloseOnOutsideClick,
// showExperimentalFeatures,
showPanel,
showHelpButtons,
scale,
hiddenTabs,
Expand Down Expand Up @@ -107,7 +107,7 @@ watchEffect(() => {
<NSwitch
flex="~ row-reverse" py1 pl2 pr1 n-lime
:model-value="!hiddenTabCategories.includes(name)"
@update:model-value="v => toggleTabCategory(name, v)"
@update:model-value="(v: boolean) => toggleTabCategory(name, v)"
>
<div flex="~ gap-2" flex-auto items-center justify-start>
<span capitalize op75>{{ name }}</span>
Expand All @@ -120,7 +120,7 @@ watchEffect(() => {
<NSwitch
flex="~ row-reverse" py1 pl2 pr1 n-primary
:model-value="!hiddenTabs.includes(tab.name)"
@update:model-value="v => toggleTab(tab.name, v)"
@update:model-value="(v: boolean) => toggleTab(tab.name, v)"
>
<div flex="~ gap-2" flex-auto items-center justify-start pr-4 :class="hiddenTabs.includes(tab.name) ? 'op25' : ''">
<TabIcon text-xl :icon="tab.icon" :title="tab.title" />
Expand Down Expand Up @@ -197,10 +197,14 @@ watchEffect(() => {
<span>Show help buttons</span>
</NCheckbox>

<NCheckbox v-model="showPanel" n-primary>
<span>Always show the floating panel</span>
</NCheckbox>

<div mx--2 my1 h-1px border="b base" op75 />

<p>Minimize floating panel on inactive</p>
<NSelect v-model.number="minimizePanelInactive" n="primary">
<NSelect v-model.number="minimizePanelInactive" n-primary>
<option v-for="i of MinimizeInactiveOptions" :key="i[0]" :value="i[1]">
{{ i[0] }}
</option>
Expand Down
1 change: 1 addition & 0 deletions packages/devtools/src/constant.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ export const defaultTabOptions: NuxtDevToolsOptions = {
interactionCloseOnOutsideClick: false,
showExperimentalFeatures: false,
showHelpButtons: true,
showPanel: null,
scale: 1,
minimizePanelInactive: 5000,
hiddenTabs: [],
Expand Down
32 changes: 29 additions & 3 deletions packages/devtools/src/module-main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,18 @@ import { existsSync } from 'node:fs'
import os from 'node:os'
import { join } from 'pathe'
import type { Nuxt } from 'nuxt/schema'
import { addPlugin, addVitePlugin, logger } from '@nuxt/kit'
import { addPlugin, addTemplate, addVitePlugin, logger } from '@nuxt/kit'
import type { ViteDevServer } from 'vite'
import { searchForWorkspaceRoot } from 'vite'
import sirv from 'sirv'
import { colors } from 'consola/utils'
import { version } from '../package.json'
import type { ModuleOptions } from './types'
import type { ModuleOptions, NuxtDevToolsOptions } from './types'
import { setupRPC } from './server-rpc'
import { clientDir, isGlobalInstall, packageDir, runtimeDir } from './dirs'
import { ROUTE_ANALYZE, ROUTE_AUTH, ROUTE_AUTH_VERIFY, ROUTE_CLIENT } from './constant'
import { ROUTE_ANALYZE, ROUTE_AUTH, ROUTE_AUTH_VERIFY, ROUTE_CLIENT, defaultTabOptions } from './constant'
import { getDevAuthToken } from './dev-auth'
import { readLocalOptions } from './utils/local-options'

export async function enableModule(options: ModuleOptions, nuxt: Nuxt) {
// Disable in test mode
Expand All @@ -30,8 +31,14 @@ export async function enableModule(options: ModuleOptions, nuxt: Nuxt) {
return
}

// Determine if user aware devtools, by checking the presentation in the config
const enabledExplicitly = (nuxt.options.devtools === true)
|| (nuxt.options.devtools && nuxt.options.devtools.enabled)
|| !!nuxt.options.modules.find(m => m === '@nuxt/devtools' || m === '@nuxt/devtools-edge')

await nuxt.callHook('devtools:before')

// Make unimport exposing more information, like the usage of each auto imported function
nuxt.options.imports.collectMeta = true

addPlugin({
Expand All @@ -44,6 +51,25 @@ export async function enableModule(options: ModuleOptions, nuxt: Nuxt) {
mode: 'server',
})

// Mainly for the injected runtime plugin to access the settings
// Usage `import settings from '#build/devtools/settings'`
addTemplate({
filename: 'devtools/settings.mjs',
async getContents() {
const uiOptions = await readLocalOptions<NuxtDevToolsOptions['ui']>(
{
...defaultTabOptions.ui,
// When not enabled explicitly, we hide the panel by default
showPanel: enabledExplicitly ? true : null,
},
{ root: nuxt.options.rootDir },
)
return `export default ${JSON.stringify({
ui: uiOptions,
})}`
},
})

// Inject inline script
nuxt.hook('nitro:config', (config) => {
config.externals = config.externals || {}
Expand Down
49 changes: 39 additions & 10 deletions packages/devtools/src/runtime/plugins/view/Main.vue
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
<script setup lang="ts">
import type { CSSProperties } from 'vue'
import { computed, onMounted, reactive, ref, watchEffect } from 'vue'
import type { CSSProperties } from 'vue'
import type { NuxtDevtoolsHostClient } from '../../../types'
import { settings } from '../../settings'
import { state } from './state'
import { millisecondToHumanreadable, useEventListener, useScreenSafeArea } from './utils'
import FrameBox from './FrameBox.vue'
Expand All @@ -20,6 +21,12 @@ const panelMargins = reactive({
const safeArea = useScreenSafeArea()

const isSafari = navigator.userAgent.includes('Safari') && !navigator.userAgent.includes('Chrome')
let isInit = true

watchEffect(() => {
if (state.value.open)
isInit = false
})

watchEffect(() => {
panelMargins.left = safeArea.left.value + 10
Expand Down Expand Up @@ -167,6 +174,17 @@ function bringUp() {
}

const isHidden = computed(() => {
if (state.value.open)
return false
if (settings.ui.showPanel === true)
return false
if (settings.ui.showPanel === false)
return true
// If not explicitly set, hide the panel on first load
return isInit
})

const isMinimized = computed(() => {
if (state.value.minimizePanelInactive < 0)
return false
if (state.value.minimizePanelInactive === 0)
Expand All @@ -180,18 +198,25 @@ const isHidden = computed(() => {
&& state.value.minimizePanelInactive
})

const anchorStyle = computed(() => ({
left: `${anchorPos.value.left}px`,
top: `${anchorPos.value.top}px`,
}))
const anchorStyle = computed(() => {
return {
left: `${anchorPos.value.left}px`,
top: `${anchorPos.value.top}px`,
pointerEvents: isHidden.value ? 'none' : 'auto',
} as const
})

const panelStyle = computed(() => {
const style: any = {
transform: isVertical.value
? `translate(${isHidden.value ? `calc(-50% ${state.value.position === 'right' ? '+' : '-'} 15px)` : '-50%'}, -50%) rotate(90deg)`
: `translate(-50%, ${isHidden.value ? `calc(-50% ${state.value.position === 'top' ? '-' : '+'} 15px)` : '-50%'})`,
? `translate(${isMinimized.value ? `calc(-50% ${state.value.position === 'right' ? '+' : '-'} 15px)` : '-50%'}, -50%) rotate(90deg)`
: `translate(-50%, ${isMinimized.value ? `calc(-50% ${state.value.position === 'top' ? '-' : '+'} 15px)` : '-50%'})`,
}
if (isHidden.value) {
style.opacity = 0
style.pointerEvents = 'none'
}
if (isMinimized.value) {
switch (state.value.position) {
case 'top':
case 'right':
Expand Down Expand Up @@ -313,11 +338,15 @@ onMounted(() => {
:style="[anchorStyle, vars]"
:class="{
'nuxt-devtools-vertical': isVertical,
'nuxt-devtools-hide': isHidden,
'nuxt-devtools-hide': isMinimized,
}"
@mousemove="bringUp"
>
<div v-if="!isSafari" class="nuxt-devtools-glowing" :style="isDragging ? 'opacity: 0.6 !important' : ''" />
<div
v-if="!isSafari"
class="nuxt-devtools-glowing"
:style="isDragging ? 'opacity: 0.6 !important' : ''"
/>
<div
ref="panelEl"
class="nuxt-devtools-panel"
Expand Down Expand Up @@ -460,7 +489,7 @@ onMounted(() => {
user-select: none;
touch-action: none;
max-width: 150px;
transition: max-width 0.6s ease, padding 0.5s ease, transform 0.4s ease, all 0.6s ease;
transition: all 0.6s ease, max-width 0.6s ease, padding 0.5s ease, transform 0.4s ease, opacity 0.2s ease;
}

#nuxt-devtools-anchor.nuxt-devtools-hide .nuxt-devtools-panel {
Expand Down
8 changes: 8 additions & 0 deletions packages/devtools/src/runtime/settings.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import type { NuxtDevToolsOptions } from '../types'

// @ts-expect-error virtual module
import _settings from '#build/devtools/settings'

export const settings = _settings as {
ui: NuxtDevToolsOptions['ui']
}
18 changes: 13 additions & 5 deletions packages/devtools/src/server-rpc/options.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { NuxtDevToolsOptions, NuxtDevtoolsServerContext, ServerFunctions } from '../types'
import { readOptions, writeOptions } from '../utils/options'
import { readLocalOptions, writeLocalOptions } from '../utils/local-options'
import { defaultTabOptions } from '../constant'

export function setupOptionsRPC({ nuxt }: NuxtDevtoolsServerContext) {
Expand All @@ -15,7 +15,7 @@ export function setupOptionsRPC({ nuxt }: NuxtDevtoolsServerContext) {
}

async function read<T extends keyof NuxtDevToolsOptions>(tab: T) {
options![tab] = await readOptions<NuxtDevToolsOptions[T]>(defaultTabOptions[tab], {
options![tab] = await readLocalOptions<NuxtDevToolsOptions[T]>(defaultTabOptions[tab], {
root: nuxt.options.rootDir,
key: tab !== 'ui' && tab,
})
Expand All @@ -26,9 +26,17 @@ export function setupOptionsRPC({ nuxt }: NuxtDevtoolsServerContext) {
async updateOptions(tab, _settings) {
const settings = await getOptions(tab)
Object.assign(settings, _settings)
await writeOptions({ ...settings }, {
root: nuxt.options.rootDir,
key: tab !== 'ui' && tab,
await writeLocalOptions(
{ ...settings },
{
root: nuxt.options.rootDir,
key: tab !== 'ui' && tab,
},
)
nuxt.callHook('builder:generateApp', {
filter(template) {
return template.filename.includes('devtools/settings.mjs')
},
})
},
getOptions,
Expand Down
Loading