@mulmoclaude/mulmoscript-plugin 4.3.0 → 4.5.0
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/contract-BHqxMUWm.cjs +82 -0
- package/dist/contract-BHqxMUWm.cjs.map +1 -0
- package/dist/contract-BnIl6w_f.js +53 -0
- package/dist/contract-BnIl6w_f.js.map +1 -0
- package/dist/core/contract.d.ts +80 -6
- package/dist/core/contract.d.ts.map +1 -1
- package/dist/core/definition.d.ts.map +1 -1
- package/dist/core/paths.d.ts +41 -0
- package/dist/core/paths.d.ts.map +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.js +1 -1
- package/dist/lang/de.d.ts.map +1 -1
- package/dist/lang/en.d.ts.map +1 -1
- package/dist/lang/es.d.ts.map +1 -1
- package/dist/lang/fr.d.ts.map +1 -1
- package/dist/lang/ja.d.ts.map +1 -1
- package/dist/lang/ko.d.ts.map +1 -1
- package/dist/lang/messages.d.ts +4 -0
- package/dist/lang/messages.d.ts.map +1 -1
- package/dist/lang/ptBR.d.ts.map +1 -1
- package/dist/lang/zh.d.ts.map +1 -1
- package/dist/{plugin-BOq5YkTl.cjs → plugin-C5JC2lNR.cjs} +51 -1
- package/dist/plugin-C5JC2lNR.cjs.map +1 -0
- package/dist/{plugin-CAhxJ5WM.js → plugin-Jo8iGv4K.js} +40 -2
- package/dist/plugin-Jo8iGv4K.js.map +1 -0
- package/dist/server/dispatch.d.ts +0 -6
- package/dist/server/dispatch.d.ts.map +1 -1
- package/dist/server/ops.d.ts +29 -18
- package/dist/server/ops.d.ts.map +1 -1
- package/dist/server/types.d.ts +64 -2
- package/dist/server/types.d.ts.map +1 -1
- package/dist/server.cjs +423 -110
- package/dist/server.cjs.map +1 -1
- package/dist/server.js +423 -110
- package/dist/server.js.map +1 -1
- package/dist/style.css +46 -18
- package/dist/vue/View.vue.d.ts.map +1 -1
- package/dist/vue/composables/useDeckEditor.d.ts +1 -1
- package/dist/vue/composables/useDeckEditor.d.ts.map +1 -1
- package/dist/vue/helpers.d.ts +11 -8
- package/dist/vue/helpers.d.ts.map +1 -1
- package/dist/vue/index.d.ts +1 -1
- package/dist/vue/index.d.ts.map +1 -1
- package/dist/vue/subscription.d.ts +16 -0
- package/dist/vue/subscription.d.ts.map +1 -0
- package/dist/vue/transport.d.ts +16 -5
- package/dist/vue/transport.d.ts.map +1 -1
- package/dist/vue.cjs +244 -110
- package/dist/vue.cjs.map +1 -1
- package/dist/vue.js +244 -110
- package/dist/vue.js.map +1 -1
- package/package.json +11 -11
- package/dist/contract-BhN3yKJC.cjs +0 -36
- package/dist/contract-BhN3yKJC.cjs.map +0 -1
- package/dist/contract-CIt1ZAtt.js +0 -19
- package/dist/contract-CIt1ZAtt.js.map +0 -1
- package/dist/plugin-BOq5YkTl.cjs.map +0 -1
- package/dist/plugin-CAhxJ5WM.js.map +0 -1
package/dist/vue.cjs
CHANGED
|
@@ -2,8 +2,8 @@ Object.defineProperties(exports, {
|
|
|
2
2
|
__esModule: { value: true },
|
|
3
3
|
[Symbol.toStringTag]: { value: "Module" }
|
|
4
4
|
});
|
|
5
|
-
const require_plugin = require("./plugin-
|
|
6
|
-
const require_contract = require("./contract-
|
|
5
|
+
const require_plugin = require("./plugin-C5JC2lNR.cjs");
|
|
6
|
+
const require_contract = require("./contract-BHqxMUWm.cjs");
|
|
7
7
|
let _mulmocast_types = require("@mulmocast/types");
|
|
8
8
|
let vue = require("vue");
|
|
9
9
|
let _mulmocast_beat_editor = require("@mulmocast/beat-editor");
|
|
@@ -119,22 +119,20 @@ function beatMayHaveMovie(beat) {
|
|
|
119
119
|
function isBeatImageReference(beat) {
|
|
120
120
|
return beat.image?.type === "beat";
|
|
121
121
|
}
|
|
122
|
-
/**
|
|
123
|
-
*
|
|
124
|
-
*
|
|
125
|
-
*
|
|
126
|
-
*
|
|
127
|
-
*
|
|
128
|
-
*
|
|
129
|
-
|
|
122
|
+
/** Whether the beat editor has anything to edit.
|
|
123
|
+
*
|
|
124
|
+
* Any beat type, not just `slide`: `@mulmocast/beat-editor` renders and edits all eight
|
|
125
|
+
* (`textSlide` / `markdown` / `chart` / `mermaid` / `image` / `movie` / `slide` /
|
|
126
|
+
* `html_tailwind`). The all-slide test this replaces was a limit of the OLD iframe deck
|
|
127
|
+
* editor, which only understood decks — it stayed in place through the migration and kept a
|
|
128
|
+
* markdown script read-only for no reason.
|
|
129
|
+
*
|
|
130
|
+
* Empty / missing `beats[]` is false: there is nothing to edit, and the per-beat list already
|
|
131
|
+
* renders an empty state. */
|
|
132
|
+
function hasEditableBeats(script) {
|
|
130
133
|
if (!isRecord(script)) return false;
|
|
131
134
|
const { beats } = script;
|
|
132
|
-
|
|
133
|
-
return beats.every((beat) => {
|
|
134
|
-
if (!isRecord(beat)) return false;
|
|
135
|
-
const { image } = beat;
|
|
136
|
-
return isRecord(image) && image.type === "slide";
|
|
137
|
-
});
|
|
135
|
+
return Array.isArray(beats) && beats.length > 0;
|
|
138
136
|
}
|
|
139
137
|
/** Resolve the beat the View should render at `index`: the user's
|
|
140
138
|
* in-place edit (`overrides`) wins over the on-disk beat, and an
|
|
@@ -221,6 +219,57 @@ function focusLeftContainer(container, movedTo) {
|
|
|
221
219
|
return !container.contains(movedTo);
|
|
222
220
|
}
|
|
223
221
|
//#endregion
|
|
222
|
+
//#region src/vue/subscription.ts
|
|
223
|
+
/** A caller that predates roots is asking for the host's default root. */
|
|
224
|
+
var DEFAULT_ROOT_GETTER = () => void 0;
|
|
225
|
+
/**
|
|
226
|
+
* The object form is checked at runtime, not only by the type.
|
|
227
|
+
*
|
|
228
|
+
* This package is published, so a JavaScript consumer reaches these functions
|
|
229
|
+
* with no call-site checking at all. An object missing `root` type-checks
|
|
230
|
+
* nowhere and passed through here unchanged, and the failure surfaced much
|
|
231
|
+
* later as `sub.root is not a function` — thrown inside a pubsub delivery,
|
|
232
|
+
* where there is no caller left to catch it and the only symptom is a View
|
|
233
|
+
* that silently stops updating (CodeRabbit on #3015).
|
|
234
|
+
*
|
|
235
|
+
* A missing `root` is the one field with a safe answer: absent means the
|
|
236
|
+
* default root, which is exactly what a caller who did not think about roots
|
|
237
|
+
* intended. A missing `filePath` or `handler` has no such answer, so it
|
|
238
|
+
* throws HERE, at the subscribe call, where the stack points at the bug.
|
|
239
|
+
*/
|
|
240
|
+
function checkedSubscription(subscription, label) {
|
|
241
|
+
if (typeof subscription.filePath !== "function" || typeof subscription.handler !== "function") throw new TypeError(`${label}: filePath and handler must both be functions`);
|
|
242
|
+
if (subscription.root === void 0) return {
|
|
243
|
+
...subscription,
|
|
244
|
+
root: DEFAULT_ROOT_GETTER
|
|
245
|
+
};
|
|
246
|
+
if (typeof subscription.root !== "function") throw new TypeError(`${label}: root must be a function returning the root id, or be omitted`);
|
|
247
|
+
return subscription;
|
|
248
|
+
}
|
|
249
|
+
function normalizeGenerationSubscription(first, legacyHandler) {
|
|
250
|
+
if (typeof first !== "function") return checkedSubscription(first, "onGenerationEvent(subscription)");
|
|
251
|
+
if (!legacyHandler) throw new TypeError("onGenerationEvent(filePath, handler): handler is required");
|
|
252
|
+
return {
|
|
253
|
+
filePath: first,
|
|
254
|
+
root: DEFAULT_ROOT_GETTER,
|
|
255
|
+
handler: legacyHandler
|
|
256
|
+
};
|
|
257
|
+
}
|
|
258
|
+
function normalizeScriptChangedSubscription(first, legacyOwnOrigin, legacyHandler) {
|
|
259
|
+
if (typeof first !== "function") {
|
|
260
|
+
const checked = checkedSubscription(first, "onScriptChanged(subscription)");
|
|
261
|
+
if (typeof checked.ownOrigin !== "string") throw new TypeError("onScriptChanged(subscription): ownOrigin must be a string");
|
|
262
|
+
return checked;
|
|
263
|
+
}
|
|
264
|
+
if (typeof legacyOwnOrigin !== "string" || !legacyHandler) throw new TypeError("onScriptChanged(filePath, ownOrigin, handler): ownOrigin and handler are required");
|
|
265
|
+
return {
|
|
266
|
+
filePath: first,
|
|
267
|
+
root: DEFAULT_ROOT_GETTER,
|
|
268
|
+
ownOrigin: legacyOwnOrigin,
|
|
269
|
+
handler: legacyHandler
|
|
270
|
+
};
|
|
271
|
+
}
|
|
272
|
+
//#endregion
|
|
224
273
|
//#region src/vue/transport.ts
|
|
225
274
|
var GENERATION_EVENT_KINDS = /* @__PURE__ */ new Set([
|
|
226
275
|
"beatImage",
|
|
@@ -229,26 +278,53 @@ var GENERATION_EVENT_KINDS = /* @__PURE__ */ new Set([
|
|
|
229
278
|
"movie",
|
|
230
279
|
"pdf"
|
|
231
280
|
]);
|
|
281
|
+
/**
|
|
282
|
+
* A field that is absent, or a string.
|
|
283
|
+
*
|
|
284
|
+
* `undefined` is a legitimate answer for both `root` and `origin`, so a
|
|
285
|
+
* present-but-wrong-typed value CANNOT be flattened into it: `root: 42` read
|
|
286
|
+
* as "no root" makes a named root's event look like a default-root one, and
|
|
287
|
+
* the subscriber then routes another repository's script to this View
|
|
288
|
+
* (CodeRabbit on #3015 — the same shape the dispatch boundary was just fixed
|
|
289
|
+
* for). Malformed means malformed; the caller rejects the payload.
|
|
290
|
+
*/
|
|
291
|
+
function optionalString(value) {
|
|
292
|
+
if (value === void 0) return {
|
|
293
|
+
ok: true,
|
|
294
|
+
value: void 0
|
|
295
|
+
};
|
|
296
|
+
return typeof value === "string" ? {
|
|
297
|
+
ok: true,
|
|
298
|
+
value
|
|
299
|
+
} : { ok: false };
|
|
300
|
+
}
|
|
232
301
|
function parseScriptChangedEvent(payload) {
|
|
233
302
|
if (!isRecord(payload)) return null;
|
|
234
|
-
const { filePath, origin } = payload;
|
|
303
|
+
const { filePath, origin, root } = payload;
|
|
235
304
|
if (typeof filePath !== "string") return null;
|
|
305
|
+
const parsedOrigin = optionalString(origin);
|
|
306
|
+
const parsedRoot = optionalString(root);
|
|
307
|
+
if (!parsedOrigin.ok || !parsedRoot.ok) return null;
|
|
236
308
|
return {
|
|
237
309
|
filePath,
|
|
238
|
-
...
|
|
310
|
+
...parsedOrigin.value !== void 0 ? { origin: parsedOrigin.value } : {},
|
|
311
|
+
...parsedRoot.value !== void 0 ? { root: parsedRoot.value } : {}
|
|
239
312
|
};
|
|
240
313
|
}
|
|
241
314
|
function parseGenerationEvent(payload) {
|
|
242
315
|
if (!isRecord(payload)) return null;
|
|
243
|
-
const { kind, filePath, key, done, error } = payload;
|
|
316
|
+
const { kind, filePath, key, done, error, root } = payload;
|
|
244
317
|
if (typeof kind !== "string" || !GENERATION_EVENT_KINDS.has(kind)) return null;
|
|
245
318
|
if (typeof filePath !== "string" || typeof key !== "string" || typeof done !== "boolean") return null;
|
|
319
|
+
const parsedRoot = optionalString(root);
|
|
320
|
+
if (!parsedRoot.ok) return null;
|
|
246
321
|
return {
|
|
247
322
|
kind,
|
|
248
323
|
filePath,
|
|
249
324
|
key,
|
|
250
325
|
done,
|
|
251
|
-
...typeof error === "string" ? { error } : {}
|
|
326
|
+
...typeof error === "string" ? { error } : {},
|
|
327
|
+
...parsedRoot.value !== void 0 ? { root: parsedRoot.value } : {}
|
|
252
328
|
};
|
|
253
329
|
}
|
|
254
330
|
function useMulmoScriptTransport() {
|
|
@@ -275,12 +351,13 @@ function useMulmoScriptTransport() {
|
|
|
275
351
|
data: result
|
|
276
352
|
};
|
|
277
353
|
}
|
|
278
|
-
function onGenerationEvent(
|
|
354
|
+
function onGenerationEvent(first, legacyHandler) {
|
|
355
|
+
const { filePath, root, handler } = normalizeGenerationSubscription(first, legacyHandler);
|
|
279
356
|
return runtime.pubsub.subscribe(require_contract.GENERATION_EVENT, (payload) => {
|
|
280
357
|
const event = parseGenerationEvent(payload);
|
|
281
358
|
if (!event) return;
|
|
282
359
|
const current = filePath();
|
|
283
|
-
if (!current || event.filePath !== current) return;
|
|
360
|
+
if (!current || event.filePath !== current || !require_contract.sameRoot(event.root, root())) return;
|
|
284
361
|
handler(event);
|
|
285
362
|
});
|
|
286
363
|
}
|
|
@@ -291,11 +368,12 @@ function useMulmoScriptTransport() {
|
|
|
291
368
|
* on them would rebuild the element the caret is in on every keystroke, so they are dropped
|
|
292
369
|
* here. A write from the agent carries no origin and always reaches the handler.
|
|
293
370
|
*/
|
|
294
|
-
function onScriptChanged(
|
|
371
|
+
function onScriptChanged(first, legacyOwnOrigin, legacyHandler) {
|
|
372
|
+
const { filePath, root, ownOrigin, handler } = normalizeScriptChangedSubscription(first, legacyOwnOrigin, legacyHandler);
|
|
295
373
|
return runtime.pubsub.subscribe(require_contract.SCRIPT_CHANGED_EVENT, (payload) => {
|
|
296
374
|
const event = parseScriptChangedEvent(payload);
|
|
297
375
|
if (!event) return;
|
|
298
|
-
if (!require_contract.shouldReloadForScriptChange(event, filePath(), ownOrigin)) return;
|
|
376
|
+
if (!require_contract.shouldReloadForScriptChange(event, filePath(), ownOrigin, root())) return;
|
|
299
377
|
handler();
|
|
300
378
|
});
|
|
301
379
|
}
|
|
@@ -608,7 +686,7 @@ var DECK_SAVE_DEBOUNCE_MS = 300;
|
|
|
608
686
|
*/
|
|
609
687
|
var EDITOR_ORIGIN = `deck-editor-${Math.random().toString(36).slice(2)}`;
|
|
610
688
|
function useDeckEditor({ api, filePath, effectiveScript, commitScript }) {
|
|
611
|
-
const
|
|
689
|
+
const canEditBeats = (0, vue.computed)(() => hasEditableBeats(effectiveScript.value));
|
|
612
690
|
const deckScriptInput = (0, vue.computed)(() => effectiveScript.value);
|
|
613
691
|
let deckSaveTimer = null;
|
|
614
692
|
let pendingDeckScript = null;
|
|
@@ -652,13 +730,18 @@ function useDeckEditor({ api, filePath, effectiveScript, commitScript }) {
|
|
|
652
730
|
* flushing cannot clobber it out of order.
|
|
653
731
|
*/
|
|
654
732
|
function watchForeignWrites(reload) {
|
|
655
|
-
return api.onScriptChanged(
|
|
656
|
-
|
|
657
|
-
|
|
733
|
+
return api.onScriptChanged({
|
|
734
|
+
filePath: () => filePath.value,
|
|
735
|
+
root: () => void 0,
|
|
736
|
+
ownOrigin: EDITOR_ORIGIN,
|
|
737
|
+
handler: () => {
|
|
738
|
+
flushPendingDeckSave();
|
|
739
|
+
reload();
|
|
740
|
+
}
|
|
658
741
|
});
|
|
659
742
|
}
|
|
660
743
|
return {
|
|
661
|
-
|
|
744
|
+
canEditBeats,
|
|
662
745
|
deckScriptInput,
|
|
663
746
|
onDeckUpdate,
|
|
664
747
|
flushPendingDeckSave,
|
|
@@ -672,6 +755,8 @@ function useDeckEditor({ api, filePath, effectiveScript, commitScript }) {
|
|
|
672
755
|
var useT = (0, gui_chat_protocol_vue.createUseT)({
|
|
673
756
|
de: {
|
|
674
757
|
beatCount: (count) => count === 1 ? `${count} Beat` : `${count} Beats`,
|
|
758
|
+
editTab: "Bearbeiten",
|
|
759
|
+
mediaTab: "Medien",
|
|
675
760
|
movie: "Video",
|
|
676
761
|
generating: "Wird generiert…",
|
|
677
762
|
rendering: "Wird gerendert…",
|
|
@@ -704,6 +789,8 @@ var useT = (0, gui_chat_protocol_vue.createUseT)({
|
|
|
704
789
|
},
|
|
705
790
|
en: {
|
|
706
791
|
beatCount: (count) => count === 1 ? `${count} beat` : `${count} beats`,
|
|
792
|
+
editTab: "Edit",
|
|
793
|
+
mediaTab: "Media",
|
|
707
794
|
movie: "Movie",
|
|
708
795
|
generating: "Generating…",
|
|
709
796
|
rendering: "Rendering…",
|
|
@@ -736,6 +823,8 @@ var useT = (0, gui_chat_protocol_vue.createUseT)({
|
|
|
736
823
|
},
|
|
737
824
|
es: {
|
|
738
825
|
beatCount: (count) => count === 1 ? `${count} beat` : `${count} beats`,
|
|
826
|
+
editTab: "Editar",
|
|
827
|
+
mediaTab: "Medios",
|
|
739
828
|
movie: "Vídeo",
|
|
740
829
|
generating: "Generando…",
|
|
741
830
|
rendering: "Renderizando…",
|
|
@@ -768,6 +857,8 @@ var useT = (0, gui_chat_protocol_vue.createUseT)({
|
|
|
768
857
|
},
|
|
769
858
|
fr: {
|
|
770
859
|
beatCount: (count) => count === 1 ? `${count} beat` : `${count} beats`,
|
|
860
|
+
editTab: "Éditer",
|
|
861
|
+
mediaTab: "Médias",
|
|
771
862
|
movie: "Film",
|
|
772
863
|
generating: "Génération…",
|
|
773
864
|
rendering: "Rendu…",
|
|
@@ -800,6 +891,8 @@ var useT = (0, gui_chat_protocol_vue.createUseT)({
|
|
|
800
891
|
},
|
|
801
892
|
ja: {
|
|
802
893
|
beatCount: (count) => `${count} ビート`,
|
|
894
|
+
editTab: "編集",
|
|
895
|
+
mediaTab: "メディア",
|
|
803
896
|
movie: "動画",
|
|
804
897
|
generating: "生成中…",
|
|
805
898
|
rendering: "レンダリング中…",
|
|
@@ -832,6 +925,8 @@ var useT = (0, gui_chat_protocol_vue.createUseT)({
|
|
|
832
925
|
},
|
|
833
926
|
ko: {
|
|
834
927
|
beatCount: (count) => `${count}개 비트`,
|
|
928
|
+
editTab: "편집",
|
|
929
|
+
mediaTab: "미디어",
|
|
835
930
|
movie: "영상",
|
|
836
931
|
generating: "생성 중…",
|
|
837
932
|
rendering: "렌더링 중…",
|
|
@@ -864,6 +959,8 @@ var useT = (0, gui_chat_protocol_vue.createUseT)({
|
|
|
864
959
|
},
|
|
865
960
|
"pt-BR": {
|
|
866
961
|
beatCount: (count) => count === 1 ? `${count} beat` : `${count} beats`,
|
|
962
|
+
editTab: "Editar",
|
|
963
|
+
mediaTab: "Mídia",
|
|
867
964
|
movie: "Vídeo",
|
|
868
965
|
generating: "Gerando…",
|
|
869
966
|
rendering: "Renderizando…",
|
|
@@ -896,6 +993,8 @@ var useT = (0, gui_chat_protocol_vue.createUseT)({
|
|
|
896
993
|
},
|
|
897
994
|
zh: {
|
|
898
995
|
beatCount: (count) => `${count} 个 beat`,
|
|
996
|
+
editTab: "编辑",
|
|
997
|
+
mediaTab: "媒体",
|
|
899
998
|
movie: "视频",
|
|
900
999
|
generating: "生成中…",
|
|
901
1000
|
rendering: "渲染中…",
|
|
@@ -1325,115 +1424,120 @@ var _hoisted_10 = { class: "flex-1 min-w-0" };
|
|
|
1325
1424
|
var _hoisted_11 = { class: "font-medium" };
|
|
1326
1425
|
var _hoisted_12 = { class: "break-words whitespace-pre-wrap mt-0.5" };
|
|
1327
1426
|
var _hoisted_13 = ["disabled"];
|
|
1328
|
-
var _hoisted_14 = {
|
|
1329
|
-
|
|
1427
|
+
var _hoisted_14 = {
|
|
1428
|
+
key: 2,
|
|
1429
|
+
class: "flex shrink-0 gap-1 px-2 pt-1 text-[11px]"
|
|
1430
|
+
};
|
|
1431
|
+
var _hoisted_15 = { class: "flex gap-3 items-stretch" };
|
|
1432
|
+
var _hoisted_16 = [
|
|
1330
1433
|
"onDragover",
|
|
1331
1434
|
"onDragleave",
|
|
1332
1435
|
"onDrop"
|
|
1333
1436
|
];
|
|
1334
|
-
var
|
|
1335
|
-
var
|
|
1336
|
-
var
|
|
1437
|
+
var _hoisted_17 = ["data-testid"];
|
|
1438
|
+
var _hoisted_18 = ["src", "data-testid"];
|
|
1439
|
+
var _hoisted_19 = [
|
|
1337
1440
|
"title",
|
|
1338
1441
|
"aria-label",
|
|
1339
1442
|
"data-testid",
|
|
1340
1443
|
"onClick"
|
|
1341
1444
|
];
|
|
1342
|
-
var
|
|
1445
|
+
var _hoisted_20 = [
|
|
1343
1446
|
"src",
|
|
1344
1447
|
"alt",
|
|
1345
1448
|
"onClick"
|
|
1346
1449
|
];
|
|
1347
|
-
var
|
|
1450
|
+
var _hoisted_21 = [
|
|
1348
1451
|
"title",
|
|
1349
1452
|
"aria-label",
|
|
1350
1453
|
"data-testid",
|
|
1351
1454
|
"onClick"
|
|
1352
1455
|
];
|
|
1353
|
-
var
|
|
1456
|
+
var _hoisted_22 = {
|
|
1354
1457
|
key: 0,
|
|
1355
1458
|
class: "animate-spin w-5 h-5",
|
|
1356
1459
|
viewBox: "0 0 24 24",
|
|
1357
1460
|
fill: "none"
|
|
1358
1461
|
};
|
|
1359
|
-
var
|
|
1462
|
+
var _hoisted_23 = {
|
|
1360
1463
|
key: 1,
|
|
1361
1464
|
class: "material-icons text-3xl"
|
|
1362
1465
|
};
|
|
1363
|
-
var
|
|
1364
|
-
var
|
|
1466
|
+
var _hoisted_24 = ["disabled", "onClick"];
|
|
1467
|
+
var _hoisted_25 = {
|
|
1365
1468
|
key: 3,
|
|
1366
1469
|
class: "w-full aspect-video flex flex-col items-center justify-center gap-1 p-2"
|
|
1367
1470
|
};
|
|
1368
|
-
var
|
|
1369
|
-
var
|
|
1471
|
+
var _hoisted_26 = { class: "text-xs text-green-500" };
|
|
1472
|
+
var _hoisted_27 = {
|
|
1370
1473
|
key: 1,
|
|
1371
1474
|
class: "text-xs text-red-400 text-center"
|
|
1372
1475
|
};
|
|
1373
|
-
var
|
|
1476
|
+
var _hoisted_28 = {
|
|
1374
1477
|
key: 0,
|
|
1375
1478
|
class: "text-xs text-gray-400 text-center italic leading-relaxed px-1"
|
|
1376
1479
|
};
|
|
1377
|
-
var
|
|
1480
|
+
var _hoisted_29 = {
|
|
1378
1481
|
key: 1,
|
|
1379
1482
|
class: "text-xs text-gray-300"
|
|
1380
1483
|
};
|
|
1381
|
-
var
|
|
1484
|
+
var _hoisted_30 = {
|
|
1382
1485
|
key: 2,
|
|
1383
1486
|
class: "absolute inset-0 flex items-center justify-center bg-blue-50/80 pointer-events-none"
|
|
1384
1487
|
};
|
|
1385
|
-
var
|
|
1386
|
-
var
|
|
1488
|
+
var _hoisted_31 = { class: "text-xs text-blue-500 font-medium" };
|
|
1489
|
+
var _hoisted_32 = {
|
|
1387
1490
|
key: 3,
|
|
1388
1491
|
class: "absolute bottom-0 inset-x-0 text-center text-xs text-gray-400 bg-white/70 py-0.5 pointer-events-none"
|
|
1389
1492
|
};
|
|
1390
|
-
var
|
|
1391
|
-
var
|
|
1392
|
-
var
|
|
1393
|
-
var
|
|
1394
|
-
var
|
|
1395
|
-
var
|
|
1493
|
+
var _hoisted_33 = ["onClick"];
|
|
1494
|
+
var _hoisted_34 = { class: "flex flex-col flex-1 min-w-0 px-2 py-1.5" };
|
|
1495
|
+
var _hoisted_35 = { class: "text-sm text-gray-800 leading-relaxed" };
|
|
1496
|
+
var _hoisted_36 = { class: "flex justify-between mt-auto pt-1" };
|
|
1497
|
+
var _hoisted_37 = { class: "flex items-center gap-1" };
|
|
1498
|
+
var _hoisted_38 = {
|
|
1396
1499
|
key: 0,
|
|
1397
1500
|
class: "animate-spin w-3 h-3 text-green-400",
|
|
1398
1501
|
viewBox: "0 0 24 24",
|
|
1399
1502
|
fill: "none"
|
|
1400
1503
|
};
|
|
1401
|
-
var
|
|
1402
|
-
var
|
|
1403
|
-
var
|
|
1404
|
-
var
|
|
1405
|
-
var
|
|
1504
|
+
var _hoisted_39 = ["onClick"];
|
|
1505
|
+
var _hoisted_40 = ["title"];
|
|
1506
|
+
var _hoisted_41 = ["disabled", "onClick"];
|
|
1507
|
+
var _hoisted_42 = ["onClick"];
|
|
1508
|
+
var _hoisted_43 = [
|
|
1406
1509
|
"title",
|
|
1407
1510
|
"data-testid",
|
|
1408
1511
|
"onClick"
|
|
1409
1512
|
];
|
|
1410
|
-
var
|
|
1513
|
+
var _hoisted_44 = {
|
|
1411
1514
|
key: 0,
|
|
1412
1515
|
class: "border-t border-gray-100"
|
|
1413
1516
|
};
|
|
1414
|
-
var
|
|
1415
|
-
var
|
|
1416
|
-
var
|
|
1517
|
+
var _hoisted_45 = ["onUpdate:modelValue", "data-testid"];
|
|
1518
|
+
var _hoisted_46 = { class: "flex items-center justify-end gap-2 px-2 pb-2" };
|
|
1519
|
+
var _hoisted_47 = {
|
|
1417
1520
|
key: 0,
|
|
1418
1521
|
class: "text-xs text-red-600",
|
|
1419
1522
|
role: "alert"
|
|
1420
1523
|
};
|
|
1421
|
-
var
|
|
1524
|
+
var _hoisted_48 = [
|
|
1422
1525
|
"disabled",
|
|
1423
1526
|
"data-testid",
|
|
1424
1527
|
"onClick"
|
|
1425
1528
|
];
|
|
1426
|
-
var
|
|
1529
|
+
var _hoisted_49 = {
|
|
1427
1530
|
key: 0,
|
|
1428
1531
|
class: "flex items-center justify-center h-32 text-gray-400 text-sm"
|
|
1429
1532
|
};
|
|
1430
|
-
var
|
|
1431
|
-
var
|
|
1432
|
-
var
|
|
1433
|
-
var
|
|
1434
|
-
var
|
|
1533
|
+
var _hoisted_50 = { class: "bottom-bar-wrapper" };
|
|
1534
|
+
var _hoisted_51 = { class: "editor-actions" };
|
|
1535
|
+
var _hoisted_52 = ["disabled"];
|
|
1536
|
+
var _hoisted_53 = ["title"];
|
|
1537
|
+
var _hoisted_54 = { class: "material-icons" };
|
|
1435
1538
|
var SILENT_BEAT_DEFAULT_SEC = 3;
|
|
1436
1539
|
var MS_PER_SECOND = 1e3;
|
|
1540
|
+
var BEAT_TAB_BASE = "rounded px-2 py-0.5 font-sans";
|
|
1437
1541
|
var View_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ (0, vue.defineComponent)({
|
|
1438
1542
|
__name: "View",
|
|
1439
1543
|
props: { selectedResult: {} },
|
|
@@ -1600,12 +1704,27 @@ var View_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ (0, vue.def
|
|
|
1600
1704
|
}
|
|
1601
1705
|
});
|
|
1602
1706
|
}
|
|
1603
|
-
const {
|
|
1707
|
+
const { canEditBeats, deckScriptInput, onDeckUpdate, flushPendingDeckSave, watchForeignWrites } = useDeckEditor({
|
|
1604
1708
|
api,
|
|
1605
1709
|
filePath,
|
|
1606
1710
|
effectiveScript,
|
|
1607
1711
|
commitScript
|
|
1608
1712
|
});
|
|
1713
|
+
/**
|
|
1714
|
+
* Which pane the beats are shown in.
|
|
1715
|
+
*
|
|
1716
|
+
* `edit` is the beat editor — every beat type, edited in place. `media` is the per-beat list,
|
|
1717
|
+
* which is the only place audio / image / movie generation lives. A script with nothing to edit
|
|
1718
|
+
* has only the list, so the switch is hidden and this is ignored.
|
|
1719
|
+
*
|
|
1720
|
+
* `media` is the default because opening the script is what triggers rendering each beat's
|
|
1721
|
+
* image: the auto-render on mount lives in that list, so defaulting to `edit` silently stopped
|
|
1722
|
+
* thumbnails from being produced at all. Someone who wants to edit clicks once; nobody has to
|
|
1723
|
+
* click to get the previews they always got.
|
|
1724
|
+
*/
|
|
1725
|
+
const beatPane = (0, vue.ref)("media");
|
|
1726
|
+
const showBeatEditor = (0, vue.computed)(() => canEditBeats.value && beatPane.value === "edit");
|
|
1727
|
+
const beatPaneTabClass = (active) => [BEAT_TAB_BASE, active ? "bg-gray-700 text-white" : "bg-gray-100 text-gray-600 hover:bg-gray-200"];
|
|
1609
1728
|
const unsubscribeForeignWrites = watchForeignWrites(() => {
|
|
1610
1729
|
refreshScriptFromDisk();
|
|
1611
1730
|
});
|
|
@@ -1980,14 +2099,18 @@ var View_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ (0, vue.def
|
|
|
1980
2099
|
}
|
|
1981
2100
|
(0, vue.onMounted)(initializeScript);
|
|
1982
2101
|
(0, vue.watch)(() => props.selectedResult, initializeScript);
|
|
1983
|
-
const unsubscribeGenerationEvents = api.onGenerationEvent(
|
|
1984
|
-
|
|
1985
|
-
|
|
1986
|
-
|
|
2102
|
+
const unsubscribeGenerationEvents = api.onGenerationEvent({
|
|
2103
|
+
filePath: () => filePath.value,
|
|
2104
|
+
root: () => void 0,
|
|
2105
|
+
handler: (event) => {
|
|
2106
|
+
if (!event.done) {
|
|
2107
|
+
reflectGenerationStart(event);
|
|
2108
|
+
return;
|
|
2109
|
+
}
|
|
2110
|
+
reflectGenerationFinish(event).catch((err) => {
|
|
2111
|
+
console.error("[presentMulmoScript] reload on finish failed:", err);
|
|
2112
|
+
});
|
|
1987
2113
|
}
|
|
1988
|
-
reflectGenerationFinish(event).catch((err) => {
|
|
1989
|
-
console.error("[presentMulmoScript] reload on finish failed:", err);
|
|
1990
|
-
});
|
|
1991
2114
|
});
|
|
1992
2115
|
function reflectGenerationStart(entry) {
|
|
1993
2116
|
if (entry.kind === "beatImage") {
|
|
@@ -2062,7 +2185,7 @@ var View_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ (0, vue.def
|
|
|
2062
2185
|
"onDownloadPdf"
|
|
2063
2186
|
])]),
|
|
2064
2187
|
(0, vue.unref)(movieError) ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_9, [
|
|
2065
|
-
_cache[
|
|
2188
|
+
_cache[5] || (_cache[5] = (0, vue.createElementVNode)("span", { class: "material-icons text-base shrink-0 mt-px" }, "error_outline", -1)),
|
|
2066
2189
|
(0, vue.createElementVNode)("div", _hoisted_10, [(0, vue.createElementVNode)("div", _hoisted_11, (0, vue.toDisplayString)((0, vue.unref)(m).movieGenerationFailed), 1), (0, vue.createElementVNode)("div", _hoisted_12, (0, vue.toDisplayString)((0, vue.unref)(movieError)), 1)]),
|
|
2067
2190
|
(0, vue.createElementVNode)("button", {
|
|
2068
2191
|
class: "shrink-0 h-7 px-2 text-xs rounded border border-red-300 text-red-700 hover:bg-red-100 disabled:opacity-50",
|
|
@@ -2102,8 +2225,19 @@ var View_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ (0, vue.def
|
|
|
2102
2225
|
"onCharDrop",
|
|
2103
2226
|
"onRenderCharacter"
|
|
2104
2227
|
])) : (0, vue.createCommentVNode)("", true),
|
|
2105
|
-
(0, vue.unref)(
|
|
2106
|
-
|
|
2228
|
+
(0, vue.unref)(canEditBeats) ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_14, [(0, vue.createElementVNode)("button", {
|
|
2229
|
+
type: "button",
|
|
2230
|
+
class: (0, vue.normalizeClass)(beatPaneTabClass(beatPane.value === "edit")),
|
|
2231
|
+
"data-testid": "mulmo-script-tab-edit",
|
|
2232
|
+
onClick: _cache[1] || (_cache[1] = ($event) => beatPane.value = "edit")
|
|
2233
|
+
}, (0, vue.toDisplayString)((0, vue.unref)(m).editTab), 3), (0, vue.createElementVNode)("button", {
|
|
2234
|
+
type: "button",
|
|
2235
|
+
class: (0, vue.normalizeClass)(beatPaneTabClass(beatPane.value === "media")),
|
|
2236
|
+
"data-testid": "mulmo-script-tab-media",
|
|
2237
|
+
onClick: _cache[2] || (_cache[2] = ($event) => beatPane.value = "media")
|
|
2238
|
+
}, (0, vue.toDisplayString)((0, vue.unref)(m).mediaTab), 3)])) : (0, vue.createCommentVNode)("", true),
|
|
2239
|
+
showBeatEditor.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", {
|
|
2240
|
+
key: 3,
|
|
2107
2241
|
class: "flex-1 overflow-hidden",
|
|
2108
2242
|
"data-testid": "mulmo-script-deck-editor",
|
|
2109
2243
|
onFocusout: onDeckFocusOut
|
|
@@ -2111,7 +2245,7 @@ var View_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ (0, vue.def
|
|
|
2111
2245
|
beats: deckBeats.value,
|
|
2112
2246
|
"onUpdate:beats": onDeckBeatsUpdate
|
|
2113
2247
|
}, null, 8, ["beats"])], 32)) : ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", {
|
|
2114
|
-
key:
|
|
2248
|
+
key: 4,
|
|
2115
2249
|
ref_key: "beatListEl",
|
|
2116
2250
|
ref: beatListEl,
|
|
2117
2251
|
class: "flex-1 overflow-y-auto p-2 space-y-1.5"
|
|
@@ -2119,7 +2253,7 @@ var View_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ (0, vue.def
|
|
|
2119
2253
|
return (0, vue.openBlock)(), (0, vue.createElementBlock)("div", {
|
|
2120
2254
|
key: index,
|
|
2121
2255
|
class: "rounded-lg border border-gray-200 overflow-hidden"
|
|
2122
|
-
}, [(0, vue.createElementVNode)("div",
|
|
2256
|
+
}, [(0, vue.createElementVNode)("div", _hoisted_15, [(0, vue.createElementVNode)("div", {
|
|
2123
2257
|
class: (0, vue.normalizeClass)(["relative shrink-0 w-[45%] overflow-hidden bg-gray-50 transition-colors", beatDragOver[index] ? "bg-blue-50" : ""]),
|
|
2124
2258
|
onDragover: ($event) => onBeatDragOver($event, index),
|
|
2125
2259
|
onDragleave: ($event) => onBeatDragLeave(index),
|
|
@@ -2128,27 +2262,27 @@ var View_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ (0, vue.def
|
|
|
2128
2262
|
(0, vue.createElementVNode)("div", {
|
|
2129
2263
|
class: "absolute top-1.5 left-1.5 z-10 px-1.5 py-0.5 rounded bg-black/55 text-white text-xs font-medium leading-none pointer-events-none",
|
|
2130
2264
|
"data-testid": `mulmo-script-beat-number-${index}`
|
|
2131
|
-
}, (0, vue.toDisplayString)(index + 1), 9,
|
|
2265
|
+
}, (0, vue.toDisplayString)(index + 1), 9, _hoisted_17),
|
|
2132
2266
|
(0, vue.unref)(beatMovieOpen)[index] && (0, vue.unref)(beatMovieUrls)[index] ? ((0, vue.openBlock)(), (0, vue.createElementBlock)(vue.Fragment, { key: 0 }, [(0, vue.createElementVNode)("video", {
|
|
2133
2267
|
src: (0, vue.unref)(beatMovieUrls)[index],
|
|
2134
2268
|
class: "w-full object-contain",
|
|
2135
2269
|
controls: "",
|
|
2136
2270
|
autoplay: "",
|
|
2137
2271
|
"data-testid": `mulmo-script-beat-movie-player-${index}`
|
|
2138
|
-
}, null, 8,
|
|
2272
|
+
}, null, 8, _hoisted_18), (0, vue.createElementVNode)("button", {
|
|
2139
2273
|
class: "absolute top-1.5 right-1.5 flex items-center justify-center w-6 h-6 rounded border border-gray-400 text-gray-600 bg-white hover:bg-gray-50",
|
|
2140
2274
|
title: (0, vue.unref)(m).close,
|
|
2141
2275
|
"aria-label": (0, vue.unref)(m).close,
|
|
2142
2276
|
"data-testid": `mulmo-script-beat-movie-close-${index}`,
|
|
2143
2277
|
onClick: (0, vue.withModifiers)(($event) => (0, vue.unref)(closeBeatMovie)(index), ["stop"])
|
|
2144
|
-
}, [..._cache[
|
|
2278
|
+
}, [..._cache[6] || (_cache[6] = [(0, vue.createElementVNode)("span", { class: "material-icons text-sm" }, "close", -1)])], 8, _hoisted_19)], 64)) : ((0, vue.openBlock)(), (0, vue.createElementBlock)(vue.Fragment, { key: 1 }, [
|
|
2145
2279
|
renderedImages[index] ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("img", {
|
|
2146
2280
|
key: 0,
|
|
2147
2281
|
src: renderedImages[index],
|
|
2148
2282
|
class: "w-full object-contain cursor-zoom-in",
|
|
2149
2283
|
alt: `Beat ${index + 1}`,
|
|
2150
2284
|
onClick: ($event) => openLightbox(index)
|
|
2151
|
-
}, null, 8,
|
|
2285
|
+
}, null, 8, _hoisted_20)) : (0, vue.createCommentVNode)("", true),
|
|
2152
2286
|
renderedImages[index] && (0, vue.unref)(beatMovies)[index] && canFetchMedia.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("button", {
|
|
2153
2287
|
key: 1,
|
|
2154
2288
|
class: "absolute inset-0 m-auto w-12 h-12 flex items-center justify-center rounded-full bg-black/50 text-white hover:bg-black/70",
|
|
@@ -2156,7 +2290,7 @@ var View_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ (0, vue.def
|
|
|
2156
2290
|
"aria-label": (0, vue.unref)(m).play,
|
|
2157
2291
|
"data-testid": `mulmo-script-beat-movie-play-${index}`,
|
|
2158
2292
|
onClick: (0, vue.withModifiers)(($event) => (0, vue.unref)(playBeatMovie)(index), ["stop"])
|
|
2159
|
-
}, [(0, vue.unref)(beatMovieLoading)[index] ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("svg",
|
|
2293
|
+
}, [(0, vue.unref)(beatMovieLoading)[index] ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("svg", _hoisted_22, [..._cache[7] || (_cache[7] = [(0, vue.createElementVNode)("circle", {
|
|
2160
2294
|
class: "opacity-25",
|
|
2161
2295
|
cx: "12",
|
|
2162
2296
|
cy: "12",
|
|
@@ -2167,13 +2301,13 @@ var View_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ (0, vue.def
|
|
|
2167
2301
|
class: "opacity-75",
|
|
2168
2302
|
fill: "currentColor",
|
|
2169
2303
|
d: "M4 12a8 8 0 018-8v8H4z"
|
|
2170
|
-
}, null, -1)])])) : ((0, vue.openBlock)(), (0, vue.createElementBlock)("span",
|
|
2304
|
+
}, null, -1)])])) : ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", _hoisted_23, "play_arrow"))], 8, _hoisted_21)) : (0, vue.createCommentVNode)("", true),
|
|
2171
2305
|
renderedImages[index] && renderState[index] !== "rendering" ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("button", {
|
|
2172
2306
|
key: 2,
|
|
2173
2307
|
class: "absolute top-1.5 right-1.5 flex items-center gap-1 px-2 py-0.5 text-xs rounded border border-gray-400 text-gray-600 bg-white hover:bg-gray-50 disabled:opacity-60 disabled:cursor-not-allowed",
|
|
2174
2308
|
disabled: (0, vue.unref)(movieGenerating),
|
|
2175
2309
|
onClick: (0, vue.withModifiers)(($event) => regenerateBeat(index), ["stop"])
|
|
2176
|
-
}, " ↺ ", 8,
|
|
2310
|
+
}, " ↺ ", 8, _hoisted_24)) : !renderedImages[index] ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_25, [renderState[index] === "rendering" || (0, vue.unref)(movieGenerating) && !renderedImages[index] && effectiveBeat$1(index).imagePrompt ? ((0, vue.openBlock)(), (0, vue.createElementBlock)(vue.Fragment, { key: 0 }, [_cache[8] || (_cache[8] = (0, vue.createElementVNode)("svg", {
|
|
2177
2311
|
class: "animate-spin w-4 h-4 text-green-400",
|
|
2178
2312
|
viewBox: "0 0 24 24",
|
|
2179
2313
|
fill: "none"
|
|
@@ -2188,15 +2322,15 @@ var View_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ (0, vue.def
|
|
|
2188
2322
|
class: "opacity-75",
|
|
2189
2323
|
fill: "currentColor",
|
|
2190
2324
|
d: "M4 12a8 8 0 018-8v8H4z"
|
|
2191
|
-
})], -1)), (0, vue.createElementVNode)("span",
|
|
2325
|
+
})], -1)), (0, vue.createElementVNode)("span", _hoisted_26, (0, vue.toDisplayString)((0, vue.unref)(m).rendering), 1)], 64)) : renderState[index] === "error" ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", _hoisted_27, (0, vue.toDisplayString)(renderErrors[index]), 1)) : ((0, vue.openBlock)(), (0, vue.createElementBlock)(vue.Fragment, { key: 2 }, [effectiveBeat$1(index).imagePrompt ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", _hoisted_28, (0, vue.toDisplayString)(effectiveBeat$1(index).imagePrompt), 1)) : ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", _hoisted_29, (0, vue.toDisplayString)(beat.image?.type ?? "—"), 1))], 64))])) : (0, vue.createCommentVNode)("", true)
|
|
2192
2326
|
], 64)),
|
|
2193
|
-
beatDragOver[index] ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div",
|
|
2327
|
+
beatDragOver[index] ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_30, [(0, vue.createElementVNode)("span", _hoisted_31, (0, vue.toDisplayString)((0, vue.unref)(m).drop), 1)])) : !renderedImages[index] && renderState[index] !== "rendering" ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_32, (0, vue.toDisplayString)((0, vue.unref)(m).orDropImage), 1)) : (0, vue.createCommentVNode)("", true),
|
|
2194
2328
|
!renderedImages[index] && renderState[index] !== "rendering" && !(0, vue.unref)(movieGenerating) && !(0, vue.unref)(isBeatImageReference)(effectiveBeat$1(index)) ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("button", {
|
|
2195
2329
|
key: 4,
|
|
2196
2330
|
class: "absolute top-1.5 right-1.5 flex items-center gap-1 px-2 py-0.5 text-xs rounded border border-blue-400 text-blue-600 bg-white hover:bg-blue-50",
|
|
2197
2331
|
onClick: ($event) => renderBeat(index)
|
|
2198
|
-
}, (0, vue.toDisplayString)((0, vue.unref)(m).generate), 9,
|
|
2199
|
-
], 42,
|
|
2332
|
+
}, (0, vue.toDisplayString)((0, vue.unref)(m).generate), 9, _hoisted_33)) : (0, vue.createCommentVNode)("", true)
|
|
2333
|
+
], 42, _hoisted_16), (0, vue.createElementVNode)("div", _hoisted_34, [(0, vue.createElementVNode)("span", _hoisted_35, (0, vue.toDisplayString)(effectiveBeat$1(index).text), 1), (0, vue.createElementVNode)("div", _hoisted_36, [(0, vue.createElementVNode)("div", _hoisted_37, [audioState[index] === "generating" || (0, vue.unref)(movieGenerating) && !beatAudios[index] && effectiveBeat$1(index).text ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("svg", _hoisted_38, [..._cache[9] || (_cache[9] = [(0, vue.createElementVNode)("circle", {
|
|
2200
2334
|
class: "opacity-25",
|
|
2201
2335
|
cx: "12",
|
|
2202
2336
|
cy: "12",
|
|
@@ -2211,24 +2345,24 @@ var View_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ (0, vue.def
|
|
|
2211
2345
|
key: 1,
|
|
2212
2346
|
class: (0, vue.normalizeClass)(["text-xs px-2 py-0.5 rounded border", playingAudio.value?.index === index ? "border-red-400 text-red-600 hover:bg-red-50" : "border-green-400 text-green-600 hover:bg-green-50"]),
|
|
2213
2347
|
onClick: ($event) => playAudio(index)
|
|
2214
|
-
}, (0, vue.toDisplayString)(playingAudio.value?.index === index ? (0, vue.unref)(m).stop : (0, vue.unref)(m).play), 11,
|
|
2348
|
+
}, (0, vue.toDisplayString)(playingAudio.value?.index === index ? (0, vue.unref)(m).stop : (0, vue.unref)(m).play), 11, _hoisted_39)) : audioErrors[index] ? ((0, vue.openBlock)(), (0, vue.createElementBlock)(vue.Fragment, { key: 2 }, [(0, vue.createElementVNode)("span", {
|
|
2215
2349
|
class: "text-xs text-red-400 truncate min-w-0 max-w-[20rem]",
|
|
2216
2350
|
title: audioErrors[index]
|
|
2217
|
-
}, (0, vue.toDisplayString)((0, vue.unref)(m).errPrefix) + " " + (0, vue.toDisplayString)(audioErrors[index]), 9,
|
|
2351
|
+
}, (0, vue.toDisplayString)((0, vue.unref)(m).errPrefix) + " " + (0, vue.toDisplayString)(audioErrors[index]), 9, _hoisted_40), effectiveBeat$1(index).text ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("button", {
|
|
2218
2352
|
key: 0,
|
|
2219
2353
|
class: "text-xs px-2 py-0.5 rounded border border-gray-300 text-gray-500 hover:bg-gray-50 disabled:opacity-50",
|
|
2220
2354
|
disabled: (0, vue.unref)(movieGenerating),
|
|
2221
2355
|
onClick: ($event) => generateAudio(index)
|
|
2222
|
-
}, " ↺ ", 8,
|
|
2356
|
+
}, " ↺ ", 8, _hoisted_41)) : (0, vue.createCommentVNode)("", true)], 64)) : effectiveBeat$1(index).text ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("button", {
|
|
2223
2357
|
key: 3,
|
|
2224
2358
|
class: "text-xs px-2 py-0.5 rounded border border-gray-300 text-gray-500 hover:bg-gray-50",
|
|
2225
2359
|
onClick: ($event) => generateAudio(index)
|
|
2226
|
-
}, (0, vue.toDisplayString)((0, vue.unref)(m).generateAudio), 9,
|
|
2360
|
+
}, (0, vue.toDisplayString)((0, vue.unref)(m).generateAudio), 9, _hoisted_42)) : (0, vue.createCommentVNode)("", true)]), (0, vue.createElementVNode)("button", {
|
|
2227
2361
|
class: "text-gray-400 hover:text-gray-600",
|
|
2228
2362
|
title: sourceOpen[index] ? "Hide source" : "Show source",
|
|
2229
2363
|
"data-testid": `mulmo-script-beat-source-toggle-${index}`,
|
|
2230
2364
|
onClick: ($event) => toggleSource(index)
|
|
2231
|
-
}, [..._cache[
|
|
2365
|
+
}, [..._cache[10] || (_cache[10] = [(0, vue.createElementVNode)("svg", {
|
|
2232
2366
|
xmlns: "http://www.w3.org/2000/svg",
|
|
2233
2367
|
class: "w-3.5 h-3.5",
|
|
2234
2368
|
viewBox: "0 0 24 24",
|
|
@@ -2237,36 +2371,36 @@ var View_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ (0, vue.def
|
|
|
2237
2371
|
"stroke-width": "2",
|
|
2238
2372
|
"stroke-linecap": "round",
|
|
2239
2373
|
"stroke-linejoin": "round"
|
|
2240
|
-
}, [(0, vue.createElementVNode)("polyline", { points: "16 18 22 12 16 6" }), (0, vue.createElementVNode)("polyline", { points: "8 6 2 12 8 18" })], -1)])], 8,
|
|
2374
|
+
}, [(0, vue.createElementVNode)("polyline", { points: "16 18 22 12 16 6" }), (0, vue.createElementVNode)("polyline", { points: "8 6 2 12 8 18" })], -1)])], 8, _hoisted_43)])])]), sourceOpen[index] ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_44, [(0, vue.withDirectives)((0, vue.createElementVNode)("textarea", {
|
|
2241
2375
|
"onUpdate:modelValue": ($event) => sourceText[index] = $event,
|
|
2242
2376
|
class: (0, vue.normalizeClass)(["w-full text-xs text-gray-600 bg-gray-50 p-2 font-mono resize-none", isValidBeat$1(index) ? "outline-none" : "outline outline-2 outline-red-400"]),
|
|
2243
2377
|
rows: "8",
|
|
2244
2378
|
spellcheck: "false",
|
|
2245
2379
|
"data-testid": `mulmo-script-beat-source-textarea-${index}`
|
|
2246
|
-
}, null, 10,
|
|
2380
|
+
}, null, 10, _hoisted_45), [[vue.vModelText, sourceText[index]]]), (0, vue.createElementVNode)("div", _hoisted_46, [beatSaveErrors[index] ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", _hoisted_47, (0, vue.toDisplayString)(beatSaveErrors[index].kind === "invalidJson" ? (0, vue.unref)(m).saveErrorInvalidJson(beatSaveErrors[index].error) : (0, vue.unref)(m).saveErrorSaveFailed(beatSaveErrors[index].error)), 1)) : (0, vue.createCommentVNode)("", true), (0, vue.createElementVNode)("button", {
|
|
2247
2381
|
class: (0, vue.normalizeClass)(["px-2 py-1 text-xs rounded border", isValidBeat$1(index) && !beatSaving[index] ? "border-blue-400 text-blue-600 hover:bg-blue-50 cursor-pointer" : "border-gray-200 text-gray-300 cursor-not-allowed"]),
|
|
2248
2382
|
disabled: !isValidBeat$1(index) || !!beatSaving[index],
|
|
2249
2383
|
"data-testid": `mulmo-script-beat-update-button-${index}`,
|
|
2250
2384
|
onClick: ($event) => updateBeat(index)
|
|
2251
|
-
}, (0, vue.toDisplayString)(beatSaving[index] ? (0, vue.unref)(m).saving : (0, vue.unref)(m).update), 11,
|
|
2252
|
-
}), 128)), beats.value.length === 0 ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div",
|
|
2253
|
-
(0, vue.createElementVNode)("div",
|
|
2385
|
+
}, (0, vue.toDisplayString)(beatSaving[index] ? (0, vue.unref)(m).saving : (0, vue.unref)(m).update), 11, _hoisted_48)])])) : (0, vue.createCommentVNode)("", true)]);
|
|
2386
|
+
}), 128)), beats.value.length === 0 ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_49, (0, vue.toDisplayString)((0, vue.unref)(m).noBeats), 1)) : (0, vue.createCommentVNode)("", true)], 512)),
|
|
2387
|
+
(0, vue.createElementVNode)("div", _hoisted_50, [(0, vue.createElementVNode)("details", {
|
|
2254
2388
|
ref_key: "sourceDetails",
|
|
2255
2389
|
ref: sourceDetails,
|
|
2256
2390
|
class: "script-source",
|
|
2257
|
-
onToggle: _cache[
|
|
2391
|
+
onToggle: _cache[4] || (_cache[4] = ($event) => onSourceToggle($event.target.open))
|
|
2258
2392
|
}, [
|
|
2259
2393
|
(0, vue.createElementVNode)("summary", null, (0, vue.toDisplayString)((0, vue.unref)(m).editSource), 1),
|
|
2260
2394
|
(0, vue.withDirectives)((0, vue.createElementVNode)("textarea", {
|
|
2261
|
-
"onUpdate:modelValue": _cache[
|
|
2395
|
+
"onUpdate:modelValue": _cache[3] || (_cache[3] = ($event) => editableSource.value = $event),
|
|
2262
2396
|
class: (0, vue.normalizeClass)(["script-editor", { "script-editor-invalid": sourceChanged.value && !sourceValid.value }]),
|
|
2263
2397
|
spellcheck: "false"
|
|
2264
2398
|
}, null, 2), [[vue.vModelText, editableSource.value]]),
|
|
2265
|
-
(0, vue.createElementVNode)("div",
|
|
2399
|
+
(0, vue.createElementVNode)("div", _hoisted_51, [(0, vue.createElementVNode)("button", {
|
|
2266
2400
|
class: "apply-btn",
|
|
2267
2401
|
disabled: !sourceChanged.value || !sourceValid.value,
|
|
2268
2402
|
onClick: applySource
|
|
2269
|
-
}, (0, vue.toDisplayString)((0, vue.unref)(m).applyChanges), 9,
|
|
2403
|
+
}, (0, vue.toDisplayString)((0, vue.unref)(m).applyChanges), 9, _hoisted_52), (0, vue.createElementVNode)("button", {
|
|
2270
2404
|
class: "cancel-btn",
|
|
2271
2405
|
onClick: cancelSourceEdit
|
|
2272
2406
|
}, (0, vue.toDisplayString)((0, vue.unref)(m).cancel), 1)])
|
|
@@ -2274,9 +2408,9 @@ var View_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ (0, vue.def
|
|
|
2274
2408
|
class: "copy-btn",
|
|
2275
2409
|
title: (0, vue.unref)(copied) ? "Copied!" : "Copy",
|
|
2276
2410
|
onClick: copyText
|
|
2277
|
-
}, [(0, vue.createElementVNode)("span",
|
|
2411
|
+
}, [(0, vue.createElementVNode)("span", _hoisted_54, (0, vue.toDisplayString)((0, vue.unref)(copied) ? "check" : "content_copy"), 1)], 8, _hoisted_53), [[vue.vShow, !editing.value]])]),
|
|
2278
2412
|
lightbox.value ? ((0, vue.openBlock)(), (0, vue.createBlock)(BeatLightbox_default, {
|
|
2279
|
-
key:
|
|
2413
|
+
key: 5,
|
|
2280
2414
|
lightbox: lightbox.value,
|
|
2281
2415
|
"beat-count": beats.value.length,
|
|
2282
2416
|
"beat-texts": beatTexts.value,
|
|
@@ -2312,7 +2446,7 @@ var _plugin_vue_export_helper_default = (sfc, props) => {
|
|
|
2312
2446
|
};
|
|
2313
2447
|
//#endregion
|
|
2314
2448
|
//#region src/vue/View.vue
|
|
2315
|
-
var View_default = /*#__PURE__*/ _plugin_vue_export_helper_default(View_vue_vue_type_script_setup_true_lang_default, [["__scopeId", "data-v-
|
|
2449
|
+
var View_default = /*#__PURE__*/ _plugin_vue_export_helper_default(View_vue_vue_type_script_setup_true_lang_default, [["__scopeId", "data-v-2d5f76ac"]]);
|
|
2316
2450
|
//#endregion
|
|
2317
2451
|
//#region src/vue/Preview.vue?vue&type=script&setup=true&lang.ts
|
|
2318
2452
|
var _hoisted_1 = {
|