docs-please 0.2.0-beta.0

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.
Files changed (120) hide show
  1. package/README.md +63 -0
  2. package/app/app.config.ts +13 -0
  3. package/app/app.vue +17 -0
  4. package/app/assets/css/main.css +367 -0
  5. package/app/components/Icons.ts +163 -0
  6. package/app/components/app/AppFooter.vue +24 -0
  7. package/app/components/app/AppHeader.vue +58 -0
  8. package/app/components/content/BrowserFrame.vue +21 -0
  9. package/app/components/content/Callout.vue +80 -0
  10. package/app/components/content/Caution.vue +25 -0
  11. package/app/components/content/CodeBlockCommand.vue +92 -0
  12. package/app/components/content/CodeCollapsibleWrapper.vue +50 -0
  13. package/app/components/content/CodeTabs.vue +14 -0
  14. package/app/components/content/ComponentPreview.vue +71 -0
  15. package/app/components/content/ComponentsList.vue +24 -0
  16. package/app/components/content/CopyButton.vue +39 -0
  17. package/app/components/content/FeatureCard.vue +25 -0
  18. package/app/components/content/LinkedCard.vue +19 -0
  19. package/app/components/content/Note.vue +25 -0
  20. package/app/components/content/ProseA.vue +18 -0
  21. package/app/components/content/ProseBlockQuote.vue +8 -0
  22. package/app/components/content/ProseCode.vue +8 -0
  23. package/app/components/content/ProseH1.vue +7 -0
  24. package/app/components/content/ProseH2.vue +8 -0
  25. package/app/components/content/ProseH3.vue +9 -0
  26. package/app/components/content/ProseH4.vue +9 -0
  27. package/app/components/content/ProseH5.vue +7 -0
  28. package/app/components/content/ProseH6.vue +7 -0
  29. package/app/components/content/ProseHr.vue +6 -0
  30. package/app/components/content/ProseIcon.vue +32 -0
  31. package/app/components/content/ProseImg.vue +6 -0
  32. package/app/components/content/ProseLi.vue +8 -0
  33. package/app/components/content/ProseOl.vue +8 -0
  34. package/app/components/content/ProseP.vue +14 -0
  35. package/app/components/content/ProsePre.vue +80 -0
  36. package/app/components/content/ProseStrong.vue +8 -0
  37. package/app/components/content/ProseTable.vue +26 -0
  38. package/app/components/content/ProseTd.vue +8 -0
  39. package/app/components/content/ProseTh.vue +8 -0
  40. package/app/components/content/ProseTr.vue +8 -0
  41. package/app/components/content/ProseUl.vue +8 -0
  42. package/app/components/content/Step.vue +18 -0
  43. package/app/components/content/Steps.vue +18 -0
  44. package/app/components/content/Tabs.vue +129 -0
  45. package/app/components/content/TabsItem.vue +26 -0
  46. package/app/components/content/Tip.vue +25 -0
  47. package/app/components/content/UButton.vue +34 -0
  48. package/app/components/content/UColorModeImage.vue +48 -0
  49. package/app/components/content/UPageCard.vue +83 -0
  50. package/app/components/content/UPageGrid.vue +18 -0
  51. package/app/components/content/UPageHero.vue +92 -0
  52. package/app/components/content/UPageSection.vue +90 -0
  53. package/app/components/content/Warning.vue +25 -0
  54. package/app/components/docs/DocsPageHeader.vue +20 -0
  55. package/app/components/docs/DocsPageNav.vue +31 -0
  56. package/app/components/docs/DocsSidebar.vue +97 -0
  57. package/app/components/docs/DocsTableOfContents.vue +64 -0
  58. package/app/components/ui/accordion/Accordion.vue +22 -0
  59. package/app/components/ui/accordion/AccordionContent.vue +23 -0
  60. package/app/components/ui/accordion/AccordionItem.vue +24 -0
  61. package/app/components/ui/accordion/AccordionTrigger.vue +37 -0
  62. package/app/components/ui/accordion/index.ts +4 -0
  63. package/app/components/ui/alert/Alert.vue +21 -0
  64. package/app/components/ui/alert/AlertDescription.vue +17 -0
  65. package/app/components/ui/alert/AlertTitle.vue +17 -0
  66. package/app/components/ui/alert/index.ts +28 -0
  67. package/app/components/ui/button/Button.vue +29 -0
  68. package/app/components/ui/button/index.ts +38 -0
  69. package/app/components/ui/card/Card.vue +22 -0
  70. package/app/components/ui/card/CardAction.vue +17 -0
  71. package/app/components/ui/card/CardContent.vue +17 -0
  72. package/app/components/ui/card/CardDescription.vue +17 -0
  73. package/app/components/ui/card/CardFooter.vue +17 -0
  74. package/app/components/ui/card/CardHeader.vue +17 -0
  75. package/app/components/ui/card/CardTitle.vue +17 -0
  76. package/app/components/ui/card/index.ts +7 -0
  77. package/app/components/ui/collapsible/Collapsible.vue +19 -0
  78. package/app/components/ui/collapsible/CollapsibleContent.vue +15 -0
  79. package/app/components/ui/collapsible/CollapsibleTrigger.vue +15 -0
  80. package/app/components/ui/collapsible/index.ts +3 -0
  81. package/app/components/ui/separator/Separator.vue +29 -0
  82. package/app/components/ui/separator/index.ts +1 -0
  83. package/app/components/ui/switch/Switch.vue +35 -0
  84. package/app/components/ui/switch/index.ts +1 -0
  85. package/app/components/ui/table/Table.vue +16 -0
  86. package/app/components/ui/table/TableBody.vue +14 -0
  87. package/app/components/ui/table/TableCaption.vue +14 -0
  88. package/app/components/ui/table/TableCell.vue +21 -0
  89. package/app/components/ui/table/TableEmpty.vue +34 -0
  90. package/app/components/ui/table/TableFooter.vue +14 -0
  91. package/app/components/ui/table/TableHead.vue +14 -0
  92. package/app/components/ui/table/TableHeader.vue +14 -0
  93. package/app/components/ui/table/TableRow.vue +14 -0
  94. package/app/components/ui/table/index.ts +9 -0
  95. package/app/components/ui/tabs/Tabs.vue +15 -0
  96. package/app/components/ui/tabs/TabsContent.vue +20 -0
  97. package/app/components/ui/tabs/TabsList.vue +23 -0
  98. package/app/components/ui/tabs/TabsTrigger.vue +27 -0
  99. package/app/components/ui/tabs/index.ts +4 -0
  100. package/app/components/ui/tooltip/Tooltip.vue +19 -0
  101. package/app/components/ui/tooltip/TooltipContent.vue +34 -0
  102. package/app/components/ui/tooltip/TooltipProvider.vue +14 -0
  103. package/app/components/ui/tooltip/TooltipTrigger.vue +15 -0
  104. package/app/components/ui/tooltip/index.ts +4 -0
  105. package/app/composables/useConfig.ts +24 -0
  106. package/app/composables/useNavigation.ts +43 -0
  107. package/app/layouts/default.vue +12 -0
  108. package/app/layouts/docs.vue +27 -0
  109. package/app/lib/utils.ts +7 -0
  110. package/app/pages/[...slug].vue +97 -0
  111. package/app/pages/index.vue +29 -0
  112. package/app/plugins/ssr-width.ts +5 -0
  113. package/content.config.ts +36 -0
  114. package/i18n/locales/en.json +14 -0
  115. package/modules/config.ts +38 -0
  116. package/modules/css.ts +38 -0
  117. package/modules/shadcn.ts +116 -0
  118. package/nuxt.config.ts +125 -0
  119. package/nuxt.schema.ts +68 -0
  120. package/package.json +81 -0
