All files / src/shared/lib/uge/editor helpers.ts

96.3% Statements 26/27
79.17% Branches 19/24
100% Functions 3/3
95.83% Lines 23/24

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69    41x                       41x           4x 4x   4x 4x   4x       4x 4x 4x   4x 3x 3x 3x     1x 1x       3x 2x     1x       41x 23x           41x           7x    
import { Pattern, PatternCell, SequenceItem } from "shared/lib/uge/types";
import { PatternCellAddress } from "./types";
import clamp from "shared/lib/helpers/clamp";
 
type SharedSelectionValue<T> =
  | { type: "none"; value: null }
  | { type: "shared"; value: T }
  | { type: "multiple"; value: null };
 
/**
 * Extracts a single value from a set of selected PatternCells using `getValue`.
 * Returns `{type:"shared"}` if all cells agree, `{type:"multiple"}` if they
 * differ, or `{type:"none"}` if no cells have a value.
 */
export const getPatternCellSelectionValue = <T>(
  sequence: SequenceItem[],
  patterns: Pattern[],
  patternCells: PatternCellAddress[],
  getValue: (cell: PatternCell) => T | null | undefined,
): SharedSelectionValue<T> => {
  let hasValue = false;
  let sharedValue: T | null | undefined = undefined;
 
  for (const { sequenceId, rowId, channelId } of patternCells) {
    const patternId = sequence[sequenceId]?.channels[channelId];
 
    Iif (patternId === undefined) {
      continue;
    }
 
    const pattern = patterns?.[patternId];
    const cell = pattern?.[rowId];
    const value = cell ? getValue(cell) : null;
 
    if (!hasValue) {
      sharedValue = value;
      hasValue = true;
      continue;
    }
 
    if (sharedValue !== value) {
      return { type: "multiple", value: null };
    }
  }
 
  if (!hasValue || sharedValue == null) {
    return { type: "none", value: null };
  }
 
  return { type: "shared", value: sharedValue };
};
 
/** Clamps `index` to the valid channel range 0–3. */
export const toValidChannelId = (index: number): 0 | 1 | 2 | 3 => {
  return clamp(index, 0, 3) as 0 | 1 | 2 | 3;
};
 
/** Check if sequence items are consecutive starting from a multiple of 4 to
 *  to determine if sequence is simple or if different patterns are set per channel
 */
export const isSplitPatternSequence = ([a, b, c, d]: [
  number,
  number,
  number,
  number,
]): boolean => {
  return a % 4 !== 0 || b !== a + 1 || c !== a + 2 || d !== a + 3;
};