boltdocs 2.7.10 → 2.7.11

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 (137) hide show
  1. package/dist/client/index.cjs +1929 -1
  2. package/dist/client/index.js +1880 -1
  3. package/dist/client/mdx.cjs +7 -1
  4. package/dist/client/mdx.js +7 -1
  5. package/dist/client/primitives.cjs +60 -1
  6. package/dist/client/primitives.js +20 -1
  7. package/dist/docs-layout-BXHV0xw_.cjs +1431 -0
  8. package/dist/docs-layout-DwFndmj5.js +1231 -0
  9. package/dist/icons-dev-3cZMyt8r.cjs +1204 -0
  10. package/dist/icons-dev-Df8OQ481.js +839 -0
  11. package/dist/image-DtrI2cw3.cjs +268 -0
  12. package/dist/image-jxPb-2iV.js +214 -0
  13. package/dist/mdx-BdWkJTeB.cjs +523 -0
  14. package/dist/mdx-UTTLFWJq.js +494 -0
  15. package/dist/node/cli-entry.cjs +1 -1
  16. package/dist/node/cli-entry.mjs +1 -1
  17. package/dist/node/index.cjs +1 -1
  18. package/dist/node/index.mjs +1 -1
  19. package/dist/{node-DtEDyN1u.cjs → node-BSM4qcDK.cjs} +1 -1
  20. package/dist/{node-_1jhMGYx.mjs → node-BspZN3R2.mjs} +1 -1
  21. package/dist/{package-DrwtlXfk.cjs → package-DIIrjuWI.cjs} +1 -1
  22. package/dist/{package--0Yf0t1N.mjs → package-K0zsjGIz.mjs} +1 -1
  23. package/dist/{search-dialog-ByvGScjt.js → search-dialog-BHuIiUC6.js} +3 -1
  24. package/dist/search-dialog-BNF10tDl.js +375 -0
  25. package/dist/search-dialog-BwkDuI9R.cjs +220 -0
  26. package/dist/search-dialog-C7xuvyNk.cjs +386 -0
  27. package/dist/search-dialog-CIQg6k8c.cjs +8 -0
  28. package/dist/search-dialog-D-DDN7zJ.js +208 -0
  29. package/package.json +3 -4
  30. package/dist/docs-layout-KoWNZc8_.js +0 -6
  31. package/dist/docs-layout-x2yKt2cL.cjs +0 -6
  32. package/dist/icons-dev-B_RZIyxu.js +0 -6
  33. package/dist/icons-dev-BlV3wWFT.cjs +0 -6
  34. package/dist/image-BHhTvQzr.cjs +0 -6
  35. package/dist/image-CqKzYD8f.js +0 -6
  36. package/dist/mdx-DudBEac0.js +0 -7
  37. package/dist/mdx-r4cDQxWu.cjs +0 -7
  38. package/dist/search-dialog-B584t9ZF.js +0 -6
  39. package/dist/search-dialog-BvBopRsZ.cjs +0 -6
  40. package/dist/search-dialog-Cyko6TJm.cjs +0 -6
  41. package/dist/search-dialog-D6BNohIJ.js +0 -6
  42. package/dist/search-dialog-DuYTIefy.cjs +0 -6
  43. package/src/client/app/config-context.tsx +0 -51
  44. package/src/client/app/doc-page.tsx +0 -38
  45. package/src/client/app/docs-layout.tsx +0 -28
  46. package/src/client/app/head.tsx +0 -122
  47. package/src/client/app/helmet-compat.tsx +0 -36
  48. package/src/client/app/mdx-component.tsx +0 -8
  49. package/src/client/app/mdx-components-context.tsx +0 -72
  50. package/src/client/app/routes-context.tsx +0 -34
  51. package/src/client/app/scroll-handler.tsx +0 -74
  52. package/src/client/app/theme-context.tsx +0 -103
  53. package/src/client/app/ui-context.tsx +0 -42
  54. package/src/client/components/docs-layout-default.tsx +0 -85
  55. package/src/client/components/icons-dev.tsx +0 -282
  56. package/src/client/components/mdx/callout.tsx +0 -97
  57. package/src/client/components/mdx/card.tsx +0 -99
  58. package/src/client/components/mdx/cards.tsx +0 -27
  59. package/src/client/components/mdx/code-block.tsx +0 -184
  60. package/src/client/components/mdx/field.tsx +0 -33
  61. package/src/client/components/mdx/image.tsx +0 -44
  62. package/src/client/components/mdx/index.ts +0 -19
  63. package/src/client/components/mdx/table.tsx +0 -54
  64. package/src/client/components/mdx/typographics.tsx +0 -120
  65. package/src/client/components/mdx/use-code-block.ts +0 -34
  66. package/src/client/components/primitives/breadcrumbs.tsx +0 -54
  67. package/src/client/components/primitives/button-group.tsx +0 -54
  68. package/src/client/components/primitives/button.tsx +0 -6
  69. package/src/client/components/primitives/code-block.tsx +0 -120
  70. package/src/client/components/primitives/docs-layout.tsx +0 -125
  71. package/src/client/components/primitives/error-boundary.tsx +0 -107
  72. package/src/client/components/primitives/heading.tsx +0 -128
  73. package/src/client/components/primitives/helpers/observer.ts +0 -141
  74. package/src/client/components/primitives/image.tsx +0 -26
  75. package/src/client/components/primitives/link.tsx +0 -102
  76. package/src/client/components/primitives/menu.tsx +0 -137
  77. package/src/client/components/primitives/navbar.tsx +0 -466
  78. package/src/client/components/primitives/on-this-page.tsx +0 -430
  79. package/src/client/components/primitives/page-nav.tsx +0 -51
  80. package/src/client/components/primitives/popover.tsx +0 -28
  81. package/src/client/components/primitives/search-dialog.tsx +0 -193
  82. package/src/client/components/primitives/sidebar.tsx +0 -423
  83. package/src/client/components/primitives/skeleton.tsx +0 -26
  84. package/src/client/components/primitives/tabs.tsx +0 -70
  85. package/src/client/components/primitives/tooltip.tsx +0 -81
  86. package/src/client/components/primitives/types.ts +0 -11
  87. package/src/client/components/ui-base/banner.tsx +0 -66
  88. package/src/client/components/ui-base/breadcrumbs.tsx +0 -44
  89. package/src/client/components/ui-base/copy-markdown.tsx +0 -107
  90. package/src/client/components/ui-base/error-boundary.tsx +0 -15
  91. package/src/client/components/ui-base/github-stars.tsx +0 -29
  92. package/src/client/components/ui-base/icons.tsx +0 -240
  93. package/src/client/components/ui-base/index.ts +0 -16
  94. package/src/client/components/ui-base/last-updated.tsx +0 -27
  95. package/src/client/components/ui-base/navbar.tsx +0 -266
  96. package/src/client/components/ui-base/not-found.tsx +0 -26
  97. package/src/client/components/ui-base/on-this-page.tsx +0 -57
  98. package/src/client/components/ui-base/page-nav.tsx +0 -50
  99. package/src/client/components/ui-base/search-dialog.tsx +0 -163
  100. package/src/client/components/ui-base/search-highlight.tsx +0 -10
  101. package/src/client/components/ui-base/sidebar.tsx +0 -92
  102. package/src/client/components/ui-base/tabs.tsx +0 -83
  103. package/src/client/components/ui-base/theme-toggle.tsx +0 -130
  104. package/src/client/components/ui-base/version-i18n.tsx +0 -80
  105. package/src/client/hooks/index.ts +0 -13
  106. package/src/client/hooks/use-analytics.ts +0 -272
  107. package/src/client/hooks/use-breadcrumbs.ts +0 -22
  108. package/src/client/hooks/use-i18n.ts +0 -182
  109. package/src/client/hooks/use-localized-to.ts +0 -113
  110. package/src/client/hooks/use-location.ts +0 -5
  111. package/src/client/hooks/use-navbar.ts +0 -130
  112. package/src/client/hooks/use-page-nav.ts +0 -46
  113. package/src/client/hooks/use-routes.ts +0 -108
  114. package/src/client/hooks/use-search-highlight.ts +0 -185
  115. package/src/client/hooks/use-search.ts +0 -118
  116. package/src/client/hooks/use-sidebar.ts +0 -205
  117. package/src/client/hooks/use-tabs.ts +0 -46
  118. package/src/client/hooks/use-version.ts +0 -111
  119. package/src/client/index.ts +0 -31
  120. package/src/client/mdx.ts +0 -2
  121. package/src/client/primitives.ts +0 -19
  122. package/src/client/ssg/boltdocs-shell.tsx +0 -148
  123. package/src/client/ssg/create-routes.tsx +0 -473
  124. package/src/client/ssg/index.ts +0 -4
  125. package/src/client/ssg/mdx-page.tsx +0 -38
  126. package/src/client/store/boltdocs-context.tsx +0 -137
  127. package/src/client/theme/neutral.css +0 -141
  128. package/src/client/theme/reset.css +0 -189
  129. package/src/client/types.ts +0 -116
  130. package/src/client/utils/cn.ts +0 -6
  131. package/src/client/utils/copy-clipboard.ts +0 -22
  132. package/src/client/utils/get-base-file-path.ts +0 -21
  133. package/src/client/utils/github.ts +0 -121
  134. package/src/client/utils/i18n.ts +0 -23
  135. package/src/client/utils/path.ts +0 -9
  136. package/src/client/utils/react-to-text.ts +0 -34
  137. package/src/client/virtual.d.ts +0 -24
