@lobehub/ui 5.42.7 → 5.42.8
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/README.md +10 -7
- package/es/Image/viewer/ImageViewer.mjs +73 -79
- package/es/Image/viewer/ImageViewer.mjs.map +1 -1
- package/es/base-ui/DraggablePanel/atoms.mjs +5 -3
- package/es/base-ui/DraggablePanel/atoms.mjs.map +1 -1
- package/es/base-ui/Input/style.d.mts +1 -1
- package/es/base-ui/Text/style.d.mts +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -119,31 +119,34 @@ import hotkeyMessages from '@lobehub/ui/i18n/resources/hotkey';
|
|
|
119
119
|
|
|
120
120
|
### ConfigProvider (Motion)
|
|
121
121
|
|
|
122
|
-
You must pass a motion component via `ConfigProvider
|
|
123
|
-
If your app uses `LazyMotion`, pass `m`:
|
|
122
|
+
You must pass a motion component via `ConfigProvider`, and `ConfigProvider` must wrap `ThemeProvider` — never the other way round. `ThemeProvider` renders the antd `App` that hosts the static `notification` / `modal` holders and reads the CDN config for its webfonts, so both need the contexts from `ConfigProvider` above them.
|
|
124
123
|
|
|
125
124
|
```tsx
|
|
126
|
-
import { ConfigProvider } from '@lobehub/ui';
|
|
125
|
+
import { ConfigProvider, ThemeProvider } from '@lobehub/ui';
|
|
127
126
|
import { motion } from 'motion/react';
|
|
128
127
|
|
|
129
128
|
export default () => (
|
|
130
129
|
<ConfigProvider motion={motion}>
|
|
131
|
-
<
|
|
130
|
+
<ThemeProvider>
|
|
131
|
+
<App />
|
|
132
|
+
</ThemeProvider>
|
|
132
133
|
</ConfigProvider>
|
|
133
134
|
);
|
|
134
135
|
```
|
|
135
136
|
|
|
136
|
-
If your app uses `LazyMotion`:
|
|
137
|
+
If your app uses `LazyMotion`, pass `m`:
|
|
137
138
|
|
|
138
139
|
```tsx
|
|
139
|
-
import { ConfigProvider } from '@lobehub/ui';
|
|
140
|
+
import { ConfigProvider, ThemeProvider } from '@lobehub/ui';
|
|
140
141
|
import { LazyMotion, domAnimation } from 'motion/react';
|
|
141
142
|
import * as m from 'motion/react-m';
|
|
142
143
|
|
|
143
144
|
export default () => (
|
|
144
145
|
<LazyMotion features={domAnimation}>
|
|
145
146
|
<ConfigProvider motion={m}>
|
|
146
|
-
<
|
|
147
|
+
<ThemeProvider>
|
|
148
|
+
<App />
|
|
149
|
+
</ThemeProvider>
|
|
147
150
|
</ConfigProvider>
|
|
148
151
|
</LazyMotion>
|
|
149
152
|
);
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import { MotionComponent } from "../../MotionProvider/index.mjs";
|
|
3
2
|
import { useAppElement } from "../../ThemeProvider/AppElementContext.mjs";
|
|
4
3
|
import { useLayerZIndex } from "../../base-ui/zIndex/useLayerZIndex.mjs";
|
|
5
4
|
import { styles } from "../style.mjs";
|
|
@@ -13,9 +12,8 @@ import { readNatural, useGalleryNav } from "./useGalleryNav.mjs";
|
|
|
13
12
|
import { useRefitTransition } from "./useRefitTransition.mjs";
|
|
14
13
|
import { useZoomPan } from "./useZoomPan.mjs";
|
|
15
14
|
import ViewerChrome from "./ViewerChrome.mjs";
|
|
16
|
-
import { memo,
|
|
15
|
+
import { memo, useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
17
16
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
18
|
-
import { motion } from "motion/react";
|
|
19
17
|
import { useMergeRefs } from "react-merge-refs";
|
|
20
18
|
import { Dialog } from "@base-ui/react/dialog";
|
|
21
19
|
//#region src/Image/viewer/ImageViewer.tsx
|
|
@@ -27,8 +25,7 @@ const prefersReducedMotion = () => window.matchMedia?.("(prefers-reduced-motion:
|
|
|
27
25
|
const ImageViewer = memo(({ entries, index, openerFocusElement, token }) => {
|
|
28
26
|
const openerEntry = entries[index];
|
|
29
27
|
const appElement = useAppElement();
|
|
30
|
-
const
|
|
31
|
-
const [animated] = useState(() => !!motionComponent && !prefersReducedMotion());
|
|
28
|
+
const [animated] = useState(() => !prefersReducedMotion());
|
|
32
29
|
const { ref: layerRef, zIndex } = useLayerZIndex("modal");
|
|
33
30
|
const [currentIndex, setCurrentIndex] = useState(index);
|
|
34
31
|
const currentEntry = entries[currentIndex];
|
|
@@ -205,80 +202,77 @@ const ImageViewer = memo(({ entries, index, openerFocusElement, token }) => {
|
|
|
205
202
|
useEffect(() => () => {
|
|
206
203
|
if (!openerEntry.element.isConnected) endClosePreview(token);
|
|
207
204
|
}, [openerEntry, token]);
|
|
208
|
-
return /* @__PURE__ */ jsx(
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
children:
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
/* @__PURE__ */ jsx(ToastHost, { root: appElement ?? void 0 })
|
|
280
|
-
]
|
|
281
|
-
})
|
|
205
|
+
return /* @__PURE__ */ jsx(Dialog.Root, {
|
|
206
|
+
modal: true,
|
|
207
|
+
open: true,
|
|
208
|
+
onOpenChange: handleDialogOpenChange,
|
|
209
|
+
children: /* @__PURE__ */ jsxs(Dialog.Portal, {
|
|
210
|
+
container: appElement ?? void 0,
|
|
211
|
+
children: [
|
|
212
|
+
/* @__PURE__ */ jsx(Dialog.Backdrop, {
|
|
213
|
+
forceRender: true,
|
|
214
|
+
className: styles.viewerBackdrop,
|
|
215
|
+
ref: backdropRef,
|
|
216
|
+
style: zIndex === void 0 ? void 0 : { zIndex },
|
|
217
|
+
onClick: gestures.onSurfaceClick
|
|
218
|
+
}),
|
|
219
|
+
/* @__PURE__ */ jsxs(Dialog.Popup, {
|
|
220
|
+
"aria-label": currentEntry.element.alt || void 0,
|
|
221
|
+
className: styles.viewerPopup,
|
|
222
|
+
finalFocus,
|
|
223
|
+
initialFocus: popupNodeRef,
|
|
224
|
+
ref: popupRef,
|
|
225
|
+
style: zIndex === void 0 ? void 0 : { zIndex: zIndex + 1 },
|
|
226
|
+
tabIndex: -1,
|
|
227
|
+
onClick: gestures.onSurfaceClick,
|
|
228
|
+
onPointerCancel: gestures.onPointerFinish,
|
|
229
|
+
onPointerDown: gestures.onPointerDown,
|
|
230
|
+
onPointerMove: gestures.onPointerMove,
|
|
231
|
+
onPointerUp: gestures.onPointerFinish,
|
|
232
|
+
children: [/* @__PURE__ */ jsx("img", {
|
|
233
|
+
alt: currentEntry.element.alt,
|
|
234
|
+
className: styles.viewerImage,
|
|
235
|
+
ref: imageRef,
|
|
236
|
+
src: source,
|
|
237
|
+
style: {
|
|
238
|
+
cursor: gestures.cursor,
|
|
239
|
+
height: imageRect.height,
|
|
240
|
+
left: imageRect.x,
|
|
241
|
+
top: imageRect.y,
|
|
242
|
+
width: imageRect.width
|
|
243
|
+
},
|
|
244
|
+
onClick: gestures.onImageClick,
|
|
245
|
+
onDoubleClick: gestures.onImageDoubleClick,
|
|
246
|
+
onLoad: handleLoad
|
|
247
|
+
}), /* @__PURE__ */ jsx(ViewerChrome, {
|
|
248
|
+
canZoomIn,
|
|
249
|
+
canZoomOut,
|
|
250
|
+
chromeRef,
|
|
251
|
+
current: currentIndex,
|
|
252
|
+
fitRect,
|
|
253
|
+
flipHorizontal,
|
|
254
|
+
flipVertical,
|
|
255
|
+
hasNext,
|
|
256
|
+
hasPrev,
|
|
257
|
+
natural,
|
|
258
|
+
next,
|
|
259
|
+
prev,
|
|
260
|
+
rotateLeft,
|
|
261
|
+
rotateRight,
|
|
262
|
+
rotation,
|
|
263
|
+
scale,
|
|
264
|
+
source,
|
|
265
|
+
toggleActualSize,
|
|
266
|
+
toolbarAddon: currentEntry.options.toolbarAddon,
|
|
267
|
+
total: entries.length,
|
|
268
|
+
zoomIn,
|
|
269
|
+
zoomOut,
|
|
270
|
+
onClose: handleClose,
|
|
271
|
+
onDownload: currentEntry.options.onDownload
|
|
272
|
+
})]
|
|
273
|
+
}),
|
|
274
|
+
/* @__PURE__ */ jsx(ToastHost, { root: appElement ?? void 0 })
|
|
275
|
+
]
|
|
282
276
|
})
|
|
283
277
|
});
|
|
284
278
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ImageViewer.mjs","names":[],"sources":["../../../src/Image/viewer/ImageViewer.tsx"],"sourcesContent":["'use client';\n\nimport { Dialog, type DialogRootProps } from '@base-ui/react/dialog';\nimport { motion } from 'motion/react';\nimport {\n memo,\n type SyntheticEvent,\n use,\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from 'react';\nimport { useMergeRefs } from 'react-merge-refs';\n\nimport { ToastHost } from '@/base-ui/Toast';\nimport { useLayerZIndex } from '@/base-ui/zIndex';\nimport { MotionComponent } from '@/MotionProvider';\nimport { useAppElement } from '@/ThemeProvider';\n\nimport { styles } from '../style';\nimport { computeFit, type Size, unrotatedRect } from './geometry';\nimport { beginClosePreview, endClosePreview, type PreviewEntry } from './registry';\nimport { useFinalFocus } from './useFinalFocus';\nimport { useFlipTransition } from './useFlipTransition';\nimport { readNatural, useGalleryNav } from './useGalleryNav';\nimport { useRefitTransition } from './useRefitTransition';\nimport { useViewerGestures } from './useViewerGestures';\nimport { useZoomPan } from './useZoomPan';\nimport ViewerChrome from './ViewerChrome';\n\nexport interface ImageViewerProps {\n entries: PreviewEntry[];\n index: number;\n openerFocusElement: HTMLElement | null;\n token: number;\n}\n\nconst readViewport = (): Size => ({ height: window.innerHeight, width: window.innerWidth });\n\nconst prefersReducedMotion = () =>\n window.matchMedia?.('(prefers-reduced-motion: reduce)').matches ?? false;\n\nconst ImageViewer = memo<ImageViewerProps>(({ entries, index, openerFocusElement, token }) => {\n const openerEntry = entries[index];\n const appElement = useAppElement();\n const motionComponent = use(MotionComponent);\n const [animated] = useState(() => !!motionComponent && !prefersReducedMotion());\n\n const { ref: layerRef, zIndex } = useLayerZIndex<HTMLDivElement>('modal');\n\n const [currentIndex, setCurrentIndex] = useState(index);\n const currentEntry = entries[currentIndex];\n const currentEntryRef = useRef(currentEntry);\n currentEntryRef.current = currentEntry;\n\n const [source, setSource] = useState(openerEntry.src);\n const [natural, setNatural] = useState<Size>(() => readNatural(openerEntry.element));\n const [viewport, setViewport] = useState<Size>(readViewport);\n\n const closeRef = useRef<(() => void) | null>(null);\n const requestClose = useCallback(() => closeRef.current?.(), []);\n\n // useZoomPan needs to gate its wheel/toolbar entry points on close-in-flight,\n // but that state only exists once useFlipTransition (below) has run — and it\n // needs useZoomPan's own transform values first. Break the cycle with a\n // stable indirection: the ref is repointed at the real isClosing once it's\n // available, written directly during render like the other *Ref fields here.\n const isClosingIndirectRef = useRef<() => boolean>(() => false);\n const isClosingIndirect = useCallback(() => isClosingIndirectRef.current(), []);\n\n const isTransitioningIndirectRef = useRef<() => boolean>(() => true);\n const isTransitioningIndirect = useCallback(() => isTransitioningIndirectRef.current(), []);\n\n const fillViewport = Boolean(\n currentEntry.previewSrc && currentEntry.previewSrc !== currentEntry.src,\n );\n\n const {\n canZoomIn,\n canZoomOut,\n dragBy,\n dragEnd,\n escIntent,\n flipHorizontal,\n flipVertical,\n flipX,\n flipY,\n getInitialScale,\n handleDoubleClick,\n handleWheel,\n isClean,\n isZoomed,\n reset,\n resetCloseTracking,\n rotate,\n rotateLeft,\n rotateRight,\n rotation,\n scale,\n setNatural: syncZoomNatural,\n setViewport: syncZoomViewport,\n toggleActualSize,\n x,\n y,\n zoomIn,\n zoomOut,\n } = useZoomPan({\n autoZoomThreshold: currentEntry.options.autoZoomThreshold,\n defaultZoom: currentEntry.options.defaultZoom,\n fillViewport,\n isClosing: isClosingIndirect,\n isTransitioning: isTransitioningIndirect,\n maxScale: currentEntry.options.maxScale,\n natural,\n onCloseRequest: requestClose,\n viewport,\n });\n\n const fitRect = useMemo(\n () => computeFit(natural, viewport, rotation, fillViewport),\n [natural, viewport, rotation, fillViewport],\n );\n const fitRectRef = useRef(fitRect);\n fitRectRef.current = fitRect;\n const getFitRect = useCallback(() => fitRectRef.current, []);\n\n const imageRect = useMemo(() => unrotatedRect(fitRect, rotation), [fitRect, rotation]);\n\n const viewportRef = useRef(viewport);\n viewportRef.current = viewport;\n const getViewportWidth = useCallback(() => viewportRef.current.width, []);\n\n const getCloseSource = useCallback(() => currentEntryRef.current.element, []);\n\n const transform = useMemo(\n () => ({ flipX, flipY, rotate, scale, x, y }),\n [flipX, flipY, rotate, scale, x, y],\n );\n const handleClosed = useCallback(() => endClosePreview(token), [token]);\n\n const {\n backdropRef,\n chromeRef,\n close,\n imageRef: flipImageRef,\n isClosing,\n isTransitioning,\n switchTo,\n } = useFlipTransition({\n animated,\n getCloseSource,\n getFitRect,\n getInitialScale,\n getViewportWidth,\n onClosed: handleClosed,\n source: openerEntry.element,\n transform,\n });\n isClosingIndirectRef.current = isClosing;\n isTransitioningIndirectRef.current = isTransitioning;\n\n useRefitTransition({\n animated,\n fillViewport,\n isTransitioning,\n natural,\n rotation,\n scale,\n viewport,\n x,\n y,\n });\n const finalFocus = useFinalFocus(openerFocusElement);\n\n const isCleanRef = useRef(isClean);\n isCleanRef.current = isClean;\n\n const handleClose = useCallback(() => {\n beginClosePreview(token);\n close({ fade: !isCleanRef.current });\n }, [close, token]);\n closeRef.current = handleClose;\n\n const handleDialogOpenChange = useCallback<NonNullable<DialogRootProps['onOpenChange']>>(\n (open, eventDetails) => {\n if (open) return;\n // Base UI fires this on every Esc regardless of whether we're already\n // mid-close (our Dialog.Root's open prop never actually flips to\n // false), so without this guard a second Esc during the close window\n // reads escIntent() off the close spring's mid-flight scale, decides\n // 'reset', and cancels the close animation out from under itself.\n if (isClosing()) return;\n if (eventDetails.reason === 'escape-key' && escIntent() === 'reset') {\n eventDetails.cancel();\n reset();\n return;\n }\n handleClose();\n },\n [escIntent, handleClose, isClosing, reset],\n );\n\n const gestures = useViewerGestures({\n dragBy,\n dragEnd,\n handleDoubleClick,\n handleWheel,\n isClean,\n isZoomed,\n onClose: handleClose,\n reset,\n zoomIn,\n zoomOut,\n });\n\n const { hasNext, hasPrev, next, prev } = useGalleryNav({\n cancelPendingClose: gestures.cancelPendingClose,\n currentIndex,\n entries,\n flipX,\n flipY,\n getInitialScale,\n resetCloseTracking,\n rotate,\n scale,\n setCurrentIndex,\n setNatural,\n setSource,\n switchTo,\n syncZoomNatural,\n x,\n y,\n });\n\n const popupNodeRef = useRef<HTMLDivElement | null>(null);\n const popupRef = useMergeRefs<HTMLDivElement>([layerRef, gestures.popupRef, popupNodeRef]);\n const imageRef = useMergeRefs<HTMLImageElement>([flipImageRef, gestures.imageRef]);\n\n const handleLoad = useCallback(\n (event: SyntheticEvent<HTMLImageElement>) => {\n const loaded = event.currentTarget;\n if (!loaded.naturalWidth || !loaded.naturalHeight) return;\n const next = { height: loaded.naturalHeight, width: loaded.naturalWidth };\n setNatural((prev) =>\n prev.width === next.width && prev.height === next.height ? prev : next,\n );\n syncZoomNatural(next);\n },\n [syncZoomNatural],\n );\n\n useEffect(() => {\n const handleResize = () => {\n const next = readViewport();\n setViewport(next);\n syncZoomViewport(next);\n };\n window.addEventListener('resize', handleResize);\n return () => window.removeEventListener('resize', handleResize);\n }, [syncZoomViewport]);\n\n useEffect(() => {\n const { previewSrc, src } = currentEntry;\n if (!previewSrc || previewSrc === src) return;\n let cancelled = false;\n const loader = new window.Image();\n const handleLoaded = () => {\n if (!cancelled) setSource(previewSrc);\n };\n loader.addEventListener('load', handleLoaded);\n loader.src = previewSrc;\n return () => {\n cancelled = true;\n loader.removeEventListener('load', handleLoaded);\n };\n }, [currentEntry]);\n\n useEffect(\n () => () => {\n const thumbnailWasRemoved = !openerEntry.element.isConnected;\n if (thumbnailWasRemoved) endClosePreview(token);\n },\n [openerEntry, token],\n );\n\n return (\n // The chrome is built from Base UI controls, which need a motion component to\n // render at all. The viewer itself still degrades to a plain fade without one —\n // `animated` stays false — but the toolbar has no such fallback, so an app that\n // skipped ConfigProvider gets motion here rather than a crash.\n <MotionComponent value={motionComponent ?? motion}>\n <Dialog.Root modal open onOpenChange={handleDialogOpenChange}>\n <Dialog.Portal container={appElement ?? undefined}>\n {/* Base UI drops a nested dialog's backdrop so overlays don't stack. The viewer is\n not an overlay on the surface it opened from — it replaces the screen — so it\n keeps its own scrim, or a viewer opened from a maskless drawer would show the\n page straight through the letterbox around the image. */}\n <Dialog.Backdrop\n forceRender\n className={styles.viewerBackdrop}\n ref={backdropRef}\n style={zIndex === undefined ? undefined : { zIndex }}\n onClick={gestures.onSurfaceClick}\n />\n <Dialog.Popup\n aria-label={currentEntry.element.alt || undefined}\n className={styles.viewerPopup}\n finalFocus={finalFocus}\n // Focus the popup itself instead of Base UI's default (the first\n // tabbable — the close button): a focus-visible close button pins\n // the idle auto-hide open forever and pops its tooltip on open.\n initialFocus={popupNodeRef}\n ref={popupRef}\n style={zIndex === undefined ? undefined : { zIndex: zIndex + 1 }}\n tabIndex={-1}\n onClick={gestures.onSurfaceClick}\n onPointerCancel={gestures.onPointerFinish}\n onPointerDown={gestures.onPointerDown}\n onPointerMove={gestures.onPointerMove}\n onPointerUp={gestures.onPointerFinish}\n >\n <img\n alt={currentEntry.element.alt}\n className={styles.viewerImage}\n ref={imageRef}\n src={source}\n style={{\n cursor: gestures.cursor,\n height: imageRect.height,\n left: imageRect.x,\n top: imageRect.y,\n width: imageRect.width,\n }}\n onClick={gestures.onImageClick}\n onDoubleClick={gestures.onImageDoubleClick}\n onLoad={handleLoad}\n />\n <ViewerChrome\n canZoomIn={canZoomIn}\n canZoomOut={canZoomOut}\n chromeRef={chromeRef}\n current={currentIndex}\n fitRect={fitRect}\n flipHorizontal={flipHorizontal}\n flipVertical={flipVertical}\n hasNext={hasNext}\n hasPrev={hasPrev}\n natural={natural}\n next={next}\n prev={prev}\n rotateLeft={rotateLeft}\n rotateRight={rotateRight}\n rotation={rotation}\n scale={scale}\n source={source}\n toggleActualSize={toggleActualSize}\n toolbarAddon={currentEntry.options.toolbarAddon}\n total={entries.length}\n zoomIn={zoomIn}\n zoomOut={zoomOut}\n onClose={handleClose}\n onDownload={currentEntry.options.onDownload}\n />\n </Dialog.Popup>\n <ToastHost root={appElement ?? undefined} />\n </Dialog.Portal>\n </Dialog.Root>\n </MotionComponent>\n );\n});\n\nImageViewer.displayName = 'ImageViewer';\n\nexport default ImageViewer;\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;AAuCA,MAAM,sBAA4B;CAAE,QAAQ,OAAO;CAAa,OAAO,OAAO;AAAW;AAEzF,MAAM,6BACJ,OAAO,aAAa,kCAAkC,CAAC,CAAC,WAAW;AAErE,MAAM,cAAc,MAAwB,EAAE,SAAS,OAAO,oBAAoB,YAAY;CAC5F,MAAM,cAAc,QAAQ;CAC5B,MAAM,aAAa,cAAc;CACjC,MAAM,kBAAkB,IAAI,eAAe;CAC3C,MAAM,CAAC,YAAY,eAAe,CAAC,CAAC,mBAAmB,CAAC,qBAAqB,CAAC;CAE9E,MAAM,EAAE,KAAK,UAAU,WAAW,eAA+B,OAAO;CAExE,MAAM,CAAC,cAAc,mBAAmB,SAAS,KAAK;CACtD,MAAM,eAAe,QAAQ;CAC7B,MAAM,kBAAkB,OAAO,YAAY;CAC3C,gBAAgB,UAAU;CAE1B,MAAM,CAAC,QAAQ,aAAa,SAAS,YAAY,GAAG;CACpD,MAAM,CAAC,SAAS,cAAc,eAAqB,YAAY,YAAY,OAAO,CAAC;CACnF,MAAM,CAAC,UAAU,eAAe,SAAe,YAAY;CAE3D,MAAM,WAAW,OAA4B,IAAI;CACjD,MAAM,eAAe,kBAAkB,SAAS,UAAU,GAAG,CAAC,CAAC;CAO/D,MAAM,uBAAuB,aAA4B,KAAK;CAC9D,MAAM,oBAAoB,kBAAkB,qBAAqB,QAAQ,GAAG,CAAC,CAAC;CAE9E,MAAM,6BAA6B,aAA4B,IAAI;CACnE,MAAM,0BAA0B,kBAAkB,2BAA2B,QAAQ,GAAG,CAAC,CAAC;CAE1F,MAAM,eAAe,QACnB,aAAa,cAAc,aAAa,eAAe,aAAa,GACtE;CAEA,MAAM,EACJ,WACA,YACA,QACA,SACA,WACA,gBACA,cACA,OACA,OACA,iBACA,mBACA,aACA,SACA,UACA,OACA,oBACA,QACA,YACA,aACA,UACA,OACA,YAAY,iBACZ,aAAa,kBACb,kBACA,GACA,GACA,QACA,YACE,WAAW;EACb,mBAAmB,aAAa,QAAQ;EACxC,aAAa,aAAa,QAAQ;EAClC;EACA,WAAW;EACX,iBAAiB;EACjB,UAAU,aAAa,QAAQ;EAC/B;EACA,gBAAgB;EAChB;CACF,CAAC;CAED,MAAM,UAAU,cACR,WAAW,SAAS,UAAU,UAAU,YAAY,GAC1D;EAAC;EAAS;EAAU;EAAU;CAAY,CAC5C;CACA,MAAM,aAAa,OAAO,OAAO;CACjC,WAAW,UAAU;CACrB,MAAM,aAAa,kBAAkB,WAAW,SAAS,CAAC,CAAC;CAE3D,MAAM,YAAY,cAAc,cAAc,SAAS,QAAQ,GAAG,CAAC,SAAS,QAAQ,CAAC;CAErF,MAAM,cAAc,OAAO,QAAQ;CACnC,YAAY,UAAU;CACtB,MAAM,mBAAmB,kBAAkB,YAAY,QAAQ,OAAO,CAAC,CAAC;CAExE,MAAM,iBAAiB,kBAAkB,gBAAgB,QAAQ,SAAS,CAAC,CAAC;CAE5E,MAAM,YAAY,eACT;EAAE;EAAO;EAAO;EAAQ;EAAO;EAAG;CAAE,IAC3C;EAAC;EAAO;EAAO;EAAQ;EAAO;EAAG;CAAC,CACpC;CACA,MAAM,eAAe,kBAAkB,gBAAgB,KAAK,GAAG,CAAC,KAAK,CAAC;CAEtE,MAAM,EACJ,aACA,WACA,OACA,UAAU,cACV,WACA,iBACA,aACE,kBAAkB;EACpB;EACA;EACA;EACA;EACA;EACA,UAAU;EACV,QAAQ,YAAY;EACpB;CACF,CAAC;CACD,qBAAqB,UAAU;CAC/B,2BAA2B,UAAU;CAErC,mBAAmB;EACjB;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;CACF,CAAC;CACD,MAAM,aAAa,cAAc,kBAAkB;CAEnD,MAAM,aAAa,OAAO,OAAO;CACjC,WAAW,UAAU;CAErB,MAAM,cAAc,kBAAkB;EACpC,kBAAkB,KAAK;EACvB,MAAM,EAAE,MAAM,CAAC,WAAW,QAAQ,CAAC;CACrC,GAAG,CAAC,OAAO,KAAK,CAAC;CACjB,SAAS,UAAU;CAEnB,MAAM,yBAAyB,aAC5B,MAAM,iBAAiB;EACtB,IAAI,MAAM;EAMV,IAAI,UAAU,GAAG;EACjB,IAAI,aAAa,WAAW,gBAAgB,UAAU,MAAM,SAAS;GACnE,aAAa,OAAO;GACpB,MAAM;GACN;EACF;EACA,YAAY;CACd,GACA;EAAC;EAAW;EAAa;EAAW;CAAK,CAC3C;CAEA,MAAM,WAAW,kBAAkB;EACjC;EACA;EACA;EACA;EACA;EACA;EACA,SAAS;EACT;EACA;EACA;CACF,CAAC;CAED,MAAM,EAAE,SAAS,SAAS,MAAM,SAAS,cAAc;EACrD,oBAAoB,SAAS;EAC7B;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;CACF,CAAC;CAED,MAAM,eAAe,OAA8B,IAAI;CACvD,MAAM,WAAW,aAA6B;EAAC;EAAU,SAAS;EAAU;CAAY,CAAC;CACzF,MAAM,WAAW,aAA+B,CAAC,cAAc,SAAS,QAAQ,CAAC;CAEjF,MAAM,aAAa,aAChB,UAA4C;EAC3C,MAAM,SAAS,MAAM;EACrB,IAAI,CAAC,OAAO,gBAAgB,CAAC,OAAO,eAAe;EACnD,MAAM,OAAO;GAAE,QAAQ,OAAO;GAAe,OAAO,OAAO;EAAa;EACxE,YAAY,SACV,KAAK,UAAU,KAAK,SAAS,KAAK,WAAW,KAAK,SAAS,OAAO,IACpE;EACA,gBAAgB,IAAI;CACtB,GACA,CAAC,eAAe,CAClB;CAEA,gBAAgB;EACd,MAAM,qBAAqB;GACzB,MAAM,OAAO,aAAa;GAC1B,YAAY,IAAI;GAChB,iBAAiB,IAAI;EACvB;EACA,OAAO,iBAAiB,UAAU,YAAY;EAC9C,aAAa,OAAO,oBAAoB,UAAU,YAAY;CAChE,GAAG,CAAC,gBAAgB,CAAC;CAErB,gBAAgB;EACd,MAAM,EAAE,YAAY,QAAQ;EAC5B,IAAI,CAAC,cAAc,eAAe,KAAK;EACvC,IAAI,YAAY;EAChB,MAAM,SAAS,IAAI,OAAO,MAAM;EAChC,MAAM,qBAAqB;GACzB,IAAI,CAAC,WAAW,UAAU,UAAU;EACtC;EACA,OAAO,iBAAiB,QAAQ,YAAY;EAC5C,OAAO,MAAM;EACb,aAAa;GACX,YAAY;GACZ,OAAO,oBAAoB,QAAQ,YAAY;EACjD;CACF,GAAG,CAAC,YAAY,CAAC;CAEjB,sBACc;EAEV,IAAI,CADyB,YAAY,QAAQ,aACxB,gBAAgB,KAAK;CAChD,GACA,CAAC,aAAa,KAAK,CACrB;CAEA,OAKE,oBAAC,iBAAD;EAAiB,OAAO,mBAAmB;EACzC,UAAA,oBAAC,OAAO,MAAR;GAAa,OAAA;GAAM,MAAA;GAAK,cAAc;GACpC,UAAA,qBAAC,OAAO,QAAR;IAAe,WAAW,cAAc,KAAA;IAAxC,UAAA;KAKE,oBAAC,OAAO,UAAR;MACE,aAAA;MACA,WAAW,OAAO;MAClB,KAAK;MACL,OAAO,WAAW,KAAA,IAAY,KAAA,IAAY,EAAE,OAAO;MACnD,SAAS,SAAS;KACnB,CAAA;KACD,qBAAC,OAAO,OAAR;MACE,cAAY,aAAa,QAAQ,OAAO,KAAA;MACxC,WAAW,OAAO;MACN;MAIZ,cAAc;MACd,KAAK;MACL,OAAO,WAAW,KAAA,IAAY,KAAA,IAAY,EAAE,QAAQ,SAAS,EAAE;MAC/D,UAAU;MACV,SAAS,SAAS;MAClB,iBAAiB,SAAS;MAC1B,eAAe,SAAS;MACxB,eAAe,SAAS;MACxB,aAAa,SAAS;MAfxB,UAAA,CAiBE,oBAAC,OAAD;OACE,KAAK,aAAa,QAAQ;OAC1B,WAAW,OAAO;OAClB,KAAK;OACL,KAAK;OACL,OAAO;QACL,QAAQ,SAAS;QACjB,QAAQ,UAAU;QAClB,MAAM,UAAU;QAChB,KAAK,UAAU;QACf,OAAO,UAAU;OACnB;OACA,SAAS,SAAS;OAClB,eAAe,SAAS;OACxB,QAAQ;MACT,CAAA,GACD,oBAAC,cAAD;OACa;OACC;OACD;OACX,SAAS;OACA;OACO;OACF;OACL;OACA;OACA;OACH;OACA;OACM;OACC;OACH;OACH;OACC;OACU;OAClB,cAAc,aAAa,QAAQ;OACnC,OAAO,QAAQ;OACP;OACC;OACT,SAAS;OACT,YAAY,aAAa,QAAQ;MAClC,CAAA,CACW;;KACd,oBAAC,WAAD,EAAW,MAAM,cAAc,KAAA,EAAY,CAAA;IAC9B;;EACJ,CAAA;CACE,CAAA;AAErB,CAAC;AAED,YAAY,cAAc"}
|
|
1
|
+
{"version":3,"file":"ImageViewer.mjs","names":[],"sources":["../../../src/Image/viewer/ImageViewer.tsx"],"sourcesContent":["'use client';\n\nimport { Dialog, type DialogRootProps } from '@base-ui/react/dialog';\nimport {\n memo,\n type SyntheticEvent,\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from 'react';\nimport { useMergeRefs } from 'react-merge-refs';\n\nimport { ToastHost } from '@/base-ui/Toast';\nimport { useLayerZIndex } from '@/base-ui/zIndex';\nimport { useAppElement } from '@/ThemeProvider';\n\nimport { styles } from '../style';\nimport { computeFit, type Size, unrotatedRect } from './geometry';\nimport { beginClosePreview, endClosePreview, type PreviewEntry } from './registry';\nimport { useFinalFocus } from './useFinalFocus';\nimport { useFlipTransition } from './useFlipTransition';\nimport { readNatural, useGalleryNav } from './useGalleryNav';\nimport { useRefitTransition } from './useRefitTransition';\nimport { useViewerGestures } from './useViewerGestures';\nimport { useZoomPan } from './useZoomPan';\nimport ViewerChrome from './ViewerChrome';\n\nexport interface ImageViewerProps {\n entries: PreviewEntry[];\n index: number;\n openerFocusElement: HTMLElement | null;\n token: number;\n}\n\nconst readViewport = (): Size => ({ height: window.innerHeight, width: window.innerWidth });\n\nconst prefersReducedMotion = () =>\n window.matchMedia?.('(prefers-reduced-motion: reduce)').matches ?? false;\n\nconst ImageViewer = memo<ImageViewerProps>(({ entries, index, openerFocusElement, token }) => {\n const openerEntry = entries[index];\n const appElement = useAppElement();\n const [animated] = useState(() => !prefersReducedMotion());\n\n const { ref: layerRef, zIndex } = useLayerZIndex<HTMLDivElement>('modal');\n\n const [currentIndex, setCurrentIndex] = useState(index);\n const currentEntry = entries[currentIndex];\n const currentEntryRef = useRef(currentEntry);\n currentEntryRef.current = currentEntry;\n\n const [source, setSource] = useState(openerEntry.src);\n const [natural, setNatural] = useState<Size>(() => readNatural(openerEntry.element));\n const [viewport, setViewport] = useState<Size>(readViewport);\n\n const closeRef = useRef<(() => void) | null>(null);\n const requestClose = useCallback(() => closeRef.current?.(), []);\n\n // useZoomPan needs to gate its wheel/toolbar entry points on close-in-flight,\n // but that state only exists once useFlipTransition (below) has run — and it\n // needs useZoomPan's own transform values first. Break the cycle with a\n // stable indirection: the ref is repointed at the real isClosing once it's\n // available, written directly during render like the other *Ref fields here.\n const isClosingIndirectRef = useRef<() => boolean>(() => false);\n const isClosingIndirect = useCallback(() => isClosingIndirectRef.current(), []);\n\n const isTransitioningIndirectRef = useRef<() => boolean>(() => true);\n const isTransitioningIndirect = useCallback(() => isTransitioningIndirectRef.current(), []);\n\n const fillViewport = Boolean(\n currentEntry.previewSrc && currentEntry.previewSrc !== currentEntry.src,\n );\n\n const {\n canZoomIn,\n canZoomOut,\n dragBy,\n dragEnd,\n escIntent,\n flipHorizontal,\n flipVertical,\n flipX,\n flipY,\n getInitialScale,\n handleDoubleClick,\n handleWheel,\n isClean,\n isZoomed,\n reset,\n resetCloseTracking,\n rotate,\n rotateLeft,\n rotateRight,\n rotation,\n scale,\n setNatural: syncZoomNatural,\n setViewport: syncZoomViewport,\n toggleActualSize,\n x,\n y,\n zoomIn,\n zoomOut,\n } = useZoomPan({\n autoZoomThreshold: currentEntry.options.autoZoomThreshold,\n defaultZoom: currentEntry.options.defaultZoom,\n fillViewport,\n isClosing: isClosingIndirect,\n isTransitioning: isTransitioningIndirect,\n maxScale: currentEntry.options.maxScale,\n natural,\n onCloseRequest: requestClose,\n viewport,\n });\n\n const fitRect = useMemo(\n () => computeFit(natural, viewport, rotation, fillViewport),\n [natural, viewport, rotation, fillViewport],\n );\n const fitRectRef = useRef(fitRect);\n fitRectRef.current = fitRect;\n const getFitRect = useCallback(() => fitRectRef.current, []);\n\n const imageRect = useMemo(() => unrotatedRect(fitRect, rotation), [fitRect, rotation]);\n\n const viewportRef = useRef(viewport);\n viewportRef.current = viewport;\n const getViewportWidth = useCallback(() => viewportRef.current.width, []);\n\n const getCloseSource = useCallback(() => currentEntryRef.current.element, []);\n\n const transform = useMemo(\n () => ({ flipX, flipY, rotate, scale, x, y }),\n [flipX, flipY, rotate, scale, x, y],\n );\n const handleClosed = useCallback(() => endClosePreview(token), [token]);\n\n const {\n backdropRef,\n chromeRef,\n close,\n imageRef: flipImageRef,\n isClosing,\n isTransitioning,\n switchTo,\n } = useFlipTransition({\n animated,\n getCloseSource,\n getFitRect,\n getInitialScale,\n getViewportWidth,\n onClosed: handleClosed,\n source: openerEntry.element,\n transform,\n });\n isClosingIndirectRef.current = isClosing;\n isTransitioningIndirectRef.current = isTransitioning;\n\n useRefitTransition({\n animated,\n fillViewport,\n isTransitioning,\n natural,\n rotation,\n scale,\n viewport,\n x,\n y,\n });\n const finalFocus = useFinalFocus(openerFocusElement);\n\n const isCleanRef = useRef(isClean);\n isCleanRef.current = isClean;\n\n const handleClose = useCallback(() => {\n beginClosePreview(token);\n close({ fade: !isCleanRef.current });\n }, [close, token]);\n closeRef.current = handleClose;\n\n const handleDialogOpenChange = useCallback<NonNullable<DialogRootProps['onOpenChange']>>(\n (open, eventDetails) => {\n if (open) return;\n // Base UI fires this on every Esc regardless of whether we're already\n // mid-close (our Dialog.Root's open prop never actually flips to\n // false), so without this guard a second Esc during the close window\n // reads escIntent() off the close spring's mid-flight scale, decides\n // 'reset', and cancels the close animation out from under itself.\n if (isClosing()) return;\n if (eventDetails.reason === 'escape-key' && escIntent() === 'reset') {\n eventDetails.cancel();\n reset();\n return;\n }\n handleClose();\n },\n [escIntent, handleClose, isClosing, reset],\n );\n\n const gestures = useViewerGestures({\n dragBy,\n dragEnd,\n handleDoubleClick,\n handleWheel,\n isClean,\n isZoomed,\n onClose: handleClose,\n reset,\n zoomIn,\n zoomOut,\n });\n\n const { hasNext, hasPrev, next, prev } = useGalleryNav({\n cancelPendingClose: gestures.cancelPendingClose,\n currentIndex,\n entries,\n flipX,\n flipY,\n getInitialScale,\n resetCloseTracking,\n rotate,\n scale,\n setCurrentIndex,\n setNatural,\n setSource,\n switchTo,\n syncZoomNatural,\n x,\n y,\n });\n\n const popupNodeRef = useRef<HTMLDivElement | null>(null);\n const popupRef = useMergeRefs<HTMLDivElement>([layerRef, gestures.popupRef, popupNodeRef]);\n const imageRef = useMergeRefs<HTMLImageElement>([flipImageRef, gestures.imageRef]);\n\n const handleLoad = useCallback(\n (event: SyntheticEvent<HTMLImageElement>) => {\n const loaded = event.currentTarget;\n if (!loaded.naturalWidth || !loaded.naturalHeight) return;\n const next = { height: loaded.naturalHeight, width: loaded.naturalWidth };\n setNatural((prev) =>\n prev.width === next.width && prev.height === next.height ? prev : next,\n );\n syncZoomNatural(next);\n },\n [syncZoomNatural],\n );\n\n useEffect(() => {\n const handleResize = () => {\n const next = readViewport();\n setViewport(next);\n syncZoomViewport(next);\n };\n window.addEventListener('resize', handleResize);\n return () => window.removeEventListener('resize', handleResize);\n }, [syncZoomViewport]);\n\n useEffect(() => {\n const { previewSrc, src } = currentEntry;\n if (!previewSrc || previewSrc === src) return;\n let cancelled = false;\n const loader = new window.Image();\n const handleLoaded = () => {\n if (!cancelled) setSource(previewSrc);\n };\n loader.addEventListener('load', handleLoaded);\n loader.src = previewSrc;\n return () => {\n cancelled = true;\n loader.removeEventListener('load', handleLoaded);\n };\n }, [currentEntry]);\n\n useEffect(\n () => () => {\n const thumbnailWasRemoved = !openerEntry.element.isConnected;\n if (thumbnailWasRemoved) endClosePreview(token);\n },\n [openerEntry, token],\n );\n\n return (\n <Dialog.Root modal open onOpenChange={handleDialogOpenChange}>\n <Dialog.Portal container={appElement ?? undefined}>\n {/* Base UI drops a nested dialog's backdrop so overlays don't stack. The viewer is\n not an overlay on the surface it opened from — it replaces the screen — so it\n keeps its own scrim, or a viewer opened from a maskless drawer would show the\n page straight through the letterbox around the image. */}\n <Dialog.Backdrop\n forceRender\n className={styles.viewerBackdrop}\n ref={backdropRef}\n style={zIndex === undefined ? undefined : { zIndex }}\n onClick={gestures.onSurfaceClick}\n />\n <Dialog.Popup\n aria-label={currentEntry.element.alt || undefined}\n className={styles.viewerPopup}\n finalFocus={finalFocus}\n // Focus the popup itself instead of Base UI's default (the first\n // tabbable — the close button): a focus-visible close button pins\n // the idle auto-hide open forever and pops its tooltip on open.\n initialFocus={popupNodeRef}\n ref={popupRef}\n style={zIndex === undefined ? undefined : { zIndex: zIndex + 1 }}\n tabIndex={-1}\n onClick={gestures.onSurfaceClick}\n onPointerCancel={gestures.onPointerFinish}\n onPointerDown={gestures.onPointerDown}\n onPointerMove={gestures.onPointerMove}\n onPointerUp={gestures.onPointerFinish}\n >\n <img\n alt={currentEntry.element.alt}\n className={styles.viewerImage}\n ref={imageRef}\n src={source}\n style={{\n cursor: gestures.cursor,\n height: imageRect.height,\n left: imageRect.x,\n top: imageRect.y,\n width: imageRect.width,\n }}\n onClick={gestures.onImageClick}\n onDoubleClick={gestures.onImageDoubleClick}\n onLoad={handleLoad}\n />\n <ViewerChrome\n canZoomIn={canZoomIn}\n canZoomOut={canZoomOut}\n chromeRef={chromeRef}\n current={currentIndex}\n fitRect={fitRect}\n flipHorizontal={flipHorizontal}\n flipVertical={flipVertical}\n hasNext={hasNext}\n hasPrev={hasPrev}\n natural={natural}\n next={next}\n prev={prev}\n rotateLeft={rotateLeft}\n rotateRight={rotateRight}\n rotation={rotation}\n scale={scale}\n source={source}\n toggleActualSize={toggleActualSize}\n toolbarAddon={currentEntry.options.toolbarAddon}\n total={entries.length}\n zoomIn={zoomIn}\n zoomOut={zoomOut}\n onClose={handleClose}\n onDownload={currentEntry.options.onDownload}\n />\n </Dialog.Popup>\n <ToastHost root={appElement ?? undefined} />\n </Dialog.Portal>\n </Dialog.Root>\n );\n});\n\nImageViewer.displayName = 'ImageViewer';\n\nexport default ImageViewer;\n"],"mappings":"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"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
"use client";
|
|
2
|
+
import { useMotionComponent } from "../../MotionProvider/index.mjs";
|
|
2
3
|
import ActionIcon from "../ActionIcon/ActionIcon.mjs";
|
|
3
4
|
import { DraggablePanelContext, useDraggablePanelContext } from "./context.mjs";
|
|
4
5
|
import { AXES } from "./core/axes.mjs";
|
|
@@ -10,7 +11,7 @@ import { BOW, handleVariants, rootVariants, styles, toggleVariants } from "./sty
|
|
|
10
11
|
import { memo, useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
11
12
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
12
13
|
import { cx } from "antd-style";
|
|
13
|
-
import {
|
|
14
|
+
import { useTransform } from "motion/react";
|
|
14
15
|
import useMergeState from "use-merge-value";
|
|
15
16
|
import { ChevronLeft } from "lucide-react";
|
|
16
17
|
//#region src/base-ui/DraggablePanel/atoms.tsx
|
|
@@ -140,12 +141,13 @@ const DraggablePanelRoot = memo(({ backgroundColor, children, className, collaps
|
|
|
140
141
|
});
|
|
141
142
|
DraggablePanelRoot.displayName = "DraggablePanelRoot";
|
|
142
143
|
const DraggablePanelContent = memo(({ children, className, style, ...rest }) => {
|
|
144
|
+
const Motion = useMotionComponent();
|
|
143
145
|
const { axis, controller, expand, placement, state } = useDraggablePanelContext();
|
|
144
146
|
const extent = useTransform(controller.motion.size, (value) => Math.max(0, value));
|
|
145
147
|
const target = useStore(controller.subscribe, () => controller.target);
|
|
146
148
|
const clipping = state.dragging || state.folding || target === 0;
|
|
147
149
|
const shrunk = state.collapsing || !expand;
|
|
148
|
-
return /* @__PURE__ */ jsx(
|
|
150
|
+
return /* @__PURE__ */ jsx(Motion.div, {
|
|
149
151
|
inert: !expand,
|
|
150
152
|
style: {
|
|
151
153
|
display: "flex",
|
|
@@ -156,7 +158,7 @@ const DraggablePanelContent = memo(({ children, className, style, ...rest }) =>
|
|
|
156
158
|
[axis.cross]: "100%",
|
|
157
159
|
[axis.extent]: extent
|
|
158
160
|
},
|
|
159
|
-
children: /* @__PURE__ */ jsx(
|
|
161
|
+
children: /* @__PURE__ */ jsx(Motion.div, {
|
|
160
162
|
animate: { scale: shrunk ? COLLAPSED_SCALE : 1 },
|
|
161
163
|
className: cx(styles.content, className),
|
|
162
164
|
transition: timing(),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"atoms.mjs","names":["useControlledState","getHandleSize"],"sources":["../../../src/base-ui/DraggablePanel/atoms.tsx"],"sourcesContent":["'use client';\n\nimport { cx } from 'antd-style';\nimport { ChevronLeft } from 'lucide-react';\nimport type { HTMLMotionProps, MotionStyle } from 'motion/react';\nimport { motion, useTransform } from 'motion/react';\nimport {\n type CSSProperties,\n memo,\n type ReactNode,\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from 'react';\nimport useControlledState from 'use-merge-value';\n\nimport ActionIcon from '@/base-ui/ActionIcon';\nimport type { DivProps } from '@/types';\n\nimport { DraggablePanelContext, useDraggablePanelContext } from './context';\nimport type { Placement } from './core/axes';\nimport { AXES } from './core/axes';\nimport type { PanelControllerOptions } from './core/controller';\nimport { createPanelController } from './core/controller';\nimport { coarsePointer, handleSize as getHandleSize } from './core/env';\nimport { useIsomorphicLayoutEffect, useStore } from './core/internal';\nimport { timing } from './core/transition';\nimport { BOW, handleVariants, rootVariants, styles, toggleVariants } from './style';\n\nconst PAN_THRESHOLD = 3;\n\nconst BOW_CX = 15;\nconst BOW_CY = BOW.half + 8;\nconst BOW_W = BOW_CX * 2;\nconst BOW_H = BOW_CY * 2;\n\nconst bowPath = (direction: 1 | -1, verticalSeam: boolean) => {\n const k = BOW.half * BOW.curve;\n const b = BOW_CX + BOW.bulge * direction;\n const a0 = BOW_CY - BOW.half;\n const a1 = BOW_CY + BOW.half;\n // `a` runs along the seam, `b` across it; a horizontal seam swaps the two.\n const pt = (along: number, across: number) =>\n verticalSeam ? `${along} ${across}` : `${across} ${along}`;\n return [\n `M${pt(BOW_CX, a0)}`,\n `C${pt(BOW_CX, a0 + k)} ${pt(b, BOW_CY - k)} ${pt(b, BOW_CY)}`,\n `C${pt(b, BOW_CY + k)} ${pt(BOW_CX, a1 - k)} ${pt(BOW_CX, a1)}`,\n ].join(' ');\n};\n\nconst BOW_PATHS = {\n horizontalSeam: [bowPath(-1, false), bowPath(1, false)],\n verticalSeam: [bowPath(-1, true), bowPath(1, true)],\n};\n\n/** The chevron points the way a click moves the panel. */\nconst CHEVRON_TURN = { bottom: 270, left: 0, right: 180, top: 90 } as const;\n\nconst chevronPath = (cx: number, cy: number) =>\n `M${cx + 2.4} ${cy - 4.8} L${cx - 2.4} ${cy} L${cx + 2.4} ${cy + 4.8}`;\n\nconst ORIGIN_MAP = {\n bottom: 'center bottom',\n left: 'left center',\n right: 'right center',\n top: 'center top',\n} as const;\n\nconst COLLAPSED_SCALE = 0.97;\n\nconst EDGE_INSET = {\n bottom: 'insetBlockEnd',\n left: 'insetInlineStart',\n right: 'insetInlineEnd',\n top: 'insetBlockStart',\n} as const;\n\nexport interface DraggablePanelRootProps extends Omit<DivProps, 'onDrag'> {\n backgroundColor?: string;\n collapseThreshold?: number;\n defaultExpand?: boolean;\n defaultSize?: number;\n expand?: boolean;\n expandable?: boolean;\n max?: number;\n min?: number;\n mode?: 'fixed' | 'float';\n onExpandChange?: (expand: boolean) => void;\n onSizeChange?: (size: number, delta: number) => void;\n onSizeDragging?: (size: number, delta: number) => void;\n placement?: Placement;\n showBorder?: boolean;\n size?: number;\n}\n\nexport const DraggablePanelRoot = memo<DraggablePanelRootProps>(\n ({\n backgroundColor,\n children,\n className,\n collapseThreshold,\n defaultExpand = true,\n defaultSize,\n expand,\n expandable = true,\n max,\n min = 0,\n mode = 'fixed',\n onExpandChange,\n onSizeChange,\n onSizeDragging,\n placement = 'right',\n showBorder = true,\n size,\n style,\n ...rest\n }) => {\n const axis = AXES[placement];\n const fallbackSize = axis.vertical ? 180 : 280;\n const resolvedDefaultSize = defaultSize ?? fallbackSize;\n\n const [isExpand, setIsExpand] = useControlledState(defaultExpand, {\n onChange: onExpandChange,\n value: expand,\n });\n const [innerSize, setInnerSize] = useState(resolvedDefaultSize);\n const currentSize = size ?? innerSize;\n\n const commitSize = useCallback(\n (next: number, delta: number) => {\n if (size === undefined) setInnerSize(next);\n onSizeChange?.(next, delta);\n },\n [onSizeChange, size],\n );\n\n const options: PanelControllerOptions = {\n collapseThreshold,\n defaultSize: resolvedDefaultSize,\n expand: isExpand,\n max,\n min,\n onExpandChange: setIsExpand,\n onSizeChange: commitSize,\n onSizeDragging,\n placement,\n size: currentSize,\n };\n\n const [controller] = useState(() => createPanelController(options));\n const state = useStore(controller.subscribe, () => controller.state);\n const elementRef = useRef<HTMLElement>(null);\n\n useIsomorphicLayoutEffect(() => {\n controller.sync(options);\n });\n\n useIsomorphicLayoutEffect(() => {\n const node = elementRef.current;\n return node ? controller.attach(node) : undefined;\n }, [controller]);\n\n const toggleExpand = useCallback(() => {\n if (expandable) setIsExpand(!isExpand);\n }, [expandable, isExpand, setIsExpand]);\n\n const context = useMemo(\n () => ({\n axis,\n controller,\n expand: isExpand,\n expandable,\n placement,\n showBorder,\n state,\n toggleExpand,\n }),\n [axis, controller, isExpand, expandable, placement, showBorder, state, toggleExpand],\n );\n\n return (\n <DraggablePanelContext value={context}>\n <aside\n className={cx(rootVariants({ mode, placement }), className)}\n data-expand={isExpand}\n data-expandable={expandable}\n data-resizing={state.dragging}\n ref={elementRef}\n style={\n {\n '--draggable-panel-bg': backgroundColor || '',\n 'flexDirection': axis.vertical ? 'column' : 'row',\n ...style,\n } as CSSProperties\n }\n {...rest}\n >\n {children}\n </aside>\n </DraggablePanelContext>\n );\n },\n);\n\nDraggablePanelRoot.displayName = 'DraggablePanelRoot';\n\nexport interface DraggablePanelContentProps extends Omit<DivProps, 'onDrag'> {}\n\nexport const DraggablePanelContent = memo<DraggablePanelContentProps>(\n ({ children, className, style, ...rest }) => {\n const { axis, controller, expand, placement, state } = useDraggablePanelContext();\n const extent = useTransform(controller.motion.size, (value) => Math.max(0, value));\n // Subscribed, not read: a collapse that changes only the target would otherwise\n // leave the content unclipped and painted outside the zero-width box.\n const target = useStore(controller.subscribe, () => controller.target);\n const clipping = state.dragging || state.folding || target === 0;\n const shrunk = state.collapsing || !expand;\n\n return (\n <motion.div\n inert={!expand}\n style={\n {\n display: 'flex',\n flexDirection: axis.vertical ? 'column' : 'row',\n flexShrink: 0,\n justifyContent: axis.anchorEnd ? 'flex-end' : 'flex-start',\n overflow: clipping ? 'clip' : 'visible',\n [axis.cross]: '100%',\n [axis.extent]: extent,\n } as MotionStyle\n }\n >\n <motion.div\n animate={{ scale: shrunk ? COLLAPSED_SCALE : 1 }}\n className={cx(styles.content, className)}\n transition={timing()}\n style={\n {\n transformOrigin: ORIGIN_MAP[placement],\n [axis.cross]: '100%',\n [axis.extent]: controller.motion.content,\n ...style,\n } as MotionStyle\n }\n {...(rest as HTMLMotionProps<'div'>)}\n >\n {children}\n </motion.div>\n </motion.div>\n );\n },\n);\n\nDraggablePanelContent.displayName = 'DraggablePanelContent';\n\nexport interface DraggablePanelHandleProps extends Omit<DivProps, 'onDrag'> {\n wideArea?: boolean;\n}\n\nexport const DraggablePanelHandle = memo<DraggablePanelHandleProps>(\n ({ className, style, wideArea = true, ...rest }) => {\n const { axis, controller, expand, showBorder, state } = useDraggablePanelContext();\n const size = useStore(coarsePointer.subscribe, () => getHandleSize(wideArea));\n const target = useStore(controller.subscribe, () => controller.target);\n useEffect(() => () => controller.drag.cancel(), [controller]);\n\n const pressedRef = useRef<{ x: number; y: number } | null>(null);\n const draggingRef = useRef(false);\n const draggedRef = useRef(false);\n const { max, min } = controller.bounds();\n\n if (!expand) return null;\n\n return (\n <div\n aria-orientation={axis.ariaOrientation}\n aria-valuemax={Number.isFinite(max) ? max : undefined}\n aria-valuemin={min}\n aria-valuenow={target}\n aria-valuetext={`${target} pixels`}\n className={cx(handleVariants({ edge: axis.edge }), className)}\n data-border={showBorder}\n data-resizing={state.dragging || undefined}\n role=\"separator\"\n tabIndex={0}\n style={\n {\n '--draggable-panel-handle-size': `${size}px`,\n [EDGE_INSET[axis.edge]]: -size / 2,\n ...style,\n } as CSSProperties\n }\n onKeyDown={(event) => controller.resizeByKey(event)}\n onDoubleClick={() => {\n if (!draggedRef.current) controller.reset();\n }}\n onLostPointerCapture={() => {\n if (draggingRef.current) controller.drag.cancel();\n pressedRef.current = null;\n draggingRef.current = false;\n }}\n onPointerCancel={() => {\n controller.drag.cancel();\n pressedRef.current = null;\n draggingRef.current = false;\n }}\n onPointerDown={(event) => {\n draggedRef.current = false;\n pressedRef.current = { x: event.clientX, y: event.clientY };\n // A synthetic pointerdown carries no active pointer, and capturing throws.\n try {\n event.currentTarget.setPointerCapture(event.pointerId);\n } catch {\n /* empty */\n }\n }}\n onPointerMove={(event) => {\n if (!pressedRef.current) return;\n const offset = {\n x: event.clientX - pressedRef.current.x,\n y: event.clientY - pressedRef.current.y,\n };\n if (!draggingRef.current) {\n if (Math.hypot(offset.x, offset.y) < PAN_THRESHOLD) return;\n draggingRef.current = true;\n draggedRef.current = true;\n controller.drag.start();\n }\n controller.drag.move(offset);\n }}\n onPointerUp={() => {\n if (draggingRef.current) controller.drag.end();\n pressedRef.current = null;\n draggingRef.current = false;\n }}\n {...rest}\n />\n );\n },\n);\n\nDraggablePanelHandle.displayName = 'DraggablePanelHandle';\n\nexport interface DraggablePanelToggleProps extends Omit<DivProps, 'onDrag'> {\n showHandleWhenCollapsed?: boolean;\n}\n\nexport const DraggablePanelToggle = memo<DraggablePanelToggleProps>(\n ({ className, showHandleWhenCollapsed, style, ...rest }) => {\n const { axis, expand, expandable, placement, toggleExpand } = useDraggablePanelContext();\n\n if (!expandable) return null;\n\n const turn = CHEVRON_TURN[placement] + (expand ? 0 : 180);\n const chevX = axis.vertical ? BOW_CY : BOW_CX;\n const chevY = axis.vertical ? BOW_CX : BOW_CY;\n\n return (\n <div\n className={cx(toggleVariants({ placement }), className)}\n style={{ opacity: expand ? undefined : showHandleWhenCollapsed ? 1 : 0, ...style }}\n {...rest}\n >\n <button\n aria-label={expand ? 'Collapse panel' : 'Expand panel'}\n type=\"button\"\n onClick={toggleExpand}\n >\n <svg\n fill=\"none\"\n height={axis.vertical ? BOW_W : BOW_H}\n viewBox={`0 0 ${axis.vertical ? BOW_H : BOW_W} ${axis.vertical ? BOW_W : BOW_H}`}\n width={axis.vertical ? BOW_H : BOW_W}\n >\n {BOW_PATHS[axis.vertical ? 'horizontalSeam' : 'verticalSeam'].map((d) => (\n <path d={d} data-bow=\"\" key={d} strokeLinecap=\"round\" strokeWidth={BOW.stroke} />\n ))}\n <g\n style={{\n rotate: `${turn}deg`,\n transformOrigin: `${chevX}px ${chevY}px`,\n transition: 'rotate 0.25s var(--ant-motion-ease-out, ease)',\n }}\n >\n <path\n d={chevronPath(chevX, chevY)}\n stroke=\"currentColor\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={1.6}\n />\n </g>\n </svg>\n </button>\n </div>\n );\n },\n);\n\nDraggablePanelToggle.displayName = 'DraggablePanelToggle';\n\nexport type DraggablePanelContainerProps = DivProps;\n\nexport const DraggablePanelContainer = memo<DraggablePanelContainerProps>(\n ({ className, ...rest }) => <div className={cx(styles.container, className)} {...rest} />,\n);\n\nDraggablePanelContainer.displayName = 'DraggablePanelContainer';\n\nexport type DraggablePanelBodyProps = DivProps;\n\nexport const DraggablePanelBody = memo<DraggablePanelBodyProps>(({ className, style, ...rest }) => (\n <div className={cx(styles.body, className)} style={{ flex: 1, ...style }} {...rest} />\n));\n\nDraggablePanelBody.displayName = 'DraggablePanelBody';\n\nexport type DraggablePanelFooterProps = DivProps;\n\nexport const DraggablePanelFooter = memo<DraggablePanelFooterProps>(({ className, ...rest }) => (\n <div className={cx(styles.footer, className)} {...rest} />\n));\n\nDraggablePanelFooter.displayName = 'DraggablePanelFooter';\n\nexport interface DraggablePanelHeaderProps extends Omit<DivProps, 'children' | 'title'> {\n extra?: ReactNode;\n onCollapse?: () => void;\n title?: ReactNode;\n}\n\nexport const DraggablePanelHeader = memo<DraggablePanelHeaderProps>(\n ({ className, extra, onCollapse, title, ...rest }) => {\n const { toggleExpand } = useDraggablePanelContext();\n\n return (\n <div className={cx(styles.header, className)} {...rest}>\n <ActionIcon icon={ChevronLeft} size={'small'} onClick={onCollapse ?? toggleExpand} />\n {title}\n {extra}\n </div>\n );\n },\n);\n\nDraggablePanelHeader.displayName = 'DraggablePanelHeader';\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"atoms.mjs","names":["useControlledState","getHandleSize"],"sources":["../../../src/base-ui/DraggablePanel/atoms.tsx"],"sourcesContent":["'use client';\n\nimport { cx } from 'antd-style';\nimport { ChevronLeft } from 'lucide-react';\nimport type { HTMLMotionProps, MotionStyle } from 'motion/react';\nimport { useTransform } from 'motion/react';\nimport {\n type CSSProperties,\n memo,\n type ReactNode,\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from 'react';\nimport useControlledState from 'use-merge-value';\n\nimport ActionIcon from '@/base-ui/ActionIcon';\nimport { useMotionComponent } from '@/MotionProvider';\nimport type { DivProps } from '@/types';\n\nimport { DraggablePanelContext, useDraggablePanelContext } from './context';\nimport type { Placement } from './core/axes';\nimport { AXES } from './core/axes';\nimport type { PanelControllerOptions } from './core/controller';\nimport { createPanelController } from './core/controller';\nimport { coarsePointer, handleSize as getHandleSize } from './core/env';\nimport { useIsomorphicLayoutEffect, useStore } from './core/internal';\nimport { timing } from './core/transition';\nimport { BOW, handleVariants, rootVariants, styles, toggleVariants } from './style';\n\nconst PAN_THRESHOLD = 3;\n\nconst BOW_CX = 15;\nconst BOW_CY = BOW.half + 8;\nconst BOW_W = BOW_CX * 2;\nconst BOW_H = BOW_CY * 2;\n\nconst bowPath = (direction: 1 | -1, verticalSeam: boolean) => {\n const k = BOW.half * BOW.curve;\n const b = BOW_CX + BOW.bulge * direction;\n const a0 = BOW_CY - BOW.half;\n const a1 = BOW_CY + BOW.half;\n // `a` runs along the seam, `b` across it; a horizontal seam swaps the two.\n const pt = (along: number, across: number) =>\n verticalSeam ? `${along} ${across}` : `${across} ${along}`;\n return [\n `M${pt(BOW_CX, a0)}`,\n `C${pt(BOW_CX, a0 + k)} ${pt(b, BOW_CY - k)} ${pt(b, BOW_CY)}`,\n `C${pt(b, BOW_CY + k)} ${pt(BOW_CX, a1 - k)} ${pt(BOW_CX, a1)}`,\n ].join(' ');\n};\n\nconst BOW_PATHS = {\n horizontalSeam: [bowPath(-1, false), bowPath(1, false)],\n verticalSeam: [bowPath(-1, true), bowPath(1, true)],\n};\n\n/** The chevron points the way a click moves the panel. */\nconst CHEVRON_TURN = { bottom: 270, left: 0, right: 180, top: 90 } as const;\n\nconst chevronPath = (cx: number, cy: number) =>\n `M${cx + 2.4} ${cy - 4.8} L${cx - 2.4} ${cy} L${cx + 2.4} ${cy + 4.8}`;\n\nconst ORIGIN_MAP = {\n bottom: 'center bottom',\n left: 'left center',\n right: 'right center',\n top: 'center top',\n} as const;\n\nconst COLLAPSED_SCALE = 0.97;\n\nconst EDGE_INSET = {\n bottom: 'insetBlockEnd',\n left: 'insetInlineStart',\n right: 'insetInlineEnd',\n top: 'insetBlockStart',\n} as const;\n\nexport interface DraggablePanelRootProps extends Omit<DivProps, 'onDrag'> {\n backgroundColor?: string;\n collapseThreshold?: number;\n defaultExpand?: boolean;\n defaultSize?: number;\n expand?: boolean;\n expandable?: boolean;\n max?: number;\n min?: number;\n mode?: 'fixed' | 'float';\n onExpandChange?: (expand: boolean) => void;\n onSizeChange?: (size: number, delta: number) => void;\n onSizeDragging?: (size: number, delta: number) => void;\n placement?: Placement;\n showBorder?: boolean;\n size?: number;\n}\n\nexport const DraggablePanelRoot = memo<DraggablePanelRootProps>(\n ({\n backgroundColor,\n children,\n className,\n collapseThreshold,\n defaultExpand = true,\n defaultSize,\n expand,\n expandable = true,\n max,\n min = 0,\n mode = 'fixed',\n onExpandChange,\n onSizeChange,\n onSizeDragging,\n placement = 'right',\n showBorder = true,\n size,\n style,\n ...rest\n }) => {\n const axis = AXES[placement];\n const fallbackSize = axis.vertical ? 180 : 280;\n const resolvedDefaultSize = defaultSize ?? fallbackSize;\n\n const [isExpand, setIsExpand] = useControlledState(defaultExpand, {\n onChange: onExpandChange,\n value: expand,\n });\n const [innerSize, setInnerSize] = useState(resolvedDefaultSize);\n const currentSize = size ?? innerSize;\n\n const commitSize = useCallback(\n (next: number, delta: number) => {\n if (size === undefined) setInnerSize(next);\n onSizeChange?.(next, delta);\n },\n [onSizeChange, size],\n );\n\n const options: PanelControllerOptions = {\n collapseThreshold,\n defaultSize: resolvedDefaultSize,\n expand: isExpand,\n max,\n min,\n onExpandChange: setIsExpand,\n onSizeChange: commitSize,\n onSizeDragging,\n placement,\n size: currentSize,\n };\n\n const [controller] = useState(() => createPanelController(options));\n const state = useStore(controller.subscribe, () => controller.state);\n const elementRef = useRef<HTMLElement>(null);\n\n useIsomorphicLayoutEffect(() => {\n controller.sync(options);\n });\n\n useIsomorphicLayoutEffect(() => {\n const node = elementRef.current;\n return node ? controller.attach(node) : undefined;\n }, [controller]);\n\n const toggleExpand = useCallback(() => {\n if (expandable) setIsExpand(!isExpand);\n }, [expandable, isExpand, setIsExpand]);\n\n const context = useMemo(\n () => ({\n axis,\n controller,\n expand: isExpand,\n expandable,\n placement,\n showBorder,\n state,\n toggleExpand,\n }),\n [axis, controller, isExpand, expandable, placement, showBorder, state, toggleExpand],\n );\n\n return (\n <DraggablePanelContext value={context}>\n <aside\n className={cx(rootVariants({ mode, placement }), className)}\n data-expand={isExpand}\n data-expandable={expandable}\n data-resizing={state.dragging}\n ref={elementRef}\n style={\n {\n '--draggable-panel-bg': backgroundColor || '',\n 'flexDirection': axis.vertical ? 'column' : 'row',\n ...style,\n } as CSSProperties\n }\n {...rest}\n >\n {children}\n </aside>\n </DraggablePanelContext>\n );\n },\n);\n\nDraggablePanelRoot.displayName = 'DraggablePanelRoot';\n\nexport interface DraggablePanelContentProps extends Omit<DivProps, 'onDrag'> {}\n\nexport const DraggablePanelContent = memo<DraggablePanelContentProps>(\n ({ children, className, style, ...rest }) => {\n const Motion = useMotionComponent();\n const { axis, controller, expand, placement, state } = useDraggablePanelContext();\n const extent = useTransform(controller.motion.size, (value) => Math.max(0, value));\n // Subscribed, not read: a collapse that changes only the target would otherwise\n // leave the content unclipped and painted outside the zero-width box.\n const target = useStore(controller.subscribe, () => controller.target);\n const clipping = state.dragging || state.folding || target === 0;\n const shrunk = state.collapsing || !expand;\n\n return (\n <Motion.div\n inert={!expand}\n style={\n {\n display: 'flex',\n flexDirection: axis.vertical ? 'column' : 'row',\n flexShrink: 0,\n justifyContent: axis.anchorEnd ? 'flex-end' : 'flex-start',\n overflow: clipping ? 'clip' : 'visible',\n [axis.cross]: '100%',\n [axis.extent]: extent,\n } as MotionStyle\n }\n >\n <Motion.div\n animate={{ scale: shrunk ? COLLAPSED_SCALE : 1 }}\n className={cx(styles.content, className)}\n transition={timing()}\n style={\n {\n transformOrigin: ORIGIN_MAP[placement],\n [axis.cross]: '100%',\n [axis.extent]: controller.motion.content,\n ...style,\n } as MotionStyle\n }\n {...(rest as HTMLMotionProps<'div'>)}\n >\n {children}\n </Motion.div>\n </Motion.div>\n );\n },\n);\n\nDraggablePanelContent.displayName = 'DraggablePanelContent';\n\nexport interface DraggablePanelHandleProps extends Omit<DivProps, 'onDrag'> {\n wideArea?: boolean;\n}\n\nexport const DraggablePanelHandle = memo<DraggablePanelHandleProps>(\n ({ className, style, wideArea = true, ...rest }) => {\n const { axis, controller, expand, showBorder, state } = useDraggablePanelContext();\n const size = useStore(coarsePointer.subscribe, () => getHandleSize(wideArea));\n const target = useStore(controller.subscribe, () => controller.target);\n useEffect(() => () => controller.drag.cancel(), [controller]);\n\n const pressedRef = useRef<{ x: number; y: number } | null>(null);\n const draggingRef = useRef(false);\n const draggedRef = useRef(false);\n const { max, min } = controller.bounds();\n\n if (!expand) return null;\n\n return (\n <div\n aria-orientation={axis.ariaOrientation}\n aria-valuemax={Number.isFinite(max) ? max : undefined}\n aria-valuemin={min}\n aria-valuenow={target}\n aria-valuetext={`${target} pixels`}\n className={cx(handleVariants({ edge: axis.edge }), className)}\n data-border={showBorder}\n data-resizing={state.dragging || undefined}\n role=\"separator\"\n tabIndex={0}\n style={\n {\n '--draggable-panel-handle-size': `${size}px`,\n [EDGE_INSET[axis.edge]]: -size / 2,\n ...style,\n } as CSSProperties\n }\n onKeyDown={(event) => controller.resizeByKey(event)}\n onDoubleClick={() => {\n if (!draggedRef.current) controller.reset();\n }}\n onLostPointerCapture={() => {\n if (draggingRef.current) controller.drag.cancel();\n pressedRef.current = null;\n draggingRef.current = false;\n }}\n onPointerCancel={() => {\n controller.drag.cancel();\n pressedRef.current = null;\n draggingRef.current = false;\n }}\n onPointerDown={(event) => {\n draggedRef.current = false;\n pressedRef.current = { x: event.clientX, y: event.clientY };\n // A synthetic pointerdown carries no active pointer, and capturing throws.\n try {\n event.currentTarget.setPointerCapture(event.pointerId);\n } catch {\n /* empty */\n }\n }}\n onPointerMove={(event) => {\n if (!pressedRef.current) return;\n const offset = {\n x: event.clientX - pressedRef.current.x,\n y: event.clientY - pressedRef.current.y,\n };\n if (!draggingRef.current) {\n if (Math.hypot(offset.x, offset.y) < PAN_THRESHOLD) return;\n draggingRef.current = true;\n draggedRef.current = true;\n controller.drag.start();\n }\n controller.drag.move(offset);\n }}\n onPointerUp={() => {\n if (draggingRef.current) controller.drag.end();\n pressedRef.current = null;\n draggingRef.current = false;\n }}\n {...rest}\n />\n );\n },\n);\n\nDraggablePanelHandle.displayName = 'DraggablePanelHandle';\n\nexport interface DraggablePanelToggleProps extends Omit<DivProps, 'onDrag'> {\n showHandleWhenCollapsed?: boolean;\n}\n\nexport const DraggablePanelToggle = memo<DraggablePanelToggleProps>(\n ({ className, showHandleWhenCollapsed, style, ...rest }) => {\n const { axis, expand, expandable, placement, toggleExpand } = useDraggablePanelContext();\n\n if (!expandable) return null;\n\n const turn = CHEVRON_TURN[placement] + (expand ? 0 : 180);\n const chevX = axis.vertical ? BOW_CY : BOW_CX;\n const chevY = axis.vertical ? BOW_CX : BOW_CY;\n\n return (\n <div\n className={cx(toggleVariants({ placement }), className)}\n style={{ opacity: expand ? undefined : showHandleWhenCollapsed ? 1 : 0, ...style }}\n {...rest}\n >\n <button\n aria-label={expand ? 'Collapse panel' : 'Expand panel'}\n type=\"button\"\n onClick={toggleExpand}\n >\n <svg\n fill=\"none\"\n height={axis.vertical ? BOW_W : BOW_H}\n viewBox={`0 0 ${axis.vertical ? BOW_H : BOW_W} ${axis.vertical ? BOW_W : BOW_H}`}\n width={axis.vertical ? BOW_H : BOW_W}\n >\n {BOW_PATHS[axis.vertical ? 'horizontalSeam' : 'verticalSeam'].map((d) => (\n <path d={d} data-bow=\"\" key={d} strokeLinecap=\"round\" strokeWidth={BOW.stroke} />\n ))}\n <g\n style={{\n rotate: `${turn}deg`,\n transformOrigin: `${chevX}px ${chevY}px`,\n transition: 'rotate 0.25s var(--ant-motion-ease-out, ease)',\n }}\n >\n <path\n d={chevronPath(chevX, chevY)}\n stroke=\"currentColor\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={1.6}\n />\n </g>\n </svg>\n </button>\n </div>\n );\n },\n);\n\nDraggablePanelToggle.displayName = 'DraggablePanelToggle';\n\nexport type DraggablePanelContainerProps = DivProps;\n\nexport const DraggablePanelContainer = memo<DraggablePanelContainerProps>(\n ({ className, ...rest }) => <div className={cx(styles.container, className)} {...rest} />,\n);\n\nDraggablePanelContainer.displayName = 'DraggablePanelContainer';\n\nexport type DraggablePanelBodyProps = DivProps;\n\nexport const DraggablePanelBody = memo<DraggablePanelBodyProps>(({ className, style, ...rest }) => (\n <div className={cx(styles.body, className)} style={{ flex: 1, ...style }} {...rest} />\n));\n\nDraggablePanelBody.displayName = 'DraggablePanelBody';\n\nexport type DraggablePanelFooterProps = DivProps;\n\nexport const DraggablePanelFooter = memo<DraggablePanelFooterProps>(({ className, ...rest }) => (\n <div className={cx(styles.footer, className)} {...rest} />\n));\n\nDraggablePanelFooter.displayName = 'DraggablePanelFooter';\n\nexport interface DraggablePanelHeaderProps extends Omit<DivProps, 'children' | 'title'> {\n extra?: ReactNode;\n onCollapse?: () => void;\n title?: ReactNode;\n}\n\nexport const DraggablePanelHeader = memo<DraggablePanelHeaderProps>(\n ({ className, extra, onCollapse, title, ...rest }) => {\n const { toggleExpand } = useDraggablePanelContext();\n\n return (\n <div className={cx(styles.header, className)} {...rest}>\n <ActionIcon icon={ChevronLeft} size={'small'} onClick={onCollapse ?? toggleExpand} />\n {title}\n {extra}\n </div>\n );\n },\n);\n\nDraggablePanelHeader.displayName = 'DraggablePanelHeader';\n"],"mappings":"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"}
|
|
@@ -24,7 +24,7 @@ declare const styles: {
|
|
|
24
24
|
declare const rootVariants: (props?: ({
|
|
25
25
|
shadow?: boolean | null | undefined;
|
|
26
26
|
size?: "large" | "middle" | "small" | null | undefined;
|
|
27
|
-
variant?: "
|
|
27
|
+
variant?: "filled" | "borderless" | "outlined" | null | undefined;
|
|
28
28
|
} & import("class-variance-authority/types").ClassProp) | undefined) => string;
|
|
29
29
|
//#endregion
|
|
30
30
|
export { rootVariants, styles };
|
|
@@ -42,7 +42,7 @@ declare const variants: (props?: ({
|
|
|
42
42
|
mark?: boolean | null | undefined;
|
|
43
43
|
shiny?: boolean | null | undefined;
|
|
44
44
|
strong?: boolean | null | undefined;
|
|
45
|
-
type?: "danger" | "
|
|
45
|
+
type?: "danger" | "success" | "info" | "warning" | "secondary" | null | undefined;
|
|
46
46
|
underline?: boolean | null | undefined;
|
|
47
47
|
} & import("class-variance-authority/types").ClassProp) | undefined) => string;
|
|
48
48
|
//#endregion
|