@tradly/asset 1.0.3 → 1.0.5

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 (33) hide show
  1. package/dist/components/FileUpload.js +163 -0
  2. package/dist/components/Icons.js +39 -0
  3. package/dist/components/ImagesSkeleton.js +21 -0
  4. package/dist/components/MediaGallery.js +153 -0
  5. package/dist/components/MediaPopup.js +104 -0
  6. package/dist/components/MediaTab.js +141 -0
  7. package/dist/components/Pagination.js +141 -0
  8. package/dist/components/VideosGallery.js +153 -0
  9. package/dist/esm/components/FileUpload.js +155 -0
  10. package/dist/esm/components/Icons.js +32 -0
  11. package/dist/esm/components/ImagesSkeleton.js +14 -0
  12. package/dist/esm/components/MediaGallery.js +144 -0
  13. package/dist/esm/components/MediaPopup.js +97 -0
  14. package/dist/esm/components/MediaTab.js +132 -0
  15. package/dist/esm/components/Pagination.js +134 -0
  16. package/dist/esm/components/VideosGallery.js +144 -0
  17. package/{index.js → dist/esm/index.js} +6 -6
  18. package/dist/esm/services/apiService.js +373 -0
  19. package/dist/index.js +60 -0
  20. package/dist/services/apiService.js +379 -0
  21. package/package.json +17 -6
  22. package/EXAMPLE_USAGE.jsx +0 -128
  23. package/MIGRATION_GUIDE.md +0 -249
  24. package/STYLING_GUIDE.md +0 -219
  25. package/src/components/FileUpload.jsx +0 -114
  26. package/src/components/Icons.jsx +0 -23
  27. package/src/components/ImagesSkeleton.jsx +0 -18
  28. package/src/components/MediaGallery.jsx +0 -125
  29. package/src/components/MediaPopup.jsx +0 -101
  30. package/src/components/MediaTab.jsx +0 -152
  31. package/src/components/Pagination.jsx +0 -175
  32. package/src/components/VideosGallery.jsx +0 -121
  33. package/src/services/apiService.js +0 -270