@@ -0,0 +1,58 @@
1
+ <script setup lang="ts">
2
+ import { Moon, Sun } from 'lucide-vue-next'
3
+ import { Button } from '~/components/ui/button'
4
+
5
+ const colorMode = useColorMode()
6
+
7
+ function toggleColorMode() {
8
+ colorMode.preference = colorMode.value === 'dark' ? 'light' : 'dark'
9
+ }
10
+
11
+ const appConfig = useAppConfig()
12
+ const title = computed(() => appConfig.docs?.title || 'Docs')
13
+ </script>
14
+
15
+ <template>
16
+ <header class="sticky top-0 z-50 w-full border-b bg-background/95 backdrop-blur supports-[backdrop-filter]:bg-background/60">
17
+ <div class="container flex h-14 items-center">
18
+ <!-- Logo -->
19
+ <div class="mr-4 flex">
20
+ <NuxtLink
21
+ to="/"
22
+ class="flex items-center space-x-2"
23
+ >
24
+ <span class="font-bold">{{ title }}</span>
25
+ </NuxtLink>
26
+ </div>
27
+
28
+ <!-- Navigation -->
29
+ <nav class="flex flex-1 items-center space-x-6 text-sm font-medium">
30
+ <NuxtLink
31
+ to="/docs"
32
+ class="text-muted-foreground transition-colors hover:text-foreground"
33
+ >
34
+ Documentation
35
+ </NuxtLink>
36
+ </nav>
37
+
38
+ <!-- Actions -->
39
+ <div class="flex items-center space-x-2">
40
+ <Button
41
+ variant="ghost"
42
+ size="icon"
43
+ @click="toggleColorMode"
44
+ >
45
+ <Sun
46
+ v-if="colorMode.value === 'dark'"
47
+ class="size-5"
48
+ />
49
+ <Moon
50
+ v-else
51
+ class="size-5"
52
+ />
53
+ <span class="sr-only">Toggle theme</span>
54
+ </Button>
55
+ </div>
56
+ </div>
57
+ </header>
58
+ </template>
@@ -0,0 +1,21 @@
1
+ <script setup lang="ts">
2
+ defineProps<{
3
+ title?: string
4
+ }>()
5
+ </script>
6
+
7
+ <template>
8
+ <div class="w-fit rounded-xl border border-border bg-muted shadow-md overflow-hidden px-2 pb-2">
9
+ <div class="flex justify-between items-center px-2 py-2 bg-muted border-border border-b">
10
+ <div class="flex items-center gap-2">
11
+ <span class="w-3 h-3 bg-red-500 rounded-full" />
12
+ <span class="w-3 h-3 bg-yellow-500 rounded-full" />
13
+ <span class="w-3 h-3 bg-green-500 rounded-full" />
14
+ </div>
15
+ <div class="text-muted-foreground text-sm">
16
+ {{ title }}
17
+ </div>
18
+ </div>
19
+ <slot mdc-unwrap="p" />
20
+ </div>
21
+ </template>
@@ -0,0 +1,80 @@
1
+ <script setup lang="ts">
2
+ import type { HTMLAttributes, Component } from 'vue'
3
+ import type { AlertVariants } from '~/components/ui/alert'
4
+ import {
5
+ CircleAlertIcon,
6
+ CircleCheckIcon,
7
+ CircleXIcon,
8
+ InfoIcon,
9
+ LightbulbIcon,
10
+ TriangleAlertIcon,
11
+ } from 'lucide-vue-next'
12
+ import { computed } from 'vue'
13
+ import { cn } from '~/lib/utils'
14
+ import {
15
+ Alert,
16
+ AlertDescription,
17
+ AlertTitle,
18
+ } from '~/components/ui/alert'
19
+
20
+ export type CalloutType = 'note' | 'tip' | 'warning' | 'caution' | 'info' | 'success' | 'error'
21
+
22
+ const props = withDefaults(defineProps<{
23
+ icon?: boolean | Component
24
+ title?: string
25
+ class?: HTMLAttributes['class']
26
+ variant?: AlertVariants['variant']
27
+ type?: CalloutType
28
+ }>(), {
29
+ icon: true,
30
+ })
31
+
32
+ const typeConfig: Record<CalloutType, { icon: Component, variant: AlertVariants['variant'], defaultTitle: string }> = {
33
+ note: { icon: InfoIcon, variant: 'info', defaultTitle: 'Note' },
34
+ tip: { icon: LightbulbIcon, variant: 'success', defaultTitle: 'Tip' },
35
+ warning: { icon: TriangleAlertIcon, variant: 'warning', defaultTitle: 'Warning' },
36
+ caution: { icon: CircleAlertIcon, variant: 'error', defaultTitle: 'Caution' },
37
+ info: { icon: InfoIcon, variant: 'info', defaultTitle: 'Info' },
38
+ success: { icon: CircleCheckIcon, variant: 'success', defaultTitle: 'Success' },
39
+ error: { icon: CircleXIcon, variant: 'error', defaultTitle: 'Error' },
40
+ }
41
+
42
+ const config = computed(() => {
43
+ if (props.type && typeConfig[props.type]) {
44
+ return typeConfig[props.type]
45
+ }
46
+ return null
47
+ })
48
+
49
+ const resolvedVariant = computed(() => props.variant ?? config.value?.variant ?? 'default')
50
+ const resolvedIcon = computed(() => {
51
+ if (props.icon === false) return null
52
+ if (typeof props.icon === 'object') return props.icon
53
+ return config.value?.icon ?? InfoIcon
54
+ })
55
+ </script>
56
+
57
+ <template>
58
+ <Alert
59
+ :class="cn(
60
+ 'my-6 w-auto md:-mx-1',
61
+ props.class,
62
+ )"
63
+ :variant="resolvedVariant"
64
+ >
65
+ <component
66
+ :is="resolvedIcon"
67
+ v-if="resolvedIcon"
68
+ />
69
+ <AlertTitle v-if="title || $slots.title">
70
+ <slot name="title">
71
+ {{ title }}
72
+ </slot>
73
+ </AlertTitle>
74
+ <AlertDescription>
75
+ <slot name="description">
76
+ <slot />
77
+ </slot>
78
+ </AlertDescription>
79
+ </Alert>
80
+ </template>
@@ -0,0 +1,25 @@
1
+ <script setup lang="ts">
2
+ import type { HTMLAttributes } from 'vue'
3
+ import Callout from './Callout.vue'
4
+
5
+ defineProps<{
6
+ title?: string
7
+ class?: HTMLAttributes['class']
8
+ }>()
9
+ </script>
10
+
11
+ <template>
12
+ <Callout
13
+ type="caution"
14
+ :title
15
+ :class
16
+ >
17
+ <template
18
+ v-if="$slots.title"
19
+ #title
20
+ >
21
+ <slot name="title" />
22
+ </template>
23
+ <slot />
24
+ </Callout>
25
+ </template>
@@ -0,0 +1,92 @@
1
+ <script setup lang="ts">
2
+ import { TerminalIcon } from 'lucide-vue-next'
3
+ import {
4
+ Tabs,
5
+ TabsContent,
6
+ TabsList,
7
+ TabsTrigger,
8
+ } from '~/components/ui/tabs'
9
+
10
+ const props = defineProps<{
11
+ code: string
12
+ }>()
13
+
14
+ const tabs = computed(() => {
15
+ const data = { bun: '', pnpm: '', npm: '', yarn: '' }
16
+
17
+ if (props.code.includes('npm install')) {
18
+ data.npm = props.code
19
+ data.yarn = props.code.replaceAll('npm install', 'yarn add')
20
+ data.pnpm = props.code.replaceAll('npm install', 'pnpm add')
21
+ data.bun = props.code.replaceAll('npm install', 'bun add')
22
+ }
23
+ else if (props.code.includes('npx create-')) {
24
+ data.npm = props.code
25
+ data.yarn = props.code.replaceAll('npx create-', 'yarn create')
26
+ data.pnpm = props.code.replaceAll('npx create-', 'pnpm create')
27
+ data.bun = props.code.replaceAll('npx', 'bunx --bun')
28
+ }
29
+ else if (props.code.includes('npm create')) {
30
+ data.npm = props.code
31
+ data.yarn = props.code.replaceAll('npm create', 'yarn create')
32
+ data.pnpm = props.code.replaceAll('npm create', 'pnpm create')
33
+ data.bun = props.code.replaceAll('npm create', 'bun create')
34
+ }
35
+ else if (props.code.includes('npx')) {
36
+ data.npm = props.code
37
+ data.yarn = props.code.replaceAll('npx', 'yarn dlx')
38
+ data.pnpm = props.code.replaceAll('npx', 'pnpm dlx')
39
+ data.bun = props.code.replaceAll('npx', 'bunx --bun')
40
+ }
41
+ else if (props.code.includes('npm run')) {
42
+ data.npm = props.code
43
+ data.yarn = props.code.replaceAll('npm run', 'yarn')
44
+ data.pnpm = props.code.replaceAll('npm run', 'pnpm')
45
+ data.bun = props.code.replaceAll('npm run', 'bun')
46
+ }
47
+
48
+ return data
49
+ })
50
+
51
+ const { config } = useConfig()
52
+ </script>
53
+
54
+ <template>
55
+ <div class="relative overflow-x-auto">
56
+ <Tabs
57
+ v-model="config.packageManager"
58
+ class="gap-0"
59
+ >
60
+ <div class="border-border/50 flex items-center gap-2 border-b px-3 py-1">
61
+ <div class="bg-foreground flex size-4 items-center justify-center rounded-[1px] opacity-70">
62
+ <TerminalIcon class="text-code size-3" />
63
+ </div>
64
+ <TabsList class="rounded-none bg-transparent p-0">
65
+ <TabsTrigger
66
+ v-for="key in Object.keys(tabs)"
67
+ :key="key"
68
+ :value="key"
69
+ class="data-[state=active]:bg-accent data-[state=active]:border-input h-7 border border-transparent pt-0.5 data-[state=active]:shadow-none"
70
+ >
71
+ {{ key }}
72
+ </TabsTrigger>
73
+ </TabsList>
74
+ </div>
75
+
76
+ <div class="no-scrollbar overflow-x-auto">
77
+ <TabsContent
78
+ v-for="([key, value]) in Object.entries(tabs)"
79
+ :key="key"
80
+ :value="key"
81
+ class="mt-0 px-4 py-3.5"
82
+ >
83
+ <pre class="language-bash shiki shiki-themes github-light-default github-dark"><code class="relative font-mono text-sm leading-none"><span class="line"><span>{{ value }}</span></span></code></pre>
84
+ </TabsContent>
85
+ </div>
86
+ </Tabs>
87
+ <CopyButton
88
+ class="absolute top-2 right-2 z-10 size-7 opacity-70 hover:opacity-100 focus-visible:opacity-100"
89
+ :value="tabs[config.packageManager]"
90
+ />
91
+ </div>
92
+ </template>
@@ -0,0 +1,50 @@
1
+ <script setup lang="ts">
2
+ import type { HTMLAttributes } from 'vue'
3
+ import { cn } from '~/lib/utils'
4
+ import { Button } from '~/components/ui/button'
5
+ import {
6
+ Collapsible,
7
+ CollapsibleContent,
8
+ CollapsibleTrigger,
9
+ } from '~/components/ui/collapsible'
10
+ import { Separator } from '~/components/ui/separator'
11
+
12
+ const props = defineProps<{
13
+ class?: HTMLAttributes['class']
14
+ }>()
15
+
16
+ const open = ref(false)
17
+ </script>
18
+
19
+ <template>
20
+ <Collapsible
21
+ v-model:open="open"
22
+ :class="cn('group/collapsible relative md:-mx-1', props.class)"
23
+ >
24
+ <CollapsibleTrigger as-child>
25
+ <div class="absolute top-1.5 right-9 z-10 flex items-center">
26
+ <Button
27
+ variant="ghost"
28
+ size="sm"
29
+ class="text-muted-foreground h-7 rounded-md px-2"
30
+ >
31
+ {{ open ? "Collapse" : "Expand" }}
32
+ </Button>
33
+ <Separator
34
+ orientation="vertical"
35
+ class="mx-1.5 !h-4"
36
+ />
37
+ </div>
38
+ </CollapsibleTrigger>
39
+
40
+ <CollapsibleContent
41
+ force-mount
42
+ class="relative mt-6 overflow-hidden data-[state=closed]:max-h-64 [&>figure]:mt-0 [&>figure]:md:!mx-0"
43
+ >
44
+ <slot />
45
+ </CollapsibleContent>
46
+ <CollapsibleTrigger class="from-code/70 to-code text-muted-foreground absolute inset-x-0 -bottom-2 flex h-20 items-center justify-center rounded-b-lg bg-gradient-to-b text-sm group-data-[state=open]/collapsible:hidden">
47
+ {{ open ? "Collapse" : "Expand" }}
48
+ </CollapsibleTrigger>
49
+ </Collapsible>
50
+ </template>
@@ -0,0 +1,14 @@
1
+ <script setup lang="ts">
2
+ import { Tabs } from '~/components/ui/tabs'
3
+
4
+ const { config } = useConfig()
5
+ </script>
6
+
7
+ <template>
8
+ <Tabs
9
+ v-model="config.installationType"
10
+ class="relative mt-6 w-full"
11
+ >
12
+ <slot />
13
+ </Tabs>
14
+ </template>
@@ -0,0 +1,71 @@
1
+ <script setup lang="ts">
2
+ import type { HTMLAttributes } from 'vue'
3
+
4
+ const props = defineProps<{
5
+ name: string
6
+ align?: 'center' | 'start' | 'end'
7
+ description?: string
8
+ hideCode?: boolean
9
+ type?: 'block' | 'component' | 'example'
10
+ class?: HTMLAttributes['class']
11
+ }>()
12
+
13
+ // For now, only support demo components - blocks and charts are not supported in the docs layer
14
+ const Component = defineAsyncComponent({
15
+ loader: () => import(`~/components/demo/${props.name}.vue`),
16
+ errorComponent: () => null,
17
+ })
18
+ </script>
19
+
20
+ <template>
21
+ <p
22
+ v-if="!Component"
23
+ class="text-muted-foreground text-sm"
24
+ >
25
+ Component
26
+ <code class="bg-muted relative rounded px-[0.3rem] py-[0.2rem] font-mono text-sm">
27
+ {{ name }}
28
+ </code>
29
+ not found in registry.
30
+ </p>
31
+
32
+ <div
33
+ v-else-if="type === 'block'"
34
+ class="relative aspect-[4/2.5] w-full overflow-hidden rounded-md border md:-mx-1"
35
+ >
36
+ <img
37
+ :src="`/r/styles/new-york-v4/${name}-light.png`"
38
+ :alt="name"
39
+ width="1440"
40
+ height="900"
41
+ class="bg-background absolute top-0 left-0 z-20 w-[970px] max-w-none sm:w-[1280px] md:hidden dark:hidden md:dark:hidden"
42
+ >
43
+ <img
44
+ :src="`/r/styles/new-york-v4/${name}-dark.png`"
45
+ :alt="name"
46
+ :width="1440"
47
+ :height="900"
48
+ class="bg-background absolute top-0 left-0 z-20 hidden w-[970px] max-w-none sm:w-[1280px] md:hidden dark:block md:dark:hidden"
49
+ >
50
+ <div class="bg-background absolute inset-0 hidden w-[1600px] md:block">
51
+ <iframe
52
+ :src="`/view/${name}`"
53
+ class="size-full"
54
+ />
55
+ </div>
56
+ </div>
57
+
58
+ <ComponentPreviewTabs
59
+ v-else
60
+ :class="props.class"
61
+ :align
62
+ :hide-code
63
+ :component="Component"
64
+ >
65
+ <ComponentSource
66
+ v-if="!hideCode"
67
+ :name
68
+ :collapsible="false"
69
+ />
70
+ </ComponentPreviewTabs>
71
+ </template>
@@ -0,0 +1,24 @@
1
+ <script setup lang="ts">
2
+ const { data } = await useNavigation()
3
+
4
+ const list = computed(() => data.value?.[0]?.children.find(item => item.title === 'Components')?.children ?? [])
5
+ </script>
6
+
7
+ <template>
8
+ <div class="grid grid-cols-1 gap-4 sm:grid-cols-2 md:grid-cols-3 md:gap-x-8 lg:gap-x-16 lg:gap-y-6 xl:gap-x-20">
9
+ <NuxtLink
10
+ v-for="component in list"
11
+ :key="component.title"
12
+ :to="component.path"
13
+ class="inline-flex items-center gap-2 text-lg font-medium underline-offset-4 hover:underline md:text-base"
14
+ >
15
+ {{ component.title }}
16
+
17
+ <span
18
+ v-if="component.new"
19
+ class="flex size-2 rounded-full bg-green-500"
20
+ title="New"
21
+ />
22
+ </NuxtLink>
23
+ </div>
24
+ </template>
@@ -0,0 +1,39 @@
1
+ <script setup lang="ts">
2
+ import type { HTMLAttributes } from 'vue'
3
+ import { Check, Copy } from 'lucide-vue-next'
4
+ import { useClipboard } from '@vueuse/core'
5
+ import { toRefs } from 'vue'
6
+ import { cn } from '~/lib/utils'
7
+
8
+ const props = withDefaults(defineProps<{
9
+ value?: string
10
+ class?: HTMLAttributes['class']
11
+ }>(), {
12
+ value: '',
13
+ })
14
+ const { value } = toRefs(props)
15
+
16
+ const { copy, copied } = useClipboard({ source: value })
17
+ </script>
18
+
19
+ <template>
20
+ <button
21
+ type="button"
22
+ data-slot="copy-button"
23
+ :class="cn(
24
+ 'bg-code absolute top-3 right-2 z-10 size-7 rounded-md flex items-center justify-center opacity-70 hover:opacity-100 focus-visible:opacity-100 transition-opacity',
25
+ props.class,
26
+ )"
27
+ @click="copy()"
28
+ >
29
+ <span class="sr-only">Copy</span>
30
+ <Check
31
+ v-if="copied"
32
+ class="size-4"
33
+ />
34
+ <Copy
35
+ v-else
36
+ class="size-4"
37
+ />
38
+ </button>
39
+ </template>
@@ -0,0 +1,25 @@
1
+ <script setup lang="ts">
2
+ import type { HTMLAttributes } from 'vue'
3
+ import {
4
+ Card,
5
+ CardContent,
6
+ CardHeader,
7
+ CardTitle,
8
+ } from '~/components/ui/card'
9
+
10
+ const props = defineProps<{
11
+ title?: string
12
+ class?: HTMLAttributes['class']
13
+ }>()
14
+ </script>
15
+
16
+ <template>
17
+ <Card :class="props.class">
18
+ <CardHeader v-if="title">
19
+ <CardTitle>{{ title }}</CardTitle>
20
+ </CardHeader>
21
+ <CardContent>
22
+ <slot />
23
+ </CardContent>
24
+ </Card>
25
+ </template>
@@ -0,0 +1,19 @@
1
+ <script setup lang="ts">
2
+ import type { HTMLAttributes } from 'vue'
3
+ import { cn } from '~/lib/utils'
4
+
5
+ const props = defineProps<{
6
+ class?: HTMLAttributes['class']
7
+ }>()
8
+ </script>
9
+
10
+ <template>
11
+ <NuxtLink
12
+ :class="cn(
13
+ 'bg-surface text-surface-foreground hover:bg-surface/80 flex w-full flex-col items-center rounded-xl p-6 transition-colors sm:p-10',
14
+ props.class,
15
+ )"
16
+ >
17
+ <slot />
18
+ </NuxtLink>
19
+ </template>
@@ -0,0 +1,25 @@
1
+ <script setup lang="ts">
2
+ import type { HTMLAttributes } from 'vue'
3
+ import Callout from './Callout.vue'
4
+
5
+ defineProps<{
6
+ title?: string
7
+ class?: HTMLAttributes['class']
8
+ }>()
9
+ </script>
10
+
11
+ <template>
12
+ <Callout
13
+ type="note"
14
+ :title
15
+ :class
16
+ >
17
+ <template
18
+ v-if="$slots.title"
19
+ #title
20
+ >
21
+ <slot name="title" />
22
+ </template>
23
+ <slot />
24
+ </Callout>
25
+ </template>
@@ -0,0 +1,18 @@
1
+ <script setup lang="ts">
2
+ const props = withDefaults(defineProps<{
3
+ href?: string
4
+ target?: '_blank' | '_parent' | '_self' | '_top' | (string & object) | null | undefined
5
+ }>(), {
6
+ href: '',
7
+ })
8
+ </script>
9
+
10
+ <template>
11
+ <NuxtLink
12
+ :href="props.href"
13
+ :target="props.target"
14
+ class="font-medium underline underline-offset-4"
15
+ >
16
+ <slot />
17
+ </NuxtLink>
18
+ </template>
@@ -0,0 +1,8 @@
1
+ <script setup lang="ts">
2
+ </script>
3
+
4
+ <template>
5
+ <blockquote class="mt-6 border-l-2 pl-6 italic">
6
+ <slot />
7
+ </blockquote>
8
+ </template>
@@ -0,0 +1,8 @@
1
+ <script setup lang="ts">
2
+ </script>
3
+
4
+ <template>
5
+ <code class="bg-muted relative rounded-md px-[0.3rem] py-[0.2rem] font-mono text-[0.8rem] outline-none">
6
+ <slot />
7
+ </code>
8
+ </template>
@@ -0,0 +1,7 @@
1
+ <script setup lang="ts"></script>
2
+
3
+ <template>
4
+ <h1 class="font-heading mt-2 scroll-m-28 text-3xl font-bold tracking-tight">
5
+ <slot />
6
+ </h1>
7
+ </template>
@@ -0,0 +1,8 @@
1
+ <script setup lang="ts">
2
+ </script>
3
+
4
+ <template>
5
+ <h2 class="font-heading [&+]*:[code]:text-xl mt-10 scroll-m-28 text-xl font-medium tracking-tight first:mt-0 lg:mt-16 [&+.steps]:!mt-0 [&+.steps>h3]:!mt-4 [&+h3]:!mt-6 [&+p]:!mt-4">
6
+ <slot />
7
+ </h2>
8
+ </template>
@@ -0,0 +1,9 @@
1
+ <script setup lang="ts"></script>
2
+
3
+ <template>
4
+ <h3
5
+ class="font-heading mt-12 scroll-m-28 text-lg font-medium tracking-tight [&+p]:!mt-4 *:[code]:text-xl"
6
+ >
7
+ <slot />
8
+ </h3>
9
+ </template>
@@ -0,0 +1,9 @@
1
+ <script setup lang="ts"></script>
2
+
3
+ <template>
4
+ <h4
5
+ class="font-heading mt-8 scroll-m-28 text-base font-medium tracking-tight"
6
+ >
7
+ <slot />
8
+ </h4>
9
+ </template>
@@ -0,0 +1,7 @@
1
+ <script setup lang="ts"></script>
2
+
3
+ <template>
4
+ <h5 class="mt-8 scroll-m-28 text-base font-medium tracking-tight">
5
+ <slot />
6
+ </h5>
7
+ </template>
@@ -0,0 +1,7 @@
1
+ <script setup lang="ts"></script>
2
+
3
+ <template>
4
+ <h6 class="mt-8 scroll-m-28 text-base font-medium tracking-tight">
5
+ <slot />
6
+ </h6>
7
+ </template>
@@ -0,0 +1,6 @@
1
+ <script setup lang="ts">
2
+ </script>
3
+
4
+ <template>
5
+ <hr class="my-4 md:my-8">
6
+ </template>