Parcourir la source

WIP: impl new input component

Yuki Takei il y a 1 an
Parent
commit
dd7e1d50c1

+ 19 - 0
apps/app/src/components/Common/SubmittableInput/AutosizeSubmittableInput.tsx

@@ -0,0 +1,19 @@
+import type {
+  ReactElement,
+} from 'react';
+
+import type { AutosizeInputProps } from 'react-input-autosize';
+import AutosizeInput from 'react-input-autosize';
+
+import type { SubmittableInputProps } from './types';
+import { useSubmittable } from './use-submittable';
+
+
+export const AutosizeSubmittableInput = (props: SubmittableInputProps<AutosizeInputProps>): ReactElement<AutosizeInput> => {
+
+  const submittableProps = useSubmittable(props);
+
+  return (
+    <AutosizeInput {...submittableProps} />
+  );
+};

+ 23 - 0
apps/app/src/components/Common/SubmittableInput/SubmittableInput.tsx

@@ -0,0 +1,23 @@
+import type {
+  ReactElement,
+} from 'react';
+
+import type { SubmittableInputProps } from './types';
+import { useSubmittable } from './use-submittable';
+
+
+export const SubmittableInput = (props: SubmittableInputProps): ReactElement<HTMLInputElement> => {
+  // // autoFocus
+  // useEffect(() => {
+  //   if (inputRef?.current == null) {
+  //     return;
+  //   }
+  //   inputRef.current.focus();
+  // });
+
+  const submittableProps = useSubmittable(props);
+
+  return (
+    <input {...submittableProps} />
+  );
+};

+ 2 - 0
apps/app/src/components/Common/SubmittableInput/index.ts

@@ -0,0 +1,2 @@
+export * from './SubmittableInput';
+export * from './AutosizeSubmittableInput';

+ 7 - 0
apps/app/src/components/Common/SubmittableInput/types.d.ts

@@ -0,0 +1,7 @@
+export type SubmittableInputProps<T extends InputHTMLAttributes<HTMLInputElement> = InputHTMLAttributes<HTMLInputElement>> =
+  Omit<InputHTMLAttributes<T>, 'value' | 'onKeyDown' | 'onSubmit'>
+  & {
+    value?: string,
+    onSubmit?: (inputText: string) => void,
+    onCancel?: () => void,
+  }

+ 79 - 0
apps/app/src/components/Common/SubmittableInput/use-submittable.ts

@@ -0,0 +1,79 @@
+import type {
+  CompositionEvent,
+} from 'react';
+import type React from 'react';
+import {
+  useCallback, useState,
+} from 'react';
+
+import type { SubmittableInputProps } from './types';
+
+export const useSubmittable = (props: SubmittableInputProps): Partial<React.InputHTMLAttributes<HTMLInputElement>> => {
+
+  const {
+    value,
+    onChange, onBlur,
+    onCompositionStart, onCompositionEnd,
+    onSubmit, onCancel,
+  } = props;
+
+  const [inputText, setInputText] = useState(value ?? '');
+  const [isComposing, setComposing] = useState(false);
+
+  const changeHandler = useCallback(async(e: React.ChangeEvent<HTMLInputElement>) => {
+    const inputText = e.target.value;
+    setInputText(inputText);
+
+    onChange?.(e);
+  }, [onChange]);
+
+  const keyDownHandler = useCallback((e) => {
+    switch (e.key) {
+      case 'Enter':
+        // Do nothing when composing
+        if (isComposing) {
+          return;
+        }
+        onSubmit?.(inputText.trim());
+        break;
+      case 'Escape':
+        if (isComposing) {
+          return;
+        }
+        onCancel?.();
+        break;
+    }
+  }, [inputText, isComposing, onCancel, onSubmit]);
+
+  const blurHandler = useCallback((e) => {
+    // submit on blur
+    onSubmit?.(inputText.trim());
+    onBlur?.(e);
+  }, [inputText, onSubmit, onBlur]);
+
+  const compositionStartHandler = useCallback((e: CompositionEvent<HTMLInputElement>) => {
+    setComposing(true);
+    onCompositionStart?.(e);
+  }, [onCompositionStart]);
+
+  const compositionEndHandler = useCallback((e: CompositionEvent<HTMLInputElement>) => {
+    setComposing(false);
+    onCompositionEnd?.(e);
+  }, [onCompositionEnd]);
+
+  const {
+    // eslint-disable-next-line @typescript-eslint/no-unused-vars
+    onSubmit: _onSubmit, onCancel: _onCancel,
+    ...cleanedProps
+  } = props;
+
+  return {
+    ...cleanedProps,
+    onChange: changeHandler,
+    onKeyDown: keyDownHandler,
+    onBlur: blurHandler,
+    onCompositionStart: compositionStartHandler,
+    onCompositionEnd: compositionEndHandler,
+  };
+
+};