field typing changes due to useFieldType updates
This commit is contained in:
@@ -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)
|
||||
@@ -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,
|
||||
}
|
||||
|
||||
@@ -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}
|
||||
|
||||
@@ -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)) && (
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
{
|
||||
|
||||
@@ -40,7 +40,6 @@ const Checkbox: React.FC<Props> = (props) => {
|
||||
setValue,
|
||||
} = useFieldType({
|
||||
path,
|
||||
required,
|
||||
validate: memoizedValidate,
|
||||
disableFormData,
|
||||
});
|
||||
|
||||
@@ -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}
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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}
|
||||
|
||||
@@ -25,7 +25,7 @@ const HiddenInput: React.FC<Props> = (props) => {
|
||||
return (
|
||||
<input
|
||||
type="hidden"
|
||||
value={value || ''}
|
||||
value={value as string || ''}
|
||||
onChange={setValue}
|
||||
name={path}
|
||||
/>
|
||||
|
||||
@@ -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}
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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}
|
||||
|
||||
@@ -31,3 +31,8 @@ type ADD = {
|
||||
}
|
||||
|
||||
export type Action = REPLACE | ADD
|
||||
|
||||
export type ValueWithRelation = {
|
||||
relationTo: string
|
||||
value: string
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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,
|
||||
});
|
||||
|
||||
|
||||
@@ -55,8 +55,6 @@ const Select: React.FC<Props> = (props) => {
|
||||
errorMessage,
|
||||
} = useFieldType({
|
||||
path,
|
||||
label,
|
||||
required,
|
||||
validate: memoizedValidate,
|
||||
});
|
||||
|
||||
|
||||
@@ -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}
|
||||
|
||||
@@ -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}
|
||||
|
||||
@@ -50,7 +50,6 @@ const Upload: React.FC<Props> = (props) => {
|
||||
|
||||
const fieldType = useFieldType({
|
||||
path,
|
||||
required,
|
||||
validate: memoizedValidate,
|
||||
});
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
19
src/admin/components/forms/useFieldType/types.ts
Normal file
19
src/admin/components/forms/useFieldType/types.ts
Normal 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
|
||||
}
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user