@farming-labs/nuxt-theme 0.0.51 → 0.0.53
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 +2 -2
- package/src/components/DocsContent.vue +112 -0
- package/styles/docs.css +38 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@farming-labs/nuxt-theme",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.53",
|
|
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.
|
|
63
|
+
"@farming-labs/docs": "0.0.53"
|
|
64
64
|
},
|
|
65
65
|
"peerDependencies": {
|
|
66
66
|
"nuxt": ">=3.0.0",
|
|
@@ -20,6 +20,7 @@ const props = defineProps<{
|
|
|
20
20
|
editOnGithub?: string;
|
|
21
21
|
lastModified?: string;
|
|
22
22
|
entry?: string;
|
|
23
|
+
slug?: string;
|
|
23
24
|
locale?: string;
|
|
24
25
|
};
|
|
25
26
|
config?: Record<string, unknown> | null;
|
|
@@ -29,6 +30,7 @@ const route = useRoute();
|
|
|
29
30
|
const openDropdownMenu = ref(false);
|
|
30
31
|
const copyLabel = ref("Copy page");
|
|
31
32
|
const copied = ref(false);
|
|
33
|
+
const selectedFeedback = ref<"positive" | "negative" | null>(null);
|
|
32
34
|
|
|
33
35
|
const titleSuffix = computed(() =>
|
|
34
36
|
props.config?.metadata?.titleTemplate
|
|
@@ -145,6 +147,35 @@ const showPageActions = computed(
|
|
|
145
147
|
);
|
|
146
148
|
const showActionsAbove = computed(() => pageActionsPosition.value === "above-title" && showPageActions.value);
|
|
147
149
|
const showActionsBelow = computed(() => pageActionsPosition.value === "below-title" && showPageActions.value);
|
|
150
|
+
const feedbackConfig = computed(() => {
|
|
151
|
+
const defaults = {
|
|
152
|
+
enabled: false,
|
|
153
|
+
question: "How is this guide?",
|
|
154
|
+
positiveLabel: "Good",
|
|
155
|
+
negativeLabel: "Bad",
|
|
156
|
+
onFeedback: undefined as ((payload: Record<string, unknown>) => void) | undefined,
|
|
157
|
+
};
|
|
158
|
+
|
|
159
|
+
const feedback = props.config?.feedback as Record<string, unknown> | boolean | null | undefined;
|
|
160
|
+
if (feedback === undefined || feedback === false) return defaults;
|
|
161
|
+
if (feedback === true) return { ...defaults, enabled: true };
|
|
162
|
+
if (typeof feedback !== "object" || feedback === null) return defaults;
|
|
163
|
+
|
|
164
|
+
return {
|
|
165
|
+
enabled: feedback.enabled !== false,
|
|
166
|
+
question: String((feedback as { question?: string }).question ?? defaults.question),
|
|
167
|
+
positiveLabel: String(
|
|
168
|
+
feedback.positiveLabel ?? defaults.positiveLabel,
|
|
169
|
+
),
|
|
170
|
+
negativeLabel: String(
|
|
171
|
+
feedback.negativeLabel ?? defaults.negativeLabel,
|
|
172
|
+
),
|
|
173
|
+
onFeedback:
|
|
174
|
+
typeof feedback.onFeedback === "function"
|
|
175
|
+
? (feedback.onFeedback as (payload: Record<string, unknown>) => void)
|
|
176
|
+
: undefined,
|
|
177
|
+
};
|
|
178
|
+
});
|
|
148
179
|
|
|
149
180
|
useHead({
|
|
150
181
|
title: () => `${props.data.title}${titleSuffix.value}`,
|
|
@@ -201,6 +232,43 @@ function openInProvider(provider: { name: string; urlTemplate: string }) {
|
|
|
201
232
|
closeDropdown();
|
|
202
233
|
}
|
|
203
234
|
|
|
235
|
+
function handleFeedback(value: "positive" | "negative") {
|
|
236
|
+
selectedFeedback.value = value;
|
|
237
|
+
|
|
238
|
+
const pathname =
|
|
239
|
+
typeof window !== "undefined"
|
|
240
|
+
? window.location.pathname.replace(/\/$/, "") || "/"
|
|
241
|
+
: props.data.slug
|
|
242
|
+
? `/${entry.value}/${props.data.slug}`
|
|
243
|
+
: `/${entry.value}`;
|
|
244
|
+
|
|
245
|
+
const payload = {
|
|
246
|
+
value,
|
|
247
|
+
title: props.data.title,
|
|
248
|
+
description: props.data.description,
|
|
249
|
+
url: typeof window !== "undefined" ? window.location.href : pathname,
|
|
250
|
+
pathname,
|
|
251
|
+
path: pathname,
|
|
252
|
+
entry: entry.value,
|
|
253
|
+
slug: props.data.slug ?? "",
|
|
254
|
+
locale: props.data.locale,
|
|
255
|
+
};
|
|
256
|
+
|
|
257
|
+
try {
|
|
258
|
+
feedbackConfig.value.onFeedback?.(payload);
|
|
259
|
+
} catch {}
|
|
260
|
+
|
|
261
|
+
try {
|
|
262
|
+
if (typeof window !== "undefined" && (window as any).__fdOnFeedback__) {
|
|
263
|
+
(window as any).__fdOnFeedback__(payload);
|
|
264
|
+
}
|
|
265
|
+
} catch {}
|
|
266
|
+
|
|
267
|
+
if (typeof window !== "undefined") {
|
|
268
|
+
window.dispatchEvent(new CustomEvent("fd:feedback", { detail: payload }));
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
|
|
204
272
|
function handleClickOutside(e: MouseEvent) {
|
|
205
273
|
const target = e.target as Node;
|
|
206
274
|
if (openDropdownMenu.value && !(target as Element).closest?.(".fd-page-action-dropdown")) {
|
|
@@ -354,5 +422,49 @@ onUnmounted(() => {
|
|
|
354
422
|
</template>
|
|
355
423
|
|
|
356
424
|
<div v-html="htmlWithoutFirstH1" />
|
|
425
|
+
|
|
426
|
+
<section v-if="feedbackConfig.enabled" class="fd-feedback" aria-label="Page feedback">
|
|
427
|
+
<div class="fd-feedback-content">
|
|
428
|
+
<p class="fd-feedback-question">{{ feedbackConfig.question }}</p>
|
|
429
|
+
<div class="fd-feedback-actions" role="group" :aria-label="feedbackConfig.question">
|
|
430
|
+
<button
|
|
431
|
+
type="button"
|
|
432
|
+
class="fd-page-action-btn"
|
|
433
|
+
:aria-pressed="selectedFeedback === 'positive'"
|
|
434
|
+
:data-selected="selectedFeedback === 'positive' ? 'true' : undefined"
|
|
435
|
+
@click="handleFeedback('positive')"
|
|
436
|
+
>
|
|
437
|
+
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" aria-hidden="true">
|
|
438
|
+
<path
|
|
439
|
+
d="M7 21H5a2 2 0 0 1-2-2v-7a2 2 0 0 1 2-2h2m0 11V10m0 11h9.28a2 2 0 0 0 1.97-1.66l1.2-7A2 2 0 0 0 17.48 10H13V6.5a2.5 2.5 0 0 0-2.5-2.5L7 10"
|
|
440
|
+
stroke="currentColor"
|
|
441
|
+
stroke-width="2"
|
|
442
|
+
stroke-linecap="round"
|
|
443
|
+
stroke-linejoin="round"
|
|
444
|
+
/>
|
|
445
|
+
</svg>
|
|
446
|
+
<span>{{ feedbackConfig.positiveLabel }}</span>
|
|
447
|
+
</button>
|
|
448
|
+
<button
|
|
449
|
+
type="button"
|
|
450
|
+
class="fd-page-action-btn"
|
|
451
|
+
:aria-pressed="selectedFeedback === 'negative'"
|
|
452
|
+
:data-selected="selectedFeedback === 'negative' ? 'true' : undefined"
|
|
453
|
+
@click="handleFeedback('negative')"
|
|
454
|
+
>
|
|
455
|
+
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" aria-hidden="true">
|
|
456
|
+
<path
|
|
457
|
+
d="M17 3h2a2 2 0 0 1 2 2v7a2 2 0 0 1-2 2h-2M17 3v11m0-11H7.72a2 2 0 0 0-1.97 1.66l-1.2 7A2 2 0 0 0 6.52 14H11v3.5a2.5 2.5 0 0 0 2.5 2.5L17 14"
|
|
458
|
+
stroke="currentColor"
|
|
459
|
+
stroke-width="2"
|
|
460
|
+
stroke-linecap="round"
|
|
461
|
+
stroke-linejoin="round"
|
|
462
|
+
/>
|
|
463
|
+
</svg>
|
|
464
|
+
<span>{{ feedbackConfig.negativeLabel }}</span>
|
|
465
|
+
</button>
|
|
466
|
+
</div>
|
|
467
|
+
</div>
|
|
468
|
+
</section>
|
|
357
469
|
</DocsPage>
|
|
358
470
|
</template>
|
package/styles/docs.css
CHANGED
|
@@ -649,10 +649,19 @@ samp {
|
|
|
649
649
|
color: var(--color-fd-foreground);
|
|
650
650
|
}
|
|
651
651
|
|
|
652
|
+
.fd-page-action-btn[data-selected="true"] {
|
|
653
|
+
color: var(--color-fd-accent-foreground);
|
|
654
|
+
background: var(--color-fd-accent);
|
|
655
|
+
}
|
|
656
|
+
|
|
652
657
|
.fd-page-action-btn svg {
|
|
653
658
|
flex-shrink: 0;
|
|
654
659
|
}
|
|
655
660
|
|
|
661
|
+
.fd-page-action-btn[data-selected="true"] svg {
|
|
662
|
+
color: currentColor;
|
|
663
|
+
}
|
|
664
|
+
|
|
656
665
|
.fd-page-action-dropdown {
|
|
657
666
|
position: relative;
|
|
658
667
|
}
|
|
@@ -720,6 +729,35 @@ samp {
|
|
|
720
729
|
margin-bottom: 1rem;
|
|
721
730
|
}
|
|
722
731
|
|
|
732
|
+
.fd-feedback {
|
|
733
|
+
margin-top: 2rem;
|
|
734
|
+
padding-top: 1.25rem;
|
|
735
|
+
border-top: 1px solid var(--color-fd-border);
|
|
736
|
+
}
|
|
737
|
+
|
|
738
|
+
.fd-feedback-content {
|
|
739
|
+
display: flex;
|
|
740
|
+
align-items: center;
|
|
741
|
+
justify-content: space-between;
|
|
742
|
+
gap: 1rem;
|
|
743
|
+
flex-wrap: wrap;
|
|
744
|
+
}
|
|
745
|
+
|
|
746
|
+
.fd-feedback-question {
|
|
747
|
+
margin: 0;
|
|
748
|
+
font-size: 0.9375rem;
|
|
749
|
+
font-weight: 600;
|
|
750
|
+
line-height: 1.5;
|
|
751
|
+
color: var(--color-fd-foreground);
|
|
752
|
+
}
|
|
753
|
+
|
|
754
|
+
.fd-feedback-actions {
|
|
755
|
+
display: inline-flex;
|
|
756
|
+
align-items: center;
|
|
757
|
+
gap: 0.5rem;
|
|
758
|
+
flex-wrap: wrap;
|
|
759
|
+
}
|
|
760
|
+
|
|
723
761
|
/* ─── Breadcrumb ─────────────────────────────────────────────────────── */
|
|
724
762
|
|
|
725
763
|
.fd-breadcrumb {
|