@rulab/adminjs-components 0.2.2 → 0.2.4-beta
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/dist/components/Editor/AudioOrVideoPlayer.d.ts +14 -0
- package/dist/components/Editor/AudioOrVideoPlayer.js +95 -0
- package/dist/components/Editor/MediaPlayer.d.ts +14 -0
- package/dist/components/Editor/MediaPlayer.js +109 -0
- package/dist/components/Editor/config.d.ts +2 -2
- package/dist/components/Editor/config.js +2 -6
- package/package.json +2 -3
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
declare const AudioOrVideoPlayer_base: any;
|
|
2
|
+
export declare class AudioOrVideoPlayer extends AudioOrVideoPlayer_base {
|
|
3
|
+
private inputEl?;
|
|
4
|
+
static get toolbox(): any;
|
|
5
|
+
private applyWrapperSizing;
|
|
6
|
+
private applyMediaSizing;
|
|
7
|
+
private replaceMediaTag;
|
|
8
|
+
private syncMediaByInputValue;
|
|
9
|
+
render(): HTMLElement;
|
|
10
|
+
save(blockContent: HTMLElement): {
|
|
11
|
+
src: string;
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
export {};
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
// @ts-ignore
|
|
2
|
+
import AudioPlayer from "editorjs-audio-player";
|
|
3
|
+
const getFileExtension = (url) => {
|
|
4
|
+
try {
|
|
5
|
+
const pathname = new URL(url).pathname;
|
|
6
|
+
const filename = pathname.split("/").pop() ?? "";
|
|
7
|
+
return filename.includes(".") ? filename.split(".").pop()?.toLowerCase() ?? "" : "";
|
|
8
|
+
}
|
|
9
|
+
catch {
|
|
10
|
+
const cleanUrl = url.split("?")[0]?.split("#")[0] ?? "";
|
|
11
|
+
const filename = cleanUrl.split("/").pop() ?? "";
|
|
12
|
+
return filename.includes(".") ? filename.split(".").pop()?.toLowerCase() ?? "" : "";
|
|
13
|
+
}
|
|
14
|
+
};
|
|
15
|
+
const isMp4File = (url) => getFileExtension(url) === "mp4";
|
|
16
|
+
export class AudioOrVideoPlayer extends AudioPlayer {
|
|
17
|
+
inputEl;
|
|
18
|
+
static get toolbox() {
|
|
19
|
+
const baseToolbox = AudioPlayer.toolbox ?? {};
|
|
20
|
+
return {
|
|
21
|
+
...baseToolbox,
|
|
22
|
+
title: "mediaPlayer",
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
applyWrapperSizing(tag) {
|
|
26
|
+
const wrapper = this.nodes?.wrapper;
|
|
27
|
+
if (!wrapper) {
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
if (tag === "video") {
|
|
31
|
+
wrapper.style.height = "auto";
|
|
32
|
+
wrapper.style.minHeight = "7rem";
|
|
33
|
+
wrapper.style.justifyContent = "flex-start";
|
|
34
|
+
wrapper.style.gap = "8px";
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
wrapper.style.height = "";
|
|
38
|
+
wrapper.style.minHeight = "";
|
|
39
|
+
wrapper.style.justifyContent = "";
|
|
40
|
+
wrapper.style.gap = "";
|
|
41
|
+
}
|
|
42
|
+
applyMediaSizing(media, tag) {
|
|
43
|
+
if (tag === "video") {
|
|
44
|
+
media.style.maxHeight = "100px";
|
|
45
|
+
media.style.height = "auto";
|
|
46
|
+
media.style.width = "auto";
|
|
47
|
+
media.style.maxWidth = "100%";
|
|
48
|
+
media.style.display = "block";
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
media.style.maxHeight = "";
|
|
52
|
+
media.style.height = "";
|
|
53
|
+
media.style.width = "";
|
|
54
|
+
media.style.maxWidth = "";
|
|
55
|
+
media.style.display = "";
|
|
56
|
+
}
|
|
57
|
+
replaceMediaTag(targetTag) {
|
|
58
|
+
const currentMedia = this.nodes?.audio;
|
|
59
|
+
if (!currentMedia) {
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
if (currentMedia.tagName.toLowerCase() === targetTag) {
|
|
63
|
+
this.applyWrapperSizing(targetTag);
|
|
64
|
+
this.applyMediaSizing(currentMedia, targetTag);
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
const newMedia = document.createElement(targetTag);
|
|
68
|
+
const src = currentMedia.getAttribute("src");
|
|
69
|
+
newMedia.setAttribute("controls", "controls");
|
|
70
|
+
if (src) {
|
|
71
|
+
newMedia.setAttribute("src", src);
|
|
72
|
+
}
|
|
73
|
+
this.applyWrapperSizing(targetTag);
|
|
74
|
+
this.applyMediaSizing(newMedia, targetTag);
|
|
75
|
+
currentMedia.replaceWith(newMedia);
|
|
76
|
+
this.nodes.audio = newMedia;
|
|
77
|
+
}
|
|
78
|
+
syncMediaByInputValue = () => {
|
|
79
|
+
const value = this.inputEl?.value ?? "";
|
|
80
|
+
this.replaceMediaTag(isMp4File(value) ? "video" : "audio");
|
|
81
|
+
};
|
|
82
|
+
render() {
|
|
83
|
+
const wrapper = super.render();
|
|
84
|
+
this.inputEl = wrapper.querySelector('input[name="audioUrl"]');
|
|
85
|
+
this.syncMediaByInputValue();
|
|
86
|
+
this.inputEl?.addEventListener("change", this.syncMediaByInputValue);
|
|
87
|
+
return wrapper;
|
|
88
|
+
}
|
|
89
|
+
save(blockContent) {
|
|
90
|
+
const media = blockContent.querySelector("audio, video");
|
|
91
|
+
return {
|
|
92
|
+
src: media?.src ?? "",
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
declare const MediaPlayer_base: any;
|
|
2
|
+
export declare class MediaPlayer extends MediaPlayer_base {
|
|
3
|
+
private inputEl?;
|
|
4
|
+
static get toolbox(): any;
|
|
5
|
+
private applyWrapperSizing;
|
|
6
|
+
private applyMediaSizing;
|
|
7
|
+
private replaceMediaTag;
|
|
8
|
+
private syncMediaByInputValue;
|
|
9
|
+
render(): HTMLElement;
|
|
10
|
+
save(blockContent: HTMLElement): {
|
|
11
|
+
src: string;
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
export {};
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
// @ts-ignore
|
|
2
|
+
import AudioPlayer from "editorjs-audio-player";
|
|
3
|
+
const getFileExtension = (url) => {
|
|
4
|
+
try {
|
|
5
|
+
const pathname = new URL(url).pathname;
|
|
6
|
+
const filename = pathname.split("/").pop() ?? "";
|
|
7
|
+
return filename.includes(".") ? filename.split(".").pop()?.toLowerCase() ?? "" : "";
|
|
8
|
+
}
|
|
9
|
+
catch {
|
|
10
|
+
const cleanUrl = url.split("?")[0]?.split("#")[0] ?? "";
|
|
11
|
+
const filename = cleanUrl.split("/").pop() ?? "";
|
|
12
|
+
return filename.includes(".") ? filename.split(".").pop()?.toLowerCase() ?? "" : "";
|
|
13
|
+
}
|
|
14
|
+
};
|
|
15
|
+
const VIDEO_EXTENSIONS = new Set([
|
|
16
|
+
"mp4",
|
|
17
|
+
"m4v",
|
|
18
|
+
"webm",
|
|
19
|
+
"ogv",
|
|
20
|
+
"ogg",
|
|
21
|
+
"mov",
|
|
22
|
+
"m3u8",
|
|
23
|
+
"3gp",
|
|
24
|
+
"3g2",
|
|
25
|
+
]);
|
|
26
|
+
const isNativeVideoFile = (url) => VIDEO_EXTENSIONS.has(getFileExtension(url));
|
|
27
|
+
export class MediaPlayer extends AudioPlayer {
|
|
28
|
+
inputEl;
|
|
29
|
+
static get toolbox() {
|
|
30
|
+
const baseToolbox = AudioPlayer.toolbox ?? {};
|
|
31
|
+
return {
|
|
32
|
+
...baseToolbox,
|
|
33
|
+
title: "Media Player",
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
applyWrapperSizing(tag) {
|
|
37
|
+
const wrapper = this.nodes?.wrapper;
|
|
38
|
+
if (!wrapper) {
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
if (tag === "video") {
|
|
42
|
+
wrapper.style.height = "auto";
|
|
43
|
+
wrapper.style.minHeight = "7rem";
|
|
44
|
+
wrapper.style.justifyContent = "flex-start";
|
|
45
|
+
wrapper.style.gap = "8px";
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
wrapper.style.height = "";
|
|
49
|
+
wrapper.style.minHeight = "";
|
|
50
|
+
wrapper.style.justifyContent = "";
|
|
51
|
+
wrapper.style.gap = "";
|
|
52
|
+
}
|
|
53
|
+
applyMediaSizing(media, tag) {
|
|
54
|
+
if (tag === "video") {
|
|
55
|
+
media.style.maxHeight = "100px";
|
|
56
|
+
media.style.height = "auto";
|
|
57
|
+
media.style.width = "auto";
|
|
58
|
+
media.style.maxWidth = "100%";
|
|
59
|
+
media.style.display = "block";
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
media.style.maxHeight = "";
|
|
63
|
+
media.style.height = "";
|
|
64
|
+
media.style.width = "";
|
|
65
|
+
media.style.maxWidth = "";
|
|
66
|
+
media.style.display = "";
|
|
67
|
+
}
|
|
68
|
+
replaceMediaTag(targetTag) {
|
|
69
|
+
const currentMedia = this.nodes?.audio;
|
|
70
|
+
if (!currentMedia) {
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
if (currentMedia.tagName.toLowerCase() === targetTag) {
|
|
74
|
+
this.applyWrapperSizing(targetTag);
|
|
75
|
+
this.applyMediaSizing(currentMedia, targetTag);
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
const newMedia = document.createElement(targetTag);
|
|
79
|
+
const src = currentMedia.getAttribute("src");
|
|
80
|
+
newMedia.setAttribute("controls", "controls");
|
|
81
|
+
if (src) {
|
|
82
|
+
newMedia.setAttribute("src", src);
|
|
83
|
+
}
|
|
84
|
+
this.applyWrapperSizing(targetTag);
|
|
85
|
+
this.applyMediaSizing(newMedia, targetTag);
|
|
86
|
+
currentMedia.replaceWith(newMedia);
|
|
87
|
+
this.nodes.audio = newMedia;
|
|
88
|
+
}
|
|
89
|
+
syncMediaByInputValue = () => {
|
|
90
|
+
const value = this.inputEl?.value ?? "";
|
|
91
|
+
this.replaceMediaTag(isNativeVideoFile(value) ? "video" : "audio");
|
|
92
|
+
};
|
|
93
|
+
render() {
|
|
94
|
+
const wrapper = super.render();
|
|
95
|
+
this.inputEl = wrapper.querySelector('input[name="audioUrl"]');
|
|
96
|
+
if (this.inputEl) {
|
|
97
|
+
this.inputEl.placeholder = "Enter your url of media file";
|
|
98
|
+
}
|
|
99
|
+
this.syncMediaByInputValue();
|
|
100
|
+
this.inputEl?.addEventListener("change", this.syncMediaByInputValue);
|
|
101
|
+
return wrapper;
|
|
102
|
+
}
|
|
103
|
+
save(blockContent) {
|
|
104
|
+
const media = blockContent.querySelector("audio, video");
|
|
105
|
+
return {
|
|
106
|
+
src: media?.src ?? "",
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import Quote from "@editorjs/quote";
|
|
2
2
|
import Table from "@editorjs/table";
|
|
3
|
+
import { MediaPlayer } from "./MediaPlayer.js";
|
|
3
4
|
export declare const EDITOR_TOOLS: {
|
|
4
5
|
paragraph: {
|
|
5
6
|
class: any;
|
|
@@ -25,6 +26,5 @@ export declare const EDITOR_TOOLS: {
|
|
|
25
26
|
class: typeof Quote;
|
|
26
27
|
inlineToolbar: boolean;
|
|
27
28
|
};
|
|
28
|
-
audioPlayer:
|
|
29
|
-
video: any;
|
|
29
|
+
audioPlayer: typeof MediaPlayer;
|
|
30
30
|
};
|
|
@@ -3,10 +3,7 @@ import List from "@editorjs/list";
|
|
|
3
3
|
import Paragraph from "@editorjs/paragraph";
|
|
4
4
|
import Quote from "@editorjs/quote";
|
|
5
5
|
import Table from "@editorjs/table";
|
|
6
|
-
|
|
7
|
-
import AudioPlayer from "editorjs-audio-player";
|
|
8
|
-
// @ts-ignore
|
|
9
|
-
import SimpleVideo from "simple-video-editorjs";
|
|
6
|
+
import { MediaPlayer } from "./MediaPlayer.js";
|
|
10
7
|
export const EDITOR_TOOLS = {
|
|
11
8
|
paragraph: {
|
|
12
9
|
class: Paragraph,
|
|
@@ -32,6 +29,5 @@ export const EDITOR_TOOLS = {
|
|
|
32
29
|
class: Quote,
|
|
33
30
|
inlineToolbar: true,
|
|
34
31
|
},
|
|
35
|
-
audioPlayer:
|
|
36
|
-
video: SimpleVideo,
|
|
32
|
+
audioPlayer: MediaPlayer,
|
|
37
33
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rulab/adminjs-components",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.4-beta",
|
|
4
4
|
"description": "Prebuilt AdminJS features for common UI needs.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -51,7 +51,6 @@
|
|
|
51
51
|
"editorjs-audio-player": "~0.0.3",
|
|
52
52
|
"editorjs-html": "~3.4.3",
|
|
53
53
|
"react-select": "^5.8.0",
|
|
54
|
-
"simple-video-editorjs": "~1.4.9",
|
|
55
54
|
"slugify": "^1.6.6"
|
|
56
55
|
},
|
|
57
56
|
"peerDependencies": {
|
|
@@ -69,10 +68,10 @@
|
|
|
69
68
|
"devDependencies": {
|
|
70
69
|
"@adminjs/design-system": "^4.1.1",
|
|
71
70
|
"@adminjs/upload": "^4.0.2",
|
|
72
|
-
"adminjs": "^7.8.1",
|
|
73
71
|
"@types/chroma-js": "^2.4.4",
|
|
74
72
|
"@types/node": "^20.11.24",
|
|
75
73
|
"@types/react": "^18.2.61",
|
|
74
|
+
"adminjs": "^7.8.1",
|
|
76
75
|
"react": "^18.2.0",
|
|
77
76
|
"styled-components": "^6.1.11",
|
|
78
77
|
"typescript": "^5.3.2"
|