@vectara/vectara-ui 9.16.1 → 9.17.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/components/image/Image.d.ts +1 -1
- package/lib/components/image/Image.js +2 -2
- package/lib/components/image/ImagePreview.d.ts +7 -2
- package/lib/components/image/ImagePreview.js +41 -9
- package/lib/components/image/_index.scss +19 -8
- package/lib/styles/index.css +19 -8
- package/package.json +1 -1
|
@@ -7,5 +7,5 @@ type Props = {
|
|
|
7
7
|
isFailure?: boolean;
|
|
8
8
|
allowPreview?: boolean;
|
|
9
9
|
};
|
|
10
|
-
export declare const VuiImage: ({ src, alt, caption, className, isLoading, allowPreview, isFailure
|
|
10
|
+
export declare const VuiImage: ({ src, alt, caption, className, isLoading, allowPreview, isFailure }: Props) => import("react/jsx-runtime").JSX.Element;
|
|
11
11
|
export {};
|
|
@@ -7,7 +7,7 @@ import { VuiText } from "../typography/Text";
|
|
|
7
7
|
import { VuiImagePreview } from "./ImagePreview";
|
|
8
8
|
import { VuiIcon } from "../icon/Icon";
|
|
9
9
|
import { BiImage, BiError } from "react-icons/bi";
|
|
10
|
-
export const VuiImage = ({ src, alt, caption, className, isLoading = false, allowPreview = true, isFailure = false
|
|
10
|
+
export const VuiImage = ({ src, alt, caption, className, isLoading = false, allowPreview = true, isFailure = false }) => {
|
|
11
11
|
const [isPreviewOpen, setIsPreviewOpen] = useState(false);
|
|
12
12
|
const handlePreviewClick = () => {
|
|
13
13
|
if (allowPreview) {
|
|
@@ -23,5 +23,5 @@ export const VuiImage = ({ src, alt, caption, className, isLoading = false, allo
|
|
|
23
23
|
if (isFailure) {
|
|
24
24
|
return (_jsx("div", Object.assign({ className: "vuiImage__placeholder vuiImage__placeholder--error" }, { children: _jsxs(VuiFlexContainer, Object.assign({ direction: "column", alignItems: "center", justifyContent: "center", spacing: "s" }, { children: [_jsx(VuiFlexItem, Object.assign({ grow: false }, { children: _jsx("div", Object.assign({ className: "vuiImage__iconWrapper" }, { children: _jsx(VuiIcon, Object.assign({ size: "m", color: "danger" }, { children: _jsx(BiError, {}) })) })) })), _jsx(VuiFlexItem, Object.assign({ grow: false }, { children: _jsx(VuiText, Object.assign({ size: "s", align: "center" }, { children: _jsx("p", { children: "Missing image" }) })) }))] })) })));
|
|
25
25
|
}
|
|
26
|
-
return (_jsxs(_Fragment, { children: [_jsx(VuiFlexContainer, Object.assign({ direction: "column", spacing: "s" }, { children: _jsxs("figure", { children: [_jsx(VuiFlexItem, Object.assign({ grow: false }, { children: _jsx("div", Object.assign({ className: "vuiImage__imageWrapper" }, { children: _jsx("img", { src: src, alt: alt, className: imageClasses, onClick: handlePreviewClick }) })) })), caption && (_jsx(VuiFlexItem, Object.assign({ grow: false }, { children: _jsx(VuiText, Object.assign({ size: "s" }, { children: _jsx("figcaption", { children: caption }) })) })))] }) })), allowPreview && (_jsx(VuiImagePreview, {
|
|
26
|
+
return (_jsxs(_Fragment, { children: [_jsx(VuiFlexContainer, Object.assign({ direction: "column", spacing: "s" }, { children: _jsxs("figure", { children: [_jsx(VuiFlexItem, Object.assign({ grow: false }, { children: _jsx("div", Object.assign({ className: "vuiImage__imageWrapper" }, { children: _jsx("img", { src: src, alt: alt, className: imageClasses, onClick: handlePreviewClick }) })) })), caption && (_jsx(VuiFlexItem, Object.assign({ grow: false }, { children: _jsx(VuiText, Object.assign({ size: "s" }, { children: _jsx("figcaption", { children: caption }) })) })))] }) })), allowPreview && (_jsx(VuiImagePreview, { images: [{ src, alt, caption }], isOpen: isPreviewOpen, onClose: () => setIsPreviewOpen(false) }))] }));
|
|
27
27
|
};
|
|
@@ -1,9 +1,14 @@
|
|
|
1
|
-
type
|
|
1
|
+
type ImageData = {
|
|
2
2
|
src: string;
|
|
3
3
|
alt?: string;
|
|
4
|
+
caption?: string;
|
|
5
|
+
};
|
|
6
|
+
type Props = {
|
|
7
|
+
images: ImageData[];
|
|
8
|
+
initialIndex?: number;
|
|
4
9
|
isOpen: boolean;
|
|
5
10
|
onClose: () => void;
|
|
6
11
|
className?: string;
|
|
7
12
|
};
|
|
8
|
-
export declare const VuiImagePreview: ({
|
|
13
|
+
export declare const VuiImagePreview: ({ images, initialIndex, isOpen, onClose, className }: Props) => import("react/jsx-runtime").JSX.Element;
|
|
9
14
|
export {};
|
|
@@ -1,27 +1,59 @@
|
|
|
1
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { useEffect, useRef } from "react";
|
|
1
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useEffect, useRef, useState } from "react";
|
|
3
3
|
import { FocusOn } from "react-focus-on";
|
|
4
|
-
import { BiX } from "react-icons/bi";
|
|
4
|
+
import { BiX, BiChevronLeft, BiChevronRight } from "react-icons/bi";
|
|
5
5
|
import { VuiIconButton } from "../button/IconButton";
|
|
6
6
|
import { VuiIcon } from "../icon/Icon";
|
|
7
7
|
import { VuiPortal } from "../portal/Portal";
|
|
8
|
-
import {
|
|
9
|
-
|
|
8
|
+
import { VuiFlexContainer } from "../flex/FlexContainer";
|
|
9
|
+
import { VuiFlexItem } from "../flex/FlexItem";
|
|
10
|
+
import { VuiText } from "../typography/Text";
|
|
11
|
+
import { VuiTextColor } from "../typography/TextColor";
|
|
12
|
+
export const VuiImagePreview = ({ images, initialIndex = 0, isOpen, onClose, className }) => {
|
|
10
13
|
const returnFocusElRef = useRef(null);
|
|
11
|
-
|
|
14
|
+
const [currentIndex, setCurrentIndex] = useState(initialIndex);
|
|
15
|
+
const isCarousel = images.length > 1;
|
|
12
16
|
useEffect(() => {
|
|
13
17
|
var _a;
|
|
14
18
|
if (isOpen) {
|
|
15
19
|
returnFocusElRef.current = document.activeElement;
|
|
20
|
+
setCurrentIndex(initialIndex);
|
|
16
21
|
}
|
|
17
22
|
else {
|
|
18
23
|
(_a = returnFocusElRef.current) === null || _a === void 0 ? void 0 : _a.focus();
|
|
19
24
|
returnFocusElRef.current = null;
|
|
20
25
|
}
|
|
21
|
-
}, [isOpen]);
|
|
22
|
-
|
|
26
|
+
}, [isOpen, initialIndex]);
|
|
27
|
+
useEffect(() => {
|
|
28
|
+
if (!isOpen)
|
|
29
|
+
return;
|
|
30
|
+
const handleKeyDown = (e) => {
|
|
31
|
+
if (e.key === "ArrowLeft") {
|
|
32
|
+
e.preventDefault();
|
|
33
|
+
handlePrevious();
|
|
34
|
+
}
|
|
35
|
+
else if (e.key === "ArrowRight") {
|
|
36
|
+
e.preventDefault();
|
|
37
|
+
handleNext();
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
window.addEventListener("keydown", handleKeyDown);
|
|
41
|
+
return () => window.removeEventListener("keydown", handleKeyDown);
|
|
42
|
+
}, [isOpen, currentIndex]);
|
|
43
|
+
const handlePrevious = () => {
|
|
44
|
+
setCurrentIndex((prev) => (prev > 0 ? prev - 1 : images.length - 1));
|
|
45
|
+
};
|
|
46
|
+
const handleNext = () => {
|
|
47
|
+
setCurrentIndex((prev) => (prev < images.length - 1 ? prev + 1 : 0));
|
|
48
|
+
};
|
|
23
49
|
const handleOnClose = () => {
|
|
24
50
|
onClose === null || onClose === void 0 ? void 0 : onClose();
|
|
25
51
|
};
|
|
26
|
-
return (_jsx(VuiPortal, { children: isOpen && (_jsx("div", Object.assign({ className: className }, { children: _jsx(FocusOn, Object.assign({ onEscapeKey: handleOnClose, returnFocus: false, autoFocus: isOpen }, { children: _jsx(
|
|
52
|
+
return (_jsx(VuiPortal, { children: isOpen && (_jsx("div", Object.assign({ className: className }, { children: _jsx(FocusOn, Object.assign({ onEscapeKey: handleOnClose, returnFocus: false, autoFocus: isOpen }, { children: _jsx("figure", { children: _jsx("div", Object.assign({ className: "vuiImagePreview__container" }, { children: _jsxs("div", Object.assign({ className: "vuiImagePreview__mask", onClick: handleOnClose }, { children: [_jsx("div", Object.assign({ onClick: (e) => e.stopPropagation() }, { children: _jsxs(VuiFlexContainer, Object.assign({ alignItems: "center", justifyContent: "spaceBetween", className: "vuiImagePreview__header" }, { children: [_jsx(VuiFlexItem, { children: _jsxs(VuiFlexContainer, Object.assign({ alignItems: "center", spacing: "xs" }, { children: [isCarousel && (_jsxs(_Fragment, { children: [_jsx(VuiFlexItem, { children: _jsx(VuiIconButton, { "aria-label": "Previous image", onClick: (e) => {
|
|
53
|
+
e.stopPropagation();
|
|
54
|
+
handlePrevious();
|
|
55
|
+
}, color: "neutral", size: "s", icon: _jsx(VuiIcon, Object.assign({ size: "m", color: "empty" }, { children: _jsx(BiChevronLeft, {}) })) }) }), _jsx(VuiFlexItem, { children: _jsx(VuiIconButton, { "aria-label": "Next image", onClick: (e) => {
|
|
56
|
+
e.stopPropagation();
|
|
57
|
+
handleNext();
|
|
58
|
+
}, color: "neutral", size: "s", icon: _jsx(VuiIcon, Object.assign({ size: "m", color: "empty" }, { children: _jsx(BiChevronRight, {}) })) }) })] })), _jsx(VuiFlexItem, { children: _jsx(VuiText, Object.assign({ size: "s" }, { children: _jsx(VuiTextColor, Object.assign({ color: "empty" }, { children: _jsxs("figcaption", { children: [isCarousel && `Image ${currentIndex + 1} of ${images.length}: `, images[currentIndex].caption] }) })) })) })] })) }), _jsx(VuiFlexItem, Object.assign({ grow: false }, { children: _jsx("div", Object.assign({ className: "vuiImagePreview__closeButton" }, { children: _jsx(VuiIconButton, { "aria-label": "Close preview", onClick: handleOnClose, color: "neutral", icon: _jsx(VuiIcon, Object.assign({ size: "l", color: "empty" }, { children: _jsx(BiX, {}) })) }) })) }))] })) })), _jsx("div", Object.assign({ className: "vuiImagePreview__imageContainer" }, { children: _jsx("img", { src: images[currentIndex].src, alt: images[currentIndex].alt, className: "vuiImagePreview__image", draggable: false }) }))] })) })) }) })) }))) }));
|
|
27
59
|
};
|
|
@@ -47,32 +47,43 @@
|
|
|
47
47
|
left: 0;
|
|
48
48
|
right: 0;
|
|
49
49
|
bottom: 0;
|
|
50
|
-
|
|
50
|
+
z-index: $screenBlockZIndex;
|
|
51
51
|
}
|
|
52
52
|
|
|
53
|
-
.
|
|
53
|
+
.vuiImagePreview__mask {
|
|
54
|
+
height: 100%;
|
|
55
|
+
background-color: transparentize($colorFullShade, 0.4);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
.vuiImagePreview__header {
|
|
54
59
|
position: absolute;
|
|
55
|
-
top:
|
|
56
|
-
|
|
60
|
+
top: 0;
|
|
61
|
+
left: 0;
|
|
62
|
+
right: 0;
|
|
63
|
+
height: $sizeL * 2;
|
|
64
|
+
padding: $sizeS $sizeM;
|
|
65
|
+
background-color: $colorFullShade;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
.vuiImagePreview__closeButton {
|
|
57
69
|
pointer-events: all;
|
|
58
|
-
z-index: 1;
|
|
59
70
|
}
|
|
60
71
|
|
|
61
72
|
.vuiImagePreview__imageContainer {
|
|
62
73
|
position: absolute;
|
|
63
|
-
top:
|
|
74
|
+
top: $sizeL * 2;
|
|
64
75
|
left: 0;
|
|
65
76
|
right: 0;
|
|
66
|
-
bottom: 0;
|
|
67
77
|
display: flex;
|
|
68
78
|
align-items: center;
|
|
69
79
|
justify-content: center;
|
|
70
80
|
overflow: visible;
|
|
81
|
+
height: calc(100vh - #{$sizeL * 2});
|
|
71
82
|
}
|
|
72
83
|
|
|
73
84
|
.vuiImagePreview__image {
|
|
74
85
|
max-width: calc(100vw - #{$sizeXl * 2});
|
|
75
|
-
max-height: calc(100vh - #{$
|
|
86
|
+
max-height: calc(100vh - #{$sizeL * 4});
|
|
76
87
|
width: auto;
|
|
77
88
|
height: auto;
|
|
78
89
|
object-fit: contain;
|
package/lib/styles/index.css
CHANGED
|
@@ -3002,32 +3002,43 @@ h2.react-datepicker__current-month {
|
|
|
3002
3002
|
left: 0;
|
|
3003
3003
|
right: 0;
|
|
3004
3004
|
bottom: 0;
|
|
3005
|
-
|
|
3005
|
+
z-index: 10;
|
|
3006
3006
|
}
|
|
3007
3007
|
|
|
3008
|
-
.
|
|
3008
|
+
.vuiImagePreview__mask {
|
|
3009
|
+
height: 100%;
|
|
3010
|
+
background-color: rgba(11, 12, 14, 0.6);
|
|
3011
|
+
}
|
|
3012
|
+
|
|
3013
|
+
.vuiImagePreview__header {
|
|
3009
3014
|
position: absolute;
|
|
3010
|
-
top:
|
|
3011
|
-
|
|
3015
|
+
top: 0;
|
|
3016
|
+
left: 0;
|
|
3017
|
+
right: 0;
|
|
3018
|
+
height: 48px;
|
|
3019
|
+
padding: 12px 16px;
|
|
3020
|
+
background-color: #0b0c0e;
|
|
3021
|
+
}
|
|
3022
|
+
|
|
3023
|
+
.vuiImagePreview__closeButton {
|
|
3012
3024
|
pointer-events: all;
|
|
3013
|
-
z-index: 1;
|
|
3014
3025
|
}
|
|
3015
3026
|
|
|
3016
3027
|
.vuiImagePreview__imageContainer {
|
|
3017
3028
|
position: absolute;
|
|
3018
|
-
top:
|
|
3029
|
+
top: 48px;
|
|
3019
3030
|
left: 0;
|
|
3020
3031
|
right: 0;
|
|
3021
|
-
bottom: 0;
|
|
3022
3032
|
display: flex;
|
|
3023
3033
|
align-items: center;
|
|
3024
3034
|
justify-content: center;
|
|
3025
3035
|
overflow: visible;
|
|
3036
|
+
height: calc(100vh - 48px);
|
|
3026
3037
|
}
|
|
3027
3038
|
|
|
3028
3039
|
.vuiImagePreview__image {
|
|
3029
3040
|
max-width: calc(100vw - 64px);
|
|
3030
|
-
max-height: calc(100vh -
|
|
3041
|
+
max-height: calc(100vh - 96px);
|
|
3031
3042
|
width: auto;
|
|
3032
3043
|
height: auto;
|
|
3033
3044
|
object-fit: contain;
|