Codedmod migration to implicit children (#34882)

Co-authored-by: gitstart-sourcegraph <gitstart@users.noreply.github.com>
This commit is contained in:
GitStart-SourceGraph 2022-05-05 12:09:18 +05:30 committed by GitHub
parent 7407b1bac1
commit 9adaf3702e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
954 changed files with 3797 additions and 2826 deletions

View File

@ -11,7 +11,7 @@ import { Tooltip, WildcardThemeContext } from '@sourcegraph/wildcard'
import brandedStyles from '../global-styles/index.scss'
export interface BrandedProps extends MemoryRouterProps, Pick<MockedStoryProviderProps, 'mocks' | 'useStrictMocking'> {
children: React.FunctionComponent<ThemeProps>
children: React.FunctionComponent<React.PropsWithChildren<ThemeProps>>
styles?: string
}
@ -19,7 +19,7 @@ export interface BrandedProps extends MemoryRouterProps, Pick<MockedStoryProvide
* Wrapper component for branded Storybook stories that provides light theme and react-router props.
* Takes a render function as children that gets called with the props.
*/
export const BrandedStory: React.FunctionComponent<BrandedProps> = ({
export const BrandedStory: React.FunctionComponent<React.PropsWithChildren<BrandedProps>> = ({
children: Children,
styles = brandedStyles,
mocks,

View File

@ -20,7 +20,7 @@ interface CodeSnippetProps {
className?: string
}
export const CodeSnippet: React.FunctionComponent<CodeSnippetProps> = ({
export const CodeSnippet: React.FunctionComponent<React.PropsWithChildren<CodeSnippetProps>> = ({
code,
language,
className,

View File

@ -14,7 +14,11 @@ interface Props {
className?: string
}
export const LoaderInput: React.FunctionComponent<Props> = ({ loading, children, className }) => (
export const LoaderInput: React.FunctionComponent<React.PropsWithChildren<Props>> = ({
loading,
children,
className,
}) => (
<div className={classNames(styles.container, className)}>
{children}
{loading && <LoadingSpinner inline={false} className={styles.spinner} />}

View File

@ -1,6 +1,8 @@
import React from 'react'
export const SourcegraphLogo: React.FunctionComponent<React.SVGAttributes<SVGSVGElement>> = props => (
export const SourcegraphLogo: React.FunctionComponent<
React.PropsWithChildren<React.SVGAttributes<SVGSVGElement>>
> = props => (
<svg viewBox="0 0 304 52" fill="none" xmlns="http://www.w3.org/2000/svg" {...props}>
<path
d="M30.8 51.8c-2.8.5-5.5-1.3-6-4.1L17.2 6.2c-.5-2.8 1.3-5.5 4.1-6s5.5 1.3 6 4.1l7.6 41.5c.5 2.8-1.4 5.5-4.1 6z"

View File

@ -37,7 +37,7 @@ interface Props {
}
/** A toggle switch input component. */
export const Toggle: React.FunctionComponent<Props> = ({
export const Toggle: React.FunctionComponent<React.PropsWithChildren<Props>> = ({
disabled,
className,
id,

View File

@ -39,7 +39,7 @@ interface Props {
}
/** A big toggle switch input component. */
export const ToggleBig: React.FunctionComponent<Props> = ({
export const ToggleBig: React.FunctionComponent<React.PropsWithChildren<Props>> = ({
disabled,
className,
id,

View File

@ -12,9 +12,10 @@ export const renderError = (error: unknown): string =>
.replace(/^<p>/, '')
.replace(/<\/p>$/, '')
export const ErrorMessage: React.FunctionComponent<{ className?: string; error: unknown }> = ({ className, error }) => (
<Markdown className={className} wrapper="span" dangerousInnerHTML={renderError(error)} />
)
export const ErrorMessage: React.FunctionComponent<React.PropsWithChildren<{ className?: string; error: unknown }>> = ({
className,
error,
}) => <Markdown className={className} wrapper="span" dangerousInnerHTML={renderError(error)} />
export type ErrorAlertProps = {
/**
@ -50,7 +51,7 @@ export type ErrorAlertProps = {
* bullet points, respect line breaks, code and bolded elements.
* Made to work with Go `multierror`.
*/
export const ErrorAlert: React.FunctionComponent<ErrorAlertProps> = ({
export const ErrorAlert: React.FunctionComponent<React.PropsWithChildren<ErrorAlertProps>> = ({
error,
className,
icon = true,

View File

@ -11,7 +11,7 @@ interface EmptyPanelViewProps {
className?: string
}
export const EmptyPanelView: React.FunctionComponent<EmptyPanelViewProps> = props => {
export const EmptyPanelView: React.FunctionComponent<React.PropsWithChildren<EmptyPanelViewProps>> = props => {
const { className, children } = props
return (

View File

@ -10,7 +10,9 @@ interface ExtensionsLoadingPanelViewProps {
className?: string
}
export const ExtensionsLoadingPanelView: React.FunctionComponent<ExtensionsLoadingPanelViewProps> = props => {
export const ExtensionsLoadingPanelView: React.FunctionComponent<
React.PropsWithChildren<ExtensionsLoadingPanelViewProps>
> = props => {
const { className } = props
return (

View File

@ -21,19 +21,21 @@ import { LoadingSpinner, Alert, Icon } from '@sourcegraph/wildcard'
import styles from './FileLocations.module.scss'
export const FileLocationsError: React.FunctionComponent<{ error: ErrorLike }> = ({ error }) => (
export const FileLocationsError: React.FunctionComponent<React.PropsWithChildren<{ error: ErrorLike }>> = ({
error,
}) => (
<Alert className="m-2" variant="danger">
Error getting locations: {upperFirst(error.message)}
</Alert>
)
export const FileLocationsNotFound: React.FunctionComponent = () => (
export const FileLocationsNotFound: React.FunctionComponent<React.PropsWithChildren<unknown>> = () => (
<div className={classNames('m-2', styles.notFound)}>
<Icon as={MapSearchIcon} /> No locations found
</div>
)
export const FileLocationsNoGroupSelected: React.FunctionComponent = () => (
export const FileLocationsNoGroupSelected: React.FunctionComponent<React.PropsWithChildren<unknown>> = () => (
<div className="m-2">
<Icon as={MapSearchIcon} /> No locations found in the current repository
</div>

View File

@ -13,7 +13,9 @@ interface HierarchicalLocationsViewButtonProps {
onClick: (event: React.MouseEvent<HTMLElement>) => void
}
export const HierarchicalLocationsViewButton: React.FunctionComponent<HierarchicalLocationsViewButtonProps> = props => {
export const HierarchicalLocationsViewButton: React.FunctionComponent<
React.PropsWithChildren<HierarchicalLocationsViewButtonProps>
> = props => {
const { groupKey, groupCount, isActive, onClick } = props
return (

View File

@ -5,7 +5,7 @@ import { getSemanticColorVariables } from '../utils'
import styles from './ColorVariants.module.scss'
export const ColorVariants: React.FunctionComponent = () => (
export const ColorVariants: React.FunctionComponent<React.PropsWithChildren<unknown>> = () => (
<div className={styles.grid}>
{getSemanticColorVariables().map(variant => (
<div className="m-2 text-center" key={variant}>

View File

@ -10,22 +10,26 @@ import styles from './FormFieldVariants.module.scss'
type FieldVariants = 'standard' | 'invalid' | 'valid' | 'disabled'
interface WithVariantsProps {
field: React.ComponentType<{
className?: string
disabled?: boolean
message?: ReactNode
variant: FieldVariants
}>
field: React.ComponentType<
React.PropsWithChildren<{
className?: string
disabled?: boolean
message?: ReactNode
variant: FieldVariants
}>
>
}
const FieldMessageText = 'Helper text'
const FieldMessage: React.FunctionComponent<{ className?: string }> = ({ className }) => (
const FieldMessage: React.FunctionComponent<React.PropsWithChildren<{ className?: string }>> = ({ className }) => (
<small className={className}>{FieldMessageText}</small>
)
// Use this temporarily for form components which ones we haven't implemented in wilcard package yet
const WithVariantsAndMessageElements: React.FunctionComponent<WithVariantsProps> = ({ field: Field }) => (
const WithVariantsAndMessageElements: React.FunctionComponent<React.PropsWithChildren<WithVariantsProps>> = ({
field: Field,
}) => (
<>
<Field variant="standard" message={<FieldMessage className="field-message" />} />
<Field variant="invalid" className="is-invalid" message={<FieldMessage className="invalid-feedback" />} />
@ -34,7 +38,7 @@ const WithVariantsAndMessageElements: React.FunctionComponent<WithVariantsProps>
</>
)
const WithVariants: React.FunctionComponent<WithVariantsProps> = ({ field: Field }) => (
const WithVariants: React.FunctionComponent<React.PropsWithChildren<WithVariantsProps>> = ({ field: Field }) => (
<>
<Field variant="standard" message={FieldMessageText} />
<Field variant="invalid" message={FieldMessageText} />
@ -43,7 +47,7 @@ const WithVariants: React.FunctionComponent<WithVariantsProps> = ({ field: Field
</>
)
export const FormFieldVariants: React.FunctionComponent = () => (
export const FormFieldVariants: React.FunctionComponent<React.PropsWithChildren<unknown>> = () => (
<div className={styles.grid}>
<WithVariantsAndMessageElements
field={({ className, message, ...props }) => (

View File

@ -6,7 +6,7 @@ import { Link } from '@sourcegraph/wildcard'
import { SEMANTIC_COLORS } from './constants'
import { TextVariants } from './TextVariants'
export const TextStory: React.FunctionComponent = () => (
export const TextStory: React.FunctionComponent<React.PropsWithChildren<unknown>> = () => (
<>
<h2>Headings</h2>
<table className="table">

View File

@ -17,7 +17,7 @@ interface TextLabelProps {
className?: string
}
const TextLabel: React.FunctionComponent<TextLabelProps> = props => {
const TextLabel: React.FunctionComponent<React.PropsWithChildren<TextLabelProps>> = props => {
const { size, weight, name, className } = props
const label = `This is ${name} / ${size} / ${weight}`
@ -39,7 +39,7 @@ interface TextVariantsProps {
className?: string
}
const TextVariations: React.FunctionComponent<TextVariantsProps> = props => {
const TextVariations: React.FunctionComponent<React.PropsWithChildren<TextVariantsProps>> = props => {
const { component: Component, name, weights = ['Regular'], className } = props
const textVariations = SIZE_VARIANTS.flatMap(size =>
@ -59,7 +59,7 @@ const TextVariations: React.FunctionComponent<TextVariantsProps> = props => {
return <>{textVariations}</>
}
export const TextVariants: React.FunctionComponent = () => (
export const TextVariants: React.FunctionComponent<React.PropsWithChildren<unknown>> = () => (
<table className="table">
<tbody>
<tr>

View File

@ -19,7 +19,9 @@ import { getPlatformName } from '../../shared/util/context'
import styles from './AfterInstallPageContent.module.scss'
const Video: React.FunctionComponent<
{ name: string } & Pick<VideoHTMLAttributes<HTMLVideoElement>, 'width' | 'height'> & ThemeProps
React.PropsWithChildren<
{ name: string } & Pick<VideoHTMLAttributes<HTMLVideoElement>, 'width' | 'height'> & ThemeProps
>
> = ({ name, isLightTheme, width, height }) => {
const suffix = isLightTheme ? 'Light' : 'Dark'
return (
@ -47,7 +49,7 @@ const Video: React.FunctionComponent<
)
}
export const AfterInstallPageContent: React.FunctionComponent<ThemeProps> = props => {
export const AfterInstallPageContent: React.FunctionComponent<React.PropsWithChildren<ThemeProps>> = props => {
// Safari does not support the search shortcut. So don't show the feature.
const isSafari = getPlatformName() === 'safari-extension'
const showSearchShortcut = !isSafari

View File

@ -26,7 +26,7 @@ const config: Meta = {
export default config
const OptionsPageWrapper: React.FunctionComponent<Partial<OptionsPageProps>> = props => (
const OptionsPageWrapper: React.FunctionComponent<React.PropsWithChildren<Partial<OptionsPageProps>>> = props => (
<OptionsPage
isFullPage={false}
isActivated={true}

View File

@ -64,7 +64,7 @@ const NEW_TAB_LINK_PROPS: Pick<React.AnchorHTMLAttributes<HTMLAnchorElement>, 'r
rel: 'noopener noreferrer',
}
export const OptionsPage: React.FunctionComponent<OptionsPageProps> = ({
export const OptionsPage: React.FunctionComponent<React.PropsWithChildren<OptionsPageProps>> = ({
version,
sourcegraphUrl,
validateSourcegraphUrl,
@ -175,12 +175,12 @@ export const OptionsPage: React.FunctionComponent<OptionsPageProps> = ({
}
interface PermissionAlertProps {
icon?: React.ComponentType<{ className?: string }>
icon?: React.ComponentType<React.PropsWithChildren<{ className?: string }>>
name: string
onClickGrantPermissions?: React.MouseEventHandler
}
const PermissionAlert: React.FunctionComponent<PermissionAlertProps> = ({
const PermissionAlert: React.FunctionComponent<React.PropsWithChildren<PermissionAlertProps>> = ({
name,
icon: AlertIcon,
onClickGrantPermissions,
@ -198,10 +198,12 @@ const PermissionAlert: React.FunctionComponent<PermissionAlertProps> = ({
</section>
)
const RepoSyncErrorAlert: React.FunctionComponent<{
sourcegraphUrl: OptionsPageProps['sourcegraphUrl']
currentUser: NonNullable<OptionsPageProps['currentUser']>
}> = ({ sourcegraphUrl, currentUser }) => {
const RepoSyncErrorAlert: React.FunctionComponent<
React.PropsWithChildren<{
sourcegraphUrl: OptionsPageProps['sourcegraphUrl']
currentUser: NonNullable<OptionsPageProps['currentUser']>
}>
> = ({ sourcegraphUrl, currentUser }) => {
const isDefaultURL = isDefaultSourcegraphUrl(sourcegraphUrl)
if (isDefaultURL && !currentUser.settingsURL) {
@ -258,7 +260,7 @@ const RepoSyncErrorAlert: React.FunctionComponent<{
)
}
const SourcegraphCloudAlert: React.FunctionComponent = () => (
const SourcegraphCloudAlert: React.FunctionComponent<React.PropsWithChildren<unknown>> = () => (
<section className={classNames('bg-2', styles.section)}>
<h4>
<Icon className="mr-2" as={CheckCircleOutlineIcon} />
@ -279,7 +281,7 @@ interface SourcegraphURLFormProps {
suggestions: OptionsPageProps['sourcegraphUrl'][]
}
export const SourcegraphURLForm: React.FunctionComponent<SourcegraphURLFormProps> = ({
export const SourcegraphURLForm: React.FunctionComponent<React.PropsWithChildren<SourcegraphURLFormProps>> = ({
value,
validate,
suggestions,

View File

@ -11,10 +11,9 @@ interface OptionsPageAdvancedSettingsProps {
onChangeOptionFlag: (key: string, value: boolean) => void
}
export const OptionsPageAdvancedSettings: React.FunctionComponent<OptionsPageAdvancedSettingsProps> = ({
optionFlags,
onChangeOptionFlag,
}) => (
export const OptionsPageAdvancedSettings: React.FunctionComponent<
React.PropsWithChildren<OptionsPageAdvancedSettingsProps>
> = ({ optionFlags, onChangeOptionFlag }) => (
<section className="mt-2">
<ul className={classNames(styles.list, 'p-0 m-0')}>
{optionFlags.map(({ label, key, value }, index) => (

View File

@ -6,7 +6,7 @@ import styles from './OptionsPageContainer.module.scss'
type OptionsPageContainerProps = HTMLAttributes<HTMLElement> & { isFullPage?: boolean }
export const OptionsPageContainer: React.FunctionComponent<OptionsPageContainerProps> = ({
export const OptionsPageContainer: React.FunctionComponent<React.PropsWithChildren<OptionsPageContainerProps>> = ({
children,
isFullPage,
className,

View File

@ -13,7 +13,7 @@ import { ThemeWrapper } from '../ThemeWrapper'
setLinkComponent(AnchorLink)
const AfterInstallPage: React.FunctionComponent = () => (
const AfterInstallPage: React.FunctionComponent<React.PropsWithChildren<unknown>> = () => (
<ThemeWrapper>
{({ isLightTheme }) => (
<WildcardThemeProvider isBranded={true}>

View File

@ -167,7 +167,7 @@ const fetchCurrentUser = (sourcegraphURL: string): Observable<Pick<GQL.IUser, 's
const uniqURLs = (urls: (string | undefined)[]): string[] =>
uniq(urls.filter(value => !!value).map(value => trimEnd(value, '/')))
const Options: React.FunctionComponent = () => {
const Options: React.FunctionComponent<React.PropsWithChildren<unknown>> = () => {
const sourcegraphUrl = useObservable(observingSourcegraphUrl)
const [previousSourcegraphUrl, setPreviousSourcegraphUrl] = useState(sourcegraphUrl)
const telemetryService = useTelemetryService(sourcegraphUrl)

View File

@ -9,16 +9,18 @@ import { useEventObservable } from '@sourcegraph/wildcard'
import { SourcegraphIconButton } from '../../components/SourcegraphIconButton'
import { getPlatformName } from '../../util/context'
export const SignInButton: React.FunctionComponent<{
className?: string
iconClassName?: string
sourcegraphURL: string
/**
* Gets called when the user closed the sign in tab.
* Does not guarantee the sign in was sucessful.
*/
onSignInClose?: () => void
}> = ({ className, iconClassName, sourcegraphURL, onSignInClose }) => {
export const SignInButton: React.FunctionComponent<
React.PropsWithChildren<{
className?: string
iconClassName?: string
sourcegraphURL: string
/**
* Gets called when the user closed the sign in tab.
* Does not guarantee the sign in was sucessful.
*/
onSignInClose?: () => void
}>
> = ({ className, iconClassName, sourcegraphURL, onSignInClose }) => {
const signInUrl = createURLWithUTM(new URL('/sign-in?close=true', sourcegraphURL), {
utm_source: getPlatformName(),
utm_campaign: 'sign-in-button',

View File

@ -37,7 +37,9 @@ interface ViewOnSourcegraphButtonProps
onSignInClose?: () => void
}
export const ViewOnSourcegraphButton: React.FunctionComponent<ViewOnSourcegraphButtonProps> = ({
export const ViewOnSourcegraphButton: React.FunctionComponent<
React.PropsWithChildren<ViewOnSourcegraphButtonProps>
> = ({
codeHostType,
repoExistsOrError,
sourcegraphURL,
@ -142,11 +144,9 @@ interface ConfigureSourcegraphButtonProps extends Partial<SourcegraphIconButtonP
onConfigureSourcegraphClick?: React.MouseEventHandler<HTMLAnchorElement>
}
export const ConfigureSourcegraphButton: React.FunctionComponent<ConfigureSourcegraphButtonProps> = ({
onConfigureSourcegraphClick,
codeHostType,
...commonProps
}) => (
export const ConfigureSourcegraphButton: React.FunctionComponent<
React.PropsWithChildren<ConfigureSourcegraphButtonProps>
> = ({ onConfigureSourcegraphClick, codeHostType, ...commonProps }) => (
<SourcegraphIconButton
{...commonProps}
href={commonProps.href || new URL(snakeCase(codeHostType), 'https://docs.sourcegraph.com/integration/').href}

View File

@ -59,7 +59,7 @@ export interface CodeViewToolbarProps
hideActions?: boolean
}
export const CodeViewToolbar: React.FunctionComponent<CodeViewToolbarProps> = props => (
export const CodeViewToolbar: React.FunctionComponent<React.PropsWithChildren<CodeViewToolbarProps>> = props => (
<ul className={classNames(styles.codeViewToolbar, props.className)} data-testid="code-view-toolbar">
{!props.hideActions && (
<ActionsNavItems

View File

@ -15,7 +15,9 @@ interface Props extends PlatformContextProps<'sideloadedExtensionURL' | 'setting
sourcegraphURL: string
}
const makeExtensionLink = (sourcegraphURL: string): React.FunctionComponent<{ id: string }> => props => {
const makeExtensionLink = (
sourcegraphURL: string
): React.FunctionComponent<React.PropsWithChildren<{ id: string }>> => props => {
const extensionURL = new URL(sourcegraphURL)
extensionURL.pathname = `extensions/${props.id}`
return <Link to={extensionURL.href}>{props.id}</Link>
@ -24,7 +26,7 @@ const makeExtensionLink = (sourcegraphURL: string): React.FunctionComponent<{ id
/**
* A global debug toolbar shown in the bottom right of the window.
*/
export const GlobalDebug: React.FunctionComponent<Props> = props => (
export const GlobalDebug: React.FunctionComponent<React.PropsWithChildren<Props>> = props => (
<div className="navbar navbar-expand" data-global-debug={true}>
<div className="navbar-nav align-items-center">
<div className="nav-item">

View File

@ -14,7 +14,7 @@ interface Props extends SourcegraphIconButtonProps {
openProps: OpenInSourcegraphProps
}
export const OpenOnSourcegraph: React.FunctionComponent<Props> = ({
export const OpenOnSourcegraph: React.FunctionComponent<React.PropsWithChildren<Props>> = ({
openProps: { sourcegraphURL, repoName, revision, filePath },
className,
...props

View File

@ -14,7 +14,7 @@ export interface SourcegraphIconButtonProps
dataTestId?: string
}
export const SourcegraphIconButton: React.FunctionComponent<SourcegraphIconButtonProps> = ({
export const SourcegraphIconButton: React.FunctionComponent<React.PropsWithChildren<SourcegraphIconButtonProps>> = ({
iconClassName,
label,
ariaLabel,

View File

@ -8,7 +8,7 @@ interface TrackAnchorClickProps {
/**
* Track all anchor link clicks in children components
*/
export const TrackAnchorClick: React.FunctionComponent<TrackAnchorClickProps> = ({
export const TrackAnchorClick: React.FunctionComponent<React.PropsWithChildren<TrackAnchorClickProps>> = ({
children,
onClick,
as: Tag = 'div',

View File

@ -2,6 +2,7 @@ import React from 'react'
import { WildcardTheme, WildcardThemeContext } from '@sourcegraph/wildcard'
export const WildcardThemeProvider: React.FunctionComponent<WildcardTheme> = ({ children, ...props }) => (
<WildcardThemeContext.Provider value={props}>{children}</WildcardThemeContext.Provider>
)
export const WildcardThemeProvider: React.FunctionComponent<React.PropsWithChildren<WildcardTheme>> = ({
children,
...props
}) => <WildcardThemeContext.Provider value={props}>{children}</WildcardThemeContext.Provider>

View File

@ -24,7 +24,11 @@ interface Props {
onOpen: (match: ContentMatch, lineIndex: number) => void
}
export const App: React.FunctionComponent<Props> = ({ onPreviewChange, onPreviewClear, onOpen }: Props) => {
export const App: React.FunctionComponent<React.PropsWithChildren<Props>> = ({
onPreviewChange,
onPreviewClear,
onOpen,
}: Props) => {
const [caseSensitive, setCaseSensitivity] = useState(false)
const [patternType, setPatternType] = useState(SearchPatternType.literal)
const [results, setResults] = useState<SearchMatch[]>([])

View File

@ -9,10 +9,9 @@ interface SyntaxHighlightedSearchQueryProps extends React.HTMLAttributes<HTMLSpa
}
// A read-only syntax highlighted search query
export const SyntaxHighlightedSearchQuery: React.FunctionComponent<SyntaxHighlightedSearchQueryProps> = ({
query,
...otherProps
}) => {
export const SyntaxHighlightedSearchQuery: React.FunctionComponent<
React.PropsWithChildren<SyntaxHighlightedSearchQueryProps>
> = ({ query, ...otherProps }) => {
const tokens = useMemo(() => {
const scannedQuery = scanSearchQuery(query)
return scannedQuery.type === 'success'

View File

@ -19,7 +19,7 @@ interface ModalVideoProps {
assetsRoot?: string
}
export const ModalVideo: React.FunctionComponent<ModalVideoProps> = ({
export const ModalVideo: React.FunctionComponent<React.PropsWithChildren<ModalVideoProps>> = ({
id,
title,
src,

View File

@ -49,7 +49,7 @@ const replacePattern = /[\n\r↵]/g
* - Not supplying 'onSubmit' and setting 'preventNewLine' to false will result
* in a new line being added when Enter is pressed
*/
export const CodeMirrorMonacoFacade: React.FunctionComponent<MonacoQueryInputProps> = ({
export const CodeMirrorMonacoFacade: React.FunctionComponent<React.PropsWithChildren<MonacoQueryInputProps>> = ({
patternType,
selectedSearchContextSpec,
queryState,
@ -251,7 +251,7 @@ interface CodeMirrorQueryInputProps extends ThemeProps, SearchPatternTypeProps {
* "Core" codemirror query input component. Provides the basic behavior such as
* theming, syntax highlighting and token info.
*/
const CodeMirrorQueryInput: React.FunctionComponent<CodeMirrorQueryInputProps> = React.memo(
const CodeMirrorQueryInput: React.FunctionComponent<React.PropsWithChildren<CodeMirrorQueryInputProps>> = React.memo(
({ isLightTheme, onEditorCreated, patternType, interpretComments, value, className, extensions = [] }) => {
// This is using state instead of a ref because `useRef` doesn't cause a
// re-render when the ref is attached, but we need that so that

View File

@ -41,10 +41,9 @@ function highlightSearchContextSpecPart(specPart?: string, highlightPart?: strin
return specPart && highlightPart ? <>{highlightText(specPart, highlightPart, styles.itemHighlighted)}</> : specPart
}
export const HighlightedSearchContextSpec: React.FunctionComponent<{ spec: string; searchFilter: string }> = ({
spec,
searchFilter,
}) => {
export const HighlightedSearchContextSpec: React.FunctionComponent<
React.PropsWithChildren<{ spec: string; searchFilter: string }>
> = ({ spec, searchFilter }) => {
if (searchFilter.length === 0) {
return <>{spec}</>
}

View File

@ -24,7 +24,7 @@ const CodemirrorQueryInput = lazyComponent(() => import('./CodeMirrorQueryInput'
* It has no suggestions, but still allows to type in and submit queries.
*/
export const PlainQueryInput: React.FunctionComponent<
Pick<MonacoQueryInputProps, 'queryState' | 'autoFocus' | 'onChange' | 'className'>
React.PropsWithChildren<Pick<MonacoQueryInputProps, 'queryState' | 'autoFocus' | 'onChange' | 'className'>>
> = ({ queryState, autoFocus, onChange, className }) => {
const onInputChange = React.useCallback(
(event: React.ChangeEvent<HTMLInputElement>) => {
@ -54,7 +54,7 @@ export interface LazyMonacoQueryInputProps extends MonacoQueryInputProps {
/**
* A lazily-loaded {@link MonacoQueryInput}, displaying a read-only query field as a fallback during loading.
*/
export const LazyMonacoQueryInput: React.FunctionComponent<LazyMonacoQueryInputProps> = ({
export const LazyMonacoQueryInput: React.FunctionComponent<React.PropsWithChildren<LazyMonacoQueryInputProps>> = ({
editorComponent,
...props
}) => {

View File

@ -152,7 +152,7 @@ export const toMonacoSelection = (range: Monaco.IRange): Monaco.ISelection => ({
* This component should not be imported directly: use {@link LazyMonacoQueryInput} instead
* to avoid bundling the Monaco editor on every page.
*/
export const MonacoQueryInput: React.FunctionComponent<MonacoQueryInputProps> = ({
export const MonacoQueryInput: React.FunctionComponent<React.PropsWithChildren<MonacoQueryInputProps>> = ({
queryState,
onFocus,
onBlur,

View File

@ -60,7 +60,7 @@ export interface SearchBoxProps
onEditorCreated?: (editor: IEditor) => void
}
export const SearchBox: React.FunctionComponent<SearchBoxProps> = props => {
export const SearchBox: React.FunctionComponent<React.PropsWithChildren<SearchBoxProps>> = props => {
const { queryState, onEditorCreated: onEditorCreatedCallback } = props
const [editor, setEditor] = useState<IEditor>()

View File

@ -21,7 +21,7 @@ interface Props extends TelemetryProps {
* A search button with a dropdown with related links. It must be wrapped in a form whose onSubmit
* handler performs the search.
*/
export const SearchButton: React.FunctionComponent<Props> = ({
export const SearchButton: React.FunctionComponent<React.PropsWithChildren<Props>> = ({
hideHelpButton,
className,
isSourcegraphDotCom,

View File

@ -17,7 +17,7 @@ export interface SearchContextCtaPromptProps extends TelemetryProps {
isExternalServicesUserModeAll?: boolean
}
export const SearchContextCtaPrompt: React.FunctionComponent<SearchContextCtaPromptProps> = ({
export const SearchContextCtaPrompt: React.FunctionComponent<React.PropsWithChildren<SearchContextCtaPromptProps>> = ({
authenticatedUser,
hasUserAddedExternalServices,
telemetryService,

View File

@ -31,7 +31,9 @@ export interface SearchContextDropdownProps
isExternalServicesUserModeAll?: boolean
}
export const SearchContextDropdown: React.FunctionComponent<SearchContextDropdownProps> = props => {
export const SearchContextDropdown: React.FunctionComponent<
React.PropsWithChildren<SearchContextDropdownProps>
> = props => {
const {
isSourcegraphDotCom,
authenticatedUser,

View File

@ -28,16 +28,18 @@ import { HighlightedSearchContextSpec } from './HighlightedSearchContextSpec'
import styles from './SearchContextMenu.module.scss'
export const SearchContextMenuItem: React.FunctionComponent<
{
spec: string
description: string
query: string
selected: boolean
isDefault: boolean
selectSearchContextSpec: (spec: string) => void
searchFilter: string
onKeyDown: (key: string) => void
} & TelemetryProps
React.PropsWithChildren<
{
spec: string
description: string
query: string
selected: boolean
isDefault: boolean
selectSearchContextSpec: (spec: string) => void
searchFilter: string
onKeyDown: (key: string) => void
} & TelemetryProps
>
> = ({
spec,
description,
@ -114,7 +116,7 @@ const searchContextsPerPageToLoad = 15
const getSearchContextMenuItem = (spec: string): HTMLButtonElement | null =>
document.querySelector(`[data-search-context-spec="${spec}"]`)
export const SearchContextMenu: React.FunctionComponent<SearchContextMenuProps> = ({
export const SearchContextMenu: React.FunctionComponent<React.PropsWithChildren<SearchContextMenuProps>> = ({
authenticatedUser,
selectedSearchContextSpec,
defaultSearchContextSpec,

View File

@ -28,10 +28,9 @@ interface SearchHelpDropdownButtonProps extends TelemetryProps {
* A dropdown button that shows a menu with reference documentation for Sourcegraph search query
* syntax.
*/
export const SearchHelpDropdownButton: React.FunctionComponent<SearchHelpDropdownButtonProps> = ({
isSourcegraphDotCom,
telemetryService,
}) => {
export const SearchHelpDropdownButton: React.FunctionComponent<
React.PropsWithChildren<SearchHelpDropdownButtonProps>
> = ({ isSourcegraphDotCom, telemetryService }) => {
const [isOpen, setIsOpen] = useState(false)
const toggleIsOpen = useCallback(() => setIsOpen(!isOpen), [isOpen])
const onQueryDocumentationLinkClicked = useCallback(() => {

View File

@ -20,7 +20,7 @@ interface Props {
/**
* A repository header action that copies the current page's URL to the clipboard.
*/
export const CopyQueryButton: React.FunctionComponent<Props> = (props: Props) => {
export const CopyQueryButton: React.FunctionComponent<React.PropsWithChildren<Props>> = (props: Props) => {
// Convoluted, but using props.fullQuery directly in the copyFullQuery callback does not work, since
// props.fullQuery is not refrenced during the render and it is not updated within the callback.
const fullQueryReference = useRef<string>('')

View File

@ -36,7 +36,11 @@ export interface ToggleProps {
/**
* A toggle displayed in the QueryInput.
*/
export const QueryInputToggle: React.FunctionComponent<ToggleProps> = ({ onToggle, interactive = true, ...props }) => {
export const QueryInputToggle: React.FunctionComponent<React.PropsWithChildren<ToggleProps>> = ({
onToggle,
interactive = true,
...props
}) => {
const toggleCheckbox = useRef<HTMLDivElement | null>(null)
const disabledRule = useMemo(() => props.disableOn?.find(({ condition }) => condition), [props.disableOn])

View File

@ -59,7 +59,7 @@ export const getFullQuery = (
/**
* The toggles displayed in the query input.
*/
export const Toggles: React.FunctionComponent<TogglesProps> = (props: TogglesProps) => {
export const Toggles: React.FunctionComponent<React.PropsWithChildren<TogglesProps>> = (props: TogglesProps) => {
const {
navbarSearchQuery,
patternType,

View File

@ -56,128 +56,128 @@ function arrow(x: number, width: number, position: 'above' | 'below'): React.Rea
)
}
export const AnnotatedSearchInput: React.FunctionComponent<{ showSearchContext: boolean }> = React.memo(
({ showSearchContext }) => {
// I'd like to say that there is a logic behind these numbers but it's
// mostly trial and error.
const inputStart = showSearchContext ? 56.5 : 178
const filterTextStart = 116 + (showSearchContext ? 0 : 30)
const viewBoxX = showSearchContext ? 55 : filterTextStart
const width = 736 - viewBoxX
const height = showSearchContext ? 222 : 222
export const AnnotatedSearchInput: React.FunctionComponent<
React.PropsWithChildren<{ showSearchContext: boolean }>
> = React.memo(({ showSearchContext }) => {
// I'd like to say that there is a logic behind these numbers but it's
// mostly trial and error.
const inputStart = showSearchContext ? 56.5 : 178
const filterTextStart = 116 + (showSearchContext ? 0 : 30)
const viewBoxX = showSearchContext ? 55 : filterTextStart
const width = 736 - viewBoxX
const height = showSearchContext ? 222 : 222
return (
// the viewBox is adjusted to "crop" the image to its content
// Original width and height of the image was 800x270
<svg
className={styles.annotatedSearchInput}
width={width}
height={height}
viewBox={`${viewBoxX} 35 ${width} ${height}`}
preserveAspectRatio="xMidYMid meet"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<g>
<path
d={`M ${inputStart} 113 c 0 -1.381 1.1193 -2.5 2.5 -2.5 H 688.5 v 33 H ${
inputStart + 2.5
} c -1.3807 0 -2.5 -1.119 -2.5 -2.5 v -28 z`}
className={styles.searchBox}
/>
{showSearchContext && (
<>
<text className={styles.code} x="68" y="130.836">
<tspan className={styles.filter}>context:</tspan>
<tspan>global</tspan>
</text>
<line className={styles.separator} x1="178" y1="118" x2="178" y2="137" />
</>
)}
<text className={styles.code} x="171.852" y="130.836">
<tspan className={styles.filter}>{' '}repo:</tspan>
<tspan>sourcegraph/sourcegraph</tspan>
<tspan className={styles.metaRegexpCharacterSet}>.</tspan>
<tspan className={styles.metaRegexpRangeQuantifier}>*</tspan>
<tspan> function auth(){'{'} </tspan>
</text>
<Icon x="590" y="115" as={FormatLetterCaseIcon} />
<Icon x="620" y="115" as={RegexIcon} />
<Icon x="650" y="115" as={CodeBracketsIcon} />
<path
d="M688 110H731C732.105 110 733 110.895 733 112V142C733 143.105 732.105 144 731 144H688V110Z"
fill="#1475CF"
/>
<Icon className={styles.searchIcon} x="698" y="115" as={SearchIcon} />
return (
// the viewBox is adjusted to "crop" the image to its content
// Original width and height of the image was 800x270
<svg
className={styles.annotatedSearchInput}
width={width}
height={height}
viewBox={`${viewBoxX} 35 ${width} ${height}`}
preserveAspectRatio="xMidYMid meet"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<g>
<path
d={`M ${inputStart} 113 c 0 -1.381 1.1193 -2.5 2.5 -2.5 H 688.5 v 33 H ${
inputStart + 2.5
} c -1.3807 0 -2.5 -1.119 -2.5 -2.5 v -28 z`}
className={styles.searchBox}
/>
{showSearchContext && (
<>
<text className={styles.code} x="68" y="130.836">
<tspan className={styles.filter}>context:</tspan>
<tspan>global</tspan>
</text>
<line className={styles.separator} x1="178" y1="118" x2="178" y2="137" />
</>
)}
<text className={styles.code} x="171.852" y="130.836">
<tspan className={styles.filter}>{' '}repo:</tspan>
<tspan>sourcegraph/sourcegraph</tspan>
<tspan className={styles.metaRegexpCharacterSet}>.</tspan>
<tspan className={styles.metaRegexpRangeQuantifier}>*</tspan>
<tspan> function auth(){'{'} </tspan>
</text>
<Icon x="590" y="115" as={FormatLetterCaseIcon} />
<Icon x="620" y="115" as={RegexIcon} />
<Icon x="650" y="115" as={CodeBracketsIcon} />
<path
d="M688 110H731C732.105 110 733 110.895 733 112V142C733 143.105 732.105 144 731 144H688V110Z"
fill="#1475CF"
/>
<Icon className={styles.searchIcon} x="698" y="115" as={SearchIcon} />
{arrow(188, 30, 'above')}
<text transform={`translate(${filterTextStart}, 44)`}>
<tspan x="0" y="0">
Filters scope your search to repos,{' '}
</tspan>
<tspan x="0" y="16">
orgs, languages, and more.
</tspan>
</text>
{arrow(188, 30, 'above')}
<text transform={`translate(${filterTextStart}, 44)`}>
<tspan x="0" y="0">
Filters scope your search to repos,{' '}
</tspan>
<tspan x="0" y="16">
orgs, languages, and more.
</tspan>
</text>
{arrow(410, 120, 'above')}
<text transform="translate(395, 44)">
<tspan x="0" y="0">
By default, search terms are{' '}
</tspan>
<tspan x="0" y="16">
interpreted literally (without regexp).
</tspan>
</text>
{arrow(410, 120, 'above')}
<text transform="translate(395, 44)">
<tspan x="0" y="0">
By default, search terms are{' '}
</tspan>
<tspan x="0" y="16">
interpreted literally (without regexp).
</tspan>
</text>
{showSearchContext && (
<>
{arrow(68, 108, 'below')}
<text transform="translate(56, 200)">
<tspan x="0" y="0">
By default, Sourcegraph searches the{' '}
</tspan>
<tspan x="0" y="16">
<tspan className={styles.bold}>global </tspan>
context, which is publicly
</tspan>
<tspan x="0" y="32">
available code on code hosts such as{' '}
</tspan>
<tspan x="0" y="48">
GitHub and GitLab.
</tspan>
</text>
</>
)}
{showSearchContext && (
<>
{arrow(68, 108, 'below')}
<text transform="translate(56, 200)">
<tspan x="0" y="0">
By default, Sourcegraph searches the{' '}
</tspan>
<tspan x="0" y="16">
<tspan className={styles.bold}>global </tspan>
context, which is publicly
</tspan>
<tspan x="0" y="32">
available code on code hosts such as{' '}
</tspan>
<tspan x="0" y="48">
GitHub and GitLab.
</tspan>
</text>
</>
)}
{arrow(387, 16, 'below')}
<text transform="translate(340, 200)">
<tspan x="0" y="0">
You can use regexp inside{' '}
</tspan>
<tspan x="0" y="16">
filters, even when not in{' '}
</tspan>
<tspan x="0" y="32">
regexp mode
</tspan>
</text>
{arrow(387, 16, 'below')}
<text transform="translate(340, 200)">
<tspan x="0" y="0">
You can use regexp inside{' '}
</tspan>
<tspan x="0" y="16">
filters, even when not in{' '}
</tspan>
<tspan x="0" y="32">
regexp mode
</tspan>
</text>
{arrow(590, 82, 'below')}
<text transform="translate(538, 200)">
<tspan x="0" y="0">
Search can be case-sensitive{' '}
</tspan>
<tspan x="0" y="16">
one of three modes: literal{' '}
</tspan>
<tspan x="0" y="32">
(default), regexp or structural.
</tspan>
</text>
</g>
</svg>
)
}
)
{arrow(590, 82, 'below')}
<text transform="translate(538, 200)">
<tspan x="0" y="0">
Search can be case-sensitive{' '}
</tspan>
<tspan x="0" y="16">
one of three modes: literal{' '}
</tspan>
<tspan x="0" y="32">
(default), regexp or structural.
</tspan>
</text>
</g>
</svg>
)
})

View File

@ -32,7 +32,7 @@ interface SearchInputExampleProps {
onRun: () => void
}
const SearchInputExample: React.FunctionComponent<SearchInputExampleProps> = ({
const SearchInputExample: React.FunctionComponent<React.PropsWithChildren<SearchInputExampleProps>> = ({
showSearchContext,
query,
patternType = SearchPatternType.literal,
@ -129,7 +129,7 @@ interface ContainerProps {
onClose?: (sectionID: SectionID) => void
}
const Container: React.FunctionComponent<ContainerProps> = ({
const Container: React.FunctionComponent<React.PropsWithChildren<ContainerProps>> = ({
sectionID,
title,
children,
@ -179,7 +179,7 @@ interface NoResultsPageProps extends ThemeProps, TelemetryProps, Pick<SearchCont
assetsRoot?: string
}
export const NoResultsPage: React.FunctionComponent<NoResultsPageProps> = ({
export const NoResultsPage: React.FunctionComponent<React.PropsWithChildren<NoResultsPageProps>> = ({
searchContextsEnabled,
isLightTheme,
telemetryService,

View File

@ -10,10 +10,12 @@ import { StreamingProgressCount } from './progress/StreamingProgressCount'
import styles from './StreamingSearchResultsList.module.scss'
export const StreamingSearchResultFooter: React.FunctionComponent<{
results?: AggregateStreamingSearchResults
children?: React.ReactChild | React.ReactChild[]
}> = ({ results, children }) => (
export const StreamingSearchResultFooter: React.FunctionComponent<
React.PropsWithChildren<{
results?: AggregateStreamingSearchResults
children?: React.ReactChild | React.ReactChild[]
}>
> = ({ results, children }) => (
<div className={classNames(styles.contentCentered, 'd-flex flex-column align-items-center')}>
{(!results || results?.state === 'loading') && (
<div className="text-center my-4" data-testid="loading-container">

View File

@ -71,7 +71,9 @@ export interface StreamingSearchResultsListProps
resultClassName?: string
}
export const StreamingSearchResultsList: React.FunctionComponent<StreamingSearchResultsListProps> = ({
export const StreamingSearchResultsList: React.FunctionComponent<
React.PropsWithChildren<StreamingSearchResultsListProps>
> = ({
results,
allExpanded,
fetchHighlightedFileLineRanges,

View File

@ -12,7 +12,7 @@ export interface StreamingProgressProps {
onSearchAgain: (additionalFilters: string[]) => void
}
export const StreamingProgress: React.FunctionComponent<StreamingProgressProps> = props => (
export const StreamingProgress: React.FunctionComponent<React.PropsWithChildren<StreamingProgressProps>> = props => (
<>
<StreamingProgressCount {...props} />
<StreamingProgressSkippedButton {...props} />

View File

@ -28,7 +28,7 @@ const abbreviateNumber = (number: number): string => {
const limitHit = (progress: Progress): boolean => progress.skipped.some(skipped => skipped.reason.indexOf('-limit') > 0)
export const StreamingProgressCount: React.FunctionComponent<
Pick<StreamingProgressProps, 'progress' | 'state' | 'showTrace'> & { className?: string }
React.PropsWithChildren<Pick<StreamingProgressProps, 'progress' | 'state' | 'showTrace'> & { className?: string }>
> = ({ progress, state, showTrace, className = '' }) => (
<>
<small

View File

@ -11,7 +11,7 @@ import { StreamingProgressSkippedPopover } from './StreamingProgressSkippedPopov
import styles from './StreamingProgressSkippedButton.module.scss'
export const StreamingProgressSkippedButton: React.FunctionComponent<
Pick<StreamingProgressProps, 'progress' | 'onSearchAgain'>
React.PropsWithChildren<Pick<StreamingProgressProps, 'progress' | 'onSearchAgain'>>
> = ({ progress, onSearchAgain }) => {
const [isOpen, setIsOpen] = useState(false)

View File

@ -37,7 +37,10 @@ const sortBySeverity = (a: Skipped, b: Skipped): number => {
return aSev - bSev
}
const SkippedMessage: React.FunctionComponent<{ skipped: Skipped; startOpen: boolean }> = ({ skipped, startOpen }) => {
const SkippedMessage: React.FunctionComponent<React.PropsWithChildren<{ skipped: Skipped; startOpen: boolean }>> = ({
skipped,
startOpen,
}) => {
// Reactstrap is preventing default behavior on all non-DropdownItem elements inside a Dropdown,
// so we need to stop propagation to allow normal behavior (e.g. enter and space to activate buttons)
// See Reactstrap bug: https://github.com/reactstrap/reactstrap/issues/2099
@ -100,7 +103,7 @@ const SkippedMessage: React.FunctionComponent<{ skipped: Skipped; startOpen: boo
}
export const StreamingProgressSkippedPopover: React.FunctionComponent<
Pick<StreamingProgressProps, 'progress' | 'onSearchAgain'>
React.PropsWithChildren<Pick<StreamingProgressProps, 'progress' | 'onSearchAgain'>>
> = ({ progress, onSearchAgain }) => {
const [selectedSuggestedSearches, setSelectedSuggestedSearches] = useState(new Set<string>())
const submitHandler = useCallback(

View File

@ -25,7 +25,7 @@ export interface FilterLinkProps {
onFilterChosen: (value: string) => void
}
export const FilterLink: React.FunctionComponent<FilterLinkProps> = ({
export const FilterLink: React.FunctionComponent<React.PropsWithChildren<FilterLinkProps>> = ({
label,
value,
count,

View File

@ -341,7 +341,10 @@ interface SearchReferenceExampleProps {
onClick?: (example: string) => void
}
const SearchReferenceExample: React.FunctionComponent<SearchReferenceExampleProps> = ({ example, onClick }) => {
const SearchReferenceExample: React.FunctionComponent<React.PropsWithChildren<SearchReferenceExampleProps>> = ({
example,
onClick,
}) => {
// All current examples are literal queries
const scanResult = scanSearchQuery(example, false, SearchPatternType.literal)
// We only use valid queries as examples, so this will always be true

View File

@ -71,7 +71,7 @@ const selectFromQueryState = ({
submitSearch,
})
export const SearchSidebar: React.FunctionComponent<SearchSidebarProps> = props => {
export const SearchSidebar: React.FunctionComponent<React.PropsWithChildren<SearchSidebarProps>> = props => {
const history = useHistory()
const [collapsedSections, setCollapsedSections] = useTemporarySetting('search.collapsedSidebarSections', {})

View File

@ -10,26 +10,28 @@ import { FilterLink, FilterLinkProps } from './FilterLink'
import styles from './SearchSidebarSection.module.scss'
export const SearchSidebarSection: React.FunctionComponent<{
sectionId: string
header: string
children?: React.ReactElement | React.ReactElement[] | ((filter: string) => React.ReactElement)
className?: string
showSearch?: boolean // Search only works if children are FilterLink
onToggle?: (id: string, open: boolean) => void
startCollapsed?: boolean
/**
* Shown when the built-in search doesn't find any results.
*/
noResultText?: React.ReactElement | string
/**
* Clear the search input whenever this value changes. This is supposed to
* be used together with function children, which use the search input but
* handle search on their own.
* Defaults to the component's children.
*/
clearSearchOnChange?: {}
}> = React.memo(
export const SearchSidebarSection: React.FunctionComponent<
React.PropsWithChildren<{
sectionId: string
header: string
children?: React.ReactElement | React.ReactElement[] | ((filter: string) => React.ReactElement)
className?: string
showSearch?: boolean // Search only works if children are FilterLink
onToggle?: (id: string, open: boolean) => void
startCollapsed?: boolean
/**
* Shown when the built-in search doesn't find any results.
*/
noResultText?: React.ReactElement | string
/**
* Clear the search input whenever this value changes. This is supposed to
* be used together with function children, which use the search input but
* handle search on their own.
* Defaults to the component's children.
*/
clearSearchOnChange?: {}
}>
> = React.memo(
({
sectionId,
header,

View File

@ -38,7 +38,7 @@ interface SearchTypeLinkProps extends SearchTypeLinksProps {
* SearchTypeLink renders to a Link which immediately triggers a new search when
* clicked.
*/
const SearchTypeLink: React.FunctionComponent<SearchTypeLinkProps> = ({
const SearchTypeLink: React.FunctionComponent<React.PropsWithChildren<SearchTypeLinkProps>> = ({
type,
query,
selectedSearchContextSpec,
@ -66,7 +66,10 @@ interface SearchTypeButtonProps {
* SearchTypeButton renders to a button which updates the query state without
* triggering a search. This allows users to adjust the query.
*/
const SearchTypeButton: React.FunctionComponent<SearchTypeButtonProps> = ({ children, onClick }) => (
const SearchTypeButton: React.FunctionComponent<React.PropsWithChildren<SearchTypeButtonProps>> = ({
children,
onClick,
}) => (
<Button
className={classNames(styles.sidebarSectionListItem, styles.sidebarSectionButtonLink, 'flex-1')}
value={children}
@ -83,7 +86,7 @@ const SearchTypeButton: React.FunctionComponent<SearchTypeButtonProps> = ({ chil
* patterns) or whether to allow the user to complete query and triggering it
* themselves.
*/
const SearchSymbol: React.FunctionComponent<Omit<SearchTypeLinkProps, 'type'>> = props => {
const SearchSymbol: React.FunctionComponent<React.PropsWithChildren<Omit<SearchTypeLinkProps, 'type'>>> = props => {
const type = 'symbol'
const { query, onNavbarQueryChange } = props

View File

@ -21,9 +21,11 @@ export const SearchQueryStateStoreContext = createContext<SearchQueryStateStore
* Example: Both the VS Code extension and the web app render `<SearchSidebar>`, so it needs to
* reference the appropriate zustand store through context (provided here).
*/
export const SearchQueryStateStoreProvider: React.FunctionComponent<{
useSearchQueryState: SearchQueryStateStore
}> = ({ children, useSearchQueryState }) => (
export const SearchQueryStateStoreProvider: React.FunctionComponent<
React.PropsWithChildren<{
useSearchQueryState: SearchQueryStateStore
}>
> = ({ children, useSearchQueryState }) => (
<SearchQueryStateStoreContext.Provider value={useSearchQueryState}>
{children}
</SearchQueryStateStoreContext.Provider>

View File

@ -39,7 +39,7 @@ interface Props extends ActionsProps, TelemetryProps {
}
/** Displays the actions in a container, with a wrapper and/or empty element. */
export const ActionsContainer: React.FunctionComponent<Props> = props => {
export const ActionsContainer: React.FunctionComponent<React.PropsWithChildren<Props>> = props => {
const { scope, extraContext, returnInactiveMenuItems, extensionsController, menu, empty } = props
const contributions = useObservable(

View File

@ -67,7 +67,7 @@ export interface ActionsNavItemsProps
* Renders the actions as a fragment of <li class="nav-item"> elements, for use in a Bootstrap <ul
* class="nav"> or <ul class="navbar-nav">.
*/
export const ActionsNavItems: React.FunctionComponent<ActionsNavItemsProps> = props => {
export const ActionsNavItems: React.FunctionComponent<React.PropsWithChildren<ActionsNavItemsProps>> = props => {
const { scope, extraContext, extensionsController, menu, wrapInList, transformContributions = identity } = props
const scopeChanges = useMemo(() => new ReplaySubject<ContributionScope>(1), [])

View File

@ -374,7 +374,9 @@ export interface CommandListPopoverButtonProps
keyboardShortcutForShow?: KeyboardShortcut
}
export const CommandListPopoverButton: React.FunctionComponent<CommandListPopoverButtonProps> = ({
export const CommandListPopoverButton: React.FunctionComponent<
React.PropsWithChildren<CommandListPopoverButtonProps>
> = ({
buttonClassName,
buttonElement = 'span',
buttonOpenClassName,

View File

@ -14,7 +14,10 @@ interface Props {
sourcegraphURL: string
}
export const EmptyCommandList: React.FunctionComponent<Props> = ({ settingsCascade, sourcegraphURL }) => {
export const EmptyCommandList: React.FunctionComponent<React.PropsWithChildren<Props>> = ({
settingsCascade,
sourcegraphURL,
}) => {
// if no settings cascade, default to 'no active extensions'
const onlyDefault = settingsCascade ? onlyDefaultExtensionsAdded(settingsCascade) : false

View File

@ -6,11 +6,9 @@ import styles from './EmptyCommandListContainer.module.scss'
type EmptyCommandListContainerProps = HTMLAttributes<HTMLDivElement>
export const EmptyCommandListContainer: React.FunctionComponent<EmptyCommandListContainerProps> = ({
className,
children,
...rest
}) => (
export const EmptyCommandListContainer: React.FunctionComponent<
React.PropsWithChildren<EmptyCommandListContainerProps>
> = ({ className, children, ...rest }) => (
<div className={classNames(styles.emptyCommandList, className)} {...rest}>
{children}
</div>

View File

@ -25,7 +25,7 @@ export interface CtaAlertProps {
onClose: () => void
}
export const CtaAlert: React.FunctionComponent<CtaAlertProps> = props => (
export const CtaAlert: React.FunctionComponent<React.PropsWithChildren<CtaAlertProps>> = props => (
<Card
className={classNames(
'my-2',

View File

@ -147,7 +147,7 @@ function navigateToFileOnMiddleMouseButtonClick(event: MouseEvent<HTMLElement>):
}
}
export const FileMatchChildren: React.FunctionComponent<FileMatchProps> = props => {
export const FileMatchChildren: React.FunctionComponent<React.PropsWithChildren<FileMatchProps>> = props => {
// If optimizeHighlighting is enabled, compile a list of the highlighted file ranges we want to
// fetch (instead of the entire file.)
const optimizeHighlighting =

View File

@ -83,7 +83,7 @@ const BY_LINE_RANKING = 'by-line-number'
const DEFAULT_CONTEXT = 1
// This is a search result for types file (content), path, or symbol.
export const FileSearchResult: React.FunctionComponent<Props> = props => {
export const FileSearchResult: React.FunctionComponent<React.PropsWithChildren<Props>> = props => {
const result = props.result
const repoAtRevisionURL = getRepositoryUrl(result.repository, result.branches)
const revisionDisplayName = getRevision(result.branches, result.commit)

View File

@ -1,16 +1,18 @@
import * as React from 'react'
/** Wraps matches of pattern in text with <strong>. */
export const HighlightedMatches: React.FunctionComponent<{
/* The text to display matches in. */
text: string
export const HighlightedMatches: React.FunctionComponent<
React.PropsWithChildren<{
/* The text to display matches in. */
text: string
/* The pattern to highlight in the text. */
pattern: string
/* The pattern to highlight in the text. */
pattern: string
/** The class name for the <strong> element for matches. */
className?: string
}> = ({ text, pattern, className }) => (
/** The class name for the <strong> element for matches. */
className?: string
}>
> = ({ text, pattern, className }) => (
<span>
{fuzzyMatches(text.toLowerCase(), pattern.toLowerCase()).map((span, index) =>
span.match ? (

View File

@ -13,7 +13,7 @@ export interface Props {
className?: string
}
export const LastSyncedIcon: React.FunctionComponent<Props> = props => {
export const LastSyncedIcon: React.FunctionComponent<React.PropsWithChildren<Props>> = props => {
const formattedTime = format(Date.parse(props.lastSyncedTime), "yyyy-MM-dd'T'HH:mm:ss")
return (

View File

@ -9,10 +9,12 @@ import { Link } from '@sourcegraph/wildcard'
* text in a <span> (with no link).
*/
export const LinkOrSpan: React.FunctionComponent<
{
to: LocationDescriptor | undefined | null
children?: React.ReactNode
} & React.AnchorHTMLAttributes<HTMLAnchorElement>
React.PropsWithChildren<
{
to: LocationDescriptor | undefined | null
children?: React.ReactNode
} & React.AnchorHTMLAttributes<HTMLAnchorElement>
>
> = ({ to, className = '', children, ...otherProps }) => {
if (to) {
return (

View File

@ -3,7 +3,7 @@ import React from 'react'
/**
* Displays a "/"-separated path with the last path component bolded.
*/
export const Path: React.FunctionComponent<{ path: string }> = ({ path }) => {
export const Path: React.FunctionComponent<React.PropsWithChildren<{ path: string }>> = ({ path }) => {
if (path === '') {
return null
}

View File

@ -37,7 +37,7 @@ interface Props {
* A link to a repository or a file within a repository, formatted as "repo" or "repo > file". Unless you
* absolutely need breadcrumb-like behavior, use this instead of FilePathBreadcrumb.
*/
export const RepoFileLink: React.FunctionComponent<Props> = ({
export const RepoFileLink: React.FunctionComponent<React.PropsWithChildren<Props>> = ({
repoDisplayName,
repoName,
repoURL,

View File

@ -10,11 +10,11 @@ import { Icon } from '@sourcegraph/wildcard'
/**
* Returns the icon for the repository's code host
*/
export const RepoIcon: React.FunctionComponent<{ repoName: string; className?: string }> = ({
export const RepoIcon: React.FunctionComponent<React.PropsWithChildren<{ repoName: string; className?: string }>> = ({
repoName,
className,
}) => {
const iconMap: { [key: string]: React.ComponentType<MdiReactIconProps> } = {
const iconMap: { [key: string]: React.ComponentType<React.PropsWithChildren<MdiReactIconProps>> } = {
'github.com': GithubIcon,
'gitlab.com': GitlabIcon,
'bitbucket.com': BitbucketIcon,
@ -22,7 +22,7 @@ export const RepoIcon: React.FunctionComponent<{ repoName: string; className?: s
const hostName = repoName.split('/')[0]
const CodehostIcon: React.ComponentType<MdiReactIconProps> | undefined = iconMap[hostName]
const CodehostIcon: React.ComponentType<React.PropsWithChildren<MdiReactIconProps>> | undefined = iconMap[hostName]
if (CodehostIcon) {
return (

View File

@ -19,7 +19,7 @@ interface Props {
onClick?: React.MouseEventHandler<HTMLElement>
}
export const RepoLink: React.FunctionComponent<Props> = ({
export const RepoLink: React.FunctionComponent<React.PropsWithChildren<Props>> = ({
repoName: fullRepoName,
to,
className,

View File

@ -110,7 +110,7 @@ export interface Props {
/**
* The container component for a result in the SearchResults component.
*/
export const ResultContainer: React.FunctionComponent<Props> = ({
export const ResultContainer: React.FunctionComponent<React.PropsWithChildren<Props>> = ({
defaultExpanded,
allExpanded,
collapsible,

View File

@ -4,4 +4,6 @@ import StarIcon from 'mdi-react/StarIcon'
import styles from './SearchResultStar.module.scss'
export const SearchResultStar: React.FunctionComponent = () => <StarIcon className={styles.star} />
export const SearchResultStar: React.FunctionComponent<React.PropsWithChildren<unknown>> = () => (
<StarIcon className={styles.star} />
)

View File

@ -21,10 +21,9 @@ interface ActivationChecklistItemProps extends ActivationStep {
/**
* A single item in the activation checklist.
*/
export const ActivationChecklistItem: React.FunctionComponent<ActivationChecklistItemProps> = ({
className = '',
...props
}: ActivationChecklistItemProps) => (
export const ActivationChecklistItem: React.FunctionComponent<
React.PropsWithChildren<ActivationChecklistItemProps>
> = ({ className = '', ...props }: ActivationChecklistItemProps) => (
<div className={classNames('d-flex justify-content-between', styles.activationChecklistItem, className)}>
<div className="d-flex align-items-center">
<Icon className={classNames(styles.iconContainer, styles.iconDown)} as="span">
@ -55,7 +54,7 @@ export interface ActivationChecklistProps {
/**
* Renders an activation checklist.
*/
export const ActivationChecklist: React.FunctionComponent<ActivationChecklistProps> = ({
export const ActivationChecklist: React.FunctionComponent<React.PropsWithChildren<ActivationChecklistProps>> = ({
className,
steps,
completed,

View File

@ -18,25 +18,25 @@ function sizeProps(props: IconProps): { width: number; height: number; viewBox:
}
}
export const ChatIcon: React.FunctionComponent<IconProps> = props => (
export const ChatIcon: React.FunctionComponent<React.PropsWithChildren<IconProps>> = props => (
<svg {...props} {...sizeProps(props)} className={classNames('mdi-icon', props.className)}>
<path d="M 2 11.636 A 10 8 0 0 0 4.75 17.146 A 9 9 0 0 1 2 21.636 A 10.4 10.4 0 0 0 8.5 19.13 A 10 8 0 0 0 12 19.636 A 10 8 0 0 0 22 11.636 A 10 8 0 0 0 12 3.636 A 10 8 0 0 0 2 11.636 Z" />
</svg>
)
export const CircleChevronLeftIcon: React.FunctionComponent<IconProps> = props => (
export const CircleChevronLeftIcon: React.FunctionComponent<React.PropsWithChildren<IconProps>> = props => (
<svg {...props} {...sizeProps(props)} className={classNames('mdi-icon', props.className)}>
<path d="M22,12c0,5.5-4.5,10-10,10S2,17.5,2,12S6.5,2,12,2S22,6.5,22,12z M15.4,16.6L10.8,12l4.6-4.6L14,6l-6,6l6,6L15.4,16.6z" />
</svg>
)
export const CircleChevronRightIcon: React.FunctionComponent<IconProps> = props => (
export const CircleChevronRightIcon: React.FunctionComponent<React.PropsWithChildren<IconProps>> = props => (
<svg {...props} {...sizeProps(props)} className={classNames('mdi-icon', props.className)}>
<path d="M22,12c0,5.5-4.5,10-10,10S2,17.5,2,12S6.5,2,12,2S22,6.5,22,12z M10,18l6-6l-6-6L8.6,7.4l4.6,4.6l-4.6,4.6L10,18z" />
</svg>
)
export const RepoQuestionIcon: React.FunctionComponent<IconProps> = props => (
export const RepoQuestionIcon: React.FunctionComponent<React.PropsWithChildren<IconProps>> = props => (
<svg {...props} {...sizeProps(props)} className={classNames('mdi-icon', props.className)} viewBox="0 0 64 64">
<title>Icons 400</title>
<g>
@ -52,13 +52,13 @@ export const RepoQuestionIcon: React.FunctionComponent<IconProps> = props => (
</svg>
)
export const FormatListBulletedIcon: React.FunctionComponent<IconProps> = props => (
export const FormatListBulletedIcon: React.FunctionComponent<React.PropsWithChildren<IconProps>> = props => (
<svg {...props} {...sizeProps(props)} className={classNames('mdi-icon', props.className)}>
<path d="M7,5H21V7H7V5M7,13V11H21V13H7M4,4.5A1.5,1.5 0 0,1 5.5,6A1.5,1.5 0 0,1 4,7.5A1.5,1.5 0 0,1 2.5,6A1.5,1.5 0 0,1 4,4.5M4,10.5A1.5,1.5 0 0,1 5.5,12A1.5,1.5 0 0,1 4,13.5A1.5,1.5 0 0,1 2.5,12A1.5,1.5 0 0,1 4,10.5M7,19V17H21V19H7M4,16.5A1.5,1.5 0 0,1 5.5,18A1.5,1.5 0 0,1 4,19.5A1.5,1.5 0 0,1 2.5,18A1.5,1.5 0 0,1 4,16.5Z" />
</svg>
)
export const PhabricatorIcon: React.FunctionComponent<IconProps> = props => (
export const PhabricatorIcon: React.FunctionComponent<React.PropsWithChildren<IconProps>> = props => (
<svg
{...props}
{...sizeProps(props)}
@ -94,14 +94,14 @@ export const PhabricatorIcon: React.FunctionComponent<IconProps> = props => (
</svg>
)
export const WrapDisabledIcon: React.FunctionComponent<IconProps> = props => (
export const WrapDisabledIcon: React.FunctionComponent<React.PropsWithChildren<IconProps>> = props => (
<svg {...props} {...sizeProps(props)} className={classNames('mdi-icon', props.className)}>
<path d="M16,7H3V5H16ZM3,19H16V17H3Zm19-7L18,9v2H3v2H18v2Z" />
</svg>
)
// TODO: Rename name when refresh design is complete
export const CloudAlertIconRefresh: React.FunctionComponent<IconProps> = props => (
export const CloudAlertIconRefresh: React.FunctionComponent<React.PropsWithChildren<IconProps>> = props => (
<svg
{...props}
{...sizeProps(props)}
@ -128,7 +128,7 @@ export const CloudAlertIconRefresh: React.FunctionComponent<IconProps> = props =
)
// TODO: Rename name when refresh design is complete
export const CloudSyncIconRefresh: React.FunctionComponent<IconProps> = props => (
export const CloudSyncIconRefresh: React.FunctionComponent<React.PropsWithChildren<IconProps>> = props => (
<svg
{...props}
{...sizeProps(props)}
@ -159,7 +159,7 @@ export const CloudSyncIconRefresh: React.FunctionComponent<IconProps> = props =>
)
// TODO: Rename name when refresh design is complete
export const CloudCheckIconRefresh: React.FunctionComponent<IconProps> = props => (
export const CloudCheckIconRefresh: React.FunctionComponent<React.PropsWithChildren<IconProps>> = props => (
<svg
{...props}
{...sizeProps(props)}

View File

@ -74,7 +74,7 @@ export const languageIcons: Record<string, MdiReactIconComponentType | undefined
webassembly: undefined,
}
export const LanguageIcon: React.FunctionComponent<Props> = ({ language, size }) => {
export const LanguageIcon: React.FunctionComponent<React.PropsWithChildren<Props>> = ({ language, size }) => {
const LanguageIconComponent = languageIcons[language] || WebIcon
return <LanguageIconComponent size={size} />
}

View File

@ -25,7 +25,7 @@ interface Props extends ExtensionsControllerProps, ApplyLinkPreviewOptions {
* Renders HTML in a component with link previews applied from providers registered with
* {@link sourcegraph.content.registerLinkPreviewProvider}.
*/
export const WithLinkPreviews: React.FunctionComponent<Props> = ({
export const WithLinkPreviews: React.FunctionComponent<React.PropsWithChildren<Props>> = ({
dangerousInnerHTML,
children,
extensionsController,

View File

@ -10,7 +10,9 @@ import { wrapRemoteObservable } from '../../api/client/api/common'
import { ExtensionsDevelopmentToolsProps } from '.'
export const ActiveExtensionsPanel: React.FunctionComponent<ExtensionsDevelopmentToolsProps> = props => {
export const ActiveExtensionsPanel: React.FunctionComponent<
React.PropsWithChildren<ExtensionsDevelopmentToolsProps>
> = props => {
const extensionsOrError = useObservable(
useMemo(
() =>

View File

@ -29,7 +29,7 @@ import styles from './index.module.scss'
export interface ExtensionsDevelopmentToolsProps
extends ExtensionsControllerProps,
PlatformContextProps<'sideloadedExtensionURL' | 'settings'> {
link: React.ComponentType<{ id: string }>
link: React.ComponentType<React.PropsWithChildren<{ id: string }>>
}
const LAST_TAB_STORAGE_KEY = 'ExtensionDevTools.lastTab'
@ -39,14 +39,16 @@ type ExtensionDevelopmentToolsTabID = 'activeExtensions' | 'loggers'
interface ExtensionDevelopmentToolsTab {
id: ExtensionDevelopmentToolsTabID
label: string
component: React.ComponentType<ExtensionsDevelopmentToolsProps>
component: React.ComponentType<React.PropsWithChildren<ExtensionsDevelopmentToolsProps>>
}
const TABS: ExtensionDevelopmentToolsTab[] = [
{ id: 'activeExtensions', label: 'Active extensions', component: ActiveExtensionsPanel },
]
const ExtensionDevelopmentTools: React.FunctionComponent<ExtensionsDevelopmentToolsProps> = props => {
const ExtensionDevelopmentTools: React.FunctionComponent<
React.PropsWithChildren<ExtensionsDevelopmentToolsProps>
> = props => {
const [tabIndex, setTabIndex] = useLocalStorage(LAST_TAB_STORAGE_KEY, 0)
const handleTabsChange = useCallback((index: number) => setTabIndex(index), [setTabIndex])

View File

@ -81,7 +81,7 @@ const getOverlayStyle = (overlayPosition: HoverOverlayProps['overlayPosition']):
}
}
export const HoverOverlay: React.FunctionComponent<HoverOverlayProps> = props => {
export const HoverOverlay: React.FunctionComponent<React.PropsWithChildren<HoverOverlayProps>> = props => {
const {
hoverOrError,
hoverRef,

View File

@ -29,7 +29,7 @@ const iconKindToNotificationType: Record<Required<HoverAlert>['iconKind'], Param
error: NotificationType.Error,
}
export const HoverOverlayAlerts: React.FunctionComponent<HoverOverlayAlertsProps> = props => {
export const HoverOverlayAlerts: React.FunctionComponent<React.PropsWithChildren<HoverOverlayAlertsProps>> = props => {
const { hoverAlerts, onAlertDismissed, getAlertClassName, getAlertVariant } = props
const createAlertDismissedHandler = (alertType: string) => (event: React.MouseEvent<HTMLAnchorElement>) => {

View File

@ -33,7 +33,9 @@ function tryMarkdownRender(content: string): string | Error {
}
}
export const HoverOverlayContent: React.FunctionComponent<HoverOverlayContentProps> = props => {
export const HoverOverlayContent: React.FunctionComponent<
React.PropsWithChildren<HoverOverlayContentProps>
> = props => {
const { content, aggregatedBadges = [], index, errorAlertClassName, errorAlertVariant, badgeClassName } = props
if (content.kind !== 'markdown') {

View File

@ -20,7 +20,9 @@ interface HoverOverlayContentsProps extends Pick<HoverOverlayBaseProps, 'hoverOr
contentClassName?: string
}
export const HoverOverlayContents: React.FunctionComponent<HoverOverlayContentsProps> = props => {
export const HoverOverlayContents: React.FunctionComponent<
React.PropsWithChildren<HoverOverlayContentsProps>
> = props => {
const {
hoverOrError,
iconClassName,

View File

@ -6,7 +6,9 @@ import { SourcegraphIcon } from '@sourcegraph/wildcard'
import styles from './HoverOverlayLogo.module.scss'
export const HoverOverlayLogo: React.FunctionComponent<{ className?: string }> = ({ className }) => (
export const HoverOverlayLogo: React.FunctionComponent<React.PropsWithChildren<{ className?: string }>> = ({
className,
}) => (
<span className={classNames(styles.container, className)}>
<SourcegraphIcon className={styles.icon} />
</span>

View File

@ -35,7 +35,7 @@ const KEY_TO_NAMES: { [P in Key | ModifierKey]?: string } = {
const MODAL_LABEL_ID = 'keyboard-shortcuts-help-modal-title'
export const KeyboardShortcutsHelp: React.FunctionComponent<Props> = ({
export const KeyboardShortcutsHelp: React.FunctionComponent<React.PropsWithChildren<Props>> = ({
keyboardShortcutForShow,
keyboardShortcuts,
}) => {

View File

@ -12,9 +12,11 @@ TemporarySettingsContext.displayName = 'TemporarySettingsContext'
* React context provider for the temporary settings.
* The web app needs to be wrapped around this.
*/
export const TemporarySettingsProvider: React.FunctionComponent<{
temporarySettingsStorage: TemporarySettingsStorage
}> = ({ children, temporarySettingsStorage }) => {
export const TemporarySettingsProvider: React.FunctionComponent<
React.PropsWithChildren<{
temporarySettingsStorage: TemporarySettingsStorage
}>
> = ({ children, temporarySettingsStorage }) => {
// On first run, migrate the settings from the local storage to the temporary storage.
useEffect(() => {
const migrate = async (): Promise<void> => {

View File

@ -7,10 +7,12 @@ import { TemporarySettings } from './TemporarySettings'
import { TemporarySettingsContext } from './TemporarySettingsProvider'
import { InMemoryMockSettingsBackend, TemporarySettingsStorage } from './TemporarySettingsStorage'
export const MockTemporarySettings: React.FunctionComponent<{
settings: TemporarySettings
onSettingsChanged?: (settings: TemporarySettings) => void
}> = ({ settings, onSettingsChanged, children }) => {
export const MockTemporarySettings: React.FunctionComponent<
React.PropsWithChildren<{
settings: TemporarySettings
onSettingsChanged?: (settings: TemporarySettings) => void
}>
> = ({ settings, onSettingsChanged, children }) => {
const mockClient = createMockClient(
null,
gql`

View File

@ -107,7 +107,10 @@ function getSymbolIconClassName(kind: SymbolKind): string | undefined {
/**
* Renders an Icon for a given symbol kind
*/
export const SymbolIcon: React.FunctionComponent<SymbolIconProps> = ({ kind, className = '' }) => (
export const SymbolIcon: React.FunctionComponent<React.PropsWithChildren<SymbolIconProps>> = ({
kind,
className = '',
}) => (
<Icon
className={classNames(getSymbolIconClassName(kind), className)}
data-tooltip={kind.toLowerCase()}

View File

@ -4,7 +4,10 @@ import { MockedProvider, MockedProviderProps } from '@apollo/client/testing'
import { generateCache } from '@sourcegraph/http-client'
export const MockedTestProvider: React.FunctionComponent<MockedProviderProps> = ({ children, ...props }) => {
export const MockedTestProvider: React.FunctionComponent<React.PropsWithChildren<MockedProviderProps>> = ({
children,
...props
}) => {
/**
* Generate a fresh cache for each instance of MockedTestProvider.
* Important to ensure tests don't share cached data.

View File

@ -11,13 +11,13 @@ import React, { Attributes, PropsWithChildren, PropsWithRef } from 'react'
* @param name The export binding name of the component in its module.
*/
export const lazyComponent = <P extends {}, K extends string>(
componentFactory: () => Promise<{ [k in K]: React.ComponentType<P> }>,
componentFactory: () => Promise<{ [k in K]: React.ComponentType<React.PropsWithChildren<P>> }>,
name: K
): React.FunctionComponent<PropsWithRef<PropsWithChildren<P>> & Attributes> => {
): React.FunctionComponent<React.PropsWithChildren<PropsWithRef<PropsWithChildren<P>> & Attributes>> => {
// Force returning a React.FunctionComponent-like so our result is callable (because it's used
// in <Route render={...} /> elements where it is expected to be callable).
const LazyComponent = React.lazy(async () => {
const component: React.ComponentType<P> = (await componentFactory())[name]
const component: React.ComponentType<React.PropsWithChildren<P>> = (await componentFactory())[name]
return { default: component }
})
return props => <LazyComponent {...props} />

View File

@ -35,7 +35,7 @@ export interface MockedStoryProviderProps extends MockedProviderProps {
* MockedProvider does not support dynamic variable matching for mocks.
* This wrapper **only** mocks against the operation name, the specific provided variables are not used to match against a mock.
*/
export const MockedStoryProvider: React.FunctionComponent<MockedStoryProviderProps> = ({
export const MockedStoryProvider: React.FunctionComponent<React.PropsWithChildren<MockedStoryProviderProps>> = ({
children,
mocks = [],
useStrictMocking,

View File

@ -15,7 +15,7 @@ export const createChromaticStory = (options: CreateChromaticStoryOptions): Stor
const { storyFn, isDarkModeEnabled } = options
// The `storyFn` is retrieved from the `StoryStore`, so it already has a `StoryContext`.
// We can safely change its type to remove required props `StoryContext` props check.
const Story = storyFn as React.ComponentType
const Story = storyFn as React.ComponentType<React.PropsWithChildren<unknown>>
const isDarkModeEnabledInitially = useDarkMode()

View File

@ -26,7 +26,7 @@ interface RepoViewProps extends Pick<WebviewPageProps, 'extensionCoreAPI' | 'pla
setQueryState: (query: QueryState) => void
}
export const RepoView: React.FunctionComponent<RepoViewProps> = ({
export const RepoView: React.FunctionComponent<React.PropsWithChildren<RepoViewProps>> = ({
extensionCoreAPI,
platformContext,
repositoryMatch,

View File

@ -29,7 +29,7 @@ export interface SearchHomeViewProps extends WebviewPageProps {
context: SearchHomeState['context']
}
export const SearchHomeView: React.FunctionComponent<SearchHomeViewProps> = ({
export const SearchHomeView: React.FunctionComponent<React.PropsWithChildren<SearchHomeViewProps>> = ({
extensionCoreAPI,
authenticatedUser,
platformContext,

View File

@ -43,7 +43,7 @@ export interface SearchResultsViewProps extends WebviewPageProps {
context: SearchResultsState['context']
}
export const SearchResultsView: React.FunctionComponent<SearchResultsViewProps> = ({
export const SearchResultsView: React.FunctionComponent<React.PropsWithChildren<SearchResultsViewProps>> = ({
extensionCoreAPI,
authenticatedUser,
platformContext,

View File

@ -144,7 +144,7 @@ function navigateToFileOnMiddleMouseButtonClick(event: MouseEvent<HTMLElement>):
}
}
export const FileMatchChildren: React.FunctionComponent<FileMatchProps> = props => {
export const FileMatchChildren: React.FunctionComponent<React.PropsWithChildren<FileMatchProps>> = props => {
// If optimizeHighlighting is enabled, compile a list of the highlighted file ranges we want to
// fetch (instead of the entire file.)
const optimizeHighlighting =

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