@brightcove/components-embed-code-modal 1.1.2 → 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 (196) hide show
  1. package/.eslintignore +7 -0
  2. package/.eslintrc +23 -0
  3. package/.github/workflows/ci.yml +23 -0
  4. package/.husky/pre-commit +4 -0
  5. package/.nvmrc +1 -0
  6. package/.prettierignore +7 -0
  7. package/.prettierrc +5 -0
  8. package/.release-it.json +40 -0
  9. package/.whitesource +3 -0
  10. package/CHANGELOG.md +423 -0
  11. package/CODEOWNERS +37 -0
  12. package/PULL_REQUEST_TEMPLATE.md +17 -0
  13. package/__tests__/EmbedCode.test.tsx +51 -0
  14. package/__tests__/InteractivityProject.test.tsx +50 -0
  15. package/__tests__/PlayerPreview.test.tsx +23 -0
  16. package/__tests__/PrismLiveModal.test.tsx +85 -0
  17. package/__tests__/PrismPlayerControls.test.tsx +139 -0
  18. package/__tests__/PrismPlayerPreview.test.tsx +168 -0
  19. package/__tests__/TabsHeader.test.tsx +19 -0
  20. package/__tests__/TabsSection.test.tsx +46 -0
  21. package/__tests__/TitleWithTooltip.test.tsx +45 -0
  22. package/__tests__/VideoPlayer.test.tsx +105 -0
  23. package/__tests__/embedCodeGenerator.test.ts +111 -0
  24. package/__tests__/util.test.ts +89 -0
  25. package/babel.config.json +17 -0
  26. package/build/README.md +109 -0
  27. package/build/__tests__/PrismLiveModal.test.d.ts +2 -0
  28. package/build/__tests__/PrismLiveModal.test.d.ts.map +1 -0
  29. package/build/index.js +9 -0
  30. package/build/index.js.map +1 -0
  31. package/build/package.json +100 -0
  32. package/{src → build/src}/js/components/prism/PrismLiveModal.d.ts.map +1 -1
  33. package/{src → build/src}/js/components/prism/PrismPlayerControls.d.ts +2 -1
  34. package/{src → build/src}/js/components/prism/PrismPlayerControls.d.ts.map +1 -1
  35. package/{src → build/src}/js/components/prism/PrismPlayerPreview.d.ts +2 -1
  36. package/build/src/js/components/prism/PrismPlayerPreview.d.ts.map +1 -0
  37. package/build/src/js/hooks/useIsMobile.d.ts +3 -0
  38. package/build/src/js/hooks/useIsMobile.d.ts.map +1 -0
  39. package/{src → build/src}/js/i18n.d.ts +24 -0
  40. package/{src → build/src}/js/i18n.d.ts.map +1 -1
  41. package/etc/wildcard.brightcove.com.key +27 -0
  42. package/etc/wildcard.brightcove.com.pem +96 -0
  43. package/jest/jest.setup.js +90 -0
  44. package/jest/jest.stub.js +4 -0
  45. package/jest.config.js +24 -0
  46. package/package.json +17 -7
  47. package/scripts/create-dist-pkg-prod.js +19 -0
  48. package/src/index.ts +17 -0
  49. package/src/js/EmbedCodeModal.tsx +105 -0
  50. package/src/js/components/CustomSettingsDropdown.tsx +184 -0
  51. package/src/js/components/EmbedCopySection.tsx +130 -0
  52. package/src/js/components/ModalContainer.tsx +367 -0
  53. package/src/js/components/NoPlayerModal.tsx +42 -0
  54. package/src/js/components/PlayerPreview.tsx +116 -0
  55. package/src/js/components/TabsHeader.tsx +31 -0
  56. package/src/js/components/TabsSection.tsx +74 -0
  57. package/src/js/components/TitleWithTooltip.tsx +39 -0
  58. package/src/js/components/VideoLinks.tsx +83 -0
  59. package/src/js/components/VideoPlayer.tsx +324 -0
  60. package/src/js/components/index.ts +9 -0
  61. package/src/js/components/prism/PrismLiveModal.tsx +196 -0
  62. package/src/js/components/prism/PrismPlayerControls.tsx +356 -0
  63. package/src/js/components/prism/PrismPlayerPreview.tsx +200 -0
  64. package/src/js/components/prism/index.ts +3 -0
  65. package/src/js/constants/baseUrls.ts +4 -0
  66. package/src/js/constants/embed.ts +12 -0
  67. package/src/js/constants/player.ts +32 -0
  68. package/src/js/constants/pluginsRegistry.ts +30 -0
  69. package/src/js/hooks/useGetPlayers.ts +12 -0
  70. package/src/js/hooks/useIsMobile.ts +33 -0
  71. package/src/js/i18n.ts +43 -0
  72. package/src/js/services/players-api.ts +26 -0
  73. package/src/js/services/url-shortener.ts +10 -0
  74. package/src/js/types/EmbedCodeModalProps.ts +72 -0
  75. package/src/js/types/EmbedCodeProps.ts +13 -0
  76. package/src/js/types/brightcoveEmbedCode.d.ts +18 -0
  77. package/src/js/types/players.ts +64 -0
  78. package/src/js/types/react-i18next.d.ts +8 -0
  79. package/src/js/types/studioModule.ts +7 -0
  80. package/src/js/utils/addPluginsDataToPlayers.ts +59 -0
  81. package/src/js/utils/call.ts +31 -0
  82. package/src/js/utils/dimensions.ts +53 -0
  83. package/src/js/utils/embedCodeGenerator.ts +120 -0
  84. package/src/js/utils/featureSwitches.ts +16 -0
  85. package/src/js/utils/util.ts +153 -0
  86. package/src/module.tsx +280 -0
  87. package/src/styles/CustomSettingsDropdown.sass +42 -0
  88. package/src/styles/EmbedCode.sass +30 -0
  89. package/src/styles/EmbedCodeModal.sass +76 -0
  90. package/src/styles/base.sass +1 -0
  91. package/src/styles/prism/PrismLiveModal.sass +128 -0
  92. package/src/styles/theme.sass +11 -0
  93. package/src/styles/typings.td.ts +9 -0
  94. package/src/translations/en.json +69 -0
  95. package/src/translations/es.json +69 -0
  96. package/src/translations/fr.json +69 -0
  97. package/src/translations/ja.json +69 -0
  98. package/src/translations/ko.json +69 -0
  99. package/src/translations/zh.json +69 -0
  100. package/src/types/studio.ts +197 -0
  101. package/tsconfig.json +34 -0
  102. package/webpack.config.js +117 -0
  103. package/index.js +0 -9
  104. package/index.js.map +0 -1
  105. package/src/js/components/prism/PrismPlayerPreview.d.ts.map +0 -1
  106. /package/{__tests__ → build/__tests__}/EmbedCode.test.d.ts +0 -0
  107. /package/{__tests__ → build/__tests__}/EmbedCode.test.d.ts.map +0 -0
  108. /package/{__tests__ → build/__tests__}/InteractivityProject.test.d.ts +0 -0
  109. /package/{__tests__ → build/__tests__}/InteractivityProject.test.d.ts.map +0 -0
  110. /package/{__tests__ → build/__tests__}/PlayerPreview.test.d.ts +0 -0
  111. /package/{__tests__ → build/__tests__}/PlayerPreview.test.d.ts.map +0 -0
  112. /package/{__tests__ → build/__tests__}/PrismPlayerControls.test.d.ts +0 -0
  113. /package/{__tests__ → build/__tests__}/PrismPlayerControls.test.d.ts.map +0 -0
  114. /package/{__tests__ → build/__tests__}/PrismPlayerPreview.test.d.ts +0 -0
  115. /package/{__tests__ → build/__tests__}/PrismPlayerPreview.test.d.ts.map +0 -0
  116. /package/{__tests__ → build/__tests__}/TabsHeader.test.d.ts +0 -0
  117. /package/{__tests__ → build/__tests__}/TabsHeader.test.d.ts.map +0 -0
  118. /package/{__tests__ → build/__tests__}/TabsSection.test.d.ts +0 -0
  119. /package/{__tests__ → build/__tests__}/TabsSection.test.d.ts.map +0 -0
  120. /package/{__tests__ → build/__tests__}/TitleWithTooltip.test.d.ts +0 -0
  121. /package/{__tests__ → build/__tests__}/TitleWithTooltip.test.d.ts.map +0 -0
  122. /package/{__tests__ → build/__tests__}/VideoPlayer.test.d.ts +0 -0
  123. /package/{__tests__ → build/__tests__}/VideoPlayer.test.d.ts.map +0 -0
  124. /package/{__tests__ → build/__tests__}/embedCodeGenerator.test.d.ts +0 -0
  125. /package/{__tests__ → build/__tests__}/embedCodeGenerator.test.d.ts.map +0 -0
  126. /package/{__tests__ → build/__tests__}/util.test.d.ts +0 -0
  127. /package/{__tests__ → build/__tests__}/util.test.d.ts.map +0 -0
  128. /package/{src → build/src}/index.d.ts +0 -0
  129. /package/{src → build/src}/index.d.ts.map +0 -0
  130. /package/{src → build/src}/js/EmbedCodeModal.d.ts +0 -0
  131. /package/{src → build/src}/js/EmbedCodeModal.d.ts.map +0 -0
  132. /package/{src → build/src}/js/components/CustomSettingsDropdown.d.ts +0 -0
  133. /package/{src → build/src}/js/components/CustomSettingsDropdown.d.ts.map +0 -0
  134. /package/{src → build/src}/js/components/EmbedCopySection.d.ts +0 -0
  135. /package/{src → build/src}/js/components/EmbedCopySection.d.ts.map +0 -0
  136. /package/{src → build/src}/js/components/ModalContainer.d.ts +0 -0
  137. /package/{src → build/src}/js/components/ModalContainer.d.ts.map +0 -0
  138. /package/{src → build/src}/js/components/NoPlayerModal.d.ts +0 -0
  139. /package/{src → build/src}/js/components/NoPlayerModal.d.ts.map +0 -0
  140. /package/{src → build/src}/js/components/PlayerPreview.d.ts +0 -0
  141. /package/{src → build/src}/js/components/PlayerPreview.d.ts.map +0 -0
  142. /package/{src → build/src}/js/components/TabsHeader.d.ts +0 -0
  143. /package/{src → build/src}/js/components/TabsHeader.d.ts.map +0 -0
  144. /package/{src → build/src}/js/components/TabsSection.d.ts +0 -0
  145. /package/{src → build/src}/js/components/TabsSection.d.ts.map +0 -0
  146. /package/{src → build/src}/js/components/TitleWithTooltip.d.ts +0 -0
  147. /package/{src → build/src}/js/components/TitleWithTooltip.d.ts.map +0 -0
  148. /package/{src → build/src}/js/components/VideoLinks.d.ts +0 -0
  149. /package/{src → build/src}/js/components/VideoLinks.d.ts.map +0 -0
  150. /package/{src → build/src}/js/components/VideoPlayer.d.ts +0 -0
  151. /package/{src → build/src}/js/components/VideoPlayer.d.ts.map +0 -0
  152. /package/{src → build/src}/js/components/index.d.ts +0 -0
  153. /package/{src → build/src}/js/components/index.d.ts.map +0 -0
  154. /package/{src → build/src}/js/components/prism/PrismLiveModal.d.ts +0 -0
  155. /package/{src → build/src}/js/components/prism/index.d.ts +0 -0
  156. /package/{src → build/src}/js/components/prism/index.d.ts.map +0 -0
  157. /package/{src → build/src}/js/constants/baseUrls.d.ts +0 -0
  158. /package/{src → build/src}/js/constants/baseUrls.d.ts.map +0 -0
  159. /package/{src → build/src}/js/constants/embed.d.ts +0 -0
  160. /package/{src → build/src}/js/constants/embed.d.ts.map +0 -0
  161. /package/{src → build/src}/js/constants/player.d.ts +0 -0
  162. /package/{src → build/src}/js/constants/player.d.ts.map +0 -0
  163. /package/{src → build/src}/js/constants/pluginsRegistry.d.ts +0 -0
  164. /package/{src → build/src}/js/constants/pluginsRegistry.d.ts.map +0 -0
  165. /package/{src → build/src}/js/hooks/useGetPlayers.d.ts +0 -0
  166. /package/{src → build/src}/js/hooks/useGetPlayers.d.ts.map +0 -0
  167. /package/{src → build/src}/js/services/players-api.d.ts +0 -0
  168. /package/{src → build/src}/js/services/players-api.d.ts.map +0 -0
  169. /package/{src → build/src}/js/services/url-shortener.d.ts +0 -0
  170. /package/{src → build/src}/js/services/url-shortener.d.ts.map +0 -0
  171. /package/{src → build/src}/js/types/EmbedCodeModalProps.d.ts +0 -0
  172. /package/{src → build/src}/js/types/EmbedCodeModalProps.d.ts.map +0 -0
  173. /package/{src → build/src}/js/types/EmbedCodeProps.d.ts +0 -0
  174. /package/{src → build/src}/js/types/EmbedCodeProps.d.ts.map +0 -0
  175. /package/{src → build/src}/js/types/players.d.ts +0 -0
  176. /package/{src → build/src}/js/types/players.d.ts.map +0 -0
  177. /package/{src → build/src}/js/types/studioModule.d.ts +0 -0
  178. /package/{src → build/src}/js/types/studioModule.d.ts.map +0 -0
  179. /package/{src → build/src}/js/utils/addPluginsDataToPlayers.d.ts +0 -0
  180. /package/{src → build/src}/js/utils/addPluginsDataToPlayers.d.ts.map +0 -0
  181. /package/{src → build/src}/js/utils/call.d.ts +0 -0
  182. /package/{src → build/src}/js/utils/call.d.ts.map +0 -0
  183. /package/{src → build/src}/js/utils/dimensions.d.ts +0 -0
  184. /package/{src → build/src}/js/utils/dimensions.d.ts.map +0 -0
  185. /package/{src → build/src}/js/utils/embedCodeGenerator.d.ts +0 -0
  186. /package/{src → build/src}/js/utils/embedCodeGenerator.d.ts.map +0 -0
  187. /package/{src → build/src}/js/utils/featureSwitches.d.ts +0 -0
  188. /package/{src → build/src}/js/utils/featureSwitches.d.ts.map +0 -0
  189. /package/{src → build/src}/js/utils/util.d.ts +0 -0
  190. /package/{src → build/src}/js/utils/util.d.ts.map +0 -0
  191. /package/{src → build/src}/module.d.ts +0 -0
  192. /package/{src → build/src}/module.d.ts.map +0 -0
  193. /package/{src → build/src}/styles/typings.td.d.ts +0 -0
  194. /package/{src → build/src}/styles/typings.td.d.ts.map +0 -0
  195. /package/{src → build/src}/types/studio.d.ts +0 -0
  196. /package/{src → build/src}/types/studio.d.ts.map +0 -0
