dinocollab-core 1.0.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 (214) hide show
  1. package/README.md +54 -0
  2. package/dist/_virtual/_rollupPluginBabelHelpers.js +431 -0
  3. package/dist/_virtual/_rollupPluginBabelHelpers.js.map +1 -0
  4. package/dist/assets/vector-404265a04f4f9c8be1f.webp +0 -0
  5. package/dist/node_modules/.pnpm/@rollup_plugin-typescript@1_d0d2002d9033600b6738d939bd598bc6/node_modules/tslib/tslib.es6.js +46 -0
  6. package/dist/node_modules/.pnpm/@rollup_plugin-typescript@1_d0d2002d9033600b6738d939bd598bc6/node_modules/tslib/tslib.es6.js.map +1 -0
  7. package/dist/src/api-context/alert-global.js +151 -0
  8. package/dist/src/api-context/alert-global.js.map +1 -0
  9. package/dist/src/api-context/drawer-global.js +105 -0
  10. package/dist/src/api-context/drawer-global.js.map +1 -0
  11. package/dist/src/api-context/global-modal.js +87 -0
  12. package/dist/src/api-context/global-modal.js.map +1 -0
  13. package/dist/src/api-context/popover-global.js +102 -0
  14. package/dist/src/api-context/popover-global.js.map +1 -0
  15. package/dist/src/api-context/popover.js +86 -0
  16. package/dist/src/api-context/popover.js.map +1 -0
  17. package/dist/src/api-context/ui.units.js +21 -0
  18. package/dist/src/api-context/ui.units.js.map +1 -0
  19. package/dist/src/components/copy-to-clipboard.js +105 -0
  20. package/dist/src/components/copy-to-clipboard.js.map +1 -0
  21. package/dist/src/components/custom.breadcrumbs.js +61 -0
  22. package/dist/src/components/custom.breadcrumbs.js.map +1 -0
  23. package/dist/src/components/help-tooltip.js +91 -0
  24. package/dist/src/components/help-tooltip.js.map +1 -0
  25. package/dist/src/components/image-with-fallback.js +48 -0
  26. package/dist/src/components/image-with-fallback.js.map +1 -0
  27. package/dist/src/components/text-editor.js +117 -0
  28. package/dist/src/components/text-editor.js.map +1 -0
  29. package/dist/src/form/create.autocomplete.chips.js +218 -0
  30. package/dist/src/form/create.autocomplete.chips.js.map +1 -0
  31. package/dist/src/form/create.date-expired.js +201 -0
  32. package/dist/src/form/create.date-expired.js.map +1 -0
  33. package/dist/src/form/create.date-picker.js +125 -0
  34. package/dist/src/form/create.date-picker.js.map +1 -0
  35. package/dist/src/form/create.form-base.js +135 -0
  36. package/dist/src/form/create.form-base.js.map +1 -0
  37. package/dist/src/form/create.form-comfirm.js +119 -0
  38. package/dist/src/form/create.form-comfirm.js.map +1 -0
  39. package/dist/src/form/create.form-grid-layout.js +177 -0
  40. package/dist/src/form/create.form-grid-layout.js.map +1 -0
  41. package/dist/src/form/create.form-grid-layout.units.js +39 -0
  42. package/dist/src/form/create.form-grid-layout.units.js.map +1 -0
  43. package/dist/src/form/create.input-base.js +260 -0
  44. package/dist/src/form/create.input-base.js.map +1 -0
  45. package/dist/src/form/create.input.file.js +74 -0
  46. package/dist/src/form/create.input.file.js.map +1 -0
  47. package/dist/src/form/create.select-simple.js +104 -0
  48. package/dist/src/form/create.select-simple.js.map +1 -0
  49. package/dist/src/form/create.select-with-api.js +271 -0
  50. package/dist/src/form/create.select-with-api.js.map +1 -0
  51. package/dist/src/form/create.text-editor.js +156 -0
  52. package/dist/src/form/create.text-editor.js.map +1 -0
  53. package/dist/src/form/dino-form.js +42 -0
  54. package/dist/src/form/dino-form.js.map +1 -0
  55. package/dist/src/form/helper.js +157 -0
  56. package/dist/src/form/helper.js.map +1 -0
  57. package/dist/src/form/modal-wrapper.js +75 -0
  58. package/dist/src/form/modal-wrapper.js.map +1 -0
  59. package/dist/src/form/validator.js +186 -0
  60. package/dist/src/form/validator.js.map +1 -0
  61. package/dist/src/hooks/index.js +48 -0
  62. package/dist/src/hooks/index.js.map +1 -0
  63. package/dist/src/index.js +26 -0
  64. package/dist/src/index.js.map +1 -0
  65. package/dist/src/redux/create.hoc-lazy.js +67 -0
  66. package/dist/src/redux/create.hoc-lazy.js.map +1 -0
  67. package/dist/src/redux/dino.js +11 -0
  68. package/dist/src/redux/dino.js.map +1 -0
  69. package/dist/src/redux/types.js +9 -0
  70. package/dist/src/redux/types.js.map +1 -0
  71. package/dist/src/redux/ui.error-page.js +80 -0
  72. package/dist/src/redux/ui.error-page.js.map +1 -0
  73. package/dist/src/redux/vector-404.webp.js +4 -0
  74. package/dist/src/redux/vector-404.webp.js.map +1 -0
  75. package/dist/src/table/context.js +12 -0
  76. package/dist/src/table/context.js.map +1 -0
  77. package/dist/src/table/create.action-row.js +135 -0
  78. package/dist/src/table/create.action-row.js.map +1 -0
  79. package/dist/src/table/create.status-cell.js +49 -0
  80. package/dist/src/table/create.status-cell.js.map +1 -0
  81. package/dist/src/table/create.table.js +233 -0
  82. package/dist/src/table/create.table.js.map +1 -0
  83. package/dist/src/table/custom.filter-operators.js +89 -0
  84. package/dist/src/table/custom.filter-operators.js.map +1 -0
  85. package/dist/src/table/dino.js +129 -0
  86. package/dist/src/table/dino.js.map +1 -0
  87. package/dist/src/table/helpers.js +116 -0
  88. package/dist/src/table/helpers.js.map +1 -0
  89. package/dist/src/table/model-filter.js +23 -0
  90. package/dist/src/table/model-filter.js.map +1 -0
  91. package/dist/src/table/toolbar-pannel.js +134 -0
  92. package/dist/src/table/toolbar-pannel.js.map +1 -0
  93. package/dist/src/table/ui.buttons.js +60 -0
  94. package/dist/src/table/ui.buttons.js.map +1 -0
  95. package/dist/src/table/ui.units.js +201 -0
  96. package/dist/src/table/ui.units.js.map +1 -0
  97. package/dist/src/utils/dayjs-config.js +12 -0
  98. package/dist/src/utils/dayjs-config.js.map +1 -0
  99. package/dist/src/utils/helpers.js +197 -0
  100. package/dist/src/utils/helpers.js.map +1 -0
  101. package/dist/src/utils/json-object.js +38 -0
  102. package/dist/src/utils/json-object.js.map +1 -0
  103. package/dist/src/utils/query-param.js +172 -0
  104. package/dist/src/utils/query-param.js.map +1 -0
  105. package/package.json +52 -0
  106. package/rollup.config.js +39 -0
  107. package/src/@types/global.d.ts +5 -0
  108. package/src/api-context/alert-global.tsx +174 -0
  109. package/src/api-context/drawer-global.tsx +116 -0
  110. package/src/api-context/global-modal.tsx +109 -0
  111. package/src/api-context/index.ts +13 -0
  112. package/src/api-context/popover-global.tsx +107 -0
  113. package/src/api-context/popover.tsx +89 -0
  114. package/src/api-context/ui.units.tsx +10 -0
  115. package/src/components/copy-to-clipboard.tsx +86 -0
  116. package/src/components/custom.breadcrumbs.tsx +67 -0
  117. package/src/components/help-tooltip.tsx +75 -0
  118. package/src/components/image-with-fallback.tsx +51 -0
  119. package/src/components/index.tsx +1 -0
  120. package/src/components/input-debounce-timer.tsx +138 -0
  121. package/src/components/loading-buttons.tsx +35 -0
  122. package/src/components/text-editor.preview.tsx +30 -0
  123. package/src/components/text-editor.tsx +125 -0
  124. package/src/form/README.md +55 -0
  125. package/src/form/create.autocomplete.chips.tsx +199 -0
  126. package/src/form/create.date-expired.tsx +195 -0
  127. package/src/form/create.date-picker.tsx +122 -0
  128. package/src/form/create.form-base.tsx +102 -0
  129. package/src/form/create.form-comfirm.tsx +83 -0
  130. package/src/form/create.form-grid-layout.tsx +170 -0
  131. package/src/form/create.form-grid-layout.units.tsx +37 -0
  132. package/src/form/create.input-base.tsx +222 -0
  133. package/src/form/create.input.file.tsx +76 -0
  134. package/src/form/create.select-simple.tsx +101 -0
  135. package/src/form/create.select-with-api.tsx +213 -0
  136. package/src/form/create.text-editor.tsx +161 -0
  137. package/src/form/dino-form.tsx +40 -0
  138. package/src/form/helper.ts +132 -0
  139. package/src/form/index.ts +12 -0
  140. package/src/form/modal-wrapper.tsx +75 -0
  141. package/src/form/types.ts +16 -0
  142. package/src/form/validator.ts +202 -0
  143. package/src/hooks/index.ts +44 -0
  144. package/src/index.ts +7 -0
  145. package/src/lab/create.autocomplete.simple.tsx +57 -0
  146. package/src/lab/create.dino-store.ts +59 -0
  147. package/src/lab/create.multi-select-dropdown.tsx +189 -0
  148. package/src/lab/create.select-mul-with-api/index.tsx +271 -0
  149. package/src/lab/create.select-mul-with-api/table-custom.tsx +194 -0
  150. package/src/lab/create.select-mul-with-api/types.ts +26 -0
  151. package/src/lab/create.select-mul-with-api/ui.units.tsx +163 -0
  152. package/src/lab/filter-bar/base.tsx +162 -0
  153. package/src/lab/filter-bar/create.filter-bar.tsx +190 -0
  154. package/src/lab/filter-bar/create.filter-menu.tsx +156 -0
  155. package/src/lab/filter-bar/create.filter-panel.tsx +95 -0
  156. package/src/lab/filter-bar/create.filtered.tsx +41 -0
  157. package/src/lab/filter-bar/create.sort-menu.tsx +43 -0
  158. package/src/lab/filter-bar/demo.tsx +50 -0
  159. package/src/lab/filter-bar/index.ts +6 -0
  160. package/src/lab/filter-bar/types.ts +105 -0
  161. package/src/lab/filter-bar/ui.units.tsx +70 -0
  162. package/src/lab/grafana-dashboard/configs.ts +43 -0
  163. package/src/lab/grafana-dashboard/date-time-range/absolute-time-rage.tsx +137 -0
  164. package/src/lab/grafana-dashboard/date-time-range/helpers.ts +126 -0
  165. package/src/lab/grafana-dashboard/date-time-range/index.tsx +62 -0
  166. package/src/lab/grafana-dashboard/date-time-range/menu-wrap.tsx +101 -0
  167. package/src/lab/grafana-dashboard/date-time-range/quick-ranges.tsx +161 -0
  168. package/src/lab/grafana-dashboard/date-time-range/types.ts +9 -0
  169. package/src/lab/grafana-dashboard/date-time-range/units.tsx +18 -0
  170. package/src/lab/grafana-dashboard/helper.ts +25 -0
  171. package/src/lab/grafana-dashboard/hooks.tsx +79 -0
  172. package/src/lab/grafana-dashboard/icons.tsx +67 -0
  173. package/src/lab/grafana-dashboard/index.tsx +120 -0
  174. package/src/lab/grafana-dashboard/top-bar.tsx +62 -0
  175. package/src/lab/grafana-dashboard/top-bar.types.ts +5 -0
  176. package/src/lab/grafana-dashboard/types.ts +8 -0
  177. package/src/lab/media-player.core1.tsx +273 -0
  178. package/src/lab/media-player.muted.tsx +62 -0
  179. package/src/lab/media-player.units.ts +80 -0
  180. package/src/lab/table-grid/create.table-grid.tsx +183 -0
  181. package/src/lab/table-grid/demo.tsx +53 -0
  182. package/src/lab/table-grid/dino.tsx +8 -0
  183. package/src/lab/table-grid/helpers.tsx +11 -0
  184. package/src/lab/table-grid/index.ts +3 -0
  185. package/src/lab/table-grid/item-actions.tsx +138 -0
  186. package/src/lab/table-grid/toolbar-pannel.tsx +98 -0
  187. package/src/lab/table-grid/types.ts +68 -0
  188. package/src/redux/create.hoc-lazy.tsx +80 -0
  189. package/src/redux/dino.ts +9 -0
  190. package/src/redux/index.ts +6 -0
  191. package/src/redux/types.ts +27 -0
  192. package/src/redux/ui.error-page.tsx +62 -0
  193. package/src/redux/ui.units.tsx +41 -0
  194. package/src/redux/vector-404.webp +0 -0
  195. package/src/table/context.tsx +16 -0
  196. package/src/table/create.action-row.tsx +91 -0
  197. package/src/table/create.status-cell.tsx +51 -0
  198. package/src/table/create.table.tsx +239 -0
  199. package/src/table/custom.filter-operators.ts +94 -0
  200. package/src/table/dino.tsx +120 -0
  201. package/src/table/helpers.ts +94 -0
  202. package/src/table/index.ts +13 -0
  203. package/src/table/model-filter.ts +43 -0
  204. package/src/table/toolbar-pannel.tsx +106 -0
  205. package/src/table/types.ts +50 -0
  206. package/src/table/ui.buttons.tsx +54 -0
  207. package/src/table/ui.units.tsx +189 -0
  208. package/src/utils/dayjs-config.ts +13 -0
  209. package/src/utils/helpers.ts +171 -0
  210. package/src/utils/index.ts +7 -0
  211. package/src/utils/json-object.ts +29 -0
  212. package/src/utils/mfe-events.tsx +34 -0
  213. package/src/utils/query-param.ts +129 -0
  214. package/tsconfig.json +20 -0
