react#TouchEvent TypeScript Examples

The following examples show how to use react#TouchEvent. 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: App.tsx    From cra-template-ch5-typescript with MIT License 6 votes vote down vote up
AnalogDiv: React.FunctionComponent<AnalogDivProps> = (props) => {
  const publish = usePublishAnalog(props.analogSendSignalName);
  const value = useSubscribeAnalog(props.analogsubscribeSignalName);
  const divref = React.useRef<HTMLDivElement>(null);

  const percent = value * 100 / 65535;

  const percentString = percent + '%';

  const touch = (event:TouchEvent<HTMLDivElement>) => {
    if (divref.current) {
      const clientRect = divref.current.getBoundingClientRect();
      const width = clientRect.right - clientRect.left;

      for (var i = 0; i < event.changedTouches.length; i++) {
        const value = clamp(Math.round(65535 * (event.changedTouches[i].pageX - clientRect.left) / width), 0, 65535);
        publish(value);
        console.log(value);
      }
    }
  }

  return (
    <div ref={divref} onTouchStart={touch} onTouchMove={touch} style={{ margin: '0 1rem', border: '1px solid black', display: 'inline-block', width: '20rem', height: '4rem', backgroundColor: '#aaa' }}> 
      <div style={{backgroundColor: '#2f2', width: percentString, height: '4rem'}}></div>
    </div>
  );
}
Example #2
Source File: TouchSensor.ts    From dnd-kit with MIT License 6 votes vote down vote up
static activators = [
    {
      eventName: 'onTouchStart' as const,
      handler: (
        {nativeEvent: event}: TouchEvent,
        {onActivation}: TouchSensorOptions
      ) => {
        const {touches} = event;

        if (touches.length > 1) {
          return false;
        }

        onActivation?.({event});

        return true;
      },
    },
  ];
Example #3
Source File: TorrentListRow.tsx    From flood with GNU General Public License v3.0 6 votes vote down vote up
displayContextMenu = (hash: string, event: KeyboardEvent | MouseEvent | TouchEvent) => {
  if (event.cancelable === true) {
    event.preventDefault();
  }

  const mouseClientX = (event as unknown as MouseEvent).clientX;
  const mouseClientY = (event as unknown as MouseEvent).clientY;
  const touchClientX = (event as unknown as TouchEvent).touches?.[0].clientX;
  const touchClientY = (event as unknown as TouchEvent).touches?.[0].clientY;

  if (!TorrentStore.selectedTorrents.includes(hash)) {
    TorrentStore.setSelectedTorrents({hash, event});
  }

  const {torrentContextMenuActions = defaultFloodSettings.torrentContextMenuActions} = SettingStore.floodSettings;
  const torrent = TorrentStore.torrents[hash];

  UIStore.setActiveContextMenu({
    id: 'torrent-list-item',
    clickPosition: {
      x: mouseClientX || touchClientX || 0,
      y: mouseClientY || touchClientY || 0,
    },
    items: getContextMenuItems(torrent).filter((item) => {
      if (item.type === 'separator') {
        return true;
      }

      return torrentContextMenuActions.some((action) => action.id === item.action && action.visible === true);
    }),
  });
}
Example #4
Source File: TorrentFilterStore.ts    From flood with GNU General Public License v3.0 6 votes vote down vote up
setTagFilters(filter: string, event: KeyboardEvent | MouseEvent | TouchEvent) {
    const tags = Object.keys(this.taxonomy.tagCounts).sort((a, b) => {
      if (a === 'untagged') return -1;
      else if (b === 'untagged') return 1;
      else return a.localeCompare(b);
    });

    // Put 'untagged' in the correct second position for shift click ordering
    tags.splice(tags.indexOf('untagged'), 1);
    tags.splice(1, 0, 'untagged');

    this.computeFilters(tags, this.tagFilter, filter, event);
    this.filterTrigger = !this.filterTrigger;
  }