@@ -0,0 +1,153 @@
1
+ import {
2
+ QA_URL,
3
+ PROD_URL,
4
+ QA_PREVIEW_URL,
5
+ PROD_PREVIEW_URL,
6
+ } from 'js/constants/baseUrls';
7
+ import { StudioModule, StudioBrightcove } from 'types/studio';
8
+ import { PlayerSelectItem } from '../types/players';
9
+
10
+ const QA = 'qa';
11
+ const PRODUCTION = 'production';
12
+ const TITLE_CHAR_LIMIT = 60;
13
+ export const ROLES = {
14
+ PUBLISHING: 'PUBLISHING',
15
+ };
16
+ export const PREVIEW_URL_BASE = () => {
17
+ const env = getStudioEnvironment();
18
+ const envMap = {
19
+ qa: '.qa',
20
+ staging: '.staging',
21
+ production: '',
22
+ };
23
+ return `//preview-players${envMap[env]}.brightcove.net/v2/accounts`;
24
+ };
25
+
26
+ /**
27
+ * Get the studio environment as a string.
28
+ * @returns the studio environment
29
+ */
30
+ export function getStudioEnvironment(): string {
31
+ return window.StudioModule?.config.product.env || PRODUCTION;
32
+ }
33
+
34
+ /**
35
+ * Is the module running in QA environment?
36
+ */
37
+ export function isQA() {
38
+ return getStudioEnvironment() === QA;
39
+ }
40
+
41
+ /**
42
+ * Gets the correct player url base depending on environment
43
+ */
44
+ export function getUrlBase() {
45
+ return isQA() ? QA_URL : PROD_URL;
46
+ }
47
+
48
+ /**
49
+ *
50
+ * @param options : array of PlayerSelectItem
51
+ * @returns options ordered ascending
52
+ */
53
+ export function sortAsc(options: PlayerSelectItem[]): PlayerSelectItem[] {
54
+ return options.sort((a, b) => a.label.localeCompare(b.label));
55
+ }
56
+
57
+ export type VideoPreviewLinkOptions = {
58
+ accountId: string;
59
+ videoId?: string;
60
+ interactivityProjectId?: string;
61
+ playerId: string;
62
+ adConfigId?: string;
63
+ livePlaybackToken?: string;
64
+ };
65
+ /**
66
+ *
67
+ * @param accountId : accountId of current user
68
+ * @param videoId : VideoPayload type info
69
+ * @param interactivityProjectId : id of interactivity project
70
+ * @param playerId : playerId used for preview
71
+ * @returns a working preview link with given information
72
+ * @param adConfigId : token for live playback
73
+ * @param livePlaybackToken : token for live playback
74
+ */
75
+ export const getVideoPreviewLink = (options: VideoPreviewLinkOptions) => {
76
+ const {
77
+ accountId,
78
+ videoId,
79
+ interactivityProjectId,
80
+ playerId,
81
+ adConfigId,
82
+ livePlaybackToken,
83
+ } = options;
84
+ const params = new URLSearchParams();
85
+ if (interactivityProjectId) {
86
+ params.append('interactivityProjectId', interactivityProjectId);
87
+ }
88
+
89
+ if (videoId) {
90
+ params.append('videoId', videoId);
91
+ }
92
+
93
+ if (adConfigId) {
94
+ params.append('adConfigId', adConfigId);
95
+ }
96
+
97
+ if (livePlaybackToken) {
98
+ params.append('livePlaybackToken', livePlaybackToken);
99
+ }
100
+ const paramsString = params.toString();
101
+ return `${getUrlBase()}${accountId}/${playerId}_default/index.html${
102
+ paramsString !== '' ? `?${paramsString}` : ''
103
+ }`;
104
+ };
105
+
106
+ /**
107
+ * Truncates a video title property
108
+ * @param videoName - video title
109
+ * @returns truncated video title
110
+ */
111
+ export const truncateVideoTitle = (videoName: string): string => {
112
+ if (videoName.length > TITLE_CHAR_LIMIT) {
113
+ return `${videoName.substring(0, TITLE_CHAR_LIMIT).trim()}...`;
114
+ }
115
+ return videoName;
116
+ };
117
+
118
+ export function getPreviewUrlBase() {
119
+ return isQA() ? QA_PREVIEW_URL : PROD_PREVIEW_URL;
120
+ }
121
+
122
+ /**
123
+ *
124
+ * @param accountId : account id of current user
125
+ * @param playerId : playerId used for preview
126
+ * @returns a working preview url with given information
127
+ */
128
+ export const getPreviewPlayerUrl = (
129
+ accountId: string,
130
+ playerId: string,
131
+ ): string =>
132
+ `${getPreviewUrlBase()}/v2/accounts/${accountId}/players/${playerId}/preview/embeds/default/master/index.html`;
133
+
134
+ export const getStudioModule = (): StudioModule => window.StudioModule;
135
+
136
+ export const getBrightcove = (): StudioBrightcove => window.brightcove;
137
+
138
+ export function getProductPath(): string {
139
+ return getStudioModule()?.config?.product?.path || '/products/videocloud';
140
+ }
141
+
142
+ /**
143
+ * @returns Player Manager Module URL
144
+ */
145
+ export const getPlayerManagerModuleUrl = () => {
146
+ return `${getProductPath()}/players`;
147
+ };
148
+
149
+ export const decodeHtmlEntities = (str: string) => {
150
+ const textarea = document.createElement('textarea');
151
+ textarea.innerHTML = str;
152
+ return textarea.value;
153
+ };
package/src/module.tsx ADDED
@@ -0,0 +1,280 @@
1
+ import React, { useState } from 'react';
2
+ import { createRoot } from 'react-dom/client';
3
+
4
+ import {
5
+ initialize,
6
+ Button,
7
+ Select,
8
+ Input,
9
+ Flex,
10
+ Checkbox,
11
+ } from '@brightcove/studio-components';
12
+
13
+ import { StudioModule } from 'types/studio';
14
+ import { EmbedCodeModal } from './index';
15
+ import {
16
+ VideoPayload,
17
+ EmbedCodeModalTypes,
18
+ EmbedCodeUnits,
19
+ EmbedCodeAspectRatio,
20
+ } from 'js/types/EmbedCodeModalProps';
21
+ import { EmbedCodeModalProps } from 'js/EmbedCodeModal';
22
+
23
+ const videoObj: VideoPayload = {
24
+ videoId: '70709819045202', // string
25
+ videoName: 'Media Title', // string
26
+ accountId: '70712710456202', // string
27
+ posterUrl: 'http://...', // string
28
+ duration: 120, // number (in seconds)
29
+ };
30
+
31
+ type LangType = 'en' | 'es' | 'fr' | 'ja' | 'ko' | 'zh';
32
+ type ThemeType = 'blueSteel' | 'prism';
33
+
34
+ const appNode = document.getElementById('bc-content');
35
+ let root: ReturnType<typeof createRoot> | null = null;
36
+
37
+ const App = () => {
38
+ const [language, setLanguage] = useState<LangType>('en');
39
+ const [theme, setTheme] = useState<ThemeType>('blueSteel');
40
+ const [accountId, setAccountId] = useState('70713602761202');
41
+ const [videoId, setVideoId] = useState('70716855695113');
42
+ const [interactivityProjectId, setInteractivityProjectId] = useState(
43
+ '63ed6c0cf2b60d00179ec101',
44
+ );
45
+ const [embedProperties, setEmbedProperties] = useState({
46
+ units: EmbedCodeUnits.PX,
47
+ responsive: false,
48
+ width: 0,
49
+ height: 0,
50
+ aspectRatio: EmbedCodeAspectRatio.FLUID,
51
+ });
52
+ const [embedVideoObj, setEmbedVideoObj] = useState<EmbedCodeModalProps>();
53
+ const [showDVR, setShowDVR] = useState(false);
54
+ const [showLowLatency, setShowLowLatency] = useState(false);
55
+ const [showSSAI, setShowSSAI] = useState(false);
56
+
57
+ const handlePropertiesUpdate = (name: string, value: string) => {
58
+ setEmbedProperties({
59
+ ...embedProperties,
60
+ [name]: value,
61
+ });
62
+ };
63
+
64
+ return (
65
+ <div style={{ padding: 20 }}>
66
+ <h1> Embed Code Sandbox demo </h1>
67
+ <h5>
68
+ {' '}
69
+ Use the url params to select environment. Ex. `env=production`. <br />{' '}
70
+ Default is `qa`
71
+ </h5>
72
+ <h5> Select component`s language </h5>
73
+ <Select
74
+ value={language}
75
+ options={[
76
+ { label: 'English', value: 'en' },
77
+ { label: 'Spanish', value: 'es' },
78
+ { label: 'French', value: 'fr' },
79
+ { label: 'Japanese', value: 'ja' },
80
+ { label: 'Korean', value: 'ko' },
81
+ { label: 'Chinese', value: 'zh' },
82
+ ]}
83
+ onChange={(value: LangType) => {
84
+ setLanguage(value);
85
+ }}
86
+ />
87
+ <h5> Select theme </h5>
88
+ <Select
89
+ value={theme}
90
+ options={[
91
+ { label: 'Blue Steel', value: 'blueSteel' },
92
+ { label: 'Prism', value: 'prism' },
93
+ ]}
94
+ onChange={(value: ThemeType) => {
95
+ setTheme(value);
96
+ }}
97
+ />
98
+ <h5>
99
+ Enter a valid account ID and video ID. Keep in mind the environment
100
+ </h5>
101
+ <Flex gap='sm'>
102
+ <Input
103
+ label='BC account ID'
104
+ value={accountId}
105
+ onChange={(value: string) => {
106
+ setAccountId(value);
107
+ }}
108
+ />
109
+ <Input
110
+ label='Video ID'
111
+ value={videoId}
112
+ onChange={(value: string) => {
113
+ setVideoId(value);
114
+ }}
115
+ />
116
+ <Input
117
+ label='Project ID'
118
+ value={interactivityProjectId}
119
+ onChange={(value: string) => {
120
+ setInteractivityProjectId(value);
121
+ }}
122
+ />
123
+ </Flex>
124
+ <h4>Optional properties for the embed code</h4>
125
+ <br />
126
+ <Flex gap='sm' alignItems='center'>
127
+ <Select
128
+ label='Units'
129
+ value={embedProperties.units}
130
+ options={[
131
+ { label: 'px', value: EmbedCodeUnits.PX },
132
+ { label: 'em', value: EmbedCodeUnits.EM },
133
+ { label: '%', value: EmbedCodeUnits.PERCENT },
134
+ ]}
135
+ onChange={(value: string) => handlePropertiesUpdate('units', value)}
136
+ />
137
+ <Input
138
+ label='Width'
139
+ type='number'
140
+ value={embedProperties.width}
141
+ onChange={(value: string) => handlePropertiesUpdate('width', value)}
142
+ />
143
+ <Input
144
+ label='Height'
145
+ type='number'
146
+ value={embedProperties.height}
147
+ onChange={(value: string) => handlePropertiesUpdate('height', value)}
148
+ />
149
+ <Select
150
+ label='Aspect ratio'
151
+ value={embedProperties.aspectRatio}
152
+ options={[
153
+ { label: 'fluid', value: EmbedCodeAspectRatio.FLUID },
154
+ { label: '1:1', value: EmbedCodeAspectRatio.ONE_ONE },
155
+ { label: '4:3', value: EmbedCodeAspectRatio.FOUR_THREE },
156
+ { label: '16:9', value: EmbedCodeAspectRatio.SIXTEEN_NINE },
157
+ { label: '9:16', value: EmbedCodeAspectRatio.NINE_SIXTEEN },
158
+ ]}
159
+ onChange={(value: string) =>
160
+ handlePropertiesUpdate('aspectRatio', value)
161
+ }
162
+ />
163
+ <Checkbox onChange={setShowDVR} checked={showDVR}>
164
+ <strong>Show DVR</strong>
165
+ </Checkbox>
166
+ <Checkbox onChange={setShowLowLatency} checked={showLowLatency}>
167
+ <strong>Show Low Latency</strong>
168
+ </Checkbox>
169
+ <Checkbox onChange={setShowSSAI} checked={showSSAI}>
170
+ <strong>Show Ad Configuration</strong>
171
+ </Checkbox>
172
+ </Flex>
173
+ <Button
174
+ text='Show Modal Video'
175
+ onClick={() => {
176
+ setEmbedVideoObj({
177
+ data: { ...videoObj, videoId, accountId },
178
+ embedCodeModalType: EmbedCodeModalTypes.VIDEO,
179
+ language,
180
+ theme,
181
+ });
182
+ }}
183
+ large
184
+ />
185
+ <Button
186
+ text='Show Modal Player'
187
+ onClick={() => {
188
+ setEmbedVideoObj({
189
+ data: { id: 'default', accountId },
190
+ embedCodeModalType: EmbedCodeModalTypes.PLAYER,
191
+ language: language,
192
+ theme,
193
+ });
194
+ }}
195
+ large
196
+ />
197
+ <Button
198
+ text='Show Modal Project'
199
+ onClick={() => {
200
+ setEmbedVideoObj({
201
+ data: {
202
+ accountId,
203
+ videoId,
204
+ interactivityProjectId,
205
+ interactivityProjectName: 'My Project Name',
206
+ },
207
+ embedCodeModalType: EmbedCodeModalTypes.PROJECT,
208
+ language: language,
209
+ theme,
210
+ });
211
+ }}
212
+ large
213
+ />
214
+ <Button
215
+ text='Show Modal Live'
216
+ onClick={() => {
217
+ setEmbedVideoObj({
218
+ data: {
219
+ videoId,
220
+ accountId,
221
+ livePlaybackToken: 'live-playback-token-test',
222
+ adConfigId: 'ad-config-id-test',
223
+ },
224
+ embedCodeModalType: EmbedCodeModalTypes.LIVE,
225
+ showDVR,
226
+ dvrTime: 900,
227
+ language,
228
+ theme,
229
+ ssai: showSSAI,
230
+ adConfigOptions: [
231
+ { label: 'Basic Ad Config', value: 'basic' },
232
+ { label: 'Advanced Ad Config', value: 'advanced' },
233
+ { label: 'Premium Ad Config', value: 'premium' },
234
+ ],
235
+ onDVRClick: (newValue) => {
236
+ console.log('DVR clicked', newValue);
237
+ },
238
+ showLowLatency,
239
+ onLowLatencyClick: (newValue) => {
240
+ console.log('Low Latency clicked', newValue);
241
+ },
242
+ });
243
+ }}
244
+ large
245
+ />
246
+ {embedVideoObj && (
247
+ <EmbedCodeModal
248
+ {...embedVideoObj}
249
+ language={language}
250
+ theme={theme}
251
+ embedCodeProperties={embedProperties}
252
+ />
253
+ )}
254
+ </div>
255
+ );
256
+ };
257
+
258
+ const initBCAPI = (studioModule: StudioModule) => {
259
+ const onAuth = () => {
260
+ if (appNode) {
261
+ if (!root) {
262
+ root = createRoot(appNode);
263
+ }
264
+ root.render(<App />);
265
+ }
266
+ };
267
+
268
+ studioModule.once('auth', onAuth);
269
+ const { module, user } = studioModule.config;
270
+ const accountId = user.currentAccount.id;
271
+ const moduleId = module.id;
272
+ const moduleScope = module.scope;
273
+ const moduleBcApiConfig = module.bcApiConfig;
274
+
275
+ // eslint-disable-next-line no-underscore-dangle
276
+ studioModule._initBCApi(accountId, moduleId, moduleScope, moduleBcApiConfig);
277
+ };
278
+
279
+ initialize();
280
+ initBCAPI(window.StudioModule);
@@ -0,0 +1,42 @@
1
+ @import './base.sass'
2
+
3
+ @include themed() using ($theme)
4
+ .featuresDropdown
5
+ background: white
6
+ margin-bottom: 10px
7
+ .topArea
8
+ border-top: 1px solid theme($theme, gray-30)
9
+ border-bottom: 1px solid theme($theme, gray-30)
10
+ background: white
11
+ display: flex
12
+ padding: 16px
13
+ justify-content: space-between
14
+ cursor: pointer
15
+
16
+ .title
17
+ font-weight: theme($theme, heading-weight)
18
+ color: black
19
+
20
+ .right
21
+ display: flex
22
+ .description
23
+ font-size: theme($theme, label-font-size)
24
+ margin-right: 30px
25
+ .icon
26
+ color: theme($theme, navy)
27
+
28
+ .hiddenArea
29
+ .hiddenAreaContainer
30
+ padding: 28px 16px
31
+ .aspectRatioSelect
32
+ span[class^="Select-wrapper"]
33
+ width: 343px
34
+ .sizeEdit
35
+ display: flex
36
+ gap: 16px
37
+ label
38
+ padding: 0
39
+ max-width: 110px
40
+ div[class^="InputGroup-labelRight-"]
41
+ display: none
42
+
@@ -0,0 +1,30 @@
1
+ @import './base.sass'
2
+
3
+ @include themed() using ($theme)
4
+ // Override studio-components styles
5
+ .hint
6
+ padding-top: 2px
7
+ .input
8
+ margin: 0 !important
9
+ padding-bottom: 4px !important
10
+ .textArea
11
+ color: theme($theme, gray-35) !important
12
+ background-color: theme($theme, gray-20) !important
13
+ border: none !important
14
+ resize: none
15
+ .copyInput
16
+ margin: 0 !important
17
+ padding-bottom: 4px !important
18
+ .textAreaDimensions
19
+ height: 210px
20
+ width: 390px
21
+ span[class^="CopyField-copyIcon"]
22
+ margin-right: 10px
23
+ .helperText
24
+ color: theme($theme, gray-40)
25
+ font-size: 14px
26
+ a.copyLink
27
+ text-decoration: none
28
+ font-weight: theme($theme, body-small-weight-bold)
29
+ cursor: pointer
30
+ padding-left: 4px
@@ -0,0 +1,76 @@
1
+ @import './base.sass'
2
+
3
+ @include themed() using ($theme)
4
+ .videoDetailsContainer
5
+ margin-bottom: 27px
6
+ .leftContent
7
+ width: 540px
8
+ margin-right: 34px
9
+ .timeInput input
10
+ width: 150px
11
+ .dvrCheckbox span
12
+ font-weight: theme($theme, label-font-weight)
13
+ .rightContent
14
+ flex-grow: 1
15
+ max-height: 468px
16
+ overflow-y: auto
17
+ .expandRightContent
18
+ max-height: 620px
19
+ .rightContentFullWidth
20
+ [class^="EmbedCode__copyInput"]
21
+ textarea
22
+ width: 100%
23
+ > div > div > div
24
+ flex: 1
25
+ .mediaData
26
+ margin-top: 23px
27
+ padding: 0
28
+ .redHelperText
29
+ color: theme($theme, red)
30
+ font-size: 14px
31
+ .tabPanelContent > div > div > div
32
+ display: block !important
33
+ .mediaTitle
34
+ color: theme($theme, text-primary-dark)
35
+ font-size: theme($theme, heading-xs-size)
36
+ font-weight: theme($theme, heading-weight)
37
+ line-height: theme($theme, heading-xs-line-height)
38
+ word-break: break-all
39
+ .text
40
+ color: theme($theme, gray-40)
41
+ font-size: theme($theme, body-small-text-size)
42
+ font-weight: theme($theme, body-small-weight-normal)
43
+ .playerSelectLabel
44
+ font-family: theme($theme, label-font)
45
+ font-size: theme($theme, label-font-size)
46
+ font-weight: theme($theme, label-font-weight)
47
+ line-height: theme($theme, label-line-height)
48
+ letter-spacing: theme($theme, label-letter-spacing)
49
+ color: theme($theme, label-color)
50
+ padding: 0 0 .4rem
51
+ .playerSelect
52
+ width: 100%
53
+ .getURLBtnContainer
54
+ display: inline-flex
55
+ .getURLBtnSpinner
56
+ left: -5px
57
+ position: relative
58
+ margin-right: 8px
59
+ .mediaId
60
+ @extend .text
61
+ margin-bottom: 25px
62
+ .tooltip
63
+ margin-left: theme($theme, padding-sm)
64
+ .customPluginNotice
65
+ font-size: 14px
66
+ .playerLoader
67
+ video-js
68
+ width: 539px !important
69
+ height: 303.2px !important
70
+ margin-bottom: theme($theme, padding-sm)
71
+ iframe
72
+ width: 539px !important
73
+ height: 303.2px !important
74
+ .previewButton
75
+ align-self: center
76
+
@@ -0,0 +1 @@
1
+ @import 'theme.sass'
@@ -0,0 +1,128 @@
1
+ @import "~@brightcove/prism-core/build/scss/tokens"
2
+
3
+ .prismLiveModalContent
4
+ display: grid
5
+ grid-template-columns: minmax(0, 52%) minmax(0, 48%)
6
+ gap: 0
7
+ height: 100%
8
+ min-height: 0
9
+ min-width: 0
10
+
11
+ .prismLeftColumn
12
+ padding: var(--spacing-5, 24px)
13
+ display: flex
14
+ flex-direction: column
15
+ gap: var(--spacing-4, 16px)
16
+ overflow-y: auto
17
+ min-height: 0
18
+ min-width: 0
19
+ border-right: 1px solid var(--stroke-tertiary-default, #f5f4f0)
20
+ background: var(--surface-primary-default, #ffffff)
21
+
22
+ .prismRightColumn
23
+ padding: var(--spacing-5, 24px)
24
+ display: flex
25
+ flex-direction: column
26
+ overflow-y: auto
27
+ min-height: 0
28
+ min-width: 0
29
+ background: var(--surface-primary-default, #ffffff)
30
+
31
+ .prismInputGroup
32
+ display: flex
33
+ gap: var(--spacing-2, 8px)
34
+ align-items: flex-end
35
+
36
+ .prismSizingField
37
+ flex: 1 1 0
38
+ min-width: 0
39
+
40
+ .prismLinkButton
41
+ margin-bottom: 8px
42
+ flex-shrink: 0
43
+
44
+ // Let the card grow with the code (all lines visible, long code scrolls the
45
+ // column) and keep a 150px floor. The clip keeps the rounded corners that
46
+ // `indefiniteGrow` gives up on the card root.
47
+ .prismCodeCard
48
+ flex: 0 0 auto
49
+ border-radius: var(--radius-2, 8px)
50
+ overflow: hidden
51
+
52
+ // PrismCodeCard pins its code area at min-height 170px.
53
+ [class*='CodeCard__scroll']
54
+ min-height: 150px
55
+
56
+ .prismCustomPluginNotice
57
+ padding: var(--spacing-2, 8px) var(--spacing-3, 12px)
58
+ background: var(--surface-warning-subdued, #fff4e5)
59
+ color: var(--text-warning-default, #b54708)
60
+ font-size: var(--font-size-4xs, 12px)
61
+ line-height: var(--font-line-height-5xs, 15px)
62
+ border-radius: var(--radius-2, 8px)
63
+ margin-top: var(--spacing-3, 12px)
64
+
65
+ // Player Preview Styles
66
+ .prismPlayerPreviewContainer
67
+ display: flex
68
+ flex-direction: column
69
+ height: 100%
70
+ gap: var(--spacing-3, 12px)
71
+
72
+ .prismPlayerActions
73
+ display: flex
74
+ gap: var(--spacing-2, 8px)
75
+ justify-content: flex-end
76
+
77
+ .prismPlayerWrapper
78
+ flex: 1
79
+ position: relative
80
+ border-radius: var(--radius-2, 8px)
81
+ overflow: hidden
82
+ display: flex
83
+ align-items: center
84
+ justify-content: center
85
+
86
+ video
87
+ width: 100%
88
+ height: auto
89
+
90
+ iframe
91
+ width: 100%
92
+ max-width: 100%
93
+ aspect-ratio: 16 / 9
94
+ border: none
95
+ border-radius: var(--radius-2, 8px)
96
+
97
+ .playerLoader
98
+ width: 100%
99
+ max-width: 100%
100
+ aspect-ratio: 16 / 9
101
+ display: flex
102
+ align-items: center
103
+ justify-content: center
104
+
105
+ video
106
+ width: 100%
107
+ height: 100%
108
+ object-fit: contain
109
+
110
+ // Responsive adjustments. Matches useIsMobile / media's Prism modal policy:
111
+ // below 1024 the modal is a vertical stack, from 1024 up it is two columns.
112
+ @media (max-width: 1023px)
113
+ .prismLiveModalContent
114
+ grid-template-columns: minmax(0, 1fr)
115
+ height: auto
116
+
117
+ .prismLeftColumn
118
+ overflow-y: visible
119
+ border-right: none
120
+ border-bottom: 1px solid var(--stroke-tertiary-default, #f5f4f0)
121
+
122
+ .prismRightColumn
123
+ overflow-y: visible
124
+ min-height: 400px
125
+
126
+ // On phones the footer offers Copy Code instead of showing the card.
127
+ .prismCodeCard
128
+ display: none