Skip to content

Commit c20c724

Browse files
userquinantfu
andauthored
feat: add directives page (#740)
Co-authored-by: Anthony Fu <[email protected]>
1 parent dd9a91a commit c20c724

File tree

9 files changed

+121
-30
lines changed

9 files changed

+121
-30
lines changed

packages/devtools/client/components/ComposableItem.vue

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,21 @@
11
<script setup lang="ts">
22
import type { Import, UnimportMeta } from 'unimport'
3+
import { kebabCase } from 'scule'
34
import { computed } from 'vue'
45
import { ComposablesDocs } from '~/composables/constants'
56
import { useCopy, useOpenInEditor } from '~/composables/editor'
67
78
const props = withDefaults(
89
defineProps<{
910
item: Import
11+
isDirective?: boolean
1012
metadata?: UnimportMeta
1113
filepath?: string
1214
counter?: boolean
1315
classes?: string
1416
}>(),
1517
{
18+
isDirective: false,
1619
counter: true,
1720
classes: 'px2 py1 text-sm bg-gray:5 ',
1821
},
@@ -22,6 +25,16 @@ const copy = useCopy()
2225
const openInEditor = useOpenInEditor()
2326
2427
const name = computed(() => props.item.as || props.item.name)
28+
const copyName = computed(() => {
29+
let n = name.value
30+
if (props.isDirective) {
31+
if (n[0] !== 'v') {
32+
n = `v${n}`
33+
}
34+
n = kebabCase(n)
35+
}
36+
return n
37+
})
2538
const usageCount = computed(() => props.metadata?.injectionUsage?.[name.value]?.count || 0)
2639
const modules = computed(() =>
2740
(props.metadata?.injectionUsage?.[name.value]?.moduleIds || [])
@@ -40,14 +53,18 @@ const docsUrl = computed(() => {
4053

4154
<template>
4255
<VDropdown :disabled="!props.metadata">
43-
<button hover:text-primary>
44-
<code
45-
rounded font-mono
46-
:class="[metadata && !usageCount ? 'op30 hover:op100' : '', classes]"
47-
>
56+
<button hover:text-primary :class="[metadata && !usageCount ? 'op30 hover:op100' : '', classes]">
57+
<code rounded font-mono>
4858
{{ name }}
4959
<sup v-if="usageCount && counter" text-primary>x{{ usageCount }}</sup>
5060
</code>
61+
<sup v-if="isDirective">
62+
<abbr title="Vue Directive">
63+
<NIcon
64+
icon="tabler:hexagon-letter-d"
65+
/>
66+
</abbr>
67+
</sup>
5168
</button>
5269
<template #popper>
5370
<div max-w-100>
@@ -59,7 +76,7 @@ const docsUrl = computed(() => {
5976
:markdown="item.meta.description"
6077
/>
6178
<div flex="~ gap2" n="primary xs">
62-
<NButton icon="carbon-copy" @click="copy(name, 'imports-name')">
79+
<NButton icon="carbon-copy" @click="copy(copyName, 'imports-name')">
6380
Copy
6481
</NButton>
6582
<NButton v-if="filepath" icon="carbon-code" @click="filepath && openInEditor(filepath)">

packages/devtools/client/components/ComposableTree.vue

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ defineProps<{
1717
v-for="i of value" :key="i.as"
1818
:item="i"
1919
:metadata="metadata"
20+
:is-directive="i.meta?.vueDirective === true"
2021
:filepath="key.match(/^[\w@]/) ? undefined : key"
2122
/>
2223
</div>

packages/devtools/client/components/docs/imports.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,3 +15,9 @@ Meanwhile, modules could also provide auto-imports for their own components. You
1515
<hr>
1616

1717
[Learn more in the documentation](https://nuxt.com/docs/guide/concepts/auto-imports)
18+
19+
## Directives
20+
21+
Directives placed in the directives/ directory are automatically registered by Nuxt. They can be used in your templates without importing them.
22+
23+
[Learn more in the documentation](https://nuxt.com/docs/guide/directory-structure/directives)

packages/devtools/client/pages/modules/imports.vue

Lines changed: 43 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ definePageMeta({
1515
1616
const config = useServerConfig()
1717
const filterMode = ref<'all' | 'using' | 'not-used'>('all')
18+
const filterEntries = ref<'all' | 'composables' | 'directives'>('all')
1819
1920
const search = ref('')
2021
const autoImports = useAutoImports()
@@ -39,6 +40,15 @@ const filtered = computed(() => {
3940
? fuse.value.search(search.value).map(i => i.item)
4041
: functions.value
4142
43+
const filter = filterEntries.value
44+
45+
if (filter === 'composables') {
46+
result = result.filter(i => !(i.meta?.vueDirective === true))
47+
}
48+
else if (filter === 'directives') {
49+
result = result.filter(i => i.meta?.vueDirective === true)
50+
}
51+
4252
if (filterMode.value === 'using' && importsMetadata.value) {
4353
result = result
4454
.filter(i => (i.as || i.name) in importsMetadata.value!.injectionUsage)
@@ -74,12 +84,28 @@ const filtered = computed(() => {
7484
count,
7585
}
7686
})
87+
88+
const filteredUserCountTitle = computed(() => {
89+
return filterEntries.value === 'directives'
90+
? `${filtered.value.count.user} directives from ${filtered.value.user.size} modules`
91+
: `${filtered.value.count.user} composables from ${filtered.value.user.size} modules`
92+
})
93+
const filteredBuiltinTitle = computed(() => {
94+
return filterEntries.value === 'directives'
95+
? `${filtered.value.count.builtin} directives`
96+
: `${filtered.value.count.builtin} composables`
97+
})
98+
const filteredLibTitle = computed(() => {
99+
return filterEntries.value === 'directives'
100+
? `${filtered.value.count.lib} directives from ${filtered.value.lib.size} packages`
101+
: `${filtered.value.count.lib} composables from ${filtered.value.lib.size} packages`
102+
})
77103
</script>
78104

79105
<template>
80106
<div v-if="config" relative h-full of-auto>
81107
<NNavbar v-model:search="search" pb3>
82-
<div v-if="importsMetadata" flex="~ gap-2 items-center">
108+
<div v-if="importsMetadata" flex="~ gap-2 items-center lt-sm:col lt-sm:items-start">
83109
<NIcon icon="carbon-filter" op50 />
84110
<NSelectTabs
85111
v-model="filterMode"
@@ -90,32 +116,41 @@ const filtered = computed(() => {
90116
{ label: 'Not used', value: 'not-used' },
91117
]"
92118
/>
119+
<NSelectTabs
120+
v-model="filterEntries"
121+
n="primary sm"
122+
:options="[
123+
{ label: 'All', value: 'all' },
124+
{ label: 'Composables', value: 'composables' },
125+
{ label: 'Directives', value: 'directives' },
126+
]"
127+
/>
93128
</div>
94129
</NNavbar>
95130
<NSectionBlock
96131
v-if="filtered.user.size"
97132
:open="filtered.count.user <= DETAILS_MAX_ITEMS"
98-
icon="carbon-function"
99-
text="User composables"
100-
:description="`${filtered.count.user} composables from ${filtered.user.size} modules`"
133+
:icon="filterEntries === 'directives' ? 'tabler:hexagon-letter-d' : 'carbon-function'"
134+
:text="`User ${filterEntries === 'directives' ? 'directives' : 'composables'}`"
135+
:description="filteredUserCountTitle"
101136
>
102137
<ComposableTree :map="filtered.user" :root="config.rootDir" :metadata="importsMetadata" />
103138
</NSectionBlock>
104139
<NSectionBlock
105140
v-if="filtered.builtin.size"
106141
:open="filtered.count.builtin <= DETAILS_MAX_ITEMS"
107142
icon="simple-icons-nuxtdotjs"
108-
text="Built-in composables"
109-
:description="`${filtered.count.builtin} composables`"
143+
:text="`Built-in ${filterEntries === 'directives' ? 'directives' : 'composables'}`"
144+
:description="filteredBuiltinTitle"
110145
>
111146
<ComposableTree :map="filtered.builtin" :root="config.rootDir" :metadata="importsMetadata" />
112147
</NSectionBlock>
113148
<NSectionBlock
114149
v-if="filtered.lib.size"
115150
:open="filtered.count.lib <= DETAILS_MAX_ITEMS"
116151
icon="carbon-3d-mpr-toggle"
117-
text="Composables from libraries"
118-
:description="`${filtered.count.lib} composables from ${filtered.lib.size} packages`"
152+
:text="`${filterEntries === 'directives' ? 'Directives' : 'Composables'} from libraries`"
153+
:description="filteredLibTitle"
119154
>
120155
<ComposableTree :map="filtered.lib" :root="config.rootDir" :metadata="importsMetadata" />
121156
</NSectionBlock>
Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
import type { NuxtDevtoolsServerContext } from '../types'
2-
import { addPluginTemplate } from '@nuxt/kit'
2+
import { addPluginTemplate, resolvePath } from '@nuxt/kit'
33
import { join } from 'pathe'
44
import { runtimeDir } from '../dirs'
55

6-
export function setup({ nuxt }: NuxtDevtoolsServerContext) {
6+
export async function setup({ nuxt }: NuxtDevtoolsServerContext) {
77
if (!nuxt.options.dev || nuxt.options.test)
88
return
99

1010
addPluginTemplate({
1111
name: 'vue-devtools-client',
1212
mode: 'client',
13-
src: join(runtimeDir, 'vue-devtools-client.js'),
13+
src: await resolvePath(join(runtimeDir, 'vue-devtools-client')),
1414
})
1515
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// todo: remove this once nuxt with directives folder here
2+
import type { DirectiveBinding } from 'vue'
3+
4+
function mounted(el: HTMLElement, binding: DirectiveBinding) {
5+
// eslint-disable-next-line no-console
6+
console.log('mounted', el, binding)
7+
}
8+
9+
function unmounted(el: HTMLElement, binding: DirectiveBinding) {
10+
// eslint-disable-next-line no-console
11+
console.log('unmounted', el, binding)
12+
}
13+
14+
function updated(el: HTMLElement, binding: DirectiveBinding) {
15+
// eslint-disable-next-line no-console
16+
console.log('updated', el, binding)
17+
}
18+
19+
export const Focus = {
20+
mounted,
21+
unmounted,
22+
updated,
23+
}

playgrounds/tab-pinia/nuxt.config.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
import { createResolver } from '@nuxt/kit'
2+
3+
const resolver = createResolver(import.meta.url)
4+
15
export default defineNuxtConfig({
26
css: ['~/assets/main.css'],
37

@@ -9,6 +13,20 @@ export default defineNuxtConfig({
913

1014
imports: {
1115
dirs: ['./stores'],
16+
presets: [{
17+
from: resolver.resolve('directives/focus.ts'),
18+
imports: [{
19+
name: 'Focus',
20+
meta: {
21+
vueDirective: true,
22+
docsUrl: 'https://vuetifyjs.com/en/directives/click-outside/#usage',
23+
description: 'The v-focus directive focus the element once mounted.',
24+
},
25+
}],
26+
}],
27+
addons: {
28+
vueDirectives: true,
29+
},
1230
},
1331

1432
pinia: {

playgrounds/tab-pinia/pages/index.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ const counter = useCounter()
1010

1111
<template>
1212
<div>
13-
<div style="margin: 1rem 0">
13+
<div v-focus style="margin: 1rem 0">
1414
<PiniaLogo />
1515
</div>
1616

pnpm-lock.yaml

Lines changed: 3 additions & 12 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)