src/services/focus.mjs
BeforeProposed
+14−2
11import {ContractError, id} from '../models/building.mjs';
22
33export function focusOrder(items) {
4 // Implement eligibility and tab order.
5 return items.map(item => item.id);
4 if (!Array.isArray(items) || items.length > 1000) throw new ContractError('invalid focus list');
5 const seen = new Set();
6 const normalized = items.map((item, index) => {
7 const name = id(item.id, 'control');
8 if (seen.has(name)) throw new ContractError('duplicate control');
9 seen.add(name);
10 const tabIndex = item.tabIndex ?? 0;
11 if (!Number.isInteger(tabIndex) || tabIndex < -1 || tabIndex > 32767) throw new ContractError('invalid tabIndex');
12 for (const flag of ['hidden', 'disabled', 'inert']) if (item[flag] !== undefined && typeof item[flag] !== 'boolean') throw new ContractError('invalid ' + flag);
13 return {...item, tabIndex, index};
14 });
15 return normalized.filter(item => !item.hidden && !item.disabled && !item.inert && item.tabIndex >= 0)
16 .sort((a, b) => (a.tabIndex === 0 ? Infinity : a.tabIndex) - (b.tabIndex === 0 ? Infinity : b.tabIndex) || a.index - b.index)
17 .map(item => item.id);
618}
719
820export function moveFocus(items, current, direction) {