boltdocs 2.6.2 → 2.7.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 (178) hide show
  1. package/bin/boltdocs.js +0 -1
  2. package/dist/cache-CQKlT4fI.mjs +6 -0
  3. package/dist/cache-DorPMFgW.cjs +6 -0
  4. package/dist/cards-BLoSiRuL.d.ts +30 -0
  5. package/dist/cards-CQn9mXZS.d.cts +30 -0
  6. package/dist/chunk-Ds5LZdWN.cjs +6 -0
  7. package/dist/client/index.cjs +1 -1
  8. package/dist/client/index.d.cts +168 -1339
  9. package/dist/client/index.d.ts +167 -1338
  10. package/dist/client/index.js +1 -1
  11. package/dist/{package-CFP44vfn.cjs → client/mdx.cjs} +1 -1
  12. package/dist/client/mdx.d.cts +128 -0
  13. package/dist/client/mdx.d.ts +129 -0
  14. package/dist/client/mdx.js +6 -0
  15. package/dist/client/primitives.cjs +6 -0
  16. package/dist/client/primitives.d.cts +818 -0
  17. package/dist/client/primitives.d.ts +818 -0
  18. package/dist/client/primitives.js +6 -0
  19. package/dist/client/theme/neutral.css +74 -361
  20. package/dist/client/theme/reset.css +189 -0
  21. package/dist/docs-layout-BlDhcQRv.cjs +6 -0
  22. package/dist/docs-layout-BvAOWEJw.js +6 -0
  23. package/dist/doctor-BQiQhCTl.cjs +6 -0
  24. package/dist/doctor-COpf35L2.cjs +20 -0
  25. package/dist/doctor-Dh1XP7Pz.mjs +20 -0
  26. package/dist/generator-DGW6pkCC.cjs +22 -0
  27. package/dist/generator-Dv3wEmhZ.mjs +22 -0
  28. package/dist/icons-dev-CrQLjoQp.js +6 -0
  29. package/dist/icons-dev-rzdz6Lf3.cjs +6 -0
  30. package/dist/image-BkIfa9oo.js +6 -0
  31. package/dist/image-DIGjCPe6.cjs +6 -0
  32. package/dist/mdx-K0WYBAJ3.js +7 -0
  33. package/dist/mdx-hpErbRUe.cjs +7 -0
  34. package/dist/meta-loader-0gJ4PtBC.cjs +6 -0
  35. package/dist/meta-loader-9IpAHWDS.mjs +6 -0
  36. package/dist/node/cli-entry.cjs +1 -2
  37. package/dist/node/cli-entry.mjs +1 -2
  38. package/dist/node/index.cjs +1 -1
  39. package/dist/node/index.d.cts +55 -11
  40. package/dist/node/index.d.mts +55 -12
  41. package/dist/node/index.mjs +1 -1
  42. package/dist/node/routes/worker.cjs +6 -0
  43. package/dist/node/routes/worker.d.cts +2 -0
  44. package/dist/node/routes/worker.d.mts +2 -0
  45. package/dist/node/routes/worker.mjs +6 -0
  46. package/dist/node-BzKYJJuY.cjs +111 -0
  47. package/dist/node-m6fKXXVs.mjs +111 -0
  48. package/dist/{package-Bqbn1AYK.mjs → package-2TVh81ZC.mjs} +1 -1
  49. package/dist/package-D1O_gJub.cjs +6 -0
  50. package/dist/parser-Bh11BsdA.cjs +6 -0
  51. package/dist/parser-D8eQvE7N.mjs +6 -0
  52. package/dist/parser-DYRzXWmA.cjs +6 -0
  53. package/dist/routes-CHf76Ye4.cjs +6 -0
  54. package/dist/routes-CMUZGI6T.mjs +6 -0
  55. package/dist/routes-Co1mRM58.cjs +6 -0
  56. package/dist/search-dialog-BACuzoVX.cjs +6 -0
  57. package/dist/search-dialog-BKagVT17.js +6 -0
  58. package/dist/search-dialog-C8w12eUx.js +6 -0
  59. package/dist/search-dialog-CGyrozZE.cjs +6 -0
  60. package/dist/search-dialog-D26rUnJ_.cjs +6 -0
  61. package/dist/sidebar-DKvg6KOc.d.cts +491 -0
  62. package/dist/sidebar-Dr1TiRIy.d.ts +491 -0
  63. package/dist/utils-BxNAXhZZ.mjs +7 -0
  64. package/dist/utils-Clzu7jvb.cjs +7 -0
  65. package/dist/worker-pool-Bd8Y9KDv.mjs +6 -0
  66. package/dist/worker-pool-BwU8ckrg.cjs +6 -0
  67. package/package.json +27 -8
  68. package/src/client/app/doc-page.tsx +9 -5
  69. package/src/client/app/docs-layout.tsx +17 -3
  70. package/src/client/app/head.tsx +122 -0
  71. package/src/client/app/helmet-compat.tsx +36 -0
  72. package/src/client/app/mdx-component.tsx +5 -52
  73. package/src/client/app/mdx-components-context.tsx +32 -8
  74. package/src/client/app/routes-context.tsx +2 -2
  75. package/src/client/app/scroll-handler.tsx +1 -1
  76. package/src/client/app/theme-context.tsx +5 -5
  77. package/src/client/app/ui-context.tsx +42 -0
  78. package/src/client/components/docs-layout-default.tsx +85 -0
  79. package/src/client/components/icons-dev.tsx +38 -15
  80. package/src/client/components/mdx/callout.tsx +97 -0
  81. package/src/client/components/mdx/card.tsx +73 -98
  82. package/src/client/components/mdx/cards.tsx +27 -0
  83. package/src/client/components/mdx/code-block.tsx +37 -17
  84. package/src/client/components/mdx/field.tsx +24 -56
  85. package/src/client/components/mdx/image.tsx +36 -15
  86. package/src/client/components/mdx/index.ts +19 -53
  87. package/src/client/components/mdx/table.tsx +46 -148
  88. package/src/client/components/mdx/typographics.tsx +120 -0
  89. package/src/client/components/mdx/{hooks/use-code-block.ts → use-code-block.ts} +5 -7
  90. package/src/client/components/primitives/breadcrumbs.tsx +5 -24
  91. package/src/client/components/primitives/button.tsx +3 -142
  92. package/src/client/components/primitives/code-block.tsx +104 -97
  93. package/src/client/components/{docs-layout.tsx → primitives/docs-layout.tsx} +15 -24
  94. package/src/client/components/primitives/error-boundary.tsx +107 -0
  95. package/src/client/components/primitives/heading.tsx +128 -0
  96. package/src/client/components/primitives/helpers/observer.ts +62 -32
  97. package/src/client/components/primitives/image.tsx +26 -0
  98. package/src/client/components/primitives/link.tsx +50 -52
  99. package/src/client/components/primitives/menu.tsx +25 -49
  100. package/src/client/components/primitives/navbar.tsx +234 -59
  101. package/src/client/components/primitives/on-this-page.tsx +169 -40
  102. package/src/client/components/primitives/page-nav.tsx +11 -39
  103. package/src/client/components/primitives/popover.tsx +12 -30
  104. package/src/client/components/primitives/search-dialog.tsx +77 -71
  105. package/src/client/components/primitives/sidebar.tsx +312 -119
  106. package/src/client/components/primitives/skeleton.tsx +1 -1
  107. package/src/client/components/primitives/tabs.tsx +5 -16
  108. package/src/client/components/primitives/tooltip.tsx +1 -1
  109. package/src/client/components/ui-base/banner.tsx +66 -0
  110. package/src/client/components/ui-base/breadcrumbs.tsx +26 -20
  111. package/src/client/components/ui-base/copy-markdown.tsx +43 -35
  112. package/src/client/components/ui-base/error-boundary.tsx +9 -46
  113. package/src/client/components/ui-base/github-stars.tsx +5 -3
  114. package/src/client/components/ui-base/index.ts +3 -3
  115. package/src/client/components/ui-base/last-updated.tsx +27 -0
  116. package/src/client/components/ui-base/navbar.tsx +183 -89
  117. package/src/client/components/ui-base/not-found.tsx +11 -9
  118. package/src/client/components/ui-base/on-this-page.tsx +8 -104
  119. package/src/client/components/ui-base/page-nav.tsx +23 -9
  120. package/src/client/components/ui-base/search-dialog.tsx +111 -36
  121. package/src/client/components/ui-base/search-highlight.tsx +10 -0
  122. package/src/client/components/ui-base/sidebar.tsx +77 -154
  123. package/src/client/components/ui-base/tabs.tsx +20 -7
  124. package/src/client/components/ui-base/theme-toggle.tsx +88 -10
  125. package/src/client/components/ui-base/version-i18n.tsx +80 -0
  126. package/src/client/hooks/index.ts +2 -1
  127. package/src/client/hooks/use-analytics.ts +272 -0
  128. package/src/client/hooks/use-i18n.ts +116 -50
  129. package/src/client/hooks/use-localized-to.ts +70 -27
  130. package/src/client/hooks/use-navbar.ts +69 -39
  131. package/src/client/hooks/use-page-nav.ts +28 -25
  132. package/src/client/hooks/use-routes.ts +63 -80
  133. package/src/client/hooks/use-search-highlight.ts +185 -0
  134. package/src/client/hooks/use-search.ts +12 -3
  135. package/src/client/hooks/use-sidebar.ts +183 -80
  136. package/src/client/hooks/use-tabs.ts +3 -4
  137. package/src/client/hooks/use-version.ts +44 -29
  138. package/src/client/index.ts +13 -87
  139. package/src/client/mdx.ts +2 -0
  140. package/src/client/primitives.ts +19 -0
  141. package/src/client/ssg/boltdocs-shell.tsx +68 -79
  142. package/src/client/ssg/create-routes.tsx +268 -72
  143. package/src/client/ssg/index.ts +1 -0
  144. package/src/client/ssg/mdx-page.tsx +2 -1
  145. package/src/client/store/boltdocs-context.tsx +72 -20
  146. package/src/client/theme/neutral.css +74 -361
  147. package/src/client/theme/reset.css +189 -0
  148. package/src/client/types.ts +10 -2
  149. package/src/client/utils/path.ts +9 -0
  150. package/src/client/utils/react-to-text.ts +24 -24
  151. package/src/client/virtual.d.ts +1 -1
  152. package/src/shared/types.ts +82 -22
  153. package/dist/node-Bogvkxao.mjs +0 -101
  154. package/dist/node-CXaog6St.cjs +0 -101
  155. package/dist/search-dialog-CV3eJzMm.cjs +0 -6
  156. package/dist/search-dialog-DNTomKgu.js +0 -6
  157. package/dist/use-search-CS3gH19M.js +0 -6
  158. package/dist/use-search-DBpJZQuw.cjs +0 -6
  159. package/src/client/components/mdx/admonition.tsx +0 -91
  160. package/src/client/components/mdx/badge.tsx +0 -41
  161. package/src/client/components/mdx/button.tsx +0 -35
  162. package/src/client/components/mdx/component-preview.tsx +0 -37
  163. package/src/client/components/mdx/component-props.tsx +0 -83
  164. package/src/client/components/mdx/file-tree.tsx +0 -325
  165. package/src/client/components/mdx/hooks/use-component-preview.ts +0 -16
  166. package/src/client/components/mdx/hooks/useTable.ts +0 -74
  167. package/src/client/components/mdx/hooks/useTabs.ts +0 -68
  168. package/src/client/components/mdx/link.tsx +0 -38
  169. package/src/client/components/mdx/list.tsx +0 -192
  170. package/src/client/components/mdx/tabs.tsx +0 -135
  171. package/src/client/components/mdx/video.tsx +0 -68
  172. package/src/client/components/primitives/index.ts +0 -19
  173. package/src/client/components/primitives/navigation-menu.tsx +0 -114
  174. package/src/client/components/ui-base/head.tsx +0 -83
  175. package/src/client/components/ui-base/loading.tsx +0 -57
  176. package/src/client/components/ui-base/powered-by.tsx +0 -25
  177. package/src/client/hooks/use-onthispage.ts +0 -23
  178. package/src/client/utils/use-on-change.ts +0 -15