@@ -1,54 +0,0 @@
1
- import { cn } from '../../utils/cn'
2
- import type { ComponentBase } from './types'
3
-
4
- export interface ButtonGroupProps extends ComponentBase {
5
- vertical?: boolean
6
- }
7
-
8
- export const ButtonGroup = ({
9
- children,
10
- className,
11
- vertical = false,
12
- }: ButtonGroupProps) => {
13
- return (
14
- <div
15
- className={cn(
16
- 'inline-flex',
17
- vertical ? 'flex-col' : 'flex-row',
18
- // Handle nested button borders and radii
19
- !vertical && [
20
- '[&>*:not(:first-child)]:-ml-px',
21
- '[&>*:first-child]:rounded-r-none',
22
- '[&>*:last-child]:rounded-l-none',
23
- '[&>*:not(:first-child):not(:last-child)]:rounded-none',
24
- // Extra polish for outer corners
25
- className?.includes('rounded-full') && [
26
- '[&>*:first-child]:rounded-l-full',
27
- '[&>*:last-child]:rounded-r-full',
28
- ],
29
- className?.includes('rounded-xl') && [
30
- '[&>*:first-child]:rounded-l-xl',
31
- '[&>*:last-child]:rounded-r-xl',
32
- ],
33
- className?.includes('rounded-lg') && [
34
- '[&>*:first-child]:rounded-l-lg',
35
- '[&>*:last-child]:rounded-r-lg',
36
- ],
37
- ],
38
- vertical && [
39
- '[&>*:not(:first-child)]:-mt-px',
40
- '[&>*:first-child]:rounded-b-none',
41
- '[&>*:last-child]:rounded-t-none',
42
- '[&>*:not(:first-child):not(:last-child)]:rounded-none',
43
- className?.includes('rounded-full') && [
44
- '[&>*:first-child]:rounded-t-full',
45
- '[&>*:last-child]:rounded-b-full',
46
- ],
47
- ],
48
- className,
49
- )}
50
- >
51
- {children}
52
- </div>
53
- )
54
- }
@@ -1,6 +0,0 @@
1
- import * as RAC from 'react-aria-components'
2
- export interface ButtonProps extends RAC.ButtonProps {}
3
-
4
- export const Button = ({ ...props }: ButtonProps) => {
5
- return <RAC.Button {...props} />
6
- }
@@ -1,120 +0,0 @@
1
- import type { ComponentProps } from 'react'
2
- import { cn } from '../../utils/cn'
3
-
4
- interface CodeBlockRootProps extends ComponentProps<'div'> {
5
- /**
6
- * Whether the code block is in plain mode (no borders/padding)
7
- * @default false
8
- */
9
- plain?: boolean
10
- }
11
-
12
- export interface CodeBlockHeaderProps extends ComponentProps<'div'> {}
13
- export interface CodeBlockGroupProps extends ComponentProps<'div'> {}
14
- export interface CodeBlockContentProps extends ComponentProps<'div'> {
15
- /**
16
- * Whether the code content should be truncated with an expand button
17
- * @default false
18
- */
19
- shouldTruncate?: boolean
20
- }
21
-
22
- /**
23
- * Root component for code blocks.
24
- * Handles background, borders, and general layout.
25
- */
26
- const CodeBlock = ({
27
- children,
28
- className,
29
- plain = false,
30
- ...props
31
- }: CodeBlockRootProps) => {
32
- return (
33
- <div
34
- className={cn(
35
- 'not-prose boltdocs-code-block',
36
- 'group relative overflow-hidden bg-(--color-code-bg)',
37
- 'contain-layout contain-paint',
38
- {
39
- 'my-6 rounded-xl border border-subtle': !plain,
40
- },
41
- className,
42
- )}
43
- {...props}
44
- >
45
- {children}
46
- </div>
47
- )
48
- }
49
-
50
- /**
51
- * Header section of the code block.
52
- * Usually contains the title, language label, and action buttons.
53
- */
54
- const CodeBlockHeader = ({
55
- children,
56
- className,
57
- ...props
58
- }: CodeBlockHeaderProps) => {
59
- return (
60
- <div
61
- className={cn(
62
- 'flex h-9 items-center justify-between px-4 py-1.5',
63
- 'text-[13px] font-medium text-muted',
64
- className,
65
- )}
66
- {...props}
67
- >
68
- {children}
69
- </div>
70
- )
71
- }
72
-
73
- /**
74
- * Horizontal group for organizing items within the header (e.g., logo + label).
75
- */
76
- const CodeBlockGroup = ({
77
- children,
78
- className,
79
- ...props
80
- }: CodeBlockGroupProps) => {
81
- return (
82
- <div className={cn('flex items-center space-x-2', className)} {...props}>
83
- {children}
84
- </div>
85
- )
86
- }
87
-
88
- /**
89
- * Content area of the code block.
90
- * Wraps the `<pre>` or `<div>` containing the code.
91
- */
92
- const CodeBlockContent = ({
93
- className,
94
- children,
95
- shouldTruncate = false,
96
- ...props
97
- }: CodeBlockContentProps) => {
98
- return (
99
- <div
100
- className={cn(
101
- 'relative',
102
- {
103
- '[&>pre]:max-h-[300px] [&>pre]:overflow-hidden [&>div>pre]:max-h-[300px] [&>div>pre]:overflow-hidden':
104
- shouldTruncate,
105
- },
106
- className,
107
- )}
108
- {...props}
109
- >
110
- {children}
111
- </div>
112
- )
113
- }
114
-
115
- // Assign sub-components
116
- CodeBlock.Header = CodeBlockHeader
117
- CodeBlock.Group = CodeBlockGroup
118
- CodeBlock.Content = CodeBlockContent
119
-
120
- export { CodeBlock, CodeBlockHeader, CodeBlockGroup, CodeBlockContent }
@@ -1,125 +0,0 @@
1
- import { cn } from '../../utils/cn'
2
- import { SearchHighlight } from '../ui-base/search-highlight'
3
-
4
- /**
5
- * Props shared by all layout slot components.
6
- */
7
- interface SlotProps {
8
- children?: React.ReactNode
9
- className?: string
10
- style?: React.CSSProperties
11
- }
12
-
13
- /**
14
- * Root layout shell. Renders a full-height flex column.
15
- *
16
- * Usage:
17
- * ```tsx
18
- * <DocsLayout>
19
- * <Navbar />
20
- * <DocsLayout.Body>...</DocsLayout.Body>
21
- * </DocsLayout>
22
- * ```
23
- */
24
- function DocsLayoutRoot({ children, className, style }: SlotProps) {
25
- return (
26
- <div
27
- className={cn(
28
- 'h-screen flex flex-col overflow-hidden bg-main text-body',
29
- className,
30
- )}
31
- style={style}
32
- >
33
- {children}
34
- </div>
35
- )
36
- }
37
-
38
- /**
39
- * Horizontal flex container for sidebar + content + toc.
40
- */
41
- function Body({ children, className, style }: SlotProps) {
42
- return (
43
- <div
44
- className={cn(
45
- 'mx-auto flex flex-1 w-full max-w-(--breakpoint-3xl) bg-main overflow-hidden',
46
- className,
47
- )}
48
- style={style}
49
- >
50
- {children}
51
- </div>
52
- )
53
- }
54
-
55
- /**
56
- * Main scrollable content area.
57
- */
58
- function Content({ children, className, style }: SlotProps) {
59
- return (
60
- <main
61
- className={cn(
62
- 'boltdocs-content flex-1 min-w-0 overflow-y-auto',
63
- 'contain-layout', // Optimization: isolate main content layout
64
- className,
65
- )}
66
- style={style}
67
- >
68
- {children}
69
- </main>
70
- )
71
- }
72
-
73
- /**
74
- * MDX Content wrapper with standard page padding and max-width logic.
75
- */
76
- function ContentMdx({ children, className, style }: SlotProps) {
77
- return (
78
- <div
79
- className={cn('boltdocs-page mx-auto pt-4 pb-20 px-4 sm:px-8', className)}
80
- style={style}
81
- >
82
- <SearchHighlight />
83
- {children}
84
- </div>
85
- )
86
- }
87
-
88
- /**
89
- * Content header area (breadcrumbs, title, description, etc).
90
- */
91
- function Header({ children, className, style }: SlotProps) {
92
- return (
93
- <header className={cn('mb-10', className)} style={style}>
94
- {children}
95
- </header>
96
- )
97
- }
98
-
99
- /**
100
- * Footer area inside the content section (page nav).
101
- */
102
- function Footer({ children, className, style }: SlotProps) {
103
- return (
104
- <div className={cn('mt-20', className)} style={style}>
105
- {children}
106
- </div>
107
- )
108
- }
109
-
110
- interface DocsLayoutComponent extends React.FC<SlotProps> {
111
- Body: typeof Body
112
- Content: typeof Content
113
- ContentMdx: typeof ContentMdx
114
- Header: typeof Header
115
- Footer: typeof Footer
116
- }
117
-
118
- // Attach sub-components to the root
119
- export const DocsLayout = Object.assign(DocsLayoutRoot, {
120
- Body,
121
- Content,
122
- ContentMdx,
123
- Header,
124
- Footer,
125
- }) as DocsLayoutComponent
@@ -1,107 +0,0 @@
1
- import * as React from 'react'
2
- import type { ErrorInfo, ComponentType, ReactNode } from 'react'
3
- import { Component } from 'react'
4
- import { Button } from './button'
5
-
6
- export interface FallbackProps {
7
- error: Error
8
- resetErrorBoundary: () => void
9
- }
10
-
11
- export interface ErrorBoundaryProps {
12
- children?: ReactNode
13
- fallback?: ReactNode
14
- FallbackComponent?: ComponentType<FallbackProps>
15
- onError?: (error: Error, info: ErrorInfo) => void
16
- onReset?: () => void
17
- }
18
-
19
- interface ErrorBoundaryState {
20
- hasError: boolean
21
- error: Error | null
22
- }
23
-
24
- export class ErrorBoundary extends Component<
25
- ErrorBoundaryProps,
26
- ErrorBoundaryState
27
- > {
28
- public state: ErrorBoundaryState = { hasError: false, error: null }
29
-
30
- public static getDerivedStateFromError(error: Error): ErrorBoundaryState {
31
- return { hasError: true, error }
32
- }
33
-
34
- public componentDidCatch(error: Error, errorInfo: ErrorInfo) {
35
- if (this.props.onError) {
36
- this.props.onError(error, errorInfo)
37
- } else {
38
- console.error(
39
- 'ErrorBoundary caught an unhandled error:',
40
- error,
41
- errorInfo,
42
- )
43
- }
44
- }
45
-
46
- public resetErrorBoundary = () => {
47
- if (this.props.onReset) {
48
- this.props.onReset()
49
- }
50
- this.setState({ hasError: false, error: null })
51
- }
52
-
53
- public render() {
54
- const { hasError, error } = this.state
55
- const { children, fallback, FallbackComponent } = this.props
56
-
57
- if (hasError && error) {
58
- if (FallbackComponent) {
59
- return (
60
- <FallbackComponent
61
- error={error}
62
- resetErrorBoundary={this.resetErrorBoundary}
63
- />
64
- )
65
- }
66
- if (fallback) {
67
- return fallback
68
- }
69
- return (
70
- <ErrorBoundaryFallback
71
- error={error}
72
- resetErrorBoundary={this.resetErrorBoundary}
73
- />
74
- )
75
- }
76
-
77
- return children
78
- }
79
- }
80
-
81
- export interface ErrorBoundaryFallbackProps {
82
- error: Error
83
- resetErrorBoundary: () => void
84
- }
85
-
86
- export function ErrorBoundaryFallback({
87
- error,
88
- resetErrorBoundary,
89
- }: ErrorBoundaryFallbackProps) {
90
- return (
91
- <div className="flex flex-col items-center justify-center min-h-[40vh] text-center gap-4 px-6 py-8 border border-subtle bg-surface rounded-2xl max-w-lg mx-auto shadow-xs">
92
- <div className="text-lg font-bold text-rose-600 dark:text-rose-400">
93
- Something went wrong
94
- </div>
95
- <p className="text-sm text-muted max-w-sm leading-relaxed">
96
- {error?.message ||
97
- 'An unexpected error occurred while rendering this page.'}
98
- </p>
99
- <Button
100
- className="rounded-xl border border-subtle bg-main px-6 py-2.5 text-xs font-semibold text-body hover:bg-primary-50/50 hover:border-primary-500/50 transition-all duration-300 cursor-pointer outline-none select-none"
101
- onPress={resetErrorBoundary}
102
- >
103
- Try again
104
- </Button>
105
- </div>
106
- )
107
- }
@@ -1,128 +0,0 @@
1
- import * as React from 'react'
2
- import { Link as LucideLink } from '../ui-base/icons'
3
- import { Link } from './link'
4
- import { cn } from '../../utils/cn'
5
-
6
- export interface HeadingProps extends React.HTMLAttributes<HTMLHeadingElement> {
7
- level: 1 | 2 | 3 | 4 | 5 | 6
8
- id?: string
9
- /** Whether to show the anchor icon/link. Defaults to true if id is provided. */
10
- showAnchor?: boolean
11
- /** Position of the anchor link relative to children. Defaults to 'wrap'. */
12
- anchorPosition?: 'wrap' | 'after' | 'before'
13
- /** Custom icon to display for the anchor. */
14
- anchorIcon?: React.ReactNode
15
- /** Custom classes for the anchor link wrapper. */
16
- anchorClassName?: string
17
- }
18
-
19
- export const Heading = React.forwardRef<HTMLHeadingElement, HeadingProps>(
20
- (
21
- {
22
- level,
23
- id,
24
- children,
25
- className,
26
- showAnchor = true,
27
- anchorPosition = 'wrap',
28
- anchorIcon,
29
- anchorClassName,
30
- ...props
31
- },
32
- ref,
33
- ) => {
34
- const safeLevel = Math.min(Math.max(Math.floor(level), 1), 6) as
35
- | 1
36
- | 2
37
- | 3
38
- | 4
39
- | 5
40
- | 6
41
- const Tag = `h${safeLevel}` as const
42
-
43
- const hasAnchor = !!(id && showAnchor)
44
-
45
- // Default icon with hover transition
46
- const defaultIcon = (
47
- <LucideLink
48
- className={cn(
49
- 'transition-all duration-200',
50
- anchorPosition === 'wrap'
51
- ? 'opacity-0 ml-2 text-muted/50 group-hover:text-primary-500 group-hover:opacity-100'
52
- : 'text-muted/50 hover:text-primary-500',
53
- )}
54
- size={16}
55
- />
56
- )
57
-
58
- const icon = anchorIcon ?? defaultIcon
59
-
60
- const renderContent = () => {
61
- if (!hasAnchor) {
62
- return children
63
- }
64
-
65
- if (anchorPosition === 'wrap') {
66
- return (
67
- <Link
68
- href={`#${id}`}
69
- className={cn(
70
- 'header-anchor flex flex-row items-center no-underline text-inherit',
71
- anchorClassName,
72
- )}
73
- aria-label="Anchor"
74
- >
75
- {children}
76
- {icon}
77
- </Link>
78
- )
79
- }
80
-
81
- return (
82
- <>
83
- {anchorPosition === 'before' && (
84
- <Link
85
- href={`#${id}`}
86
- className={cn(
87
- 'header-anchor mr-2 opacity-0 group-hover:opacity-100 transition-opacity duration-200',
88
- anchorClassName,
89
- )}
90
- aria-label="Anchor"
91
- >
92
- {icon}
93
- </Link>
94
- )}
95
- {children}
96
- {anchorPosition === 'after' && (
97
- <Link
98
- href={`#${id}`}
99
- className={cn(
100
- 'header-anchor ml-2 opacity-0 group-hover:opacity-100 transition-opacity duration-200',
101
- anchorClassName,
102
- )}
103
- aria-label="Anchor"
104
- >
105
- {icon}
106
- </Link>
107
- )}
108
- </>
109
- )
110
- }
111
-
112
- return (
113
- <Tag
114
- ref={ref}
115
- id={id}
116
- className={cn(
117
- 'boltdocs-heading relative group flex items-center scroll-mt-24',
118
- className,
119
- )}
120
- {...props}
121
- >
122
- {renderContent()}
123
- </Tag>
124
- )
125
- },
126
- )
127
-
128
- Heading.displayName = 'Heading'
@@ -1,141 +0,0 @@
1
- import type { TOCItemInfo, TOCItemType } from '../on-this-page'
2
-
3
- export function getItemId(url: string) {
4
- if (url.startsWith('#')) return url.slice(1)
5
- return null
6
- }
7
-
8
- export class Observer {
9
- items: TOCItemInfo[] = []
10
- single = false
11
- private observer: IntersectionObserver | null = null
12
- onChange?: () => void
13
-
14
- private callback(_entries: IntersectionObserverEntry[]) {
15
- // For each item, check if it's currently in viewport
16
- for (const item of this.items) {
17
- const element = document.getElementById(item.id)
18
- if (!element) {
19
- item.active = false
20
- item.fallback = false
21
- continue
22
- }
23
-
24
- const rect = element.getBoundingClientRect()
25
- const viewportHeight =
26
- typeof window !== 'undefined' ? window.innerHeight : 1000
27
-
28
- // Check if element is currently in viewport (visible)
29
- // rect.bottom > 0
30
- // rect.top < viewportHeight:
31
- const isInViewport = rect.bottom > 0 && rect.top < viewportHeight
32
-
33
- // Update active state based on current position
34
- item.active = isInViewport
35
-
36
- // Fallback: element has scrolled past but is still near viewport
37
- item.fallback =
38
- !isInViewport && rect.top > 0 && rect.top < viewportHeight * 2
39
- }
40
-
41
- // 3. Determine which items should be active based on single mode
42
- if (this.single) {
43
- // Single mode: only ONE active item (the one closest to the top of viewport)
44
- let highlightIdx = -1
45
-
46
- // Find all visible items and pick the one closest to the top of viewport
47
- const visibleItems = this.items
48
- .map((item, idx) => ({ item, idx }))
49
- .filter(({ item }) => item.active)
50
-
51
- if (visibleItems.length > 0) {
52
- // Take the first one (closest to top of viewport)
53
- highlightIdx = visibleItems[0].idx
54
- } else {
55
- // If nothing visible, check fallback items
56
- const fallbackItems = this.items
57
- .map((item, idx) => ({ item, idx }))
58
- .filter(({ item }) => item.fallback)
59
-
60
- if (fallbackItems.length > 0) {
61
- highlightIdx = fallbackItems[0].idx
62
- } else if (this.items.length > 0) {
63
- highlightIdx = 0
64
- }
65
- }
66
-
67
- // Map back to UI state - only one active
68
- this.items = this.items.map((item, idx) => ({
69
- ...item,
70
- active: idx === highlightIdx,
71
- t: idx === highlightIdx ? Date.now() : item.t,
72
- }))
73
- } else {
74
- // Multi mode: items active when they are in viewport
75
- // This ensures items activate when visible and deactivate when they leave viewport
76
- this.items = this.items.map((item, idx) => ({
77
- ...item,
78
- active: item.active,
79
- t: item.active ? Date.now() : item.t,
80
- }))
81
- }
82
-
83
- this.onChange?.()
84
- }
85
-
86
- setItems(newItems: TOCItemType[]) {
87
- const observer = this.observer
88
- if (observer) {
89
- for (const item of this.items) {
90
- const element = document.getElementById(item.id)
91
- if (!element) continue
92
- observer.unobserve(element)
93
- }
94
- }
95
-
96
- this.items = []
97
- for (const item of newItems) {
98
- const id = getItemId(item.url)
99
- if (!id) continue
100
-
101
- this.items.push({
102
- id,
103
- active: false,
104
- fallback: false,
105
- t: 0,
106
- original: item,
107
- })
108
- }
109
- this.watchItems()
110
-
111
- // In an SPA, the TOC might update before the MDX content is in the DOM.
112
- // We perform a few delayed scans to ensure we catch those elements.
113
- if (typeof window !== 'undefined') {
114
- setTimeout(() => this.watchItems(), 100)
115
- setTimeout(() => this.watchItems(), 500)
116
- setTimeout(() => this.watchItems(), 1000)
117
- }
118
-
119
- this.onChange?.()
120
- }
121
-
122
- watch(options?: IntersectionObserverInit) {
123
- if (this.observer) return
124
- this.observer = new IntersectionObserver(this.callback.bind(this), options)
125
- this.watchItems()
126
- }
127
-
128
- private watchItems() {
129
- if (!this.observer) return
130
- for (const item of this.items) {
131
- const element = document.getElementById(item.id)
132
- if (!element) continue
133
- this.observer.observe(element)
134
- }
135
- }
136
-
137
- unwatch() {
138
- this.observer?.disconnect()
139
- this.observer = null
140
- }
141
- }
@@ -1,26 +0,0 @@
1
- import type { ImgHTMLAttributes } from 'react'
2
- import { useTheme } from '../../app/theme-context'
3
- import { cn } from '../../utils/cn'
4
-
5
- export interface ImageProps extends ImgHTMLAttributes<HTMLImageElement> {
6
- theme?: 'light' | 'dark'
7
- }
8
-
9
- /**
10
- * A responsive image component that automatically supports dark and light theme variations
11
- * via the `theme` prop.
12
- */
13
- export function Image({ theme, className, ...props }: ImageProps) {
14
- const { resolvedTheme } = useTheme()
15
-
16
- if (theme && theme !== resolvedTheme) {
17
- return null
18
- }
19
-
20
- return (
21
- <img
22
- className={cn('max-w-full h-auto rounded-lg my-8', className)}
23
- {...props}
24
- />
25
- )
26
- }