@caratlogic/design-system 0.1.10 → 0.1.11
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/dist/components/organisms/MediaGallery/MediaGallery.d.ts +1 -1
- package/dist/components/organisms/MediaGallery/MediaGallery.d.ts.map +1 -1
- package/dist/components/organisms/MediaGallery/MediaGallery.utils.d.ts +6 -0
- package/dist/components/organisms/MediaGallery/MediaGallery.utils.d.ts.map +1 -1
- package/dist/constants/filePatterns.d.ts +3 -0
- package/dist/constants/filePatterns.d.ts.map +1 -1
- package/dist/index.cjs.js +25 -3
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.esm.js +25 -3
- package/dist/index.esm.js.map +1 -1
- package/package.json +1 -1
package/dist/index.esm.js
CHANGED
|
@@ -64641,6 +64641,8 @@ const FILE_TYPE_PATTERNS = {
|
|
|
64641
64641
|
DOCUMENT: /\.(doc|docx|xls|xlsx|ppt|pptx)($|\?)/i,
|
|
64642
64642
|
VIDEO: /\.(mp4|m4v|avi|mov|wmv|flv|webm|mkv|ogv|mpe?g|3gp)($|\?)/i,
|
|
64643
64643
|
AUDIO: /\.(mp3|wav|flac|aac|ogg)($|\?)/i,
|
|
64644
|
+
/** Interactive viewer pages (supplier 360° spinners), not media files. */
|
|
64645
|
+
EMBED: /\.html?($|\?|#)/i,
|
|
64644
64646
|
};
|
|
64645
64647
|
const isFileType = {
|
|
64646
64648
|
pdf: (url) => FILE_TYPE_PATTERNS.PDF.test(url),
|
|
@@ -64648,6 +64650,7 @@ const isFileType = {
|
|
|
64648
64650
|
document: (url) => FILE_TYPE_PATTERNS.DOCUMENT.test(url),
|
|
64649
64651
|
video: (url) => FILE_TYPE_PATTERNS.VIDEO.test(url),
|
|
64650
64652
|
audio: (url) => FILE_TYPE_PATTERNS.AUDIO.test(url),
|
|
64653
|
+
embed: (url) => FILE_TYPE_PATTERNS.EMBED.test(url),
|
|
64651
64654
|
};
|
|
64652
64655
|
|
|
64653
64656
|
/** Seek to ~1st frame for static video thumbnails (HTML5 media fragment). */
|
|
@@ -64663,6 +64666,12 @@ const createVideoMediaItem = (src, index, idPrefix = 'vid') => ({
|
|
|
64663
64666
|
src,
|
|
64664
64667
|
thumbSrc: videoThumbnailSrc(src),
|
|
64665
64668
|
});
|
|
64669
|
+
/**
|
|
64670
|
+
* True when a "video" is really an interactive viewer page. Supplier 360°
|
|
64671
|
+
* spinners (Vision360, Varni) serve `text/html`, so `<video>` renders nothing
|
|
64672
|
+
* and there is no frame to seek for a thumbnail — they need an iframe.
|
|
64673
|
+
*/
|
|
64674
|
+
const isEmbedMediaItem = (item) => item.kind === 'video' && isFileType.embed(item.src);
|
|
64666
64675
|
const isPdfMediaItem = (item) => item.isPdf === true ||
|
|
64667
64676
|
isFileType.pdf(item.src) ||
|
|
64668
64677
|
(item.kind === 'certificate' && !isFileType.image(item.src));
|
|
@@ -65770,9 +65779,22 @@ const PdfPreview = ({ item }) => {
|
|
|
65770
65779
|
const docsViewer = `https://docs.google.com/gview?embedded=1&url=${encodeURIComponent(item.src)}`;
|
|
65771
65780
|
return (jsx("object", { data: item.src, type: "application/pdf", className: "h-full w-full bg-card", "aria-label": item.name ?? 'Certificate PDF', children: jsx("iframe", { title: item.name ?? 'Certificate PDF', className: "h-full w-full border-0 bg-card", src: docsViewer }) }));
|
|
65772
65781
|
};
|
|
65782
|
+
/**
|
|
65783
|
+
* Videos arrive as either a real file or a supplier's 360° viewer page. The URL
|
|
65784
|
+
* settles most cases, but not every viewer ends in `.html` (v360, loupe360),
|
|
65785
|
+
* so a `<video>` that fails to load falls back to the iframe as well. Remounted
|
|
65786
|
+
* per selection via `key`, which resets that fallback.
|
|
65787
|
+
*/
|
|
65788
|
+
const VideoOrEmbed = ({ item }) => {
|
|
65789
|
+
const [useEmbed, setUseEmbed] = useState(() => isEmbedMediaItem(item));
|
|
65790
|
+
if (useEmbed) {
|
|
65791
|
+
return (jsx("iframe", { src: item.src, title: item.name ?? '360\u00B0 viewer', className: "h-full w-full border-0 bg-card", allowFullScreen: true }));
|
|
65792
|
+
}
|
|
65793
|
+
return (jsx("video", { src: item.src, controls: true, onError: () => setUseEmbed(true), className: "h-full w-full object-cover", "aria-label": item.name ?? 'Video' }));
|
|
65794
|
+
};
|
|
65773
65795
|
const MainMedia = ({ item }) => {
|
|
65774
65796
|
if (item.kind === 'video') {
|
|
65775
|
-
return
|
|
65797
|
+
return jsx(VideoOrEmbed, { item: item });
|
|
65776
65798
|
}
|
|
65777
65799
|
if (isPdfMediaItem(item)) {
|
|
65778
65800
|
return jsx(PdfPreview, { item: item });
|
|
@@ -65782,7 +65804,7 @@ const MainMedia = ({ item }) => {
|
|
|
65782
65804
|
const Thumbnail = ({ item, isActive, onSelect }) => {
|
|
65783
65805
|
const Icon = KIND_ICON[item.kind];
|
|
65784
65806
|
const isPdf = isPdfMediaItem(item);
|
|
65785
|
-
const isVideoWithoutThumb = item.kind === 'video' && !item.thumbSrc;
|
|
65807
|
+
const isVideoWithoutThumb = item.kind === 'video' && (!item.thumbSrc || isEmbedMediaItem(item));
|
|
65786
65808
|
return (jsxs("button", { type: "button", onClick: onSelect, "aria-label": `Select ${item.name ?? item.kind}`, "aria-pressed": isActive, className: cn('group relative flex aspect-square w-full cursor-pointer overflow-hidden rounded-lg border transition-colors', isActive
|
|
65787
65809
|
? 'border-primary ring-2 ring-primary/30'
|
|
65788
65810
|
: 'border-border hover:border-primary/40'), children: [isPdf ? (jsxs("span", { className: "flex h-full w-full flex-col items-center justify-center gap-1 bg-muted p-2 text-muted-foreground", children: [jsx(Icon, { size: 20 }), jsx("span", { className: "text-[10px] font-medium uppercase", children: "PDF" })] })) : isVideoWithoutThumb ? (jsx("div", { className: "h-full w-full flex items-center justify-center bg-muted", children: jsx(Icon, { size: 24, className: "text-muted-foreground" }) })) : item.kind === 'video' ? (jsx("video", { src: item.thumbSrc ?? item.src, muted: true, playsInline: true, preload: "metadata", className: "h-full w-full object-cover", "aria-hidden": "true" })) : (jsx("img", { src: item.thumbSrc ?? item.src, alt: "", className: "h-full w-full object-cover" })), !isPdf && item.kind !== 'image' && !isVideoWithoutThumb && (jsx("span", { className: "pointer-events-none absolute inset-0 flex items-center justify-center bg-black/30 text-white", children: jsx(Icon, { size: 20 }) })), isVideoWithoutThumb && (jsx("span", { className: "pointer-events-none absolute inset-0 flex items-center justify-center bg-black/30" }))] }));
|
|
@@ -65803,7 +65825,7 @@ const MediaGallery = ({ items, thumbsVisible = 4, hideTabs = false, mainAspectCl
|
|
|
65803
65825
|
(kinds.length > 0 ? (jsx(Tabs, { value: activeKind ?? undefined, onValueChange: (v) => setActiveKind(v), tabStyle: "boxed", size: "sm", children: jsx(TabsList, { children: kinds.map((kind) => {
|
|
65804
65826
|
const Icon = KIND_ICON[kind];
|
|
65805
65827
|
return (jsx(TabsTrigger, { value: kind, icon: jsx(Icon, { size: 14 }), children: MEDIA_KIND_LABEL[kind] }, kind));
|
|
65806
|
-
}) }) })) : (jsx("div", { className: "h-9", "aria-hidden": "true" }))), selected && isZoomableImage ? (jsxs("div", { className: "relative", children: [jsx(ZoomSplitViewer, { src: selected.src, alt: selected.name ?? 'Media' }), !hideDownload && (jsx("div", { className: "absolute right-3 top-3 z-20", children: jsx("button", { type: "button", onClick: handleDownload, "aria-label": "Download media", className: "inline-flex h-9 w-9 cursor-pointer items-center justify-center rounded-md border border-border bg-card text-foreground transition-all hover:border-primary hover:shadow-[0_0_0_4px_rgba(49,122,81,0.10)] focus-visible:border-primary focus-visible:shadow-[0_0_0_4px_rgba(49,122,81,0.10)] focus-visible:outline-none", children: jsx(Download, { className: "h-4 w-4" }) }) }))] })) : selected ? (jsxs("div", { className: cn('relative overflow-hidden rounded-xl border border-border bg-muted', mainAspectClassName), children: [jsx(MainMedia, { item: selected }), !hideDownload && (jsx("div", { className: "absolute right-3 top-3", children: jsx("button", { type: "button", onClick: handleDownload, "aria-label": "Download media", className: "inline-flex h-9 w-9 cursor-pointer items-center justify-center rounded-md border border-border bg-card text-foreground transition-all hover:border-primary hover:shadow-[0_0_0_4px_rgba(49,122,81,0.10)] focus-visible:border-primary focus-visible:shadow-[0_0_0_4px_rgba(49,122,81,0.10)] focus-visible:outline-none", children: jsx(Download, { className: "h-4 w-4" }) }) }))] })) : (jsx("div", { className: cn('flex items-center justify-center rounded-xl border border-dashed border-border bg-muted/40 text-sm text-muted-foreground', mainAspectClassName), children: emptyText })), visibleItems.length > 1 && (jsx("div", { className: "grid gap-3", style: {
|
|
65828
|
+
}) }) })) : (jsx("div", { className: "h-9", "aria-hidden": "true" }))), selected && isZoomableImage ? (jsxs("div", { className: "relative", children: [jsx(ZoomSplitViewer, { src: selected.src, alt: selected.name ?? 'Media' }), !hideDownload && (jsx("div", { className: "absolute right-3 top-3 z-20", children: jsx("button", { type: "button", onClick: handleDownload, "aria-label": "Download media", className: "inline-flex h-9 w-9 cursor-pointer items-center justify-center rounded-md border border-border bg-card text-foreground transition-all hover:border-primary hover:shadow-[0_0_0_4px_rgba(49,122,81,0.10)] focus-visible:border-primary focus-visible:shadow-[0_0_0_4px_rgba(49,122,81,0.10)] focus-visible:outline-none", children: jsx(Download, { className: "h-4 w-4" }) }) }))] })) : selected ? (jsxs("div", { className: cn('relative overflow-hidden rounded-xl border border-border bg-muted', mainAspectClassName), children: [jsx(MainMedia, { item: selected }, selected.id), !hideDownload && !isEmbedMediaItem(selected) && (jsx("div", { className: "absolute right-3 top-3", children: jsx("button", { type: "button", onClick: handleDownload, "aria-label": "Download media", className: "inline-flex h-9 w-9 cursor-pointer items-center justify-center rounded-md border border-border bg-card text-foreground transition-all hover:border-primary hover:shadow-[0_0_0_4px_rgba(49,122,81,0.10)] focus-visible:border-primary focus-visible:shadow-[0_0_0_4px_rgba(49,122,81,0.10)] focus-visible:outline-none", children: jsx(Download, { className: "h-4 w-4" }) }) }))] })) : (jsx("div", { className: cn('flex items-center justify-center rounded-xl border border-dashed border-border bg-muted/40 text-sm text-muted-foreground', mainAspectClassName), children: emptyText })), visibleItems.length > 1 && (jsx("div", { className: "grid gap-3", style: {
|
|
65807
65829
|
gridTemplateColumns: `repeat(${Math.min(visibleItems.length, thumbsVisible)}, minmax(0, 1fr))`,
|
|
65808
65830
|
}, children: visibleItems.slice(0, thumbsVisible).map((item) => (jsx(Thumbnail, { item: item, isActive: selected?.id === item.id, onSelect: () => setSelected(item) }, item.id))) }))] }));
|
|
65809
65831
|
};
|