@@ -0,0 +1,273 @@
1
+ import React, { useRef, useState, useEffect, Fragment } from 'react'
2
+ import { Box, IconButton, SvgIconOwnProps, Typography, keyframes, styled } from '@mui/material'
3
+ import PauseIcon from '@mui/icons-material/Pause'
4
+ import PlayArrowIcon from '@mui/icons-material/PlayArrow'
5
+
6
+ const MPCore1Classes = {
7
+ root: 'MPCore1-root',
8
+ control: 'MPCore1-control',
9
+ controlCompact: 'MPCore1-control-compact',
10
+ overlay: 'MPCore1-overlay',
11
+ playButton: 'MPCore1-play-button',
12
+ timer: 'MPCore1-timer',
13
+ progressBar: 'MPCore1-progress-bar',
14
+ loading: 'MPCore1-loading',
15
+ timeline: 'MPCore1-timeline',
16
+ bufferedSegments: 'MPCore1-buffered-segments'
17
+ }
18
+
19
+ const formatTime = (time: number): string => {
20
+ if (isNaN(time)) return '0:00'
21
+ const minutes = Math.floor(time / 60)
22
+ const seconds = Math.floor(time % 60)
23
+ .toString()
24
+ .padStart(2, '0')
25
+ return `${minutes}:${seconds}`
26
+ }
27
+
28
+ export interface MediaPlayerCore1Slots {
29
+ autoPlay?: boolean
30
+ muted?: boolean
31
+ iconPlayProps?: SvgIconOwnProps
32
+ }
33
+
34
+ interface IProps {
35
+ src: string
36
+ className?: string
37
+ slots?: MediaPlayerCore1Slots
38
+ }
39
+
40
+ const MediaPlayerCore1: React.FC<IProps> = (props) => {
41
+ const videoRef = useRef<HTMLVideoElement | null>(null)
42
+ const progressBarRef = useRef<HTMLDivElement>(null)
43
+ const [isLoading, setIsLoading] = useState(true)
44
+ const [isPlaying, setIsPlaying] = useState(false)
45
+ const [progress, setProgress] = useState(0)
46
+ const [currentTime, setCurrentTime] = useState(0)
47
+ const [duration, setDuration] = useState(0)
48
+ const [bufferedSegments, setBufferedSegments] = useState<{ left: number; width: number }[]>([])
49
+
50
+ useEffect(() => {
51
+ const video = videoRef.current
52
+ if (!video) return
53
+
54
+ const updateTime = () => {
55
+ setProgress((video.currentTime / video.duration) * 100)
56
+ setCurrentTime(video.currentTime)
57
+ }
58
+
59
+ const updateBuffered = () => {
60
+ const duration = video.duration
61
+ const segments = []
62
+ for (let i = 0; i < video.buffered.length; i++) {
63
+ const start = video.buffered.start(i)
64
+ const end = video.buffered.end(i)
65
+ segments.push({
66
+ left: (start / duration) * 100,
67
+ width: ((end - start) / duration) * 100
68
+ })
69
+ }
70
+ setBufferedSegments(segments)
71
+ }
72
+
73
+ video.addEventListener('play', () => setIsPlaying(true))
74
+ video.addEventListener('pause', () => setIsPlaying(false))
75
+
76
+ video.addEventListener('waiting', () => setIsLoading(true))
77
+ video.addEventListener('playing', () => setIsLoading(false))
78
+
79
+ video.addEventListener('timeupdate', updateTime)
80
+ video.addEventListener('progress', updateBuffered)
81
+ video.addEventListener('loadedmetadata', () => {
82
+ setDuration(video.duration)
83
+ updateBuffered()
84
+ })
85
+
86
+ return () => {
87
+ video.removeEventListener('timeupdate', updateTime)
88
+ video.removeEventListener('progress', updateBuffered)
89
+ videoRef.current = null
90
+ }
91
+ }, [])
92
+
93
+ const togglePlay = () => {
94
+ const video = videoRef.current
95
+ if (!video) return
96
+ if (video.paused) {
97
+ video.play()
98
+ } else {
99
+ video.pause()
100
+ }
101
+ }
102
+
103
+ const handleSeek = (e: React.MouseEvent<HTMLDivElement>) => {
104
+ const video = videoRef.current
105
+ const player = progressBarRef.current
106
+ if (!video || !player) return
107
+ const rect = player.getBoundingClientRect()
108
+ const percent = (e.clientX - rect.left) / rect.width
109
+ video.currentTime = percent * video.duration
110
+ }
111
+
112
+ const getClasses = () => {
113
+ return [MPCore1Classes.root, props.className].filter((x) => !!x).join(' ')
114
+ }
115
+
116
+ const renderProgressBarContent = () => (
117
+ <Fragment>
118
+ {bufferedSegments.map((seg, idx) => (
119
+ <Box key={idx} className={MPCore1Classes.bufferedSegments} sx={{ left: `${seg.left}%`, width: `${seg.width}%` }} />
120
+ ))}
121
+ <Box className={MPCore1Classes.timeline} sx={{ width: `${progress}%` }} />
122
+ {isLoading && <Box className={MPCore1Classes.loading} />}
123
+ </Fragment>
124
+ )
125
+ return (
126
+ <Wrap className={getClasses()}>
127
+ <video ref={videoRef} width='100%' height='100%' preload='auto' src={props.src} autoPlay={props.slots?.autoPlay} muted={props.slots?.muted} />
128
+ <div className={MPCore1Classes.overlay} onClick={togglePlay} />
129
+ <div className={MPCore1Classes.control}>
130
+ <div className={MPCore1Classes.playButton}>
131
+ <IconButton size='small' onClick={togglePlay}>
132
+ {isPlaying ? <PauseIcon {...props.slots?.iconPlayProps} /> : <PlayArrowIcon {...props.slots?.iconPlayProps} />}
133
+ </IconButton>
134
+ </div>
135
+ <div ref={progressBarRef} onClick={handleSeek} className={MPCore1Classes.progressBar}>
136
+ {renderProgressBarContent()}
137
+ </div>
138
+ <Typography className={MPCore1Classes.timer} variant='body2' color='white'>
139
+ {formatTime(currentTime)} / {formatTime(duration)}
140
+ </Typography>
141
+ </div>
142
+ <div className={MPCore1Classes.controlCompact}>
143
+ <div className={MPCore1Classes.progressBar}>{renderProgressBarContent()}</div>
144
+ </div>
145
+ </Wrap>
146
+ )
147
+ }
148
+
149
+ export default MediaPlayerCore1
150
+
151
+ const stripeAnimation = keyframes`
152
+ 0% {
153
+ background-position: 0 0;
154
+ }
155
+ 100% {
156
+ background-position: 48px 0;
157
+ }
158
+ `
159
+
160
+ const Wrap = styled(Box)({
161
+ // '--mp-core1-color-main': '#ed4229',
162
+ // '--mp-core1-color-text': '#fff',
163
+ // '--mp-core1-icon-size': '34px',
164
+ width: '640px',
165
+ height: '360px',
166
+ position: 'relative',
167
+ [`.${MPCore1Classes.playButton}`]: {
168
+ flex: '0 0 auto',
169
+ '.MuiButtonBase-root': {
170
+ width: 'var(--mp-core1-icon-size, 34px)',
171
+ height: 'var(--mp-core1-icon-size, 34px)',
172
+ background: 'var(--mp-core1-color-main, #fff)',
173
+ color: 'var(--mp-core1-color-text, #000)'
174
+ }
175
+ },
176
+ [`.${MPCore1Classes.control}`]: {
177
+ position: 'absolute',
178
+ bottom: 0,
179
+ left: 0,
180
+ width: '100%',
181
+ display: 'flex',
182
+ alignItems: 'center',
183
+ padding: '6px 8px',
184
+ gap: '8px',
185
+ zIndex: 3,
186
+ transition: '0.3s',
187
+ transform: 'translateY(100%)'
188
+ },
189
+ [`.${MPCore1Classes.controlCompact}`]: {
190
+ position: 'absolute',
191
+ bottom: 0,
192
+ left: 0,
193
+ width: '100%',
194
+ padding: '3px',
195
+ transition: '0.3s',
196
+ zIndex: 2,
197
+ opacity: 0.5,
198
+ [`.${MPCore1Classes.progressBar}`]: {
199
+ height: 6
200
+ }
201
+ },
202
+ [`.${MPCore1Classes.overlay}`]: {
203
+ position: 'absolute',
204
+ bottom: 0,
205
+ left: 0,
206
+ width: '100%',
207
+ height: '100%',
208
+ zIndex: 1,
209
+ opacity: 0,
210
+ transition: '0.3s',
211
+ cursor: 'pointer',
212
+ background: 'linear-gradient(to top, rgba(0, 0, 0, 0.7) 0%, rgba(0, 0, 0, 0) 20%)'
213
+ },
214
+ [`.${MPCore1Classes.timer}`]: {
215
+ marginTop: '2px',
216
+ flex: '0 0 auto'
217
+ },
218
+ [`.${MPCore1Classes.progressBar}`]: {
219
+ flex: 1,
220
+ position: 'relative',
221
+ cursor: 'pointer',
222
+ height: 8,
223
+ marginTop: 1,
224
+ borderRadius: '4px',
225
+ overflow: 'hidden',
226
+ backgroundColor: 'rgba(255,255,255,0.4)'
227
+ },
228
+ [`.${MPCore1Classes.loading}`]: {
229
+ position: 'absolute',
230
+ top: 0,
231
+ left: 0,
232
+ height: '100%',
233
+ width: '100%',
234
+ backgroundImage: `repeating-linear-gradient(
235
+ 30deg,
236
+ rgba(255,255,255,0.2) 0px,
237
+ rgba(255,255,255,0.2) 6px,
238
+ rgba(255,255,255,0.08) 6px,
239
+ rgba(255,255,255,0.08) 12px
240
+ )`,
241
+ filter: 'blur(0.5px)',
242
+ backgroundSize: '48px 48px',
243
+ animation: `${stripeAnimation} 4s linear infinite`,
244
+ pointerEvents: 'none',
245
+ overflow: 'hidden'
246
+ },
247
+ [`.${MPCore1Classes.bufferedSegments}`]: {
248
+ position: 'absolute',
249
+ top: 0,
250
+ height: '100%',
251
+ backgroundColor: 'rgba(255,255,255,0.4)',
252
+ pointerEvents: 'none'
253
+ },
254
+ [`.${MPCore1Classes.timeline}`]: {
255
+ position: 'absolute',
256
+ top: 0,
257
+ left: 0,
258
+ height: '100%',
259
+ background: 'var(--mp-core1-color-main, #fff)',
260
+ pointerEvents: 'none'
261
+ },
262
+ '&:hover': {
263
+ [`.${MPCore1Classes.overlay}`]: {
264
+ opacity: 1
265
+ },
266
+ [`.${MPCore1Classes.control}`]: {
267
+ transform: 'translateY(0)'
268
+ },
269
+ [`.${MPCore1Classes.controlCompact}`]: {
270
+ transform: 'translateY(100%)'
271
+ }
272
+ }
273
+ })
@@ -0,0 +1,62 @@
1
+ import React, { FC } from 'react'
2
+ import { Box, Fade, Skeleton, styled } from '@mui/material'
3
+ import { EMediaPlayerStatus, getAspectRatioStyled, MediaPlayerBaseProps, MediaPlayerBaseSlots, useStreamUrl } from './media-player.units'
4
+ import MediaPlayerCore1, { MediaPlayerCore1Slots } from './media-player.core1'
5
+
6
+ interface IProps extends MediaPlayerBaseProps {
7
+ slots?: MediaPlayerBaseSlots & {
8
+ core1Props?: MediaPlayerCore1Slots
9
+ }
10
+ }
11
+
12
+ const MediaPlayerMuted: FC<IProps> = (props) => {
13
+ const { status, streamUrl } = useStreamUrl(props.resourceId, props.fetchDataStream)
14
+
15
+ const renderLoading = () => {
16
+ if (props.slots?.loading) return props.slots.loading
17
+ const duration = props.slots?.loadingProps?.animationDuration ?? '1s'
18
+ return <Skeleton animation='wave' variant='rounded' sx={{ width: '100%', height: '100%', '&::after': { animationDuration: duration } }} />
19
+ }
20
+
21
+ return (
22
+ <WrapPlayer className={status === EMediaPlayerStatus.Loaded ? 'loaded' : ''} sx={getAspectRatioStyled(props.slots?.aspectRatio)}>
23
+ <WrapVideo>{streamUrl && <MediaPlayerCore1 className='player' src={streamUrl} slots={props.slots?.core1Props} />}</WrapVideo>
24
+ <Fade in={status === EMediaPlayerStatus.Loading || props.loading}>
25
+ <WrapVideo>{renderLoading()}</WrapVideo>
26
+ </Fade>
27
+ <Fade in={status === EMediaPlayerStatus.Error && !props.loading} unmountOnExit>
28
+ <WrapVideo>
29
+ <img src='images/video-error.webp' alt='video-error' style={{ width: '100%', height: '100%' }} />
30
+ </WrapVideo>
31
+ </Fade>
32
+ </WrapPlayer>
33
+ )
34
+ }
35
+
36
+ export default MediaPlayerMuted
37
+
38
+ const WrapPlayer = styled(Box)({
39
+ '--mp-core1-color-main': '#ed4229',
40
+ '--mp-core1-color-text': '#fff',
41
+ '--mp-core1-icon-size': '34px',
42
+ position: 'relative',
43
+ paddingBottom: '56.25%',
44
+ borderRadius: '6px',
45
+ overflow: 'hidden',
46
+ '&.loaded': {
47
+ background: '#000'
48
+ }
49
+ })
50
+
51
+ const WrapVideo = styled(Box)({
52
+ position: 'absolute',
53
+ top: 0,
54
+ left: 0,
55
+ width: '100%',
56
+ height: '100%',
57
+ zIndex: 2,
58
+ '.player': {
59
+ width: '100%',
60
+ height: '100%'
61
+ }
62
+ })
@@ -0,0 +1,80 @@
1
+ import { ReactNode, useEffect, useState } from 'react'
2
+ import { Breakpoint, SxProps, Theme } from '@mui/material'
3
+
4
+ export interface IMediaStream {
5
+ code: number
6
+ token: string
7
+ StreamUrl: string
8
+ }
9
+
10
+ export interface MediaPlayerBaseProps {
11
+ resourceId: string
12
+ fetchDataStream: (resourceId: string, signal?: AbortSignal) => Promise<IMediaStream[]>
13
+ loading?: boolean
14
+ }
15
+
16
+ export type AspectRatioParams = number | Partial<Record<Breakpoint, number>>
17
+
18
+ export interface MediaPlayerBaseSlots {
19
+ /**
20
+ * Aspect ratio (height / width), used to calculate height based on width.
21
+ * @default 56.25 (%)
22
+ */
23
+ aspectRatio?: AspectRatioParams
24
+ loading?: ReactNode
25
+ loadingProps?: {
26
+ disabled?: boolean
27
+ animationDuration?: string
28
+ }
29
+ }
30
+
31
+ export enum EMediaPlayerStatus {
32
+ Loading = 'Loading',
33
+ Loaded = 'Loaded',
34
+ Error = 'Error'
35
+ }
36
+
37
+ export const useStreamUrl = (resourceId: string | null, fetchDataStream: MediaPlayerBaseProps['fetchDataStream']) => {
38
+ const [status, setStatus] = useState(EMediaPlayerStatus.Loading)
39
+ const [streamUrl, setStreamUrl] = useState<string | null>(null)
40
+
41
+ useEffect(() => {
42
+ const abortController = new AbortController()
43
+ const func = async () => {
44
+ setStatus(EMediaPlayerStatus.Loading)
45
+ try {
46
+ if (!resourceId) return
47
+ const res = await fetchDataStream(resourceId, abortController.signal)
48
+ const url = res[0].StreamUrl
49
+ if (typeof url === 'string' && !!url) setStreamUrl(url)
50
+ setStatus(EMediaPlayerStatus.Loaded)
51
+ } catch {
52
+ setStatus(EMediaPlayerStatus.Error)
53
+ }
54
+ }
55
+ func()
56
+ return () => {
57
+ setStatus(EMediaPlayerStatus.Loading)
58
+ abortController.abort()
59
+ }
60
+ }, [resourceId, fetchDataStream])
61
+
62
+ return { status, streamUrl }
63
+ }
64
+
65
+ export const getAspectRatio = (value?: AspectRatioParams, defaultAspectRatio = '56.25%') => {
66
+ if (!value) return defaultAspectRatio
67
+ if (typeof value === 'number') return `${value}%`
68
+ if (typeof value === 'object') {
69
+ const result: Partial<Record<Breakpoint, string>> = {}
70
+ for (const key in value) {
71
+ result[key as Breakpoint] = `${value[key as Breakpoint]}%`
72
+ }
73
+ return result
74
+ }
75
+ return undefined
76
+ }
77
+
78
+ export const getAspectRatioStyled = (value?: AspectRatioParams): SxProps<Theme> => {
79
+ return { paddingBottom: getAspectRatio(value) }
80
+ }
@@ -0,0 +1,183 @@
1
+ import React, { Component, ReactNode } from 'react'
2
+ import { alpha, Box, CircularProgress, colors, Divider, Fade, Grid, styled, TablePagination, Typography } from '@mui/material'
3
+ import { mergeObjects } from '../../utils'
4
+ import { tableGridClasses } from './helpers'
5
+ import { CreateTableGridItemActions } from './item-actions'
6
+ import { CreateFilterBar, FilterState } from '../filter-bar'
7
+ import { GlobalModal, PopoverGlobal } from '../../api-context'
8
+ import { TableGridFilter, PaginationModel, TableGridParams, TableGridProps, TableGridInnerSlots } from './types'
9
+ import ToolbarPannelDefault from './toolbar-pannel'
10
+
11
+ function CreateTableGrid<T extends object>(params: TableGridParams<T>) {
12
+ const FilterBarInstance = CreateFilterBar<T>(params.filterBarConfig ?? { fields: {} })
13
+ const ItemActions = CreateTableGridItemActions<T>()
14
+
15
+ class TableGrid extends Component<TableGridProps<T>> {
16
+ defaultPagination: PaginationModel = { page: 0, pageSize: 10 }
17
+ private filterStateStore: TableGridFilter<T> = { pagination: this.defaultPagination }
18
+ get filterState(): TableGridFilter<T> {
19
+ return this.props.filter ?? this.filterStateStore
20
+ }
21
+
22
+ get slots(): TableGridInnerSlots<T> {
23
+ const obj = mergeObjects(params.slots, this.props.slots)
24
+ return {
25
+ ...obj,
26
+ TableGridItem: this.props.slots?.item ?? params.item ?? (() => <ItemDefault />),
27
+ ToolbarPannel: this.props.slots?.toolbar ?? params.slots?.toolbar ?? ToolbarPannelDefault
28
+ }
29
+ }
30
+
31
+ get mergeConfig() {
32
+ return {
33
+ size: params.size ?? { xs: 12, sm: 6, md: 4 }
34
+ }
35
+ }
36
+
37
+ setFilterState = (value: Partial<TableGridFilter<T>>) => {
38
+ try {
39
+ if (!!value.details) {
40
+ this.filterStateStore = { pagination: this.filterStateStore.pagination, ...value }
41
+ } else {
42
+ this.filterStateStore = mergeObjects<any>({}, this.filterState, value)
43
+ }
44
+ this.props.onFilterChange && this.props.onFilterChange(this.filterStateStore)
45
+ this.forceUpdate()
46
+ } catch (error) {
47
+ console.log(error)
48
+ }
49
+ }
50
+
51
+ render() {
52
+ const { TableGridItem, ToolbarPannel, actionProps } = this.slots
53
+ const items = this.getItems()
54
+ return this.preRender(
55
+ <Wrap className={this.getRootClases()}>
56
+ <ToolbarPannel title={params.title} {...this.slots.toolbarProps} />
57
+ <FilterBarInstance value={this.filterState} onChange={this.handleFilterChange} />
58
+ <div className={tableGridClasses.content}>
59
+ <div className={[tableGridClasses.contentInner, tableGridClasses.contentPosition].join(' ')}>
60
+ <Grid container spacing={2} {...this.slots.gridContainer}>
61
+ {items.map((item, index) => (
62
+ <Grid key={params.getSelecterId(item).toString() + index} item {...this.mergeConfig.size} {...this.slots.gridItem}>
63
+ <div className={tableGridClasses.item}>
64
+ <TableGridItem value={item} />
65
+ <Box className={tableGridClasses.actions}>
66
+ <ItemActions value={item} {...actionProps} />
67
+ </Box>
68
+ </div>
69
+ </Grid>
70
+ ))}
71
+ </Grid>
72
+ </div>
73
+ <Fade in={this.filterState.loading} unmountOnExit>
74
+ <div className={[tableGridClasses.overlay, tableGridClasses.contentPosition].join(' ')}>
75
+ <CircularProgress size={36} />
76
+ </div>
77
+ </Fade>
78
+ <Fade in={items.length < 1 && !this.filterState.loading} unmountOnExit>
79
+ <div className={[tableGridClasses.noItems, tableGridClasses.contentPosition].join(' ')}>
80
+ <Typography variant='body2'>No items data</Typography>
81
+ </div>
82
+ </Fade>
83
+ </div>
84
+ <Divider />
85
+ <TablePagination
86
+ component='div'
87
+ count={this.props.data.totalItems ?? 0}
88
+ page={this.filterState.pagination.page}
89
+ onPageChange={this.handleChangePage}
90
+ rowsPerPage={this.filterState.pagination.pageSize}
91
+ onRowsPerPageChange={this.handleChangeRowsPerPage}
92
+ slotProps={{ select: { MenuProps: { disableScrollLock: true } } }}
93
+ />
94
+ </Wrap>
95
+ )
96
+ }
97
+
98
+ preRender = (children?: ReactNode) => (
99
+ <GlobalModal>
100
+ <PopoverGlobal.Provider />
101
+ {children}
102
+ </GlobalModal>
103
+ )
104
+
105
+ getRootClases = () => {
106
+ const classes = [tableGridClasses.root]
107
+ if (this.filterState.loading) classes.push(tableGridClasses.loading)
108
+ return classes.join(' ')
109
+ }
110
+
111
+ getItems = () => {
112
+ return this.props.data.items ?? []
113
+ }
114
+
115
+ handleFilterChange = (filterStateChange: FilterState<T>) => {
116
+ this.setFilterState(filterStateChange)
117
+ }
118
+
119
+ handleChangePage = (_: React.MouseEvent<HTMLButtonElement, MouseEvent> | null, page: number) => {
120
+ // this.setState((prev) => ({ pagination: { ...prev.pagination, page } }))
121
+ this.setFilterState({ pagination: { page, pageSize: this.filterState.pagination.pageSize } })
122
+ }
123
+
124
+ handleChangeRowsPerPage: React.ChangeEventHandler<HTMLInputElement | HTMLTextAreaElement> = (event) => {
125
+ // this.setState({ pagination: { page: 0, pageSize: parseInt(event.target.value, 10) } })
126
+ this.setFilterState({ pagination: { page: 0, pageSize: parseInt(event.target.value, 10) } })
127
+ }
128
+ }
129
+
130
+ return TableGrid
131
+ }
132
+
133
+ export default CreateTableGrid
134
+
135
+ const Wrap = styled(Box)({
136
+ flex: 1,
137
+ height: '100%',
138
+ display: 'flex',
139
+ flexDirection: 'column',
140
+ [`.${tableGridClasses.content}`]: {
141
+ position: 'relative',
142
+ flex: 1
143
+ },
144
+ [`.${tableGridClasses.contentPosition}`]: {
145
+ position: 'absolute',
146
+ top: 0,
147
+ left: 0,
148
+ width: '100%',
149
+ height: '100%'
150
+ },
151
+ [`.${tableGridClasses.contentInner}`]: {
152
+ overflowY: 'auto',
153
+ padding: '10px 5px'
154
+ },
155
+ [`.${tableGridClasses.overlay}`]: {
156
+ display: 'flex',
157
+ alignItems: 'center',
158
+ justifyContent: 'center',
159
+ background: alpha(colors.common.white, 0.4),
160
+ zIndex: 10
161
+ },
162
+ [`.${tableGridClasses.noItems}`]: {
163
+ display: 'flex',
164
+ alignItems: 'center',
165
+ justifyContent: 'center'
166
+ },
167
+ [`.${tableGridClasses.item}`]: {
168
+ position: 'relative'
169
+ },
170
+ [`.${tableGridClasses.actions}`]: {
171
+ position: 'absolute',
172
+ top: '5px',
173
+ right: '5px',
174
+ zIndex: 5,
175
+ display: 'inline-block'
176
+ }
177
+ })
178
+
179
+ const ItemDefault = styled(Box)({
180
+ width: '100%',
181
+ paddingBottom: '100%',
182
+ background: colors.grey[600]
183
+ })
@@ -0,0 +1,53 @@
1
+ import React, { FC } from 'react'
2
+ import CreateTableGrid from './create.table-grid'
3
+ import { Box, Container, Typography } from '@mui/material'
4
+ import { ESearchMatch } from '../filter-bar'
5
+
6
+ // interface IData {
7
+ // Id: string
8
+ // Title: string
9
+ // Description?: string
10
+ // }
11
+
12
+ // const getData = () => {
13
+ // const list: IData[] = []
14
+ // for (let index = 0; index < 50; index++) {
15
+ // list.push({
16
+ // Id: crypto.randomUUID(),
17
+ // Title: 'Title - ' + index,
18
+ // Description: 'Description - ' + index
19
+ // })
20
+ // }
21
+ // return list
22
+ // }
23
+
24
+ // const TableGridInstance = CreateTableGrid<IData>({
25
+ // getSelecterId: (x) => x.Id,
26
+ // filterBarConfig: {
27
+ // fields: {
28
+ // Id: { searchMatches: { rule: ESearchMatch.AlwaysVisible } },
29
+ // Title: { searchMatches: { rule: ESearchMatch.AlwaysVisible } },
30
+ // Description: { searchMatches: { rule: ESearchMatch.AlwaysVisible } }
31
+ // }
32
+ // },
33
+ // item: (p) => {
34
+ // return (
35
+ // <Box sx={{ padding: '12px' }}>
36
+ // <Typography>Media Group Item</Typography>
37
+ // <Typography variant='body2'>{p.value.Id}</Typography>
38
+ // <Typography variant='body2'>{p.value.Title}</Typography>
39
+ // </Box>
40
+ // )
41
+ // }
42
+ // })
43
+
44
+ const TableGridDemo: FC = () => {
45
+ return (
46
+ <Container maxWidth='xl'>
47
+ <Typography>TableGridDemo</Typography>
48
+ {/* <TableGridInstance value={getData()} /> */}
49
+ </Container>
50
+ )
51
+ }
52
+
53
+ export default TableGridDemo
@@ -0,0 +1,8 @@
1
+ import CreateLayoutGrid from './create.table-grid'
2
+
3
+ class DinoTableGridBase {
4
+ createTable = CreateLayoutGrid
5
+ }
6
+
7
+ const DinoTableGrid = new DinoTableGridBase()
8
+ export default DinoTableGrid
@@ -0,0 +1,11 @@
1
+ export const tableGridClasses = {
2
+ root: 'TableGrid-root',
3
+ content: 'TableGrid-content',
4
+ contentPosition: 'TableGrid-contentPosition',
5
+ contentInner: 'TableGrid-contentInner',
6
+ loading: 'TableGrid-loading',
7
+ overlay: 'TableGrid-overlay',
8
+ item: 'TableGrid-item',
9
+ actions: 'TableGrid-actions',
10
+ noItems: 'TableGrid-noItems'
11
+ }
@@ -0,0 +1,3 @@
1
+ export { default as DinoTableGrid } from './dino'
2
+
3
+ export * from './types'