radiant-docs 0.1.60 → 0.1.61
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 +1 -1
- package/template/src/components/OpenApiPage.astro +161 -13
- package/template/src/components/chat/AssistantEmbedPanel.tsx +18 -7
- package/template/src/components/endpoint/PlaygroundBar.astro +54 -9
- package/template/src/components/endpoint/PlaygroundForm.astro +1 -1
- package/template/src/components/endpoint/RequestSnippets.astro +6 -1
- package/template/src/components/endpoint/ResponseFieldTree.astro +17 -13
- package/template/src/components/endpoint/ResponseFields.astro +4 -6
- package/template/src/components/endpoint/ResponseSnippets.astro +6 -1
- package/template/src/components/sidebar/SidebarEndpointLink.astro +9 -12
- package/template/src/components/sidebar/SidebarOpenApi.astro +3 -9
- package/template/src/components/ui/Field.astro +18 -15
- package/template/src/components/ui/Tag.astro +16 -2
- package/template/src/lib/utils.ts +11 -0
package/package.json
CHANGED
|
@@ -111,13 +111,29 @@ const formattedBodyDescription = bodyDescription
|
|
|
111
111
|
/>
|
|
112
112
|
)
|
|
113
113
|
}
|
|
114
|
-
<div class="xl:hidden space-y-6 mt-6">
|
|
115
|
-
<
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
114
|
+
<div data-inline-snippet-stack class="xl:hidden space-y-6 mt-6">
|
|
115
|
+
<div
|
|
116
|
+
data-snippet-slot
|
|
117
|
+
data-inline-snippet-slot
|
|
118
|
+
class="min-h-0 min-w-0 overflow-hidden transition-[height,max-height] duration-[360ms] ease-[cubic-bezier(0.22,1,0.36,1)]"
|
|
119
|
+
>
|
|
120
|
+
<RequestSnippets
|
|
121
|
+
api={api}
|
|
122
|
+
method={route.openApiMethod}
|
|
123
|
+
path={route.openApiPath}
|
|
124
|
+
/>
|
|
125
|
+
</div>
|
|
126
|
+
{
|
|
127
|
+
responses && (
|
|
128
|
+
<div
|
|
129
|
+
data-snippet-slot
|
|
130
|
+
data-inline-snippet-slot
|
|
131
|
+
class="min-h-0 min-w-0 overflow-hidden transition-[height,max-height] duration-[360ms] ease-[cubic-bezier(0.22,1,0.36,1)]"
|
|
132
|
+
>
|
|
133
|
+
<ResponseSnippets responses={responses} />
|
|
134
|
+
</div>
|
|
135
|
+
)
|
|
136
|
+
}
|
|
121
137
|
</div>
|
|
122
138
|
<div class="mt-10">
|
|
123
139
|
<!-- Request -->
|
|
@@ -157,10 +173,9 @@ const formattedBodyDescription = bodyDescription
|
|
|
157
173
|
/>
|
|
158
174
|
)}
|
|
159
175
|
{hasCommonFields && (
|
|
160
|
-
<div x-data="{ expanded:
|
|
176
|
+
<div x-data="{ expanded: true }" class="mt-4">
|
|
161
177
|
<div
|
|
162
|
-
class="w-full overflow-hidden rounded-xl border border-neutral-
|
|
163
|
-
x-bind:class="expanded ? 'border-neutral-300 dark:border-neutral-700' : 'border-neutral-200 dark:border-neutral-800'"
|
|
178
|
+
class="w-full overflow-hidden rounded-xl border-[0.5px] border-neutral-900/8 bg-white shadow-[0_.5px_1px_rgba(0,0,0,0.15),0_5px_12px_-6px_rgba(0,0,0,0.08)] transition-colors duration-200 dark:border-white/6 dark:bg-(--rd-code-surface) dark:shadow-[0_-.5px_1px_rgba(255,255,255,0.15),0_5px_12px_-6px_rgba(0,0,0,0.2)]"
|
|
164
179
|
>
|
|
165
180
|
<button
|
|
166
181
|
type="button"
|
|
@@ -201,10 +216,9 @@ const formattedBodyDescription = bodyDescription
|
|
|
201
216
|
<div class="mb-2 text-xs font-medium text-neutral-600 dark:text-neutral-400">
|
|
202
217
|
{variant.label}
|
|
203
218
|
</div>
|
|
204
|
-
<div x-data="{ expanded:
|
|
219
|
+
<div x-data="{ expanded: true }">
|
|
205
220
|
<div
|
|
206
|
-
class="w-full overflow-hidden rounded-lg border border-neutral-
|
|
207
|
-
x-bind:class="expanded ? 'border-neutral-300 dark:border-neutral-700' : 'border-neutral-200 dark:border-neutral-800'"
|
|
221
|
+
class="w-full overflow-hidden rounded-lg border-[0.5px] border-neutral-900/8 bg-white shadow-[0_.5px_1px_rgba(0,0,0,0.15),0_5px_12px_-6px_rgba(0,0,0,0.08)] transition-colors duration-200 dark:border-white/6 dark:bg-(--rd-code-surface) dark:shadow-[0_-.5px_1px_rgba(255,255,255,0.15),0_5px_12px_-6px_rgba(0,0,0,0.2)]"
|
|
208
222
|
>
|
|
209
223
|
<button
|
|
210
224
|
type="button"
|
|
@@ -485,4 +499,138 @@ const formattedBodyDescription = bodyDescription
|
|
|
485
499
|
);
|
|
486
500
|
applySlotHeights();
|
|
487
501
|
}
|
|
502
|
+
|
|
503
|
+
const inlineStack = document.querySelector("[data-inline-snippet-stack]");
|
|
504
|
+
|
|
505
|
+
if (inlineStack instanceof HTMLElement) {
|
|
506
|
+
const inlineSlots = Array.from(
|
|
507
|
+
inlineStack.querySelectorAll("[data-inline-snippet-slot]"),
|
|
508
|
+
).filter((slot) => slot instanceof HTMLElement);
|
|
509
|
+
|
|
510
|
+
const getInlineViewportHeight = () => {
|
|
511
|
+
if (window.visualViewport?.height) {
|
|
512
|
+
return Math.floor(window.visualViewport.height);
|
|
513
|
+
}
|
|
514
|
+
return Math.floor(window.innerHeight);
|
|
515
|
+
};
|
|
516
|
+
|
|
517
|
+
const getInlineSlotHeightCap = () => {
|
|
518
|
+
const viewportCap = Math.floor(getInlineViewportHeight() * 0.7);
|
|
519
|
+
return Math.max(0, Math.min(448, viewportCap));
|
|
520
|
+
};
|
|
521
|
+
|
|
522
|
+
const inlinePrefersReducedMotion =
|
|
523
|
+
typeof window.matchMedia === "function" &&
|
|
524
|
+
window.matchMedia("(prefers-reduced-motion: reduce)").matches;
|
|
525
|
+
const inlineSlotHeightTransitionMs = 360;
|
|
526
|
+
let isAnimatingInlineSlotHeights = false;
|
|
527
|
+
let inlineSlotHeightAnimationTimeoutId = null;
|
|
528
|
+
|
|
529
|
+
const resetInlineSlotHeights = () => {
|
|
530
|
+
for (const slot of inlineSlots) {
|
|
531
|
+
slot.style.height = "";
|
|
532
|
+
slot.style.maxHeight = "";
|
|
533
|
+
}
|
|
534
|
+
};
|
|
535
|
+
|
|
536
|
+
const applyInlineSlotHeights = ({ animate = false } = {}) => {
|
|
537
|
+
if (!inlineSlots.length) return;
|
|
538
|
+
if (isAnimatingInlineSlotHeights && !animate) return;
|
|
539
|
+
|
|
540
|
+
if (window.getComputedStyle(inlineStack).display === "none") {
|
|
541
|
+
resetInlineSlotHeights();
|
|
542
|
+
return;
|
|
543
|
+
}
|
|
544
|
+
|
|
545
|
+
const shouldAnimate = animate && !inlinePrefersReducedMotion;
|
|
546
|
+
const previousHeights = shouldAnimate
|
|
547
|
+
? inlineSlots.map((slot) =>
|
|
548
|
+
Math.ceil(slot.getBoundingClientRect().height),
|
|
549
|
+
)
|
|
550
|
+
: [];
|
|
551
|
+
const previousTransitions = shouldAnimate
|
|
552
|
+
? inlineSlots.map((slot) => slot.style.transition)
|
|
553
|
+
: [];
|
|
554
|
+
const heightCap = getInlineSlotHeightCap();
|
|
555
|
+
|
|
556
|
+
if (shouldAnimate) {
|
|
557
|
+
for (const slot of inlineSlots) {
|
|
558
|
+
slot.style.transition = "none";
|
|
559
|
+
}
|
|
560
|
+
}
|
|
561
|
+
|
|
562
|
+
for (const slot of inlineSlots) {
|
|
563
|
+
slot.style.height = "auto";
|
|
564
|
+
slot.style.maxHeight = "none";
|
|
565
|
+
}
|
|
566
|
+
|
|
567
|
+
const targetHeights = inlineSlots.map((slot) => {
|
|
568
|
+
const naturalHeight = Math.ceil(slot.scrollHeight);
|
|
569
|
+
return Math.min(naturalHeight, heightCap);
|
|
570
|
+
});
|
|
571
|
+
|
|
572
|
+
const setInlineSlotHeights = () => {
|
|
573
|
+
for (let i = 0; i < inlineSlots.length; i += 1) {
|
|
574
|
+
const height = targetHeights[i];
|
|
575
|
+
inlineSlots[i].style.height = `${height}px`;
|
|
576
|
+
inlineSlots[i].style.maxHeight = `${height}px`;
|
|
577
|
+
}
|
|
578
|
+
};
|
|
579
|
+
|
|
580
|
+
if (!shouldAnimate) {
|
|
581
|
+
setInlineSlotHeights();
|
|
582
|
+
return;
|
|
583
|
+
}
|
|
584
|
+
|
|
585
|
+
isAnimatingInlineSlotHeights = true;
|
|
586
|
+
if (inlineSlotHeightAnimationTimeoutId) {
|
|
587
|
+
window.clearTimeout(inlineSlotHeightAnimationTimeoutId);
|
|
588
|
+
}
|
|
589
|
+
|
|
590
|
+
for (let i = 0; i < inlineSlots.length; i += 1) {
|
|
591
|
+
const height = previousHeights[i];
|
|
592
|
+
inlineSlots[i].style.height = `${height}px`;
|
|
593
|
+
inlineSlots[i].style.maxHeight = `${height}px`;
|
|
594
|
+
}
|
|
595
|
+
|
|
596
|
+
void inlineStack.offsetHeight;
|
|
597
|
+
|
|
598
|
+
for (let i = 0; i < inlineSlots.length; i += 1) {
|
|
599
|
+
inlineSlots[i].style.transition = previousTransitions[i];
|
|
600
|
+
}
|
|
601
|
+
|
|
602
|
+
window.requestAnimationFrame(setInlineSlotHeights);
|
|
603
|
+
|
|
604
|
+
inlineSlotHeightAnimationTimeoutId = window.setTimeout(() => {
|
|
605
|
+
isAnimatingInlineSlotHeights = false;
|
|
606
|
+
inlineSlotHeightAnimationTimeoutId = null;
|
|
607
|
+
applyInlineSlotHeights();
|
|
608
|
+
}, inlineSlotHeightTransitionMs + 80);
|
|
609
|
+
};
|
|
610
|
+
|
|
611
|
+
let inlineSlotAnimationFrameId = null;
|
|
612
|
+
const scheduleInlineSlotHeights = (options = {}) => {
|
|
613
|
+
if (inlineSlotAnimationFrameId) {
|
|
614
|
+
window.cancelAnimationFrame(inlineSlotAnimationFrameId);
|
|
615
|
+
}
|
|
616
|
+
|
|
617
|
+
inlineSlotAnimationFrameId = window.requestAnimationFrame(() => {
|
|
618
|
+
inlineSlotAnimationFrameId = window.requestAnimationFrame(() => {
|
|
619
|
+
inlineSlotAnimationFrameId = null;
|
|
620
|
+
applyInlineSlotHeights(options);
|
|
621
|
+
});
|
|
622
|
+
});
|
|
623
|
+
};
|
|
624
|
+
|
|
625
|
+
const inlineResizeObserver = new ResizeObserver(scheduleInlineSlotHeights);
|
|
626
|
+
inlineResizeObserver.observe(inlineStack);
|
|
627
|
+
|
|
628
|
+
window.addEventListener("resize", scheduleInlineSlotHeights);
|
|
629
|
+
window.visualViewport?.addEventListener("resize", scheduleInlineSlotHeights);
|
|
630
|
+
window.addEventListener(
|
|
631
|
+
"rd:snippet-content-change",
|
|
632
|
+
() => scheduleInlineSlotHeights({ animate: true }),
|
|
633
|
+
);
|
|
634
|
+
scheduleInlineSlotHeights();
|
|
635
|
+
}
|
|
488
636
|
</script>
|
|
@@ -1963,7 +1963,7 @@ export default function AssistantEmbedPanel({
|
|
|
1963
1963
|
<AssistantPanelIcon
|
|
1964
1964
|
color={launcherIconColor}
|
|
1965
1965
|
imageSrc={launcherIconImageSrc}
|
|
1966
|
-
className="assistant-embed-header-icon inline-flex size-9 shrink-0 items-center justify-center rounded-md dark:border-[0.5px] border-neutral-900/7 bg-
|
|
1966
|
+
className="assistant-embed-header-icon inline-flex size-9 shrink-0 items-center justify-center rounded-md dark:border-[0.5px] border-neutral-900/7 bg-neutral-700/7 dark:bg-white/6 text-neutral-900 dark:border-white/7 dark:text-neutral-50 [&_img]:block [&_img]:size-5.5 [&_img]:object-contain [&_svg]:static [&_svg]:block [&_svg]:size-5 [&_svg]:transform-none [&_svg]:opacity-100"
|
|
1967
1967
|
/>
|
|
1968
1968
|
<div className="min-w-0 space-y-px">
|
|
1969
1969
|
<p className="truncate text-sm font-medium leading-3.5 text-neutral-900 dark:text-neutral-50">
|
|
@@ -2198,14 +2198,25 @@ export default function AssistantEmbedPanel({
|
|
|
2198
2198
|
</p>
|
|
2199
2199
|
<button
|
|
2200
2200
|
type="button"
|
|
2201
|
-
className="mt-1 inline-flex items-center gap-1.5 rounded-md border border-neutral-900/8 bg-white px-2.5 py-1.5 text-[13px] font-medium text-neutral-700 shadow-xs transition hover:bg-neutral-50 dark:border-white/10 dark:bg-white/5 dark:text-neutral-200 dark:hover:bg-white/10 cursor-pointer"
|
|
2201
|
+
className="mt-1 inline-flex items-center gap-1.5 rounded-md border border-neutral-900/8 bg-white px-2.5 py-1.5 text-[13px] font-medium text-neutral-700 shadow-xs transition hover:bg-neutral-50/80 dark:border-white/10 dark:bg-white/5 dark:text-neutral-200 dark:hover:bg-white/10 cursor-pointer"
|
|
2202
2202
|
onClick={handleUnavailableBack}
|
|
2203
2203
|
>
|
|
2204
|
-
<
|
|
2205
|
-
|
|
2206
|
-
|
|
2207
|
-
|
|
2208
|
-
|
|
2204
|
+
<svg
|
|
2205
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
2206
|
+
width="14px"
|
|
2207
|
+
height="14px"
|
|
2208
|
+
viewBox="0 0 24 24"
|
|
2209
|
+
>
|
|
2210
|
+
<path d="M0 0h24v24H0z" fill="none" />
|
|
2211
|
+
<path
|
|
2212
|
+
fill="none"
|
|
2213
|
+
stroke="currentColor"
|
|
2214
|
+
stroke-linecap="round"
|
|
2215
|
+
stroke-linejoin="round"
|
|
2216
|
+
stroke-width="2"
|
|
2217
|
+
d="m12 19l-7-7l7-7m7 7H5"
|
|
2218
|
+
/>
|
|
2219
|
+
</svg>
|
|
2209
2220
|
Back
|
|
2210
2221
|
</button>
|
|
2211
2222
|
</div>
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
import { Icon } from "astro-icon/components";
|
|
3
|
-
import {
|
|
3
|
+
import { methodTagColors } from "../../lib/utils";
|
|
4
4
|
import type { OpenApiRoute } from "../../lib/routes";
|
|
5
5
|
|
|
6
6
|
interface Props {
|
|
@@ -9,18 +9,26 @@ interface Props {
|
|
|
9
9
|
}
|
|
10
10
|
|
|
11
11
|
const { route, serverUrl } = Astro.props;
|
|
12
|
+
const methodColor =
|
|
13
|
+
methodTagColors[route.openApiMethod.toLowerCase()] ?? methodTagColors.get;
|
|
14
|
+
|
|
15
|
+
const pathParts = route.openApiPath
|
|
16
|
+
.split(/(\{[^}]+\})/g)
|
|
17
|
+
.filter(Boolean)
|
|
18
|
+
.map((text) => ({
|
|
19
|
+
text,
|
|
20
|
+
isParam: text.startsWith("{") && text.endsWith("}"),
|
|
21
|
+
}));
|
|
12
22
|
---
|
|
13
23
|
|
|
14
24
|
<div
|
|
15
|
-
class="min-w-0 flex-1 flex items-center p-1 border border-neutral-
|
|
25
|
+
class="min-w-0 flex-1 flex items-center p-1 border-[0.5px] border-neutral-900/8 bg-white rounded-xl shadow-[0_.5px_1px_rgba(0,0,0,0.15),0_5px_12px_-6px_rgba(0,0,0,0.08)] overflow-hidden dark:border-white/6 dark:bg-(--rd-code-surface) dark:shadow-[0_-.5px_1px_rgba(255,255,255,0.15),0_5px_12px_-6px_rgba(0,0,0,0.2)]"
|
|
16
26
|
>
|
|
17
27
|
<span
|
|
18
|
-
class
|
|
19
|
-
|
|
20
|
-
methodColors[route.openApiMethod.toLowerCase()] || methodColors.get,
|
|
21
|
-
]}
|
|
28
|
+
class="rd-endpoint-method-tag shrink-0 inline-block px-1.5 ml-1 text-sm font-semibold rounded-md uppercase border"
|
|
29
|
+
style={`--rd-tag-color-light:${methodColor};--rd-tag-color-dark:${methodColor};`}
|
|
22
30
|
>
|
|
23
|
-
{route.openApiMethod}
|
|
31
|
+
{route.openApiMethod.toUpperCase()}
|
|
24
32
|
</span>
|
|
25
33
|
<code
|
|
26
34
|
class="group flex-1 mx-2 h-[30px] flex items-center text-[13px] text-neutral-600 dark:text-neutral-300 min-w-0 relative cursor-pointer"
|
|
@@ -41,8 +49,23 @@ const { route, serverUrl } = Astro.props;
|
|
|
41
49
|
}
|
|
42
50
|
}`
|
|
43
51
|
>
|
|
44
|
-
<span
|
|
45
|
-
|
|
52
|
+
<span
|
|
53
|
+
class="flex min-w-0 flex-1 items-center overflow-hidden whitespace-nowrap"
|
|
54
|
+
>
|
|
55
|
+
{
|
|
56
|
+
pathParts.map((part) =>
|
|
57
|
+
part.isParam ? (
|
|
58
|
+
<span
|
|
59
|
+
class="rd-endpoint-path-param inline-block rounded-sm border p-px leading-none"
|
|
60
|
+
style={`--rd-tag-color-light:${methodColor};--rd-tag-color-dark:${methodColor};`}
|
|
61
|
+
>
|
|
62
|
+
{part.text}
|
|
63
|
+
</span>
|
|
64
|
+
) : (
|
|
65
|
+
<span>{part.text}</span>
|
|
66
|
+
),
|
|
67
|
+
)
|
|
68
|
+
}
|
|
46
69
|
</span>
|
|
47
70
|
<div
|
|
48
71
|
class="absolute right-0 top-1/2 -translate-y-1/2 flex items-center gap-1 text-[12px] px-1.5 py-px bg-white border border-neutral-200 rounded-md duration-200 opacity-0 scale-75 group-hover:scale-100 group-hover:opacity-100 group-hover:duration-200 group-hover:ease-out group-hover:delay-75 dark:border-neutral-700 dark:bg-neutral-900 dark:text-neutral-300"
|
|
@@ -62,3 +85,25 @@ const { route, serverUrl } = Astro.props;
|
|
|
62
85
|
</code>
|
|
63
86
|
<slot />
|
|
64
87
|
</div>
|
|
88
|
+
|
|
89
|
+
<style>
|
|
90
|
+
.rd-endpoint-method-tag,
|
|
91
|
+
.rd-endpoint-path-param {
|
|
92
|
+
--rd-tag-color: var(--rd-tag-color-light, var(--color-theme));
|
|
93
|
+
background-color: color-mix(in oklab, var(--rd-tag-color) 8%, transparent);
|
|
94
|
+
border-color: color-mix(in oklab, var(--rd-tag-color) 0%, transparent);
|
|
95
|
+
color: color-mix(in oklab, var(--rd-tag-color) 95%, transparent);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
:global(.dark) .rd-endpoint-method-tag,
|
|
99
|
+
:global(.dark) .rd-endpoint-path-param,
|
|
100
|
+
:global([data-theme="dark"]) .rd-endpoint-method-tag,
|
|
101
|
+
:global([data-theme="dark"]) .rd-endpoint-path-param {
|
|
102
|
+
--rd-tag-color: var(
|
|
103
|
+
--rd-tag-color-dark,
|
|
104
|
+
var(--rd-tag-color-light, var(--color-theme))
|
|
105
|
+
);
|
|
106
|
+
background-color: color-mix(in oklab, var(--rd-tag-color) 12%, transparent);
|
|
107
|
+
color: color-mix(in oklab, var(--rd-tag-color) 85%, transparent);
|
|
108
|
+
}
|
|
109
|
+
</style>
|
|
@@ -587,7 +587,7 @@ const sectionVariantFieldNames = Object.fromEntries(
|
|
|
587
587
|
}
|
|
588
588
|
|
|
589
589
|
return (
|
|
590
|
-
<div class="border border-neutral-
|
|
590
|
+
<div class="border-[0.5px] border-neutral-900/8 bg-white shadow-[0_.5px_1px_rgba(0,0,0,0.15),0_5px_12px_-6px_rgba(0,0,0,0.08)] rounded-xl p-4 pb-0 dark:border-white/6 dark:bg-(--rd-code-surface) dark:shadow-[0_-.5px_1px_rgba(255,255,255,0.15),0_5px_12px_-6px_rgba(0,0,0,0.2)] [&_[role='region']]:border-b-0">
|
|
591
591
|
<Accordion title={headers[key]} defaultOpen titleSize="xl">
|
|
592
592
|
{key === "body" && formattedBodyDescription && (
|
|
593
593
|
<div
|
|
@@ -593,7 +593,12 @@ const hasMultipleRequests = requestSnippetItems.length > 1;
|
|
|
593
593
|
</div>
|
|
594
594
|
</div>
|
|
595
595
|
|
|
596
|
-
<div
|
|
596
|
+
<div
|
|
597
|
+
class:list={[
|
|
598
|
+
"relative min-h-0 min-w-0 flex-1 overflow-hidden rounded-b-xl border-[0.5px] border-(--rd-code-tab-edge-border) bg-(--rd-code-surface)",
|
|
599
|
+
hasMultipleRequests && "rounded-tl-xl",
|
|
600
|
+
]}
|
|
601
|
+
>
|
|
597
602
|
<div
|
|
598
603
|
x-ref="snippetPanels"
|
|
599
604
|
class="relative h-full overflow-auto transition-[height] motion-reduce:transition-none [scrollbar-width:thin] [scrollbar-color:var(--color-neutral-300)_transparent] [&::-webkit-scrollbar]:h-1.5 [&::-webkit-scrollbar]:w-1.5 [&::-webkit-scrollbar-track]:bg-transparent [&::-webkit-scrollbar-thumb]:rounded-full [&::-webkit-scrollbar-thumb]:bg-neutral-300/70 hover:[&::-webkit-scrollbar-thumb]:bg-neutral-300/90 dark:[scrollbar-color:var(--color-neutral-700)_transparent] dark:[&::-webkit-scrollbar-thumb]:bg-neutral-700/70 dark:hover:[&::-webkit-scrollbar-thumb]:bg-neutral-700/90"
|
|
@@ -46,7 +46,9 @@ function countImmediateChildren(field: ResponseField): number {
|
|
|
46
46
|
}
|
|
47
47
|
---
|
|
48
48
|
|
|
49
|
-
<div
|
|
49
|
+
<div
|
|
50
|
+
class="flex flex-col gap-4 divide-y divide-neutral-100 dark:divide-neutral-800 *:pb-3 *:last:pb-0"
|
|
51
|
+
>
|
|
50
52
|
{
|
|
51
53
|
fields.map((field) => {
|
|
52
54
|
const revealedFieldCount = countImmediateChildren(field);
|
|
@@ -69,10 +71,7 @@ function countImmediateChildren(field: ResponseField): number {
|
|
|
69
71
|
exclusiveMaximum={field.exclusiveMaximum}
|
|
70
72
|
/>
|
|
71
73
|
{hasExpandableContent && (
|
|
72
|
-
<div
|
|
73
|
-
class="mt-2 w-full overflow-hidden rounded-lg border border-neutral-200 bg-white transition-colors duration-200 dark:border-neutral-800 dark:bg-(--rd-code-surface)"
|
|
74
|
-
x-bind:class="expanded ? 'border-neutral-300 dark:border-neutral-700' : 'border-neutral-200 dark:border-neutral-800'"
|
|
75
|
-
>
|
|
74
|
+
<div class="mt-2.5 w-full overflow-hidden rounded-lg border-[0.5px] border-neutral-900/8 bg-white shadow-[0_.5px_1px_rgba(0,0,0,0.15),0_5px_12px_-6px_rgba(0,0,0,0.08)] transition-colors duration-200 dark:border-white/6 dark:bg-(--rd-code-surface) dark:shadow-[0_-.5px_1px_rgba(255,255,255,0.15),0_5px_12px_-6px_rgba(0,0,0,0.2)]">
|
|
76
75
|
<button
|
|
77
76
|
type="button"
|
|
78
77
|
x-on:click="expanded = !expanded"
|
|
@@ -83,19 +82,21 @@ function countImmediateChildren(field: ResponseField): number {
|
|
|
83
82
|
<ListChevronsToggle class="size-4 shrink-0 text-neutral-400 group-hover:text-neutral-600 transition duration-200 dark:text-neutral-500 dark:group-hover:text-neutral-300" />
|
|
84
83
|
<span>
|
|
85
84
|
{revealedFieldCount}{" "}
|
|
86
|
-
{revealedFieldCount === 1
|
|
87
|
-
? "field"
|
|
88
|
-
: "fields"}
|
|
85
|
+
{revealedFieldCount === 1 ? "field" : "fields"}
|
|
89
86
|
</span>
|
|
90
87
|
</span>
|
|
91
88
|
</button>
|
|
92
89
|
<div x-show="expanded" x-collapse x-cloak>
|
|
93
90
|
<div class="border-t border-neutral-100 px-3 py-3 dark:border-neutral-800">
|
|
94
|
-
{field.nested &&
|
|
95
|
-
|
|
96
|
-
|
|
91
|
+
{field.nested &&
|
|
92
|
+
field.nested.length > 0 &&
|
|
93
|
+
nestedFieldCount > 0 && (
|
|
94
|
+
<Astro.self fields={field.nested} depth={depth + 1} />
|
|
95
|
+
)}
|
|
97
96
|
{field.variants && field.variants.length > 0 && (
|
|
98
|
-
<div
|
|
97
|
+
<div
|
|
98
|
+
class:list={["space-y-2", nestedFieldCount > 0 && "mt-3"]}
|
|
99
|
+
>
|
|
99
100
|
<p class="text-xs text-neutral-500 dark:text-neutral-400">
|
|
100
101
|
{field.variantType === "anyOf"
|
|
101
102
|
? "One or more variants may apply."
|
|
@@ -107,7 +108,10 @@ function countImmediateChildren(field: ResponseField): number {
|
|
|
107
108
|
<div class="mb-2 text-xs font-medium text-neutral-600 dark:text-neutral-400">
|
|
108
109
|
{variant.label}
|
|
109
110
|
</div>
|
|
110
|
-
<Astro.self
|
|
111
|
+
<Astro.self
|
|
112
|
+
fields={variant.fields}
|
|
113
|
+
depth={depth + 1}
|
|
114
|
+
/>
|
|
111
115
|
</div>
|
|
112
116
|
{field.variantType === "oneOf" &&
|
|
113
117
|
index < field.variants.length - 1 && (
|
|
@@ -771,10 +771,9 @@ Object.entries(responses)
|
|
|
771
771
|
{response.variants && response.variants.length > 0 && (
|
|
772
772
|
<p class="mb-2 text-xs text-neutral-500 dark:text-neutral-400">Common fields</p>
|
|
773
773
|
)}
|
|
774
|
-
<div x-data="{ expanded:
|
|
774
|
+
<div x-data="{ expanded: true }">
|
|
775
775
|
<div
|
|
776
|
-
class="w-full overflow-hidden rounded-xl border border-neutral-
|
|
777
|
-
x-bind:class="expanded ? 'border-neutral-300 dark:border-neutral-700' : 'border-neutral-200 dark:border-neutral-800'"
|
|
776
|
+
class="w-full overflow-hidden rounded-xl border-[0.5px] border-neutral-900/8 bg-white shadow-[0_.5px_1px_rgba(0,0,0,0.15),0_5px_12px_-6px_rgba(0,0,0,0.08)] transition-colors duration-200 dark:border-white/6 dark:bg-(--rd-code-surface) dark:shadow-[0_-.5px_1px_rgba(255,255,255,0.15),0_5px_12px_-6px_rgba(0,0,0,0.2)]"
|
|
778
777
|
>
|
|
779
778
|
<button
|
|
780
779
|
type="button"
|
|
@@ -814,10 +813,9 @@ Object.entries(responses)
|
|
|
814
813
|
<div class="mb-2 text-xs font-medium text-neutral-600 dark:text-neutral-400">
|
|
815
814
|
{variant.label}
|
|
816
815
|
</div>
|
|
817
|
-
<div x-data="{ expanded:
|
|
816
|
+
<div x-data="{ expanded: true }">
|
|
818
817
|
<div
|
|
819
|
-
class="w-full overflow-hidden rounded-lg border border-neutral-
|
|
820
|
-
x-bind:class="expanded ? 'border-neutral-300 dark:border-neutral-700' : 'border-neutral-200 dark:border-neutral-800'"
|
|
818
|
+
class="w-full overflow-hidden rounded-lg border-[0.5px] border-neutral-900/8 bg-white shadow-[0_.5px_1px_rgba(0,0,0,0.15),0_5px_12px_-6px_rgba(0,0,0,0.08)] transition-colors duration-200 dark:border-white/6 dark:bg-(--rd-code-surface) dark:shadow-[0_-.5px_1px_rgba(255,255,255,0.15),0_5px_12px_-6px_rgba(0,0,0,0.2)]"
|
|
821
819
|
>
|
|
822
820
|
<button
|
|
823
821
|
type="button"
|
|
@@ -513,7 +513,12 @@ const hasMultipleResponses = responseSnippetItems.length > 1;
|
|
|
513
513
|
</div>
|
|
514
514
|
</div>
|
|
515
515
|
|
|
516
|
-
<div
|
|
516
|
+
<div
|
|
517
|
+
class:list={[
|
|
518
|
+
"relative min-h-0 min-w-0 flex-1 overflow-hidden rounded-b-xl border-[0.5px] border-(--rd-code-tab-edge-border) bg-(--rd-code-surface)",
|
|
519
|
+
hasMultipleResponses && "rounded-tl-xl",
|
|
520
|
+
]}
|
|
521
|
+
>
|
|
517
522
|
<div
|
|
518
523
|
x-ref="snippetPanels"
|
|
519
524
|
class="relative h-full overflow-auto transition-[height] motion-reduce:transition-none [scrollbar-width:thin] [scrollbar-color:var(--color-neutral-300)_transparent] [&::-webkit-scrollbar]:h-1.5 [&::-webkit-scrollbar]:w-1.5 [&::-webkit-scrollbar-track]:bg-transparent [&::-webkit-scrollbar-thumb]:rounded-full [&::-webkit-scrollbar-thumb]:bg-neutral-300/70 hover:[&::-webkit-scrollbar-thumb]:bg-neutral-300/90 dark:[scrollbar-color:var(--color-neutral-700)_transparent] dark:[&::-webkit-scrollbar-thumb]:bg-neutral-700/70 dark:hover:[&::-webkit-scrollbar-thumb]:bg-neutral-700/90"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
import Tag from "../ui/Tag.astro";
|
|
3
|
-
import {
|
|
3
|
+
import { methodTagColors } from "../../lib/utils";
|
|
4
4
|
import { getOpenApiEndpointRouteHref } from "../../lib/routes";
|
|
5
5
|
import type { NavTag } from "../../lib/validation";
|
|
6
6
|
|
|
@@ -34,6 +34,10 @@ const href = await getOpenApiEndpointRouteHref({
|
|
|
34
34
|
|
|
35
35
|
// Use summary for title, fallback to method + path
|
|
36
36
|
const text = title || summary || `${normalizedMethod.toUpperCase()} ${pathStr}`;
|
|
37
|
+
const methodLabel = (
|
|
38
|
+
normalizedMethod !== "delete" ? normalizedMethod : "del"
|
|
39
|
+
).toUpperCase();
|
|
40
|
+
const methodColor = methodTagColors[normalizedMethod] ?? methodTagColors.get;
|
|
37
41
|
|
|
38
42
|
// Normalize paths for comparison (remove trailing slashes)
|
|
39
43
|
const currentPath = Astro.url.pathname.replace(/\/$/, "");
|
|
@@ -44,22 +48,15 @@ const isActive = currentPath === targetPath;
|
|
|
44
48
|
<a
|
|
45
49
|
href={href}
|
|
46
50
|
class:list={[
|
|
47
|
-
"flex items-center px-2 py-[7px] text-sm relative z-0 before:-z-10 before:absolute before:inset-x-0 before:inset-y-px before:rounded-md before:duration-150",
|
|
51
|
+
"flex items-center gap-2 px-2 py-[7px] text-sm relative z-0 before:-z-10 before:absolute before:inset-x-0 before:inset-y-px before:rounded-md before:duration-150",
|
|
48
52
|
isActive
|
|
49
53
|
? "before:bg-neutral-200/50 dark:before:bg-neutral-800 text-neutral-900 dark:text-neutral-200"
|
|
50
54
|
: "text-neutral-600 dark:text-neutral-400 hover:before:bg-neutral-100/70 dark:hover:before:bg-neutral-800/50 hover:text-neutral-900 dark:hover:text-neutral-300",
|
|
51
55
|
]}
|
|
52
56
|
>
|
|
53
|
-
<
|
|
54
|
-
class
|
|
55
|
-
"px-1 py-px mr-1.5 border rounded-md text-[10px] font-semibold uppercase",
|
|
56
|
-
methodColors[normalizedMethod] ?? methodColors.get,
|
|
57
|
-
]}
|
|
58
|
-
>
|
|
59
|
-
{normalizedMethod !== "delete" ? normalizedMethod : "del"}
|
|
60
|
-
</span>
|
|
61
|
-
<div class="flex items-center gap-2 min-w-0">
|
|
62
|
-
<span>{text}</span>
|
|
57
|
+
<div class="flex min-w-0 flex-1 items-center gap-2">
|
|
58
|
+
<span class="min-w-0 truncate">{text}</span>
|
|
63
59
|
{tag && <Tag tag={tag} />}
|
|
64
60
|
</div>
|
|
61
|
+
<Tag color={methodColor}>{methodLabel}</Tag>
|
|
65
62
|
</a>
|
|
@@ -31,7 +31,7 @@ const openApiDoc = await loadOpenApiSpec(openApiPath);
|
|
|
31
31
|
|
|
32
32
|
// Helper function to parse endpoint string
|
|
33
33
|
function parseEndpointString(
|
|
34
|
-
endpointStr: string
|
|
34
|
+
endpointStr: string,
|
|
35
35
|
): { method: string; path: string } | null {
|
|
36
36
|
const trimmed = endpointStr.trim();
|
|
37
37
|
const parts = trimmed.split(/\s+/);
|
|
@@ -57,7 +57,7 @@ function shouldIncludeEndpoint(
|
|
|
57
57
|
method: string,
|
|
58
58
|
pathStr: string,
|
|
59
59
|
include?: string[],
|
|
60
|
-
exclude?: string[]
|
|
60
|
+
exclude?: string[],
|
|
61
61
|
): boolean {
|
|
62
62
|
const normalizedMethod = method.toUpperCase();
|
|
63
63
|
const normalizedPath = pathStr.toLowerCase();
|
|
@@ -168,13 +168,7 @@ const sortedTagGroups: TagGroup[] = Array.from(tagGroups.entries())
|
|
|
168
168
|
// If there are tagged groups, render them (including "Other" if it exists)
|
|
169
169
|
hasTaggedGroups
|
|
170
170
|
? sortedTagGroups.map((group, index) => (
|
|
171
|
-
<li
|
|
172
|
-
class={
|
|
173
|
-
index > 0
|
|
174
|
-
? "mt-5 pt-[25px] relative before:absolute before:top-0 before:inset-x-0 before:h-px before:bg-linear-[90deg,transparent,var(--color-neutral-200)_20%,var(--color-neutral-200)_80%,transparent] dark:before:bg-linear-[90deg,transparent,var(--color-neutral-700)_20%,var(--color-neutral-700)_80%,transparent]"
|
|
175
|
-
: ""
|
|
176
|
-
}
|
|
177
|
-
>
|
|
171
|
+
<li class="my-8 first:mt-0 last:mb-0">
|
|
178
172
|
<div class="text-sm font-semibold mb-2 flex items-center gap-2 px-2">
|
|
179
173
|
{group.tag}
|
|
180
174
|
</div>
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
---
|
|
2
|
-
import { renderMarkdown } from "../../lib/utils";
|
|
2
|
+
import { methodTagColors, renderMarkdown } from "../../lib/utils";
|
|
3
|
+
import Tag from "./Tag.astro";
|
|
3
4
|
|
|
4
5
|
interface Props {
|
|
5
6
|
name: string;
|
|
@@ -73,6 +74,9 @@ if (hasMinLength && hasMaxLength) {
|
|
|
73
74
|
} else if (hasMaxLength) {
|
|
74
75
|
stringLengthLabel = `length <= ${maxLength}`;
|
|
75
76
|
}
|
|
77
|
+
|
|
78
|
+
const codeChipClass =
|
|
79
|
+
"mx-px px-[5px] pr-1 bg-neutral-100/80 text-neutral-700/90 rounded-sm leading-none font-mono font-normal border border-neutral-900/4 after:hidden before:hidden dark:bg-neutral-800/90 dark:text-neutral-200/90 dark:border-white/3";
|
|
76
80
|
---
|
|
77
81
|
|
|
78
82
|
<div class="space-y-3">
|
|
@@ -80,15 +84,14 @@ if (hasMinLength && hasMaxLength) {
|
|
|
80
84
|
<span class="font-medium leading-4">
|
|
81
85
|
{name}
|
|
82
86
|
</span>
|
|
83
|
-
<code
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
>
|
|
87
|
+
<code class:list={["text-[10px] py-[1.5px]", codeChipClass]}>
|
|
88
|
+
{type}
|
|
89
|
+
</code>
|
|
87
90
|
{
|
|
88
91
|
required && (
|
|
89
|
-
<
|
|
92
|
+
<Tag color={methodTagColors.delete} class="text-[10px]!">
|
|
90
93
|
required
|
|
91
|
-
</
|
|
94
|
+
</Tag>
|
|
92
95
|
)
|
|
93
96
|
}
|
|
94
97
|
{
|
|
@@ -114,14 +117,14 @@ if (hasMinLength && hasMaxLength) {
|
|
|
114
117
|
<span class="font-medium text-xs">Options:</span>
|
|
115
118
|
{enumValues.map((v, i, a) => {
|
|
116
119
|
return (
|
|
117
|
-
<div class="flex">
|
|
118
|
-
<
|
|
119
|
-
|
|
120
|
-
</
|
|
120
|
+
<div class="inline-flex items-center leading-none">
|
|
121
|
+
<code class:list={["text-[11px] py-[2px]", codeChipClass]}>
|
|
122
|
+
{v}
|
|
123
|
+
</code>
|
|
121
124
|
{a.length - 2 === i ? (
|
|
122
|
-
<span class="ml-1"> or </span>
|
|
125
|
+
<span class="ml-1 leading-none"> or </span>
|
|
123
126
|
) : (
|
|
124
|
-
a.length - 1 !== i && <span>, </span>
|
|
127
|
+
a.length - 1 !== i && <span class="leading-none">, </span>
|
|
125
128
|
)}
|
|
126
129
|
</div>
|
|
127
130
|
);
|
|
@@ -133,7 +136,7 @@ if (hasMinLength && hasMaxLength) {
|
|
|
133
136
|
numericRangeLabel && (
|
|
134
137
|
<div class="text-sm">
|
|
135
138
|
<span class="font-medium text-xs">Range:</span>
|
|
136
|
-
<code class="text-[11px]
|
|
139
|
+
<code class:list={["text-[11px]", codeChipClass]}>
|
|
137
140
|
{numericRangeLabel}
|
|
138
141
|
</code>
|
|
139
142
|
</div>
|
|
@@ -143,7 +146,7 @@ if (hasMinLength && hasMaxLength) {
|
|
|
143
146
|
stringLengthLabel && (
|
|
144
147
|
<div class="text-sm">
|
|
145
148
|
<span class="font-medium text-xs">Length:</span>
|
|
146
|
-
<code class="text-[11px]
|
|
149
|
+
<code class:list={["text-[11px]", codeChipClass]}>
|
|
147
150
|
{stringLengthLabel}
|
|
148
151
|
</code>
|
|
149
152
|
</div>
|
|
@@ -8,9 +8,10 @@ import {
|
|
|
8
8
|
interface Props {
|
|
9
9
|
tag?: NavTag;
|
|
10
10
|
color?: string | ThemeColorByMode;
|
|
11
|
+
class?: string;
|
|
11
12
|
}
|
|
12
13
|
|
|
13
|
-
const { tag, color } = Astro.props;
|
|
14
|
+
const { tag, color, class: className } = Astro.props;
|
|
14
15
|
const config = await getConfig();
|
|
15
16
|
|
|
16
17
|
function getTagText(value: NavTag | undefined): string | undefined {
|
|
@@ -51,7 +52,10 @@ const colorStyle = resolvedColor
|
|
|
51
52
|
---
|
|
52
53
|
|
|
53
54
|
<span
|
|
54
|
-
class=
|
|
55
|
+
class:list={[
|
|
56
|
+
"rd-tag text-[9px] border px-[5px] py-[2px] rounded-full tracking-wide leading-none font-medium shrink-0",
|
|
57
|
+
className,
|
|
58
|
+
]}
|
|
55
59
|
style={colorStyle}
|
|
56
60
|
>
|
|
57
61
|
{text ? text : <slot />}
|
|
@@ -64,4 +68,14 @@ const colorStyle = resolvedColor
|
|
|
64
68
|
border-color: color-mix(in oklab, var(--rd-tag-color) 0%, transparent);
|
|
65
69
|
color: color-mix(in oklab, var(--rd-tag-color) 95%, transparent);
|
|
66
70
|
}
|
|
71
|
+
|
|
72
|
+
:global(.dark) .rd-tag,
|
|
73
|
+
:global([data-theme="dark"]) .rd-tag {
|
|
74
|
+
--rd-tag-color: var(
|
|
75
|
+
--rd-tag-color-dark,
|
|
76
|
+
var(--rd-tag-color-light, var(--color-theme))
|
|
77
|
+
);
|
|
78
|
+
background-color: color-mix(in oklab, var(--rd-tag-color) 12%, transparent);
|
|
79
|
+
color: color-mix(in oklab, var(--rd-tag-color) 85%, transparent);
|
|
80
|
+
}
|
|
67
81
|
</style>
|
|
@@ -44,6 +44,17 @@ export const methodColors: Record<string, string> = {
|
|
|
44
44
|
"bg-red-50 dark:bg-red-900 text-red-700/70 dark:text-red-700/10 border-red-700/10",
|
|
45
45
|
};
|
|
46
46
|
|
|
47
|
+
export const methodTagColors: Record<string, string> = {
|
|
48
|
+
get: "#1d4ed8",
|
|
49
|
+
post: "#15803d",
|
|
50
|
+
put: "#c2410c",
|
|
51
|
+
patch: "#a16207",
|
|
52
|
+
delete: "#b91c1c",
|
|
53
|
+
head: "#4338ca",
|
|
54
|
+
options: "#7e22ce",
|
|
55
|
+
trace: "#3f3f46",
|
|
56
|
+
};
|
|
57
|
+
|
|
47
58
|
export function deriveTitleFromEntryId(filePath: string): string {
|
|
48
59
|
const filename = path.basename(filePath);
|
|
49
60
|
const raw = filename.replace(/\.(md|mdx)$/i, "");
|