@brightcove/components-embed-code-modal 1.1.1 → 1.1.3

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 (34) hide show
  1. package/.github/workflows/ci.yml +1 -1
  2. package/CHANGELOG.md +21 -1
  3. package/__tests__/PrismLiveModal.test.tsx +85 -0
  4. package/__tests__/PrismPlayerControls.test.tsx +139 -0
  5. package/__tests__/VideoPlayer.test.tsx +68 -1
  6. package/build/__tests__/PrismLiveModal.test.d.ts +2 -0
  7. package/build/__tests__/PrismLiveModal.test.d.ts.map +1 -0
  8. package/build/__tests__/PrismPlayerControls.test.d.ts +2 -0
  9. package/build/__tests__/PrismPlayerControls.test.d.ts.map +1 -0
  10. package/build/index.js +2 -2
  11. package/build/index.js.map +1 -1
  12. package/build/package.json +2 -2
  13. package/build/src/js/components/prism/PrismLiveModal.d.ts.map +1 -1
  14. package/build/src/js/components/prism/PrismPlayerControls.d.ts +2 -1
  15. package/build/src/js/components/prism/PrismPlayerControls.d.ts.map +1 -1
  16. package/build/src/js/components/prism/PrismPlayerPreview.d.ts +2 -1
  17. package/build/src/js/components/prism/PrismPlayerPreview.d.ts.map +1 -1
  18. package/build/src/js/hooks/useIsMobile.d.ts +3 -0
  19. package/build/src/js/hooks/useIsMobile.d.ts.map +1 -0
  20. package/build/src/js/i18n.d.ts +24 -0
  21. package/build/src/js/i18n.d.ts.map +1 -1
  22. package/package.json +2 -2
  23. package/src/js/components/VideoPlayer.tsx +2 -2
  24. package/src/js/components/prism/PrismLiveModal.tsx +40 -6
  25. package/src/js/components/prism/PrismPlayerControls.tsx +56 -43
  26. package/src/js/components/prism/PrismPlayerPreview.tsx +19 -7
  27. package/src/js/hooks/useIsMobile.ts +33 -0
  28. package/src/styles/prism/PrismLiveModal.sass +35 -62
  29. package/src/translations/en.json +4 -0
  30. package/src/translations/es.json +4 -0
  31. package/src/translations/fr.json +4 -0
  32. package/src/translations/ja.json +4 -0
  33. package/src/translations/ko.json +4 -0
  34. package/src/translations/zh.json +4 -0
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@brightcove/components-embed-code-modal",
3
- "version": "1.1.1",
3
+ "version": "1.1.3",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "https://bithub.brightcove.com/studio-ui-kit/studio-components-embed-code-modal.git"
@@ -34,7 +34,7 @@
34
34
  "@brightcove/kacl": "^0.1.11",
35
35
  "@brightcove/notify-change": "^0.1.7",
36
36
  "@brightcove/player-embed-code": "^2.0.4",
37
- "@brightcove/prism-core": "^1.64.0",
37
+ "@brightcove/prism-core": "^1.174.0",
38
38
  "@brightcove/react-player-loader": "^1.4.2",
39
39
  "@brightcove/studio-api-services": "^7.0.0",
40
40
  "@brightcove/studio-components": "^7.23.4",
