@brightcove/components-embed-code-modal 1.0.7 → 1.0.8

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 (181) 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 +387 -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__/TabsHeader.test.tsx +19 -0
  17. package/__tests__/TabsSection.test.tsx +46 -0
  18. package/__tests__/TitleWithTooltip.test.tsx +45 -0
  19. package/__tests__/VideoPlayer.test.tsx +38 -0
  20. package/__tests__/embedCodeGenerator.test.ts +111 -0
  21. package/__tests__/util.test.ts +89 -0
  22. package/babel.config.json +17 -0
  23. package/build/README.md +109 -0
  24. package/build/package.json +100 -0
  25. package/etc/wildcard.brightcove.com.key +27 -0
  26. package/etc/wildcard.brightcove.com.pem +96 -0
  27. package/jest/jest.setup.js +62 -0
  28. package/jest/jest.stub.js +4 -0
  29. package/jest.config.js +24 -0
  30. package/package.json +15 -5
  31. package/scripts/create-dist-pkg-prod.js +18 -0
  32. package/src/index.ts +17 -0
  33. package/src/js/EmbedCodeModal.tsx +105 -0
  34. package/src/js/components/CustomSettingsDropdown.tsx +184 -0
  35. package/src/js/components/EmbedCopySection.tsx +130 -0
  36. package/src/js/components/ModalContainer.tsx +367 -0
  37. package/src/js/components/NoPlayerModal.tsx +42 -0
  38. package/src/js/components/PlayerPreview.tsx +116 -0
  39. package/src/js/components/TabsHeader.tsx +31 -0
  40. package/src/js/components/TabsSection.tsx +74 -0
  41. package/src/js/components/TitleWithTooltip.tsx +39 -0
  42. package/src/js/components/VideoLinks.tsx +83 -0
  43. package/src/js/components/VideoPlayer.tsx +324 -0
  44. package/src/js/components/index.ts +9 -0
  45. package/src/js/components/prism/PrismLiveModal.tsx +162 -0
  46. package/src/js/components/prism/PrismPlayerControls.tsx +343 -0
  47. package/src/js/components/prism/PrismPlayerPreview.tsx +98 -0
  48. package/src/js/components/prism/index.ts +3 -0
  49. package/src/js/constants/baseUrls.ts +4 -0
  50. package/src/js/constants/embed.ts +12 -0
  51. package/src/js/constants/player.ts +32 -0
  52. package/src/js/constants/pluginsRegistry.ts +30 -0
  53. package/src/js/hooks/useGetPlayers.ts +12 -0
  54. package/src/js/i18n.ts +43 -0
  55. package/src/js/services/players-api.ts +26 -0
  56. package/src/js/services/url-shortener.ts +10 -0
  57. package/src/js/types/EmbedCodeModalProps.ts +72 -0
  58. package/src/js/types/EmbedCodeProps.ts +13 -0
  59. package/src/js/types/brightcoveEmbedCode.d.ts +18 -0
  60. package/src/js/types/players.ts +64 -0
  61. package/src/js/types/react-i18next.d.ts +8 -0
  62. package/src/js/types/studioModule.ts +7 -0
  63. package/src/js/utils/addPluginsDataToPlayers.ts +59 -0
  64. package/src/js/utils/call.ts +31 -0
  65. package/src/js/utils/dimensions.ts +53 -0
  66. package/src/js/utils/embedCodeGenerator.ts +120 -0
  67. package/src/js/utils/featureSwitches.ts +16 -0
  68. package/src/js/utils/util.ts +153 -0
  69. package/src/module.tsx +280 -0
  70. package/src/styles/CustomSettingsDropdown.sass +42 -0
  71. package/src/styles/EmbedCode.sass +30 -0
  72. package/src/styles/EmbedCodeModal.sass +76 -0
  73. package/src/styles/base.sass +1 -0
  74. package/src/styles/prism/PrismLiveModal.sass +155 -0
  75. package/src/styles/theme.sass +11 -0
  76. package/src/styles/typings.td.ts +9 -0
  77. package/src/translations/en.json +61 -0
  78. package/src/translations/es.json +61 -0
  79. package/src/translations/fr.json +61 -0
  80. package/src/translations/ja.json +61 -0
  81. package/src/translations/ko.json +61 -0
  82. package/src/translations/zh.json +61 -0
  83. package/src/types/studio.ts +197 -0
  84. package/tsconfig.json +34 -0
  85. package/webpack.config.js +117 -0
  86. /package/{__tests__ → build/__tests__}/EmbedCode.test.d.ts +0 -0
  87. /package/{__tests__ → build/__tests__}/EmbedCode.test.d.ts.map +0 -0
  88. /package/{__tests__ → build/__tests__}/InteractivityProject.test.d.ts +0 -0
  89. /package/{__tests__ → build/__tests__}/InteractivityProject.test.d.ts.map +0 -0
  90. /package/{__tests__ → build/__tests__}/PlayerPreview.test.d.ts +0 -0
  91. /package/{__tests__ → build/__tests__}/PlayerPreview.test.d.ts.map +0 -0
  92. /package/{__tests__ → build/__tests__}/TabsHeader.test.d.ts +0 -0
  93. /package/{__tests__ → build/__tests__}/TabsHeader.test.d.ts.map +0 -0
  94. /package/{__tests__ → build/__tests__}/TabsSection.test.d.ts +0 -0
  95. /package/{__tests__ → build/__tests__}/TabsSection.test.d.ts.map +0 -0
  96. /package/{__tests__ → build/__tests__}/TitleWithTooltip.test.d.ts +0 -0
  97. /package/{__tests__ → build/__tests__}/TitleWithTooltip.test.d.ts.map +0 -0
  98. /package/{__tests__ → build/__tests__}/VideoPlayer.test.d.ts +0 -0
  99. /package/{__tests__ → build/__tests__}/VideoPlayer.test.d.ts.map +0 -0
  100. /package/{__tests__ → build/__tests__}/embedCodeGenerator.test.d.ts +0 -0
  101. /package/{__tests__ → build/__tests__}/embedCodeGenerator.test.d.ts.map +0 -0
  102. /package/{__tests__ → build/__tests__}/util.test.d.ts +0 -0
  103. /package/{__tests__ → build/__tests__}/util.test.d.ts.map +0 -0
  104. /package/{index.js → build/index.js} +0 -0
  105. /package/{index.js.map → build/index.js.map} +0 -0
  106. /package/{src → build/src}/index.d.ts +0 -0
  107. /package/{src → build/src}/index.d.ts.map +0 -0
  108. /package/{src → build/src}/js/EmbedCodeModal.d.ts +0 -0
  109. /package/{src → build/src}/js/EmbedCodeModal.d.ts.map +0 -0
  110. /package/{src → build/src}/js/components/CustomSettingsDropdown.d.ts +0 -0
  111. /package/{src → build/src}/js/components/CustomSettingsDropdown.d.ts.map +0 -0
  112. /package/{src → build/src}/js/components/EmbedCopySection.d.ts +0 -0
  113. /package/{src → build/src}/js/components/EmbedCopySection.d.ts.map +0 -0
  114. /package/{src → build/src}/js/components/ModalContainer.d.ts +0 -0
  115. /package/{src → build/src}/js/components/ModalContainer.d.ts.map +0 -0
  116. /package/{src → build/src}/js/components/NoPlayerModal.d.ts +0 -0
  117. /package/{src → build/src}/js/components/NoPlayerModal.d.ts.map +0 -0
  118. /package/{src → build/src}/js/components/PlayerPreview.d.ts +0 -0
  119. /package/{src → build/src}/js/components/PlayerPreview.d.ts.map +0 -0
  120. /package/{src → build/src}/js/components/TabsHeader.d.ts +0 -0
  121. /package/{src → build/src}/js/components/TabsHeader.d.ts.map +0 -0
  122. /package/{src → build/src}/js/components/TabsSection.d.ts +0 -0
  123. /package/{src → build/src}/js/components/TabsSection.d.ts.map +0 -0
  124. /package/{src → build/src}/js/components/TitleWithTooltip.d.ts +0 -0
  125. /package/{src → build/src}/js/components/TitleWithTooltip.d.ts.map +0 -0
  126. /package/{src → build/src}/js/components/VideoLinks.d.ts +0 -0
  127. /package/{src → build/src}/js/components/VideoLinks.d.ts.map +0 -0
  128. /package/{src → build/src}/js/components/VideoPlayer.d.ts +0 -0
  129. /package/{src → build/src}/js/components/VideoPlayer.d.ts.map +0 -0
  130. /package/{src → build/src}/js/components/index.d.ts +0 -0
  131. /package/{src → build/src}/js/components/index.d.ts.map +0 -0
  132. /package/{src → build/src}/js/components/prism/PrismLiveModal.d.ts +0 -0
  133. /package/{src → build/src}/js/components/prism/PrismLiveModal.d.ts.map +0 -0
  134. /package/{src → build/src}/js/components/prism/PrismPlayerControls.d.ts +0 -0
  135. /package/{src → build/src}/js/components/prism/PrismPlayerControls.d.ts.map +0 -0
  136. /package/{src → build/src}/js/components/prism/PrismPlayerPreview.d.ts +0 -0
  137. /package/{src → build/src}/js/components/prism/PrismPlayerPreview.d.ts.map +0 -0
  138. /package/{src → build/src}/js/components/prism/index.d.ts +0 -0
  139. /package/{src → build/src}/js/components/prism/index.d.ts.map +0 -0
  140. /package/{src → build/src}/js/constants/baseUrls.d.ts +0 -0
  141. /package/{src → build/src}/js/constants/baseUrls.d.ts.map +0 -0
  142. /package/{src → build/src}/js/constants/embed.d.ts +0 -0
  143. /package/{src → build/src}/js/constants/embed.d.ts.map +0 -0
  144. /package/{src → build/src}/js/constants/player.d.ts +0 -0
  145. /package/{src → build/src}/js/constants/player.d.ts.map +0 -0
  146. /package/{src → build/src}/js/constants/pluginsRegistry.d.ts +0 -0
  147. /package/{src → build/src}/js/constants/pluginsRegistry.d.ts.map +0 -0
  148. /package/{src → build/src}/js/hooks/useGetPlayers.d.ts +0 -0
  149. /package/{src → build/src}/js/hooks/useGetPlayers.d.ts.map +0 -0
  150. /package/{src → build/src}/js/i18n.d.ts +0 -0
  151. /package/{src → build/src}/js/i18n.d.ts.map +0 -0
  152. /package/{src → build/src}/js/services/players-api.d.ts +0 -0
  153. /package/{src → build/src}/js/services/players-api.d.ts.map +0 -0
  154. /package/{src → build/src}/js/services/url-shortener.d.ts +0 -0
  155. /package/{src → build/src}/js/services/url-shortener.d.ts.map +0 -0
  156. /package/{src → build/src}/js/types/EmbedCodeModalProps.d.ts +0 -0
  157. /package/{src → build/src}/js/types/EmbedCodeModalProps.d.ts.map +0 -0
  158. /package/{src → build/src}/js/types/EmbedCodeProps.d.ts +0 -0
  159. /package/{src → build/src}/js/types/EmbedCodeProps.d.ts.map +0 -0
  160. /package/{src → build/src}/js/types/players.d.ts +0 -0
  161. /package/{src → build/src}/js/types/players.d.ts.map +0 -0
  162. /package/{src → build/src}/js/types/studioModule.d.ts +0 -0
  163. /package/{src → build/src}/js/types/studioModule.d.ts.map +0 -0
  164. /package/{src → build/src}/js/utils/addPluginsDataToPlayers.d.ts +0 -0
  165. /package/{src → build/src}/js/utils/addPluginsDataToPlayers.d.ts.map +0 -0
  166. /package/{src → build/src}/js/utils/call.d.ts +0 -0
  167. /package/{src → build/src}/js/utils/call.d.ts.map +0 -0
  168. /package/{src → build/src}/js/utils/dimensions.d.ts +0 -0
  169. /package/{src → build/src}/js/utils/dimensions.d.ts.map +0 -0
  170. /package/{src → build/src}/js/utils/embedCodeGenerator.d.ts +0 -0
  171. /package/{src → build/src}/js/utils/embedCodeGenerator.d.ts.map +0 -0
  172. /package/{src → build/src}/js/utils/featureSwitches.d.ts +0 -0
  173. /package/{src → build/src}/js/utils/featureSwitches.d.ts.map +0 -0
  174. /package/{src → build/src}/js/utils/util.d.ts +0 -0
  175. /package/{src → build/src}/js/utils/util.d.ts.map +0 -0
  176. /package/{src → build/src}/module.d.ts +0 -0
  177. /package/{src → build/src}/module.d.ts.map +0 -0
  178. /package/{src → build/src}/styles/typings.td.d.ts +0 -0
  179. /package/{src → build/src}/styles/typings.td.d.ts.map +0 -0
  180. /package/{src → build/src}/types/studio.d.ts +0 -0
  181. /package/{src → build/src}/types/studio.d.ts.map +0 -0
