@hh.ru/magritte-ui-video 1.0.1 → 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/index.css CHANGED
@@ -21,7 +21,7 @@
21
21
  .magritte-zp-day-theme{
22
22
  --magritte-color-background-accent-v26-0-2:#7195AF;
23
23
  }
24
- .magritte-player___IHHy5_1-0-1{
24
+ .magritte-player___IHHy5_1-0-2{
25
25
  position:relative;
26
26
  width:100%;
27
27
  overflow:hidden;
@@ -32,23 +32,23 @@
32
32
  -webkit-user-select:none;
33
33
  -webkit-touch-callout:none;
34
34
  }
35
- .magritte-player-fit___TX-6X_1-0-1{
35
+ .magritte-player-fit___TX-6X_1-0-2{
36
36
  height:100%;
37
37
  }
38
- .magritte-player-embedded___GNvRb_1-0-1{
38
+ .magritte-player-embedded___GNvRb_1-0-2{
39
39
  overflow:visible;
40
40
  background-color:transparent;
41
41
  }
42
- .magritte-video___4cS-u_1-0-1{
42
+ .magritte-video___4cS-u_1-0-2{
43
43
  display:block;
44
44
  width:100%;
45
45
  height:100%;
46
46
  object-fit:contain;
47
47
  }
48
- .magritte-video-hidden___agqVq_1-0-1{
48
+ .magritte-video-hidden___agqVq_1-0-2{
49
49
  visibility:hidden;
50
50
  }
51
- .magritte-overlay-button___MIRAP_1-0-1{
51
+ .magritte-overlay-button___MIRAP_1-0-2{
52
52
  position:absolute;
53
53
  top:50%;
54
54
  left:50%;
@@ -58,7 +58,7 @@
58
58
  backdrop-filter:blur(24px);
59
59
  transition:opacity var(--magritte-semantic-animation-time-m-duration-v26-0-2) var(--magritte-semantic-animation-ease-base-timing-function-v26-0-2);
60
60
  }
61
- .magritte-duration___ND1ei_1-0-1{
61
+ .magritte-duration___ND1ei_1-0-2{
62
62
  position:absolute;
63
63
  right:16px;
64
64
  bottom:16px;
@@ -69,7 +69,7 @@
69
69
  backdrop-filter:blur(24px);
70
70
  pointer-events:none;
71
71
  }
72
- .magritte-seek-indicator___VJQBC_1-0-1{
72
+ .magritte-seek-indicator___VJQBC_1-0-2{
73
73
  position:absolute;
74
74
  top:50%;
75
75
  display:flex;
@@ -78,25 +78,25 @@
78
78
  transform:translateY(-50%);
79
79
  pointer-events:none;
80
80
  }
81
- .magritte-seek-indicator-forward___9C5gD_1-0-1{
81
+ .magritte-seek-indicator-forward___9C5gD_1-0-2{
82
82
  right:40px;
83
83
  }
84
- .magritte-seek-indicator-backward___gIZ0E_1-0-1{
84
+ .magritte-seek-indicator-backward___gIZ0E_1-0-2{
85
85
  left:40px;
86
86
  flex-direction:row-reverse;
87
87
  --magritte-ui-video-seek-arrow-shift:16px;
88
88
  }
89
- .magritte-seek-arrows___Ql1eP_1-0-1{
89
+ .magritte-seek-arrows___Ql1eP_1-0-2{
90
90
  position:relative;
91
91
  display:flex;
92
92
  }
93
- .magritte-seek-arrow-incoming___oZxww_1-0-1{
93
+ .magritte-seek-arrow-incoming___oZxww_1-0-2{
94
94
  position:absolute;
95
95
  inset:0;
96
96
  display:flex;
97
- animation:magritte-seek-arrow-in___CB4-s_1-0-1 var(--magritte-semantic-animation-time-m-duration-v26-0-2) var(--magritte-semantic-animation-ease-base-timing-function-v26-0-2) both;
97
+ animation:magritte-seek-arrow-in___CB4-s_1-0-2 var(--magritte-semantic-animation-time-m-duration-v26-0-2) var(--magritte-semantic-animation-ease-base-timing-function-v26-0-2) both;
98
98
  }
99
- @keyframes magritte-seek-arrow-in___CB4-s_1-0-1{
99
+ @keyframes magritte-seek-arrow-in___CB4-s_1-0-2{
100
100
  from{
101
101
  transform:translateX(var(--magritte-ui-video-seek-arrow-shift, -16px));
102
102
  }
@@ -104,7 +104,7 @@
104
104
  transform:translateX(0);
105
105
  }
106
106
  }
107
- .magritte-boost-indicator___ujllx_1-0-1{
107
+ .magritte-boost-indicator___ujllx_1-0-2{
108
108
  position:absolute;
109
109
  top:24px;
110
110
  left:50%;
@@ -118,7 +118,7 @@
118
118
  transform:translateX(-50%);
119
119
  pointer-events:none;
120
120
  }
121
- .magritte-loader___qVu0P_1-0-1{
121
+ .magritte-loader___qVu0P_1-0-2{
122
122
  position:absolute;
123
123
  top:50%;
124
124
  left:50%;
@@ -126,7 +126,7 @@
126
126
  display:flex;
127
127
  pointer-events:none;
128
128
  }
129
- .magritte-error___Rm7uG_1-0-1{
129
+ .magritte-error___Rm7uG_1-0-2{
130
130
  position:absolute;
131
131
  inset:0;
132
132
  display:flex;
@@ -135,12 +135,12 @@
135
135
  padding:16px;
136
136
  overflow:auto;
137
137
  }
138
- .magritte-overlay-button-hidden___AoGFc_1-0-1,
139
- .magritte-controls___pKoSN_1-0-1.magritte-controls-hidden___bePTD_1-0-1{
138
+ .magritte-overlay-button-hidden___AoGFc_1-0-2,
139
+ .magritte-controls___pKoSN_1-0-2.magritte-controls-hidden___bePTD_1-0-2{
140
140
  opacity:0;
141
141
  pointer-events:none;
142
142
  }
143
- .magritte-controls___pKoSN_1-0-1{
143
+ .magritte-controls___pKoSN_1-0-2{
144
144
  display:flex;
145
145
  flex-direction:column;
146
146
  gap:4px;
@@ -148,52 +148,52 @@
148
148
  pointer-events:auto;
149
149
  transition:opacity var(--magritte-semantic-animation-time-m-duration-v26-0-2) var(--magritte-semantic-animation-ease-base-timing-function-v26-0-2);
150
150
  }
151
- .magritte-controls-mobile___tdKGT_1-0-1{
151
+ .magritte-controls-mobile___tdKGT_1-0-2{
152
152
  gap:6px;
153
153
  padding:4px 16px 8px;
154
154
  }
155
- .magritte-controls-overlay___mRsJL_1-0-1{
155
+ .magritte-controls-overlay___mRsJL_1-0-2{
156
156
  position:absolute;
157
157
  right:0;
158
158
  bottom:0;
159
159
  left:0;
160
160
  }
161
- .magritte-controls-row___2sdJg_1-0-1{
161
+ .magritte-controls-row___2sdJg_1-0-2{
162
162
  display:flex;
163
163
  align-items:center;
164
164
  justify-content:space-between;
165
165
  gap:8px;
166
166
  }
167
- .magritte-controls-group-start___yY9ZA_1-0-1,
168
- .magritte-controls-group-end___ziIm8_1-0-1{
167
+ .magritte-controls-group-start___yY9ZA_1-0-2,
168
+ .magritte-controls-group-end___ziIm8_1-0-2{
169
169
  display:flex;
170
170
  align-items:center;
171
171
  min-width:0;
172
172
  }
173
- .magritte-controls-group-start___yY9ZA_1-0-1{
173
+ .magritte-controls-group-start___yY9ZA_1-0-2{
174
174
  gap:12px;
175
175
  }
176
- .magritte-controls-group-end___ziIm8_1-0-1{
176
+ .magritte-controls-group-end___ziIm8_1-0-2{
177
177
  gap:8px;
178
178
  }
179
- .magritte-controls-mobile___tdKGT_1-0-1 .magritte-controls-group-end___ziIm8_1-0-1{
179
+ .magritte-controls-mobile___tdKGT_1-0-2 .magritte-controls-group-end___ziIm8_1-0-2{
180
180
  gap:4px;
181
181
  }
182
- .magritte-control-pill___hK8Mv_1-0-1,
183
- .magritte-controls-time___e9zoz_1-0-1,
184
- .magritte-controls-volume___o4ajR_1-0-1{
182
+ .magritte-control-pill___hK8Mv_1-0-2,
183
+ .magritte-controls-time___e9zoz_1-0-2,
184
+ .magritte-controls-volume___o4ajR_1-0-2{
185
185
  display:flex;
186
186
  align-items:center;
187
187
  justify-content:center;
188
188
  border-radius:999px;
189
189
  backdrop-filter:blur(24px);
190
190
  }
191
- .magritte-control-pill-bare___lU9ev_1-0-1{
191
+ .magritte-control-pill-bare___lU9ev_1-0-2{
192
192
  backdrop-filter:none;
193
193
  }
194
- .magritte-control-button___VJ2Qr_1-0-1,
195
- .magritte-controls-time___e9zoz_1-0-1,
196
- .magritte-controls-volume___o4ajR_1-0-1{
194
+ .magritte-control-button___VJ2Qr_1-0-2,
195
+ .magritte-controls-time___e9zoz_1-0-2,
196
+ .magritte-controls-volume___o4ajR_1-0-2{
197
197
  box-sizing:border-box;
198
198
  min-width:48px;
199
199
  min-height:48px;
@@ -201,27 +201,27 @@
201
201
  border-radius:999px;
202
202
  background-color:var(--magritte-color-background-overlay-v26-0-2);
203
203
  }
204
- .magritte-control-button___VJ2Qr_1-0-1{
204
+ .magritte-control-button___VJ2Qr_1-0-2{
205
205
  display:flex;
206
206
  align-items:center;
207
207
  justify-content:center;
208
208
  border-width:0;
209
209
  cursor:pointer;
210
210
  }
211
- .magritte-control-button___VJ2Qr_1-0-1.focus-visible{
211
+ .magritte-control-button___VJ2Qr_1-0-2.focus-visible{
212
212
  outline:4px solid var(--magritte-color-stroke-state-focused-accessible-v26-0-2);
213
213
  }
214
- .magritte-controls-time___e9zoz_1-0-1{
214
+ .magritte-controls-time___e9zoz_1-0-2{
215
215
  padding:12px 16px;
216
216
  white-space:nowrap;
217
217
  }
218
- .magritte-controls-mobile___tdKGT_1-0-1 .magritte-controls-time___e9zoz_1-0-1{
218
+ .magritte-controls-mobile___tdKGT_1-0-2 .magritte-controls-time___e9zoz_1-0-2{
219
219
  padding:12px;
220
220
  }
221
- .magritte-controls-volume___o4ajR_1-0-1{
221
+ .magritte-controls-volume___o4ajR_1-0-2{
222
222
  gap:6px;
223
223
  }
224
- .magritte-scrubber___-K3ik_1-0-1{
224
+ .magritte-scrubber___-K3ik_1-0-2{
225
225
  position:relative;
226
226
  display:flex;
227
227
  align-items:center;
@@ -232,32 +232,32 @@
232
232
  --magritte-ui-video-scrubber-track-height:4px;
233
233
  --magritte-ui-video-scrubber-thumb-size:8px;
234
234
  }
235
- .magritte-controls-mobile___tdKGT_1-0-1 .magritte-scrubber___-K3ik_1-0-1::before{
235
+ .magritte-controls-mobile___tdKGT_1-0-2 .magritte-scrubber___-K3ik_1-0-2::before{
236
236
  content:'';
237
237
  position:absolute;
238
238
  inset:calc(-1 * 20px) 0 calc(-1 * 6px);
239
239
  }
240
- .magritte-scrubber___-K3ik_1-0-1.focus-visible{
240
+ .magritte-scrubber___-K3ik_1-0-2.focus-visible{
241
241
  outline:4px solid var(--magritte-color-stroke-state-focused-accessible-v26-0-2);
242
242
  border-radius:4px;
243
243
  }
244
- .magritte-scrubber___-K3ik_1-0-1[data-scrubbing]{
244
+ .magritte-scrubber___-K3ik_1-0-2[data-scrubbing]{
245
245
  --magritte-ui-video-scrubber-track-height:6px;
246
246
  --magritte-ui-video-scrubber-thumb-size:12px;
247
247
  }
248
248
  @media (min-width: 1020px){
249
- body.magritte-old-layout .magritte-scrubber___-K3ik_1-0-1:hover{
249
+ body.magritte-old-layout .magritte-scrubber___-K3ik_1-0-2:hover{
250
250
  --magritte-ui-video-scrubber-track-height:6px;
251
251
  --magritte-ui-video-scrubber-thumb-size:12px;
252
252
  }
253
253
  }
254
254
  @media (min-width: 1024px){
255
- body:not(.magritte-old-layout) .magritte-scrubber___-K3ik_1-0-1:hover{
255
+ body:not(.magritte-old-layout) .magritte-scrubber___-K3ik_1-0-2:hover{
256
256
  --magritte-ui-video-scrubber-track-height:6px;
257
257
  --magritte-ui-video-scrubber-thumb-size:12px;
258
258
  }
259
259
  }
260
- .magritte-scrubber-track___ki1zV_1-0-1{
260
+ .magritte-scrubber-track___ki1zV_1-0-2{
261
261
  position:relative;
262
262
  flex-grow:1;
263
263
  height:var(--magritte-ui-video-scrubber-track-height);
@@ -265,21 +265,21 @@
265
265
  border-radius:999px;
266
266
  background-color:var(--magritte-color-background-overlay-v26-0-2);
267
267
  }
268
- .magritte-scrubber-buffered___ufvLe_1-0-1,
269
- .magritte-scrubber-progress___ZIyew_1-0-1{
268
+ .magritte-scrubber-buffered___ufvLe_1-0-2,
269
+ .magritte-scrubber-progress___ZIyew_1-0-2{
270
270
  position:absolute;
271
271
  inset:0;
272
272
  transform-origin:left;
273
273
  }
274
- .magritte-scrubber-buffered___ufvLe_1-0-1{
274
+ .magritte-scrubber-buffered___ufvLe_1-0-2{
275
275
  background-color:var(--magritte-color-stroke-neutral-v26-0-2);
276
276
  transform:scaleX(var(--magritte-ui-video-scrubber-buffered, 0));
277
277
  }
278
- .magritte-scrubber-progress___ZIyew_1-0-1{
278
+ .magritte-scrubber-progress___ZIyew_1-0-2{
279
279
  background-color:var(--magritte-color-background-accent-v26-0-2);
280
280
  transform:scaleX(var(--magritte-ui-video-scrubber-progress, 0));
281
281
  }
282
- .magritte-scrubber-thumb___VXyPP_1-0-1{
282
+ .magritte-scrubber-thumb___VXyPP_1-0-2{
283
283
  position:absolute;
284
284
  top:50%;
285
285
  left:calc(var(--magritte-ui-video-scrubber-progress, 0) * 100%);
@@ -290,7 +290,7 @@
290
290
  transform:translate(-50%, -50%);
291
291
  pointer-events:none;
292
292
  }
293
- .magritte-scrubber-timecode___M-syA_1-0-1{
293
+ .magritte-scrubber-timecode___M-syA_1-0-2{
294
294
  position:absolute;
295
295
  bottom:calc(100% + 8px);
296
296
  left:calc(var(--magritte-ui-video-scrubber-timecode, 0) * 100%);
@@ -302,20 +302,20 @@
302
302
  white-space:nowrap;
303
303
  pointer-events:none;
304
304
  }
305
- .magritte-scrubber___-K3ik_1-0-1[data-scrubbing] .magritte-scrubber-timecode___M-syA_1-0-1{
305
+ .magritte-scrubber___-K3ik_1-0-2[data-scrubbing] .magritte-scrubber-timecode___M-syA_1-0-2{
306
306
  display:flex;
307
307
  }
308
308
  @media (min-width: 1020px){
309
- body.magritte-old-layout .magritte-scrubber___-K3ik_1-0-1:hover .magritte-scrubber-timecode___M-syA_1-0-1{
309
+ body.magritte-old-layout .magritte-scrubber___-K3ik_1-0-2:hover .magritte-scrubber-timecode___M-syA_1-0-2{
310
310
  display:flex;
311
311
  }
312
312
  }
313
313
  @media (min-width: 1024px){
314
- body:not(.magritte-old-layout) .magritte-scrubber___-K3ik_1-0-1:hover .magritte-scrubber-timecode___M-syA_1-0-1{
314
+ body:not(.magritte-old-layout) .magritte-scrubber___-K3ik_1-0-2:hover .magritte-scrubber-timecode___M-syA_1-0-2{
315
315
  display:flex;
316
316
  }
317
317
  }
318
- .magritte-volume-slider___qE2P7_1-0-1{
318
+ .magritte-volume-slider___qE2P7_1-0-2{
319
319
  display:flex;
320
320
  align-items:center;
321
321
  width:64px;
@@ -324,25 +324,25 @@
324
324
  touch-action:none;
325
325
  outline:none;
326
326
  }
327
- .magritte-volume-slider___qE2P7_1-0-1.focus-visible{
327
+ .magritte-volume-slider___qE2P7_1-0-2.focus-visible{
328
328
  outline:4px solid var(--magritte-color-stroke-state-focused-accessible-v26-0-2);
329
329
  border-radius:4px;
330
330
  }
331
- .magritte-volume-track___up8nd_1-0-1{
331
+ .magritte-volume-track___up8nd_1-0-2{
332
332
  position:relative;
333
333
  flex-grow:1;
334
334
  height:4px;
335
335
  border-radius:999px;
336
336
  background-color:var(--magritte-color-background-overlay-v26-0-2);
337
337
  }
338
- .magritte-volume-value___aUSuU_1-0-1{
338
+ .magritte-volume-value___aUSuU_1-0-2{
339
339
  position:relative;
340
340
  width:calc(var(--magritte-ui-video-volume, 1) * 100%);
341
341
  height:100%;
342
342
  border-radius:999px;
343
343
  background-color:var(--magritte-color-stroke-neutral-v26-0-2);
344
344
  }
345
- .magritte-volume-value___aUSuU_1-0-1::after{
345
+ .magritte-volume-value___aUSuU_1-0-2::after{
346
346
  content:'';
347
347
  position:absolute;
348
348
  top:50%;
package/index.js CHANGED
@@ -11,7 +11,7 @@ import '@hh.ru/magritte-ui-icon/icon';
11
11
  import '@hh.ru/magritte-ui-typography';
12
12
  import './internal/ControlButton.js';
13
13
  import '@hh.ru/magritte-ui-tooltip';
14
- import './video-C-iklAZX.js';
14
+ import './video-BnfN4Emx.js';
15
15
  import './internal/Scrubber.js';
16
16
  import './internal/formatTime.js';
17
17
  import './internal/useSliderPointer.js';
@@ -30,4 +30,5 @@ import '@hh.ru/magritte-ui-placeholder';
30
30
  import './internal/SeekIndicator.js';
31
31
  import './internal/store.js';
32
32
  import './internal/useCanvasGestures.js';
33
+ import './internal/useViewportVisibility.js';
33
34
  //# sourceMappingURL=index.js.map
package/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -3,7 +3,7 @@ import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
3
3
  import { useRef } from 'react';
4
4
  import classnames from 'classnames';
5
5
  import { TooltipHover } from '@hh.ru/magritte-ui-tooltip';
6
- import { s as styles } from '../video-C-iklAZX.js';
6
+ import { s as styles } from '../video-BnfN4Emx.js';
7
7
 
8
8
  const ControlButton = ({
9
9
  control,
@@ -6,7 +6,7 @@ import { Text } from '@hh.ru/magritte-ui-typography';
6
6
  import { formatTime, formatDuration } from './formatTime.js';
7
7
  import { useSliderPointer } from './useSliderPointer.js';
8
8
  import { SEEK_STEP_SECONDS } from './useVideoHotkeys.js';
9
- import { s as styles } from '../video-C-iklAZX.js';
9
+ import { s as styles } from '../video-BnfN4Emx.js';
10
10
  import '@hh.ru/magritte-common-keyboard';
11
11
 
12
12
  const KEYBOARD_SEEK_STEP = SEEK_STEP_SECONDS;
@@ -3,7 +3,7 @@ import { jsxs, jsx } from 'react/jsx-runtime';
3
3
  import classnames from 'classnames';
4
4
  import { ChevronRightOutlinedSize24, ChevronLeftOutlinedSize24 } from '@hh.ru/magritte-ui-icon/icon';
5
5
  import { Text } from '@hh.ru/magritte-ui-typography';
6
- import { s as styles } from '../video-C-iklAZX.js';
6
+ import { s as styles } from '../video-BnfN4Emx.js';
7
7
 
8
8
  const SeekIndicator = ({ direction, seconds, count }) => {
9
9
  const forward = direction > 0;
@@ -3,7 +3,7 @@ import { jsx } from 'react/jsx-runtime';
3
3
  import { useTranslation } from '@hh.ru/magritte-common-use-translation';
4
4
  import { useVideoState } from './context.js';
5
5
  import { useSliderPointer } from './useSliderPointer.js';
6
- import { s as styles } from '../video-C-iklAZX.js';
6
+ import { s as styles } from '../video-BnfN4Emx.js';
7
7
  import 'react';
8
8
 
9
9
  const KEYBOARD_VOLUME_STEP = 0.1;
@@ -5,6 +5,10 @@ export interface VideoContextValue {
5
5
  preview?: string;
6
6
  /** Длительность из пропсов — до загрузки метаданных */
7
7
  duration?: number;
8
+ /** `false` — неинтерактивный режим: без кнопок, контролов, жестов и горячих клавиш */
9
+ interactive: boolean;
10
+ /** Плеер сообщает стору свою видимость во вьюпорте (автовоспроизведение, автопауза) */
11
+ observeViewport: boolean;
8
12
  }
9
13
  export declare const VideoContext: import("react").Context<VideoContextValue | null>;
10
14
  export declare const useVideoContext: (componentName: string) => VideoContextValue;
@@ -1 +1 @@
1
- {"version":3,"file":"context.js","sources":["src/internal/context.ts"],"sourcesContent":["import { createContext, type ReactElement, type ReactNode, useContext, useSyncExternalStore } from 'react';\n\nimport { type VideoState, type VideoStore } from '@hh.ru/magritte-ui-video/internal/store';\n\nexport interface VideoContextValue {\n store: VideoStore;\n preview?: string;\n /** Длительность из пропсов — до загрузки метаданных */\n duration?: number;\n}\n\nexport const VideoContext = createContext<VideoContextValue | null>(null);\n\nexport const useVideoContext = (componentName: string): VideoContextValue => {\n const context = useContext(VideoContext);\n if (!context) {\n throw new Error(`${componentName} must be used within <Video>`);\n }\n return context;\n};\n\n/** Подписка на часть состояния: компонент перерендеривается, только когда она меняется */\nexport const useVideoState = <T>(store: VideoStore, selector: (state: VideoState) => T): T => {\n const getSnapshot = () => selector(store.getState());\n return useSyncExternalStore(store.subscribe, getSnapshot, getSnapshot);\n};\n\n/** Части видео внутри `Video.Player` (например, `Video.Controls`) раскладываются поверх видео */\nexport const VideoPlayerContext = createContext(false);\n\n/**\n * Встраивание `Video.Player` в другой компонент дизайн-системы (вьювер медиа): хост оборачивает `<video>` в свою\n * разметку (например, трансформацию зума), оверлеи плеера остаются без неё. Только для внутреннего использования\n */\nexport interface VideoPlayerHost {\n renderVideo: (video: ReactElement) => ReactNode;\n}\n\nexport const VideoPlayerHostContext = createContext<VideoPlayerHost | null>(null);\n"],"names":[],"mappings":";;AAWa,MAAA,YAAA,GAAe,cAAwC,IAAI,EAAA;AAE3D,MAAA,eAAA,GAAkB,CAAC,aAA6C,KAAA;AACzE,EAAM,MAAA,OAAA,GAAU,WAAW,YAAY,CAAA,CAAA;AACvC,EAAA,IAAI,CAAC,OAAS,EAAA;AACV,IAAA,MAAM,IAAI,KAAA,CAAM,CAAG,EAAA,aAAa,CAA8B,4BAAA,CAAA,CAAA,CAAA;AAAA,GAClE;AACA,EAAO,OAAA,OAAA,CAAA;AACX,EAAA;AAGa,MAAA,aAAA,GAAgB,CAAI,KAAA,EAAmB,QAA0C,KAAA;AAC1F,EAAA,MAAM,WAAc,GAAA,MAAM,QAAS,CAAA,KAAA,CAAM,UAAU,CAAA,CAAA;AACnD,EAAA,OAAO,oBAAqB,CAAA,KAAA,CAAM,SAAW,EAAA,WAAA,EAAa,WAAW,CAAA,CAAA;AACzE,EAAA;AAGa,MAAA,kBAAA,GAAqB,cAAc,KAAK,EAAA;AAUxC,MAAA,sBAAA,GAAyB,cAAsC,IAAI;;;;"}
1
+ {"version":3,"file":"context.js","sources":["src/internal/context.ts"],"sourcesContent":["import { createContext, type ReactElement, type ReactNode, useContext, useSyncExternalStore } from 'react';\n\nimport { type VideoState, type VideoStore } from '@hh.ru/magritte-ui-video/internal/store';\n\nexport interface VideoContextValue {\n store: VideoStore;\n preview?: string;\n /** Длительность из пропсов — до загрузки метаданных */\n duration?: number;\n /** `false` — неинтерактивный режим: без кнопок, контролов, жестов и горячих клавиш */\n interactive: boolean;\n /** Плеер сообщает стору свою видимость во вьюпорте (автовоспроизведение, автопауза) */\n observeViewport: boolean;\n}\n\nexport const VideoContext = createContext<VideoContextValue | null>(null);\n\nexport const useVideoContext = (componentName: string): VideoContextValue => {\n const context = useContext(VideoContext);\n if (!context) {\n throw new Error(`${componentName} must be used within <Video>`);\n }\n return context;\n};\n\n/** Подписка на часть состояния: компонент перерендеривается, только когда она меняется */\nexport const useVideoState = <T>(store: VideoStore, selector: (state: VideoState) => T): T => {\n const getSnapshot = () => selector(store.getState());\n return useSyncExternalStore(store.subscribe, getSnapshot, getSnapshot);\n};\n\n/** Части видео внутри `Video.Player` (например, `Video.Controls`) раскладываются поверх видео */\nexport const VideoPlayerContext = createContext(false);\n\n/**\n * Встраивание `Video.Player` в другой компонент дизайн-системы (вьювер медиа): хост оборачивает `<video>` в свою\n * разметку (например, трансформацию зума), оверлеи плеера остаются без неё. Только для внутреннего использования\n */\nexport interface VideoPlayerHost {\n renderVideo: (video: ReactElement) => ReactNode;\n}\n\nexport const VideoPlayerHostContext = createContext<VideoPlayerHost | null>(null);\n"],"names":[],"mappings":";;AAea,MAAA,YAAA,GAAe,cAAwC,IAAI,EAAA;AAE3D,MAAA,eAAA,GAAkB,CAAC,aAA6C,KAAA;AACzE,EAAM,MAAA,OAAA,GAAU,WAAW,YAAY,CAAA,CAAA;AACvC,EAAA,IAAI,CAAC,OAAS,EAAA;AACV,IAAA,MAAM,IAAI,KAAA,CAAM,CAAG,EAAA,aAAa,CAA8B,4BAAA,CAAA,CAAA,CAAA;AAAA,GAClE;AACA,EAAO,OAAA,OAAA,CAAA;AACX,EAAA;AAGa,MAAA,aAAA,GAAgB,CAAI,KAAA,EAAmB,QAA0C,KAAA;AAC1F,EAAA,MAAM,WAAc,GAAA,MAAM,QAAS,CAAA,KAAA,CAAM,UAAU,CAAA,CAAA;AACnD,EAAA,OAAO,oBAAqB,CAAA,KAAA,CAAM,SAAW,EAAA,WAAA,EAAa,WAAW,CAAA,CAAA;AACzE,EAAA;AAGa,MAAA,kBAAA,GAAqB,cAAc,KAAK,EAAA;AAUxC,MAAA,sBAAA,GAAyB,cAAsC,IAAI;;;;"}
@@ -3,6 +3,11 @@ export interface VideoState {
3
3
  status: VideoStatus;
4
4
  /** Воспроизведение запущено, но видео ждёт данные */
5
5
  waiting: boolean;
6
+ /**
7
+ * Повторная попытка после ошибки: до начала воспроизведения видео и превью не показываются — лоадер на тёмном
8
+ * фоне, а не мелькание превью перед новой ошибкой
9
+ */
10
+ retrying: boolean;
6
11
  /** Длительность из метаданных; `null`, пока неизвестна или бесконечна (live) */
7
12
  duration: number | null;
8
13
  /** Натуральный размер видео из метаданных */
@@ -27,6 +32,25 @@ export interface VideoState {
27
32
  /** Куда переносится индикатор ускорения вне fullscreen; `null` — вверху плеера */
28
33
  indicatorContainer: HTMLElement | null;
29
34
  }
35
+ /**
36
+ * Исключение из правил владельца видимости контролов: `shown` — показать и не прятать (фокус с клавиатуры в контролах,
37
+ * перетаскивание бегунка), `hidden` — спрятать и не показывать от активности (ускорение удержанием на desktop),
38
+ * `null` — исключений нет
39
+ */
40
+ export type VideoControlsPin = 'shown' | 'hidden' | null;
41
+ /**
42
+ * Внешний владелец видимости контролов (тулбары вьювера медиа). Пока он подключён, контролы показываются и прячутся
43
+ * только по нему: собственного таймера у плеера нет, активность и тапы по видео передаются ему
44
+ */
45
+ export interface VideoControlsVisibilityHost {
46
+ isVisible: () => boolean;
47
+ subscribe: (listener: (visible: boolean) => void) => VoidFunction;
48
+ /** Активность пользователя в плеере: движение мыши, нажатия, горячие клавиши */
49
+ notifyActivity: VoidFunction;
50
+ /** Тап по видео (mobile) */
51
+ toggle: VoidFunction;
52
+ setPin: (pin: VideoControlsPin) => void;
53
+ }
30
54
  export interface VideoTime {
31
55
  current: number;
32
56
  duration: number;
@@ -43,11 +67,23 @@ export interface VideoSourceOptions {
43
67
  sources?: VideoSource[];
44
68
  }
45
69
  type VideoCallbacks = Pick<VideoProps, 'onPlay' | 'onPause' | 'onEnded' | 'onError'>;
70
+ /** Режимы воспроизведения из пропсов `Video`; `interactive={false}` включает autoPlay и loop */
71
+ export interface VideoPlaybackOptions {
72
+ autoPlay: boolean;
73
+ autoPause: boolean;
74
+ loop: boolean;
75
+ interactive: boolean;
76
+ }
46
77
  export interface VideoStoreOptions extends VideoSourceOptions {
47
78
  /** Актуальные колбэки и attachMedia читаются в момент события — без пересоздания стора */
48
79
  getCallbacks: () => VideoCallbacks & {
49
80
  attachMedia?: VideoAttachMedia;
50
81
  };
82
+ /** Актуальные режимы воспроизведения; после их смены стор надо уведомить через `syncOptions` */
83
+ getOptions: () => VideoPlaybackOptions;
84
+ /** Звук и громкость на старте */
85
+ defaultMuted?: boolean;
86
+ defaultVolume?: number;
51
87
  }
52
88
  export interface VideoStore {
53
89
  getState: () => VideoState;
@@ -66,6 +102,13 @@ export interface VideoStore {
66
102
  seek: (seconds: number) => void;
67
103
  /** Перемотка относительно текущей позиции */
68
104
  seekBy: (seconds: number) => void;
105
+ /**
106
+ * Видимость плеера во вьюпорте (видно не меньше 10%): по ней работают автовоспроизведение и автопауза.
107
+ * `null` — неизвестно (плеер размонтирован)
108
+ */
109
+ setVisible: (visible: boolean | null) => void;
110
+ /** Режимы воспроизведения из пропсов изменились */
111
+ syncOptions: VoidFunction;
69
112
  /** Повторная загрузка после ошибки с запуском воспроизведения */
70
113
  retry: VoidFunction;
71
114
  /** play, если видео на паузе, закончилось или ещё не запускалось; иначе pause */
@@ -83,6 +126,8 @@ export interface VideoStore {
83
126
  setHideWhenPaused: (hide: boolean) => void;
84
127
  /** Пока удержание активно (фокус внутри контролов, перетаскивание ползунка), контролы не прячутся */
85
128
  holdControls: (hold: boolean) => void;
129
+ /** Подключить внешнего владельца видимости контролов; `null` — плеер снова управляет ими сам */
130
+ setControlsVisibilityHost: (host: VideoControlsVisibilityHost | null) => void;
86
131
  /** Callback ref для корня `Video.Player` — элемента, который разворачивается на весь экран */
87
132
  attachRoot: (element: HTMLElement | null) => void;
88
133
  getRoot: () => HTMLElement | null;
@@ -105,5 +150,5 @@ export declare const PLAYBACK_RATES: number[];
105
150
  export declare const BOOST_RATE = 2;
106
151
  /** Задержка автоскрытия контролов по спеке */
107
152
  export declare const CONTROLS_HIDE_DELAY_MS = 4000;
108
- export declare const createVideoStore: ({ getCallbacks, ...initialSource }: VideoStoreOptions) => VideoStore;
153
+ export declare const createVideoStore: ({ getCallbacks, getOptions, defaultMuted, defaultVolume, ...initialSource }: VideoStoreOptions) => VideoStore;
109
154
  export {};