react#WheelEventHandler TypeScript Examples

The following examples show how to use react#WheelEventHandler. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: KeybindingsForButton.tsx    From xcloud-keyboard-mouse with GNU General Public License v3.0 4 votes vote down vote up
function KeybindingsForButton({ button, value, onChange, readOnly, error, useSpacers = false }: TrippleKeybindProps) {
  const [isListening, setIsListening] = useState(false);
  const keyListener = useRef<null | ((e: KeyboardEvent) => void)>(null);
  const codes = useMemo(() => (!value ? [] : Array.isArray(value) ? value : [value]), [value]);

  const handleCancelListen = useCallback(() => {
    setIsListening(false);
    if (keyListener.current) document.removeEventListener('keydown', keyListener.current);
  }, []);

  const handleMouseDown: MouseEventHandler<HTMLDivElement> = useCallback(
    (e) => {
      if (e.cancelable) e.preventDefault();
      const { button: mouseButton } = e;
      if (mouseButton === 0 || mouseButton === 2) {
        const code = mouseButton === 0 ? 'Click' : 'RightClick';
        if (codes.indexOf(code) === -1) {
          onChange(button, codes.concat([code]));
        }
      }
      handleCancelListen();
      return false;
    },
    [button, codes, handleCancelListen, onChange],
  );

  const handleWheel: WheelEventHandler<HTMLDivElement> = useCallback(
    (e) => {
      if (e.cancelable) e.preventDefault();
      const code = 'Scroll';
      if (codes.indexOf(code) === -1) {
        onChange(button, codes.concat([code]));
      }
      handleCancelListen();
    },
    [button, codes, handleCancelListen, onChange],
  );

  const handleClickAdd = useCallback(() => {
    if (readOnly) return;
    setIsListening(true);
    keyListener.current = function onKeyDown(e: KeyboardEvent) {
      if (e.cancelable) e.preventDefault();
      const { code } = e;
      if (code !== 'Escape' && codes.indexOf(code) === -1) {
        onChange(button, codes.concat([code]));
      }
      handleCancelListen();
    };
    document.addEventListener('keydown', keyListener.current, false);
  }, [button, codes, readOnly, handleCancelListen, onChange]);

  const handleRemove = (i: number) => {
    onChange(
      button,
      codes.filter((_, j) => i !== j),
    );
  };

  const showNoneMessage = !codes.length && readOnly;
  const canAddMore = codes.length < MAX_BINDINGS;
  const showAddBtn = !readOnly && canAddMore;
  const numSpacers = readOnly || codes.length >= MAX_BINDINGS - 1 ? 0 : 1;
  const spacers: string[] = !useSpacers || showNoneMessage ? [] : new Array(numSpacers).fill(' ');
  const modal = (
    <Modal
      center
      open={isListening}
      onClose={handleCancelListen}
      showCloseIcon={false}
      focusTrapped={true}
      closeOnEsc={false}
    >
      <div
        className="vertical centered unselectable"
        style={{ width: '60vw', height: '50vh', padding: 20 }}
        onMouseDown={isListening ? handleMouseDown : undefined}
        onWheel={isListening ? handleWheel : undefined}
      >
        <h3>Press any key or click to bind...</h3>
        <p>(Press Esc to cancel)</p>
      </div>
    </Modal>
  );
  const errorNotice = error ? (
    <TooltipHost content={error} id={`keybind-error-tooltip-${button}`} directionalHint={DirectionalHint.rightCenter}>
      <ExclamationCircle className="error margin-left-s" />
    </TooltipHost>
  ) : null;
  return (
    <tr>
      <th>
        {camelToSpace(button)}
        {modal}
        {errorNotice}
      </th>
      {showNoneMessage ? (
        <td className="none" colSpan={3}>
          No bindings for button
        </td>
      ) : null}
      {codes.map((code, i) => (
        <td key={code}>
          <div>
            <span>{formatCodeName(code)}</span>
            {readOnly ? null : (
              <IconButton
                className="error-bg delete-icon"
                size={18}
                iconProps={{ iconName: 'BoxMultiplySolid', className: 'error' }}
                title="Remove binding"
                disabled={isListening}
                onClick={() => handleRemove(i)}
              />
            )}
          </div>
        </td>
      ))}
      {showAddBtn ? (
        <td>
          <IconButton
            iconProps={{ iconName: 'Add' }}
            title="Add binding"
            size={18}
            disabled={isListening}
            onClick={handleClickAdd}
          />
        </td>
      ) : null}
      {spacers.map((_, i) => (
        <td className="empty" key={`s${i}`}>
          <div>Empty Binding</div>
        </td>
      ))}
    </tr>
  );
}