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