@tailor-cms/ce-brightcove-video-display 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1 @@
1
+ # Content element `Display` component
package/dist/index.cjs ADDED
@@ -0,0 +1,257 @@
1
+ "use strict";
2
+ var import_index = require("./index.css");
3
+ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toStringTag]: { value: "Module" } });
4
+ const vue = require("vue");
5
+ var type = "BRIGHTCOVE_VIDEO";
6
+ var name = "Brightcove Video";
7
+ var initState = () => ({});
8
+ var ui = {
9
+ // Display icon, https://pictogrammers.com/library/mdi/
10
+ icon: "mdi-video",
11
+ // Does element support only full width or can be used within layouts
12
+ // (e.g. 50/50 layout)
13
+ forceFullWidth: false
14
+ };
15
+ var manifest$1 = {
16
+ type,
17
+ version: "1.0",
18
+ name,
19
+ ssr: false,
20
+ initState,
21
+ ui
22
+ };
23
+ var index_default = manifest$1;
24
+ function normalize(strArray) {
25
+ var resultArray = [];
26
+ if (strArray.length === 0) {
27
+ return "";
28
+ }
29
+ if (typeof strArray[0] !== "string") {
30
+ throw new TypeError("Url must be a string. Received " + strArray[0]);
31
+ }
32
+ if (strArray[0].match(/^[^/:]+:\/*$/) && strArray.length > 1) {
33
+ var first = strArray.shift();
34
+ strArray[0] = first + strArray[0];
35
+ }
36
+ if (strArray[0].match(/^file:\/\/\//)) {
37
+ strArray[0] = strArray[0].replace(/^([^/:]+):\/*/, "$1:///");
38
+ } else {
39
+ strArray[0] = strArray[0].replace(/^([^/:]+):\/*/, "$1://");
40
+ }
41
+ for (var i = 0; i < strArray.length; i++) {
42
+ var component = strArray[i];
43
+ if (typeof component !== "string") {
44
+ throw new TypeError("Url must be a string. Received " + component);
45
+ }
46
+ if (component === "") {
47
+ continue;
48
+ }
49
+ if (i > 0) {
50
+ component = component.replace(/^[\/]+/, "");
51
+ }
52
+ if (i < strArray.length - 1) {
53
+ component = component.replace(/[\/]+$/, "");
54
+ } else {
55
+ component = component.replace(/[\/]+$/, "/");
56
+ }
57
+ resultArray.push(component);
58
+ }
59
+ var str = resultArray.join("/");
60
+ str = str.replace(/\/(\?|&|#[^!])/g, "$1");
61
+ var parts = str.split("?");
62
+ str = parts.shift() + (parts.length > 0 ? "?" : "") + parts.join("&");
63
+ return str;
64
+ }
65
+ function urlJoin() {
66
+ var input;
67
+ if (typeof arguments[0] === "object") {
68
+ input = arguments[0];
69
+ } else {
70
+ input = [].slice.call(arguments);
71
+ }
72
+ return normalize(input);
73
+ }
74
+ const _hoisted_1$1 = { class: "brightcove-player" };
75
+ const BASE_URL = "//players.brightcove.net/";
76
+ const _sfc_main$1 = /* @__PURE__ */ vue.defineComponent({
77
+ __name: "BrightcovePlayer",
78
+ props: {
79
+ accountId: {},
80
+ playerId: {},
81
+ videoId: {}
82
+ },
83
+ setup(__props, { expose: __expose }) {
84
+ const BrightcoveErrorCode = {
85
+ NOT_FOUND: "VIDEO_CLOUD_ERR_VIDEO_NOT_FOUND",
86
+ INVALID_CONFIG: "ERR_INVALID_CONFIGURATION"
87
+ };
88
+ const props = __props;
89
+ const error = vue.ref(null);
90
+ const style = vue.ref(null);
91
+ const script = vue.ref(null);
92
+ const player = vue.ref(null);
93
+ const playerUrl = vue.computed(
94
+ () => urlJoin(BASE_URL, props.accountId, `${props.playerId}_default`, "index.min.js")
95
+ );
96
+ const showError = vue.computed(() => {
97
+ if (!error.value) return false;
98
+ const code = error.value.code;
99
+ return code === BrightcoveErrorCode.NOT_FOUND || code === BrightcoveErrorCode.INVALID_CONFIG;
100
+ });
101
+ const createPlayer = () => {
102
+ const video = document.createElement("video");
103
+ Object.assign(video.dataset, {
104
+ account: props.accountId,
105
+ player: props.playerId,
106
+ videoId: props.videoId
107
+ });
108
+ video.className = "video-js";
109
+ video.setAttribute("controls", "");
110
+ return video;
111
+ };
112
+ const destroyPlayer = () => {
113
+ if (player.value) {
114
+ player.value.pause();
115
+ player.value.dispose();
116
+ player.value = null;
117
+ }
118
+ error.value = null;
119
+ if (script.value) document.body.removeChild(script.value);
120
+ script.value = null;
121
+ if (style.value) document.head.removeChild(style.value);
122
+ style.value = null;
123
+ if (videoWrapper.value) videoWrapper.value.innerHTML = "";
124
+ };
125
+ const initPlayer = (url = playerUrl.value) => {
126
+ destroyPlayer();
127
+ script.value = loadScript(url, document.body, (err) => {
128
+ var _a;
129
+ if (err) {
130
+ onError({
131
+ code: BrightcoveErrorCode.INVALID_CONFIG,
132
+ accountId: props.accountId,
133
+ playerId: props.playerId
134
+ });
135
+ return;
136
+ }
137
+ style.value = setTheme();
138
+ const video = createPlayer();
139
+ (_a = videoWrapper.value) == null ? void 0 : _a.appendChild(video);
140
+ player.value = window.bc(video);
141
+ player.value.autoplay(false);
142
+ player.value.on("error", () => onError(player.value.error()));
143
+ });
144
+ };
145
+ const setTheme = () => {
146
+ const cls = `bc-style-${props.playerId}-default`;
147
+ const theme = document.head.getElementsByClassName(cls)[0];
148
+ return document.head.insertBefore(theme, null);
149
+ };
150
+ const pause = () => {
151
+ if (player.value) player.value.pause();
152
+ };
153
+ const onError = (err) => {
154
+ error.value = err;
155
+ };
156
+ vue.watch(playerUrl, () => {
157
+ if (!videoWrapper.value) return;
158
+ initPlayer();
159
+ });
160
+ vue.watch(
161
+ () => props.videoId,
162
+ () => {
163
+ if (!videoWrapper.value) return;
164
+ initPlayer();
165
+ }
166
+ );
167
+ vue.onMounted(() => {
168
+ initPlayer();
169
+ });
170
+ vue.onBeforeUnmount(() => {
171
+ destroyPlayer();
172
+ });
173
+ const videoWrapper = vue.ref(null);
174
+ function loadScript(url, dest, cb) {
175
+ const script2 = document.createElement("script");
176
+ script2.src = url;
177
+ script2.async = false;
178
+ script2.onload = () => cb(null, script2);
179
+ script2.onerror = () => cb(new Error("Error loading script!"), script2);
180
+ return dest.appendChild(script2);
181
+ }
182
+ __expose({
183
+ pause
184
+ });
185
+ return (_ctx, _cache) => {
186
+ const _component_VIcon = vue.resolveComponent("VIcon");
187
+ const _component_VSheet = vue.resolveComponent("VSheet");
188
+ return vue.openBlock(), vue.createElementBlock("div", _hoisted_1$1, [
189
+ showError.value ? (vue.openBlock(), vue.createBlock(_component_VSheet, {
190
+ key: 0,
191
+ class: "h-100 d-flex flex-column align-center justify-center opacity-90",
192
+ color: "black"
193
+ }, {
194
+ default: vue.withCtx(() => [
195
+ vue.createVNode(_component_VIcon, {
196
+ class: "mb-2",
197
+ icon: "mdi-alert",
198
+ size: "42"
199
+ }),
200
+ _cache[0] || (_cache[0] = vue.createElementVNode("div", { class: "text-h6" }, "Error loading media!", -1))
201
+ ]),
202
+ _: 1
203
+ })) : vue.createCommentVNode("", true),
204
+ vue.withDirectives(vue.createElementVNode("div", {
205
+ ref_key: "videoWrapper",
206
+ ref: videoWrapper,
207
+ class: "wrapper"
208
+ }, null, 512), [
209
+ [vue.vShow, !showError.value]
210
+ ])
211
+ ]);
212
+ };
213
+ }
214
+ });
215
+ const _export_sfc = (sfc, props) => {
216
+ const target = sfc.__vccOpts || sfc;
217
+ for (const [key, val] of props) {
218
+ target[key] = val;
219
+ }
220
+ return target;
221
+ };
222
+ const BrightcovePlayer = /* @__PURE__ */ _export_sfc(_sfc_main$1, [["__scopeId", "data-v-dd41e47c"]]);
223
+ const _hoisted_1 = { class: "tce-root" };
224
+ const _sfc_main = /* @__PURE__ */ vue.defineComponent({
225
+ __name: "Display",
226
+ props: {
227
+ id: {},
228
+ data: {},
229
+ userState: {}
230
+ },
231
+ emits: ["interaction"],
232
+ setup(__props) {
233
+ const props = __props;
234
+ const isConfigured = vue.computed(
235
+ () => props.data.accountId && props.data.playerId && props.data.videoId
236
+ );
237
+ return (_ctx, _cache) => {
238
+ return vue.openBlock(), vue.createElementBlock("div", _hoisted_1, [
239
+ isConfigured.value ? (vue.openBlock(), vue.createBlock(BrightcovePlayer, {
240
+ key: 0,
241
+ ref: "player",
242
+ "account-id": _ctx.data.accountId,
243
+ "player-id": _ctx.data.playerId,
244
+ "video-id": _ctx.data.videoId,
245
+ class: "player"
246
+ }, null, 8, ["account-id", "player-id", "video-id"])) : vue.createCommentVNode("", true)
247
+ ]);
248
+ };
249
+ }
250
+ });
251
+ const Display = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-5cbb7746"]]);
252
+ const manifest = {
253
+ ...index_default,
254
+ Display
255
+ };
256
+ exports.Display = Display;
257
+ exports.default = manifest;
package/dist/index.css ADDED
@@ -0,0 +1,9 @@
1
+ .brightcove-player[data-v-dd41e47c],
2
+ .brightcove-player[data-v-dd41e47c] .video-js {
3
+ width: 100%;
4
+ height: 360px;
5
+ }
6
+ .tce-root[data-v-5cbb7746] {
7
+ font-family: Arial, Helvetica, sans-serif;
8
+ font-size: 1rem;
9
+ }
package/dist/index.js ADDED
@@ -0,0 +1,257 @@
1
+ import "./index.css";
2
+ import { defineComponent, ref, computed, watch, onMounted, onBeforeUnmount, resolveComponent, createElementBlock, openBlock, createBlock, createCommentVNode, withDirectives, withCtx, createVNode, createElementVNode, vShow } from "vue";
3
+ var type = "BRIGHTCOVE_VIDEO";
4
+ var name = "Brightcove Video";
5
+ var initState = () => ({});
6
+ var ui = {
7
+ // Display icon, https://pictogrammers.com/library/mdi/
8
+ icon: "mdi-video",
9
+ // Does element support only full width or can be used within layouts
10
+ // (e.g. 50/50 layout)
11
+ forceFullWidth: false
12
+ };
13
+ var manifest$1 = {
14
+ type,
15
+ version: "1.0",
16
+ name,
17
+ ssr: false,
18
+ initState,
19
+ ui
20
+ };
21
+ var index_default = manifest$1;
22
+ function normalize(strArray) {
23
+ var resultArray = [];
24
+ if (strArray.length === 0) {
25
+ return "";
26
+ }
27
+ if (typeof strArray[0] !== "string") {
28
+ throw new TypeError("Url must be a string. Received " + strArray[0]);
29
+ }
30
+ if (strArray[0].match(/^[^/:]+:\/*$/) && strArray.length > 1) {
31
+ var first = strArray.shift();
32
+ strArray[0] = first + strArray[0];
33
+ }
34
+ if (strArray[0].match(/^file:\/\/\//)) {
35
+ strArray[0] = strArray[0].replace(/^([^/:]+):\/*/, "$1:///");
36
+ } else {
37
+ strArray[0] = strArray[0].replace(/^([^/:]+):\/*/, "$1://");
38
+ }
39
+ for (var i = 0; i < strArray.length; i++) {
40
+ var component = strArray[i];
41
+ if (typeof component !== "string") {
42
+ throw new TypeError("Url must be a string. Received " + component);
43
+ }
44
+ if (component === "") {
45
+ continue;
46
+ }
47
+ if (i > 0) {
48
+ component = component.replace(/^[\/]+/, "");
49
+ }
50
+ if (i < strArray.length - 1) {
51
+ component = component.replace(/[\/]+$/, "");
52
+ } else {
53
+ component = component.replace(/[\/]+$/, "/");
54
+ }
55
+ resultArray.push(component);
56
+ }
57
+ var str = resultArray.join("/");
58
+ str = str.replace(/\/(\?|&|#[^!])/g, "$1");
59
+ var parts = str.split("?");
60
+ str = parts.shift() + (parts.length > 0 ? "?" : "") + parts.join("&");
61
+ return str;
62
+ }
63
+ function urlJoin() {
64
+ var input;
65
+ if (typeof arguments[0] === "object") {
66
+ input = arguments[0];
67
+ } else {
68
+ input = [].slice.call(arguments);
69
+ }
70
+ return normalize(input);
71
+ }
72
+ const _hoisted_1$1 = { class: "brightcove-player" };
73
+ const BASE_URL = "//players.brightcove.net/";
74
+ const _sfc_main$1 = /* @__PURE__ */ defineComponent({
75
+ __name: "BrightcovePlayer",
76
+ props: {
77
+ accountId: {},
78
+ playerId: {},
79
+ videoId: {}
80
+ },
81
+ setup(__props, { expose: __expose }) {
82
+ const BrightcoveErrorCode = {
83
+ NOT_FOUND: "VIDEO_CLOUD_ERR_VIDEO_NOT_FOUND",
84
+ INVALID_CONFIG: "ERR_INVALID_CONFIGURATION"
85
+ };
86
+ const props = __props;
87
+ const error = ref(null);
88
+ const style = ref(null);
89
+ const script = ref(null);
90
+ const player = ref(null);
91
+ const playerUrl = computed(
92
+ () => urlJoin(BASE_URL, props.accountId, `${props.playerId}_default`, "index.min.js")
93
+ );
94
+ const showError = computed(() => {
95
+ if (!error.value) return false;
96
+ const code = error.value.code;
97
+ return code === BrightcoveErrorCode.NOT_FOUND || code === BrightcoveErrorCode.INVALID_CONFIG;
98
+ });
99
+ const createPlayer = () => {
100
+ const video = document.createElement("video");
101
+ Object.assign(video.dataset, {
102
+ account: props.accountId,
103
+ player: props.playerId,
104
+ videoId: props.videoId
105
+ });
106
+ video.className = "video-js";
107
+ video.setAttribute("controls", "");
108
+ return video;
109
+ };
110
+ const destroyPlayer = () => {
111
+ if (player.value) {
112
+ player.value.pause();
113
+ player.value.dispose();
114
+ player.value = null;
115
+ }
116
+ error.value = null;
117
+ if (script.value) document.body.removeChild(script.value);
118
+ script.value = null;
119
+ if (style.value) document.head.removeChild(style.value);
120
+ style.value = null;
121
+ if (videoWrapper.value) videoWrapper.value.innerHTML = "";
122
+ };
123
+ const initPlayer = (url = playerUrl.value) => {
124
+ destroyPlayer();
125
+ script.value = loadScript(url, document.body, (err) => {
126
+ var _a;
127
+ if (err) {
128
+ onError({
129
+ code: BrightcoveErrorCode.INVALID_CONFIG,
130
+ accountId: props.accountId,
131
+ playerId: props.playerId
132
+ });
133
+ return;
134
+ }
135
+ style.value = setTheme();
136
+ const video = createPlayer();
137
+ (_a = videoWrapper.value) == null ? void 0 : _a.appendChild(video);
138
+ player.value = window.bc(video);
139
+ player.value.autoplay(false);
140
+ player.value.on("error", () => onError(player.value.error()));
141
+ });
142
+ };
143
+ const setTheme = () => {
144
+ const cls = `bc-style-${props.playerId}-default`;
145
+ const theme = document.head.getElementsByClassName(cls)[0];
146
+ return document.head.insertBefore(theme, null);
147
+ };
148
+ const pause = () => {
149
+ if (player.value) player.value.pause();
150
+ };
151
+ const onError = (err) => {
152
+ error.value = err;
153
+ };
154
+ watch(playerUrl, () => {
155
+ if (!videoWrapper.value) return;
156
+ initPlayer();
157
+ });
158
+ watch(
159
+ () => props.videoId,
160
+ () => {
161
+ if (!videoWrapper.value) return;
162
+ initPlayer();
163
+ }
164
+ );
165
+ onMounted(() => {
166
+ initPlayer();
167
+ });
168
+ onBeforeUnmount(() => {
169
+ destroyPlayer();
170
+ });
171
+ const videoWrapper = ref(null);
172
+ function loadScript(url, dest, cb) {
173
+ const script2 = document.createElement("script");
174
+ script2.src = url;
175
+ script2.async = false;
176
+ script2.onload = () => cb(null, script2);
177
+ script2.onerror = () => cb(new Error("Error loading script!"), script2);
178
+ return dest.appendChild(script2);
179
+ }
180
+ __expose({
181
+ pause
182
+ });
183
+ return (_ctx, _cache) => {
184
+ const _component_VIcon = resolveComponent("VIcon");
185
+ const _component_VSheet = resolveComponent("VSheet");
186
+ return openBlock(), createElementBlock("div", _hoisted_1$1, [
187
+ showError.value ? (openBlock(), createBlock(_component_VSheet, {
188
+ key: 0,
189
+ class: "h-100 d-flex flex-column align-center justify-center opacity-90",
190
+ color: "black"
191
+ }, {
192
+ default: withCtx(() => [
193
+ createVNode(_component_VIcon, {
194
+ class: "mb-2",
195
+ icon: "mdi-alert",
196
+ size: "42"
197
+ }),
198
+ _cache[0] || (_cache[0] = createElementVNode("div", { class: "text-h6" }, "Error loading media!", -1))
199
+ ]),
200
+ _: 1
201
+ })) : createCommentVNode("", true),
202
+ withDirectives(createElementVNode("div", {
203
+ ref_key: "videoWrapper",
204
+ ref: videoWrapper,
205
+ class: "wrapper"
206
+ }, null, 512), [
207
+ [vShow, !showError.value]
208
+ ])
209
+ ]);
210
+ };
211
+ }
212
+ });
213
+ const _export_sfc = (sfc, props) => {
214
+ const target = sfc.__vccOpts || sfc;
215
+ for (const [key, val] of props) {
216
+ target[key] = val;
217
+ }
218
+ return target;
219
+ };
220
+ const BrightcovePlayer = /* @__PURE__ */ _export_sfc(_sfc_main$1, [["__scopeId", "data-v-dd41e47c"]]);
221
+ const _hoisted_1 = { class: "tce-root" };
222
+ const _sfc_main = /* @__PURE__ */ defineComponent({
223
+ __name: "Display",
224
+ props: {
225
+ id: {},
226
+ data: {},
227
+ userState: {}
228
+ },
229
+ emits: ["interaction"],
230
+ setup(__props) {
231
+ const props = __props;
232
+ const isConfigured = computed(
233
+ () => props.data.accountId && props.data.playerId && props.data.videoId
234
+ );
235
+ return (_ctx, _cache) => {
236
+ return openBlock(), createElementBlock("div", _hoisted_1, [
237
+ isConfigured.value ? (openBlock(), createBlock(BrightcovePlayer, {
238
+ key: 0,
239
+ ref: "player",
240
+ "account-id": _ctx.data.accountId,
241
+ "player-id": _ctx.data.playerId,
242
+ "video-id": _ctx.data.videoId,
243
+ class: "player"
244
+ }, null, 8, ["account-id", "player-id", "video-id"])) : createCommentVNode("", true)
245
+ ]);
246
+ };
247
+ }
248
+ });
249
+ const Display = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-5cbb7746"]]);
250
+ const manifest = {
251
+ ...index_default,
252
+ Display
253
+ };
254
+ export {
255
+ Display,
256
+ manifest as default
257
+ };
package/package.json ADDED
@@ -0,0 +1,42 @@
1
+ {
2
+ "name": "@tailor-cms/ce-brightcove-video-display",
3
+ "description": "Tailor CMS Brightcove video end-user component",
4
+ "author": "Studion <info@gostudion.com> (https://github.com/tailor-cms)",
5
+ "type": "module",
6
+ "version": "0.0.1",
7
+ "exports": {
8
+ ".": {
9
+ "import": "./dist/index.js",
10
+ "require": "./dist/index.cjs"
11
+ }
12
+ },
13
+ "main": "./dist/index.cjs",
14
+ "files": [
15
+ "dist"
16
+ ],
17
+ "peerDependencies": {
18
+ "vue": "^3.5.13"
19
+ },
20
+ "devDependencies": {
21
+ "@tailor-cms/eslint-config": "0.0.2",
22
+ "@types/lodash": "^4.17.12",
23
+ "@vitejs/plugin-vue": "^5.2.1",
24
+ "typescript": "^5.7.3",
25
+ "vite": "^6.1.0",
26
+ "vue-tsc": "^2.2.0",
27
+ "@tailor-cms/ce-brightcove-video-manifest": "0.0.1"
28
+ },
29
+ "dependencies": {
30
+ "lodash": "^4.17.21",
31
+ "url-join": "^5.0.0"
32
+ },
33
+ "publishConfig": {
34
+ "access": "public"
35
+ },
36
+ "scripts": {
37
+ "dev": "vite build --watch",
38
+ "build": "vue-tsc --noEmit && vite build",
39
+ "lint": "eslint --ext .js,.ts,.vue ./src",
40
+ "lint:fix": "pnpm lint --fix"
41
+ }
42
+ }