Merge branch 'ts-final' of github.com:trouble/payload into ts-final

This commit is contained in:
Dan Ribbens
2020-12-01 11:47:24 -05:00
36 changed files with 144 additions and 82 deletions

View File

@@ -1,6 +1,6 @@
import React from 'react';
import { Link } from 'react-router-dom';
import { Props } from './types';
import { Props, RenderedTypeProps } from './types';
import './index.scss';
@@ -25,7 +25,7 @@ const Banner: React.FC<Props> = ({
icon && `${baseClass}--align-icon-${alignIcon}`,
].filter(Boolean).join(' ');
let RenderedType = 'div';
let RenderedType: string | React.ComponentType<RenderedTypeProps> = 'div';
if (onClick && !to) RenderedType = 'button';
if (to) RenderedType = Link;
@@ -34,7 +34,6 @@ const Banner: React.FC<Props> = ({
<RenderedType
className={classes}
onClick={onClick}
type={RenderedType === 'button' ? 'button' : undefined}
to={to || undefined}
>
{(icon && alignIcon === 'left') && (

View File

@@ -1,11 +1,19 @@
import { MouseEvent } from 'react';
type onClick = (event: MouseEvent) => void
export type Props = {
children?: React.ReactNode,
className?: string,
icon?: React.ReactNode,
alignIcon?: 'left' | 'right',
onClick?: (event: MouseEvent) => void,
onClick?: onClick
to?: string,
type?: 'error' | 'success' | 'info' | 'default',
}
export type RenderedTypeProps = {
className?: string
onClick?: onClick
to: string
}

View File

@@ -1,4 +1,6 @@
const getInitialColumnState = (fields, useAsTitle, defaultColumns) => {
import { Field, fieldHasSubFields } from '../../../../fields/config/types';
const getInitialColumnState = (fields: Field[], useAsTitle: string, defaultColumns: string[]): { columns: string[] } => {
let initialColumns = [];
if (Array.isArray(defaultColumns) && defaultColumns.length >= 1) {
@@ -17,7 +19,7 @@ const getInitialColumnState = (fields, useAsTitle, defaultColumns) => {
return remaining;
}
if (!field.name && Array.isArray(field.fields)) {
if (!field.name && fieldHasSubFields(field)) {
return [
...remaining,
...field.fields.map((subField) => subField.name),
@@ -39,4 +41,4 @@ const getInitialColumnState = (fields, useAsTitle, defaultColumns) => {
};
module.exports = getInitialColumnState;
export default getInitialColumnState;

View File

@@ -1,6 +1,6 @@
import { Collection } from '../../../../collections/config/types';
import { CollectionConfig } from '../../../../collections/config/types';
export type Props = {
collection: Collection,
collection: CollectionConfig,
handleChange: (columns) => void,
}

View File

@@ -3,7 +3,7 @@ import Loading from '../Loading';
const DatePicker = lazy(() => import('./DatePicker'));
export default (props) => (
export default (props: unknown): React.ReactNode => (
<Suspense fallback={<Loading />}>
<DatePicker {...props} />
</Suspense>

View File

@@ -83,7 +83,6 @@ const DeleteDocument: React.FC<Props> = (props) => {
<React.Fragment>
<button
type="button"
slug={modalSlug}
className={`${baseClass}__toggle`}
onClick={(e) => {
e.preventDefault();

View File

@@ -1,7 +1,7 @@
import { Collection } from '../../../../collections/config/types';
import { CollectionConfig } from '../../../../collections/config/types';
export type Props = {
collection?: Collection,
collection?: CollectionConfig,
id?: string,
title?: string,
}

View File

@@ -31,7 +31,6 @@ const GenerateConfirmation: React.FC<Props> = (props) => {
<Button
size="small"
buttonStyle="secondary"
slug={modalSlug}
onClick={() => {
toggle(modalSlug);
}}

View File

@@ -1,5 +1,3 @@
import { createTrue } from 'typescript';
export type Props = {
setKey: () => void,
highlightField: (Boolean) => void,

View File

@@ -22,7 +22,6 @@ const ListControls: React.FC<Props> = (props) => {
fields,
admin: {
useAsTitle,
defaultColumns,
},
},
} = props;
@@ -31,7 +30,7 @@ const ListControls: React.FC<Props> = (props) => {
const [search, setSearch] = useState('');
const [columns, setColumns] = useState([]);
const [where, setWhere] = useState({});
const [visibleDrawer, setVisibleDrawer] = useState(false);
const [visibleDrawer, setVisibleDrawer] = useState<'where' | 'sort' | 'columns'>();
useEffect(() => {
if (useAsTitle) {
@@ -44,7 +43,7 @@ const ListControls: React.FC<Props> = (props) => {
}, [useAsTitle, fields]);
useEffect(() => {
const newState = {
const newState: any = {
columns,
};
@@ -83,7 +82,7 @@ const ListControls: React.FC<Props> = (props) => {
<Button
className={`${baseClass}__toggle-columns`}
buttonStyle={visibleDrawer === 'columns' ? undefined : 'secondary'}
onClick={() => setVisibleDrawer(visibleDrawer !== 'columns' ? 'columns' : false)}
onClick={() => setVisibleDrawer(visibleDrawer !== 'columns' ? 'columns' : undefined)}
icon="chevron"
iconStyle="none"
>
@@ -93,7 +92,7 @@ const ListControls: React.FC<Props> = (props) => {
<Button
className={`${baseClass}__toggle-where`}
buttonStyle={visibleDrawer === 'where' ? undefined : 'secondary'}
onClick={() => setVisibleDrawer(visibleDrawer !== 'where' ? 'where' : false)}
onClick={() => setVisibleDrawer(visibleDrawer !== 'where' ? 'where' : undefined)}
icon="chevron"
iconStyle="none"
>
@@ -103,7 +102,7 @@ const ListControls: React.FC<Props> = (props) => {
<Button
className={`${baseClass}__toggle-sort`}
buttonStyle={visibleDrawer === 'sort' ? undefined : 'secondary'}
onClick={() => setVisibleDrawer(visibleDrawer !== 'sort' ? 'sort' : false)}
onClick={() => setVisibleDrawer(visibleDrawer !== 'sort' ? 'sort' : undefined)}
icon="chevron"
iconStyle="none"
>
@@ -120,7 +119,6 @@ const ListControls: React.FC<Props> = (props) => {
>
<ColumnSelector
collection={collection}
defaultColumns={defaultColumns}
handleChange={setColumns}
/>
</AnimateHeight>

View File

@@ -1,9 +1,9 @@
import { Collection } from '../../../../collections/config/types';
import { CollectionConfig } from '../../../../collections/config/types';
export type Props = {
enableColumns?: boolean,
enableSort?: boolean,
setSort: () => void,
collection: Collection,
collection: CollectionConfig,
handleChange: (newState) => void,
}

View File

@@ -47,7 +47,7 @@ const Localizer: React.FC<Props> = () => {
return (
<li
key={localeOption}
className={localeClasses}
className={localeClasses.join(' ')}
>
<Link
to={{ search }}

View File

@@ -127,7 +127,7 @@ const DefaultNav = () => {
);
};
const Nav = () => {
const Nav: React.FC = () => {
const {
admin: {
components: {

View File

@@ -1,7 +1,7 @@
import React from 'react';
import { useHistory, useLocation } from 'react-router-dom';
import queryString from 'qs';
import { Props } from './types';
import { Props, Node } from './types';
import Page from './Page';
import Separator from './Separator';
@@ -58,7 +58,7 @@ const Pagination: React.FC<Props> = (props) => {
const rangeEndIndex = (currentPage - 1) + numberOfNeighbors + 1;
// Slice out the range of pages that we want to render
const nodes = pages.slice(rangeStartIndex, rangeEndIndex);
const nodes: Node[] = pages.slice(rangeStartIndex, rangeEndIndex);
// Add prev separator if necessary
if (currentPage - numberOfNeighbors - 1 >= 2) nodes.unshift({ type: 'Separator' });

View File

@@ -8,5 +8,17 @@ export type Props = {
nextPage?: number,
numberOfNeighbors?: number,
disableHistoryChange?: boolean,
onChange?: (page) => void,
onChange?: (page: number) => void,
}
export type Node = {
type: 'Page' | 'Separator' | 'ClickableArrow'
props?: {
page?: number
updatePage: (page?: number) => void
isFirstPage?: boolean
isLastPage?: boolean
isDisabled?: boolean
direction?: 'right' | 'left'
}
} | number

View File

@@ -1,6 +1,6 @@
import React from 'react';
import { Link } from 'react-router-dom';
import { Props } from './types';
import { Props, RenderedTypeProps } from './types';
import './index.scss';
@@ -25,7 +25,7 @@ const Pill: React.FC<Props> = ({
icon && `${baseClass}--align-icon-${alignIcon}`,
].filter(Boolean).join(' ');
let RenderedType = 'div';
let RenderedType: string | React.FC<RenderedTypeProps> = 'div';
if (onClick && !to) RenderedType = 'button';
if (to) RenderedType = Link;

View File

@@ -1,9 +1,15 @@
export type Props = {
children?: React.ReactNode,
className?: string,
to?: string,
icon?: React.ReactNode,
alignIcon?: 'left' | 'right',
onClick?: (onClick) => void,
onClick?: () => void,
pillStyle?: 'light' | 'dark' | 'light-gray',
}
export type RenderedTypeProps = {
className?: string,
to: string,
onClick?: () => void,
type?: 'button'
}

View File

@@ -28,7 +28,7 @@ const PopupButton: React.FC<Props> = (props) => {
return (
<div
role="button"
tabIndex="0"
tabIndex={0}
onKeyDown={(e) => { if (e.key === 'Enter') handleClick(); }}
onClick={handleClick}
className={classes}

View File

@@ -1,7 +1,7 @@
export type Props = {
buttonType: 'custom' | 'default',
button: React.ReactNode,
setActive: () => void,
setActive: (active: boolean) => void,
active: boolean,
onToggleOpen: () => void,
onToggleOpen: (active: boolean) => void,
}

View File

@@ -1,6 +1,6 @@
import React from 'react';
import { useForm } from '../../forms/Form/context';
import { useAuth } from '@payloadcms/config-provider';
import { useForm } from '../../forms/Form/context';
import Button from '../Button';
import { Props } from './types';

View File

@@ -1,6 +1,6 @@
import React from 'react';
import Select from 'react-select';
import { Props } from './types';
import Select, { ValueType, OptionsType } from 'react-select';
import { Props, Value } from './types';
import Chevron from '../../icons/Chevron';
import './index.scss';
@@ -9,7 +9,6 @@ const ReactSelect: React.FC<Props> = (props) => {
const {
showError = false,
options,
isMulti = false,
onChange,
value,
disabled = false,
@@ -25,13 +24,13 @@ const ReactSelect: React.FC<Props> = (props) => {
<Select
{...props}
value={value}
onChange={(selected) => {
onChange={(selected: ValueType<Value>) => {
if (formatValue) {
onChange(formatValue(selected));
} else {
let valueToChange;
let valueToChange: string | string[];
if (isMulti) {
if (Array.isArray(selected)) {
if (selected) {
valueToChange = selected.map((selectedOption) => {
if (typeof selectedOption === 'string') {
@@ -45,7 +44,7 @@ const ReactSelect: React.FC<Props> = (props) => {
});
}
} else if (selected) {
valueToChange = selected.value;
valueToChange = (selected as Value).value;
}
onChange(valueToChange);
}
@@ -54,20 +53,19 @@ const ReactSelect: React.FC<Props> = (props) => {
components={{ DropdownIndicator: Chevron }}
className={classes}
classNamePrefix="rs"
options={options.map((option) => {
const formattedOption = {
value: option,
label: option,
};
if (typeof option === 'object') {
formattedOption.value = option.value;
formattedOption.label = option.label;
if (option.options) formattedOption.options = option.options;
options={(options as OptionsType<Value>).map((option) => {
if (typeof option === 'string') {
return {
value: option,
label: option,
};
}
return formattedOption;
return {
value: option.value,
label: option.label,
options: option?.options,
};
})}
/>
);

View File

@@ -1,9 +1,18 @@
import { ValueType, OptionsType, GroupedOptionsType } from 'react-select';
export type Value = {
label: string
value: string
options?: Value[]
}
export type Props = {
value?: string | [],
onChange?: (formatValue) => void,
value?: ValueType<Value>,
onChange?: (value: any) => void,
disabled?: boolean,
showError?: boolean,
formatValue?: () => void,
options?: string[] | { value: string, label: string }[],
formatValue?: (value: ValueType<Value>) => string[] | string,
options: OptionsType<Value> | GroupedOptionsType<Value>
isMulti?: boolean,
isDisabled?: boolean
}

View File

@@ -1,6 +1,6 @@
import { Collection } from '../../../../collections/config/types';
import { CollectionConfig } from '../../../../collections/config/types';
export type Props = {
handleChange: (any) => void,
collection: Collection,
handleChange: (controls: any) => void,
collection: CollectionConfig,
}

View File

@@ -12,7 +12,6 @@ const Table: React.FC<Props> = ({ columns, data }) => {
<table
cellPadding="0"
cellSpacing="0"
border="0"
>
<thead>
<tr>

View File

@@ -1,9 +1,11 @@
import React from 'react';
export type Props = {
columns: {
accessor: string,
components: {
Heading: React.ReactNode,
renderCell: () => void,
renderCell: (row: any, data: any) => React.ReactNode,
},
}[],
data: []

View File

@@ -13,7 +13,7 @@ const Thumbnail: React.FC<Props> = (props) => {
filename,
mimeType,
staticURL,
sizes = 'medium',
sizes,
adminThumbnail,
size,
} = props;

View File

@@ -1,6 +1,8 @@
import { FileSizes } from '../../../../uploads/types';
export type Props = {
filename: string,
sizes?: unknown,
sizes?: FileSizes
adminThumbnail?: string,
mimeType?: string,
staticURL: string,

View File

@@ -1,3 +1,4 @@
/* eslint-disable jsx-a11y/click-events-have-key-events */
import React from 'react';
import { Props } from './types';
import Thumbnail from '../Thumbnail';

View File

@@ -1,10 +1,11 @@
import { Collection } from '../../../../collections/config/types';
import { CollectionConfig } from '../../../../collections/config/types';
import { FileSizes } from '../../../../uploads/types';
export type Props = {
collection: Collection,
collection: CollectionConfig,
id: string,
filename: string,
mimeType: string,
sizes?: unknown,
sizes?: FileSizes,
onClick?: () => void,
}

View File

@@ -1,6 +1,6 @@
import { Collection } from '../../../../collections/config/types';
import { CollectionConfig } from '../../../../collections/config/types';
export type Props = {
handleChange: () => void,
collection: Collection,
handleChange: (controls: any) => void,
collection: CollectionConfig,
}

View File

@@ -4,11 +4,13 @@ import { Fields, Field, Data } from './types';
const buildValidationPromise = async (fieldState: Field, field: FieldSchema) => {
const validatedFieldState = fieldState;
validatedFieldState.valid = typeof field.validate === 'function' ? await field.validate(fieldState.value, field) : true;
const validationResult = typeof field.validate === 'function' ? await field.validate(fieldState.value, field) : true;
if (typeof validatedFieldState.valid === 'string') {
validatedFieldState.errorMessage = validatedFieldState.valid;
if (typeof validationResult === 'string') {
validatedFieldState.errorMessage = validationResult;
validatedFieldState.valid = false;
} else {
validatedFieldState.valid = true;
}
};
@@ -86,7 +88,7 @@ const buildStateFromSchema = async (fieldSchema: FieldSchema[], fullData: Data =
}
// Handle non-array-based nested fields (group, etc)
if (field.type === 'row' || field.type === 'group') {
if (field.type === 'group') {
const subFieldData = initialData?.[field.name] as Data;
return {
@@ -102,7 +104,7 @@ const buildStateFromSchema = async (fieldSchema: FieldSchema[], fullData: Data =
}
// Handle field types that do not use names (row, etc)
if (field.type === 'row' || field.type === 'group') {
if (field.type === 'row') {
return {
...state,
...iterateFields(field.fields, data, path),

View File

@@ -6,6 +6,7 @@ import useFieldType from '../../useFieldType';
import Label from '../../Label';
import Error from '../../Error';
import { select } from '../../../../../fields/validations';
import { Props } from './types';
import './index.scss';
@@ -62,7 +63,7 @@ const formatRenderValue = (value, options) => {
return value;
};
const Select = (props) => {
const Select: React.FC<Props> = (props) => {
const {
path: pathFromProps,
name,

View File

@@ -0,0 +1,17 @@
import React from 'react';
import { Validate } from '../../../../../fields/config/types';
export type Props = {
path?: string
name: string
required?: boolean
validate?: Validate
label?: string
options?: string[] | { label: string, value: string }[]
hasMany?: boolean
admin?: {
readOnly?: boolean
width?: string
style?: React.CSSProperties
}
}

View File

@@ -195,3 +195,12 @@ export type Field =
export type FieldWithPath = Field & {
path?: string
}
export type FieldWithSubFields =
GroupField
| ArrayField
| RowField;
export function fieldHasSubFields(field: Field): field is FieldWithSubFields {
return (field.type === 'group' || field.type === 'array' || field.type === 'row');
}

View File

@@ -1,7 +1,7 @@
import isImage from './isImage';
import { FileData } from './types';
import { FileSizes } from './types';
const getThumbnail = (mimeType: string, staticURL: string, filename: string, sizes: FileData[], adminThumbnail: string): string | boolean => {
const getThumbnail = (mimeType: string, staticURL: string, filename: string, sizes: FileSizes, adminThumbnail: string): string | boolean => {
if (isImage(mimeType)) {
if (sizes?.[adminThumbnail]?.filename) {
return `${staticURL}/${sizes[adminThumbnail].filename}`;