@@ -1,125 +0,0 @@
1
- import React, { useState, useEffect } from 'react'
2
- import FileUpload from './FileUpload'
3
- import ImagesSkeleton from './ImagesSkeleton'
4
- import Pagination from './Pagination'
5
-
6
- const IMAGE_MIME_TYPES = [
7
- 'image/png',
8
- 'image/jpeg',
9
- 'image/webp',
10
- 'image/svg+xml',
11
- 'image/gif',
12
- 'image/avif',
13
- 'image/x-icon',
14
- 'image/vnd.microsoft.icon',
15
- 'image/heic',
16
- 'image/heif',
17
- ]
18
-
19
- const ImagesGallery = ({
20
- update_data,
21
- closePopup,
22
- apiService,
23
- onError,
24
- // Styling props
25
- className,
26
- gridClassName,
27
- imageItemClassName,
28
- paginationContainerClassName,
29
- }) => {
30
- const [images, setImages] = useState([])
31
- const [total_count, setTotalCount] = useState(0)
32
- const [currentPage, setCurrentPage] = useState(1)
33
- const [isLoading, setISLoading] = useState(false)
34
-
35
- // Fetch images
36
- useEffect(() => {
37
- loadMedia()
38
- }, [])
39
-
40
- const loadMedia = async (page_number = 1) => {
41
- try {
42
- const response = await apiService.fetchMedia({
43
- mimeTypes: IMAGE_MIME_TYPES,
44
- page: page_number,
45
- setISLoading,
46
- isLoading,
47
- })
48
-
49
- // Handle different response formats
50
- // Response might be: { media: [...], count: ... } or { data: { media: [...], count: ... } } or directly [...]
51
- const mediaData = response?.media || response?.data?.media || response?.data || response || []
52
- const count = response?.count || response?.data?.count || response?.total || 0
53
-
54
- setImages(Array.isArray(mediaData) ? mediaData : [])
55
- setTotalCount(count)
56
- setCurrentPage(page_number)
57
- } catch (error) {
58
- console.error('Error loading media:', error)
59
- if (onError) {
60
- onError(error)
61
- }
62
- }
63
- }
64
-
65
- const handleImageClick = (image) => {
66
- if (update_data) {
67
- update_data(image.url || image)
68
- }
69
- if (closePopup) {
70
- closePopup()
71
- }
72
- }
73
-
74
- // Default classes with customization support
75
- const defaultContainerClass = 'h-full flex flex-col justify-between'
76
- const defaultGridClass = 'grid grid-cols-[repeat(auto-fill,minmax(calc(160px),1fr))] gap-5'
77
- const defaultImageItemClass =
78
- 'cursor-pointer w-full h-40 object-contain p-3 overflow-hidden bg-white rounded-md shadow-md hover:shadow-lg transition-shadow'
79
- const defaultPaginationContainerClass = 'mb-4 bg-gray-100/90 p-4 sticky bottom-0'
80
-
81
- return (
82
- <div className={className || defaultContainerClass}>
83
- <div className={gridClassName || defaultGridClass}>
84
- <FileUpload
85
- loadMedia={loadMedia}
86
- accept="image/*"
87
- title="Add Image"
88
- apiService={apiService}
89
- onUploadError={onError}
90
- />
91
-
92
- {isLoading ? (
93
- <ImagesSkeleton />
94
- ) : (
95
- images?.map((image, index) => {
96
- const imageUrl = typeof image === 'string' ? image : image.url
97
- const imageKey = image.id || image.url || index
98
-
99
- return (
100
- <img
101
- key={imageKey}
102
- onClick={() => handleImageClick(image)}
103
- className={imageItemClassName || defaultImageItemClass}
104
- src={imageUrl}
105
- alt={image.name || 'Media item'}
106
- />
107
- )
108
- })
109
- )}
110
- </div>
111
-
112
- <div className={paginationContainerClassName || defaultPaginationContainerClass}>
113
- {total_count > 0 && (
114
- <Pagination
115
- nextPage={(value) => loadMedia(value)}
116
- pageCount={Math.ceil(total_count / 30)}
117
- current_page={currentPage}
118
- />
119
- )}
120
- </div>
121
- </div>
122
- )
123
- }
124
-
125
- export default ImagesGallery
@@ -1,101 +0,0 @@
1
- import React from 'react'
2
- import { createPortal } from 'react-dom'
3
- import MediaTab from './MediaTab'
4
- import { CloseIcon } from './Icons'
5
-
6
- const MediaPopup = ({
7
- isOpen,
8
- onClose,
9
- onSelect,
10
- currentData,
11
- options = ['image'],
12
- apiService,
13
- onError,
14
- title = 'Media Gallery',
15
- // Styling props
16
- className,
17
- overlayClassName,
18
- containerClassName,
19
- headerClassName,
20
- titleClassName,
21
- closeButtonClassName,
22
- // Pass-through styling props for child components
23
- tabListClassName,
24
- tabButtonClassName,
25
- tabButtonActiveClassName,
26
- tabButtonInactiveClassName,
27
- tabPanelClassName,
28
- gridClassName,
29
- imageItemClassName,
30
- videoItemClassName,
31
- paginationContainerClassName,
32
- }) => {
33
- if (!isOpen) return null
34
-
35
- const handleUpdate = (data) => {
36
- if (onSelect) {
37
- onSelect(data)
38
- }
39
- }
40
-
41
- const handleClose = () => {
42
- if (onClose) {
43
- onClose()
44
- }
45
- }
46
-
47
- // Default classes with customization support
48
- const defaultOverlayClass = 'fixed inset-0 w-screen h-screen bg-black opacity-10'
49
- const defaultContainerClass =
50
- 'origin-top-right z-[9999] absolute inset-0 max-w-3xl mx-auto my-auto min-h-[200px] h-[600px] bg-white rounded shadow-inner cursor-auto p-6'
51
- const defaultHeaderClass = 'flex items-center justify-between gap-4'
52
- const defaultTitleClass = 'text-[#000] font-bold text-2xl'
53
- const defaultCloseButtonClass =
54
- 'bg-transparent rounded-full hover:bg-gray-100 p-1 transition-colors'
55
-
56
- return createPortal(
57
- <>
58
- <div
59
- className={overlayClassName || defaultOverlayClass}
60
- style={{ zIndex: 9998 }}
61
- onClick={handleClose}
62
- />
63
- <div className={containerClassName || defaultContainerClass} style={{ zIndex: 9999 }}>
64
- {/* Header */}
65
- <div className={headerClassName || defaultHeaderClass}>
66
- <p className={titleClassName || defaultTitleClass}>{title}</p>
67
- <button
68
- className={closeButtonClassName || defaultCloseButtonClass}
69
- type="button"
70
- onClick={handleClose}
71
- aria-label="Close"
72
- >
73
- <CloseIcon />
74
- </button>
75
- </div>
76
- <MediaTab
77
- imagePopup={isOpen}
78
- update_data={handleUpdate}
79
- current_data={currentData}
80
- closePopup={handleClose}
81
- options={options}
82
- apiService={apiService}
83
- onError={onError}
84
- // Pass styling props through
85
- tabListClassName={tabListClassName}
86
- tabButtonClassName={tabButtonClassName}
87
- tabButtonActiveClassName={tabButtonActiveClassName}
88
- tabButtonInactiveClassName={tabButtonInactiveClassName}
89
- tabPanelClassName={tabPanelClassName}
90
- gridClassName={gridClassName}
91
- imageItemClassName={imageItemClassName}
92
- videoItemClassName={videoItemClassName}
93
- paginationContainerClassName={paginationContainerClassName}
94
- />
95
- </div>
96
- </>,
97
- document.body
98
- )
99
- }
100
-
101
- export default MediaPopup
@@ -1,152 +0,0 @@
1
- import React, { useState } from 'react'
2
- import { Tab } from '@headlessui/react'
3
- import ImagesGallery from './MediaGallery'
4
- import VideosGallery from './VideosGallery'
5
-
6
- function classNames(...classes) {
7
- return classes.filter(Boolean).join(' ')
8
- }
9
-
10
- const MediaTab = ({
11
- imagePopup,
12
- current_data,
13
- update_data,
14
- closePopup,
15
- options,
16
- apiService,
17
- onError,
18
- // Styling props
19
- className,
20
- tabListClassName,
21
- tabButtonClassName,
22
- tabButtonActiveClassName,
23
- tabButtonInactiveClassName,
24
- tabPanelClassName,
25
- // Pass-through styling props for gallery components
26
- gridClassName,
27
- imageItemClassName,
28
- videoItemClassName,
29
- paginationContainerClassName,
30
- }) => {
31
- const [selectedIndex, setSelectedIndex] = useState(0)
32
-
33
- // Default classes with customization support
34
- const defaultTabGroupClass = 'h-[520px] overflow-y-auto scrollbar-none'
35
- const defaultTabListClass = 'sticky top-0 z-30 bg-white w-full flex border-b-2 border-gray-200'
36
- const defaultTabButtonBaseClass =
37
- 'rounded-lg py-2.5 px-8 text-base font-medium leading-5 flex flex-col md:flex-row items-center justify-center gap-3 ring-0 focus:outline-none'
38
- const defaultTabButtonActiveClass =
39
- 'relative text-primary after:content-[""] after:h-1 after:w-full after:block after:absolute after:-bottom-0.5 after:bg-primary after:rounded-card'
40
- const defaultTabButtonInactiveClass = 'text-[#4F4F4F]'
41
- const defaultTabPanelClass = 'h-full py-4 relative'
42
-
43
- return (
44
- <Tab.Group
45
- as="div"
46
- key={selectedIndex}
47
- className={className || defaultTabGroupClass}
48
- onChange={setSelectedIndex}
49
- selectedIndex={selectedIndex}
50
- >
51
- <Tab.List className={tabListClassName || defaultTabListClass}>
52
- {options.includes('image') && (
53
- <Tab
54
- as="p"
55
- id="image-tab-button"
56
- className={({ selected }) =>
57
- classNames(
58
- tabButtonClassName || defaultTabButtonBaseClass,
59
- selected
60
- ? tabButtonActiveClassName || defaultTabButtonActiveClass
61
- : tabButtonInactiveClassName || defaultTabButtonInactiveClass
62
- )
63
- }
64
- >
65
- <span>Images</span>
66
- </Tab>
67
- )}
68
- {options.includes('video') && (
69
- <Tab
70
- as="p"
71
- id="video-tab-button"
72
- className={({ selected }) =>
73
- classNames(
74
- tabButtonClassName || defaultTabButtonBaseClass,
75
- selected
76
- ? tabButtonActiveClassName || defaultTabButtonActiveClass
77
- : tabButtonInactiveClassName || defaultTabButtonInactiveClass
78
- )
79
- }
80
- >
81
- <span>Videos</span>
82
- </Tab>
83
- )}
84
- {options.includes('file') && (
85
- <Tab
86
- as="p"
87
- id="file-tab-button"
88
- className={({ selected }) =>
89
- classNames(
90
- tabButtonClassName || defaultTabButtonBaseClass,
91
- selected
92
- ? tabButtonActiveClassName || defaultTabButtonActiveClass
93
- : tabButtonInactiveClassName || defaultTabButtonInactiveClass
94
- )
95
- }
96
- >
97
- <span>Files</span>
98
- </Tab>
99
- )}
100
- </Tab.List>
101
- <Tab.Panels className="h-full" selectedIndex={selectedIndex}>
102
- {options.includes('image') && (
103
- <Tab.Panel className={tabPanelClassName || defaultTabPanelClass}>
104
- <ImagesGallery
105
- imagePopup={imagePopup}
106
- update_data={update_data}
107
- current_data={current_data}
108
- closePopup={closePopup}
109
- apiService={apiService}
110
- onError={onError}
111
- gridClassName={gridClassName}
112
- imageItemClassName={imageItemClassName}
113
- paginationContainerClassName={paginationContainerClassName}
114
- />
115
- </Tab.Panel>
116
- )}
117
- {options.includes('video') && (
118
- <Tab.Panel className={tabPanelClassName || defaultTabPanelClass}>
119
- <VideosGallery
120
- imagePopup={imagePopup}
121
- update_data={update_data}
122
- current_data={current_data}
123
- closePopup={closePopup}
124
- apiService={apiService}
125
- onError={onError}
126
- gridClassName={gridClassName}
127
- videoItemClassName={videoItemClassName}
128
- paginationContainerClassName={paginationContainerClassName}
129
- />
130
- </Tab.Panel>
131
- )}
132
- {options.includes('file') && (
133
- <Tab.Panel className={tabPanelClassName || defaultTabPanelClass}>
134
- <ImagesGallery
135
- imagePopup={imagePopup}
136
- update_data={update_data}
137
- current_data={current_data}
138
- closePopup={closePopup}
139
- apiService={apiService}
140
- onError={onError}
141
- gridClassName={gridClassName}
142
- imageItemClassName={imageItemClassName}
143
- paginationContainerClassName={paginationContainerClassName}
144
- />
145
- </Tab.Panel>
146
- )}
147
- </Tab.Panels>
148
- </Tab.Group>
149
- )
150
- }
151
-
152
- export default MediaTab
@@ -1,175 +0,0 @@
1
- import React from 'react'
2
-
3
- const Pagination = ({
4
- className,
5
- nextPage,
6
- current_page,
7
- pageCount,
8
- // Styling props
9
- navClassName,
10
- previousButtonClassName,
11
- nextButtonClassName,
12
- pageButtonClassName,
13
- pageButtonActiveClassName,
14
- ellipsisClassName,
15
- }) => {
16
- const totalPages = Math.ceil(pageCount) || 1
17
- const currentPage = current_page || 1
18
-
19
- // Generate page numbers to display
20
- const getPageNumbers = () => {
21
- const pages = []
22
- const maxVisible = 5
23
- let startPage = Math.max(1, currentPage - Math.floor(maxVisible / 2))
24
- let endPage = Math.min(totalPages, startPage + maxVisible - 1)
25
-
26
- if (endPage - startPage < maxVisible - 1) {
27
- startPage = Math.max(1, endPage - maxVisible + 1)
28
- }
29
-
30
- // Add first page and ellipsis
31
- if (startPage > 1) {
32
- pages.push(1)
33
- if (startPage > 2) {
34
- pages.push('...')
35
- }
36
- }
37
-
38
- // Add visible pages
39
- for (let i = startPage; i <= endPage; i++) {
40
- pages.push(i)
41
- }
42
-
43
- // Add ellipsis and last page
44
- if (endPage < totalPages) {
45
- if (endPage < totalPages - 1) {
46
- pages.push('...')
47
- }
48
- pages.push(totalPages)
49
- }
50
-
51
- return pages
52
- }
53
-
54
- const handlePageClick = (page) => {
55
- if (page !== currentPage && page >= 1 && page <= totalPages) {
56
- nextPage(page)
57
- }
58
- }
59
-
60
- const handlePrevious = () => {
61
- if (currentPage > 1) {
62
- nextPage(currentPage - 1)
63
- }
64
- }
65
-
66
- const handleNext = () => {
67
- if (currentPage < totalPages) {
68
- nextPage(currentPage + 1)
69
- }
70
- }
71
-
72
- if (totalPages <= 1) return null
73
-
74
- const pageNumbers = getPageNumbers()
75
-
76
- // Default classes with customization support
77
- const defaultContainerClass = 'flex justify-center'
78
- const defaultNavClass =
79
- 'relative z-0 inline-flex flex-wrap justify-center rounded-md shadow-sm -space-x-px'
80
- const defaultPreviousButtonClass =
81
- 'relative inline-flex items-center px-2 py-2 border border-gray-300 bg-white text-sm font-medium text-gray-500 hover:bg-gray-50'
82
- const defaultNextButtonClass =
83
- 'relative inline-flex items-center px-2 py-2 border border-gray-300 bg-white text-sm font-medium text-gray-500 hover:bg-gray-50'
84
- const defaultPageButtonClass =
85
- 'relative inline-flex items-center px-4 py-2 border bg-white border-gray-300 text-gray-500 hover:bg-gray-50 text-sm font-medium'
86
- const defaultPageButtonActiveClass =
87
- 'z-10 bg-primary border-primary text-white relative inline-flex items-center px-4 py-2 border text-md font-semibold'
88
- const defaultEllipsisClass =
89
- 'relative inline-flex items-center px-4 py-2 border border-gray-300 bg-white text-sm font-medium text-gray-700'
90
-
91
- return (
92
- <div className={className || defaultContainerClass}>
93
- <nav className={navClassName || defaultNavClass}>
94
- {/* Previous Button */}
95
- <button
96
- onClick={handlePrevious}
97
- disabled={currentPage === 1}
98
- className={`${previousButtonClassName || defaultPreviousButtonClass} ${
99
- currentPage === 1 ? 'opacity-50 cursor-not-allowed' : ''
100
- }`}
101
- aria-label="Previous page"
102
- >
103
- <svg
104
- className="h-5 w-5"
105
- xmlns="http://www.w3.org/2000/svg"
106
- viewBox="0 0 20 20"
107
- fill="currentColor"
108
- aria-hidden="true"
109
- >
110
- <path
111
- fillRule="evenodd"
112
- d="M12.707 5.293a1 1 0 010 1.414L9.414 10l3.293 3.293a1 1 0 01-1.414 1.414l-4-4a1 1 0 010-1.414l4-4a1 1 0 011.414 0z"
113
- clipRule="evenodd"
114
- />
115
- </svg>
116
- </button>
117
-
118
- {/* Page Numbers */}
119
- {pageNumbers.map((page, index) => {
120
- if (page === '...') {
121
- return (
122
- <span key={`ellipsis-${index}`} className={ellipsisClassName || defaultEllipsisClass}>
123
- ...
124
- </span>
125
- )
126
- }
127
-
128
- const isActive = page === currentPage
129
-
130
- return (
131
- <button
132
- key={page}
133
- onClick={() => handlePageClick(page)}
134
- className={
135
- isActive
136
- ? pageButtonActiveClassName || defaultPageButtonActiveClass
137
- : pageButtonClassName || defaultPageButtonClass
138
- }
139
- aria-label={`Page ${page}`}
140
- aria-current={isActive ? 'page' : undefined}
141
- >
142
- {page}
143
- </button>
144
- )
145
- })}
146
-
147
- {/* Next Button */}
148
- <button
149
- onClick={handleNext}
150
- disabled={currentPage === totalPages}
151
- className={`${nextButtonClassName || defaultNextButtonClass} ${
152
- currentPage === totalPages ? 'opacity-50 cursor-not-allowed' : ''
153
- }`}
154
- aria-label="Next page"
155
- >
156
- <svg
157
- className="h-5 w-5"
158
- xmlns="http://www.w3.org/2000/svg"
159
- viewBox="0 0 20 20"
160
- fill="currentColor"
161
- aria-hidden="true"
162
- >
163
- <path
164
- fillRule="evenodd"
165
- d="M7.293 14.707a1 1 0 010-1.414L10.586 10 7.293 6.707a1 1 0 011.414-1.414l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414 0z"
166
- clipRule="evenodd"
167
- />
168
- </svg>
169
- </button>
170
- </nav>
171
- </div>
172
- )
173
- }
174
-
175
- export default Pagination
@@ -1,121 +0,0 @@
1
- import React, { useState, useEffect } from 'react'
2
- import FileUpload from './FileUpload'
3
- import ImagesSkeleton from './ImagesSkeleton'
4
- import Pagination from './Pagination'
5
-
6
- const VIDEO_MIME_TYPES = [
7
- 'video/mp4',
8
- 'video/quicktime',
9
- 'video/x-ms-wmv',
10
- 'video/h265',
11
- 'video/hevc',
12
- 'video/webm',
13
- ]
14
-
15
- const VideosGallery = ({
16
- update_data,
17
- closePopup,
18
- apiService,
19
- onError,
20
- // Styling props
21
- className,
22
- gridClassName,
23
- videoItemClassName,
24
- paginationContainerClassName,
25
- }) => {
26
- const [videos, setVideos] = useState([])
27
- const [total_count, setTotalCount] = useState(0)
28
- const [currentPage, setCurrentPage] = useState(1)
29
- const [isLoading, setISLoading] = useState(false)
30
-
31
- // Fetch videos
32
- useEffect(() => {
33
- loadMedia()
34
- }, [])
35
-
36
- const loadMedia = async (page_number = 1) => {
37
- try {
38
- const response = await apiService.fetchMedia({
39
- mimeTypes: VIDEO_MIME_TYPES,
40
- page: page_number,
41
- setISLoading,
42
- isLoading,
43
- })
44
-
45
- // Handle different response formats
46
- // Response might be: { media: [...], count: ... } or { data: { media: [...], count: ... } } or directly [...]
47
- const mediaData = response?.media || response?.data?.media || response?.data || response || []
48
- const count = response?.count || response?.data?.count || response?.total || 0
49
-
50
- setVideos(Array.isArray(mediaData) ? mediaData : [])
51
- setTotalCount(count)
52
- setCurrentPage(page_number)
53
- } catch (error) {
54
- console.error('Error loading videos:', error)
55
- if (onError) {
56
- onError(error)
57
- }
58
- }
59
- }
60
-
61
- const handleVideoClick = (video) => {
62
- if (update_data) {
63
- update_data(video.url || video)
64
- }
65
- if (closePopup) {
66
- closePopup()
67
- }
68
- }
69
-
70
- // Default classes with customization support
71
- const defaultContainerClass = 'h-full flex flex-col justify-between'
72
- const defaultGridClass = 'grid grid-cols-[repeat(auto-fill,minmax(calc(180px),1fr))] gap-5'
73
- const defaultVideoItemClass =
74
- 'cursor-pointer w-full h-40 object-contain overflow-hidden bg-white rounded-md shadow-md hover:shadow-lg transition-shadow'
75
- const defaultPaginationContainerClass = 'mb-4 bg-gray-100/90 p-4 sticky bottom-0'
76
-
77
- return (
78
- <div className={className || defaultContainerClass}>
79
- <div className={gridClassName || defaultGridClass}>
80
- <FileUpload
81
- loadMedia={loadMedia}
82
- accept="video/*"
83
- title="Add Video"
84
- apiService={apiService}
85
- onUploadError={onError}
86
- />
87
-
88
- {isLoading ? (
89
- <ImagesSkeleton />
90
- ) : (
91
- videos?.map((video, index) => {
92
- const videoUrl = typeof video === 'string' ? video : video.url
93
- const videoKey = video.id || video.url || index
94
-
95
- return (
96
- <video
97
- key={videoKey}
98
- onClick={() => handleVideoClick(video)}
99
- className={videoItemClassName || defaultVideoItemClass}
100
- controls
101
- src={videoUrl}
102
- />
103
- )
104
- })
105
- )}
106
- </div>
107
-
108
- <div className={paginationContainerClassName || defaultPaginationContainerClass}>
109
- {total_count > 0 && (
110
- <Pagination
111
- nextPage={(value) => loadMedia(value)}
112
- pageCount={Math.ceil(total_count / 30)}
113
- current_page={currentPage}
114
- />
115
- )}
116
- </div>
117
- </div>
118
- )
119
- }
120
-
121
- export default VideosGallery