@signalsandsorcery/plugin-sdk 2.25.1 → 2.26.1

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 CHANGED
@@ -2465,6 +2465,8 @@ function parseCrossfadePairs(sceneData) {
2465
2465
  sliderPos: g.origin.meta.sliderPos,
2466
2466
  originDbId: g.origin.dbId,
2467
2467
  targetDbId: g.target.dbId,
2468
+ originSourceDbId: g.origin.meta.sourceTrackDbId,
2469
+ targetSourceDbId: g.target.meta.sourceTrackDbId,
2468
2470
  originSourceName: g.origin.meta.sourceName,
2469
2471
  originSoundLabel: g.origin.meta.soundLabel,
2470
2472
  targetSourceName: g.target.meta.sourceName,
@@ -2740,6 +2742,7 @@ function CrossfadeModal({
2740
2742
  toSceneId,
2741
2743
  fromSceneName,
2742
2744
  toSceneName,
2745
+ excludeSourceDbIds,
2743
2746
  onClose,
2744
2747
  onCreate,
2745
2748
  testIdPrefix = "crossfade-modal"
@@ -2749,6 +2752,8 @@ function CrossfadeModal({
2749
2752
  const [targetDbId, setTargetDbId] = useState8("");
2750
2753
  const [isCreating, setIsCreating] = useState8(false);
2751
2754
  const [error, setError] = useState8(null);
2755
+ const [fromName, setFromName] = useState8(null);
2756
+ const [toName, setToName] = useState8(null);
2752
2757
  const cancelRef = useRef7(null);
2753
2758
  const refresh = useCallback5(async () => {
2754
2759
  if (!host.listSceneFamilyTracks) {
@@ -2757,12 +2762,15 @@ function CrossfadeModal({
2757
2762
  }
2758
2763
  setLoad({ status: "loading" });
2759
2764
  try {
2760
- const [origin, target] = await Promise.all([
2765
+ const [origin, target, fName, tName] = await Promise.all([
2761
2766
  host.listSceneFamilyTracks(fromSceneId),
2762
- host.listSceneFamilyTracks(toSceneId)
2767
+ host.listSceneFamilyTracks(toSceneId),
2768
+ host.getSceneName ? host.getSceneName(fromSceneId) : Promise.resolve(null),
2769
+ host.getSceneName ? host.getSceneName(toSceneId) : Promise.resolve(null)
2763
2770
  ]);
2771
+ setFromName(fName);
2772
+ setToName(tName);
2764
2773
  setLoad({ status: "ready", origin, target });
2765
- setOriginDbId(origin[0]?.dbId ?? "");
2766
2774
  } catch (err) {
2767
2775
  setLoad({ status: "error", message: err instanceof Error ? err.message : "Failed to load tracks." });
2768
2776
  }
@@ -2776,21 +2784,26 @@ function CrossfadeModal({
2776
2784
  void refresh();
2777
2785
  }
2778
2786
  }, [open, refresh]);
2779
- const originTrack = useMemo3(
2780
- () => load.status === "ready" ? load.origin.find((t) => t.dbId === originDbId) ?? null : null,
2781
- [load, originDbId]
2787
+ const excludeSet = useMemo3(() => new Set(excludeSourceDbIds ?? []), [excludeSourceDbIds]);
2788
+ const originCandidates = useMemo3(
2789
+ () => load.status === "ready" ? load.origin.filter((t) => !excludeSet.has(t.dbId)) : [],
2790
+ [load, excludeSet]
2782
2791
  );
2783
- const originRole = originTrack?.role;
2784
- const targetCandidates = useMemo3(() => {
2785
- if (load.status !== "ready") return [];
2786
- if (!originRole) return load.target;
2787
- return load.target.filter((t) => t.role === originRole);
2788
- }, [load, originRole]);
2792
+ const targetCandidates = useMemo3(
2793
+ () => load.status === "ready" ? load.target.filter((t) => !excludeSet.has(t.dbId)) : [],
2794
+ [load, excludeSet]
2795
+ );
2796
+ useEffect7(() => {
2797
+ if (!originCandidates.some((t) => t.dbId === originDbId)) {
2798
+ setOriginDbId(originCandidates[0]?.dbId ?? "");
2799
+ }
2800
+ }, [originCandidates, originDbId]);
2789
2801
  useEffect7(() => {
2790
2802
  if (!targetCandidates.some((t) => t.dbId === targetDbId)) {
2791
2803
  setTargetDbId(targetCandidates[0]?.dbId ?? "");
2792
2804
  }
2793
2805
  }, [targetCandidates, targetDbId]);
2806
+ const originTrack = originCandidates.find((t) => t.dbId === originDbId) ?? null;
2794
2807
  const targetTrack = targetCandidates.find((t) => t.dbId === targetDbId) ?? null;
2795
2808
  const canCreate = !isCreating && !!originTrack && !!targetTrack;
2796
2809
  const handleClose = useCallback5(() => {
@@ -2811,6 +2824,8 @@ function CrossfadeModal({
2811
2824
  setIsCreating(false);
2812
2825
  }
2813
2826
  }, [originTrack, targetTrack, onCreate, onClose]);
2827
+ const fromLabel = fromName ?? fromSceneName ?? null;
2828
+ const toLabel = toName ?? toSceneName ?? null;
2814
2829
  if (!open) return null;
2815
2830
  return /* @__PURE__ */ jsx14(Modal, { open, onClose: handleClose, testIdPrefix, initialFocusRef: cancelRef, children: /* @__PURE__ */ jsxs10(
2816
2831
  "div",
@@ -2823,24 +2838,31 @@ function CrossfadeModal({
2823
2838
  /* @__PURE__ */ jsxs10("p", { className: "text-[11px] text-sas-muted leading-relaxed", children: [
2824
2839
  "Bridge a track from",
2825
2840
  " ",
2826
- /* @__PURE__ */ jsx14("span", { className: "text-sas-text", children: fromSceneName ?? "the origin scene" }),
2841
+ /* @__PURE__ */ jsx14("span", { className: "text-sas-text", children: fromLabel ?? "the origin scene" }),
2827
2842
  " into one from",
2828
2843
  " ",
2829
- /* @__PURE__ */ jsx14("span", { className: "text-sas-text", children: toSceneName ?? "the target scene" }),
2844
+ /* @__PURE__ */ jsx14("span", { className: "text-sas-text", children: toLabel ?? "the target scene" }),
2830
2845
  ". Both layers share one generated part; each keeps its own preset."
2831
2846
  ] }),
2832
2847
  load.status === "loading" && /* @__PURE__ */ jsx14("div", { className: "text-xs text-sas-muted py-4 text-center", children: "Loading tracks\u2026" }),
2833
2848
  load.status === "error" && /* @__PURE__ */ jsx14("div", { className: "text-xs text-sas-danger py-4 text-center", children: load.message }),
2834
- load.status === "ready" && (load.origin.length === 0 ? /* @__PURE__ */ jsx14(
2849
+ load.status === "ready" && (originCandidates.length === 0 ? /* @__PURE__ */ jsxs10(
2835
2850
  "div",
2836
2851
  {
2837
2852
  className: "text-xs text-sas-muted py-4 text-center",
2838
2853
  "data-testid": `${testIdPrefix}-empty-origin`,
2839
- children: "No matching tracks in the origin scene. Add one there first."
2854
+ children: [
2855
+ "No available tracks in ",
2856
+ fromLabel ?? "the origin scene",
2857
+ ". Add one (or free one from another crossfade) first."
2858
+ ]
2840
2859
  }
2841
2860
  ) : /* @__PURE__ */ jsxs10(Fragment3, { children: [
2842
2861
  /* @__PURE__ */ jsxs10("label", { className: "block", children: [
2843
- /* @__PURE__ */ jsx14("span", { className: "text-[10px] uppercase tracking-wide text-sas-muted", children: "Origin (top)" }),
2862
+ /* @__PURE__ */ jsxs10("span", { className: "text-[10px] uppercase tracking-wide text-sas-muted", children: [
2863
+ "Origin ",
2864
+ fromLabel ? `(${fromLabel})` : "(top)"
2865
+ ] }),
2844
2866
  /* @__PURE__ */ jsx14(
2845
2867
  "select",
2846
2868
  {
@@ -2849,7 +2871,7 @@ function CrossfadeModal({
2849
2871
  onChange: (e) => setOriginDbId(e.target.value),
2850
2872
  disabled: isCreating,
2851
2873
  className: "sas-input w-full mt-0.5 text-xs",
2852
- children: load.origin.map((t) => /* @__PURE__ */ jsxs10("option", { value: t.dbId, children: [
2874
+ children: originCandidates.map((t) => /* @__PURE__ */ jsxs10("option", { value: t.dbId, children: [
2853
2875
  t.name,
2854
2876
  t.role ? ` \xB7 ${t.role}` : ""
2855
2877
  ] }, t.dbId))
@@ -2858,13 +2880,13 @@ function CrossfadeModal({
2858
2880
  ] }),
2859
2881
  /* @__PURE__ */ jsxs10("label", { className: "block", children: [
2860
2882
  /* @__PURE__ */ jsxs10("span", { className: "text-[10px] uppercase tracking-wide text-sas-muted", children: [
2861
- "Target (bottom)",
2862
- originRole ? ` \xB7 ${originRole}` : ""
2883
+ "Target ",
2884
+ toLabel ? `(${toLabel})` : "(bottom)"
2863
2885
  ] }),
2864
2886
  targetCandidates.length === 0 ? /* @__PURE__ */ jsxs10("div", { className: "text-xs text-sas-danger mt-0.5", "data-testid": `${testIdPrefix}-empty-target`, children: [
2865
- "No ",
2866
- originRole ?? "matching",
2867
- " track in the target scene to crossfade into."
2887
+ "No available tracks in ",
2888
+ toLabel ?? "the target scene",
2889
+ " to crossfade into."
2868
2890
  ] }) : /* @__PURE__ */ jsx14(
2869
2891
  "select",
2870
2892
  {
@@ -3783,7 +3805,7 @@ function useTrackReorder({
3783
3805
  }
3784
3806
 
3785
3807
  // src/constants/sdk-version.ts
3786
- var PLUGIN_SDK_VERSION = "2.25.0";
3808
+ var PLUGIN_SDK_VERSION = "2.26.0";
3787
3809
 
3788
3810
  // src/utils/format-concurrent-tracks.ts
3789
3811
  function formatConcurrentTracks(ctx) {