@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,105 @@
1
+ import React, { useEffect, useState } from 'react';
2
+
3
+ import { I18nextProvider } from 'react-i18next';
4
+ import { initialize } from '@brightcove/studio-components';
5
+ import { QueryClient, QueryClientProvider } from 'react-query';
6
+
7
+ import { ModalContainer } from 'js/components';
8
+
9
+ import i18n from 'js/i18n';
10
+ import {
11
+ EmbedCodeModalTypes,
12
+ EmbedCodeProperties,
13
+ ModalDataPayload,
14
+ } from './types/EmbedCodeModalProps';
15
+
16
+ // Theme initialization moved inside component to support dynamic theme prop
17
+
18
+ const queryClient = new QueryClient();
19
+
20
+ export interface EmbedCodeModalProps {
21
+ data: ModalDataPayload;
22
+ language?: 'en' | 'es' | 'fr' | 'ko' | 'ja' | 'zh';
23
+ theme?: 'blueSteel' | 'prism';
24
+ embedCodeModalType?: EmbedCodeModalTypes;
25
+ // Parameters to be passed in case the the type is Player
26
+ embedCodeProperties?: EmbedCodeProperties;
27
+ isOutstreamPlayer?: boolean;
28
+ showDVR?: boolean;
29
+ onDVRClick?: (newValue: boolean) => void;
30
+ dvrTime?: number;
31
+ showLowLatency?: boolean;
32
+ onLowLatencyClick?: (newValue: boolean) => void;
33
+ ssai?: boolean;
34
+ adConfigOptions?: Array<{ label: string; value: string }>;
35
+ onAdConfigChange?: (value: string) => void;
36
+ }
37
+
38
+ const EmbedModal = ({
39
+ data,
40
+ language,
41
+ theme,
42
+ embedCodeModalType,
43
+ embedCodeProperties,
44
+ isOutstreamPlayer,
45
+ showDVR,
46
+ onDVRClick,
47
+ dvrTime,
48
+ showLowLatency,
49
+ onLowLatencyClick,
50
+ ssai,
51
+ adConfigOptions,
52
+ onAdConfigChange,
53
+ }: EmbedCodeModalProps) => {
54
+ const [componentKey, setComponentKey] = useState(0);
55
+ const [hasCreatedPlayer, setHasCreatedPlayer] = useState(false);
56
+
57
+ useEffect(() => {
58
+ // Default to 'blueSteel' to maintain existing behavior
59
+ const studioComponentsTheme =
60
+ theme === 'prism' ? 'blueSteel' : theme || 'blueSteel';
61
+ initialize({ theme: studioComponentsTheme });
62
+ }, [theme]);
63
+
64
+ useEffect(() => {
65
+ i18n.changeLanguage(language || window.StudioModule.config.lang);
66
+ }, [language]);
67
+
68
+ const handleSetComponentKey = () => {
69
+ setComponentKey(componentKey + 1);
70
+ };
71
+
72
+ const handleSetHasCreatedPlayer = (value: boolean) => {
73
+ setHasCreatedPlayer(value);
74
+ };
75
+
76
+ // avoid calling anything if there is not data
77
+ return data ? (
78
+ <QueryClientProvider client={queryClient}>
79
+ <I18nextProvider i18n={i18n}>
80
+ <ModalContainer
81
+ key={componentKey}
82
+ handleSetComponentKey={handleSetComponentKey}
83
+ data={data}
84
+ language={language}
85
+ theme={theme}
86
+ embedCodeModalType={embedCodeModalType}
87
+ handleSetHasCreatedPlayer={handleSetHasCreatedPlayer}
88
+ hasCreatedPlayer={hasCreatedPlayer}
89
+ embedCodeProperties={embedCodeProperties}
90
+ isOutstreamPlayer={isOutstreamPlayer}
91
+ showDVR={showDVR}
92
+ onDVRClick={onDVRClick}
93
+ dvrTime={dvrTime}
94
+ showLowLatency={showLowLatency}
95
+ onLowLatencyClick={onLowLatencyClick}
96
+ ssai={ssai}
97
+ adConfigOptions={adConfigOptions}
98
+ onAdConfigChange={onAdConfigChange}
99
+ />
100
+ </I18nextProvider>
101
+ </QueryClientProvider>
102
+ ) : null;
103
+ };
104
+
105
+ export default EmbedModal;
@@ -0,0 +1,184 @@
1
+ import React, { useState } from 'react';
2
+ import {
3
+ RadioGroup,
4
+ Select,
5
+ Input,
6
+ Icon,
7
+ ICONS,
8
+ Fadeable,
9
+ } from '@brightcove/studio-components';
10
+ import { useTranslation } from 'react-i18next';
11
+
12
+ import css from 'styles/CustomSettingsDropdown.sass';
13
+ import {
14
+ EmbedCodeAspectRatio,
15
+ EmbedCodeProperties,
16
+ EmbedCodeUnits,
17
+ } from 'js/types/EmbedCodeModalProps';
18
+ import {
19
+ calculateDimensions,
20
+ calculateHeight,
21
+ shouldUpdateWidth,
22
+ } from 'js/utils/dimensions';
23
+
24
+ export enum Sizing {
25
+ FIXED = 'Fixed',
26
+ RESPONSIVE = 'Responsive',
27
+ }
28
+
29
+ export const CustomSettingsDropdown = ({
30
+ setEmbedProperties,
31
+ embedProperties,
32
+ }: {
33
+ embedProperties: EmbedCodeProperties;
34
+ setEmbedProperties: (value: EmbedCodeProperties) => void;
35
+ }) => {
36
+ const { t } = useTranslation();
37
+ const [isHidden, setIsHidden] = useState<boolean>(true);
38
+ const [prevAspectRatio, setPrevAspectRatio] = useState(
39
+ embedProperties.aspectRatio,
40
+ );
41
+
42
+ const handlePropertiesUpdate = (
43
+ name: string,
44
+ value: string | boolean | number,
45
+ ) => {
46
+ if (name === 'aspectRatio') {
47
+ const calculateNewWidth = shouldUpdateWidth(
48
+ prevAspectRatio,
49
+ value as EmbedCodeAspectRatio,
50
+ );
51
+
52
+ setPrevAspectRatio(value as EmbedCodeAspectRatio);
53
+
54
+ const dimensions = calculateDimensions(
55
+ calculateNewWidth,
56
+ value as EmbedCodeAspectRatio,
57
+ embedProperties.width,
58
+ embedProperties.height,
59
+ );
60
+
61
+ setEmbedProperties({
62
+ ...embedProperties,
63
+ aspectRatio: value as EmbedCodeAspectRatio,
64
+ width: dimensions.width as number,
65
+ height: dimensions.height,
66
+ });
67
+
68
+ return;
69
+ } else if (
70
+ name === 'width' &&
71
+ embedProperties.aspectRatio !== EmbedCodeAspectRatio.CUSTOM
72
+ ) {
73
+ const height = calculateHeight(
74
+ value as number,
75
+ embedProperties.aspectRatio,
76
+ );
77
+
78
+ setEmbedProperties({
79
+ ...embedProperties,
80
+ width: value as number,
81
+ height,
82
+ });
83
+
84
+ return;
85
+ }
86
+
87
+ setEmbedProperties({
88
+ ...embedProperties,
89
+ [name]: value,
90
+ });
91
+ };
92
+
93
+ return (
94
+ <div className={css.featuresDropdown}>
95
+ <div className={css.topArea} onClick={() => setIsHidden(!isHidden)}>
96
+ <div className={css.title}>Custom settings</div>
97
+ <div className={css.right}>
98
+ <div className={css.description}>Sizing & ratio</div>
99
+ <Icon
100
+ name={isHidden ? ICONS.CARET_DOWN : ICONS.CARET_UP}
101
+ className={css.icon}
102
+ />
103
+ </div>
104
+ </div>
105
+ <Fadeable show={!isHidden} className={css.hiddenArea}>
106
+ <div className={css.hiddenAreaContainer}>
107
+ <RadioGroup
108
+ inline
109
+ name='sizing'
110
+ label={t('customSettings.sizing')}
111
+ value={
112
+ embedProperties.responsive ? Sizing.RESPONSIVE : Sizing.FIXED
113
+ }
114
+ options={[Sizing.FIXED, Sizing.RESPONSIVE]}
115
+ onChange={(value: string) =>
116
+ handlePropertiesUpdate('responsive', value === Sizing.RESPONSIVE)
117
+ }
118
+ testName='embed-sizing-radio-group'
119
+ />
120
+ <Select
121
+ label={t('customSettings.aspectRatio')}
122
+ value={embedProperties.aspectRatio}
123
+ options={[
124
+ EmbedCodeAspectRatio.SIXTEEN_NINE,
125
+ EmbedCodeAspectRatio.NINE_SIXTEEN,
126
+ EmbedCodeAspectRatio.ONE_ONE,
127
+ EmbedCodeAspectRatio.FOUR_THREE,
128
+ EmbedCodeAspectRatio.CUSTOM,
129
+ ]}
130
+ className={css.aspectRatioSelect}
131
+ onChange={(value: string) =>
132
+ handlePropertiesUpdate('aspectRatio', value)
133
+ }
134
+ testName='embed-aspect-ratio-select'
135
+ />
136
+ <div className={css.sizeEdit}>
137
+ <Input
138
+ label={t('customSettings.playerWidth')}
139
+ value={embedProperties.width}
140
+ onChange={(value: string) =>
141
+ handlePropertiesUpdate('width', value)
142
+ }
143
+ error={
144
+ embedProperties.width <= 0
145
+ ? 'Can only be positive integers'
146
+ : ''
147
+ }
148
+ testName='embed-width-input'
149
+ />
150
+ <Input
151
+ label={t('customSettings.playerHeight')}
152
+ value={embedProperties.height}
153
+ onChange={(value: string) =>
154
+ handlePropertiesUpdate('height', value)
155
+ }
156
+ disabled={
157
+ embedProperties.aspectRatio !== EmbedCodeAspectRatio.CUSTOM
158
+ }
159
+ error={
160
+ embedProperties.height <= 0
161
+ ? 'Can only be positive integers'
162
+ : ''
163
+ }
164
+ testName='embed-height-input'
165
+ />
166
+ <Select
167
+ label={t('customSettings.units')}
168
+ value={embedProperties.units}
169
+ options={[
170
+ EmbedCodeUnits.PX,
171
+ EmbedCodeUnits.EM,
172
+ EmbedCodeUnits.PERCENT,
173
+ ]}
174
+ onChange={(value: string) =>
175
+ handlePropertiesUpdate('units', value)
176
+ }
177
+ testName='embed-units-select'
178
+ />
179
+ </div>
180
+ </div>
181
+ </Fadeable>
182
+ </div>
183
+ );
184
+ };
@@ -0,0 +1,130 @@
1
+ import React, { useEffect, useState } from 'react';
2
+ import { useTranslation } from 'react-i18next';
3
+
4
+ import brightcoveEmbedCode from '@brightcove/player-embed-code';
5
+ import {
6
+ Flex,
7
+ FlexItem,
8
+ CopyField,
9
+ PlainTextArea,
10
+ } from '@brightcove/studio-components';
11
+
12
+ import { EmbedCodeProps } from 'js/types/EmbedCodeProps';
13
+ import { getUrlBase, getBrightcove, decodeHtmlEntities } from 'js/utils/util';
14
+
15
+ import css from 'styles/EmbedCode.sass';
16
+ import {
17
+ EmbedCodeAspectRatio,
18
+ EmbedCodeUnits,
19
+ } from 'js/types/EmbedCodeModalProps';
20
+
21
+ interface EmbedCodeConfig {
22
+ accountId: string;
23
+ responsive: boolean;
24
+ width: number;
25
+ height: number;
26
+ iframe: boolean;
27
+ videoId?: string;
28
+ interactivityProjectId?: string;
29
+ playerId: string;
30
+ urlBase: string;
31
+ playlistIsHorizontal: boolean;
32
+ units: EmbedCodeUnits;
33
+ aspectRatio?: EmbedCodeAspectRatio;
34
+ }
35
+
36
+ const DEFAULT_HEIGHT = 540;
37
+ const DEFAULT_WIDTH = 960;
38
+ const defaultConfig = {
39
+ responsive: false,
40
+ width: DEFAULT_WIDTH,
41
+ height: DEFAULT_HEIGHT,
42
+ urlBase: getUrlBase(),
43
+ playlistIsHorizontal: true,
44
+ units: EmbedCodeUnits.PX,
45
+ aspectRatio: EmbedCodeAspectRatio.FLUID,
46
+ };
47
+
48
+ const createEmbedConfigObject = ({
49
+ embedCodeProperties,
50
+ accountId,
51
+ iframe,
52
+ videoId,
53
+ playerId,
54
+ interactivityProjectId,
55
+ livePlaybackToken,
56
+ adConfigId,
57
+ }: EmbedCodeProps): EmbedCodeConfig => {
58
+ const config = {
59
+ accountId,
60
+ iframe,
61
+ videoId,
62
+ playerId,
63
+ livePlaybackToken,
64
+ adConfigId,
65
+ interactivityProjectId,
66
+ };
67
+ return Object.assign(
68
+ {},
69
+ { ...defaultConfig, ...config, ...embedCodeProperties },
70
+ );
71
+ };
72
+
73
+ export const EmbedCode = (config: EmbedCodeProps) => {
74
+ const { t } = useTranslation();
75
+ const [embedCode, setEmbedCode] = useState('');
76
+
77
+ useEffect(() => {
78
+ const embedConfigObj = createEmbedConfigObject(config);
79
+
80
+ if (embedConfigObj.aspectRatio) {
81
+ embedConfigObj.aspectRatio =
82
+ embedConfigObj.aspectRatio === EmbedCodeAspectRatio.CUSTOM
83
+ ? EmbedCodeAspectRatio.FLUID
84
+ : embedConfigObj.aspectRatio;
85
+ }
86
+
87
+ const embedCode = decodeHtmlEntities(brightcoveEmbedCode(embedConfigObj));
88
+ setEmbedCode(embedCode);
89
+ }, [config]);
90
+
91
+ const HelperTextNodeNew = (
92
+ <Flex>
93
+ <FlexItem flexGrow='1' className={css.helperText}>
94
+ {t('tabs.helperText')}
95
+ </FlexItem>
96
+ </Flex>
97
+ );
98
+
99
+ return (
100
+ <>
101
+ <CopyField
102
+ className={css.copyInput}
103
+ helperNode={HelperTextNodeNew}
104
+ Component={PlainTextArea}
105
+ componentProps={{
106
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
107
+ // @ts-ignore
108
+ disabled: true,
109
+ disableResizing: true,
110
+ className: css.textAreaDimensions,
111
+ onChange: () => void 0,
112
+ }}
113
+ onCopy={() => {
114
+ getBrightcove().Toaster.success({
115
+ title: t('toasterTitle'),
116
+ message: t('toasterMessage'),
117
+ });
118
+ }}
119
+ onError={() => {
120
+ getBrightcove().Toaster.error({
121
+ message: t('toasterErrorMessage'),
122
+ });
123
+ }}
124
+ value={embedCode}
125
+ hideButton={true}
126
+ testName='embed-copy-section'
127
+ />
128
+ </>
129
+ );
130
+ };