@@ -0,0 +1,97 @@
1
+ import { Info, Lightbulb, AlertTriangle, AlertCircle } from 'lucide-react'
2
+ import { cn } from '../../utils/cn'
3
+
4
+ export type CalloutVariant = 'note' | 'tip' | 'warning' | 'danger' | 'info'
5
+
6
+ export interface CalloutProps extends React.HTMLAttributes<HTMLDivElement> {
7
+ variant?: CalloutVariant
8
+ title?: string
9
+ }
10
+
11
+ const variantStyles: Record<
12
+ CalloutVariant,
13
+ {
14
+ container: string
15
+ titleText: string
16
+ iconColor: string
17
+ icon: React.ComponentType<any>
18
+ defaultTitle: string
19
+ }
20
+ > = {
21
+ note: {
22
+ container:
23
+ 'bg-slate-500/5 dark:bg-slate-500/10 border-slate-500/40 text-slate-800 dark:text-slate-200',
24
+ titleText: 'text-slate-900 dark:text-slate-100',
25
+ iconColor: 'text-slate-500',
26
+ icon: Info,
27
+ defaultTitle: 'Note',
28
+ },
29
+ info: {
30
+ container:
31
+ 'bg-indigo-500/5 dark:bg-indigo-500/10 border-indigo-500/40 text-indigo-800 dark:text-indigo-200',
32
+ titleText: 'text-indigo-900 dark:text-indigo-100',
33
+ iconColor: 'text-indigo-500',
34
+ icon: Info,
35
+ defaultTitle: 'Info',
36
+ },
37
+ tip: {
38
+ container:
39
+ 'bg-green-500/5 dark:bg-green-500/10 border-green-500/40 text-green-800 dark:text-green-200',
40
+ titleText: 'text-green-900 dark:text-green-100',
41
+ iconColor: 'text-green-500',
42
+ icon: Lightbulb,
43
+ defaultTitle: 'Tip',
44
+ },
45
+ warning: {
46
+ container:
47
+ 'bg-amber-500/5 dark:bg-amber-500/10 border-amber-500/40 text-amber-800 dark:text-amber-200',
48
+ titleText: 'text-amber-900 dark:text-amber-100',
49
+ iconColor: 'text-amber-500',
50
+ icon: AlertTriangle,
51
+ defaultTitle: 'Warning',
52
+ },
53
+ danger: {
54
+ container:
55
+ 'bg-rose-500/5 dark:bg-rose-500/10 border-rose-500/40 text-rose-800 dark:text-rose-200',
56
+ titleText: 'text-rose-900 dark:text-rose-100',
57
+ iconColor: 'text-rose-500',
58
+ icon: AlertCircle,
59
+ defaultTitle: 'Danger',
60
+ },
61
+ }
62
+
63
+ export function Callout({
64
+ children,
65
+ className = '',
66
+ variant = 'note',
67
+ title,
68
+ ...props
69
+ }: CalloutProps) {
70
+ const styles = variantStyles[variant] || variantStyles.note
71
+ const Icon = styles.icon
72
+
73
+ return (
74
+ <div
75
+ className={cn(
76
+ 'my-6 flex gap-4 p-4 rounded-xl border-2',
77
+ styles.container,
78
+ className,
79
+ )}
80
+ {...props}
81
+ >
82
+ <div className={cn('shrink-0 pt-0.5', styles.iconColor)}>
83
+ <Icon className="w-5 h-5 stroke-[2]" />
84
+ </div>
85
+ <div className="flex-1 text-[0.875rem] leading-[1.6]">
86
+ <div className={cn('font-bold text-sm mb-1', styles.titleText)}>
87
+ {title || styles.defaultTitle}
88
+ </div>
89
+ <div className="prose prose-neutral dark:prose-invert max-w-none [&>p]:m-0 [&>p+p]:mt-2">
90
+ {children}
91
+ </div>
92
+ </div>
93
+ </div>
94
+ )
95
+ }
96
+
97
+ export default Callout
@@ -1,124 +1,99 @@
1
- import type { MouseEvent as ReactMouseEvent } from 'react'
2
- import { useCallback, useRef } from 'react'
3
- import * as RAC from 'react-aria-components'
1
+ import { useState, useRef } from 'react'
4
2
  import { cn } from '../../utils/cn'