@@ -1 +1 @@
1
- {"version":3,"file":"PrismLiveModal.d.ts","sourceRoot":"","sources":["../../../../../src/js/components/prism/PrismLiveModal.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA8B,MAAM,OAAO,CAAC;AAGnD,OAAO,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACnE,OAAO,EACL,WAAW,EAIZ,MAAM,8BAA8B,CAAC;AAQtC,UAAU,mBAAmB;IAC3B,MAAM,EAAE,OAAO,CAAC;IAChB,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,KAAK,EAAE,WAAW,CAAC;IACnB,OAAO,EAAE,aAAa,CAAC;IACvB,sBAAsB,EAAE,gBAAgB,EAAE,CAAC;IAC3C,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,UAAU,CAAC,EAAE,CAAC,QAAQ,EAAE,OAAO,KAAK,IAAI,CAAC;IACzC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,iBAAiB,CAAC,EAAE,CAAC,QAAQ,EAAE,OAAO,KAAK,IAAI,CAAC;IAChD,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,gBAAgB,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAC3C,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,eAAe,CAAC,EAAE,KAAK,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAC3D;AAWD,eAAO,MAAM,cAAc,0LAexB,mBAAmB,sBAuGrB,CAAC"}
1
+ {"version":3,"file":"PrismLiveModal.d.ts","sourceRoot":"","sources":["../../../../../src/js/components/prism/PrismLiveModal.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA2C,MAAM,OAAO,CAAC;AAGhE,OAAO,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACnE,OAAO,EACL,WAAW,EAIZ,MAAM,8BAA8B,CAAC;AAatC,UAAU,mBAAmB;IAC3B,MAAM,EAAE,OAAO,CAAC;IAChB,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,KAAK,EAAE,WAAW,CAAC;IACnB,OAAO,EAAE,aAAa,CAAC;IACvB,sBAAsB,EAAE,gBAAgB,EAAE,CAAC;IAC3C,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,UAAU,CAAC,EAAE,CAAC,QAAQ,EAAE,OAAO,KAAK,IAAI,CAAC;IACzC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,iBAAiB,CAAC,EAAE,CAAC,QAAQ,EAAE,OAAO,KAAK,IAAI,CAAC;IAChD,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,gBAAgB,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAC3C,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,eAAe,CAAC,EAAE,KAAK,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAC3D;AAWD,eAAO,MAAM,cAAc,0LAexB,mBAAmB,sBAoIrB,CAAC"}
@@ -21,7 +21,8 @@ interface PrismPlayerControlsProps {
21
21
  label: string;
22
22
  value: string;
23
23
  }>;
24
+ onEmbedCodeChange?: (code: string) => void;
24
25
  }
25
- export declare const PrismPlayerControls: ({ video, players, playerListForSelection, selectedPlayer, onPlayerChange, embedProperties, setEmbedProperties, showDVR, onDVRClick, dvrTime, showLowLatency, onLowLatencyClick, adConfigValue, onAdConfigChange, ssai, adConfigOptions, }: PrismPlayerControlsProps) => React.JSX.Element;
26
+ export declare const PrismPlayerControls: ({ video, players, playerListForSelection, selectedPlayer, onPlayerChange, embedProperties, setEmbedProperties, showDVR, onDVRClick, dvrTime, showLowLatency, onLowLatencyClick, adConfigValue, onAdConfigChange, ssai, adConfigOptions, onEmbedCodeChange, }: PrismPlayerControlsProps) => React.JSX.Element;
26
27
  export {};
27
28
  //# sourceMappingURL=PrismPlayerControls.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"PrismPlayerControls.d.ts","sourceRoot":"","sources":["../../../../../src/js/components/prism/PrismPlayerControls.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAyC,MAAM,OAAO,CAAC;AAU9D,OAAO,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACnE,OAAO,EACL,WAAW,EAEX,mBAAmB,EACpB,MAAM,8BAA8B,CAAC;AAUtC,UAAU,wBAAwB;IAChC,KAAK,EAAE,WAAW,CAAC;IACnB,OAAO,EAAE,aAAa,CAAC;IACvB,sBAAsB,EAAE,gBAAgB,EAAE,CAAC;IAC3C,cAAc,EAAE,MAAM,CAAC;IACvB,cAAc,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;IAC3C,eAAe,EAAE,mBAAmB,CAAC;IACrC,kBAAkB,EAAE,CAAC,KAAK,EAAE,mBAAmB,KAAK,IAAI,CAAC;IACzD,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,UAAU,CAAC,EAAE,CAAC,QAAQ,EAAE,OAAO,KAAK,IAAI,CAAC;IACzC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,iBAAiB,CAAC,EAAE,CAAC,QAAQ,EAAE,OAAO,KAAK,IAAI,CAAC;IAChD,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,gBAAgB,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAC3C,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,eAAe,CAAC,EAAE,KAAK,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAC3D;AAED,eAAO,MAAM,mBAAmB,8OAiB7B,wBAAwB,sBAyR1B,CAAC"}
1
+ {"version":3,"file":"PrismPlayerControls.d.ts","sourceRoot":"","sources":["../../../../../src/js/components/prism/PrismPlayerControls.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAoD,MAAM,OAAO,CAAC;AAUzE,OAAO,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACnE,OAAO,EACL,WAAW,EAEX,mBAAmB,EACpB,MAAM,8BAA8B,CAAC;AAUtC,UAAU,wBAAwB;IAChC,KAAK,EAAE,WAAW,CAAC;IACnB,OAAO,EAAE,aAAa,CAAC;IACvB,sBAAsB,EAAE,gBAAgB,EAAE,CAAC;IAC3C,cAAc,EAAE,MAAM,CAAC;IACvB,cAAc,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;IAC3C,eAAe,EAAE,mBAAmB,CAAC;IACrC,kBAAkB,EAAE,CAAC,KAAK,EAAE,mBAAmB,KAAK,IAAI,CAAC;IACzD,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,UAAU,CAAC,EAAE,CAAC,QAAQ,EAAE,OAAO,KAAK,IAAI,CAAC;IACzC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,iBAAiB,CAAC,EAAE,CAAC,QAAQ,EAAE,OAAO,KAAK,IAAI,CAAC;IAChD,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,gBAAgB,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAC3C,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,eAAe,CAAC,EAAE,KAAK,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC1D,iBAAiB,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CAC5C;AAED,eAAO,MAAM,mBAAmB,iQAkB7B,wBAAwB,sBAoS1B,CAAC"}
@@ -6,7 +6,8 @@ interface PrismPlayerPreviewProps {
6
6
  previewUrl: string;
7
7
  livePlaybackToken?: string;
8
8
  adConfigId?: string;
9
+ isMobile?: boolean;
9
10
  }
10
- export declare const PrismPlayerPreview: ({ accountId, playerId, videoId, previewUrl, }: PrismPlayerPreviewProps) => React.JSX.Element;
11
+ export declare const PrismPlayerPreview: ({ accountId, playerId, videoId, previewUrl, isMobile, }: PrismPlayerPreviewProps) => React.JSX.Element;
11
12
  export {};
12
13
  //# sourceMappingURL=PrismPlayerPreview.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"PrismPlayerPreview.d.ts","sourceRoot":"","sources":["../../../../../src/js/components/prism/PrismPlayerPreview.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA4D,MAAM,OAAO,CAAC;AAUjF,UAAU,uBAAuB;IAC/B,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,eAAO,MAAM,kBAAkB,kDAK5B,uBAAuB,sBAmKzB,CAAC"}
1
+ {"version":3,"file":"PrismPlayerPreview.d.ts","sourceRoot":"","sources":["../../../../../src/js/components/prism/PrismPlayerPreview.tsx"],"names":[],"mappings":"AAAA,OAAO,KAMN,MAAM,OAAO,CAAC;AAUf,UAAU,uBAAuB;IAC/B,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,eAAO,MAAM,kBAAkB,4DAM5B,uBAAuB,sBAuKzB,CAAC"}
@@ -0,0 +1,3 @@
1
+ declare const useIsMobile: () => boolean;
2
+ export default useIsMobile;
3
+ //# sourceMappingURL=useIsMobile.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useIsMobile.d.ts","sourceRoot":"","sources":["../../../../src/js/hooks/useIsMobile.ts"],"names":[],"mappings":"AASA,QAAA,MAAM,WAAW,QAAO,OAqBvB,CAAC;AAEF,eAAe,WAAW,CAAC"}
@@ -22,6 +22,10 @@ export declare const resources: {
22
22
  bcMapTrackingTextWarning: string;
23
23
  };
24
24
  done: string;
25
+ urlShort: string;
26
+ previewShort: string;
27
+ copyCode: string;
28
+ codeCopied: string;
25
29
  close: string;
26
30
  toasterTitle: string;
27
31
  toasterMessage: string;
@@ -95,6 +99,10 @@ export declare const resources: {
95
99
  toasterErrorMessage: string;
96
100
  customPluginNotice: string;
97
101
  done: string;
102
+ urlShort: string;
103
+ previewShort: string;
104
+ copyCode: string;
105
+ codeCopied: string;
98
106
  close: string;
99
107
  noPlayerModalHeader: string;
100
108
  noPlayerModalContent1: string;
@@ -162,6 +170,10 @@ export declare const resources: {
162
170
  toasterErrorMessage: string;
163
171
  customPluginNotice: string;
164
172
  done: string;
173
+ urlShort: string;
174
+ previewShort: string;
175
+ copyCode: string;
176
+ codeCopied: string;
165
177
  close: string;
166
178
  noPlayerModalHeader: string;
167
179
  noPlayerModalContent1: string;
@@ -229,6 +241,10 @@ export declare const resources: {
229
241
  toasterErrorMessage: string;
230
242
  customPluginNotice: string;
231
243
  done: string;
244
+ urlShort: string;
245
+ previewShort: string;
246
+ copyCode: string;
247
+ codeCopied: string;
232
248
  close: string;
233
249
  noPlayerModalHeader: string;
234
250
  noPlayerModalContent1: string;
@@ -296,6 +312,10 @@ export declare const resources: {
296
312
  toasterErrorMessage: string;
297
313
  customPluginNotice: string;
298
314
  done: string;
315
+ urlShort: string;
316
+ previewShort: string;
317
+ copyCode: string;
318
+ codeCopied: string;
299
319
  close: string;
300
320
  noPlayerModalHeader: string;
301
321
  noPlayerModalContent1: string;
@@ -363,6 +383,10 @@ export declare const resources: {
363
383
  toasterErrorMessage: string;
364
384
  customPluginNotice: string;
365
385
  done: string;
386
+ urlShort: string;
387
+ previewShort: string;
388
+ copyCode: string;
389
+ codeCopied: string;
366
390
  close: string;
367
391
  noPlayerModalHeader: string;
368
392
  noPlayerModalContent1: string;
@@ -1 +1 @@
1
- {"version":3,"file":"i18n.d.ts","sourceRoot":"","sources":["../../../src/js/i18n.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,SAAS,CAAC;AAU3B,eAAO,MAAM,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAmBrB,CAAC;AAaF,eAAe,IAAI,CAAC"}
1
+ {"version":3,"file":"i18n.d.ts","sourceRoot":"","sources":["../../../src/js/i18n.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,SAAS,CAAC;AAU3B,eAAO,MAAM,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAmBrB,CAAC;AAaF,eAAe,IAAI,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@brightcove/components-embed-code-modal",
3
- "version": "1.1.1",
3
+ "version": "1.1.3",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "https://bithub.brightcove.com/studio-ui-kit/studio-components-embed-code-modal.git"
@@ -45,7 +45,7 @@
45
45
  "@brightcove/kacl": "^0.1.11",
46
46
  "@brightcove/notify-change": "^0.1.7",
47
47
  "@brightcove/player-embed-code": "^2.0.4",
48
- "@brightcove/prism-core": "^1.64.0",
48
+ "@brightcove/prism-core": "^1.174.0",
49
49
  "@brightcove/react-player-loader": "^1.4.2",
50
50
  "@brightcove/studio-api-services": "^7.0.0",
51
51
  "@brightcove/studio-components": "^7.23.4",
@@ -280,7 +280,7 @@ export const VideoPlayer = ({
280
280
  <TabsSection {...sharedProps} embedCodeProperties={embedProperties} />
281
281
  {showLowLatency ? (
282
282
  <Checkbox
283
- disabled={showDVR && allowDVR}
283
+ disabled={false}
284
284
  checked={allowLowLatency}
285
285
  onChange={() => {
286
286
  onLowLatencyClick?.(!allowLowLatency);
@@ -295,7 +295,7 @@ export const VideoPlayer = ({
295
295
  {showDVR && (
296
296
  <div>
297
297
  <Checkbox
298
- disabled={showLowLatency && allowLowLatency}
298
+ disabled={false}
299
299
  checked={allowDVR}
300
300
  onChange={() => {
301
301
  onDVRClick?.(!allowDVR);
@@ -1,4 +1,4 @@
1
- import React, { useState, useEffect } from 'react';
1
+ import React, { useState, useEffect, useCallback } from 'react';
2
2
  import { PrismModal } from '@brightcove/prism-core';
3
3
  import { useTranslation } from 'react-i18next';
4
4
  import { PlayerSelectItem, PlayersObject } from 'js/types/players';
@@ -8,8 +8,13 @@ import {
8
8
  EmbedCodeAspectRatio,
9
9
  EmbedCodeUnits,
10
10
  } from 'js/types/EmbedCodeModalProps';
11
- import { getVideoPreviewLink, VideoPreviewLinkOptions } from 'js/utils/util';
11
+ import {
12
+ getBrightcove,
13
+ getVideoPreviewLink,
14
+ VideoPreviewLinkOptions,
15
+ } from 'js/utils/util';
12
16
  import { getFavoritePlayer } from 'js/utils/featureSwitches';
17
+ import useIsMobile from 'js/hooks/useIsMobile';
13
18
  import { PrismPlayerControls } from './PrismPlayerControls';
14
19
  import { PrismPlayerPreview } from './PrismPlayerPreview';
15
20
 
@@ -58,12 +63,14 @@ export const PrismLiveModal = ({
58
63
  adConfigOptions,
59
64
  }: PrismLiveModalProps) => {
60
65
  const { t } = useTranslation();
66
+ const isMobile = useIsMobile();
61
67
  const [selectedPlayer, setSelectedPlayer] =
62
68
  useState<string>(DEFAULT_PLAYER_ID);
63
69
  const [embedProperties, setEmbedProperties] = useState<EmbedCodeProperties>(
64
70
  DEFAULT_EMBED_PROPERTIES,
65
71
  );
66
72
  const [previewUrl, setPreviewUrl] = useState<string>('');
73
+ const [embedCode, setEmbedCode] = useState<string>('');
67
74
 
68
75
  // Initialize selected player
69
76
  useEffect(() => {
@@ -114,15 +121,40 @@ export const PrismLiveModal = ({
114
121
  setSelectedPlayer(playerId);
115
122
  };
116
123
 
124
+ const handleCopyEmbedCode = useCallback(async () => {
125
+ if (!embedCode) {
126
+ return;
127
+ }
128
+ try {
129
+ await navigator.clipboard.writeText(embedCode);
130
+ getBrightcove().Toaster.success({
131
+ message: t('codeCopied') as string,
132
+ });
133
+ } catch {
134
+ getBrightcove().Toaster.error({
135
+ message: t('toasterErrorMessage') as string,
136
+ });
137
+ }
138
+ }, [embedCode, t]);
139
+
117
140
  return (
118
141
  <PrismModal
119
142
  isOpen={isOpen}
120
143
  onClose={onClose}
121
144
  title={(t('modalHeader') as string) || 'Publish Video'}
122
- onPrimaryAction={onClose}
123
- primaryButtonText={t('done') as string}
124
- cancelButtonText={t('cancel') as string}
125
- className={css.prismLiveModal}
145
+ bottomSheet={isMobile}
146
+ size='extraLarge'
147
+ forceMaxHeight
148
+ contentScroll={isMobile ? 'auto' : 'none'}
149
+ showHeaderBottomBorder
150
+ onPrimaryAction={isMobile ? handleCopyEmbedCode : onClose}
151
+ primaryButtonText={
152
+ isMobile ? (t('copyCode') as string) : (t('done') as string)
153
+ }
154
+ onSecondaryAction={onClose}
155
+ cancelButtonText={
156
+ isMobile ? (t('done') as string) : (t('cancel') as string)
157
+ }
126
158
  >
127
159
  <div className={css.prismLiveModalContent}>
128
160
  {/* Left Column: Player Controls */}
@@ -143,6 +175,7 @@ export const PrismLiveModal = ({
143
175
  onAdConfigChange={onAdConfigChange}
144
176
  ssai={ssai}
145
177
  adConfigOptions={adConfigOptions}
178
+ onEmbedCodeChange={setEmbedCode}
146
179
  />
147
180
 
148
181
  {/* Right Column: Player Preview */}
@@ -154,6 +187,7 @@ export const PrismLiveModal = ({
154
187
  previewUrl={previewUrl}
155
188
  livePlaybackToken={video.livePlaybackToken}
156
189
  adConfigId={adConfigValue || video.adConfigId}
190
+ isMobile={isMobile}
157
191
  />
158
192
  </div>
159
193
  </div>
@@ -1,4 +1,4 @@
1
- import React, { useState, useCallback, useMemo } from 'react';
1
+ import React, { useState, useCallback, useEffect, useMemo } from 'react';
2
2
  import {
3
3
  PrismDropDown,
4
4
  PrismInput,
@@ -40,6 +40,7 @@ interface PrismPlayerControlsProps {
40
40
  onAdConfigChange?: (value: string) => void;
41
41
  ssai?: boolean;
42
42
  adConfigOptions?: Array<{ label: string; value: string }>;
43
+ onEmbedCodeChange?: (code: string) => void;
43
44
  }
44
45
 
45
46
  export const PrismPlayerControls = ({
@@ -59,6 +60,7 @@ export const PrismPlayerControls = ({
59
60
  onAdConfigChange,
60
61
  ssai,
61
62
  adConfigOptions = [],
63
+ onEmbedCodeChange,
62
64
  }: PrismPlayerControlsProps) => {
63
65
  const { t } = useTranslation();
64
66
  const [prevAspectRatio, setPrevAspectRatio] = useState(
@@ -161,6 +163,16 @@ export const PrismPlayerControls = ({
161
163
  adConfigId: adConfigValue || video.adConfigId,
162
164
  });
163
165
 
166
+ const requiresJsEmbed = Boolean(
167
+ player?.hasCampaignPlugin ||
168
+ player?.hasViewerIDSource ||
169
+ player?.hasBcMapTracking,
170
+ );
171
+
172
+ useEffect(() => {
173
+ onEmbedCodeChange?.(requiresJsEmbed ? embedCodeJS : embedCode);
174
+ }, [embedCode, embedCodeJS, requiresJsEmbed, onEmbedCodeChange]);
175
+
164
176
  const codeCardTabs = useMemo(
165
177
  () => [
166
178
  {
@@ -189,14 +201,8 @@ export const PrismPlayerControls = ({
189
201
  if (onDVRClick) {
190
202
  onDVRClick(checked);
191
203
  }
192
- if (checked && lowLatencyEnabled) {
193
- setLowLatencyEnabled(false);
194
- if (onLowLatencyClick) {
195
- onLowLatencyClick(false);
196
- }
197
- }
198
204
  },
199
- [lowLatencyEnabled, onDVRClick, onLowLatencyClick],
205
+ [onDVRClick],
200
206
  );
201
207
 
202
208
  const handleLowLatencyChange = useCallback(
@@ -205,14 +211,8 @@ export const PrismPlayerControls = ({
205
211
  if (onLowLatencyClick) {
206
212
  onLowLatencyClick(checked);
207
213
  }
208
- if (checked && dvrEnabled) {
209
- setDvrEnabled(false);
210
- if (onDVRClick) {
211
- onDVRClick(false);
212
- }
213
- }
214
214
  },
215
- [dvrEnabled, onDVRClick, onLowLatencyClick],
215
+ [onLowLatencyClick],
216
216
  );
217
217
 
218
218
  return (
@@ -247,17 +247,22 @@ export const PrismPlayerControls = ({
247
247
 
248
248
  {/* Width/Height Input Group */}
249
249
  <div className={css.prismInputGroup}>
250
- <PrismInput
251
- variant='FieldGroup'
252
- label={(t('customSettings.playerWidth') as string) || 'Player Width'}
253
- type='number'
254
- value={String(embedProperties.width)}
255
- onChange={(value) => handlePropertiesUpdate('width', Number(value))}
256
- groupTitle='Unit'
257
- groupValue={embedProperties.units}
258
- onGroupChange={(unit) => handlePropertiesUpdate('units', unit)}
259
- groupOptions={['px', '%']}
260
- />
250
+ <div className={css.prismSizingField}>
251
+ <PrismInput
252
+ variant='FieldGroup'
253
+ fullWidth
254
+ label={
255
+ (t('customSettings.playerWidth') as string) || 'Player Width'
256
+ }
257
+ type='number'
258
+ value={String(embedProperties.width)}
259
+ onChange={(value) => handlePropertiesUpdate('width', Number(value))}
260
+ groupTitle='Unit'
261
+ groupValue={embedProperties.units}
262
+ onGroupChange={(unit) => handlePropertiesUpdate('units', unit)}
263
+ groupOptions={['px', '%']}
264
+ />
265
+ </div>
261
266
 
262
267
  <PrismIconButton
263
268
  icon='link'
@@ -268,20 +273,25 @@ export const PrismPlayerControls = ({
268
273
  className={css.prismLinkButton}
269
274
  />
270
275
 
271
- <PrismInput
272
- variant='FieldGroup'
273
- label={
274
- (t('customSettings.playerHeight') as string) || 'Player Height'
275
- }
276
- type='number'
277
- value={String(embedProperties.height)}
278
- onChange={(value) => handlePropertiesUpdate('height', Number(value))}
279
- disabled={aspectRatioLocked}
280
- groupTitle='Unit'
281
- groupValue={embedProperties.units}
282
- onGroupChange={(unit) => handlePropertiesUpdate('units', unit)}
283
- groupOptions={['px', '%']}
284
- />
276
+ <div className={css.prismSizingField}>
277
+ <PrismInput
278
+ variant='FieldGroup'
279
+ fullWidth
280
+ label={
281
+ (t('customSettings.playerHeight') as string) || 'Player Height'
282
+ }
283
+ type='number'
284
+ value={String(embedProperties.height)}
285
+ onChange={(value) =>
286
+ handlePropertiesUpdate('height', Number(value))
287
+ }
288
+ disabled={aspectRatioLocked}
289
+ groupTitle='Unit'
290
+ groupValue={embedProperties.units}
291
+ onGroupChange={(unit) => handlePropertiesUpdate('units', unit)}
292
+ groupOptions={['px', '%']}
293
+ />
294
+ </div>
285
295
  </div>
286
296
 
287
297
  {/* DVR Checkbox (conditional) */}
@@ -291,12 +301,13 @@ export const PrismPlayerControls = ({
291
301
  label={(t('dvr.allowDVR') as string) || 'Enable DVR'}
292
302
  checked={dvrEnabled}
293
303
  onChange={(e) => handleDVRChange(e.target.checked)}
294
- disabled={showLowLatency && lowLatencyEnabled}
304
+ disabled={false}
295
305
  />
296
306
  {dvrEnabled && typeof dvrTime === 'number' && (
297
307
  <div className={css.prismInputGroup}>
298
308
  <PrismInput
299
309
  variant='FieldGroup'
310
+ fullWidth
300
311
  label={(t('dvr.inputLabel') as string) || 'DVR Window'}
301
312
  type='number'
302
313
  value={String(dvrTime)}
@@ -316,7 +327,7 @@ export const PrismPlayerControls = ({
316
327
  label={(t('lowLatency') as string) || 'Enable Low Latency'}
317
328
  checked={lowLatencyEnabled}
318
329
  onChange={(e) => handleLowLatencyChange(e.target.checked)}
319
- disabled={showDVR && dvrEnabled}
330
+ disabled={false}
320
331
  />
321
332
  )}
322
333
 
@@ -337,7 +348,9 @@ export const PrismPlayerControls = ({
337
348
  <div className={css.prismCustomPluginNotice}>{warningMessage}</div>
338
349
  )}
339
350
 
340
- <PrismCodeCard className={css.prismCodeCard} tabs={codeCardTabs} />
351
+ <div className={css.prismCodeCard}>
352
+ <PrismCodeCard indefiniteGrow tabs={codeCardTabs} />
353
+ </div>
341
354
  </div>
342
355
  );
343
356
  };
@@ -1,4 +1,10 @@
1
- import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
1
+ import React, {
2
+ useCallback,
3
+ useEffect,
4
+ useMemo,
5
+ useRef,
6
+ useState,
7
+ } from 'react';
2
8
  import ReactPlayerLoader from '@brightcove/react-player-loader';
3
9
  import { PrismButton, PrismButtonDropdown } from '@brightcove/prism-core';
4
10
  import { getBrightcove, getUrlBase } from 'js/utils/util';
@@ -15,6 +21,7 @@ interface PrismPlayerPreviewProps {
15
21
  previewUrl: string;
16
22
  livePlaybackToken?: string;
17
23
  adConfigId?: string;
24
+ isMobile?: boolean;
18
25
  }
19
26
 
20
27
  export const PrismPlayerPreview = ({
@@ -22,6 +29,7 @@ export const PrismPlayerPreview = ({
22
29
  playerId,
23
30
  videoId,
24
31
  previewUrl,
32
+ isMobile,
25
33
  }: PrismPlayerPreviewProps) => {
26
34
  const { t } = useTranslation();
27
35
  const [isShorteningUrl, setIsShorteningUrl] = useState<boolean>(false);
@@ -127,7 +135,9 @@ export const PrismPlayerPreview = ({
127
135
  if (isShorteningUrl) {
128
136
  return t('prism.copying') as string;
129
137
  }
130
- return t('prism.copyURL') as string;
138
+ return isMobile
139
+ ? (t('urlShort') as string)
140
+ : (t('prism.copyURL') as string);
131
141
  };
132
142
 
133
143
  const handleOpenPreview = useCallback(() => {
@@ -152,8 +162,8 @@ export const PrismPlayerPreview = ({
152
162
  <div className={css.prismPlayerPreviewContainer}>
153
163
  <div className={css.prismPlayerActions}>
154
164
  <PrismButtonDropdown
155
- variant='Primary'
156
- size='small'
165
+ variant={isMobile ? 'Secondary' : 'Primary'}
166
+ {...(isMobile ? { size: 'mobile' as const, fullWidth: true } : {})}
157
167
  options={copyUrlOptions}
158
168
  modalTitle={t('prism.copyURL') as string}
159
169
  showDropdownIcon={!isCopied && !isShorteningUrl}
@@ -163,13 +173,15 @@ export const PrismPlayerPreview = ({
163
173
  {copyUrlLabel()}
164
174
  </PrismButtonDropdown>
165
175
  <PrismButton
166
- variant='Primary'
167
- size='small'
176
+ variant={isMobile ? 'Secondary' : 'Primary'}
177
+ {...(isMobile ? { size: 'mobile' as const, fullWidth: true } : {})}
168
178
  onClick={handleOpenPreview}
169
179
  rightIcon='link'
170
180
  disabled={!previewUrl}
171
181
  >
172
- {t('previewButton') as string}
182
+ {isMobile
183
+ ? (t('previewShort') as string)
184
+ : (t('previewButton') as string)}
173
185
  </PrismButton>
174
186
  </div>
175
187
 
@@ -0,0 +1,33 @@
1
+ import { useEffect, useState } from 'react';
2
+
3
+ const MOBILE_MEDIA_QUERY = '(max-width: 1023px)';
4
+
5
+ const getMatches = (): boolean =>
6
+ typeof window !== 'undefined' && typeof window.matchMedia === 'function'
7
+ ? window.matchMedia(MOBILE_MEDIA_QUERY).matches
8
+ : false;
9
+
10
+ const useIsMobile = (): boolean => {
11
+ const [isMobile, setIsMobile] = useState<boolean>(getMatches);
12
+
13
+ useEffect(() => {
14
+ if (
15
+ typeof window === 'undefined' ||
16
+ typeof window.matchMedia !== 'function'
17
+ ) {
18
+ return;
19
+ }
20
+
21
+ const mql = window.matchMedia(MOBILE_MEDIA_QUERY);
22
+ const handleChange = (event: MediaQueryListEvent) =>
23
+ setIsMobile(event.matches);
24
+
25
+ setIsMobile(mql.matches);
26
+ mql.addEventListener('change', handleChange);
27
+ return () => mql.removeEventListener('change', handleChange);
28
+ }, []);
29
+
30
+ return isMobile;
31
+ };
32
+
33
+ export default useIsMobile;