@@ -0,0 +1,96 @@
1
+ Certificate:
2
+ Data:
3
+ Version: 3 (0x2)
4
+ Serial Number: 4109 (0x100d)
5
+ Signature Algorithm: sha256WithRSAEncryption
6
+ Issuer: C=US, ST=Massachusetts, L=Boston, O=Brightcove Inc., OU=Systems Engineering/emailAddress=syseng@brightcove.com
7
+ Validity
8
+ Not Before: Jan 22 15:49:19 2016 GMT
9
+ Not After : Jan 19 15:49:19 2026 GMT
10
+ Subject: C=US, ST=Massachusetts, O=Brightcove Inc., OU=Systems Engineering, CN=*.brightcove.com/emailAddress=syseng@brightcove.com
11
+ Subject Public Key Info:
12
+ Public Key Algorithm: rsaEncryption
13
+ RSA Public Key: (2048 bit)
14
+ Modulus (2048 bit):
15
+ 00:c5:79:88:ee:c3:81:2a:f1:66:f1:31:48:84:aa:
16
+ 18:09:83:9a:0c:4f:ae:a5:ce:93:70:fa:8d:95:3b:
17
+ 7c:c0:0f:1b:06:95:18:25:ef:7d:a1:fb:b9:08:13:
18
+ 6c:0f:4b:88:d5:74:d6:cb:e0:63:9a:8d:7b:ec:d0:
19
+ fe:dd:aa:67:8b:a2:99:90:e8:7c:91:26:ff:e4:e0:
20
+ 0b:f9:e1:1b:a8:79:2c:2f:c6:7a:f9:b0:25:2a:d3:
21
+ a3:8f:2b:f7:49:ef:d3:f2:c1:08:a3:57:6c:ce:00:
22
+ 45:55:d3:db:41:95:6b:60:bc:c6:bb:d8:3a:b4:b7:
23
+ 2e:d6:32:7d:9a:37:42:2e:d8:44:75:22:47:b4:f9:
24
+ 13:15:46:29:f1:69:6e:a7:da:8c:9a:f1:b5:8e:8d:
25
+ b0:ab:3e:29:15:5b:47:c9:95:bf:7c:29:10:f8:c9:
26
+ 1f:78:e3:e7:1a:24:b0:da:81:27:1d:a5:66:1a:e3:
27
+ c5:7b:2c:61:58:18:76:ab:63:00:aa:9c:9c:f6:a5:
28
+ 4c:90:34:28:c1:0c:6d:83:ff:f3:39:59:6b:eb:7d:
29
+ 97:66:92:36:c6:1a:6e:20:d1:d4:ce:d0:f1:10:73:
30
+ 81:dc:77:79:95:3f:af:dd:64:2d:b5:06:7f:d6:04:
31
+ 57:68:99:05:00:62:b1:81:b2:df:b8:b8:7d:d8:bf:
32
+ 7b:e5
33
+ Exponent: 65537 (0x10001)
34
+ X509v3 extensions:
35
+ X509v3 Basic Constraints:
36
+ CA:FALSE
37
+ Netscape Comment:
38
+ OpenSSL Generated Certificate
39
+ X509v3 Subject Key Identifier:
40
+ 25:8C:64:B3:F5:49:BD:8A:1F:42:9A:D6:69:9C:B4:04:FE:4B:82:C2
41
+ X509v3 Authority Key Identifier:
42
+ keyid:D1:E0:AC:DE:01:80:DB:94:DA:29:66:0F:A9:48:11:BF:62:9F:51:9E
43
+ DirName:/C=US/ST=Massachusetts/L=Boston/O=Brightcove Inc./OU=Systems Engineering/emailAddress=syseng@brightcove.com
44
+ serial:C2:3B:9A:77:9C:63:DE:2B
45
+
46
+ X509v3 Subject Alternative Name:
47
+ DNS:*.brightcove.com, DNS:*.qa.brightcove.com, DNS:*.oauth.qa.brightcove.com, DNS:*.staging.brightcove.com
48
+ X509v3 Key Usage:
49
+ Digital Signature, Non Repudiation, Key Encipherment
50
+ Signature Algorithm: sha256WithRSAEncryption
51
+ a7:58:ec:1b:a5:c3:29:1d:71:c1:dd:b0:8c:ac:1d:34:b3:24:
52
+ 56:53:43:37:49:20:21:13:b3:1c:bc:d9:a3:e3:56:49:15:56:
53
+ 40:51:6f:cf:9e:c1:c2:ad:08:67:b1:bd:a6:11:3b:35:65:06:
54
+ b3:ff:de:36:93:86:10:45:e9:36:0a:5b:26:f0:23:82:8f:83:
55
+ 9f:1d:3f:be:ab:54:b3:f6:6c:7d:7b:67:6f:27:f7:f9:fa:30:
56
+ 27:1e:70:e4:05:85:ac:ad:d8:a5:45:83:54:68:0a:1d:fa:c2:
57
+ 05:46:41:d3:ad:a9:97:db:7a:fa:77:e1:0f:b0:29:09:da:15:
58
+ 2c:f1:d4:0f:a4:ce:90:fe:54:23:20:5c:68:3d:3a:06:0e:83:
59
+ ab:3a:3e:43:84:2f:71:5f:d9:c8:29:d1:35:51:c2:c2:57:75:
60
+ 8b:10:1e:cd:c0:8b:ca:b1:31:bb:5c:cf:03:52:05:f1:a8:0e:
61
+ bc:ca:ff:1a:7d:cf:22:fb:85:13:22:96:cb:dd:2b:00:68:5c:
62
+ ce:cd:d6:e7:5d:f1:fe:9e:60:07:7e:df:2d:d5:99:74:b3:90:
63
+ 33:55:da:18:7c:83:31:80:59:b1:a5:53:2f:5c:f2:86:d1:6f:
64
+ eb:fe:68:5d:a3:0b:52:36:d8:77:40:24:fc:ed:5c:72:7a:23:
65
+ e5:2f:bb:6b
66
+ -----BEGIN CERTIFICATE-----
67
+ MIIFTjCCBDagAwIBAgICEA0wDQYJKoZIhvcNAQELBQAwgZQxCzAJBgNVBAYTAlVT
68
+ MRYwFAYDVQQIEw1NYXNzYWNodXNldHRzMQ8wDQYDVQQHEwZCb3N0b24xGDAWBgNV
69
+ BAoTD0JyaWdodGNvdmUgSW5jLjEcMBoGA1UECxMTU3lzdGVtcyBFbmdpbmVlcmlu
70
+ ZzEkMCIGCSqGSIb3DQEJARYVc3lzZW5nQGJyaWdodGNvdmUuY29tMB4XDTE2MDEy
71
+ MjE1NDkxOVoXDTI2MDExOTE1NDkxOVowgZ4xCzAJBgNVBAYTAlVTMRYwFAYDVQQI
72
+ Ew1NYXNzYWNodXNldHRzMRgwFgYDVQQKEw9CcmlnaHRjb3ZlIEluYy4xHDAaBgNV
73
+ BAsTE1N5c3RlbXMgRW5naW5lZXJpbmcxGTAXBgNVBAMUECouYnJpZ2h0Y292ZS5j
74
+ b20xJDAiBgkqhkiG9w0BCQEWFXN5c2VuZ0BicmlnaHRjb3ZlLmNvbTCCASIwDQYJ
75
+ KoZIhvcNAQEBBQADggEPADCCAQoCggEBAMV5iO7DgSrxZvExSISqGAmDmgxPrqXO
76
+ k3D6jZU7fMAPGwaVGCXvfaH7uQgTbA9LiNV01svgY5qNe+zQ/t2qZ4uimZDofJEm
77
+ /+TgC/nhG6h5LC/GevmwJSrTo48r90nv0/LBCKNXbM4ARVXT20GVa2C8xrvYOrS3
78
+ LtYyfZo3Qi7YRHUiR7T5ExVGKfFpbqfajJrxtY6NsKs+KRVbR8mVv3wpEPjJH3jj
79
+ 5xoksNqBJx2lZhrjxXssYVgYdqtjAKqcnPalTJA0KMEMbYP/8zlZa+t9l2aSNsYa
80
+ biDR1M7Q8RBzgdx3eZU/r91kLbUGf9YEV2iZBQBisYGy37i4fdi/e+UCAwEAAaOC
81
+ AZwwggGYMAkGA1UdEwQCMAAwLAYJYIZIAYb4QgENBB8WHU9wZW5TU0wgR2VuZXJh
82
+ dGVkIENlcnRpZmljYXRlMB0GA1UdDgQWBBQljGSz9Um9ih9CmtZpnLQE/kuCwjCB
83
+ yQYDVR0jBIHBMIG+gBTR4KzeAYDblNopZg+pSBG/Yp9RnqGBmqSBlzCBlDELMAkG
84
+ A1UEBhMCVVMxFjAUBgNVBAgTDU1hc3NhY2h1c2V0dHMxDzANBgNVBAcTBkJvc3Rv
85
+ bjEYMBYGA1UEChMPQnJpZ2h0Y292ZSBJbmMuMRwwGgYDVQQLExNTeXN0ZW1zIEVu
86
+ Z2luZWVyaW5nMSQwIgYJKoZIhvcNAQkBFhVzeXNlbmdAYnJpZ2h0Y292ZS5jb22C
87
+ CQDCO5p3nGPeKzBlBgNVHREEXjBcghAqLmJyaWdodGNvdmUuY29tghMqLnFhLmJy
88
+ aWdodGNvdmUuY29tghkqLm9hdXRoLnFhLmJyaWdodGNvdmUuY29tghgqLnN0YWdp
89
+ bmcuYnJpZ2h0Y292ZS5jb20wCwYDVR0PBAQDAgXgMA0GCSqGSIb3DQEBCwUAA4IB
90
+ AQCnWOwbpcMpHXHB3bCMrB00syRWU0M3SSAhE7McvNmj41ZJFVZAUW/PnsHCrQhn
91
+ sb2mETs1ZQaz/942k4YQRek2Clsm8COCj4OfHT++q1Sz9mx9e2dvJ/f5+jAnHnDk
92
+ BYWsrdilRYNUaAod+sIFRkHTramX23r6d+EPsCkJ2hUs8dQPpM6Q/lQjIFxoPToG
93
+ DoOrOj5DhC9xX9nIKdE1UcLCV3WLEB7NwIvKsTG7XM8DUgXxqA68yv8afc8i+4UT
94
+ IpbL3SsAaFzOzdbnXfH+nmAHft8t1Zl0s5AzVdoYfIMxgFmxpVMvXPKG0W/r/mhd
95
+ owtSNth3QCT87VxyeiPlL7tr
96
+ -----END CERTIFICATE-----
@@ -0,0 +1,62 @@
1
+ import '@testing-library/jest-dom';
2
+ import 'jest-canvas-mock';
3
+ import ResizeObserver from 'resize-observer-polyfill';
4
+
5
+ // eslint-disable-next-line no-undef
6
+ jest.mock('js/hooks/useGetPlayers', () => {
7
+ // eslint-disable-next-line no-undef
8
+ return jest.fn().mockReturnValue({
9
+ isLoading: false,
10
+ data: {
11
+ items: [
12
+ {
13
+ account_id: 'test',
14
+ id: 'default',
15
+ name: 'default',
16
+ description: 'test',
17
+ branches: { master: { configuration: {} } },
18
+ created_at: 'test',
19
+ embed_count: 2,
20
+ url: 'test',
21
+ },
22
+ ],
23
+ },
24
+ });
25
+ });
26
+
27
+ // eslint-disable-next-line no-undef
28
+ jest.mock('react-i18next', () => ({
29
+ useTranslation: () => {
30
+ return {
31
+ t: (str) => str,
32
+ i18n: {
33
+ changeLanguage: () =>
34
+ new Promise(() => {
35
+ return;
36
+ }),
37
+ },
38
+ };
39
+ },
40
+ initReactI18next: {
41
+ type: '3rdParty',
42
+ init: () => {
43
+ return;
44
+ },
45
+ },
46
+ Trans: () => '<div/>',
47
+ }));
48
+
49
+ global.StudioModule = {
50
+ config: {
51
+ product: {
52
+ env: 'qa',
53
+ },
54
+ },
55
+ getCurrentUserAccount: () => {
56
+ return {
57
+ roles: [],
58
+ };
59
+ },
60
+ };
61
+
62
+ global.ResizeObserver = ResizeObserver;
@@ -0,0 +1,4 @@
1
+ // stub out modules that you want to load for tests here
2
+ module.exports = {
3
+ process: () => '',
4
+ };
package/jest.config.js ADDED
@@ -0,0 +1,24 @@
1
+ module.exports = {
2
+ transform: {
3
+ '\\.(css|sass)$': '<rootDir>/jest/jest.stub.js',
4
+ '^.+\\.(t|j)sx?$': 'babel-jest',
5
+ },
6
+ moduleNameMapper: {
7
+ '^js/(.*)$': '<rootDir>/src/js/$1',
8
+ '^styles/(.*)$': '<rootDir>/src/styles/$1',
9
+ '^mocks/(.*)$': '<rootDir>/__mocks__/$1',
10
+ '^translations/(.*)$': '<rootDir>/src/translations/$1',
11
+ '\\.(css|sass)$': '<rootDir>/jest/jest.stub.js',
12
+ },
13
+ testPathIgnorePatterns : [
14
+ './build/',
15
+ ],
16
+ setupFilesAfterEnv: ['<rootDir>/jest/jest.setup.js'],
17
+ coveragePathIgnorePatterns: [
18
+ '/node_modules/',
19
+ '/jest/',
20
+ '/locales/',
21
+ '/styles/',
22
+ ],
23
+ testEnvironment: 'jest-environment-jsdom',
24
+ };
package/package.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@brightcove/components-embed-code-modal",
3
- "version": "1.0.7",
3
+ "version": "1.0.8",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "https://bithub.brightcove.com/studio-ui-kit/studio-components-embed-code-modal.git"
7
7
  },
