@vishu1301/script-writing 1.1.4 → 1.1.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/dist/index.cjs +226 -128
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +8 -8
- package/dist/index.d.ts +8 -8
- package/dist/index.js +226 -128
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -1390,7 +1390,7 @@ function useScreenplayEditor(options) {
|
|
|
1390
1390
|
[blocks, handleBlockTextChange]
|
|
1391
1391
|
);
|
|
1392
1392
|
const handleScriptImport = react.useCallback(
|
|
1393
|
-
(title, content, preParsedBlocks) => {
|
|
1393
|
+
(title, content, preParsedBlocks, isInitialLoad) => {
|
|
1394
1394
|
let parsedBlocks = [];
|
|
1395
1395
|
if (preParsedBlocks && preParsedBlocks.length > 0) {
|
|
1396
1396
|
parsedBlocks = preParsedBlocks.map((b) => ({
|
|
@@ -1446,8 +1446,10 @@ function useScreenplayEditor(options) {
|
|
|
1446
1446
|
}).join("");
|
|
1447
1447
|
if (sbxData !== lastSavedContent.current) {
|
|
1448
1448
|
lastSavedContent.current = sbxData;
|
|
1449
|
-
|
|
1450
|
-
|
|
1449
|
+
if (!isInitialLoad) {
|
|
1450
|
+
const blob = new Blob([sbxData], { type: "text/plain" });
|
|
1451
|
+
onSaveRef.current(blob);
|
|
1452
|
+
}
|
|
1451
1453
|
}
|
|
1452
1454
|
}
|
|
1453
1455
|
setTimeout(() => {
|
|
@@ -1495,7 +1497,7 @@ function useScreenplayEditor(options) {
|
|
|
1495
1497
|
}, 200);
|
|
1496
1498
|
}, []);
|
|
1497
1499
|
const loadFromUrl = react.useCallback(
|
|
1498
|
-
async (url, fetchOptions = {}) => {
|
|
1500
|
+
async (url, fetchOptions = {}, isInitialLoad) => {
|
|
1499
1501
|
var _a;
|
|
1500
1502
|
try {
|
|
1501
1503
|
const response = await fetch(url, fetchOptions);
|
|
@@ -1567,7 +1569,7 @@ function useScreenplayEditor(options) {
|
|
|
1567
1569
|
}
|
|
1568
1570
|
}
|
|
1569
1571
|
const filename = ((_a = url.split("/").pop()) == null ? void 0 : _a.replace(/\.sbx$/i, "")) || "Imported from URL";
|
|
1570
|
-
handleScriptImport(filename, scriptContent, preParsedBlocks);
|
|
1572
|
+
handleScriptImport(filename, scriptContent, preParsedBlocks, isInitialLoad);
|
|
1571
1573
|
} catch (error) {
|
|
1572
1574
|
console.error(
|
|
1573
1575
|
"[useScreenplayEditor] Error loading script from URL:",
|
|
@@ -1581,7 +1583,7 @@ function useScreenplayEditor(options) {
|
|
|
1581
1583
|
react.useEffect(() => {
|
|
1582
1584
|
if ((options == null ? void 0 : options.initialUrl) && options.initialUrl !== loadedUrlRef.current) {
|
|
1583
1585
|
loadedUrlRef.current = options.initialUrl;
|
|
1584
|
-
loadFromUrl(options.initialUrl, options.fetchOptions);
|
|
1586
|
+
loadFromUrl(options.initialUrl, options.fetchOptions, true);
|
|
1585
1587
|
}
|
|
1586
1588
|
}, [options == null ? void 0 : options.initialUrl, options == null ? void 0 : options.fetchOptions, loadFromUrl]);
|
|
1587
1589
|
return {
|
|
@@ -1753,6 +1755,166 @@ var CATEGORIES = [
|
|
|
1753
1755
|
{ id: "LOCATION", label: "Location", color: "#FFB300", hex: "#FFE082" },
|
|
1754
1756
|
{ id: "OTHER", label: "Other", color: "#9E9E9E", hex: "#E0E0E0" }
|
|
1755
1757
|
];
|
|
1758
|
+
var PopcornIcon = ({ isSummarizing }) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1759
|
+
"svg",
|
|
1760
|
+
{
|
|
1761
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
1762
|
+
width: "24",
|
|
1763
|
+
height: "24",
|
|
1764
|
+
viewBox: "0 0 24 24",
|
|
1765
|
+
fill: "none",
|
|
1766
|
+
strokeLinecap: "round",
|
|
1767
|
+
strokeLinejoin: "round",
|
|
1768
|
+
className: `w-6 h-6 transition-all duration-500 ${isSummarizing ? "animate-cook" : "group-hover:scale-110 group-hover:-rotate-12"}`,
|
|
1769
|
+
children: [
|
|
1770
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1771
|
+
"path",
|
|
1772
|
+
{
|
|
1773
|
+
d: "M18 8a2 2 0 0 0 0-4 2 2 0 0 0-4 0 2 2 0 0 0-4 0 2 2 0 0 0-4 0 2 2 0 0 0 0 4",
|
|
1774
|
+
className: "stroke-yellow-400",
|
|
1775
|
+
strokeWidth: "2"
|
|
1776
|
+
}
|
|
1777
|
+
),
|
|
1778
|
+
/* @__PURE__ */ jsxRuntime.jsxs("g", { className: "stroke-red-500", strokeWidth: "2", children: [
|
|
1779
|
+
/* @__PURE__ */ jsxRuntime.jsx("path", { d: "M20 8c.5 0 .9.4.8 1l-2.6 12c-.1.5-.7 1-1.2 1H7c-.6 0-1.1-.4-1.2-1L3.2 9c-.1-.6.3-1 .8-1Z" }),
|
|
1780
|
+
/* @__PURE__ */ jsxRuntime.jsx("path", { d: "M10 22 9 8", className: "stroke-red-500", strokeWidth: "1" }),
|
|
1781
|
+
/* @__PURE__ */ jsxRuntime.jsx("path", { d: "m14 22 1-14", className: "stroke-red-500", strokeWidth: "1" })
|
|
1782
|
+
] })
|
|
1783
|
+
]
|
|
1784
|
+
}
|
|
1785
|
+
);
|
|
1786
|
+
var SummarizeButton = ({
|
|
1787
|
+
onSummarize,
|
|
1788
|
+
isSummarizing
|
|
1789
|
+
}) => {
|
|
1790
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1791
|
+
"button",
|
|
1792
|
+
{
|
|
1793
|
+
onClick: onSummarize,
|
|
1794
|
+
disabled: isSummarizing,
|
|
1795
|
+
className: `group relative w-full py-4 px-8 rounded-[3rem] transition-all duration-500 ease-[cubic-bezier(0.22,1,0.36,1)] border ${isSummarizing ? "bg-zinc-100 border-zinc-300 opacity-100 cursor-wait shadow-inner" : "bg-gradient-to-b from-white via-zinc-50 to-zinc-100 border-white/70 shadow-[0_10px_30px_-10px_rgba(0,0,0,0.12),inset_0_1px_0_rgba(255,255,255,0.8)] hover:shadow-[0_20px_50px_-15px_rgba(139,92,246,0.3)] hover:-translate-y-[2px] active:scale-[0.98]"}`,
|
|
1796
|
+
children: [
|
|
1797
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "absolute inset-0 opacity-0 group-hover:opacity-100 transition duration-700", children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "absolute inset-0 bg-[conic-gradient(from_0deg_at_50%_50%,#c084fc,transparent_60%,#fb7185,transparent_90%)] blur-3xl opacity-20 animate-[spin_10s_linear_infinite]" }) }),
|
|
1798
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1799
|
+
"span",
|
|
1800
|
+
{
|
|
1801
|
+
className: `absolute inset-0 transition-opacity duration-700 bg-[radial-gradient(circle_at_50%_50%,rgba(139,92,246,0.1),transparent_70%)] ${isSummarizing ? "opacity-100" : "opacity-0"}`
|
|
1802
|
+
}
|
|
1803
|
+
),
|
|
1804
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative flex items-center justify-center gap-4", children: [
|
|
1805
|
+
/* @__PURE__ */ jsxRuntime.jsx("style", { children: `
|
|
1806
|
+
@keyframes kernel-pop {
|
|
1807
|
+
0% { transform: translate(0, 0) scale(0) rotate(0deg); opacity: 0; }
|
|
1808
|
+
10% { opacity: 1; transform: translate(var(--tx1), var(--ty1)) scale(1.3) rotate(45deg); }
|
|
1809
|
+
40% { transform: translate(var(--tx2), var(--ty2)) scale(1) rotate(180deg); opacity: 1; }
|
|
1810
|
+
100% { transform: translate(var(--tx3), var(--ty3)) scale(0.4) rotate(360deg); opacity: 0; }
|
|
1811
|
+
}
|
|
1812
|
+
@keyframes icon-cook {
|
|
1813
|
+
0%, 100% { transform: scale(1.1) translateY(0); }
|
|
1814
|
+
50% { transform: scale(0.9, 1.1) translateY(-3px) rotate(3deg); }
|
|
1815
|
+
}
|
|
1816
|
+
.animate-kernel {
|
|
1817
|
+
animation: kernel-pop var(--dur) cubic-bezier(0.34, 1.56, 0.64, 1) infinite;
|
|
1818
|
+
animation-delay: var(--delay);
|
|
1819
|
+
filter: drop-shadow(0 4px 6px rgba(0,0,0,0.15)); /* Added shadow for visibility */
|
|
1820
|
+
}
|
|
1821
|
+
.animate-cook { animation: icon-cook 0.3s ease-in-out infinite; }
|
|
1822
|
+
` }),
|
|
1823
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative flex items-center justify-center", children: [
|
|
1824
|
+
/* @__PURE__ */ jsxRuntime.jsx(PopcornIcon, { isSummarizing }),
|
|
1825
|
+
isSummarizing && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "absolute inset-0 pointer-events-none", children: [
|
|
1826
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1827
|
+
"svg",
|
|
1828
|
+
{
|
|
1829
|
+
className: "animate-kernel absolute w-4 h-4",
|
|
1830
|
+
style: {
|
|
1831
|
+
"--dur": "1.2s",
|
|
1832
|
+
"--delay": "0s",
|
|
1833
|
+
"--tx1": "-18px",
|
|
1834
|
+
"--ty1": "-22px",
|
|
1835
|
+
"--tx2": "-28px",
|
|
1836
|
+
"--ty2": "-28px",
|
|
1837
|
+
"--tx3": "-38px",
|
|
1838
|
+
"--ty3": "12px"
|
|
1839
|
+
},
|
|
1840
|
+
viewBox: "0 0 24 24",
|
|
1841
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
1842
|
+
"path",
|
|
1843
|
+
{
|
|
1844
|
+
d: "M12 2a4 4 0 0 0-4 4 4 4 0 0 0-4 4 4 4 0 0 0 4 4 4 4 0 0 0 4 4 4 4 0 0 0 4-4 4 4 0 0 0 4-4 4 4 0 0 0-4-4 4 4 0 0 0-4-4z",
|
|
1845
|
+
fill: "#FBBF24",
|
|
1846
|
+
stroke: "#F59E0B",
|
|
1847
|
+
strokeWidth: "0.5"
|
|
1848
|
+
}
|
|
1849
|
+
)
|
|
1850
|
+
}
|
|
1851
|
+
),
|
|
1852
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1853
|
+
"svg",
|
|
1854
|
+
{
|
|
1855
|
+
className: "animate-kernel absolute w-3.5 h-3.5",
|
|
1856
|
+
style: {
|
|
1857
|
+
"--dur": "1.5s",
|
|
1858
|
+
"--delay": "0.3s",
|
|
1859
|
+
"--tx1": "18px",
|
|
1860
|
+
"--ty1": "-28px",
|
|
1861
|
+
"--tx2": "28px",
|
|
1862
|
+
"--ty2": "-38px",
|
|
1863
|
+
"--tx3": "38px",
|
|
1864
|
+
"--ty3": "18px"
|
|
1865
|
+
},
|
|
1866
|
+
viewBox: "0 0 24 24",
|
|
1867
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
1868
|
+
"path",
|
|
1869
|
+
{
|
|
1870
|
+
d: "M12 3c-2 0-3 1-4 2-1-1-3-1-4 1-1 2 0 4 1 5-1 1-1 3 1 4 2 1 4 0 6-1 2 1 4 2 6 1 2-1 2-3 1-4 1-1 2-3 1-5-1-2-3-2-4-1-1-1-2-2-4-2z",
|
|
1871
|
+
fill: "#FDE68A",
|
|
1872
|
+
stroke: "#FBBF24",
|
|
1873
|
+
strokeWidth: "0.5"
|
|
1874
|
+
}
|
|
1875
|
+
)
|
|
1876
|
+
}
|
|
1877
|
+
),
|
|
1878
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1879
|
+
"svg",
|
|
1880
|
+
{
|
|
1881
|
+
className: "animate-kernel absolute w-4 h-4",
|
|
1882
|
+
style: {
|
|
1883
|
+
"--dur": "1.8s",
|
|
1884
|
+
"--delay": "0.7s",
|
|
1885
|
+
"--tx1": "-2px",
|
|
1886
|
+
"--ty1": "-28px",
|
|
1887
|
+
"--tx2": "5px",
|
|
1888
|
+
"--ty2": "-48px",
|
|
1889
|
+
"--tx3": "10px",
|
|
1890
|
+
"--ty3": "18px"
|
|
1891
|
+
},
|
|
1892
|
+
viewBox: "0 0 24 24",
|
|
1893
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
1894
|
+
"path",
|
|
1895
|
+
{
|
|
1896
|
+
d: "M12 2a4 4 0 0 0-4 4 4 4 0 0 0-4 4 4 4 0 0 0 4 4 4 4 0 0 0 4 4 4 4 0 0 0 4-4 4 4 0 0 0 4-4 4 4 0 0 0-4-4 4 4 0 0 0-4-4z",
|
|
1897
|
+
fill: "#FEF3C7"
|
|
1898
|
+
}
|
|
1899
|
+
)
|
|
1900
|
+
}
|
|
1901
|
+
)
|
|
1902
|
+
] })
|
|
1903
|
+
] }),
|
|
1904
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1905
|
+
"span",
|
|
1906
|
+
{
|
|
1907
|
+
className: `text-[12px] font-bold tracking-[0.25em] uppercase transition-all duration-300 ${isSummarizing ? "text-violet-700" : "text-zinc-500 group-hover:text-zinc-900"}`,
|
|
1908
|
+
children: isSummarizing ? "Summarizing..." : "Summarize Scene"
|
|
1909
|
+
}
|
|
1910
|
+
)
|
|
1911
|
+
] }),
|
|
1912
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "absolute bottom-0 left-0 right-0 h-[1px] bg-gradient-to-r from-transparent via-white/40 to-transparent" })
|
|
1913
|
+
]
|
|
1914
|
+
}
|
|
1915
|
+
);
|
|
1916
|
+
};
|
|
1917
|
+
var summarize_button_default = SummarizeButton;
|
|
1756
1918
|
function ScriptBreakdownSceneView({
|
|
1757
1919
|
blocks,
|
|
1758
1920
|
characters,
|
|
@@ -1998,7 +2160,7 @@ function ScriptBreakdownSceneView({
|
|
|
1998
2160
|
value: sceneBrief,
|
|
1999
2161
|
onChange: (e) => setSceneBrief(e.target.value),
|
|
2000
2162
|
placeholder: "Write a brief description or notes for this scene...",
|
|
2001
|
-
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",
|
|
2163
|
+
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 select-none",
|
|
2002
2164
|
style: {
|
|
2003
2165
|
lineHeight: "1.6"
|
|
2004
2166
|
}
|
|
@@ -2006,27 +2168,15 @@ function ScriptBreakdownSceneView({
|
|
|
2006
2168
|
) })
|
|
2007
2169
|
] })
|
|
2008
2170
|
] }),
|
|
2009
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "w-full
|
|
2010
|
-
/* @__PURE__ */ jsxRuntime.
|
|
2011
|
-
|
|
2171
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "w-full flex flex-col gap-6 sticky top-6", children: [
|
|
2172
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2173
|
+
summarize_button_default,
|
|
2012
2174
|
{
|
|
2013
|
-
|
|
2014
|
-
|
|
2015
|
-
className: `group relative w-full py-4 px-6 rounded-[3rem] overflow-hidden bg-gradient-to-b from-white via-zinc-50 to-zinc-100 border border-white/70 shadow-[0_10px_30px_-10px_rgba(0,0,0,0.15),inset_0_1px_0_rgba(255,255,255,0.9)] transition-all duration-500 ease-[cubic-bezier(0.22,1,0.36,1)] ${isSummarizing ? "opacity-70 cursor-wait" : "hover:shadow-[0_20px_50px_-15px_rgba(139,92,246,0.35)] hover:-translate-y-[2px] active:scale-[0.97]"}`,
|
|
2016
|
-
children: [
|
|
2017
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "absolute inset-0 opacity-0 group-hover:opacity-100 transition duration-700", children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "absolute inset-0 bg-[conic-gradient(from_180deg_at_50%_50%,#8b5cf6,transparent_40%,#d946ef,transparent_70%)] blur-2xl opacity-30 animate-[spin_6s_linear_infinite]" }) }),
|
|
2018
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "absolute inset-0 opacity-0 group-hover:opacity-100 transition duration-500 bg-[radial-gradient(circle_at_50%_40%,rgba(139,92,246,0.18),transparent_70%)]" }),
|
|
2019
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "absolute inset-[1px] rounded-[inherit] bg-gradient-to-b from-white/90 to-transparent pointer-events-none" }),
|
|
2020
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "absolute inset-0 overflow-hidden", children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "absolute -left-[100%] top-0 h-full w-[60%] bg-gradient-to-r from-transparent via-white/60 to-transparent skew-x-[-20deg] group-hover:left-[120%] transition-all duration-[1200ms]" }) }),
|
|
2021
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "absolute inset-[2px] rounded-[inherit] opacity-0 group-hover:opacity-100 bg-gradient-to-r from-violet-200/40 via-white/40 to-fuchsia-200/40 blur-md transition duration-500" }),
|
|
2022
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative flex items-center justify-center gap-3", children: [
|
|
2023
|
-
isSummarizing ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Loader2, { className: "w-4 h-4 text-violet-500 animate-spin" }) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Sparkles, { className: "w-4 h-4 text-violet-500 transition-all duration-500 group-hover:-rotate-12 group-hover:scale-125" }),
|
|
2024
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[11px] font-semibold tracking-[0.32em] uppercase text-zinc-800 group-hover:text-zinc-950 transition-all duration-300", children: isSummarizing ? "Summarizing..." : "Summarize Scene" })
|
|
2025
|
-
] })
|
|
2026
|
-
]
|
|
2175
|
+
isSummarizing,
|
|
2176
|
+
onSummarize
|
|
2027
2177
|
}
|
|
2028
2178
|
),
|
|
2029
|
-
/* @__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: [
|
|
2179
|
+
/* @__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 w-full", children: [
|
|
2030
2180
|
/* @__PURE__ */ jsxRuntime.jsxs("h3", { className: "text-xs font-extrabold text-slate-800 uppercase tracking-[0.25em] mb-8 flex items-center gap-3", children: [
|
|
2031
2181
|
/* @__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" }) }),
|
|
2032
2182
|
"Tags",
|
|
@@ -2138,96 +2288,39 @@ function ScriptBreakdownSceneView({
|
|
|
2138
2288
|
] })
|
|
2139
2289
|
] }) });
|
|
2140
2290
|
}
|
|
2141
|
-
function
|
|
2142
|
-
scenes
|
|
2143
|
-
}) {
|
|
2144
|
-
const [parsedScenes, setParsedScenes] = react.useState(scenes || []);
|
|
2145
|
-
const [isLoading, setIsLoading] = react.useState(false);
|
|
2146
|
-
const [error, setError] = react.useState(null);
|
|
2147
|
-
const [hasFetchedFallback, setHasFetchedFallback] = react.useState(false);
|
|
2148
|
-
react.useEffect(() => {
|
|
2149
|
-
if (scenes && scenes.length > 0) {
|
|
2150
|
-
setParsedScenes(scenes);
|
|
2151
|
-
return;
|
|
2152
|
-
}
|
|
2153
|
-
if (hasFetchedFallback) return;
|
|
2154
|
-
const fetchFallback = async () => {
|
|
2155
|
-
setIsLoading(true);
|
|
2156
|
-
setHasFetchedFallback(true);
|
|
2157
|
-
try {
|
|
2158
|
-
const response = await fetch(
|
|
2159
|
-
"https://pub-4c2073ce6f434c4e92ed33f8e1c7f9ea.r2.dev/screenplay%20(1).sbx"
|
|
2160
|
-
);
|
|
2161
|
-
if (!response.ok) {
|
|
2162
|
-
throw new Error(
|
|
2163
|
-
`Failed to fetch fallback script: ${response.status}`
|
|
2164
|
-
);
|
|
2165
|
-
}
|
|
2166
|
-
let text = await response.text();
|
|
2167
|
-
if (text.includes("<div")) {
|
|
2168
|
-
const textarea = document.createElement("textarea");
|
|
2169
|
-
textarea.innerHTML = text;
|
|
2170
|
-
text = textarea.value;
|
|
2171
|
-
}
|
|
2172
|
-
const parser = new DOMParser();
|
|
2173
|
-
const doc = parser.parseFromString(text, "text/html");
|
|
2174
|
-
const divs = Array.from(doc.querySelectorAll("div"));
|
|
2175
|
-
const extractedScenes = [];
|
|
2176
|
-
let currentSceneNumber = "1";
|
|
2177
|
-
let currentContent = "";
|
|
2178
|
-
let hasSeenFirstSceneHeading = false;
|
|
2179
|
-
divs.forEach((div) => {
|
|
2180
|
-
var _a;
|
|
2181
|
-
const isSceneHeading = div.classList.contains("divtype0");
|
|
2182
|
-
const divText = ((_a = div.textContent) == null ? void 0 : _a.trim()) || "";
|
|
2183
|
-
if (!divText) return;
|
|
2184
|
-
if (isSceneHeading) {
|
|
2185
|
-
if (hasSeenFirstSceneHeading) {
|
|
2186
|
-
extractedScenes.push({
|
|
2187
|
-
scene_number: currentSceneNumber,
|
|
2188
|
-
content: currentContent.trim()
|
|
2189
|
-
});
|
|
2190
|
-
currentContent = "";
|
|
2191
|
-
}
|
|
2192
|
-
hasSeenFirstSceneHeading = true;
|
|
2193
|
-
currentSceneNumber = div.getAttribute("data-scene") || String(extractedScenes.length + 1);
|
|
2194
|
-
}
|
|
2195
|
-
currentContent += div.outerHTML + "\n";
|
|
2196
|
-
});
|
|
2197
|
-
if (currentContent.trim()) {
|
|
2198
|
-
extractedScenes.push({
|
|
2199
|
-
scene_number: currentSceneNumber,
|
|
2200
|
-
content: currentContent.trim()
|
|
2201
|
-
});
|
|
2202
|
-
}
|
|
2203
|
-
setParsedScenes(extractedScenes);
|
|
2204
|
-
} catch (err) {
|
|
2205
|
-
console.error("Error fetching fallback script:", err);
|
|
2206
|
-
setError(err instanceof Error ? err : new Error("Unknown error"));
|
|
2207
|
-
} finally {
|
|
2208
|
-
setIsLoading(false);
|
|
2209
|
-
}
|
|
2210
|
-
};
|
|
2211
|
-
fetchFallback();
|
|
2212
|
-
}, [scenes, hasFetchedFallback]);
|
|
2213
|
-
return { scenes: parsedScenes, isLoading, error };
|
|
2214
|
-
}
|
|
2215
|
-
var use_script_breakdown_default = useScriptBreakdown;
|
|
2216
|
-
|
|
2217
|
-
// app/hook/use-script-breakdown-scene.ts
|
|
2218
|
-
function useScriptBreakdownScene(sceneNumber) {
|
|
2219
|
-
const { scenes, isLoading, error } = use_script_breakdown_default({ scenes: [] });
|
|
2291
|
+
function useScriptBreakdownScene(scene_url, fetchOptions, onAISummarize, onTagAdded, onTagRemoved) {
|
|
2220
2292
|
const [tags, setTags] = react.useState([]);
|
|
2221
2293
|
const [selectionMenu, setSelectionMenu] = react.useState(null);
|
|
2222
2294
|
const autoTaggedSceneRef = react.useRef(null);
|
|
2295
|
+
const [scene, setScene] = react.useState(null);
|
|
2223
2296
|
const [menuPlacement, setMenuPlacement] = react.useState("top");
|
|
2224
2297
|
const [subLocations, setSubLocations] = react.useState([]);
|
|
2225
2298
|
const [sceneBrief, setSceneBrief] = react.useState("");
|
|
2226
2299
|
const [isSummarizing, setIsSummarizing] = react.useState(false);
|
|
2300
|
+
const [isLoading, setIsLoading] = react.useState(true);
|
|
2301
|
+
const [error, setError] = react.useState(false);
|
|
2227
2302
|
const menuRef = react.useRef(null);
|
|
2228
|
-
|
|
2229
|
-
|
|
2230
|
-
|
|
2303
|
+
react.useEffect(() => {
|
|
2304
|
+
setIsLoading(true);
|
|
2305
|
+
const fetchScene = async () => {
|
|
2306
|
+
try {
|
|
2307
|
+
const response = await fetch(scene_url, fetchOptions);
|
|
2308
|
+
if (response.ok) {
|
|
2309
|
+
const text = await response.text();
|
|
2310
|
+
setScene({ content: text });
|
|
2311
|
+
} else {
|
|
2312
|
+
console.error("Failed to fetch scene:", response);
|
|
2313
|
+
setError(true);
|
|
2314
|
+
}
|
|
2315
|
+
setIsLoading(false);
|
|
2316
|
+
} catch (error2) {
|
|
2317
|
+
setError(true);
|
|
2318
|
+
setIsLoading(false);
|
|
2319
|
+
console.error("Error fetching scene:", error2);
|
|
2320
|
+
}
|
|
2321
|
+
};
|
|
2322
|
+
fetchScene();
|
|
2323
|
+
}, []);
|
|
2231
2324
|
const blocks = react.useMemo(() => {
|
|
2232
2325
|
if (!scene || !scene.content) return [];
|
|
2233
2326
|
const parser = new DOMParser();
|
|
@@ -2269,24 +2362,15 @@ function useScriptBreakdownScene(sceneNumber) {
|
|
|
2269
2362
|
}, [blocks]);
|
|
2270
2363
|
const handleAISummarize = async () => {
|
|
2271
2364
|
setIsSummarizing(true);
|
|
2272
|
-
const res = await
|
|
2273
|
-
"https://nonfibrous-extrafloral-verlene.ngrok-free.dev/extract",
|
|
2274
|
-
{
|
|
2275
|
-
method: "POST",
|
|
2276
|
-
headers: {
|
|
2277
|
-
"Content-Type": "application/json",
|
|
2278
|
-
"ngrok-skip-browser-warning": "true"
|
|
2279
|
-
},
|
|
2280
|
-
body: JSON.stringify({
|
|
2281
|
-
script: (scene == null ? void 0 : scene.content) || ""
|
|
2282
|
-
})
|
|
2283
|
-
}
|
|
2284
|
-
);
|
|
2365
|
+
const res = await (onAISummarize == null ? void 0 : onAISummarize(scene.content));
|
|
2285
2366
|
if (res.ok) {
|
|
2286
2367
|
const data = await res.json();
|
|
2287
2368
|
setIsSummarizing(false);
|
|
2288
|
-
const
|
|
2289
|
-
|
|
2369
|
+
const normalData = JSON.parse(data.data);
|
|
2370
|
+
const parsedData = Array.isArray(normalData) ? normalData[0] : [];
|
|
2371
|
+
const summary = Array.isArray(normalData) ? normalData[1] : "";
|
|
2372
|
+
const parsedSummaryData = summary[0];
|
|
2373
|
+
setSceneBrief(parsedSummaryData.summarise);
|
|
2290
2374
|
const newTags = [];
|
|
2291
2375
|
parsedData.forEach((aiTag) => {
|
|
2292
2376
|
if (!aiTag.block_id || !aiTag.category_id || typeof aiTag.start_index !== "number" || typeof aiTag.end_index !== "number") {
|
|
@@ -2335,9 +2419,9 @@ function useScriptBreakdownScene(sceneNumber) {
|
|
|
2335
2419
|
setSubLocations([]);
|
|
2336
2420
|
setSceneBrief("");
|
|
2337
2421
|
autoTaggedSceneRef.current = null;
|
|
2338
|
-
}, [
|
|
2422
|
+
}, [scene_url]);
|
|
2339
2423
|
react.useEffect(() => {
|
|
2340
|
-
if (blocks.length > 0 && characters.length > 0 && autoTaggedSceneRef.current !==
|
|
2424
|
+
if (blocks.length > 0 && characters.length > 0 && autoTaggedSceneRef.current !== scene) {
|
|
2341
2425
|
const autoTags = [];
|
|
2342
2426
|
const escapeRegExp = (string) => string.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
2343
2427
|
const sortedChars = [...characters].sort((a, b) => b.length - a.length);
|
|
@@ -2367,9 +2451,9 @@ function useScriptBreakdownScene(sceneNumber) {
|
|
|
2367
2451
|
});
|
|
2368
2452
|
});
|
|
2369
2453
|
setTags(autoTags);
|
|
2370
|
-
autoTaggedSceneRef.current =
|
|
2454
|
+
autoTaggedSceneRef.current = scene;
|
|
2371
2455
|
}
|
|
2372
|
-
}, [blocks, characters,
|
|
2456
|
+
}, [blocks, characters, scene]);
|
|
2373
2457
|
const clearSelection = react.useCallback(() => {
|
|
2374
2458
|
var _a;
|
|
2375
2459
|
setSelectionMenu(null);
|
|
@@ -2456,7 +2540,7 @@ function useScriptBreakdownScene(sceneNumber) {
|
|
|
2456
2540
|
});
|
|
2457
2541
|
}
|
|
2458
2542
|
};
|
|
2459
|
-
const addTag = (categoryId) => {
|
|
2543
|
+
const addTag = async (categoryId) => {
|
|
2460
2544
|
if (!selectionMenu) return;
|
|
2461
2545
|
const newTag = {
|
|
2462
2546
|
id: uuid(),
|
|
@@ -2473,12 +2557,26 @@ function useScriptBreakdownScene(sceneNumber) {
|
|
|
2473
2557
|
return [...filtered, newTag];
|
|
2474
2558
|
});
|
|
2475
2559
|
clearSelection();
|
|
2560
|
+
try {
|
|
2561
|
+
await (onTagAdded == null ? void 0 : onTagAdded(newTag));
|
|
2562
|
+
} catch (error2) {
|
|
2563
|
+
console.error("Failed to add tag:", error2);
|
|
2564
|
+
setTags((prev) => prev.filter((t) => t.id !== newTag.id));
|
|
2565
|
+
}
|
|
2476
2566
|
};
|
|
2477
|
-
const removeTag = (e, id) => {
|
|
2567
|
+
const removeTag = async (e, id) => {
|
|
2478
2568
|
e.stopPropagation();
|
|
2479
2569
|
e.preventDefault();
|
|
2570
|
+
const tagToRemove = tags.find((t) => t.id === id);
|
|
2571
|
+
if (!tagToRemove) return;
|
|
2480
2572
|
setTags((prev) => prev.filter((t) => t.id !== id));
|
|
2481
2573
|
clearSelection();
|
|
2574
|
+
try {
|
|
2575
|
+
await (onTagRemoved == null ? void 0 : onTagRemoved(id));
|
|
2576
|
+
} catch (error2) {
|
|
2577
|
+
console.error("Failed to remove tag:", error2);
|
|
2578
|
+
setTags((prev) => [...prev, tagToRemove]);
|
|
2579
|
+
}
|
|
2482
2580
|
};
|
|
2483
2581
|
return {
|
|
2484
2582
|
scene,
|