@vishu1301/script-writing 0.3.2 → 0.3.4
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.mjs → index.cjs} +133 -123
- package/dist/index.cjs.map +1 -0
- package/dist/index.js +122 -132
- package/dist/index.js.map +1 -1
- package/package.json +4 -2
- package/dist/index.mjs.map +0 -1
- /package/dist/{index.d.mts → index.d.cts} +0 -0
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
"use client";
|
|
2
|
+
"use strict";
|
|
2
3
|
var __defProp = Object.defineProperty;
|
|
3
4
|
var __defProps = Object.defineProperties;
|
|
5
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
6
|
var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
|
|
7
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
8
|
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
|
|
6
9
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
10
|
var __propIsEnum = Object.prototype.propertyIsEnumerable;
|
|
@@ -18,20 +21,39 @@ var __spreadValues = (a, b) => {
|
|
|
18
21
|
return a;
|
|
19
22
|
};
|
|
20
23
|
var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
|
|
24
|
+
var __export = (target, all) => {
|
|
25
|
+
for (var name in all)
|
|
26
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
27
|
+
};
|
|
28
|
+
var __copyProps = (to, from, except, desc) => {
|
|
29
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
30
|
+
for (let key of __getOwnPropNames(from))
|
|
31
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
32
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
33
|
+
}
|
|
34
|
+
return to;
|
|
35
|
+
};
|
|
36
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
37
|
+
|
|
38
|
+
// app/index.ts
|
|
39
|
+
var index_exports = {};
|
|
40
|
+
__export(index_exports, {
|
|
41
|
+
ScreenplayEditorView: () => ScreenplayEditorView,
|
|
42
|
+
blockStyles: () => blockStyles,
|
|
43
|
+
blockTypes: () => blockTypes,
|
|
44
|
+
icons: () => icons,
|
|
45
|
+
timeOfDayOptions: () => timeOfDayOptions,
|
|
46
|
+
useScreenplayEditor: () => useScreenplayEditor,
|
|
47
|
+
uuid: () => uuid
|
|
48
|
+
});
|
|
49
|
+
module.exports = __toCommonJS(index_exports);
|
|
21
50
|
|
|
22
51
|
// app/view/screenplay-editor.view.tsx
|
|
23
|
-
|
|
52
|
+
var import_react = require("react");
|
|
24
53
|
|
|
25
54
|
// app/types/screenplay-editor.types.tsx
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
Sparkles,
|
|
29
|
-
UserRound,
|
|
30
|
-
Brackets,
|
|
31
|
-
MessageCircle,
|
|
32
|
-
ArrowRightLeft
|
|
33
|
-
} from "lucide-react";
|
|
34
|
-
import { jsx } from "react/jsx-runtime";
|
|
55
|
+
var import_lucide_react = require("lucide-react");
|
|
56
|
+
var import_jsx_runtime = require("react/jsx-runtime");
|
|
35
57
|
var timeOfDayOptions = ["DAY", "NIGHT"];
|
|
36
58
|
var blockTypes = [
|
|
37
59
|
"SCENE_HEADING",
|
|
@@ -43,12 +65,12 @@ var blockTypes = [
|
|
|
43
65
|
];
|
|
44
66
|
var uuid = () => Math.random().toString(36).slice(2, 9);
|
|
45
67
|
var icons = {
|
|
46
|
-
SCENE_HEADING: /* @__PURE__ */ jsx(Clapperboard, { className: "w-5 h-5" }),
|
|
47
|
-
ACTION: /* @__PURE__ */ jsx(Sparkles, { className: "w-5 h-5" }),
|
|
48
|
-
CHARACTER: /* @__PURE__ */ jsx(UserRound, { className: "w-5 h-5" }),
|
|
49
|
-
PARENTHETICAL: /* @__PURE__ */ jsx(Brackets, { className: "w-5 h-5" }),
|
|
50
|
-
DIALOGUE: /* @__PURE__ */ jsx(MessageCircle, { className: "w-5 h-5" }),
|
|
51
|
-
TRANSITION: /* @__PURE__ */ jsx(ArrowRightLeft, { className: "w-5 h-5" })
|
|
68
|
+
SCENE_HEADING: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_lucide_react.Clapperboard, { className: "w-5 h-5" }),
|
|
69
|
+
ACTION: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_lucide_react.Sparkles, { className: "w-5 h-5" }),
|
|
70
|
+
CHARACTER: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_lucide_react.UserRound, { className: "w-5 h-5" }),
|
|
71
|
+
PARENTHETICAL: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_lucide_react.Brackets, { className: "w-5 h-5" }),
|
|
72
|
+
DIALOGUE: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_lucide_react.MessageCircle, { className: "w-5 h-5" }),
|
|
73
|
+
TRANSITION: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_lucide_react.ArrowRightLeft, { className: "w-5 h-5" })
|
|
52
74
|
};
|
|
53
75
|
var blockStyles = {
|
|
54
76
|
SCENE_HEADING: {
|
|
@@ -133,15 +155,8 @@ var blockStyles = {
|
|
|
133
155
|
};
|
|
134
156
|
|
|
135
157
|
// app/view/screenplay-editor.view.tsx
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
ChevronRight,
|
|
139
|
-
User,
|
|
140
|
-
Cog,
|
|
141
|
-
Save,
|
|
142
|
-
FileDown
|
|
143
|
-
} from "lucide-react";
|
|
144
|
-
import { Fragment, jsx as jsx2, jsxs } from "react/jsx-runtime";
|
|
158
|
+
var import_lucide_react2 = require("lucide-react");
|
|
159
|
+
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
145
160
|
function ScreenplayEditorView({
|
|
146
161
|
blocks,
|
|
147
162
|
pages,
|
|
@@ -164,19 +179,19 @@ function ScreenplayEditorView({
|
|
|
164
179
|
onSaveAsPdf,
|
|
165
180
|
onSyncWithCloud
|
|
166
181
|
}) {
|
|
167
|
-
const [isRulesOpen, setIsRulesOpen] = useState(false);
|
|
168
|
-
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
169
|
-
/* @__PURE__ */
|
|
182
|
+
const [isRulesOpen, setIsRulesOpen] = (0, import_react.useState)(false);
|
|
183
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
|
|
184
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "sticky top-6 z-50 bg-white backdrop-blur-xl border border-white/10 rounded-full shadow-2xl flex gap-1 max-w-fit p-1.5 mb-12 select-none overflow-x-auto custom-scrollbar", children: blockTypes.map((type) => {
|
|
170
185
|
var _a;
|
|
171
186
|
const selected = ((_a = blocks.find((b) => b.id === focusedBlockId)) == null ? void 0 : _a.type) === type;
|
|
172
|
-
return /* @__PURE__ */ jsxs(
|
|
187
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
|
|
173
188
|
"button",
|
|
174
189
|
{
|
|
175
190
|
type: "button",
|
|
176
191
|
className: `flex items-center gap-2 px-4 py-2.5 rounded-full font-medium text-sm transition-all duration-300 ${selected ? "bg-zinc-900 text-white shadow-sm" : "text-zinc-400 hover:bg-zinc-800/10 hover:text-zinc-800"}`,
|
|
177
192
|
onClick: () => handleBlockTypeChange(type),
|
|
178
193
|
children: [
|
|
179
|
-
/* @__PURE__ */
|
|
194
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
180
195
|
"input",
|
|
181
196
|
{
|
|
182
197
|
type: "radio",
|
|
@@ -188,14 +203,14 @@ function ScreenplayEditorView({
|
|
|
188
203
|
readOnly: true
|
|
189
204
|
}
|
|
190
205
|
),
|
|
191
|
-
/* @__PURE__ */ jsxs(
|
|
206
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
|
|
192
207
|
"label",
|
|
193
208
|
{
|
|
194
209
|
htmlFor: `block-type-${type}`,
|
|
195
210
|
className: "flex items-center gap-2 cursor-pointer",
|
|
196
211
|
children: [
|
|
197
212
|
icons[type],
|
|
198
|
-
/* @__PURE__ */
|
|
213
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "whitespace-nowrap hidden sm:inline", children: blockStyles[type].label })
|
|
199
214
|
]
|
|
200
215
|
}
|
|
201
216
|
)
|
|
@@ -204,7 +219,7 @@ function ScreenplayEditorView({
|
|
|
204
219
|
type
|
|
205
220
|
);
|
|
206
221
|
}) }),
|
|
207
|
-
/* @__PURE__ */
|
|
222
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "flex flex-col gap-12 w-full items-center pb-24", children: pages.map((pageBlocks, pageIndex) => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
|
|
208
223
|
"div",
|
|
209
224
|
{
|
|
210
225
|
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",
|
|
@@ -214,15 +229,15 @@ function ScreenplayEditorView({
|
|
|
214
229
|
children: [
|
|
215
230
|
pageBlocks.map((block) => {
|
|
216
231
|
var _a, _b;
|
|
217
|
-
return /* @__PURE__ */
|
|
232
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
218
233
|
"div",
|
|
219
234
|
{
|
|
220
235
|
"data-block-id": block.id,
|
|
221
236
|
className: `relative rounded-sm transition-all duration-200 outline-none ${focusedBlockId === block.id ? "bg-zinc-100/50" : "bg-transparent"}`,
|
|
222
|
-
children: block.type === "SCENE_HEADING" ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
223
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 px-4 py-1 bg-transparent", children: [
|
|
224
|
-
/* @__PURE__ */
|
|
225
|
-
/* @__PURE__ */ jsxs(
|
|
237
|
+
children: block.type === "SCENE_HEADING" ? /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
|
|
238
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "flex items-center gap-2 px-4 py-1 bg-transparent", children: [
|
|
239
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "absolute -left-16 top-2 w-12 text-right text-zinc-400 font-semibold select-none", children: String(sceneNumbers[block.id] || 0) }),
|
|
240
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
|
|
226
241
|
"select",
|
|
227
242
|
{
|
|
228
243
|
className: "rounded-md text-zinc-800 font-bold px-1.5 py-1 appearance-none bg-transparent hover:bg-zinc-200/50 outline-none cursor-pointer w-fit transition-colors",
|
|
@@ -230,13 +245,13 @@ function ScreenplayEditorView({
|
|
|
230
245
|
value: (_a = block.sceneType) != null ? _a : "INT.",
|
|
231
246
|
onChange: (e) => handleSceneTypeChange(block.id, e.target.value),
|
|
232
247
|
children: [
|
|
233
|
-
/* @__PURE__ */
|
|
234
|
-
/* @__PURE__ */
|
|
235
|
-
/* @__PURE__ */
|
|
248
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("option", { children: "INT." }),
|
|
249
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("option", { children: "EXT." }),
|
|
250
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("option", { children: "INT/EXT." })
|
|
236
251
|
]
|
|
237
252
|
}
|
|
238
253
|
),
|
|
239
|
-
/* @__PURE__ */
|
|
254
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
240
255
|
"div",
|
|
241
256
|
{
|
|
242
257
|
ref: (el) => {
|
|
@@ -259,27 +274,27 @@ function ScreenplayEditorView({
|
|
|
259
274
|
onBlur: () => handleBlur(block.id)
|
|
260
275
|
}
|
|
261
276
|
),
|
|
262
|
-
/* @__PURE__ */
|
|
263
|
-
/* @__PURE__ */
|
|
277
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "text-zinc-400/80 font-bold", children: "-" }),
|
|
278
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
264
279
|
"select",
|
|
265
280
|
{
|
|
266
281
|
className: "rounded-md text-zinc-800 font-bold px-1.5 py-1 appearance-none bg-transparent hover:bg-zinc-200/50 outline-none cursor-pointer transition-colors",
|
|
267
282
|
"aria-label": "Time of Day",
|
|
268
283
|
value: (_b = block.timeOfDay) != null ? _b : "DAY",
|
|
269
284
|
onChange: (e) => handleTimeOfDayChange(block.id, e.target.value),
|
|
270
|
-
children: timeOfDayOptions.map((t) => /* @__PURE__ */
|
|
285
|
+
children: timeOfDayOptions.map((t) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("option", { children: t }, t))
|
|
271
286
|
}
|
|
272
287
|
)
|
|
273
288
|
] }),
|
|
274
|
-
focusedBlockId === block.id && showSuggestions && locations.length > 0 && /* @__PURE__ */
|
|
289
|
+
focusedBlockId === block.id && showSuggestions && locations.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
275
290
|
"div",
|
|
276
291
|
{
|
|
277
292
|
role: "listbox",
|
|
278
293
|
id: `suggestions-${block.id}`,
|
|
279
294
|
className: "absolute top-[calc(100%+6px)] left-0 min-w-[240px] z-50 bg-white border border-slate-200/80 shadow-xl shadow-slate-200/40 rounded-xl py-1 overflow-hidden animate-in fade-in zoom-in-95 duration-150",
|
|
280
|
-
children: /* @__PURE__ */
|
|
295
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "max-h-60 overflow-y-auto custom-scrollbar", children: locations.filter(
|
|
281
296
|
(loc) => loc.startsWith(block.text.toUpperCase()) && loc !== block.text.toUpperCase()
|
|
282
|
-
).map((loc) => /* @__PURE__ */ jsxs(
|
|
297
|
+
).map((loc) => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
|
|
283
298
|
"div",
|
|
284
299
|
{
|
|
285
300
|
role: "option",
|
|
@@ -301,16 +316,16 @@ function ScreenplayEditorView({
|
|
|
301
316
|
handleBlur(block.id);
|
|
302
317
|
},
|
|
303
318
|
children: [
|
|
304
|
-
/* @__PURE__ */
|
|
305
|
-
/* @__PURE__ */
|
|
319
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "text-[12px] font-semibold tracking-wide text-slate-600 uppercase line-clamp-1", children: loc }),
|
|
320
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_lucide_react2.ArrowRight, { className: "w-3.5 h-3.5 text-slate-300 opacity-0 -translate-x-2 group-hover:opacity-100 group-hover:translate-x-0 transition-all duration-200" })
|
|
306
321
|
]
|
|
307
322
|
},
|
|
308
323
|
loc
|
|
309
324
|
)) })
|
|
310
325
|
}
|
|
311
326
|
)
|
|
312
|
-
] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
313
|
-
/* @__PURE__ */
|
|
327
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
|
|
328
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
314
329
|
"div",
|
|
315
330
|
{
|
|
316
331
|
ref: (el) => {
|
|
@@ -333,15 +348,15 @@ function ScreenplayEditorView({
|
|
|
333
348
|
style: blockStyles[block.type].inputStyle
|
|
334
349
|
}
|
|
335
350
|
),
|
|
336
|
-
focusedBlockId === block.id && block.type === "CHARACTER" && showSuggestions && characters.length > 0 && /* @__PURE__ */
|
|
351
|
+
focusedBlockId === block.id && block.type === "CHARACTER" && showSuggestions && characters.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
337
352
|
"div",
|
|
338
353
|
{
|
|
339
354
|
role: "listbox",
|
|
340
355
|
id: `suggestions-${block.id}`,
|
|
341
356
|
className: "absolute top-[calc(100%+8px)] left-1/2 -translate-x-1/2 w-72 z-50 bg-white border border-slate-200 shadow-2xl shadow-slate-200/60 rounded-xl py-2 overflow-hidden animate-in fade-in zoom-in-95 duration-200",
|
|
342
|
-
children: /* @__PURE__ */
|
|
357
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "max-h-56 overflow-y-auto custom-scrollbar", children: characters.filter(
|
|
343
358
|
(char) => char.startsWith(block.text.toUpperCase()) && char !== block.text.toUpperCase()
|
|
344
|
-
).map((char) => /* @__PURE__ */ jsxs(
|
|
359
|
+
).map((char) => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
|
|
345
360
|
"div",
|
|
346
361
|
{
|
|
347
362
|
role: "option",
|
|
@@ -363,9 +378,9 @@ function ScreenplayEditorView({
|
|
|
363
378
|
handleBlur(block.id);
|
|
364
379
|
},
|
|
365
380
|
children: [
|
|
366
|
-
/* @__PURE__ */
|
|
367
|
-
/* @__PURE__ */
|
|
368
|
-
/* @__PURE__ */
|
|
381
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_lucide_react2.User, { className: "w-3.5 h-3.5 text-slate-300 group-hover:text-sky-500 transition-colors mr-3" }),
|
|
382
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "flex-1 text-[11px] font-bold tracking-[0.1em] text-slate-600 uppercase text-left", children: char }),
|
|
383
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_lucide_react2.ChevronRight, { className: "w-3 h-3 text-slate-200 opacity-0 group-hover:opacity-100 transition-all -translate-x-1 group-hover:translate-x-0" })
|
|
369
384
|
]
|
|
370
385
|
},
|
|
371
386
|
char
|
|
@@ -377,7 +392,7 @@ function ScreenplayEditorView({
|
|
|
377
392
|
block.id + "-" + block.type
|
|
378
393
|
);
|
|
379
394
|
}),
|
|
380
|
-
isPageSplitEnabled && /* @__PURE__ */ jsxs("div", { className: "absolute bottom-10 right-16 md:right-20 text-zinc-400 font-semibold text-sm select-none pointer-events-none", children: [
|
|
395
|
+
isPageSplitEnabled && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "absolute bottom-10 right-16 md:right-20 text-zinc-400 font-semibold text-sm select-none pointer-events-none", children: [
|
|
381
396
|
pageIndex + 1,
|
|
382
397
|
"."
|
|
383
398
|
] })
|
|
@@ -385,37 +400,37 @@ function ScreenplayEditorView({
|
|
|
385
400
|
},
|
|
386
401
|
pageIndex
|
|
387
402
|
)) }),
|
|
388
|
-
/* @__PURE__ */ jsxs("div", { className: "fixed bottom-6 right-6 flex flex-col items-end gap-4 z-50", children: [
|
|
389
|
-
onSave && /* @__PURE__ */ jsxs(
|
|
403
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "fixed bottom-6 right-6 flex flex-col items-end gap-4 z-50", children: [
|
|
404
|
+
onSave && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
|
|
390
405
|
"button",
|
|
391
406
|
{
|
|
392
407
|
onClick: onSave,
|
|
393
408
|
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",
|
|
394
409
|
"aria-label": "Save Script",
|
|
395
410
|
children: [
|
|
396
|
-
/* @__PURE__ */
|
|
397
|
-
/* @__PURE__ */
|
|
411
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_lucide_react2.Save, { className: "w-5 h-5" }),
|
|
412
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "text-sm font-semibold", children: "Save" })
|
|
398
413
|
]
|
|
399
414
|
}
|
|
400
415
|
),
|
|
401
|
-
onSaveAsPdf && /* @__PURE__ */ jsxs(
|
|
416
|
+
onSaveAsPdf && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
|
|
402
417
|
"button",
|
|
403
418
|
{
|
|
404
419
|
onClick: onSaveAsPdf,
|
|
405
420
|
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",
|
|
406
421
|
"aria-label": "Save Script as PDF",
|
|
407
422
|
children: [
|
|
408
|
-
/* @__PURE__ */
|
|
409
|
-
/* @__PURE__ */
|
|
423
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_lucide_react2.FileDown, { className: "w-5 h-5" }),
|
|
424
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "text-sm font-semibold", children: "Save as PDF" })
|
|
410
425
|
]
|
|
411
426
|
}
|
|
412
427
|
),
|
|
413
|
-
isRulesOpen && /* @__PURE__ */ 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: [
|
|
414
|
-
/* @__PURE__ */
|
|
415
|
-
/* @__PURE__ */ jsxs("div", { className: "space-y-4", children: [
|
|
416
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-6", children: [
|
|
417
|
-
/* @__PURE__ */
|
|
418
|
-
/* @__PURE__ */
|
|
428
|
+
isRulesOpen && /* @__PURE__ */ (0, import_jsx_runtime2.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: [
|
|
429
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("h4", { className: "font-bold text-zinc-800 mb-3 text-sm", children: "Settings & Shortcuts" }),
|
|
430
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "space-y-4", children: [
|
|
431
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "flex items-center justify-between gap-6", children: [
|
|
432
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "font-semibold text-zinc-800", children: "A4 Page Split" }),
|
|
433
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
419
434
|
"button",
|
|
420
435
|
{
|
|
421
436
|
type: "button",
|
|
@@ -423,7 +438,7 @@ function ScreenplayEditorView({
|
|
|
423
438
|
"aria-checked": isPageSplitEnabled,
|
|
424
439
|
onClick: togglePageSplit,
|
|
425
440
|
className: `${isPageSplitEnabled ? "bg-zinc-900" : "bg-zinc-300"} relative inline-flex h-5 w-9 shrink-0 cursor-pointer rounded-full border-2 border-transparent transition-colors duration-200 ease-in-out focus:outline-none`,
|
|
426
|
-
children: /* @__PURE__ */
|
|
441
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
427
442
|
"span",
|
|
428
443
|
{
|
|
429
444
|
"aria-hidden": "true",
|
|
@@ -433,33 +448,33 @@ function ScreenplayEditorView({
|
|
|
433
448
|
}
|
|
434
449
|
)
|
|
435
450
|
] }),
|
|
436
|
-
/* @__PURE__ */
|
|
437
|
-
/* @__PURE__ */ jsxs("li", { className: "flex items-center justify-between gap-6", children: [
|
|
438
|
-
/* @__PURE__ */
|
|
439
|
-
/* @__PURE__ */
|
|
451
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "space-y-1.5 pt-3 border-t border-zinc-200/50", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("ul", { className: "space-y-1.5", children: [
|
|
452
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("li", { className: "flex items-center justify-between gap-6", children: [
|
|
453
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { children: "New Block" }),
|
|
454
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.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" })
|
|
440
455
|
] }),
|
|
441
|
-
/* @__PURE__ */ jsxs("li", { className: "flex items-center justify-between gap-6", children: [
|
|
442
|
-
/* @__PURE__ */
|
|
443
|
-
/* @__PURE__ */
|
|
456
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("li", { className: "flex items-center justify-between gap-6", children: [
|
|
457
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { children: "Delete Block" }),
|
|
458
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.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" })
|
|
444
459
|
] }),
|
|
445
|
-
/* @__PURE__ */ jsxs("li", { className: "flex items-center justify-between gap-6", children: [
|
|
446
|
-
/* @__PURE__ */
|
|
447
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1", children: [
|
|
448
|
-
/* @__PURE__ */
|
|
449
|
-
/* @__PURE__ */
|
|
450
|
-
/* @__PURE__ */
|
|
460
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("li", { className: "flex items-center justify-between gap-6", children: [
|
|
461
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { children: "Change Type" }),
|
|
462
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "flex items-center gap-1", children: [
|
|
463
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.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" }),
|
|
464
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { children: "+" }),
|
|
465
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.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" })
|
|
451
466
|
] })
|
|
452
467
|
] })
|
|
453
468
|
] }) })
|
|
454
469
|
] })
|
|
455
470
|
] }),
|
|
456
|
-
/* @__PURE__ */
|
|
471
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
457
472
|
"button",
|
|
458
473
|
{
|
|
459
474
|
onClick: () => setIsRulesOpen(!isRulesOpen),
|
|
460
475
|
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"}`,
|
|
461
476
|
"aria-label": "Toggle Settings",
|
|
462
|
-
children: /* @__PURE__ */
|
|
477
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_lucide_react2.Cog, { className: "w-5 h-5" })
|
|
463
478
|
}
|
|
464
479
|
)
|
|
465
480
|
] })
|
|
@@ -467,13 +482,7 @@ function ScreenplayEditorView({
|
|
|
467
482
|
}
|
|
468
483
|
|
|
469
484
|
// app/hook/use-screenplay-editor.ts
|
|
470
|
-
|
|
471
|
-
useState as useState2,
|
|
472
|
-
useRef,
|
|
473
|
-
useEffect,
|
|
474
|
-
useMemo,
|
|
475
|
-
useCallback
|
|
476
|
-
} from "react";
|
|
485
|
+
var import_react2 = require("react");
|
|
477
486
|
|
|
478
487
|
// app/service/screenplay-editor.service.ts
|
|
479
488
|
function getNextBlockType(currentType) {
|
|
@@ -595,18 +604,18 @@ function setCaretPosition(element, offset) {
|
|
|
595
604
|
sel.addRange(range);
|
|
596
605
|
}
|
|
597
606
|
function useScreenplayEditor() {
|
|
598
|
-
const [blocks, setBlocks] =
|
|
599
|
-
const refs = useRef({});
|
|
600
|
-
const [focusedBlockId, setFocusedBlockId] =
|
|
607
|
+
const [blocks, setBlocks] = (0, import_react2.useState)(initialBlocks);
|
|
608
|
+
const refs = (0, import_react2.useRef)({});
|
|
609
|
+
const [focusedBlockId, setFocusedBlockId] = (0, import_react2.useState)(
|
|
601
610
|
initialBlocks[0].id
|
|
602
611
|
);
|
|
603
|
-
const [newBlockId, setNewBlockId] =
|
|
604
|
-
const [showSuggestions, setShowSuggestions] =
|
|
605
|
-
const blurTimeout = useRef(null);
|
|
606
|
-
const [isPageSplitEnabled, setIsPageSplitEnabled] =
|
|
607
|
-
const [pageBreaks, setPageBreaks] =
|
|
608
|
-
const focusStateRef = useRef(null);
|
|
609
|
-
const togglePageSplit = useCallback(() => {
|
|
612
|
+
const [newBlockId, setNewBlockId] = (0, import_react2.useState)(null);
|
|
613
|
+
const [showSuggestions, setShowSuggestions] = (0, import_react2.useState)(false);
|
|
614
|
+
const blurTimeout = (0, import_react2.useRef)(null);
|
|
615
|
+
const [isPageSplitEnabled, setIsPageSplitEnabled] = (0, import_react2.useState)(false);
|
|
616
|
+
const [pageBreaks, setPageBreaks] = (0, import_react2.useState)([]);
|
|
617
|
+
const focusStateRef = (0, import_react2.useRef)(null);
|
|
618
|
+
const togglePageSplit = (0, import_react2.useCallback)(() => {
|
|
610
619
|
if (focusedBlockId && document.activeElement && document.activeElement.hasAttribute("contenteditable")) {
|
|
611
620
|
const el = refs.current[focusedBlockId];
|
|
612
621
|
if (el) {
|
|
@@ -616,15 +625,15 @@ function useScreenplayEditor() {
|
|
|
616
625
|
}
|
|
617
626
|
setIsPageSplitEnabled((prev) => !prev);
|
|
618
627
|
}, [focusedBlockId]);
|
|
619
|
-
const locations = useMemo(() => {
|
|
628
|
+
const locations = (0, import_react2.useMemo)(() => {
|
|
620
629
|
const locs = blocks.filter((b) => b.type === "SCENE_HEADING" && b.text.trim() !== "").map((b) => b.text.trim().toUpperCase());
|
|
621
630
|
return [...new Set(locs)];
|
|
622
631
|
}, [blocks]);
|
|
623
|
-
const characters = useMemo(() => {
|
|
632
|
+
const characters = (0, import_react2.useMemo)(() => {
|
|
624
633
|
const chars = blocks.filter((b) => b.type === "CHARACTER" && b.text.trim() !== "").map((b) => b.text.trim().toUpperCase());
|
|
625
634
|
return [...new Set(chars)];
|
|
626
635
|
}, [blocks]);
|
|
627
|
-
const sceneNumbers = useMemo(() => {
|
|
636
|
+
const sceneNumbers = (0, import_react2.useMemo)(() => {
|
|
628
637
|
const map = {};
|
|
629
638
|
let count = 0;
|
|
630
639
|
blocks.forEach((block) => {
|
|
@@ -635,7 +644,7 @@ function useScreenplayEditor() {
|
|
|
635
644
|
});
|
|
636
645
|
return map;
|
|
637
646
|
}, [blocks]);
|
|
638
|
-
useEffect(() => {
|
|
647
|
+
(0, import_react2.useEffect)(() => {
|
|
639
648
|
var _a;
|
|
640
649
|
if (newBlockId && refs.current[newBlockId]) {
|
|
641
650
|
(_a = refs.current[newBlockId]) == null ? void 0 : _a.focus();
|
|
@@ -643,7 +652,7 @@ function useScreenplayEditor() {
|
|
|
643
652
|
setNewBlockId(null);
|
|
644
653
|
}
|
|
645
654
|
}, [newBlockId]);
|
|
646
|
-
useEffect(() => {
|
|
655
|
+
(0, import_react2.useEffect)(() => {
|
|
647
656
|
blocks.forEach((block) => {
|
|
648
657
|
const element = refs.current[block.id];
|
|
649
658
|
if (element && element.innerText !== block.text && document.activeElement !== element) {
|
|
@@ -651,7 +660,7 @@ function useScreenplayEditor() {
|
|
|
651
660
|
}
|
|
652
661
|
});
|
|
653
662
|
}, [blocks, isPageSplitEnabled, pageBreaks]);
|
|
654
|
-
useEffect(() => {
|
|
663
|
+
(0, import_react2.useEffect)(() => {
|
|
655
664
|
if (!isPageSplitEnabled) {
|
|
656
665
|
setPageBreaks([]);
|
|
657
666
|
return;
|
|
@@ -718,7 +727,7 @@ function useScreenplayEditor() {
|
|
|
718
727
|
}, 300);
|
|
719
728
|
return () => clearTimeout(timeoutId);
|
|
720
729
|
}, [blocks, isPageSplitEnabled, focusedBlockId]);
|
|
721
|
-
const pages = useMemo(() => {
|
|
730
|
+
const pages = (0, import_react2.useMemo)(() => {
|
|
722
731
|
if (!isPageSplitEnabled || pageBreaks.length === 0) return [blocks];
|
|
723
732
|
const result = [];
|
|
724
733
|
let currentPage = [];
|
|
@@ -732,7 +741,7 @@ function useScreenplayEditor() {
|
|
|
732
741
|
if (currentPage.length > 0) result.push(currentPage);
|
|
733
742
|
return result;
|
|
734
743
|
}, [blocks, isPageSplitEnabled, pageBreaks]);
|
|
735
|
-
useEffect(() => {
|
|
744
|
+
(0, import_react2.useEffect)(() => {
|
|
736
745
|
if (focusStateRef.current) {
|
|
737
746
|
const { id, offset } = focusStateRef.current;
|
|
738
747
|
const el = refs.current[id];
|
|
@@ -743,10 +752,10 @@ function useScreenplayEditor() {
|
|
|
743
752
|
focusStateRef.current = null;
|
|
744
753
|
}
|
|
745
754
|
}, [pages]);
|
|
746
|
-
const handleBlockTextChange = useCallback((id, text) => {
|
|
755
|
+
const handleBlockTextChange = (0, import_react2.useCallback)((id, text) => {
|
|
747
756
|
setBlocks((bs) => updateBlock(bs, id, "text", text));
|
|
748
757
|
}, []);
|
|
749
|
-
const handleSceneTypeChange = useCallback(
|
|
758
|
+
const handleSceneTypeChange = (0, import_react2.useCallback)(
|
|
750
759
|
(id, sceneType) => {
|
|
751
760
|
setBlocks(
|
|
752
761
|
(bs) => updateBlock(bs, id, "sceneType", sceneType)
|
|
@@ -759,7 +768,7 @@ function useScreenplayEditor() {
|
|
|
759
768
|
},
|
|
760
769
|
[]
|
|
761
770
|
);
|
|
762
|
-
const handleTimeOfDayChange = useCallback((id, time) => {
|
|
771
|
+
const handleTimeOfDayChange = (0, import_react2.useCallback)((id, time) => {
|
|
763
772
|
setBlocks((bs) => updateBlock(bs, id, "timeOfDay", time));
|
|
764
773
|
setTimeout(() => {
|
|
765
774
|
var _a;
|
|
@@ -767,7 +776,7 @@ function useScreenplayEditor() {
|
|
|
767
776
|
setFocusedBlockId(id);
|
|
768
777
|
}, 10);
|
|
769
778
|
}, []);
|
|
770
|
-
const handleBlockTypeChange = useCallback(
|
|
779
|
+
const handleBlockTypeChange = (0, import_react2.useCallback)(
|
|
771
780
|
(newType) => {
|
|
772
781
|
if (!focusedBlockId) return;
|
|
773
782
|
setBlocks(
|
|
@@ -806,7 +815,7 @@ function useScreenplayEditor() {
|
|
|
806
815
|
return updateBlock(bs, id, "type", blockTypes[newIdx]);
|
|
807
816
|
});
|
|
808
817
|
};
|
|
809
|
-
const handleKeyDown = useCallback(
|
|
818
|
+
const handleKeyDown = (0, import_react2.useCallback)(
|
|
810
819
|
(e, id, text) => {
|
|
811
820
|
var _a;
|
|
812
821
|
if ((e.key === "Backspace" || e.key === "Delete") && text.length <= 1) {
|
|
@@ -917,14 +926,14 @@ function useScreenplayEditor() {
|
|
|
917
926
|
},
|
|
918
927
|
[blocks]
|
|
919
928
|
);
|
|
920
|
-
const handleFocus = useCallback((id) => {
|
|
929
|
+
const handleFocus = (0, import_react2.useCallback)((id) => {
|
|
921
930
|
if (blurTimeout.current) {
|
|
922
931
|
clearTimeout(blurTimeout.current);
|
|
923
932
|
}
|
|
924
933
|
setFocusedBlockId(id);
|
|
925
934
|
setShowSuggestions(true);
|
|
926
935
|
}, []);
|
|
927
|
-
const handleBlur = useCallback((id) => {
|
|
936
|
+
const handleBlur = (0, import_react2.useCallback)((id) => {
|
|
928
937
|
if (document.activeElement === refs.current[id]) return;
|
|
929
938
|
blurTimeout.current = setTimeout(() => setShowSuggestions(false), 200);
|
|
930
939
|
}, []);
|
|
@@ -948,7 +957,8 @@ function useScreenplayEditor() {
|
|
|
948
957
|
handleBlur
|
|
949
958
|
};
|
|
950
959
|
}
|
|
951
|
-
export
|
|
960
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
961
|
+
0 && (module.exports = {
|
|
952
962
|
ScreenplayEditorView,
|
|
953
963
|
blockStyles,
|
|
954
964
|
blockTypes,
|
|
@@ -956,5 +966,5 @@ export {
|
|
|
956
966
|
timeOfDayOptions,
|
|
957
967
|
useScreenplayEditor,
|
|
958
968
|
uuid
|
|
959
|
-
};
|
|
960
|
-
//# sourceMappingURL=index.
|
|
969
|
+
});
|
|
970
|
+
//# sourceMappingURL=index.cjs.map
|