@lingjingai/script-editor 0.1.16 → 0.1.17
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 +250 -34
- package/dist/index.js.map +1 -1
- package/dist/style.css +44 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1360,11 +1360,12 @@ function buildLocationDistribution(data, locationId) {
|
|
|
1360
1360
|
(episode.scenes ?? []).forEach((scene, si) => {
|
|
1361
1361
|
const inIds = (scene.location_ids ?? []).some((i) => (i ?? "").trim() === locationId);
|
|
1362
1362
|
const ctx = getSceneContext(scene);
|
|
1363
|
-
const
|
|
1364
|
-
if (inIds ||
|
|
1363
|
+
const ctxRef = (ctx.locations ?? []).find((i) => (i.location_id ?? "").trim() === locationId);
|
|
1364
|
+
if (inIds || ctxRef) {
|
|
1365
1365
|
items.push({
|
|
1366
1366
|
key: `location-${locationId}-${ei}-${si}`,
|
|
1367
|
-
...refFields(episode, ei, scene, si)
|
|
1367
|
+
...refFields(episode, ei, scene, si),
|
|
1368
|
+
stateId: ctxRef?.state_id
|
|
1368
1369
|
});
|
|
1369
1370
|
}
|
|
1370
1371
|
});
|
|
@@ -1378,13 +1379,15 @@ function buildPropDistribution(data, propId, propName) {
|
|
|
1378
1379
|
(data.episodes ?? []).forEach((episode, ei) => {
|
|
1379
1380
|
(episode.scenes ?? []).forEach((scene, si) => {
|
|
1380
1381
|
const ctx = getSceneContext(scene);
|
|
1381
|
-
const
|
|
1382
|
+
const ctxRef = (ctx.props ?? []).find((i) => (i.prop_id ?? "").trim() === id);
|
|
1383
|
+
const byRef = !!ctxRef;
|
|
1382
1384
|
const byId = !byRef && id ? (scene.actions ?? []).some((i) => (i.content ?? "").includes(id)) : false;
|
|
1383
1385
|
const byName = !byRef && !byId && needle ? (scene.actions ?? []).some((i) => (i.content ?? "").toLowerCase().includes(needle)) : false;
|
|
1384
1386
|
if (byRef || byId || byName) {
|
|
1385
1387
|
items.push({
|
|
1386
1388
|
key: `prop-${id || needle}-${ei}-${si}`,
|
|
1387
|
-
...refFields(episode, ei, scene, si)
|
|
1389
|
+
...refFields(episode, ei, scene, si),
|
|
1390
|
+
stateId: ctxRef?.state_id
|
|
1388
1391
|
});
|
|
1389
1392
|
}
|
|
1390
1393
|
});
|
|
@@ -2893,33 +2896,238 @@ function DeleteConfirmButton({
|
|
|
2893
2896
|
}
|
|
2894
2897
|
);
|
|
2895
2898
|
}
|
|
2896
|
-
|
|
2899
|
+
var SPACE_ZH = { interior: "\u5185", exterior: "\u5916" };
|
|
2900
|
+
var TIME_ZH = { day: "\u65E5", night: "\u591C", dawn: "\u6668", dusk: "\u66AE" };
|
|
2901
|
+
function resolveCueId(item, actorMap, speakerMap) {
|
|
2902
|
+
const actorId = item.actor_id?.trim();
|
|
2903
|
+
if (actorId) return actorId;
|
|
2904
|
+
const spkId = item.speaker_id?.trim() || item.speakers?.[0]?.speaker_id?.trim() || "";
|
|
2905
|
+
if (!spkId) return "";
|
|
2906
|
+
const spk = speakerMap.get(spkId);
|
|
2907
|
+
const kind = spk?.source_kind?.trim();
|
|
2908
|
+
if ((kind === "actor" || kind === "prop") && spk?.source_id?.trim()) return spk.source_id.trim();
|
|
2909
|
+
if (spkId.startsWith("spk_") && actorMap.has(spkId.slice(4))) return spkId.slice(4);
|
|
2910
|
+
return "";
|
|
2911
|
+
}
|
|
2912
|
+
function ScenePreviewCard({
|
|
2913
|
+
data,
|
|
2914
|
+
anchor,
|
|
2915
|
+
highlightId,
|
|
2916
|
+
highlightKind,
|
|
2917
|
+
onEnter,
|
|
2918
|
+
onLeave
|
|
2919
|
+
}) {
|
|
2920
|
+
const actorMap = useMemo(() => getActorMap(data.actors), [data.actors]);
|
|
2921
|
+
const locationMap = useMemo(() => getLocationMap(data.locations), [data.locations]);
|
|
2922
|
+
const speakerMap = useMemo(() => getSpeakerMap(data.speakers), [data.speakers]);
|
|
2923
|
+
const episode = data.episodes?.[anchor.episodeIndex];
|
|
2924
|
+
const scene = episode?.scenes?.[anchor.sceneIndex];
|
|
2925
|
+
if (!scene) return null;
|
|
2926
|
+
const locId = getPrimarySceneLocationId(scene);
|
|
2927
|
+
const locName = (locId ? getLocationDisplayName(locationMap.get(locId)) : "") || "\u672A\u6307\u5B9A\u5730\u70B9";
|
|
2928
|
+
const env = scene.environment ?? {};
|
|
2929
|
+
const slug = `${SPACE_ZH[env.space ?? "interior"] ?? env.space ?? ""}\xB7${TIME_ZH[env.time ?? "day"] ?? env.time ?? ""}`;
|
|
2930
|
+
const actions = scene.actions ?? [];
|
|
2931
|
+
const W = 360;
|
|
2932
|
+
const vw = typeof window !== "undefined" ? window.innerWidth : 1280;
|
|
2933
|
+
const vh = typeof window !== "undefined" ? window.innerHeight : 800;
|
|
2934
|
+
const left = Math.min(Math.max(8, anchor.rect.left + anchor.rect.width / 2 - W / 2), vw - W - 8);
|
|
2935
|
+
const above = anchor.rect.top > vh * 0.55;
|
|
2936
|
+
const pos = above ? { left, bottom: vh - anchor.rect.top + 8, maxHeight: anchor.rect.top - 16 } : { left, top: anchor.rect.bottom + 8, maxHeight: vh - anchor.rect.bottom - 16 };
|
|
2937
|
+
const card = /* @__PURE__ */ jsxs("div", { className: "lj-se-spv", style: { width: W, ...pos }, onMouseEnter: onEnter, onMouseLeave: onLeave, children: [
|
|
2938
|
+
/* @__PURE__ */ jsxs("div", { className: "lj-se-spv-head", children: [
|
|
2939
|
+
/* @__PURE__ */ jsxs("span", { className: "lj-se-spv-num", children: [
|
|
2940
|
+
getEpisodeNumberLabel(episode, anchor.episodeIndex),
|
|
2941
|
+
" \xB7 ",
|
|
2942
|
+
getSceneNumberLabel(scene, anchor.sceneIndex)
|
|
2943
|
+
] }),
|
|
2944
|
+
/* @__PURE__ */ jsxs("span", { className: "lj-se-spv-slug", children: [
|
|
2945
|
+
locName,
|
|
2946
|
+
" ",
|
|
2947
|
+
/* @__PURE__ */ jsx("span", { className: "lj-se-spv-slug-env", children: slug })
|
|
2948
|
+
] })
|
|
2949
|
+
] }),
|
|
2950
|
+
/* @__PURE__ */ jsx("div", { className: "lj-se-spv-body", children: actions.length === 0 ? /* @__PURE__ */ jsx("p", { className: "lj-se-spv-empty", children: "\uFF08\u672C\u573A\u6682\u65E0\u5185\u5BB9\uFF09" }) : actions.map((item, i) => /* @__PURE__ */ jsx(
|
|
2951
|
+
PreviewLine,
|
|
2952
|
+
{
|
|
2953
|
+
item,
|
|
2954
|
+
actorMap,
|
|
2955
|
+
speakerMap,
|
|
2956
|
+
highlightId,
|
|
2957
|
+
highlightKind
|
|
2958
|
+
},
|
|
2959
|
+
i
|
|
2960
|
+
)) })
|
|
2961
|
+
] });
|
|
2962
|
+
return createPortal(card, anchor.host ?? document.body);
|
|
2963
|
+
}
|
|
2964
|
+
function PreviewLine({
|
|
2965
|
+
item,
|
|
2966
|
+
actorMap,
|
|
2967
|
+
speakerMap,
|
|
2968
|
+
highlightId,
|
|
2969
|
+
highlightKind
|
|
2970
|
+
}) {
|
|
2971
|
+
const type = item.type ?? "dialogue" /* Dialogue */;
|
|
2972
|
+
const content = item.content?.trim() ?? "";
|
|
2973
|
+
if (type === "action" /* Action */) {
|
|
2974
|
+
return /* @__PURE__ */ jsxs("p", { className: "lj-se-spv-action", children: [
|
|
2975
|
+
/* @__PURE__ */ jsx("span", { className: "lj-se-spv-mark", children: "\u25B3" }),
|
|
2976
|
+
content || "\u2026"
|
|
2977
|
+
] });
|
|
2978
|
+
}
|
|
2979
|
+
if (type === "narration" /* Narration */) {
|
|
2980
|
+
return /* @__PURE__ */ jsx("p", { className: "lj-se-spv-narr", children: content || "\u2026" });
|
|
2981
|
+
}
|
|
2982
|
+
const isInner = type === "inner_thought" /* InnerThought */;
|
|
2983
|
+
const tone = isInner ? "inner" : "dialogue";
|
|
2984
|
+
const cueId = resolveCueId(item, actorMap, speakerMap);
|
|
2985
|
+
const speaker = getDialogueSpeakerLabel(item, actorMap, speakerMap) || "\u672A\u77E5\u89D2\u8272";
|
|
2986
|
+
const emotion = translateEmotionLabel(item.emotion);
|
|
2987
|
+
const delivery = getDialogueDeliveryLabel(item.delivery);
|
|
2988
|
+
const tag = isInner ? emotion ? `OS\xB7${emotion}` : "OS" : emotion;
|
|
2989
|
+
const mine = !!highlightId && (highlightKind === "actor" || highlightKind === "prop") && cueId === highlightId;
|
|
2990
|
+
const mineStyle = mine ? { "--mine": getActorCueVar(cueId, tone) } : void 0;
|
|
2991
|
+
return /* @__PURE__ */ jsxs("p", { className: cn("lj-se-spv-cue", isInner && "is-inner", mine && "is-mine"), style: mineStyle, children: [
|
|
2992
|
+
/* @__PURE__ */ jsxs("strong", { className: "lj-se-spv-speaker", style: { color: getActorCueVar(cueId, tone) }, children: [
|
|
2993
|
+
speaker,
|
|
2994
|
+
delivery ? /* @__PURE__ */ jsxs("span", { className: "lj-se-spv-delivery", children: [
|
|
2995
|
+
"\uFF08",
|
|
2996
|
+
delivery,
|
|
2997
|
+
"\uFF09"
|
|
2998
|
+
] }) : null
|
|
2999
|
+
] }),
|
|
3000
|
+
tag ? /* @__PURE__ */ jsxs("span", { className: "lj-se-spv-tag", children: [
|
|
3001
|
+
"\uFF08",
|
|
3002
|
+
tag,
|
|
3003
|
+
"\uFF09"
|
|
3004
|
+
] }) : null,
|
|
3005
|
+
/* @__PURE__ */ jsx("span", { className: "lj-se-spv-colon", children: "\uFF1A" }),
|
|
3006
|
+
content || "\u2026"
|
|
3007
|
+
] });
|
|
3008
|
+
}
|
|
3009
|
+
var UNASSIGNED = "__unassigned__";
|
|
3010
|
+
var CUE_COUNT = 8;
|
|
3011
|
+
var COL = 32;
|
|
3012
|
+
var MIN_EP_WIDTH = 48;
|
|
3013
|
+
function AssetStateTimeline({
|
|
3014
|
+
data,
|
|
3015
|
+
assetId,
|
|
3016
|
+
assetKind,
|
|
2897
3017
|
refs,
|
|
2898
|
-
|
|
3018
|
+
states: states2,
|
|
2899
3019
|
onJump
|
|
2900
3020
|
}) {
|
|
2901
|
-
|
|
2902
|
-
|
|
2903
|
-
|
|
2904
|
-
|
|
2905
|
-
|
|
2906
|
-
|
|
3021
|
+
const [hover, setHover] = useState(null);
|
|
3022
|
+
const closeTimer = useRef(null);
|
|
3023
|
+
const cancelClose = () => {
|
|
3024
|
+
if (closeTimer.current) {
|
|
3025
|
+
clearTimeout(closeTimer.current);
|
|
3026
|
+
closeTimer.current = null;
|
|
3027
|
+
}
|
|
3028
|
+
};
|
|
3029
|
+
const scheduleClose = () => {
|
|
3030
|
+
cancelClose();
|
|
3031
|
+
closeTimer.current = setTimeout(() => setHover(null), 140);
|
|
3032
|
+
};
|
|
3033
|
+
const cols = [];
|
|
3034
|
+
for (const group of refs) for (const item of group.items) cols.push(item);
|
|
3035
|
+
const n = cols.length;
|
|
3036
|
+
if (n === 0) return null;
|
|
3037
|
+
const definedIds = states2.map((s) => (s.state_id ?? "").trim()).filter(Boolean);
|
|
3038
|
+
const lanes = states2.map((s, i) => ({ id: (s.state_id ?? "").trim(), name: getStateDisplayName(s) || "\u672A\u547D\u540D\u72B6\u6001", cueIndex: i % CUE_COUNT + 1 })).filter((l) => l.id);
|
|
3039
|
+
const isUnassigned = (c) => {
|
|
3040
|
+
const sid = (c.stateId ?? "").trim();
|
|
3041
|
+
return !sid || !definedIds.includes(sid);
|
|
3042
|
+
};
|
|
3043
|
+
if (cols.some(isUnassigned)) {
|
|
3044
|
+
lanes.push({ id: UNASSIGNED, name: lanes.length > 0 ? "\u672A\u6807\u6CE8" : "\u51FA\u73B0", cueIndex: 0 });
|
|
3045
|
+
}
|
|
3046
|
+
const colMetas = [];
|
|
3047
|
+
const epHeads = [];
|
|
3048
|
+
let x = 0;
|
|
3049
|
+
for (const group of refs) {
|
|
3050
|
+
const count = group.items.length;
|
|
3051
|
+
const w = Math.max(COL, Math.ceil(MIN_EP_WIDTH / count));
|
|
3052
|
+
epHeads.push({ episodeIndex: group.episodeIndex, episodeNumber: group.episodeNumber, width: count * w });
|
|
3053
|
+
for (const item of group.items) {
|
|
3054
|
+
colMetas.push({ item, left: x, width: w });
|
|
3055
|
+
x += w;
|
|
3056
|
+
}
|
|
3057
|
+
}
|
|
3058
|
+
const trackWidth = x;
|
|
3059
|
+
const center = (m) => m.left + m.width / 2;
|
|
3060
|
+
const cueVar = (cueIndex) => cueIndex === 0 ? "var(--lj-se-muted-fg)" : `var(--lj-se-actor-cue-${cueIndex})`;
|
|
3061
|
+
const laneMetas = (laneId) => colMetas.filter((m) => laneId === UNASSIGNED ? isUnassigned(m.item) : (m.item.stateId ?? "").trim() === laneId);
|
|
3062
|
+
return /* @__PURE__ */ jsxs("div", { className: "lj-se-sttl", children: [
|
|
3063
|
+
/* @__PURE__ */ jsxs("div", { className: "lj-se-sttl-axis", children: [
|
|
3064
|
+
/* @__PURE__ */ jsx("span", { className: "lj-se-sttl-axis-lab", children: "\u72B6\u6001 \uFF3C \u573A" }),
|
|
3065
|
+
/* @__PURE__ */ jsx("span", { className: "lj-se-sttl-axis-eps", style: { width: trackWidth }, children: epHeads.map((g) => /* @__PURE__ */ jsxs("span", { className: "lj-se-sttl-ep", style: { width: g.width }, title: `\u7B2C ${g.episodeNumber} \u96C6`, children: [
|
|
3066
|
+
"\u7B2C",
|
|
3067
|
+
String(g.episodeNumber).padStart(2, "0"),
|
|
3068
|
+
"\u96C6"
|
|
3069
|
+
] }, g.episodeIndex)) })
|
|
2907
3070
|
] }),
|
|
2908
|
-
|
|
2909
|
-
const
|
|
2910
|
-
return /* @__PURE__ */
|
|
2911
|
-
"
|
|
2912
|
-
|
|
2913
|
-
|
|
2914
|
-
className:
|
|
2915
|
-
|
|
2916
|
-
|
|
2917
|
-
|
|
2918
|
-
|
|
2919
|
-
|
|
2920
|
-
|
|
2921
|
-
|
|
2922
|
-
|
|
3071
|
+
lanes.map((lane) => {
|
|
3072
|
+
const mine = laneMetas(lane.id);
|
|
3073
|
+
return /* @__PURE__ */ jsxs("div", { className: "lj-se-sttl-lane", children: [
|
|
3074
|
+
/* @__PURE__ */ jsxs("span", { className: "lj-se-sttl-lane-head", title: lane.name, children: [
|
|
3075
|
+
/* @__PURE__ */ jsx("span", { className: "lj-se-sttl-dot", style: { background: cueVar(lane.cueIndex) } }),
|
|
3076
|
+
/* @__PURE__ */ jsx("span", { className: "lj-se-sttl-lane-name", children: lane.name }),
|
|
3077
|
+
/* @__PURE__ */ jsx("span", { className: "lj-se-sttl-lane-count", children: mine.length })
|
|
3078
|
+
] }),
|
|
3079
|
+
/* @__PURE__ */ jsxs("span", { className: "lj-se-sttl-track", style: { width: trackWidth, "--cue": cueVar(lane.cueIndex) }, children: [
|
|
3080
|
+
colMetas.map((m, i) => /* @__PURE__ */ jsx("span", { className: "lj-se-sttl-col", style: { left: m.left } }, `col-${i}`)),
|
|
3081
|
+
mine.map((m, k) => {
|
|
3082
|
+
const next = mine[k + 1];
|
|
3083
|
+
if (!next) return null;
|
|
3084
|
+
return /* @__PURE__ */ jsx(
|
|
3085
|
+
"span",
|
|
3086
|
+
{
|
|
3087
|
+
className: "lj-se-sttl-flow",
|
|
3088
|
+
style: { left: center(m), width: center(next) - center(m) }
|
|
3089
|
+
},
|
|
3090
|
+
`flow-${m.item.key}`
|
|
3091
|
+
);
|
|
3092
|
+
}),
|
|
3093
|
+
mine.map((m) => /* @__PURE__ */ jsx(
|
|
3094
|
+
"button",
|
|
3095
|
+
{
|
|
3096
|
+
type: "button",
|
|
3097
|
+
className: "lj-se-sttl-node",
|
|
3098
|
+
style: { left: center(m) },
|
|
3099
|
+
title: m.item.label,
|
|
3100
|
+
onClick: () => onJump(m.item.episodeIndex, m.item.sceneIndex),
|
|
3101
|
+
onMouseEnter: (e) => {
|
|
3102
|
+
cancelClose();
|
|
3103
|
+
const r = e.currentTarget.getBoundingClientRect();
|
|
3104
|
+
setHover({
|
|
3105
|
+
episodeIndex: m.item.episodeIndex,
|
|
3106
|
+
sceneIndex: m.item.sceneIndex,
|
|
3107
|
+
rect: { top: r.top, bottom: r.bottom, left: r.left, width: r.width },
|
|
3108
|
+
host: e.currentTarget.closest(".lj-se-root")
|
|
3109
|
+
});
|
|
3110
|
+
},
|
|
3111
|
+
onMouseLeave: scheduleClose,
|
|
3112
|
+
children: m.item.sceneNumber
|
|
3113
|
+
},
|
|
3114
|
+
m.item.key
|
|
3115
|
+
))
|
|
3116
|
+
] })
|
|
3117
|
+
] }, lane.id);
|
|
3118
|
+
}),
|
|
3119
|
+
hover ? /* @__PURE__ */ jsx(
|
|
3120
|
+
ScenePreviewCard,
|
|
3121
|
+
{
|
|
3122
|
+
data,
|
|
3123
|
+
anchor: hover,
|
|
3124
|
+
highlightId: assetId,
|
|
3125
|
+
highlightKind: assetKind,
|
|
3126
|
+
onEnter: cancelClose,
|
|
3127
|
+
onLeave: scheduleClose
|
|
3128
|
+
}
|
|
3129
|
+
) : null
|
|
3130
|
+
] });
|
|
2923
3131
|
}
|
|
2924
3132
|
var META = {
|
|
2925
3133
|
actors: { kind: "actor" },
|
|
@@ -3051,12 +3259,20 @@ function AssetCardImpl({
|
|
|
3051
3259
|
] }, sid);
|
|
3052
3260
|
}) }) : null
|
|
3053
3261
|
] }),
|
|
3054
|
-
refs.length > 0 ?
|
|
3055
|
-
|
|
3056
|
-
|
|
3057
|
-
|
|
3058
|
-
|
|
3059
|
-
|
|
3262
|
+
refs.length > 0 ? (
|
|
3263
|
+
// state→scene reverse-lookup timeline: which state appears in which
|
|
3264
|
+
// scene, and how it flows. Stateless assets degrade to one "出现" lane.
|
|
3265
|
+
/* @__PURE__ */ jsx(
|
|
3266
|
+
AssetStateTimeline,
|
|
3267
|
+
{
|
|
3268
|
+
data,
|
|
3269
|
+
assetId,
|
|
3270
|
+
assetKind: kind,
|
|
3271
|
+
refs,
|
|
3272
|
+
states: states2,
|
|
3273
|
+
onJump: (episodeIdx, sceneIdx) => onSelect({ kind: "scene", episodeIdx, sceneIdx, from: fromRef, origin: "sidebar" })
|
|
3274
|
+
}
|
|
3275
|
+
)
|
|
3060
3276
|
) : null
|
|
3061
3277
|
] }) });
|
|
3062
3278
|
}
|