field typing changes due to useFieldType updates

This commit is contained in:
James
2020-12-26 13:12:29 -05:00
parent 152799ecc7
commit e2d370a415
28 changed files with 82 additions and 72 deletions

View File

@@ -1,5 +0,0 @@
Available props per React DatePicker
- [see here](https://github.com/Hacker0x01/react-datepicker/blob/master/docs/datepicker.md)
Date FNS Information
- [popular mistakes](https://github.com/date-fns/date-fns/blob/master/docs/unicodeTokens.md)

View File

@@ -10,8 +10,8 @@ export type Props = {
maxTime?: Date,
timeIntervals?: number,
timeFormat?: string,
value?: Date | string,
onChange?: () => void,
value?: Date,
onChange?: (val: Date) => void,
admin?: {
readOnly?: boolean,
}

View File

@@ -35,7 +35,7 @@ const EditableBlockTitle: React.FC<{ path: string}> = (props) => {
<input
ref={inputRef}
id={path}
value={value || ''}
value={value as string || ''}
placeholder="Untitled"
type="text"
name={path}

View File

@@ -61,14 +61,13 @@ const ArrayFieldType: React.FC<Props> = (props) => {
validate: memoizedValidate,
disableFormData,
ignoreWhileFlattening: true,
required,
});
const addRow = useCallback(async (rowIndex) => {
const subFieldState = await buildStateFromSchema(fields);
dispatchFields({ type: 'ADD_ROW', rowIndex, subFieldState, path });
dispatchRows({ type: 'ADD', rowIndex });
setValue(value + 1);
setValue(value as number + 1);
}, [dispatchRows, dispatchFields, fields, path, setValue, value]);
const removeRow = useCallback((rowIndex) => {
@@ -119,7 +118,7 @@ const ArrayFieldType: React.FC<Props> = (props) => {
fieldTypes={fieldTypes}
fields={fields}
permissions={permissions}
value={value}
value={value as number}
readOnly={readOnly}
minRows={minRows}
maxRows={maxRows}
@@ -184,7 +183,7 @@ const RenderArray = React.memo((props: RenderArrayProps) => {
parentPath={path}
fieldTypes={fieldTypes}
fieldSchema={fields}
permissions={permissions.fields}
permissions={permissions}
/>
))}
{(rows.length < minRows || (required && rows.length === 0)) && (

View File

@@ -3,4 +3,6 @@ import { Block } from '../../../../../../../fields/config/types';
export type Props = {
blocks: Block[]
close: () => void
addRow: (i: number, block: string) => void
addRowIndex: number
}

View File

@@ -70,7 +70,6 @@ const Blocks: React.FC<Props> = (props) => {
validate: memoizedValidate,
disableFormData,
ignoreWhileFlattening: true,
required,
});
const addRow = useCallback(async (rowIndex, blockType) => {
@@ -80,13 +79,13 @@ const Blocks: React.FC<Props> = (props) => {
dispatchFields({ type: 'ADD_ROW', rowIndex, subFieldState, path, blockType });
dispatchRows({ type: 'ADD', rowIndex, blockType });
setValue(value + 1);
setValue(value as number + 1);
}, [path, setValue, value, blocks, dispatchFields]);
const removeRow = useCallback((rowIndex) => {
dispatchRows({ type: 'REMOVE', rowIndex });
dispatchFields({ type: 'REMOVE_ROW', rowIndex, path });
setValue(value - 1);
setValue(value as number - 1);
}, [path, setValue, value, dispatchFields]);
const moveRow = useCallback((moveFromIndex, moveToIndex) => {
@@ -136,7 +135,7 @@ const Blocks: React.FC<Props> = (props) => {
fieldTypes={fieldTypes}
toggleCollapse={toggleCollapse}
permissions={permissions}
value={value}
value={value as number}
blocks={blocks}
readOnly={readOnly}
minRows={minRows}
@@ -214,7 +213,7 @@ const RenderBlocks = React.memo((props: RenderBlockProps) => {
toggleRowCollapse={toggleCollapse}
parentPath={path}
fieldTypes={fieldTypes}
permissions={permissions.fields}
permissions={permissions}
fieldSchema={[
...blockToRender.fields,
{

View File

@@ -40,7 +40,6 @@ const Checkbox: React.FC<Props> = (props) => {
setValue,
} = useFieldType({
path,
required,
validate: memoizedValidate,
disableFormData,
});

View File

@@ -80,7 +80,7 @@ const Code: React.FC<Props> = (props) => {
required={required}
/>
<Editor
value={value || ''}
value={value as string || ''}
onValueChange={readOnly ? () => null : setValue}
highlight={highlighter}
padding={25}

View File

@@ -26,7 +26,6 @@ const ConfirmPassword: React.FC = () => {
} = useFieldType({
path: 'confirm-password',
disableFormData: true,
required: true,
validate,
enableDebouncedValue: true,
});
@@ -49,7 +48,7 @@ const ConfirmPassword: React.FC = () => {
required
/>
<input
value={value || ''}
value={value as string || ''}
onChange={setValue}
type="password"
autoComplete="off"

View File

@@ -40,7 +40,6 @@ const DateTime: React.FC<Props> = (props) => {
setValue,
} = useFieldType({
path,
required,
validate: memoizedValidate,
});
@@ -72,7 +71,7 @@ const DateTime: React.FC<Props> = (props) => {
<DatePicker
{...props}
onChange={readOnly ? undefined : setValue}
value={value}
value={value as Date}
/>
</div>
</div>

View File

@@ -69,7 +69,7 @@ const Email: React.FC<Props> = (props) => {
required={required}
/>
<input
value={value || ''}
value={value as string || ''}
onChange={setValue}
disabled={Boolean(readOnly)}
placeholder={placeholder}

View File

@@ -25,7 +25,7 @@ const HiddenInput: React.FC<Props> = (props) => {
return (
<input
type="hidden"
value={value || ''}
value={value as string || ''}
onChange={setValue}
name={path}
/>

View File

@@ -30,12 +30,11 @@ const Password: React.FC<Props> = (props) => {
const {
value,
showError,
processing,
formProcessing,
setValue,
errorMessage,
} = useFieldType({
path,
required,
validate: memoizedValidate,
enableDebouncedValue: true,
});
@@ -64,9 +63,9 @@ const Password: React.FC<Props> = (props) => {
required={required}
/>
<input
value={value || ''}
value={value as string || ''}
onChange={setValue}
disabled={processing}
disabled={formProcessing}
type="password"
autoComplete={autoComplete}
id={path}

View File

@@ -43,7 +43,6 @@ const RadioGroup: React.FC<Props> = (props) => {
setValue,
} = useFieldType({
path,
required,
validate: memoizedValidate,
});
@@ -89,7 +88,7 @@ const RadioGroup: React.FC<Props> = (props) => {
<RadioInput
path={path}
isSelected={isSelected}
option={option}
option={optionIsObject(option) ? option : { label: option, value: option }}
onChange={readOnly ? undefined : setValue}
/>
</li>

View File

@@ -13,7 +13,7 @@ import { relationship } from '../../../../../fields/validations';
import { PaginatedDocs } from '../../../../../collections/config/types';
import { useFormProcessing } from '../../Form/context';
import optionsReducer from './optionsReducer';
import { Props, OptionsPage, Option } from './types';
import { Props, OptionsPage, Option, ValueWithRelation } from './types';
import './index.scss';
@@ -70,7 +70,6 @@ const Relationship: React.FC<Props> = (props) => {
} = useFieldType({
path: path || name,
validate: memoizedValidate,
required,
});
const addOptions = useCallback((data, relation) => {
@@ -164,10 +163,12 @@ const Relationship: React.FC<Props> = (props) => {
if (hasMultipleRelations) {
let matchedOption: Option;
const valueWithRelation = value as ValueWithRelation;
options.forEach((opt) => {
if (opt?.options) {
opt.options.some((subOpt) => {
if (subOpt?.value === value.value) {
if (subOpt?.value === valueWithRelation.value) {
matchedOption = subOpt;
return true;
}
@@ -225,7 +226,8 @@ const Relationship: React.FC<Props> = (props) => {
if (!matchedOption) {
if (hasMultipleRelations) {
addOptionByID(value.value, value.relationTo);
const valueWithRelation = value as ValueWithRelation;
addOptionByID(valueWithRelation.value, valueWithRelation.relationTo);
} else {
addOptionByID(value, relationTo);
}
@@ -265,7 +267,7 @@ const Relationship: React.FC<Props> = (props) => {
readOnly && `${baseClass}--read-only`,
].filter(Boolean).join(' ');
const valueToRender = findOptionsByValue();
const valueToRender = (findOptionsByValue() || value) as Value;
return (
<div
@@ -305,7 +307,7 @@ const Relationship: React.FC<Props> = (props) => {
}
} : undefined}
onMenuScrollToBottom={getNextOptions}
value={valueToRender || value}
value={valueToRender}
showError={showError}
disabled={formProcessing}
options={options}

View File

@@ -31,3 +31,8 @@ type ADD = {
}
export type Action = REPLACE | ADD
export type ValueWithRelation = {
relationTo: string
value: string
}

View File

@@ -99,7 +99,6 @@ const RichText: React.FC<Props> = (props) => {
const fieldType = useFieldType({
path,
required,
validate: memoizedValidate,
stringify: true,
});
@@ -168,7 +167,7 @@ const RichText: React.FC<Props> = (props) => {
/>
<Slate
editor={editor}
value={valueToRender}
value={valueToRender as any[]}
onChange={(val) => {
if (val !== defaultValue && val !== value) {
setValue(val);

View File

@@ -1,5 +1,4 @@
import React, { Fragment, useCallback, useEffect, useRef, useState } from 'react';
import PropTypes from 'prop-types';
import { ReactEditor, useSlate } from 'slate-react';
import { useWindowInfo } from '@faceless-ui/window-info';
import { Transforms } from 'slate';
@@ -19,7 +18,7 @@ const baseClass = 'rich-text-link';
const Link = ({ attributes, children, element }) => {
const editor = useSlate();
const linkRef = useRef();
const linkRef = useRef(null);
const { height: windowHeight, width: windowWidth } = useWindowInfo();
const [left, setLeft] = useState(0);
const [top, setTop] = useState(0);
@@ -73,7 +72,6 @@ const Link = ({ attributes, children, element }) => {
>
<Popup
initActive={url === undefined}
className={`${baseClass}__popup`}
buttonType="custom"
button={<span className={`${baseClass}__button`} />}
size="small"
@@ -106,7 +104,6 @@ const Link = ({ attributes, children, element }) => {
className={`${baseClass}__confirm`}
buttonStyle="none"
icon="chevron"
onToggleOpen={calculatePosition}
onClick={(e) => {
e.preventDefault();
@@ -143,20 +140,6 @@ const Link = ({ attributes, children, element }) => {
);
};
Link.defaultProps = {
attributes: {},
children: null,
};
Link.propTypes = {
attributes: PropTypes.shape({}),
children: PropTypes.node,
element: PropTypes.shape({
url: PropTypes.string,
newTab: PropTypes.bool,
}).isRequired,
};
const LinkButton = () => {
const editor = useSlate();

View File

@@ -1,15 +1,15 @@
import { Editor, Transforms, Range } from 'slate';
export const isLinkActive = (editor) => {
export const isLinkActive = (editor: Editor): boolean => {
const [link] = Editor.nodes(editor, { match: (n) => n.type === 'link' });
return !!link;
};
export const unwrapLink = (editor) => {
export const unwrapLink = (editor: Editor): void => {
Transforms.unwrapNodes(editor, { match: (n) => n.type === 'link' });
};
export const wrapLink = (editor, url, newTab) => {
export const wrapLink = (editor: Editor, url?: string, newTab?: boolean): void => {
if (isLinkActive(editor)) {
unwrapLink(editor);
}
@@ -31,7 +31,7 @@ export const wrapLink = (editor, url, newTab) => {
}
};
export const withLinks = (incomingEditor) => {
export const withLinks = (incomingEditor: Editor): Editor => {
const editor = incomingEditor;
const { isInline } = editor;

View File

@@ -7,7 +7,7 @@ const toggleElement = (editor, format) => {
const isList = listTypes.includes(format);
Transforms.unwrapNodes(editor, {
match: (n) => listTypes.includes(n.type),
match: (n) => listTypes.includes(n.type as string),
split: true,
});

View File

@@ -55,8 +55,6 @@ const Select: React.FC<Props> = (props) => {
errorMessage,
} = useFieldType({
path,
label,
required,
validate: memoizedValidate,
});

View File

@@ -70,7 +70,7 @@ const Text: React.FC<Props> = (props) => {
required={required}
/>
<input
value={value || ''}
value={value as string || ''}
onChange={setValue}
disabled={readOnly}
placeholder={placeholder}

View File

@@ -69,7 +69,7 @@ const Textarea: React.FC<Props> = (props) => {
required={required}
/>
<textarea
value={value || ''}
value={value as string || ''}
onChange={setValue}
disabled={readOnly}
placeholder={placeholder}

View File

@@ -50,7 +50,6 @@ const Upload: React.FC<Props> = (props) => {
const fieldType = useFieldType({
path,
required,
validate: memoizedValidate,
});

View File

@@ -14,6 +14,7 @@ const reducer = (currentState, action) => {
const row = {
key: uuidv4(),
open: true,
blockType: undefined,
};
if (dataRow.blockType) {
@@ -35,6 +36,7 @@ const reducer = (currentState, action) => {
const newRow = {
open: true,
key: uuidv4(),
blockType: undefined,
};
if (blockType) newRow.blockType = blockType;

View File

@@ -3,10 +3,11 @@ import {
} from 'react';
import { useFormProcessing, useFormSubmitted, useFormModified, useForm } from '../Form/context';
import useDebounce from '../../../hooks/useDebounce';
import { Options, FieldType } from './types';
import './index.scss';
const useFieldType = (options) => {
const useFieldType = (options: Options): FieldType => {
const {
path,
validate,
@@ -43,13 +44,25 @@ const useFieldType = (options) => {
// Method to send update field values from field component(s)
// Should only be used internally
const sendField = useCallback(async (valueToSend) => {
const fieldToDispatch = { path, value: valueToSend };
const fieldToDispatch = {
path,
value: valueToSend,
valid: false,
errorMessage: undefined,
stringify: false,
disableFormData: false,
ignoreWhileFlattening: false,
initialValue: undefined,
validate: undefined,
};
fieldToDispatch.valid = typeof validate === 'function' ? await validate(valueToSend) : true;
const validationResult = typeof validate === 'function' ? await validate(valueToSend) : true;
if (typeof fieldToDispatch.valid === 'string') {
if (typeof validationResult === 'string') {
fieldToDispatch.errorMessage = fieldToDispatch.valid;
fieldToDispatch.valid = false;
} else {
fieldToDispatch.valid = validationResult;
}
fieldToDispatch.stringify = stringify;

View File

@@ -0,0 +1,19 @@
import { Validate } from '../../../../fields/config/types';
export type Options = {
path: string
validate?: Validate
enableDebouncedValue?: boolean
disableFormData?: boolean
ignoreWhileFlattening?: boolean
stringify?: boolean
}
export type FieldType = {
value: unknown
errorMessage?: string
showError: boolean
formSubmitted: boolean
formProcessing: boolean
setValue: (val: unknown) => void
}

View File

@@ -31,7 +31,7 @@ export type Labels = {
plural: string;
};
export type Validate = (value: unknown, options: any) => string | boolean;
export type Validate = (value: unknown, options?: any) => string | boolean;
export type OptionObject = {
label: string