Browse Source

ref(tsc): refactor union (#32153)

* ref(tsc): refactor union

* ref(tsc): add disabled prop

* ref(tsc): improve type narrowing and pass the correct props

* fix(link): centering

* fix(ci): empty commit to trigger CI

* ref(tsc): fix unions on booleanfield (#32158)

* ref(tsc): refactor union

* ref(tsc): fix inputField

* ref(tsc): extend the right prop

* ref(tsc): fix the types

* ref(tsc): fix other field types

* ref(tsc): remove generic

* fix(fields): more accurate types

* fix(mobx): remove object type

* fix(choicemapper): fix type

* fix(formmodel): order of props matters

* fix(fieldFromConfig): read the right prop and add back types

* ref(tsc): fix radiogroup (#32159)

* ref(tsc): fix radioGroup

* ref(radiogroup): reexport prop

* ref(tsc): fix union on modalheader (#32203)

* ref(tsc): fix union

* ref(tsc): use HTMLAttributes

* ref(tsc): remove large union on searchbar (#32204)

* fix(searchbar): remove large union

* ref(tsc): fix union on activityitem (#32205)

* fix(settingsindex): stop leaking attribute
Jonas 3 years ago
parent
commit
d631017df7

+ 3 - 3
static/app/components/activity/item/bubble.tsx

@@ -1,15 +1,15 @@
 import styled from '@emotion/styled';
 
-type Props = {
+export interface ActivityBubbleProps extends React.HTMLAttributes<HTMLDivElement> {
   backgroundColor?: string;
   borderColor?: string;
-};
+}
 
 /**
  * This creates a bordered box that has a left pointing arrow
  * on the left-side at the top.
  */
-const ActivityBubble = styled('div')<Props>`
+const ActivityBubble = styled('div')<ActivityBubbleProps>`
   flex: 1;
   background-color: ${p => p.backgroundColor || p.theme.background};
   border: 1px solid ${p => p.borderColor || p.theme.border};

+ 5 - 5
static/app/components/activity/item/index.tsx

@@ -10,13 +10,13 @@ import {AvatarUser} from 'sentry/types';
 import {isRenderFunc} from 'sentry/utils/isRenderFunc';
 
 import ActivityAvatar from './avatar';
-import ActivityBubble from './bubble';
+import ActivityBubble, {ActivityBubbleProps} from './bubble';
 
 export type ActivityAuthorType = 'user' | 'system';
 
 type ChildFunction = () => React.ReactNode;
 
-type Props = {
+interface ActivityItemProps {
   /**
    * Used to render an avatar for the author. Currently can be a user, otherwise
    * defaults as a "system" avatar (i.e. sentry)
@@ -29,7 +29,7 @@ type Props = {
   };
   // Size of the avatar.
   avatarSize?: number;
-  bubbleProps?: React.ComponentProps<typeof ActivityBubble>;
+  bubbleProps?: ActivityBubbleProps;
 
   children?: React.ReactChild | ChildFunction;
 
@@ -65,7 +65,7 @@ type Props = {
 
   // Instead of showing a relative time/date, show the time
   showTime?: boolean;
-};
+}
 
 function ActivityItem({
   author,
@@ -80,7 +80,7 @@ function ActivityItem({
   header,
   hideDate = false,
   showTime = false,
-}: Props) {
+}: ActivityItemProps) {
   const showDate = !hideDate && date && !interval;
   const showRange = !hideDate && date && interval;
   const dateEnded = showRange

+ 5 - 7
static/app/components/forms/blankField.tsx

@@ -1,16 +1,14 @@
 import * as React from 'react';
 
-import Field from 'sentry/components/forms/field';
-
-type Props = Field['props'];
+import Field, {FieldProps} from 'sentry/components/forms/field';
 
 /**
  * This class is meant to hook into `fieldFromConfig`. Like the FieldSeparator
  * class, this doesn't have any fields of its own and is just meant to make
  * forms more flexible.
  */
-export default class BlankField extends React.Component<Props> {
-  render() {
-    return <Field {...this.props} />;
-  }
+function BlankField(props: FieldProps) {
+  return <Field {...props} />;
 }
+
+export default BlankField;

+ 4 - 4
static/app/components/forms/booleanField.tsx

@@ -1,17 +1,17 @@
 import * as React from 'react';
 
 import Confirm from 'sentry/components/confirm';
-import InputField, {onEvent} from 'sentry/components/forms/inputField';
+import InputField, {InputFieldProps, onEvent} from 'sentry/components/forms/inputField';
 import Switch from 'sentry/components/switchButton';
 
-type Props = {
+export interface BooleanFieldProps extends InputFieldProps {
   confirm?: {
     false?: React.ReactNode;
     true?: React.ReactNode;
   };
-} & InputField['props'];
+}
 
-export default class BooleanField extends React.Component<Props> {
+export default class BooleanField extends React.Component<BooleanFieldProps> {
   coerceValue(value: any) {
     return !!value;
   }

+ 15 - 12
static/app/components/forms/choiceMapperField.tsx

@@ -5,16 +5,14 @@ import Button from 'sentry/components/button';
 import DropdownAutoComplete from 'sentry/components/dropdownAutoComplete';
 import {Item} from 'sentry/components/dropdownAutoComplete/types';
 import DropdownButton from 'sentry/components/dropdownButton';
-import InputField from 'sentry/components/forms/inputField';
+import InputField, {InputFieldProps} from 'sentry/components/forms/inputField';
 import SelectControl, {ControlProps} from 'sentry/components/forms/selectControl';
 import {IconAdd, IconDelete} from 'sentry/icons';
 import {t} from 'sentry/locale';
 import space from 'sentry/styles/space';
 import {defined, objectIsEmpty} from 'sentry/utils';
 
-type InputFieldProps = React.ComponentProps<typeof InputField>;
-
-type DefaultProps = {
+interface DefaultProps {
   /**
    * Text used for the 'add row' button.
    */
@@ -28,7 +26,7 @@ type DefaultProps = {
    * per item specify this as true.
    */
   perItemMapping: boolean;
-};
+}
 
 const defaultProps: DefaultProps = {
   addButtonText: t('Add Item'),
@@ -38,7 +36,7 @@ const defaultProps: DefaultProps = {
 
 type MappedSelectors = Record<string, Partial<ControlProps>>;
 
-export type ChoiceMapperProps = {
+export interface ChoiceMapperProps extends DefaultProps {
   /**
    * Props forwarded to the add mapping dropdown.
    */
@@ -93,16 +91,21 @@ export type ChoiceMapperProps = {
 
   // TODO(ts) This isn't aligned with InputField but that's what the runtime code had.
   onBlur?: () => void;
-} & DefaultProps;
+}
 
-type FieldProps = ChoiceMapperProps & InputFieldProps;
+export interface ChoiceMapperFieldProps
+  extends ChoiceMapperProps,
+    Omit<
+      InputFieldProps,
+      'onBlur' | 'onChange' | 'value' | 'formatMessageValue' | 'disabled'
+    > {}
 
-export default class ChoiceMapper extends React.Component<FieldProps> {
+export default class ChoiceMapper extends React.Component<ChoiceMapperFieldProps> {
   static defaultProps = defaultProps;
 
-  hasValue = (value: FieldProps['value']) => defined(value) && !objectIsEmpty(value);
+  hasValue = (value: InputFieldProps['value']) => defined(value) && !objectIsEmpty(value);
 
-  renderField = (props: ChoiceMapperProps) => {
+  renderField = (props: ChoiceMapperFieldProps) => {
     const {
       onChange,
       onBlur,
@@ -122,7 +125,7 @@ export default class ChoiceMapper extends React.Component<FieldProps> {
     const valueIsEmpty = this.hasValue(props.value);
     const value = valueIsEmpty ? props.value : {};
 
-    const saveChanges = (nextValue: ChoiceMapperProps['value']) => {
+    const saveChanges = (nextValue: ChoiceMapperFieldProps['value']) => {
       onChange?.(nextValue, {});
 
       const validValues = !Object.values(nextValue)

+ 9 - 4
static/app/components/forms/controls/input.tsx

@@ -1,9 +1,14 @@
+import React from 'react';
 import isPropValid from '@emotion/is-prop-valid';
-import styled, {StyledComponent} from '@emotion/styled';
+import styled from '@emotion/styled';
 
 import {inputStyles} from 'sentry/styles/input';
 
-type Props = Omit<Parameters<typeof inputStyles>[0], 'theme'>;
+export interface InputProps
+  extends React.InputHTMLAttributes<HTMLInputElement>,
+    Omit<Parameters<typeof inputStyles>[0], 'theme'> {
+  type?: React.HTMLInputTypeAttribute;
+}
 
 /**
  * Do not forward required to `input` to avoid default browser behavior
@@ -11,9 +16,9 @@ type Props = Omit<Parameters<typeof inputStyles>[0], 'theme'>;
 const Input = styled('input', {
   shouldForwardProp: prop =>
     typeof prop === 'string' && isPropValid(prop) && prop !== 'required',
-})<Props>`
+})<InputProps>`
   ${inputStyles};
 `;
 
 // Cast type to avoid exporting theme
-export default Input as StyledComponent<JSX.IntrinsicElements['input'] & Props>;
+export default Input;

+ 11 - 6
static/app/components/forms/controls/radioGroup.tsx

@@ -7,7 +7,11 @@ import Tooltip from 'sentry/components/tooltip';
 import {t} from 'sentry/locale';
 import space from 'sentry/styles/space';
 
-const Container = styled('div')<{orientInline?: boolean}>`
+interface ContainerProps extends React.HTMLAttributes<HTMLDivElement> {
+  orientInline?: boolean;
+}
+
+const Container = styled('div')<ContainerProps>`
   display: grid;
   gap: ${p => space(p.orientInline ? 3 : 1)};
   grid-auto-flow: ${p => (p.orientInline ? 'column' : 'row')};
@@ -15,7 +19,7 @@ const Container = styled('div')<{orientInline?: boolean}>`
   grid-auto-columns: max-content;
 `;
 
-type RadioGroupProps<C extends string> = {
+interface BaseRadioGroupProps<C extends string> {
   /**
    * An array of [id, name, description]
    */
@@ -32,10 +36,11 @@ type RadioGroupProps<C extends string> = {
    * Switch the radio items to flow left to right, instead of vertically.
    */
   orientInline?: boolean;
-};
+}
 
-type Props<C extends string> = RadioGroupProps<C> &
-  Omit<React.ComponentPropsWithoutRef<typeof Container>, keyof RadioGroupProps<C>>;
+export interface RadioGroupProps<C extends string>
+  extends BaseRadioGroupProps<C>,
+    Omit<ContainerProps, 'onChange'> {}
 
 const RadioGroup = <C extends string>({
   value,
@@ -46,7 +51,7 @@ const RadioGroup = <C extends string>({
   onChange,
   orientInline,
   ...props
-}: Props<C>) => (
+}: RadioGroupProps<C>) => (
   <Container
     orientInline={orientInline}
     {...props}

+ 17 - 16
static/app/components/forms/controls/textarea.tsx

@@ -7,24 +7,25 @@ import {inputStyles} from 'sentry/styles/input';
 import space from 'sentry/styles/space';
 
 type InputProps = Omit<Parameters<typeof inputStyles>[0], 'theme'>;
-type Props = Omit<React.TextareaHTMLAttributes<HTMLTextAreaElement>, 'css'> &
-  InputProps & {
-    /**
-     * Enable autosizing of the textarea.
-     */
-    autosize?: boolean;
-    /**
-     * Max number of rows to default to.
-     */
-    maxRows?: number;
-    /**
-     * Number of rows to default to.
-     */
-    rows?: number;
-  };
+export interface TextAreaProps
+  extends Omit<React.TextareaHTMLAttributes<HTMLTextAreaElement>, 'css'>,
+    InputProps {
+  /**
+   * Enable autosizing of the textarea.
+   */
+  autosize?: boolean;
+  /**
+   * Max number of rows to default to.
+   */
+  maxRows?: number;
+  /**
+   * Number of rows to default to.
+   */
+  rows?: number;
+}
 
 const TextAreaControl = React.forwardRef(function TextAreaControl(
-  {autosize, rows, maxRows, ...p}: Props,
+  {autosize, rows, maxRows, ...p}: TextAreaProps,
   ref: React.Ref<HTMLTextAreaElement>
 ) {
   return autosize ? (

+ 3 - 3
static/app/components/forms/datePickerField.tsx

@@ -10,9 +10,9 @@ import {IconCalendar} from 'sentry/icons';
 import {inputStyles} from 'sentry/styles/input';
 import space from 'sentry/styles/space';
 
-import InputField, {onEvent} from './inputField';
+import InputField, {InputFieldProps, onEvent} from './inputField';
 
-type Props = Omit<InputField['props'], 'field'>;
+interface DatePickerFieldProps extends Omit<InputFieldProps, 'field'> {}
 
 function handleChangeDate(
   onChange: onEvent,
@@ -29,7 +29,7 @@ function handleChangeDate(
 
 const Calendar = lazy(() => import('./calendarField'));
 
-export default function DatePickerField(props: Props) {
+export default function DatePickerField(props: DatePickerFieldProps) {
   return (
     <InputField
       {...props}

+ 2 - 4
static/app/components/forms/dateTimeField.tsx

@@ -1,7 +1,5 @@
-import InputField from './inputField';
+import InputField, {InputFieldProps} from './inputField';
 
-type Props = InputField['props'];
-
-export default function DateTimeField(props: Omit<Props, 'type'>) {
+export default function DateTimeField(props: Omit<InputFieldProps, 'type'>) {
   return <InputField {...props} type="datetime-local" />;
 }

Some files were not shown because too many files changed in this diff