@chayns-components/gallery 5.5.30 → 5.5.33-alpha.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.
Files changed (63) hide show
  1. package/AGENTS.md +2 -0
  2. package/lib/cjs/components/Gallery.js +4 -1
  3. package/lib/cjs/components/Gallery.js.map +1 -1
  4. package/lib/cjs/components/Gallery.types.js.map +1 -1
  5. package/lib/cjs/components/gallery-editor/GalleryEditor.js +11 -5
  6. package/lib/cjs/components/gallery-editor/GalleryEditor.js.map +1 -1
  7. package/lib/cjs/components/gallery-editor/GalleryEditor.types.js.map +1 -1
  8. package/lib/cjs/components/gallery-editor/add-file/AddFile.js +16 -2
  9. package/lib/cjs/components/gallery-editor/add-file/AddFile.js.map +1 -1
  10. package/lib/cjs/components/gallery-editor/add-file/AddFile.types.js.map +1 -1
  11. package/lib/cjs/components/gallery-editor/gallery-editor-item/GalleryEditorItem.js +16 -2
  12. package/lib/cjs/components/gallery-editor/gallery-editor-item/GalleryEditorItem.js.map +1 -1
  13. package/lib/cjs/components/gallery-editor/gallery-editor-item/GalleryEditorItem.types.js.map +1 -1
  14. package/lib/cjs/components/gallery-editor/gallery-editor-item/gallery-editor-media-item/GalleryEditorMediaItem.js +3 -1
  15. package/lib/cjs/components/gallery-editor/gallery-editor-item/gallery-editor-media-item/GalleryEditorMediaItem.js.map +1 -1
  16. package/lib/cjs/components/gallery-editor/gallery-editor-item/gallery-editor-media-item/GalleryEditorMediaItem.types.js.map +1 -1
  17. package/lib/cjs/components/gallery-viewer/GalleryViewer.js +2 -0
  18. package/lib/cjs/components/gallery-viewer/GalleryViewer.js.map +1 -1
  19. package/lib/cjs/components/gallery-viewer/GalleryViewer.types.js.map +1 -1
  20. package/lib/cjs/components/gallery-viewer/gallery-viewer-item/GalleryViewerItem.js +4 -2
  21. package/lib/cjs/components/gallery-viewer/gallery-viewer-item/GalleryViewerItem.js.map +1 -1
  22. package/lib/cjs/components/gallery-viewer/gallery-viewer-item/GalleryViewerItem.types.js.map +1 -1
  23. package/lib/cjs/components/media-content/MediaContent.js +20 -1
  24. package/lib/cjs/components/media-content/MediaContent.js.map +1 -1
  25. package/lib/cjs/components/media-content/MediaContent.types.js.map +1 -1
  26. package/lib/cjs/constants/textStrings.js +17 -0
  27. package/lib/cjs/constants/textStrings.js.map +1 -0
  28. package/lib/esm/components/Gallery.js +4 -1
  29. package/lib/esm/components/Gallery.js.map +1 -1
  30. package/lib/esm/components/Gallery.types.js.map +1 -1
  31. package/lib/esm/components/gallery-editor/GalleryEditor.js +11 -5
  32. package/lib/esm/components/gallery-editor/GalleryEditor.js.map +1 -1
  33. package/lib/esm/components/gallery-editor/GalleryEditor.types.js.map +1 -1
  34. package/lib/esm/components/gallery-editor/add-file/AddFile.js +18 -4
  35. package/lib/esm/components/gallery-editor/add-file/AddFile.js.map +1 -1
  36. package/lib/esm/components/gallery-editor/add-file/AddFile.types.js.map +1 -1
  37. package/lib/esm/components/gallery-editor/gallery-editor-item/GalleryEditorItem.js +18 -4
  38. package/lib/esm/components/gallery-editor/gallery-editor-item/GalleryEditorItem.js.map +1 -1
  39. package/lib/esm/components/gallery-editor/gallery-editor-item/GalleryEditorItem.types.js.map +1 -1
  40. package/lib/esm/components/gallery-editor/gallery-editor-item/gallery-editor-media-item/GalleryEditorMediaItem.js +3 -1
  41. package/lib/esm/components/gallery-editor/gallery-editor-item/gallery-editor-media-item/GalleryEditorMediaItem.js.map +1 -1
  42. package/lib/esm/components/gallery-editor/gallery-editor-item/gallery-editor-media-item/GalleryEditorMediaItem.types.js.map +1 -1
  43. package/lib/esm/components/gallery-viewer/GalleryViewer.js +2 -0
  44. package/lib/esm/components/gallery-viewer/GalleryViewer.js.map +1 -1
  45. package/lib/esm/components/gallery-viewer/GalleryViewer.types.js.map +1 -1
  46. package/lib/esm/components/gallery-viewer/gallery-viewer-item/GalleryViewerItem.js +4 -2
  47. package/lib/esm/components/gallery-viewer/gallery-viewer-item/GalleryViewerItem.js.map +1 -1
  48. package/lib/esm/components/gallery-viewer/gallery-viewer-item/GalleryViewerItem.types.js.map +1 -1
  49. package/lib/esm/components/media-content/MediaContent.js +21 -2
  50. package/lib/esm/components/media-content/MediaContent.js.map +1 -1
  51. package/lib/esm/components/media-content/MediaContent.types.js.map +1 -1
  52. package/lib/esm/constants/textStrings.js +11 -0
  53. package/lib/esm/constants/textStrings.js.map +1 -0
  54. package/lib/types/components/Gallery.types.d.ts +4 -0
  55. package/lib/types/components/gallery-editor/GalleryEditor.types.d.ts +4 -0
  56. package/lib/types/components/gallery-editor/add-file/AddFile.types.d.ts +4 -0
  57. package/lib/types/components/gallery-editor/gallery-editor-item/GalleryEditorItem.types.d.ts +4 -0
  58. package/lib/types/components/gallery-editor/gallery-editor-item/gallery-editor-media-item/GalleryEditorMediaItem.types.d.ts +4 -0
  59. package/lib/types/components/gallery-viewer/GalleryViewer.types.d.ts +4 -0
  60. package/lib/types/components/gallery-viewer/gallery-viewer-item/GalleryViewerItem.types.d.ts +4 -0
  61. package/lib/types/components/media-content/MediaContent.types.d.ts +4 -0
  62. package/lib/types/constants/textStrings.d.ts +11 -0
  63. package/package.json +4 -3
