@terrafirmagreg-team/kit 0.0.0-stage → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +56 -3
- package/src/components/blocks/nav-title.tsx +62 -0
- package/src/components/outline/dropdown.tsx +68 -0
- package/src/components/outline/index.ts +11 -0
- package/src/components/outline/list.tsx +121 -0
- package/src/components/outline/outline.tsx +50 -0
- package/src/components/outline/popover.tsx +77 -0
- package/src/components/page-actions.tsx +202 -0
- package/src/components/relative-link.tsx +19 -0
- package/src/components/toc/base.tsx +66 -0
- package/src/components/toc/block.tsx +112 -0
- package/src/components/toc/clerk.tsx +266 -0
- package/src/components/toc/default.tsx +334 -0
- package/src/components/version-menu.tsx +130 -0
- package/src/components/views/dataset.tsx +72 -0
- package/src/components/views/section.tsx +152 -0
- package/src/components/workspace/content.tsx +54 -0
- package/src/components/workspace/index.ts +13 -0
- package/src/components/workspace/pagination.tsx +74 -0
- package/src/components/workspace/workspace.tsx +149 -0
- package/src/hooks/use-catalog.ts +12 -0
- package/src/hooks/use-current-dataset.ts +24 -0
- package/src/hooks/use-dataset-accent.ts +14 -0
- package/src/hooks/use-nav-options.ts +87 -0
- package/src/hooks/use-section-names.ts +40 -0
- package/src/hooks/use-toc.ts +10 -0
- package/src/hooks/use-version-pref.ts +31 -0
- package/src/hooks/use-versioned-dataset.ts +21 -0
- package/src/lib/breadcrumb.ts +65 -0
- package/src/lib/config.ts +111 -0
- package/src/lib/dataset-links.ts +31 -0
- package/src/lib/datasets.ts +241 -0
- package/src/lib/landing.ts +48 -0
- package/src/lib/layout.ts +16 -0
- package/src/lib/locale/renderer.ts +49 -0
- package/src/lib/order.ts +89 -0
- package/src/lib/page.ts +109 -0
- package/src/lib/pin-tree.ts +38 -0
- package/src/lib/preview/lookup.ts +51 -0
- package/src/lib/section/schema.ts +32 -0
- package/src/lib/section/source.ts +77 -0
- package/src/lib/sources.ts +22 -0
- package/src/lib/tree.ts +61 -0
- package/src/lib/urls.ts +17 -0
- package/src/locales/en_us.json +7 -0
- package/src/locales/ru_ru.json +7 -0
- package/src/locales.ts +6 -0
- package/src/types/embeds.ts +54 -0
- package/src/types/index.ts +87 -0
- package/src/types/outline.ts +30 -0
- package/README.md +0 -3
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import {
|
|
3
|
+
AnchorProvider,
|
|
4
|
+
ScrollProvider,
|
|
5
|
+
type AnchorProviderProps,
|
|
6
|
+
} from 'fumadocs-core/toc';
|
|
7
|
+
import { useRef, type ComponentProps } from 'react';
|
|
8
|
+
import { TOCContext } from '@terrafirmagreg-team/kit/hooks/use-toc';
|
|
9
|
+
import { cn } from '@terrafirmagreg-team/ui/lib/utils/cn';
|
|
10
|
+
import { mergeRefs } from '@terrafirmagreg-team/ui/lib/utils/merge-refs';
|
|
11
|
+
|
|
12
|
+
export {
|
|
13
|
+
AnchorProvider,
|
|
14
|
+
ScrollProvider,
|
|
15
|
+
TOCItem,
|
|
16
|
+
useActiveAnchor,
|
|
17
|
+
useActiveAnchors,
|
|
18
|
+
useItems,
|
|
19
|
+
useTOC,
|
|
20
|
+
useTOCListener,
|
|
21
|
+
useTOCSelector,
|
|
22
|
+
} from 'fumadocs-core/toc';
|
|
23
|
+
export type {
|
|
24
|
+
AnchorProviderProps,
|
|
25
|
+
ScrollProviderProps,
|
|
26
|
+
TOCItemInfo,
|
|
27
|
+
TOCItemProps,
|
|
28
|
+
TOCItemType,
|
|
29
|
+
TableOfContents,
|
|
30
|
+
} from 'fumadocs-core/toc';
|
|
31
|
+
|
|
32
|
+
export type TOCProviderProps = AnchorProviderProps;
|
|
33
|
+
|
|
34
|
+
export function TOCProvider({ toc, children, ...props }: TOCProviderProps) {
|
|
35
|
+
return (
|
|
36
|
+
<TOCContext value={toc}>
|
|
37
|
+
<AnchorProvider toc={toc} {...props}>
|
|
38
|
+
{children}
|
|
39
|
+
</AnchorProvider>
|
|
40
|
+
</TOCContext>
|
|
41
|
+
);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export function TOCScrollArea({
|
|
45
|
+
ref,
|
|
46
|
+
className,
|
|
47
|
+
...props
|
|
48
|
+
}: ComponentProps<'div'>) {
|
|
49
|
+
const viewRef = useRef<HTMLDivElement>(null);
|
|
50
|
+
|
|
51
|
+
return (
|
|
52
|
+
<div
|
|
53
|
+
ref={mergeRefs(viewRef, ref)}
|
|
54
|
+
className={cn(
|
|
55
|
+
'relative min-h-0 text-sm overflow-x-clip overflow-y-auto overscroll-contain [scrollbar-width:none] mask-[linear-gradient(to_bottom,transparent,white_16px,white_calc(100%-16px),transparent)] py-3',
|
|
56
|
+
className,
|
|
57
|
+
)}
|
|
58
|
+
{...props}
|
|
59
|
+
>
|
|
60
|
+
<ScrollProvider containerRef={viewRef}>
|
|
61
|
+
{props.children}
|
|
62
|
+
</ScrollProvider>
|
|
63
|
+
</div>
|
|
64
|
+
);
|
|
65
|
+
}
|
|
66
|
+
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { useEffect, useRef, type ComponentProps } from 'react';
|
|
3
|
+
import { cn } from '@terrafirmagreg-team/ui/lib/utils/cn';
|
|
4
|
+
import { mergeRefs } from '@terrafirmagreg-team/ui/lib/utils/merge-refs';
|
|
5
|
+
import * as Primitive from './base';
|
|
6
|
+
import { TOCEmpty } from './default';
|
|
7
|
+
|
|
8
|
+
export { TOCEmpty };
|
|
9
|
+
|
|
10
|
+
export type TOCItemsProps = ComponentProps<'div'>;
|
|
11
|
+
|
|
12
|
+
export function TOCItems({
|
|
13
|
+
ref,
|
|
14
|
+
className,
|
|
15
|
+
children,
|
|
16
|
+
...props
|
|
17
|
+
}: TOCItemsProps) {
|
|
18
|
+
const containerRef = useRef<HTMLDivElement>(null);
|
|
19
|
+
const blockRef = useRef<HTMLDivElement>(null);
|
|
20
|
+
const tocInfo = Primitive.useTOC();
|
|
21
|
+
|
|
22
|
+
useEffect(() => {
|
|
23
|
+
const container = containerRef.current;
|
|
24
|
+
const block = blockRef.current;
|
|
25
|
+
if (!container || !block) return;
|
|
26
|
+
|
|
27
|
+
const positions = new Map<string, [number, number]>();
|
|
28
|
+
let height = 0;
|
|
29
|
+
|
|
30
|
+
const update = (items: Primitive.TOCItemInfo[]) => {
|
|
31
|
+
let top = -1;
|
|
32
|
+
let bottom = -1;
|
|
33
|
+
for (const item of items) {
|
|
34
|
+
if (!item.active) continue;
|
|
35
|
+
const pos = positions.get(item.original.url);
|
|
36
|
+
if (!pos) continue;
|
|
37
|
+
if (top === -1) top = pos[0];
|
|
38
|
+
bottom = pos[1];
|
|
39
|
+
}
|
|
40
|
+
if (top === -1) return;
|
|
41
|
+
block.style.clipPath = `inset(${top}px 0 ${height - bottom}px round 8px)`;
|
|
42
|
+
if (!block.hasAttribute('data-ready'))
|
|
43
|
+
requestAnimationFrame(() => block.setAttribute('data-ready', ''));
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
const observer = new ResizeObserver(() => {
|
|
47
|
+
positions.clear();
|
|
48
|
+
for (const anchor of container.getElementsByTagName('a')) {
|
|
49
|
+
const href = anchor.getAttribute('href');
|
|
50
|
+
if (href)
|
|
51
|
+
positions.set(href, [
|
|
52
|
+
anchor.offsetTop,
|
|
53
|
+
anchor.offsetTop + anchor.offsetHeight,
|
|
54
|
+
]);
|
|
55
|
+
}
|
|
56
|
+
height = container.clientHeight;
|
|
57
|
+
update(tocInfo.get());
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
observer.observe(container);
|
|
61
|
+
tocInfo.listen(update);
|
|
62
|
+
return () => {
|
|
63
|
+
observer.disconnect();
|
|
64
|
+
tocInfo.unlisten(update);
|
|
65
|
+
};
|
|
66
|
+
}, [tocInfo]);
|
|
67
|
+
|
|
68
|
+
return (
|
|
69
|
+
<div
|
|
70
|
+
ref={mergeRefs(containerRef, ref)}
|
|
71
|
+
className={cn('relative flex flex-col', className)}
|
|
72
|
+
{...props}
|
|
73
|
+
>
|
|
74
|
+
<div
|
|
75
|
+
ref={blockRef}
|
|
76
|
+
className="absolute inset-0 bg-linear-to-r from-primary/10 [clip-path:inset(0_0_100%)] data-ready:transition-[clip-path] duration-300 ease-out"
|
|
77
|
+
/>
|
|
78
|
+
{children}
|
|
79
|
+
</div>
|
|
80
|
+
);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function getItemOffset(depth: number): number {
|
|
84
|
+
if (depth <= 2) return 8;
|
|
85
|
+
if (depth === 3) return 20;
|
|
86
|
+
return 32;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
export function TOCItem({
|
|
90
|
+
item,
|
|
91
|
+
...props
|
|
92
|
+
}: Primitive.TOCItemProps & { item: Primitive.TOCItemType }) {
|
|
93
|
+
return (
|
|
94
|
+
<Primitive.TOCItem
|
|
95
|
+
href={item.url}
|
|
96
|
+
{...props}
|
|
97
|
+
className={cn(
|
|
98
|
+
'group prose relative py-1 pe-2 text-[0.8125rem]/5 scroll-m-4 text-muted-foreground hover:text-accent-foreground transition-colors wrap-anywhere data-[active=true]:text-primary',
|
|
99
|
+
props.className,
|
|
100
|
+
)}
|
|
101
|
+
style={{ paddingInlineStart: getItemOffset(item.depth), ...props.style }}
|
|
102
|
+
>
|
|
103
|
+
{item._step !== undefined && (
|
|
104
|
+
<span className="inline-flex size-4 me-1.5 items-center justify-center rounded-full align-text-bottom bg-muted text-muted-foreground font-mono font-medium text-[10px] transition-colors group-data-[active=true]:bg-primary group-data-[active=true]:text-primary-foreground">
|
|
105
|
+
{item._step}
|
|
106
|
+
</span>
|
|
107
|
+
)}
|
|
108
|
+
{item.title}
|
|
109
|
+
</Primitive.TOCItem>
|
|
110
|
+
);
|
|
111
|
+
}
|
|
112
|
+
|
|
@@ -0,0 +1,266 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import {
|
|
3
|
+
useCallback,
|
|
4
|
+
useEffect,
|
|
5
|
+
useMemo,
|
|
6
|
+
useRef,
|
|
7
|
+
useState,
|
|
8
|
+
type ComponentProps,
|
|
9
|
+
type CSSProperties,
|
|
10
|
+
type ReactNode,
|
|
11
|
+
} from 'react';
|
|
12
|
+
import { cn } from '@terrafirmagreg-team/ui/lib/utils/cn';
|
|
13
|
+
import { mergeRefs } from '@terrafirmagreg-team/ui/lib/utils/merge-refs';
|
|
14
|
+
import * as Primitive from './base';
|
|
15
|
+
import { useTOCItems } from '@terrafirmagreg-team/kit/hooks/use-toc';
|
|
16
|
+
import { TOCEmpty } from './default';
|
|
17
|
+
|
|
18
|
+
export { TOCEmpty };
|
|
19
|
+
|
|
20
|
+
interface SvgResult {
|
|
21
|
+
content: ReactNode;
|
|
22
|
+
width: number;
|
|
23
|
+
height: number;
|
|
24
|
+
positions: [number, number, number][];
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export type TOCItemsProps = ComponentProps<'div'>;
|
|
28
|
+
|
|
29
|
+
export function TOCItems({
|
|
30
|
+
ref,
|
|
31
|
+
className,
|
|
32
|
+
children,
|
|
33
|
+
...props
|
|
34
|
+
}: TOCItemsProps) {
|
|
35
|
+
const containerRef = useRef<HTMLDivElement>(null);
|
|
36
|
+
const items = useTOCItems();
|
|
37
|
+
const [svg, setSvg] = useState<SvgResult | null>(null);
|
|
38
|
+
|
|
39
|
+
const onPrint = useCallback(() => {
|
|
40
|
+
const container = containerRef.current;
|
|
41
|
+
if (!container || container.clientHeight === 0) return;
|
|
42
|
+
if (items.length === 0) {
|
|
43
|
+
setSvg(null);
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
let w = 0;
|
|
48
|
+
let h = 0;
|
|
49
|
+
let d = '';
|
|
50
|
+
const positions: [number, number, number][] = [];
|
|
51
|
+
const output: ReactNode[] = [];
|
|
52
|
+
|
|
53
|
+
for (let i = 0; i < items.length; i++) {
|
|
54
|
+
const item = items[i];
|
|
55
|
+
const element = container.querySelector<HTMLElement>(`a[href="${item.url}"]`);
|
|
56
|
+
if (!element) continue;
|
|
57
|
+
const styles = getComputedStyle(element);
|
|
58
|
+
const x = getLineOffset(item.depth) + 0.5;
|
|
59
|
+
const top = element.offsetTop + parseFloat(styles.paddingTop);
|
|
60
|
+
const bottom =
|
|
61
|
+
element.offsetTop + element.clientHeight - parseFloat(styles.paddingBottom);
|
|
62
|
+
|
|
63
|
+
w = Math.max(x + 8, w);
|
|
64
|
+
h = Math.max(h, bottom);
|
|
65
|
+
if (i === 0) d += ` M${x} ${top} L${x} ${bottom}`;
|
|
66
|
+
else {
|
|
67
|
+
const [, upperBottom, upperX] = i > 0 ? positions[i - 1] : [0, 0, 0];
|
|
68
|
+
d += ` L ${upperX} ${upperBottom} ${x} ${top} L${x} ${bottom}`;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
if (item._step !== undefined)
|
|
72
|
+
output.push(
|
|
73
|
+
<g key={i} transform={`translate(${x}, ${(top + bottom) / 2})`}>
|
|
74
|
+
<circle cx="0" cy="0" r="8" className="fill-primary" />
|
|
75
|
+
<text
|
|
76
|
+
x="0"
|
|
77
|
+
y="0"
|
|
78
|
+
textAnchor="middle"
|
|
79
|
+
alignmentBaseline="central"
|
|
80
|
+
dominantBaseline="middle"
|
|
81
|
+
className="fill-primary-foreground font-medium text-xs leading-none font-mono rtl:-scale-x-100"
|
|
82
|
+
>
|
|
83
|
+
{item._step}
|
|
84
|
+
</text>
|
|
85
|
+
</g>,
|
|
86
|
+
);
|
|
87
|
+
positions.push([top, bottom, x]);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
output.unshift(
|
|
91
|
+
<path
|
|
92
|
+
key="path"
|
|
93
|
+
d={d}
|
|
94
|
+
className="stroke-primary"
|
|
95
|
+
strokeWidth="1"
|
|
96
|
+
fill="none"
|
|
97
|
+
/>,
|
|
98
|
+
);
|
|
99
|
+
|
|
100
|
+
setSvg({ content: output, width: w, height: h, positions });
|
|
101
|
+
}, [items]);
|
|
102
|
+
|
|
103
|
+
useEffect(() => {
|
|
104
|
+
const container = containerRef.current;
|
|
105
|
+
if (!container) return;
|
|
106
|
+
const observer = new ResizeObserver(onPrint);
|
|
107
|
+
observer.observe(container);
|
|
108
|
+
onPrint();
|
|
109
|
+
return () => {
|
|
110
|
+
observer.unobserve(container);
|
|
111
|
+
};
|
|
112
|
+
}, [onPrint]);
|
|
113
|
+
|
|
114
|
+
return (
|
|
115
|
+
<div
|
|
116
|
+
ref={mergeRefs(containerRef, ref)}
|
|
117
|
+
className={cn('relative flex flex-col', className)}
|
|
118
|
+
{...props}
|
|
119
|
+
>
|
|
120
|
+
{svg && <ThumbTrack computed={svg} />}
|
|
121
|
+
{children}
|
|
122
|
+
</div>
|
|
123
|
+
);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
function ThumbTrack({ computed }: { computed: SvgResult }) {
|
|
127
|
+
const ref = useRef<HTMLDivElement>(null);
|
|
128
|
+
const tocInfo = Primitive.useTOC();
|
|
129
|
+
|
|
130
|
+
function calculate(items: Primitive.TOCItemInfo[]): CSSProperties {
|
|
131
|
+
const out: Record<string, string> = {};
|
|
132
|
+
const startIdx = items.findIndex((item) => item.active);
|
|
133
|
+
if (startIdx === -1) return out;
|
|
134
|
+
const endIdx = items.findLastIndex((item) => item.active);
|
|
135
|
+
out['--track-top'] = `${computed.positions[startIdx][0]}px`;
|
|
136
|
+
out['--track-bottom'] = `${computed.positions[endIdx][1]}px`;
|
|
137
|
+
return out as CSSProperties;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
Primitive.useTOCListener((items) => {
|
|
141
|
+
const element = ref.current;
|
|
142
|
+
if (!element) return;
|
|
143
|
+
for (const [k, v] of Object.entries(calculate(items)))
|
|
144
|
+
element.style.setProperty(k, v);
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
return (
|
|
148
|
+
<div
|
|
149
|
+
ref={ref}
|
|
150
|
+
className="absolute top-0 inset-s-0 origin-center rtl:-scale-x-100"
|
|
151
|
+
style={{
|
|
152
|
+
width: computed.width,
|
|
153
|
+
height: computed.height,
|
|
154
|
+
...calculate(tocInfo.get()),
|
|
155
|
+
}}
|
|
156
|
+
>
|
|
157
|
+
<svg
|
|
158
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
159
|
+
viewBox={`0 0 ${computed.width} ${computed.height}`}
|
|
160
|
+
className="absolute transition-[clip-path]"
|
|
161
|
+
style={{
|
|
162
|
+
width: computed.width,
|
|
163
|
+
height: computed.height,
|
|
164
|
+
clipPath: `polygon(0 var(--track-top,0), 100% var(--track-top,0), 100% var(--track-bottom,0), 0 var(--track-bottom,0))`,
|
|
165
|
+
}}
|
|
166
|
+
>
|
|
167
|
+
{computed.content}
|
|
168
|
+
</svg>
|
|
169
|
+
</div>
|
|
170
|
+
);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
const BASE = 8;
|
|
174
|
+
|
|
175
|
+
function getItemOffset(depth: number): number {
|
|
176
|
+
if (depth <= 2) return 20;
|
|
177
|
+
if (depth === 3) return 32;
|
|
178
|
+
return 44;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
function getLineOffset(depth: number): number {
|
|
182
|
+
if (depth <= 2) return BASE;
|
|
183
|
+
if (depth === 3) return 20;
|
|
184
|
+
return 32;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
export function TOCItem({
|
|
188
|
+
item,
|
|
189
|
+
...props
|
|
190
|
+
}: Primitive.TOCItemProps & { item: Primitive.TOCItemType }) {
|
|
191
|
+
const items = useTOCItems();
|
|
192
|
+
const { isFirst, isLast, svg } = useMemo(() => {
|
|
193
|
+
const index = items.indexOf(item);
|
|
194
|
+
const isFirst = index === 0;
|
|
195
|
+
const isLast = index === items.length - 1;
|
|
196
|
+
const l1 = getLineOffset(item.depth);
|
|
197
|
+
const l0 = isFirst ? l1 : getLineOffset(items[index - 1].depth);
|
|
198
|
+
const l2 = isLast ? l1 : getLineOffset(items[index + 1].depth);
|
|
199
|
+
|
|
200
|
+
return {
|
|
201
|
+
isFirst,
|
|
202
|
+
isLast,
|
|
203
|
+
svg: (
|
|
204
|
+
<svg
|
|
205
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
206
|
+
className={cn(
|
|
207
|
+
'absolute -top-1.5 inset-s-0 bottom-0 h-[calc(100%+--spacing(1.5))] -z-1 rtl:-scale-x-100',
|
|
208
|
+
l1 !== l2 && 'h-full bottom-1.5',
|
|
209
|
+
)}
|
|
210
|
+
style={{ width: Math.max(l0, l1) + 9 }}
|
|
211
|
+
>
|
|
212
|
+
{l0 !== l1 && (
|
|
213
|
+
<path
|
|
214
|
+
d={`M ${l0 + 0.5} 0 L ${l0 + 0.5} 0 ${l1 + 0.5} 12`}
|
|
215
|
+
stroke="black"
|
|
216
|
+
strokeWidth="1"
|
|
217
|
+
fill="none"
|
|
218
|
+
className="stroke-foreground/10"
|
|
219
|
+
/>
|
|
220
|
+
)}
|
|
221
|
+
<line
|
|
222
|
+
x1={l1 + 0.5}
|
|
223
|
+
y1={l0 === l1 ? '6' : '12'}
|
|
224
|
+
x2={l1 + 0.5}
|
|
225
|
+
y2="100%"
|
|
226
|
+
strokeWidth="1"
|
|
227
|
+
className="stroke-foreground/10"
|
|
228
|
+
/>
|
|
229
|
+
{item._step !== undefined && (
|
|
230
|
+
<g transform={`translate(${l1 + 0.5}, ${l1 === l2 ? '3' : '6'})`}>
|
|
231
|
+
<circle cx="0" cy="50%" r="8" className="fill-muted" />
|
|
232
|
+
<text
|
|
233
|
+
x="0"
|
|
234
|
+
y="50%"
|
|
235
|
+
textAnchor="middle"
|
|
236
|
+
alignmentBaseline="central"
|
|
237
|
+
dominantBaseline="middle"
|
|
238
|
+
className="fill-muted-foreground font-medium text-xs leading-none font-mono rtl:-scale-x-100"
|
|
239
|
+
>
|
|
240
|
+
{item._step}
|
|
241
|
+
</text>
|
|
242
|
+
</g>
|
|
243
|
+
)}
|
|
244
|
+
</svg>
|
|
245
|
+
),
|
|
246
|
+
};
|
|
247
|
+
}, [items, item]);
|
|
248
|
+
|
|
249
|
+
return (
|
|
250
|
+
<Primitive.TOCItem
|
|
251
|
+
href={item.url}
|
|
252
|
+
{...props}
|
|
253
|
+
className={cn(
|
|
254
|
+
'prose prose-sm relative py-1.5 scroll-m-4 text-muted-foreground hover:text-accent-foreground transition-colors wrap-anywhere data-[active=true]:text-primary',
|
|
255
|
+
isFirst && 'pt-0',
|
|
256
|
+
isLast && 'pb-0',
|
|
257
|
+
props.className,
|
|
258
|
+
)}
|
|
259
|
+
style={{ paddingInlineStart: getItemOffset(item.depth), ...props.style }}
|
|
260
|
+
>
|
|
261
|
+
{svg}
|
|
262
|
+
{item.title}
|
|
263
|
+
</Primitive.TOCItem>
|
|
264
|
+
);
|
|
265
|
+
}
|
|
266
|
+
|