Example #5
Source File: index.ts    From react-carousel with MIT License 5 votes vote down vote up
export function getPageX(e: TouchEvent | MouseEvent): number {
	if (e.nativeEvent instanceof MouseEvent) {
		return e.nativeEvent.pageX;
	} else if (e.nativeEvent instanceof TouchEvent) {
		return e.nativeEvent.changedTouches[0].pageX;
	}
	return 0;
}
Example #6
Source File: TorrentListRow.tsx    From flood with GNU General Public License v3.0 5 votes vote down vote up
selectTorrent = (hash: string, event: KeyboardEvent | MouseEvent | TouchEvent) =>
  TorrentStore.setSelectedTorrents({hash, event})
Example #7
Source File: TorrentListRow.tsx    From flood with GNU General Public License v3.0 5 votes vote down vote up
TorrentListRow: FC<TorrentListRowProps> = observer(({hash, style}: TorrentListRowProps) => {
  const [rowLocation, setRowLocation] = useState<number>(0);
  const shouldDisplayTorrentDetails = useRef<boolean>(false);
  const rowRef = useRef<HTMLDivElement>(null);

  const isCondensed = SettingStore.floodSettings.torrentListViewSize === 'condensed';
  const isSelected = computed(() => TorrentStore.selectedTorrents.includes(hash)).get();

  const {status, upRate, downRate} = TorrentStore.torrents?.[hash] || {};
  const torrentClasses = torrentStatusClasses(
    {status, upRate, downRate},
    classnames({
      'torrent--is-selected': isSelected,
      'torrent--is-condensed': isCondensed,
      'torrent--is-expanded': !isCondensed,
    }),
    'torrent',
  );

  const {onTouchStart, onTouchEnd} = useLongPress((e) => {
    const curRowLocation = rowRef.current?.getBoundingClientRect().top;
    if (e != null && curRowLocation != null && Math.abs(curRowLocation - rowLocation) < 25) {
      displayContextMenu(hash, e as unknown as TouchEvent);
    }
  });

  const onTouchStartHooked = (e: TouchEvent) => {
    if (!TorrentStore.selectedTorrents.includes(hash)) {
      selectTorrent(hash, e);
    }

    if (shouldDisplayTorrentDetails.current) {
      displayTorrentDetails(hash);
    } else {
      shouldDisplayTorrentDetails.current = true;
      setTimeout(() => {
        shouldDisplayTorrentDetails.current = false;
      }, 200);
    }

    setRowLocation(rowRef.current?.getBoundingClientRect().top || 0);

    onTouchStart(e);
  };

  if (isCondensed) {
    return (
      <TorrentListRowCondensed
        className={torrentClasses}
        ref={rowRef}
        style={style}
        hash={hash}
        handleClick={selectTorrent}
        handleDoubleClick={displayTorrentDetails}
        handleRightClick={displayContextMenu}
        handleTouchStart={onTouchStartHooked}
        handleTouchEnd={onTouchEnd}
        handleKeyPress={(e) => onKeyPress(hash, e)}
      />
    );
  }

  return (
    <TorrentListRowExpanded
      className={torrentClasses}
      ref={rowRef}
      style={style}
      hash={hash}
      handleClick={selectTorrent}
      handleDoubleClick={displayTorrentDetails}
      handleRightClick={displayContextMenu}
      handleTouchStart={onTouchStartHooked}
      handleTouchEnd={onTouchEnd}
      handleKeyPress={(e) => onKeyPress(hash, e)}
    />
  );
})
Example #8
Source File: TorrentFilterStore.ts    From flood with GNU General Public License v3.0 5 votes vote down vote up
setStatusFilters(filter: TorrentStatus | '', event: KeyboardEvent | MouseEvent | TouchEvent) {
    this.computeFilters(torrentStatusMap, this.statusFilter, filter, event);
    this.filterTrigger = !this.filterTrigger;
  }
Example #9
Source File: TorrentFilterStore.ts    From flood with GNU General Public License v3.0 5 votes vote down vote up
setTrackerFilters(filter: string, event: KeyboardEvent | MouseEvent | TouchEvent) {
    const trackers = Object.keys(this.taxonomy.trackerCounts).sort((a, b) => a.localeCompare(b));

    this.computeFilters(trackers, this.trackerFilter, filter, event);
    this.filterTrigger = !this.filterTrigger;
  }
