Merge pull request #25398 from overleaf/dp-file-tree-proptypes

Remove PropTypes from file-tree components

GitOrigin-RevId: 7ecbf9778da59b852be8678c5dff61e13d927b9c
This commit is contained in:
David
2025-05-12 14:44:54 +01:00
committed by Copybot
parent 82e5b2c5d7
commit 8e31c30ec7
8 changed files with 73 additions and 88 deletions
@@ -1,9 +0,0 @@
import OLNotification from '@/features/ui/components/ol/ol-notification'
import PropTypes from 'prop-types'
export default function DangerMessage({ children }) {
return <OLNotification type="error" content={children} />
}
DangerMessage.propTypes = {
children: PropTypes.any.isRequired,
}
@@ -0,0 +1,9 @@
import OLNotification from '@/features/ui/components/ol/ol-notification'
export default function DangerMessage({
children,
}: {
children: React.ReactNode
}) {
return <OLNotification type="error" content={children} />
}
@@ -1,4 +1,3 @@
import PropTypes from 'prop-types'
import { useTranslation } from 'react-i18next'
import { FetchError } from '../../../../infrastructure/fetch-json'
import RedirectToLogin from './redirect-to-login'
@@ -9,7 +8,12 @@ import {
} from '../../errors'
import DangerMessage from './danger-message'
export default function ErrorMessage({ error }) {
// TODO: Update the error type when we properly type FileTreeActionableContext
export default function ErrorMessage({
error,
}: {
error: string | Record<string, any>
}) {
const { t } = useTranslation()
const fileNameLimit = 150
@@ -119,6 +123,3 @@ export default function ErrorMessage({ error }) {
return <DangerMessage>{t('generic_something_went_wrong')}</DangerMessage>
}
}
ErrorMessage.propTypes = {
error: PropTypes.oneOfType([PropTypes.string, PropTypes.object]).isRequired,
}
@@ -1,7 +1,6 @@
import { useRef, useEffect } from 'react'
import { useTranslation } from 'react-i18next'
import { useFileTreeCreateName } from '../../contexts/file-tree-create-name'
import PropTypes from 'prop-types'
import {
BlockedFilenameError,
DuplicateFilenameError,
@@ -23,6 +22,15 @@ export default function FileTreeCreateNameInput({
placeholder,
error,
inFlight,
}: {
label?: string
focusName?: boolean
classes?: {
formGroup?: string
}
placeholder?: string
error?: string | Record<string, any>
inFlight: boolean
}) {
const { t } = useTranslation()
@@ -30,7 +38,7 @@ export default function FileTreeCreateNameInput({
const { name, setName, touchedName, validName } = useFileTreeCreateName()
// focus the first part of the filename if needed
const inputRef = useRef(null)
const inputRef = useRef<HTMLInputElement>(null)
useEffect(() => {
if (inputRef.current && focusName) {
@@ -73,18 +81,7 @@ export default function FileTreeCreateNameInput({
)
}
FileTreeCreateNameInput.propTypes = {
focusName: PropTypes.bool,
label: PropTypes.string,
classes: PropTypes.shape({
formGroup: PropTypes.string,
}),
placeholder: PropTypes.string,
error: PropTypes.oneOfType([PropTypes.object, PropTypes.string]),
inFlight: PropTypes.bool.isRequired,
}
function ErrorMessage({ error }) {
function ErrorMessage({ error }: { error: string | Record<string, any> }) {
const { t } = useTranslation()
// if (typeof error === 'string') {
@@ -124,6 +121,3 @@ function ErrorMessage({ error }) {
return null // other errors are displayed elsewhere
}
}
ErrorMessage.propTypes = {
error: PropTypes.oneOfType([PropTypes.object, PropTypes.string]).isRequired,
}
@@ -2,7 +2,6 @@ import { useTranslation } from 'react-i18next'
import { useFileTreeCreateForm } from '../../contexts/file-tree-create-form'
import { useFileTreeActionable } from '../../contexts/file-tree-actionable'
import { useFileTreeData } from '../../../../shared/context/file-tree-data-context'
import PropTypes from 'prop-types'
import OLButton from '@/features/ui/components/ol/ol-button'
import OLNotification from '@/features/ui/components/ol/ol-notification'
@@ -26,21 +25,33 @@ export function FileTreeModalCreateFileFooterContent({
valid,
fileCount,
inFlight,
newFileCreateMode,
cancel,
newFileCreateMode,
}: {
valid: boolean
fileCount:
| {
limit: number
status: string
value: number
}
| number
inFlight: boolean
cancel: () => void
newFileCreateMode?: string
}) {
const { t } = useTranslation()
return (
<>
{fileCount.status === 'warning' && (
{typeof fileCount !== 'number' && fileCount.status === 'warning' && (
<div className="modal-footer-left approaching-file-limit">
{t('project_approaching_file_limit')} ({fileCount.value}/
{fileCount.limit})
</div>
)}
{fileCount.status === 'error' && (
{typeof fileCount !== 'number' && fileCount.status === 'error' && (
<OLNotification
type="error"
className="at-file-limit"
@@ -73,14 +84,3 @@ export function FileTreeModalCreateFileFooterContent({
</>
)
}
FileTreeModalCreateFileFooterContent.propTypes = {
cancel: PropTypes.func.isRequired,
fileCount: PropTypes.shape({
limit: PropTypes.number.isRequired,
status: PropTypes.string.isRequired,
value: PropTypes.number.isRequired,
}).isRequired,
inFlight: PropTypes.bool.isRequired,
newFileCreateMode: PropTypes.string,
valid: PropTypes.bool.isRequired,
}
@@ -1,11 +1,18 @@
import classnames from 'classnames'
import PropTypes from 'prop-types'
import { useFileTreeActionable } from '../../contexts/file-tree-actionable'
import * as eventTracking from '../../../../infrastructure/event-tracking'
import OLButton from '@/features/ui/components/ol/ol-button'
import MaterialIcon from '@/shared/components/material-icon'
export default function FileTreeModalCreateFileMode({ mode, icon, label }) {
export default function FileTreeModalCreateFileMode({
mode,
icon,
label,
}: {
mode: string
icon: string
label: string
}) {
const { newFileCreateMode, startCreatingFile } = useFileTreeActionable()
const handleClick = () => {
@@ -27,9 +34,3 @@ export default function FileTreeModalCreateFileMode({ mode, icon, label }) {
</li>
)
}
FileTreeModalCreateFileMode.propTypes = {
mode: PropTypes.string.isRequired,
icon: PropTypes.string.isRequired,
label: PropTypes.string.isRequired,
}
@@ -1,6 +1,6 @@
import { useRef } from 'react'
import PropTypes from 'prop-types'
import classNames from 'classnames'
import { XYCoord } from 'react-dnd'
// a custom component rendered on top of a draggable area that renders the
// dragged item. See
@@ -12,8 +12,13 @@ function FileTreeDraggablePreviewLayer({
isDragging,
item,
clientOffset,
}: {
isOver: boolean
isDragging: boolean
item: { title: string }
clientOffset: XYCoord | null
}) {
const ref = useRef()
const ref = useRef<HTMLDivElement>(null)
return (
<div
@@ -36,29 +41,16 @@ function FileTreeDraggablePreviewLayer({
)
}
FileTreeDraggablePreviewLayer.propTypes = {
isOver: PropTypes.bool.isRequired,
isDragging: PropTypes.bool.isRequired,
item: PropTypes.shape({
title: PropTypes.string,
}),
clientOffset: PropTypes.shape({
x: PropTypes.number,
y: PropTypes.number,
}),
}
function DraggablePreviewItem({ title }) {
function DraggablePreviewItem({ title }: { title: string }) {
return <div className="dnd-draggable-preview-item">{title}</div>
}
DraggablePreviewItem.propTypes = {
title: PropTypes.string.isRequired,
}
// makes the preview item follow the cursor.
// See https://react-dnd.github.io/react-dnd/docs/api/drag-layer-monitor
function getItemStyle(clientOffset, containerOffset) {
function getItemStyle(
clientOffset: XYCoord | null,
containerOffset: DOMRect | undefined
) {
if (!containerOffset || !clientOffset) {
return {
display: 'none',
@@ -1,5 +1,4 @@
import { useEffect, useState } from 'react'
import PropTypes from 'prop-types'
import React, { useEffect, useState } from 'react'
import { useTranslation } from 'react-i18next'
import { useRefWithAutoFocus } from '../../../../shared/hooks/use-ref-with-auto-focus'
import { useFileTreeActionable } from '../../contexts/file-tree-actionable'
@@ -109,19 +108,25 @@ function InputName({
validName,
setValidName,
handleCreateFolder,
}: {
name: string
setName: (name: string) => void
validName: boolean
setValidName: (validName: boolean) => void
handleCreateFolder: () => void
}) {
const { autoFocusedRef } = useRefWithAutoFocus()
const { autoFocusedRef } = useRefWithAutoFocus<HTMLInputElement>()
function handleFocus(ev) {
function handleFocus(ev: React.FocusEvent<HTMLInputElement>) {
ev.target.setSelectionRange(0, -1)
}
function handleChange(ev) {
function handleChange(ev: React.ChangeEvent<HTMLInputElement>) {
setValidName(isCleanFilename(ev.target.value.trim()))
setName(ev.target.value)
}
function handleKeyDown(ev) {
function handleKeyDown(ev: React.KeyboardEvent<HTMLInputElement>) {
if (ev.key === 'Enter' && validName) {
handleCreateFolder()
}
@@ -140,12 +145,4 @@ function InputName({
)
}
InputName.propTypes = {
name: PropTypes.string.isRequired,
setName: PropTypes.func.isRequired,
validName: PropTypes.bool.isRequired,
setValidName: PropTypes.func.isRequired,
handleCreateFolder: PropTypes.func.isRequired,
}
export default FileTreeModalCreateFolder