8
8
  "description": "Embed Code Modal used for publishing videos",
9
- "main": "./index.js",
9
+ "main": "build/index.js",
10
10
  "types": "./src/index.d.ts",
11
11
  "author": "Campaign Team",
12
12
  "scripts": {
@@ -15,14 +15,25 @@
15
15
  "build:watch": "NODE_ENV=production webpack --watch",
16
16
  "clean": "rm -r build",
17
17
  "lint": "eslint \"{src,__tests__,demo}/**/*.{ts,tsx,js,jsx}\"",
18
+ "lint:staged": "lint-staged",
18
19
  "type-check": "tsc",
19
20
  "notify": "notify-change -m proj-projstudio",
21
+ "prepare": "husky install",
20
22
  "release": "release-it",
21
23
  "test": "jest",
22
24
  "test:coverage": "jest --coverage",
23
25
  "test:watch": "jest --watch",
24
26
  "pre-commit": "lint-staged && npm test"
25
27
  },
28
+ "lint-staged": {
29
+ "*.{ts,tsx,js,jsx}": [
30
+ "eslint --fix",
31
+ "prettier --write"
32
+ ],
33
+ "*.{css,scss}": [
34
+ "prettier --write"
35
+ ]
36
+ },
26
37
  "devDependencies": {
27
38
  "@babel/core": "^7.20.7",
28
39
  "@babel/plugin-proposal-class-properties": "^7.16.0",
@@ -95,6 +106,5 @@
95
106
  "react-dom": "^17.0.2 || ^18.0.0",
96
107
  "react-i18next": ">=11",
97
108
  "react-query": "^3.38.0"
98
- },
99
- "module": "./index.js"
100
- }
109
+ }
110
+ }
@@ -0,0 +1,18 @@
1
+ const fs = require('fs');
2
+ const path = require('path');
3
+ const pkg = require('../package.json');
4
+
5
+ const BUILD_DIR = path.resolve(__dirname, '..', 'build');
6
+
7
+ pkg.name = '@brightcove/components-embed-code-modal'
8
+ pkg.main = './index.js';
9
+ pkg.module = './index.js';
10
+
11
+ delete pkg.scripts.prepare;
12
+ delete pkg.scripts['lint:staged'];
13
+ delete pkg['lint-staged'];
14
+
15
+ fs.writeFileSync(
16
+ path.join(BUILD_DIR, 'package.json'),
17
+ JSON.stringify(pkg, null, 2)
18
+ );
package/src/index.ts ADDED
@@ -0,0 +1,17 @@
1
+ import EmbedCodeModal, { type EmbedCodeModalProps } from './js/EmbedCodeModal';
2
+ import {
3
+ type VideoPayload,
4
+ type PlayerPayload,
5
+ type ProjectPayload,
6
+ EmbedCodeModalTypes,
7
+ } from 'js/types/EmbedCodeModalProps';
8
+
9
+ export {
10
+ EmbedCodeModal,
11
+ VideoPayload,
12
+ PlayerPayload,
13
+ ProjectPayload,
14
+ EmbedCodeModalTypes,
15
+ };
16
+
17
+ export type { EmbedCodeModalProps };
@@ -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
+ };