fumadocs-ui 16.5.4 → 16.6.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.
@@ -36,6 +36,7 @@
36
36
  @source inline("-translate-y-1/2");
37
37
  @source inline("@container");
38
38
  @source inline("@defaultValue");
39
+ @source inline("@deprecated");
39
40
  @source inline("@example");
40
41
  @source inline("@keyframes");
41
42
  @source inline("@max-lg:col-span-full");
@@ -75,6 +76,7 @@
75
76
  @source inline("all");
76
77
  @source inline("allowClear");
77
78
  @source inline("allowCopy");
79
+ @source inline("allowDangerousHtml");
78
80
  @source inline("allowedMode");
79
81
  @source inline("allowing");
80
82
  @source inline("always");
@@ -130,12 +132,14 @@
130
132
  @source inline("bg-transparent");
131
133
  @source inline("black");
132
134
  @source inline("block");
135
+ @source inline("blocks");
133
136
  @source inline("body");
134
137
  @source inline("boolean");
135
138
  @source inline("border");
136
139
  @source inline("border-b");
137
140
  @source inline("border-fd-foreground/10");
138
141
  @source inline("border-l");
142
+ @source inline("border-none");
139
143
  @source inline("border-s");
140
144
  @source inline("border-t");
141
145
  @source inline("border-transparent");
@@ -193,13 +197,13 @@
193
197
  @source inline("container");
194
198
  @source inline("containerRef");
195
199
  @source inline("content");
196
- @source inline("contentWithHighlights");
197
200
  @source inline("context");
198
201
  @source inline("controlled/uncontrolled");
199
202
  @source inline("copy");
200
203
  @source inline("core");
201
204
  @source inline("counterSet");
202
205
  @source inline("createContext");
206
+ @source inline("createMarkdownRenderer");
203
207
  @source inline("createRelativeLink");
204
208
  @source inline("css");
205
209
  @source inline("ctx");
@@ -288,6 +292,7 @@
288
292
  @source inline("displayed");
289
293
  @source inline("div");
290
294
  @source inline("divide-fd-border");
295
+ @source inline("divide-x");
291
296
  @source inline("divide-y");
292
297
  @source inline("docsLayoutCtx");
293
298
  @source inline("documented");
@@ -360,6 +365,7 @@
360
365
  @source inline("formattedValue");
361
366
  @source inline("forwardRef");
362
367
  @source inline("found");
368
+ @source inline("fragment");
363
369
  @source inline("framework");
364
370
  @source inline("free");
365
371
  @source inline("from");
@@ -413,9 +419,11 @@
413
419
  @source inline("h4");
414
420
  @source inline("h5");
415
421
  @source inline("h6");
422
+ @source inline("handle");
416
423
  @source inline("happens");
417
424
  @source inline("has-focus-visible:bg-fd-accent");
418
425
  @source inline("hash");
426
+ @source inline("hast");
419
427
  @source inline("have");
420
428
  @source inline("headers");
421
429
  @source inline("heading");
@@ -423,7 +431,7 @@
423
431
  @source inline("hence");
424
432
  @source inline("here");
425
433
  @source inline("hidden");
426
- @source inline("highlights");
434
+ @source inline("highlight");
427
435
  @source inline("hooks");
428
436
  @source inline("horizontal");
429
437
  @source inline("hotKey");
@@ -449,11 +457,11 @@
449
457
  @source inline("img");
450
458
  @source inline("import");
451
459
  @source inline("in");
460
+ @source inline("inPre");
452
461
  @source inline("inTab");
453
462
  @source inline("index");
454
463
  @source inline("infinite");
455
464
  @source inline("info");
456
- @source inline("inline");
457
465
  @source inline("inline-flex");
458
466
  @source inline("input");
459
467
  @source inline("inputType");
@@ -485,7 +493,6 @@
485
493
  @source inline("k");
486
494
  @source inline("keepBackground");
487
495
  @source inline("key");
488
- @source inline("keyVariants");
489
496
  @source inline("keydown");
490
497
  @source inline("keyof");
491
498
  @source inline("label");
@@ -531,12 +538,15 @@
531
538
  @source inline("make");
532
539
  @source inline("mapped");
533
540
  @source inline("marginBottom");
541
+ @source inline("mark");
534
542
  @source inline("marked");
535
543
  @source inline("mask-[linear-gradient(to_bottom,transparent,white_16px,white_calc(100%-16px),transparent)]");
544
+ @source inline("mask-[linear-gradient(to_bottom,white,white_30px,transparent_80px)]");
536
545
  @source inline("maskComposite");
537
546
  @source inline("maskImage");
538
547
  @source inline("matching");
539
548
  @source inline("max-h-(--radix-popover-content-available-height)");
549
+ @source inline("max-h-20");
540
550
  @source inline("max-h-[460px]");
541
551
  @source inline("max-h-[600px]");
542
552
  @source inline("max-h-[80svh]");
@@ -546,6 +556,7 @@
546
556
  @source inline("max-md:rounded-md");
