@baybreezy/docd 0.0.1
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/app/app.config.ts +239 -0
- package/app/app.vue +19 -0
- package/app/assets/css/tailwind.css +335 -0
- package/app/assets/css/theme.css +1171 -0
- package/app/components/OgImage/Docs.takumi.vue +69 -0
- package/app/components/OgImage/Landing.takumi.vue +64 -0
- package/app/components/OgImage/Site.takumi.vue +32 -0
- package/app/components/Ui/Avatar/Avatar.vue +75 -0
- package/app/components/Ui/Avatar/Badge.vue +34 -0
- package/app/components/Ui/Avatar/Fallback.vue +30 -0
- package/app/components/Ui/Avatar/Group.vue +29 -0
- package/app/components/Ui/Avatar/GroupCount.vue +29 -0
- package/app/components/Ui/Avatar/Image.vue +29 -0
- package/app/components/Ui/Badge.vue +86 -0
- package/app/components/Ui/BadgeGroup.vue +314 -0
- package/app/components/Ui/BgPattern/Grid.vue +137 -0
- package/app/components/Ui/BorderBeam.vue +97 -0
- package/app/components/Ui/Breadcrumbs.vue +103 -0
- package/app/components/Ui/Button.vue +169 -0
- package/app/components/Ui/ButtonGroup/ButtonGroup.vue +54 -0
- package/app/components/Ui/ButtonGroup/Separator.vue +38 -0
- package/app/components/Ui/ButtonGroup/Text.vue +33 -0
- package/app/components/Ui/Card/Action.vue +31 -0
- package/app/components/Ui/Card/Card.vue +58 -0
- package/app/components/Ui/Card/Content.vue +34 -0
- package/app/components/Ui/Card/Description.vue +36 -0
- package/app/components/Ui/Card/Footer.vue +31 -0
- package/app/components/Ui/Card/Header.vue +31 -0
- package/app/components/Ui/Card/Title.vue +37 -0
- package/app/components/Ui/Collapsible/Collapsible.vue +16 -0
- package/app/components/Ui/Collapsible/Content.vue +27 -0
- package/app/components/Ui/Collapsible/Trigger.vue +13 -0
- package/app/components/Ui/Command/Command.vue +115 -0
- package/app/components/Ui/Command/Dialog.vue +65 -0
- package/app/components/Ui/Command/Empty.vue +32 -0
- package/app/components/Ui/Command/Footer.vue +40 -0
- package/app/components/Ui/Command/Group.vue +58 -0
- package/app/components/Ui/Command/Input.vue +57 -0
- package/app/components/Ui/Command/Item.vue +102 -0
- package/app/components/Ui/Command/List.vue +33 -0
- package/app/components/Ui/Command/Separator.vue +30 -0
- package/app/components/Ui/Command/Shortcut.vue +28 -0
- package/app/components/Ui/Container.vue +46 -0
- package/app/components/Ui/ContextMenu/Arrow.vue +43 -0
- package/app/components/Ui/ContextMenu/CheckboxItem.vue +42 -0
- package/app/components/Ui/ContextMenu/Content.vue +53 -0
- package/app/components/Ui/ContextMenu/ContextMenu.vue +14 -0
- package/app/components/Ui/ContextMenu/Group.vue +12 -0
- package/app/components/Ui/ContextMenu/Item.vue +65 -0
- package/app/components/Ui/ContextMenu/ItemIndicator.vue +30 -0
- package/app/components/Ui/ContextMenu/Label.vue +35 -0
- package/app/components/Ui/ContextMenu/Portal.vue +12 -0
- package/app/components/Ui/ContextMenu/RadioGroup.vue +16 -0
- package/app/components/Ui/ContextMenu/RadioItem.vue +40 -0
- package/app/components/Ui/ContextMenu/Separator.vue +25 -0
- package/app/components/Ui/ContextMenu/Shortcut.vue +30 -0
- package/app/components/Ui/ContextMenu/Sub.vue +15 -0
- package/app/components/Ui/ContextMenu/SubContent.vue +55 -0
- package/app/components/Ui/ContextMenu/SubTrigger.vue +42 -0
- package/app/components/Ui/ContextMenu/Trigger.vue +12 -0
- package/app/components/Ui/Dialog/Close.vue +12 -0
- package/app/components/Ui/Dialog/Content.vue +79 -0
- package/app/components/Ui/Dialog/Description.vue +29 -0
- package/app/components/Ui/Dialog/Dialog.vue +14 -0
- package/app/components/Ui/Dialog/Footer.vue +32 -0
- package/app/components/Ui/Dialog/Header.vue +32 -0
- package/app/components/Ui/Dialog/Overlay.vue +25 -0
- package/app/components/Ui/Dialog/Portal.vue +12 -0
- package/app/components/Ui/Dialog/Title.vue +29 -0
- package/app/components/Ui/Dialog/Trigger.vue +12 -0
- package/app/components/Ui/Divider.vue +102 -0
- package/app/components/Ui/Drawer/Close.vue +12 -0
- package/app/components/Ui/Drawer/Content.vue +67 -0
- package/app/components/Ui/Drawer/Description.vue +33 -0
- package/app/components/Ui/Drawer/Drawer.vue +17 -0
- package/app/components/Ui/Drawer/Footer.vue +35 -0
- package/app/components/Ui/Drawer/Header.vue +34 -0
- package/app/components/Ui/Drawer/Overlay.vue +20 -0
- package/app/components/Ui/Drawer/Portal.vue +12 -0
- package/app/components/Ui/Drawer/Title.vue +35 -0
- package/app/components/Ui/Drawer/Trigger.vue +12 -0
- package/app/components/Ui/DropdownMenu/Arrow.vue +43 -0
- package/app/components/Ui/DropdownMenu/CheckboxItem.vue +41 -0
- package/app/components/Ui/DropdownMenu/Content.vue +56 -0
- package/app/components/Ui/DropdownMenu/DropdownMenu.vue +15 -0
- package/app/components/Ui/DropdownMenu/Group.vue +12 -0
- package/app/components/Ui/DropdownMenu/Item.vue +64 -0
- package/app/components/Ui/DropdownMenu/ItemIndicator.vue +32 -0
- package/app/components/Ui/DropdownMenu/Label.vue +34 -0
- package/app/components/Ui/DropdownMenu/Portal.vue +12 -0
- package/app/components/Ui/DropdownMenu/RadioGroup.vue +16 -0
- package/app/components/Ui/DropdownMenu/RadioItem.vue +40 -0
- package/app/components/Ui/DropdownMenu/Separator.vue +25 -0
- package/app/components/Ui/DropdownMenu/Shortcut.vue +44 -0
- package/app/components/Ui/DropdownMenu/Sub.vue +14 -0
- package/app/components/Ui/DropdownMenu/SubContent.vue +56 -0
- package/app/components/Ui/DropdownMenu/SubTrigger.vue +47 -0
- package/app/components/Ui/DropdownMenu/Trigger.vue +12 -0
- package/app/components/Ui/FancyIcon.vue +243 -0
- package/app/components/Ui/GradientDivider.vue +26 -0
- package/app/components/Ui/IframeLazy.vue +97 -0
- package/app/components/Ui/Input.vue +97 -0
- package/app/components/Ui/InputGroup/Addon.vue +66 -0
- package/app/components/Ui/InputGroup/Button.vue +50 -0
- package/app/components/Ui/InputGroup/Input.vue +25 -0
- package/app/components/Ui/InputGroup/InputGroup.vue +44 -0
- package/app/components/Ui/InputGroup/Text.vue +33 -0
- package/app/components/Ui/InputGroup/Textarea.vue +25 -0
- package/app/components/Ui/Kbd/Group.vue +32 -0
- package/app/components/Ui/Kbd/Kbd.vue +62 -0
- package/app/components/Ui/Label.vue +40 -0
- package/app/components/Ui/Popover/Anchor.vue +13 -0
- package/app/components/Ui/Popover/Arrow.vue +42 -0
- package/app/components/Ui/Popover/Close.vue +13 -0
- package/app/components/Ui/Popover/Content.vue +55 -0
- package/app/components/Ui/Popover/Popover.vue +15 -0
- package/app/components/Ui/Popover/Portal.vue +13 -0
- package/app/components/Ui/Popover/Trigger.vue +12 -0
- package/app/components/Ui/Popover/X.vue +38 -0
- package/app/components/Ui/ScrollArea/Corner.vue +12 -0
- package/app/components/Ui/ScrollArea/ScrollArea.vue +38 -0
- package/app/components/Ui/ScrollArea/Scrollbar.vue +39 -0
- package/app/components/Ui/ScrollArea/Thumb.vue +39 -0
- package/app/components/Ui/ScrollArea/Viewport.vue +27 -0
- package/app/components/Ui/Scrollspy.vue +61 -0
- package/app/components/Ui/Separator.vue +40 -0
- package/app/components/Ui/Skeleton.vue +39 -0
- package/app/components/Ui/Sonner.vue +25 -0
- package/app/components/Ui/Tabs/Content.vue +27 -0
- package/app/components/Ui/Tabs/Indicator.vue +37 -0
- package/app/components/Ui/Tabs/List.vue +37 -0
- package/app/components/Ui/Tabs/Tabs.vue +25 -0
- package/app/components/Ui/Tabs/Trigger.vue +41 -0
- package/app/components/Ui/Textarea.vue +81 -0
- package/app/components/Ui/Tooltip/Arrow.vue +30 -0
- package/app/components/Ui/Tooltip/Content.vue +50 -0
- package/app/components/Ui/Tooltip/Portal.vue +12 -0
- package/app/components/Ui/Tooltip/Provider.vue +14 -0
- package/app/components/Ui/Tooltip/Tooltip.vue +25 -0
- package/app/components/Ui/Tooltip/Trigger.vue +12 -0
- package/app/components/Ui/Tree/Item.vue +15 -0
- package/app/components/Ui/Tree/Tree.vue +15 -0
- package/app/components/Ui/Tree/Virtualizer.vue +13 -0
- package/app/components/component-api/ComponentApiSection.vue +135 -0
- package/app/components/content/docs/Callout/DocsCallout.vue +99 -0
- package/app/components/content/prose/ProseA.global.vue +31 -0
- package/app/components/content/prose/ProseBlockquote.global.vue +28 -0
- package/app/components/content/prose/ProseCallout.global.vue +306 -0
- package/app/components/content/prose/ProseCard.global.vue +100 -0
- package/app/components/content/prose/ProseCodeCollapse.global.vue +125 -0
- package/app/components/content/prose/ProseCodeCopy.global.vue +67 -0
- package/app/components/content/prose/ProseCodeGroup.global.vue +104 -0
- package/app/components/content/prose/ProseCodeTree.global.vue +277 -0
- package/app/components/content/prose/ProseCollapsible.global.vue +64 -0
- package/app/components/content/prose/ProseColorModeImage.global.vue +58 -0
- package/app/components/content/prose/ProseComponentApi.global.vue +104 -0
- package/app/components/content/prose/ProseComponentEvents.global.vue +27 -0
- package/app/components/content/prose/ProseComponentExposed.global.vue +27 -0
- package/app/components/content/prose/ProseComponentProps.global.vue +27 -0
- package/app/components/content/prose/ProseComponentSlots.global.vue +27 -0
- package/app/components/content/prose/ProseEm.global.vue +5 -0
- package/app/components/content/prose/ProseField.global.vue +118 -0
- package/app/components/content/prose/ProseFieldGroup.global.vue +62 -0
- package/app/components/content/prose/ProseH1.global.vue +58 -0
- package/app/components/content/prose/ProseH2.global.vue +58 -0
- package/app/components/content/prose/ProseH3.global.vue +58 -0
- package/app/components/content/prose/ProseH4.global.vue +58 -0
- package/app/components/content/prose/ProseH5.global.vue +47 -0
- package/app/components/content/prose/ProseH6.global.vue +47 -0
- package/app/components/content/prose/ProseHr.global.vue +33 -0
- package/app/components/content/prose/ProseIconList.global.vue +113 -0
- package/app/components/content/prose/ProseImg.global.vue +119 -0
- package/app/components/content/prose/ProseLead.global.vue +28 -0
- package/app/components/content/prose/ProseLi.global.vue +25 -0
- package/app/components/content/prose/ProseMermaid.global.vue +127 -0
- package/app/components/content/prose/ProseOl.global.vue +25 -0
- package/app/components/content/prose/ProseP.global.vue +25 -0
- package/app/components/content/prose/ProsePmInstall.global.vue +60 -0
- package/app/components/content/prose/ProsePmRun.global.vue +51 -0
- package/app/components/content/prose/ProsePmX.global.vue +56 -0
- package/app/components/content/prose/ProsePre.global.vue +181 -0
- package/app/components/content/prose/ProseShowCase.global.vue +56 -0
- package/app/components/content/prose/ProseSmartIcon.global.vue +54 -0
- package/app/components/content/prose/ProseStep.global.vue +22 -0
- package/app/components/content/prose/ProseSteps.global.vue +22 -0
- package/app/components/content/prose/ProseStrong.global.vue +34 -0
- package/app/components/content/prose/ProseTable.global.vue +34 -0
- package/app/components/content/prose/ProseTabs.global.vue +104 -0
- package/app/components/content/prose/ProseTabsInner.global.vue +274 -0
- package/app/components/content/prose/ProseTbody.global.vue +5 -0
- package/app/components/content/prose/ProseTd.global.vue +25 -0
- package/app/components/content/prose/ProseTh.global.vue +25 -0
- package/app/components/content/prose/ProseThead.global.vue +9 -0
- package/app/components/content/prose/ProseTr.global.vue +35 -0
- package/app/components/content/prose/ProseUl.global.vue +25 -0
- package/app/components/docs/DocsExtraStuff.vue +39 -0
- package/app/components/docs/DocsGithubLink.vue +11 -0
- package/app/components/docs/DocsHeader.vue +3 -0
- package/app/components/docs/DocsLogo.vue +74 -0
- package/app/components/docs/DocsMobileBar.vue +26 -0
- package/app/components/docs/DocsMobileNav.vue +49 -0
- package/app/components/docs/DocsNav.vue +161 -0
- package/app/components/docs/DocsPageTransition.vue +32 -0
- package/app/components/docs/DocsSearch.vue +220 -0
- package/app/components/docs/DocsSearchButton.vue +20 -0
- package/app/components/docs/DocsThemeCustomizer.vue +229 -0
- package/app/components/docs/DocsThemeToggler.vue +98 -0
- package/app/components/docs/DocsTocRail.vue +162 -0
- package/app/components/docs/DocsToclink.vue +52 -0
- package/app/components/docs/DocsZigZagRail.vue +70 -0
- package/app/components/landing/Hero.vue +222 -0
- package/app/components/page/PageFooter.vue +49 -0
- package/app/components/page/PageHeader.vue +68 -0
- package/app/components/page/PageHeaderLinks.vue +138 -0
- package/app/components/page/PageMobileToc.vue +162 -0
- package/app/components/page/PageToc.vue +33 -0
- package/app/composables/useDefaultSlotItems.ts +90 -0
- package/app/composables/useDocPage.ts +66 -0
- package/app/composables/useDocSearch.ts +23 -0
- package/app/composables/useDocd.ts +107 -0
- package/app/composables/useLogoAssets.ts +319 -0
- package/app/composables/usePm.ts +73 -0
- package/app/composables/useProseComponentMeta.ts +30 -0
- package/app/composables/useScrollspy.ts +327 -0
- package/app/composables/useSeo.ts +240 -0
- package/app/composables/useUIConfig.ts +36 -0
- package/app/layouts/default.vue +5 -0
- package/app/layouts/docs.vue +64 -0
- package/app/middleware/colorMode.global.ts +8 -0
- package/app/middleware/doc-page-layout.ts +11 -0
- package/app/middleware/landing-page-layout.ts +11 -0
- package/app/pages/[...slug].vue +63 -0
- package/app/plugins/mermaid.client.ts +35 -0
- package/app/plugins/navigation-direction.client.ts +15 -0
- package/app/plugins/theme-restore.client.ts +7 -0
- package/app/templates/landing.vue +40 -0
- package/app/transitions/presets.ts +71 -0
- package/app/types/prose-component-meta.d.ts +4 -0
- package/app/utils/og.ts +26 -0
- package/app/utils/prerender.ts +9 -0
- package/app/utils/translucent.ts +56 -0
- package/app/utils/tw-helper.ts +4 -0
- package/content.config.ts +81 -0
- package/index.d.ts +25 -0
- package/modules/config.ts +89 -0
- package/modules/custom-icons.ts +17 -0
- package/modules/markdown-rewrite.ts +96 -0
- package/modules/prose-component-meta.ts +150 -0
- package/modules/routing.ts +22 -0
- package/modules/skills/index.ts +167 -0
- package/modules/skills/runtime/server/routes/skills-files.ts +49 -0
- package/modules/skills/runtime/server/routes/skills-index.ts +8 -0
- package/nuxt.config.ts +96 -0
- package/nuxt.schema.ts +288 -0
- package/package.json +95 -0
- package/server/mcp/tools/get-page.ts +66 -0
- package/server/mcp/tools/list-pages.ts +61 -0
- package/server/routes/sitemap.xml.ts +73 -0
- package/server/utils/content.ts +3 -0
- package/tailwind.config.cjs +55 -0
- package/utils/component-api-content.ts +467 -0
- package/utils/component-api-discovery.ts +165 -0
- package/utils/component-api-schema.ts +28 -0
- package/utils/component-api.ts +243 -0
- package/utils/generate-prose-component-meta.ts +303 -0
- package/utils/git.ts +123 -0
- package/utils/meta.ts +40 -0
- package/utils/pages.ts +21 -0
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="space-y-6">
|
|
3
|
+
<div>
|
|
4
|
+
<h3 class="mt-0">All Variants</h3>
|
|
5
|
+
<div class="space-y-4">
|
|
6
|
+
<ProseCallout variant="default" title="Default" description="This is a default callout." />
|
|
7
|
+
<ProseCallout variant="info" title="Info" description="This is an info callout." />
|
|
8
|
+
<ProseCallout variant="success" title="Success" description="This is a success callout." />
|
|
9
|
+
<ProseCallout variant="warning" title="Warning" description="This is a warning callout." />
|
|
10
|
+
<ProseCallout variant="error" title="Error" description="This is an error callout." />
|
|
11
|
+
<ProseCallout variant="tip" title="Tip" description="This is a tip callout." />
|
|
12
|
+
<ProseCallout variant="note" title="Note" description="This is a note callout." />
|
|
13
|
+
<ProseCallout variant="example" title="Example" description="This is an example callout." />
|
|
14
|
+
</div>
|
|
15
|
+
</div>
|
|
16
|
+
|
|
17
|
+
<div>
|
|
18
|
+
<h3>Filled Style</h3>
|
|
19
|
+
<div class="space-y-4">
|
|
20
|
+
<ProseCallout
|
|
21
|
+
variant="info"
|
|
22
|
+
title="Filled Info"
|
|
23
|
+
description="This uses the filled style."
|
|
24
|
+
filled
|
|
25
|
+
/>
|
|
26
|
+
<ProseCallout
|
|
27
|
+
variant="success"
|
|
28
|
+
title="Filled Success"
|
|
29
|
+
description="This uses the filled style."
|
|
30
|
+
filled
|
|
31
|
+
/>
|
|
32
|
+
<ProseCallout
|
|
33
|
+
variant="warning"
|
|
34
|
+
title="Filled Warning"
|
|
35
|
+
description="This uses the filled style."
|
|
36
|
+
filled
|
|
37
|
+
/>
|
|
38
|
+
<ProseCallout
|
|
39
|
+
variant="error"
|
|
40
|
+
title="Filled Error"
|
|
41
|
+
description="This uses the filled style."
|
|
42
|
+
filled
|
|
43
|
+
/>
|
|
44
|
+
</div>
|
|
45
|
+
</div>
|
|
46
|
+
|
|
47
|
+
<div>
|
|
48
|
+
<h3>With Slots</h3>
|
|
49
|
+
<ProseCallout variant="tip">
|
|
50
|
+
<template #icon>
|
|
51
|
+
<Icon name="lucide:sparkles" />
|
|
52
|
+
</template>
|
|
53
|
+
<template #title> Custom Slotted Title </template>
|
|
54
|
+
<template #default>
|
|
55
|
+
<p>This callout uses slots for maximum flexibility.</p>
|
|
56
|
+
<ul class="mt-2 list-inside list-disc space-y-1">
|
|
57
|
+
<li>Custom icon slot</li>
|
|
58
|
+
<li>Custom title slot</li>
|
|
59
|
+
<li>Custom content slot</li>
|
|
60
|
+
</ul>
|
|
61
|
+
</template>
|
|
62
|
+
</ProseCallout>
|
|
63
|
+
</div>
|
|
64
|
+
|
|
65
|
+
<div>
|
|
66
|
+
<h3>Clickable Callout</h3>
|
|
67
|
+
<ProseCallout
|
|
68
|
+
variant="info"
|
|
69
|
+
title="Learn More"
|
|
70
|
+
description="Click this callout to navigate to the documentation."
|
|
71
|
+
url="/docs"
|
|
72
|
+
/>
|
|
73
|
+
</div>
|
|
74
|
+
|
|
75
|
+
<div>
|
|
76
|
+
<h3>Custom Icons</h3>
|
|
77
|
+
<div class="space-y-4">
|
|
78
|
+
<ProseCallout
|
|
79
|
+
variant="success"
|
|
80
|
+
icon="lucide:trophy"
|
|
81
|
+
title="Achievement Unlocked"
|
|
82
|
+
description="You've earned a new badge!"
|
|
83
|
+
/>
|
|
84
|
+
<ProseCallout
|
|
85
|
+
variant="info"
|
|
86
|
+
icon="lucide:rocket"
|
|
87
|
+
title="Launch Ready"
|
|
88
|
+
description="Your application is ready to deploy."
|
|
89
|
+
/>
|
|
90
|
+
<ProseCallout
|
|
91
|
+
variant="tip"
|
|
92
|
+
icon="lucide:zap"
|
|
93
|
+
title="Performance Boost"
|
|
94
|
+
description="Enable caching for better performance."
|
|
95
|
+
/>
|
|
96
|
+
</div>
|
|
97
|
+
</div>
|
|
98
|
+
</div>
|
|
99
|
+
</template>
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<NuxtLink
|
|
3
|
+
data-slot="prose-a"
|
|
4
|
+
v-bind="rest"
|
|
5
|
+
:class="proseAStyles({ class: normalizeClass(_class) || undefined })"
|
|
6
|
+
>
|
|
7
|
+
<slot />
|
|
8
|
+
</NuxtLink>
|
|
9
|
+
</template>
|
|
10
|
+
|
|
11
|
+
<script lang="ts">
|
|
12
|
+
import { normalizeClass } from "vue";
|
|
13
|
+
import type { HTMLAttributes } from "vue";
|
|
14
|
+
|
|
15
|
+
import type { NuxtLinkProps } from "#app";
|
|
16
|
+
|
|
17
|
+
export type ProseAProps = NuxtLinkProps & {
|
|
18
|
+
/**
|
|
19
|
+
* Additional classes for the parent element
|
|
20
|
+
*/
|
|
21
|
+
class?: HTMLAttributes["class"];
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
export const proseAStyles = tv({
|
|
25
|
+
base: "font-semibold text-inherit underline underline-offset-4",
|
|
26
|
+
});
|
|
27
|
+
</script>
|
|
28
|
+
|
|
29
|
+
<script setup lang="ts">
|
|
30
|
+
const { class: _class, ...rest } = defineProps<ProseAProps>();
|
|
31
|
+
</script>
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<blockquote
|
|
3
|
+
data-slot="prose-blockquote"
|
|
4
|
+
:class="proseBlockquoteStyles({ class: normalizeClass(_class) || undefined })"
|
|
5
|
+
>
|
|
6
|
+
<slot />
|
|
7
|
+
</blockquote>
|
|
8
|
+
</template>
|
|
9
|
+
|
|
10
|
+
<script lang="ts">
|
|
11
|
+
import { normalizeClass } from "vue";
|
|
12
|
+
import type { HTMLAttributes } from "vue";
|
|
13
|
+
|
|
14
|
+
export type ProseBlockquoteProps = {
|
|
15
|
+
/**
|
|
16
|
+
* Additional classes for the parent element
|
|
17
|
+
*/
|
|
18
|
+
class?: HTMLAttributes["class"];
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
export const proseBlockquoteStyles = tv({
|
|
22
|
+
base: "border-l-2 pl-6 text-pretty italic not-first:mt-6",
|
|
23
|
+
});
|
|
24
|
+
</script>
|
|
25
|
+
|
|
26
|
+
<script setup lang="ts">
|
|
27
|
+
const { class: _class } = defineProps<ProseBlockquoteProps>();
|
|
28
|
+
</script>
|
|
@@ -0,0 +1,306 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<component
|
|
3
|
+
:is="componentType"
|
|
4
|
+
v-bind="linkProps"
|
|
5
|
+
data-slot="prose-callout"
|
|
6
|
+
:class="
|
|
7
|
+
calloutStyles().base({ variant, filled, class: normalizeClass(props.class) || undefined })
|
|
8
|
+
"
|
|
9
|
+
>
|
|
10
|
+
<div v-if="hasIcon" :class="calloutStyles().iconWrapper({ variant, filled })">
|
|
11
|
+
<slot name="icon">
|
|
12
|
+
<Icon
|
|
13
|
+
v-if="computedIcon"
|
|
14
|
+
:name="computedIcon"
|
|
15
|
+
:class="
|
|
16
|
+
calloutStyles().icon({
|
|
17
|
+
variant,
|
|
18
|
+
filled,
|
|
19
|
+
class: [normalizeClass(iconClass), !hasTitle && 'mt-0.75'],
|
|
20
|
+
})
|
|
21
|
+
"
|
|
22
|
+
/>
|
|
23
|
+
</slot>
|
|
24
|
+
</div>
|
|
25
|
+
|
|
26
|
+
<div :class="calloutStyles().content()">
|
|
27
|
+
<div
|
|
28
|
+
v-if="hasTitle"
|
|
29
|
+
:class="
|
|
30
|
+
calloutStyles().title({ variant, filled, class: normalizeClass(titleClass) || undefined })
|
|
31
|
+
"
|
|
32
|
+
>
|
|
33
|
+
<slot name="title">{{ title }}</slot>
|
|
34
|
+
</div>
|
|
35
|
+
|
|
36
|
+
<div
|
|
37
|
+
v-if="hasDescription || $slots.default"
|
|
38
|
+
:class="
|
|
39
|
+
calloutStyles().description({
|
|
40
|
+
variant,
|
|
41
|
+
filled,
|
|
42
|
+
class: normalizeClass(descriptionClass) || undefined,
|
|
43
|
+
})
|
|
44
|
+
"
|
|
45
|
+
>
|
|
46
|
+
<slot mdc-unwrap="p">{{ description }}</slot>
|
|
47
|
+
</div>
|
|
48
|
+
</div>
|
|
49
|
+
|
|
50
|
+
<Icon
|
|
51
|
+
v-if="url"
|
|
52
|
+
:name="target === '_blank' ? 'lucide:external-link' : 'lucide:arrow-up-right'"
|
|
53
|
+
:class="calloutStyles().linkIcon({ variant, filled })"
|
|
54
|
+
/>
|
|
55
|
+
</component>
|
|
56
|
+
</template>
|
|
57
|
+
|
|
58
|
+
<script lang="ts">
|
|
59
|
+
import type { VariantProps } from "tailwind-variants";
|
|
60
|
+
import { normalizeClass } from "vue";
|
|
61
|
+
import type { HTMLAttributes } from "vue";
|
|
62
|
+
|
|
63
|
+
export type CalloutProps = {
|
|
64
|
+
/**
|
|
65
|
+
* The title of the callout
|
|
66
|
+
*/
|
|
67
|
+
title?: string;
|
|
68
|
+
/**
|
|
69
|
+
* The description/content of the callout
|
|
70
|
+
*/
|
|
71
|
+
description?: string;
|
|
72
|
+
/**
|
|
73
|
+
* The icon to display
|
|
74
|
+
*/
|
|
75
|
+
icon?: string;
|
|
76
|
+
/**
|
|
77
|
+
* The variant style of the callout
|
|
78
|
+
*/
|
|
79
|
+
variant?: VariantProps<typeof calloutStyles>["variant"];
|
|
80
|
+
/**
|
|
81
|
+
* Whether to use filled style
|
|
82
|
+
*/
|
|
83
|
+
filled?: boolean;
|
|
84
|
+
/**
|
|
85
|
+
* Optional URL to make the callout clickable
|
|
86
|
+
*/
|
|
87
|
+
url?: string;
|
|
88
|
+
/**
|
|
89
|
+
* Link target (_blank for external links)
|
|
90
|
+
*/
|
|
91
|
+
target?: "_blank" | "_self" | "_parent" | "_top";
|
|
92
|
+
/**
|
|
93
|
+
* Additional class for the wrapper
|
|
94
|
+
*/
|
|
95
|
+
class?: HTMLAttributes["class"];
|
|
96
|
+
/**
|
|
97
|
+
* Additional class for the title
|
|
98
|
+
*/
|
|
99
|
+
titleClass?: HTMLAttributes["class"];
|
|
100
|
+
/**
|
|
101
|
+
* Additional class for the description
|
|
102
|
+
*/
|
|
103
|
+
descriptionClass?: HTMLAttributes["class"];
|
|
104
|
+
/**
|
|
105
|
+
* Additional class for the icon
|
|
106
|
+
*/
|
|
107
|
+
iconClass?: HTMLAttributes["class"];
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
export const calloutStyles = tv({
|
|
111
|
+
slots: {
|
|
112
|
+
base: "group relative flex items-start gap-3 rounded-lg border p-4 no-underline transition-colors not-first:mt-6 not-last:mb-6 [&_code]:bg-inherit! [&_code]:text-inherit! [&_li]:marker:text-inherit! [&_ol]:my-2! [&_ul]:my-2!",
|
|
113
|
+
iconWrapper: "flex items-center justify-center",
|
|
114
|
+
icon: "size-4 shrink-0",
|
|
115
|
+
content: "flex flex-1 flex-col gap-1",
|
|
116
|
+
title: "text-sm leading-none font-semibold",
|
|
117
|
+
description: "text-sm leading-relaxed *:my-0",
|
|
118
|
+
linkIcon:
|
|
119
|
+
"size-4 shrink-0 opacity-50 transition-transform group-hover:translate-x-1 group-hover:-translate-y-1 group-hover:text-inherit group-hover:opacity-100",
|
|
120
|
+
},
|
|
121
|
+
variants: {
|
|
122
|
+
variant: {
|
|
123
|
+
default: {
|
|
124
|
+
base: "border-border bg-muted/50 text-foreground dark:bg-transparent",
|
|
125
|
+
icon: "text-foreground",
|
|
126
|
+
title: "text-foreground",
|
|
127
|
+
},
|
|
128
|
+
info: {
|
|
129
|
+
base: "border-blue-200 bg-blue-50 text-blue-900 dark:border-blue-800 dark:bg-blue-950 dark:text-blue-100",
|
|
130
|
+
icon: "text-blue-600 dark:text-blue-400",
|
|
131
|
+
title: "text-blue-900 dark:text-blue-100",
|
|
132
|
+
description: "text-blue-800 dark:text-blue-200",
|
|
133
|
+
linkIcon: "text-blue-600 dark:text-blue-400",
|
|
134
|
+
},
|
|
135
|
+
success: {
|
|
136
|
+
base: "border-emerald-200 bg-emerald-50 text-emerald-900 dark:border-emerald-800 dark:bg-emerald-950 dark:text-emerald-100",
|
|
137
|
+
icon: "text-emerald-600 dark:text-emerald-400",
|
|
138
|
+
title: "text-emerald-900 dark:text-emerald-100",
|
|
139
|
+
description: "text-emerald-800 dark:text-emerald-200",
|
|
140
|
+
linkIcon: "text-emerald-600 dark:text-emerald-400",
|
|
141
|
+
},
|
|
142
|
+
warning: {
|
|
143
|
+
base: "border-yellow-200 bg-yellow-50 text-yellow-900 dark:border-yellow-800 dark:bg-yellow-950 dark:text-yellow-100",
|
|
144
|
+
icon: "text-yellow-600 dark:text-yellow-400",
|
|
145
|
+
title: "text-yellow-900 dark:text-yellow-100",
|
|
146
|
+
description: "text-yellow-800 dark:text-yellow-200",
|
|
147
|
+
linkIcon: "text-yellow-600 dark:text-yellow-400",
|
|
148
|
+
},
|
|
149
|
+
error: {
|
|
150
|
+
base: "border-red-200 bg-red-50 text-red-900 dark:border-red-800 dark:bg-red-950 dark:text-red-100",
|
|
151
|
+
icon: "text-red-600 dark:text-red-400",
|
|
152
|
+
title: "text-red-900 dark:text-red-100",
|
|
153
|
+
description: "text-red-800 dark:text-red-200",
|
|
154
|
+
linkIcon: "text-red-600 dark:text-red-400",
|
|
155
|
+
},
|
|
156
|
+
tip: {
|
|
157
|
+
base: "border-purple-200 bg-purple-50 text-purple-900 dark:border-purple-800 dark:bg-purple-950 dark:text-purple-100",
|
|
158
|
+
icon: "text-purple-600 dark:text-purple-400",
|
|
159
|
+
title: "text-purple-900 dark:text-purple-100",
|
|
160
|
+
description: "text-purple-800 dark:text-purple-200",
|
|
161
|
+
linkIcon: "text-purple-600 dark:text-purple-400",
|
|
162
|
+
},
|
|
163
|
+
note: {
|
|
164
|
+
base: "border-gray-200 bg-gray-50 text-gray-900 dark:border-gray-700 dark:bg-gray-900 dark:text-gray-100",
|
|
165
|
+
icon: "text-gray-600 dark:text-gray-400",
|
|
166
|
+
title: "text-gray-900 dark:text-gray-100",
|
|
167
|
+
description: "text-gray-800 dark:text-gray-200",
|
|
168
|
+
linkIcon: "text-gray-600 dark:text-gray-400",
|
|
169
|
+
},
|
|
170
|
+
example: {
|
|
171
|
+
base: "border-teal-200 bg-teal-50 text-teal-900 dark:border-teal-800 dark:bg-teal-950 dark:text-teal-100",
|
|
172
|
+
icon: "text-teal-600 dark:text-teal-400",
|
|
173
|
+
title: "text-teal-900 dark:text-teal-100",
|
|
174
|
+
description: "text-teal-800 dark:text-teal-200",
|
|
175
|
+
linkIcon: "text-teal-600 dark:text-teal-400",
|
|
176
|
+
},
|
|
177
|
+
},
|
|
178
|
+
filled: {
|
|
179
|
+
true: {},
|
|
180
|
+
},
|
|
181
|
+
},
|
|
182
|
+
compoundVariants: [
|
|
183
|
+
{
|
|
184
|
+
filled: true,
|
|
185
|
+
class: {
|
|
186
|
+
title: "text-white dark:text-white",
|
|
187
|
+
icon: "text-white dark:text-white",
|
|
188
|
+
},
|
|
189
|
+
},
|
|
190
|
+
{
|
|
191
|
+
variant: "info",
|
|
192
|
+
filled: true,
|
|
193
|
+
class: {
|
|
194
|
+
base: "border-blue-600 bg-blue-600 text-white dark:border-blue-500 dark:bg-blue-500",
|
|
195
|
+
description: "text-blue-50",
|
|
196
|
+
},
|
|
197
|
+
},
|
|
198
|
+
{
|
|
199
|
+
variant: "success",
|
|
200
|
+
filled: true,
|
|
201
|
+
class: {
|
|
202
|
+
base: "border-emerald-600 bg-emerald-600 text-white dark:border-emerald-500 dark:bg-emerald-500",
|
|
203
|
+
description: "text-emerald-50",
|
|
204
|
+
},
|
|
205
|
+
},
|
|
206
|
+
{
|
|
207
|
+
variant: "warning",
|
|
208
|
+
filled: true,
|
|
209
|
+
class: {
|
|
210
|
+
base: "border-yellow-600 bg-yellow-600 text-white dark:border-yellow-500 dark:bg-yellow-500",
|
|
211
|
+
description: "text-yellow-50",
|
|
212
|
+
},
|
|
213
|
+
},
|
|
214
|
+
{
|
|
215
|
+
variant: "error",
|
|
216
|
+
filled: true,
|
|
217
|
+
class: {
|
|
218
|
+
base: "border-red-600 bg-red-600 text-white dark:border-red-500 dark:bg-red-500",
|
|
219
|
+
description: "text-red-50",
|
|
220
|
+
},
|
|
221
|
+
},
|
|
222
|
+
{
|
|
223
|
+
variant: "tip",
|
|
224
|
+
filled: true,
|
|
225
|
+
class: {
|
|
226
|
+
base: "border-purple-600 bg-purple-600 text-white dark:border-purple-500 dark:bg-purple-500",
|
|
227
|
+
|
|
228
|
+
description: "text-purple-50",
|
|
229
|
+
},
|
|
230
|
+
},
|
|
231
|
+
{
|
|
232
|
+
variant: "note",
|
|
233
|
+
filled: true,
|
|
234
|
+
class: {
|
|
235
|
+
base: "border-gray-600 bg-gray-600 text-white dark:border-gray-500 dark:bg-gray-500",
|
|
236
|
+
|
|
237
|
+
description: "text-gray-50",
|
|
238
|
+
},
|
|
239
|
+
},
|
|
240
|
+
{
|
|
241
|
+
variant: "example",
|
|
242
|
+
filled: true,
|
|
243
|
+
class: {
|
|
244
|
+
base: "border-teal-600 bg-teal-600 text-white dark:border-teal-500 dark:bg-teal-500",
|
|
245
|
+
description: "text-teal-50",
|
|
246
|
+
},
|
|
247
|
+
},
|
|
248
|
+
],
|
|
249
|
+
defaultVariants: {
|
|
250
|
+
variant: "default",
|
|
251
|
+
filled: false,
|
|
252
|
+
},
|
|
253
|
+
});
|
|
254
|
+
|
|
255
|
+
const VARIANT_ICONS: Record<string, string> = {
|
|
256
|
+
info: "lucide:info",
|
|
257
|
+
success: "lucide:circle-check",
|
|
258
|
+
warning: "lucide:triangle-alert",
|
|
259
|
+
error: "lucide:circle-x",
|
|
260
|
+
tip: "lucide:lightbulb",
|
|
261
|
+
note: "lucide:sticky-note",
|
|
262
|
+
example: "lucide:code-2",
|
|
263
|
+
default: "lucide:info",
|
|
264
|
+
};
|
|
265
|
+
</script>
|
|
266
|
+
|
|
267
|
+
<script setup lang="ts">
|
|
268
|
+
const props = withDefaults(defineProps<CalloutProps>(), {
|
|
269
|
+
variant: "default",
|
|
270
|
+
filled: false,
|
|
271
|
+
target: "_self",
|
|
272
|
+
noPrefetch: false,
|
|
273
|
+
});
|
|
274
|
+
|
|
275
|
+
defineSlots<{
|
|
276
|
+
/** Default slot content */
|
|
277
|
+
default?: () => void;
|
|
278
|
+
/** Title slot content */
|
|
279
|
+
title?: () => void;
|
|
280
|
+
/** Icon slot content */
|
|
281
|
+
icon?: () => void;
|
|
282
|
+
}>();
|
|
283
|
+
|
|
284
|
+
const slots = useSlots();
|
|
285
|
+
|
|
286
|
+
const componentType = computed(() => (props.url ? resolveComponent("NuxtLink") : "div"));
|
|
287
|
+
|
|
288
|
+
const linkProps = computed(() => {
|
|
289
|
+
if (!props.url) return {};
|
|
290
|
+
return {
|
|
291
|
+
to: props.url,
|
|
292
|
+
target: props.target,
|
|
293
|
+
rel: props.target === "_blank" ? "noopener noreferrer" : undefined,
|
|
294
|
+
class: tw`cursor-pointer no-underline! transition-all! duration-300 hover:shadow-md`,
|
|
295
|
+
};
|
|
296
|
+
});
|
|
297
|
+
|
|
298
|
+
const hasIcon = computed(() => props.icon || slots.icon || props.variant);
|
|
299
|
+
const hasTitle = computed(() => props.title || slots.title);
|
|
300
|
+
const hasDescription = computed(() => props.description || slots.default);
|
|
301
|
+
|
|
302
|
+
const computedIcon = computed(() => {
|
|
303
|
+
if (props.icon) return props.icon;
|
|
304
|
+
return VARIANT_ICONS[props.variant || "default"] || VARIANT_ICONS.default;
|
|
305
|
+
});
|
|
306
|
+
</script>
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<component
|
|
3
|
+
v-bind="linkProps"
|
|
4
|
+
:is="as"
|
|
5
|
+
:class="proseCardStyles().base({ class: normalizeClass(props.class) || undefined })"
|
|
6
|
+
data-slot="prose-card"
|
|
7
|
+
>
|
|
8
|
+
<slot name="icon" mdc-unwrap="p">
|
|
9
|
+
<ProseSmartIcon v-if="icon" :name="icon" :class="proseCardStyles().icon()" />
|
|
10
|
+
</slot>
|
|
11
|
+
<slot name="title" mdc-unwrap="p">
|
|
12
|
+
<h3 v-if="title" data-slot="prose-card-title" :class="proseCardStyles().title()">
|
|
13
|
+
{{ title }}
|
|
14
|
+
</h3>
|
|
15
|
+
</slot>
|
|
16
|
+
<slot mdc-unwrap="p">
|
|
17
|
+
<p
|
|
18
|
+
v-if="description"
|
|
19
|
+
data-slot="prose-card-description"
|
|
20
|
+
:class="proseCardStyles().description()"
|
|
21
|
+
>
|
|
22
|
+
{{ description }}
|
|
23
|
+
</p>
|
|
24
|
+
</slot>
|
|
25
|
+
<slot name="footer"></slot>
|
|
26
|
+
<div v-if="to || href" class="absolute top-4 right-4">
|
|
27
|
+
<Icon
|
|
28
|
+
name="lucide:arrow-up-right"
|
|
29
|
+
class="size-5 scale-0 opacity-80 transition-all duration-200 group-hover:scale-100"
|
|
30
|
+
/>
|
|
31
|
+
</div>
|
|
32
|
+
<UiBorderBeam :duration="20" :size="100" class="opacity-0 group-hover:opacity-100" />
|
|
33
|
+
</component>
|
|
34
|
+
</template>
|
|
35
|
+
|
|
36
|
+
<script lang="ts">
|
|
37
|
+
import { normalizeClass } from "vue";
|
|
38
|
+
import type { HTMLAttributes } from "vue";
|
|
39
|
+
|
|
40
|
+
import type { NuxtLinkProps } from "#app";
|
|
41
|
+
|
|
42
|
+
export const proseCardStyles = tv({
|
|
43
|
+
slots: {
|
|
44
|
+
base: "group relative flex flex-col gap-2 rounded-lg border border-border/50 bg-card p-6 text-card-foreground no-underline! shadow-xs *:my-0!",
|
|
45
|
+
icon: "size-6 text-muted-foreground",
|
|
46
|
+
title: "not-prose text-lg font-semibold tracking-tight text-foreground",
|
|
47
|
+
description: "text-[15px] text-muted-foreground first:mt-0 last:mb-0",
|
|
48
|
+
},
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
export type ProseCardProps = NuxtLinkProps & {
|
|
52
|
+
/**
|
|
53
|
+
* Additional classes for the card wrapper
|
|
54
|
+
*/
|
|
55
|
+
class?: HTMLAttributes["class"];
|
|
56
|
+
/**
|
|
57
|
+
* Title of the card
|
|
58
|
+
*/
|
|
59
|
+
title?: string;
|
|
60
|
+
/**
|
|
61
|
+
* Description/content of the card
|
|
62
|
+
*/
|
|
63
|
+
description?: string;
|
|
64
|
+
/**
|
|
65
|
+
* Icon name to display in the card
|
|
66
|
+
*/
|
|
67
|
+
icon?: string;
|
|
68
|
+
};
|
|
69
|
+
</script>
|
|
70
|
+
|
|
71
|
+
<script lang="ts" setup>
|
|
72
|
+
const props = withDefaults(defineProps<ProseCardProps>(), {});
|
|
73
|
+
|
|
74
|
+
defineSlots<{
|
|
75
|
+
/**
|
|
76
|
+
* Slot for the card title
|
|
77
|
+
*/
|
|
78
|
+
title: () => any;
|
|
79
|
+
/**
|
|
80
|
+
* Slot for the card description/content
|
|
81
|
+
*/
|
|
82
|
+
default: () => any;
|
|
83
|
+
/**
|
|
84
|
+
* Slot for an icon to display in the card
|
|
85
|
+
*/
|
|
86
|
+
icon: () => any;
|
|
87
|
+
/**
|
|
88
|
+
* Slot for the card footer
|
|
89
|
+
*/
|
|
90
|
+
footer: () => any;
|
|
91
|
+
}>();
|
|
92
|
+
|
|
93
|
+
const linkProps = computed(() => {
|
|
94
|
+
if (!(props.to || props.href)) return {};
|
|
95
|
+
|
|
96
|
+
return reactiveOmit(props, ["class", "title", "description", "icon"]);
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
const as = computed(() => (props.to || props.href ? resolveComponent("NuxtLink") : "div"));
|
|
100
|
+
</script>
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div :class="styles.root({ class: normalizeClass([props.class]) || undefined, open })">
|
|
3
|
+
<slot />
|
|
4
|
+
<div :class="styles.footer({ open })">
|
|
5
|
+
<button
|
|
6
|
+
:class="styles.trigger({ open })"
|
|
7
|
+
variant="outline"
|
|
8
|
+
:aria-expanded="open"
|
|
9
|
+
:aria-label="`${open ? 'Collapse' : 'Expand'} ${props.name}`"
|
|
10
|
+
:data-state="open ? 'open' : 'closed'"
|
|
11
|
+
@click="open = !open"
|
|
12
|
+
>
|
|
13
|
+
<ProseSmartIcon
|
|
14
|
+
v-if="props.icon"
|
|
15
|
+
:name="props.icon"
|
|
16
|
+
:class="styles.triggerIcon()"
|
|
17
|
+
aria-hidden="true"
|
|
18
|
+
/>
|
|
19
|
+
<span>{{ open ? props.closeText : props.openText }} {{ props.name }}</span>
|
|
20
|
+
</button>
|
|
21
|
+
</div>
|
|
22
|
+
</div>
|
|
23
|
+
</template>
|
|
24
|
+
|
|
25
|
+
<script lang="ts">
|
|
26
|
+
import { normalizeClass } from "vue";
|
|
27
|
+
import type { HTMLAttributes } from "vue";
|
|
28
|
+
|
|
29
|
+
export interface ProseCodeCollapseProps {
|
|
30
|
+
/**
|
|
31
|
+
* The icon displayed to toggle the code collapse state
|
|
32
|
+
* @default "lucide:chevron-down"
|
|
33
|
+
* @example "lucide:code" | "heroicons:chevron-down"
|
|
34
|
+
*/
|
|
35
|
+
icon?: string;
|
|
36
|
+
/**
|
|
37
|
+
* The name/label displayed in the trigger button
|
|
38
|
+
* @default "Code"
|
|
39
|
+
* @example "Implementation" | "Full Code" | "Example"
|
|
40
|
+
*/
|
|
41
|
+
name?: string;
|
|
42
|
+
/**
|
|
43
|
+
* The text displayed when the code is collapsed (clickable to expand)
|
|
44
|
+
* @default "Expand"
|
|
45
|
+
* @example "Show" | "View" | "Display"
|
|
46
|
+
*/
|
|
47
|
+
openText?: string;
|
|
48
|
+
/**
|
|
49
|
+
* The text displayed when the code is expanded (clickable to collapse)
|
|
50
|
+
* @default "Collapse"
|
|
51
|
+
* @example "Hide" | "Minimize" | "Close"
|
|
52
|
+
*/
|
|
53
|
+
closeText?: string;
|
|
54
|
+
/**
|
|
55
|
+
* Additional CSS classes for the root container
|
|
56
|
+
*/
|
|
57
|
+
class?: HTMLAttributes["class"];
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Tailwind variant styles for the code collapse component
|
|
62
|
+
* Uses slots pattern for multi-part component styling with open/closed states
|
|
63
|
+
*/
|
|
64
|
+
export const proseCodeCollapseStyles = tv({
|
|
65
|
+
slots: {
|
|
66
|
+
root: "relative [&_pre]:h-50",
|
|
67
|
+
footer: "absolute inset-x-px bottom-px flex h-20 items-center justify-center rounded-b-md",
|
|
68
|
+
trigger:
|
|
69
|
+
"group flex items-center gap-2 rounded-md bg-accent py-1.5 ps-1.5 pe-3 text-sm font-medium transition-all duration-200 hover:scale-103 hover:bg-accent hover:text-foreground",
|
|
70
|
+
triggerIcon: "text-muted-foreground transition-transform group-data-[state=open]:rotate-180",
|
|
71
|
+
},
|
|
72
|
+
variants: {
|
|
73
|
+
open: {
|
|
74
|
+
true: {
|
|
75
|
+
root: "[&_pre]:h-auto [&_pre]:max-h-[80vh] [&_pre]:min-h-50 [&_pre]:pb-12",
|
|
76
|
+
trigger: "bg-accent ring-1 ring-muted dark:ring-border",
|
|
77
|
+
},
|
|
78
|
+
false: {
|
|
79
|
+
root: "[&_pre]:overflow-hidden",
|
|
80
|
+
footer: "bg-linear-to-t from-foreground/10 dark:from-muted/80",
|
|
81
|
+
},
|
|
82
|
+
},
|
|
83
|
+
},
|
|
84
|
+
});
|
|
85
|
+
</script>
|
|
86
|
+
|
|
87
|
+
<script lang="ts" setup>
|
|
88
|
+
/**
|
|
89
|
+
* ProseCodeCollapse - Collapsible code block wrapper
|
|
90
|
+
*
|
|
91
|
+
* Wraps code blocks and provides a toggle button to show/hide content.
|
|
92
|
+
* Useful for long code examples that would take up too much vertical space.
|
|
93
|
+
* Initial height is limited to 200px with a gradient fade effect.
|
|
94
|
+
*
|
|
95
|
+
* @example
|
|
96
|
+
* ```vue
|
|
97
|
+
* <ProseCodeCollapse
|
|
98
|
+
* name="Full Implementation"
|
|
99
|
+
* icon="lucide:code"
|
|
100
|
+
* open-text="Show"
|
|
101
|
+
* close-text="Hide"
|
|
102
|
+
* >
|
|
103
|
+
* <ProsePre language="typescript" code="..." />
|
|
104
|
+
* </ProseCodeCollapse>
|
|
105
|
+
* ```
|
|
106
|
+
*/
|
|
107
|
+
|
|
108
|
+
const props = withDefaults(defineProps<ProseCodeCollapseProps>(), {
|
|
109
|
+
icon: "lucide:chevron-down",
|
|
110
|
+
name: "Code",
|
|
111
|
+
openText: "Expand",
|
|
112
|
+
closeText: "Collapse",
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Toggle state for the collapse/expand functionality
|
|
117
|
+
* @default false - Starts collapsed
|
|
118
|
+
*/
|
|
119
|
+
const open = defineModel<boolean>({ default: false });
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Computed styles to avoid recalculating on each render
|
|
123
|
+
*/
|
|
124
|
+
const styles = computed(() => proseCodeCollapseStyles());
|
|
125
|
+
</script>
|