@braccato/core 1.15.2 → 1.15.3

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/engine.js CHANGED
@@ -1960,7 +1960,11 @@ function stageElements(engine) {
1960
1960
  lastEnd = Math.max(lastEnd, end);
1961
1961
  elements.push(line.lyricElement);
1962
1962
  items.push({
1963
- kind: line.lyricElement.dataset.instrumental === "true" ? "instrumental" : "line",
1963
+ kind: line.lyricElement.dataset.instrumental === "true"
1964
+ ? "instrumental"
1965
+ : line.lyricElement.dataset.blank === "true"
1966
+ ? "blank"
1967
+ : "line",
1964
1968
  start: line.time,
1965
1969
  end,
1966
1970
  });
package/dist/stage.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- export type StageItemKind = "line" | "instrumental" | "credits";
1
+ export type StageItemKind = "line" | "blank" | "instrumental" | "credits";
2
2
  export type StageRole = "current" | "previous" | "queued" | "gone";
3
3
  export interface StageItem {
4
4
  kind: StageItemKind;
package/dist/stage.js CHANGED
@@ -3,7 +3,10 @@ export const STAGE_HANDOFF_S = 0.12;
3
3
  export const STAGE_OVERLAP_S = 0.15;
4
4
  export function overlapsPrevious(items, index) {
5
5
  const previous = items[index - 1];
6
- return previous !== undefined && previous.kind === "line" && items[index].start < previous.end - STAGE_OVERLAP_S;
6
+ return (previous !== undefined &&
7
+ previous.kind === "line" &&
8
+ items[index].kind !== "blank" &&
9
+ items[index].start < previous.end - STAGE_OVERLAP_S);
7
10
  }
8
11
  export function stageEnterTimes(items) {
9
12
  return items.map((item, index) => {
@@ -68,7 +71,8 @@ export function layoutStage(roles, items, metrics, previousY, geometry) {
68
71
  });
69
72
  let box = null;
70
73
  roles.forEach((role, index) => {
71
- if ((role !== "current" && role !== "previous") || items[index].kind === "instrumental")
74
+ const { kind } = items[index];
75
+ if ((role !== "current" && role !== "previous") || kind === "instrumental" || kind === "blank")
72
76
  return;
73
77
  const { height, left, width, originX } = metrics[index];
74
78
  const scale = geometry.activeScale;
package/dist/view.js CHANGED
@@ -95,6 +95,8 @@ export function setLyrics(engine, mount, lyrics, options) {
95
95
  }
96
96
  else {
97
97
  buildSungLine(doc, lyricElement, lyricItem, line);
98
+ if (!lyricItem.words?.trim())
99
+ lyricElement.dataset.blank = "true";
98
100
  }
99
101
  container.appendChild(lyricElement);
100
102
  }
@@ -108,7 +110,10 @@ export function setLyrics(engine, mount, lyrics, options) {
108
110
  container.dataset.sync = syncType;
109
111
  if (engine.layout === "stage") {
110
112
  container.dataset.layout = "stage";
111
- if (lyrics.some(item => item.agent === "v2" || item.agent === "v3")) {
113
+ // Sides only when both are sung, so a song with one singer stays centred whichever voice it is.
114
+ const sung = lyrics.filter(item => !item.isInstrumental && item.words?.trim() && item.agent !== "v1000");
115
+ const onRight = (item) => item.agent === "v2" || item.agent === "v3";
116
+ if (sung.some(onRight) && sung.some(item => !onRight(item))) {
112
117
  container.dataset.stageDuet = "";
113
118
  }
114
119
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@braccato/core",
3
- "version": "1.15.2",
3
+ "version": "1.15.3",
4
4
  "description": "Synchronized lyrics renderer with word-by-word animations",
5
5
  "type": "module",
6
6
  "license": "MIT",