5
- import { cva } from 'class-variance-authority'
6
- import type { VariantProps } from 'class-variance-authority'
7
-
8
- const cardsVariants = cva('grid gap-4 my-6', {
9
- variants: {
10
- cols: {
11
- 1: 'grid-cols-1',
12
- 2: 'grid-cols-1 sm:grid-cols-2',
13
- 3: 'grid-cols-1 sm:grid-cols-2 lg:grid-cols-3',
14
- 4: 'grid-cols-1 sm:grid-cols-2 lg:grid-cols-4',
15
- },
16
- },
17
- defaultVariants: {
18
- cols: 3,
19
- },
20
- })
21
- type CardsVariants = VariantProps<typeof cardsVariants>
22
-
23
- export interface CardsProps
24
- extends React.HTMLAttributes<HTMLDivElement>,
25
- CardsVariants {}
26
-
27
- export function Cards({
28
- cols = 3,
29
- children,
30
- className = '',
31
- ...rest
32
- }: CardsProps) {
33
- return (
34
- <div className={cn(cardsVariants({ cols }), className)} {...rest}>
35
- {children}
36
- </div>
37
- )
38
- }
39
3
 
40
4
  export interface CardProps extends React.HTMLAttributes<HTMLDivElement> {
41
- title?: string
5
+ title?: React.ReactNode
42
6
  icon?: React.ReactNode
43
7
  href?: string
44
- children?: React.ReactNode
45
8
  }