547
557
  @source inline("max-w-[1400px]");
548
558
  @source inline("max-w-[98vw]");
559
+ @source inline("max-w-full");
549
560
  @source inline("max-w-screen-sm");
550
561
  @source inline("max-width");
551
562
  @source inline("mb-1");
@@ -555,6 +566,8 @@
555
566
  @source inline("md:mb-auto");
556
567
  @source inline("md:size-5");
557
568
  @source inline("md:top-[calc(50%-250px)]");
569
+ @source inline("mdComponents");
570
+ @source inline("mdRenderer");
558
571
  @source inline("me-1");
559
572
  @source inline("me-2");
560
573
  @source inline("me-auto");
@@ -580,6 +593,7 @@
580
593
  @source inline("mx-auto");
581
594
  @source inline("my-0");
582
595
  @source inline("my-0!");
596
+ @source inline("my-0.5");
583
597
  @source inline("my-4");
584
598
  @source inline("my-6");
585
599
  @source inline("my-auto");
@@ -613,6 +627,7 @@
613
627
  @source inline("not");
614
628
  @source inline("not-last:mb-2");
615
629
  @source inline("not-prose");
630
+ @source inline("now");
616
631
  @source inline("null");
617
632
  @source inline("num");
618
633
  @source inline("number");
@@ -633,13 +648,17 @@
633
648
  @source inline("onKey");
634
649
  @source inline("onKeyDown");
635
650
  @source inline("onOpenChange");
651
+ @source inline("onOpenChangeCallback");
636
652
  @source inline("onPointerEnter");
637
653
  @source inline("onPointerLeave");
638
654
  @source inline("onPointerMove");
639
655
  @source inline("onPrint");
640
656
  @source inline("onSearchChange");
657
+ @source inline("onSearchChangeCallback");
641
658
  @source inline("onSelect");
659
+ @source inline("onSelectCallback");
642
660
  @source inline("onTagChange");
661
+ @source inline("onTagChangeCallback");
643
662
  @source inline("onValueChange");
644
663
  @source inline("one");
645
664
  @source inline("only");
@@ -670,6 +689,7 @@
670
689
  @source inline("owner");
671
690
  @source inline("p");
672
691
  @source inline("p-0");
692
+ @source inline("p-0.5");
673
693
  @source inline("p-1");
674
694
  @source inline("p-1.5");
675
695
  @source inline("p-2");
@@ -680,6 +700,7 @@
680
700
  @source inline("page");
681
701
  @source inline("parameters");
682
702
  @source inline("params");
703
+ @source inline("parentId");
683
704
  @source inline("pass");
684
705
  @source inline("passed");
685
706
  @source inline("path");
@@ -724,11 +745,14 @@
724
745
  @source inline("pt-0");
725
746
  @source inline("pure");
726
747
  @source inline("px");
748
+ @source inline("px-0.5");
749
+ @source inline("px-1");
727
750
  @source inline("px-1.5");
728
751
  @source inline("px-2");
729
752
  @source inline("px-2.5");
730
753
  @source inline("px-3");
731
754
  @source inline("px-4");
755
+ @source inline("px-px");
732
756
  @source inline("py-0.5");
733
757
  @source inline("py-1");
734
758
  @source inline("py-1.5");
@@ -753,11 +777,17 @@
753
777
  @source inline("refs");
754
778
  @source inline("region");
755
779
  @source inline("registering");
780
+ @source inline("rehype-raw");
781
+ @source inline("rehypeCustomElements");
782
+ @source inline("rehypePlugins");
783
+ @source inline("rehypeRaw");
756
784
  @source inline("rel");
757
785
  @source inline("relative");
786
+ @source inline("remarkRehypeOptions");
758
787
  @source inline("remove");
759
788
  @source inline("render");
760
789
  @source inline("renderHighlights");
790
+ @source inline("renderMarkdown");
761
791
  @source inline("repo");
762
792
  @source inline("repository");
763
793
  @source inline("required");
@@ -791,6 +821,7 @@
791
821
  @source inline("s");
792
822
  @source inline("scroll");
793
823
  @source inline("scroll-into-view-if-needed");
824
+ @source inline("scroll-m-20");
794
825
  @source inline("scroll-m-24");
795
826
  @source inline("scroll-m-28");
796
827
  @source inline("scrollIntoView");
@@ -860,6 +891,7 @@
860
891
  @source inline("stars");
861
892
  @source inline("start-0");
862
893
  @source inline("start-3");
894
+ @source inline("start-6");
863
895
  @source inline("state");
864
896
  @source inline("static");
865
897
  @source inline("sticky");
@@ -868,6 +900,7 @@
868
900
  @source inline("stroke-fd-foreground/10");
869
901
  @source inline("stroke-width");
870
902
  @source inline("strokeWidth");
903
+ @source inline("strong");
871
904
  @source inline("style");
872
905
  @source inline("styles");
873
906
  @source inline("success");
