@vishu1301/script-writing 1.0.4 → 1.0.6
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 +8 -4
- package/dist/index.cjs +854 -129
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +86 -7
- package/dist/index.d.ts +86 -7
- package/dist/index.js +851 -131
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/dist/index.cjs
CHANGED
|
@@ -359,51 +359,127 @@ function ScreenplayEditorView({
|
|
|
359
359
|
}
|
|
360
360
|
}, [COURIER_STACK]);
|
|
361
361
|
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
362
|
-
/* @__PURE__ */ jsxRuntime.
|
|
362
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
363
363
|
"div",
|
|
364
364
|
{
|
|
365
|
-
className: "sticky top-6 z-50 bg-white backdrop-blur-
|
|
365
|
+
className: "sticky top-6 z-50 mx-auto bg-white/70 backdrop-blur-2xl border border-white/60 shadow-[0_8px_30px_rgb(0,0,0,0.04)] ring-1 ring-zinc-900/5 rounded-[2rem] flex items-center justify-between p-2 mb-12 select-none transition-all",
|
|
366
366
|
style: {
|
|
367
|
-
maxWidth: "
|
|
367
|
+
maxWidth: "1240px"
|
|
368
368
|
},
|
|
369
|
-
children:
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
369
|
+
children: [
|
|
370
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex gap-1 overflow-x-auto custom-scrollbar pr-2 items-center", children: blockTypes.map((type) => {
|
|
371
|
+
var _a;
|
|
372
|
+
const selected = ((_a = blocks.find((b) => b.id === focusedBlockId)) == null ? void 0 : _a.type) === type;
|
|
373
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
374
|
+
"button",
|
|
375
|
+
{
|
|
376
|
+
type: "button",
|
|
377
|
+
className: `group flex items-center gap-2.5 px-4 py-2 rounded-full font-semibold text-sm transition-all duration-300 ease-out active:scale-95 ${selected ? "bg-zinc-900 text-white shadow-md shadow-zinc-900/20" : "text-zinc-500 hover:bg-zinc-100 hover:text-zinc-900"}`,
|
|
378
|
+
onClick: () => handleBlockTypeChange(type),
|
|
379
|
+
children: [
|
|
380
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
381
|
+
"input",
|
|
382
|
+
{
|
|
383
|
+
type: "radio",
|
|
384
|
+
name: "blockType",
|
|
385
|
+
id: `block-type-${type}`,
|
|
386
|
+
className: "sr-only",
|
|
387
|
+
"aria-label": blockStyles[type].label,
|
|
388
|
+
checked: selected,
|
|
389
|
+
readOnly: true
|
|
390
|
+
}
|
|
391
|
+
),
|
|
392
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
393
|
+
"label",
|
|
394
|
+
{
|
|
395
|
+
htmlFor: `block-type-${type}`,
|
|
396
|
+
className: "flex items-center gap-2 cursor-pointer pointer-events-none",
|
|
397
|
+
children: [
|
|
398
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
399
|
+
"div",
|
|
400
|
+
{
|
|
401
|
+
className: `${selected ? "opacity-100" : "opacity-70 group-hover:opacity-100"} transition-opacity duration-200`,
|
|
402
|
+
children: icons[type]
|
|
403
|
+
}
|
|
404
|
+
),
|
|
405
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "whitespace-nowrap hidden sm:inline tracking-wide", children: blockStyles[type].label })
|
|
406
|
+
]
|
|
407
|
+
}
|
|
408
|
+
)
|
|
409
|
+
]
|
|
410
|
+
},
|
|
411
|
+
type
|
|
412
|
+
);
|
|
413
|
+
}) }),
|
|
414
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1 shrink-0 relative px-1", children: [
|
|
415
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-[1px] h-6 bg-zinc-200/80 mx-2 hidden sm:block rounded-full" }),
|
|
416
|
+
/* @__PURE__ */ jsxRuntime.jsx(PdfImporter, { onScriptImported: handleScriptImport, children: /* @__PURE__ */ jsxRuntime.jsx("div", { title: "Import Script", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Upload, { className: "w-[18px] h-[18px]" }) }) }),
|
|
417
|
+
onSave && /* @__PURE__ */ jsxRuntime.jsx(
|
|
418
|
+
"button",
|
|
419
|
+
{
|
|
420
|
+
onClick: onSave,
|
|
421
|
+
className: "flex items-center justify-center w-10 h-10 rounded-full text-zinc-500 hover:bg-zinc-100 hover:text-zinc-900 transition-all duration-200 active:scale-95",
|
|
422
|
+
title: "Save Script",
|
|
423
|
+
"aria-label": "Save Script",
|
|
424
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Save, { className: "w-[18px] h-[18px]" })
|
|
425
|
+
}
|
|
426
|
+
),
|
|
427
|
+
onSaveAsPdf && /* @__PURE__ */ jsxRuntime.jsx(
|
|
428
|
+
"button",
|
|
429
|
+
{
|
|
430
|
+
onClick: onSaveAsPdf,
|
|
431
|
+
className: "flex items-center justify-center w-10 h-10 rounded-full text-zinc-500 hover:bg-zinc-100 hover:text-zinc-900 transition-all duration-200 active:scale-95",
|
|
432
|
+
title: "Save as PDF",
|
|
433
|
+
"aria-label": "Save Script as PDF",
|
|
434
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.FileDown, { className: "w-[18px] h-[18px]" })
|
|
435
|
+
}
|
|
436
|
+
),
|
|
437
|
+
onSaveAsSbx && /* @__PURE__ */ jsxRuntime.jsx(
|
|
438
|
+
"button",
|
|
439
|
+
{
|
|
440
|
+
onClick: onSaveAsSbx,
|
|
441
|
+
className: "flex items-center justify-center w-10 h-10 rounded-full text-zinc-500 hover:bg-zinc-100 hover:text-zinc-900 transition-all duration-200 active:scale-95",
|
|
442
|
+
title: "Sync with Cloud (SBX)",
|
|
443
|
+
"aria-label": "Save Script as SBX",
|
|
444
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.RefreshCcw, { className: "w-[18px] h-[18px]" })
|
|
445
|
+
}
|
|
446
|
+
),
|
|
447
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
448
|
+
"button",
|
|
449
|
+
{
|
|
450
|
+
onClick: () => setIsRulesOpen(!isRulesOpen),
|
|
451
|
+
className: `flex items-center justify-center w-10 h-10 rounded-full transition-all duration-200 active:scale-95 ${isRulesOpen ? "bg-zinc-900 text-white shadow-md shadow-zinc-900/20" : "text-zinc-500 hover:bg-zinc-100 hover:text-zinc-900"}`,
|
|
452
|
+
title: "Settings & Shortcuts",
|
|
453
|
+
"aria-label": "Toggle Settings",
|
|
454
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Cog, { className: "w-[18px] h-[18px]" })
|
|
455
|
+
}
|
|
456
|
+
),
|
|
457
|
+
isRulesOpen && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "absolute top-[calc(100%+1rem)] right-0 bg-white/95 backdrop-blur-3xl rounded-[1.5rem] shadow-[0_20px_60px_-15px_rgba(0,0,0,0.1)] ring-1 ring-zinc-900/5 p-5 text-sm text-zinc-700 select-none font-sans overflow-hidden transition-all duration-300 w-72 origin-top-right animate-in fade-in zoom-in-95 z-50", children: [
|
|
458
|
+
/* @__PURE__ */ jsxRuntime.jsxs("h4", { className: "font-bold text-zinc-900 mb-4 text-sm flex items-center gap-2", children: [
|
|
459
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Cog, { className: "w-4 h-4 text-zinc-400" }),
|
|
460
|
+
"Settings & Shortcuts"
|
|
461
|
+
] }),
|
|
462
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-4", children: /* @__PURE__ */ jsxRuntime.jsxs("ul", { className: "space-y-2.5", children: [
|
|
463
|
+
/* @__PURE__ */ jsxRuntime.jsxs("li", { className: "flex items-center justify-between gap-6", children: [
|
|
464
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium text-zinc-600", children: "New Block" }),
|
|
465
|
+
/* @__PURE__ */ jsxRuntime.jsx("kbd", { className: "px-2 py-1 text-[11px] font-bold text-zinc-700 bg-white border border-zinc-200/80 shadow-[0_2px_4px_rgb(0,0,0,0.02)] rounded-md", children: "Enter" })
|
|
466
|
+
] }),
|
|
467
|
+
/* @__PURE__ */ jsxRuntime.jsxs("li", { className: "flex items-center justify-between gap-6", children: [
|
|
468
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium text-zinc-600", children: "Delete Block" }),
|
|
469
|
+
/* @__PURE__ */ jsxRuntime.jsx("kbd", { className: "px-2 py-1 text-[11px] font-bold text-zinc-700 bg-white border border-zinc-200/80 shadow-[0_2px_4px_rgb(0,0,0,0.02)] rounded-md", children: "Backspace" })
|
|
470
|
+
] }),
|
|
471
|
+
/* @__PURE__ */ jsxRuntime.jsxs("li", { className: "flex items-center justify-between gap-6", children: [
|
|
472
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium text-zinc-600", children: "Change Type" }),
|
|
473
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1", children: [
|
|
474
|
+
/* @__PURE__ */ jsxRuntime.jsx("kbd", { className: "px-2 py-1 text-[11px] font-bold text-zinc-700 bg-white border border-zinc-200/80 shadow-[0_2px_4px_rgb(0,0,0,0.02)] rounded-md", children: "Ctrl" }),
|
|
475
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-zinc-400 font-medium", children: "+" }),
|
|
476
|
+
/* @__PURE__ */ jsxRuntime.jsx("kbd", { className: "px-2 py-1 text-[11px] font-bold text-zinc-700 bg-white border border-zinc-200/80 shadow-[0_2px_4px_rgb(0,0,0,0.02)] rounded-md", children: "\u2191/\u2193" })
|
|
477
|
+
] })
|
|
478
|
+
] })
|
|
479
|
+
] }) })
|
|
480
|
+
] })
|
|
481
|
+
] })
|
|
482
|
+
]
|
|
407
483
|
}
|
|
408
484
|
),
|
|
409
485
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-col gap-12 w-full items-center pb-24", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -641,79 +717,7 @@ function ScreenplayEditorView({
|
|
|
641
717
|
);
|
|
642
718
|
})
|
|
643
719
|
}
|
|
644
|
-
) })
|
|
645
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "fixed bottom-6 right-6 flex flex-col items-end gap-4 z-50", children: [
|
|
646
|
-
/* @__PURE__ */ jsxRuntime.jsx(PdfImporter, { onScriptImported: handleScriptImport, children: /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
647
|
-
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Upload, { className: "w-5 h-5" }),
|
|
648
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm font-semibold", children: "Import" })
|
|
649
|
-
] }) }),
|
|
650
|
-
onSave && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
651
|
-
"button",
|
|
652
|
-
{
|
|
653
|
-
onClick: onSave,
|
|
654
|
-
className: "flex items-center justify-center gap-2 w-auto px-4 h-12 rounded-full bg-zinc-950 text-white shadow-xl shadow-zinc-900/20 border border-white/10 hover:bg-zinc-800 hover:scale-105 active:scale-95 transition-all duration-300",
|
|
655
|
-
"aria-label": "Save Script",
|
|
656
|
-
children: [
|
|
657
|
-
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Save, { className: "w-5 h-5" }),
|
|
658
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm font-semibold", children: "Save" })
|
|
659
|
-
]
|
|
660
|
-
}
|
|
661
|
-
),
|
|
662
|
-
onSaveAsPdf && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
663
|
-
"button",
|
|
664
|
-
{
|
|
665
|
-
onClick: onSaveAsPdf,
|
|
666
|
-
className: "flex items-center justify-center gap-2 w-auto px-4 h-12 rounded-full bg-zinc-950 text-white shadow-xl shadow-zinc-900/20 border border-white/10 hover:bg-zinc-800 hover:scale-105 active:scale-95 transition-all duration-300",
|
|
667
|
-
"aria-label": "Save Script as PDF",
|
|
668
|
-
children: [
|
|
669
|
-
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.FileDown, { className: "w-5 h-5" }),
|
|
670
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm font-semibold", children: "Save as PDF" })
|
|
671
|
-
]
|
|
672
|
-
}
|
|
673
|
-
),
|
|
674
|
-
onSaveAsSbx && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
675
|
-
"button",
|
|
676
|
-
{
|
|
677
|
-
onClick: onSaveAsSbx,
|
|
678
|
-
className: "flex items-center justify-center gap-2 w-auto px-4 h-12 rounded-full bg-zinc-950 text-white shadow-xl shadow-zinc-900/20 border border-white/10 hover:bg-zinc-800 hover:scale-105 active:scale-95 transition-all duration-300",
|
|
679
|
-
"aria-label": "Save Script as SBX",
|
|
680
|
-
children: [
|
|
681
|
-
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.RefreshCcw, { className: "w-5 h-5" }),
|
|
682
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm font-semibold", children: "Save" })
|
|
683
|
-
]
|
|
684
|
-
}
|
|
685
|
-
),
|
|
686
|
-
isRulesOpen && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bg-white/80 backdrop-blur-md rounded-xl shadow-lg border border-zinc-200/50 p-4 text-xs text-zinc-700 select-none font-sans overflow-hidden transition-all duration-300 w-64 origin-bottom-right animate-in fade-in zoom-in-95", children: [
|
|
687
|
-
/* @__PURE__ */ jsxRuntime.jsx("h4", { className: "font-bold text-zinc-800 mb-3 text-sm", children: "Settings & Shortcuts" }),
|
|
688
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-4", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-1.5", children: /* @__PURE__ */ jsxRuntime.jsxs("ul", { className: "space-y-1.5", children: [
|
|
689
|
-
/* @__PURE__ */ jsxRuntime.jsxs("li", { className: "flex items-center justify-between gap-6", children: [
|
|
690
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { children: "New Block" }),
|
|
691
|
-
/* @__PURE__ */ jsxRuntime.jsx("kbd", { className: "px-2 py-1 text-xs font-semibold text-zinc-800 bg-zinc-200/70 border border-zinc-300/70 rounded-md", children: "Enter" })
|
|
692
|
-
] }),
|
|
693
|
-
/* @__PURE__ */ jsxRuntime.jsxs("li", { className: "flex items-center justify-between gap-6", children: [
|
|
694
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { children: "Delete Block" }),
|
|
695
|
-
/* @__PURE__ */ jsxRuntime.jsx("kbd", { className: "px-2 py-1 text-xs font-semibold text-zinc-800 bg-zinc-200/70 border border-zinc-300/70 rounded-md", children: "Backspace" })
|
|
696
|
-
] }),
|
|
697
|
-
/* @__PURE__ */ jsxRuntime.jsxs("li", { className: "flex items-center justify-between gap-6", children: [
|
|
698
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { children: "Change Type" }),
|
|
699
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1", children: [
|
|
700
|
-
/* @__PURE__ */ jsxRuntime.jsx("kbd", { className: "px-2 py-1 text-xs font-semibold text-zinc-800 bg-zinc-200/70 border border-zinc-300/70 rounded-md", children: "Ctrl" }),
|
|
701
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { children: "+" }),
|
|
702
|
-
/* @__PURE__ */ jsxRuntime.jsx("kbd", { className: "px-2 py-1 text-xs font-semibold text-zinc-800 bg-zinc-200/70 border border-zinc-300/70 rounded-md", children: "\u2191/\u2193" })
|
|
703
|
-
] })
|
|
704
|
-
] })
|
|
705
|
-
] }) }) })
|
|
706
|
-
] }),
|
|
707
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
708
|
-
"button",
|
|
709
|
-
{
|
|
710
|
-
onClick: () => setIsRulesOpen(!isRulesOpen),
|
|
711
|
-
className: `flex items-center justify-center w-12 h-12 rounded-full bg-zinc-950 text-white shadow-xl shadow-zinc-900/20 border border-white/10 hover:bg-zinc-800 hover:scale-105 active:scale-95 transition-all duration-300 ${isRulesOpen ? "rotate-90" : "rotate-0"}`,
|
|
712
|
-
"aria-label": "Toggle Settings",
|
|
713
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Cog, { className: "w-5 h-5" })
|
|
714
|
-
}
|
|
715
|
-
)
|
|
716
|
-
] })
|
|
720
|
+
) })
|
|
717
721
|
] });
|
|
718
722
|
}
|
|
719
723
|
|
|
@@ -1376,6 +1380,33 @@ function useScreenplayEditor(options) {
|
|
|
1376
1380
|
return block;
|
|
1377
1381
|
});
|
|
1378
1382
|
setBlocks(finalizedBlocks);
|
|
1383
|
+
if (options == null ? void 0 : options.onSave) {
|
|
1384
|
+
options.onSave(content);
|
|
1385
|
+
const typeToDivClass = {
|
|
1386
|
+
SCENE_HEADING: "divtype0",
|
|
1387
|
+
ACTION: "divtype2",
|
|
1388
|
+
CHARACTER: "divtype3",
|
|
1389
|
+
PARENTHETICAL: "divtype4",
|
|
1390
|
+
DIALOGUE: "divtype5",
|
|
1391
|
+
TRANSITION: "divtype6",
|
|
1392
|
+
GENERAL: "divtype2"
|
|
1393
|
+
};
|
|
1394
|
+
const sbxData = finalizedBlocks.map((block) => {
|
|
1395
|
+
const divClass = typeToDivClass[block.type] || "divtype2";
|
|
1396
|
+
let text = block.text || "";
|
|
1397
|
+
let extraAttributes = "";
|
|
1398
|
+
if (block.type === "SCENE_HEADING") {
|
|
1399
|
+
text = `${block.sceneType || "INT."} ${text} - ${block.timeOfDay || "DAY"}`.toUpperCase();
|
|
1400
|
+
if (block.sceneNumber) {
|
|
1401
|
+
extraAttributes = ` data-scene="${block.sceneNumber}"`;
|
|
1402
|
+
}
|
|
1403
|
+
} else if (block.type === "CHARACTER" || block.type === "TRANSITION") {
|
|
1404
|
+
text = text.toUpperCase();
|
|
1405
|
+
}
|
|
1406
|
+
return `<div class="${divClass}" id="par${block.id}"${extraAttributes}>${text}</div>`;
|
|
1407
|
+
}).join("");
|
|
1408
|
+
options.onSave(sbxData);
|
|
1409
|
+
}
|
|
1379
1410
|
setTimeout(() => {
|
|
1380
1411
|
var _a;
|
|
1381
1412
|
const firstId = parsedBlocks[0].id;
|
|
@@ -1386,7 +1417,7 @@ function useScreenplayEditor(options) {
|
|
|
1386
1417
|
}, 100);
|
|
1387
1418
|
}
|
|
1388
1419
|
},
|
|
1389
|
-
[refs]
|
|
1420
|
+
[refs, options == null ? void 0 : options.onSave]
|
|
1390
1421
|
);
|
|
1391
1422
|
const handleFocus = react.useCallback(
|
|
1392
1423
|
(id) => {
|
|
@@ -1529,7 +1560,7 @@ function useScreenplayEditor(options) {
|
|
|
1529
1560
|
loadFromUrl
|
|
1530
1561
|
};
|
|
1531
1562
|
}
|
|
1532
|
-
var handleSaveAsPdf = (blocks, sceneNumbers) => {
|
|
1563
|
+
var handleSaveAsPdf = (blocks, sceneNumbers, project_name) => {
|
|
1533
1564
|
if (document.activeElement instanceof HTMLElement) {
|
|
1534
1565
|
document.activeElement.blur();
|
|
1535
1566
|
}
|
|
@@ -1614,9 +1645,13 @@ var handleSaveAsPdf = (blocks, sceneNumbers) => {
|
|
|
1614
1645
|
}
|
|
1615
1646
|
y += blockHeight;
|
|
1616
1647
|
});
|
|
1617
|
-
|
|
1648
|
+
if (project_name) {
|
|
1649
|
+
doc.save(`${project_name}_${(/* @__PURE__ */ new Date()).toISOString()}.pdf`);
|
|
1650
|
+
} else {
|
|
1651
|
+
doc.save("screenplay_export.pdf");
|
|
1652
|
+
}
|
|
1618
1653
|
};
|
|
1619
|
-
var
|
|
1654
|
+
var convertBlocksToSbx = (blocks, sceneNumbers) => {
|
|
1620
1655
|
const typeToDivClass = {
|
|
1621
1656
|
SCENE_HEADING: "divtype0",
|
|
1622
1657
|
ACTION: "divtype2",
|
|
@@ -1626,7 +1661,7 @@ var handleSaveAsSbx = (blocks, sceneNumbers, onSaveAsSbx) => {
|
|
|
1626
1661
|
TRANSITION: "divtype6",
|
|
1627
1662
|
GENERAL: "divtype2"
|
|
1628
1663
|
};
|
|
1629
|
-
|
|
1664
|
+
return blocks.map((block) => {
|
|
1630
1665
|
const divClass = typeToDivClass[block.type] || "divtype2";
|
|
1631
1666
|
let text = block.text || "";
|
|
1632
1667
|
let extraAttributes = "";
|
|
@@ -1641,29 +1676,719 @@ var handleSaveAsSbx = (blocks, sceneNumbers, onSaveAsSbx) => {
|
|
|
1641
1676
|
}
|
|
1642
1677
|
return `<div class="${divClass}" id="par${block.id}"${extraAttributes}>${text}</div>`;
|
|
1643
1678
|
}).join("");
|
|
1679
|
+
};
|
|
1680
|
+
var handleSaveAsSbx = (blocks, sceneNumbers, onSaveAsSbx, project_name) => {
|
|
1681
|
+
const sbxData = convertBlocksToSbx(blocks, sceneNumbers);
|
|
1644
1682
|
const blob = new Blob([sbxData], { type: "text/plain" });
|
|
1645
|
-
const url = URL.createObjectURL(blob);
|
|
1646
|
-
const a = document.createElement("a");
|
|
1647
|
-
a.href = url;
|
|
1648
|
-
a.download = "screenplay.sbx";
|
|
1649
|
-
document.body.appendChild(a);
|
|
1650
|
-
a.click();
|
|
1651
|
-
document.body.removeChild(a);
|
|
1652
|
-
URL.revokeObjectURL(url);
|
|
1653
1683
|
if (onSaveAsSbx) {
|
|
1654
|
-
|
|
1655
|
-
|
|
1684
|
+
if (project_name) {
|
|
1685
|
+
const file = new File(
|
|
1686
|
+
[blob],
|
|
1687
|
+
`${project_name}_${(/* @__PURE__ */ new Date()).toISOString()}.sbx`,
|
|
1688
|
+
{ type: "text/plain" }
|
|
1689
|
+
);
|
|
1690
|
+
onSaveAsSbx(file);
|
|
1691
|
+
} else {
|
|
1692
|
+
const file = new File([blob], "screenplay.sbx", { type: "text/plain" });
|
|
1693
|
+
onSaveAsSbx(file);
|
|
1694
|
+
}
|
|
1695
|
+
}
|
|
1696
|
+
};
|
|
1697
|
+
var handleSyncWithCloud = (blocks, sceneNumbers, onSyncWithCloud) => {
|
|
1698
|
+
if (onSyncWithCloud) {
|
|
1699
|
+
const sbxData = convertBlocksToSbx(blocks, sceneNumbers);
|
|
1700
|
+
onSyncWithCloud(sbxData);
|
|
1656
1701
|
}
|
|
1657
1702
|
};
|
|
1658
1703
|
|
|
1704
|
+
// app/types/script-breakdown.types.tsx
|
|
1705
|
+
var CATEGORIES = [
|
|
1706
|
+
{ id: "CAST", label: "Cast", color: "#7c3aed", hex: "#8b5cf6" },
|
|
1707
|
+
{ id: "PROP", label: "Prop", color: "#ea580c", hex: "#f97316" },
|
|
1708
|
+
{ id: "COSTUME", label: "Costume", color: "#db2777", hex: "#ec4899" },
|
|
1709
|
+
{ id: "VEHICLE", label: "Vehicle", color: "#2563eb", hex: "#3b82f6" },
|
|
1710
|
+
{ id: "SET_PROP", label: "Set Prop", color: "#16a34a", hex: "#22c55e" },
|
|
1711
|
+
{ id: "EXTRA", label: "Extra", color: "#0d9488", hex: "#14b8a6" },
|
|
1712
|
+
{ id: "LOCATION", label: "Location", color: "#ca8a04", hex: "#eab308" }
|
|
1713
|
+
];
|
|
1714
|
+
function ScriptBreakdownSceneView({
|
|
1715
|
+
blocks,
|
|
1716
|
+
characters,
|
|
1717
|
+
isLoading,
|
|
1718
|
+
sceneNumber,
|
|
1719
|
+
tags,
|
|
1720
|
+
selectionMenu,
|
|
1721
|
+
handleMouseUp,
|
|
1722
|
+
addTag,
|
|
1723
|
+
removeTag,
|
|
1724
|
+
clearSelection,
|
|
1725
|
+
menuPlacement,
|
|
1726
|
+
menuRef,
|
|
1727
|
+
subLocations,
|
|
1728
|
+
addSubLocation,
|
|
1729
|
+
removeSubLocation,
|
|
1730
|
+
sceneBrief,
|
|
1731
|
+
setSceneBrief
|
|
1732
|
+
}) {
|
|
1733
|
+
const COURIER_STACK = "'Courier Prime', 'Courier', monospace";
|
|
1734
|
+
const [isSubLocOpen, setIsSubLocOpen] = react.useState(false);
|
|
1735
|
+
const [subLocInput, setSubLocInput] = react.useState("");
|
|
1736
|
+
const subLocPopoverRef = react.useRef(null);
|
|
1737
|
+
react.useEffect(() => {
|
|
1738
|
+
const handleClickOutside = (e) => {
|
|
1739
|
+
if (isSubLocOpen && subLocPopoverRef.current && !subLocPopoverRef.current.contains(e.target)) {
|
|
1740
|
+
setIsSubLocOpen(false);
|
|
1741
|
+
}
|
|
1742
|
+
};
|
|
1743
|
+
document.addEventListener("mousedown", handleClickOutside);
|
|
1744
|
+
return () => document.removeEventListener("mousedown", handleClickOutside);
|
|
1745
|
+
}, [isSubLocOpen]);
|
|
1746
|
+
react.useEffect(() => {
|
|
1747
|
+
const fontId = "google-font-courier-prime";
|
|
1748
|
+
const styleId = "screenplay-editor-force-v4";
|
|
1749
|
+
if (!document.getElementById(fontId)) {
|
|
1750
|
+
const link = document.createElement("link");
|
|
1751
|
+
link.id = fontId;
|
|
1752
|
+
link.rel = "stylesheet";
|
|
1753
|
+
link.href = "https://fonts.googleapis.com/css2?family=Courier+Prime:ital,wght@0,400;0,700;1,400;1,700&display=swap";
|
|
1754
|
+
document.head.appendChild(link);
|
|
1755
|
+
}
|
|
1756
|
+
if (!document.getElementById(styleId)) {
|
|
1757
|
+
const style = document.createElement("style");
|
|
1758
|
+
style.id = styleId;
|
|
1759
|
+
style.textContent = `
|
|
1760
|
+
/* We target by the data-attribute to ensure the highest specificity possible */
|
|
1761
|
+
[data-screenplay-editor] *,
|
|
1762
|
+
[data-screenplay-editor] div,
|
|
1763
|
+
[data-screenplay-editor] span,
|
|
1764
|
+
[data-screenplay-editor] [contenteditable="true"] {
|
|
1765
|
+
font-family: ${COURIER_STACK} !important;
|
|
1766
|
+
-webkit-font-smoothing: antialiased;
|
|
1767
|
+
}
|
|
1768
|
+
`;
|
|
1769
|
+
document.head.appendChild(style);
|
|
1770
|
+
}
|
|
1771
|
+
}, [COURIER_STACK]);
|
|
1772
|
+
if (isLoading) {
|
|
1773
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col items-center justify-center py-32 gap-4", children: [
|
|
1774
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Loader2, { className: "w-8 h-8 animate-spin text-zinc-400" }),
|
|
1775
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm font-medium text-zinc-500 animate-pulse", children: "Loading scene details..." })
|
|
1776
|
+
] });
|
|
1777
|
+
}
|
|
1778
|
+
const hasLocationTag = tags.some((t) => t.categoryId === "LOCATION");
|
|
1779
|
+
const renderBlockText = (block) => {
|
|
1780
|
+
const blockTags = tags.filter((t) => t.blockId === block.id).sort((a, b) => a.startIndex - b.startIndex);
|
|
1781
|
+
if (blockTags.length === 0) return block.text;
|
|
1782
|
+
const nodes = [];
|
|
1783
|
+
let currentIndex = 0;
|
|
1784
|
+
blockTags.forEach((tag) => {
|
|
1785
|
+
if (tag.startIndex > currentIndex) {
|
|
1786
|
+
nodes.push(
|
|
1787
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: block.text.slice(currentIndex, tag.startIndex) }, `text-${currentIndex}`)
|
|
1788
|
+
);
|
|
1789
|
+
}
|
|
1790
|
+
const category = CATEGORIES.find((c) => c.id === tag.categoryId);
|
|
1791
|
+
nodes.push(
|
|
1792
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1793
|
+
"span",
|
|
1794
|
+
{
|
|
1795
|
+
title: `${category == null ? void 0 : category.label} (Click to edit)`,
|
|
1796
|
+
onClick: (e) => {
|
|
1797
|
+
e.stopPropagation();
|
|
1798
|
+
const selection = window.getSelection();
|
|
1799
|
+
if (!selection) return;
|
|
1800
|
+
const range = document.createRange();
|
|
1801
|
+
const textNode = e.currentTarget.firstChild;
|
|
1802
|
+
if (textNode && textNode.nodeType === Node.TEXT_NODE) {
|
|
1803
|
+
range.selectNodeContents(textNode);
|
|
1804
|
+
} else {
|
|
1805
|
+
range.selectNodeContents(e.currentTarget);
|
|
1806
|
+
}
|
|
1807
|
+
selection.removeAllRanges();
|
|
1808
|
+
selection.addRange(range);
|
|
1809
|
+
setTimeout(() => handleMouseUp(), 0);
|
|
1810
|
+
},
|
|
1811
|
+
className: "cursor-pointer font-bold transition-opacity hover:opacity-70",
|
|
1812
|
+
style: { color: category == null ? void 0 : category.color },
|
|
1813
|
+
children: block.text.slice(tag.startIndex, tag.endIndex)
|
|
1814
|
+
},
|
|
1815
|
+
tag.id
|
|
1816
|
+
)
|
|
1817
|
+
);
|
|
1818
|
+
currentIndex = tag.endIndex;
|
|
1819
|
+
});
|
|
1820
|
+
if (currentIndex < block.text.length) {
|
|
1821
|
+
nodes.push(
|
|
1822
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: block.text.slice(currentIndex) }, `text-${currentIndex}`)
|
|
1823
|
+
);
|
|
1824
|
+
}
|
|
1825
|
+
return nodes;
|
|
1826
|
+
};
|
|
1827
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-8 md:p-12 mx-auto w-full min-h-screen flex flex-col gap-8", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col lg:flex-row gap-8 items-start", children: [
|
|
1828
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-4", children: [
|
|
1829
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1830
|
+
"div",
|
|
1831
|
+
{
|
|
1832
|
+
className: "relative bg-[#fdfdfc] shadow-2xl shadow-zinc-300/60 border border-zinc-100 rounded-sm md:rounded-md pl-[1.5in] py-[1in] pr-[1in] flex flex-col w-[210mm] min-h-auto shrink-0",
|
|
1833
|
+
style: {
|
|
1834
|
+
fontFamily: COURIER_STACK,
|
|
1835
|
+
paddingLeft: "1.5in",
|
|
1836
|
+
paddingRight: "1in",
|
|
1837
|
+
paddingTop: "1in",
|
|
1838
|
+
paddingBottom: "1in",
|
|
1839
|
+
lineHeight: "1.2"
|
|
1840
|
+
},
|
|
1841
|
+
"data-screenplay-editor": "true",
|
|
1842
|
+
onMouseUp: handleMouseUp,
|
|
1843
|
+
children: blocks.map((block) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1844
|
+
"div",
|
|
1845
|
+
{
|
|
1846
|
+
"data-block-id": block.id,
|
|
1847
|
+
className: `relative break-words w-full px-4 py-2 ${blockStyles[block.type].className}`,
|
|
1848
|
+
style: __spreadProps(__spreadValues({}, blockStyles[block.type].inputStyle), {
|
|
1849
|
+
minHeight: "2.5rem"
|
|
1850
|
+
}),
|
|
1851
|
+
children: [
|
|
1852
|
+
renderBlockText(block),
|
|
1853
|
+
(selectionMenu == null ? void 0 : selectionMenu.blockId) === block.id && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1854
|
+
"div",
|
|
1855
|
+
{
|
|
1856
|
+
ref: menuRef,
|
|
1857
|
+
"data-screenplay-editor": "false",
|
|
1858
|
+
className: `tag-menu absolute z-50 bg-white/70 backdrop-blur-2xl shadow-[0_10px_40px_rgb(0,0,0,0.06)] border border-white rounded-[1.5rem] p-2 flex flex-col w-56 animate-in fade-in zoom-in-95 duration-300 ease-out ${menuPlacement === "top" ? "origin-bottom" : "origin-top"}`,
|
|
1859
|
+
style: {
|
|
1860
|
+
top: selectionMenu.top,
|
|
1861
|
+
left: selectionMenu.left,
|
|
1862
|
+
transform: menuPlacement === "top" ? "translate(-50%, calc(-100% - 12px))" : "translate(-50%, 32px)"
|
|
1863
|
+
},
|
|
1864
|
+
children: [
|
|
1865
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative z-10 px-3 py-2.5 border-b border-white/60 mb-1.5", children: [
|
|
1866
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-[9px] font-extrabold tracking-[0.2em] text-slate-400 uppercase mb-1", children: "Tag Element" }),
|
|
1867
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
1868
|
+
"p",
|
|
1869
|
+
{
|
|
1870
|
+
className: "text-xs font-bold text-slate-700 truncate drop-shadow-sm",
|
|
1871
|
+
title: selectionMenu.text,
|
|
1872
|
+
children: [
|
|
1873
|
+
'"',
|
|
1874
|
+
selectionMenu.text,
|
|
1875
|
+
'"'
|
|
1876
|
+
]
|
|
1877
|
+
}
|
|
1878
|
+
)
|
|
1879
|
+
] }),
|
|
1880
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative z-10 flex flex-col gap-1", children: [
|
|
1881
|
+
CATEGORIES.filter(
|
|
1882
|
+
(cat) => !(cat.id === "LOCATION" && hasLocationTag)
|
|
1883
|
+
).map((cat) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1884
|
+
"button",
|
|
1885
|
+
{
|
|
1886
|
+
onClick: () => addTag(cat.id),
|
|
1887
|
+
className: "group w-full text-[12px] font-bold px-3 py-2 rounded-xl transition-all duration-300 text-left flex items-center justify-between hover:bg-white/80 hover:shadow-[0_2px_10px_rgb(0,0,0,0.02)] active:scale-[0.98]",
|
|
1888
|
+
style: { color: cat.color },
|
|
1889
|
+
children: [
|
|
1890
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3", children: [
|
|
1891
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1892
|
+
"div",
|
|
1893
|
+
{
|
|
1894
|
+
className: "w-2 h-2 rounded-full shadow-sm group-hover:scale-125 transition-transform duration-300",
|
|
1895
|
+
style: { backgroundColor: cat.hex }
|
|
1896
|
+
}
|
|
1897
|
+
),
|
|
1898
|
+
cat.label
|
|
1899
|
+
] }),
|
|
1900
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[10px] font-bold text-slate-400 opacity-0 group-hover:opacity-100 transition-all duration-300 translate-x-1 group-hover:translate-x-0", children: "Select" })
|
|
1901
|
+
]
|
|
1902
|
+
},
|
|
1903
|
+
cat.id
|
|
1904
|
+
)),
|
|
1905
|
+
tags.some(
|
|
1906
|
+
(t) => t.blockId === block.id && t.startIndex === selectionMenu.startIndex && t.endIndex === selectionMenu.endIndex
|
|
1907
|
+
) && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-1 pt-1 border-t border-white/60", children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1908
|
+
"button",
|
|
1909
|
+
{
|
|
1910
|
+
onClick: (e) => {
|
|
1911
|
+
const tagToRemove = tags.find(
|
|
1912
|
+
(t) => t.blockId === block.id && t.startIndex === selectionMenu.startIndex && t.endIndex === selectionMenu.endIndex
|
|
1913
|
+
);
|
|
1914
|
+
if (tagToRemove) {
|
|
1915
|
+
removeTag(e, tagToRemove.id);
|
|
1916
|
+
clearSelection();
|
|
1917
|
+
}
|
|
1918
|
+
},
|
|
1919
|
+
className: "group w-full text-[12px] font-bold px-3 py-2 rounded-xl transition-all duration-300 text-left flex items-center justify-between hover:bg-rose-50 hover:text-rose-600 hover:shadow-[0_2px_10px_rgb(225,29,72,0.04)] active:scale-[0.98] text-slate-500 border border-transparent hover:border-rose-100",
|
|
1920
|
+
children: [
|
|
1921
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3", children: [
|
|
1922
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-2 h-2 rounded-full shadow-sm bg-rose-400 group-hover:scale-125 transition-transform duration-300" }),
|
|
1923
|
+
"Remove Tag"
|
|
1924
|
+
] }),
|
|
1925
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[10px] font-bold text-rose-400 opacity-0 group-hover:opacity-100 transition-all duration-300 translate-x-1 group-hover:translate-x-0", children: "Remove" })
|
|
1926
|
+
]
|
|
1927
|
+
}
|
|
1928
|
+
) })
|
|
1929
|
+
] })
|
|
1930
|
+
]
|
|
1931
|
+
}
|
|
1932
|
+
)
|
|
1933
|
+
]
|
|
1934
|
+
},
|
|
1935
|
+
block.id
|
|
1936
|
+
))
|
|
1937
|
+
}
|
|
1938
|
+
),
|
|
1939
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative bg-[#fdfdfc] shadow-2xl shadow-zinc-300/60 border border-zinc-100 rounded-sm md:rounded-md flex flex-col w-[210mm] shrink-0 p-8 md:p-12 lg:p-16", children: [
|
|
1940
|
+
/* @__PURE__ */ jsxRuntime.jsxs("h3", { className: "text-xs font-extrabold text-slate-800 uppercase tracking-[0.25em] mb-6 flex items-center gap-3 font-sans", children: [
|
|
1941
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex items-center justify-center w-8 h-8 rounded-full bg-slate-100/80 shadow-inner border border-slate-200/50", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.AlignLeft, { className: "w-3.5 h-3.5 text-slate-500" }) }),
|
|
1942
|
+
"Scene Brief"
|
|
1943
|
+
] }),
|
|
1944
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "relative bg-zinc-50/50 border border-zinc-200/60 rounded-xl p-4 md:p-6 shadow-inner focus-within:bg-white focus-within:border-zinc-300 focus-within:shadow-[0_8px_30px_rgb(0,0,0,0.04)] transition-all duration-300", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
1945
|
+
"textarea",
|
|
1946
|
+
{
|
|
1947
|
+
value: sceneBrief,
|
|
1948
|
+
onChange: (e) => setSceneBrief(e.target.value),
|
|
1949
|
+
placeholder: "Write a brief description or notes for this scene...",
|
|
1950
|
+
className: "w-full min-h-[120px] bg-transparent outline-none resize-y text-zinc-700 placeholder:text-zinc-400 text-sm md:text-base custom-scrollbar font-sans",
|
|
1951
|
+
style: {
|
|
1952
|
+
lineHeight: "1.6"
|
|
1953
|
+
}
|
|
1954
|
+
}
|
|
1955
|
+
) })
|
|
1956
|
+
] })
|
|
1957
|
+
] }),
|
|
1958
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-full lg:w-80 flex-shrink-0 flex flex-col gap-6 sticky top-6", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bg-white/50 backdrop-blur-2xl border border-white shadow-[0_8px_30px_rgb(0,0,0,0.04)] rounded-[2.5rem] p-8", children: [
|
|
1959
|
+
/* @__PURE__ */ jsxRuntime.jsxs("h3", { className: "text-xs font-extrabold text-slate-800 uppercase tracking-[0.25em] mb-8 flex items-center gap-3", children: [
|
|
1960
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex items-center justify-center w-8 h-8 rounded-full bg-white/80 shadow-[0_4px_15px_rgb(0,0,0,0.04)] border border-white", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Tags, { className: "w-3.5 h-3.5 text-slate-500" }) }),
|
|
1961
|
+
"Tags",
|
|
1962
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "ml-auto bg-slate-100/80 text-slate-500 px-2.5 py-1 rounded-lg text-[10px] font-bold tracking-widest border border-slate-200/50 shadow-inner", children: tags.length })
|
|
1963
|
+
] }),
|
|
1964
|
+
tags.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-col gap-8", children: CATEGORIES.map((cat) => {
|
|
1965
|
+
const catTags = Array.from(
|
|
1966
|
+
new Map(
|
|
1967
|
+
tags.filter((t) => t.categoryId === cat.id).map((tag) => [tag.text.toLowerCase(), tag])
|
|
1968
|
+
).values()
|
|
1969
|
+
);
|
|
1970
|
+
if (catTags.length === 0) return null;
|
|
1971
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-4", children: [
|
|
1972
|
+
/* @__PURE__ */ jsxRuntime.jsxs("h4", { className: "text-[10px] font-bold text-slate-400 uppercase tracking-[0.2em] flex items-center gap-2 border-b border-white/60 pb-2", children: [
|
|
1973
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1974
|
+
"div",
|
|
1975
|
+
{
|
|
1976
|
+
className: "w-2 h-2 rounded-full shadow-sm",
|
|
1977
|
+
style: { backgroundColor: cat.hex }
|
|
1978
|
+
}
|
|
1979
|
+
),
|
|
1980
|
+
cat.label,
|
|
1981
|
+
cat.id === "LOCATION" && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1982
|
+
"div",
|
|
1983
|
+
{
|
|
1984
|
+
className: "ml-auto relative",
|
|
1985
|
+
ref: subLocPopoverRef,
|
|
1986
|
+
children: [
|
|
1987
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1988
|
+
"button",
|
|
1989
|
+
{
|
|
1990
|
+
onClick: () => setIsSubLocOpen(!isSubLocOpen),
|
|
1991
|
+
className: "flex items-center justify-center w-5 h-5 rounded-full hover:bg-slate-200 transition-colors",
|
|
1992
|
+
title: "Add Sub Location",
|
|
1993
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Plus, { className: "w-3 h-3 text-slate-500" })
|
|
1994
|
+
}
|
|
1995
|
+
),
|
|
1996
|
+
isSubLocOpen && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "absolute right-0 top-full mt-2 w-56 bg-white backdrop-blur-2xl shadow-[0_10px_40px_rgb(0,0,0,0.06)] border border-white rounded-[1.5rem] p-3 z-50 animate-in fade-in zoom-in-95", children: [
|
|
1997
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-[9px] font-extrabold tracking-[0.2em] text-slate-400 uppercase mb-2 px-1", children: "Add Sub Location" }),
|
|
1998
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex gap-2 items-center", children: [
|
|
1999
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2000
|
+
"input",
|
|
2001
|
+
{
|
|
2002
|
+
type: "text",
|
|
2003
|
+
value: subLocInput,
|
|
2004
|
+
onChange: (e) => setSubLocInput(e.target.value),
|
|
2005
|
+
onKeyDown: (e) => {
|
|
2006
|
+
if (e.key === "Enter") {
|
|
2007
|
+
addSubLocation(subLocInput);
|
|
2008
|
+
setSubLocInput("");
|
|
2009
|
+
setIsSubLocOpen(false);
|
|
2010
|
+
}
|
|
2011
|
+
},
|
|
2012
|
+
className: "w-full text-xs px-3 py-2 bg-white/50 border border-white/60 rounded-xl outline-none focus:bg-white/80 focus:border-white transition-all text-slate-700 font-bold shadow-[0_2px_10px_rgb(0,0,0,0.02)] placeholder:font-medium placeholder:text-slate-400",
|
|
2013
|
+
placeholder: "Sub location...",
|
|
2014
|
+
autoFocus: true
|
|
2015
|
+
}
|
|
2016
|
+
),
|
|
2017
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2018
|
+
"button",
|
|
2019
|
+
{
|
|
2020
|
+
onClick: () => {
|
|
2021
|
+
addSubLocation(subLocInput);
|
|
2022
|
+
setSubLocInput("");
|
|
2023
|
+
setIsSubLocOpen(false);
|
|
2024
|
+
},
|
|
2025
|
+
className: "flex items-center justify-center shrink-0 bg-slate-800 text-white px-3.5 py-2 rounded-xl text-[11px] font-bold hover:bg-slate-700 hover:shadow-md transition-all active:scale-95",
|
|
2026
|
+
children: "Add"
|
|
2027
|
+
}
|
|
2028
|
+
)
|
|
2029
|
+
] })
|
|
2030
|
+
] })
|
|
2031
|
+
]
|
|
2032
|
+
}
|
|
2033
|
+
)
|
|
2034
|
+
] }),
|
|
2035
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap gap-2", children: [
|
|
2036
|
+
catTags.map((tag) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
2037
|
+
"span",
|
|
2038
|
+
{
|
|
2039
|
+
className: "text-[11px] font-bold px-3 py-1.5 rounded-xl bg-white/80 backdrop-blur-md border border-white shadow-[0_4px_15px_rgb(0,0,0,0.03)] hover:shadow-[0_4px_20px_rgb(0,0,0,0.06)] hover:-translate-y-0.5 transition-all duration-300 cursor-default",
|
|
2040
|
+
style: { color: cat.color },
|
|
2041
|
+
children: tag.text
|
|
2042
|
+
},
|
|
2043
|
+
tag.id
|
|
2044
|
+
)),
|
|
2045
|
+
cat.id === "LOCATION" && subLocations.map((subLoc) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2046
|
+
"span",
|
|
2047
|
+
{
|
|
2048
|
+
className: "group flex items-center gap-1.5 text-[11px] font-bold px-3 py-1.5 rounded-xl bg-white backdrop-blur-md border border-slate-200/50 shadow-[0_4px_15px_rgb(0,0,0,0.03)] transition-all duration-300 cursor-default text-slate-500",
|
|
2049
|
+
children: [
|
|
2050
|
+
subLoc,
|
|
2051
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2052
|
+
"button",
|
|
2053
|
+
{
|
|
2054
|
+
onClick: () => removeSubLocation(subLoc),
|
|
2055
|
+
className: "w-3.5 h-3.5 rounded-full hover:bg-slate-300/50 flex items-center justify-center transition-colors opacity-0 group-hover:opacity-100",
|
|
2056
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, { className: "w-2.5 h-2.5" })
|
|
2057
|
+
}
|
|
2058
|
+
)
|
|
2059
|
+
]
|
|
2060
|
+
},
|
|
2061
|
+
`sub-${subLoc}`
|
|
2062
|
+
))
|
|
2063
|
+
] })
|
|
2064
|
+
] }, cat.id);
|
|
2065
|
+
}) }) : /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs font-medium text-slate-400 italic bg-white/40 p-6 rounded-[2rem] border border-white border-dashed text-center shadow-[0_4px_20px_rgb(0,0,0,0.02)]", children: "Highlight text to tag elements." })
|
|
2066
|
+
] }) })
|
|
2067
|
+
] }) });
|
|
2068
|
+
}
|
|
2069
|
+
function useScriptBreakdown({
|
|
2070
|
+
scenes
|
|
2071
|
+
}) {
|
|
2072
|
+
const [parsedScenes, setParsedScenes] = react.useState(scenes || []);
|
|
2073
|
+
const [isLoading, setIsLoading] = react.useState(false);
|
|
2074
|
+
const [error, setError] = react.useState(null);
|
|
2075
|
+
const [hasFetchedFallback, setHasFetchedFallback] = react.useState(false);
|
|
2076
|
+
react.useEffect(() => {
|
|
2077
|
+
if (scenes && scenes.length > 0) {
|
|
2078
|
+
setParsedScenes(scenes);
|
|
2079
|
+
return;
|
|
2080
|
+
}
|
|
2081
|
+
if (hasFetchedFallback) return;
|
|
2082
|
+
const fetchFallback = async () => {
|
|
2083
|
+
setIsLoading(true);
|
|
2084
|
+
setHasFetchedFallback(true);
|
|
2085
|
+
try {
|
|
2086
|
+
const response = await fetch(
|
|
2087
|
+
"https://pub-4c2073ce6f434c4e92ed33f8e1c7f9ea.r2.dev/screenplay%20(1).sbx"
|
|
2088
|
+
);
|
|
2089
|
+
if (!response.ok) {
|
|
2090
|
+
throw new Error(
|
|
2091
|
+
`Failed to fetch fallback script: ${response.status}`
|
|
2092
|
+
);
|
|
2093
|
+
}
|
|
2094
|
+
let text = await response.text();
|
|
2095
|
+
if (text.includes("<div")) {
|
|
2096
|
+
const textarea = document.createElement("textarea");
|
|
2097
|
+
textarea.innerHTML = text;
|
|
2098
|
+
text = textarea.value;
|
|
2099
|
+
}
|
|
2100
|
+
const parser = new DOMParser();
|
|
2101
|
+
const doc = parser.parseFromString(text, "text/html");
|
|
2102
|
+
const divs = Array.from(doc.querySelectorAll("div"));
|
|
2103
|
+
const extractedScenes = [];
|
|
2104
|
+
let currentSceneNumber = "1";
|
|
2105
|
+
let currentContent = "";
|
|
2106
|
+
let hasSeenFirstSceneHeading = false;
|
|
2107
|
+
divs.forEach((div) => {
|
|
2108
|
+
var _a;
|
|
2109
|
+
const isSceneHeading = div.classList.contains("divtype0");
|
|
2110
|
+
const divText = ((_a = div.textContent) == null ? void 0 : _a.trim()) || "";
|
|
2111
|
+
if (!divText) return;
|
|
2112
|
+
if (isSceneHeading) {
|
|
2113
|
+
if (hasSeenFirstSceneHeading) {
|
|
2114
|
+
extractedScenes.push({
|
|
2115
|
+
scene_number: currentSceneNumber,
|
|
2116
|
+
content: currentContent.trim()
|
|
2117
|
+
});
|
|
2118
|
+
currentContent = "";
|
|
2119
|
+
}
|
|
2120
|
+
hasSeenFirstSceneHeading = true;
|
|
2121
|
+
currentSceneNumber = div.getAttribute("data-scene") || String(extractedScenes.length + 1);
|
|
2122
|
+
}
|
|
2123
|
+
currentContent += div.outerHTML + "\n";
|
|
2124
|
+
});
|
|
2125
|
+
if (currentContent.trim()) {
|
|
2126
|
+
extractedScenes.push({
|
|
2127
|
+
scene_number: currentSceneNumber,
|
|
2128
|
+
content: currentContent.trim()
|
|
2129
|
+
});
|
|
2130
|
+
}
|
|
2131
|
+
setParsedScenes(extractedScenes);
|
|
2132
|
+
} catch (err) {
|
|
2133
|
+
console.error("Error fetching fallback script:", err);
|
|
2134
|
+
setError(err instanceof Error ? err : new Error("Unknown error"));
|
|
2135
|
+
} finally {
|
|
2136
|
+
setIsLoading(false);
|
|
2137
|
+
}
|
|
2138
|
+
};
|
|
2139
|
+
fetchFallback();
|
|
2140
|
+
}, [scenes, hasFetchedFallback]);
|
|
2141
|
+
return { scenes: parsedScenes, isLoading, error };
|
|
2142
|
+
}
|
|
2143
|
+
var use_script_breakdown_default = useScriptBreakdown;
|
|
2144
|
+
|
|
2145
|
+
// app/hook/use-script-breakdown-scene.ts
|
|
2146
|
+
function useScriptBreakdownScene(sceneNumber) {
|
|
2147
|
+
const { scenes, isLoading, error } = use_script_breakdown_default({ scenes: [] });
|
|
2148
|
+
const scene = react.useMemo(() => {
|
|
2149
|
+
return scenes.find((s) => s.scene_number === sceneNumber);
|
|
2150
|
+
}, [scenes, sceneNumber]);
|
|
2151
|
+
const blocks = react.useMemo(() => {
|
|
2152
|
+
if (!scene || !scene.content) return [];
|
|
2153
|
+
const parser = new DOMParser();
|
|
2154
|
+
const doc = parser.parseFromString(scene.content, "text/html");
|
|
2155
|
+
const divs = Array.from(doc.querySelectorAll("div"));
|
|
2156
|
+
const parsedBlocks = [];
|
|
2157
|
+
const typeMap = {
|
|
2158
|
+
divtype0: "SCENE_HEADING",
|
|
2159
|
+
divtype2: "ACTION",
|
|
2160
|
+
divtype3: "CHARACTER",
|
|
2161
|
+
divtype4: "PARENTHETICAL",
|
|
2162
|
+
divtype5: "DIALOGUE",
|
|
2163
|
+
divtype6: "TRANSITION"
|
|
2164
|
+
};
|
|
2165
|
+
divs.forEach((div) => {
|
|
2166
|
+
var _a;
|
|
2167
|
+
const divText = ((_a = div.textContent) == null ? void 0 : _a.trim()) || "";
|
|
2168
|
+
if (!divText) return;
|
|
2169
|
+
let type = "ACTION";
|
|
2170
|
+
for (const className of Array.from(div.classList)) {
|
|
2171
|
+
if (typeMap[className]) {
|
|
2172
|
+
type = typeMap[className];
|
|
2173
|
+
break;
|
|
2174
|
+
}
|
|
2175
|
+
}
|
|
2176
|
+
parsedBlocks.push({ id: uuid(), type, text: divText });
|
|
2177
|
+
});
|
|
2178
|
+
return parsedBlocks;
|
|
2179
|
+
}, [scene]);
|
|
2180
|
+
const characters = react.useMemo(() => {
|
|
2181
|
+
const chars = blocks.filter((b) => b.type === "CHARACTER").map((b) => {
|
|
2182
|
+
const text = b.text.trim().toUpperCase();
|
|
2183
|
+
const parenIndex = text.indexOf("(");
|
|
2184
|
+
return parenIndex > -1 ? text.substring(0, parenIndex).trim() : text;
|
|
2185
|
+
}).filter(Boolean);
|
|
2186
|
+
return [...new Set(chars)];
|
|
2187
|
+
}, [blocks]);
|
|
2188
|
+
const [tags, setTags] = react.useState([]);
|
|
2189
|
+
const [selectionMenu, setSelectionMenu] = react.useState(null);
|
|
2190
|
+
const autoTaggedSceneRef = react.useRef(null);
|
|
2191
|
+
const [menuPlacement, setMenuPlacement] = react.useState("top");
|
|
2192
|
+
const menuRef = react.useRef(null);
|
|
2193
|
+
const [subLocations, setSubLocations] = react.useState([]);
|
|
2194
|
+
const addSubLocation = react.useCallback(
|
|
2195
|
+
(subLocation) => {
|
|
2196
|
+
const trimmed = subLocation.trim();
|
|
2197
|
+
if (trimmed && !subLocations.includes(trimmed)) {
|
|
2198
|
+
setSubLocations((prev) => [...prev, trimmed]);
|
|
2199
|
+
}
|
|
2200
|
+
},
|
|
2201
|
+
[subLocations]
|
|
2202
|
+
);
|
|
2203
|
+
const removeSubLocation = react.useCallback((subLocation) => {
|
|
2204
|
+
setSubLocations((prev) => prev.filter((loc) => loc !== subLocation));
|
|
2205
|
+
}, []);
|
|
2206
|
+
const [sceneBrief, setSceneBrief] = react.useState("");
|
|
2207
|
+
react.useEffect(() => {
|
|
2208
|
+
setTags([]);
|
|
2209
|
+
setSubLocations([]);
|
|
2210
|
+
setSceneBrief("");
|
|
2211
|
+
autoTaggedSceneRef.current = null;
|
|
2212
|
+
}, [sceneNumber]);
|
|
2213
|
+
react.useEffect(() => {
|
|
2214
|
+
if (blocks.length > 0 && characters.length > 0 && autoTaggedSceneRef.current !== sceneNumber) {
|
|
2215
|
+
const autoTags = [];
|
|
2216
|
+
const escapeRegExp = (string) => string.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
2217
|
+
const sortedChars = [...characters].sort((a, b) => b.length - a.length);
|
|
2218
|
+
blocks.forEach((block) => {
|
|
2219
|
+
sortedChars.forEach((char) => {
|
|
2220
|
+
const escapedChar = escapeRegExp(char);
|
|
2221
|
+
const regex = new RegExp(`\\b${escapedChar}\\b`, "gi");
|
|
2222
|
+
let match;
|
|
2223
|
+
while ((match = regex.exec(block.text)) !== null) {
|
|
2224
|
+
const isOverlapping = autoTags.some(
|
|
2225
|
+
(t) => t.blockId === block.id && match.index + char.length > t.startIndex && match.index < t.endIndex
|
|
2226
|
+
);
|
|
2227
|
+
if (!isOverlapping) {
|
|
2228
|
+
autoTags.push({
|
|
2229
|
+
id: uuid(),
|
|
2230
|
+
blockId: block.id,
|
|
2231
|
+
categoryId: "CAST",
|
|
2232
|
+
text: block.text.substring(
|
|
2233
|
+
match.index,
|
|
2234
|
+
match.index + char.length
|
|
2235
|
+
),
|
|
2236
|
+
startIndex: match.index,
|
|
2237
|
+
endIndex: match.index + char.length
|
|
2238
|
+
});
|
|
2239
|
+
}
|
|
2240
|
+
}
|
|
2241
|
+
});
|
|
2242
|
+
});
|
|
2243
|
+
setTags(autoTags);
|
|
2244
|
+
autoTaggedSceneRef.current = sceneNumber;
|
|
2245
|
+
}
|
|
2246
|
+
}, [blocks, characters, sceneNumber]);
|
|
2247
|
+
const clearSelection = react.useCallback(() => {
|
|
2248
|
+
var _a;
|
|
2249
|
+
setSelectionMenu(null);
|
|
2250
|
+
(_a = window.getSelection()) == null ? void 0 : _a.removeAllRanges();
|
|
2251
|
+
}, []);
|
|
2252
|
+
react.useEffect(() => {
|
|
2253
|
+
if (!selectionMenu) {
|
|
2254
|
+
setMenuPlacement("top");
|
|
2255
|
+
}
|
|
2256
|
+
}, [selectionMenu]);
|
|
2257
|
+
react.useEffect(() => {
|
|
2258
|
+
if (selectionMenu && menuRef.current) {
|
|
2259
|
+
const rect = menuRef.current.getBoundingClientRect();
|
|
2260
|
+
if (menuPlacement === "top" && rect.top < 100) {
|
|
2261
|
+
setMenuPlacement("bottom");
|
|
2262
|
+
} else if (menuPlacement === "bottom" && rect.bottom > window.innerHeight - 40 && rect.top > 300) {
|
|
2263
|
+
setMenuPlacement("top");
|
|
2264
|
+
}
|
|
2265
|
+
}
|
|
2266
|
+
}, [selectionMenu, menuPlacement]);
|
|
2267
|
+
react.useEffect(() => {
|
|
2268
|
+
const handleClickOutside = (e) => {
|
|
2269
|
+
if (selectionMenu && !e.target.closest(".tag-menu")) {
|
|
2270
|
+
clearSelection();
|
|
2271
|
+
}
|
|
2272
|
+
};
|
|
2273
|
+
document.addEventListener("mousedown", handleClickOutside);
|
|
2274
|
+
return () => document.removeEventListener("mousedown", handleClickOutside);
|
|
2275
|
+
}, [selectionMenu, clearSelection]);
|
|
2276
|
+
const getAbsoluteOffset = (container, targetNode, targetOffset) => {
|
|
2277
|
+
let absoluteOffset = 0;
|
|
2278
|
+
let found = false;
|
|
2279
|
+
const traverse = (node) => {
|
|
2280
|
+
var _a;
|
|
2281
|
+
if (found) return;
|
|
2282
|
+
if (node === targetNode) {
|
|
2283
|
+
absoluteOffset += targetOffset;
|
|
2284
|
+
found = true;
|
|
2285
|
+
return;
|
|
2286
|
+
}
|
|
2287
|
+
if (node.nodeType === Node.TEXT_NODE) {
|
|
2288
|
+
absoluteOffset += ((_a = node.nodeValue) == null ? void 0 : _a.length) || 0;
|
|
2289
|
+
} else {
|
|
2290
|
+
for (let i = 0; i < node.childNodes.length; i++) {
|
|
2291
|
+
traverse(node.childNodes[i]);
|
|
2292
|
+
if (found) return;
|
|
2293
|
+
}
|
|
2294
|
+
}
|
|
2295
|
+
};
|
|
2296
|
+
traverse(container);
|
|
2297
|
+
return found ? absoluteOffset : null;
|
|
2298
|
+
};
|
|
2299
|
+
const handleMouseUp = () => {
|
|
2300
|
+
const selection = window.getSelection();
|
|
2301
|
+
if (!selection || selection.isCollapsed || !selection.toString().trim())
|
|
2302
|
+
return;
|
|
2303
|
+
const range = selection.getRangeAt(0);
|
|
2304
|
+
let container = range.commonAncestorContainer;
|
|
2305
|
+
if (container.nodeType === Node.TEXT_NODE)
|
|
2306
|
+
container = container.parentElement;
|
|
2307
|
+
const blockElem = container.closest("[data-block-id]");
|
|
2308
|
+
if (!blockElem) return;
|
|
2309
|
+
const blockId = blockElem.getAttribute("data-block-id");
|
|
2310
|
+
const startOffset = getAbsoluteOffset(
|
|
2311
|
+
blockElem,
|
|
2312
|
+
range.startContainer,
|
|
2313
|
+
range.startOffset
|
|
2314
|
+
);
|
|
2315
|
+
const endOffset = getAbsoluteOffset(
|
|
2316
|
+
blockElem,
|
|
2317
|
+
range.endContainer,
|
|
2318
|
+
range.endOffset
|
|
2319
|
+
);
|
|
2320
|
+
if (startOffset !== null && endOffset !== null) {
|
|
2321
|
+
const rect = range.getBoundingClientRect();
|
|
2322
|
+
const blockRect = blockElem.getBoundingClientRect();
|
|
2323
|
+
setSelectionMenu({
|
|
2324
|
+
blockId,
|
|
2325
|
+
startIndex: Math.min(startOffset, endOffset),
|
|
2326
|
+
endIndex: Math.max(startOffset, endOffset),
|
|
2327
|
+
text: selection.toString().trim(),
|
|
2328
|
+
top: rect.top - blockRect.top,
|
|
2329
|
+
left: rect.left - blockRect.left + rect.width / 2
|
|
2330
|
+
});
|
|
2331
|
+
}
|
|
2332
|
+
};
|
|
2333
|
+
const addTag = (categoryId) => {
|
|
2334
|
+
if (!selectionMenu) return;
|
|
2335
|
+
const newTag = {
|
|
2336
|
+
id: uuid(),
|
|
2337
|
+
blockId: selectionMenu.blockId,
|
|
2338
|
+
categoryId,
|
|
2339
|
+
text: selectionMenu.text,
|
|
2340
|
+
startIndex: selectionMenu.startIndex,
|
|
2341
|
+
endIndex: selectionMenu.endIndex
|
|
2342
|
+
};
|
|
2343
|
+
setTags((prev) => {
|
|
2344
|
+
const filtered = prev.filter(
|
|
2345
|
+
(t) => t.blockId !== newTag.blockId || !(newTag.endIndex > t.startIndex && newTag.startIndex < t.endIndex)
|
|
2346
|
+
);
|
|
2347
|
+
return [...filtered, newTag];
|
|
2348
|
+
});
|
|
2349
|
+
clearSelection();
|
|
2350
|
+
};
|
|
2351
|
+
const removeTag = (e, id) => {
|
|
2352
|
+
e.stopPropagation();
|
|
2353
|
+
e.preventDefault();
|
|
2354
|
+
setTags((prev) => prev.filter((t) => t.id !== id));
|
|
2355
|
+
clearSelection();
|
|
2356
|
+
};
|
|
2357
|
+
return {
|
|
2358
|
+
scene,
|
|
2359
|
+
blocks,
|
|
2360
|
+
characters,
|
|
2361
|
+
isLoading,
|
|
2362
|
+
error,
|
|
2363
|
+
tags,
|
|
2364
|
+
selectionMenu,
|
|
2365
|
+
handleMouseUp,
|
|
2366
|
+
addTag,
|
|
2367
|
+
removeTag,
|
|
2368
|
+
clearSelection,
|
|
2369
|
+
menuPlacement,
|
|
2370
|
+
menuRef,
|
|
2371
|
+
subLocations,
|
|
2372
|
+
addSubLocation,
|
|
2373
|
+
removeSubLocation,
|
|
2374
|
+
sceneBrief,
|
|
2375
|
+
setSceneBrief
|
|
2376
|
+
};
|
|
2377
|
+
}
|
|
2378
|
+
|
|
2379
|
+
exports.CATEGORIES = CATEGORIES;
|
|
1659
2380
|
exports.ScreenplayEditorView = ScreenplayEditorView;
|
|
2381
|
+
exports.ScriptBreakdownSceneView = ScriptBreakdownSceneView;
|
|
1660
2382
|
exports.blockStyles = blockStyles;
|
|
1661
2383
|
exports.blockTypes = blockTypes;
|
|
2384
|
+
exports.convertBlocksToSbx = convertBlocksToSbx;
|
|
1662
2385
|
exports.handleSaveAsPdf = handleSaveAsPdf;
|
|
1663
2386
|
exports.handleSaveAsSbx = handleSaveAsSbx;
|
|
2387
|
+
exports.handleSyncWithCloud = handleSyncWithCloud;
|
|
1664
2388
|
exports.icons = icons;
|
|
1665
2389
|
exports.timeOfDayOptions = timeOfDayOptions;
|
|
1666
2390
|
exports.useScreenplayEditor = useScreenplayEditor;
|
|
2391
|
+
exports.useScriptBreakdownScene = useScriptBreakdownScene;
|
|
1667
2392
|
exports.uuid = uuid;
|
|
1668
2393
|
//# sourceMappingURL=index.cjs.map
|
|
1669
2394
|
//# sourceMappingURL=index.cjs.map
|