@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.
Files changed (268) hide show
  1. package/app/app.config.ts +239 -0
  2. package/app/app.vue +19 -0
  3. package/app/assets/css/tailwind.css +335 -0
  4. package/app/assets/css/theme.css +1171 -0
  5. package/app/components/OgImage/Docs.takumi.vue +69 -0
  6. package/app/components/OgImage/Landing.takumi.vue +64 -0
  7. package/app/components/OgImage/Site.takumi.vue +32 -0
  8. package/app/components/Ui/Avatar/Avatar.vue +75 -0
  9. package/app/components/Ui/Avatar/Badge.vue +34 -0
  10. package/app/components/Ui/Avatar/Fallback.vue +30 -0
  11. package/app/components/Ui/Avatar/Group.vue +29 -0
  12. package/app/components/Ui/Avatar/GroupCount.vue +29 -0
  13. package/app/components/Ui/Avatar/Image.vue +29 -0
  14. package/app/components/Ui/Badge.vue +86 -0
  15. package/app/components/Ui/BadgeGroup.vue +314 -0
  16. package/app/components/Ui/BgPattern/Grid.vue +137 -0
  17. package/app/components/Ui/BorderBeam.vue +97 -0
  18. package/app/components/Ui/Breadcrumbs.vue +103 -0
  19. package/app/components/Ui/Button.vue +169 -0
  20. package/app/components/Ui/ButtonGroup/ButtonGroup.vue +54 -0
  21. package/app/components/Ui/ButtonGroup/Separator.vue +38 -0
  22. package/app/components/Ui/ButtonGroup/Text.vue +33 -0
  23. package/app/components/Ui/Card/Action.vue +31 -0
  24. package/app/components/Ui/Card/Card.vue +58 -0
  25. package/app/components/Ui/Card/Content.vue +34 -0
  26. package/app/components/Ui/Card/Description.vue +36 -0
  27. package/app/components/Ui/Card/Footer.vue +31 -0
  28. package/app/components/Ui/Card/Header.vue +31 -0
  29. package/app/components/Ui/Card/Title.vue +37 -0
  30. package/app/components/Ui/Collapsible/Collapsible.vue +16 -0
  31. package/app/components/Ui/Collapsible/Content.vue +27 -0
  32. package/app/components/Ui/Collapsible/Trigger.vue +13 -0
  33. package/app/components/Ui/Command/Command.vue +115 -0
  34. package/app/components/Ui/Command/Dialog.vue +65 -0
  35. package/app/components/Ui/Command/Empty.vue +32 -0
  36. package/app/components/Ui/Command/Footer.vue +40 -0
  37. package/app/components/Ui/Command/Group.vue +58 -0
  38. package/app/components/Ui/Command/Input.vue +57 -0
  39. package/app/components/Ui/Command/Item.vue +102 -0
  40. package/app/components/Ui/Command/List.vue +33 -0
  41. package/app/components/Ui/Command/Separator.vue +30 -0
  42. package/app/components/Ui/Command/Shortcut.vue +28 -0
  43. package/app/components/Ui/Container.vue +46 -0
  44. package/app/components/Ui/ContextMenu/Arrow.vue +43 -0
  45. package/app/components/Ui/ContextMenu/CheckboxItem.vue +42 -0
  46. package/app/components/Ui/ContextMenu/Content.vue +53 -0
  47. package/app/components/Ui/ContextMenu/ContextMenu.vue +14 -0
  48. package/app/components/Ui/ContextMenu/Group.vue +12 -0
  49. package/app/components/Ui/ContextMenu/Item.vue +65 -0
  50. package/app/components/Ui/ContextMenu/ItemIndicator.vue +30 -0
  51. package/app/components/Ui/ContextMenu/Label.vue +35 -0
  52. package/app/components/Ui/ContextMenu/Portal.vue +12 -0
  53. package/app/components/Ui/ContextMenu/RadioGroup.vue +16 -0
  54. package/app/components/Ui/ContextMenu/RadioItem.vue +40 -0
  55. package/app/components/Ui/ContextMenu/Separator.vue +25 -0
  56. package/app/components/Ui/ContextMenu/Shortcut.vue +30 -0
  57. package/app/components/Ui/ContextMenu/Sub.vue +15 -0
  58. package/app/components/Ui/ContextMenu/SubContent.vue +55 -0
  59. package/app/components/Ui/ContextMenu/SubTrigger.vue +42 -0
  60. package/app/components/Ui/ContextMenu/Trigger.vue +12 -0
  61. package/app/components/Ui/Dialog/Close.vue +12 -0
  62. package/app/components/Ui/Dialog/Content.vue +79 -0
  63. package/app/components/Ui/Dialog/Description.vue +29 -0
  64. package/app/components/Ui/Dialog/Dialog.vue +14 -0
  65. package/app/components/Ui/Dialog/Footer.vue +32 -0
  66. package/app/components/Ui/Dialog/Header.vue +32 -0
  67. package/app/components/Ui/Dialog/Overlay.vue +25 -0
  68. package/app/components/Ui/Dialog/Portal.vue +12 -0
  69. package/app/components/Ui/Dialog/Title.vue +29 -0
  70. package/app/components/Ui/Dialog/Trigger.vue +12 -0
  71. package/app/components/Ui/Divider.vue +102 -0
  72. package/app/components/Ui/Drawer/Close.vue +12 -0
  73. package/app/components/Ui/Drawer/Content.vue +67 -0
  74. package/app/components/Ui/Drawer/Description.vue +33 -0
  75. package/app/components/Ui/Drawer/Drawer.vue +17 -0
  76. package/app/components/Ui/Drawer/Footer.vue +35 -0
  77. package/app/components/Ui/Drawer/Header.vue +34 -0
  78. package/app/components/Ui/Drawer/Overlay.vue +20 -0
  79. package/app/components/Ui/Drawer/Portal.vue +12 -0
  80. package/app/components/Ui/Drawer/Title.vue +35 -0
  81. package/app/components/Ui/Drawer/Trigger.vue +12 -0
  82. package/app/components/Ui/DropdownMenu/Arrow.vue +43 -0
  83. package/app/components/Ui/DropdownMenu/CheckboxItem.vue +41 -0
  84. package/app/components/Ui/DropdownMenu/Content.vue +56 -0
  85. package/app/components/Ui/DropdownMenu/DropdownMenu.vue +15 -0
  86. package/app/components/Ui/DropdownMenu/Group.vue +12 -0
  87. package/app/components/Ui/DropdownMenu/Item.vue +64 -0
  88. package/app/components/Ui/DropdownMenu/ItemIndicator.vue +32 -0
  89. package/app/components/Ui/DropdownMenu/Label.vue +34 -0
  90. package/app/components/Ui/DropdownMenu/Portal.vue +12 -0
  91. package/app/components/Ui/DropdownMenu/RadioGroup.vue +16 -0
  92. package/app/components/Ui/DropdownMenu/RadioItem.vue +40 -0
  93. package/app/components/Ui/DropdownMenu/Separator.vue +25 -0
  94. package/app/components/Ui/DropdownMenu/Shortcut.vue +44 -0
  95. package/app/components/Ui/DropdownMenu/Sub.vue +14 -0
  96. package/app/components/Ui/DropdownMenu/SubContent.vue +56 -0
  97. package/app/components/Ui/DropdownMenu/SubTrigger.vue +47 -0
  98. package/app/components/Ui/DropdownMenu/Trigger.vue +12 -0
  99. package/app/components/Ui/FancyIcon.vue +243 -0
  100. package/app/components/Ui/GradientDivider.vue +26 -0
  101. package/app/components/Ui/IframeLazy.vue +97 -0
  102. package/app/components/Ui/Input.vue +97 -0
  103. package/app/components/Ui/InputGroup/Addon.vue +66 -0
  104. package/app/components/Ui/InputGroup/Button.vue +50 -0
  105. package/app/components/Ui/InputGroup/Input.vue +25 -0
  106. package/app/components/Ui/InputGroup/InputGroup.vue +44 -0
  107. package/app/components/Ui/InputGroup/Text.vue +33 -0
  108. package/app/components/Ui/InputGroup/Textarea.vue +25 -0
  109. package/app/components/Ui/Kbd/Group.vue +32 -0
  110. package/app/components/Ui/Kbd/Kbd.vue +62 -0
  111. package/app/components/Ui/Label.vue +40 -0
  112. package/app/components/Ui/Popover/Anchor.vue +13 -0
  113. package/app/components/Ui/Popover/Arrow.vue +42 -0
  114. package/app/components/Ui/Popover/Close.vue +13 -0
  115. package/app/components/Ui/Popover/Content.vue +55 -0
  116. package/app/components/Ui/Popover/Popover.vue +15 -0
  117. package/app/components/Ui/Popover/Portal.vue +13 -0
  118. package/app/components/Ui/Popover/Trigger.vue +12 -0
  119. package/app/components/Ui/Popover/X.vue +38 -0
  120. package/app/components/Ui/ScrollArea/Corner.vue +12 -0
  121. package/app/components/Ui/ScrollArea/ScrollArea.vue +38 -0
  122. package/app/components/Ui/ScrollArea/Scrollbar.vue +39 -0
  123. package/app/components/Ui/ScrollArea/Thumb.vue +39 -0
  124. package/app/components/Ui/ScrollArea/Viewport.vue +27 -0
  125. package/app/components/Ui/Scrollspy.vue +61 -0
  126. package/app/components/Ui/Separator.vue +40 -0
  127. package/app/components/Ui/Skeleton.vue +39 -0
  128. package/app/components/Ui/Sonner.vue +25 -0
  129. package/app/components/Ui/Tabs/Content.vue +27 -0
  130. package/app/components/Ui/Tabs/Indicator.vue +37 -0
  131. package/app/components/Ui/Tabs/List.vue +37 -0
  132. package/app/components/Ui/Tabs/Tabs.vue +25 -0
  133. package/app/components/Ui/Tabs/Trigger.vue +41 -0
  134. package/app/components/Ui/Textarea.vue +81 -0
  135. package/app/components/Ui/Tooltip/Arrow.vue +30 -0
  136. package/app/components/Ui/Tooltip/Content.vue +50 -0
  137. package/app/components/Ui/Tooltip/Portal.vue +12 -0
  138. package/app/components/Ui/Tooltip/Provider.vue +14 -0
  139. package/app/components/Ui/Tooltip/Tooltip.vue +25 -0
  140. package/app/components/Ui/Tooltip/Trigger.vue +12 -0
  141. package/app/components/Ui/Tree/Item.vue +15 -0
  142. package/app/components/Ui/Tree/Tree.vue +15 -0
  143. package/app/components/Ui/Tree/Virtualizer.vue +13 -0
  144. package/app/components/component-api/ComponentApiSection.vue +135 -0
  145. package/app/components/content/docs/Callout/DocsCallout.vue +99 -0
  146. package/app/components/content/prose/ProseA.global.vue +31 -0
  147. package/app/components/content/prose/ProseBlockquote.global.vue +28 -0
  148. package/app/components/content/prose/ProseCallout.global.vue +306 -0
  149. package/app/components/content/prose/ProseCard.global.vue +100 -0
  150. package/app/components/content/prose/ProseCodeCollapse.global.vue +125 -0
  151. package/app/components/content/prose/ProseCodeCopy.global.vue +67 -0
  152. package/app/components/content/prose/ProseCodeGroup.global.vue +104 -0
  153. package/app/components/content/prose/ProseCodeTree.global.vue +277 -0
  154. package/app/components/content/prose/ProseCollapsible.global.vue +64 -0
  155. package/app/components/content/prose/ProseColorModeImage.global.vue +58 -0
  156. package/app/components/content/prose/ProseComponentApi.global.vue +104 -0
  157. package/app/components/content/prose/ProseComponentEvents.global.vue +27 -0
  158. package/app/components/content/prose/ProseComponentExposed.global.vue +27 -0
  159. package/app/components/content/prose/ProseComponentProps.global.vue +27 -0
  160. package/app/components/content/prose/ProseComponentSlots.global.vue +27 -0
  161. package/app/components/content/prose/ProseEm.global.vue +5 -0
  162. package/app/components/content/prose/ProseField.global.vue +118 -0
  163. package/app/components/content/prose/ProseFieldGroup.global.vue +62 -0
  164. package/app/components/content/prose/ProseH1.global.vue +58 -0
  165. package/app/components/content/prose/ProseH2.global.vue +58 -0
  166. package/app/components/content/prose/ProseH3.global.vue +58 -0
  167. package/app/components/content/prose/ProseH4.global.vue +58 -0
  168. package/app/components/content/prose/ProseH5.global.vue +47 -0
  169. package/app/components/content/prose/ProseH6.global.vue +47 -0
  170. package/app/components/content/prose/ProseHr.global.vue +33 -0
  171. package/app/components/content/prose/ProseIconList.global.vue +113 -0
  172. package/app/components/content/prose/ProseImg.global.vue +119 -0
  173. package/app/components/content/prose/ProseLead.global.vue +28 -0
  174. package/app/components/content/prose/ProseLi.global.vue +25 -0
  175. package/app/components/content/prose/ProseMermaid.global.vue +127 -0
  176. package/app/components/content/prose/ProseOl.global.vue +25 -0
  177. package/app/components/content/prose/ProseP.global.vue +25 -0
  178. package/app/components/content/prose/ProsePmInstall.global.vue +60 -0
  179. package/app/components/content/prose/ProsePmRun.global.vue +51 -0
  180. package/app/components/content/prose/ProsePmX.global.vue +56 -0
  181. package/app/components/content/prose/ProsePre.global.vue +181 -0
  182. package/app/components/content/prose/ProseShowCase.global.vue +56 -0
  183. package/app/components/content/prose/ProseSmartIcon.global.vue +54 -0
  184. package/app/components/content/prose/ProseStep.global.vue +22 -0
  185. package/app/components/content/prose/ProseSteps.global.vue +22 -0
  186. package/app/components/content/prose/ProseStrong.global.vue +34 -0
  187. package/app/components/content/prose/ProseTable.global.vue +34 -0
  188. package/app/components/content/prose/ProseTabs.global.vue +104 -0
  189. package/app/components/content/prose/ProseTabsInner.global.vue +274 -0
  190. package/app/components/content/prose/ProseTbody.global.vue +5 -0
  191. package/app/components/content/prose/ProseTd.global.vue +25 -0
  192. package/app/components/content/prose/ProseTh.global.vue +25 -0
  193. package/app/components/content/prose/ProseThead.global.vue +9 -0
  194. package/app/components/content/prose/ProseTr.global.vue +35 -0
  195. package/app/components/content/prose/ProseUl.global.vue +25 -0
  196. package/app/components/docs/DocsExtraStuff.vue +39 -0
  197. package/app/components/docs/DocsGithubLink.vue +11 -0
  198. package/app/components/docs/DocsHeader.vue +3 -0
  199. package/app/components/docs/DocsLogo.vue +74 -0
  200. package/app/components/docs/DocsMobileBar.vue +26 -0
  201. package/app/components/docs/DocsMobileNav.vue +49 -0
  202. package/app/components/docs/DocsNav.vue +161 -0
  203. package/app/components/docs/DocsPageTransition.vue +32 -0
  204. package/app/components/docs/DocsSearch.vue +220 -0
  205. package/app/components/docs/DocsSearchButton.vue +20 -0
  206. package/app/components/docs/DocsThemeCustomizer.vue +229 -0
  207. package/app/components/docs/DocsThemeToggler.vue +98 -0
  208. package/app/components/docs/DocsTocRail.vue +162 -0
  209. package/app/components/docs/DocsToclink.vue +52 -0
  210. package/app/components/docs/DocsZigZagRail.vue +70 -0
  211. package/app/components/landing/Hero.vue +222 -0
  212. package/app/components/page/PageFooter.vue +49 -0
  213. package/app/components/page/PageHeader.vue +68 -0
  214. package/app/components/page/PageHeaderLinks.vue +138 -0
  215. package/app/components/page/PageMobileToc.vue +162 -0
  216. package/app/components/page/PageToc.vue +33 -0
  217. package/app/composables/useDefaultSlotItems.ts +90 -0
  218. package/app/composables/useDocPage.ts +66 -0
  219. package/app/composables/useDocSearch.ts +23 -0
  220. package/app/composables/useDocd.ts +107 -0
  221. package/app/composables/useLogoAssets.ts +319 -0
  222. package/app/composables/usePm.ts +73 -0
  223. package/app/composables/useProseComponentMeta.ts +30 -0
  224. package/app/composables/useScrollspy.ts +327 -0
  225. package/app/composables/useSeo.ts +240 -0
  226. package/app/composables/useUIConfig.ts +36 -0
  227. package/app/layouts/default.vue +5 -0
  228. package/app/layouts/docs.vue +64 -0
  229. package/app/middleware/colorMode.global.ts +8 -0
  230. package/app/middleware/doc-page-layout.ts +11 -0
  231. package/app/middleware/landing-page-layout.ts +11 -0
  232. package/app/pages/[...slug].vue +63 -0
  233. package/app/plugins/mermaid.client.ts +35 -0
  234. package/app/plugins/navigation-direction.client.ts +15 -0
  235. package/app/plugins/theme-restore.client.ts +7 -0
  236. package/app/templates/landing.vue +40 -0
  237. package/app/transitions/presets.ts +71 -0
  238. package/app/types/prose-component-meta.d.ts +4 -0
  239. package/app/utils/og.ts +26 -0
  240. package/app/utils/prerender.ts +9 -0
  241. package/app/utils/translucent.ts +56 -0
  242. package/app/utils/tw-helper.ts +4 -0
  243. package/content.config.ts +81 -0
  244. package/index.d.ts +25 -0
  245. package/modules/config.ts +89 -0
  246. package/modules/custom-icons.ts +17 -0
  247. package/modules/markdown-rewrite.ts +96 -0
  248. package/modules/prose-component-meta.ts +150 -0
  249. package/modules/routing.ts +22 -0
  250. package/modules/skills/index.ts +167 -0
  251. package/modules/skills/runtime/server/routes/skills-files.ts +49 -0
  252. package/modules/skills/runtime/server/routes/skills-index.ts +8 -0
  253. package/nuxt.config.ts +96 -0
  254. package/nuxt.schema.ts +288 -0
  255. package/package.json +95 -0
  256. package/server/mcp/tools/get-page.ts +66 -0
  257. package/server/mcp/tools/list-pages.ts +61 -0
  258. package/server/routes/sitemap.xml.ts +73 -0
  259. package/server/utils/content.ts +3 -0
  260. package/tailwind.config.cjs +55 -0
  261. package/utils/component-api-content.ts +467 -0
  262. package/utils/component-api-discovery.ts +165 -0
  263. package/utils/component-api-schema.ts +28 -0
  264. package/utils/component-api.ts +243 -0
  265. package/utils/generate-prose-component-meta.ts +303 -0
  266. package/utils/git.ts +123 -0
  267. package/utils/meta.ts +40 -0
  268. package/utils/pages.ts +21 -0
