@adaptabletools/adaptable
Version:
Powerful AG Grid extension which provides advanced, cutting-edge functionality to meet all DataGrid requirements
162 lines (161 loc) • 8.07 kB
JavaScript
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
import * as React from 'react';
import { cn } from '../../../lib/utils';
import { Box, Flex } from '../../../components/Flex';
import SimpleButton from '../../../components/SimpleButton';
import { capturePlusMinusTriggerFromEvent, plusMinusKeyLabel, plusMinusTriggerDisplayParts, } from '../../../Utilities/Helpers/PlusMinusHelper';
import { targetOwn } from '../../../components/twUtils';
const Kbd = ({ children }) => (_jsx(Box, { as: "kbd", className: "twa:px-2 twa:py-[2px] twa:rounded-standard twa:bg-primary twa:text-2 twa:leading-none twa:font-medium twa:whitespace-nowrap", children: children }));
const renderTokens = (tokens) => tokens.map((token, index) => (_jsxs(React.Fragment, { children: [index > 0 ? _jsx(Box, { className: "twa:opacity-50 twa:text-2", children: "+" }) : null, _jsx(Kbd, { children: token })] }, `${token}-${index}`)));
export const KeyComboCaptureInput = (props) => {
const { value, isUsingDefault, placeholder, disabled, onCapture, onReset, validateCapture } = props;
const ref = React.useRef(null);
const [focused, setFocused] = React.useState(false);
const [editing, setEditing] = React.useState(false);
const [pendingModifiers, setPendingModifiers] = React.useState([]);
const [staged, setStaged] = React.useState(undefined);
const [error, setError] = React.useState(undefined);
const stopEditing = React.useCallback(() => {
setEditing(false);
setPendingModifiers([]);
setStaged(undefined);
}, []);
const handleKeyDown = (event) => {
if (disabled) {
return;
}
if (!editing) {
if (event.key === 'Enter') {
event.preventDefault();
event.stopPropagation();
setError(undefined);
setPendingModifiers([]);
setStaged(undefined);
setEditing(true);
}
return;
}
if (event.key === 'Escape') {
event.preventDefault();
event.stopPropagation();
setError(undefined);
stopEditing();
return;
}
if (event.key === 'Tab') {
if (staged && !validateCapture?.(staged)) {
onCapture(staged);
}
stopEditing();
setError(undefined);
return;
}
event.preventDefault();
event.stopPropagation();
const noModifiers = !event.ctrlKey && !event.altKey && !event.metaKey && !event.shiftKey;
if (event.key === 'Enter' && noModifiers) {
if (!staged) {
return;
}
const validationError = validateCapture?.(staged);
if (validationError) {
setError(validationError);
return;
}
const confirmed = staged;
setError(undefined);
stopEditing();
onCapture(confirmed);
return;
}
const result = capturePlusMinusTriggerFromEvent({
key: event.key,
ctrlKey: event.ctrlKey,
altKey: event.altKey,
metaKey: event.metaKey,
shiftKey: event.shiftKey,
});
if (result.kind === 'pending') {
setPendingModifiers(result.modifiers);
setError(undefined);
return;
}
if (result.kind === 'invalid') {
setPendingModifiers([]);
setStaged(undefined);
setError(result.reason);
return;
}
const validationError = validateCapture?.(result.trigger);
if (validationError) {
setPendingModifiers([]);
setStaged(undefined);
setError(validationError);
return;
}
setPendingModifiers([]);
setError(undefined);
setStaged(result.trigger);
};
const handleReset = (event) => {
event.preventDefault();
event.stopPropagation();
setError(undefined);
stopEditing();
onReset?.();
};
const handleEnterEdit = (event) => {
event.preventDefault();
event.stopPropagation();
setError(undefined);
setPendingModifiers([]);
setStaged(undefined);
setEditing(true);
ref.current?.focus();
};
const valueParts = plusMinusTriggerDisplayParts(value);
let content;
if (editing) {
if (staged) {
content = (_jsx(Flex, { className: "twa:items-center twa:gap-1", children: renderTokens(plusMinusTriggerDisplayParts(staged)) }));
}
else if (pendingModifiers.length) {
content = (_jsxs(Flex, { className: "twa:items-center twa:gap-1", children: [renderTokens(pendingModifiers.map(plusMinusKeyLabel)), _jsx(Box, { className: "twa:opacity-50 twa:text-2", children: "+ \u2026" })] }));
}
else {
content = _jsx(Box, { className: "twa:opacity-60 twa:text-2", children: "Press a key combination\u2026" });
}
}
else if (valueParts.length) {
content = (_jsxs(Flex, { className: "twa:items-center twa:gap-1", children: [renderTokens(valueParts), isUsingDefault ? (_jsx(Box, { className: "twa:opacity-60 twa:text-2 twa:ml-1", children: "(default)" })) : null] }));
}
else {
content = _jsx(Box, { className: "twa:opacity-60 twa:text-2", children: placeholder ?? 'Hit Enter to edit' });
}
return (_jsxs(Flex, { flexDirection: "column", className: "twa:gap-1 twa:max-w-[300px] twa:w-full", children: [_jsxs(Flex, { ref: ref, role: "button", tabIndex: disabled ? -1 : 0, "data-name": props['data-name'], "aria-label": "Record keyboard shortcut", onFocus: () => {
if (!disabled) {
setFocused(true);
}
}, onBlur: (event) => {
if (ref.current && event.relatedTarget && ref.current.contains(event.relatedTarget)) {
return;
}
if (editing && staged && !validateCapture?.(staged)) {
onCapture(staged);
}
setFocused(false);
stopEditing();
setError(undefined);
}, onClick: () => ref.current?.focus(), onKeyDown: handleKeyDown, className: cn('twa:min-h-input twa:rounded-input twa:px-2 twa:items-center twa:gap-2 twa:w-full', 'twa:border-input twa:border', targetOwn.focusWithinOutline, disabled
? 'twa:opacity-60 twa:cursor-not-allowed'
: 'twa:cursor-pointer twa:bg-input-background', editing ? 'twa:border-accent' : '', error ? 'twa:border-destructive' : ''), children: [_jsx(Flex, { className: "twa:flex-1 twa:flex-wrap twa:items-center twa:gap-1 twa:py-1", children: content }), !disabled && !editing ? (onReset && !isUsingDefault ? (_jsx(SimpleButton, { variant: "text", icon: "undo", tooltip: "Revert to default", "data-name": "plus-minus-reset-key", tabIndex: -1, onMouseDown: handleReset, onKeyDown: (event) => {
if (event.key === 'Enter') {
handleReset(event);
ref.current?.focus();
}
} })) : (_jsx(SimpleButton, { variant: "text", icon: "edit", tooltip: "Edit keyboard shortcut", "data-name": "plus-minus-edit-key", tabIndex: -1, onMouseDown: handleEnterEdit, onKeyDown: (event) => {
if (event.key === 'Enter') {
handleEnterEdit(event);
}
} }))) : null] }), _jsx(Box, { "data-name": error ? 'key-capture-error' : 'key-capture-hint', className: cn('twa:text-2', error ? 'twa:text-destructive' : 'twa:opacity-60', !focused && !error ? 'twa:invisible' : ''), children: error ? error : editing ? 'ENTER to confirm, ESCAPE to cancel' : 'Hit Enter to edit' })] }));
};