@farming-labs/nuxt-theme 0.0.38 → 0.0.44

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@farming-labs/nuxt-theme",
3
- "version": "0.0.38",
3
+ "version": "0.0.44",
4
4
  "description": "Nuxt/Vue UI components for @farming-labs/docs — layout, sidebar, TOC, search, and theme toggle",
5
5
  "keywords": [
6
6
  "docs",
@@ -60,7 +60,7 @@
60
60
  },
61
61
  "dependencies": {
62
62
  "sugar-high": "^0.9.5",
63
- "@farming-labs/docs": "0.0.38"
63
+ "@farming-labs/docs": "0.0.44"
64
64
  },
65
65
  "peerDependencies": {
66
66
  "nuxt": ">=3.0.0",
@@ -0,0 +1,238 @@
1
+ <script setup lang="ts">
2
+ import { computed } from "vue";
3
+
4
+ const props = withDefaults(
5
+ defineProps<{
6
+ config: Record<string, any>;
7
+ current?: "docs" | "api";
8
+ }>(),
9
+ {
10
+ current: "docs",
11
+ },
12
+ );
13
+
14
+ const route = useRoute();
15
+
16
+ const apiReference = computed(() => {
17
+ const value = props.config?.apiReference;
18
+ if (value === true) {
19
+ return {
20
+ enabled: true,
21
+ path: "api-reference",
22
+ };
23
+ }
24
+
25
+ if (!value || value === false || value.enabled === false) {
26
+ return {
27
+ enabled: false,
28
+ path: "api-reference",
29
+ };
30
+ }
31
+
32
+ return {
33
+ enabled: true,
34
+ path: String(value.path ?? "api-reference").replace(/^\/+|\/+$/g, "") || "api-reference",
35
+ };
36
+ });
37
+
38
+ const docsHref = computed(() => {
39
+ if (typeof props.config?.nav?.url === "string" && props.config.nav.url.length > 0) {
40
+ return props.config.nav.url;
41
+ }
42
+
43
+ const entry = String(props.config?.entry ?? "docs").replace(/^\/+|\/+$/g, "") || "docs";
44
+ const params = new URLSearchParams();
45
+
46
+ for (const [key, raw] of Object.entries(route.query)) {
47
+ if (raw == null) continue;
48
+ const value = Array.isArray(raw) ? raw[0] : raw;
49
+ if (value != null) params.set(key, String(value));
50
+ }
51
+
52
+ const query = params.toString();
53
+ return query ? `/${entry}?${query}` : `/${entry}`;
54
+ });
55
+
56
+ const apiHref = computed(() => {
57
+ const params = new URLSearchParams();
58
+
59
+ for (const [key, raw] of Object.entries(route.query)) {
60
+ if (raw == null) continue;
61
+ const value = Array.isArray(raw) ? raw[0] : raw;
62
+ if (value != null) params.set(key, String(value));
63
+ }
64
+
65
+ const query = params.toString();
66
+ return query ? `/${apiReference.value.path}?${query}` : `/${apiReference.value.path}`;
67
+ });
68
+ </script>
69
+
70
+ <template>
71
+ <details v-if="apiReference.enabled" class="fd-api-switcher">
72
+ <summary class="fd-api-switcher-trigger">
73
+ <span class="fd-api-switcher-trigger-copy">
74
+ <span class="fd-api-switcher-icon">{{ current === "api" ? "</>" : "▣" }}</span>
75
+ <span class="fd-api-switcher-label">
76
+ {{ current === "api" ? "API Reference" : "Documentation" }}
77
+ </span>
78
+ </span>
79
+ <span class="fd-api-switcher-caret">▿</span>
80
+ </summary>
81
+
82
+ <div class="fd-api-switcher-panel">
83
+ <NuxtLink
84
+ :to="docsHref"
85
+ class="fd-api-switcher-option"
86
+ :class="{ 'fd-api-switcher-option-active': current === 'docs' }"
87
+ >
88
+ <span class="fd-api-switcher-option-icon">▣</span>
89
+ <span class="fd-api-switcher-option-copy">
90
+ <span class="fd-api-switcher-option-title">Documentation</span>
91
+ <span class="fd-api-switcher-option-description">
92
+ Markdown pages, guides, and concepts
93
+ </span>
94
+ </span>
95
+ <span class="fd-api-switcher-option-check">✓</span>
96
+ </NuxtLink>
97
+
98
+ <NuxtLink
99
+ :to="apiHref"
100
+ class="fd-api-switcher-option"
101
+ :class="{ 'fd-api-switcher-option-active': current === 'api' }"
102
+ >
103
+ <span class="fd-api-switcher-option-icon">&lt;/&gt;</span>
104
+ <span class="fd-api-switcher-option-copy">
105
+ <span class="fd-api-switcher-option-title">API Reference</span>
106
+ <span class="fd-api-switcher-option-description">
107
+ Scalar-powered route handler reference
108
+ </span>
109
+ </span>
110
+ <span class="fd-api-switcher-option-check">✓</span>
111
+ </NuxtLink>
112
+ </div>
113
+ </details>
114
+ </template>
115
+
116
+ <style scoped>
117
+ .fd-api-switcher {
118
+ position: relative;
119
+ margin: 0;
120
+ border: 1px solid color-mix(in srgb, var(--color-fd-border) 100%, transparent);
121
+ border-radius: 14px;
122
+ background: color-mix(in srgb, var(--color-fd-card) 96%, transparent);
123
+ box-shadow: 0 0 0 1px color-mix(in srgb, var(--color-fd-border) 28%, transparent);
124
+ overflow: hidden;
125
+ }
126
+
127
+ .fd-api-switcher-trigger {
128
+ list-style: none;
129
+ display: flex;
130
+ align-items: center;
131
+ justify-content: space-between;
132
+ gap: 10px;
133
+ cursor: pointer;
134
+ padding: 11px 13px;
135
+ background: color-mix(in srgb, var(--color-fd-card) 98%, transparent);
136
+ }
137
+
138
+ .fd-api-switcher-trigger::-webkit-details-marker {
139
+ display: none;
140
+ }
141
+
142
+ .fd-api-switcher-trigger-copy {
143
+ display: inline-flex;
144
+ align-items: center;
145
+ gap: 10px;
146
+ min-width: 0;
147
+ }
148
+
149
+ .fd-api-switcher-icon,
150
+ .fd-api-switcher-option-icon {
151
+ display: inline-flex;
152
+ width: 20px;
153
+ height: 20px;
154
+ align-items: center;
155
+ justify-content: center;
156
+ flex: 0 0 20px;
157
+ border-radius: 6px;
158
+ border: 1px solid color-mix(in srgb, var(--color-fd-border) 100%, transparent);
159
+ background: color-mix(in srgb, var(--color-fd-card) 92%, transparent);
160
+ color: var(--color-fd-primary);
161
+ box-shadow: 0 0 0 1px color-mix(in srgb, var(--color-fd-border) 28%, transparent);
162
+ font-size: 9px;
163
+ font-weight: 700;
164
+ }
165
+
166
+ .fd-api-switcher-label {
167
+ font-size: 14px;
168
+ font-weight: 600;
169
+ line-height: 1.2;
170
+ }
171
+
172
+ .fd-api-switcher-caret {
173
+ font-size: 11px;
174
+ opacity: 0.56;
175
+ transform: translateY(1px);
176
+ }
177
+
178
+ .fd-api-switcher-panel {
179
+ display: flex;
180
+ flex-direction: column;
181
+ gap: 2px;
182
+ padding: 8px;
183
+ background: color-mix(in srgb, var(--color-fd-card) 96%, transparent);
184
+ border-top: 1px solid color-mix(in srgb, var(--color-fd-border) 100%, transparent);
185
+ }
186
+
187
+ .fd-api-switcher-option {
188
+ display: grid;
189
+ grid-template-columns: 20px 1fr 14px;
190
+ gap: 12px;
191
+ align-items: start;
192
+ padding: 11px 12px;
193
+ border-radius: 12px;
194
+ text-decoration: none;
195
+ color: inherit;
196
+ transition:
197
+ background-color 0.15s ease,
198
+ color 0.15s ease;
199
+ }
200
+
201
+ .fd-api-switcher-option:hover {
202
+ background: color-mix(in srgb, var(--color-fd-primary) 6%, transparent);
203
+ }
204
+
205
+ .fd-api-switcher-option-active {
206
+ background: color-mix(in srgb, var(--color-fd-primary) 10%, transparent);
207
+ }
208
+
209
+ .fd-api-switcher-option-copy {
210
+ display: flex;
211
+ min-width: 0;
212
+ flex-direction: column;
213
+ gap: 4px;
214
+ }
215
+
216
+ .fd-api-switcher-option-title {
217
+ font-size: 13px;
218
+ font-weight: 600;
219
+ line-height: 1.25;
220
+ }
221
+
222
+ .fd-api-switcher-option-description {
223
+ font-size: 12px;
224
+ line-height: 1.4;
225
+ opacity: 0.62;
226
+ }
227
+
228
+ .fd-api-switcher-option-check {
229
+ padding-top: 2px;
230
+ font-size: 12px;
231
+ color: var(--color-fd-primary);
232
+ opacity: 0;
233
+ }
234
+
235
+ .fd-api-switcher-option-active .fd-api-switcher-option-check {
236
+ opacity: 1;
237
+ }
238
+ </style>
@@ -178,8 +178,7 @@ function buildLayoutCSS(layout: Record<string, any> | undefined): string {
178
178
  }
179
179
 
180
180
  const overrideCSS = computed(() => {
181
- const colorOverrides =
182
- (props.config?.theme as any)?._userColorOverrides ?? (props.config?.theme as any)?.ui?.colors;
181
+ const colorOverrides = (props.config?.theme as any)?._userColorOverrides;
183
182
  const typography = (props.config?.theme as any)?.ui?.typography;
184
183
  const layout = (props.config?.theme as any)?.ui?.layout;
185
184
  return [buildColorsCSS(colorOverrides), buildTypographyCSS(typography), buildLayoutCSS(layout)]
package/src/index.d.ts CHANGED
@@ -8,6 +8,7 @@ export const TableOfContents: Component;
8
8
  export const Breadcrumb: Component;
9
9
  export const SearchDialog: Component;
10
10
  export const FloatingAIChat: Component;
11
+ export const ApiReferenceSwitcher: Component;
11
12
 
12
13
  export declare const fumadocs: (overrides?: Partial<DocsTheme>) => DocsTheme;
13
14
  export declare const DefaultUIDefaults: Record<string, any>;
package/src/index.js CHANGED
@@ -11,6 +11,7 @@ export { default as TableOfContents } from "./components/TableOfContents.vue";
11
11
  export { default as Breadcrumb } from "./components/Breadcrumb.vue";
12
12
  export { default as SearchDialog } from "./components/SearchDialog.vue";
13
13
  export { default as FloatingAIChat } from "./components/FloatingAIChat.vue";
14
+ export { default as ApiReferenceSwitcher } from "./components/ApiReferenceSwitcher.vue";
14
15
  export { default as ThemeToggle } from "./components/ThemeToggle.vue";
15
16
 
16
17
  export { fumadocs, DefaultUIDefaults } from "./themes/default.js";