@@ -0,0 +1,243 @@
1
+ <template>
2
+ <div
3
+ data-slot="fancy-icon"
4
+ :class="styles({ class: normalizeClass(props.class) || undefined, color, size, theme })"
5
+ >
6
+ <slot>
7
+ <Icon v-if="icon" data-slot="fancy-icon-icon" :name="icon" />
8
+ </slot>
9
+ </div>
10
+ </template>
11
+
12
+ <script lang="ts" setup>
13
+ import { normalizeClass } from "vue";
14
+ import type { HTMLAttributes } from "vue";
15
+
16
+ const props = withDefaults(
17
+ defineProps<{
18
+ /**
19
+ * Custom class(es) to add to the icon container.
20
+ */
21
+ class?: HTMLAttributes["class"];
22
+ /**
23
+ * The icon to display.
24
+ */
25
+ icon?: string;
26
+ /**
27
+ * The color variant of the icon.
28
+ */
29
+ color?: VariantProps<typeof styles>["color"];
30
+ /**
31
+ * The theme variant of the icon.
32
+ */
33
+ theme?: VariantProps<typeof styles>["theme"];
34
+ /**
35
+ * The size variant of the icon.
36
+ */
37
+ size?: VariantProps<typeof styles>["size"];
38
+ }>(),
39
+ {
40
+ color: "primary",
41
+ theme: "modern",
42
+ size: "lg",
43
+ }
44
+ );
45
+
46
+ const styles = tv({
47
+ base: "relative flex shrink-0 items-center justify-center",
48
+ variants: {
49
+ theme: {
50
+ light: "rounded-full",
51
+ gradient:
52
+ "rounded-full text-white *:z-10 before:absolute before:inset-0 before:size-full before:rounded-full before:border before:mask-b-from-0% after:absolute after:block after:rounded-full",
53
+ dark: "text-white before:absolute before:inset-px before:border before:border-white/10 before:mask-b-from-0%",
54
+ modern: "bg-background ring-1 ring-inset",
55
+ "modern-neue": [
56
+ "ring-1 ring-inset before:absolute before:inset-1 dark:bg-muted/40",
57
+ "before:shadow-[0px_1px_2px_0px_rgba(0,0,0,0.1),0px_3px_3px_0px_rgba(0,0,0,0.09),1px_8px_5px_0px_rgba(0,0,0,0.05),2px_21px_6px_0px_rgba(0,0,0,0),0px_0px_0px_1px_rgba(0,0,0,0.08),1px_13px_5px_0px_rgba(0,0,0,0.01),0px_-2px_2px_0px_rgba(0,0,0,0.13)_inset] before:ring-1 before:ring-border",
58
+ ],
59
+ outline:
60
+ "before:absolute before:rounded-full before:border-2 after:absolute after:rounded-full after:border-2",
61
+ },
62
+ size: {
63
+ sm: "*:size-4",
64
+ md: "*:size-5",
65
+ lg: "*:size-6",
66
+ xl: "*:size-7",
67
+ },
68
+ color: {
69
+ primary: "",
70
+ gray: "",
71
+ error: "",
72
+ warning: "",
73
+ success: "",
74
+ info: "",
75
+ },
76
+ },
77
+
78
+ compoundVariants: [
79
+ // Apply shadow to dark and modern
80
+ {
81
+ theme: ["dark", "modern"],
82
+ class:
83
+ "shadow-[0px_0px_0px_1px_rgba(10,13,18,0.18)_inset,0px_-2px_0px_0px_rgba(10,13,18,0.05)_inset,0px_1px_2px_rgba(10,13,18,0.05)]",
84
+ },
85
+ // Light sizes
86
+ { theme: "light", size: "sm", class: "size-8" },
87
+ { theme: "light", size: "md", class: "size-10" },
88
+ { theme: "light", size: "lg", class: "size-12" },
89
+ { theme: "light", size: "xl", class: "size-14" },
90
+ // Light colors
91
+ {
92
+ theme: "light",
93
+ color: "primary",
94
+ class: "bg-primary/10 text-primary dark:bg-primary dark:text-primary-foreground",
95
+ },
96
+ { theme: "light", color: "gray", class: "bg-muted text-muted-foreground" },
97
+ {
98
+ theme: "light",
99
+ color: "error",
100
+ class: "bg-red-500/10 text-red-500 dark:bg-red-500 dark:text-white",
101
+ },
102
+ {
103
+ theme: "light",
104
+ color: "warning",
105
+ class: "bg-amber-500/10 text-amber-500 dark:bg-amber-500 dark:text-white",
106
+ },
107
+ {
108
+ theme: "light",
109
+ color: "success",
110
+ class: "bg-green-500/10 text-green-500 dark:bg-green-500 dark:text-white",
111
+ },
112
+ {
113
+ theme: "light",
114
+ color: "info",
115
+ class: "bg-blue-500/10 text-blue-500 dark:bg-blue-500 dark:text-white",
116
+ },
117
+ // Gradient sizes
118
+ { theme: "gradient", size: "sm", class: "size-8 after:size-6 [*>svg]:size-4" },
119
+ { theme: "gradient", size: "md", class: "size-10 after:size-7 [*>svg]:size-4" },
120
+ { theme: "gradient", size: "lg", class: "size-12 after:size-8 [*>svg]:size-5" },
121
+ { theme: "gradient", size: "xl", class: "size-14 after:size-10 [*>svg]:size-5" },
122
+ // Gradient colors
123
+ {
124
+ theme: "gradient",
125
+ color: "primary",
126
+ class:
127
+ "before:border-primary/40 before:bg-primary/10 before:text-white after:bg-primary after:text-white",
128
+ },
129
+ {
130
+ theme: "gradient",
131
+ color: "gray",
132
+ class:
133
+ "before:border-gray-700/20 before:bg-gray-700/10 after:bg-gray-700 dark:before:bg-gray-700/50",
134
+ },
135
+ {
136
+ theme: "gradient",
137
+ color: "error",
138
+ class: "before:border-red-800/20 before:bg-red-500/10 after:bg-red-500",
139
+ },
140
+ {
141
+ theme: "gradient",
142
+ color: "warning",
143
+ class: "before:border-amber-800/20 before:bg-amber-500/10 after:bg-amber-500",
144
+ },
145
+ {
146
+ theme: "gradient",
147
+ color: "success",
148
+ class: "before:border-green-800/20 before:bg-green-500/10 after:bg-green-500",
149
+ },
150
+ {
151
+ theme: "gradient",
152
+ color: "info",
153
+ class: "before:border-blue-800/20 before:bg-blue-500/10 after:bg-blue-500",
154
+ },
155
+ // Dark sizes
156
+ { theme: "dark", size: "sm", class: "size-8 rounded-md before:rounded-[5px]" },
157
+ { theme: "dark", size: "md", class: "size-10 rounded-lg before:rounded-[7px]" },
158
+ { theme: "dark", size: "lg", class: "size-12 rounded-[10px] before:rounded-[9px]" },
159
+ { theme: "dark", size: "xl", class: "size-14 rounded-xl before:rounded-[11px]" },
160
+ // Dark colors
161
+ { theme: "dark", color: "primary", class: "bg-primary before:border-primary/12" },
162
+ {
163
+ theme: "dark",
164
+ color: "gray",
165
+ class: "bg-gray-800/80 before:border-muted/12 dark:bg-gray-700",
166
+ },
167
+ { theme: "dark", color: "error", class: "bg-red-500 before:border-red-800/12" },
168
+ {
169
+ theme: "dark",
170
+ color: "warning",
171
+ class: "bg-amber-500 before:border-amber-800/12",
172
+ },
173
+ {
174
+ theme: "dark",
175
+ color: "success",
176
+ class: "bg-green-500 before:border-green-800/12",
177
+ },
178
+ {
179
+ theme: "dark",
180
+ color: "info",
181
+ class: "bg-blue-500 before:border-blue-800/12",
182
+ },
183
+ // Modern sizes
184
+ { theme: "modern", size: "sm", class: "size-8 rounded-md" },
185
+ { theme: "modern", size: "md", class: "size-10 rounded-lg" },
186
+ { theme: "modern", size: "lg", class: "size-12 rounded-[10px]" },
187
+ { theme: "modern", size: "xl", class: "size-14 rounded-xl" },
188
+ // Modern colors
189
+ {
190
+ theme: "modern",
191
+ class: "text-foreground ring-border",
192
+ },
193
+ // Modern Neue sizes
194
+ { theme: "modern-neue", size: "sm", class: "size-8 rounded-[8px] before:rounded-[4px]" },
195
+ { theme: "modern-neue", size: "md", class: "size-10 rounded-[10px] before:rounded-[6px]" },
196
+ { theme: "modern-neue", size: "lg", class: "size-12 rounded-[12px] before:rounded-[8px]" },
197
+ { theme: "modern-neue", size: "xl", class: "size-14 rounded-[14px] before:rounded-[10px]" },
198
+ // Modern Neue colors
199
+ {
200
+ theme: "modern-neue",
201
+ class: "text-foreground ring-border",
202
+ },
203
+ // Outline sizes
204
+ { theme: "outline", size: "sm", class: "size-4 before:size-6 after:size-8.5" },
205
+ { theme: "outline", size: "md", class: "size-5 before:size-7 after:size-9.5" },
206
+ { theme: "outline", size: "lg", class: "size-6 before:size-8 after:size-10.5" },
207
+ { theme: "outline", size: "xl", class: "size-7 before:size-9 after:size-11.5" },
208
+ // Outline colors
209
+ {
210
+ theme: "outline",
211
+ color: "primary",
212
+ class: "text-primary before:border-primary/30 after:border-primary/10",
213
+ },
214
+ {
215
+ theme: "outline",
216
+ color: "gray",
217
+ class:
218
+ "text-muted-foreground before:border-muted-foreground/30 after:border-muted-foreground/10",
219
+ },
220
+ {
221
+ theme: "outline",
222
+ color: "error",
223
+ class: "text-red-500 before:border-red-500/30 after:border-red-500/10",
224
+ },
225
+ {
226
+ theme: "outline",
227
+ color: "warning",
228
+ class: "text-amber-500 before:border-amber-500/30 after:border-amber-500/10",
229
+ },
230
+ {
231
+ theme: "outline",
232
+ color: "success",
233
+ class: "text-green-500 before:border-green-500/30 after:border-green-500/10",
234
+ },
235
+ {
236
+ theme: "outline",
237
+ color: "info",
238
+ class: "text-blue-500 before:border-blue-500/30 after:border-blue-500/10",
239
+ },
240
+ ],
241
+ defaultVariants: { theme: "light", size: "md", color: "primary" },
242
+ });
243
+ </script>
@@ -0,0 +1,26 @@
1
+ <template>
2
+ <Separator
3
+ v-bind="forwarded"
4
+ :class="styles({ class: normalizeClass(props.class) || undefined })"
5
+ />
6
+ </template>
7
+
8
+ <script lang="ts" setup>
9
+ import { Separator } from "reka-ui";
10
+ import type { SeparatorProps } from "reka-ui";
11
+ import { normalizeClass } from "vue";
12
+ import type { HTMLAttributes } from "vue";
13
+
14
+ const props = defineProps<
15
+ SeparatorProps & {
16
+ /** Custom class(es) to add to parent element */
17
+ class?: HTMLAttributes["class"];
18
+ }
19
+ >();
20
+
21
+ const forwarded = reactiveOmit(props, "class");
22
+
23
+ const styles = tv({
24
+ base: "h-px w-full border-t-0 bg-[linear-gradient(90deg,--alpha(var(--input)/10%),var(--input),--alpha(var(--input)/10%))]",
25
+ });
26
+ </script>
@@ -0,0 +1,97 @@
1
+ <template>
2
+ <div ref="root" :class="styles().wrapper({ class: normalizeClass(props.class) || undefined })">
3
+ <div v-if="!visible && placeholder" class="size-full">
4
+ <slot name="placeholder"> <div class="size-full bg-muted" /> </slot>
5
+ </div>
6
+
7
+ <iframe
8
+ v-show="visible"
9
+ :src="visible ? src : undefined"
10
+ :class="styles().iframe({ class: normalizeClass(iframeClass) || undefined })"
11
+ :loading
12
+ frameborder="0"
13
+ allowfullscreen
14
+ :scrolling="disableScroll ? 'no' : 'yes'"
15
+ @load="$emit('load', $event)"
16
+ />
17
+ </div>
18
+ </template>
19
+
20
+ <script setup lang="ts">
21
+ import { normalizeClass } from "vue";
22
+ import type { HTMLAttributes } from "vue";
23
+
24
+ defineEmits<{ load: [event: Event] }>();
25
+
26
+ type IFrameLazyProps = {
27
+ /**
28
+ * The URL of the page to embed in the iframe.
29
+ */
30
+ src?: string;
31
+ /**
32
+ * Additional classes to apply to the wrapper element.
33
+ */
34
+ class?: HTMLAttributes["class"];
35
+ /**
36
+ * Additional classes to apply to the iframe element.
37
+ */
38
+ iframeClass?: HTMLAttributes["class"];
39
+ /**
40
+ * Indicates when the browser should load the iframe
41
+ *
42
+ * - `lazy`: Load the iframe when it is about to come into view.
43
+ * - `eager`: Load the iframe immediately.
44
+ *
45
+ * @default "lazy"
46
+ */
47
+ loading?: "lazy" | "eager";
48
+ /**
49
+ * Whether to show a placeholder before the iframe is loaded.
50
+ *
51
+ * @default true
52
+ */
53
+ placeholder?: boolean;
54
+ /**
55
+ * A string which specifies a set of offsets to add to the root's bounding box when calculating intersections.
56
+ *
57
+ * @default "150px"
58
+ */
59
+ rootMargin?: string;
60
+ /**
61
+ * Either a single number or an array of numbers between 0.0 and 1.0, specifying a ratio of intersection area to total bounding box area for the observed target.
62
+ * @default 0
63
+ */
64
+ threshold?: number | number[];
65
+ /**
66
+ * Disable scrolling within the iframe.
67
+ */
68
+ disableScroll?: boolean;
69
+ };
70
+
71
+ const props = withDefaults(defineProps<IFrameLazyProps>(), {
72
+ loading: "lazy",
73
+ rootMargin: "150px",
74
+ placeholder: true,
75
+ });
76
+
77
+ const styles = tv({
78
+ slots: {
79
+ wrapper: "relative size-full",
80
+ iframe: "size-full",
81
+ },
82
+ });
83
+
84
+ const root = useTemplateRef("root");
85
+ const visible = shallowRef(false);
86
+
87
+ useIntersectionObserver(
88
+ root,
89
+ ([entry], observerElement) => {
90
+ if (entry?.isIntersecting) {
91
+ visible.value = true;
92
+ observerElement?.disconnect();
93
+ }
94
+ },
95
+ { root: null, rootMargin: props.rootMargin, threshold: props.threshold }
96
+ );
97
+ </script>
@@ -0,0 +1,97 @@
1
+ <template>
2
+ <input
3
+ v-bind="props"
4
+ ref="input"
5
+ data-slot="input"
6
+ :class="styles({ class: normalizeClass(props.class) || undefined, type: props.type as any })"
7
+ :value="modelValue"
8
+ @input="handleInput"
9
+ />
10
+ </template>
11
+
12
+ <script lang="ts">
13
+ import { normalizeClass } from "vue";
14
+ import type { HTMLAttributes, InputHTMLAttributes } from "vue";
15
+
16
+ export type InputProps = {
17
+ /** Additional classes to add to the input */
18
+ class?: HTMLAttributes["class"];
19
+ /** The id of the input */
20
+ id?: string;
21
+ /** The name of the input */
22
+ name?: string;
23
+ /** The placeholder of the input */
24
+ placeholder?: string;
25
+ /** Whether the input is disabled */
26
+ disabled?: boolean;
27
+ /** Whether the input is required */
28
+ required?: boolean;
29
+ /** The type of the input */
30
+ type?: InputHTMLAttributes["type"];
31
+ /** The value of the input */
32
+ modelValue?: any;
33
+ /** The maximum length of the input */
34
+ maxlength?: number;
35
+ /** The `RegExp` pattern of the input */
36
+ pattern?: string;
37
+ /** When `true`, the input will be focused when mounted */
38
+ autofocus?: boolean;
39
+ };
40
+ </script>
41
+
42
+ <script lang="ts" setup>
43
+ const props = withDefaults(defineProps<InputProps>(), {
44
+ type: "text",
45
+ modelValue: "",
46
+ });
47
+
48
+ const inputRef = useTemplateRef("input");
49
+
50
+ const emit = defineEmits<{
51
+ "update:modelValue": [value: string];
52
+ }>();
53
+
54
+ const handleInput = (event: Event) => {
55
+ const target = event.target as HTMLInputElement;
56
+ let value = target.value;
57
+
58
+ /* val input with pattern */
59
+ if (props.pattern) {
60
+ const regex = new RegExp(props.pattern);
61
+ value = Array.from(value)
62
+ .filter((char) => regex.test(char))
63
+ .join("");
64
+ }
65
+
66
+ /* Handle maxlength */
67
+ if (props.maxlength) {
68
+ value = value.slice(0, props.maxlength);
69
+ }
70
+
71
+ target.value = value;
72
+ emit("update:modelValue", value);
73
+ };
74
+
75
+ const styles = tv({
76
+ base: [
77
+ "flex h-9 w-full min-w-0 rounded-md border border-input bg-transparent px-3 py-1 text-sm shadow-xs transition-[color,box-shadow] outline-none selection:bg-primary selection:text-primary-foreground file:inline-flex file:h-7 file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground placeholder:text-muted-foreground/70 disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 dark:bg-input/30",
78
+ "focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50",
79
+ "aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40",
80
+ ],
81
+ variants: {
82
+ type: {
83
+ search:
84
+ "[&::-webkit-search-cancel-button]:appearance-none [&::-webkit-search-decoration]:appearance-none [&::-webkit-search-results-button]:appearance-none [&::-webkit-search-results-decoration]:appearance-none",
85
+ file: "p-0 pr-3 text-muted-foreground/70 italic file:me-3 file:h-full file:border-0 file:border-r file:border-solid file:border-input file:bg-transparent file:px-3 file:text-sm file:font-medium file:text-foreground file:not-italic",
86
+ },
87
+ },
88
+ });
89
+
90
+ onMounted(() => {
91
+ if (props.autofocus) {
92
+ inputRef.value?.focus();
93
+ }
94
+ });
95
+
96
+ defineExpose({ inputRef });
97
+ </script>
@@ -0,0 +1,66 @@
1
+ <template>
2
+ <Primitive
3
+ v-bind="forwarded"
4
+ role="group"
5
+ data-slot="input-group-addon"
6
+ :data-align="align || undefined"
7
+ :class="inputGroupAddonVariants({ class: normalizeClass(props.class) || undefined, align })"
8
+ @click="onClick"
9
+ >
10
+ <slot />
11
+ </Primitive>
12
+ </template>
13
+
14
+ <script lang="ts">
15
+ import { Primitive } from "reka-ui";
16
+ import type { PrimitiveProps } from "reka-ui";
17
+ import type { VariantProps } from "tailwind-variants";
18
+ import { normalizeClass } from "vue";
19
+ import type { HTMLAttributes } from "vue";
20
+
21
+ const inputGroupAddonVariants = tv({
22
+ base: "flex h-auto cursor-text items-center justify-center gap-2 py-1.5 text-sm font-medium text-muted-foreground select-none group-data-[disabled=true]/input-group:opacity-50 [&>kbd]:rounded-[calc(var(--radius)-5px)] [&>svg:not([class*='size-'])]:size-4",
23
+
24
+ variants: {
25
+ align: {
26
+ "inline-start": "order-first pl-3 has-[>button]:ml-[-0.45rem] has-[>kbd]:ml-[-0.35rem]",
27
+ "inline-end": "order-last pr-3 has-[>button]:mr-[-0.45rem] has-[>kbd]:mr-[-0.35rem]",
28
+ "block-start":
29
+ "order-first w-full justify-start px-3 pt-3 group-has-[>input]/input-group:pt-2.5 [.border-b]:pb-3",
30
+ "block-end":
31
+ "order-last w-full flex-wrap justify-start gap-y-2 px-3 pb-3 group-has-[>input]/input-group:pb-2.5 [.border-t]:pt-3",
32
+ },
33
+ },
34
+ defaultVariants: {
35
+ align: "inline-start",
36
+ },
37
+ });
38
+
39
+ export type InputGroupAddonVariants = PrimitiveProps & {
40
+ /**
41
+ * Alignment of the addon within the input group.
42
+ * @default "inline-start"
43
+ */
44
+ align?: VariantProps<typeof inputGroupAddonVariants>["align"];
45
+ /**
46
+ * Additional classes to apply to the input group addon container.
47
+ */
48
+ class?: HTMLAttributes["class"];
49
+ };
50
+ </script>
51
+
52
+ <script lang="ts" setup>
53
+ const props = withDefaults(defineProps<InputGroupAddonVariants>(), {
54
+ align: "inline-start",
55
+ });
56
+
57
+ const forwarded = reactiveOmit(props, ["align", "class"]);
58
+
59
+ const onClick = (e: any) => {
60
+ if ((e.target as HTMLElement).closest("button")) {
61
+ return;
62
+ }
63
+ // Focus the associated input, textarea, or textbox when the addon is clicked.
64
+ e.currentTarget?.parentElement?.querySelector("input, textarea, [role='textbox']")?.focus();
65
+ };
66
+ </script>
@@ -0,0 +1,50 @@
1
+ <template>
2
+ <UiButton
3
+ data-slot="input-group-button"
4
+ v-bind="forwarded"
5
+ :data-size="size"
6
+ :class="inputGroupButtonVariants({ class: normalizeClass(props.class) || undefined, size })"
7
+ >
8
+ <slot />
9
+ </UiButton>
10
+ </template>
11
+
12
+ <script lang="ts">
13
+ import type { VariantProps } from "tailwind-variants";
14
+ import { normalizeClass } from "vue";
15
+
16
+ import type { ButtonProps } from "@/components/Ui/Button.vue";
17
+
18
+ export const inputGroupButtonVariants = tv({
19
+ base: "flex items-center gap-2 text-sm shadow-none",
20
+ variants: {
21
+ size: {
22
+ xs: "h-6 gap-1 rounded-[calc(var(--radius)-5px)] px-2 has-[>svg]:px-2 [&>svg:not([class*='size-'])]:size-3.5",
23
+ sm: "h-8 gap-1.5 rounded-md px-2.5 has-[>svg]:px-2.5",
24
+ "icon-xs": "size-6 rounded-[calc(var(--radius)-5px)] p-0 has-[>svg]:p-0",
25
+ "icon-sm": "size-8 p-0 has-[>svg]:p-0",
26
+ },
27
+ },
28
+ defaultVariants: {
29
+ size: "xs",
30
+ },
31
+ });
32
+
33
+ export type InputGroupAddonVariants = Omit<ButtonProps, "size"> & {
34
+ /**
35
+ * The size of the button within the input group.
36
+ * @default "xs"
37
+ */
38
+ size?: VariantProps<typeof inputGroupButtonVariants>["size"];
39
+ };
40
+ </script>
41
+
42
+ <script lang="ts" setup>
43
+ const props = withDefaults(defineProps<InputGroupAddonVariants>(), {
44
+ size: "xs",
45
+ variant: "ghost",
46
+ type: "button",
47
+ });
48
+
49
+ const forwarded = reactiveOmit(props, ["size", "class"]);
50
+ </script>
@@ -0,0 +1,25 @@
1
+ <template>
2
+ <UiInput
3
+ v-bind="forwarded"
4
+ data-slot="input-group-input"
5
+ :class="inputGroupInputStyles({ class: normalizeClass(props.class) || undefined })"
6
+ >
7
+ <slot />
8
+ </UiInput>
9
+ </template>
10
+
11
+ <script lang="ts">
12
+ import { normalizeClass } from "vue";
13
+
14
+ import type { InputProps } from "@/components/Ui/Input.vue";
15
+
16
+ const inputGroupInputStyles = tv({
17
+ base: "flex-1 rounded-none border-0 bg-transparent shadow-none focus-visible:ring-0 dark:bg-transparent",
18
+ });
19
+ </script>
20
+
21
+ <script lang="ts" setup>
22
+ const props = defineProps<InputProps>();
23
+
24
+ const forwarded = reactiveOmit(props, ["class"]);
25
+ </script>
@@ -0,0 +1,44 @@
1
+ <template>
2
+ <Primitive
3
+ v-bind="props"
4
+ data-slot="input-group"
5
+ role="group"
6
+ :class="inputGroupStyles({ class: normalizeClass(props.class) || undefined })"
7
+ >
8
+ <slot />
9
+ </Primitive>
10
+ </template>
11
+
12
+ <script lang="ts">
13
+ import { Primitive } from "reka-ui";
14
+ import type { PrimitiveProps } from "reka-ui";
15
+ import { normalizeClass } from "vue";
16
+ import type { HTMLAttributes } from "vue";
17
+
18
+ export const inputGroupStyles = tv({
19
+ base: [
20
+ "group/input-group relative flex w-full items-center rounded-md border border-input shadow-xs transition-[color,box-shadow] outline-none dark:bg-input/30",
21
+ "h-9 has-[>textarea]:h-auto",
22
+ // Variants based on alignment.
23
+ "has-[>[data-align=inline-start]]:[&>input]:pl-2",
24
+ "has-[>[data-align=inline-end]]:[&>input]:pr-2",
25
+ "has-[>[data-align=block-start]]:h-auto has-[>[data-align=block-start]]:flex-col has-[>[data-align=block-start]]:[&>input]:pb-3",
26
+ "has-[>[data-align=block-end]]:h-auto has-[>[data-align=block-end]]:flex-col has-[>[data-align=block-end]]:[&>input]:pt-3",
27
+ // Focus state.
28
+ "has-[[data-slot=input-group-control]:focus-visible]:border-ring has-[[data-slot=input-group-control]:focus-visible]:ring-[3px] has-[[data-slot=input-group-control]:focus-visible]:ring-ring/50",
29
+ // Error state.
30
+ "has-[[data-slot][aria-invalid=true]]:border-destructive has-[[data-slot][aria-invalid=true]]:ring-destructive/20 dark:has-[[data-slot][aria-invalid=true]]:ring-destructive/40",
31
+ ],
32
+ });
33
+ </script>
34
+
35
+ <script lang="ts" setup>
36
+ const props = defineProps<
37
+ PrimitiveProps & {
38
+ /**
39
+ * Additional classes to apply to the input group container.
40
+ */
41
+ class?: HTMLAttributes["class"];
42
+ }
43
+ >();
44
+ </script>
@@ -0,0 +1,33 @@
1
+ <template>
2
+ <Primitive
3
+ v-bind="forwarded"
4
+ data-slot="input-group-text"
5
+ :class="inputGroupTextStyles({ class: normalizeClass(props.class) || undefined })"
6
+ >
7
+ <slot />
8
+ </Primitive>
9
+ </template>
10
+
11
+ <script lang="ts">
12
+ import { Primitive } from "reka-ui";
13
+ import type { PrimitiveProps } from "reka-ui";
14
+ import { normalizeClass } from "vue";
15
+ import type { HTMLAttributes } from "vue";
16
+
17
+ const inputGroupTextStyles = tv({
18
+ base: "flex items-center gap-2 text-sm text-muted-foreground [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4",
19
+ });
20
+
21
+ export type InputGroupText = PrimitiveProps & {
22
+ /**
23
+ * Additional classes to apply to the input group addon container.
24
+ */
25
+ class?: HTMLAttributes["class"];
26
+ };
27
+ </script>
28
+
29
+ <script lang="ts" setup>
30
+ const props = defineProps<InputGroupText>();
31
+
32
+ const forwarded = reactiveOmit(props, ["class"]);
33
+ </script>