nuxtseo-layer-devtools 0.2.3 → 0.2.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -62,7 +62,9 @@ const isRouteNav = computed(() => navItems.some(item => item.to))
|
|
|
62
62
|
|
|
63
63
|
const modeDropdownOpen = ref(false)
|
|
64
64
|
const modeDropdownRef = ref<HTMLElement>()
|
|
65
|
-
onClickOutside(modeDropdownRef, () => {
|
|
65
|
+
onClickOutside(modeDropdownRef, () => {
|
|
66
|
+
modeDropdownOpen.value = false
|
|
67
|
+
})
|
|
66
68
|
|
|
67
69
|
function selectMode(mode: 'local' | 'production') {
|
|
68
70
|
previewSource.value = mode
|
package/nuxt.config.ts
CHANGED
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nuxtseo-layer-devtools",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.2.
|
|
4
|
+
"version": "0.2.5",
|
|
5
5
|
"description": "Shared Nuxt layer for Nuxt SEO devtools clients.",
|
|
6
6
|
"author": {
|
|
7
7
|
"name": "Harlan Wilton",
|
|
@@ -9,6 +9,12 @@
|
|
|
9
9
|
"url": "https://harlanzw.com/"
|
|
10
10
|
},
|
|
11
11
|
"license": "MIT",
|
|
12
|
+
"exports": {
|
|
13
|
+
".": "./nuxt.config.ts",
|
|
14
|
+
"./composables/shiki": "./composables/shiki.ts",
|
|
15
|
+
"./composables/rpc": "./composables/rpc.ts",
|
|
16
|
+
"./composables/state": "./composables/state.ts"
|
|
17
|
+
},
|
|
12
18
|
"main": "./nuxt.config.ts",
|
|
13
19
|
"files": [
|
|
14
20
|
"app.config.ts",
|
|
@@ -19,7 +19,7 @@ Shared Nuxt layer providing components, composables, and a design system for all
|
|
|
19
19
|
|
|
20
20
|
1. ALWAYS extend `nuxtseo-layer-devtools` in client/nuxt.config.ts
|
|
21
21
|
2. ALWAYS create `client/composables/rpc.ts` that calls `useDevtoolsConnection()`
|
|
22
|
-
3. ALWAYS use layer components over custom HTML: `DevtoolsSection` not custom details, `DevtoolsKeyValue` not custom tables, `DevtoolsSnippet` not custom code blocks
|
|
22
|
+
3. ALWAYS use layer components over custom HTML: `DevtoolsSection` not custom details, `DevtoolsKeyValue` not custom tables, `DevtoolsSnippet` not custom code blocks. Use `KeyValueItem.code` for inline code rendering instead of separate snippets
|
|
23
23
|
4. NEVER add custom CSS that duplicates what the layer provides
|
|
24
24
|
5. NEVER enable SSR in the client (it runs in an iframe)
|
|
25
25
|
6. ALWAYS disable the module itself in the client nuxt config (e.g. `robots: false`)
|
|
@@ -52,7 +52,7 @@ For full component/composable API reference, read [reference.md](./reference.md)
|
|
|
52
52
|
```ts
|
|
53
53
|
export default defineNuxtConfig({
|
|
54
54
|
extends: ['nuxtseo-layer-devtools'],
|
|
55
|
-
<moduleName>: false,
|
|
55
|
+
// <moduleName>: false,
|
|
56
56
|
app: { baseURL: '/__<module-route>' },
|
|
57
57
|
nitro: { output: { publicDir: resolve('./dist/client') } },
|
|
58
58
|
})
|
|
@@ -93,7 +93,9 @@ if (nuxt.options.dev) {
|
|
|
93
93
|
const activeTab = ref('overview')
|
|
94
94
|
const loading = ref(true)
|
|
95
95
|
const { data } = await useAsyncData('debug', () => $fetch('/__<module>__/debug.json'), { watch: [refreshTime] })
|
|
96
|
-
watch(data, () => {
|
|
96
|
+
watch(data, () => {
|
|
97
|
+
loading.value = false
|
|
98
|
+
})
|
|
97
99
|
</script>
|
|
98
100
|
|
|
99
101
|
<template>
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
|
|
16
16
|
| Component | Props | Key Slots | Purpose |
|
|
17
17
|
|---|---|---|---|
|
|
18
|
-
| `DevtoolsAlert` | `icon?`, `variant` ('info'\|'warning'\|'success'\|'production') | default, `action` | Color coded status bar |
|
|
18
|
+
| `DevtoolsAlert` | `icon?`, `variant` ('info'\|'warning'\|'error'\|'success'\|'production') | default, `action` | Color coded status bar |
|
|
19
19
|
| `DevtoolsError` | `icon?`, `title?`, `error?` | default | Centered error display |
|
|
20
20
|
| `DevtoolsEmptyState` | `icon?`, `title`, `description?`, `variant` ('default'\|'error') | default, `description` | No results placeholder |
|
|
21
21
|
| `DevtoolsProductionError` | `error?` | none | Production URL unreachable |
|
|
@@ -25,10 +25,10 @@
|
|
|
25
25
|
|
|
26
26
|
| Component | Props | Key Slots | Purpose |
|
|
27
27
|
|---|---|---|---|
|
|
28
|
-
| `DevtoolsKeyValue` | `items: KeyValueItem[]`, `striped?` | none | Key value table with copy, links, booleans |
|
|
28
|
+
| `DevtoolsKeyValue` | `items: KeyValueItem[]`, `striped?` | none | Key value table with copy, links, booleans, inline code |
|
|
29
29
|
| `DevtoolsMetric` | `label?`, `value`, `icon?`, `variant` | none | Small inline metric badge |
|
|
30
30
|
| `DevtoolsCopyButton` | `text` | none | Copy to clipboard button |
|
|
31
|
-
| `DevtoolsSnippet` | `label?`, `code`, `lang` ('js'\|'json'\|'xml') | `header` | Code block with header
|
|
31
|
+
| `DevtoolsSnippet` | `label?`, `code`, `lang` ('js'\|'json'\|'xml') | `header` | Code block with header, copy, max 300px scroll |
|
|
32
32
|
| `OCodeBlock` | `code`, `lang`, `lines?`, `transformRendered?` | none | Shiki syntax highlighted pre |
|
|
33
33
|
| `DevtoolsDocs` | `url` | none | Full height iframe |
|
|
34
34
|
|
|
@@ -41,6 +41,8 @@ interface KeyValueItem {
|
|
|
41
41
|
copyable?: boolean
|
|
42
42
|
mono?: boolean
|
|
43
43
|
link?: string
|
|
44
|
+
/** Render value using DevtoolsSnippet. Pass the language for syntax highlighting. */
|
|
45
|
+
code?: 'js' | 'json' | 'xml'
|
|
44
46
|
}
|
|
45
47
|
```
|
|
46
48
|
|
|
@@ -68,8 +70,8 @@ const path: Ref<string>
|
|
|
68
70
|
const query: Ref<any>
|
|
69
71
|
const base: Ref<string>
|
|
70
72
|
const host: ComputedRef<string>
|
|
71
|
-
const refreshSources:
|
|
72
|
-
const slowRefreshSources:
|
|
73
|
+
const refreshSources: () => void // Debounced 200ms
|
|
74
|
+
const slowRefreshSources: () => void // Debounced 1000ms
|
|
73
75
|
|
|
74
76
|
// Production preview mode
|
|
75
77
|
const previewSource: Ref<'local' | 'production'> // localStorage persisted
|
|
@@ -101,7 +103,7 @@ Do NOT add custom CSS unless layer components are insufficient.
|
|
|
101
103
|
|
|
102
104
|
### Utility Classes
|
|
103
105
|
|
|
104
|
-
`.glass` (backdrop blur), `.gradient-bg` (green/blue radials), `.card` (elevated hover), `.code-block`, `.status-enabled/.status-disabled`, `.link-external` (with arrow), `.hint-callout`, `.panel-grids`, `.animate-fade-up/.scale-in/.spin`, `.stagger-children`
|
|
106
|
+
`.glass` (backdrop blur), `.gradient-bg` (green/blue radials), `.card` (elevated hover), `.code-block`, `.status-enabled/.status-disabled`, `.link-external` (with arrow), `.hint-callout`, `.panel-grids`, `.animate-fade-up/.scale-in/.spin`, `.stagger-children`, `.devtools-main-content` (max-width 80rem centered container)
|
|
105
107
|
|
|
106
108
|
### Nuxt UI Defaults (app.config.ts)
|
|
107
109
|
|
|
@@ -127,7 +129,9 @@ watch(isProductionMode, refreshSources)
|
|
|
127
129
|
import { loadShiki as _loadShiki } from '#imports'
|
|
128
130
|
|
|
129
131
|
const customLang: LanguageRegistration = { name: 'my-lang', scopeName: 'source.my-lang', patterns: [] }
|
|
130
|
-
export function loadShiki() {
|
|
132
|
+
export function loadShiki() {
|
|
133
|
+
return _loadShiki({ extraLangs: [customLang] })
|
|
134
|
+
}
|
|
131
135
|
```
|
|
132
136
|
|
|
133
137
|
### Fallback Connection
|
|
@@ -135,14 +139,26 @@ export function loadShiki() { return _loadShiki({ extraLangs: [customLang] }) }
|
|
|
135
139
|
```ts
|
|
136
140
|
const connectionState = ref<'connecting' | 'connected' | 'fallback' | 'failed'>('connecting')
|
|
137
141
|
useDevtoolsConnection({
|
|
138
|
-
onConnected() {
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
appFetch.value = $fetch.create({ baseURL: 'http://localhost:3000' })
|
|
142
|
+
onConnected() {
|
|
143
|
+
connectionState.value = 'connected'
|
|
144
|
+
refreshSources()
|
|
145
|
+
},
|
|
146
|
+
onRouteChange(route) {
|
|
147
|
+
path.value = route.path
|
|
145
148
|
refreshSources()
|
|
146
|
-
}
|
|
147
|
-
}
|
|
149
|
+
},
|
|
150
|
+
})
|
|
151
|
+
onMounted(() => {
|
|
152
|
+
const timer = setTimeout(() => {
|
|
153
|
+
if (connectionState.value === 'connecting') {
|
|
154
|
+
connectionState.value = 'fallback'
|
|
155
|
+
appFetch.value = $fetch.create({ baseURL: 'http://localhost:3000' })
|
|
156
|
+
refreshSources()
|
|
157
|
+
}
|
|
158
|
+
}, 2000)
|
|
159
|
+
|
|
160
|
+
onUnmounted(() => {
|
|
161
|
+
clearTimeout(timer)
|
|
162
|
+
})
|
|
163
|
+
})
|
|
148
164
|
```
|