radiant-docs 0.1.48 → 0.1.49
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/LogoLink.astro +2 -2
- package/template/src/components/endpoint/RequestSnippets.astro +30 -12
- package/template/src/components/endpoint/ResponseDisplay.astro +8 -9
- package/template/src/components/endpoint/ResponseSnippets.astro +27 -9
- package/template/src/components/user/Accordion.astro +18 -4
- package/template/src/components/user/CodeBlock.astro +14 -4
- package/template/src/components/user/CodeGroup.astro +28 -11
- package/template/src/components/user/ComponentPreviewBlock.astro +32 -24
- package/template/src/components/user/Image.astro +88 -24
- package/template/src/components/user/Step.astro +2 -2
- package/template/src/components/user/Tabs.astro +59 -27
- package/template/src/styles/global.css +3 -6
package/package.json
CHANGED
|
@@ -64,7 +64,7 @@ const darkLogoContainerStyle = `padding-top: ${darkLogo.paddingTop}px; padding-b
|
|
|
64
64
|
|
|
65
65
|
<a
|
|
66
66
|
href={logoHref}
|
|
67
|
-
class="h-full flex items-center justify-center gap-2 lg:gap-
|
|
67
|
+
class="h-full flex items-center justify-center gap-2 lg:gap-2.5 text-xl font-bold text-neutral-800 dark:text-neutral-100 overflow-hidden"
|
|
68
68
|
>
|
|
69
69
|
{
|
|
70
70
|
lightLogoUrl || darkLogoUrl ? (
|
|
@@ -95,7 +95,7 @@ const darkLogoContainerStyle = `padding-top: ${darkLogo.paddingTop}px; padding-b
|
|
|
95
95
|
logoPillText && (
|
|
96
96
|
<span
|
|
97
97
|
class:list={[
|
|
98
|
-
"text-[10px] text-neutral-500 font-
|
|
98
|
+
"text-[10px] text-neutral-500 dark:text-neutral-400 font-normal bg-neutral-100 dark:bg-neutral-800 px-2 py-px rounded-full border-[0.5px] border-neutral-900/8 dark:border-neutral-50/8",
|
|
99
99
|
]}
|
|
100
100
|
>
|
|
101
101
|
{logoPillText}
|
|
@@ -325,13 +325,26 @@ const hasMultipleRequests = requestSnippetItems.length > 1;
|
|
|
325
325
|
isTransitioning: false,
|
|
326
326
|
isManagedSlot: false,
|
|
327
327
|
transitionDirection: 1,
|
|
328
|
-
transitionDurationMs:
|
|
328
|
+
transitionDurationMs: 400,
|
|
329
329
|
transitionEasing: "cubic-bezier(0.22, 1, 0.36, 1)",
|
|
330
330
|
tabSyncHandler: null,
|
|
331
331
|
transitionTimeoutId: null,
|
|
332
332
|
copyTimeoutId: null,
|
|
333
|
+
readMotionTokens() {
|
|
334
|
+
const styles = window.getComputedStyle(document.documentElement);
|
|
335
|
+
const configuredDurationMs = Number.parseFloat(
|
|
336
|
+
styles.getPropertyValue("--rd-panel-transition-duration-ms"),
|
|
337
|
+
);
|
|
338
|
+
this.transitionDurationMs = Number.isFinite(configuredDurationMs)
|
|
339
|
+
? configuredDurationMs
|
|
340
|
+
: this.transitionDurationMs;
|
|
341
|
+
this.transitionEasing =
|
|
342
|
+
styles.getPropertyValue("--rd-panel-transition-easing").trim() ||
|
|
343
|
+
this.transitionEasing;
|
|
344
|
+
},
|
|
333
345
|
init() {
|
|
334
346
|
this.isManagedSlot = !!this.$root?.closest("[data-snippet-slot]");
|
|
347
|
+
this.readMotionTokens();
|
|
335
348
|
if (
|
|
336
349
|
typeof window.matchMedia === "function" &&
|
|
337
350
|
window.matchMedia("(prefers-reduced-motion: reduce)").matches
|
|
@@ -348,6 +361,8 @@ const hasMultipleRequests = requestSnippetItems.length > 1;
|
|
|
348
361
|
if (this.$refs.snippetPanels) {
|
|
349
362
|
this.$refs.snippetPanels.style.transitionDuration =
|
|
350
363
|
this.transitionDurationMs + "ms";
|
|
364
|
+
this.$refs.snippetPanels.style.transitionTimingFunction =
|
|
365
|
+
this.transitionEasing;
|
|
351
366
|
}
|
|
352
367
|
this.syncPill();
|
|
353
368
|
this.syncSnippetHeight();
|
|
@@ -492,18 +507,18 @@ const hasMultipleRequests = requestSnippetItems.length > 1;
|
|
|
492
507
|
class="flex h-full min-h-0 w-full max-w-full min-w-0 flex-col rounded-xl"
|
|
493
508
|
>
|
|
494
509
|
<div
|
|
495
|
-
class="flex items-center justify-between gap-2
|
|
510
|
+
class="flex items-center justify-between gap-2"
|
|
496
511
|
>
|
|
497
512
|
{
|
|
498
513
|
hasMultipleRequests ? (
|
|
499
514
|
<div class="min-w-0 flex-1 overflow-hidden rounded-t-xl">
|
|
500
515
|
<div
|
|
501
516
|
x-ref="tabList"
|
|
502
|
-
class="relative flex min-w-0 items-end gap-1 overflow-x-auto pl-1 pr-8 [scrollbar-width:none] [&::-webkit-scrollbar]:hidden"
|
|
517
|
+
class="relative flex min-w-0 items-end gap-1 overflow-x-auto overscroll-x-contain pl-1 pr-8 [scrollbar-width:none] [&::-webkit-scrollbar]:hidden"
|
|
503
518
|
>
|
|
504
519
|
<div
|
|
505
520
|
aria-hidden="true"
|
|
506
|
-
class="pointer-events-none absolute top-
|
|
521
|
+
class="pointer-events-none absolute top-0 z-0 h-[28px] rounded-[9px] border-[0.5px] border-(--rd-code-tab-edge-border) bg-(--rd-code-surface) transition-[left,width,opacity] duration-200 ease-out"
|
|
507
522
|
x-bind:class="pillVisible ? 'opacity-100' : 'opacity-0'"
|
|
508
523
|
x-bind:style="'left:' + pillLeft + 'px;width:' + pillWidth + 'px;'"
|
|
509
524
|
/>
|
|
@@ -516,15 +531,17 @@ const hasMultipleRequests = requestSnippetItems.length > 1;
|
|
|
516
531
|
type="button"
|
|
517
532
|
x-bind:data-rd-snippet-tab="index"
|
|
518
533
|
x-on:click="select(index)"
|
|
519
|
-
class="relative z-10 inline-flex h-9 items-
|
|
534
|
+
class="relative z-10 inline-flex h-9 items-start border-0 bg-transparent px-3 py-0 text-xs font-medium transition-colors duration-150 focus:outline-none focus-visible:outline-none cursor-pointer"
|
|
520
535
|
x-bind:class="selected === index ? 'text-foreground' : 'text-muted-foreground'"
|
|
521
536
|
>
|
|
522
|
-
<span
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
537
|
+
<span class="pointer-events-none inline-flex h-[28px] items-center gap-2">
|
|
538
|
+
<span
|
|
539
|
+
x-show="snippet.iconSvg"
|
|
540
|
+
x-html="snippet.iconSvg"
|
|
541
|
+
class="inline-flex size-3.5 shrink-0 items-center rounded-[4px] transition-opacity duration-150"
|
|
542
|
+
x-bind:class="selected === index ? 'opacity-100' : 'opacity-70'"></span>
|
|
543
|
+
<span class="whitespace-pre leading-none" x-text="snippet.label"></span>
|
|
544
|
+
</span>
|
|
528
545
|
</button>
|
|
529
546
|
</template>
|
|
530
547
|
</div>
|
|
@@ -579,7 +596,8 @@ const hasMultipleRequests = requestSnippetItems.length > 1;
|
|
|
579
596
|
<div class="relative min-h-0 min-w-0 flex-1 overflow-hidden rounded-b-xl rounded-tl-xl border-[0.5px] border-(--rd-code-tab-edge-border) bg-(--rd-code-surface)">
|
|
580
597
|
<div
|
|
581
598
|
x-ref="snippetPanels"
|
|
582
|
-
class="relative h-full overflow-auto transition-[height]
|
|
599
|
+
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"
|
|
600
|
+
style="transition-duration: var(--rd-panel-transition-duration); transition-timing-function: var(--rd-panel-transition-easing);"
|
|
583
601
|
>
|
|
584
602
|
{
|
|
585
603
|
requestSnippetItems.map((snippet, index) => (
|
|
@@ -74,9 +74,7 @@ import { Icon } from "astro-icon/components";
|
|
|
74
74
|
<div
|
|
75
75
|
class="flex h-full min-h-0 w-full max-w-full min-w-0 flex-col rounded-xl"
|
|
76
76
|
>
|
|
77
|
-
<div
|
|
78
|
-
class="flex items-center justify-between gap-2 bg-(--rd-code-header-surface)"
|
|
79
|
-
>
|
|
77
|
+
<div class="flex items-center justify-between gap-2">
|
|
80
78
|
<div class="min-w-0 flex-1 overflow-hidden rounded-t-xl">
|
|
81
79
|
<div
|
|
82
80
|
x-ref="tabList"
|
|
@@ -84,7 +82,7 @@ import { Icon } from "astro-icon/components";
|
|
|
84
82
|
>
|
|
85
83
|
<div
|
|
86
84
|
aria-hidden="true"
|
|
87
|
-
class="pointer-events-none absolute top-
|
|
85
|
+
class="pointer-events-none absolute top-0 z-0 h-[28px] rounded-[9px] border-[0.5px] border-(--rd-code-tab-edge-border) bg-(--rd-code-surface) transition-[left,width,opacity] duration-200 ease-out"
|
|
88
86
|
x-bind:class="pillVisible ? 'opacity-100' : 'opacity-0'"
|
|
89
87
|
x-bind:style="'left:' + pillLeft + 'px;width:' + pillWidth + 'px;'"
|
|
90
88
|
>
|
|
@@ -95,11 +93,12 @@ import { Icon } from "astro-icon/components";
|
|
|
95
93
|
type="button"
|
|
96
94
|
x-bind:data-rd-response-tab="tab.id"
|
|
97
95
|
x-on:click="select(tab.id)"
|
|
98
|
-
class="relative z-10 inline-flex h-9 items-
|
|
96
|
+
class="relative z-10 inline-flex h-9 items-start border-0 bg-transparent px-3 py-0 text-xs font-medium transition-colors duration-150 focus:outline-none focus-visible:outline-none cursor-pointer"
|
|
99
97
|
x-bind:class="selected === tab.id ? 'text-foreground' : 'text-muted-foreground'"
|
|
100
98
|
>
|
|
101
|
-
<span
|
|
102
|
-
|
|
99
|
+
<span
|
|
100
|
+
class="pointer-events-none inline-flex h-[28px] items-center whitespace-pre leading-none"
|
|
101
|
+
x-text="tab.label"></span>
|
|
103
102
|
</button>
|
|
104
103
|
</template>
|
|
105
104
|
</div>
|
|
@@ -147,7 +146,7 @@ import { Icon } from "astro-icon/components";
|
|
|
147
146
|
x-show="!response || !response.highlightedData"
|
|
148
147
|
class="text-sm px-4 py-4 xs:py-8 flex flex-col items-center justify-center h-full text-foreground"
|
|
149
148
|
>
|
|
150
|
-
<div class="
|
|
149
|
+
<div class="p-2 rounded-xl mb-1">
|
|
151
150
|
<Icon
|
|
152
151
|
class="size-6 text-neutral-300 dark:text-neutral-600"
|
|
153
152
|
name="lucide:square-arrow-up-right"
|
|
@@ -171,7 +170,7 @@ import { Icon } from "astro-icon/components";
|
|
|
171
170
|
x-show="!response || !response.highlightedHeaders"
|
|
172
171
|
class="text-sm px-4 py-4 xs:py-8 flex flex-col items-center justify-center h-full text-foreground"
|
|
173
172
|
>
|
|
174
|
-
<div class="
|
|
173
|
+
<div class="p-2 rounded-xl mb-1">
|
|
175
174
|
<Icon
|
|
176
175
|
class="size-6 text-neutral-300 dark:text-neutral-600"
|
|
177
176
|
name="lucide:square-arrow-up-right"
|
|
@@ -248,13 +248,26 @@ const hasMultipleResponses = responseSnippetItems.length > 1;
|
|
|
248
248
|
isTransitioning: false,
|
|
249
249
|
isManagedSlot: false,
|
|
250
250
|
transitionDirection: 1,
|
|
251
|
-
transitionDurationMs:
|
|
251
|
+
transitionDurationMs: 400,
|
|
252
252
|
transitionEasing: "cubic-bezier(0.22, 1, 0.36, 1)",
|
|
253
253
|
tabSyncHandler: null,
|
|
254
254
|
transitionTimeoutId: null,
|
|
255
255
|
copyTimeoutId: null,
|
|
256
|
+
readMotionTokens() {
|
|
257
|
+
const styles = window.getComputedStyle(document.documentElement);
|
|
258
|
+
const configuredDurationMs = Number.parseFloat(
|
|
259
|
+
styles.getPropertyValue("--rd-panel-transition-duration-ms"),
|
|
260
|
+
);
|
|
261
|
+
this.transitionDurationMs = Number.isFinite(configuredDurationMs)
|
|
262
|
+
? configuredDurationMs
|
|
263
|
+
: this.transitionDurationMs;
|
|
264
|
+
this.transitionEasing =
|
|
265
|
+
styles.getPropertyValue("--rd-panel-transition-easing").trim() ||
|
|
266
|
+
this.transitionEasing;
|
|
267
|
+
},
|
|
256
268
|
init() {
|
|
257
269
|
this.isManagedSlot = !!this.$root?.closest("[data-snippet-slot]");
|
|
270
|
+
this.readMotionTokens();
|
|
258
271
|
if (
|
|
259
272
|
typeof window.matchMedia === "function" &&
|
|
260
273
|
window.matchMedia("(prefers-reduced-motion: reduce)").matches
|
|
@@ -271,6 +284,8 @@ const hasMultipleResponses = responseSnippetItems.length > 1;
|
|
|
271
284
|
if (this.$refs.snippetPanels) {
|
|
272
285
|
this.$refs.snippetPanels.style.transitionDuration =
|
|
273
286
|
this.transitionDurationMs + "ms";
|
|
287
|
+
this.$refs.snippetPanels.style.transitionTimingFunction =
|
|
288
|
+
this.transitionEasing;
|
|
274
289
|
}
|
|
275
290
|
this.syncPill();
|
|
276
291
|
this.syncSnippetHeight();
|
|
@@ -415,7 +430,7 @@ const hasMultipleResponses = responseSnippetItems.length > 1;
|
|
|
415
430
|
class="flex h-full min-h-0 w-full max-w-full min-w-0 flex-col rounded-xl"
|
|
416
431
|
>
|
|
417
432
|
<div
|
|
418
|
-
class="flex items-center justify-between gap-2
|
|
433
|
+
class="flex items-center justify-between gap-2"
|
|
419
434
|
>
|
|
420
435
|
{
|
|
421
436
|
hasMultipleResponses ? (
|
|
@@ -426,7 +441,7 @@ const hasMultipleResponses = responseSnippetItems.length > 1;
|
|
|
426
441
|
>
|
|
427
442
|
<div
|
|
428
443
|
aria-hidden="true"
|
|
429
|
-
class="pointer-events-none absolute top-
|
|
444
|
+
class="pointer-events-none absolute top-0 z-0 h-[28px] rounded-[9px] border-[0.5px] border-(--rd-code-tab-edge-border) bg-(--rd-code-surface) transition-[left,width,opacity] duration-200 ease-out"
|
|
430
445
|
x-bind:class="pillVisible ? 'opacity-100' : 'opacity-0'"
|
|
431
446
|
x-bind:style="'left:' + pillLeft + 'px;width:' + pillWidth + 'px;'"
|
|
432
447
|
/>
|
|
@@ -439,13 +454,15 @@ const hasMultipleResponses = responseSnippetItems.length > 1;
|
|
|
439
454
|
type="button"
|
|
440
455
|
x-bind:data-rd-snippet-tab="index"
|
|
441
456
|
x-on:click="select(index)"
|
|
442
|
-
class="relative z-10 inline-flex h-9 items-
|
|
457
|
+
class="relative z-10 inline-flex h-9 items-start border-0 bg-transparent px-3 py-0 text-xs font-medium transition-colors duration-150 focus:outline-none focus-visible:outline-none cursor-pointer"
|
|
443
458
|
x-bind:class="selected === index ? 'text-foreground' : 'text-muted-foreground'"
|
|
444
459
|
>
|
|
445
|
-
<span
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
460
|
+
<span class="pointer-events-none inline-flex h-[28px] items-center gap-2">
|
|
461
|
+
<span
|
|
462
|
+
class="size-[7px] shrink-0 rounded-full transition-opacity duration-150"
|
|
463
|
+
x-bind:class="(selected === index ? 'opacity-100 ' : 'opacity-70 ') + snippet.dotClass"></span>
|
|
464
|
+
<span class="whitespace-pre leading-none" x-text="snippet.statusCode"></span>
|
|
465
|
+
</span>
|
|
449
466
|
</button>
|
|
450
467
|
</template>
|
|
451
468
|
</div>
|
|
@@ -499,7 +516,8 @@ const hasMultipleResponses = responseSnippetItems.length > 1;
|
|
|
499
516
|
<div class="relative min-h-0 min-w-0 flex-1 overflow-hidden rounded-b-xl rounded-tl-xl border-[0.5px] border-(--rd-code-tab-edge-border) bg-(--rd-code-surface)">
|
|
500
517
|
<div
|
|
501
518
|
x-ref="snippetPanels"
|
|
502
|
-
class="relative h-full overflow-auto transition-[height]
|
|
519
|
+
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"
|
|
520
|
+
style="transition-duration: var(--rd-panel-transition-duration); transition-timing-function: var(--rd-panel-transition-easing);"
|
|
503
521
|
>
|
|
504
522
|
{
|
|
505
523
|
responseSnippetItems.map((snippet, index) => (
|
|
@@ -50,7 +50,7 @@ validateProps(
|
|
|
50
50
|
}`
|
|
51
51
|
x-init="id = (typeof register === 'function') ? register() : Math.random()"
|
|
52
52
|
role="region"
|
|
53
|
-
class="rd-accordion block border-b border-neutral-800/10 dark:border-neutral-700/50 last:border-b-0. [&:first-child>h4>button]:pt-0
|
|
53
|
+
class="rd-accordion block border-b border-neutral-800/10 dark:border-neutral-700/50 last:border-b-0. [&:first-child>h4>button]:pt-0"
|
|
54
54
|
>
|
|
55
55
|
<h4 class="not-prose">
|
|
56
56
|
<button
|
|
@@ -70,9 +70,23 @@ validateProps(
|
|
|
70
70
|
/>
|
|
71
71
|
</button>
|
|
72
72
|
</h4>
|
|
73
|
-
<div
|
|
74
|
-
|
|
75
|
-
|
|
73
|
+
<div
|
|
74
|
+
class:list={[
|
|
75
|
+
"grid overflow-hidden transition-[grid-template-rows,opacity] motion-reduce:transition-none",
|
|
76
|
+
defaultOpen ? "grid-rows-[1fr] opacity-100" : "grid-rows-[0fr] opacity-0",
|
|
77
|
+
]}
|
|
78
|
+
:class="expanded ? 'grid-rows-[1fr] opacity-100' : 'grid-rows-[0fr] opacity-0'"
|
|
79
|
+
:aria-hidden="(!expanded).toString()"
|
|
80
|
+
x-bind:inert="!expanded"
|
|
81
|
+
style="transition-duration: var(--rd-panel-transition-duration); transition-timing-function: var(--rd-panel-transition-easing);"
|
|
82
|
+
>
|
|
83
|
+
<div class="min-h-0 overflow-hidden">
|
|
84
|
+
<div
|
|
85
|
+
data-rd-accordion-content-inner
|
|
86
|
+
class="prose-rules max-w-none! *:max-w-none! pb-4!"
|
|
87
|
+
>
|
|
88
|
+
<slot />
|
|
89
|
+
</div>
|
|
76
90
|
</div>
|
|
77
91
|
</div>
|
|
78
92
|
</div>
|
|
@@ -16,6 +16,7 @@ interface Props {
|
|
|
16
16
|
showLineNumbers?: boolean | string;
|
|
17
17
|
hideLanguageIcon?: boolean | string;
|
|
18
18
|
inCodeGroup?: boolean | string;
|
|
19
|
+
flushTop?: boolean | string;
|
|
19
20
|
highlightedLines?: string;
|
|
20
21
|
collapsedLines?: string;
|
|
21
22
|
}
|
|
@@ -28,6 +29,7 @@ const {
|
|
|
28
29
|
showLineNumbers = false,
|
|
29
30
|
hideLanguageIcon = false,
|
|
30
31
|
inCodeGroup = false,
|
|
32
|
+
flushTop = false,
|
|
31
33
|
highlightedLines = "",
|
|
32
34
|
collapsedLines = "",
|
|
33
35
|
} = Astro.props as Props;
|
|
@@ -191,6 +193,7 @@ const parsedShowFilename = parsedInCodeGroup
|
|
|
191
193
|
: toBoolean(showFilename, false);
|
|
192
194
|
const parsedShowLineNumbers = toBoolean(showLineNumbers, false);
|
|
193
195
|
const parsedHideLanguageIcon = toBoolean(hideLanguageIcon, false);
|
|
196
|
+
const parsedFlushTop = !parsedInCodeGroup && toBoolean(flushTop, false);
|
|
194
197
|
const shouldRenderLanguageIcon = !parsedHideLanguageIcon;
|
|
195
198
|
|
|
196
199
|
const trimmedFilename = filename.trim();
|
|
@@ -262,7 +265,8 @@ const renderedCodeLinesHtml = normalizedTokenLines
|
|
|
262
265
|
|
|
263
266
|
<div
|
|
264
267
|
class:list={[
|
|
265
|
-
"group/prose-code not-prose relative w-full max-w-full min-w-0
|
|
268
|
+
"group/prose-code not-prose relative w-full max-w-full min-w-0",
|
|
269
|
+
parsedFlushTop ? "rounded-b-xl" : "rounded-xl",
|
|
266
270
|
parsedInCodeGroup ? "my-0" : "rd-prose-block",
|
|
267
271
|
]}
|
|
268
272
|
data-rd-code-block-root="true"
|
|
@@ -279,12 +283,16 @@ const renderedCodeLinesHtml = normalizedTokenLines
|
|
|
279
283
|
<div
|
|
280
284
|
class:list={[
|
|
281
285
|
"w-full max-w-full min-w-0 bg-(--rd-code-surface)",
|
|
282
|
-
parsedInCodeGroup
|
|
286
|
+
parsedInCodeGroup
|
|
287
|
+
? "rounded-tr-none rounded-xl"
|
|
288
|
+
: parsedFlushTop
|
|
289
|
+
? "rounded-b-xl"
|
|
290
|
+
: "rounded-xl",
|
|
283
291
|
]}
|
|
284
292
|
>
|
|
285
293
|
{
|
|
286
294
|
!parsedInCodeGroup && parsedShowFilename ? (
|
|
287
|
-
<div class="flex items-center justify-between gap-2 border-b-[0.5px] border-(--rd-code-tab-edge-border)
|
|
295
|
+
<div class="flex items-center justify-between gap-2 border-b-[0.5px] border-(--rd-code-tab-edge-border)">
|
|
288
296
|
<div class="min-w-0 flex-1">
|
|
289
297
|
<div class="relative h-9 w-fit max-w-full rounded-tl-xl bg-(--rd-code-surface)">
|
|
290
298
|
<div class="absolute inset-x-0 -bottom-px h-px bg-(--rd-code-surface)" />
|
|
@@ -331,7 +339,9 @@ const renderedCodeLinesHtml = normalizedTokenLines
|
|
|
331
339
|
|
|
332
340
|
<div
|
|
333
341
|
class:list={[
|
|
334
|
-
"relative min-w-0 border-[0.5px]
|
|
342
|
+
"relative min-w-0 border-[0.5px] overflow-hidden border-(--rd-code-tab-edge-border)",
|
|
343
|
+
parsedFlushTop ? "rounded-b-xl" : "rounded-xl",
|
|
344
|
+
parsedFlushTop && "border-t-0",
|
|
335
345
|
parsedShowFilename && "border-t-0 rounded-t-none",
|
|
336
346
|
parsedInCodeGroup && "rounded-tl-xl border-0!",
|
|
337
347
|
]}
|
|
@@ -7,19 +7,17 @@ import CodeTabEdge from "../ui/CodeTabEdge.astro";
|
|
|
7
7
|
class="rd-prose-block group/prose-code-group not-prose relative w-full max-w-full min-w-0 rounded-xl"
|
|
8
8
|
data-rd-code-group-root="true"
|
|
9
9
|
>
|
|
10
|
-
<div
|
|
11
|
-
class="relative z-10 overflow-visible rounded-t-xl bg-(--rd-code-header-surface)"
|
|
12
|
-
>
|
|
10
|
+
<div class="relative z-10 overflow-visible rounded-t-xl">
|
|
13
11
|
<div class="flex min-w-0 items-end justify-between gap-2">
|
|
14
12
|
<div class="min-w-0 flex-1 overflow-hidden rounded-t-xl">
|
|
15
13
|
<div
|
|
16
14
|
data-rd-code-group-tabs
|
|
17
|
-
class="relative flex min-w-0 items-end gap-1 overflow-x-auto pl-1 pr-8 [scrollbar-width:none] [&::-webkit-scrollbar]:hidden"
|
|
15
|
+
class="relative flex min-w-0 items-end gap-1 overflow-x-auto overscroll-x-contain pl-1 pr-8 [scrollbar-width:none] [&::-webkit-scrollbar]:hidden"
|
|
18
16
|
>
|
|
19
17
|
<div
|
|
20
18
|
data-rd-code-group-pill
|
|
21
19
|
aria-hidden="true"
|
|
22
|
-
class="pointer-events-none absolute top-
|
|
20
|
+
class="pointer-events-none absolute top-0 z-0 h-[28px] rounded-[9px] border-[0.5px] border-(--rd-code-tab-edge-border) bg-(--rd-code-surface) opacity-0 transition-[left,width,opacity] duration-200 ease-out"
|
|
23
21
|
>
|
|
24
22
|
</div>
|
|
25
23
|
</div>
|
|
@@ -58,7 +56,8 @@ import CodeTabEdge from "../ui/CodeTabEdge.astro";
|
|
|
58
56
|
|
|
59
57
|
<div
|
|
60
58
|
data-rd-code-group-content
|
|
61
|
-
class="relative min-w-0 overflow-hidden transition-[height]
|
|
59
|
+
class="relative min-w-0 overflow-hidden transition-[height] bg-(--rd-code-surface) rounded-xl rounded-tr-none border-[0.5px] border-(--rd-code-tab-edge-border)"
|
|
60
|
+
style="transition-duration: var(--rd-panel-transition-duration); transition-timing-function: var(--rd-panel-transition-easing);"
|
|
62
61
|
>
|
|
63
62
|
<slot />
|
|
64
63
|
</div>
|
|
@@ -91,8 +90,20 @@ import CodeTabEdge from "../ui/CodeTabEdge.astro";
|
|
|
91
90
|
const prefersReducedMotion =
|
|
92
91
|
typeof window.matchMedia === "function" &&
|
|
93
92
|
window.matchMedia("(prefers-reduced-motion: reduce)").matches;
|
|
94
|
-
const
|
|
95
|
-
const
|
|
93
|
+
const rootStyles = window.getComputedStyle(document.documentElement);
|
|
94
|
+
const configuredDurationMs = Number.parseFloat(
|
|
95
|
+
rootStyles.getPropertyValue("--rd-panel-transition-duration-ms"),
|
|
96
|
+
);
|
|
97
|
+
const configuredEasing = rootStyles
|
|
98
|
+
.getPropertyValue("--rd-panel-transition-easing")
|
|
99
|
+
.trim();
|
|
100
|
+
const TRANSITION_DURATION_MS = prefersReducedMotion
|
|
101
|
+
? 0
|
|
102
|
+
: Number.isFinite(configuredDurationMs)
|
|
103
|
+
? configuredDurationMs
|
|
104
|
+
: 400;
|
|
105
|
+
const TRANSITION_EASING =
|
|
106
|
+
configuredEasing || "cubic-bezier(0.22, 1, 0.36, 1)";
|
|
96
107
|
|
|
97
108
|
let activeIndex = 0;
|
|
98
109
|
let transitionTimeoutId = null;
|
|
@@ -138,10 +149,14 @@ import CodeTabEdge from "../ui/CodeTabEdge.astro";
|
|
|
138
149
|
|
|
139
150
|
const tabButton = document.createElement("button");
|
|
140
151
|
tabButton.type = "button";
|
|
141
|
-
tabButton.className =
|
|
152
|
+
tabButton.className =
|
|
153
|
+
"relative inline-flex h-9 items-start border-0 bg-transparent px-3 py-0 text-xs font-medium transition-colors duration-150 focus:outline-none focus-visible:outline-none cursor-pointer";
|
|
142
154
|
tabButton.setAttribute("aria-label", filename);
|
|
143
155
|
tabButton.setAttribute("data-rd-code-group-tab", String(index));
|
|
144
156
|
|
|
157
|
+
const tabContent = document.createElement("span");
|
|
158
|
+
tabContent.className = `pointer-events-none inline-flex h-[28px] items-center ${hasTabIcon ? "gap-2" : ""}`;
|
|
159
|
+
|
|
145
160
|
let iconContainer = null;
|
|
146
161
|
if (hasTabIcon) {
|
|
147
162
|
iconContainer = document.createElement("span");
|
|
@@ -155,9 +170,10 @@ import CodeTabEdge from "../ui/CodeTabEdge.astro";
|
|
|
155
170
|
labelElement.textContent = filename;
|
|
156
171
|
|
|
157
172
|
if (iconContainer) {
|
|
158
|
-
|
|
173
|
+
tabContent.appendChild(iconContainer);
|
|
159
174
|
}
|
|
160
|
-
|
|
175
|
+
tabContent.appendChild(labelElement);
|
|
176
|
+
tabButton.appendChild(tabContent);
|
|
161
177
|
tabWrapper.appendChild(tabButton);
|
|
162
178
|
tabsElement.appendChild(tabWrapper);
|
|
163
179
|
|
|
@@ -182,6 +198,7 @@ import CodeTabEdge from "../ui/CodeTabEdge.astro";
|
|
|
182
198
|
});
|
|
183
199
|
|
|
184
200
|
contentElement.style.transitionDuration = `${TRANSITION_DURATION_MS}ms`;
|
|
201
|
+
contentElement.style.transitionTimingFunction = TRANSITION_EASING;
|
|
185
202
|
|
|
186
203
|
const syncPill = () => {
|
|
187
204
|
const activeTab = tabs[activeIndex]?.tabWrapper;
|
|
@@ -60,16 +60,20 @@ const isInitiallyExpanded = shouldShowAllCode || totalLineCount <= visibleLines;
|
|
|
60
60
|
---
|
|
61
61
|
|
|
62
62
|
<div
|
|
63
|
-
class="rd-prose-block rd-component-preview flex w-full max-w-full min-w-0 flex-col"
|
|
63
|
+
class="rd-prose-block rd-component-preview isolate flex w-full max-w-full min-w-0 flex-col"
|
|
64
64
|
data-rd-component-preview-root="true"
|
|
65
65
|
>
|
|
66
66
|
<div
|
|
67
|
-
class="w-full max-w-full min-w-0
|
|
67
|
+
class="relative z-10 w-full max-w-full min-w-0 rounded-t-xl border-[0.5px] border-b-0 border-(--rd-code-tab-edge-border) bg-(--rd-code-surface) p-2"
|
|
68
68
|
>
|
|
69
|
-
<
|
|
69
|
+
<div
|
|
70
|
+
class="bg-white dark:bg-neutral-900/70 rounded-xl border-[0.5px] border-neutral-900/10 dark:border-white/8 p-4 xs:p-6 sm:p-9 sm:px-12 *:first:mt-0! *:last:mb-0! shadow-[0_.5px_1px_rgba(0,0,0,0.15),0_5px_12px_-8px_rgba(0,0,0,0.08)] dark:shadow-[0_-0.5px_1px_rgba(255,255,255,0.1),0_5px_12px_-4px_rgba(0,0,0,0.15)] overflow-x-auto"
|
|
71
|
+
>
|
|
72
|
+
<slot />
|
|
73
|
+
</div>
|
|
70
74
|
</div>
|
|
71
75
|
<div
|
|
72
|
-
class="rd-component-preview__code not-prose relative overflow-hidden rounded-b-xl
|
|
76
|
+
class="rd-component-preview__code not-prose relative z-0 overflow-hidden rounded-b-xl"
|
|
73
77
|
data-rd-preview-expanded={isInitiallyExpanded ? "true" : "false"}
|
|
74
78
|
style={{ "--rd-preview-visible-lines": String(visibleLines) }}
|
|
75
79
|
>
|
|
@@ -82,16 +86,19 @@ const isInitiallyExpanded = shouldShowAllCode || totalLineCount <= visibleLines;
|
|
|
82
86
|
hideLanguageIcon={hideLanguageIcon}
|
|
83
87
|
highlightedLines={highlightedLines}
|
|
84
88
|
collapsedLines={collapsedLines}
|
|
89
|
+
flushTop
|
|
85
90
|
/>
|
|
86
91
|
<div
|
|
87
|
-
class="rd-component-preview__overlay pointer-events-none absolute inset-
|
|
92
|
+
class="rd-component-preview__overlay pointer-events-none absolute inset-0 hidden items-end justify-center rounded-b-xl pb-4"
|
|
88
93
|
data-rd-preview-overlay
|
|
89
94
|
aria-hidden="true"
|
|
90
95
|
>
|
|
91
|
-
<div
|
|
96
|
+
<div
|
|
97
|
+
class="bg-white dark:bg-neutral-800 rounded-xl [corner-shape:superellipse(1.2)]"
|
|
98
|
+
>
|
|
92
99
|
<button
|
|
93
100
|
type="button"
|
|
94
|
-
class="pointer-events-auto inline-flex h-8 items-center justify-center rounded-
|
|
101
|
+
class="pointer-events-auto inline-flex h-8 items-center justify-center rounded-xl [corner-shape:superellipse(1.2)] border-[0.5px] border-neutral-900/10 dark:border-white/8 bg-linear-to-br from-white via-white/10 to-neutral-900/5 dark:from-white/7 dark:via-white/6 dark:to-white/2 px-3 text-sm font-medium text-neutral-600 hover:text-neutral-900 dark:text-neutral-300/90 hover:dark:text-neutral-200 transition-colors duration-200 hover:bg-neutral-50/80 cursor-pointer dark:hover:bg-neutral-700/30 shadow-[0_.5px_1px_rgba(0,0,0,0.15),0_5px_12px_-4px_rgba(0,0,0,0.08)] dark:shadow-[0_-0.5px_0px_rgba(255,255,255,0.15),0_5px_12px_-4px_rgba(0,0,0,0.6)]"
|
|
95
102
|
data-rd-preview-expand
|
|
96
103
|
>
|
|
97
104
|
View code
|
|
@@ -174,36 +181,37 @@ const isInitiallyExpanded = shouldShowAllCode || totalLineCount <= visibleLines;
|
|
|
174
181
|
.rd-component-preview__code[data-rd-preview-expanded="false"]
|
|
175
182
|
.rd-component-preview__overlay {
|
|
176
183
|
display: flex;
|
|
177
|
-
background: linear-gradient(
|
|
178
|
-
to top,
|
|
179
|
-
rgb(250 250 250 / 90%),
|
|
180
|
-
rgb(250 250 250 / 30%)
|
|
181
|
-
);
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
:global(.dark)
|
|
185
|
-
.rd-component-preview__code[data-rd-preview-expanded="false"]
|
|
186
|
-
.rd-component-preview__overlay {
|
|
187
|
-
background: linear-gradient(
|
|
188
|
-
to top,
|
|
189
|
-
color-mix(in srgb, var(--rd-code-surface) 90%, transparent),
|
|
190
|
-
color-mix(in srgb, var(--rd-code-surface) 35%, transparent)
|
|
191
|
-
);
|
|
192
184
|
}
|
|
193
185
|
|
|
194
186
|
.rd-component-preview__code :global([data-rd-code-scroll-area]) {
|
|
195
187
|
overflow-y: hidden;
|
|
196
|
-
transition:
|
|
188
|
+
transition:
|
|
189
|
+
max-height 280ms cubic-bezier(0.22, 1, 0.36, 1),
|
|
190
|
+
mask-image 180ms ease-out;
|
|
197
191
|
}
|
|
198
192
|
|
|
199
193
|
.rd-component-preview__code[data-rd-preview-expanded="false"]
|
|
200
194
|
:global([data-rd-code-scroll-area]) {
|
|
201
|
-
max-height: calc(var(--rd-preview-visible-lines, 5) * 1.5rem +
|
|
195
|
+
max-height: calc(var(--rd-preview-visible-lines, 5) * 1.5rem + 0.75rem);
|
|
196
|
+
-webkit-mask-image: linear-gradient(
|
|
197
|
+
to bottom,
|
|
198
|
+
rgb(0 0 0 / 80%) 0%,
|
|
199
|
+
rgb(0 0 0 / 32%) 82%,
|
|
200
|
+
transparent 110%
|
|
201
|
+
);
|
|
202
|
+
mask-image: linear-gradient(
|
|
203
|
+
to bottom,
|
|
204
|
+
rgb(0 0 0 / 80%) 0%,
|
|
205
|
+
rgb(0 0 0 / 32%) 82%,
|
|
206
|
+
transparent 110%
|
|
207
|
+
);
|
|
202
208
|
}
|
|
203
209
|
|
|
204
210
|
.rd-component-preview__code[data-rd-preview-expanded="true"]
|
|
205
211
|
:global([data-rd-code-scroll-area]) {
|
|
206
212
|
max-height: var(--rd-preview-expanded-height, 200rem);
|
|
213
|
+
-webkit-mask-image: none;
|
|
214
|
+
mask-image: none;
|
|
207
215
|
}
|
|
208
216
|
</style>
|
|
209
217
|
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
---
|
|
2
2
|
import { validateNoUnknownProps, validateProps } from "../../lib/component-error";
|
|
3
|
-
import { renderMarkdown } from "../../lib/utils";
|
|
4
3
|
import { resolveStaticAssetUrl } from "../../lib/static-asset-url";
|
|
5
4
|
|
|
6
5
|
interface Props {
|
|
7
|
-
src: string;
|
|
6
|
+
src: string | { light?: string; dark?: string };
|
|
8
7
|
alt?: string;
|
|
9
8
|
title?: string;
|
|
10
9
|
width?: number | string;
|
|
@@ -24,7 +23,7 @@ validateProps(
|
|
|
24
23
|
"Image",
|
|
25
24
|
imageProps,
|
|
26
25
|
{
|
|
27
|
-
src: { required: true, type: "string" },
|
|
26
|
+
src: { required: true, type: ["string", "object"] },
|
|
28
27
|
alt: { type: "string" },
|
|
29
28
|
title: { type: "string" },
|
|
30
29
|
width: { type: ["number", "string"] },
|
|
@@ -35,17 +34,51 @@ validateProps(
|
|
|
35
34
|
|
|
36
35
|
const { src, alt, title, width, zoom = true } = imageProps as Props;
|
|
37
36
|
const zoomEnabled = zoom !== false;
|
|
38
|
-
const resolvedSrc = resolveStaticAssetUrl(src);
|
|
39
37
|
const rawWidth = width;
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
38
|
+
|
|
39
|
+
function normalizeImageSource(value: Props["src"]): {
|
|
40
|
+
light: string;
|
|
41
|
+
dark?: string;
|
|
42
|
+
} {
|
|
43
|
+
if (typeof value === "string") {
|
|
44
|
+
return { light: value };
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const light = typeof value.light === "string" ? value.light : "";
|
|
48
|
+
const dark = typeof value.dark === "string" ? value.dark : undefined;
|
|
49
|
+
|
|
50
|
+
return { light, dark };
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const normalizedSource = normalizeImageSource(src);
|
|
54
|
+
if (!normalizedSource.light.trim()) {
|
|
55
|
+
throw new Error(
|
|
56
|
+
`[USER_ERROR]: <Image>: Invalid prop "src": object form requires a non-empty "light" string (in ${Astro.url.pathname})`,
|
|
57
|
+
);
|
|
43
58
|
}
|
|
44
|
-
|
|
45
|
-
|
|
59
|
+
|
|
60
|
+
const resolvedLightSrc = resolveStaticAssetUrl(normalizedSource.light);
|
|
61
|
+
const resolvedDarkSrc =
|
|
62
|
+
typeof normalizedSource.dark === "string" && normalizedSource.dark.trim()
|
|
63
|
+
? resolveStaticAssetUrl(normalizedSource.dark)
|
|
64
|
+
: undefined;
|
|
65
|
+
const hasDarkSource =
|
|
66
|
+
typeof resolvedDarkSrc === "string" && resolvedDarkSrc !== resolvedLightSrc;
|
|
67
|
+
|
|
68
|
+
function createImageAttrs(source: string): Record<string, unknown> {
|
|
69
|
+
const attrs: Record<string, unknown> = { src: source };
|
|
70
|
+
if (typeof alt === "string") {
|
|
71
|
+
attrs.alt = alt;
|
|
72
|
+
}
|
|
73
|
+
if (width !== undefined) {
|
|
74
|
+
attrs.width = width;
|
|
75
|
+
}
|
|
76
|
+
return attrs;
|
|
46
77
|
}
|
|
47
78
|
|
|
48
|
-
const
|
|
79
|
+
const lightImageAttrs = createImageAttrs(resolvedLightSrc);
|
|
80
|
+
const darkImageAttrs = hasDarkSource ? createImageAttrs(resolvedDarkSrc!) : null;
|
|
81
|
+
const zoomAttrs: Record<string, unknown> = { src: resolvedLightSrc };
|
|
49
82
|
if (typeof alt === "string") {
|
|
50
83
|
zoomAttrs.alt = alt;
|
|
51
84
|
}
|
|
@@ -83,15 +116,15 @@ function isConstrainedWidthValue(value: unknown): boolean {
|
|
|
83
116
|
|
|
84
117
|
const hasCustomImageWidth = isConstrainedWidthValue(rawWidth);
|
|
85
118
|
|
|
86
|
-
const
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
119
|
+
const slotCaptionHtml = Astro.slots.has("default")
|
|
120
|
+
? (await Astro.slots.render("default")).trim()
|
|
121
|
+
: "";
|
|
122
|
+
const hasCaption = slotCaptionHtml.length > 0;
|
|
90
123
|
---
|
|
91
124
|
|
|
92
125
|
<figure
|
|
93
126
|
class:list={[
|
|
94
|
-
"rd-prose-block p-1.5 pb-1 xs:pb-1.5 group border border-neutral-
|
|
127
|
+
"rd-prose-block p-1.5 pb-1 xs:pb-1.5 group border-[0.5px] border-neutral-900/8 dark:border-white/6 bg-(--rd-code-surface) rounded-2xl shadow-[0_.5px_1px_rgba(0,0,0,0.15),0_5px_12px_-8px_rgba(0,0,0,0.08)] dark:shadow-[0_-.5px_1px_rgba(255,255,255,0.15),0_5px_12px_-8px_rgba(0,0,0,0.2)]",
|
|
95
128
|
hasCustomImageWidth ? "w-fit max-w-full mx-auto" : "w-full",
|
|
96
129
|
]}
|
|
97
130
|
x-data="{
|
|
@@ -102,8 +135,16 @@ const captionHtml =
|
|
|
102
135
|
style: 'visibility: hidden;',
|
|
103
136
|
fullShadow: '0 25px 50px -12px rgba(0, 0, 0, 0.25)',
|
|
104
137
|
noShadow: '0 0 0 rgba(0, 0, 0, 0)',
|
|
138
|
+
zoomSrc: '',
|
|
139
|
+
activeImage() {
|
|
140
|
+
const darkImg = this.$refs.darkImg;
|
|
141
|
+
if (darkImg && window.getComputedStyle(darkImg).display !== 'none') {
|
|
142
|
+
return darkImg;
|
|
143
|
+
}
|
|
144
|
+
return this.$refs.lightImg;
|
|
145
|
+
},
|
|
105
146
|
computeZoomSize() {
|
|
106
|
-
const img = this
|
|
147
|
+
const img = this.activeImage();
|
|
107
148
|
const zoomContainer = this.$refs.zoomViewport;
|
|
108
149
|
if (!img || !zoomContainer) {
|
|
109
150
|
this.zoomSize = `width: min(92vw, ${this.zoomMaxWidth}px);`;
|
|
@@ -138,9 +179,12 @@ const captionHtml =
|
|
|
138
179
|
return this.zoomSize;
|
|
139
180
|
},
|
|
140
181
|
async zoom() {
|
|
182
|
+
const img = this.activeImage();
|
|
183
|
+
if (!img) return;
|
|
141
184
|
// 1. Lock scroll and measure
|
|
142
185
|
document.body.style.overflow = 'hidden';
|
|
143
|
-
|
|
186
|
+
this.zoomSrc = img.currentSrc || img.src;
|
|
187
|
+
const rect = img.getBoundingClientRect();
|
|
144
188
|
|
|
145
189
|
// 2. Prepare the zoomed image (hidden but in DOM)
|
|
146
190
|
this.style = 'opacity: 0; transition: none;';
|
|
@@ -176,7 +220,9 @@ const captionHtml =
|
|
|
176
220
|
},
|
|
177
221
|
close() {
|
|
178
222
|
document.body.style.overflow = 'auto';
|
|
179
|
-
const
|
|
223
|
+
const img = this.activeImage();
|
|
224
|
+
if (!img) return;
|
|
225
|
+
const rect = img.getBoundingClientRect();
|
|
180
226
|
const zRect = this.$refs.zoomedImg.getBoundingClientRect();
|
|
181
227
|
|
|
182
228
|
const scale = rect.width / zRect.width;
|
|
@@ -194,25 +240,42 @@ const captionHtml =
|
|
|
194
240
|
}"
|
|
195
241
|
>
|
|
196
242
|
<div
|
|
197
|
-
class="overflow-hidden rounded-
|
|
243
|
+
class="overflow-hidden rounded-[11px]"
|
|
198
244
|
>
|
|
199
245
|
<img
|
|
200
|
-
{...
|
|
201
|
-
x-ref="
|
|
246
|
+
{...lightImageAttrs}
|
|
247
|
+
x-ref="lightImg"
|
|
202
248
|
title={title}
|
|
203
249
|
class:list={[
|
|
204
250
|
"h-auto my-0! block transition-opacity",
|
|
251
|
+
hasDarkSource && "dark:hidden",
|
|
205
252
|
zoomEnabled && "cursor-zoom-in",
|
|
206
253
|
hasCustomImageWidth ? "max-w-full" : "w-full",
|
|
207
254
|
]}
|
|
208
255
|
:class="showZoomed ? 'opacity-0 duration-0' : 'opacity-100 duration-300'"
|
|
209
256
|
@click={zoomEnabled ? "zoom()" : undefined}
|
|
210
257
|
/>
|
|
258
|
+
{
|
|
259
|
+
darkImageAttrs && (
|
|
260
|
+
<img
|
|
261
|
+
{...darkImageAttrs}
|
|
262
|
+
x-ref="darkImg"
|
|
263
|
+
title={title}
|
|
264
|
+
class:list={[
|
|
265
|
+
"h-auto my-0! hidden transition-opacity dark:block",
|
|
266
|
+
zoomEnabled && "cursor-zoom-in",
|
|
267
|
+
hasCustomImageWidth ? "max-w-full" : "w-full",
|
|
268
|
+
]}
|
|
269
|
+
:class="showZoomed ? 'opacity-0 duration-0' : 'opacity-100 duration-300'"
|
|
270
|
+
@click={zoomEnabled ? "zoom()" : undefined}
|
|
271
|
+
/>
|
|
272
|
+
)
|
|
273
|
+
}
|
|
211
274
|
</div>
|
|
212
275
|
{
|
|
213
|
-
|
|
214
|
-
<figcaption class="mt-1! xs:mt-1.5! text-center text-xs! xs:text-sm! text-neutral-500 dark:text-neutral-400
|
|
215
|
-
<
|
|
276
|
+
hasCaption && (
|
|
277
|
+
<figcaption class="prose-rules mt-1! xs:mt-1.5! max-w-none! *:max-w-none! text-center text-xs! xs:text-sm! text-neutral-500 dark:text-neutral-400 leading-relaxed px-2">
|
|
278
|
+
<Fragment set:html={slotCaptionHtml} />
|
|
216
279
|
</figcaption>
|
|
217
280
|
)
|
|
218
281
|
}
|
|
@@ -243,6 +306,7 @@ const captionHtml =
|
|
|
243
306
|
<img
|
|
244
307
|
{...zoomAttrs}
|
|
245
308
|
x-ref="zoomedImg"
|
|
309
|
+
:src="zoomSrc || $el.getAttribute('src')"
|
|
246
310
|
class="relative z-10 max-w-full max-h-full object-contain rounded-2xl shadow-none will-change-transform pointer-events-none"
|
|
247
311
|
:style="style"
|
|
248
312
|
/>
|
|
@@ -21,14 +21,14 @@ validateProps(
|
|
|
21
21
|
<div
|
|
22
22
|
class:list={[
|
|
23
23
|
"relative pl-10 step-item pb-4 last:pb-0 space-y-4",
|
|
24
|
-
"before:absolute before:left-[
|
|
24
|
+
"before:mask-b-from-90% before:absolute before:left-[13.25px] before:top-[28px] before:bottom-0 before:w-[1.5px] before:bg-neutral-900/8 dark:before:bg-neutral-50/8",
|
|
25
25
|
]}
|
|
26
26
|
data-step-panel
|
|
27
27
|
>
|
|
28
28
|
<div
|
|
29
29
|
class:list={[
|
|
30
30
|
"flex items-center gap-1.5 not-prose",
|
|
31
|
-
"step-number before:
|
|
31
|
+
"step-number before:leading-none before:size-7 before:bg-neutral-900/6 dark:before:bg-neutral-50/6 before:rounded-full before:text-neutral-700 dark:before:text-neutral-100 before:flex before:items-center before:justify-center before:text-[13px] before:font-medium before:absolute before:left-0 before:top-0",
|
|
32
32
|
]}
|
|
33
33
|
>
|
|
34
34
|
<h3 class="text-lg font-semibold text-neutral-900 dark:text-neutral-100">
|
|
@@ -30,12 +30,33 @@ if (labels.length === 0) {
|
|
|
30
30
|
previousTab: null,
|
|
31
31
|
transitionDirection: 1,
|
|
32
32
|
isTransitioning: false,
|
|
33
|
-
transitionDurationMs:
|
|
33
|
+
transitionDurationMs: 400,
|
|
34
|
+
transitionEasing: 'cubic-bezier(0.22, 1, 0.36, 1)',
|
|
34
35
|
transitionTimeout: null,
|
|
35
36
|
containerHeight: 'auto',
|
|
36
37
|
markerStyle: { left: null, width: null },
|
|
37
38
|
resizeHandler: null,
|
|
39
|
+
readMotionTokens() {
|
|
40
|
+
const styles = window.getComputedStyle(document.documentElement);
|
|
41
|
+
const configuredDurationMs = Number.parseFloat(
|
|
42
|
+
styles.getPropertyValue('--rd-panel-transition-duration-ms'),
|
|
43
|
+
);
|
|
44
|
+
this.transitionDurationMs = Number.isFinite(configuredDurationMs)
|
|
45
|
+
? configuredDurationMs
|
|
46
|
+
: this.transitionDurationMs;
|
|
47
|
+
this.transitionEasing =
|
|
48
|
+
styles.getPropertyValue('--rd-panel-transition-easing').trim() ||
|
|
49
|
+
this.transitionEasing;
|
|
50
|
+
|
|
51
|
+
if (
|
|
52
|
+
typeof window.matchMedia === 'function' &&
|
|
53
|
+
window.matchMedia('(prefers-reduced-motion: reduce)').matches
|
|
54
|
+
) {
|
|
55
|
+
this.transitionDurationMs = 0;
|
|
56
|
+
}
|
|
57
|
+
},
|
|
38
58
|
init() {
|
|
59
|
+
this.readMotionTokens();
|
|
39
60
|
this.resizeHandler = () => {
|
|
40
61
|
this.updateMarker(this.activeTab);
|
|
41
62
|
this.updateHeight(this.isTransitioning);
|
|
@@ -68,7 +89,7 @@ if (labels.length === 0) {
|
|
|
68
89
|
this.isTransitioning = true;
|
|
69
90
|
this.activeTab = index;
|
|
70
91
|
this.updateMarker(this.activeTab);
|
|
71
|
-
this.updateHeight(
|
|
92
|
+
this.updateHeight();
|
|
72
93
|
|
|
73
94
|
this.transitionTimeout = window.setTimeout(() => {
|
|
74
95
|
this.isTransitioning = false;
|
|
@@ -87,7 +108,7 @@ if (labels.length === 0) {
|
|
|
87
108
|
}
|
|
88
109
|
},
|
|
89
110
|
getPanelStyle(index) {
|
|
90
|
-
const base = 'position: absolute;
|
|
111
|
+
const base = 'position: absolute; top: 0; left: 0; right: 0; width: 100%;';
|
|
91
112
|
|
|
92
113
|
const isActive = index === this.activeTab;
|
|
93
114
|
const isPrevious = this.isTransitioning && index === this.previousTab;
|
|
@@ -105,29 +126,23 @@ if (labels.length === 0) {
|
|
|
105
126
|
this.transitionDirection === 1
|
|
106
127
|
? 'rd-tabs-slide-in-from-right'
|
|
107
128
|
: 'rd-tabs-slide-in-from-left';
|
|
108
|
-
return `${base} opacity: 1; pointer-events: auto; visibility: visible; z-index: 2; animation: ${animationName} ${this.transitionDurationMs}ms
|
|
129
|
+
return `${base} opacity: 1; pointer-events: auto; visibility: visible; z-index: 2; animation: ${animationName} ${this.transitionDurationMs}ms ${this.transitionEasing} both;`;
|
|
109
130
|
}
|
|
110
131
|
|
|
111
132
|
const animationName =
|
|
112
133
|
this.transitionDirection === 1
|
|
113
134
|
? 'rd-tabs-slide-out-to-left'
|
|
114
135
|
: 'rd-tabs-slide-out-to-right';
|
|
115
|
-
return `${base} opacity: 1; pointer-events: none; visibility: visible; z-index: 1; animation: ${animationName} ${this.transitionDurationMs}ms
|
|
136
|
+
return `${base} opacity: 1; pointer-events: none; visibility: visible; z-index: 1; animation: ${animationName} ${this.transitionDurationMs}ms ${this.transitionEasing} both;`;
|
|
116
137
|
},
|
|
117
|
-
updateHeight(
|
|
138
|
+
updateHeight() {
|
|
118
139
|
this.$nextTick(() => {
|
|
119
140
|
const activeSlide = this.$refs['content-' + this.activeTab];
|
|
120
141
|
if (!activeSlide) return;
|
|
142
|
+
const activeContent = activeSlide.querySelector('[data-rd-tabs-panel-content]');
|
|
143
|
+
const measuredElement = activeContent || activeSlide;
|
|
121
144
|
|
|
122
|
-
|
|
123
|
-
if (includePrevious && this.previousTab !== null) {
|
|
124
|
-
const previousSlide = this.$refs['content-' + this.previousTab];
|
|
125
|
-
if (previousSlide) {
|
|
126
|
-
nextHeight = Math.max(nextHeight, previousSlide.scrollHeight);
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
this.containerHeight = nextHeight + 'px';
|
|
145
|
+
this.containerHeight = measuredElement.scrollHeight + 'px';
|
|
131
146
|
});
|
|
132
147
|
}
|
|
133
148
|
}"
|
|
@@ -167,19 +182,28 @@ class="rd-prose-block">
|
|
|
167
182
|
</ul>
|
|
168
183
|
|
|
169
184
|
<div
|
|
170
|
-
class="relative mt-4 overflow-
|
|
171
|
-
:style="'height: ' + containerHeight"
|
|
185
|
+
class="relative mt-4 overflow-visible transition-[height] motion-reduce:transition-none"
|
|
186
|
+
:style="'height: ' + containerHeight + '; transition-duration: ' + transitionDurationMs + 'ms; transition-timing-function: ' + transitionEasing + ';'"
|
|
172
187
|
>
|
|
173
|
-
|
|
174
|
-
<div
|
|
175
|
-
{
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
188
|
+
<div class="relative -mx-4 h-full overflow-x-clip overflow-y-visible">
|
|
189
|
+
<div class="relative mx-4 h-full">
|
|
190
|
+
{ tabContents.map((content, index) => (
|
|
191
|
+
<div
|
|
192
|
+
{...(index !== 0 ? { "x-cloak": true } : {})}
|
|
193
|
+
x-ref={`content-${index}`}
|
|
194
|
+
class="w-full"
|
|
195
|
+
:style={`getPanelStyle(${index})`}
|
|
196
|
+
style={index === 0 ? 'position: relative;' : ''}
|
|
197
|
+
>
|
|
198
|
+
<div
|
|
199
|
+
data-rd-tabs-panel-content
|
|
200
|
+
class="prose-rules w-full max-w-none! *:max-w-none!"
|
|
201
|
+
set:html={content}
|
|
202
|
+
/>
|
|
203
|
+
</div>
|
|
204
|
+
)) }
|
|
205
|
+
</div>
|
|
206
|
+
</div>
|
|
183
207
|
</div>
|
|
184
208
|
</div>
|
|
185
209
|
|
|
@@ -187,36 +211,44 @@ class="rd-prose-block">
|
|
|
187
211
|
@keyframes rd-tabs-slide-in-from-right {
|
|
188
212
|
from {
|
|
189
213
|
transform: translateX(100%);
|
|
214
|
+
opacity: 0;
|
|
190
215
|
}
|
|
191
216
|
to {
|
|
192
217
|
transform: translateX(0);
|
|
218
|
+
opacity: 1;
|
|
193
219
|
}
|
|
194
220
|
}
|
|
195
221
|
|
|
196
222
|
@keyframes rd-tabs-slide-in-from-left {
|
|
197
223
|
from {
|
|
198
224
|
transform: translateX(-100%);
|
|
225
|
+
opacity: 0;
|
|
199
226
|
}
|
|
200
227
|
to {
|
|
201
228
|
transform: translateX(0);
|
|
229
|
+
opacity: 1;
|
|
202
230
|
}
|
|
203
231
|
}
|
|
204
232
|
|
|
205
233
|
@keyframes rd-tabs-slide-out-to-left {
|
|
206
234
|
from {
|
|
207
235
|
transform: translateX(0);
|
|
236
|
+
opacity: 1;
|
|
208
237
|
}
|
|
209
238
|
to {
|
|
210
239
|
transform: translateX(-100%);
|
|
240
|
+
opacity: 0;
|
|
211
241
|
}
|
|
212
242
|
}
|
|
213
243
|
|
|
214
244
|
@keyframes rd-tabs-slide-out-to-right {
|
|
215
245
|
from {
|
|
216
246
|
transform: translateX(0);
|
|
247
|
+
opacity: 1;
|
|
217
248
|
}
|
|
218
249
|
to {
|
|
219
250
|
transform: translateX(100%);
|
|
251
|
+
opacity: 0;
|
|
220
252
|
}
|
|
221
253
|
}
|
|
222
254
|
</style>
|
|
@@ -55,12 +55,14 @@
|
|
|
55
55
|
--border-light: var(--color-neutral-100);
|
|
56
56
|
--input: oklch(0.922 0 0);
|
|
57
57
|
--ring: oklch(0.708 0 0);
|
|
58
|
+
--rd-panel-transition-duration-ms: 400;
|
|
59
|
+
--rd-panel-transition-duration: 400ms;
|
|
60
|
+
--rd-panel-transition-easing: cubic-bezier(0.22, 1, 0.36, 1);
|
|
58
61
|
--rd-code-surface: color-mix(
|
|
59
62
|
in srgb,
|
|
60
63
|
var(--color-neutral-100) 60%,
|
|
61
64
|
var(--background) 40%
|
|
62
65
|
);
|
|
63
|
-
--rd-code-header-surface: var(--color-white);
|
|
64
66
|
--rd-code-tab-edge-bg: var(--rd-code-surface);
|
|
65
67
|
--rd-code-tab-edge-border: color-mix(
|
|
66
68
|
in oklab,
|
|
@@ -94,11 +96,6 @@
|
|
|
94
96
|
var(--color-neutral-800) 55%,
|
|
95
97
|
var(--color-neutral-900) 45%
|
|
96
98
|
);
|
|
97
|
-
--rd-code-header-surface: color-mix(
|
|
98
|
-
in srgb,
|
|
99
|
-
var(--color-neutral-900) 100%,
|
|
100
|
-
var(--rd-code-surface) 0%
|
|
101
|
-
);
|
|
102
99
|
--rd-code-tab-edge-bg: var(--rd-code-surface);
|
|
103
100
|
--rd-code-tab-edge-border: color-mix(
|
|
104
101
|
in oklab,
|