@@ -886,6 +919,7 @@
886
919
  @source inline("tabs");
887
920
  @source inline("tabsRef");
888
921
  @source inline("tag");
922
+ @source inline("tagName");
889
923
  @source inline("tags");
890
924
  @source inline("tailwind-merge");
891
925
  @source inline("target");
@@ -934,6 +968,7 @@
934
968
  @source inline("top-0");
935
969
  @source inline("top-1.5");
936
970
  @source inline("top-1/2");
971
+ @source inline("top-2.5");
937
972
  @source inline("top-3");
938
973
  @source inline("top-4");
939
974
  @source inline("touch");
@@ -960,6 +995,8 @@
960
995
  @source inline("under");
961
996
  @source inline("underline");
962
997
  @source inline("underlying");
998
+ @source inline("unified");
999
+ @source inline("unist-util-visit");
963
1000
  @source inline("unknown");
964
1001
  @source inline("unmounted");
965
1002
  @source inline("updateAnchor");
@@ -989,12 +1026,12 @@
989
1026
  @source inline("useTheme");
990
1027
  @source inline("useTreeContext");
991
1028
  @source inline("useTreePath");
992
- @source inline("used");
993
1029
  @source inline("useful");
994
1030
  @source inline("user");
995
1031
  @source inline("users");
996
1032
  @source inline("using");
997
1033
  @source inline("usually");
1034
+ @source inline("v");
998
1035
  @source inline("v17");
999
1036
  @source inline("value");
1000
1037
  @source inline("valueToIdMap");
@@ -1007,13 +1044,14 @@
1007
1044
  @source inline("viewRef");
1008
1045
  @source inline("viewport");
1009
1046
  @source inline("viewportProps");
1047
+ @source inline("visit");
1010
1048
  @source inline("void");
1011
1049
  @source inline("w");
1012
1050
  @source inline("w-(--radix-popover-trigger-width)");
1013
1051
  @source inline("w-0");
1014
1052
  @source inline("w-0.5");
1015
1053
  @source inline("w-1.5");
1016
- @source inline("w-[25%]");
1054
+ @source inline("w-1/4");
1017
1055
  @source inline("w-[calc(100%-1rem)]");
1018
1056
  @source inline("w-fit");
1019
1057
  @source inline("w-full");
@@ -65,10 +65,12 @@ declare function SearchDialogListItem({
65
65
  item,
66
66
  className,
67
67
  children,
68
- renderHighlights: render,
68
+ renderMarkdown,
69
+ renderHighlights: _,
69
70
  ...props
70
71
  }: ComponentProps<'button'> & {
71
- renderHighlights?: typeof renderHighlights;
72
+ renderMarkdown?: (v: string) => ReactNode; /** @deprecated highlight blocks is now wrapped in `<mark />`, use `renderMarkdown` to handle instead. */
73
+ renderHighlights?: (blocks: HighlightedText<ReactNode>[]) => ReactNode;
72
74
  item: SearchItemType;
73
75
  }): react_jsx_runtime0.JSX.Element;
74
76
  declare function SearchDialogIcon(props: ComponentProps<'svg'>): react_jsx_runtime0.JSX.Element;
@@ -90,7 +92,6 @@ declare function TagsListItem({
90
92
  }: ComponentProps<'button'> & {
91
93
  value: string;
92
94
  }): react_jsx_runtime0.JSX.Element;
