@fumadocs/base-ui 16.7.14 → 16.7.15

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.
@@ -24,6 +24,8 @@
24
24
  @source inline("--easing");
25
25
  @source inline("--fd-animated-height");
26
26
  @source inline("--fd-banner-height");
27
+ @source inline("--offset-distance");
28
+ @source inline("--opacity");
27
29
  @source inline("--padding-right");
28
30
  @source inline("--popup-height");
29
31
  @source inline("--popup-width");
@@ -32,6 +34,8 @@
32
34
  @source inline("--shiki-light-bg");
33
35
  @source inline("--spacing");
34
36
  @source inline("--t");
37
+ @source inline("--track-bottom");
38
+ @source inline("--track-top");
35
39
  @source inline("--transform-origin");
36
40
  @source inline("-circle");
37
41
  @source inline("-mb-px");
@@ -65,6 +69,7 @@
65
69
  @source inline("[&_svg]:size-5");
66
70
  @source inline("[&_svg]:size-full");
67
71
  @source inline("[&_svg]:text-fd-muted-foreground");
72
+ @source inline("[offset-distance:var(--offset-distance,0)]");
68
73
  @source inline("[scrollbar-width:none]");
69
74
  @source inline("a");
70
75
  @source inline("about");
@@ -160,7 +165,9 @@
160
165
  @source inline("bottom-1.5");
161
166
  @source inline("bound");
162
167
  @source inline("boundary");
168
+ @source inline("box");
163
169
  @source inline("box-border");
170
+ @source inline("boxRef");
164
171
  @source inline("breaking");
165
172
  @source inline("button");
166
173
  @source inline("buttonVariants");
@@ -715,7 +722,6 @@
715
722
  @source inline("of");
716
723
  @source inline("official");
717
724
  @source inline("offset");
718
- @source inline("offsetDistance");
719
725
  @source inline("offsetPath");
720
726
  @source inline("offsetTop");
721
727
  @source inline("on");
@@ -739,8 +745,10 @@
739
745
  @source inline("onSelectCallback");
740
746
  @source inline("onTagChange");
741
747
  @source inline("onTagChangeCallback");
748
+ @source inline("onUpdate");
742
749
  @source inline("onValueChange");
743
750
  @source inline("only");
751
+ @source inline("opacity-(--opacity,0)");
744
752
  @source inline("opacity-0");
745
753
  @source inline("open");
746
754
  @source inline("opening");
@@ -853,6 +861,7 @@
853
861
  @source inline("rainbowColors");
854
862
  @source inline("raw");
855
863
  @source inline("rawTree");
864
+ @source inline("re-exported");
856
865
  @source inline("react");
857
866
  @source inline("react-dom");
858
867
  @source inline("react-hooks/exhaustive-deps");
@@ -909,7 +918,6 @@
909
918
  @source inline("rtl:rotate-180");
910
919
  @source inline("rtl:rotate-90");
911
920
  @source inline("s");
912
- @source inline("scale");
913
921
  @source inline("scope");
914
922
  @source inline("scroll");
915
923
  @source inline("scroll-into-view-if-needed");
@@ -1012,6 +1020,7 @@
1012
1020
  @source inline("supposed");
1013
1021
  @source inline("sure");
1014
1022
  @source inline("svg");
1023
+ @source inline("svgRef");
1015
1024
  @source inline("switch");
1016
1025
  @source inline("system");
1017
1026
  @source inline("t");
@@ -1067,6 +1076,7 @@
1067
1076
  @source inline("title");
1068
1077
  @source inline("to");
1069
1078
  @source inline("toc");
1079
+ @source inline("tocInfo");
1070
1080
  @source inline("tocNoHeadings");
1071
1081
  @source inline("toolbar");
1072
1082
  @source inline("top");
@@ -1083,7 +1093,7 @@
1083
1093
  @source inline("transition-[clip-path]");
1084
1094
  @source inline("transition-[height,opacity]");
1085
1095
  @source inline("transition-[height]");
1086
- @source inline("transition-[offset-distance]");
1096
+ @source inline("transition-[opacity,offset-distance]");
1087
1097
  @source inline("transition-[opacity,transform,translate]");
1088
1098
  @source inline("transition-[opacity,transform,width,height,scale,translate]");
1089
1099
  @source inline("transition-all");
@@ -105,13 +105,9 @@ function TOCItems({ ref, className, thumbBox = true, ...props }) {
105
105
  observer.unobserve(container);
106
106
  };
107
107
  }, [onPrint]);
