UNPKG

@adaptabletools/adaptable

Version:

Powerful AG Grid extension which provides advanced, cutting-edge functionality to meet all DataGrid requirements

226 lines (225 loc) 6.94 kB
import { eventMatchesKeyboardShortcut } from '@infinite-table/infinite-react'; const DEFAULT_INCREMENT_KEY = '+'; const DEFAULT_DECREMENT_KEY = '-'; const MODIFIER_TOKENS = new Set(['cmd', 'meta', 'ctrl', 'control', 'alt', 'shift']); const MODIFIER_ALIASES = { control: 'ctrl', meta: 'cmd' }; const KEY_ALIASES = { esc: 'escape' }; function isPlusMinusCombination(trigger) { return trigger.length > 1; } export function resolvePlusMinusTriggerKeysForNudge(nudge, globalOptions) { const incrementKey = nudge.IncrementKey?.trim() || plusMinusIncrementKeyFromOptionsOnly(globalOptions); const decrementKey = nudge.DecrementKey?.trim() || plusMinusDecrementKeyFromOptionsOnly(globalOptions); return { incrementKey, decrementKey }; } export function plusMinusResolvedKeysConflict(nudge, globalOptions) { const { incrementKey, decrementKey } = resolvePlusMinusTriggerKeysForNudge(nudge, globalOptions); const normalizedIncrement = normalizePlusMinusTrigger(incrementKey); const normalizedDecrement = normalizePlusMinusTrigger(decrementKey); if (!normalizedIncrement || !normalizedDecrement) { return false; } return normalizedIncrement === normalizedDecrement; } export function plusMinusEventMatchesTrigger(event, configuredKey) { const trigger = (configuredKey ?? '').trim(); if (!trigger) { return false; } const pressedKey = event?.key; if (!pressedKey) { return false; } if (!isPlusMinusCombination(trigger)) { return pressedKey.length === 1 && pressedKey.toLowerCase() === trigger.toLowerCase(); } return eventMatchesKeyboardShortcut({ key: pressedKey, metaKey: !!event.metaKey, altKey: !!event.altKey, ctrlKey: !!event.ctrlKey, shiftKey: !!event.shiftKey, }, trigger); } export function plusMinusIncrementKeyFromOptionsOnly(globalOptions) { return globalOptions?.incrementKey?.trim() || DEFAULT_INCREMENT_KEY; } export function plusMinusDecrementKeyFromOptionsOnly(globalOptions) { return globalOptions?.decrementKey?.trim() || DEFAULT_DECREMENT_KEY; } export function normalizePlusMinusTrigger(trigger) { const value = (trigger ?? '').trim(); if (!value) { return ''; } if (!isPlusMinusCombination(value)) { return value.toLowerCase(); } const parts = value .split('+') .map((part) => part.trim().toLowerCase()) .filter(Boolean); const modifiers = []; const keys = []; for (const part of parts) { if (MODIFIER_TOKENS.has(part)) { modifiers.push(MODIFIER_ALIASES[part] ?? part); } else { keys.push(KEY_ALIASES[part] ?? part); } } modifiers.sort(); return [...modifiers, ...keys].join('+'); } export function plusMinusTriggerSameAsBaseline(candidate, baseline) { return normalizePlusMinusTrigger(candidate) === normalizePlusMinusTrigger(baseline); } const MODIFIER_KEY_NAMES = new Set([ 'Shift', 'Control', 'Alt', 'Meta', 'OS', 'AltGraph', 'CapsLock', 'NumLock', 'ScrollLock', 'Hyper', 'Super', 'Fn', 'FnLock', 'Dead', ]); function activeModifierTokens(event) { const tokens = []; if (event.ctrlKey) { tokens.push('ctrl'); } if (event.altKey) { tokens.push('alt'); } if (event.metaKey) { tokens.push('cmd'); } if (event.shiftKey) { tokens.push('shift'); } return tokens; } export function capturePlusMinusTriggerFromEvent(event) { const key = event?.key; const modifiers = activeModifierTokens(event); if (!key || MODIFIER_KEY_NAMES.has(key)) { return { kind: 'pending', modifiers }; } const isPrintable = key.length === 1; const keyPart = isPrintable ? key.toLowerCase() : key; if (!modifiers.length) { return { kind: 'captured', trigger: keyPart }; } const shiftOnly = modifiers.length === 1 && modifiers[0] === 'shift'; const isLetter = isPrintable && /^[a-z]$/.test(keyPart); if (isPrintable && shiftOnly && !isLetter) { return { kind: 'captured', trigger: keyPart }; } if (keyPart.includes('+')) { return { kind: 'invalid', reason: 'This key cannot be combined with modifiers.' }; } return { kind: 'captured', trigger: [...modifiers, keyPart].join('+') }; } const KEY_DISPLAY_LABELS = { ctrl: 'Ctrl', cmd: 'Cmd', alt: 'Alt', shift: 'Shift', enter: 'Enter', escape: 'Esc', esc: 'Esc', tab: 'Tab', space: 'Space', backspace: 'Backspace', delete: 'Delete', insert: 'Insert', arrowup: '↑', arrowdown: '↓', arrowleft: '←', arrowright: '→', pageup: 'Page Up', pagedown: 'Page Down', home: 'Home', end: 'End', }; export function plusMinusKeyLabel(token) { const value = (token ?? '').trim(); if (!value) { return ''; } const lower = value.toLowerCase(); if (KEY_DISPLAY_LABELS[lower]) { return KEY_DISPLAY_LABELS[lower]; } if (value.length === 1) { return value; } return value.charAt(0).toUpperCase() + value.slice(1); } export function plusMinusTriggerDisplayParts(trigger) { const value = (trigger ?? '').trim(); if (!value) { return []; } if (!isPlusMinusCombination(value)) { return [plusMinusKeyLabel(value)]; } return value .split('+') .map((part) => part.trim()) .filter(Boolean) .map(plusMinusKeyLabel); } function addConfiguredKeyToLookup(lookup, configuredKey) { const trigger = (configuredKey ?? '').trim(); if (!trigger) { return; } if (!isPlusMinusCombination(trigger)) { lookup.effectiveKeysLower.add(trigger.toLowerCase()); return; } const parts = trigger .split('+') .map((part) => part.trim().toLowerCase()) .filter(Boolean); for (const part of parts) { if (MODIFIER_TOKENS.has(part)) { continue; } if (part === '*') { lookup.matchAnyKey = true; continue; } lookup.effectiveKeysLower.add(KEY_ALIASES[part] ?? part); } } export function buildPlusMinusTriggerKeyLookup(nudges, globalOptions) { const lookup = { effectiveKeysLower: new Set(), matchAnyKey: false, }; for (const nudge of nudges) { const { incrementKey, decrementKey } = resolvePlusMinusTriggerKeysForNudge(nudge, globalOptions); addConfiguredKeyToLookup(lookup, incrementKey); addConfiguredKeyToLookup(lookup, decrementKey); } return lookup; } export function plusMinusKeyCouldTrigger(keyEventString, lookup) { if (lookup.matchAnyKey) { return true; } if (!keyEventString) { return false; } return lookup.effectiveKeysLower.has(keyEventString.toLowerCase()); }