@vishu1301/script-writing 0.3.7 → 0.3.9

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.js CHANGED
@@ -46,6 +46,7 @@ var blockStyles = {
46
46
  inputStyle: {
47
47
  textTransform: "uppercase",
48
48
  fontWeight: 700,
49
+ maxWidth: "6.0in",
49
50
  outline: "none",
50
51
  whiteSpace: "pre-wrap",
51
52
  overflowWrap: "break-word",
@@ -54,21 +55,24 @@ var blockStyles = {
54
55
  },
55
56
  ACTION: {
56
57
  label: "Action",
57
- className: "text-zinc-800 leading-relaxed",
58
+ className: "text-zinc-800",
58
59
  inputStyle: {
60
+ maxWidth: "6.0in",
59
61
  outline: "none",
60
62
  whiteSpace: "pre-wrap",
61
63
  overflowWrap: "break-word",
62
64
  wordBreak: "break-word",
63
- lineHeight: 1.7
65
+ lineHeight: "12pt"
64
66
  }
65
67
  },
66
68
  CHARACTER: {
67
69
  label: "Character",
68
- className: "uppercase font-bold text-center text-zinc-900 tracking-widest",
70
+ className: "uppercase font-bold text-zinc-900 tracking-widest",
69
71
  inputStyle: {
70
72
  textTransform: "uppercase",
71
- textAlign: "center",
73
+ textAlign: "left",
74
+ marginLeft: "2.0in",
75
+ maxWidth: "4.0in",
72
76
  fontWeight: 700,
73
77
  letterSpacing: "0.1em",
74
78
  outline: "none",
@@ -79,37 +83,39 @@ var blockStyles = {
79
83
  },
80
84
  PARENTHETICAL: {
81
85
  label: "Parenthetical",
82
- className: "text-center text-zinc-600",
86
+ className: "text-zinc-600",
83
87
  inputStyle: {
84
88
  fontStyle: "normal",
85
- maxWidth: "20rem",
86
- margin: "0 auto",
89
+ maxWidth: "3.0in",
90
+ marginLeft: "1.5in",
91
+ textTransform: "lowercase",
87
92
  outline: "none",
88
93
  whiteSpace: "pre-wrap",
89
94
  overflowWrap: "break-word",
90
95
  wordBreak: "break-word",
91
- textAlign: "center"
96
+ textAlign: "left"
92
97
  }
93
98
  },
94
99
  DIALOGUE: {
95
100
  label: "Dialogue",
96
- className: "text-zinc-900 leading-relaxed max-w-[30rem] mx-auto",
101
+ className: "text-zinc-900",
97
102
  inputStyle: {
98
- marginLeft: "auto",
99
- marginRight: "auto",
103
+ marginLeft: "1.0in",
104
+ maxWidth: "3.5in",
100
105
  outline: "none",
101
106
  whiteSpace: "pre-wrap",
102
107
  overflowWrap: "break-word",
103
108
  wordBreak: "break-word",
104
109
  fontSize: "1.05rem",
105
110
  textAlign: "left",
106
- lineHeight: 1.7
111
+ lineHeight: "12pt"
107
112
  }
108
113
  },
109
114
  TRANSITION: {
110
115
  label: "Transition",
111
116
  className: "uppercase font-bold text-right text-zinc-900",
112
117
  inputStyle: {
118
+ marginLeft: "4.0in",
113
119
  textTransform: "uppercase",
114
120
  fontWeight: 600,
115
121
  textAlign: "right",
@@ -185,7 +191,7 @@ function ScreenplayEditorView({
185
191
  /* @__PURE__ */ jsx("div", { className: "flex flex-col gap-12 w-full items-center pb-24", children: pages.map((pageBlocks, pageIndex) => /* @__PURE__ */ jsxs(
186
192
  "div",
187
193
  {
188
- className: "relative bg-[#fdfdfc] shadow-2xl shadow-zinc-300/60 ring-1 ring-zinc-200/50 rounded-sm md:rounded-md p-16 md:p-20 flex flex-col w-[210mm] min-h-[297mm] shrink-0",
194
+ className: "relative bg-[#fdfdfc] shadow-2xl shadow-zinc-300/60 ring-1 ring-zinc-200/50 rounded-sm md:rounded-md pl-[1.5in] py-[1in] pr-[1in] flex flex-col w-[210mm] min-h-[297mm] shrink-0",
189
195
  style: {
190
196
  fontFamily: "var(--font-courier-prime, 'Courier New', Courier, monospace)"
191
197
  },
@@ -227,7 +233,7 @@ function ScreenplayEditorView({
227
233
  "aria-haspopup": "listbox",
228
234
  "aria-expanded": focusedBlockId === block.id && showSuggestions && locations.length > 0,
229
235
  spellCheck: false,
230
- className: "min-w-[5rem] py-1 outline-none text-base font-bold uppercase tracking-widest break-all bg-transparent",
236
+ className: "min-w-[3rem] py-1 outline-none text-base font-bold uppercase tracking-widest break-all bg-transparent",
231
237
  onInput: (e) => handleBlockTextChange(
232
238
  block.id,
233
239
  e.target.innerText
@@ -466,6 +472,8 @@ function createNewBlock(type) {
466
472
  if (type === "SCENE_HEADING") {
467
473
  newBlock.sceneType = "INT.";
468
474
  newBlock.timeOfDay = "DAY";
475
+ } else if (type === "PARENTHETICAL") {
476
+ newBlock.text = "()";
469
477
  }
470
478
  return newBlock;
471
479
  }
@@ -605,13 +613,22 @@ function useScreenplayEditor() {
605
613
  return map;
606
614
  }, [blocks]);
607
615
  useEffect(() => {
608
- var _a;
609
616
  if (newBlockId && refs.current[newBlockId]) {
610
- (_a = refs.current[newBlockId]) == null ? void 0 : _a.focus();
617
+ const block = blocks.find((b) => b.id === newBlockId);
618
+ const el = refs.current[newBlockId];
619
+ if (el && block) {
620
+ el.focus();
621
+ el.innerText = block.text;
622
+ if (block.type === "PARENTHETICAL") {
623
+ setTimeout(() => setCaretPosition(el, 1), 0);
624
+ } else {
625
+ setTimeout(() => setCaretPosition(el, block.text.length), 0);
626
+ }
627
+ }
611
628
  setFocusedBlockId(newBlockId);
612
629
  setNewBlockId(null);
613
630
  }
614
- }, [newBlockId]);
631
+ }, [newBlockId, blocks]);
615
632
  useEffect(() => {
616
633
  blocks.forEach((block) => {
617
634
  const element = refs.current[block.id];
@@ -620,6 +637,22 @@ function useScreenplayEditor() {
620
637
  }
621
638
  });
622
639
  }, [blocks, isPageSplitEnabled, pageBreaks]);
640
+ useEffect(() => {
641
+ const handleClickOutside = (e) => {
642
+ const target = e.target;
643
+ const isInsideBlock = target.closest("[data-block-id]");
644
+ const isInsideToolbar = target.closest(".sticky");
645
+ const isInsideSuggestions = target.closest('[role="listbox"]');
646
+ if (!isInsideBlock && !isInsideToolbar && !isInsideSuggestions) {
647
+ setFocusedBlockId("");
648
+ setShowSuggestions(false);
649
+ }
650
+ };
651
+ document.addEventListener("mousedown", handleClickOutside);
652
+ return () => {
653
+ document.removeEventListener("mousedown", handleClickOutside);
654
+ };
655
+ }, []);
623
656
  useEffect(() => {
624
657
  if (!isPageSplitEnabled) {
625
658
  setPageBreaks([]);
@@ -712,9 +745,31 @@ function useScreenplayEditor() {
712
745
  focusStateRef.current = null;
713
746
  }
714
747
  }, [pages]);
715
- const handleBlockTextChange = useCallback((id, text) => {
716
- setBlocks((bs) => updateBlock(bs, id, "text", text));
717
- }, []);
748
+ const handleBlockTextChange = useCallback(
749
+ (id, text) => {
750
+ const block = blocks.find((b) => b.id === id);
751
+ if (!block) return;
752
+ let processedText = text;
753
+ if (block.type === "PARENTHETICAL") {
754
+ const clean = text.replace(/[()]/g, "");
755
+ processedText = `(${clean})`;
756
+ }
757
+ setBlocks(
758
+ (bs) => updateBlock(bs, id, "text", processedText)
759
+ );
760
+ if (text !== processedText) {
761
+ const el = refs.current[id];
762
+ if (el) {
763
+ const offset = getCaretCharacterOffsetWithin(el);
764
+ const charsBeforeCaret = text.substring(0, offset).replace(/[()]/g, "").length;
765
+ const newOffset = 1 + charsBeforeCaret;
766
+ el.innerText = processedText;
767
+ setCaretPosition(el, newOffset);
768
+ }
769
+ }
770
+ },
771
+ [blocks]
772
+ );
718
773
  const handleSceneTypeChange = useCallback(
719
774
  (id, sceneType) => {
720
775
  setBlocks(
@@ -745,8 +800,14 @@ function useScreenplayEditor() {
745
800
  setTimeout(() => {
746
801
  const el = refs.current[focusedBlockId];
747
802
  if (el) {
748
- el.innerText = "";
749
803
  el.focus();
804
+ const newBlock = createNewBlock(newType);
805
+ el.innerText = newBlock.text;
806
+ if (newType === "PARENTHETICAL") {
807
+ setCaretPosition(el, 1);
808
+ } else {
809
+ setCaretPosition(el, newBlock.text.length);
810
+ }
750
811
  }
751
812
  }, 0);
752
813
  },
@@ -765,19 +826,44 @@ function useScreenplayEditor() {
765
826
  sel.addRange(range);
766
827
  };
767
828
  const cycleBlockType = (id, direction) => {
768
- setBlocks((bs) => {
769
- const block = bs.find((b) => b.id === id);
770
- if (!block) return bs;
771
- const idx = blockTypes.indexOf(block.type);
772
- let newIdx = direction === "up" ? idx - 1 : idx + 1;
773
- if (newIdx < 0) newIdx = blockTypes.length - 1;
774
- if (newIdx >= blockTypes.length) newIdx = 0;
775
- return updateBlock(bs, id, "type", blockTypes[newIdx]);
776
- });
829
+ const block = blocks.find((b) => b.id === id);
830
+ if (!block) return;
831
+ const idx = blockTypes.indexOf(block.type);
832
+ let newIdx = direction === "up" ? idx - 1 : idx + 1;
833
+ if (newIdx < 0) newIdx = blockTypes.length - 1;
834
+ if (newIdx >= blockTypes.length) newIdx = 0;
835
+ const newType = blockTypes[newIdx];
836
+ setBlocks((bs) => changeBlockType(bs, id, newType));
837
+ setTimeout(() => {
838
+ const el = refs.current[id];
839
+ if (el) {
840
+ el.focus();
841
+ const newBlock = createNewBlock(newType);
842
+ el.innerText = newBlock.text;
843
+ if (newType === "PARENTHETICAL") {
844
+ setCaretPosition(el, 1);
845
+ } else {
846
+ setCaretPosition(el, el.innerText.length);
847
+ }
848
+ }
849
+ }, 10);
777
850
  };
778
851
  const handleKeyDown = useCallback(
779
852
  (e, id, text) => {
780
853
  var _a;
854
+ const block = blocks.find((b) => b.id === id);
855
+ if ((block == null ? void 0 : block.type) === "PARENTHETICAL") {
856
+ const offset = getCaretCharacterOffsetWithin(e.currentTarget);
857
+ if (e.key === "Backspace" && (offset <= 1 || text === "()")) {
858
+ e.preventDefault();
859
+ cycleBlockType(id, "up");
860
+ return;
861
+ }
862
+ if (e.key === "Delete" && (offset >= text.length - 1 || text === "()")) {
863
+ e.preventDefault();
864
+ return;
865
+ }
866
+ }
781
867
  if ((e.key === "Backspace" || e.key === "Delete") && text.length <= 1) {
782
868
  e.preventDefault();
783
869
  const { newBlocks, nextFocusedId } = deleteBlock(
@@ -803,11 +889,9 @@ function useScreenplayEditor() {
803
889
  } else if (e.key === "ArrowUp" && e.ctrlKey) {
804
890
  e.preventDefault();
805
891
  cycleBlockType(id, "up");
806
- requestAnimationFrame(() => focusBlock(id));
807
892
  } else if (e.key === "ArrowDown" && e.ctrlKey) {
808
893
  e.preventDefault();
809
894
  cycleBlockType(id, "down");
810
- requestAnimationFrame(() => focusBlock(id));
811
895
  } else if (e.key === "ArrowUp" && !e.ctrlKey) {
812
896
  const selection = window.getSelection();
813
897
  if (!selection || !selection.isCollapsed || selection.rangeCount === 0) {
@@ -884,7 +968,7 @@ function useScreenplayEditor() {
884
968
  }
885
969
  }
886
970
  },
887
- [blocks]
971
+ [blocks, handleBlockTextChange]
888
972
  );
889
973
  const handleFocus = useCallback((id) => {
890
974
  if (blurTimeout.current) {