@lingjingai/script-editor 0.1.20 → 0.1.22
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.d.ts +10 -1
- package/dist/index.js +434 -135
- package/dist/index.js.map +1 -1
- package/dist/style.css +26 -3
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { createContext, memo, useState, useMemo, useCallback, Fragment, useRef, useContext, useEffect, useLayoutEffect, useDeferredValue } from 'react';
|
|
2
|
-
import { Plus, Trash2, X, Check,
|
|
2
|
+
import { Plus, Trash2, X, Check, ArrowUp, ArrowDown, GripVertical, MessageCircle, Film, Brain, BookOpen, Eraser, Scissors, ArrowUpToLine, BookText, ChevronRight, FileText, Users, MapPin, Package, Undo2, Redo2, MessageSquareQuote, ArrowLeft, ChevronLeft, Search, Loader2, AlertCircle } from 'lucide-react';
|
|
3
3
|
import { jsxs, jsx, Fragment as Fragment$1 } from 'react/jsx-runtime';
|
|
4
4
|
import { Virtuoso } from 'react-virtuoso';
|
|
5
5
|
import { createPortal } from 'react-dom';
|
|
@@ -1087,33 +1087,108 @@ function updateSceneField(data, episodeIndex, sceneIndex, field, value) {
|
|
|
1087
1087
|
});
|
|
1088
1088
|
});
|
|
1089
1089
|
}
|
|
1090
|
-
function
|
|
1090
|
+
function updateSceneActorRefState(scene, actorId, stateId) {
|
|
1091
|
+
const context = getSceneContext(scene);
|
|
1092
|
+
let matched = false;
|
|
1093
|
+
let changed = false;
|
|
1094
|
+
const actors = (context.actors ?? []).map((item) => {
|
|
1095
|
+
if ((item.actor_id ?? "").trim() !== actorId) return item;
|
|
1096
|
+
matched = true;
|
|
1097
|
+
if ((item.state_id ?? null) === stateId) return item;
|
|
1098
|
+
changed = true;
|
|
1099
|
+
return { ...item, state_id: stateId };
|
|
1100
|
+
});
|
|
1101
|
+
if (!matched) {
|
|
1102
|
+
changed = true;
|
|
1103
|
+
actors.push({ actor_id: actorId, state_id: stateId });
|
|
1104
|
+
}
|
|
1105
|
+
return changed ? setSceneContext(scene, { actors }) : scene;
|
|
1106
|
+
}
|
|
1107
|
+
function updateSceneLocationRefState(scene, locationId, stateId) {
|
|
1108
|
+
const context = getSceneContext(scene);
|
|
1109
|
+
let matched = false;
|
|
1110
|
+
let changed = false;
|
|
1111
|
+
const locations = (context.locations ?? []).map((item) => {
|
|
1112
|
+
if ((item.location_id ?? "").trim() !== locationId) return item;
|
|
1113
|
+
matched = true;
|
|
1114
|
+
if ((item.state_id ?? null) === stateId) return item;
|
|
1115
|
+
changed = true;
|
|
1116
|
+
return { ...item, state_id: stateId };
|
|
1117
|
+
});
|
|
1118
|
+
if (!matched) {
|
|
1119
|
+
changed = true;
|
|
1120
|
+
locations.push({ location_id: locationId, state_id: stateId });
|
|
1121
|
+
}
|
|
1122
|
+
return changed ? setSceneContext(scene, { locations }) : scene;
|
|
1123
|
+
}
|
|
1124
|
+
function updateScenePropRefState(scene, propId, stateId) {
|
|
1125
|
+
const context = getSceneContext(scene);
|
|
1126
|
+
let matched = false;
|
|
1127
|
+
let changed = false;
|
|
1128
|
+
const props = (context.props ?? []).map((item) => {
|
|
1129
|
+
if ((item.prop_id ?? "").trim() !== propId) return item;
|
|
1130
|
+
matched = true;
|
|
1131
|
+
if ((item.state_id ?? null) === stateId) return item;
|
|
1132
|
+
changed = true;
|
|
1133
|
+
return { ...item, state_id: stateId };
|
|
1134
|
+
});
|
|
1135
|
+
if (!matched) {
|
|
1136
|
+
changed = true;
|
|
1137
|
+
props.push({ prop_id: propId, state_id: stateId });
|
|
1138
|
+
}
|
|
1139
|
+
return changed ? setSceneContext(scene, { props }) : scene;
|
|
1140
|
+
}
|
|
1141
|
+
function updateSceneAssetRefState(data, episodeIndex, sceneIndex, kind, targetId, stateId) {
|
|
1091
1142
|
const normalizedTarget = targetId.trim();
|
|
1092
1143
|
const normalizedState = stateId?.trim() || null;
|
|
1093
1144
|
if (!normalizedTarget) return data;
|
|
1094
1145
|
return withSceneUpdated(data, episodeIndex, sceneIndex, (scene) => {
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
const next = list.map((item) => {
|
|
1099
|
-
if ((item[idKey] || "").toString().trim() !== normalizedTarget) return item;
|
|
1100
|
-
matched = true;
|
|
1101
|
-
return { ...item, state_id: normalizedState };
|
|
1102
|
-
});
|
|
1103
|
-
if (!matched) {
|
|
1104
|
-
next.push({ [idKey]: normalizedTarget, state_id: normalizedState });
|
|
1105
|
-
}
|
|
1106
|
-
return setSceneContext(scene, { [field]: next });
|
|
1146
|
+
if (kind === "actor") return updateSceneActorRefState(scene, normalizedTarget, normalizedState);
|
|
1147
|
+
if (kind === "location") return updateSceneLocationRefState(scene, normalizedTarget, normalizedState);
|
|
1148
|
+
return updateScenePropRefState(scene, normalizedTarget, normalizedState);
|
|
1107
1149
|
});
|
|
1108
1150
|
}
|
|
1109
1151
|
function updateSceneActorState(data, episodeIndex, sceneIndex, actorId, stateId) {
|
|
1110
|
-
return updateSceneAssetRefState(data, episodeIndex, sceneIndex, "
|
|
1152
|
+
return updateSceneAssetRefState(data, episodeIndex, sceneIndex, "actor", actorId, stateId);
|
|
1111
1153
|
}
|
|
1112
1154
|
function updateSceneLocationState(data, episodeIndex, sceneIndex, locationId, stateId) {
|
|
1113
|
-
return updateSceneAssetRefState(data, episodeIndex, sceneIndex, "
|
|
1155
|
+
return updateSceneAssetRefState(data, episodeIndex, sceneIndex, "location", locationId, stateId);
|
|
1114
1156
|
}
|
|
1115
1157
|
function updateScenePropState(data, episodeIndex, sceneIndex, propId, stateId) {
|
|
1116
|
-
return updateSceneAssetRefState(data, episodeIndex, sceneIndex, "
|
|
1158
|
+
return updateSceneAssetRefState(data, episodeIndex, sceneIndex, "prop", propId, stateId);
|
|
1159
|
+
}
|
|
1160
|
+
function updateSceneAssetStateBindings(data, kind, assetId, targets, stateId) {
|
|
1161
|
+
const normalizedAssetId = assetId.trim();
|
|
1162
|
+
if (!normalizedAssetId || targets.length === 0) return data;
|
|
1163
|
+
const normalizedState = stateId?.trim() || null;
|
|
1164
|
+
const byEpisode = /* @__PURE__ */ new Map();
|
|
1165
|
+
for (const target of targets) {
|
|
1166
|
+
if (target.episodeIndex < 0 || target.sceneIndex < 0) continue;
|
|
1167
|
+
let scenes = byEpisode.get(target.episodeIndex);
|
|
1168
|
+
if (!scenes) {
|
|
1169
|
+
scenes = /* @__PURE__ */ new Set();
|
|
1170
|
+
byEpisode.set(target.episodeIndex, scenes);
|
|
1171
|
+
}
|
|
1172
|
+
scenes.add(target.sceneIndex);
|
|
1173
|
+
}
|
|
1174
|
+
if (byEpisode.size === 0) return data;
|
|
1175
|
+
let changed = false;
|
|
1176
|
+
const episodes = (data.episodes ?? []).map((episode, episodeIndex) => {
|
|
1177
|
+
const sceneIndexes = byEpisode.get(episodeIndex);
|
|
1178
|
+
if (!sceneIndexes) return episode;
|
|
1179
|
+
let episodeChanged = false;
|
|
1180
|
+
const scenes = episode.scenes?.map((scene, sceneIndex) => {
|
|
1181
|
+
if (!sceneIndexes.has(sceneIndex)) return scene;
|
|
1182
|
+
const nextScene = kind === "actor" ? updateSceneActorRefState(scene, normalizedAssetId, normalizedState) : kind === "location" ? updateSceneLocationRefState(scene, normalizedAssetId, normalizedState) : updateScenePropRefState(scene, normalizedAssetId, normalizedState);
|
|
1183
|
+
if (nextScene !== scene) {
|
|
1184
|
+
episodeChanged = true;
|
|
1185
|
+
changed = true;
|
|
1186
|
+
}
|
|
1187
|
+
return nextScene;
|
|
1188
|
+
});
|
|
1189
|
+
return scenes && episodeChanged ? { ...episode, scenes } : episode;
|
|
1190
|
+
});
|
|
1191
|
+
return changed ? { ...data, episodes } : data;
|
|
1117
1192
|
}
|
|
1118
1193
|
function updateSceneItemContent(data, episodeIndex, sceneIndex, itemIndex, content) {
|
|
1119
1194
|
return withSceneUpdated(data, episodeIndex, sceneIndex, (scene) => {
|
|
@@ -2782,56 +2857,6 @@ function removeEntityState(data, kind, id, stateId) {
|
|
|
2782
2857
|
states: (e.states ?? []).filter((s) => (s.state_id ?? "").trim() !== stateId)
|
|
2783
2858
|
}));
|
|
2784
2859
|
}
|
|
2785
|
-
var CONFIRM_TTL_MS = 2500;
|
|
2786
|
-
function DeleteConfirmButton({
|
|
2787
|
-
onConfirm,
|
|
2788
|
-
disabled,
|
|
2789
|
-
targetScope,
|
|
2790
|
-
title = "\u5220\u9664\uFF1F"
|
|
2791
|
-
}) {
|
|
2792
|
-
const [confirming, setConfirming] = useState(false);
|
|
2793
|
-
const timerRef = useRef(null);
|
|
2794
|
-
useEffect(
|
|
2795
|
-
() => () => {
|
|
2796
|
-
if (timerRef.current) clearTimeout(timerRef.current);
|
|
2797
|
-
},
|
|
2798
|
-
[]
|
|
2799
|
-
);
|
|
2800
|
-
const cancel = () => {
|
|
2801
|
-
if (timerRef.current) {
|
|
2802
|
-
clearTimeout(timerRef.current);
|
|
2803
|
-
timerRef.current = null;
|
|
2804
|
-
}
|
|
2805
|
-
setConfirming(false);
|
|
2806
|
-
};
|
|
2807
|
-
const handleClick = () => {
|
|
2808
|
-
if (confirming) {
|
|
2809
|
-
cancel();
|
|
2810
|
-
void onConfirm();
|
|
2811
|
-
return;
|
|
2812
|
-
}
|
|
2813
|
-
setConfirming(true);
|
|
2814
|
-
if (timerRef.current) clearTimeout(timerRef.current);
|
|
2815
|
-
timerRef.current = setTimeout(() => {
|
|
2816
|
-
setConfirming(false);
|
|
2817
|
-
timerRef.current = null;
|
|
2818
|
-
}, CONFIRM_TTL_MS);
|
|
2819
|
-
};
|
|
2820
|
-
return /* @__PURE__ */ jsx(
|
|
2821
|
-
"button",
|
|
2822
|
-
{
|
|
2823
|
-
type: "button",
|
|
2824
|
-
disabled,
|
|
2825
|
-
"data-delete-target": targetScope,
|
|
2826
|
-
"data-confirming": confirming || void 0,
|
|
2827
|
-
onClick: handleClick,
|
|
2828
|
-
"aria-label": confirming ? `\u518D\u70B9\u4E00\u6B21\u786E\u8BA4\uFF1A${title}` : title,
|
|
2829
|
-
title: confirming ? "\u518D\u70B9\u4E00\u6B21\u786E\u8BA4\uFF082.5 \u79D2\u540E\u81EA\u52A8\u53D6\u6D88\uFF09" : title,
|
|
2830
|
-
className: cn("lj-se-del", confirming && "is-confirming"),
|
|
2831
|
-
children: confirming ? /* @__PURE__ */ jsx(Check, { className: "lj-se-icon", strokeWidth: 2.2 }) : /* @__PURE__ */ jsx(Eraser, { className: "lj-se-icon", strokeWidth: 1.5 })
|
|
2832
|
-
}
|
|
2833
|
-
);
|
|
2834
|
-
}
|
|
2835
2860
|
var SPACE_ZH = { interior: "\u5185", exterior: "\u5916" };
|
|
2836
2861
|
var TIME_ZH = { day: "\u65E5", night: "\u591C", dawn: "\u6668", dusk: "\u66AE" };
|
|
2837
2862
|
function resolveCueId(item, actorMap, speakerMap) {
|
|
@@ -2943,6 +2968,7 @@ function PreviewLine({
|
|
|
2943
2968
|
] });
|
|
2944
2969
|
}
|
|
2945
2970
|
var UNASSIGNED = "__unassigned__";
|
|
2971
|
+
var DRAG_THRESHOLD = 4;
|
|
2946
2972
|
var CUE_COUNT = 8;
|
|
2947
2973
|
var COL = 32;
|
|
2948
2974
|
var MIN_EP_WIDTH = 48;
|
|
@@ -2952,9 +2978,20 @@ function AssetStateTimeline({
|
|
|
2952
2978
|
assetKind,
|
|
2953
2979
|
refs,
|
|
2954
2980
|
states: states2,
|
|
2981
|
+
disabled = false,
|
|
2982
|
+
onBind,
|
|
2955
2983
|
onJump
|
|
2956
2984
|
}) {
|
|
2957
2985
|
const [hover, setHover] = useState(null);
|
|
2986
|
+
const [selectedKeys, setSelectedKeys] = useState(() => /* @__PURE__ */ new Set());
|
|
2987
|
+
const [draggingKeys, setDraggingKeys] = useState(() => /* @__PURE__ */ new Set());
|
|
2988
|
+
const [dropLaneId, setDropLaneId] = useState(null);
|
|
2989
|
+
const [box, setBox] = useState(null);
|
|
2990
|
+
const [dragGhost, setDragGhost] = useState(null);
|
|
2991
|
+
const rootRef = useRef(null);
|
|
2992
|
+
const dragRef = useRef(null);
|
|
2993
|
+
const boxRef = useRef(null);
|
|
2994
|
+
const suppressClickRef = useRef(false);
|
|
2958
2995
|
const closeTimer = useRef(null);
|
|
2959
2996
|
const cancelClose = () => {
|
|
2960
2997
|
if (closeTimer.current) {
|
|
@@ -2966,6 +3003,7 @@ function AssetStateTimeline({
|
|
|
2966
3003
|
cancelClose();
|
|
2967
3004
|
closeTimer.current = setTimeout(() => setHover(null), 140);
|
|
2968
3005
|
};
|
|
3006
|
+
useEffect(() => () => cancelClose(), []);
|
|
2969
3007
|
const cols = [];
|
|
2970
3008
|
for (const group of refs) for (const item of group.items) cols.push(item);
|
|
2971
3009
|
const n = cols.length;
|
|
@@ -2976,10 +3014,11 @@ function AssetStateTimeline({
|
|
|
2976
3014
|
const sid = (c.stateId ?? "").trim();
|
|
2977
3015
|
return !sid || !definedIds.includes(sid);
|
|
2978
3016
|
};
|
|
2979
|
-
if (cols.some(isUnassigned)) {
|
|
3017
|
+
if (cols.some(isUnassigned) || !disabled && lanes.length > 0) {
|
|
2980
3018
|
lanes.push({ id: UNASSIGNED, name: lanes.length > 0 ? "\u672A\u6807\u6CE8" : "\u51FA\u73B0", cueIndex: 0 });
|
|
2981
3019
|
}
|
|
2982
3020
|
const colMetas = [];
|
|
3021
|
+
const itemByKey = /* @__PURE__ */ new Map();
|
|
2983
3022
|
const epHeads = [];
|
|
2984
3023
|
let x = 0;
|
|
2985
3024
|
for (const group of refs) {
|
|
@@ -2988,82 +3027,251 @@ function AssetStateTimeline({
|
|
|
2988
3027
|
epHeads.push({ episodeIndex: group.episodeIndex, episodeNumber: group.episodeNumber, width: count * w });
|
|
2989
3028
|
for (const item of group.items) {
|
|
2990
3029
|
colMetas.push({ item, left: x, width: w });
|
|
3030
|
+
itemByKey.set(item.key, item);
|
|
2991
3031
|
x += w;
|
|
2992
3032
|
}
|
|
2993
3033
|
}
|
|
2994
3034
|
const trackWidth = x;
|
|
3035
|
+
useEffect(() => {
|
|
3036
|
+
setSelectedKeys((prev) => {
|
|
3037
|
+
const next = new Set(Array.from(prev).filter((key) => itemByKey.has(key)));
|
|
3038
|
+
return next.size === prev.size ? prev : next;
|
|
3039
|
+
});
|
|
3040
|
+
}, [refs]);
|
|
2995
3041
|
const center = (m) => m.left + m.width / 2;
|
|
2996
3042
|
const cueVar = (cueIndex) => cueIndex === 0 ? "var(--lj-se-muted-fg)" : `var(--lj-se-actor-cue-${cueIndex})`;
|
|
2997
3043
|
const laneMetas = (laneId) => colMetas.filter((m) => laneId === UNASSIGNED ? isUnassigned(m.item) : (m.item.stateId ?? "").trim() === laneId);
|
|
2998
|
-
|
|
2999
|
-
|
|
3000
|
-
|
|
3001
|
-
|
|
3002
|
-
|
|
3003
|
-
|
|
3004
|
-
|
|
3005
|
-
|
|
3006
|
-
|
|
3007
|
-
|
|
3008
|
-
|
|
3009
|
-
|
|
3010
|
-
|
|
3011
|
-
|
|
3012
|
-
|
|
3013
|
-
|
|
3044
|
+
const laneIds = new Set(lanes.map((lane) => lane.id));
|
|
3045
|
+
const stateIdForLane = (laneId) => laneId === UNASSIGNED ? null : laneId;
|
|
3046
|
+
const targetsForKeys = (keys) => Array.from(keys).map((key) => itemByKey.get(key)).filter((item) => !!item).map((item) => ({ episodeIndex: item.episodeIndex, sceneIndex: item.sceneIndex }));
|
|
3047
|
+
const findLaneIdAt = (clientX, clientY) => {
|
|
3048
|
+
const lane = document.elementFromPoint(clientX, clientY)?.closest(".lj-se-sttl-lane");
|
|
3049
|
+
const laneId = lane?.dataset.sttlLaneId;
|
|
3050
|
+
return laneId && laneIds.has(laneId) ? laneId : null;
|
|
3051
|
+
};
|
|
3052
|
+
const selectKeysInBox = (nextBox) => {
|
|
3053
|
+
const left = Math.min(nextBox.startX, nextBox.currentX);
|
|
3054
|
+
const right = Math.max(nextBox.startX, nextBox.currentX);
|
|
3055
|
+
const top = Math.min(nextBox.startY, nextBox.currentY);
|
|
3056
|
+
const bottom = Math.max(nextBox.startY, nextBox.currentY);
|
|
3057
|
+
const next = /* @__PURE__ */ new Set();
|
|
3058
|
+
rootRef.current?.querySelectorAll("[data-sttl-node-key]").forEach((node) => {
|
|
3059
|
+
const r = node.getBoundingClientRect();
|
|
3060
|
+
const x2 = r.left + r.width / 2;
|
|
3061
|
+
const y = r.top + r.height / 2;
|
|
3062
|
+
if (x2 >= left && x2 <= right && y >= top && y <= bottom) {
|
|
3063
|
+
const key = node.dataset.sttlNodeKey;
|
|
3064
|
+
if (key) next.add(key);
|
|
3065
|
+
}
|
|
3066
|
+
});
|
|
3067
|
+
setSelectedKeys(next);
|
|
3068
|
+
};
|
|
3069
|
+
const boxStyle = () => {
|
|
3070
|
+
if (!box || !rootRef.current) return void 0;
|
|
3071
|
+
const r = rootRef.current.getBoundingClientRect();
|
|
3072
|
+
return {
|
|
3073
|
+
left: Math.min(box.startX, box.currentX) - r.left + rootRef.current.scrollLeft,
|
|
3074
|
+
top: Math.min(box.startY, box.currentY) - r.top + rootRef.current.scrollTop,
|
|
3075
|
+
width: Math.abs(box.currentX - box.startX),
|
|
3076
|
+
height: Math.abs(box.currentY - box.startY)
|
|
3077
|
+
};
|
|
3078
|
+
};
|
|
3079
|
+
const clearPointerState = (pointerId) => {
|
|
3080
|
+
if (rootRef.current?.hasPointerCapture(pointerId)) rootRef.current.releasePointerCapture(pointerId);
|
|
3081
|
+
dragRef.current = null;
|
|
3082
|
+
boxRef.current = null;
|
|
3083
|
+
setDraggingKeys(/* @__PURE__ */ new Set());
|
|
3084
|
+
setDropLaneId(null);
|
|
3085
|
+
setBox(null);
|
|
3086
|
+
setDragGhost(null);
|
|
3087
|
+
};
|
|
3088
|
+
const handleNodePointerDown = (e, key) => {
|
|
3089
|
+
if (disabled || e.button !== 0) return;
|
|
3090
|
+
e.stopPropagation();
|
|
3091
|
+
cancelClose();
|
|
3092
|
+
setHover(null);
|
|
3093
|
+
const keys = selectedKeys.has(key) ? new Set(selectedKeys) : /* @__PURE__ */ new Set([key]);
|
|
3094
|
+
setSelectedKeys(keys);
|
|
3095
|
+
dragRef.current = {
|
|
3096
|
+
pointerId: e.pointerId,
|
|
3097
|
+
startX: e.clientX,
|
|
3098
|
+
startY: e.clientY,
|
|
3099
|
+
keys,
|
|
3100
|
+
dragging: false
|
|
3101
|
+
};
|
|
3102
|
+
rootRef.current?.setPointerCapture(e.pointerId);
|
|
3103
|
+
};
|
|
3104
|
+
const dragLabel = (keys) => {
|
|
3105
|
+
if (keys.size !== 1) return `${keys.size} \u573A`;
|
|
3106
|
+
const item = itemByKey.get(Array.from(keys)[0]);
|
|
3107
|
+
return item ? String(item.sceneNumber) : "1 \u573A";
|
|
3108
|
+
};
|
|
3109
|
+
const handleTrackPointerDown = (e) => {
|
|
3110
|
+
if (disabled || e.button !== 0 || e.target instanceof HTMLElement && e.target.closest("[data-sttl-node-key]")) return;
|
|
3111
|
+
const next = {
|
|
3112
|
+
pointerId: e.pointerId,
|
|
3113
|
+
startX: e.clientX,
|
|
3114
|
+
startY: e.clientY,
|
|
3115
|
+
currentX: e.clientX,
|
|
3116
|
+
currentY: e.clientY,
|
|
3117
|
+
moved: false
|
|
3118
|
+
};
|
|
3119
|
+
setSelectedKeys(/* @__PURE__ */ new Set());
|
|
3120
|
+
boxRef.current = next;
|
|
3121
|
+
setBox(next);
|
|
3122
|
+
rootRef.current?.setPointerCapture(e.pointerId);
|
|
3123
|
+
};
|
|
3124
|
+
const handlePointerMove = (e) => {
|
|
3125
|
+
const drag = dragRef.current;
|
|
3126
|
+
if (drag?.pointerId === e.pointerId) {
|
|
3127
|
+
const moved2 = Math.hypot(e.clientX - drag.startX, e.clientY - drag.startY) >= DRAG_THRESHOLD;
|
|
3128
|
+
if (!drag.dragging && moved2) {
|
|
3129
|
+
drag.dragging = true;
|
|
3130
|
+
setDraggingKeys(new Set(drag.keys));
|
|
3131
|
+
}
|
|
3132
|
+
if (drag.dragging) {
|
|
3133
|
+
e.preventDefault();
|
|
3134
|
+
setDragGhost({ x: e.clientX, y: e.clientY, label: dragLabel(drag.keys) });
|
|
3135
|
+
setDropLaneId(findLaneIdAt(e.clientX, e.clientY));
|
|
3136
|
+
}
|
|
3137
|
+
return;
|
|
3138
|
+
}
|
|
3139
|
+
const nextBox = boxRef.current;
|
|
3140
|
+
if (nextBox?.pointerId !== e.pointerId) return;
|
|
3141
|
+
const moved = nextBox.moved || Math.hypot(e.clientX - nextBox.startX, e.clientY - nextBox.startY) >= DRAG_THRESHOLD;
|
|
3142
|
+
const updated = { ...nextBox, currentX: e.clientX, currentY: e.clientY, moved };
|
|
3143
|
+
boxRef.current = updated;
|
|
3144
|
+
setBox(updated);
|
|
3145
|
+
if (updated.moved) selectKeysInBox(updated);
|
|
3146
|
+
};
|
|
3147
|
+
const handlePointerUp = (e) => {
|
|
3148
|
+
const drag = dragRef.current;
|
|
3149
|
+
if (drag?.pointerId === e.pointerId) {
|
|
3150
|
+
if (drag.dragging) {
|
|
3151
|
+
const laneId = dropLaneId ?? findLaneIdAt(e.clientX, e.clientY);
|
|
3152
|
+
if (laneId) {
|
|
3153
|
+
const targets = targetsForKeys(drag.keys);
|
|
3154
|
+
if (targets.length > 0) onBind(targets, stateIdForLane(laneId));
|
|
3155
|
+
}
|
|
3156
|
+
suppressClickRef.current = true;
|
|
3157
|
+
window.setTimeout(() => {
|
|
3158
|
+
suppressClickRef.current = false;
|
|
3159
|
+
}, 0);
|
|
3160
|
+
e.preventDefault();
|
|
3161
|
+
}
|
|
3162
|
+
clearPointerState(e.pointerId);
|
|
3163
|
+
return;
|
|
3164
|
+
}
|
|
3165
|
+
const nextBox = boxRef.current;
|
|
3166
|
+
if (nextBox?.pointerId !== e.pointerId) return;
|
|
3167
|
+
if (nextBox.moved) selectKeysInBox(nextBox);
|
|
3168
|
+
else setSelectedKeys(/* @__PURE__ */ new Set());
|
|
3169
|
+
clearPointerState(e.pointerId);
|
|
3170
|
+
};
|
|
3171
|
+
return /* @__PURE__ */ jsxs(
|
|
3172
|
+
"div",
|
|
3173
|
+
{
|
|
3174
|
+
ref: rootRef,
|
|
3175
|
+
className: cn("lj-se-sttl", !disabled && "is-editable", draggingKeys.size > 0 && "is-dragging"),
|
|
3176
|
+
onPointerMove: handlePointerMove,
|
|
3177
|
+
onPointerUp: handlePointerUp,
|
|
3178
|
+
onPointerCancel: (e) => clearPointerState(e.pointerId),
|
|
3179
|
+
children: [
|
|
3180
|
+
/* @__PURE__ */ jsxs("div", { className: "lj-se-sttl-axis", children: [
|
|
3181
|
+
/* @__PURE__ */ jsx("span", { className: "lj-se-sttl-axis-lab", children: "\u72B6\u6001 \uFF3C \u573A" }),
|
|
3182
|
+
/* @__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: [
|
|
3183
|
+
"\u7B2C",
|
|
3184
|
+
String(g.episodeNumber).padStart(2, "0"),
|
|
3185
|
+
"\u96C6"
|
|
3186
|
+
] }, g.episodeIndex)) })
|
|
3014
3187
|
] }),
|
|
3015
|
-
|
|
3016
|
-
|
|
3017
|
-
|
|
3018
|
-
|
|
3019
|
-
|
|
3020
|
-
|
|
3188
|
+
lanes.map((lane) => {
|
|
3189
|
+
const mine = laneMetas(lane.id);
|
|
3190
|
+
return /* @__PURE__ */ jsxs("div", { className: cn("lj-se-sttl-lane", dropLaneId === lane.id && "is-drop"), "data-sttl-lane-id": lane.id, children: [
|
|
3191
|
+
/* @__PURE__ */ jsxs("span", { className: "lj-se-sttl-lane-head", title: lane.name, children: [
|
|
3192
|
+
/* @__PURE__ */ jsx("span", { className: "lj-se-sttl-dot", style: { background: cueVar(lane.cueIndex) } }),
|
|
3193
|
+
/* @__PURE__ */ jsx("span", { className: "lj-se-sttl-lane-name", children: lane.name }),
|
|
3194
|
+
/* @__PURE__ */ jsx("span", { className: "lj-se-sttl-lane-count", children: mine.length })
|
|
3195
|
+
] }),
|
|
3196
|
+
/* @__PURE__ */ jsxs(
|
|
3021
3197
|
"span",
|
|
3022
3198
|
{
|
|
3023
|
-
className: "lj-se-sttl-
|
|
3024
|
-
style: {
|
|
3025
|
-
|
|
3026
|
-
|
|
3027
|
-
|
|
3028
|
-
|
|
3029
|
-
|
|
3030
|
-
|
|
3031
|
-
|
|
3032
|
-
|
|
3033
|
-
|
|
3034
|
-
|
|
3035
|
-
|
|
3036
|
-
|
|
3037
|
-
|
|
3038
|
-
|
|
3039
|
-
|
|
3040
|
-
|
|
3041
|
-
|
|
3042
|
-
|
|
3043
|
-
|
|
3044
|
-
|
|
3045
|
-
|
|
3046
|
-
|
|
3047
|
-
|
|
3048
|
-
|
|
3049
|
-
|
|
3050
|
-
|
|
3051
|
-
|
|
3052
|
-
|
|
3053
|
-
|
|
3054
|
-
|
|
3055
|
-
|
|
3056
|
-
|
|
3057
|
-
|
|
3058
|
-
|
|
3059
|
-
|
|
3060
|
-
|
|
3061
|
-
|
|
3062
|
-
|
|
3063
|
-
|
|
3064
|
-
|
|
3065
|
-
|
|
3066
|
-
|
|
3199
|
+
className: "lj-se-sttl-track",
|
|
3200
|
+
style: { width: trackWidth, "--cue": cueVar(lane.cueIndex) },
|
|
3201
|
+
onPointerDown: handleTrackPointerDown,
|
|
3202
|
+
children: [
|
|
3203
|
+
colMetas.map((m, i) => /* @__PURE__ */ jsx("span", { className: "lj-se-sttl-col", style: { left: m.left } }, `col-${i}`)),
|
|
3204
|
+
mine.map((m, k) => {
|
|
3205
|
+
const next = mine[k + 1];
|
|
3206
|
+
if (!next) return null;
|
|
3207
|
+
return /* @__PURE__ */ jsx(
|
|
3208
|
+
"span",
|
|
3209
|
+
{
|
|
3210
|
+
className: "lj-se-sttl-flow",
|
|
3211
|
+
style: { left: center(m), width: center(next) - center(m) }
|
|
3212
|
+
},
|
|
3213
|
+
`flow-${m.item.key}`
|
|
3214
|
+
);
|
|
3215
|
+
}),
|
|
3216
|
+
mine.map((m) => /* @__PURE__ */ jsx(
|
|
3217
|
+
"button",
|
|
3218
|
+
{
|
|
3219
|
+
type: "button",
|
|
3220
|
+
className: cn(
|
|
3221
|
+
"lj-se-sttl-node",
|
|
3222
|
+
selectedKeys.has(m.item.key) && "is-selected",
|
|
3223
|
+
draggingKeys.has(m.item.key) && "is-dragging"
|
|
3224
|
+
),
|
|
3225
|
+
"data-sttl-node-key": m.item.key,
|
|
3226
|
+
"aria-pressed": selectedKeys.has(m.item.key),
|
|
3227
|
+
style: { left: center(m) },
|
|
3228
|
+
title: m.item.label,
|
|
3229
|
+
onPointerDown: (e) => handleNodePointerDown(e, m.item.key),
|
|
3230
|
+
onClick: (e) => {
|
|
3231
|
+
if (suppressClickRef.current) {
|
|
3232
|
+
suppressClickRef.current = false;
|
|
3233
|
+
e.preventDefault();
|
|
3234
|
+
return;
|
|
3235
|
+
}
|
|
3236
|
+
onJump(m.item.episodeIndex, m.item.sceneIndex);
|
|
3237
|
+
},
|
|
3238
|
+
onMouseEnter: (e) => {
|
|
3239
|
+
if (dragRef.current?.dragging) return;
|
|
3240
|
+
cancelClose();
|
|
3241
|
+
const r = e.currentTarget.getBoundingClientRect();
|
|
3242
|
+
setHover({
|
|
3243
|
+
episodeIndex: m.item.episodeIndex,
|
|
3244
|
+
sceneIndex: m.item.sceneIndex,
|
|
3245
|
+
rect: { top: r.top, bottom: r.bottom, left: r.left, width: r.width },
|
|
3246
|
+
host: e.currentTarget.closest(".lj-se-root")
|
|
3247
|
+
});
|
|
3248
|
+
},
|
|
3249
|
+
onMouseLeave: scheduleClose,
|
|
3250
|
+
children: m.item.sceneNumber
|
|
3251
|
+
},
|
|
3252
|
+
m.item.key
|
|
3253
|
+
))
|
|
3254
|
+
]
|
|
3255
|
+
}
|
|
3256
|
+
)
|
|
3257
|
+
] }, lane.id);
|
|
3258
|
+
}),
|
|
3259
|
+
box ? /* @__PURE__ */ jsx("span", { className: "lj-se-sttl-select-box", style: boxStyle() }) : null,
|
|
3260
|
+
dragGhost ? /* @__PURE__ */ jsx("span", { className: "lj-se-sttl-drag-ghost", style: { left: dragGhost.x, top: dragGhost.y }, children: dragGhost.label }) : null,
|
|
3261
|
+
hover ? /* @__PURE__ */ jsx(
|
|
3262
|
+
ScenePreviewCard,
|
|
3263
|
+
{
|
|
3264
|
+
data,
|
|
3265
|
+
anchor: hover,
|
|
3266
|
+
highlightId: assetId,
|
|
3267
|
+
highlightKind: assetKind,
|
|
3268
|
+
onEnter: cancelClose,
|
|
3269
|
+
onLeave: scheduleClose
|
|
3270
|
+
}
|
|
3271
|
+
) : null
|
|
3272
|
+
]
|
|
3273
|
+
}
|
|
3274
|
+
);
|
|
3067
3275
|
}
|
|
3068
3276
|
var META = {
|
|
3069
3277
|
actors: { kind: "actor" },
|
|
@@ -3073,6 +3281,38 @@ var META = {
|
|
|
3073
3281
|
function newStateId(id) {
|
|
3074
3282
|
return `st_${id}_${Date.now().toString(36)}`;
|
|
3075
3283
|
}
|
|
3284
|
+
function StateDeleteButton({ stateName, onConfirm }) {
|
|
3285
|
+
const [open, setOpen] = useState(false);
|
|
3286
|
+
return /* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
3287
|
+
/* @__PURE__ */ jsx("button", { type: "button", className: "lj-se-assetcard-state-del", title: "\u5220\u9664\u8BE5\u72B6\u6001", "aria-label": "\u5220\u9664\u8BE5\u72B6\u6001", onClick: () => setOpen(true), children: /* @__PURE__ */ jsx(X, { className: "lj-se-ic-3", strokeWidth: 1.8 }) }),
|
|
3288
|
+
open ? /* @__PURE__ */ jsx("div", { className: "lj-se-modal-backdrop", role: "presentation", onMouseDown: () => setOpen(false), children: /* @__PURE__ */ jsxs("div", { className: "lj-se-modal", role: "dialog", "aria-modal": "true", "aria-labelledby": "lj-se-delete-state-title", onMouseDown: (e) => e.stopPropagation(), children: [
|
|
3289
|
+
/* @__PURE__ */ jsxs("div", { className: "lj-se-modal-head", children: [
|
|
3290
|
+
/* @__PURE__ */ jsx("h2", { id: "lj-se-delete-state-title", className: "lj-se-modal-title", children: "\u5220\u9664\u72B6\u6001" }),
|
|
3291
|
+
/* @__PURE__ */ jsx("button", { type: "button", className: "lj-se-modal-x", "aria-label": "\u5173\u95ED", onClick: () => setOpen(false), children: /* @__PURE__ */ jsx(X, { className: "lj-se-ic-3", strokeWidth: 1.8 }) })
|
|
3292
|
+
] }),
|
|
3293
|
+
/* @__PURE__ */ jsxs("p", { className: "lj-se-modal-body", children: [
|
|
3294
|
+
"\u786E\u8BA4\u5220\u9664\u300C",
|
|
3295
|
+
stateName || "\u672A\u547D\u540D\u72B6\u6001",
|
|
3296
|
+
"\u300D\uFF1F"
|
|
3297
|
+
] }),
|
|
3298
|
+
/* @__PURE__ */ jsxs("div", { className: "lj-se-modal-actions", children: [
|
|
3299
|
+
/* @__PURE__ */ jsx("button", { type: "button", className: "lj-se-modal-btn", onClick: () => setOpen(false), children: "\u53D6\u6D88" }),
|
|
3300
|
+
/* @__PURE__ */ jsx(
|
|
3301
|
+
"button",
|
|
3302
|
+
{
|
|
3303
|
+
type: "button",
|
|
3304
|
+
className: "lj-se-modal-btn lj-se-modal-btn-danger",
|
|
3305
|
+
onClick: () => {
|
|
3306
|
+
setOpen(false);
|
|
3307
|
+
onConfirm();
|
|
3308
|
+
},
|
|
3309
|
+
children: "\u5220\u9664"
|
|
3310
|
+
}
|
|
3311
|
+
)
|
|
3312
|
+
] })
|
|
3313
|
+
] }) }) : null
|
|
3314
|
+
] });
|
|
3315
|
+
}
|
|
3076
3316
|
function AssetCardImpl({
|
|
3077
3317
|
data,
|
|
3078
3318
|
group,
|
|
@@ -3179,7 +3419,13 @@ function AssetCardImpl({
|
|
|
3179
3419
|
onSave: (v) => onEdit((p) => updateEntityStateField(p, kind, assetId, sid, "state_name", v))
|
|
3180
3420
|
}
|
|
3181
3421
|
),
|
|
3182
|
-
!disabled && (state.state_id ?? "").trim() ? /* @__PURE__ */ jsx(
|
|
3422
|
+
!disabled && (state.state_id ?? "").trim() ? /* @__PURE__ */ jsx(
|
|
3423
|
+
StateDeleteButton,
|
|
3424
|
+
{
|
|
3425
|
+
stateName: state.state_name ?? state.name ?? "",
|
|
3426
|
+
onConfirm: () => onEdit((p) => removeEntityState(p, kind, assetId, sid))
|
|
3427
|
+
}
|
|
3428
|
+
) : null
|
|
3183
3429
|
] }),
|
|
3184
3430
|
/* @__PURE__ */ jsx(
|
|
3185
3431
|
EditableText,
|
|
@@ -3206,6 +3452,8 @@ function AssetCardImpl({
|
|
|
3206
3452
|
assetKind: kind,
|
|
3207
3453
|
refs,
|
|
3208
3454
|
states: states2,
|
|
3455
|
+
disabled,
|
|
3456
|
+
onBind: (targets, stateId) => onEdit((p) => updateSceneAssetStateBindings(p, kind, assetId, targets, stateId)),
|
|
3209
3457
|
onJump: (episodeIdx, sceneIdx) => onSelect({ kind: "scene", episodeIdx, sceneIdx, from: fromRef, origin: "sidebar" })
|
|
3210
3458
|
}
|
|
3211
3459
|
)
|
|
@@ -4534,6 +4782,7 @@ __export(mutations_exports, {
|
|
|
4534
4782
|
updateEntityName: () => updateEntityName,
|
|
4535
4783
|
updateEntityStateField: () => updateEntityStateField,
|
|
4536
4784
|
updateSceneActorState: () => updateSceneActorState,
|
|
4785
|
+
updateSceneAssetStateBindings: () => updateSceneAssetStateBindings,
|
|
4537
4786
|
updateSceneField: () => updateSceneField,
|
|
4538
4787
|
updateSceneItemActor: () => updateSceneItemActor,
|
|
4539
4788
|
updateSceneItemContent: () => updateSceneItemContent,
|
|
@@ -4542,6 +4791,56 @@ __export(mutations_exports, {
|
|
|
4542
4791
|
updateSceneLocationState: () => updateSceneLocationState,
|
|
4543
4792
|
updateScenePropState: () => updateScenePropState
|
|
4544
4793
|
});
|
|
4794
|
+
var CONFIRM_TTL_MS = 2500;
|
|
4795
|
+
function DeleteConfirmButton({
|
|
4796
|
+
onConfirm,
|
|
4797
|
+
disabled,
|
|
4798
|
+
targetScope,
|
|
4799
|
+
title = "\u5220\u9664\uFF1F"
|
|
4800
|
+
}) {
|
|
4801
|
+
const [confirming, setConfirming] = useState(false);
|
|
4802
|
+
const timerRef = useRef(null);
|
|
4803
|
+
useEffect(
|
|
4804
|
+
() => () => {
|
|
4805
|
+
if (timerRef.current) clearTimeout(timerRef.current);
|
|
4806
|
+
},
|
|
4807
|
+
[]
|
|
4808
|
+
);
|
|
4809
|
+
const cancel = () => {
|
|
4810
|
+
if (timerRef.current) {
|
|
4811
|
+
clearTimeout(timerRef.current);
|
|
4812
|
+
timerRef.current = null;
|
|
4813
|
+
}
|
|
4814
|
+
setConfirming(false);
|
|
4815
|
+
};
|
|
4816
|
+
const handleClick = () => {
|
|
4817
|
+
if (confirming) {
|
|
4818
|
+
cancel();
|
|
4819
|
+
void onConfirm();
|
|
4820
|
+
return;
|
|
4821
|
+
}
|
|
4822
|
+
setConfirming(true);
|
|
4823
|
+
if (timerRef.current) clearTimeout(timerRef.current);
|
|
4824
|
+
timerRef.current = setTimeout(() => {
|
|
4825
|
+
setConfirming(false);
|
|
4826
|
+
timerRef.current = null;
|
|
4827
|
+
}, CONFIRM_TTL_MS);
|
|
4828
|
+
};
|
|
4829
|
+
return /* @__PURE__ */ jsx(
|
|
4830
|
+
"button",
|
|
4831
|
+
{
|
|
4832
|
+
type: "button",
|
|
4833
|
+
disabled,
|
|
4834
|
+
"data-delete-target": targetScope,
|
|
4835
|
+
"data-confirming": confirming || void 0,
|
|
4836
|
+
onClick: handleClick,
|
|
4837
|
+
"aria-label": confirming ? `\u518D\u70B9\u4E00\u6B21\u786E\u8BA4\uFF1A${title}` : title,
|
|
4838
|
+
title: confirming ? "\u518D\u70B9\u4E00\u6B21\u786E\u8BA4\uFF082.5 \u79D2\u540E\u81EA\u52A8\u53D6\u6D88\uFF09" : title,
|
|
4839
|
+
className: cn("lj-se-del", confirming && "is-confirming"),
|
|
4840
|
+
children: confirming ? /* @__PURE__ */ jsx(Check, { className: "lj-se-icon", strokeWidth: 2.2 }) : /* @__PURE__ */ jsx(Eraser, { className: "lj-se-icon", strokeWidth: 1.5 })
|
|
4841
|
+
}
|
|
4842
|
+
);
|
|
4843
|
+
}
|
|
4545
4844
|
|
|
4546
4845
|
export { DeleteConfirmButton, EMPTY_SELECTION, EditableText, Popover, ScriptContentType, ScriptEditor, SelectField, acceptActionIntoBaseline, acceptSceneIntoBaseline, applyActionAccept, applyActionReject, buildActionDiff, buildDiffFromBaseline, buildScriptNav, buildSelectionFrom, changeSetToDiffScenes, computeChangeSet, computeSceneActionDiff, findBaselineScene, fromToSelection, getActorCueVar, getActorMap, getEpisodeTitle, getLocationMap, getPropMap, getSceneContext, getSelectionEpisodeIdx, getSpeakerMap, isClipSelected, isEpisodeOpen, isSameSelectionTarget, isSceneSelected, mutations_exports as mutations, rejectActionToBaseline, rejectSceneToBaseline, sceneChangeKey, selectionFromScriptReference, selectionTargetKey, withOrigin };
|
|
4547
4846
|
//# sourceMappingURL=index.js.map
|