@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.d.cts
CHANGED
|
@@ -43,11 +43,11 @@ declare function useScreenplayEditor(options?: UseScreenplayEditorOptions): {
|
|
|
43
43
|
handleBlockTypeChange: (newType: BlockType) => void;
|
|
44
44
|
handleSelectCharacterExtension: (extension: string) => void;
|
|
45
45
|
handleKeyDown: (e: KeyboardEvent<HTMLDivElement>, id: string, text: string) => void;
|
|
46
|
-
handleScriptImport: (title: string, content: string, preParsedBlocks?: Partial<Block>[]) => void;
|
|
46
|
+
handleScriptImport: (title: string, content: string, preParsedBlocks?: Partial<Block>[], isInitialLoad?: boolean) => void;
|
|
47
47
|
handleSceneNumberChange: (id: string, newNumber: string) => void;
|
|
48
48
|
handleFocus: (id: string) => void;
|
|
49
49
|
handleBlur: (id: string) => void;
|
|
50
|
-
loadFromUrl: (url: string, fetchOptions?: RequestInit) => Promise<void>;
|
|
50
|
+
loadFromUrl: (url: string, fetchOptions?: RequestInit, isInitialLoad?: boolean) => Promise<void>;
|
|
51
51
|
};
|
|
52
52
|
|
|
53
53
|
type ScreenplayEditorViewProps = ReturnType<typeof useScreenplayEditor> & {
|
|
@@ -120,12 +120,12 @@ declare function ScriptBreakdownSceneView({ blocks, characters, isLoading, scene
|
|
|
120
120
|
isSummarizing?: boolean;
|
|
121
121
|
}): react_jsx_runtime.JSX.Element;
|
|
122
122
|
|
|
123
|
-
declare function useScriptBreakdownScene(
|
|
124
|
-
scene:
|
|
123
|
+
declare function useScriptBreakdownScene(scene_url: string, fetchOptions?: RequestInit, onAISummarize?: (scene: any) => void, onTagAdded?: (tag: Tag) => void, onTagRemoved?: (tagId: string) => void): {
|
|
124
|
+
scene: any;
|
|
125
125
|
blocks: Block[];
|
|
126
126
|
characters: string[];
|
|
127
127
|
isLoading: boolean;
|
|
128
|
-
error:
|
|
128
|
+
error: boolean;
|
|
129
129
|
tags: Tag[];
|
|
130
130
|
selectionMenu: {
|
|
131
131
|
blockId: string;
|
|
@@ -136,10 +136,10 @@ declare function useScriptBreakdownScene(sceneNumber: string): {
|
|
|
136
136
|
left: number;
|
|
137
137
|
} | null;
|
|
138
138
|
handleMouseUp: () => void;
|
|
139
|
-
addTag: (categoryId: ElementCategory) => void
|
|
140
|
-
removeTag: (e: React.MouseEvent, id: string) => void
|
|
139
|
+
addTag: (categoryId: ElementCategory) => Promise<void>;
|
|
140
|
+
removeTag: (e: React.MouseEvent, id: string) => Promise<void>;
|
|
141
141
|
clearSelection: () => void;
|
|
142
|
-
menuPlacement: "
|
|
142
|
+
menuPlacement: "bottom" | "top";
|
|
143
143
|
menuRef: React$1.RefObject<HTMLDivElement | null>;
|
|
144
144
|
subLocations: string[];
|
|
145
145
|
addSubLocation: (subLocation: string) => void;
|
package/dist/index.d.ts
CHANGED
|
@@ -43,11 +43,11 @@ declare function useScreenplayEditor(options?: UseScreenplayEditorOptions): {
|
|
|
43
43
|
handleBlockTypeChange: (newType: BlockType) => void;
|
|
44
44
|
handleSelectCharacterExtension: (extension: string) => void;
|
|
45
45
|
handleKeyDown: (e: KeyboardEvent<HTMLDivElement>, id: string, text: string) => void;
|
|
46
|
-
handleScriptImport: (title: string, content: string, preParsedBlocks?: Partial<Block>[]) => void;
|
|
46
|
+
handleScriptImport: (title: string, content: string, preParsedBlocks?: Partial<Block>[], isInitialLoad?: boolean) => void;
|
|
47
47
|
handleSceneNumberChange: (id: string, newNumber: string) => void;
|
|
48
48
|
handleFocus: (id: string) => void;
|
|
49
49
|
handleBlur: (id: string) => void;
|
|
50
|
-
loadFromUrl: (url: string, fetchOptions?: RequestInit) => Promise<void>;
|
|
50
|
+
loadFromUrl: (url: string, fetchOptions?: RequestInit, isInitialLoad?: boolean) => Promise<void>;
|
|
51
51
|
};
|
|
52
52
|
|
|
53
53
|
type ScreenplayEditorViewProps = ReturnType<typeof useScreenplayEditor> & {
|
|
@@ -120,12 +120,12 @@ declare function ScriptBreakdownSceneView({ blocks, characters, isLoading, scene
|
|
|
120
120
|
isSummarizing?: boolean;
|
|
121
121
|
}): react_jsx_runtime.JSX.Element;
|
|
122
122
|
|
|
123
|
-
declare function useScriptBreakdownScene(
|
|
124
|
-
scene:
|
|
123
|
+
declare function useScriptBreakdownScene(scene_url: string, fetchOptions?: RequestInit, onAISummarize?: (scene: any) => void, onTagAdded?: (tag: Tag) => void, onTagRemoved?: (tagId: string) => void): {
|
|
124
|
+
scene: any;
|
|
125
125
|
blocks: Block[];
|
|
126
126
|
characters: string[];
|
|
127
127
|
isLoading: boolean;
|
|
128
|
-
error:
|
|
128
|
+
error: boolean;
|
|
129
129
|
tags: Tag[];
|
|
130
130
|
selectionMenu: {
|
|
131
131
|
blockId: string;
|
|
@@ -136,10 +136,10 @@ declare function useScriptBreakdownScene(sceneNumber: string): {
|
|
|
136
136
|
left: number;
|
|
137
137
|
} | null;
|
|
138
138
|
handleMouseUp: () => void;
|
|
139
|
-
addTag: (categoryId: ElementCategory) => void
|
|
140
|
-
removeTag: (e: React.MouseEvent, id: string) => void
|
|
139
|
+
addTag: (categoryId: ElementCategory) => Promise<void>;
|
|
140
|
+
removeTag: (e: React.MouseEvent, id: string) => Promise<void>;
|
|
141
141
|
clearSelection: () => void;
|
|
142
|
-
menuPlacement: "
|
|
142
|
+
menuPlacement: "bottom" | "top";
|
|
143
143
|
menuRef: React$1.RefObject<HTMLDivElement | null>;
|
|
144
144
|
subLocations: string[];
|
|
145
145
|
addSubLocation: (subLocation: string) => void;
|
package/dist/index.js
CHANGED
|
@@ -1365,7 +1365,7 @@ function useScreenplayEditor(options) {
|
|
|
1365
1365
|
[blocks, handleBlockTextChange]
|
|
1366
1366
|
);
|
|
1367
1367
|
const handleScriptImport = useCallback(
|
|
1368
|
-
(title, content, preParsedBlocks) => {
|
|
1368
|
+
(title, content, preParsedBlocks, isInitialLoad) => {
|
|
1369
1369
|
let parsedBlocks = [];
|
|
1370
1370
|
if (preParsedBlocks && preParsedBlocks.length > 0) {
|
|
1371
1371
|
parsedBlocks = preParsedBlocks.map((b) => ({
|
|
@@ -1421,8 +1421,10 @@ function useScreenplayEditor(options) {
|
|
|
1421
1421
|
}).join("");
|
|
1422
1422
|
if (sbxData !== lastSavedContent.current) {
|
|
1423
1423
|
lastSavedContent.current = sbxData;
|
|
1424
|
-
|
|
1425
|
-
|
|
1424
|
+
if (!isInitialLoad) {
|
|
1425
|
+
const blob = new Blob([sbxData], { type: "text/plain" });
|
|
1426
|
+
onSaveRef.current(blob);
|
|
1427
|
+
}
|
|
1426
1428
|
}
|
|
1427
1429
|
}
|
|
1428
1430
|
setTimeout(() => {
|
|
@@ -1470,7 +1472,7 @@ function useScreenplayEditor(options) {
|
|
|
1470
1472
|
}, 200);
|
|
1471
1473
|
}, []);
|
|
1472
1474
|
const loadFromUrl = useCallback(
|
|
1473
|
-
async (url, fetchOptions = {}) => {
|
|
1475
|
+
async (url, fetchOptions = {}, isInitialLoad) => {
|
|
1474
1476
|
var _a;
|
|
1475
1477
|
try {
|
|
1476
1478
|
const response = await fetch(url, fetchOptions);
|
|
@@ -1542,7 +1544,7 @@ function useScreenplayEditor(options) {
|
|
|
1542
1544
|
}
|
|
1543
1545
|
}
|
|
1544
1546
|
const filename = ((_a = url.split("/").pop()) == null ? void 0 : _a.replace(/\.sbx$/i, "")) || "Imported from URL";
|
|
1545
|
-
handleScriptImport(filename, scriptContent, preParsedBlocks);
|
|
1547
|
+
handleScriptImport(filename, scriptContent, preParsedBlocks, isInitialLoad);
|
|
1546
1548
|
} catch (error) {
|
|
1547
1549
|
console.error(
|
|
1548
1550
|
"[useScreenplayEditor] Error loading script from URL:",
|
|
@@ -1556,7 +1558,7 @@ function useScreenplayEditor(options) {
|
|
|
1556
1558
|
useEffect(() => {
|
|
1557
1559
|
if ((options == null ? void 0 : options.initialUrl) && options.initialUrl !== loadedUrlRef.current) {
|
|
1558
1560
|
loadedUrlRef.current = options.initialUrl;
|
|
1559
|
-
loadFromUrl(options.initialUrl, options.fetchOptions);
|
|
1561
|
+
loadFromUrl(options.initialUrl, options.fetchOptions, true);
|
|
1560
1562
|
}
|
|
1561
1563
|
}, [options == null ? void 0 : options.initialUrl, options == null ? void 0 : options.fetchOptions, loadFromUrl]);
|
|
1562
1564
|
return {
|
|
@@ -1728,6 +1730,166 @@ var CATEGORIES = [
|
|
|
1728
1730
|
{ id: "LOCATION", label: "Location", color: "#FFB300", hex: "#FFE082" },
|
|
1729
1731
|
{ id: "OTHER", label: "Other", color: "#9E9E9E", hex: "#E0E0E0" }
|
|
1730
1732
|
];
|
|
1733
|
+
var PopcornIcon = ({ isSummarizing }) => /* @__PURE__ */ jsxs(
|
|
1734
|
+
"svg",
|
|
1735
|
+
{
|
|
1736
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
1737
|
+
width: "24",
|
|
1738
|
+
height: "24",
|
|
1739
|
+
viewBox: "0 0 24 24",
|
|
1740
|
+
fill: "none",
|
|
1741
|
+
strokeLinecap: "round",
|
|
1742
|
+
strokeLinejoin: "round",
|
|
1743
|
+
className: `w-6 h-6 transition-all duration-500 ${isSummarizing ? "animate-cook" : "group-hover:scale-110 group-hover:-rotate-12"}`,
|
|
1744
|
+
children: [
|
|
1745
|
+
/* @__PURE__ */ jsx(
|
|
1746
|
+
"path",
|
|
1747
|
+
{
|
|
1748
|
+
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",
|
|
1749
|
+
className: "stroke-yellow-400",
|
|
1750
|
+
strokeWidth: "2"
|
|
1751
|
+
}
|
|
1752
|
+
),
|
|
1753
|
+
/* @__PURE__ */ jsxs("g", { className: "stroke-red-500", strokeWidth: "2", children: [
|
|
1754
|
+
/* @__PURE__ */ 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" }),
|
|
1755
|
+
/* @__PURE__ */ jsx("path", { d: "M10 22 9 8", className: "stroke-red-500", strokeWidth: "1" }),
|
|
1756
|
+
/* @__PURE__ */ jsx("path", { d: "m14 22 1-14", className: "stroke-red-500", strokeWidth: "1" })
|
|
1757
|
+
] })
|
|
1758
|
+
]
|
|
1759
|
+
}
|
|
1760
|
+
);
|
|
1761
|
+
var SummarizeButton = ({
|
|
1762
|
+
onSummarize,
|
|
1763
|
+
isSummarizing
|
|
1764
|
+
}) => {
|
|
1765
|
+
return /* @__PURE__ */ jsxs(
|
|
1766
|
+
"button",
|
|
1767
|
+
{
|
|
1768
|
+
onClick: onSummarize,
|
|
1769
|
+
disabled: isSummarizing,
|
|
1770
|
+
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]"}`,
|
|
1771
|
+
children: [
|
|
1772
|
+
/* @__PURE__ */ jsx("span", { className: "absolute inset-0 opacity-0 group-hover:opacity-100 transition duration-700", children: /* @__PURE__ */ 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]" }) }),
|
|
1773
|
+
/* @__PURE__ */ jsx(
|
|
1774
|
+
"span",
|
|
1775
|
+
{
|
|
1776
|
+
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"}`
|
|
1777
|
+
}
|
|
1778
|
+
),
|
|
1779
|
+
/* @__PURE__ */ jsxs("div", { className: "relative flex items-center justify-center gap-4", children: [
|
|
1780
|
+
/* @__PURE__ */ jsx("style", { children: `
|
|
1781
|
+
@keyframes kernel-pop {
|
|
1782
|
+
0% { transform: translate(0, 0) scale(0) rotate(0deg); opacity: 0; }
|
|
1783
|
+
10% { opacity: 1; transform: translate(var(--tx1), var(--ty1)) scale(1.3) rotate(45deg); }
|
|
1784
|
+
40% { transform: translate(var(--tx2), var(--ty2)) scale(1) rotate(180deg); opacity: 1; }
|
|
1785
|
+
100% { transform: translate(var(--tx3), var(--ty3)) scale(0.4) rotate(360deg); opacity: 0; }
|
|
1786
|
+
}
|
|
1787
|
+
@keyframes icon-cook {
|
|
1788
|
+
0%, 100% { transform: scale(1.1) translateY(0); }
|
|
1789
|
+
50% { transform: scale(0.9, 1.1) translateY(-3px) rotate(3deg); }
|
|
1790
|
+
}
|
|
1791
|
+
.animate-kernel {
|
|
1792
|
+
animation: kernel-pop var(--dur) cubic-bezier(0.34, 1.56, 0.64, 1) infinite;
|
|
1793
|
+
animation-delay: var(--delay);
|
|
1794
|
+
filter: drop-shadow(0 4px 6px rgba(0,0,0,0.15)); /* Added shadow for visibility */
|
|
1795
|
+
}
|
|
1796
|
+
.animate-cook { animation: icon-cook 0.3s ease-in-out infinite; }
|
|
1797
|
+
` }),
|
|
1798
|
+
/* @__PURE__ */ jsxs("div", { className: "relative flex items-center justify-center", children: [
|
|
1799
|
+
/* @__PURE__ */ jsx(PopcornIcon, { isSummarizing }),
|
|
1800
|
+
isSummarizing && /* @__PURE__ */ jsxs("div", { className: "absolute inset-0 pointer-events-none", children: [
|
|
1801
|
+
/* @__PURE__ */ jsx(
|
|
1802
|
+
"svg",
|
|
1803
|
+
{
|
|
1804
|
+
className: "animate-kernel absolute w-4 h-4",
|
|
1805
|
+
style: {
|
|
1806
|
+
"--dur": "1.2s",
|
|
1807
|
+
"--delay": "0s",
|
|
1808
|
+
"--tx1": "-18px",
|
|
1809
|
+
"--ty1": "-22px",
|
|
1810
|
+
"--tx2": "-28px",
|
|
1811
|
+
"--ty2": "-28px",
|
|
1812
|
+
"--tx3": "-38px",
|
|
1813
|
+
"--ty3": "12px"
|
|
1814
|
+
},
|
|
1815
|
+
viewBox: "0 0 24 24",
|
|
1816
|
+
children: /* @__PURE__ */ jsx(
|
|
1817
|
+
"path",
|
|
1818
|
+
{
|
|
1819
|
+
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",
|
|
1820
|
+
fill: "#FBBF24",
|
|
1821
|
+
stroke: "#F59E0B",
|
|
1822
|
+
strokeWidth: "0.5"
|
|
1823
|
+
}
|
|
1824
|
+
)
|
|
1825
|
+
}
|
|
1826
|
+
),
|
|
1827
|
+
/* @__PURE__ */ jsx(
|
|
1828
|
+
"svg",
|
|
1829
|
+
{
|
|
1830
|
+
className: "animate-kernel absolute w-3.5 h-3.5",
|
|
1831
|
+
style: {
|
|
1832
|
+
"--dur": "1.5s",
|
|
1833
|
+
"--delay": "0.3s",
|
|
1834
|
+
"--tx1": "18px",
|
|
1835
|
+
"--ty1": "-28px",
|
|
1836
|
+
"--tx2": "28px",
|
|
1837
|
+
"--ty2": "-38px",
|
|
1838
|
+
"--tx3": "38px",
|
|
1839
|
+
"--ty3": "18px"
|
|
1840
|
+
},
|
|
1841
|
+
viewBox: "0 0 24 24",
|
|
1842
|
+
children: /* @__PURE__ */ jsx(
|
|
1843
|
+
"path",
|
|
1844
|
+
{
|
|
1845
|
+
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",
|
|
1846
|
+
fill: "#FDE68A",
|
|
1847
|
+
stroke: "#FBBF24",
|
|
1848
|
+
strokeWidth: "0.5"
|
|
1849
|
+
}
|
|
1850
|
+
)
|
|
1851
|
+
}
|
|
1852
|
+
),
|
|
1853
|
+
/* @__PURE__ */ jsx(
|
|
1854
|
+
"svg",
|
|
1855
|
+
{
|
|
1856
|
+
className: "animate-kernel absolute w-4 h-4",
|
|
1857
|
+
style: {
|
|
1858
|
+
"--dur": "1.8s",
|
|
1859
|
+
"--delay": "0.7s",
|
|
1860
|
+
"--tx1": "-2px",
|
|
1861
|
+
"--ty1": "-28px",
|
|
1862
|
+
"--tx2": "5px",
|
|
1863
|
+
"--ty2": "-48px",
|
|
1864
|
+
"--tx3": "10px",
|
|
1865
|
+
"--ty3": "18px"
|
|
1866
|
+
},
|
|
1867
|
+
viewBox: "0 0 24 24",
|
|
1868
|
+
children: /* @__PURE__ */ jsx(
|
|
1869
|
+
"path",
|
|
1870
|
+
{
|
|
1871
|
+
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",
|
|
1872
|
+
fill: "#FEF3C7"
|
|
1873
|
+
}
|
|
1874
|
+
)
|
|
1875
|
+
}
|
|
1876
|
+
)
|
|
1877
|
+
] })
|
|
1878
|
+
] }),
|
|
1879
|
+
/* @__PURE__ */ jsx(
|
|
1880
|
+
"span",
|
|
1881
|
+
{
|
|
1882
|
+
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"}`,
|
|
1883
|
+
children: isSummarizing ? "Summarizing..." : "Summarize Scene"
|
|
1884
|
+
}
|
|
1885
|
+
)
|
|
1886
|
+
] }),
|
|
1887
|
+
/* @__PURE__ */ jsx("span", { className: "absolute bottom-0 left-0 right-0 h-[1px] bg-gradient-to-r from-transparent via-white/40 to-transparent" })
|
|
1888
|
+
]
|
|
1889
|
+
}
|
|
1890
|
+
);
|
|
1891
|
+
};
|
|
1892
|
+
var summarize_button_default = SummarizeButton;
|
|
1731
1893
|
function ScriptBreakdownSceneView({
|
|
1732
1894
|
blocks,
|
|
1733
1895
|
characters,
|
|
@@ -1973,7 +2135,7 @@ function ScriptBreakdownSceneView({
|
|
|
1973
2135
|
value: sceneBrief,
|
|
1974
2136
|
onChange: (e) => setSceneBrief(e.target.value),
|
|
1975
2137
|
placeholder: "Write a brief description or notes for this scene...",
|
|
1976
|
-
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",
|
|
2138
|
+
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",
|
|
1977
2139
|
style: {
|
|
1978
2140
|
lineHeight: "1.6"
|
|
1979
2141
|
}
|
|
@@ -1981,27 +2143,15 @@ function ScriptBreakdownSceneView({
|
|
|
1981
2143
|
) })
|
|
1982
2144
|
] })
|
|
1983
2145
|
] }),
|
|
1984
|
-
/* @__PURE__ */ jsxs("div", { className: "w-full
|
|
1985
|
-
/* @__PURE__ */
|
|
1986
|
-
|
|
2146
|
+
/* @__PURE__ */ jsxs("div", { className: "w-full flex flex-col gap-6 sticky top-6", children: [
|
|
2147
|
+
/* @__PURE__ */ jsx(
|
|
2148
|
+
summarize_button_default,
|
|
1987
2149
|
{
|
|
1988
|
-
|
|
1989
|
-
|
|
1990
|
-
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]"}`,
|
|
1991
|
-
children: [
|
|
1992
|
-
/* @__PURE__ */ jsx("span", { className: "absolute inset-0 opacity-0 group-hover:opacity-100 transition duration-700", children: /* @__PURE__ */ 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]" }) }),
|
|
1993
|
-
/* @__PURE__ */ 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%)]" }),
|
|
1994
|
-
/* @__PURE__ */ jsx("span", { className: "absolute inset-[1px] rounded-[inherit] bg-gradient-to-b from-white/90 to-transparent pointer-events-none" }),
|
|
1995
|
-
/* @__PURE__ */ jsx("span", { className: "absolute inset-0 overflow-hidden", children: /* @__PURE__ */ 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]" }) }),
|
|
1996
|
-
/* @__PURE__ */ 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" }),
|
|
1997
|
-
/* @__PURE__ */ jsxs("div", { className: "relative flex items-center justify-center gap-3", children: [
|
|
1998
|
-
isSummarizing ? /* @__PURE__ */ jsx(Loader2, { className: "w-4 h-4 text-violet-500 animate-spin" }) : /* @__PURE__ */ jsx(Sparkles, { className: "w-4 h-4 text-violet-500 transition-all duration-500 group-hover:-rotate-12 group-hover:scale-125" }),
|
|
1999
|
-
/* @__PURE__ */ 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" })
|
|
2000
|
-
] })
|
|
2001
|
-
]
|
|
2150
|
+
isSummarizing,
|
|
2151
|
+
onSummarize
|
|
2002
2152
|
}
|
|
2003
2153
|
),
|
|
2004
|
-
/* @__PURE__ */ 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: [
|
|
2154
|
+
/* @__PURE__ */ 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: [
|
|
2005
2155
|
/* @__PURE__ */ jsxs("h3", { className: "text-xs font-extrabold text-slate-800 uppercase tracking-[0.25em] mb-8 flex items-center gap-3", children: [
|
|
2006
2156
|
/* @__PURE__ */ 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__ */ jsx(Tags, { className: "w-3.5 h-3.5 text-slate-500" }) }),
|
|
2007
2157
|
"Tags",
|
|
@@ -2113,96 +2263,39 @@ function ScriptBreakdownSceneView({
|
|
|
2113
2263
|
] })
|
|
2114
2264
|
] }) });
|
|
2115
2265
|
}
|
|
2116
|
-
function
|
|
2117
|
-
scenes
|
|
2118
|
-
}) {
|
|
2119
|
-
const [parsedScenes, setParsedScenes] = useState(scenes || []);
|
|
2120
|
-
const [isLoading, setIsLoading] = useState(false);
|
|
2121
|
-
const [error, setError] = useState(null);
|
|
2122
|
-
const [hasFetchedFallback, setHasFetchedFallback] = useState(false);
|
|
2123
|
-
useEffect(() => {
|
|
2124
|
-
if (scenes && scenes.length > 0) {
|
|
2125
|
-
setParsedScenes(scenes);
|
|
2126
|
-
return;
|
|
2127
|
-
}
|
|
2128
|
-
if (hasFetchedFallback) return;
|
|
2129
|
-
const fetchFallback = async () => {
|
|
2130
|
-
setIsLoading(true);
|
|
2131
|
-
setHasFetchedFallback(true);
|
|
2132
|
-
try {
|
|
2133
|
-
const response = await fetch(
|
|
2134
|
-
"https://pub-4c2073ce6f434c4e92ed33f8e1c7f9ea.r2.dev/screenplay%20(1).sbx"
|
|
2135
|
-
);
|
|
2136
|
-
if (!response.ok) {
|
|
2137
|
-
throw new Error(
|
|
2138
|
-
`Failed to fetch fallback script: ${response.status}`
|
|
2139
|
-
);
|
|
2140
|
-
}
|
|
2141
|
-
let text = await response.text();
|
|
2142
|
-
if (text.includes("<div")) {
|
|
2143
|
-
const textarea = document.createElement("textarea");
|
|
2144
|
-
textarea.innerHTML = text;
|
|
2145
|
-
text = textarea.value;
|
|
2146
|
-
}
|
|
2147
|
-
const parser = new DOMParser();
|
|
2148
|
-
const doc = parser.parseFromString(text, "text/html");
|
|
2149
|
-
const divs = Array.from(doc.querySelectorAll("div"));
|
|
2150
|
-
const extractedScenes = [];
|
|
2151
|
-
let currentSceneNumber = "1";
|
|
2152
|
-
let currentContent = "";
|
|
2153
|
-
let hasSeenFirstSceneHeading = false;
|
|
2154
|
-
divs.forEach((div) => {
|
|
2155
|
-
var _a;
|
|
2156
|
-
const isSceneHeading = div.classList.contains("divtype0");
|
|
2157
|
-
const divText = ((_a = div.textContent) == null ? void 0 : _a.trim()) || "";
|
|
2158
|
-
if (!divText) return;
|
|
2159
|
-
if (isSceneHeading) {
|
|
2160
|
-
if (hasSeenFirstSceneHeading) {
|
|
2161
|
-
extractedScenes.push({
|
|
2162
|
-
scene_number: currentSceneNumber,
|
|
2163
|
-
content: currentContent.trim()
|
|
2164
|
-
});
|
|
2165
|
-
currentContent = "";
|
|
2166
|
-
}
|
|
2167
|
-
hasSeenFirstSceneHeading = true;
|
|
2168
|
-
currentSceneNumber = div.getAttribute("data-scene") || String(extractedScenes.length + 1);
|
|
2169
|
-
}
|
|
2170
|
-
currentContent += div.outerHTML + "\n";
|
|
2171
|
-
});
|
|
2172
|
-
if (currentContent.trim()) {
|
|
2173
|
-
extractedScenes.push({
|
|
2174
|
-
scene_number: currentSceneNumber,
|
|
2175
|
-
content: currentContent.trim()
|
|
2176
|
-
});
|
|
2177
|
-
}
|
|
2178
|
-
setParsedScenes(extractedScenes);
|
|
2179
|
-
} catch (err) {
|
|
2180
|
-
console.error("Error fetching fallback script:", err);
|
|
2181
|
-
setError(err instanceof Error ? err : new Error("Unknown error"));
|
|
2182
|
-
} finally {
|
|
2183
|
-
setIsLoading(false);
|
|
2184
|
-
}
|
|
2185
|
-
};
|
|
2186
|
-
fetchFallback();
|
|
2187
|
-
}, [scenes, hasFetchedFallback]);
|
|
2188
|
-
return { scenes: parsedScenes, isLoading, error };
|
|
2189
|
-
}
|
|
2190
|
-
var use_script_breakdown_default = useScriptBreakdown;
|
|
2191
|
-
|
|
2192
|
-
// app/hook/use-script-breakdown-scene.ts
|
|
2193
|
-
function useScriptBreakdownScene(sceneNumber) {
|
|
2194
|
-
const { scenes, isLoading, error } = use_script_breakdown_default({ scenes: [] });
|
|
2266
|
+
function useScriptBreakdownScene(scene_url, fetchOptions, onAISummarize, onTagAdded, onTagRemoved) {
|
|
2195
2267
|
const [tags, setTags] = useState([]);
|
|
2196
2268
|
const [selectionMenu, setSelectionMenu] = useState(null);
|
|
2197
2269
|
const autoTaggedSceneRef = useRef(null);
|
|
2270
|
+
const [scene, setScene] = useState(null);
|
|
2198
2271
|
const [menuPlacement, setMenuPlacement] = useState("top");
|
|
2199
2272
|
const [subLocations, setSubLocations] = useState([]);
|
|
2200
2273
|
const [sceneBrief, setSceneBrief] = useState("");
|
|
2201
2274
|
const [isSummarizing, setIsSummarizing] = useState(false);
|
|
2275
|
+
const [isLoading, setIsLoading] = useState(true);
|
|
2276
|
+
const [error, setError] = useState(false);
|
|
2202
2277
|
const menuRef = useRef(null);
|
|
2203
|
-
|
|
2204
|
-
|
|
2205
|
-
|
|
2278
|
+
useEffect(() => {
|
|
2279
|
+
setIsLoading(true);
|
|
2280
|
+
const fetchScene = async () => {
|
|
2281
|
+
try {
|
|
2282
|
+
const response = await fetch(scene_url, fetchOptions);
|
|
2283
|
+
if (response.ok) {
|
|
2284
|
+
const text = await response.text();
|
|
2285
|
+
setScene({ content: text });
|
|
2286
|
+
} else {
|
|
2287
|
+
console.error("Failed to fetch scene:", response);
|
|
2288
|
+
setError(true);
|
|
2289
|
+
}
|
|
2290
|
+
setIsLoading(false);
|
|
2291
|
+
} catch (error2) {
|
|
2292
|
+
setError(true);
|
|
2293
|
+
setIsLoading(false);
|
|
2294
|
+
console.error("Error fetching scene:", error2);
|
|
2295
|
+
}
|
|
2296
|
+
};
|
|
2297
|
+
fetchScene();
|
|
2298
|
+
}, []);
|
|
2206
2299
|
const blocks = useMemo(() => {
|
|
2207
2300
|
if (!scene || !scene.content) return [];
|
|
2208
2301
|
const parser = new DOMParser();
|
|
@@ -2244,24 +2337,15 @@ function useScriptBreakdownScene(sceneNumber) {
|
|
|
2244
2337
|
}, [blocks]);
|
|
2245
2338
|
const handleAISummarize = async () => {
|
|
2246
2339
|
setIsSummarizing(true);
|
|
2247
|
-
const res = await
|
|
2248
|
-
"https://nonfibrous-extrafloral-verlene.ngrok-free.dev/extract",
|
|
2249
|
-
{
|
|
2250
|
-
method: "POST",
|
|
2251
|
-
headers: {
|
|
2252
|
-
"Content-Type": "application/json",
|
|
2253
|
-
"ngrok-skip-browser-warning": "true"
|
|
2254
|
-
},
|
|
2255
|
-
body: JSON.stringify({
|
|
2256
|
-
script: (scene == null ? void 0 : scene.content) || ""
|
|
2257
|
-
})
|
|
2258
|
-
}
|
|
2259
|
-
);
|
|
2340
|
+
const res = await (onAISummarize == null ? void 0 : onAISummarize(scene.content));
|
|
2260
2341
|
if (res.ok) {
|
|
2261
2342
|
const data = await res.json();
|
|
2262
2343
|
setIsSummarizing(false);
|
|
2263
|
-
const
|
|
2264
|
-
|
|
2344
|
+
const normalData = JSON.parse(data.data);
|
|
2345
|
+
const parsedData = Array.isArray(normalData) ? normalData[0] : [];
|
|
2346
|
+
const summary = Array.isArray(normalData) ? normalData[1] : "";
|
|
2347
|
+
const parsedSummaryData = summary[0];
|
|
2348
|
+
setSceneBrief(parsedSummaryData.summarise);
|
|
2265
2349
|
const newTags = [];
|
|
2266
2350
|
parsedData.forEach((aiTag) => {
|
|
2267
2351
|
if (!aiTag.block_id || !aiTag.category_id || typeof aiTag.start_index !== "number" || typeof aiTag.end_index !== "number") {
|
|
@@ -2310,9 +2394,9 @@ function useScriptBreakdownScene(sceneNumber) {
|
|
|
2310
2394
|
setSubLocations([]);
|
|
2311
2395
|
setSceneBrief("");
|
|
2312
2396
|
autoTaggedSceneRef.current = null;
|
|
2313
|
-
}, [
|
|
2397
|
+
}, [scene_url]);
|
|
2314
2398
|
useEffect(() => {
|
|
2315
|
-
if (blocks.length > 0 && characters.length > 0 && autoTaggedSceneRef.current !==
|
|
2399
|
+
if (blocks.length > 0 && characters.length > 0 && autoTaggedSceneRef.current !== scene) {
|
|
2316
2400
|
const autoTags = [];
|
|
2317
2401
|
const escapeRegExp = (string) => string.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
2318
2402
|
const sortedChars = [...characters].sort((a, b) => b.length - a.length);
|
|
@@ -2342,9 +2426,9 @@ function useScriptBreakdownScene(sceneNumber) {
|
|
|
2342
2426
|
});
|
|
2343
2427
|
});
|
|
2344
2428
|
setTags(autoTags);
|
|
2345
|
-
autoTaggedSceneRef.current =
|
|
2429
|
+
autoTaggedSceneRef.current = scene;
|
|
2346
2430
|
}
|
|
2347
|
-
}, [blocks, characters,
|
|
2431
|
+
}, [blocks, characters, scene]);
|
|
2348
2432
|
const clearSelection = useCallback(() => {
|
|
2349
2433
|
var _a;
|
|
2350
2434
|
setSelectionMenu(null);
|
|
@@ -2431,7 +2515,7 @@ function useScriptBreakdownScene(sceneNumber) {
|
|
|
2431
2515
|
});
|
|
2432
2516
|
}
|
|
2433
2517
|
};
|
|
2434
|
-
const addTag = (categoryId) => {
|
|
2518
|
+
const addTag = async (categoryId) => {
|
|
2435
2519
|
if (!selectionMenu) return;
|
|
2436
2520
|
const newTag = {
|
|
2437
2521
|
id: uuid(),
|
|
@@ -2448,12 +2532,26 @@ function useScriptBreakdownScene(sceneNumber) {
|
|
|
2448
2532
|
return [...filtered, newTag];
|
|
2449
2533
|
});
|
|
2450
2534
|
clearSelection();
|
|
2535
|
+
try {
|
|
2536
|
+
await (onTagAdded == null ? void 0 : onTagAdded(newTag));
|
|
2537
|
+
} catch (error2) {
|
|
2538
|
+
console.error("Failed to add tag:", error2);
|
|
2539
|
+
setTags((prev) => prev.filter((t) => t.id !== newTag.id));
|
|
2540
|
+
}
|
|
2451
2541
|
};
|
|
2452
|
-
const removeTag = (e, id) => {
|
|
2542
|
+
const removeTag = async (e, id) => {
|
|
2453
2543
|
e.stopPropagation();
|
|
2454
2544
|
e.preventDefault();
|
|
2545
|
+
const tagToRemove = tags.find((t) => t.id === id);
|
|
2546
|
+
if (!tagToRemove) return;
|
|
2455
2547
|
setTags((prev) => prev.filter((t) => t.id !== id));
|
|
2456
2548
|
clearSelection();
|
|
2549
|
+
try {
|
|
2550
|
+
await (onTagRemoved == null ? void 0 : onTagRemoved(id));
|
|
2551
|
+
} catch (error2) {
|
|
2552
|
+
console.error("Failed to remove tag:", error2);
|
|
2553
|
+
setTags((prev) => [...prev, tagToRemove]);
|
|
2554
|
+
}
|
|
2457
2555
|
};
|
|
2458
2556
|
return {
|
|
2459
2557
|
scene,
|