@video-editor/ui 0.0.1-beta.7

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,3 @@
1
+ # @video-editor/ui
2
+
3
+ video editor UI package
@@ -0,0 +1,94 @@
1
+ import { ComponentOptionsMixin } from 'vue';
2
+ import { ComponentProvideOptions } from 'vue';
3
+ import { DefineComponent } from 'vue';
4
+ import { ITrackType } from '@video-editor/shared';
5
+ import { IVideoProtocol } from '@video-editor/shared';
6
+ import { PublicProps } from 'vue';
7
+ import { SegmentUnion } from '@video-editor/shared';
8
+ import { TrackUnion } from '@video-editor/shared';
9
+
10
+ declare type __VLS_Props = {
11
+ protocol?: IVideoProtocol | null;
12
+ currentTime: number;
13
+ zoom?: number;
14
+ snapStep?: number;
15
+ selectedSegmentId?: string | null;
16
+ trackTypes?: ITrackType[];
17
+ disableInteraction?: boolean;
18
+ };
19
+
20
+ declare const _default: DefineComponent<__VLS_Props, {}, {}, {}, {}, ComponentOptionsMixin, ComponentOptionsMixin, {} & {
21
+ "update:currentTime": (value: number) => any;
22
+ "update:zoom": (value: number) => any;
23
+ segmentClick: (payload: {
24
+ segment: SegmentUnion;
25
+ track: TrackUnion;
26
+ }) => any;
27
+ segmentDragEnd: (payload: SegmentDragPayload) => any;
28
+ segmentResizeEnd: (payload: SegmentResizePayload) => any;
29
+ "update:selectedSegmentId": (value: string | null) => any;
30
+ }, string, PublicProps, Readonly<__VLS_Props> & Readonly<{
31
+ "onUpdate:currentTime"?: ((value: number) => any) | undefined;
32
+ "onUpdate:zoom"?: ((value: number) => any) | undefined;
33
+ onSegmentClick?: ((payload: {
34
+ segment: SegmentUnion;
35
+ track: TrackUnion;
36
+ }) => any) | undefined;
37
+ onSegmentDragEnd?: ((payload: SegmentDragPayload) => any) | undefined;
38
+ onSegmentResizeEnd?: ((payload: SegmentResizePayload) => any) | undefined;
39
+ "onUpdate:selectedSegmentId"?: ((value: string | null) => any) | undefined;
40
+ }>, {
41
+ disableInteraction: boolean;
42
+ snapStep: number;
43
+ selectedSegmentId: string | null;
44
+ protocol: IVideoProtocol | null;
45
+ trackTypes: ITrackType[];
46
+ }, {}, {}, {}, string, ComponentProvideOptions, false, {}, HTMLDivElement>;
47
+ export default _default;
48
+
49
+ declare interface SegmentDragPayload {
50
+ segment: TimelineSegment;
51
+ track: TimelineTrack;
52
+ trackIndex: number;
53
+ segmentIndex: number;
54
+ startTime: number;
55
+ endTime: number;
56
+ targetTrackIndex: number;
57
+ targetTrackId: string;
58
+ isNewTrack: boolean;
59
+ newTrackInsertIndex?: number;
60
+ visualTrackIndex: number;
61
+ isValidTarget: boolean;
62
+ mouseDeltaY: number;
63
+ }
64
+
65
+ declare interface SegmentResizePayload {
66
+ segment: TimelineSegment;
67
+ track: TimelineTrack;
68
+ trackIndex: number;
69
+ segmentIndex: number;
70
+ startTime: number;
71
+ endTime: number;
72
+ edge: 'start' | 'end';
73
+ }
74
+
75
+ declare interface TimelineSegment {
76
+ id: string;
77
+ start: number;
78
+ end: number;
79
+ type?: string;
80
+ color?: string;
81
+ payload?: unknown;
82
+ }
83
+
84
+ declare interface TimelineTrack {
85
+ id: string;
86
+ label?: string;
87
+ type?: string;
88
+ color?: string;
89
+ isMain?: boolean;
90
+ payload?: unknown;
91
+ segments: TimelineSegment[];
92
+ }
93
+
94
+ export { }
@@ -0,0 +1,248 @@
1
+ import { defineComponent as C, reactive as N, watch as V, onBeforeUnmount as O, createElementBlock as c, openBlock as r, createCommentVNode as M, normalizeStyle as x, Fragment as S, renderList as D, createElementVNode as y, toDisplayString as _, computed as b, ref as P, createBlock as z, withCtx as H, unref as L } from "vue";
2
+ import { _ as U, V as J } from "./index-y5KhRW21.js";
3
+ import { generateThumbnails as Y } from "@video-editor/protocol";
4
+ import { isVideoFramesSegment as q } from "@video-editor/shared";
5
+ const G = { class: "frames-segment" }, K = {
6
+ key: 0,
7
+ class: "frames-segment__video"
8
+ }, Q = {
9
+ key: 1,
10
+ class: "frames-segment__placeholder"
11
+ }, W = { key: 0 }, X = { key: 1 }, Z = { key: 2 }, ee = {
12
+ key: 2,
13
+ class: "frames-segment__placeholder"
14
+ }, te = {
15
+ key: 3,
16
+ class: "frames-segment__badge"
17
+ }, ne = /* @__PURE__ */ C({
18
+ name: "FramesSegment",
19
+ __name: "FramesSegment",
20
+ props: {
21
+ segment: {}
22
+ },
23
+ setup(o) {
24
+ const g = o, t = N({ items: [], loading: !1, error: null });
25
+ let l = 0;
26
+ V(() => g.segment, (s, i) => {
27
+ if (!q(s))
28
+ return;
29
+ (!i || f(i, s)) && v(s);
30
+ }, { immediate: !0, deep: !0 }), O(() => {
31
+ h();
32
+ });
33
+ function f(s, i) {
34
+ return s.url !== i.url || s.startTime !== i.startTime || s.endTime !== i.endTime || s.fromTime !== i.fromTime;
35
+ }
36
+ async function v(s) {
37
+ if (!s.url)
38
+ return;
39
+ const i = ++l;
40
+ h(), t.loading = !0, t.error = null;
41
+ try {
42
+ const m = I(s), u = await Y(s.url, m);
43
+ if (l !== i)
44
+ return;
45
+ const T = u.map((k) => ({
46
+ tsMs: Math.round(k.ts / 1e3),
47
+ url: URL.createObjectURL(k.img)
48
+ }));
49
+ t.items = T, t.loading = !1;
50
+ } catch (m) {
51
+ if (l !== i)
52
+ return;
53
+ t.error = m instanceof Error ? m.message : String(m), t.loading = !1;
54
+ }
55
+ }
56
+ function I(s) {
57
+ const i = Math.max(s.fromTime ?? 0, 0) * 1e3, m = Math.max(s.endTime - s.startTime, 1), u = i + m * 1e3, k = Math.max(Math.floor((u - i) / 8), 2e5);
58
+ return { start: i, end: u, step: k };
59
+ }
60
+ function h() {
61
+ t.items.forEach((s) => URL.revokeObjectURL(s.url)), t.items = [];
62
+ }
63
+ function $() {
64
+ return {
65
+ backgroundImage: g.segment.url ? `url(${g.segment.url})` : "",
66
+ backgroundRepeat: "repeat-x",
67
+ backgroundSize: "56px 56px",
68
+ backgroundPosition: "left center"
69
+ };
70
+ }
71
+ return (s, i) => (r(), c("div", G, [
72
+ o.segment.type === "image" ? (r(), c("div", {
73
+ key: 0,
74
+ class: "frames-segment__image",
75
+ style: x($())
76
+ }, null, 4)) : o.segment.type === "video" ? (r(), c(S, { key: 1 }, [
77
+ t.items.length ? (r(), c("div", K, [
78
+ (r(!0), c(S, null, D(t.items, (m) => (r(), c("div", {
79
+ key: `${o.segment.id}-${m.tsMs}`,
80
+ class: "frames-segment__thumb",
81
+ style: x({ backgroundImage: `url(${m.url})` })
82
+ }, null, 4))), 128))
83
+ ])) : (r(), c("div", Q, [
84
+ t.loading ? (r(), c("span", W, "抽帧中…")) : t.error ? (r(), c("span", X, "生成失败")) : (r(), c("span", Z, "未生成缩略图"))
85
+ ]))
86
+ ], 64)) : (r(), c("div", ee, [
87
+ y("span", null, _(o.segment.type), 1)
88
+ ])),
89
+ o.segment.extra?.label ? (r(), c("span", te, _(o.segment.extra?.label), 1)) : M("", !0)
90
+ ]));
91
+ }
92
+ }), se = /* @__PURE__ */ U(ne, [["__scopeId", "data-v-dd7a5d19"]]), re = { class: "segment-base" }, ae = { class: "segment-base__content" }, oe = { class: "segment-base__pill segment-base__pill--primary" }, ie = { class: "segment-base__pill segment-base__pill--muted" }, ce = {
93
+ key: 0,
94
+ class: "segment-base__badge"
95
+ }, le = /* @__PURE__ */ C({
96
+ name: "SegmentBase",
97
+ __name: "SegmentBase",
98
+ props: {
99
+ segment: {},
100
+ trackType: {},
101
+ accentColor: { default: "#222226" }
102
+ },
103
+ setup(o) {
104
+ const g = o, t = b(() => {
105
+ const l = g.segment?.extra?.label;
106
+ return typeof l == "string" ? l : null;
107
+ });
108
+ return (l, f) => (r(), c("div", re, [
109
+ y("div", ae, [
110
+ y("span", oe, _(o.trackType), 1),
111
+ y("span", ie, _(o.segment.segmentType), 1)
112
+ ]),
113
+ t.value ? (r(), c("span", ce, _(t.value), 1)) : M("", !0)
114
+ ]));
115
+ }
116
+ }), me = /* @__PURE__ */ U(le, [["__scopeId", "data-v-d386af72"]]), de = { class: "ve-editor-segment__preview" }, E = "#222226", ue = 0.4, ge = /* @__PURE__ */ C({
117
+ name: "VideoEditorTimeline",
118
+ __name: "index",
119
+ props: {
120
+ protocol: { default: null },
121
+ currentTime: {},
122
+ zoom: {},
123
+ snapStep: { default: 0 },
124
+ selectedSegmentId: { default: null },
125
+ trackTypes: { default: void 0 },
126
+ disableInteraction: { type: Boolean, default: !1 }
127
+ },
128
+ emits: ["update:currentTime", "update:zoom", "update:selectedSegmentId", "segmentClick", "segmentDragEnd", "segmentResizeEnd"],
129
+ setup(o, { emit: g }) {
130
+ const t = o, l = g, f = P(t.selectedSegmentId ?? null);
131
+ V(() => t.selectedSegmentId, (e) => {
132
+ f.value = e ?? null;
133
+ });
134
+ const v = {
135
+ frames: E,
136
+ audio: "#0ea5e9",
137
+ text: "#16a34a",
138
+ sticker: "#f97316",
139
+ effect: "#a855f7",
140
+ filter: "#64748b"
141
+ }, I = b(() => t.protocol?.tracks?.length ? t.trackTypes?.length ? t.protocol.tracks.filter((e) => t.trackTypes?.includes(e.trackType)) : t.protocol.tracks : []), h = b(() => I.value.map((e, a) => {
142
+ const n = v[e.trackType] || E, d = s(n, ue), R = e.trackType === "frames" && e.isMain === !0;
143
+ return {
144
+ id: e.trackId || `${e.trackType}-${a}`,
145
+ label: e.trackType,
146
+ type: e.trackType,
147
+ color: n,
148
+ isMain: R,
149
+ payload: e,
150
+ segments: e.children.map((p) => ({
151
+ id: p.id,
152
+ start: p.startTime,
153
+ end: p.endTime,
154
+ type: p.segmentType,
155
+ color: d,
156
+ payload: p
157
+ }))
158
+ };
159
+ })), $ = b(() => {
160
+ if (!t.protocol?.tracks?.length)
161
+ return 0;
162
+ const e = t.protocol.tracks.flatMap((a) => a.children.map((n) => n.endTime));
163
+ return e.length ? Math.max(...e) : 0;
164
+ });
165
+ function s(e, a) {
166
+ const n = e.replace("#", "");
167
+ if (!(n.length === 3 || n.length === 6))
168
+ return e;
169
+ const d = n.length === 3 ? n.split("").map((B) => B + B).join("") : n, R = Number.parseInt(d.slice(0, 2), 16), p = Number.parseInt(d.slice(2, 4), 16), A = Number.parseInt(d.slice(4, 6), 16);
170
+ return `rgba(${R}, ${p}, ${A}, ${a})`;
171
+ }
172
+ function i(e) {
173
+ return e && typeof e == "object" && "segmentType" in e ? e : null;
174
+ }
175
+ function m(e) {
176
+ const a = e.payload;
177
+ if (a)
178
+ return a;
179
+ if (t.protocol)
180
+ return t.protocol.tracks.find((n) => n.trackId === e.id);
181
+ }
182
+ function u(e) {
183
+ f.value = e, l("update:selectedSegmentId", e);
184
+ }
185
+ function T(e) {
186
+ const a = i(e.segment.payload), n = m(e.track);
187
+ a && (u(a.id), n && l("segmentClick", { segment: a, track: n }));
188
+ }
189
+ function k(e) {
190
+ u(e.segment.id);
191
+ }
192
+ function F(e) {
193
+ l("segmentDragEnd", e);
194
+ }
195
+ function w(e) {
196
+ u(e.segment.id);
197
+ }
198
+ function j(e) {
199
+ l("segmentResizeEnd", e);
200
+ }
201
+ return (e, a) => (r(), z(J, {
202
+ tracks: h.value,
203
+ duration: $.value,
204
+ "current-time": o.currentTime,
205
+ zoom: o.zoom,
206
+ fps: o.protocol?.fps || 30,
207
+ "snap-step": o.snapStep,
208
+ "selected-segment-id": f.value ?? null,
209
+ "disable-interaction": o.disableInteraction,
210
+ "onUpdate:currentTime": a[0] || (a[0] = (n) => l("update:currentTime", n)),
211
+ "onUpdate:zoom": a[1] || (a[1] = (n) => l("update:zoom", n)),
212
+ onSegmentClick: T,
213
+ onSegmentDragStart: k,
214
+ onSegmentDragEnd: F,
215
+ onSegmentResizeStart: w,
216
+ onSegmentResizeEnd: j,
217
+ onBackgroundClick: a[2] || (a[2] = (n) => u(null))
218
+ }, {
219
+ segment: H(({ layout: n }) => [
220
+ (r(!0), c(S, null, D([i(n.segment.payload)], (d) => (r(), c(S, {
221
+ key: d?.id || n.segment.id
222
+ }, [
223
+ d ? (r(), c("div", {
224
+ key: 0,
225
+ class: "ve-editor-segment",
226
+ style: x({ "--ve-segment-accent": n.track.color || E })
227
+ }, [
228
+ y("div", de, [
229
+ d.segmentType === "frames" ? (r(), z(L(se), {
230
+ key: 0,
231
+ segment: d
232
+ }, null, 8, ["segment"])) : (r(), z(L(me), {
233
+ key: 1,
234
+ segment: d,
235
+ "track-type": n.track.type || "unknown",
236
+ "accent-color": n.track.color
237
+ }, null, 8, ["segment", "track-type", "accent-color"]))
238
+ ])
239
+ ], 4)) : M("", !0)
240
+ ], 64))), 128))
241
+ ]),
242
+ _: 1
243
+ }, 8, ["tracks", "duration", "current-time", "zoom", "fps", "snap-step", "selected-segment-id", "disable-interaction"]));
244
+ }
245
+ }), _e = /* @__PURE__ */ U(ge, [["__scopeId", "data-v-4ec48d8d"]]);
246
+ export {
247
+ _e as default
248
+ };
@@ -0,0 +1,200 @@
1
+ import { ComponentOptionsMixin } from 'vue';
2
+ import { ComponentProvideOptions } from 'vue';
3
+ import { DefineComponent } from 'vue';
4
+ import { PublicProps } from 'vue';
5
+ import { TimelineSegment as TimelineSegment_2 } from './types';
6
+
7
+ declare const __VLS_component: DefineComponent<__VLS_Props, {}, {}, {}, {}, ComponentOptionsMixin, ComponentOptionsMixin, {} & {
8
+ "update:currentTime": (value: number) => any;
9
+ "update:zoom": (value: number) => any;
10
+ segmentClick: (layout: SegmentLayout, event: MouseEvent) => any;
11
+ segmentDragStart: (payload: SegmentDragPayload) => any;
12
+ segmentDrag: (payload: SegmentDragPayload) => any;
13
+ segmentDragEnd: (payload: SegmentDragPayload) => any;
14
+ segmentResizeStart: (payload: SegmentResizePayload) => any;
15
+ segmentResize: (payload: SegmentResizePayload) => any;
16
+ segmentResizeEnd: (payload: SegmentResizePayload) => any;
17
+ backgroundClick: (event: MouseEvent) => any;
18
+ }, string, PublicProps, Readonly<__VLS_Props> & Readonly<{
19
+ "onUpdate:currentTime"?: ((value: number) => any) | undefined;
20
+ "onUpdate:zoom"?: ((value: number) => any) | undefined;
21
+ onSegmentClick?: ((layout: SegmentLayout, event: MouseEvent) => any) | undefined;
22
+ onSegmentDragStart?: ((payload: SegmentDragPayload) => any) | undefined;
23
+ onSegmentDrag?: ((payload: SegmentDragPayload) => any) | undefined;
24
+ onSegmentDragEnd?: ((payload: SegmentDragPayload) => any) | undefined;
25
+ onSegmentResizeStart?: ((payload: SegmentResizePayload) => any) | undefined;
26
+ onSegmentResize?: ((payload: SegmentResizePayload) => any) | undefined;
27
+ onSegmentResizeEnd?: ((payload: SegmentResizePayload) => any) | undefined;
28
+ onBackgroundClick?: ((event: MouseEvent) => any) | undefined;
29
+ }>, {
30
+ minZoom: number;
31
+ maxZoom: number;
32
+ disableInteraction: boolean;
33
+ snapStep: number;
34
+ trackHeight: number;
35
+ trackGap: number;
36
+ rulerHeight: number;
37
+ minSegmentDuration: number;
38
+ selectedSegmentId: string | null;
39
+ fps: number;
40
+ }, {}, {}, {}, string, ComponentProvideOptions, false, {
41
+ viewportRef: HTMLDivElement;
42
+ contentRef: HTMLDivElement;
43
+ tracksRef: HTMLDivElement;
44
+ }, HTMLDivElement>;
45
+
46
+ declare type __VLS_Props = {
47
+ tracks: TimelineTrack[];
48
+ currentTime: number;
49
+ duration?: number;
50
+ zoom?: number;
51
+ minZoom?: number;
52
+ maxZoom?: number;
53
+ snapStep?: number;
54
+ trackHeight?: number;
55
+ trackGap?: number;
56
+ rulerHeight?: number;
57
+ minSegmentDuration?: number;
58
+ selectedSegmentId?: string | null;
59
+ disableInteraction?: boolean;
60
+ fps?: number;
61
+ };
62
+
63
+ declare function __VLS_template(): {
64
+ attrs: Partial<{}>;
65
+ slots: {
66
+ toolbar?(_: {
67
+ zoom: number;
68
+ canZoomIn: boolean;
69
+ canZoomOut: boolean;
70
+ zoomIn: typeof zoomIn;
71
+ zoomOut: typeof zoomOut;
72
+ currentTime: number;
73
+ duration: number;
74
+ formatTime: typeof formatTime;
75
+ }): any;
76
+ ruler?(_: {
77
+ ticks: TimelineTick[];
78
+ pixelsPerMs: number;
79
+ }): any;
80
+ playhead?(_: {
81
+ left: number;
82
+ currentTime: number;
83
+ }): any;
84
+ track?(_: {
85
+ track: TimelineTrack;
86
+ index: number;
87
+ segments: SegmentLayout[];
88
+ pixelsPerMs: number;
89
+ height: number;
90
+ }): any;
91
+ segment?(_: {
92
+ layout: SegmentLayout;
93
+ segment: TimelineSegment_2;
94
+ track: TimelineTrack;
95
+ isSelected: boolean;
96
+ }): any;
97
+ segment?(_: {
98
+ layout: {
99
+ left: number;
100
+ top: number;
101
+ segment: TimelineSegment_2;
102
+ track: TimelineTrack;
103
+ trackIndex: number;
104
+ segmentIndex: number;
105
+ width: number;
106
+ isSelected: boolean;
107
+ };
108
+ segment: TimelineSegment_2;
109
+ track: TimelineTrack;
110
+ isSelected: boolean;
111
+ }): any;
112
+ };
113
+ refs: {
114
+ viewportRef: HTMLDivElement;
115
+ contentRef: HTMLDivElement;
116
+ tracksRef: HTMLDivElement;
117
+ };
118
+ rootEl: HTMLDivElement;
119
+ };
120
+
121
+ declare type __VLS_TemplateResult = ReturnType<typeof __VLS_template>;
122
+
123
+ declare type __VLS_WithTemplateSlots<T, S> = T & {
124
+ new (): {
125
+ $slots: S;
126
+ };
127
+ };
128
+
129
+ declare const _default: __VLS_WithTemplateSlots<typeof __VLS_component, __VLS_TemplateResult["slots"]>;
130
+ export default _default;
131
+
132
+ declare function formatTime(ms: number): string;
133
+
134
+ declare interface SegmentDragPayload {
135
+ segment: TimelineSegment;
136
+ track: TimelineTrack;
137
+ trackIndex: number;
138
+ segmentIndex: number;
139
+ startTime: number;
140
+ endTime: number;
141
+ targetTrackIndex: number;
142
+ targetTrackId: string;
143
+ isNewTrack: boolean;
144
+ newTrackInsertIndex?: number;
145
+ visualTrackIndex: number;
146
+ isValidTarget: boolean;
147
+ mouseDeltaY: number;
148
+ }
149
+
150
+ declare interface SegmentLayout {
151
+ segment: TimelineSegment;
152
+ track: TimelineTrack;
153
+ trackIndex: number;
154
+ segmentIndex: number;
155
+ left: number;
156
+ width: number;
157
+ isSelected: boolean;
158
+ }
159
+
160
+ declare interface SegmentResizePayload {
161
+ segment: TimelineSegment;
162
+ track: TimelineTrack;
163
+ trackIndex: number;
164
+ segmentIndex: number;
165
+ startTime: number;
166
+ endTime: number;
167
+ edge: 'start' | 'end';
168
+ }
169
+
170
+ declare interface TimelineSegment {
171
+ id: string;
172
+ start: number;
173
+ end: number;
174
+ type?: string;
175
+ color?: string;
176
+ payload?: unknown;
177
+ }
178
+
179
+ declare interface TimelineTick {
180
+ position: number;
181
+ timeMs: number;
182
+ isMajor: boolean;
183
+ label?: string;
184
+ }
185
+
186
+ declare interface TimelineTrack {
187
+ id: string;
188
+ label?: string;
189
+ type?: string;
190
+ color?: string;
191
+ isMain?: boolean;
192
+ payload?: unknown;
193
+ segments: TimelineSegment[];
194
+ }
195
+
196
+ declare function zoomIn(): void;
197
+
198
+ declare function zoomOut(): void;
199
+
200
+ export { }
@@ -0,0 +1,4 @@
1
+ import { V as f } from "./index-y5KhRW21.js";
2
+ export {
3
+ f as default
4
+ };