Считаем повторения символов, приведённых к нижнему регистру, также, встречая символ впервые, запоминаем индекс и оригинальный вид символа (до приведения к нижнему регистру); ищем среди результатов подсчёта повторений такой, который равен единице, и при этом имеет минимально возможный индекс; достаём из найденного оригинальный символ:
const firstNonRepeatingLetter = ([...str]) => Object
.values(str.reduce((acc, n, i) => ((acc[n.toLowerCase()] ??= [ 0, i, n ])[0]++, acc), {}))
.reduce((min, n) => (n[0] === 1 && n[1] < min[1] ? n : min), [ 0, Infinity, '' ])
.pop();
Или. Приводим строку к нижнему регистру; ищем индекс первого уникального символа, т.е. такого, у которого индекс первого вхождения в строку равен индексу последнего вхождения; по найденному индексу извлекаем из исходной строки символ:
const firstNonRepeatingLetter = str =>
str.charAt(Array
.from(str.toLowerCase())
.findIndex((n, i, a) => a.indexOf(n) === a.lastIndexOf(n))
);