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, () => { modeDropdownOpen.value = false })
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
@@ -18,6 +18,18 @@ export default defineNuxtConfig({
18
18
  ],
19
19
  },
20
20
 
21
+ vite: {
22
+ optimizeDeps: {
23
+ include: [
24
+ '@vueuse/core',
25
+ ],
26
+ },
27
+ },
28
+
29
+ imports: {
30
+ autoImport: true,
31
+ },
32
+
21
33
  devtools: {
22
34
  enabled: false,
23
35
  },
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "nuxtseo-layer-devtools",
3
3
  "type": "module",
4
- "version": "0.2.3",
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, () => { loading.value = false })
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 and copy |
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: Function // Debounced 200ms
72
- const slowRefreshSources: Function // Debounced 1000ms
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() { return _loadShiki({ extraLangs: [customLang] }) }
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() { connectionState.value = 'connected'; refreshSources() },
139
- onRouteChange(route) { path.value = route.path; refreshSources() },
140
- })
141
- setTimeout(() => {
142
- if (connectionState.value === 'connecting') {
143
- connectionState.value = 'fallback'
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
- }, 2000)
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
  ```