@fumadocs/base-ui 16.7.13 → 16.7.14

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.
@@ -5,7 +5,7 @@ import * as _$class_variance_authority_types0 from "class-variance-authority/typ
5
5
  declare const buttonVariants: (props?: ({
6
6
  variant?: "primary" | "outline" | "ghost" | "secondary" | null | undefined;
7
7
  color?: "primary" | "outline" | "ghost" | "secondary" | null | undefined;
8
- size?: "sm" | "icon" | "icon-sm" | "icon-xs" | null | undefined;
8
+ size?: "icon" | "sm" | "icon-sm" | "icon-xs" | null | undefined;
9
9
  } & _$class_variance_authority_types0.ClassProp) | undefined) => string;
10
10
  type ButtonProps = VariantProps<typeof buttonVariants>;
11
11
  //#endregion
@@ -4,7 +4,7 @@ import * as _$class_variance_authority_types0 from "class-variance-authority/typ
4
4
 
5
5
  //#region src/layouts/home/slots/header.d.ts
6
6
  declare const navItemVariants: (props?: ({
7
- variant?: "icon" | "button" | "main" | null | undefined;
7
+ variant?: "icon" | "main" | "button" | null | undefined;
8
8
  } & _$class_variance_authority_types0.ClassProp) | undefined) => string;
9
9
  declare function Header(props: ComponentProps<'header'>): _$react_jsx_runtime0.JSX.Element;
10
10
  //#endregion