Example #10
Source File: TorrentFilterStore.ts    From flood with GNU General Public License v3.0 5 votes vote down vote up
private computeFilters<T extends TorrentStatus | string>(
    keys: readonly T[],
    currentFilters: Array<T>,
    newFilter: T,
    event: KeyboardEvent | MouseEvent | TouchEvent,
  ) {
    if (newFilter === ('' as T)) {
      currentFilters.splice(0);
    } else if (event.shiftKey) {
      if (currentFilters.length) {
        const lastKey = currentFilters[currentFilters.length - 1];
        const lastKeyIndex = keys.indexOf(lastKey);
        let currentKeyIndex = keys.indexOf(newFilter);

        if (!~currentKeyIndex || !~lastKeyIndex) {
          return;
        }

        // from the previously selected index to the currently selected index,
        // add all filters to the selected array.
        // if the newly selected index is larger than the previous, start from
        // the newly selected index and work backwards. otherwise go forwards.
        const increment = currentKeyIndex > lastKeyIndex ? -1 : 1;

        for (; currentKeyIndex !== lastKeyIndex; currentKeyIndex += increment) {
          const foundKey = keys[currentKeyIndex] as T;
          // if the filter isn't already selected, add the filter to the array.
          if (!currentFilters.includes(foundKey)) {
            currentFilters.push(foundKey);
          }
        }
      } else {
        currentFilters.splice(0, currentFilters.length, newFilter);
      }
    } else if (event.metaKey || event.ctrlKey) {
      if (currentFilters.includes(newFilter)) {
        currentFilters.splice(currentFilters.indexOf(newFilter), 1);
      } else {
        currentFilters.push(newFilter);
      }
    } else {
      currentFilters.splice(0, currentFilters.length, newFilter);
    }
  }