108
- return /* @__PURE__ */ jsxs(Fragment$1, { children: [svg && /* @__PURE__ */ jsxs("div", {
109
- className: "absolute top-0 inset-s-0",
110
- style: {
111
- width: svg.width,
112
- height: svg.height
113
- },
114
- children: [/* @__PURE__ */ jsx(ThumbTrack, { computed: svg }), thumbBox && /* @__PURE__ */ jsx(ThumbBox, { computed: svg })]
108
+ return /* @__PURE__ */ jsxs(Fragment$1, { children: [svg && /* @__PURE__ */ jsx(ThumbTrack, {
109
+ computed: svg,
110
+ thumbBox
115
111
  }), /* @__PURE__ */ jsx("div", {
116
112
  ref: mergeRefs(containerRef, ref),
117
113
  className: cn("flex flex-col", className),
@@ -125,48 +121,61 @@ function TOCEmpty() {
125
121
  children: text.tocNoHeadings
126
122
  });
127
123
  }
128
- function ThumbTrack({ computed }) {
129
- const items = Primitive.useItems();
130
- const startIdx = items.findIndex((item) => item.active);
131
- if (startIdx === -1) return;
132
- const endIdx = items.findLastIndex((item) => item.active);
133
- const top = `${computed.positions[startIdx][0]}px`;
134
- const bottom = `${computed.positions[endIdx][1]}px`;
135
- return /* @__PURE__ */ jsx("svg", {
136
- xmlns: "http://www.w3.org/2000/svg",
137
- viewBox: `0 0 ${computed.width} ${computed.height}`,
138
- className: "absolute transition-[clip-path]",
124
+ function ThumbTrack({ computed, thumbBox }) {
125
+ const svgRef = useRef(null);
126
+ const boxRef = useRef(null);
127
+ const previousRef = useRef(null);
128
+ const tocInfo = Primitive.useTOC();
129
+ const onUpdate = useCallback((items) => {
130
+ const svg = svgRef.current;
131
+ if (!svg) return;
132
+ const startIdx = items.findIndex((item) => item.active);
133
+ if (startIdx === -1) return;
134
+ const endIdx = items.findLastIndex((item) => item.active);
135
+ svg.style.setProperty("--track-top", `${computed.positions[startIdx][0]}px`);
136
+ svg.style.setProperty("--track-bottom", `${computed.positions[endIdx][1]}px`);
137
+ const box = boxRef.current;
138
+ if (box) {
139
+ let isUp = false;
140
+ if (previousRef.current) {
141
+ const prev = previousRef.current;
142
+ isUp = prev.startIdx > startIdx || prev.endIdx > endIdx || prev.startIdx === startIdx && prev.endIdx === endIdx && prev.isUp;
143
+ }
144
+ previousRef.current = {
145
+ startIdx,
146
+ endIdx,
147
+ isUp
148
+ };
149
+ box.style.setProperty("--offset-distance", isUp ? `${computed.itemLineLengths[startIdx][0]}px` : `${computed.itemLineLengths[endIdx][1]}px`);
150
+ box.style.setProperty("--opacity", items[isUp ? startIdx : endIdx].original._step !== void 0 ? "0" : "1");
151
+ }
152
+ }, [computed]);
153
+ Primitive.useTOCListener(onUpdate);
154
+ useEffect(() => {
155
+ onUpdate(tocInfo.get());
156
+ }, [onUpdate, tocInfo]);
157
+ return /* @__PURE__ */ jsxs("div", {
158
+ className: "absolute top-0 inset-s-0",
139
159
  style: {
140
160
  width: computed.width,
141
- height: computed.height,
142
- clipPath: `polygon(0 ${top}, 100% ${top}, 100% ${bottom}, 0 ${bottom})`
161
+ height: computed.height
143
162
  },
144
- children: computed.content
145
- });
146
- }
147
- function ThumbBox({ computed }) {
148
- const items = Primitive.useItems();
149
- const previousRef = useRef(null);
150
- const startIdx = items.findIndex((item) => item.active);
151
- if (startIdx === -1) return;
152
- const endIdx = items.findLastIndex((item) => item.active);
153
- let isUp = false;
154
- if (previousRef.current) {
155
- const prev = previousRef.current;
156
- isUp = prev.startIdx > startIdx || prev.endIdx > endIdx || prev.startIdx === startIdx && prev.endIdx === endIdx && prev.isUp;
157
- }
158
- previousRef.current = {
159
- startIdx,
160
- endIdx,
161
- isUp
162
- };
163
- return /* @__PURE__ */ jsx("div", {
164
- className: "absolute size-1 bg-fd-primary rounded-full transition-[offset-distance]",
165
- style: {
166
- offsetPath: `path("${computed.d}")`,
167
- offsetDistance: isUp ? computed.itemLineLengths[startIdx][0] : computed.itemLineLengths[endIdx][1],
168
- scale: items[isUp ? startIdx : endIdx].original._step !== void 0 ? "0" : "1"
169
- }
163
+ children: [/* @__PURE__ */ jsx("svg", {
164
+ ref: svgRef,
165
+ xmlns: "http://www.w3.org/2000/svg",
166
+ viewBox: `0 0 ${computed.width} ${computed.height}`,
167
+ className: "absolute transition-[clip-path]",
168
+ style: {
169
+ width: computed.width,
170
+ height: computed.height,
171
+ clipPath: `polygon(0 var(--track-top,0), 100% var(--track-top,0), 100% var(--track-bottom,0), 0 var(--track-bottom,0))`
172
+ },
173
+ children: computed.content
174
+ }), thumbBox && /* @__PURE__ */ jsx("div", {
175
+ ref: boxRef,
176
+ className: "absolute size-1 bg-fd-primary rounded-full [offset-distance:var(--offset-distance,0)] opacity-(--opacity,0) transition-[opacity,offset-distance]",
177
+ style: { offsetPath: `path("${computed.d}")` }
178
+ })]
170
179
  });
171
180
  }
172
181
  const a = 8;
@@ -53,15 +53,25 @@ function TOCItems({ ref, className, ...props }) {
53
53
  });
54
54
  }
55
55
  function TocThumb({ computed }) {
56
- const items = Primitive.useItems();
57
- const startIdx = items.findIndex((item) => item.active);
58
- if (startIdx === -1) return;
59
- const endIdx = items.findLastIndex((item) => item.active);
60
- const top = `${computed.positions[startIdx][0]}px`;
61
- const bottom = `${computed.positions[endIdx][1]}px`;
56
+ const ref = useRef(null);
57
+ const tocInfo = Primitive.useTOC();
58
+ const onUpdate = useCallback((items) => {
59
+ const element = ref.current;
60
+ if (!element) return;
61
+ const startIdx = items.findIndex((item) => item.active);
62
+ if (startIdx === -1) return;
63
+ const endIdx = items.findLastIndex((item) => item.active);
64
+ element.style.setProperty("--track-top", `${computed.positions[startIdx][0]}px`);
65
+ element.style.setProperty("--track-bottom", `${computed.positions[endIdx][1]}px`);
66
+ }, [computed]);
67
+ Primitive.useTOCListener(onUpdate);
68
+ useEffect(() => {
69
+ onUpdate(tocInfo.get());
70
+ }, [onUpdate, tocInfo]);
62
71
  return /* @__PURE__ */ jsx("div", {
72
+ ref,
63
73
  className: "absolute inset-y-0 inset-s-0 bg-fd-primary w-px transition-[clip-path]",
64
- style: { clipPath: `polygon(0 ${top}, 100% ${top}, 100% ${bottom}, 0 ${bottom})` }
74
+ style: { clipPath: `polygon(0 var(--track-top,0), 100% var(--track-top,0), 100% var(--track-bottom,0), 0 var(--track-bottom,0))` }
65
75
  });
66
76
  }
67
77
  function TOCEmpty() {
@@ -1,9 +1,9 @@
1
1
  import { SearchProviderProps } from "../contexts/search.js";
2
2
  import { DefaultSearchDialogProps } from "../components/dialog/search-default.js";
3
3
  import { I18nProviderProps } from "../contexts/i18n.js";
4
- import { ComponentPropsWithoutRef, ReactNode } from "react";
4
+ import { ReactNode } from "react";
5
5
  import * as _$react_jsx_runtime0 from "react/jsx-runtime";
6
- import { ThemeProvider } from "next-themes";
6
+ import { ThemeProviderProps, UseThemeProps, useTheme } from "next-themes";
7
7
 
8
8
  //#region src/provider/base.d.ts
9
9
  interface SearchOptions extends Omit<SearchProviderProps, 'children'> {
@@ -15,6 +15,14 @@ interface SearchOptions extends Omit<SearchProviderProps, 'children'> {
15
15
  */
16
16
  enabled?: boolean;
17
17
  }
18
+ interface ThemeOptions extends ThemeProviderProps {
19
+ /**
20
+ * Enable `next-themes`
21
+ *
22
+ * @defaultValue true
23
+ */
24
+ enabled?: boolean;
25
+ }
18
26
  interface RootProviderProps {
19
27
  /**
20
28
  * `dir` option for Base UI
@@ -25,16 +33,9 @@ interface RootProviderProps {
25
33
  */
26
34
  search?: Partial<SearchOptions>;
27
35
  /**
28
- * Customise options of `next-themes`
36
+ * Customise options for `next-themes`
29
37
  */
30
- theme?: Partial<ComponentPropsWithoutRef<typeof ThemeProvider>> & {
31
- /**
32
- * Enable `next-themes`
33
- *
34
- * @defaultValue true
35
- */
36
- enabled?: boolean;
37
- };
38
+ theme?: ThemeOptions;
38
39
  i18n?: Omit<I18nProviderProps, 'children'>;
39
40
  children?: ReactNode;
40
41
  }
@@ -46,4 +47,4 @@ declare function RootProvider({
46
47
  i18n
47
48
  }: RootProviderProps): _$react_jsx_runtime0.JSX.Element;
48
49
  //#endregion
49
- export { RootProvider, RootProviderProps };
50
+ export { RootProvider, RootProviderProps, type UseThemeProps, useTheme };
@@ -3,7 +3,7 @@ import { I18nProvider } from "../contexts/i18n.js";
3
3
  import { SearchProvider } from "../contexts/search.js";
4
4
  import { lazy } from "react";
5
5
  import { jsx } from "react/jsx-runtime";
6
- import { ThemeProvider } from "next-themes";
6
+ import { ThemeProvider, useTheme } from "next-themes";
7
7
  import { DirectionProvider } from "@base-ui/react/direction-provider";
8
8
  //#region src/provider/base.tsx
9
9
  const DefaultSearchDialog = lazy(() => import("../components/dialog/search-default.js"));
@@ -32,4 +32,4 @@ function RootProvider({ children, dir = "ltr", theme = {}, search, i18n }) {
32
32
  });
33
33
  }
34
34
  //#endregion
35
- export { RootProvider };
35
+ export { RootProvider, useTheme };
package/dist/style.css CHANGED
@@ -1814,6 +1814,9 @@
1814
1814
  .underline {
1815
1815
  text-decoration-line: underline;
1816
1816
  }
1817
+ .opacity-\(--opacity\,0\) {
1818
+ opacity: var(--opacity,0);
1819
+ }
1817
1820
  .opacity-0 {
1818
1821
  opacity: 0%;
1819
1822
  }
@@ -1885,8 +1888,8 @@
1885
1888
  transition-timing-function: var(--tw-ease, var(--default-transition-timing-function));
1886
1889
  transition-duration: var(--tw-duration, var(--default-transition-duration));
1887
1890
  }
1888
- .transition-\[offset-distance\] {
1889
- transition-property: offset-distance;
1891
+ .transition-\[opacity\,offset-distance\] {
1892
+ transition-property: opacity,offset-distance;
1890
1893
  transition-timing-function: var(--tw-ease, var(--default-transition-timing-function));
1891
1894
  transition-duration: var(--tw-duration, var(--default-transition-duration));
1892
1895
  }
@@ -2004,6 +2007,9 @@
2004
2007
  .\[grid-area\:toc\] {
2005
2008
  grid-area: toc;
2006
2009
  }
2010
+ .\[offset-distance\:var\(--offset-distance\,0\)\] {
2011
+ offset-distance: var(--offset-distance,0);
2012
+ }
2007
2013
  .\[scrollbar-width\:none\] {
2008
2014
  scrollbar-width: none;
2009
2015
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fumadocs/base-ui",
3
- "version": "16.7.14",
3
+ "version": "16.7.15",
4
4
  "description": "The Base UI version of Fumadocs UI",
5
5
  "keywords": [
6
6
  "Docs",
@@ -124,6 +124,7 @@
124
124
  "react-remove-scroll": "^2.7.2",
125
125
  "rehype-raw": "^7.0.0",
126
126
  "scroll-into-view-if-needed": "^3.1.0",
127
+ "shiki": "^4.0.2",
127
128
  "tailwind-merge": "^3.5.0",
128
129
  "unist-util-visit": "^5.1.0",
129
130
  "@fumadocs/tailwind": "0.0.5"
@@ -138,12 +139,11 @@
138
139
  "@types/react-dom": "^19.2.3",
139
140
  "fuma-cli": "^0.0.5",
140
141
  "react-medium-image-zoom": "^5.4.3",
141
- "shiki": "^4.0.2",
142
142
  "tailwindcss": "^4.2.2",
143
143
  "tsdown": "0.21.7",
144
144
  "unified": "^11.0.5",
145
145
  "@fumadocs/cli": "1.3.7",
146
- "fumadocs-core": "16.7.14",
146
+ "fumadocs-core": "16.7.15",
147
147
  "tsconfig": "0.0.0"
148
148
  },
149
149
  "peerDependencies": {
@@ -153,13 +153,9 @@
153
153
  "next": "16.x.x",
154
154
  "react": "^19.2.0",
155
155
  "react-dom": "^19.2.0",
156
- "shiki": "*",
157
- "fumadocs-core": "16.7.14"
156
+ "fumadocs-core": "16.7.15"
158
157
  },
159
158
  "peerDependenciesMeta": {
160
- "shiki": {
161
- "optional": true
162
- },
163
159
  "next": {
164
160
  "optional": true
165
161
  },