93
- declare function renderHighlights(highlights: HighlightedText<ReactNode>[]): ReactNode;
94
95
  declare function useSearch(): {
95
96
  open: boolean;
96
97
  onOpenChange: (open: boolean) => void;
@@ -11,35 +11,123 @@ import { cva } from "class-variance-authority";
11
11
  import { useOnChange } from "fumadocs-core/utils/use-on-change";
12
12
  import scrollIntoView from "scroll-into-view-if-needed";
13
13
  import { Dialog, DialogContent, DialogOverlay, DialogTitle } from "@radix-ui/react-dialog";
14
+ import { createMarkdownRenderer } from "fumadocs-core/content/md";
15
+ import rehypeRaw from "rehype-raw";
16
+ import { visit } from "unist-util-visit";
14
17
 
15
18
  //#region src/components/dialog/search.tsx
16
- const Context = createContext(null);
19
+ const RootContext = createContext(null);
17
20
  const ListContext = createContext(null);
18
21
  const TagsListContext = createContext(null);
22
+ const PreContext = createContext(false);
23
+ const mdRenderer = createMarkdownRenderer({
24
+ remarkRehypeOptions: { allowDangerousHtml: true },
25
+ rehypePlugins: [rehypeRaw, rehypeCustomElements]
26
+ });
27
+ const mdComponents = {
28
+ mark(props) {
29
+ return /* @__PURE__ */ jsx("span", {
30
+ ...props,
31
+ className: "text-fd-primary underline"
32
+ });
33
+ },
34
+ a: "span",
35
+ p(props) {
36
+ return /* @__PURE__ */ jsx("p", {
37
+ ...props,
38
+ className: "min-w-0"
39
+ });
40
+ },
41
+ strong(props) {
42
+ return /* @__PURE__ */ jsx("strong", {
43
+ ...props,
44
+ className: "text-fd-accent-foreground font-medium"
45
+ });
46
+ },
47
+ code(props) {
48
+ if (use(PreContext)) return /* @__PURE__ */ jsx("code", {
49
+ ...props,
50
+ className: "mask-[linear-gradient(to_bottom,white,white_30px,transparent_80px)]"
51
+ });
52
+ return /* @__PURE__ */ jsx("code", {
53
+ ...props,
54
+ className: "border rounded-md px-px bg-fd-secondary text-fd-secondary-foreground"
55
+ });
56
+ },
57
+ custom({ _tagName = "fragment", children, ...rest }) {
58
+ return /* @__PURE__ */ jsxs("span", {
59
+ className: "inline-flex max-w-full items-center border p-0.5 rounded-md bg-fd-card text-fd-card-foreground divide-x divide-fd-border",
60
+ children: [
61
+ /* @__PURE__ */ jsx("code", {
62
+ className: "rounded-sm px-0.5 me-1 bg-fd-primary font-medium text-xs text-fd-primary-foreground border-none",
63
+ children: _tagName
64
+ }),
65
+ Object.entries(rest).map(([k, v]) => {
66
+ if (typeof v !== "string") return;
67
+ return /* @__PURE__ */ jsxs("code", {
68
+ className: "truncate text-xs text-fd-muted-foreground px-1",
69
+ children: [/* @__PURE__ */ jsxs("span", {
70
+ className: "text-fd-card-foreground",
71
+ children: [k, ": "]
72
+ }), v]
73
+ }, k);
74
+ }),
75
+ children && /* @__PURE__ */ jsx("span", {
76
+ className: "ps-1",
77
+ children
78
+ })
79
+ ]
80
+ });
81
+ },
82
+ pre(props) {
83
+ return /* @__PURE__ */ jsx("pre", {
84
+ ...props,
85
+ className: cn("flex flex-col border rounded-md my-0.5 p-2 bg-fd-secondary text-fd-secondary-foreground max-h-20 overflow-hidden", props.className),
86
+ children: /* @__PURE__ */ jsx(PreContext, {
87
+ value: true,
88
+ children: props.children
89
+ })
90
+ });
91
+ }
92
+ };
93
+ function rehypeCustomElements() {
94
+ return (tree) => {
95
+ visit(tree, (node) => {
96
+ if (node.type === "element" && document.createElement(node.tagName) instanceof HTMLUnknownElement) {
97
+ node.properties._tagName = node.tagName;
98
+ node.tagName = "custom";
99
+ }
100
+ });
101
+ };
102
+ }
19
103
  function SearchDialog({ open, onOpenChange, search, onSearchChange, isLoading = false, onSelect: onSelectProp, children }) {
20
104
  const router = useRouter();
21
- const onSelect = useEffectEvent((item) => {
105
+ const onOpenChangeCallback = useRef(onOpenChange);
106
+ onOpenChangeCallback.current = onOpenChange;
107
+ const onSearchChangeCallback = useRef(onSearchChange);
108
+ onSearchChangeCallback.current = onSearchChange;
109
+ const onSelect = (item) => {
22
110
  if (item.type === "action") item.onSelect();
23
111
  else if (item.external) window.open(item.url, "_blank")?.focus();
24
112
  else router.push(item.url);
25
113
  onOpenChange(false);
26
114
  onSelectProp?.(item);
27
- });
115
+ };
116
+ const onSelectCallback = useRef(onSelect);
117
+ onSelectCallback.current = onSelect;
28
118
  return /* @__PURE__ */ jsx(Dialog, {
29
119
  open,
30
120
  onOpenChange,
31
- children: /* @__PURE__ */ jsx(Context.Provider, {
121
+ children: /* @__PURE__ */ jsx(RootContext, {
32
122
  value: useMemo(() => ({
33
123
  open,
34
- onOpenChange,
35
124
  search,
36
- onSearchChange,
37
- onSelect,
38
- isLoading
125
+ isLoading,
126
+ onOpenChange: (v) => onOpenChangeCallback.current(v),
127
+ onSearchChange: (v) => onSearchChangeCallback.current(v),
128
+ onSelect: (v) => onSelectCallback.current(v)
39
129
  }), [
40
130
  isLoading,
41
- onOpenChange,
42
- onSearchChange,
43
131
  open,
44
132
  search
45
133
  ]),
@@ -150,7 +238,7 @@ function SearchDialogList({ items = null, Empty = () => /* @__PURE__ */ jsx("div
150
238
  className: cn("overflow-hidden h-(--fd-animated-height) transition-[height]", props.className),
151
239
  children: /* @__PURE__ */ jsx("div", {
152
240
  className: cn("w-full flex flex-col overflow-y-auto max-h-[460px] p-1", !items && "hidden"),
153
- children: /* @__PURE__ */ jsxs(ListContext.Provider, {
241
+ children: /* @__PURE__ */ jsxs(ListContext, {
154
242
  value: useMemo(() => ({
155
243
  active,
156
244
  setActive
@@ -163,7 +251,10 @@ function SearchDialogList({ items = null, Empty = () => /* @__PURE__ */ jsx("div
163
251
  })
164
252
  });
165
253
  }
166
- function SearchDialogListItem({ item, className, children, renderHighlights: render = renderHighlights, ...props }) {
254
+ function SearchDialogListItem({ item, className, children, renderMarkdown = (s) => /* @__PURE__ */ jsx(mdRenderer.Markdown, {
255
+ components: mdComponents,
256
+ children: s
257
+ }), renderHighlights: _, ...props }) {
167
258
  const { active: activeId, setActive } = useSearchList();
168
259
  const active = item.id === activeId;
169
260
  if (item.type === "action") children ??= item.node;
@@ -176,9 +267,10 @@ function SearchDialogListItem({ item, className, children, renderHighlights: ren
176
267
  role: "none",
177
268
  className: "absolute start-3 inset-y-0 w-px bg-fd-border"
178
269
  }),
179
- /* @__PURE__ */ jsxs("p", {
180
- className: cn("min-w-0 truncate", item.type !== "page" && "ps-4", item.type === "page" || item.type === "heading" ? "font-medium" : "text-fd-popover-foreground/80"),
181
- children: [item.type === "heading" && /* @__PURE__ */ jsx(Hash, { className: "inline me-1 size-4 text-fd-muted-foreground" }), item.contentWithHighlights ? render(item.contentWithHighlights) : item.content]
270
+ item.type === "heading" && /* @__PURE__ */ jsx(Hash, { className: "absolute start-6 top-2.5 size-4 text-fd-muted-foreground" }),
271
+ /* @__PURE__ */ jsx("div", {
272
+ className: cn("min-w-0", item.type === "text" && "ps-4", item.type === "heading" && "ps-8", item.type === "page" || item.type === "heading" ? "font-medium" : "text-fd-popover-foreground/80"),
273
+ children: typeof item.content === "string" ? renderMarkdown(item.content) : item.content
182
274
  })
183
275
  ] });
184
276
  return /* @__PURE__ */ jsx("button", {
@@ -191,7 +283,7 @@ function SearchDialogListItem({ item, className, children, renderHighlights: ren
191
283
  });
192
284
  }, [active]),
193
285
  "aria-selected": active,
194
- className: cn("relative select-none px-2.5 py-2 text-start text-sm rounded-lg", active && "bg-fd-accent text-fd-accent-foreground", className),
286
+ className: cn("relative select-none shrink-0 px-2.5 py-2 text-start text-sm overflow-hidden rounded-lg", active && "bg-fd-accent text-fd-accent-foreground", className),
195
287
  onPointerMove: () => setActive(item.id),
196
288
  ...props,
197
289
  children
@@ -206,19 +298,17 @@ function SearchDialogIcon(props) {
206
298
  }
207
299
  const itemVariants = cva("rounded-md border px-2 py-0.5 text-xs font-medium text-fd-muted-foreground transition-colors", { variants: { active: { true: "bg-fd-accent text-fd-accent-foreground" } } });
208
300
  function TagsList({ tag, onTagChange, allowClear = false, ...props }) {
301
+ const onTagChangeCallback = useRef(onTagChange);
302
+ onTagChangeCallback.current = onTagChange;
209
303
  return /* @__PURE__ */ jsx("div", {
210
304
  ...props,
211
305
  className: cn("flex items-center gap-1 flex-wrap", props.className),
212
- children: /* @__PURE__ */ jsx(TagsListContext.Provider, {
306
+ children: /* @__PURE__ */ jsx(TagsListContext, {
213
307
  value: useMemo(() => ({
214
308
  value: tag,
215
- onValueChange: onTagChange,
309
+ onValueChange: (v) => onTagChangeCallback.current(v),
216
310
  allowClear
217
- }), [
218
- allowClear,
219
- onTagChange,
220
- tag
221
- ]),
311
+ }), [allowClear, tag]),
222
312
  children: props.children
223
313
  })
224
314
  });
@@ -233,25 +323,14 @@ function TagsListItem({ value, className, ...props }) {
233
323
  active: selected,
234
324
  className
235
325
  })),
236
- onClick: () => {
237
- onValueChange(selected && allowClear ? void 0 : value);
238
- },
326
+ onClick: () => onValueChange(selected && allowClear ? void 0 : value),
239
327
  tabIndex: -1,
240
328
  ...props,
241
329
  children: props.children
242
330
  });
243
331
  }
244
- function renderHighlights(highlights) {
245
- return highlights.map((node, i) => {
246
- if (node.styles?.highlight) return /* @__PURE__ */ jsx("span", {
247
- className: "text-fd-primary underline",
248
- children: node.content
249
- }, i);
250
- return /* @__PURE__ */ jsx(Fragment, { children: node.content }, i);
251
- });
252
- }
253
332
  function useSearch() {
254
- const ctx = use(Context);
333
+ const ctx = use(RootContext);
255
334
  if (!ctx) throw new Error("Missing <SearchDialog />");
256
335
  return ctx;
257
336
  }
@@ -1,4 +1,4 @@
1
- import { ReactNode } from "react";
1
+ import { ComponentProps, ReactNode } from "react";
2
2
  import * as react_jsx_runtime0 from "react/jsx-runtime";
3
3
 
4
4
  //#region src/components/type-table.d.ts
@@ -30,9 +30,12 @@ interface TypeNode {
30
30
  returns?: ReactNode;
31
31
  }
32
32
  declare function TypeTable({
33
- type
33
+ id,
34
+ type,
35
+ className,
36
+ ...props
34
37
  }: {
35
38
  type: Record<string, TypeNode>;
36
- }): react_jsx_runtime0.JSX.Element;
39
+ } & ComponentProps<'div'>): react_jsx_runtime0.JSX.Element;
37
40
  //#endregion
38
41
  export { ParameterNode, TypeNode, TypeTable };
@@ -2,47 +2,56 @@
2
2
 
3
3
  import { cn } from "../utils/cn.js";
4
4
  import { Collapsible, CollapsibleContent, CollapsibleTrigger } from "./ui/collapsible.js";
5
- import { useState } from "react";
5
+ import { useEffect, useState } from "react";
6
6
  import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
7
7
  import Link from "fumadocs-core/link";
8
8
  import { ChevronDown } from "lucide-react";
9
9
  import { cva } from "class-variance-authority";
10
10
 
11
11
  //#region src/components/type-table.tsx
12
- const keyVariants = cva("text-fd-primary", { variants: { deprecated: { true: "line-through text-fd-primary/50" } } });
13
12
  const fieldVariants = cva("text-fd-muted-foreground not-prose pe-2");
14
- function TypeTable({ type }) {
13
+ function TypeTable({ id, type, className, ...props }) {
15
14
  return /* @__PURE__ */ jsxs("div", {
16
- className: "@container flex flex-col p-1 bg-fd-card text-fd-card-foreground rounded-2xl border my-6 text-sm overflow-hidden",
15
+ id,
16
+ className: cn("@container flex flex-col p-1 bg-fd-card text-fd-card-foreground rounded-2xl border my-6 text-sm overflow-hidden", className),
17
+ ...props,
17
18
  children: [/* @__PURE__ */ jsxs("div", {
18
19
  className: "flex font-medium items-center px-3 py-1 not-prose text-fd-muted-foreground",
19
20
  children: [/* @__PURE__ */ jsx("p", {
20
- className: "w-[25%]",
21
+ className: "w-1/4",
21
22
  children: "Prop"
22
23
  }), /* @__PURE__ */ jsx("p", {
23
24
  className: "@max-xl:hidden",
24
25
  children: "Type"
25
26
  })]
26
27
  }), Object.entries(type).map(([key, value]) => /* @__PURE__ */ jsx(Item, {
28
+ parentId: id,
27
29
  name: key,
28
30
  item: value
29
31
  }, key))]
30
32
  });
31
33
  }
32
- function Item({ name, item: { parameters = [], description, required = false, deprecated, typeDescription, default: defaultValue, type, typeDescriptionLink, returns } }) {
34
+ function Item({ parentId, name, item: { parameters = [], description, required = false, deprecated, typeDescription, default: defaultValue, type, typeDescriptionLink, returns } }) {
33
35
  const [open, setOpen] = useState(false);
36
+ const id = parentId ? `${parentId}-${name}` : void 0;
37
+ useEffect(() => {
38
+ const hash = window.location.hash;
39
+ if (!id || !hash) return;
40
+ if (`#${id}` === hash) setOpen(true);
41
+ }, [id]);
34
42
  return /* @__PURE__ */ jsxs(Collapsible, {
43
+ id,
35
44
  open,
36
- onOpenChange: setOpen,
37
- className: cn("rounded-xl border overflow-hidden transition-all", open ? "shadow-sm bg-fd-background not-last:mb-2" : "border-transparent"),
45
+ onOpenChange: (v) => {
46
+ if (v && id) window.history.replaceState(null, "", `#${id}`);
47
+ setOpen(v);
48
+ },
49
+ className: cn("rounded-xl border overflow-hidden scroll-m-20 transition-all", open ? "shadow-sm bg-fd-background not-last:mb-2" : "border-transparent"),
38
50
  children: [/* @__PURE__ */ jsxs(CollapsibleTrigger, {
39
51
  className: "relative flex flex-row items-center w-full group text-start px-3 py-2 not-prose hover:bg-fd-accent",
40
52
  children: [
41
53
  /* @__PURE__ */ jsxs("code", {
42
- className: cn(keyVariants({
43
- deprecated,
44
- className: "min-w-fit w-[25%] font-medium pe-2"
45
- })),
54
+ className: cn("text-fd-primary min-w-fit w-1/4 font-mono font-medium pe-2", deprecated && "line-through text-fd-primary/50"),
46
55
  children: [name, !required && "?"]
47
56
  }),
48
57
  typeDescriptionLink ? /* @__PURE__ */ jsx(Link, {
@@ -4,7 +4,7 @@ import * as class_variance_authority_types0 from "class-variance-authority/types
4
4
 
5
5
  //#region src/layouts/home/client.d.ts
6
6
  declare const navItemVariants: (props?: ({
7
- variant?: "main" | "icon" | "button" | null | undefined;
7
+ variant?: "icon" | "button" | "main" | null | undefined;
8
8
  } & class_variance_authority_types0.ClassProp) | undefined) => string;
9
9
  declare function Header({
10
10
  nav,
package/dist/style.css CHANGED
@@ -318,6 +318,9 @@
318
318
  .start-4 {
319
319
  inset-inline-start: calc(var(--spacing) * 4);
320
320
  }
321
+ .start-6 {
322
+ inset-inline-start: calc(var(--spacing) * 6);
323
+ }
321
324
  .end-0 {
322
325
  inset-inline-end: calc(var(--spacing) * 0);
323
326
  }
@@ -348,6 +351,9 @@
348
351
  .top-1\/2 {
349
352
  top: calc(1/2 * 100%);
350
353
  }
354
+ .top-2\.5 {
355
+ top: calc(var(--spacing) * 2.5);
356
+ }
351
357
  .top-3 {
352
358
  top: calc(var(--spacing) * 3);
353
359
  }
@@ -432,6 +438,9 @@
432
438
  .my-0\! {
433
439
  margin-block: calc(var(--spacing) * 0) !important;
434
440
  }
441
+ .my-0\.5 {
442
+ margin-block: calc(var(--spacing) * 0.5);
443
+ }
435
444
  .my-4 {
436
445
  margin-block: calc(var(--spacing) * 4);
437
446
  }
@@ -1002,6 +1011,9 @@
1002
1011
  .max-h-\(--radix-popover-content-available-height\) {
1003
1012
  max-height: var(--radix-popover-content-available-height);
1004
1013
  }
1014
+ .max-h-20 {
1015
+ max-height: calc(var(--spacing) * 20);
1016
+ }
1005
1017
  .max-h-\[50vh\] {
1006
1018
  max-height: 50vh;
1007
1019
  }
@@ -1041,12 +1053,12 @@
1041
1053
  .w-1\.5 {
1042
1054
  width: calc(var(--spacing) * 1.5);
1043
1055
  }
1056
+ .w-1\/4 {
1057
+ width: calc(1/4 * 100%);
1058
+ }
1044
1059
  .w-4 {
1045
1060
  width: calc(var(--spacing) * 4);
1046
1061
  }
1047
- .w-\[25\%\] {
1048
- width: 25%;
1049
- }
1050
1062
  .w-\[85\%\] {
1051
1063
  width: 85%;
1052
1064
  }
@@ -1086,6 +1098,9 @@
1086
1098
  .max-w-\[1400px\] {
1087
1099
  max-width: 1400px;
1088
1100
  }
1101
+ .max-w-full {
1102
+ max-width: 100%;
1103
+ }
1089
1104
  .max-w-screen-sm {
1090
1105
  max-width: var(--breakpoint-sm);
1091
1106
  }
@@ -1165,6 +1180,9 @@
1165
1180
  .animate-pulse {
1166
1181
  animation: var(--animate-pulse);
1167
1182
  }
1183
+ .scroll-m-20 {
1184
+ scroll-margin: calc(var(--spacing) * 20);
1185
+ }
1168
1186
  .scroll-m-24 {
1169
1187
  scroll-margin: calc(var(--spacing) * 24);
1170
1188
  }
@@ -1246,6 +1264,14 @@
1246
1264
  .gap-y-4 {
1247
1265
  row-gap: calc(var(--spacing) * 4);
1248
1266
  }
1267
+ .divide-x {
1268
+ :where(& > :not(:last-child)) {
1269
+ --tw-divide-x-reverse: 0;
1270
+ border-inline-style: var(--tw-border-style);
1271
+ border-inline-start-width: calc(1px * var(--tw-divide-x-reverse));
1272
+ border-inline-end-width: calc(1px * calc(1 - var(--tw-divide-x-reverse)));
1273
+ }
1274
+ }
1249
1275
  .divide-y {
1250
1276
  :where(& > :not(:last-child)) {
1251
1277
  --tw-divide-y-reverse: 0;
@@ -1346,6 +1372,10 @@
1346
1372
  border-left-style: var(--tw-border-style);
1347
1373
  border-left-width: 1px;
1348
1374
  }
1375
+ .border-none {
1376
+ --tw-border-style: none;
1377
+ border-style: none;
1378
+ }
1349
1379
  .border-fd-foreground\/10 {
1350
1380
  border-color: color-mix(in srgb, hsl(0, 0%, 3.9%) 10%, transparent);
1351
1381
  @supports (color: color-mix(in lab, red, red)) {
@@ -1445,6 +1475,9 @@
1445
1475
  .mask-\[linear-gradient\(to_bottom\,transparent\,white_calc\(var\(--spacing\)\*14\)\,white_calc\(100\%-var\(--spacing\)\*14\)\,transparent\)\] {
1446
1476
  mask-image: linear-gradient(to bottom,transparent,white calc(var(--spacing) * 14),white calc(100% - var(--spacing) * 14),transparent);
1447
1477
  }
1478
+ .mask-\[linear-gradient\(to_bottom\,white\,white_30px\,transparent_80px\)\] {
1479
+ mask-image: linear-gradient(to bottom,white,white 30px,transparent 80px);
1480
+ }
1448
1481
  .fill-\(--callout-color\) {
1449
1482
  fill: var(--callout-color);
1450
1483
  }
@@ -1484,6 +1517,9 @@
1484
1517
  .px-0\.5 {
1485
1518
  padding-inline: calc(var(--spacing) * 0.5);
1486
1519
  }
1520
+ .px-1 {
1521
+ padding-inline: calc(var(--spacing) * 1);
1522
+ }
1487
1523
  .px-1\.5 {
1488
1524
  padding-inline: calc(var(--spacing) * 1.5);
1489
1525
  }
@@ -1502,6 +1538,9 @@
1502
1538
  .px-6 {
1503
1539
  padding-inline: calc(var(--spacing) * 6);
1504
1540
  }
1541
+ .px-px {
1542
+ padding-inline: 1px;
1543
+ }
1505
1544
  .py-0\.5 {
1506
1545
  padding-block: calc(var(--spacing) * 0.5);
1507
1546
  }
@@ -2971,6 +3010,11 @@
2971
3010
  syntax: "*";
2972
3011
  inherits: false;
2973
3012
  }
3013
+ @property --tw-divide-x-reverse {
3014
+ syntax: "*";
3015
+ inherits: false;
3016
+ initial-value: 0;
3017
+ }
2974
3018
  @property --tw-divide-y-reverse {
2975
3019
  syntax: "*";
2976
3020
  inherits: false;
@@ -3340,6 +3384,7 @@
3340
3384
  --tw-rotate-z: initial;
3341
3385
  --tw-skew-x: initial;
3342
3386
  --tw-skew-y: initial;
3387
+ --tw-divide-x-reverse: 0;
3343
3388
  --tw-divide-y-reverse: 0;
3344
3389
  --tw-leading: initial;
3345
3390
  --tw-font-weight: initial;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fumadocs-ui",
3
- "version": "16.5.4",
3
+ "version": "16.6.1",
4
4
  "description": "The Radix UI version of Fumadocs UI",
5
5
  "keywords": [
6
6
  "Docs",
@@ -114,24 +114,28 @@
114
114
  "@radix-ui/react-tabs": "^1.1.13",
115
115
  "class-variance-authority": "^0.7.1",
116
116
  "lucide-react": "^0.563.0",
117
- "motion": "^12.33.0",
117
+ "motion": "^12.34.0",
118
118
  "next-themes": "^0.4.6",
119
119
  "react-medium-image-zoom": "^5.4.0",
120
120
  "react-remove-scroll": "^2.7.2",
121
+ "rehype-raw": "^7.0.0",
121
122
  "scroll-into-view-if-needed": "^3.1.0",
122
123
  "tailwind-merge": "^3.4.0",
124
+ "unist-util-visit": "^5.1.0",
123
125
  "@fumadocs/tailwind": "0.0.2"
124
126
  },
125
127
  "devDependencies": {
126
128
  "@tailwindcss/cli": "^4.1.18",
127
- "@types/node": "^25.2.1",
128
- "@types/react": "^19.2.13",
129
+ "@types/hast": "^3.0.4",
130
+ "@types/node": "^25.2.3",
131
+ "@types/react": "^19.2.14",
129
132
  "@types/react-dom": "^19.2.3",
130
133
  "tailwindcss": "^4.1.18",
131
134
  "tsdown": "^0.20.3",
135
+ "unified": "^11.0.5",
132
136
  "@fumadocs/cli": "1.2.4",
133
137
  "eslint-config-custom": "0.0.0",
134
- "fumadocs-core": "16.5.4",
138
+ "fumadocs-core": "16.6.1",
135
139
  "tsconfig": "0.0.0"
136
140
  },
137
141
  "peerDependencies": {
@@ -139,7 +143,7 @@
139
143
  "next": "16.x.x",
140
144
  "react": "^19.2.0",
141
145
  "react-dom": "^19.2.0",
142
- "fumadocs-core": "16.5.4"
146
+ "fumadocs-core": "16.6.1"
143
147
  },
144
148
  "peerDependenciesMeta": {
145
149
  "next": {