@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
@@ -1 +1 @@
1
- {"version":3,"file":"GalleryViewer.js","names":["React","memo","useCallback","GalleryViewerItem","StyledGalleryViewer","StyledGalleryViewerItemWrapper","getGalleryRatio","getGalleryViewerKey","getReadOnlyItemRatio","openKnownFiles","GalleryViewMode","GALLERY_VIEWER_MAX_VISIBLE_ITEMS","EMPTY_FILE_ITEMS","GalleryViewer","files","shouldLoadImages","viewMode","GRID","fileItems","ratio","handleOpenFiles","file","visibleItems","slice","createElement","$ratio","$itemCount","length","$viewMode","map","index","key","fileItem","onClick","remainingItemsLength","undefined","displayName"],"sources":["../../../../src/components/gallery-viewer/GalleryViewer.tsx"],"sourcesContent":["import type { FileItem } from '@chayns-components/core';\nimport React, { FC, memo, useCallback } from 'react';\nimport GalleryViewerItem from './gallery-viewer-item/GalleryViewerItem';\nimport { StyledGalleryViewer, StyledGalleryViewerItemWrapper } from './GalleryViewer.styles';\nimport type { GalleryViewerProps } from './GalleryViewer.types';\nimport {\n getGalleryRatio,\n getGalleryViewerKey,\n getReadOnlyItemRatio,\n openKnownFiles,\n} from '../../utils/gallery';\nimport { GalleryViewMode } from '../../types/gallery';\nimport { GALLERY_VIEWER_MAX_VISIBLE_ITEMS } from './GalleryViewer.constants';\n\nconst EMPTY_FILE_ITEMS: FileItem[] = [];\n\nconst GalleryViewer: FC<GalleryViewerProps> = ({\n files,\n shouldLoadImages = true,\n viewMode = GalleryViewMode.GRID,\n}) => {\n const fileItems = files ?? EMPTY_FILE_ITEMS;\n const ratio = getGalleryRatio(fileItems);\n\n const handleOpenFiles = useCallback(\n (file: FileItem) => {\n openKnownFiles(fileItems, file);\n },\n [fileItems],\n );\n\n const visibleItems = fileItems.slice(0, GALLERY_VIEWER_MAX_VISIBLE_ITEMS);\n\n return (\n <StyledGalleryViewer>\n <StyledGalleryViewerItemWrapper\n $ratio={ratio}\n $itemCount={fileItems.length}\n $viewMode={viewMode}\n >\n {visibleItems.map((file, index) => (\n <GalleryViewerItem\n key={getGalleryViewerKey(file, index)}\n fileItem={file}\n onClick={handleOpenFiles}\n ratio={getReadOnlyItemRatio({ fileItems, index, viewMode })}\n shouldLoadImages={shouldLoadImages}\n remainingItemsLength={\n fileItems.length > GALLERY_VIEWER_MAX_VISIBLE_ITEMS && index === 3\n ? fileItems.length\n : undefined\n }\n />\n ))}\n </StyledGalleryViewerItemWrapper>\n </StyledGalleryViewer>\n );\n};\n\nGalleryViewer.displayName = 'GalleryViewer';\n\nexport default memo(GalleryViewer);\n"],"mappings":"AACA,OAAOA,KAAK,IAAQC,IAAI,EAAEC,WAAW,QAAQ,OAAO;AACpD,OAAOC,iBAAiB,MAAM,yCAAyC;AACvE,SAASC,mBAAmB,EAAEC,8BAA8B,QAAQ,wBAAwB;AAE5F,SACIC,eAAe,EACfC,mBAAmB,EACnBC,oBAAoB,EACpBC,cAAc,QACX,qBAAqB;AAC5B,SAASC,eAAe,QAAQ,qBAAqB;AACrD,SAASC,gCAAgC,QAAQ,2BAA2B;AAE5E,MAAMC,gBAA4B,GAAG,EAAE;AAEvC,MAAMC,aAAqC,GAAGA,CAAC;EAC3CC,KAAK;EACLC,gBAAgB,GAAG,IAAI;EACvBC,QAAQ,GAAGN,eAAe,CAACO;AAC/B,CAAC,KAAK;EACF,MAAMC,SAAS,GAAGJ,KAAK,IAAIF,gBAAgB;EAC3C,MAAMO,KAAK,GAAGb,eAAe,CAACY,SAAS,CAAC;EAExC,MAAME,eAAe,GAAGlB,WAAW,CAC9BmB,IAAc,IAAK;IAChBZ,cAAc,CAACS,SAAS,EAAEG,IAAI,CAAC;EACnC,CAAC,EACD,CAACH,SAAS,CACd,CAAC;EAED,MAAMI,YAAY,GAAGJ,SAAS,CAACK,KAAK,CAAC,CAAC,EAAEZ,gCAAgC,CAAC;EAEzE,oBACIX,KAAA,CAAAwB,aAAA,CAACpB,mBAAmB,qBAChBJ,KAAA,CAAAwB,aAAA,CAACnB,8BAA8B;IAC3BoB,MAAM,EAAEN,KAAM;IACdO,UAAU,EAAER,SAAS,CAACS,MAAO;IAC7BC,SAAS,EAAEZ;EAAS,GAEnBM,YAAY,CAACO,GAAG,CAAC,CAACR,IAAI,EAAES,KAAK,kBAC1B9B,KAAA,CAAAwB,aAAA,CAACrB,iBAAiB;IACd4B,GAAG,EAAExB,mBAAmB,CAACc,IAAI,EAAES,KAAK,CAAE;IACtCE,QAAQ,EAAEX,IAAK;IACfY,OAAO,EAAEb,eAAgB;IACzBD,KAAK,EAAEX,oBAAoB,CAAC;MAAEU,SAAS;MAAEY,KAAK;MAAEd;IAAS,CAAC,CAAE;IAC5DD,gBAAgB,EAAEA,gBAAiB;IACnCmB,oBAAoB,EAChBhB,SAAS,CAACS,MAAM,GAAGhB,gCAAgC,IAAImB,KAAK,KAAK,CAAC,GAC5DZ,SAAS,CAACS,MAAM,GAChBQ;EACT,CACJ,CACJ,CAC2B,CACf,CAAC;AAE9B,CAAC;AAEDtB,aAAa,CAACuB,WAAW,GAAG,eAAe;AAE3C,4BAAenC,IAAI,CAACY,aAAa,CAAC","ignoreList":[]}
1
+ {"version":3,"file":"GalleryViewer.js","names":["React","memo","useCallback","GalleryViewerItem","StyledGalleryViewer","StyledGalleryViewerItemWrapper","getGalleryRatio","getGalleryViewerKey","getReadOnlyItemRatio","openKnownFiles","GalleryViewMode","GALLERY_VIEWER_MAX_VISIBLE_ITEMS","EMPTY_FILE_ITEMS","GalleryViewer","files","shouldLoadImages","shouldEnableKeyboardHighlighting","viewMode","GRID","fileItems","ratio","handleOpenFiles","file","visibleItems","slice","createElement","$ratio","$itemCount","length","$viewMode","map","index","key","fileItem","onClick","remainingItemsLength","undefined","displayName"],"sources":["../../../../src/components/gallery-viewer/GalleryViewer.tsx"],"sourcesContent":["import type { FileItem } from '@chayns-components/core';\nimport React, { FC, memo, useCallback } from 'react';\nimport GalleryViewerItem from './gallery-viewer-item/GalleryViewerItem';\nimport { StyledGalleryViewer, StyledGalleryViewerItemWrapper } from './GalleryViewer.styles';\nimport type { GalleryViewerProps } from './GalleryViewer.types';\nimport {\n getGalleryRatio,\n getGalleryViewerKey,\n getReadOnlyItemRatio,\n openKnownFiles,\n} from '../../utils/gallery';\nimport { GalleryViewMode } from '../../types/gallery';\nimport { GALLERY_VIEWER_MAX_VISIBLE_ITEMS } from './GalleryViewer.constants';\n\nconst EMPTY_FILE_ITEMS: FileItem[] = [];\n\nconst GalleryViewer: FC<GalleryViewerProps> = ({\n files,\n shouldLoadImages = true,\n shouldEnableKeyboardHighlighting,\n viewMode = GalleryViewMode.GRID,\n}) => {\n const fileItems = files ?? EMPTY_FILE_ITEMS;\n const ratio = getGalleryRatio(fileItems);\n\n const handleOpenFiles = useCallback(\n (file: FileItem) => {\n openKnownFiles(fileItems, file);\n },\n [fileItems],\n );\n\n const visibleItems = fileItems.slice(0, GALLERY_VIEWER_MAX_VISIBLE_ITEMS);\n\n return (\n <StyledGalleryViewer>\n <StyledGalleryViewerItemWrapper\n $ratio={ratio}\n $itemCount={fileItems.length}\n $viewMode={viewMode}\n >\n {visibleItems.map((file, index) => (\n <GalleryViewerItem\n key={getGalleryViewerKey(file, index)}\n fileItem={file}\n onClick={handleOpenFiles}\n ratio={getReadOnlyItemRatio({ fileItems, index, viewMode })}\n shouldLoadImages={shouldLoadImages}\n shouldEnableKeyboardHighlighting={shouldEnableKeyboardHighlighting}\n remainingItemsLength={\n fileItems.length > GALLERY_VIEWER_MAX_VISIBLE_ITEMS && index === 3\n ? fileItems.length\n : undefined\n }\n />\n ))}\n </StyledGalleryViewerItemWrapper>\n </StyledGalleryViewer>\n );\n};\n\nGalleryViewer.displayName = 'GalleryViewer';\n\nexport default memo(GalleryViewer);\n"],"mappings":"AACA,OAAOA,KAAK,IAAQC,IAAI,EAAEC,WAAW,QAAQ,OAAO;AACpD,OAAOC,iBAAiB,MAAM,yCAAyC;AACvE,SAASC,mBAAmB,EAAEC,8BAA8B,QAAQ,wBAAwB;AAE5F,SACIC,eAAe,EACfC,mBAAmB,EACnBC,oBAAoB,EACpBC,cAAc,QACX,qBAAqB;AAC5B,SAASC,eAAe,QAAQ,qBAAqB;AACrD,SAASC,gCAAgC,QAAQ,2BAA2B;AAE5E,MAAMC,gBAA4B,GAAG,EAAE;AAEvC,MAAMC,aAAqC,GAAGA,CAAC;EAC3CC,KAAK;EACLC,gBAAgB,GAAG,IAAI;EACvBC,gCAAgC;EAChCC,QAAQ,GAAGP,eAAe,CAACQ;AAC/B,CAAC,KAAK;EACF,MAAMC,SAAS,GAAGL,KAAK,IAAIF,gBAAgB;EAC3C,MAAMQ,KAAK,GAAGd,eAAe,CAACa,SAAS,CAAC;EAExC,MAAME,eAAe,GAAGnB,WAAW,CAC9BoB,IAAc,IAAK;IAChBb,cAAc,CAACU,SAAS,EAAEG,IAAI,CAAC;EACnC,CAAC,EACD,CAACH,SAAS,CACd,CAAC;EAED,MAAMI,YAAY,GAAGJ,SAAS,CAACK,KAAK,CAAC,CAAC,EAAEb,gCAAgC,CAAC;EAEzE,oBACIX,KAAA,CAAAyB,aAAA,CAACrB,mBAAmB,qBAChBJ,KAAA,CAAAyB,aAAA,CAACpB,8BAA8B;IAC3BqB,MAAM,EAAEN,KAAM;IACdO,UAAU,EAAER,SAAS,CAACS,MAAO;IAC7BC,SAAS,EAAEZ;EAAS,GAEnBM,YAAY,CAACO,GAAG,CAAC,CAACR,IAAI,EAAES,KAAK,kBAC1B/B,KAAA,CAAAyB,aAAA,CAACtB,iBAAiB;IACd6B,GAAG,EAAEzB,mBAAmB,CAACe,IAAI,EAAES,KAAK,CAAE;IACtCE,QAAQ,EAAEX,IAAK;IACfY,OAAO,EAAEb,eAAgB;IACzBD,KAAK,EAAEZ,oBAAoB,CAAC;MAAEW,SAAS;MAAEY,KAAK;MAAEd;IAAS,CAAC,CAAE;IAC5DF,gBAAgB,EAAEA,gBAAiB;IACnCC,gCAAgC,EAAEA,gCAAiC;IACnEmB,oBAAoB,EAChBhB,SAAS,CAACS,MAAM,GAAGjB,gCAAgC,IAAIoB,KAAK,KAAK,CAAC,GAC5DZ,SAAS,CAACS,MAAM,GAChBQ;EACT,CACJ,CACJ,CAC2B,CACf,CAAC;AAE9B,CAAC;AAEDvB,aAAa,CAACwB,WAAW,GAAG,eAAe;AAE3C,4BAAepC,IAAI,CAACY,aAAa,CAAC","ignoreList":[]}
@@ -1 +1 @@
1
- {"version":3,"file":"GalleryViewer.types.js","names":[],"sources":["../../../../src/components/gallery-viewer/GalleryViewer.types.ts"],"sourcesContent":["import type { FileItem } from '@chayns-components/core';\nimport type { GalleryViewMode } from '../../types/gallery';\n\n/**\n * Props for the prop-driven read-only gallery viewer.\n */\nexport interface GalleryViewerProps {\n /**\n * Provides the already known media items that should be rendered without local upload state.\n * @description\n * The viewer renders these files directly from props and does not mirror them into local component state.\n * @example\n * <GalleryViewer files={files} />\n * @optional\n */\n files?: FileItem[];\n /**\n * Controls whether the viewer may load the final media assets immediately.\n * @description\n * When set to `true`, the viewer renders and loads the actual images right away.\n * When set to `false`, the viewer keeps showing previews first and defers the final image load until this flag becomes `true`.\n * @default true\n * @example\n * <GalleryViewer files={files} shouldLoadImages={false} />\n * @optional\n */\n shouldLoadImages?: boolean;\n /**\n * Defines how the media tiles are arranged in read-only mode.\n * @description\n * Use this prop to switch between the supported viewer layouts for known media.\n * @default GalleryViewMode.GRID\n * @example\n * <GalleryViewer files={files} viewMode={GalleryViewMode.SQUARE} />\n * @optional\n */\n viewMode?: GalleryViewMode;\n}\n"],"mappings":"","ignoreList":[]}
1
+ {"version":3,"file":"GalleryViewer.types.js","names":[],"sources":["../../../../src/components/gallery-viewer/GalleryViewer.types.ts"],"sourcesContent":["import type { FileItem } from '@chayns-components/core';\nimport type { GalleryViewMode } from '../../types/gallery';\n\n/**\n * Props for the prop-driven read-only gallery viewer.\n */\nexport interface GalleryViewerProps {\n /**\n * Provides the already known media items that should be rendered without local upload state.\n * @description\n * The viewer renders these files directly from props and does not mirror them into local component state.\n * @example\n * <GalleryViewer files={files} />\n * @optional\n */\n files?: FileItem[];\n /**\n * Controls whether the viewer may load the final media assets immediately.\n * @description\n * When set to `true`, the viewer renders and loads the actual images right away.\n * When set to `false`, the viewer keeps showing previews first and defers the final image load until this flag becomes `true`.\n * @default true\n * @example\n * <GalleryViewer files={files} shouldLoadImages={false} />\n * @optional\n */\n shouldLoadImages?: boolean;\n /**\n * Enables keyboard-only focus highlighting for media tiles.\n */\n shouldEnableKeyboardHighlighting?: boolean;\n /**\n * Defines how the media tiles are arranged in read-only mode.\n * @description\n * Use this prop to switch between the supported viewer layouts for known media.\n * @default GalleryViewMode.GRID\n * @example\n * <GalleryViewer files={files} viewMode={GalleryViewMode.SQUARE} />\n * @optional\n */\n viewMode?: GalleryViewMode;\n}\n"],"mappings":"","ignoreList":[]}
@@ -6,14 +6,16 @@ const GalleryViewerItem = ({
6
6
  shouldLoadImages = true,
7
7
  ratio = 1,
8
8
  remainingItemsLength,
9
- onClick
9
+ onClick,
10
+ shouldEnableKeyboardHighlighting
10
11
  }) => {
11
12
  const handleClick = useCallback(() => onClick(fileItem), [fileItem, onClick]);
12
13
  return /*#__PURE__*/React.createElement(StyledGalleryViewerItem, null, /*#__PURE__*/React.createElement(MediaContent, {
13
14
  file: fileItem.file,
14
15
  onClick: handleClick,
15
16
  ratio: ratio,
16
- shouldLoadImages: shouldLoadImages
17
+ shouldLoadImages: shouldLoadImages,
18
+ shouldEnableKeyboardHighlighting: shouldEnableKeyboardHighlighting
17
19
  }), remainingItemsLength && /*#__PURE__*/React.createElement(StyledGalleryViewerMoreItemsIndicator, {
18
20
  onClick: handleClick
19
21
  }, /*#__PURE__*/React.createElement("p", null, `+ ${remainingItemsLength - 3}`)));
@@ -1 +1 @@
1
- {"version":3,"file":"GalleryViewerItem.js","names":["React","memo","useCallback","MediaContent","StyledGalleryViewerItem","StyledGalleryViewerMoreItemsIndicator","GalleryViewerItem","fileItem","shouldLoadImages","ratio","remainingItemsLength","onClick","handleClick","createElement","file","displayName"],"sources":["../../../../../src/components/gallery-viewer/gallery-viewer-item/GalleryViewerItem.tsx"],"sourcesContent":["import React, { FC, memo, useCallback } from 'react';\nimport MediaContent from '../../media-content/MediaContent';\nimport {\n StyledGalleryViewerItem,\n StyledGalleryViewerMoreItemsIndicator,\n} from './GalleryViewerItem.styles';\nimport type { GalleryViewerItemProps } from './GalleryViewerItem.types';\n\nconst GalleryViewerItem: FC<GalleryViewerItemProps> = ({\n fileItem,\n shouldLoadImages = true,\n ratio = 1,\n remainingItemsLength,\n onClick,\n}) => {\n const handleClick = useCallback(() => onClick(fileItem), [fileItem, onClick]);\n\n return (\n <StyledGalleryViewerItem>\n <MediaContent\n file={fileItem.file}\n onClick={handleClick}\n ratio={ratio}\n shouldLoadImages={shouldLoadImages}\n />\n {remainingItemsLength && (\n <StyledGalleryViewerMoreItemsIndicator onClick={handleClick}>\n <p>{`+ ${remainingItemsLength - 3}`}</p>\n </StyledGalleryViewerMoreItemsIndicator>\n )}\n </StyledGalleryViewerItem>\n );\n};\n\nGalleryViewerItem.displayName = 'GalleryViewerItem';\n\nexport default memo(GalleryViewerItem);\n"],"mappings":"AAAA,OAAOA,KAAK,IAAQC,IAAI,EAAEC,WAAW,QAAQ,OAAO;AACpD,OAAOC,YAAY,MAAM,kCAAkC;AAC3D,SACIC,uBAAuB,EACvBC,qCAAqC,QAClC,4BAA4B;AAGnC,MAAMC,iBAA6C,GAAGA,CAAC;EACnDC,QAAQ;EACRC,gBAAgB,GAAG,IAAI;EACvBC,KAAK,GAAG,CAAC;EACTC,oBAAoB;EACpBC;AACJ,CAAC,KAAK;EACF,MAAMC,WAAW,GAAGV,WAAW,CAAC,MAAMS,OAAO,CAACJ,QAAQ,CAAC,EAAE,CAACA,QAAQ,EAAEI,OAAO,CAAC,CAAC;EAE7E,oBACIX,KAAA,CAAAa,aAAA,CAACT,uBAAuB,qBACpBJ,KAAA,CAAAa,aAAA,CAACV,YAAY;IACTW,IAAI,EAAEP,QAAQ,CAACO,IAAK;IACpBH,OAAO,EAAEC,WAAY;IACrBH,KAAK,EAAEA,KAAM;IACbD,gBAAgB,EAAEA;EAAiB,CACtC,CAAC,EACDE,oBAAoB,iBACjBV,KAAA,CAAAa,aAAA,CAACR,qCAAqC;IAACM,OAAO,EAAEC;EAAY,gBACxDZ,KAAA,CAAAa,aAAA,YAAI,KAAKH,oBAAoB,GAAG,CAAC,EAAM,CACJ,CAEtB,CAAC;AAElC,CAAC;AAEDJ,iBAAiB,CAACS,WAAW,GAAG,mBAAmB;AAEnD,4BAAed,IAAI,CAACK,iBAAiB,CAAC","ignoreList":[]}
1
+ {"version":3,"file":"GalleryViewerItem.js","names":["React","memo","useCallback","MediaContent","StyledGalleryViewerItem","StyledGalleryViewerMoreItemsIndicator","GalleryViewerItem","fileItem","shouldLoadImages","ratio","remainingItemsLength","onClick","shouldEnableKeyboardHighlighting","handleClick","createElement","file","displayName"],"sources":["../../../../../src/components/gallery-viewer/gallery-viewer-item/GalleryViewerItem.tsx"],"sourcesContent":["import React, { FC, memo, useCallback } from 'react';\nimport MediaContent from '../../media-content/MediaContent';\nimport {\n StyledGalleryViewerItem,\n StyledGalleryViewerMoreItemsIndicator,\n} from './GalleryViewerItem.styles';\nimport type { GalleryViewerItemProps } from './GalleryViewerItem.types';\n\nconst GalleryViewerItem: FC<GalleryViewerItemProps> = ({\n fileItem,\n shouldLoadImages = true,\n ratio = 1,\n remainingItemsLength,\n onClick,\n shouldEnableKeyboardHighlighting,\n}) => {\n const handleClick = useCallback(() => onClick(fileItem), [fileItem, onClick]);\n\n return (\n <StyledGalleryViewerItem>\n <MediaContent\n file={fileItem.file}\n onClick={handleClick}\n ratio={ratio}\n shouldLoadImages={shouldLoadImages}\n shouldEnableKeyboardHighlighting={shouldEnableKeyboardHighlighting}\n />\n {remainingItemsLength && (\n <StyledGalleryViewerMoreItemsIndicator onClick={handleClick}>\n <p>{`+ ${remainingItemsLength - 3}`}</p>\n </StyledGalleryViewerMoreItemsIndicator>\n )}\n </StyledGalleryViewerItem>\n );\n};\n\nGalleryViewerItem.displayName = 'GalleryViewerItem';\n\nexport default memo(GalleryViewerItem);\n"],"mappings":"AAAA,OAAOA,KAAK,IAAQC,IAAI,EAAEC,WAAW,QAAQ,OAAO;AACpD,OAAOC,YAAY,MAAM,kCAAkC;AAC3D,SACIC,uBAAuB,EACvBC,qCAAqC,QAClC,4BAA4B;AAGnC,MAAMC,iBAA6C,GAAGA,CAAC;EACnDC,QAAQ;EACRC,gBAAgB,GAAG,IAAI;EACvBC,KAAK,GAAG,CAAC;EACTC,oBAAoB;EACpBC,OAAO;EACPC;AACJ,CAAC,KAAK;EACF,MAAMC,WAAW,GAAGX,WAAW,CAAC,MAAMS,OAAO,CAACJ,QAAQ,CAAC,EAAE,CAACA,QAAQ,EAAEI,OAAO,CAAC,CAAC;EAE7E,oBACIX,KAAA,CAAAc,aAAA,CAACV,uBAAuB,qBACpBJ,KAAA,CAAAc,aAAA,CAACX,YAAY;IACTY,IAAI,EAAER,QAAQ,CAACQ,IAAK;IACpBJ,OAAO,EAAEE,WAAY;IACrBJ,KAAK,EAAEA,KAAM;IACbD,gBAAgB,EAAEA,gBAAiB;IACnCI,gCAAgC,EAAEA;EAAiC,CACtE,CAAC,EACDF,oBAAoB,iBACjBV,KAAA,CAAAc,aAAA,CAACT,qCAAqC;IAACM,OAAO,EAAEE;EAAY,gBACxDb,KAAA,CAAAc,aAAA,YAAI,KAAKJ,oBAAoB,GAAG,CAAC,EAAM,CACJ,CAEtB,CAAC;AAElC,CAAC;AAEDJ,iBAAiB,CAACU,WAAW,GAAG,mBAAmB;AAEnD,4BAAef,IAAI,CAACK,iBAAiB,CAAC","ignoreList":[]}
@@ -1 +1 @@
1
- {"version":3,"file":"GalleryViewerItem.types.js","names":[],"sources":["../../../../../src/components/gallery-viewer/gallery-viewer-item/GalleryViewerItem.types.ts"],"sourcesContent":["import type { FileItem } from '@chayns-components/core';\n\n/**\n * Props for a dedicated read-only gallery tile.\n */\nexport interface GalleryViewerItemProps {\n /**\n * Provides the uploaded media that should be rendered.\n * @description\n * The viewer item renders only already known media and never deals with upload-specific transient state.\n * @example\n * <GalleryViewerItem fileItem={file} onClick={handleOpen} />\n */\n fileItem: FileItem;\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 preview-first rendering can be controlled by the parent gallery.\n * @default true\n * @optional\n */\n shouldLoadImages?: boolean;\n /**\n * Defines the aspect ratio that should be reserved for the tile.\n * @description\n * Use this prop to reserve a deterministic tile height for stable read-only rendering.\n * @default 1\n * @example\n * <GalleryViewerItem fileItem={file} onClick={handleOpen} ratio={1.5} />\n * @optional\n */\n ratio?: number;\n /**\n * Provides the total item count when the last visible tile should show a remaining-items overlay.\n * @description\n * When this prop is set on the last visible viewer tile, the tile displays the `+n` overlay for hidden items.\n * @example\n * <GalleryViewerItem fileItem={file} onClick={handleOpen} remainingItemsLength={5} />\n * @optional\n */\n remainingItemsLength?: number;\n /**\n * Is called when the tile is selected.\n * @description\n * The viewer uses this callback to open the selected file inside the slideshow flow.\n * @example\n * <GalleryViewerItem fileItem={file} onClick={handleOpen} />\n */\n onClick: (file: FileItem) => void;\n}\n"],"mappings":"","ignoreList":[]}
1
+ {"version":3,"file":"GalleryViewerItem.types.js","names":[],"sources":["../../../../../src/components/gallery-viewer/gallery-viewer-item/GalleryViewerItem.types.ts"],"sourcesContent":["import type { FileItem } from '@chayns-components/core';\n\n/**\n * Props for a dedicated read-only gallery tile.\n */\nexport interface GalleryViewerItemProps {\n /**\n * Provides the uploaded media that should be rendered.\n * @description\n * The viewer item renders only already known media and never deals with upload-specific transient state.\n * @example\n * <GalleryViewerItem fileItem={file} onClick={handleOpen} />\n */\n fileItem: FileItem;\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 preview-first rendering can be controlled by the parent gallery.\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 * Defines the aspect ratio that should be reserved for the tile.\n * @description\n * Use this prop to reserve a deterministic tile height for stable read-only rendering.\n * @default 1\n * @example\n * <GalleryViewerItem fileItem={file} onClick={handleOpen} ratio={1.5} />\n * @optional\n */\n ratio?: number;\n /**\n * Provides the total item count when the last visible tile should show a remaining-items overlay.\n * @description\n * When this prop is set on the last visible viewer tile, the tile displays the `+n` overlay for hidden items.\n * @example\n * <GalleryViewerItem fileItem={file} onClick={handleOpen} remainingItemsLength={5} />\n * @optional\n */\n remainingItemsLength?: number;\n /**\n * Is called when the tile is selected.\n * @description\n * The viewer uses this callback to open the selected file inside the slideshow flow.\n * @example\n * <GalleryViewerItem fileItem={file} onClick={handleOpen} />\n */\n onClick: (file: FileItem) => void;\n}\n"],"mappings":"","ignoreList":[]}
@@ -1,4 +1,4 @@
1
- import { Icon } from '@chayns-components/core';
1
+ import { Icon, useFocusRingPortal, useKeyboardFocusHighlighting } from '@chayns-components/core';
2
2
  import React, { memo, useEffect, useMemo, useRef, useState } from 'react';
3
3
  import { StyledMediaContentImage, StyledMediaContentImageWrapper, StyledMediaContentPlayIcon, StyledMediaContentPreviewImage, StyledMediaContentVideo, StyledMediaContentVideoWrapper } from './MediaContent.styles';
4
4
  import { getMediaPreviewUrl, getMediaSourceUrl, getResponsiveImageServiceUrl, isVideoFile } from './MediaContent.utils';
@@ -10,6 +10,7 @@ const MediaContent = ({
10
10
  ratio,
11
11
  onClick,
12
12
  shouldLoadImages = true,
13
+ shouldEnableKeyboardHighlighting,
13
14
  playIconSize = 50
14
15
  }) => {
15
16
  const isVideo = isVideoFile(file);
@@ -19,6 +20,7 @@ const MediaContent = ({
19
20
  const [resolvedFinalSourceUrl, setResolvedFinalSourceUrl] = useState();
20
21
  const [containerElement, setContainerElement] = useState(null);
21
22
  const imageRef = useRef(null);
23
+ const contentRef = useRef(null);
22
24
  const videoRef = useRef(null);
23
25
  const renderSize = useMediaContentSize(containerElement);
24
26
  const devicePixelRatio = typeof window !== 'undefined' && Number.isFinite(window.devicePixelRatio) && window.devicePixelRatio > 0 ? window.devicePixelRatio : 1;
@@ -64,9 +66,21 @@ const MediaContent = ({
64
66
  }, [finalSourceUrl, isVideo, shouldLoadImages]);
65
67
  const shouldRenderFinalImage = shouldLoadImages && Boolean(finalSourceUrl);
66
68
  const shouldShowPreview = Boolean(displayPreviewUrl);
69
+ const shouldShowKeyboardHighlighting = useKeyboardFocusHighlighting(shouldEnableKeyboardHighlighting);
70
+ useFocusRingPortal(contentRef, {
71
+ isEnabled: shouldShowKeyboardHighlighting
72
+ });
73
+ const handleKeyDown = event => {
74
+ if (event.key === 'Enter' || event.key === ' ') {
75
+ event.preventDefault();
76
+ onClick();
77
+ }
78
+ };
67
79
  if (isVideo) {
68
80
  return /*#__PURE__*/React.createElement(StyledMediaContentVideoWrapper, {
69
81
  ref: setContainerElement,
82
+ tabIndex: 0,
83
+ onKeyDown: handleKeyDown,
70
84
  onClick: onClick,
71
85
  $ratio: ratio
72
86
  }, displayPreviewUrl && /*#__PURE__*/React.createElement(StyledMediaContentPreviewImage, {
@@ -90,7 +104,12 @@ const MediaContent = ({
90
104
  })));
91
105
  }
92
106
  return /*#__PURE__*/React.createElement(StyledMediaContentImageWrapper, {
93
- ref: setContainerElement,
107
+ ref: element => {
108
+ setContainerElement(element);
109
+ contentRef.current = element;
110
+ },
111
+ tabIndex: 0,
112
+ onKeyDown: handleKeyDown,
94
113
  onClick: onClick,
95
114
  $ratio: ratio
96
115
  }, shouldShowPreview && /*#__PURE__*/React.createElement(StyledMediaContentPreviewImage, {
@@ -1 +1 @@
1
- {"version":3,"file":"MediaContent.js","names":["Icon","React","memo","useEffect","useMemo","useRef","useState","StyledMediaContentImage","StyledMediaContentImageWrapper","StyledMediaContentPlayIcon","StyledMediaContentPreviewImage","StyledMediaContentVideo","StyledMediaContentVideoWrapper","getMediaPreviewUrl","getMediaSourceUrl","getResponsiveImageServiceUrl","isVideoFile","MEDIA_CONTENT_IMAGE_FADE_DURATION_MS","useMediaContentSize","MediaContent","file","previewUrl","ratio","onClick","shouldLoadImages","playIconSize","isVideo","sourceKey","previewSourceUrl","hasLoadedFinalMedia","setHasLoadedFinalMedia","resolvedFinalSourceUrl","setResolvedFinalSourceUrl","containerElement","setContainerElement","imageRef","videoRef","renderSize","devicePixelRatio","window","Number","isFinite","displayPreviewUrl","undefined","finalSourceUrl","shouldHidePreview","previewLayerStyle","opacity","filter","finalMediaStyle","transition","current","complete","naturalWidth","readyState","shouldRenderFinalImage","Boolean","shouldShowPreview","createElement","ref","$ratio","draggable","src","alt","style","size","icons","poster","preload","onLoadedData","type","onLoad","displayName"],"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":["Icon","useFocusRingPortal","useKeyboardFocusHighlighting","React","memo","useEffect","useMemo","useRef","useState","StyledMediaContentImage","StyledMediaContentImageWrapper","StyledMediaContentPlayIcon","StyledMediaContentPreviewImage","StyledMediaContentVideo","StyledMediaContentVideoWrapper","getMediaPreviewUrl","getMediaSourceUrl","getResponsiveImageServiceUrl","isVideoFile","MEDIA_CONTENT_IMAGE_FADE_DURATION_MS","useMediaContentSize","MediaContent","file","previewUrl","ratio","onClick","shouldLoadImages","shouldEnableKeyboardHighlighting","playIconSize","isVideo","sourceKey","previewSourceUrl","hasLoadedFinalMedia","setHasLoadedFinalMedia","resolvedFinalSourceUrl","setResolvedFinalSourceUrl","containerElement","setContainerElement","imageRef","contentRef","videoRef","renderSize","devicePixelRatio","window","Number","isFinite","displayPreviewUrl","undefined","finalSourceUrl","shouldHidePreview","previewLayerStyle","opacity","filter","finalMediaStyle","transition","current","complete","naturalWidth","readyState","shouldRenderFinalImage","Boolean","shouldShowPreview","shouldShowKeyboardHighlighting","isEnabled","handleKeyDown","event","key","preventDefault","createElement","ref","tabIndex","onKeyDown","$ratio","draggable","src","alt","style","size","icons","poster","preload","onLoadedData","type","element","onLoad","displayName"],"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,11 @@
1
+ export default {
2
+ galleryEditor: {
3
+ accessibility: {
4
+ removeImage: {
5
+ stringName: 'txt_chayns_components_gallery_galleryEditor_accessibility_removeImage',
6
+ fallback: 'Bild entfernen'
7
+ }
8
+ }
9
+ }
10
+ };
11
+ //# 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":"AAAA,eAAe;EACXA,aAAa,EAAE;IACXC,aAAa,EAAE;MACXC,WAAW,EAAE;QACTC,UAAU,EAAE,uEAAuE;QACnFC,QAAQ,EAAE;MACd;IACJ;EACJ;AACJ,CAAC","ignoreList":[]}
@@ -94,6 +94,10 @@ export interface GalleryProps {
94
94
  * @optional
95
95
  */
96
96
  shouldLoadImages?: boolean;
97
+ /**
98
+ * Enables keyboard-only focus highlighting for interactive gallery tiles.
99
+ */
100
+ shouldEnableKeyboardHighlighting?: boolean;
97
101
  /**
98
102
  * Is called after a file has been uploaded successfully in edit mode.
99
103
  * @description
@@ -64,6 +64,10 @@ export interface GalleryEditorProps {
64
64
  * @optional
65
65
  */
66
66
  shouldLoadImages?: boolean;
67
+ /**
68
+ * Enables keyboard-only focus highlighting for interactive gallery tiles.
69
+ */
70
+ shouldEnableKeyboardHighlighting?: boolean;
67
71
  /**
68
72
  * Limits how many files can be managed by the editor.
69
73
  * @description
@@ -20,4 +20,8 @@ export interface AddFileProps {
20
20
  * <AddFile onAdd={(files) => console.log(files)} />
21
21
  */
22
22
  onAdd: (files: File[]) => void;
23
+ /**
24
+ * Enables keyboard-only focus highlighting for the add-file button.
25
+ */
26
+ shouldEnableKeyboardHighlighting?: boolean;
23
27
  }
@@ -19,6 +19,10 @@ export interface GalleryEditorItemProps {
19
19
  * @optional
20
20
  */
21
21
  shouldLoadImages?: boolean;
22
+ /**
23
+ * Enables keyboard-only focus highlighting for the media tile and delete button.
24
+ */
25
+ shouldEnableKeyboardHighlighting?: boolean;
22
26
  /**
23
27
  * Is called when the delete button is clicked in edit mode.
24
28
  * @description
@@ -19,6 +19,10 @@ export interface GalleryEditorMediaItemProps {
19
19
  * @optional
20
20
  */
21
21
  shouldLoadImages?: boolean;
22
+ /**
23
+ * Enables keyboard-only focus highlighting for the media tile.
24
+ */
25
+ shouldEnableKeyboardHighlighting?: boolean;
22
26
  /**
23
27
  * Is called when the media tile is selected.
24
28
  * @description
@@ -24,6 +24,10 @@ export interface GalleryViewerProps {
24
24
  * @optional
25
25
  */
26
26
  shouldLoadImages?: boolean;
27
+ /**
28
+ * Enables keyboard-only focus highlighting for media tiles.
29
+ */
30
+ shouldEnableKeyboardHighlighting?: boolean;
27
31
  /**
28
32
  * Defines how the media tiles are arranged in read-only mode.
29
33
  * @description
@@ -19,6 +19,10 @@ export interface GalleryViewerItemProps {
19
19
  * @optional
20
20
  */
21
21
  shouldLoadImages?: boolean;
22
+ /**
23
+ * Enables keyboard-only focus highlighting for the media tile.
24
+ */
25
+ shouldEnableKeyboardHighlighting?: boolean;
22
26
  /**
23
27
  * Defines the aspect ratio that should be reserved for the tile.
24
28
  * @description
@@ -35,6 +35,10 @@ export interface MediaContentProps {
35
35
  * @optional
36
36
  */
37
37
  shouldLoadImages?: boolean;
38
+ /**
39
+ * Enables keyboard-only focus highlighting for the media tile.
40
+ */
41
+ shouldEnableKeyboardHighlighting?: boolean;
38
42
  /**
39
43
  * Is called when the media tile is selected.
40
44
  * @description
@@ -0,0 +1,11 @@
1
+ declare const _default: {
2
+ readonly galleryEditor: {
3
+ readonly accessibility: {
4
+ readonly removeImage: {
5
+ readonly stringName: "txt_chayns_components_gallery_galleryEditor_accessibility_removeImage";
6
+ readonly fallback: "Bild entfernen";
7
+ };
8
+ };
9
+ };
10
+ };
11
+ export default _default;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@chayns-components/gallery",
3
- "version": "5.5.30",
3
+ "version": "5.5.33-alpha.0",
4
4
  "description": "A set of beautiful React components for developing your own applications with chayns.",
5
5
  "sideEffects": false,
6
6
  "browserslist": [
@@ -69,7 +69,8 @@
69
69
  "typescript": "^5.9.3"
70
70
  },
71
71
  "dependencies": {
72
- "@chayns-components/core": "^5.5.30",
72
+ "@chayns-components/core": "^5.5.31-alpha.0",
73
+ "@chayns/textstrings": "^1.0.1",
73
74
  "react-compiler-runtime": "^1.0.0",
74
75
  "uuid": "^10.0.0"
75
76
  },
@@ -83,5 +84,5 @@
83
84
  "publishConfig": {
84
85
  "access": "public"
85
86
  },
86
- "gitHead": "b90fd1685e1067d28e29580095f3d290be892769"
87
+ "gitHead": "0f3671424b04650c8c56d8b90b4a0397a60e78ba"
87
88
  }