@vishu1301/script-writing 0.5.1 → 0.5.3

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 CHANGED
@@ -283,7 +283,7 @@ function PdfImporter({ onScriptImported, children }) {
283
283
  {
284
284
  ref: fileInputRef,
285
285
  type: "file",
286
- accept: ".pdf,.sbx,application/pdf",
286
+ accept: ".pdf,application/pdf",
287
287
  onChange: handleFileChange,
288
288
  disabled: isProcessing,
289
289
  className: "hidden",
@@ -337,7 +337,7 @@ function ScreenplayEditorView({
337
337
  const link = document.createElement("link");
338
338
  link.id = fontId;
339
339
  link.rel = "stylesheet";
340
- link.href = "https://fonts.googleapis.com/css2?family=Courier+Prime&display=swap";
340
+ link.href = "https://fonts.googleapis.com/css2?family=Courier+Prime:ital,wght@0,400;0,700;1,400;1,700&display=swap";
341
341
  document.head.appendChild(link);
342
342
  }
343
343
  }, []);
@@ -385,7 +385,7 @@ function ScreenplayEditorView({
385
385
  {
386
386
  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-[297mm] shrink-0",
387
387
  style: {
388
- fontFamily: "'Courier Prime', 'Courier New', Courier, monospace",
388
+ fontFamily: "var(--font-courier-prime, 'Courier Prime', 'Courier New', Courier, monospace) !important",
389
389
  paddingLeft: "1.5in",
390
390
  paddingRight: "1in",
391
391
  paddingTop: "1in",
@@ -451,6 +451,9 @@ function ScreenplayEditorView({
451
451
  "aria-expanded": focusedBlockId === block.id && showSuggestions && locations.length > 0,
452
452
  spellCheck: false,
453
453
  className: "min-w-[3rem] py-1 outline-none text-base font-bold uppercase tracking-widest break-all bg-transparent",
454
+ style: {
455
+ minWidth: "3rem"
456
+ },
454
457
  onInput: (e) => handleBlockTextChange(
455
458
  block.id,
456
459
  e.target.innerText
@@ -949,7 +952,7 @@ function setCaretPosition(element, offset) {
949
952
  sel.removeAllRanges();
950
953
  sel.addRange(range);
951
954
  }
952
- function useScreenplayEditor() {
955
+ function useScreenplayEditor(options) {
953
956
  const [blocks, setBlocks] = react.useState(initialBlocks);
954
957
  const refs = react.useRef({});
955
958
  const [focusedBlockId, setFocusedBlockId] = react.useState(
@@ -959,6 +962,7 @@ function useScreenplayEditor() {
959
962
  const [showSuggestions, setShowSuggestions] = react.useState(false);
960
963
  const [showExtensionSuggestions, setShowExtensionSuggestions] = react.useState(false);
961
964
  const blurTimeout = react.useRef(null);
965
+ const loadedUrlRef = react.useRef(null);
962
966
  const characterExtensions = react.useMemo(
963
967
  () => ["(V.O.)", "(O.S.)", "(O.C.)", "(SUBTITLE)", "(CONT'D)"],
964
968
  []
@@ -1388,6 +1392,92 @@ function useScreenplayEditor() {
1388
1392
  setShowExtensionSuggestions(false);
1389
1393
  }, 200);
1390
1394
  }, []);
1395
+ const loadFromUrl = react.useCallback(
1396
+ async (url, fetchOptions = {}) => {
1397
+ var _a;
1398
+ try {
1399
+ const response = await fetch(url, fetchOptions);
1400
+ if (!response.ok) {
1401
+ throw new Error(
1402
+ `[useScreenplayEditor] Failed to fetch script. HTTP Status: ${response.status}`
1403
+ );
1404
+ }
1405
+ let text = await response.text();
1406
+ let preParsedBlocks = void 0;
1407
+ let scriptContent = text;
1408
+ if (text.includes('class="divtype') || url.toLowerCase().includes(".sbx")) {
1409
+ if (text.includes("<div")) {
1410
+ const textarea = document.createElement("textarea");
1411
+ textarea.innerHTML = text;
1412
+ text = textarea.value;
1413
+ }
1414
+ const parser = new DOMParser();
1415
+ const doc = parser.parseFromString(text, "text/html");
1416
+ const divs = Array.from(doc.querySelectorAll("div"));
1417
+ const parsed = [];
1418
+ const typeMap = {
1419
+ divtype0: "SCENE_HEADING",
1420
+ divtype2: "ACTION",
1421
+ divtype3: "CHARACTER",
1422
+ divtype4: "PARENTHETICAL",
1423
+ divtype5: "DIALOGUE",
1424
+ divtype6: "TRANSITION"
1425
+ };
1426
+ divs.forEach((div) => {
1427
+ var _a2;
1428
+ let divText = ((_a2 = div.textContent) == null ? void 0 : _a2.trim()) || "";
1429
+ if (!divText) return;
1430
+ let type = "ACTION";
1431
+ for (const className of Array.from(div.classList)) {
1432
+ if (typeMap[className]) {
1433
+ type = typeMap[className];
1434
+ break;
1435
+ }
1436
+ }
1437
+ const block = { type, text: divText };
1438
+ if (type === "SCENE_HEADING") {
1439
+ const sceneNum = div.getAttribute("data-scene");
1440
+ if (sceneNum) block.sceneNumber = sceneNum;
1441
+ let parsedText = divText;
1442
+ const typeMatch = parsedText.match(/^(INT\/EXT|INT|EXT)\.?\s+/i);
1443
+ if (typeMatch) {
1444
+ let sType = typeMatch[1].toUpperCase();
1445
+ if (!sType.endsWith(".")) sType += ".";
1446
+ block.sceneType = sType;
1447
+ parsedText = parsedText.substring(typeMatch[0].length).trim();
1448
+ }
1449
+ const timeMatch = parsedText.match(/\s+-\s+([^-]+)$/);
1450
+ if (timeMatch) {
1451
+ block.timeOfDay = timeMatch[1].trim().toUpperCase();
1452
+ parsedText = parsedText.substring(0, timeMatch.index).trim();
1453
+ }
1454
+ block.text = parsedText;
1455
+ }
1456
+ parsed.push(block);
1457
+ });
1458
+ if (parsed.length > 0) {
1459
+ preParsedBlocks = parsed;
1460
+ scriptContent = "";
1461
+ }
1462
+ }
1463
+ const filename = ((_a = url.split("/").pop()) == null ? void 0 : _a.replace(/\.sbx$/i, "")) || "Imported from URL";
1464
+ handleScriptImport(filename, scriptContent, preParsedBlocks);
1465
+ } catch (error) {
1466
+ console.error(
1467
+ "[useScreenplayEditor] Error loading script from URL:",
1468
+ error
1469
+ );
1470
+ throw error;
1471
+ }
1472
+ },
1473
+ [handleScriptImport]
1474
+ );
1475
+ react.useEffect(() => {
1476
+ if ((options == null ? void 0 : options.initialUrl) && options.initialUrl !== loadedUrlRef.current) {
1477
+ loadedUrlRef.current = options.initialUrl;
1478
+ loadFromUrl(options.initialUrl, options.fetchOptions);
1479
+ }
1480
+ }, [options == null ? void 0 : options.initialUrl, options == null ? void 0 : options.fetchOptions, loadFromUrl]);
1391
1481
  return {
1392
1482
  blocks,
1393
1483
  refs,
@@ -1407,7 +1497,8 @@ function useScreenplayEditor() {
1407
1497
  handleScriptImport,
1408
1498
  handleSceneNumberChange,
1409
1499
  handleFocus,
1410
- handleBlur
1500
+ handleBlur,
1501
+ loadFromUrl
1411
1502
  };
1412
1503
  }
1413
1504
  var handleSaveAsPdf = (blocks, sceneNumbers) => {