46
9
 
47
10
  export function Card({
11
+ className,
48
12
  title,
49
13
  icon,
50
14
  href,
51
15
  children,
52
- className = '',
53
- ...rest
16
+ ...props
54
17
  }: CardProps) {
18
+ const [position, setPosition] = useState({ x: 0, y: 0 })
19
+ const [opacity, setOpacity] = useState(0)
55
20
  const cardRef = useRef<HTMLDivElement>(null)
56
- const linkRef = useRef<HTMLAnchorElement>(null)
57
21
 
58
- const handleMouseMove = useCallback((e: ReactMouseEvent<HTMLDivElement>) => {
59
- const el = cardRef.current || linkRef.current
60
- if (!el) return
61
- const { left, top } = el.getBoundingClientRect()
62
- el.style.setProperty('--x', `${e.clientX - left}px`)
63
- el.style.setProperty('--y', `${e.clientY - top}px`)
64
- }, [])
22
+ const handleMouseMove = (e: React.MouseEvent<HTMLDivElement>) => {
23
+ if (!cardRef.current) return
24
+ const rect = cardRef.current.getBoundingClientRect()
25
+ setPosition({ x: e.clientX - rect.left, y: e.clientY - rect.top })
26
+ }
27
+
28
+ const handleMouseEnter = () => setOpacity(1)
29
+ const handleMouseLeave = () => setOpacity(0)
65
30
 
66
- const inner = (
67
- <>
31
+ const Wrapper = href ? 'a' : 'div'
32
+ const spotlightColor = 'var(--color-primary-500, #eb5828)'
33
+
34
+ return (
35
+ <Wrapper
36
+ ref={cardRef}
37
+ href={href}
38
+ onMouseMove={handleMouseMove}
39
+ onMouseEnter={handleMouseEnter}
40
+ onMouseLeave={handleMouseLeave}
41
+ className={cn(
42
+ 'group relative flex flex-col gap-3 rounded-2xl border p-6 overflow-hidden transition-all duration-300',
43
+ 'hover:shadow-lg dark:hover:shadow-none hover:-translate-y-0.5',
44
+ 'bg-surface border-subtle text-paragraph',
45
+ href && 'cursor-pointer',
46
+ className,
47
+ )}
48
+ {...(props as any)}
49
+ >
50
+ {/* Background Spotlight */}
68
51
  <div
69
- className="pointer-events-none absolute -inset-px rounded-xl opacity-0 transition-opacity duration-300 group-hover:opacity-100"
52
+ className="pointer-events-none absolute inset-0 transition-opacity duration-300"
70
53
  style={{
71
- background:
72
- 'radial-gradient(400px circle at var(--x) var(--y), color-mix(in oklch, var(--color-primary-500), transparent 90%), transparent 80%)',
54
+ opacity,
55
+ background: `radial-gradient(600px circle at ${position.x}px ${position.y}px, color-mix(in srgb, ${spotlightColor} 8%, transparent), transparent 40%)`,
73
56
  }}
74
57
  />
75
- {icon && (
76
- <div className="mb-3 flex h-10 w-10 items-center justify-center rounded-lg bg-primary-500/10 text-primary-400 text-lg transition-transform duration-300 group-hover:scale-105 group-hover:-rotate-3">
77
- {icon}
78
- </div>
79
- )}
80
- <div className="space-y-1.5">
81
- {title && <h3 className="text-sm font-bold text-text-main">{title}</h3>}
82
- {children && (
83
- <div className="text-sm text-text-muted leading-relaxed">
84
- {children}
58
+ {/* Border Spotlight Glow */}
59
+ <div
60
+ className="pointer-events-none absolute inset-0 rounded-2xl transition-opacity duration-300"
61
+ style={{
62
+ opacity,
63
+ padding: '1px',
64
+ background: `radial-gradient(400px circle at ${position.x}px ${position.y}px, color-mix(in srgb, ${spotlightColor} 50%, transparent), transparent 40%)`,
65
+ WebkitMask:
66
+ 'linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0)',
67
+ WebkitMaskComposite: 'xor',
68
+ maskComposite: 'exclude',
69
+ }}
70
+ />
71
+
72
+ {/* Header Content */}
73
+ <div className="relative z-10 flex items-center gap-3">
74
+ {icon && (
75
+ <div
76
+ className={cn(
77
+ 'shrink-0 transition-transform duration-500 group-hover:rotate-[15deg] group-hover:scale-110 flex items-center justify-center text-muted group-hover:text-primary-500',
78
+ '[&>svg]:w-6 [&>svg]:h-6 [&>svg]:stroke-[1.5]',
79
+ )}
80
+ >
81
+ {icon}
85
82
  </div>
86
83
  )}
84
+ {title && (
85
+ <h3 className="font-semibold text-base m-0 leading-none text-body">
86
+ {title}
87
+ </h3>
88
+ )}
87
89
  </div>
88
- </>
89
- )
90
-
91
- const cardClasses = cn(
92
- 'group relative block rounded-xl border border-border-subtle bg-bg-surface p-5 outline-none overflow-hidden',
93
- 'transition-all duration-200 hover:border-primary-500/40 hover:shadow-lg hover:shadow-primary-500/5',
94
- 'focus-visible:ring-2 focus-visible:ring-primary-500/30',
95
- className,
96
- )
97
90
 
98
- if (href) {
99
- return (
100
- <RAC.Link
101
- ref={linkRef}
102
- href={href}
103
- className={cn(cardClasses, 'no-underline cursor-pointer')}
104
- onMouseMove={handleMouseMove}
105
- {...(rest as any)}
106
- >
107
- {inner}
108
- </RAC.Link>
109
- )
110
- }
111
-
112
- return (
113
- // biome-ignore lint/a11y/noStaticElementInteractions: spotlight effect is decorative
114
- <div
115
- ref={cardRef}
116
- role="presentation"
117
- className={cardClasses}
118
- onMouseMove={handleMouseMove}
119
- {...rest}
120
- >
121
- {inner}
122
- </div>
91
+ {/* Body Content */}
92
+ <div className="relative z-10 text-[0.875rem] leading-[1.6] opacity-90 prose prose-neutral dark:prose-invert max-w-none [&>p]:m-0 [&>p+p]:mt-2">
93
+ {children}
94
+ </div>
95
+ </Wrapper>
123
96
  )
124
97
  }
98
+
99
+ export default Card
@@ -0,0 +1,27 @@
1
+ import { cn } from '../../utils/cn'
2
+
3
+ export interface CardsProps extends React.HTMLAttributes<HTMLDivElement> {
4
+ cols?: 1 | 2 | 3 | 4
5
+ }
6
+
7
+ export function Cards({ children, className, cols = 2, ...props }: CardsProps) {
8
+ return (
9
+ <div
10
+ className={cn(
11
+ 'grid gap-4 my-6',
12
+ {
13
+ 'grid-cols-1': cols === 1,
14
+ 'grid-cols-1 sm:grid-cols-2': cols === 2,
15
+ 'grid-cols-1 sm:grid-cols-2 md:grid-cols-3': cols === 3,
16
+ 'grid-cols-1 sm:grid-cols-2 lg:grid-cols-4': cols === 4,
17
+ },
18
+ className,
19
+ )}
20
+ {...props}
21
+ >
22
+ {children}
23
+ </div>
24
+ )
25
+ }
26
+
27
+ export default Cards
@@ -2,7 +2,7 @@ import { Button } from 'react-aria-components'
2
2
  import { Copy, Check, File } from 'lucide-react'
3
3
  import { cn } from '../../utils/cn'
4
4
  import { reactToText } from '../../utils/react-to-text'
5
- import { useCodeBlock } from './hooks/use-code-block'
5
+ import { useCodeBlock } from './use-code-block'
6
6
  import * as CodePrimitive from '../primitives/code-block'
7
7
  import {
8
8
  TypeScript,
@@ -16,6 +16,7 @@ import {
16
16
  Yaml,
17
17
  Rust,
18
18
  BracketsRed,
19
+ Csv,
19
20
  } from '../icons-dev'
20
21
  import { Tooltip } from '../primitives/tooltip'
21
22
 
@@ -35,7 +36,8 @@ const langIconMap: Record<string, React.ComponentType<{ size?: number }>> = {
35
36
  yml: Yaml,
36
37
  rs: Rust,
37
38
  rust: Rust,
38
- toml: BracketsRed
39
+ toml: BracketsRed,
40
+ csv: Csv,
39
41
  }
40
42
 
41
43
  export interface CodeBlockProps {
@@ -51,17 +53,21 @@ export interface CodeBlockProps {
51
53
  [key: string]: any
52
54
  }
53
55
 
54
- const CopyButton = ({ copied, handleCopy }: { copied: boolean; handleCopy: () => void }) => {
56
+ const CopyButton = ({
57
+ copied,
58
+ handleCopy,
59
+ }: {
60
+ copied: boolean
61
+ handleCopy: () => void
62
+ }) => {
55
63
  return (
56
64
  <Tooltip content={copied ? 'Copied!' : 'Copy code'}>
57
65
  {/* @ts-ignore */}
58
66
  <Button
59
67
  onPress={handleCopy}
60
68
  className={cn(
61
- 'grid place-items-center size-8 bg-transparent outline-none cursor-pointer transition-all duration-200 hover:scale-110 active:scale-95 [&>svg]:size-4 [&>svg]:stroke-2',
62
- copied
63
- ? 'text-emerald-400'
64
- : 'text-text-muted hover:text-text-main',
69
+ 'grid place-items-center size-8 bg-transparent outline-none cursor-pointer transition-all duration-200 hover:scale-110 active:scale-95 [&>svg]:size-4 [&>svg]:stroke-2 z-10',
70
+ copied ? 'text-emerald-400' : 'text-muted hover:text-body',
65
71
  )}
66
72
  aria-label="Copy code"
67
73
  >
@@ -85,7 +91,14 @@ export function CodeBlock(props: CodeBlockProps) {
85
91
  ...rest
86
92
  } = props
87
93
 
88
- const effectiveHighlightedHtml = highlightedHtml || dataHighlightedHtml
94
+ const rawHighlightedHtml = highlightedHtml || dataHighlightedHtml
95
+ const effectiveHighlightedHtml =
96
+ typeof rawHighlightedHtml === 'string'
97
+ ? rawHighlightedHtml.replace(
98
+ /<span class="line">\s*(?:<span[^>]*>\s*<\/span>)?\s*<\/span>\s*(<\/code>\s*<\/pre>)/g,
99
+ '$1',
100
+ )
101
+ : rawHighlightedHtml
89
102
  const effectiveTitle = title || dataTitle
90
103
  const lang = props.lang || dataLang || ''
91
104
 
@@ -104,39 +117,46 @@ export function CodeBlock(props: CodeBlockProps) {
104
117
  return (
105
118
  <CodePrimitive.CodeBlock plain={plain} className={props.className}>
106
119
  {(effectiveTitle || !hideCopy) && (
107
- <CodePrimitive.CodeBlockHeader>
120
+ <CodePrimitive.CodeBlockHeader
121
+ className={cn({
122
+ 'absolute top-2 left-0 w-full': !effectiveTitle,
123
+ })}
124
+ >
108
125
  <CodePrimitive.CodeBlockGroup>
109
126
  {effectiveTitle && (
110
127
  <>
111
128
  {LangIcon ? (
112
129
  <LangIcon size={14} />
113
130
  ) : (
114
- // @ts-ignore
115
131
  <File size={14} className="opacity-60" />
116
132
  )}
117
133
  <span>{effectiveTitle}</span>
118
134
  </>
119
135
  )}
120
136
  </CodePrimitive.CodeBlockGroup>
121
- {!hideCopy && <CopyButton copied={copied} handleCopy={handleCopy} />}
137
+ <div className="flex items-center gap-1">
138
+ {!hideCopy && (
139
+ <CopyButton copied={copied} handleCopy={handleCopy} />
140
+ )}
141
+ </div>
122
142
  </CodePrimitive.CodeBlockHeader>
123
143
  )}
124
144
 
125
145
  <CodePrimitive.CodeBlockContent shouldTruncate={shouldTruncate}>
126
146
  {effectiveHighlightedHtml ? (
127
147
  <div
128
- // @ts-ignore
148
+ // @ts-expect-error
129
149
  ref={preRef}
130
- className="shiki-wrapper [&>pre]:m-0! [&>pre]:rounded-none! [&>pre]:border-none! [&>pre]:bg-inherit! [&>pre>code]:grid! [&>pre>code]:p-5! [&>.shiki.shiki-themes]:bg-transparent!"
150
+ className="shiki-wrapper overflow-x-auto [&>pre]:m-0! [&>pre]:rounded-none! [&>pre]:border-none! [&>pre]:bg-inherit! [&>pre>code]:grid! [&>pre>code]:p-5! [&>pre>code]:text-[0.875rem]! [&>pre>code]:leading-[1.6]! [&>.shiki.shiki-themes]:bg-transparent!"
131
151
  dangerouslySetInnerHTML={{ __html: effectiveHighlightedHtml }}
132
152
  />
133
153
  ) : (
134
154
  <pre
135
155
  ref={preRef}
136
- className="m-0! p-5! rounded-none! border-none! bg-inherit! font-mono text-[0.8125rem] leading-[1.7] overflow-x-auto"
156
+ className="m-0! p-5! rounded-none! border-none! bg-inherit! font-mono text-[0.875rem] leading-[1.6] overflow-x-auto"
137
157
  {...rest}
138
158
  >
139
- {reactToText(children)}
159
+ {reactToText(children).trimEnd()}
140
160
  </pre>
141
161
  )}
142
162
 
@@ -146,13 +166,13 @@ export function CodeBlock(props: CodeBlockProps) {
146
166
  className={cn(
147
167
  shouldTruncate
148
168
  ? 'absolute bottom-0 inset-x-0 h-24 bg-linear-to-t from-(--color-code-bg) to-transparent flex items-end justify-center pb-4 z-10'
149
- : 'relative flex justify-center py-4',
169
+ : 'relative flex justify-center pb-4 pt-1 -mt-4',
150
170
  )}
151
171
  >
152
172
  {/* @ts-ignore */}
153
173
  <Button
154
174
  onPress={() => setIsExpanded(!isExpanded)}
155
- className="rounded-full bg-bg-surface border border-border-subtle px-5 py-2 text-[0.8125rem] font-medium text-text-main outline-none cursor-pointer transition-all hover:bg-border-subtle hover:-translate-y-px backdrop-blur-md"
175
+ className="rounded-full bg-surface border border-subtle px-5 py-2 text-[0.8125rem] font-medium text-body outline-none cursor-pointer transition-all hover:bg-soft hover:-translate-y-px backdrop-blur-md"
156
176
  >
157
177
  {isExpanded ? 'Show less' : 'Expand code'}
158
178
  </Button>
@@ -1,65 +1,33 @@
1
- import { cn } from '../../utils/cn'
2
-
3
1
  export interface FieldProps {
2
+ children?: React.ReactNode
4
3
  name: string
5
4
  type?: string
6
- defaultValue?: string
5
+ description?: string
7
6
  required?: boolean
8
- children: React.ReactNode
9
- id?: string
10
- className?: string
11
7
  }
12
8
 
13
- export function Field({
9
+ export const Field = ({
10
+ children,
14
11
  name,
15
12
  type,
16
- defaultValue,
17
- required = false,
18
- children,
19
- id,
20
- className = '',
21
- }: FieldProps) {
22
- return (
23
- <article
24
- className={cn(
25
- 'group relative my-6 rounded-xl border border-border-subtle bg-bg-surface p-5 transition-all duration-300',
26
- className,
13
+ description,
14
+ required,
15
+ }: FieldProps) => (
16
+ <div className="my-4 border border-subtle bg-surface/50 p-4 rounded-xl flex flex-col gap-1 text-sm select-none">
17
+ <div className="flex items-center gap-2">
18
+ <span className="font-mono font-bold text-primary-500">{name}</span>
19
+ {type && (
20
+ <span className="text-xs text-muted font-mono bg-soft px-1.5 py-0.5 rounded-md">
21
+ {type}
22
+ </span>
27
23
  )}
28
- id={id}
29
- >
30
- <div className="flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between mb-4">
31
- <div className="flex flex-wrap items-center gap-2.5">
32
- <code className="inline-flex items-center rounded-md bg-primary-500/10 px-2.5 py-1 font-mono text-sm font-bold text-primary-400 border border-primary-500/20 shadow-sm transition-colors">
33
- {name}
34
- </code>
35
- {type && (
36
- <span className="rounded-md bg-bg-muted/80 border border-border-subtle px-2 py-0.5 text-[11px] font-semibold text-text-muted uppercase shadow-sm">
37
- {type}
38
- </span>
39
- )}
40
- {required && (
41
- <div className="flex items-center gap-1.5 rounded-full bg-red-500/10 px-2.5 py-0.5 text-[10px] font-bold uppercase text-red-400 border border-red-500/20 shadow-sm">
42
- <span className="h-1 w-1 rounded-full bg-red-400 animate-pulse" />
43
- Required
44
- </div>
45
- )}
46
- </div>
47
-
48
- {defaultValue && (
49
- <div className="flex items-center gap-2 text-[11px] text-text-muted bg-bg-muted/30 px-2.5 py-1 rounded-md border border-border-subtle/50">
50
- <span className="font-semibold opacity-60 uppercase tracking-tighter">
51
- Default
52
- </span>
53
- <code className="font-mono text-text-main font-medium">
54
- {defaultValue}
55
- </code>
56
- </div>
57
- )}
58
- </div>
59
-
60
- <div className="text-sm text-text-muted leading-relaxed [&>p]:m-0 selection:bg-primary-500/30">
61
- {children}
62
- </div>
63
- </article>
64
- )
65
- }
24
+ {required && (
25
+ <span className="text-xs text-rose-500 font-semibold">required</span>
26
+ )}
27
+ </div>
28
+ {description && (
29
+ <div className="text-muted text-xs mt-1">{description}</div>
30
+ )}
31
+ {children && <div className="mt-2">{children}</div>}
32
+ </div>
33
+ )
@@ -1,23 +1,44 @@
1
- import type { ImgHTMLAttributes } from 'react'
2
1
  import { useTheme } from '../../app/theme-context'
2
+ import { cn } from '../../utils/cn'
3
+ import { Image as ImagePrimitive } from '../primitives/image'
3
4
 
4
- export interface ImageProps extends ImgHTMLAttributes<HTMLImageElement> {
5
- src: string
6
- darkSrc?: string
5
+ export interface ImageProps extends React.ImgHTMLAttributes<HTMLImageElement> {
7
6
  theme?: 'light' | 'dark'
8
7
  }
9
8
 
10
- /**
11
- * A themed Image component for Boltdocs.
12
- * It supports rendering based on the current active theme.
13
- */
14
- export function Image({ src, alt, theme: imageTheme, ...props }: ImageProps) {
15
- const { theme: currentTheme } = useTheme()
9
+ const Image = ({ src, alt, title, theme, className, ...props }: ImageProps) => {
10
+ const { theme: themeContext } = useTheme()
11
+ if (!src) return null
12
+ if (theme !== themeContext) return null
16
13
 
17
- // If a specific theme is required for this image, only render if it matches
18
- if (imageTheme && imageTheme !== currentTheme) {
19
- return null
20
- }
14
+ const caption = title || alt
21
15
 
22
- return <img src={src} alt={alt || ''} {...props} />
16
+ return (
17
+ <figure className="my-6 sm:my-8 flex flex-col items-center justify-center group not-prose">
18
+ <div className="relative w-full overflow-hidden rounded-lg sm:rounded-2xl border border-subtle bg-soft/30 transition-all duration-300 sm:max-w-[85%] lg:max-w-full">
19
+ <ImagePrimitive
20
+ src={src}
21
+ alt={alt || ''}
22
+ theme={theme}
23
+ loading="lazy"
24
+ decoding="async"
25
+ className={cn(
26
+ 'w-full h-auto object-contain transition-transform duration-500 group-hover:scale-[1.01] my-0 rounded-md sm:rounded-xl block',
27
+ className,
28
+ )}
29
+ {...props}
30
+ />
31
+ </div>
32
+ {caption && (
33
+ <figcaption className="mt-2 sm:mt-3 text-center text-xs sm:text-sm text-muted font-medium select-none tracking-wide opacity-90 sm:opacity-80 group-hover:opacity-100 transition-opacity duration-300 px-2">
34
+ {caption}
35
+ </figcaption>
36
+ )}
37
+ </figure>
38
+ )
39
+ }
40
+
41
+ export const ImageComponents = {
42
+ img: Image,
43
+ Image,
23
44
  }