Example #11
Source File: helpers.spec.tsx    From react-carousel with MIT License 4 votes vote down vote up
describe('helpers', () => {
	it('should return to head of circular items list', async () => {
		const items = carouselItemNodes(2);
		const circular = new helpers.Circular(items, 0);
		circular.next();
		circular.next();

		expect(circular.current()).toEqual(items[0]);
	});

	it('should add items to right and left of the array', async () => {
		const items = carouselItemNodes(2);
		const showingItems = carouselItemNodes(2);
		const result = helpers.rotateItems(
			items,
			showingItems,
			0,
			1,
			1,
			SlideDirection.Right,
		);

		expect(result.length).toEqual(4);
	});

	it('should get indicator of the items array', async () => {
		const result = helpers.getCurrent(0, 2, 4, SlideDirection.Right);

		expect(result).toEqual(2);
	});

	it('should get indicator of the items array in circular manner', async () => {
		const result = helpers.getCurrent(0, 5, 4, SlideDirection.Right);

		expect(result).toEqual(1);
	});

	it('should return 0 if event is not mouseEvent or touchEvent', async () => {
		const mouseEvent = { nativeEvent: { pageX: 10 } };
		const result = helpers.getPageX(mouseEvent as React.MouseEvent);

		expect(result).toEqual(0);
	});

	it('should return pageX if event is mouseEvent', async () => {
		const nativeEvent = new MouseEvent('mousedown');
		const pageX = 10;
		Object.defineProperty(nativeEvent, 'pageX', { value: pageX });
		const event = { nativeEvent };
		const result = helpers.getPageX(event as MouseEvent);

		expect(result).toEqual(pageX);
	});

	it('should return pageX if event is touchEvent', async () => {
		const nativeEvent = new TouchEvent('mousedown');
		const pageX = 10;
		const changedTouches = [{ pageX }];
		Object.defineProperty(nativeEvent, 'changedTouches', { value: changedTouches });
		const event = { nativeEvent };
		const result = helpers.getPageX(event as TouchEvent);

		expect(result).toEqual(pageX);
	});

	it('should return width of element', async () => {
		const width = 30;
		const element = document.createElement('div');
		Object.defineProperty(element, 'offsetWidth', { value: width });
		const result = getOuterWidth(element);

		expect(result).toEqual(width);
	});

	it('should update nodes', async () => {
		const oldNodes = reactNodes('old', 5) as Item[];
		const newNodes = reactNodes('new', 6) as Item[];
		const expected = reactNodes('new', 5) as Item[];
		const prevChildren = undefined;
		const infinite = true;
		const slide = 5;

		const result = helpers.updateNodes(
			oldNodes,
			newNodes,
			prevChildren,
			slide,
			infinite,
		);

		expect(result).toEqual(expected);
	});

	it('should change nodes with new items when nodes not matched', async () => {
		const oldNodes = reactNodes('old', 5) as Item[];
		const infinite = true;
		const slide = 2;
		const prevChildren = undefined;
		const newNodes = ([
			{
				key: 14,
				props: '',
			},
			{
				key: 15,
				props: '',
			},
		] as unknown) as Item[];
		const expectedNodes = ([
			{
				key: 14,
				props: '',
			},
			{
				key: 15,
				props: '',
			},
			{
				key: 14,
				props: '',
			},
			{
				key: 15,
				props: '',
			},
		] as unknown) as Item[];

		const result = helpers.updateNodes(
			oldNodes,
			newNodes,
			prevChildren,
			slide,
			infinite,
		);

		expect(result).toEqual(expectedNodes);
	});

	it('should update nodes when previous children length is less than new children', async () => {
		const oldNodes = reactNodes('old', 5) as Item[];
		const newNodes = reactNodes('new', 6) as Item[];
		const prevChildren = newNodes.slice(0, 5);
		const expected = newNodes.slice(1, 6).concat(newNodes);
		const infinite = true;
		const slide = 5;

		const result = helpers.updateNodes(
			oldNodes,
			newNodes,
			prevChildren,
			slide,
			infinite,
		);

		expect(result).toEqual(expected);
	});

	it('should get corre transform amount', async () => {
		const width = 100;
		const slideCount = 2;
		const direction = SlideDirection.Left;
		const expected = 200;

		const result = helpers.getTransformAmount(width, slideCount, direction);

		expect(result).toEqual(expected);
	});

	it('should return false if hideArrows property is true', async () => {
		const itemCount = 10;
		const itemsToShow = 3;
		const infinite = true;
		const current = 1;
		const hideArrows = true;

		const expected = {
			left: false,
			right: false,
		};

		const result = helpers.getShowArrow({
			itemCount,
			itemsToShow,
			infinite,
			current,
			hideArrows,
		});

		expect(result).toEqual(expected);
	});
});
Example #12
Source File: index.tsx    From react-carousel with MIT License 4 votes vote down vote up
ItemProvider: FunctionComponent<ItemProviderProps> = (
	props: ItemProviderProps,
) => {
	const [width, setWidth] = useState(200);
	const ref = useCallback(
		(node) => {
			if (node !== null) {
				const calculated = node.getBoundingClientRect().width / props.show;
				setWidth(calculated);
				props.widthCallBack(calculated);
			}
		},
		[width],
	);

	// tslint:disable-next-line: no-unused-expression
	props.responsive &&
		useWindowWidthChange((change: number) => {
			setWidth(width - change);
		});
	const [drag, setDrag] = useState({
		initial: props.transform,
		start: 0,
		isDown: false,
		drag: 0,
		finished: true,
		pointers: true,
	});
	const handleDragStart = (e: MouseEvent | TouchEvent) => {
		e.persist();
		setDrag({
			...drag,
			isDown: true,
			start: getPageX(e),
			initial: props.transform,
			finished: false,
		});
	};
	const handleDragFinish = (e: MouseEvent | TouchEvent) => {
		e.persist();
		if (drag.finished) {
			return;
		}
		if (Math.abs(drag.drag) < width * props.swipeOn) {
			props.dragCallback(props.transform);
			return setDrag({
				initial: props.transform,
				start: 0,
				isDown: false,
				drag: 0,
				finished: true,
				pointers: true,
			});
		}

		props.slideCallback(drag.drag > 0 ? SlideDirection.Right : SlideDirection.Left);
		setDrag({ ...drag, drag: 0, isDown: false, finished: true, pointers: true });
		return;
	};
	const handleDragMove = (e: MouseEvent | TouchEvent) => {
		e.persist();
		if (!drag.isDown) {
			return;
		}
		const pos = getPageX(e);
		setDrag({
			...drag,
			drag: drag.start - pos,
			pointers: Math.abs(drag.start - pos) < props.triggerClickOn,
		});
	};
	const swipeProps = props.swiping
		? {
				onTouchCancel: handleDragFinish,
				onTouchEnd: handleDragFinish,
				onTouchMove: handleDragMove,
				onTouchStart: handleDragStart,
				onMouseDown: handleDragStart,
				onMouseLeave: handleDragFinish,
				onMouseUp: handleDragFinish,
				onMouseMove: handleDragMove,
		  }
		: {};

	return (
		<div ref={ref} className={styles.itemProvider}>
			<div
				data-testid="trackList"
				{...swipeProps}
				className={styles.itemTracker}
				style={{
					transform: `translateX(${props.transform - drag.drag}px)`,
					transition: `transform ${props.transition}s ease 0s`,
					width: width * props.items.length,
				}}
			>
				{props.items.map((item, i) => (
					<div
						key={i}
						style={{ width, pointerEvents: drag.pointers ? 'all' : 'none' }}
						className={styles.itemContainer}
					>
						{item}
					</div>
				))}
			</div>
		</div>
	);
}
Example #13
Source File: index.tsx    From ui with MIT License 4 votes vote down vote up
LicenseKeyBoard: React.FC<LicenseKeyBoardProps> = p => {
  const props = mergeProps(defaultProps, p);
  const {
    visible,
    title,
    value,
    confirmText,
    showCloseButton,
    onInput,
  } = props;

  const keyboardRef = useRef<HTMLDivElement | null>(null);

  const keys = useMemo(() => {
    const defaultKeys = '京沪粤津浙苏湘渝云豫皖陕桂新青琼闽蒙辽宁鲁晋吉冀黑甘鄂赣贵川藏民使领警学港澳'.split(
      '',
    );
    defaultKeys.push('BACKSPACE');
    return defaultKeys;
  }, []);

  const smallVehicleNewEnergy = '1234567890';
  const newEnergyLetter = 'ABCDEFGHJK';
  const newEnergyLetterReg = new RegExp(`[${newEnergyLetter}]`);

  /**
   新能源车牌号规则:
   https://zh.wikipedia.org/wiki/中华人民共和国民用机动车号牌#新能源汽车号牌
   */
  const isNewEnergyPlate = (plate: string): false | string => {
    if (isNewEnergyBigVehicle(plate)) {
      return newEnergyLetter;
    } else if (isNewEnergySmallVehicle(plate)) {
      return smallVehicleNewEnergy;
    }
    return false;
  };

  const isNewEnergySmallVehicle = (plate: string) =>
    newEnergyLetterReg.test(plate[2]) && /^[0-9]+$/.test(plate.slice(4, 7));

  const isNewEnergyBigVehicle = (plate: string) =>
    /^[0-9]+$/.test(plate.slice(2, 7));

  const numberKeys = smallVehicleNewEnergy.split('');
  const letterKeys = 'QWERTYUIOPASDFGHJKLZXCVBNM'.split('');
  letterKeys.push('OK');
  const specialKeys = '港澳警领应学挂'.split('');
  specialKeys.push('BACKSPACE');

  const timeoutRef = useRef(-1);
  const intervalRef = useRef(-1);

  const onDelete = useMemoizedFn(() => {
    props.onDelete?.();
  });
  const onBackspacePressStart = () => {
    timeoutRef.current = window.setTimeout(() => {
      onDelete();
      intervalRef.current = window.setInterval(onDelete, 150);
    }, 700);
  };
  const onBackspacePressEnd = () => {
    clearTimeout(timeoutRef.current);
    clearInterval(intervalRef.current);
  };

  // 点击键盘按键
  const onKeyPress = (
    e: TouchEvent<HTMLDivElement> | MouseEvent<HTMLDivElement>,
    key: string,
  ) => {
    e.preventDefault();

    switch (key) {
      case 'BACKSPACE':
        onDelete?.();
        break;
      case 'OK':
        props.onConfirm?.();
        if (props.closeOnConfirm) {
          props.onClose?.();
        }
        break;
      default:
        if (key !== '') onInput?.(key);
        break;
    }
  };

  // 渲染 title 和 close button
  const renderHeader = () => {
    if (!showCloseButton && !title) return null;
    return (
      <div
        className={classNames(`${classPrefix}-header`, {
          'with-title': !!title,
        })}
      >
        {title && <div className={`${classPrefix}-title`}>{title}</div>}
        {showCloseButton && (
          <span
            className={`${classPrefix}-header-close-button`}
            onClick={() => {
              props.onClose?.();
            }}
            role="button"
            title="CLOSE"
          >
            <Rotate angle={90}>
              <Icon name={'kq-right'} size={32} color={'#999999'} />
            </Rotate>
          </span>
        )}
      </div>
    );
  };

  // 渲染基础键盘按键
  const renderKey = (key: string) => {
    const isNumberKey = /^\d$/.test(key);
    const isSpecialCharacters = /[港澳警领应学挂]/.test(key);
    const isDisabledKey = /^(I|O)$/.test(key);
    const className = classNames(`${classPrefix}-key`, {
      'number-key': isNumberKey,
      'sign-key': !isNumberKey && key,
      'a-key': key === 'A',
      'l-key': key === 'L',
      'z-key': key === 'Z',
      'm-key': key === 'M',
      'ok-key': key === 'OK',
      'del-key': key === 'BACKSPACE',
      'disabled-key':
        (value.length < 2 && (isNumberKey || isSpecialCharacters)) ||
        isDisabledKey ||
        ((isNewEnergyPlate(value) ? value.length >= 8 : value.length >= 7) &&
          key !== 'OK' &&
          key !== 'BACKSPACE'),
    });

    return (
      <div
        key={key}
        className={className}
        onTouchStart={() => {
          if (key === 'BACKSPACE') {
            onBackspacePressStart();
          }
        }}
        onTouchEnd={e => {
          if (
            (value.length < 2 && (isNumberKey || isSpecialCharacters)) ||
            isDisabledKey ||
            ((isNewEnergyPlate(value)
              ? value.length >= 8
              : value.length >= 7) &&
              key !== 'OK' &&
              key !== 'BACKSPACE')
          )
            return;
          onKeyPress(e, key);
          if (key === 'BACKSPACE') {
            onBackspacePressEnd();
          }
        }}
        onMouseUp={e => {
          if (
            (value.length < 2 && (isNumberKey || isSpecialCharacters)) ||
            isDisabledKey ||
            ((isNewEnergyPlate(value)
              ? value.length >= 8
              : value.length >= 7) &&
              key !== 'OK' &&
              key !== 'BACKSPACE')
          )
            return;
          onKeyPress(e, key);
        }}
        title={key}
        role="button"
      >
        {key === 'BACKSPACE' ? (
          <Icon name={'kq-shanchu'} size={36} />
        ) : key === 'OK' ? (
          confirmText ? (
            confirmText
          ) : (
            key
          )
        ) : (
          key
        )}
      </div>
    );
  };

  return (
    <Popup
      visible={visible}
      mask={false}
      afterClose={props.afterClose}
      afterShow={props.afterShow}
      className={`${classPrefix}-popup`}
      stopPropagation={props.stopPropagation}
    >
      {withNativeProps(
        props,
        <div
          ref={keyboardRef}
          className={classPrefix}
          onMouseDown={e => {
            e.preventDefault();
          }}
        >
          {renderHeader()}
          <div className={`${classPrefix}-wrapper`}>
            {value.length === 0 ? (
              <div
                className={classNames(`${classPrefix}-main`, {
                  'confirmed-style': !!confirmText,
                })}
              >
                {keys.map(renderKey)}
              </div>
            ) : (
              <div
                className={classNames(`${classPrefix}-main`, {
                  'confirmed-style': !!confirmText,
                })}
              >
                {numberKeys.map(renderKey)}
                {letterKeys.map(renderKey)}
                {specialKeys.map(renderKey)}
              </div>
            )}
          </div>
          {props.safeArea && (
            <div className={`${classPrefix}-footer`}>
              <SafeArea position="bottom" />
            </div>
          )}
        </div>,
      )}
    </Popup>
  );
}