@@ -18,6 +18,7 @@ const MediaContent = ({
18
18
  ratio,
19
19
  onClick,
20
20
  shouldLoadImages = true,
21
+ shouldEnableKeyboardHighlighting,
21
22
  playIconSize = 50
22
23
  }) => {
23
24
  const isVideo = (0, _MediaContent2.isVideoFile)(file);
@@ -27,6 +28,7 @@ const MediaContent = ({
27
28
  const [resolvedFinalSourceUrl, setResolvedFinalSourceUrl] = (0, _react.useState)();
28
29
  const [containerElement, setContainerElement] = (0, _react.useState)(null);
29
30
  const imageRef = (0, _react.useRef)(null);
31
+ const contentRef = (0, _react.useRef)(null);
30
32
  const videoRef = (0, _react.useRef)(null);
31
33
  const renderSize = (0, _useMediaContentSize.default)(containerElement);
32
34
  const devicePixelRatio = typeof window !== 'undefined' && Number.isFinite(window.devicePixelRatio) && window.devicePixelRatio > 0 ? window.devicePixelRatio : 1;
@@ -73,9 +75,21 @@ const MediaContent = ({
73
75
  }, [finalSourceUrl, isVideo, shouldLoadImages]);
74
76
  const shouldRenderFinalImage = shouldLoadImages && Boolean(finalSourceUrl);
75
77
  const shouldShowPreview = Boolean(displayPreviewUrl);
78
+ const shouldShowKeyboardHighlighting = (0, _core.useKeyboardFocusHighlighting)(shouldEnableKeyboardHighlighting);
79
+ (0, _core.useFocusRingPortal)(contentRef, {
80
+ isEnabled: shouldShowKeyboardHighlighting
81
+ });
82
+ const handleKeyDown = event => {
83
+ if (event.key === 'Enter' || event.key === ' ') {
84
+ event.preventDefault();
85
+ onClick();
86
+ }
87
+ };
76
88
  if (isVideo) {
77
89
  return /*#__PURE__*/_react.default.createElement(_MediaContent.StyledMediaContentVideoWrapper, {
78
90
  ref: setContainerElement,
91
+ tabIndex: 0,
92
+ onKeyDown: handleKeyDown,
79
93
  onClick: onClick,
80
94
  $ratio: ratio
81
95
  }, displayPreviewUrl && /*#__PURE__*/_react.default.createElement(_MediaContent.StyledMediaContentPreviewImage, {
@@ -99,7 +113,12 @@ const MediaContent = ({
99
113
  })));
100
114
  }
101
115
  return /*#__PURE__*/_react.default.createElement(_MediaContent.StyledMediaContentImageWrapper, {
102
- ref: setContainerElement,
116
+ ref: element => {
117
+ setContainerElement(element);
118
+ contentRef.current = element;
119
+ },
120
+ tabIndex: 0,
121
+ onKeyDown: handleKeyDown,
103
122
  onClick: onClick,
104
123
  $ratio: ratio
105
124
  }, shouldShowPreview && /*#__PURE__*/_react.default.createElement(_MediaContent.StyledMediaContentPreviewImage, {
@@ -1 +1 @@
1
- {"version":3,"file":"MediaContent.js","names":["_core","require","_react","_interopRequireWildcard","_MediaContent","_MediaContent2","_MediaContent3","_useMediaContentSize","_interopRequireDefault","e","__esModule","default","t","WeakMap","r","n","o","i","f","__proto__","has","get","set","hasOwnProperty","call","Object","defineProperty","getOwnPropertyDescriptor","MediaContent","file","previewUrl","ratio","onClick","shouldLoadImages","playIconSize","isVideo","isVideoFile","sourceKey","getMediaSourceUrl","previewSourceUrl","getMediaPreviewUrl","hasLoadedFinalMedia","setHasLoadedFinalMedia","useState","resolvedFinalSourceUrl","setResolvedFinalSourceUrl","containerElement","setContainerElement","imageRef","useRef","videoRef","renderSize","useMediaContentSize","devicePixelRatio","window","Number","isFinite","displayPreviewUrl","useMemo","getResponsiveImageServiceUrl","undefined","finalSourceUrl","shouldHidePreview","previewLayerStyle","opacity","filter","finalMediaStyle","transition","MEDIA_CONTENT_IMAGE_FADE_DURATION_MS","useEffect","_imageRef$current","_videoRef$current","current","complete","naturalWidth","readyState","shouldRenderFinalImage","Boolean","shouldShowPreview","createElement","StyledMediaContentVideoWrapper","ref","$ratio","StyledMediaContentPreviewImage","draggable","src","alt","style","StyledMediaContentPlayIcon","Icon","size","icons","StyledMediaContentVideo","poster","preload","onLoadedData","type","StyledMediaContentImageWrapper","StyledMediaContentImage","onLoad","displayName","_default","exports","memo"],"sources":["../../../../src/components/media-content/MediaContent.tsx"],"sourcesContent":["import { Icon } from '@chayns-components/core';\nimport React, { FC, memo, useEffect, useMemo, useRef, useState } from 'react';\nimport {\n StyledMediaContentImage,\n StyledMediaContentImageWrapper,\n StyledMediaContentPlayIcon,\n StyledMediaContentPreviewImage,\n StyledMediaContentVideo,\n StyledMediaContentVideoWrapper,\n} from './MediaContent.styles';\nimport type { MediaContentProps } from './MediaContent.types';\nimport {\n getMediaPreviewUrl,\n getMediaSourceUrl,\n getResponsiveImageServiceUrl,\n isVideoFile,\n} from './MediaContent.utils';\nimport { MEDIA_CONTENT_IMAGE_FADE_DURATION_MS } from './MediaContent.constants';\nimport useMediaContentSize from './useMediaContentSize';\n\nconst MediaContent: FC<MediaContentProps> = ({\n file,\n previewUrl,\n ratio,\n onClick,\n shouldLoadImages = true,\n playIconSize = 50,\n}) => {\n const isVideo = isVideoFile(file);\n const sourceKey = getMediaSourceUrl(file);\n const previewSourceUrl = getMediaPreviewUrl(file, previewUrl);\n const [hasLoadedFinalMedia, setHasLoadedFinalMedia] = useState(false);\n const [resolvedFinalSourceUrl, setResolvedFinalSourceUrl] = useState<string>();\n const [containerElement, setContainerElement] = useState<HTMLDivElement | null>(null);\n const imageRef = useRef<HTMLImageElement>(null);\n const videoRef = useRef<HTMLVideoElement>(null);\n const renderSize = useMediaContentSize(containerElement);\n const devicePixelRatio =\n typeof window !== 'undefined' &&\n Number.isFinite(window.devicePixelRatio) &&\n window.devicePixelRatio > 0\n ? window.devicePixelRatio\n : 1;\n const displayPreviewUrl = useMemo(\n () =>\n previewSourceUrl\n ? getResponsiveImageServiceUrl(previewSourceUrl, renderSize, devicePixelRatio)\n : undefined,\n [devicePixelRatio, previewSourceUrl, renderSize],\n );\n const finalSourceUrl = isVideo ? sourceKey : resolvedFinalSourceUrl;\n const shouldHidePreview = shouldLoadImages && hasLoadedFinalMedia;\n const previewLayerStyle = {\n opacity: shouldHidePreview ? 0 : 1,\n filter: shouldHidePreview ? 'blur(0px)' : undefined,\n };\n const finalMediaStyle = {\n opacity: hasLoadedFinalMedia || !displayPreviewUrl ? 1 : 0,\n transition: `opacity ${MEDIA_CONTENT_IMAGE_FADE_DURATION_MS}ms ease`,\n };\n\n useEffect(() => {\n setHasLoadedFinalMedia(false);\n }, [sourceKey]);\n\n useEffect(() => {\n if (!shouldLoadImages) {\n setResolvedFinalSourceUrl(undefined);\n return;\n }\n\n if (isVideo) {\n setResolvedFinalSourceUrl(sourceKey);\n return;\n }\n\n if (!renderSize) {\n setResolvedFinalSourceUrl(undefined);\n return;\n }\n\n setResolvedFinalSourceUrl(\n getResponsiveImageServiceUrl(sourceKey, renderSize, devicePixelRatio),\n );\n }, [devicePixelRatio, isVideo, renderSize, shouldLoadImages, sourceKey]);\n\n useEffect(() => {\n if (!shouldLoadImages || !finalSourceUrl) {\n return;\n }\n\n if (!isVideo && imageRef.current?.complete && imageRef.current.naturalWidth > 0) {\n setHasLoadedFinalMedia(true);\n }\n\n if (isVideo && videoRef.current?.readyState && videoRef.current.readyState >= 2) {\n setHasLoadedFinalMedia(true);\n }\n }, [finalSourceUrl, isVideo, shouldLoadImages]);\n\n const shouldRenderFinalImage = shouldLoadImages && Boolean(finalSourceUrl);\n const shouldShowPreview = Boolean(displayPreviewUrl);\n\n if (isVideo) {\n return (\n <StyledMediaContentVideoWrapper\n ref={setContainerElement}\n onClick={onClick}\n $ratio={ratio}\n >\n {displayPreviewUrl && (\n <StyledMediaContentPreviewImage\n draggable={false}\n src={displayPreviewUrl}\n alt=\"\"\n aria-hidden=\"true\"\n style={previewLayerStyle}\n />\n )}\n <StyledMediaContentPlayIcon>\n <Icon size={playIconSize} icons={['fa fa-play']} />\n </StyledMediaContentPlayIcon>\n {shouldRenderFinalImage && (\n <StyledMediaContentVideo\n ref={videoRef}\n poster={displayPreviewUrl}\n preload=\"metadata\"\n onLoadedData={() => setHasLoadedFinalMedia(true)}\n style={finalMediaStyle}\n >\n <source src={finalSourceUrl} type=\"video/mp4\" />\n </StyledMediaContentVideo>\n )}\n </StyledMediaContentVideoWrapper>\n );\n }\n\n return (\n <StyledMediaContentImageWrapper ref={setContainerElement} onClick={onClick} $ratio={ratio}>\n {shouldShowPreview && (\n <StyledMediaContentPreviewImage\n draggable={false}\n src={displayPreviewUrl}\n alt=\"\"\n aria-hidden=\"true\"\n style={previewLayerStyle}\n />\n )}\n {shouldRenderFinalImage && (\n <StyledMediaContentImage\n ref={imageRef}\n draggable={false}\n src={finalSourceUrl}\n alt=\"\"\n onLoad={() => setHasLoadedFinalMedia(true)}\n style={finalMediaStyle}\n />\n )}\n </StyledMediaContentImageWrapper>\n );\n};\n\nMediaContent.displayName = 'MediaContent';\n\nexport default memo(MediaContent);\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"file":"MediaContent.js","names":["_core","require","_react","_interopRequireWildcard","_MediaContent","_MediaContent2","_MediaContent3","_useMediaContentSize","_interopRequireDefault","e","__esModule","default","t","WeakMap","r","n","o","i","f","__proto__","has","get","set","hasOwnProperty","call","Object","defineProperty","getOwnPropertyDescriptor","MediaContent","file","previewUrl","ratio","onClick","shouldLoadImages","shouldEnableKeyboardHighlighting","playIconSize","isVideo","isVideoFile","sourceKey","getMediaSourceUrl","previewSourceUrl","getMediaPreviewUrl","hasLoadedFinalMedia","setHasLoadedFinalMedia","useState","resolvedFinalSourceUrl","setResolvedFinalSourceUrl","containerElement","setContainerElement","imageRef","useRef","contentRef","videoRef","renderSize","useMediaContentSize","devicePixelRatio","window","Number","isFinite","displayPreviewUrl","useMemo","getResponsiveImageServiceUrl","undefined","finalSourceUrl","shouldHidePreview","previewLayerStyle","opacity","filter","finalMediaStyle","transition","MEDIA_CONTENT_IMAGE_FADE_DURATION_MS","useEffect","_imageRef$current","_videoRef$current","current","complete","naturalWidth","readyState","shouldRenderFinalImage","Boolean","shouldShowPreview","shouldShowKeyboardHighlighting","useKeyboardFocusHighlighting","useFocusRingPortal","isEnabled","handleKeyDown","event","key","preventDefault","createElement","StyledMediaContentVideoWrapper","ref","tabIndex","onKeyDown","$ratio","StyledMediaContentPreviewImage","draggable","src","alt","style","StyledMediaContentPlayIcon","Icon","size","icons","StyledMediaContentVideo","poster","preload","onLoadedData","type","StyledMediaContentImageWrapper","element","StyledMediaContentImage","onLoad","displayName","_default","exports","memo"],"sources":["../../../../src/components/media-content/MediaContent.tsx"],"sourcesContent":["import { Icon, useFocusRingPortal, useKeyboardFocusHighlighting } from '@chayns-components/core';\nimport React, { FC, KeyboardEventHandler, memo, useEffect, useMemo, useRef, useState } from 'react';\nimport {\n StyledMediaContentImage,\n StyledMediaContentImageWrapper,\n StyledMediaContentPlayIcon,\n StyledMediaContentPreviewImage,\n StyledMediaContentVideo,\n StyledMediaContentVideoWrapper,\n} from './MediaContent.styles';\nimport type { MediaContentProps } from './MediaContent.types';\nimport {\n getMediaPreviewUrl,\n getMediaSourceUrl,\n getResponsiveImageServiceUrl,\n isVideoFile,\n} from './MediaContent.utils';\nimport { MEDIA_CONTENT_IMAGE_FADE_DURATION_MS } from './MediaContent.constants';\nimport useMediaContentSize from './useMediaContentSize';\n\nconst MediaContent: FC<MediaContentProps> = ({\n file,\n previewUrl,\n ratio,\n onClick,\n shouldLoadImages = true,\n shouldEnableKeyboardHighlighting,\n playIconSize = 50,\n}) => {\n const isVideo = isVideoFile(file);\n const sourceKey = getMediaSourceUrl(file);\n const previewSourceUrl = getMediaPreviewUrl(file, previewUrl);\n const [hasLoadedFinalMedia, setHasLoadedFinalMedia] = useState(false);\n const [resolvedFinalSourceUrl, setResolvedFinalSourceUrl] = useState<string>();\n const [containerElement, setContainerElement] = useState<HTMLDivElement | null>(null);\n const imageRef = useRef<HTMLImageElement>(null);\n const contentRef = useRef<HTMLDivElement | null>(null);\n const videoRef = useRef<HTMLVideoElement>(null);\n const renderSize = useMediaContentSize(containerElement);\n const devicePixelRatio =\n typeof window !== 'undefined' &&\n Number.isFinite(window.devicePixelRatio) &&\n window.devicePixelRatio > 0\n ? window.devicePixelRatio\n : 1;\n const displayPreviewUrl = useMemo(\n () =>\n previewSourceUrl\n ? getResponsiveImageServiceUrl(previewSourceUrl, renderSize, devicePixelRatio)\n : undefined,\n [devicePixelRatio, previewSourceUrl, renderSize],\n );\n const finalSourceUrl = isVideo ? sourceKey : resolvedFinalSourceUrl;\n const shouldHidePreview = shouldLoadImages && hasLoadedFinalMedia;\n const previewLayerStyle = {\n opacity: shouldHidePreview ? 0 : 1,\n filter: shouldHidePreview ? 'blur(0px)' : undefined,\n };\n const finalMediaStyle = {\n opacity: hasLoadedFinalMedia || !displayPreviewUrl ? 1 : 0,\n transition: `opacity ${MEDIA_CONTENT_IMAGE_FADE_DURATION_MS}ms ease`,\n };\n\n useEffect(() => {\n setHasLoadedFinalMedia(false);\n }, [sourceKey]);\n\n useEffect(() => {\n if (!shouldLoadImages) {\n setResolvedFinalSourceUrl(undefined);\n return;\n }\n\n if (isVideo) {\n setResolvedFinalSourceUrl(sourceKey);\n return;\n }\n\n if (!renderSize) {\n setResolvedFinalSourceUrl(undefined);\n return;\n }\n\n setResolvedFinalSourceUrl(\n getResponsiveImageServiceUrl(sourceKey, renderSize, devicePixelRatio),\n );\n }, [devicePixelRatio, isVideo, renderSize, shouldLoadImages, sourceKey]);\n\n useEffect(() => {\n if (!shouldLoadImages || !finalSourceUrl) {\n return;\n }\n\n if (!isVideo && imageRef.current?.complete && imageRef.current.naturalWidth > 0) {\n setHasLoadedFinalMedia(true);\n }\n\n if (isVideo && videoRef.current?.readyState && videoRef.current.readyState >= 2) {\n setHasLoadedFinalMedia(true);\n }\n }, [finalSourceUrl, isVideo, shouldLoadImages]);\n\n const shouldRenderFinalImage = shouldLoadImages && Boolean(finalSourceUrl);\n const shouldShowPreview = Boolean(displayPreviewUrl);\n const shouldShowKeyboardHighlighting = useKeyboardFocusHighlighting(\n shouldEnableKeyboardHighlighting,\n );\n useFocusRingPortal(contentRef, { isEnabled: shouldShowKeyboardHighlighting });\n\n const handleKeyDown = ((event) => {\n if (event.key === 'Enter' || event.key === ' ') {\n event.preventDefault();\n onClick();\n }\n }) as KeyboardEventHandler<HTMLDivElement>;\n\n if (isVideo) {\n return (\n <StyledMediaContentVideoWrapper\n ref={setContainerElement}\n tabIndex={0}\n onKeyDown={handleKeyDown}\n onClick={onClick}\n $ratio={ratio}\n >\n {displayPreviewUrl && (\n <StyledMediaContentPreviewImage\n draggable={false}\n src={displayPreviewUrl}\n alt=\"\"\n aria-hidden=\"true\"\n style={previewLayerStyle}\n />\n )}\n <StyledMediaContentPlayIcon>\n <Icon size={playIconSize} icons={['fa fa-play']} />\n </StyledMediaContentPlayIcon>\n {shouldRenderFinalImage && (\n <StyledMediaContentVideo\n ref={videoRef}\n poster={displayPreviewUrl}\n preload=\"metadata\"\n onLoadedData={() => setHasLoadedFinalMedia(true)}\n style={finalMediaStyle}\n >\n <source src={finalSourceUrl} type=\"video/mp4\" />\n </StyledMediaContentVideo>\n )}\n </StyledMediaContentVideoWrapper>\n );\n }\n\n return (\n <StyledMediaContentImageWrapper\n ref={(element) => {\n setContainerElement(element);\n contentRef.current = element;\n }}\n tabIndex={0}\n onKeyDown={handleKeyDown}\n onClick={onClick}\n $ratio={ratio}\n >\n {shouldShowPreview && (\n <StyledMediaContentPreviewImage\n draggable={false}\n src={displayPreviewUrl}\n alt=\"\"\n aria-hidden=\"true\"\n style={previewLayerStyle}\n />\n )}\n {shouldRenderFinalImage && (\n <StyledMediaContentImage\n ref={imageRef}\n draggable={false}\n src={finalSourceUrl}\n alt=\"\"\n onLoad={() => setHasLoadedFinalMedia(true)}\n style={finalMediaStyle}\n />\n )}\n </StyledMediaContentImageWrapper>\n );\n};\n\nMediaContent.displayName = 'MediaContent';\n\nexport default memo(MediaContent);\n"],"mappings":"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","ignoreList":[]}
@@ -1 +1 @@
1
- {"version":3,"file":"MediaContent.types.js","names":[],"sources":["../../../../src/components/media-content/MediaContent.types.ts"],"sourcesContent":["import type { FileItem } from '@chayns-components/core';\n\n/**\n * Props for the low-level uploaded media renderer shared by viewer and editor.\n */\nexport interface MediaContentProps {\n /**\n * Provides the uploaded media item that should be rendered.\n * @description\n * This low-level renderer accepts already known image or video data and does not handle upload-specific state.\n * @example\n * <MediaContent file={file.file} onClick={handleOpen} ratio={1} />\n */\n file: FileItem['file'];\n /**\n * Provides an optional preview source that can be displayed while the final media is still loading.\n * @description\n * This preview can be a base64 data URL or any low-resolution fallback image.\n * When provided, the component shows the preview first and swaps to the final image once it has finished loading.\n * @optional\n */\n previewUrl?: string;\n /**\n * Defines the aspect ratio that should be reserved for the media.\n * @description\n * The surrounding tile uses this value to reserve a deterministic media height before the asset finishes loading.\n * @example\n * <MediaContent file={file.file} onClick={handleOpen} ratio={1.5} />\n */\n ratio: number;\n /**\n * Controls whether the final media source may be loaded immediately.\n * @description\n * When set to `false`, only the preview source is rendered until this flag becomes `true`.\n * @default true\n * @optional\n */\n shouldLoadImages?: boolean;\n /**\n * Is called when the media tile is selected.\n * @description\n * Use this callback to react to clicks on the rendered image or video tile.\n * @example\n * <MediaContent file={file.file} onClick={() => console.log('open')} ratio={1} />\n */\n onClick: () => void;\n /**\n * Defines the size of the video play icon.\n * @description\n * This prop only affects rendered videos. Image tiles ignore it.\n * @default 50\n * @example\n * <MediaContent file={file.file} onClick={handleOpen} playIconSize={30} ratio={1} />\n * @optional\n */\n playIconSize?: number;\n}\n"],"mappings":"","ignoreList":[]}
1
+ {"version":3,"file":"MediaContent.types.js","names":[],"sources":["../../../../src/components/media-content/MediaContent.types.ts"],"sourcesContent":["import type { FileItem } from '@chayns-components/core';\n\n/**\n * Props for the low-level uploaded media renderer shared by viewer and editor.\n */\nexport interface MediaContentProps {\n /**\n * Provides the uploaded media item that should be rendered.\n * @description\n * This low-level renderer accepts already known image or video data and does not handle upload-specific state.\n * @example\n * <MediaContent file={file.file} onClick={handleOpen} ratio={1} />\n */\n file: FileItem['file'];\n /**\n * Provides an optional preview source that can be displayed while the final media is still loading.\n * @description\n * This preview can be a base64 data URL or any low-resolution fallback image.\n * When provided, the component shows the preview first and swaps to the final image once it has finished loading.\n * @optional\n */\n previewUrl?: string;\n /**\n * Defines the aspect ratio that should be reserved for the media.\n * @description\n * The surrounding tile uses this value to reserve a deterministic media height before the asset finishes loading.\n * @example\n * <MediaContent file={file.file} onClick={handleOpen} ratio={1.5} />\n */\n ratio: number;\n /**\n * Controls whether the final media source may be loaded immediately.\n * @description\n * When set to `false`, only the preview source is rendered until this flag becomes `true`.\n * @default true\n * @optional\n */\n shouldLoadImages?: boolean;\n /**\n * Enables keyboard-only focus highlighting for the media tile.\n */\n shouldEnableKeyboardHighlighting?: boolean;\n /**\n * Is called when the media tile is selected.\n * @description\n * Use this callback to react to clicks on the rendered image or video tile.\n * @example\n * <MediaContent file={file.file} onClick={() => console.log('open')} ratio={1} />\n */\n onClick: () => void;\n /**\n * Defines the size of the video play icon.\n * @description\n * This prop only affects rendered videos. Image tiles ignore it.\n * @default 50\n * @example\n * <MediaContent file={file.file} onClick={handleOpen} playIconSize={30} ratio={1} />\n * @optional\n */\n playIconSize?: number;\n}\n"],"mappings":"","ignoreList":[]}
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = void 0;
7
+ var _default = exports.default = {
8
+ galleryEditor: {
9
+ accessibility: {
10
+ removeImage: {
11
+ stringName: 'txt_chayns_components_gallery_galleryEditor_accessibility_removeImage',
12
+ fallback: 'Bild entfernen'
13
+ }
14
+ }
15
+ }
16
+ };
17
+ //# sourceMappingURL=textStrings.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"textStrings.js","names":["galleryEditor","accessibility","removeImage","stringName","fallback"],"sources":["../../../src/constants/textStrings.ts"],"sourcesContent":["export default {\n galleryEditor: {\n accessibility: {\n removeImage: {\n stringName: 'txt_chayns_components_gallery_galleryEditor_accessibility_removeImage',\n fallback: 'Bild entfernen',\n },\n },\n },\n} as const;\n"],"mappings":";;;;;;iCAAe;EACXA,aAAa,EAAE;IACXC,aAAa,EAAE;MACXC,WAAW,EAAE;QACTC,UAAU,EAAE,uEAAuE;QACnFC,QAAQ,EAAE;MACd;IACJ;EACJ;AACJ,CAAC","ignoreList":[]}
@@ -14,6 +14,7 @@ const Gallery = /*#__PURE__*/forwardRef(({
14
14
  onFileCountChange,
15
15
  onRemove,
16
16
  shouldLoadImages = true,
17
+ shouldEnableKeyboardHighlighting,
17
18
  viewMode = GalleryViewMode.GRID
18
19
  }, ref) => {
19
20
  const editorRef = useRef(null);
@@ -38,9 +39,11 @@ const Gallery = /*#__PURE__*/forwardRef(({
38
39
  onAdd: onAdd,
39
40
  onFileCountChange: onFileCountChange,
40
41
  onRemove: onRemove,
41
- shouldLoadImages: shouldLoadImages
42
+ shouldLoadImages: shouldLoadImages,
43
+ shouldEnableKeyboardHighlighting: shouldEnableKeyboardHighlighting
42
44
  }) : /*#__PURE__*/React.createElement(GalleryViewer, {
43
45
  files: files,
46
+ shouldEnableKeyboardHighlighting: shouldEnableKeyboardHighlighting,
44
47
  shouldLoadImages: shouldLoadImages,
45
48
  viewMode: viewMode
46
49
  });
@@ -1 +1 @@
1
- {"version":3,"file":"Gallery.js","names":["React","forwardRef","useCallback","useImperativeHandle","useRef","GalleryEditor","GalleryViewer","GalleryViewMode","Gallery","allowDragAndDrop","addFileIcon","doubleFileDialogMessage","isEditMode","fileMinWidth","files","maxFiles","onAdd","onFileCountChange","onRemove","shouldLoadImages","viewMode","GRID","ref","editorRef","handleClear","console","warn","current","clear","createElement","displayName"],"sources":["../../../src/components/Gallery.tsx"],"sourcesContent":["import React, { forwardRef, useCallback, useImperativeHandle, useRef } from 'react';\nimport GalleryEditor from './gallery-editor/GalleryEditor';\nimport type { GalleryEditorRef } from './gallery-editor/GalleryEditor.types';\nimport GalleryViewer from './gallery-viewer/GalleryViewer';\nimport type { GalleryProps, GalleryRef } from './Gallery.types';\nimport { GalleryViewMode } from '../types/gallery';\n\nconst Gallery = forwardRef<GalleryRef, GalleryProps>(\n (\n {\n allowDragAndDrop = false,\n addFileIcon = 'fa fa-plus',\n doubleFileDialogMessage = 'Diese Datei ist bereits vorhanden',\n isEditMode = false,\n fileMinWidth = 100,\n files,\n maxFiles,\n onAdd,\n onFileCountChange,\n onRemove,\n shouldLoadImages = true,\n viewMode = GalleryViewMode.GRID,\n },\n ref,\n ) => {\n const editorRef = useRef<GalleryEditorRef>(null);\n\n const handleClear = useCallback(() => {\n if (!isEditMode) {\n console.warn('Gallery.clear() can only be used in edit mode.');\n return;\n }\n\n editorRef.current?.clear();\n }, [isEditMode]);\n\n useImperativeHandle(\n ref,\n () => ({\n clear: handleClear,\n }),\n [handleClear],\n );\n\n return isEditMode ? (\n <GalleryEditor\n ref={editorRef}\n allowDragAndDrop={allowDragAndDrop}\n addFileIcon={addFileIcon}\n doubleFileDialogMessage={doubleFileDialogMessage}\n fileMinWidth={fileMinWidth}\n files={files}\n maxFiles={maxFiles}\n onAdd={onAdd}\n onFileCountChange={onFileCountChange}\n onRemove={onRemove}\n shouldLoadImages={shouldLoadImages}\n />\n ) : (\n <GalleryViewer files={files} shouldLoadImages={shouldLoadImages} viewMode={viewMode} />\n );\n },\n);\n\nGallery.displayName = 'Gallery';\n\nexport default Gallery;\n"],"mappings":"AAAA,OAAOA,KAAK,IAAIC,UAAU,EAAEC,WAAW,EAAEC,mBAAmB,EAAEC,MAAM,QAAQ,OAAO;AACnF,OAAOC,aAAa,MAAM,gCAAgC;AAE1D,OAAOC,aAAa,MAAM,gCAAgC;AAE1D,SAASC,eAAe,QAAQ,kBAAkB;AAElD,MAAMC,OAAO,gBAAGP,UAAU,CACtB,CACI;EACIQ,gBAAgB,GAAG,KAAK;EACxBC,WAAW,GAAG,YAAY;EAC1BC,uBAAuB,GAAG,mCAAmC;EAC7DC,UAAU,GAAG,KAAK;EAClBC,YAAY,GAAG,GAAG;EAClBC,KAAK;EACLC,QAAQ;EACRC,KAAK;EACLC,iBAAiB;EACjBC,QAAQ;EACRC,gBAAgB,GAAG,IAAI;EACvBC,QAAQ,GAAGb,eAAe,CAACc;AAC/B,CAAC,EACDC,GAAG,KACF;EACD,MAAMC,SAAS,GAAGnB,MAAM,CAAmB,IAAI,CAAC;EAEhD,MAAMoB,WAAW,GAAGtB,WAAW,CAAC,MAAM;IAClC,IAAI,CAACU,UAAU,EAAE;MACba,OAAO,CAACC,IAAI,CAAC,gDAAgD,CAAC;MAC9D;IACJ;IAEAH,SAAS,CAACI,OAAO,EAAEC,KAAK,CAAC,CAAC;EAC9B,CAAC,EAAE,CAAChB,UAAU,CAAC,CAAC;EAEhBT,mBAAmB,CACfmB,GAAG,EACH,OAAO;IACHM,KAAK,EAAEJ;EACX,CAAC,CAAC,EACF,CAACA,WAAW,CAChB,CAAC;EAED,OAAOZ,UAAU,gBACbZ,KAAA,CAAA6B,aAAA,CAACxB,aAAa;IACViB,GAAG,EAAEC,SAAU;IACfd,gBAAgB,EAAEA,gBAAiB;IACnCC,WAAW,EAAEA,WAAY;IACzBC,uBAAuB,EAAEA,uBAAwB;IACjDE,YAAY,EAAEA,YAAa;IAC3BC,KAAK,EAAEA,KAAM;IACbC,QAAQ,EAAEA,QAAS;IACnBC,KAAK,EAAEA,KAAM;IACbC,iBAAiB,EAAEA,iBAAkB;IACrCC,QAAQ,EAAEA,QAAS;IACnBC,gBAAgB,EAAEA;EAAiB,CACtC,CAAC,gBAEFnB,KAAA,CAAA6B,aAAA,CAACvB,aAAa;IAACQ,KAAK,EAAEA,KAAM;IAACK,gBAAgB,EAAEA,gBAAiB;IAACC,QAAQ,EAAEA;EAAS,CAAE,CACzF;AACL,CACJ,CAAC;AAEDZ,OAAO,CAACsB,WAAW,GAAG,SAAS;AAE/B,eAAetB,OAAO","ignoreList":[]}
1
+ {"version":3,"file":"Gallery.js","names":["React","forwardRef","useCallback","useImperativeHandle","useRef","GalleryEditor","GalleryViewer","GalleryViewMode","Gallery","allowDragAndDrop","addFileIcon","doubleFileDialogMessage","isEditMode","fileMinWidth","files","maxFiles","onAdd","onFileCountChange","onRemove","shouldLoadImages","shouldEnableKeyboardHighlighting","viewMode","GRID","ref","editorRef","handleClear","console","warn","current","clear","createElement","displayName"],"sources":["../../../src/components/Gallery.tsx"],"sourcesContent":["import React, { forwardRef, useCallback, useImperativeHandle, useRef } from 'react';\nimport GalleryEditor from './gallery-editor/GalleryEditor';\nimport type { GalleryEditorRef } from './gallery-editor/GalleryEditor.types';\nimport GalleryViewer from './gallery-viewer/GalleryViewer';\nimport type { GalleryProps, GalleryRef } from './Gallery.types';\nimport { GalleryViewMode } from '../types/gallery';\n\nconst Gallery = forwardRef<GalleryRef, GalleryProps>(\n (\n {\n allowDragAndDrop = false,\n addFileIcon = 'fa fa-plus',\n doubleFileDialogMessage = 'Diese Datei ist bereits vorhanden',\n isEditMode = false,\n fileMinWidth = 100,\n files,\n maxFiles,\n onAdd,\n onFileCountChange,\n onRemove,\n shouldLoadImages = true,\n shouldEnableKeyboardHighlighting,\n viewMode = GalleryViewMode.GRID,\n },\n ref,\n ) => {\n const editorRef = useRef<GalleryEditorRef>(null);\n\n const handleClear = useCallback(() => {\n if (!isEditMode) {\n console.warn('Gallery.clear() can only be used in edit mode.');\n return;\n }\n\n editorRef.current?.clear();\n }, [isEditMode]);\n\n useImperativeHandle(\n ref,\n () => ({\n clear: handleClear,\n }),\n [handleClear],\n );\n\n return isEditMode ? (\n <GalleryEditor\n ref={editorRef}\n allowDragAndDrop={allowDragAndDrop}\n addFileIcon={addFileIcon}\n doubleFileDialogMessage={doubleFileDialogMessage}\n fileMinWidth={fileMinWidth}\n files={files}\n maxFiles={maxFiles}\n onAdd={onAdd}\n onFileCountChange={onFileCountChange}\n onRemove={onRemove}\n shouldLoadImages={shouldLoadImages}\n shouldEnableKeyboardHighlighting={shouldEnableKeyboardHighlighting}\n />\n ) : (\n <GalleryViewer\n files={files}\n shouldEnableKeyboardHighlighting={shouldEnableKeyboardHighlighting}\n shouldLoadImages={shouldLoadImages}\n viewMode={viewMode}\n />\n );\n },\n);\n\nGallery.displayName = 'Gallery';\n\nexport default Gallery;\n"],"mappings":"AAAA,OAAOA,KAAK,IAAIC,UAAU,EAAEC,WAAW,EAAEC,mBAAmB,EAAEC,MAAM,QAAQ,OAAO;AACnF,OAAOC,aAAa,MAAM,gCAAgC;AAE1D,OAAOC,aAAa,MAAM,gCAAgC;AAE1D,SAASC,eAAe,QAAQ,kBAAkB;AAElD,MAAMC,OAAO,gBAAGP,UAAU,CACtB,CACI;EACIQ,gBAAgB,GAAG,KAAK;EACxBC,WAAW,GAAG,YAAY;EAC1BC,uBAAuB,GAAG,mCAAmC;EAC7DC,UAAU,GAAG,KAAK;EAClBC,YAAY,GAAG,GAAG;EAClBC,KAAK;EACLC,QAAQ;EACRC,KAAK;EACLC,iBAAiB;EACjBC,QAAQ;EACRC,gBAAgB,GAAG,IAAI;EACvBC,gCAAgC;EAChCC,QAAQ,GAAGd,eAAe,CAACe;AAC/B,CAAC,EACDC,GAAG,KACF;EACD,MAAMC,SAAS,GAAGpB,MAAM,CAAmB,IAAI,CAAC;EAEhD,MAAMqB,WAAW,GAAGvB,WAAW,CAAC,MAAM;IAClC,IAAI,CAACU,UAAU,EAAE;MACbc,OAAO,CAACC,IAAI,CAAC,gDAAgD,CAAC;MAC9D;IACJ;IAEAH,SAAS,CAACI,OAAO,EAAEC,KAAK,CAAC,CAAC;EAC9B,CAAC,EAAE,CAACjB,UAAU,CAAC,CAAC;EAEhBT,mBAAmB,CACfoB,GAAG,EACH,OAAO;IACHM,KAAK,EAAEJ;EACX,CAAC,CAAC,EACF,CAACA,WAAW,CAChB,CAAC;EAED,OAAOb,UAAU,gBACbZ,KAAA,CAAA8B,aAAA,CAACzB,aAAa;IACVkB,GAAG,EAAEC,SAAU;IACff,gBAAgB,EAAEA,gBAAiB;IACnCC,WAAW,EAAEA,WAAY;IACzBC,uBAAuB,EAAEA,uBAAwB;IACjDE,YAAY,EAAEA,YAAa;IAC3BC,KAAK,EAAEA,KAAM;IACbC,QAAQ,EAAEA,QAAS;IACnBC,KAAK,EAAEA,KAAM;IACbC,iBAAiB,EAAEA,iBAAkB;IACrCC,QAAQ,EAAEA,QAAS;IACnBC,gBAAgB,EAAEA,gBAAiB;IACnCC,gCAAgC,EAAEA;EAAiC,CACtE,CAAC,gBAEFpB,KAAA,CAAA8B,aAAA,CAACxB,aAAa;IACVQ,KAAK,EAAEA,KAAM;IACbM,gCAAgC,EAAEA,gCAAiC;IACnED,gBAAgB,EAAEA,gBAAiB;IACnCE,QAAQ,EAAEA;EAAS,CACtB,CACJ;AACL,CACJ,CAAC;AAEDb,OAAO,CAACuB,WAAW,GAAG,SAAS;AAE/B,eAAevB,OAAO","ignoreList":[]}
@@ -1 +1 @@
1
- {"version":3,"file":"Gallery.types.js","names":[],"sources":["../../../src/components/Gallery.types.ts"],"sourcesContent":["import type { FileItem } from '@chayns-components/core';\nimport type { GalleryViewMode } from '../types/gallery';\n\n/**\n * Props for the public Gallery wrapper component.\n */\nexport type GalleryRef = {\n /**\n * Clears all locally managed gallery items in edit mode.\n * @description\n * When the gallery is rendered in read-only mode, calling this method only emits a console warning.\n */\n clear: () => void;\n};\n\nexport interface GalleryProps {\n /**\n * Enables drag and drop while the component is used in edit mode.\n * @description\n * This prop only affects the editor path. In read-only mode, drag and drop stays disabled regardless of this value.\n * @default false\n * @example\n * <Gallery allowDragAndDrop isEditMode files={files} />\n * @optional\n */\n allowDragAndDrop?: boolean;\n /**\n * Defines the dialog message that is shown when a duplicate upload is detected.\n * @description\n * The message is used by the editor when a locally added file resolves to an already known uploaded file.\n * @default 'Diese Datei ist bereits vorhanden'\n * @example\n * <Gallery doubleFileDialogMessage=\"This file already exists.\" isEditMode files={files} />\n * @optional\n */\n doubleFileDialogMessage?: string;\n /**\n * Defines the minimum width of one tile in edit mode.\n * @description\n * The editor uses this value to build its responsive grid. It has no effect in the read-only viewer.\n * @default 100\n * @example\n * <Gallery fileMinWidth={140} isEditMode files={files} />\n * @optional\n */\n fileMinWidth?: number;\n /**\n * Defines the icon that is shown in the add-file tile in edit mode.\n * @description\n * The icon is forwarded to the editor and replaces the default plus icon on the add-tile.\n * @default 'fa fa-plus'\n * @example\n * <Gallery addFileIcon=\"fa fa-image-circle-plus\" isEditMode files={files} />\n * @optional\n */\n addFileIcon?: string;\n /**\n * Provides already known media items that should be rendered by the gallery.\n * @description\n * In read-only mode, these files are rendered directly from props. In edit mode, they are used as the external baseline\n * for already uploaded media while local uploads are managed internally.\n * @example\n * <Gallery files={files} />\n * @optional\n */\n files?: FileItem[];\n /**\n * Enables the editable upload mode instead of the read-only viewer mode.\n * @description\n * When set to `true`, the public wrapper renders `GalleryEditor`. Otherwise it renders `GalleryViewer`.\n * @default false\n * @example\n * <Gallery isEditMode files={files} />\n * @optional\n */\n isEditMode?: boolean;\n /**\n * Limits how many files can be managed in edit mode.\n * @description\n * Once the limit is reached, the editor hides the add-tile and does not accept more files.\n * This prop has no effect in read-only mode.\n * @example\n * <Gallery isEditMode maxFiles={6} files={files} />\n * @optional\n */\n maxFiles?: number;\n /**\n * Controls when the gallery is allowed to load the final media assets.\n * @description\n * When set to `true`, the gallery loads the actual images immediately as before.\n * When set to `false`, the gallery keeps rendering previews first and delays the final media load until this flag becomes `true`.\n * This setting applies to the whole gallery wrapper and is intended for external loading control such as virtualized message lists.\n * @default true\n * @example\n * <Gallery files={files} shouldLoadImages={false} />\n * @optional\n */\n shouldLoadImages?: boolean;\n /**\n * Is called after a file has been uploaded successfully in edit mode.\n * @description\n * The callback receives the uploaded file representation that should be merged into the consuming state.\n * It is never called by the read-only viewer.\n * @example\n * <Gallery isEditMode onAdd={(file) => setFiles((prev) => [...prev, file])} />\n * @optional\n */\n onAdd?: (file: FileItem) => void;\n /**\n * Is called whenever the internal item count changes in edit mode.\n * @description\n * This includes already uploaded files and locally pending uploads that are currently managed by the editor.\n * It is useful when surrounding UI needs to know whether uploads are still in progress.\n * @example\n * <Gallery isEditMode onFileCountChange={(count) => console.log(count)} />\n * @optional\n */\n onFileCountChange?: (fileCount: number) => void;\n /**\n * Is called after an uploaded file has been removed in edit mode.\n * @description\n * The callback receives the removed uploaded file so the consuming state can remove it as well.\n * It is never called by the read-only viewer.\n * @example\n * <Gallery isEditMode onRemove={(file) => removeFile(file.id)} />\n * @optional\n */\n onRemove?: (file: FileItem) => void;\n /**\n * Defines how known media items are arranged in read-only mode.\n * @description\n * This prop only affects the viewer path. The editor always uses its dedicated editable grid layout.\n * @default GalleryViewMode.GRID\n * @example\n * <Gallery files={files} viewMode={GalleryViewMode.SQUARE} />\n * @optional\n */\n viewMode?: GalleryViewMode;\n}\n"],"mappings":"","ignoreList":[]}
1
+ {"version":3,"file":"Gallery.types.js","names":[],"sources":["../../../src/components/Gallery.types.ts"],"sourcesContent":["import type { FileItem } from '@chayns-components/core';\nimport type { GalleryViewMode } from '../types/gallery';\n\n/**\n * Props for the public Gallery wrapper component.\n */\nexport type GalleryRef = {\n /**\n * Clears all locally managed gallery items in edit mode.\n * @description\n * When the gallery is rendered in read-only mode, calling this method only emits a console warning.\n */\n clear: () => void;\n};\n\nexport interface GalleryProps {\n /**\n * Enables drag and drop while the component is used in edit mode.\n * @description\n * This prop only affects the editor path. In read-only mode, drag and drop stays disabled regardless of this value.\n * @default false\n * @example\n * <Gallery allowDragAndDrop isEditMode files={files} />\n * @optional\n */\n allowDragAndDrop?: boolean;\n /**\n * Defines the dialog message that is shown when a duplicate upload is detected.\n * @description\n * The message is used by the editor when a locally added file resolves to an already known uploaded file.\n * @default 'Diese Datei ist bereits vorhanden'\n * @example\n * <Gallery doubleFileDialogMessage=\"This file already exists.\" isEditMode files={files} />\n * @optional\n */\n doubleFileDialogMessage?: string;\n /**\n * Defines the minimum width of one tile in edit mode.\n * @description\n * The editor uses this value to build its responsive grid. It has no effect in the read-only viewer.\n * @default 100\n * @example\n * <Gallery fileMinWidth={140} isEditMode files={files} />\n * @optional\n */\n fileMinWidth?: number;\n /**\n * Defines the icon that is shown in the add-file tile in edit mode.\n * @description\n * The icon is forwarded to the editor and replaces the default plus icon on the add-tile.\n * @default 'fa fa-plus'\n * @example\n * <Gallery addFileIcon=\"fa fa-image-circle-plus\" isEditMode files={files} />\n * @optional\n */\n addFileIcon?: string;\n /**\n * Provides already known media items that should be rendered by the gallery.\n * @description\n * In read-only mode, these files are rendered directly from props. In edit mode, they are used as the external baseline\n * for already uploaded media while local uploads are managed internally.\n * @example\n * <Gallery files={files} />\n * @optional\n */\n files?: FileItem[];\n /**\n * Enables the editable upload mode instead of the read-only viewer mode.\n * @description\n * When set to `true`, the public wrapper renders `GalleryEditor`. Otherwise it renders `GalleryViewer`.\n * @default false\n * @example\n * <Gallery isEditMode files={files} />\n * @optional\n */\n isEditMode?: boolean;\n /**\n * Limits how many files can be managed in edit mode.\n * @description\n * Once the limit is reached, the editor hides the add-tile and does not accept more files.\n * This prop has no effect in read-only mode.\n * @example\n * <Gallery isEditMode maxFiles={6} files={files} />\n * @optional\n */\n maxFiles?: number;\n /**\n * Controls when the gallery is allowed to load the final media assets.\n * @description\n * When set to `true`, the gallery loads the actual images immediately as before.\n * When set to `false`, the gallery keeps rendering previews first and delays the final media load until this flag becomes `true`.\n * This setting applies to the whole gallery wrapper and is intended for external loading control such as virtualized message lists.\n * @default true\n * @example\n * <Gallery files={files} shouldLoadImages={false} />\n * @optional\n */\n shouldLoadImages?: boolean;\n /**\n * Enables keyboard-only focus highlighting for interactive gallery tiles.\n */\n shouldEnableKeyboardHighlighting?: boolean;\n /**\n * Is called after a file has been uploaded successfully in edit mode.\n * @description\n * The callback receives the uploaded file representation that should be merged into the consuming state.\n * It is never called by the read-only viewer.\n * @example\n * <Gallery isEditMode onAdd={(file) => setFiles((prev) => [...prev, file])} />\n * @optional\n */\n onAdd?: (file: FileItem) => void;\n /**\n * Is called whenever the internal item count changes in edit mode.\n * @description\n * This includes already uploaded files and locally pending uploads that are currently managed by the editor.\n * It is useful when surrounding UI needs to know whether uploads are still in progress.\n * @example\n * <Gallery isEditMode onFileCountChange={(count) => console.log(count)} />\n * @optional\n */\n onFileCountChange?: (fileCount: number) => void;\n /**\n * Is called after an uploaded file has been removed in edit mode.\n * @description\n * The callback receives the removed uploaded file so the consuming state can remove it as well.\n * It is never called by the read-only viewer.\n * @example\n * <Gallery isEditMode onRemove={(file) => removeFile(file.id)} />\n * @optional\n */\n onRemove?: (file: FileItem) => void;\n /**\n * Defines how known media items are arranged in read-only mode.\n * @description\n * This prop only affects the viewer path. The editor always uses its dedicated editable grid layout.\n * @default GalleryViewMode.GRID\n * @example\n * <Gallery files={files} viewMode={GalleryViewMode.SQUARE} />\n * @optional\n */\n viewMode?: GalleryViewMode;\n}\n"],"mappings":"","ignoreList":[]}
@@ -5,6 +5,7 @@ import { StyledGalleryEditor, StyledGalleryEditorGrid } from './GalleryEditor.st
5
5
  import GalleryEditorItem from './gallery-editor-item/GalleryEditorItem';
6
6
  import { GALLERY_EDITOR_GRID_GAP_PX } from './GalleryEditor.constants';
7
7
  import useGalleryEditorState from './useGalleryEditorState';
8
+ import { TextStringProvider } from '@chayns/textstrings';
8
9
  const GalleryEditor = /*#__PURE__*/forwardRef(({
9
10
  allowDragAndDrop = false,
10
11
  addFileIcon = 'fa fa-plus',
@@ -15,7 +16,8 @@ const GalleryEditor = /*#__PURE__*/forwardRef(({
15
16
  onAdd,
16
17
  onFileCountChange,
17
18
  onRemove,
18
- shouldLoadImages = true
19
+ shouldLoadImages = true,
20
+ shouldEnableKeyboardHighlighting
19
21
  }, ref) => {
20
22
  const {
21
23
  fileItems,
@@ -37,7 +39,9 @@ const GalleryEditor = /*#__PURE__*/forwardRef(({
37
39
  clear: handleClear
38
40
  }), [handleClear]);
39
41
  const shouldShowAddFileTile = !maxFiles || maxFiles > fileItems.length;
40
- return /*#__PURE__*/React.createElement(StyledGalleryEditor, null, /*#__PURE__*/React.createElement(StyledGalleryEditorGrid, {
42
+ return /*#__PURE__*/React.createElement(TextStringProvider, {
43
+ libraries: "@chayns-components-gallery"
44
+ }, /*#__PURE__*/React.createElement(StyledGalleryEditor, null, /*#__PURE__*/React.createElement(StyledGalleryEditorGrid, {
41
45
  $fileMinWidth: fileMinWidth,
42
46
  $gap: GALLERY_EDITOR_GRID_GAP_PX,
43
47
  onDragOver: event => event.preventDefault(),
@@ -49,11 +53,13 @@ const GalleryEditor = /*#__PURE__*/forwardRef(({
49
53
  fileItem: file,
50
54
  handleDeleteFile: handleDeleteFile,
51
55
  onClick: handleOpenFiles,
52
- shouldLoadImages: shouldLoadImages
56
+ shouldLoadImages: shouldLoadImages,
57
+ shouldEnableKeyboardHighlighting: shouldEnableKeyboardHighlighting
53
58
  }))), shouldShowAddFileTile && /*#__PURE__*/React.createElement(AddFile, {
54
59
  addFileIcon: addFileIcon,
55
- onAdd: handleAddFiles
56
- })));
60
+ onAdd: handleAddFiles,
61
+ shouldEnableKeyboardHighlighting: shouldEnableKeyboardHighlighting
62
+ }))));
57
63
  });
58
64
  GalleryEditor.displayName = 'GalleryEditor';
59
65
  export default GalleryEditor;
@@ -1 +1 @@
1
- {"version":3,"file":"GalleryEditor.js","names":["AnimatePresence","React","forwardRef","useImperativeHandle","AddFile","StyledGalleryEditor","StyledGalleryEditorGrid","GalleryEditorItem","GALLERY_EDITOR_GRID_GAP_PX","useGalleryEditorState","GalleryEditor","allowDragAndDrop","addFileIcon","doubleFileDialogMessage","fileMinWidth","files","maxFiles","onAdd","onFileCountChange","onRemove","shouldLoadImages","ref","fileItems","handleAddFiles","handleClear","handleDeleteFile","handleDrop","handleOpenFiles","clear","shouldShowAddFileTile","length","createElement","$fileMinWidth","$gap","onDragOver","event","preventDefault","onDrop","initial","map","file","key","id","fileItem","onClick","displayName"],"sources":["../../../../src/components/gallery-editor/GalleryEditor.tsx"],"sourcesContent":["import { AnimatePresence } from 'motion/react';\nimport React, { forwardRef, useImperativeHandle } from 'react';\nimport AddFile from './add-file/AddFile';\nimport { StyledGalleryEditor, StyledGalleryEditorGrid } from './GalleryEditor.styles';\nimport type { GalleryEditorProps, GalleryEditorRef } from './GalleryEditor.types';\nimport GalleryEditorItem from './gallery-editor-item/GalleryEditorItem';\nimport { GALLERY_EDITOR_GRID_GAP_PX } from './GalleryEditor.constants';\nimport useGalleryEditorState from './useGalleryEditorState';\n\nconst GalleryEditor = forwardRef<GalleryEditorRef, GalleryEditorProps>(\n (\n {\n allowDragAndDrop = false,\n addFileIcon = 'fa fa-plus',\n doubleFileDialogMessage = 'Diese Datei ist bereits vorhanden',\n fileMinWidth = 100,\n files,\n maxFiles,\n onAdd,\n onFileCountChange,\n onRemove,\n shouldLoadImages = true,\n },\n ref,\n ) => {\n const {\n fileItems,\n handleAddFiles,\n handleClear,\n handleDeleteFile,\n handleDrop,\n handleOpenFiles,\n } = useGalleryEditorState({\n allowDragAndDrop,\n doubleFileDialogMessage,\n files,\n maxFiles,\n onAdd,\n onFileCountChange,\n onRemove,\n });\n\n useImperativeHandle(\n ref,\n () => ({\n clear: handleClear,\n }),\n [handleClear],\n );\n\n const shouldShowAddFileTile = !maxFiles || maxFiles > fileItems.length;\n\n return (\n <StyledGalleryEditor>\n <StyledGalleryEditorGrid\n $fileMinWidth={fileMinWidth}\n $gap={GALLERY_EDITOR_GRID_GAP_PX}\n onDragOver={(event) => event.preventDefault()}\n onDrop={(event) => void handleDrop(event)}\n >\n <AnimatePresence initial={false}>\n {fileItems.map((file) => (\n <GalleryEditorItem\n key={file.id}\n fileItem={file}\n handleDeleteFile={handleDeleteFile}\n onClick={handleOpenFiles}\n shouldLoadImages={shouldLoadImages}\n />\n ))}\n </AnimatePresence>\n\n {shouldShowAddFileTile && (\n <AddFile addFileIcon={addFileIcon} onAdd={handleAddFiles} />\n )}\n </StyledGalleryEditorGrid>\n </StyledGalleryEditor>\n );\n },\n);\n\nGalleryEditor.displayName = 'GalleryEditor';\n\nexport default GalleryEditor;\n"],"mappings":"AAAA,SAASA,eAAe,QAAQ,cAAc;AAC9C,OAAOC,KAAK,IAAIC,UAAU,EAAEC,mBAAmB,QAAQ,OAAO;AAC9D,OAAOC,OAAO,MAAM,oBAAoB;AACxC,SAASC,mBAAmB,EAAEC,uBAAuB,QAAQ,wBAAwB;AAErF,OAAOC,iBAAiB,MAAM,yCAAyC;AACvE,SAASC,0BAA0B,QAAQ,2BAA2B;AACtE,OAAOC,qBAAqB,MAAM,yBAAyB;AAE3D,MAAMC,aAAa,gBAAGR,UAAU,CAC5B,CACI;EACIS,gBAAgB,GAAG,KAAK;EACxBC,WAAW,GAAG,YAAY;EAC1BC,uBAAuB,GAAG,mCAAmC;EAC7DC,YAAY,GAAG,GAAG;EAClBC,KAAK;EACLC,QAAQ;EACRC,KAAK;EACLC,iBAAiB;EACjBC,QAAQ;EACRC,gBAAgB,GAAG;AACvB,CAAC,EACDC,GAAG,KACF;EACD,MAAM;IACFC,SAAS;IACTC,cAAc;IACdC,WAAW;IACXC,gBAAgB;IAChBC,UAAU;IACVC;EACJ,CAAC,GAAGlB,qBAAqB,CAAC;IACtBE,gBAAgB;IAChBE,uBAAuB;IACvBE,KAAK;IACLC,QAAQ;IACRC,KAAK;IACLC,iBAAiB;IACjBC;EACJ,CAAC,CAAC;EAEFhB,mBAAmB,CACfkB,GAAG,EACH,OAAO;IACHO,KAAK,EAAEJ;EACX,CAAC,CAAC,EACF,CAACA,WAAW,CAChB,CAAC;EAED,MAAMK,qBAAqB,GAAG,CAACb,QAAQ,IAAIA,QAAQ,GAAGM,SAAS,CAACQ,MAAM;EAEtE,oBACI7B,KAAA,CAAA8B,aAAA,CAAC1B,mBAAmB,qBAChBJ,KAAA,CAAA8B,aAAA,CAACzB,uBAAuB;IACpB0B,aAAa,EAAElB,YAAa;IAC5BmB,IAAI,EAAEzB,0BAA2B;IACjC0B,UAAU,EAAGC,KAAK,IAAKA,KAAK,CAACC,cAAc,CAAC,CAAE;IAC9CC,MAAM,EAAGF,KAAK,IAAK,KAAKT,UAAU,CAACS,KAAK;EAAE,gBAE1ClC,KAAA,CAAA8B,aAAA,CAAC/B,eAAe;IAACsC,OAAO,EAAE;EAAM,GAC3BhB,SAAS,CAACiB,GAAG,CAAEC,IAAI,iBAChBvC,KAAA,CAAA8B,aAAA,CAACxB,iBAAiB;IACdkC,GAAG,EAAED,IAAI,CAACE,EAAG;IACbC,QAAQ,EAAEH,IAAK;IACff,gBAAgB,EAAEA,gBAAiB;IACnCmB,OAAO,EAAEjB,eAAgB;IACzBP,gBAAgB,EAAEA;EAAiB,CACtC,CACJ,CACY,CAAC,EAEjBS,qBAAqB,iBAClB5B,KAAA,CAAA8B,aAAA,CAAC3B,OAAO;IAACQ,WAAW,EAAEA,WAAY;IAACK,KAAK,EAAEM;EAAe,CAAE,CAE1C,CACR,CAAC;AAE9B,CACJ,CAAC;AAEDb,aAAa,CAACmC,WAAW,GAAG,eAAe;AAE3C,eAAenC,aAAa","ignoreList":[]}
1
+ {"version":3,"file":"GalleryEditor.js","names":["AnimatePresence","React","forwardRef","useImperativeHandle","AddFile","StyledGalleryEditor","StyledGalleryEditorGrid","GalleryEditorItem","GALLERY_EDITOR_GRID_GAP_PX","useGalleryEditorState","TextStringProvider","GalleryEditor","allowDragAndDrop","addFileIcon","doubleFileDialogMessage","fileMinWidth","files","maxFiles","onAdd","onFileCountChange","onRemove","shouldLoadImages","shouldEnableKeyboardHighlighting","ref","fileItems","handleAddFiles","handleClear","handleDeleteFile","handleDrop","handleOpenFiles","clear","shouldShowAddFileTile","length","createElement","libraries","$fileMinWidth","$gap","onDragOver","event","preventDefault","onDrop","initial","map","file","key","id","fileItem","onClick","displayName"],"sources":["../../../../src/components/gallery-editor/GalleryEditor.tsx"],"sourcesContent":["import { AnimatePresence } from 'motion/react';\nimport React, { forwardRef, useImperativeHandle } from 'react';\nimport AddFile from './add-file/AddFile';\nimport { StyledGalleryEditor, StyledGalleryEditorGrid } from './GalleryEditor.styles';\nimport type { GalleryEditorProps, GalleryEditorRef } from './GalleryEditor.types';\nimport GalleryEditorItem from './gallery-editor-item/GalleryEditorItem';\nimport { GALLERY_EDITOR_GRID_GAP_PX } from './GalleryEditor.constants';\nimport useGalleryEditorState from './useGalleryEditorState';\nimport { TextStringProvider } from '@chayns/textstrings';\n\nconst GalleryEditor = forwardRef<GalleryEditorRef, GalleryEditorProps>(\n (\n {\n allowDragAndDrop = false,\n addFileIcon = 'fa fa-plus',\n doubleFileDialogMessage = 'Diese Datei ist bereits vorhanden',\n fileMinWidth = 100,\n files,\n maxFiles,\n onAdd,\n onFileCountChange,\n onRemove,\n shouldLoadImages = true,\n shouldEnableKeyboardHighlighting,\n },\n ref,\n ) => {\n const {\n fileItems,\n handleAddFiles,\n handleClear,\n handleDeleteFile,\n handleDrop,\n handleOpenFiles,\n } = useGalleryEditorState({\n allowDragAndDrop,\n doubleFileDialogMessage,\n files,\n maxFiles,\n onAdd,\n onFileCountChange,\n onRemove,\n });\n\n useImperativeHandle(\n ref,\n () => ({\n clear: handleClear,\n }),\n [handleClear],\n );\n\n const shouldShowAddFileTile = !maxFiles || maxFiles > fileItems.length;\n\n return (\n <TextStringProvider libraries=\"@chayns-components-gallery\">\n <StyledGalleryEditor>\n <StyledGalleryEditorGrid\n $fileMinWidth={fileMinWidth}\n $gap={GALLERY_EDITOR_GRID_GAP_PX}\n onDragOver={(event) => event.preventDefault()}\n onDrop={(event) => void handleDrop(event)}\n >\n <AnimatePresence initial={false}>\n {fileItems.map((file) => (\n <GalleryEditorItem\n key={file.id}\n fileItem={file}\n handleDeleteFile={handleDeleteFile}\n onClick={handleOpenFiles}\n shouldLoadImages={shouldLoadImages}\n shouldEnableKeyboardHighlighting={\n shouldEnableKeyboardHighlighting\n }\n />\n ))}\n </AnimatePresence>\n\n {shouldShowAddFileTile && (\n <AddFile\n addFileIcon={addFileIcon}\n onAdd={handleAddFiles}\n shouldEnableKeyboardHighlighting={shouldEnableKeyboardHighlighting}\n />\n )}\n </StyledGalleryEditorGrid>\n </StyledGalleryEditor>\n </TextStringProvider>\n );\n },\n);\n\nGalleryEditor.displayName = 'GalleryEditor';\n\nexport default GalleryEditor;\n"],"mappings":"AAAA,SAASA,eAAe,QAAQ,cAAc;AAC9C,OAAOC,KAAK,IAAIC,UAAU,EAAEC,mBAAmB,QAAQ,OAAO;AAC9D,OAAOC,OAAO,MAAM,oBAAoB;AACxC,SAASC,mBAAmB,EAAEC,uBAAuB,QAAQ,wBAAwB;AAErF,OAAOC,iBAAiB,MAAM,yCAAyC;AACvE,SAASC,0BAA0B,QAAQ,2BAA2B;AACtE,OAAOC,qBAAqB,MAAM,yBAAyB;AAC3D,SAASC,kBAAkB,QAAQ,qBAAqB;AAExD,MAAMC,aAAa,gBAAGT,UAAU,CAC5B,CACI;EACIU,gBAAgB,GAAG,KAAK;EACxBC,WAAW,GAAG,YAAY;EAC1BC,uBAAuB,GAAG,mCAAmC;EAC7DC,YAAY,GAAG,GAAG;EAClBC,KAAK;EACLC,QAAQ;EACRC,KAAK;EACLC,iBAAiB;EACjBC,QAAQ;EACRC,gBAAgB,GAAG,IAAI;EACvBC;AACJ,CAAC,EACDC,GAAG,KACF;EACD,MAAM;IACFC,SAAS;IACTC,cAAc;IACdC,WAAW;IACXC,gBAAgB;IAChBC,UAAU;IACVC;EACJ,CAAC,GAAGpB,qBAAqB,CAAC;IACtBG,gBAAgB;IAChBE,uBAAuB;IACvBE,KAAK;IACLC,QAAQ;IACRC,KAAK;IACLC,iBAAiB;IACjBC;EACJ,CAAC,CAAC;EAEFjB,mBAAmB,CACfoB,GAAG,EACH,OAAO;IACHO,KAAK,EAAEJ;EACX,CAAC,CAAC,EACF,CAACA,WAAW,CAChB,CAAC;EAED,MAAMK,qBAAqB,GAAG,CAACd,QAAQ,IAAIA,QAAQ,GAAGO,SAAS,CAACQ,MAAM;EAEtE,oBACI/B,KAAA,CAAAgC,aAAA,CAACvB,kBAAkB;IAACwB,SAAS,EAAC;EAA4B,gBACtDjC,KAAA,CAAAgC,aAAA,CAAC5B,mBAAmB,qBAChBJ,KAAA,CAAAgC,aAAA,CAAC3B,uBAAuB;IACpB6B,aAAa,EAAEpB,YAAa;IAC5BqB,IAAI,EAAE5B,0BAA2B;IACjC6B,UAAU,EAAGC,KAAK,IAAKA,KAAK,CAACC,cAAc,CAAC,CAAE;IAC9CC,MAAM,EAAGF,KAAK,IAAK,KAAKV,UAAU,CAACU,KAAK;EAAE,gBAE1CrC,KAAA,CAAAgC,aAAA,CAACjC,eAAe;IAACyC,OAAO,EAAE;EAAM,GAC3BjB,SAAS,CAACkB,GAAG,CAAEC,IAAI,iBAChB1C,KAAA,CAAAgC,aAAA,CAAC1B,iBAAiB;IACdqC,GAAG,EAAED,IAAI,CAACE,EAAG;IACbC,QAAQ,EAAEH,IAAK;IACfhB,gBAAgB,EAAEA,gBAAiB;IACnCoB,OAAO,EAAElB,eAAgB;IACzBR,gBAAgB,EAAEA,gBAAiB;IACnCC,gCAAgC,EAC5BA;EACH,CACJ,CACJ,CACY,CAAC,EAEjBS,qBAAqB,iBAClB9B,KAAA,CAAAgC,aAAA,CAAC7B,OAAO;IACJS,WAAW,EAAEA,WAAY;IACzBK,KAAK,EAAEO,cAAe;IACtBH,gCAAgC,EAAEA;EAAiC,CACtE,CAEgB,CACR,CACL,CAAC;AAE7B,CACJ,CAAC;AAEDX,aAAa,CAACqC,WAAW,GAAG,eAAe;AAE3C,eAAerC,aAAa","ignoreList":[]}
@@ -1 +1 @@
1
- {"version":3,"file":"GalleryEditor.types.js","names":[],"sources":["../../../../src/components/gallery-editor/GalleryEditor.types.ts"],"sourcesContent":["import type { FileItem } from '@chayns-components/core';\nimport type { GalleryRef } from '../Gallery.types';\n\n/**\n * Props for the editable gallery component.\n */\nexport interface GalleryEditorProps {\n /**\n * Enables drag and drop file selection inside the editor grid.\n * @description\n * When enabled, users can drop local image or video files onto the editor grid to start the upload flow.\n * @default false\n * @example\n * <GalleryEditor allowDragAndDrop files={files} />\n * @optional\n */\n allowDragAndDrop?: boolean;\n /**\n * Defines the dialog message that is shown when a duplicate upload is detected.\n * @description\n * The message is shown when a newly uploaded file resolves to a URL that already exists in the editor state.\n * @default 'Diese Datei ist bereits vorhanden'\n * @example\n * <GalleryEditor doubleFileDialogMessage=\"This file already exists.\" files={files} />\n * @optional\n */\n doubleFileDialogMessage?: string;\n /**\n * Defines the minimum width of one tile in the editor grid.\n * @description\n * The editor uses this value to size the responsive grid columns that hold uploaded items and the add-tile.\n * @default 100\n * @example\n * <GalleryEditor fileMinWidth={140} files={files} />\n * @optional\n */\n fileMinWidth?: number;\n /**\n * Defines the icon that is shown in the add-file tile.\n * @description\n * The editor renders this icon inside the tile that opens the file picker for adding more items.\n * @default 'fa fa-plus'\n * @example\n * <GalleryEditor addFileIcon=\"fa fa-image-circle-plus\" files={files} />\n * @optional\n */\n addFileIcon?: string;\n /**\n * Provides already uploaded media items that should be merged into the editor state.\n * @description\n * These files represent the externally known uploaded baseline. The editor may additionally hold local pending uploads.\n * @example\n * <GalleryEditor files={files} />\n * @optional\n */\n files?: FileItem[];\n /**\n * Controls whether the editor may load the final media assets immediately.\n * @description\n * When set to `true`, the editor behaves like the current implementation and loads the final media immediately.\n * When set to `false`, uploaded media keeps rendering previews first and delays the final image load until this flag becomes `true`.\n * @default true\n * @example\n * <GalleryEditor files={files} shouldLoadImages={false} />\n * @optional\n */\n shouldLoadImages?: boolean;\n /**\n * Limits how many files can be managed by the editor.\n * @description\n * After the limit is reached, the add-tile is hidden and additional file selection is ignored.\n * @example\n * <GalleryEditor files={files} maxFiles={6} />\n * @optional\n */\n maxFiles?: number;\n /**\n * Is called after a file has been uploaded successfully.\n * @description\n * The callback receives the uploaded file representation so the consuming state can persist it externally.\n * @example\n * <GalleryEditor onAdd={(file) => setFiles((prev) => [...prev, file])} />\n * @optional\n */\n onAdd?: (file: FileItem) => void;\n /**\n * Is called whenever the internal item count changes, including local pending uploads.\n * @description\n * Use this callback when surrounding UI needs to react to the number of currently managed items.\n * @example\n * <GalleryEditor onFileCountChange={(count) => console.log(count)} />\n * @optional\n */\n onFileCountChange?: (fileCount: number) => void;\n /**\n * Is called after an uploaded file has been removed.\n * @description\n * The callback receives the removed uploaded file so the consuming state can remove it from its controlled `files` array.\n * @example\n * <GalleryEditor onRemove={(file) => removeFile(file.id)} />\n * @optional\n */\n onRemove?: (file: FileItem) => void;\n}\n\nexport type GalleryEditorRef = GalleryRef;\n"],"mappings":"","ignoreList":[]}
1
+ {"version":3,"file":"GalleryEditor.types.js","names":[],"sources":["../../../../src/components/gallery-editor/GalleryEditor.types.ts"],"sourcesContent":["import type { FileItem } from '@chayns-components/core';\nimport type { GalleryRef } from '../Gallery.types';\n\n/**\n * Props for the editable gallery component.\n */\nexport interface GalleryEditorProps {\n /**\n * Enables drag and drop file selection inside the editor grid.\n * @description\n * When enabled, users can drop local image or video files onto the editor grid to start the upload flow.\n * @default false\n * @example\n * <GalleryEditor allowDragAndDrop files={files} />\n * @optional\n */\n allowDragAndDrop?: boolean;\n /**\n * Defines the dialog message that is shown when a duplicate upload is detected.\n * @description\n * The message is shown when a newly uploaded file resolves to a URL that already exists in the editor state.\n * @default 'Diese Datei ist bereits vorhanden'\n * @example\n * <GalleryEditor doubleFileDialogMessage=\"This file already exists.\" files={files} />\n * @optional\n */\n doubleFileDialogMessage?: string;\n /**\n * Defines the minimum width of one tile in the editor grid.\n * @description\n * The editor uses this value to size the responsive grid columns that hold uploaded items and the add-tile.\n * @default 100\n * @example\n * <GalleryEditor fileMinWidth={140} files={files} />\n * @optional\n */\n fileMinWidth?: number;\n /**\n * Defines the icon that is shown in the add-file tile.\n * @description\n * The editor renders this icon inside the tile that opens the file picker for adding more items.\n * @default 'fa fa-plus'\n * @example\n * <GalleryEditor addFileIcon=\"fa fa-image-circle-plus\" files={files} />\n * @optional\n */\n addFileIcon?: string;\n /**\n * Provides already uploaded media items that should be merged into the editor state.\n * @description\n * These files represent the externally known uploaded baseline. The editor may additionally hold local pending uploads.\n * @example\n * <GalleryEditor files={files} />\n * @optional\n */\n files?: FileItem[];\n /**\n * Controls whether the editor may load the final media assets immediately.\n * @description\n * When set to `true`, the editor behaves like the current implementation and loads the final media immediately.\n * When set to `false`, uploaded media keeps rendering previews first and delays the final image load until this flag becomes `true`.\n * @default true\n * @example\n * <GalleryEditor files={files} shouldLoadImages={false} />\n * @optional\n */\n shouldLoadImages?: boolean;\n /**\n * Enables keyboard-only focus highlighting for interactive gallery tiles.\n */\n shouldEnableKeyboardHighlighting?: boolean;\n /**\n * Limits how many files can be managed by the editor.\n * @description\n * After the limit is reached, the add-tile is hidden and additional file selection is ignored.\n * @example\n * <GalleryEditor files={files} maxFiles={6} />\n * @optional\n */\n maxFiles?: number;\n /**\n * Is called after a file has been uploaded successfully.\n * @description\n * The callback receives the uploaded file representation so the consuming state can persist it externally.\n * @example\n * <GalleryEditor onAdd={(file) => setFiles((prev) => [...prev, file])} />\n * @optional\n */\n onAdd?: (file: FileItem) => void;\n /**\n * Is called whenever the internal item count changes, including local pending uploads.\n * @description\n * Use this callback when surrounding UI needs to react to the number of currently managed items.\n * @example\n * <GalleryEditor onFileCountChange={(count) => console.log(count)} />\n * @optional\n */\n onFileCountChange?: (fileCount: number) => void;\n /**\n * Is called after an uploaded file has been removed.\n * @description\n * The callback receives the removed uploaded file so the consuming state can remove it from its controlled `files` array.\n * @example\n * <GalleryEditor onRemove={(file) => removeFile(file.id)} />\n * @optional\n */\n onRemove?: (file: FileItem) => void;\n}\n\nexport type GalleryEditorRef = GalleryRef;\n"],"mappings":"","ignoreList":[]}
@@ -1,10 +1,16 @@
1
- import { Icon, selectFiles } from '@chayns-components/core';
2
- import React, { memo, useCallback } from 'react';
1
+ import { Icon, selectFiles, useFocusRingPortal, useKeyboardFocusHighlighting } from '@chayns-components/core';
2
+ import React, { memo, useCallback, useRef } from 'react';
3
3
  import { StyledAddFile, StyledAddFIleIconWrapper } from './AddFile.styles';
4
4
  const AddFile = ({
5
5
  addFileIcon = 'fa fa-plus',
6
- onAdd
6
+ onAdd,
7
+ shouldEnableKeyboardHighlighting
7
8
  }) => {
9
+ const iconWrapperRef = useRef(null);
10
+ const shouldShowKeyboardHighlighting = useKeyboardFocusHighlighting(shouldEnableKeyboardHighlighting);
11
+ useFocusRingPortal(iconWrapperRef, {
12
+ isEnabled: shouldShowKeyboardHighlighting
13
+ });
8
14
  const openSelectDialog = useCallback(async () => {
9
15
  const files = await selectFiles({
10
16
  multiple: true,
@@ -12,10 +18,18 @@ const AddFile = ({
12
18
  });
13
19
  onAdd(files);
14
20
  }, [onAdd]);
21
+ const handleKeyDown = useCallback(event => {
22
+ if (event.key === 'Enter' || event.key === ' ') {
23
+ event.preventDefault();
24
+ void openSelectDialog();
25
+ }
26
+ }, [openSelectDialog]);
15
27
  return /*#__PURE__*/React.createElement(StyledAddFile, {
16
28
  key: "addButton"
17
29
  }, /*#__PURE__*/React.createElement(StyledAddFIleIconWrapper, {
18
- onClick: () => void openSelectDialog()
30
+ ref: iconWrapperRef,
31
+ onClick: () => void openSelectDialog(),
32
+ onKeyDown: handleKeyDown
19
33
  }, /*#__PURE__*/React.createElement(Icon, {
20
34
  size: 40,
21
35
  icons: [addFileIcon]
@@ -1 +1 @@
1
- {"version":3,"file":"AddFile.js","names":["Icon","selectFiles","React","memo","useCallback","StyledAddFile","StyledAddFIleIconWrapper","AddFile","addFileIcon","onAdd","openSelectDialog","files","multiple","type","createElement","key","onClick","size","icons","displayName"],"sources":["../../../../../src/components/gallery-editor/add-file/AddFile.tsx"],"sourcesContent":["import { Icon, selectFiles } from '@chayns-components/core';\nimport React, { FC, memo, useCallback } from 'react';\nimport { StyledAddFile, StyledAddFIleIconWrapper } from './AddFile.styles';\nimport type { AddFileProps } from './AddFile.types';\n\nconst AddFile: FC<AddFileProps> = ({ addFileIcon = 'fa fa-plus', onAdd }) => {\n const openSelectDialog = useCallback(async () => {\n const files = await selectFiles({\n multiple: true,\n type: 'image/*, video/*',\n });\n\n onAdd(files);\n }, [onAdd]);\n\n return (\n <StyledAddFile key=\"addButton\">\n <StyledAddFIleIconWrapper onClick={() => void openSelectDialog()}>\n <Icon size={40} icons={[addFileIcon]} />\n </StyledAddFIleIconWrapper>\n </StyledAddFile>\n );\n};\n\nAddFile.displayName = 'AddFile';\n\nexport default memo(AddFile);\n"],"mappings":"AAAA,SAASA,IAAI,EAAEC,WAAW,QAAQ,yBAAyB;AAC3D,OAAOC,KAAK,IAAQC,IAAI,EAAEC,WAAW,QAAQ,OAAO;AACpD,SAASC,aAAa,EAAEC,wBAAwB,QAAQ,kBAAkB;AAG1E,MAAMC,OAAyB,GAAGA,CAAC;EAAEC,WAAW,GAAG,YAAY;EAAEC;AAAM,CAAC,KAAK;EACzE,MAAMC,gBAAgB,GAAGN,WAAW,CAAC,YAAY;IAC7C,MAAMO,KAAK,GAAG,MAAMV,WAAW,CAAC;MAC5BW,QAAQ,EAAE,IAAI;MACdC,IAAI,EAAE;IACV,CAAC,CAAC;IAEFJ,KAAK,CAACE,KAAK,CAAC;EAChB,CAAC,EAAE,CAACF,KAAK,CAAC,CAAC;EAEX,oBACIP,KAAA,CAAAY,aAAA,CAACT,aAAa;IAACU,GAAG,EAAC;EAAW,gBAC1Bb,KAAA,CAAAY,aAAA,CAACR,wBAAwB;IAACU,OAAO,EAAEA,CAAA,KAAM,KAAKN,gBAAgB,CAAC;EAAE,gBAC7DR,KAAA,CAAAY,aAAA,CAACd,IAAI;IAACiB,IAAI,EAAE,EAAG;IAACC,KAAK,EAAE,CAACV,WAAW;EAAE,CAAE,CACjB,CACf,CAAC;AAExB,CAAC;AAEDD,OAAO,CAACY,WAAW,GAAG,SAAS;AAE/B,4BAAehB,IAAI,CAACI,OAAO,CAAC","ignoreList":[]}
1
+ {"version":3,"file":"AddFile.js","names":["Icon","selectFiles","useFocusRingPortal","useKeyboardFocusHighlighting","React","memo","useCallback","useRef","StyledAddFile","StyledAddFIleIconWrapper","AddFile","addFileIcon","onAdd","shouldEnableKeyboardHighlighting","iconWrapperRef","shouldShowKeyboardHighlighting","isEnabled","openSelectDialog","files","multiple","type","handleKeyDown","event","key","preventDefault","createElement","ref","onClick","onKeyDown","size","icons","displayName"],"sources":["../../../../../src/components/gallery-editor/add-file/AddFile.tsx"],"sourcesContent":["import {\n Icon,\n selectFiles,\n useFocusRingPortal,\n useKeyboardFocusHighlighting,\n} from '@chayns-components/core';\nimport React, { FC, KeyboardEventHandler, memo, useCallback, useRef } from 'react';\nimport { StyledAddFile, StyledAddFIleIconWrapper } from './AddFile.styles';\nimport type { AddFileProps } from './AddFile.types';\n\nconst AddFile: FC<AddFileProps> = ({\n addFileIcon = 'fa fa-plus',\n onAdd,\n shouldEnableKeyboardHighlighting,\n}) => {\n const iconWrapperRef = useRef<HTMLButtonElement>(null);\n const shouldShowKeyboardHighlighting = useKeyboardFocusHighlighting(\n shouldEnableKeyboardHighlighting,\n );\n useFocusRingPortal(iconWrapperRef, { isEnabled: shouldShowKeyboardHighlighting });\n const openSelectDialog = useCallback(async () => {\n const files = await selectFiles({\n multiple: true,\n type: 'image/*, video/*',\n });\n\n onAdd(files);\n }, [onAdd]);\n\n const handleKeyDown = useCallback<KeyboardEventHandler<HTMLButtonElement>>(\n (event) => {\n if (event.key === 'Enter' || event.key === ' ') {\n event.preventDefault();\n void openSelectDialog();\n }\n },\n [openSelectDialog],\n );\n\n return (\n <StyledAddFile key=\"addButton\">\n <StyledAddFIleIconWrapper\n ref={iconWrapperRef}\n onClick={() => void openSelectDialog()}\n onKeyDown={handleKeyDown}\n >\n <Icon size={40} icons={[addFileIcon]} />\n </StyledAddFIleIconWrapper>\n </StyledAddFile>\n );\n};\n\nAddFile.displayName = 'AddFile';\n\nexport default memo(AddFile);\n"],"mappings":"AAAA,SACIA,IAAI,EACJC,WAAW,EACXC,kBAAkB,EAClBC,4BAA4B,QACzB,yBAAyB;AAChC,OAAOC,KAAK,IAA8BC,IAAI,EAAEC,WAAW,EAAEC,MAAM,QAAQ,OAAO;AAClF,SAASC,aAAa,EAAEC,wBAAwB,QAAQ,kBAAkB;AAG1E,MAAMC,OAAyB,GAAGA,CAAC;EAC/BC,WAAW,GAAG,YAAY;EAC1BC,KAAK;EACLC;AACJ,CAAC,KAAK;EACF,MAAMC,cAAc,GAAGP,MAAM,CAAoB,IAAI,CAAC;EACtD,MAAMQ,8BAA8B,GAAGZ,4BAA4B,CAC/DU,gCACJ,CAAC;EACDX,kBAAkB,CAACY,cAAc,EAAE;IAAEE,SAAS,EAAED;EAA+B,CAAC,CAAC;EACjF,MAAME,gBAAgB,GAAGX,WAAW,CAAC,YAAY;IAC7C,MAAMY,KAAK,GAAG,MAAMjB,WAAW,CAAC;MAC5BkB,QAAQ,EAAE,IAAI;MACdC,IAAI,EAAE;IACV,CAAC,CAAC;IAEFR,KAAK,CAACM,KAAK,CAAC;EAChB,CAAC,EAAE,CAACN,KAAK,CAAC,CAAC;EAEX,MAAMS,aAAa,GAAGf,WAAW,CAC5BgB,KAAK,IAAK;IACP,IAAIA,KAAK,CAACC,GAAG,KAAK,OAAO,IAAID,KAAK,CAACC,GAAG,KAAK,GAAG,EAAE;MAC5CD,KAAK,CAACE,cAAc,CAAC,CAAC;MACtB,KAAKP,gBAAgB,CAAC,CAAC;IAC3B;EACJ,CAAC,EACD,CAACA,gBAAgB,CACrB,CAAC;EAED,oBACIb,KAAA,CAAAqB,aAAA,CAACjB,aAAa;IAACe,GAAG,EAAC;EAAW,gBAC1BnB,KAAA,CAAAqB,aAAA,CAAChB,wBAAwB;IACrBiB,GAAG,EAAEZ,cAAe;IACpBa,OAAO,EAAEA,CAAA,KAAM,KAAKV,gBAAgB,CAAC,CAAE;IACvCW,SAAS,EAAEP;EAAc,gBAEzBjB,KAAA,CAAAqB,aAAA,CAACzB,IAAI;IAAC6B,IAAI,EAAE,EAAG;IAACC,KAAK,EAAE,CAACnB,WAAW;EAAE,CAAE,CACjB,CACf,CAAC;AAExB,CAAC;AAEDD,OAAO,CAACqB,WAAW,GAAG,SAAS;AAE/B,4BAAe1B,IAAI,CAACK,OAAO,CAAC","ignoreList":[]}
@@ -1 +1 @@
1
- {"version":3,"file":"AddFile.types.js","names":[],"sources":["../../../../../src/components/gallery-editor/add-file/AddFile.types.ts"],"sourcesContent":["/**\n * Props for the add-file tile inside the gallery editor.\n */\nexport interface AddFileProps {\n /**\n * Defines the icon that is displayed inside the add-file tile.\n * @description\n * This icon is shown in the tile that opens the file picker for adding new items to the gallery.\n * @default 'fa fa-plus'\n * @example\n * <AddFile addFileIcon=\"fa fa-image-circle-plus\" onAdd={(files) => console.log(files)} />\n * @optional\n */\n addFileIcon?: string;\n /**\n * Is called with the selected local files.\n * @description\n * The editor add-tile uses this callback after the file picker resolves with the selected local image or video files.\n * @example\n * <AddFile onAdd={(files) => console.log(files)} />\n */\n onAdd: (files: File[]) => void;\n}\n"],"mappings":"","ignoreList":[]}
1
+ {"version":3,"file":"AddFile.types.js","names":[],"sources":["../../../../../src/components/gallery-editor/add-file/AddFile.types.ts"],"sourcesContent":["/**\n * Props for the add-file tile inside the gallery editor.\n */\nexport interface AddFileProps {\n /**\n * Defines the icon that is displayed inside the add-file tile.\n * @description\n * This icon is shown in the tile that opens the file picker for adding new items to the gallery.\n * @default 'fa fa-plus'\n * @example\n * <AddFile addFileIcon=\"fa fa-image-circle-plus\" onAdd={(files) => console.log(files)} />\n * @optional\n */\n addFileIcon?: string;\n /**\n * Is called with the selected local files.\n * @description\n * The editor add-tile uses this callback after the file picker resolves with the selected local image or video files.\n * @example\n * <AddFile onAdd={(files) => console.log(files)} />\n */\n onAdd: (files: File[]) => void;\n /**\n * Enables keyboard-only focus highlighting for the add-file button.\n */\n shouldEnableKeyboardHighlighting?: boolean;\n}\n"],"mappings":"","ignoreList":[]}
@@ -1,16 +1,28 @@
1
- import { Icon } from '@chayns-components/core';
2
- import React, { memo } from 'react';
1
+ import { Icon, useFocusRingPortal, useKeyboardFocusHighlighting } from '@chayns-components/core';
2
+ import React, { memo, useRef } from 'react';
3
3
  import { StyledMotionGalleryEditorItem, StyledGalleryEditorItemDeleteButton } from './GalleryEditorItem.styles';
4
4
  import GalleryEditorMediaItem from './gallery-editor-media-item/GalleryEditorMediaItem';
5
5
  import GalleryEditorPreviewItem from './gallery-editor-preview-item/GalleryEditorPreviewItem';
6
6
  import { GALLERY_EDITOR_DELETE_BUTTON_Z_INDEX, GALLERY_EDITOR_ITEM_FADE_DURATION_S } from '../GalleryEditor.constants';
7
+ import { useTranslation } from '@chayns/textstrings';
8
+ import textStrings from '../../../constants/textStrings';
7
9
  const GalleryEditorItem = ({
8
10
  fileItem,
9
11
  handleDeleteFile,
10
12
  shouldLoadImages = true,
13
+ shouldEnableKeyboardHighlighting,
11
14
  ratio = 1,
12
15
  onClick
13
16
  }) => {
17
+ const {
18
+ t
19
+ } = useTranslation();
20
+ const deleteButtonRef = useRef(null);
21
+ const shouldShowKeyboardHighlighting = useKeyboardFocusHighlighting(shouldEnableKeyboardHighlighting);
22
+ useFocusRingPortal(deleteButtonRef, {
23
+ isEnabled: shouldShowKeyboardHighlighting,
24
+ padding: -1
25
+ });
14
26
  const shouldRenderPreview = fileItem.state === 'uploading';
15
27
  const shouldRenderMedia = fileItem.state !== 'none' && (Boolean(fileItem.previewUrl) || Boolean(fileItem.uploadedFile));
16
28
  let mediaContent = null;
@@ -25,7 +37,8 @@ const GalleryEditorItem = ({
25
37
  ratio: ratio,
26
38
  openSelectedFile: onClick,
27
39
  previewUrl: fileItem.previewUrl,
28
- shouldLoadImages: shouldLoadImages
40
+ shouldLoadImages: shouldLoadImages,
41
+ shouldEnableKeyboardHighlighting: shouldEnableKeyboardHighlighting
29
42
  });
30
43
  }
31
44
  return /*#__PURE__*/React.createElement(StyledMotionGalleryEditorItem, {
@@ -45,13 +58,14 @@ const GalleryEditorItem = ({
45
58
  duration: GALLERY_EDITOR_ITEM_FADE_DURATION_S
46
59
  }
47
60
  }, mediaContent, /*#__PURE__*/React.createElement(StyledGalleryEditorItemDeleteButton, {
61
+ ref: deleteButtonRef,
48
62
  type: "button",
49
63
  onClick: event => {
50
64
  event.stopPropagation();
51
65
  handleDeleteFile(fileItem.id);
52
66
  },
53
67
  $zIndex: GALLERY_EDITOR_DELETE_BUTTON_Z_INDEX,
54
- "aria-label": "Bild entfernen"
68
+ "aria-label": t(textStrings.galleryEditor.accessibility.removeImage)
55
69
  }, /*#__PURE__*/React.createElement(Icon, {
56
70
  size: 20,
57
71
  icons: ['ts-wrong']
@@ -1 +1 @@
1
- {"version":3,"file":"GalleryEditorItem.js","names":["Icon","React","memo","StyledMotionGalleryEditorItem","StyledGalleryEditorItemDeleteButton","GalleryEditorMediaItem","GalleryEditorPreviewItem","GALLERY_EDITOR_DELETE_BUTTON_Z_INDEX","GALLERY_EDITOR_ITEM_FADE_DURATION_S","GalleryEditorItem","fileItem","handleDeleteFile","shouldLoadImages","ratio","onClick","shouldRenderPreview","state","shouldRenderMedia","Boolean","previewUrl","uploadedFile","mediaContent","createElement","openSelectedFile","initial","opacity","scale","animate","exit","transition","duration","type","event","stopPropagation","id","$zIndex","size","icons","displayName"],"sources":["../../../../../src/components/gallery-editor/gallery-editor-item/GalleryEditorItem.tsx"],"sourcesContent":["import { Icon } from '@chayns-components/core';\nimport React, { FC, ReactNode, memo } from 'react';\nimport {\n StyledMotionGalleryEditorItem,\n StyledGalleryEditorItemDeleteButton,\n} from './GalleryEditorItem.styles';\nimport GalleryEditorMediaItem from './gallery-editor-media-item/GalleryEditorMediaItem';\nimport GalleryEditorPreviewItem from './gallery-editor-preview-item/GalleryEditorPreviewItem';\nimport type { GalleryEditorItemProps } from './GalleryEditorItem.types';\nimport {\n GALLERY_EDITOR_DELETE_BUTTON_Z_INDEX,\n GALLERY_EDITOR_ITEM_FADE_DURATION_S,\n} from '../GalleryEditor.constants';\n\nconst GalleryEditorItem: FC<GalleryEditorItemProps> = ({\n fileItem,\n handleDeleteFile,\n shouldLoadImages = true,\n ratio = 1,\n onClick,\n}) => {\n const shouldRenderPreview = fileItem.state === 'uploading';\n const shouldRenderMedia =\n fileItem.state !== 'none' &&\n (Boolean(fileItem.previewUrl) || Boolean(fileItem.uploadedFile));\n\n let mediaContent: ReactNode = null;\n\n if (shouldRenderPreview) {\n mediaContent = <GalleryEditorPreviewItem ratio={ratio} fileItem={fileItem} />;\n } else if (shouldRenderMedia) {\n mediaContent = (\n <GalleryEditorMediaItem\n fileItem={fileItem}\n ratio={ratio}\n openSelectedFile={onClick}\n previewUrl={fileItem.previewUrl}\n shouldLoadImages={shouldLoadImages}\n />\n );\n }\n\n return (\n <StyledMotionGalleryEditorItem\n initial={{ opacity: 0, scale: 0.98 }}\n animate={{ opacity: 1, scale: 1 }}\n exit={{ opacity: 0, scale: 0.98 }}\n transition={{ duration: GALLERY_EDITOR_ITEM_FADE_DURATION_S }}\n >\n {mediaContent}\n <StyledGalleryEditorItemDeleteButton\n type=\"button\"\n onClick={(event) => {\n event.stopPropagation();\n handleDeleteFile(fileItem.id);\n }}\n $zIndex={GALLERY_EDITOR_DELETE_BUTTON_Z_INDEX}\n aria-label=\"Bild entfernen\"\n >\n <Icon size={20} icons={['ts-wrong']} />\n </StyledGalleryEditorItemDeleteButton>\n </StyledMotionGalleryEditorItem>\n );\n};\n\nGalleryEditorItem.displayName = 'GalleryEditorItem';\n\nexport default memo(GalleryEditorItem);\n"],"mappings":"AAAA,SAASA,IAAI,QAAQ,yBAAyB;AAC9C,OAAOC,KAAK,IAAmBC,IAAI,QAAQ,OAAO;AAClD,SACIC,6BAA6B,EAC7BC,mCAAmC,QAChC,4BAA4B;AACnC,OAAOC,sBAAsB,MAAM,oDAAoD;AACvF,OAAOC,wBAAwB,MAAM,wDAAwD;AAE7F,SACIC,oCAAoC,EACpCC,mCAAmC,QAChC,4BAA4B;AAEnC,MAAMC,iBAA6C,GAAGA,CAAC;EACnDC,QAAQ;EACRC,gBAAgB;EAChBC,gBAAgB,GAAG,IAAI;EACvBC,KAAK,GAAG,CAAC;EACTC;AACJ,CAAC,KAAK;EACF,MAAMC,mBAAmB,GAAGL,QAAQ,CAACM,KAAK,KAAK,WAAW;EAC1D,MAAMC,iBAAiB,GACnBP,QAAQ,CAACM,KAAK,KAAK,MAAM,KACxBE,OAAO,CAACR,QAAQ,CAACS,UAAU,CAAC,IAAID,OAAO,CAACR,QAAQ,CAACU,YAAY,CAAC,CAAC;EAEpE,IAAIC,YAAuB,GAAG,IAAI;EAElC,IAAIN,mBAAmB,EAAE;IACrBM,YAAY,gBAAGpB,KAAA,CAAAqB,aAAA,CAAChB,wBAAwB;MAACO,KAAK,EAAEA,KAAM;MAACH,QAAQ,EAAEA;IAAS,CAAE,CAAC;EACjF,CAAC,MAAM,IAAIO,iBAAiB,EAAE;IAC1BI,YAAY,gBACRpB,KAAA,CAAAqB,aAAA,CAACjB,sBAAsB;MACnBK,QAAQ,EAAEA,QAAS;MACnBG,KAAK,EAAEA,KAAM;MACbU,gBAAgB,EAAET,OAAQ;MAC1BK,UAAU,EAAET,QAAQ,CAACS,UAAW;MAChCP,gBAAgB,EAAEA;IAAiB,CACtC,CACJ;EACL;EAEA,oBACIX,KAAA,CAAAqB,aAAA,CAACnB,6BAA6B;IAC1BqB,OAAO,EAAE;MAAEC,OAAO,EAAE,CAAC;MAAEC,KAAK,EAAE;IAAK,CAAE;IACrCC,OAAO,EAAE;MAAEF,OAAO,EAAE,CAAC;MAAEC,KAAK,EAAE;IAAE,CAAE;IAClCE,IAAI,EAAE;MAAEH,OAAO,EAAE,CAAC;MAAEC,KAAK,EAAE;IAAK,CAAE;IAClCG,UAAU,EAAE;MAAEC,QAAQ,EAAEtB;IAAoC;EAAE,GAE7Da,YAAY,eACbpB,KAAA,CAAAqB,aAAA,CAAClB,mCAAmC;IAChC2B,IAAI,EAAC,QAAQ;IACbjB,OAAO,EAAGkB,KAAK,IAAK;MAChBA,KAAK,CAACC,eAAe,CAAC,CAAC;MACvBtB,gBAAgB,CAACD,QAAQ,CAACwB,EAAE,CAAC;IACjC,CAAE;IACFC,OAAO,EAAE5B,oCAAqC;IAC9C,cAAW;EAAgB,gBAE3BN,KAAA,CAAAqB,aAAA,CAACtB,IAAI;IAACoC,IAAI,EAAE,EAAG;IAACC,KAAK,EAAE,CAAC,UAAU;EAAE,CAAE,CACL,CACV,CAAC;AAExC,CAAC;AAED5B,iBAAiB,CAAC6B,WAAW,GAAG,mBAAmB;AAEnD,4BAAepC,IAAI,CAACO,iBAAiB,CAAC","ignoreList":[]}
1
+ {"version":3,"file":"GalleryEditorItem.js","names":["Icon","useFocusRingPortal","useKeyboardFocusHighlighting","React","memo","useRef","StyledMotionGalleryEditorItem","StyledGalleryEditorItemDeleteButton","GalleryEditorMediaItem","GalleryEditorPreviewItem","GALLERY_EDITOR_DELETE_BUTTON_Z_INDEX","GALLERY_EDITOR_ITEM_FADE_DURATION_S","useTranslation","textStrings","GalleryEditorItem","fileItem","handleDeleteFile","shouldLoadImages","shouldEnableKeyboardHighlighting","ratio","onClick","t","deleteButtonRef","shouldShowKeyboardHighlighting","isEnabled","padding","shouldRenderPreview","state","shouldRenderMedia","Boolean","previewUrl","uploadedFile","mediaContent","createElement","openSelectedFile","initial","opacity","scale","animate","exit","transition","duration","ref","type","event","stopPropagation","id","$zIndex","galleryEditor","accessibility","removeImage","size","icons","displayName"],"sources":["../../../../../src/components/gallery-editor/gallery-editor-item/GalleryEditorItem.tsx"],"sourcesContent":["import { Icon, useFocusRingPortal, useKeyboardFocusHighlighting } from '@chayns-components/core';\nimport React, { FC, ReactNode, memo, useRef } from 'react';\nimport {\n StyledMotionGalleryEditorItem,\n StyledGalleryEditorItemDeleteButton,\n} from './GalleryEditorItem.styles';\nimport GalleryEditorMediaItem from './gallery-editor-media-item/GalleryEditorMediaItem';\nimport GalleryEditorPreviewItem from './gallery-editor-preview-item/GalleryEditorPreviewItem';\nimport type { GalleryEditorItemProps } from './GalleryEditorItem.types';\nimport {\n GALLERY_EDITOR_DELETE_BUTTON_Z_INDEX,\n GALLERY_EDITOR_ITEM_FADE_DURATION_S,\n} from '../GalleryEditor.constants';\nimport { useTranslation } from '@chayns/textstrings';\nimport textStrings from '../../../constants/textStrings';\n\nconst GalleryEditorItem: FC<GalleryEditorItemProps> = ({\n fileItem,\n handleDeleteFile,\n shouldLoadImages = true,\n shouldEnableKeyboardHighlighting,\n ratio = 1,\n onClick,\n}) => {\n const { t } = useTranslation();\n const deleteButtonRef = useRef<HTMLButtonElement>(null);\n const shouldShowKeyboardHighlighting = useKeyboardFocusHighlighting(\n shouldEnableKeyboardHighlighting,\n );\n useFocusRingPortal(deleteButtonRef, { isEnabled: shouldShowKeyboardHighlighting, padding: -1 });\n\n const shouldRenderPreview = fileItem.state === 'uploading';\n const shouldRenderMedia =\n fileItem.state !== 'none' &&\n (Boolean(fileItem.previewUrl) || Boolean(fileItem.uploadedFile));\n\n let mediaContent: ReactNode = null;\n\n if (shouldRenderPreview) {\n mediaContent = <GalleryEditorPreviewItem ratio={ratio} fileItem={fileItem} />;\n } else if (shouldRenderMedia) {\n mediaContent = (\n <GalleryEditorMediaItem\n fileItem={fileItem}\n ratio={ratio}\n openSelectedFile={onClick}\n previewUrl={fileItem.previewUrl}\n shouldLoadImages={shouldLoadImages}\n shouldEnableKeyboardHighlighting={shouldEnableKeyboardHighlighting}\n />\n );\n }\n\n return (\n <StyledMotionGalleryEditorItem\n initial={{ opacity: 0, scale: 0.98 }}\n animate={{ opacity: 1, scale: 1 }}\n exit={{ opacity: 0, scale: 0.98 }}\n transition={{ duration: GALLERY_EDITOR_ITEM_FADE_DURATION_S }}\n >\n {mediaContent}\n <StyledGalleryEditorItemDeleteButton\n ref={deleteButtonRef}\n type=\"button\"\n onClick={(event) => {\n event.stopPropagation();\n handleDeleteFile(fileItem.id);\n }}\n $zIndex={GALLERY_EDITOR_DELETE_BUTTON_Z_INDEX}\n aria-label={t(textStrings.galleryEditor.accessibility.removeImage)}\n >\n <Icon size={20} icons={['ts-wrong']} />\n </StyledGalleryEditorItemDeleteButton>\n </StyledMotionGalleryEditorItem>\n );\n};\n\nGalleryEditorItem.displayName = 'GalleryEditorItem';\n\nexport default memo(GalleryEditorItem);\n"],"mappings":"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","ignoreList":[]}
@@ -1 +1 @@
1
- {"version":3,"file":"GalleryEditorItem.types.js","names":[],"sources":["../../../../../src/components/gallery-editor/gallery-editor-item/GalleryEditorItem.types.ts"],"sourcesContent":["import type { InternalFileItem } from '@chayns-components/core';\n\n/**\n * Props for a single editable gallery tile.\n */\nexport interface GalleryEditorItemProps {\n /**\n * Provides the media item that should be rendered inside the tile.\n * @description\n * The item may represent a pending local upload or an already uploaded media file managed by the editor.\n * @example\n * <GalleryEditorItem fileItem={fileItem} handleDeleteFile={handleDeleteFile} onClick={handleOpen} />\n */\n fileItem: InternalFileItem;\n /**\n * Controls whether the item may load the final media source immediately.\n * @description\n * The item forwards this flag to the shared media renderer so uploaded media can stay on the preview until loading is allowed.\n * @default true\n * @optional\n */\n shouldLoadImages?: boolean;\n /**\n * Is called when the delete button is clicked in edit mode.\n * @description\n * The callback receives the internal item identifier so the editor can remove the item from its local state.\n * @example\n * <GalleryEditorItem handleDeleteFile={(id) => console.log(id)} fileItem={fileItem} onClick={handleOpen} />\n */\n handleDeleteFile: (id?: string) => void;\n /**\n * Defines the aspect ratio that should be reserved for the rendered media.\n * @description\n * Use this when the editor item should reserve a fixed tile ratio for uploaded previews.\n * @default 1\n * @example\n * <GalleryEditorItem fileItem={fileItem} handleDeleteFile={handleDeleteFile} onClick={handleOpen} ratio={1.5} />\n * @optional\n */\n ratio?: number;\n /**\n * Is called when the tile is clicked.\n * @description\n * The editor uses this callback to open the currently selected media within the slideshow flow.\n * @example\n * <GalleryEditorItem fileItem={fileItem} handleDeleteFile={handleDeleteFile} onClick={handleOpen} />\n */\n onClick: (file: InternalFileItem) => void;\n}\n"],"mappings":"","ignoreList":[]}
1
+ {"version":3,"file":"GalleryEditorItem.types.js","names":[],"sources":["../../../../../src/components/gallery-editor/gallery-editor-item/GalleryEditorItem.types.ts"],"sourcesContent":["import type { InternalFileItem } from '@chayns-components/core';\n\n/**\n * Props for a single editable gallery tile.\n */\nexport interface GalleryEditorItemProps {\n /**\n * Provides the media item that should be rendered inside the tile.\n * @description\n * The item may represent a pending local upload or an already uploaded media file managed by the editor.\n * @example\n * <GalleryEditorItem fileItem={fileItem} handleDeleteFile={handleDeleteFile} onClick={handleOpen} />\n */\n fileItem: InternalFileItem;\n /**\n * Controls whether the item may load the final media source immediately.\n * @description\n * The item forwards this flag to the shared media renderer so uploaded media can stay on the preview until loading is allowed.\n * @default true\n * @optional\n */\n shouldLoadImages?: boolean;\n /**\n * Enables keyboard-only focus highlighting for the media tile and delete button.\n */\n shouldEnableKeyboardHighlighting?: boolean;\n /**\n * Is called when the delete button is clicked in edit mode.\n * @description\n * The callback receives the internal item identifier so the editor can remove the item from its local state.\n * @example\n * <GalleryEditorItem handleDeleteFile={(id) => console.log(id)} fileItem={fileItem} onClick={handleOpen} />\n */\n handleDeleteFile: (id?: string) => void;\n /**\n * Defines the aspect ratio that should be reserved for the rendered media.\n * @description\n * Use this when the editor item should reserve a fixed tile ratio for uploaded previews.\n * @default 1\n * @example\n * <GalleryEditorItem fileItem={fileItem} handleDeleteFile={handleDeleteFile} onClick={handleOpen} ratio={1.5} />\n * @optional\n */\n ratio?: number;\n /**\n * Is called when the tile is clicked.\n * @description\n * The editor uses this callback to open the currently selected media within the slideshow flow.\n * @example\n * <GalleryEditorItem fileItem={fileItem} handleDeleteFile={handleDeleteFile} onClick={handleOpen} />\n */\n onClick: (file: InternalFileItem) => void;\n}\n"],"mappings":"","ignoreList":[]}
@@ -7,6 +7,7 @@ const GalleryEditorMediaItem = ({
7
7
  openSelectedFile,
8
8
  previewUrl,
9
9
  shouldLoadImages = true,
10
+ shouldEnableKeyboardHighlighting,
10
11
  ratio
11
12
  }) => /*#__PURE__*/React.createElement(StyledMotionGalleryEditorMediaItem, {
12
13
  animate: {
@@ -27,7 +28,8 @@ const GalleryEditorMediaItem = ({
27
28
  playIconSize: 30,
28
29
  previewUrl: previewUrl,
29
30
  ratio: ratio,
30
- shouldLoadImages: shouldLoadImages
31
+ shouldLoadImages: shouldLoadImages,
32
+ shouldEnableKeyboardHighlighting: shouldEnableKeyboardHighlighting
31
33
  }));
32
34
  GalleryEditorMediaItem.displayName = 'GalleryEditorMediaItem';
33
35
  export default /*#__PURE__*/memo(GalleryEditorMediaItem);
@@ -1 +1 @@
1
- {"version":3,"file":"GalleryEditorMediaItem.js","names":["React","memo","MediaContent","StyledMotionGalleryEditorMediaItem","GALLERY_EDITOR_MEDIA_FADE_DURATION_S","GalleryEditorMediaItem","fileItem","openSelectedFile","previewUrl","shouldLoadImages","ratio","createElement","animate","opacity","initial","exit","transition","duration","uploadedFile","file","onClick","playIconSize","displayName"],"sources":["../../../../../../src/components/gallery-editor/gallery-editor-item/gallery-editor-media-item/GalleryEditorMediaItem.tsx"],"sourcesContent":["import React, { FC, memo } from 'react';\nimport MediaContent from '../../../media-content/MediaContent';\nimport { StyledMotionGalleryEditorMediaItem } from './GalleryEditorMediaItem.styles';\nimport type { GalleryEditorMediaItemProps } from './GalleryEditorMediaItem.types';\nimport { GALLERY_EDITOR_MEDIA_FADE_DURATION_S } from '../../GalleryEditor.constants';\n\nconst GalleryEditorMediaItem: FC<GalleryEditorMediaItemProps> = ({\n fileItem,\n openSelectedFile,\n previewUrl,\n shouldLoadImages = true,\n ratio,\n}) => (\n <StyledMotionGalleryEditorMediaItem\n animate={{ opacity: 1 }}\n initial={{ opacity: 0 }}\n exit={{ opacity: 0 }}\n transition={{ duration: GALLERY_EDITOR_MEDIA_FADE_DURATION_S }}\n >\n {fileItem.uploadedFile && (\n <MediaContent\n file={fileItem.uploadedFile}\n onClick={() => openSelectedFile(fileItem)}\n playIconSize={30}\n previewUrl={previewUrl}\n ratio={ratio}\n shouldLoadImages={shouldLoadImages}\n />\n )}\n </StyledMotionGalleryEditorMediaItem>\n);\n\nGalleryEditorMediaItem.displayName = 'GalleryEditorMediaItem';\n\nexport default memo(GalleryEditorMediaItem);\n"],"mappings":"AAAA,OAAOA,KAAK,IAAQC,IAAI,QAAQ,OAAO;AACvC,OAAOC,YAAY,MAAM,qCAAqC;AAC9D,SAASC,kCAAkC,QAAQ,iCAAiC;AAEpF,SAASC,oCAAoC,QAAQ,+BAA+B;AAEpF,MAAMC,sBAAuD,GAAGA,CAAC;EAC7DC,QAAQ;EACRC,gBAAgB;EAChBC,UAAU;EACVC,gBAAgB,GAAG,IAAI;EACvBC;AACJ,CAAC,kBACGV,KAAA,CAAAW,aAAA,CAACR,kCAAkC;EAC/BS,OAAO,EAAE;IAAEC,OAAO,EAAE;EAAE,CAAE;EACxBC,OAAO,EAAE;IAAED,OAAO,EAAE;EAAE,CAAE;EACxBE,IAAI,EAAE;IAAEF,OAAO,EAAE;EAAE,CAAE;EACrBG,UAAU,EAAE;IAAEC,QAAQ,EAAEb;EAAqC;AAAE,GAE9DE,QAAQ,CAACY,YAAY,iBAClBlB,KAAA,CAAAW,aAAA,CAACT,YAAY;EACTiB,IAAI,EAAEb,QAAQ,CAACY,YAAa;EAC5BE,OAAO,EAAEA,CAAA,KAAMb,gBAAgB,CAACD,QAAQ,CAAE;EAC1Ce,YAAY,EAAE,EAAG;EACjBb,UAAU,EAAEA,UAAW;EACvBE,KAAK,EAAEA,KAAM;EACbD,gBAAgB,EAAEA;AAAiB,CACtC,CAE2B,CACvC;AAEDJ,sBAAsB,CAACiB,WAAW,GAAG,wBAAwB;AAE7D,4BAAerB,IAAI,CAACI,sBAAsB,CAAC","ignoreList":[]}
1
+ {"version":3,"file":"GalleryEditorMediaItem.js","names":["React","memo","MediaContent","StyledMotionGalleryEditorMediaItem","GALLERY_EDITOR_MEDIA_FADE_DURATION_S","GalleryEditorMediaItem","fileItem","openSelectedFile","previewUrl","shouldLoadImages","shouldEnableKeyboardHighlighting","ratio","createElement","animate","opacity","initial","exit","transition","duration","uploadedFile","file","onClick","playIconSize","displayName"],"sources":["../../../../../../src/components/gallery-editor/gallery-editor-item/gallery-editor-media-item/GalleryEditorMediaItem.tsx"],"sourcesContent":["import React, { FC, memo } from 'react';\nimport MediaContent from '../../../media-content/MediaContent';\nimport { StyledMotionGalleryEditorMediaItem } from './GalleryEditorMediaItem.styles';\nimport type { GalleryEditorMediaItemProps } from './GalleryEditorMediaItem.types';\nimport { GALLERY_EDITOR_MEDIA_FADE_DURATION_S } from '../../GalleryEditor.constants';\n\nconst GalleryEditorMediaItem: FC<GalleryEditorMediaItemProps> = ({\n fileItem,\n openSelectedFile,\n previewUrl,\n shouldLoadImages = true,\n shouldEnableKeyboardHighlighting,\n ratio,\n}) => (\n <StyledMotionGalleryEditorMediaItem\n animate={{ opacity: 1 }}\n initial={{ opacity: 0 }}\n exit={{ opacity: 0 }}\n transition={{ duration: GALLERY_EDITOR_MEDIA_FADE_DURATION_S }}\n >\n {fileItem.uploadedFile && (\n <MediaContent\n file={fileItem.uploadedFile}\n onClick={() => openSelectedFile(fileItem)}\n playIconSize={30}\n previewUrl={previewUrl}\n ratio={ratio}\n shouldLoadImages={shouldLoadImages}\n shouldEnableKeyboardHighlighting={shouldEnableKeyboardHighlighting}\n />\n )}\n </StyledMotionGalleryEditorMediaItem>\n);\n\nGalleryEditorMediaItem.displayName = 'GalleryEditorMediaItem';\n\nexport default memo(GalleryEditorMediaItem);\n"],"mappings":"AAAA,OAAOA,KAAK,IAAQC,IAAI,QAAQ,OAAO;AACvC,OAAOC,YAAY,MAAM,qCAAqC;AAC9D,SAASC,kCAAkC,QAAQ,iCAAiC;AAEpF,SAASC,oCAAoC,QAAQ,+BAA+B;AAEpF,MAAMC,sBAAuD,GAAGA,CAAC;EAC7DC,QAAQ;EACRC,gBAAgB;EAChBC,UAAU;EACVC,gBAAgB,GAAG,IAAI;EACvBC,gCAAgC;EAChCC;AACJ,CAAC,kBACGX,KAAA,CAAAY,aAAA,CAACT,kCAAkC;EAC/BU,OAAO,EAAE;IAAEC,OAAO,EAAE;EAAE,CAAE;EACxBC,OAAO,EAAE;IAAED,OAAO,EAAE;EAAE,CAAE;EACxBE,IAAI,EAAE;IAAEF,OAAO,EAAE;EAAE,CAAE;EACrBG,UAAU,EAAE;IAAEC,QAAQ,EAAEd;EAAqC;AAAE,GAE9DE,QAAQ,CAACa,YAAY,iBAClBnB,KAAA,CAAAY,aAAA,CAACV,YAAY;EACTkB,IAAI,EAAEd,QAAQ,CAACa,YAAa;EAC5BE,OAAO,EAAEA,CAAA,KAAMd,gBAAgB,CAACD,QAAQ,CAAE;EAC1CgB,YAAY,EAAE,EAAG;EACjBd,UAAU,EAAEA,UAAW;EACvBG,KAAK,EAAEA,KAAM;EACbF,gBAAgB,EAAEA,gBAAiB;EACnCC,gCAAgC,EAAEA;AAAiC,CACtE,CAE2B,CACvC;AAEDL,sBAAsB,CAACkB,WAAW,GAAG,wBAAwB;AAE7D,4BAAetB,IAAI,CAACI,sBAAsB,CAAC","ignoreList":[]}
@@ -1 +1 @@
1
- {"version":3,"file":"GalleryEditorMediaItem.types.js","names":[],"sources":["../../../../../../src/components/gallery-editor/gallery-editor-item/gallery-editor-media-item/GalleryEditorMediaItem.types.ts"],"sourcesContent":["import type { InternalFileItem } from '@chayns-components/core';\n\n/**\n * Props for a rendered uploaded media item.\n */\nexport interface GalleryEditorMediaItemProps {\n /**\n * Provides the uploaded media item that should be rendered.\n * @description\n * This item is expected to contain an `uploadedFile` because pending uploads are rendered by the preview component instead.\n * @example\n * <GalleryEditorMediaItem fileItem={fileItem} onClick={handleOpen} ratio={1} />\n */\n fileItem: InternalFileItem;\n /**\n * Controls whether the media renderer may load the final uploaded source immediately.\n * @description\n * When disabled, the shared media renderer keeps showing the preview until the parent gallery allows the final load.\n * @default true\n * @optional\n */\n shouldLoadImages?: boolean;\n /**\n * Is called when the media tile is selected.\n * @description\n * The editor uses this callback to open the uploaded media in the slideshow flow.\n * @example\n * <GalleryEditorMediaItem fileItem={fileItem} openSelectedFile={handleOpen} ratio={1} />\n */\n openSelectedFile: (file: InternalFileItem) => void;\n /**\n * Defines the aspect ratio that should be reserved for the media.\n * @description\n * The media tile keeps this ratio reserved so the editor grid remains visually stable.\n * @example\n * <GalleryEditorMediaItem fileItem={fileItem} openSelectedFile={handleOpen} ratio={1.5} />\n */\n ratio: number;\n /**\n * Provides an optional preview source that can be shown before the final uploaded media loads.\n * @description\n * This is typically the local base64 preview generated while the file is still being uploaded.\n * @optional\n */\n previewUrl?: string;\n}\n"],"mappings":"","ignoreList":[]}
1
+ {"version":3,"file":"GalleryEditorMediaItem.types.js","names":[],"sources":["../../../../../../src/components/gallery-editor/gallery-editor-item/gallery-editor-media-item/GalleryEditorMediaItem.types.ts"],"sourcesContent":["import type { InternalFileItem } from '@chayns-components/core';\n\n/**\n * Props for a rendered uploaded media item.\n */\nexport interface GalleryEditorMediaItemProps {\n /**\n * Provides the uploaded media item that should be rendered.\n * @description\n * This item is expected to contain an `uploadedFile` because pending uploads are rendered by the preview component instead.\n * @example\n * <GalleryEditorMediaItem fileItem={fileItem} onClick={handleOpen} ratio={1} />\n */\n fileItem: InternalFileItem;\n /**\n * Controls whether the media renderer may load the final uploaded source immediately.\n * @description\n * When disabled, the shared media renderer keeps showing the preview until the parent gallery allows the final load.\n * @default true\n * @optional\n */\n shouldLoadImages?: boolean;\n /**\n * Enables keyboard-only focus highlighting for the media tile.\n */\n shouldEnableKeyboardHighlighting?: boolean;\n /**\n * Is called when the media tile is selected.\n * @description\n * The editor uses this callback to open the uploaded media in the slideshow flow.\n * @example\n * <GalleryEditorMediaItem fileItem={fileItem} openSelectedFile={handleOpen} ratio={1} />\n */\n openSelectedFile: (file: InternalFileItem) => void;\n /**\n * Defines the aspect ratio that should be reserved for the media.\n * @description\n * The media tile keeps this ratio reserved so the editor grid remains visually stable.\n * @example\n * <GalleryEditorMediaItem fileItem={fileItem} openSelectedFile={handleOpen} ratio={1.5} />\n */\n ratio: number;\n /**\n * Provides an optional preview source that can be shown before the final uploaded media loads.\n * @description\n * This is typically the local base64 preview generated while the file is still being uploaded.\n * @optional\n */\n previewUrl?: string;\n}\n"],"mappings":"","ignoreList":[]}
@@ -8,6 +8,7 @@ const EMPTY_FILE_ITEMS = [];
8
8
  const GalleryViewer = ({
9
9
  files,
10
10
  shouldLoadImages = true,
11
+ shouldEnableKeyboardHighlighting,
11
12
  viewMode = GalleryViewMode.GRID
12
13
  }) => {
13
14
  const fileItems = files ?? EMPTY_FILE_ITEMS;
@@ -30,6 +31,7 @@ const GalleryViewer = ({
30
31
  viewMode
31
32
  }),
32
33
  shouldLoadImages: shouldLoadImages,
34
+ shouldEnableKeyboardHighlighting: shouldEnableKeyboardHighlighting,
33
35
  remainingItemsLength: fileItems.length > GALLERY_VIEWER_MAX_VISIBLE_ITEMS && index === 3 ? fileItems.length : undefined
34
36
  }))));
35
37
  };