@@ -0,0 +1,36 @@
1
+ import React from "react";
2
+
3
+ //#region ../../node_modules/.pnpm/react-medium-image-zoom@5.4.3_react-dom@19.2.5_react@19.2.5__react@19.2.5/node_modules/react-medium-image-zoom/dist/Controlled.d.ts
4
+ declare const enum ModalState {
5
+ LOADED = "LOADED",
6
+ LOADING = "LOADING",
7
+ UNLOADED = "UNLOADED",
8
+ UNLOADING = "UNLOADING"
9
+ }
10
+ interface ControlledProps {
11
+ a11yNameButtonUnzoom?: string;
12
+ a11yNameButtonZoom?: string;
13
+ canSwipeToUnzoom?: boolean;
14
+ children: React.ReactNode;
15
+ classDialog?: string;
16
+ IconUnzoom?: React.ElementType;
17
+ IconZoom?: React.ElementType;
18
+ isDisabled?: boolean;
19
+ isZoomed: boolean;
20
+ onZoomChange?: (value: boolean, data: {
21
+ event: React.SyntheticEvent | Event;
22
+ }) => void;
23
+ swipeToUnzoomThreshold?: number;
24
+ wrapElement?: 'div' | 'span';
25
+ ZoomContent?: (data: {
26
+ buttonUnzoom: React.ReactElement<HTMLButtonElement>;
27
+ img: React.ReactElement | null;
28
+ isZoomImgLoaded: boolean;
29
+ modalState: ModalState;
30
+ onUnzoom: (e: Event) => void;
31
+ }) => React.ReactElement;
32
+ zoomImg?: React.ImgHTMLAttributes<HTMLImageElement>;
33
+ zoomMargin?: number;
34
+ }
35
+ //#endregion
36
+ export { ControlledProps };
@@ -0,0 +1,435 @@
1
+ import { ICompress, IEnlarge } from "./icons.js";
2
+ import { adjustSvgIDs, getImgAlt, getImgSrc, getStyleGhost, getStyleModalImg, testDiv, testImg, testImgLoaded, testSvg } from "./utils.js";
3
+ import React from "react";
4
+ import ReactDOM from "react-dom";
5
+ //#region ../../node_modules/.pnpm/react-medium-image-zoom@5.4.3_react-dom@19.2.5_react@19.2.5__react@19.2.5/node_modules/react-medium-image-zoom/dist/Controlled.js
6
+ const IMAGE_QUERY = [
7
+ "img",
8
+ "svg",
9
+ "[role=\"img\"]",
10
+ "[data-zoom]"
11
+ ].map((x) => `${x}:not([aria-hidden="true"])`).join(",");
12
+ const defaultBodyAttrs = {
13
+ overflow: "",
14
+ width: ""
15
+ };
16
+ function getDialogContainer() {
17
+ const existing = document.querySelector("[data-rmiz-portal]");
18
+ if (existing != null) return existing;
19
+ const el = document.createElement("div");
20
+ el.setAttribute("data-rmiz-portal", "");
21
+ document.body.appendChild(el);
22
+ return el;
23
+ }
24
+ function handleDialogCancelStatic(e) {
25
+ e.preventDefault();
26
+ }
27
+ function Controlled(props) {
28
+ return React.createElement(ControlledBase, { ...props });
29
+ }
30
+ var ControlledBase = class extends React.Component {
31
+ constructor() {
32
+ super(...arguments);
33
+ this.state = {
34
+ id: "",
35
+ isZoomImgLoaded: false,
36
+ loadedImgEl: void 0,
37
+ modalState: "UNLOADED",
38
+ shouldRefresh: false,
39
+ styleGhost: {}
40
+ };
41
+ this.refContent = React.createRef();
42
+ this.refDialog = React.createRef();
43
+ this.refModalContent = React.createRef();
44
+ this.refModalImg = React.createRef();
45
+ this.refWrap = React.createRef();
46
+ this.imgEl = null;
47
+ this.isScaling = false;
48
+ this.prevBodyAttrs = defaultBodyAttrs;
49
+ this.styleModalImg = {};
50
+ this.handleModalStateChange = (prevModalState) => {
51
+ const { state: { modalState } } = this;
52
+ if (prevModalState !== "LOADING" && modalState === "LOADING") {
53
+ this.loadZoomImg();
54
+ window.addEventListener("resize", this.handleResize, { passive: true });
55
+ window.addEventListener("touchstart", this.handleTouchStart, { passive: true });
56
+ window.addEventListener("touchmove", this.handleTouchMove, { passive: true });
57
+ window.addEventListener("touchend", this.handleTouchEnd, { passive: true });
58
+ window.addEventListener("touchcancel", this.handleTouchCancel, { passive: true });
59
+ document.addEventListener("keydown", this.handleKeyDown, true);
60
+ } else if (prevModalState !== "LOADED" && modalState === "LOADED") window.addEventListener("wheel", this.handleWheel, { passive: true });
61
+ else if (prevModalState !== "UNLOADING" && modalState === "UNLOADING") {
62
+ this.ensureImgTransitionEnd();
63
+ window.removeEventListener("wheel", this.handleWheel);
64
+ window.removeEventListener("touchstart", this.handleTouchStart);
65
+ window.removeEventListener("touchmove", this.handleTouchMove);
66
+ window.removeEventListener("touchend", this.handleTouchEnd);
67
+ window.removeEventListener("touchcancel", this.handleTouchCancel);
68
+ document.removeEventListener("keydown", this.handleKeyDown, true);
69
+ } else if (prevModalState !== "UNLOADED" && modalState === "UNLOADED") {
70
+ this.bodyScrollEnable();
71
+ window.removeEventListener("resize", this.handleResize);
72
+ this.refModalImg.current?.removeEventListener("transitionend", this.handleImgTransitionEnd);
73
+ this.refDialog.current?.close();
74
+ }
75
+ };
76
+ this.setId = () => {
77
+ const gen4 = () => Math.random().toString(16).slice(-4);
78
+ this.setState({ id: gen4() + gen4() + gen4() });
79
+ };
80
+ this.setAndTrackImg = () => {
81
+ const { refContent: { current: contentEl } } = this;
82
+ if (contentEl == null) return;
83
+ this.imgEl = contentEl.querySelector(IMAGE_QUERY);
84
+ if (this.imgEl !== null) {
85
+ this.contentNotFoundChangeObserver?.disconnect();
86
+ this.imgEl.addEventListener("load", this.handleImgLoad);
87
+ this.imgEl.addEventListener("click", this.handleZoom);
88
+ if (this.state.loadedImgEl == null) this.handleImgLoad();
89
+ this.imgElResizeObserver = new ResizeObserver((entries) => {
90
+ const [entry] = entries;
91
+ if (entry?.target !== void 0) {
92
+ this.imgEl = entry.target;
93
+ this.setState({ styleGhost: getStyleGhost(this.imgEl) });
94
+ }
95
+ });
96
+ this.imgElResizeObserver.observe(this.imgEl);
97
+ if (this.contentChangeObserver == null) {
98
+ this.contentChangeObserver = new MutationObserver(() => {
99
+ this.setState({ styleGhost: getStyleGhost(this.imgEl) });
100
+ });
101
+ this.contentChangeObserver.observe(contentEl, {
102
+ attributes: true,
103
+ childList: true,
104
+ subtree: true
105
+ });
106
+ }
107
+ } else if (this.contentNotFoundChangeObserver == null) {
108
+ this.contentNotFoundChangeObserver = new MutationObserver(this.setAndTrackImg);
109
+ this.contentNotFoundChangeObserver.observe(contentEl, {
110
+ childList: true,
111
+ subtree: true
112
+ });
113
+ }
114
+ };
115
+ this.handleIfZoomChanged = (prevIsZoomed) => {
116
+ const { props: { isZoomed } } = this;
117
+ if (!prevIsZoomed && isZoomed) this.zoom();
118
+ else if (prevIsZoomed && !isZoomed) this.unzoom();
119
+ };
120
+ this.handleImgLoad = () => {
121
+ const imgSrc = getImgSrc(this.imgEl);
122
+ if (imgSrc == null || imgSrc === "") return;
123
+ const img = new Image();
124
+ const { imgEl } = this;
125
+ if (testImg(imgEl)) {
126
+ const { sizes, srcset, crossOrigin } = imgEl;
127
+ img.sizes = sizes;
128
+ img.srcset = srcset;
129
+ img.crossOrigin = crossOrigin;
130
+ }
131
+ img.src = imgSrc;
132
+ const setLoaded = () => {
133
+ this.setState({
134
+ loadedImgEl: img,
135
+ styleGhost: getStyleGhost(this.imgEl)
136
+ });
137
+ };
138
+ img.decode().then(setLoaded).catch(() => {
139
+ if (testImgLoaded(img)) {
140
+ setLoaded();
141
+ return;
142
+ }
143
+ img.onload = setLoaded;
144
+ });
145
+ };
146
+ this.handleZoom = (e) => {
147
+ if (this.props.isDisabled !== true && this.hasImage()) this.props.onZoomChange?.(true, { event: e });
148
+ };
149
+ this.handleUnzoom = (e) => {
150
+ if (this.props.isDisabled !== true) this.props.onZoomChange?.(false, { event: e });
151
+ };
152
+ this.handleBtnUnzoomClick = (e) => {
153
+ e.preventDefault();
154
+ e.stopPropagation();
155
+ this.handleUnzoom(e);
156
+ };
157
+ this.handleDialogClick = (e) => {
158
+ if (e.target === this.refModalContent.current || e.target === this.refModalImg.current) {
159
+ e.stopPropagation();
160
+ this.handleUnzoom(e);
161
+ }
162
+ };
163
+ this.handleDialogClose = (e) => {
164
+ e.stopPropagation();
165
+ this.handleUnzoom(e);
166
+ };
167
+ this.handleKeyDown = (e) => {
168
+ if (e.key === "Escape") {
169
+ e.preventDefault();
170
+ e.stopPropagation();
171
+ this.handleUnzoom(e);
172
+ }
173
+ };
174
+ this.handleWheel = (e) => {
175
+ if (e.ctrlKey) return;
176
+ e.stopPropagation();
177
+ queueMicrotask(() => {
178
+ this.handleUnzoom(e);
179
+ });
180
+ };
181
+ this.handleTouchStart = (e) => {
182
+ if (e.touches.length > 1) {
183
+ this.isScaling = true;
184
+ return;
185
+ }
186
+ const { changedTouches } = e;
187
+ const [changedTouch] = changedTouches;
188
+ if (changedTouches.length === 1 && changedTouch !== void 0) {
189
+ const { screenY } = changedTouch;
190
+ this.touchYStart = screenY;
191
+ }
192
+ };
193
+ this.handleTouchMove = (e) => {
194
+ const browserScale = window.visualViewport?.scale ?? 1;
195
+ const { changedTouches: changedTouchesMove } = e;
196
+ const [changedTouchMove] = changedTouchesMove;
197
+ if (this.props.canSwipeToUnzoom && !this.isScaling && browserScale <= 1 && this.touchYStart != null && changedTouchMove !== void 0) {
198
+ const { screenY } = changedTouchMove;
199
+ this.touchYEnd = screenY;
200
+ const max = Math.max(this.touchYStart, this.touchYEnd);
201
+ const min = Math.min(this.touchYStart, this.touchYEnd);
202
+ if (Math.abs(max - min) > this.props.swipeToUnzoomThreshold) {
203
+ this.touchYStart = void 0;
204
+ this.touchYEnd = void 0;
205
+ this.handleUnzoom(e);
206
+ }
207
+ }
208
+ };
209
+ this.handleTouchEnd = () => {
210
+ this.isScaling = false;
211
+ this.touchYStart = void 0;
212
+ this.touchYEnd = void 0;
213
+ };
214
+ this.handleTouchCancel = () => {
215
+ this.isScaling = false;
216
+ this.touchYStart = void 0;
217
+ this.touchYEnd = void 0;
218
+ };
219
+ this.handleResize = () => {
220
+ this.setState({ shouldRefresh: true });
221
+ };
222
+ this.hasImage = () => this.imgEl !== null && (this.state.loadedImgEl !== void 0 || testSvg(this.imgEl)) && window.getComputedStyle(this.imgEl).display !== "none";
223
+ this.zoom = () => {
224
+ this.bodyScrollDisable();
225
+ this.refDialog.current?.showModal();
226
+ this.refModalImg.current?.addEventListener("transitionend", this.handleImgTransitionEnd);
227
+ this.setState({ modalState: "LOADING" });
228
+ };
229
+ this.unzoom = () => {
230
+ this.setState({ modalState: "UNLOADING" });
231
+ };
232
+ this.handleImgTransitionEnd = () => {
233
+ clearTimeout(this.timeoutTransitionEnd);
234
+ if (this.state.modalState === "LOADING") this.setState({ modalState: "LOADED" });
235
+ else if (this.state.modalState === "UNLOADING") this.setState({
236
+ shouldRefresh: false,
237
+ modalState: "UNLOADED"
238
+ });
239
+ };
240
+ this.ensureImgTransitionEnd = () => {
241
+ if (this.refModalImg.current !== null) {
242
+ const { transitionDuration: td } = window.getComputedStyle(this.refModalImg.current);
243
+ const tdFloat = parseFloat(td);
244
+ if (tdFloat !== 0 && !Number.isNaN(tdFloat)) {
245
+ const tdMs = tdFloat * (td.endsWith("ms") ? 1 : 1e3) + 50;
246
+ this.timeoutTransitionEnd = setTimeout(this.handleImgTransitionEnd, tdMs);
247
+ }
248
+ }
249
+ };
250
+ this.bodyScrollDisable = () => {
251
+ this.prevBodyAttrs = {
252
+ overflow: document.body.style.overflow,
253
+ width: document.body.style.width
254
+ };
255
+ const { body: { clientWidth } } = document;
256
+ document.body.style.overflow = "hidden";
257
+ document.body.style.width = `${clientWidth}px`;
258
+ };
259
+ this.bodyScrollEnable = () => {
260
+ const { prevBodyAttrs: { overflow, width } } = this;
261
+ document.body.style.width = width;
262
+ document.body.style.overflow = overflow;
263
+ this.prevBodyAttrs = defaultBodyAttrs;
264
+ };
265
+ this.loadZoomImg = () => {
266
+ const { props: { zoomImg } } = this;
267
+ if (zoomImg == null) return;
268
+ const { src: zoomImgSrc } = zoomImg;
269
+ if (zoomImgSrc !== void 0 && zoomImgSrc !== "") {
270
+ const img = new Image();
271
+ img.sizes = zoomImg.sizes ?? "";
272
+ img.srcset = zoomImg.srcSet ?? "";
273
+ img.crossOrigin = zoomImg.crossOrigin ?? void 0;
274
+ img.src = zoomImgSrc;
275
+ const setLoaded = () => {
276
+ this.setState({ isZoomImgLoaded: true });
277
+ };
278
+ img.decode().then(setLoaded).catch(() => {
279
+ if (testImgLoaded(img)) {
280
+ setLoaded();
281
+ return;
282
+ }
283
+ img.onload = setLoaded;
284
+ });
285
+ }
286
+ };
287
+ this.UNSAFE_handleSvg = () => {
288
+ const { imgEl, refModalImg, styleModalImg } = this;
289
+ if (testSvg(imgEl)) {
290
+ const svgEl = imgEl.cloneNode(true);
291
+ adjustSvgIDs(svgEl);
292
+ svgEl.style.width = `${styleModalImg.width ?? 0}px`;
293
+ svgEl.style.height = `${styleModalImg.height ?? 0}px`;
294
+ svgEl.addEventListener("click", this.handleUnzoom);
295
+ refModalImg.current?.firstChild?.remove();
296
+ refModalImg.current?.appendChild(svgEl);
297
+ }
298
+ };
299
+ }
300
+ render() {
301
+ const { handleBtnUnzoomClick, handleDialogClick, handleDialogClose, handleUnzoom, handleZoom, imgEl, props: { a11yNameButtonUnzoom, a11yNameButtonZoom, children, classDialog, IconUnzoom, IconZoom, isZoomed, wrapElement: WrapElement, ZoomContent, zoomImg, zoomMargin }, refContent, refDialog, refModalContent, refModalImg, refWrap, state: { id, isZoomImgLoaded, loadedImgEl, modalState, shouldRefresh, styleGhost } } = this;
302
+ const idModal = `rmiz-modal-${id}`;
303
+ const idModalImg = `rmiz-modal-img-${id}`;
304
+ const isDiv = testDiv(imgEl);
305
+ const isImg = testImg(imgEl);
306
+ const isSvg = testSvg(imgEl);
307
+ const imgAlt = getImgAlt(imgEl);
308
+ const imgSrc = getImgSrc(imgEl);
309
+ const imgSizes = isImg ? imgEl.sizes : void 0;
310
+ const imgSrcSet = isImg ? imgEl.srcset : void 0;
311
+ const imgCrossOrigin = isImg ? imgEl.crossOrigin : void 0;
312
+ const hasZoomImg = zoomImg?.src !== void 0 && zoomImg.src !== "";
313
+ const hasImage = this.hasImage();
314
+ const labelBtnZoom = imgAlt !== void 0 && imgAlt !== "" ? `${a11yNameButtonZoom}: ${imgAlt}` : a11yNameButtonZoom;
315
+ const isModalActive = modalState === "LOADING" || modalState === "LOADED";
316
+ const dataContentState = hasImage ? "found" : "not-found";
317
+ const dataOverlayState = modalState === "UNLOADED" || modalState === "UNLOADING" ? "hidden" : "visible";
318
+ const styleContent = { visibility: modalState === "UNLOADED" ? "visible" : "hidden" };
319
+ this.styleModalImg = hasImage && imgEl !== null ? getStyleModalImg({
320
+ hasZoomImg,
321
+ imgSrc,
322
+ isSvg,
323
+ isZoomed: isZoomed && isModalActive,
324
+ loadedImgEl,
325
+ offset: zoomMargin,
326
+ shouldRefresh,
327
+ targetEl: imgEl
328
+ }) : {};
329
+ let modalContent = null;
330
+ if (hasImage) {
331
+ const modalImg = isImg || isDiv ? React.createElement("img", {
332
+ alt: imgAlt,
333
+ crossOrigin: imgCrossOrigin,
334
+ sizes: imgSizes,
335
+ src: imgSrc,
336
+ srcSet: imgSrcSet,
337
+ ...isZoomImgLoaded && modalState === "LOADED" ? zoomImg : {},
338
+ "data-rmiz-modal-img": "",
339
+ height: this.styleModalImg.height ?? void 0,
340
+ id: idModalImg,
341
+ ref: refModalImg,
342
+ style: this.styleModalImg,
343
+ width: this.styleModalImg.width ?? void 0
344
+ }) : isSvg ? React.createElement("div", {
345
+ "data-rmiz-modal-img": true,
346
+ ref: refModalImg,
347
+ style: this.styleModalImg
348
+ }) : null;
349
+ const modalBtnUnzoom = React.createElement("button", {
350
+ "aria-label": a11yNameButtonUnzoom,
351
+ "data-rmiz-btn-unzoom": "",
352
+ onClick: handleBtnUnzoomClick,
353
+ type: "button"
354
+ }, React.createElement(IconUnzoom, null));
355
+ modalContent = ZoomContent == null ? React.createElement(React.Fragment, null, modalImg, modalBtnUnzoom) : React.createElement(ZoomContent, {
356
+ buttonUnzoom: modalBtnUnzoom,
357
+ modalState,
358
+ img: modalImg,
359
+ isZoomImgLoaded,
360
+ onUnzoom: handleUnzoom
361
+ });
362
+ }
363
+ return React.createElement(WrapElement, {
364
+ "aria-owns": idModal,
365
+ "data-rmiz": "",
366
+ ref: refWrap
367
+ }, React.createElement(WrapElement, {
368
+ "data-rmiz-content": dataContentState,
369
+ ref: refContent,
370
+ style: styleContent
371
+ }, children), hasImage && React.createElement(WrapElement, {
372
+ "data-rmiz-ghost": "",
373
+ style: styleGhost
374
+ }, React.createElement("button", {
375
+ "aria-label": labelBtnZoom,
376
+ "data-rmiz-btn-zoom": "",
377
+ onClick: handleZoom,
378
+ type: "button"
379
+ }, React.createElement(IconZoom, null))), hasImage && ReactDOM.createPortal(React.createElement("dialog", {
380
+ "aria-labelledby": idModalImg,
381
+ "aria-modal": "true",
382
+ className: classDialog,
383
+ "data-rmiz-modal": "",
384
+ id: idModal,
385
+ onClick: handleDialogClick,
386
+ onClose: handleDialogClose,
387
+ onCancel: handleDialogCancelStatic,
388
+ ref: refDialog,
389
+ role: "dialog"
390
+ }, React.createElement("div", { "data-rmiz-modal-overlay": dataOverlayState }), React.createElement("div", {
391
+ "data-rmiz-modal-content": "",
392
+ ref: refModalContent
393
+ }, modalContent)), getDialogContainer()));
394
+ }
395
+ componentDidMount() {
396
+ this.setId();
397
+ this.setAndTrackImg();
398
+ this.handleImgLoad();
399
+ this.UNSAFE_handleSvg();
400
+ }
401
+ componentWillUnmount() {
402
+ if (this.state.modalState !== "UNLOADED") this.bodyScrollEnable();
403
+ this.contentChangeObserver?.disconnect();
404
+ this.contentNotFoundChangeObserver?.disconnect();
405
+ this.imgElResizeObserver?.disconnect();
406
+ this.imgEl?.removeEventListener("load", this.handleImgLoad);
407
+ this.imgEl?.removeEventListener("click", this.handleZoom);
408
+ this.refModalImg.current?.removeEventListener("transitionend", this.handleImgTransitionEnd);
409
+ window.removeEventListener("wheel", this.handleWheel);
410
+ window.removeEventListener("touchstart", this.handleTouchStart);
411
+ window.removeEventListener("touchmove", this.handleTouchMove);
412
+ window.removeEventListener("touchend", this.handleTouchEnd);
413
+ window.removeEventListener("touchcancel", this.handleTouchCancel);
414
+ window.removeEventListener("resize", this.handleResize);
415
+ document.removeEventListener("keydown", this.handleKeyDown, true);
416
+ }
417
+ componentDidUpdate(prevProps, prevState) {
418
+ this.handleModalStateChange(prevState.modalState);
419
+ this.UNSAFE_handleSvg();
420
+ this.handleIfZoomChanged(prevProps.isZoomed);
421
+ }
422
+ };
423
+ ControlledBase.defaultProps = {
424
+ a11yNameButtonUnzoom: "Minimize image",
425
+ a11yNameButtonZoom: "Expand image",
426
+ canSwipeToUnzoom: true,
427
+ IconUnzoom: ICompress,
428
+ IconZoom: IEnlarge,
429
+ isDisabled: false,
430
+ swipeToUnzoomThreshold: 10,
431
+ wrapElement: "div",
432
+ zoomMargin: 0
433
+ };
434
+ //#endregion
435
+ export { Controlled };
@@ -0,0 +1,7 @@
1
+ import { ControlledProps } from "./Controlled.js";
2
+ import React from "react";
3
+
4
+ //#region ../../node_modules/.pnpm/react-medium-image-zoom@5.4.3_react-dom@19.2.5_react@19.2.5__react@19.2.5/node_modules/react-medium-image-zoom/dist/Uncontrolled.d.ts
5
+ type UncontrolledProps = Omit<ControlledProps, 'isZoomed'>;
6
+ //#endregion
7
+ export { UncontrolledProps };
@@ -0,0 +1,17 @@
1
+ import { Controlled } from "./Controlled.js";
2
+ import React from "react";
3
+ //#region ../../node_modules/.pnpm/react-medium-image-zoom@5.4.3_react-dom@19.2.5_react@19.2.5__react@19.2.5/node_modules/react-medium-image-zoom/dist/Uncontrolled.js
4
+ function Uncontrolled({ onZoomChange, ...props }) {
5
+ const [isZoomed, setIsZoomed] = React.useState(false);
6
+ const handleZoomChange = React.useCallback((value, { event }) => {
7
+ setIsZoomed(value);
8
+ onZoomChange?.(value, { event });
9
+ }, [onZoomChange]);
10
+ return React.createElement(Controlled, {
11
+ ...props,
12
+ isZoomed,
13
+ onZoomChange: handleZoomChange
14
+ });
15
+ }
16
+ //#endregion
17
+ export { Uncontrolled };
@@ -0,0 +1,24 @@
1
+ import React from "react";
2
+ //#region ../../node_modules/.pnpm/react-medium-image-zoom@5.4.3_react-dom@19.2.5_react@19.2.5__react@19.2.5/node_modules/react-medium-image-zoom/dist/icons.js
3
+ function ICompress() {
4
+ return React.createElement("svg", {
5
+ "aria-hidden": "true",
6
+ "data-rmiz-btn-unzoom-icon": true,
7
+ fill: "currentColor",
8
+ focusable: "false",
9
+ viewBox: "0 0 16 16",
10
+ xmlns: "http://www.w3.org/2000/svg"
11
+ }, React.createElement("path", { d: "M 14.144531 1.148438 L 9 6.292969 L 9 3 L 8 3 L 8 8 L 13 8 L 13 7 L 9.707031 7 L 14.855469 1.851563 Z M 8 8 L 3 8 L 3 9 L 6.292969 9 L 1.148438 14.144531 L 1.851563 14.855469 L 7 9.707031 L 7 13 L 8 13 Z" }));
12
+ }
13
+ function IEnlarge() {
14
+ return React.createElement("svg", {
15
+ "aria-hidden": "true",
16
+ "data-rmiz-btn-zoom-icon": true,
17
+ fill: "currentColor",
18
+ focusable: "false",
19
+ viewBox: "0 0 16 16",
20
+ xmlns: "http://www.w3.org/2000/svg"
21
+ }, React.createElement("path", { d: "M 9 1 L 9 2 L 12.292969 2 L 2 12.292969 L 2 9 L 1 9 L 1 14 L 6 14 L 6 13 L 2.707031 13 L 13 2.707031 L 13 6 L 14 6 L 14 1 Z" }));
22
+ }
23
+ //#endregion
24
+ export { ICompress, IEnlarge };
@@ -0,0 +1,2 @@
1
+ import { ControlledProps } from "./Controlled.js";
2
+ import { UncontrolledProps } from "./Uncontrolled.js";
@@ -0,0 +1,372 @@
1
+ //#region ../../node_modules/.pnpm/react-medium-image-zoom@5.4.3_react-dom@19.2.5_react@19.2.5__react@19.2.5/node_modules/react-medium-image-zoom/dist/utils.js
2
+ function isElement(el) {
3
+ if (typeof Element === "undefined") return false;
4
+ return el instanceof Element;
5
+ }
6
+ const testElType = (type, el) => isElement(el) && el.tagName.toUpperCase() === type;
7
+ const testDiv = (el) => testElType("DIV", el) || testElType("SPAN", el);
8
+ const testImg = (el) => testElType("IMG", el);
9
+ const testImgLoaded = (el) => el.complete && el.naturalHeight !== 0;
10
+ const testSvg = (el) => testElType("SVG", el);
11
+ const getScaleToWindow = ({ height, offset, width }) => Math.min((window.innerWidth - offset * 2) / width, (window.innerHeight - offset * 2) / height);
12
+ const getScaleToWindowMax = ({ containerHeight, containerWidth, offset, targetHeight, targetWidth }) => {
13
+ const scale = getScaleToWindow({
14
+ height: targetHeight,
15
+ offset,
16
+ width: targetWidth
17
+ });
18
+ const ratio = targetWidth > targetHeight ? targetWidth / containerWidth : targetHeight / containerHeight;
19
+ return scale > 1 ? ratio : scale * ratio;
20
+ };
21
+ const getScale = ({ containerHeight, containerWidth, hasScalableSrc, offset, targetHeight, targetWidth }) => {
22
+ if (containerHeight === 0 || containerWidth === 0) return 1;
23
+ return !hasScalableSrc && targetHeight !== 0 && targetWidth !== 0 ? getScaleToWindowMax({
24
+ containerHeight,
25
+ containerWidth,
26
+ offset,
27
+ targetHeight,
28
+ targetWidth
29
+ }) : getScaleToWindow({
30
+ height: containerHeight,
31
+ offset,
32
+ width: containerWidth
33
+ });
34
+ };
35
+ const URL_REGEX = /url(?:\(['"]?)(?<url>.*?)(?:['"]?\))/;
36
+ const getImgSrc = (imgEl) => {
37
+ if (imgEl !== null) {
38
+ if (testImg(imgEl)) return imgEl.currentSrc === "" ? void 0 : imgEl.currentSrc;
39
+ else if (testDiv(imgEl)) {
40
+ const { backgroundImage: bgImg } = window.getComputedStyle(imgEl);
41
+ if (bgImg !== "") return URL_REGEX.exec(bgImg)?.[1];
42
+ }
43
+ }
44
+ };
45
+ const getImgAlt = (imgEl) => {
46
+ if (imgEl !== null) if (testImg(imgEl)) return imgEl.alt;
47
+ else return imgEl.getAttribute("aria-label") ?? void 0;
48
+ };
49
+ const getImgRegularStyle = ({ containerHeight, containerLeft, containerTop, containerWidth, hasScalableSrc, offset, targetHeight, targetWidth }) => {
50
+ const scale = getScale({
51
+ containerHeight,
52
+ containerWidth,
53
+ hasScalableSrc,
54
+ offset,
55
+ targetHeight,
56
+ targetWidth
57
+ });
58
+ return {
59
+ top: containerTop,
60
+ left: containerLeft,
61
+ width: containerWidth * scale,
62
+ height: containerHeight * scale,
63
+ transform: `translate(0,0) scale(${1 / scale})`
64
+ };
65
+ };
66
+ const parsePosition = ({ position, relativeNum }) => {
67
+ const positionNum = parseFloat(position);
68
+ return position.endsWith("%") ? relativeNum * positionNum / 100 : positionNum;
69
+ };
70
+ const getImgObjectFitStyle = ({ containerHeight, containerLeft, containerTop, containerWidth, hasScalableSrc, objectFit: objectFitParam, objectPosition, offset, targetHeight, targetWidth }) => {
71
+ let resolvedObjectFit = objectFitParam;
72
+ if (resolvedObjectFit === "scale-down") if (targetWidth <= containerWidth && targetHeight <= containerHeight) resolvedObjectFit = "none";
73
+ else resolvedObjectFit = "contain";
74
+ if (resolvedObjectFit === "cover" || resolvedObjectFit === "contain") {
75
+ const widthRatio = containerWidth / targetWidth;
76
+ const heightRatio = containerHeight / targetHeight;
77
+ const ratio = resolvedObjectFit === "cover" ? Math.max(widthRatio, heightRatio) : Math.min(widthRatio, heightRatio);
78
+ const [posLeft = "50%", posTop = "50%"] = objectPosition.split(" ");
79
+ const posX = parsePosition({
80
+ position: posLeft,
81
+ relativeNum: containerWidth - targetWidth * ratio
82
+ });
83
+ const posY = parsePosition({
84
+ position: posTop,
85
+ relativeNum: containerHeight - targetHeight * ratio
86
+ });
87
+ const scale = getScale({
88
+ containerHeight: targetHeight * ratio,
89
+ containerWidth: targetWidth * ratio,
90
+ hasScalableSrc,
91
+ offset,
92
+ targetHeight,
93
+ targetWidth
94
+ });
95
+ return {
96
+ top: containerTop + posY,
97
+ left: containerLeft + posX,
98
+ width: targetWidth * ratio * scale,
99
+ height: targetHeight * ratio * scale,
100
+ transform: `translate(0,0) scale(${1 / scale})`
101
+ };
102
+ } else if (resolvedObjectFit === "none") {
103
+ const [posLeft = "50%", posTop = "50%"] = objectPosition.split(" ");
104
+ const posX = parsePosition({
105
+ position: posLeft,
106
+ relativeNum: containerWidth - targetWidth
107
+ });
108
+ const posY = parsePosition({
109
+ position: posTop,
110
+ relativeNum: containerHeight - targetHeight
111
+ });
112
+ const scale = getScale({
113
+ containerHeight: targetHeight,
114
+ containerWidth: targetWidth,
115
+ hasScalableSrc,
116
+ offset,
117
+ targetHeight,
118
+ targetWidth
119
+ });
120
+ return {
121
+ top: containerTop + posY,
122
+ left: containerLeft + posX,
123
+ width: targetWidth * scale,
124
+ height: targetHeight * scale,
125
+ transform: `translate(0,0) scale(${1 / scale})`
126
+ };
127
+ } else if (resolvedObjectFit === "fill") {
128
+ const widthRatio = containerWidth / targetWidth;
129
+ const heightRatio = containerHeight / targetHeight;
130
+ const ratio = Math.max(widthRatio, heightRatio);
131
+ const scale = getScale({
132
+ containerHeight: targetHeight * ratio,
133
+ containerWidth: targetWidth * ratio,
134
+ hasScalableSrc,
135
+ offset,
136
+ targetHeight,
137
+ targetWidth
138
+ });
139
+ return {
140
+ width: containerWidth * scale,
141
+ height: containerHeight * scale,
142
+ transform: `translate(0,0) scale(${1 / scale})`
143
+ };
144
+ } else return {};
145
+ };
146
+ const getDivImgStyle = ({ backgroundPosition, backgroundSize, containerHeight, containerLeft, containerTop, containerWidth, hasScalableSrc, offset, targetHeight, targetWidth }) => {
147
+ if (backgroundSize === "cover" || backgroundSize === "contain") {
148
+ const widthRatio = containerWidth / targetWidth;
149
+ const heightRatio = containerHeight / targetHeight;
150
+ const ratio = backgroundSize === "cover" ? Math.max(widthRatio, heightRatio) : Math.min(widthRatio, heightRatio);
151
+ const [posLeft = "50%", posTop = "50%"] = backgroundPosition.split(" ");
152
+ const posX = parsePosition({
153
+ position: posLeft,
154
+ relativeNum: containerWidth - targetWidth * ratio
155
+ });
156
+ const posY = parsePosition({
157
+ position: posTop,
158
+ relativeNum: containerHeight - targetHeight * ratio
159
+ });
160
+ const scale = getScale({
161
+ containerHeight: targetHeight * ratio,
162
+ containerWidth: targetWidth * ratio,
163
+ hasScalableSrc,
164
+ offset,
165
+ targetHeight,
166
+ targetWidth
167
+ });
168
+ return {
169
+ top: containerTop + posY,
170
+ left: containerLeft + posX,
171
+ width: targetWidth * ratio * scale,
172
+ height: targetHeight * ratio * scale,
173
+ transform: `translate(0,0) scale(${1 / scale})`
174
+ };
175
+ } else if (backgroundSize === "auto") {
176
+ const [posLeft = "50%", posTop = "50%"] = backgroundPosition.split(" ");
177
+ const posX = parsePosition({
178
+ position: posLeft,
179
+ relativeNum: containerWidth - targetWidth
180
+ });
181
+ const posY = parsePosition({
182
+ position: posTop,
183
+ relativeNum: containerHeight - targetHeight
184
+ });
185
+ const scale = getScale({
186
+ containerHeight: targetHeight,
187
+ containerWidth: targetWidth,
188
+ hasScalableSrc,
189
+ offset,
190
+ targetHeight,
191
+ targetWidth
192
+ });
193
+ return {
194
+ top: containerTop + posY,
195
+ left: containerLeft + posX,
196
+ width: targetWidth * scale,
197
+ height: targetHeight * scale,
198
+ transform: `translate(0,0) scale(${1 / scale})`
199
+ };
200
+ } else {
201
+ const [sizeW = "50%", sizeH = "50%"] = backgroundSize.split(" ");
202
+ const sizeWidth = parsePosition({
203
+ position: sizeW,
204
+ relativeNum: containerWidth
205
+ });
206
+ const sizeHeight = parsePosition({
207
+ position: sizeH,
208
+ relativeNum: containerHeight
209
+ });
210
+ const widthRatio = sizeWidth / targetWidth;
211
+ const heightRatio = sizeHeight / targetHeight;
212
+ const ratio = Math.min(widthRatio, heightRatio);
213
+ const [posLeft = "50%", posTop = "50%"] = backgroundPosition.split(" ");
214
+ const posX = parsePosition({
215
+ position: posLeft,
216
+ relativeNum: containerWidth - targetWidth * ratio
217
+ });
218
+ const posY = parsePosition({
219
+ position: posTop,
220
+ relativeNum: containerHeight - targetHeight * ratio
221
+ });
222
+ const scale = getScale({
223
+ containerHeight: targetHeight * ratio,
224
+ containerWidth: targetWidth * ratio,
225
+ hasScalableSrc,
226
+ offset,
227
+ targetHeight,
228
+ targetWidth
229
+ });
230
+ return {
231
+ top: containerTop + posY,
232
+ left: containerLeft + posX,
233
+ width: targetWidth * ratio * scale,
234
+ height: targetHeight * ratio * scale,
235
+ transform: `translate(0,0) scale(${1 / scale})`
236
+ };
237
+ }
238
+ };
239
+ const SRC_SVG_REGEX = /\.svg$/i;
240
+ const getStyleModalImg = ({ hasZoomImg, imgSrc, isSvg, isZoomed, loadedImgEl, offset, shouldRefresh, targetEl }) => {
241
+ const hasScalableSrc = isSvg || imgSrc?.slice(0, 18) === "data:image/svg+xml" || hasZoomImg || imgSrc !== void 0 && SRC_SVG_REGEX.test(imgSrc);
242
+ const imgRect = targetEl.getBoundingClientRect();
243
+ const targetElComputedStyle = window.getComputedStyle(targetEl);
244
+ const isDivImg = loadedImgEl != null && testDiv(targetEl);
245
+ const isImgObjectFit = loadedImgEl != null && !isDivImg;
246
+ const targetHeight = loadedImgEl != null && loadedImgEl.naturalHeight !== 0 ? loadedImgEl.naturalHeight : imgRect.height;
247
+ const targetWidth = loadedImgEl != null && loadedImgEl.naturalWidth !== 0 ? loadedImgEl.naturalWidth : imgRect.width;
248
+ const styleImgRegular = getImgRegularStyle({
249
+ containerHeight: imgRect.height,
250
+ containerLeft: imgRect.left,
251
+ containerTop: imgRect.top,
252
+ containerWidth: imgRect.width,
253
+ hasScalableSrc,
254
+ offset,
255
+ targetHeight,
256
+ targetWidth
257
+ });
258
+ const styleImgObjectFit = isImgObjectFit ? getImgObjectFitStyle({
259
+ containerHeight: imgRect.height,
260
+ containerLeft: imgRect.left,
261
+ containerTop: imgRect.top,
262
+ containerWidth: imgRect.width,
263
+ hasScalableSrc,
264
+ objectFit: targetElComputedStyle.objectFit,
265
+ objectPosition: targetElComputedStyle.objectPosition,
266
+ offset,
267
+ targetHeight,
268
+ targetWidth
269
+ }) : void 0;
270
+ const styleDivImg = isDivImg ? getDivImgStyle({
271
+ backgroundPosition: targetElComputedStyle.backgroundPosition,
272
+ backgroundSize: targetElComputedStyle.backgroundSize,
273
+ containerHeight: imgRect.height,
274
+ containerLeft: imgRect.left,
275
+ containerTop: imgRect.top,
276
+ containerWidth: imgRect.width,
277
+ hasScalableSrc,
278
+ offset,
279
+ targetHeight,
280
+ targetWidth
281
+ }) : void 0;
282
+ const style = {
283
+ ...styleImgRegular,
284
+ ...styleImgObjectFit,
285
+ ...styleDivImg
286
+ };
287
+ if (isZoomed) {
288
+ const viewportX = window.innerWidth / 2;
289
+ const viewportY = window.innerHeight / 2;
290
+ const childCenterX = parseFloat(String(style.left ?? 0)) + parseFloat(String(style.width ?? 0)) / 2;
291
+ const childCenterY = parseFloat(String(style.top ?? 0)) + parseFloat(String(style.height ?? 0)) / 2;
292
+ const translateX = viewportX - childCenterX;
293
+ const translateY = viewportY - childCenterY;
294
+ if (shouldRefresh) style.transitionDuration = "0.01ms";
295
+ style.transform = `translate(${translateX}px,${translateY}px) scale(1)`;
296
+ }
297
+ return style;
298
+ };
299
+ const getStyleGhost = (imgEl) => {
300
+ if (imgEl == null) return {};
301
+ if (testSvg(imgEl)) {
302
+ const { parentElement: parentEl } = imgEl;
303
+ const rect = imgEl.getBoundingClientRect();
304
+ if (parentEl == null) return {
305
+ height: rect.height,
306
+ left: rect.left,
307
+ width: rect.width,
308
+ top: rect.top
309
+ };
310
+ else {
311
+ const parentRect = parentEl.getBoundingClientRect();
312
+ return {
313
+ height: rect.height,
314
+ left: parentRect.left - rect.left,
315
+ top: parentRect.top - rect.top,
316
+ width: rect.width
317
+ };
318
+ }
319
+ } else return {
320
+ height: imgEl.offsetHeight,
321
+ left: imgEl.offsetLeft,
322
+ width: imgEl.offsetWidth,
323
+ top: imgEl.offsetTop
324
+ };
325
+ };
326
+ const adjustSvgIDs = (svgEl) => {
327
+ const newIdSuffix = "-zoom";
328
+ const attrs = [
329
+ "clip-path",
330
+ "fill",
331
+ "mask",
332
+ "marker-start",
333
+ "marker-mid",
334
+ "marker-end"
335
+ ];
336
+ const idMap = /* @__PURE__ */ new Map();
337
+ if (svgEl.hasAttribute("id")) {
338
+ const { id: oldId } = svgEl;
339
+ const newId = oldId + newIdSuffix;
340
+ idMap.set(oldId, newId);
341
+ const svgNode = svgEl;
342
+ svgNode.id = newId;
343
+ }
344
+ svgEl.querySelectorAll("[id]").forEach((el) => {
345
+ const { id: oldId } = el;
346
+ const newId = oldId + newIdSuffix;
347
+ idMap.set(oldId, newId);
348
+ const node = el;
349
+ node.id = newId;
350
+ });
351
+ idMap.forEach((newId, oldId) => {
352
+ const urlOldID = `url(#${oldId})`;
353
+ const urlNewID = `url(#${newId})`;
354
+ const attrsQuery = attrs.map((attr) => `[${attr}="${urlOldID}"]`).join(", ");
355
+ svgEl.querySelectorAll(attrsQuery).forEach((usedEl) => {
356
+ attrs.forEach((attr) => {
357
+ if (usedEl.getAttribute(attr) === urlOldID) usedEl.setAttribute(attr, urlNewID);
358
+ });
359
+ });
360
+ });
361
+ svgEl.querySelectorAll("style").forEach((styleEl) => {
362
+ idMap.forEach((newId, oldId) => {
363
+ const { textContent } = styleEl;
364
+ if (textContent !== "") {
365
+ const styleNode = styleEl;
366
+ styleNode.textContent = textContent.replaceAll(`#${oldId}`, `#${newId}`);
367
+ }
368
+ });
369
+ });
370
+ };
371
+ //#endregion
372
+ export { adjustSvgIDs, getImgAlt, getImgSrc, getStyleGhost, getStyleModalImg, testDiv, testImg, testImgLoaded, testSvg };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fumadocs/base-ui",
3
- "version": "16.7.13",
3
+ "version": "16.7.14",
4
4
  "description": "The Base UI version of Fumadocs UI",
5
5
  "keywords": [
6
6
  "Docs",
@@ -11,8 +11,8 @@
11
11
  "author": "Fuma Nama",
12
12
  "repository": "github:fuma-nama/fumadocs",
13
13
  "files": [
14
- "css/*",
15
- "dist/*"
14
+ "css",
15
+ "dist"
16
16
  ],
17
17
  "type": "module",
18
18
  "exports": {
@@ -126,7 +126,7 @@
126
126
  "scroll-into-view-if-needed": "^3.1.0",
127
127
  "tailwind-merge": "^3.5.0",
128
128
  "unist-util-visit": "^5.1.0",
129
- "@fumadocs/tailwind": "0.0.4"
129
+ "@fumadocs/tailwind": "0.0.5"
130
130
  },
131
131
  "devDependencies": {
132
132
  "@tailwindcss/cli": "^4.2.2",
@@ -142,8 +142,8 @@
142
142
  "tailwindcss": "^4.2.2",
143
143
  "tsdown": "0.21.7",
144
144
  "unified": "^11.0.5",
145
- "@fumadocs/cli": "1.3.6",
146
- "fumadocs-core": "16.7.13",
145
+ "@fumadocs/cli": "1.3.7",
146
+ "fumadocs-core": "16.7.14",
147
147
  "tsconfig": "0.0.0"
148
148
  },
149
149
  "peerDependencies": {
@@ -154,7 +154,7 @@
154
154
  "react": "^19.2.0",
155
155
  "react-dom": "^19.2.0",
156
156
  "shiki": "*",
157
- "fumadocs-core": "16.7.13"
157
+ "fumadocs-core": "16.7.14"
158
158
  },
159
159
  "peerDependenciesMeta": {
160
160
  "shiki": {