parent
b6c5791d6c
commit
0655f5c382
@ -54,6 +54,9 @@
|
|||||||
"@codemirror/state": "6.1.4",
|
"@codemirror/state": "6.1.4",
|
||||||
"@codemirror/theme-one-dark": "6.1.0",
|
"@codemirror/theme-one-dark": "6.1.0",
|
||||||
"@codemirror/view": "6.6.0",
|
"@codemirror/view": "6.6.0",
|
||||||
|
"@dnd-kit/core": "6.0.5",
|
||||||
|
"@dnd-kit/sortable": "7.0.1",
|
||||||
|
"@dnd-kit/utilities": "3.2.0",
|
||||||
"@emotion/babel-preset-css-prop": "11.10.0",
|
"@emotion/babel-preset-css-prop": "11.10.0",
|
||||||
"@emotion/css": "11.10.5",
|
"@emotion/css": "11.10.5",
|
||||||
"@emotion/react": "11.10.5",
|
"@emotion/react": "11.10.5",
|
||||||
@ -121,7 +124,6 @@
|
|||||||
"react-redux": "8.0.5",
|
"react-redux": "8.0.5",
|
||||||
"react-router-dom": "6.4.4",
|
"react-router-dom": "6.4.4",
|
||||||
"react-scroll-sync": "0.11.0",
|
"react-scroll-sync": "0.11.0",
|
||||||
"react-sortable-hoc": "2.0.0",
|
|
||||||
"react-textarea-autosize": "8.4.0",
|
"react-textarea-autosize": "8.4.0",
|
||||||
"react-topbar-progress-indicator": "4.1.1",
|
"react-topbar-progress-indicator": "4.1.1",
|
||||||
"react-virtualized-auto-sizer": "1.0.7",
|
"react-virtualized-auto-sizer": "1.0.7",
|
||||||
@ -235,6 +237,7 @@
|
|||||||
"postcss-scss": "4.0.6",
|
"postcss-scss": "4.0.6",
|
||||||
"prettier": "2.8.0",
|
"prettier": "2.8.0",
|
||||||
"process": "0.11.10",
|
"process": "0.11.10",
|
||||||
|
"prop-types": "15.8.1",
|
||||||
"react-refresh": "0.14.0",
|
"react-refresh": "0.14.0",
|
||||||
"react-svg-loader": "3.0.3",
|
"react-svg-loader": "3.0.3",
|
||||||
"rimraf": "3.0.2",
|
"rimraf": "3.0.2",
|
||||||
|
@ -5,7 +5,6 @@ import { connect } from 'react-redux';
|
|||||||
|
|
||||||
import { logoutUser as logoutUserAction } from '@staticcms/core/actions/auth';
|
import { logoutUser as logoutUserAction } from '@staticcms/core/actions/auth';
|
||||||
import {
|
import {
|
||||||
changeDraftFieldValidation as changeDraftFieldValidationAction,
|
|
||||||
createDraftDuplicateFromEntry as createDraftDuplicateFromEntryAction,
|
createDraftDuplicateFromEntry as createDraftDuplicateFromEntryAction,
|
||||||
createEmptyDraft as createEmptyDraftAction,
|
createEmptyDraft as createEmptyDraftAction,
|
||||||
deleteDraftLocalBackup as deleteDraftLocalBackupAction,
|
deleteDraftLocalBackup as deleteDraftLocalBackupAction,
|
||||||
@ -385,7 +384,6 @@ const mapDispatchToProps = {
|
|||||||
retrieveLocalBackup: retrieveLocalBackupAction,
|
retrieveLocalBackup: retrieveLocalBackupAction,
|
||||||
persistLocalBackup: persistLocalBackupAction,
|
persistLocalBackup: persistLocalBackupAction,
|
||||||
deleteLocalBackup: deleteLocalBackupAction,
|
deleteLocalBackup: deleteLocalBackupAction,
|
||||||
changeDraftFieldValidation: changeDraftFieldValidationAction,
|
|
||||||
createDraftDuplicateFromEntry: createDraftDuplicateFromEntryAction,
|
createDraftDuplicateFromEntry: createDraftDuplicateFromEntryAction,
|
||||||
createEmptyDraft: createEmptyDraftAction,
|
createEmptyDraft: createEmptyDraftAction,
|
||||||
discardDraft: discardDraftAction,
|
discardDraft: discardDraftAction,
|
||||||
|
@ -7,7 +7,7 @@ import { connect } from 'react-redux';
|
|||||||
|
|
||||||
import {
|
import {
|
||||||
changeDraftField as changeDraftFieldAction,
|
changeDraftField as changeDraftFieldAction,
|
||||||
changeDraftFieldValidation as changeDraftFieldValidationAction,
|
changeDraftFieldValidation,
|
||||||
} from '@staticcms/core/actions/entries';
|
} from '@staticcms/core/actions/entries';
|
||||||
import { getAsset as getAssetAction } from '@staticcms/core/actions/media';
|
import { getAsset as getAssetAction } from '@staticcms/core/actions/media';
|
||||||
import {
|
import {
|
||||||
@ -20,10 +20,13 @@ import { query as queryAction } from '@staticcms/core/actions/search';
|
|||||||
import { borders, colors, lengths, transitions } from '@staticcms/core/components/UI/styles';
|
import { borders, colors, lengths, transitions } from '@staticcms/core/components/UI/styles';
|
||||||
import { transientOptions } from '@staticcms/core/lib';
|
import { transientOptions } from '@staticcms/core/lib';
|
||||||
import useMemoCompare from '@staticcms/core/lib/hooks/useMemoCompare';
|
import useMemoCompare from '@staticcms/core/lib/hooks/useMemoCompare';
|
||||||
|
import useUUID from '@staticcms/core/lib/hooks/useUUID';
|
||||||
import { resolveWidget } from '@staticcms/core/lib/registry';
|
import { resolveWidget } from '@staticcms/core/lib/registry';
|
||||||
import { getFieldLabel } from '@staticcms/core/lib/util/field.util';
|
import { getFieldLabel } from '@staticcms/core/lib/util/field.util';
|
||||||
import { validate } from '@staticcms/core/lib/util/validation.util';
|
import { validate } from '@staticcms/core/lib/util/validation.util';
|
||||||
|
import { selectFieldErrors } from '@staticcms/core/reducers/entryDraft';
|
||||||
import { selectIsLoadingAsset } from '@staticcms/core/reducers/medias';
|
import { selectIsLoadingAsset } from '@staticcms/core/reducers/medias';
|
||||||
|
import { useAppDispatch, useAppSelector } from '@staticcms/core/store/hooks';
|
||||||
|
|
||||||
import type {
|
import type {
|
||||||
Field,
|
Field,
|
||||||
@ -146,7 +149,6 @@ const EditorControl = ({
|
|||||||
isHidden = false,
|
isHidden = false,
|
||||||
locale,
|
locale,
|
||||||
mediaPaths,
|
mediaPaths,
|
||||||
changeDraftFieldValidation,
|
|
||||||
openMediaLibrary,
|
openMediaLibrary,
|
||||||
parentPath,
|
parentPath,
|
||||||
query,
|
query,
|
||||||
@ -158,6 +160,10 @@ const EditorControl = ({
|
|||||||
changeDraftField,
|
changeDraftField,
|
||||||
i18n,
|
i18n,
|
||||||
}: TranslatedProps<EditorControlProps>) => {
|
}: TranslatedProps<EditorControlProps>) => {
|
||||||
|
const dispatch = useAppDispatch();
|
||||||
|
|
||||||
|
const id = useUUID();
|
||||||
|
|
||||||
const widgetName = field.widget;
|
const widgetName = field.widget;
|
||||||
const widget = resolveWidget(widgetName) as Widget<ValueOrNestedValue>;
|
const widget = resolveWidget(widgetName) as Widget<ValueOrNestedValue>;
|
||||||
const fieldHint = field.hint;
|
const fieldHint = field.hint;
|
||||||
@ -168,8 +174,10 @@ const EditorControl = ({
|
|||||||
);
|
);
|
||||||
|
|
||||||
const [dirty, setDirty] = useState(!isEmpty(value));
|
const [dirty, setDirty] = useState(!isEmpty(value));
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
||||||
const errors = useMemo(() => fieldsErrors[path] ?? [], [fieldsErrors[path]]);
|
const fieldErrorsSelector = useMemo(() => selectFieldErrors(path), [path]);
|
||||||
|
const errors = useAppSelector(fieldErrorsSelector);
|
||||||
|
|
||||||
const hasErrors = (submitted || dirty) && Boolean(errors.length);
|
const hasErrors = (submitted || dirty) && Boolean(errors.length);
|
||||||
|
|
||||||
const handleGetAsset: GetAssetFunction = useMemo(
|
const handleGetAsset: GetAssetFunction = useMemo(
|
||||||
@ -181,12 +189,17 @@ const EditorControl = ({
|
|||||||
);
|
);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
if (!dirty && !submitted) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const validateValue = async () => {
|
const validateValue = async () => {
|
||||||
await validate(path, field, value, widget, changeDraftFieldValidation, t);
|
const errors = await validate(field, value, widget, t);
|
||||||
|
dispatch(changeDraftFieldValidation(path, errors));
|
||||||
};
|
};
|
||||||
|
|
||||||
validateValue();
|
validateValue();
|
||||||
}, [field, value, changeDraftFieldValidation, path, t, widget, dirty]);
|
}, [dispatch, field, path, t, value, widget, dirty, submitted]);
|
||||||
|
|
||||||
const handleChangeDraftField = useCallback(
|
const handleChangeDraftField = useCallback(
|
||||||
(value: ValueOrNestedValue) => {
|
(value: ValueOrNestedValue) => {
|
||||||
@ -209,7 +222,7 @@ const EditorControl = ({
|
|||||||
<ControlContainer $isHidden={isHidden}>
|
<ControlContainer $isHidden={isHidden}>
|
||||||
<>
|
<>
|
||||||
{createElement(widget.control, {
|
{createElement(widget.control, {
|
||||||
key: `field_${path}`,
|
key: id,
|
||||||
collection,
|
collection,
|
||||||
config,
|
config,
|
||||||
entry,
|
entry,
|
||||||
@ -318,7 +331,6 @@ function mapStateToProps(state: RootState, ownProps: EditorControlOwnProps) {
|
|||||||
|
|
||||||
const mapDispatchToProps = {
|
const mapDispatchToProps = {
|
||||||
changeDraftField: changeDraftFieldAction,
|
changeDraftField: changeDraftFieldAction,
|
||||||
changeDraftFieldValidation: changeDraftFieldValidationAction,
|
|
||||||
openMediaLibrary: openMediaLibraryAction,
|
openMediaLibrary: openMediaLibraryAction,
|
||||||
clearMediaControl: clearMediaControlAction,
|
clearMediaControl: clearMediaControlAction,
|
||||||
removeMediaControl: removeMediaControlAction,
|
removeMediaControl: removeMediaControlAction,
|
||||||
|
@ -1,14 +1,15 @@
|
|||||||
import { styled } from '@mui/material/styles';
|
|
||||||
import CloseIcon from '@mui/icons-material/Close';
|
import CloseIcon from '@mui/icons-material/Close';
|
||||||
import DragHandleIcon from '@mui/icons-material/DragHandle';
|
import DragHandleIcon from '@mui/icons-material/DragHandle';
|
||||||
import ExpandMoreIcon from '@mui/icons-material/ExpandMore';
|
import ExpandMoreIcon from '@mui/icons-material/ExpandMore';
|
||||||
import IconButton from '@mui/material/IconButton';
|
import IconButton from '@mui/material/IconButton';
|
||||||
|
import { styled } from '@mui/material/styles';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
import { transientOptions } from '@staticcms/core/lib/util';
|
import { transientOptions } from '@staticcms/core/lib/util';
|
||||||
import { buttons, colors, lengths, transitions } from './styles';
|
import { buttons, colors, lengths, transitions } from './styles';
|
||||||
|
|
||||||
import type { ComponentClass, MouseEvent, ReactNode } from 'react';
|
import type { SyntheticListenerMap } from '@dnd-kit/core/dist/hooks/utilities';
|
||||||
|
import type { MouseEvent, ReactNode } from 'react';
|
||||||
|
|
||||||
interface TopBarProps {
|
interface TopBarProps {
|
||||||
$isVariableTypesList: boolean;
|
$isVariableTypesList: boolean;
|
||||||
@ -74,16 +75,15 @@ const DragIconContainer = styled(TopBarButtonSpan)`
|
|||||||
`;
|
`;
|
||||||
|
|
||||||
export interface DragHandleProps {
|
export interface DragHandleProps {
|
||||||
dragHandleHOC: (render: () => ReactNode) => ComponentClass;
|
listeners: SyntheticListenerMap | undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
const DragHandle = ({ dragHandleHOC }: DragHandleProps) => {
|
const DragHandle = ({ listeners }: DragHandleProps) => {
|
||||||
const Handle = dragHandleHOC(() => (
|
return (
|
||||||
<DragIconContainer>
|
<DragIconContainer {...listeners}>
|
||||||
<DragHandleIcon />
|
<DragHandleIcon />
|
||||||
</DragIconContainer>
|
</DragIconContainer>
|
||||||
));
|
);
|
||||||
return <Handle />;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export interface ListItemTopBarProps {
|
export interface ListItemTopBarProps {
|
||||||
@ -92,8 +92,8 @@ export interface ListItemTopBarProps {
|
|||||||
collapsed?: boolean;
|
collapsed?: boolean;
|
||||||
onCollapseToggle?: (event: MouseEvent) => void;
|
onCollapseToggle?: (event: MouseEvent) => void;
|
||||||
onRemove: (event: MouseEvent) => void;
|
onRemove: (event: MouseEvent) => void;
|
||||||
dragHandleHOC: (render: () => ReactNode) => ComponentClass;
|
|
||||||
isVariableTypesList?: boolean;
|
isVariableTypesList?: boolean;
|
||||||
|
listeners: SyntheticListenerMap | undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
const ListItemTopBar = ({
|
const ListItemTopBar = ({
|
||||||
@ -102,8 +102,8 @@ const ListItemTopBar = ({
|
|||||||
collapsed = false,
|
collapsed = false,
|
||||||
onCollapseToggle,
|
onCollapseToggle,
|
||||||
onRemove,
|
onRemove,
|
||||||
dragHandleHOC,
|
|
||||||
isVariableTypesList = false,
|
isVariableTypesList = false,
|
||||||
|
listeners,
|
||||||
}: ListItemTopBarProps) => {
|
}: ListItemTopBarProps) => {
|
||||||
return (
|
return (
|
||||||
<TopBar className={className} $collapsed={collapsed} $isVariableTypesList={isVariableTypesList}>
|
<TopBar className={className} $collapsed={collapsed} $isVariableTypesList={isVariableTypesList}>
|
||||||
@ -120,7 +120,7 @@ const ListItemTopBar = ({
|
|||||||
<StyledTitle key="title" onClick={onCollapseToggle}>
|
<StyledTitle key="title" onClick={onCollapseToggle}>
|
||||||
{title}
|
{title}
|
||||||
</StyledTitle>
|
</StyledTitle>
|
||||||
{dragHandleHOC ? <DragHandle dragHandleHOC={dragHandleHOC} /> : null}
|
{listeners ? <DragHandle listeners={listeners} /> : null}
|
||||||
{onRemove ? (
|
{onRemove ? (
|
||||||
<TopBarButton onClick={onRemove}>
|
<TopBarButton onClick={onRemove}>
|
||||||
<CloseIcon />
|
<CloseIcon />
|
||||||
|
6
core/src/lib/hooks/useUUID.ts
Normal file
6
core/src/lib/hooks/useUUID.ts
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
import { useMemo } from 'react';
|
||||||
|
import { v4 as uuid } from 'uuid';
|
||||||
|
|
||||||
|
export default function useUUID() {
|
||||||
|
return useMemo(() => uuid(), []);
|
||||||
|
}
|
@ -78,11 +78,9 @@ export function validatePattern({
|
|||||||
}
|
}
|
||||||
|
|
||||||
export async function validate(
|
export async function validate(
|
||||||
path: string,
|
|
||||||
field: Field,
|
field: Field,
|
||||||
value: ValueOrNestedValue,
|
value: ValueOrNestedValue,
|
||||||
widget: Widget<any, any>,
|
widget: Widget<any, any>,
|
||||||
onValidate: (path: string, errors: FieldError[]) => void,
|
|
||||||
t: t,
|
t: t,
|
||||||
): Promise<FieldError[]> {
|
): Promise<FieldError[]> {
|
||||||
const validValue = widget.getValidValue(value);
|
const validValue = widget.getValidValue(value);
|
||||||
@ -100,6 +98,5 @@ export async function validate(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onValidate(path, errors);
|
|
||||||
return errors;
|
return errors;
|
||||||
}
|
}
|
||||||
|
@ -24,6 +24,7 @@ import { set } from '../lib/util/object.util';
|
|||||||
|
|
||||||
import type { EntriesAction } from '../actions/entries';
|
import type { EntriesAction } from '../actions/entries';
|
||||||
import type { Entry, FieldsErrors } from '../interface';
|
import type { Entry, FieldsErrors } from '../interface';
|
||||||
|
import type { RootState } from '../store';
|
||||||
|
|
||||||
export interface EntryDraftState {
|
export interface EntryDraftState {
|
||||||
original?: Entry;
|
original?: Entry;
|
||||||
@ -300,3 +301,7 @@ function entryDraftReducer(
|
|||||||
}
|
}
|
||||||
|
|
||||||
export default entryDraftReducer;
|
export default entryDraftReducer;
|
||||||
|
|
||||||
|
export const selectFieldErrors = (path: string) => (state: RootState) => {
|
||||||
|
return state.entryDraft.fieldsErrors[path] ?? [];
|
||||||
|
};
|
||||||
|
@ -2,10 +2,10 @@ import { styled } from '@mui/material/styles';
|
|||||||
import { loadLanguage } from '@uiw/codemirror-extensions-langs';
|
import { loadLanguage } from '@uiw/codemirror-extensions-langs';
|
||||||
import CodeMirror from '@uiw/react-codemirror';
|
import CodeMirror from '@uiw/react-codemirror';
|
||||||
import React, { useCallback, useMemo, useState } from 'react';
|
import React, { useCallback, useMemo, useState } from 'react';
|
||||||
import { v4 as uuid } from 'uuid';
|
|
||||||
|
|
||||||
import ObjectWidgetTopBar from '@staticcms/core/components/UI/ObjectWidgetTopBar';
|
import ObjectWidgetTopBar from '@staticcms/core/components/UI/ObjectWidgetTopBar';
|
||||||
import Outline from '@staticcms/core/components/UI/Outline';
|
import Outline from '@staticcms/core/components/UI/Outline';
|
||||||
|
import useUUID from '@staticcms/core/lib/hooks/useUUID';
|
||||||
import transientOptions from '@staticcms/core/lib/util/transientOptions';
|
import transientOptions from '@staticcms/core/lib/util/transientOptions';
|
||||||
import languages from './data/languages';
|
import languages from './data/languages';
|
||||||
import SettingsButton from './SettingsButton';
|
import SettingsButton from './SettingsButton';
|
||||||
@ -146,7 +146,7 @@ const CodeControl: FC<WidgetControlProps<string | { [key: string]: string }, Cod
|
|||||||
setSettingsVisible(false);
|
setSettingsVisible(false);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const uniqueId = useMemo(() => uuid(), []);
|
const uniqueId = useUUID();
|
||||||
|
|
||||||
// If `allow_language_selection` is not set, default to true. Otherwise, use its value.
|
// If `allow_language_selection` is not set, default to true. Otherwise, use its value.
|
||||||
const allowLanguageSelection = useMemo(
|
const allowLanguageSelection = useMemo(
|
||||||
|
@ -3,15 +3,13 @@ import PhotoIcon from '@mui/icons-material/Photo';
|
|||||||
import Button from '@mui/material/Button';
|
import Button from '@mui/material/Button';
|
||||||
import IconButton from '@mui/material/IconButton';
|
import IconButton from '@mui/material/IconButton';
|
||||||
import { styled } from '@mui/material/styles';
|
import { styled } from '@mui/material/styles';
|
||||||
import { arrayMoveImmutable } from 'array-move';
|
|
||||||
import React, { memo, useCallback, useEffect, useMemo, useState } from 'react';
|
import React, { memo, useCallback, useEffect, useMemo, useState } from 'react';
|
||||||
import { SortableContainer, SortableElement } from 'react-sortable-hoc';
|
|
||||||
import { v4 as uuid } from 'uuid';
|
|
||||||
|
|
||||||
import ObjectWidgetTopBar from '@staticcms/core/components/UI/ObjectWidgetTopBar';
|
import ObjectWidgetTopBar from '@staticcms/core/components/UI/ObjectWidgetTopBar';
|
||||||
import Outline from '@staticcms/core/components/UI/Outline';
|
import Outline from '@staticcms/core/components/UI/Outline';
|
||||||
import { borders, effects, lengths, shadows } from '@staticcms/core/components/UI/styles';
|
import { borders, effects, lengths, shadows } from '@staticcms/core/components/UI/styles';
|
||||||
import useMediaInsert from '@staticcms/core/lib/hooks/useMediaInsert';
|
import useMediaInsert from '@staticcms/core/lib/hooks/useMediaInsert';
|
||||||
|
import useUUID from '@staticcms/core/lib/hooks/useUUID';
|
||||||
import { basename, transientOptions } from '@staticcms/core/lib/util';
|
import { basename, transientOptions } from '@staticcms/core/lib/util';
|
||||||
import { isEmpty } from '@staticcms/core/lib/util/string.util';
|
import { isEmpty } from '@staticcms/core/lib/util/string.util';
|
||||||
|
|
||||||
@ -137,67 +135,43 @@ interface SortableImageProps {
|
|||||||
onReplace: MouseEventHandler;
|
onReplace: MouseEventHandler;
|
||||||
}
|
}
|
||||||
|
|
||||||
const SortableImage = SortableElement<SortableImageProps>(
|
const SortableImage: FC<SortableImageProps> = ({
|
||||||
({ itemValue, getAsset, field, onRemove, onReplace }: SortableImageProps) => {
|
itemValue,
|
||||||
const [assetSource, setAssetSource] = useState('');
|
getAsset,
|
||||||
useEffect(() => {
|
field,
|
||||||
const getImage = async () => {
|
onRemove,
|
||||||
const asset = (await getAsset(itemValue, field))?.toString() ?? '';
|
onReplace,
|
||||||
setAssetSource(asset);
|
}: SortableImageProps) => {
|
||||||
};
|
const [assetSource, setAssetSource] = useState('');
|
||||||
|
useEffect(() => {
|
||||||
|
const getImage = async () => {
|
||||||
|
const asset = (await getAsset(itemValue, field))?.toString() ?? '';
|
||||||
|
setAssetSource(asset);
|
||||||
|
};
|
||||||
|
|
||||||
getImage();
|
getImage();
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
}, [itemValue]);
|
}, [itemValue]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<ImageWrapper key="image-wrapper" $sortable>
|
<ImageWrapper key="image-wrapper" $sortable>
|
||||||
<Image key="image" src={assetSource} />
|
<Image key="image" src={assetSource} />
|
||||||
</ImageWrapper>
|
</ImageWrapper>
|
||||||
<SortableImageButtons
|
<SortableImageButtons
|
||||||
key="image-buttons"
|
key="image-buttons"
|
||||||
onRemove={onRemove}
|
onRemove={onRemove}
|
||||||
onReplace={onReplace}
|
onReplace={onReplace}
|
||||||
></SortableImageButtons>
|
></SortableImageButtons>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
},
|
};
|
||||||
);
|
|
||||||
|
|
||||||
const StyledSortableMultiImageWrapper = styled('div')`
|
const StyledMultiImageWrapper = styled('div')`
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
interface SortableMultiImageWrapperProps {
|
|
||||||
items: string[];
|
|
||||||
getAsset: GetAssetFunction<FileOrImageField>;
|
|
||||||
field: FileOrImageField;
|
|
||||||
onRemoveOne: (index: number) => MouseEventHandler;
|
|
||||||
onReplaceOne: (index: number) => MouseEventHandler;
|
|
||||||
}
|
|
||||||
|
|
||||||
const SortableMultiImageWrapper = SortableContainer<SortableMultiImageWrapperProps>(
|
|
||||||
({ items, getAsset, field, onRemoveOne, onReplaceOne }: SortableMultiImageWrapperProps) => {
|
|
||||||
return (
|
|
||||||
<StyledSortableMultiImageWrapper key="multi-image-wrapper">
|
|
||||||
{items.map((itemValue, index) => (
|
|
||||||
<SortableImage
|
|
||||||
key={`item-${itemValue}`}
|
|
||||||
index={index}
|
|
||||||
itemValue={itemValue}
|
|
||||||
getAsset={getAsset}
|
|
||||||
field={field}
|
|
||||||
onRemove={onRemoveOne(index)}
|
|
||||||
onReplace={onReplaceOne(index)}
|
|
||||||
/>
|
|
||||||
))}
|
|
||||||
</StyledSortableMultiImageWrapper>
|
|
||||||
);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
const FileLink = styled('a')`
|
const FileLink = styled('a')`
|
||||||
margin-bottom: 20px;
|
margin-bottom: 20px;
|
||||||
font-weight: normal;
|
font-weight: normal;
|
||||||
@ -247,7 +221,7 @@ const withFileControl = ({ forImage = false }: WithFileControlProps = {}) => {
|
|||||||
hasErrors,
|
hasErrors,
|
||||||
t,
|
t,
|
||||||
}) => {
|
}) => {
|
||||||
const controlID = useMemo(() => uuid(), []);
|
const controlID = useUUID();
|
||||||
const [collapsed, setCollapsed] = useState(false);
|
const [collapsed, setCollapsed] = useState(false);
|
||||||
const [internalValue, setInternalValue] = useState(value ?? '');
|
const [internalValue, setInternalValue] = useState(value ?? '');
|
||||||
|
|
||||||
@ -345,15 +319,16 @@ const withFileControl = ({ forImage = false }: WithFileControlProps = {}) => {
|
|||||||
[config, controlID, field, openMediaLibrary, internalValue],
|
[config, controlID, field, openMediaLibrary, internalValue],
|
||||||
);
|
);
|
||||||
|
|
||||||
const onSortEnd = useCallback(
|
// TODO Readd when multiple uploads is supported
|
||||||
({ oldIndex, newIndex }: { oldIndex: number; newIndex: number }) => {
|
// const onSortEnd = useCallback(
|
||||||
if (Array.isArray(internalValue)) {
|
// ({ oldIndex, newIndex }: { oldIndex: number; newIndex: number }) => {
|
||||||
const newValue = arrayMoveImmutable(internalValue, oldIndex, newIndex);
|
// if (Array.isArray(internalValue)) {
|
||||||
handleOnChange(newValue);
|
// const newValue = arrayMoveImmutable(internalValue, oldIndex, newIndex);
|
||||||
}
|
// handleOnChange(newValue);
|
||||||
},
|
// }
|
||||||
[handleOnChange, internalValue],
|
// },
|
||||||
);
|
// [handleOnChange, internalValue],
|
||||||
|
// );
|
||||||
|
|
||||||
const renderFileLink = useCallback((link: string | undefined | null) => {
|
const renderFileLink = useCallback((link: string | undefined | null) => {
|
||||||
const size = MAX_DISPLAY_LENGTH;
|
const size = MAX_DISPLAY_LENGTH;
|
||||||
@ -393,18 +368,18 @@ const withFileControl = ({ forImage = false }: WithFileControlProps = {}) => {
|
|||||||
|
|
||||||
if (isMultiple(internalValue)) {
|
if (isMultiple(internalValue)) {
|
||||||
return (
|
return (
|
||||||
<SortableMultiImageWrapper
|
<StyledMultiImageWrapper key="multi-image-wrapper">
|
||||||
key="mulitple-image-wrapper"
|
{internalValue.map((itemValue, index) => (
|
||||||
items={internalValue}
|
<SortableImage
|
||||||
onSortEnd={onSortEnd}
|
key={`item-${itemValue}`}
|
||||||
onRemoveOne={onRemoveOne}
|
itemValue={itemValue}
|
||||||
onReplaceOne={onReplaceOne}
|
getAsset={getAsset}
|
||||||
distance={4}
|
field={field}
|
||||||
getAsset={getAsset}
|
onRemove={onRemoveOne(index)}
|
||||||
field={field}
|
onReplace={onReplaceOne(index)}
|
||||||
axis="xy"
|
/>
|
||||||
lockToContainerEdges={true}
|
))}
|
||||||
></SortableMultiImageWrapper>
|
</StyledMultiImageWrapper>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -428,16 +403,7 @@ const withFileControl = ({ forImage = false }: WithFileControlProps = {}) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return <FileLinks key="single-file-links">{renderFileLink(internalValue)}</FileLinks>;
|
return <FileLinks key="single-file-links">{renderFileLink(internalValue)}</FileLinks>;
|
||||||
}, [
|
}, [assetSource, field, getAsset, internalValue, onRemoveOne, onReplaceOne, renderFileLink]);
|
||||||
assetSource,
|
|
||||||
field,
|
|
||||||
getAsset,
|
|
||||||
internalValue,
|
|
||||||
onRemoveOne,
|
|
||||||
onReplaceOne,
|
|
||||||
onSortEnd,
|
|
||||||
renderFileLink,
|
|
||||||
]);
|
|
||||||
|
|
||||||
const content = useMemo(() => {
|
const content = useMemo(() => {
|
||||||
const subject = forImage ? 'image' : 'file';
|
const subject = forImage ? 'image' : 'file';
|
||||||
|
@ -1,8 +1,10 @@
|
|||||||
|
import { DndContext } from '@dnd-kit/core';
|
||||||
|
import { SortableContext, useSortable } from '@dnd-kit/sortable';
|
||||||
|
import { CSS } from '@dnd-kit/utilities';
|
||||||
import { styled } from '@mui/material/styles';
|
import { styled } from '@mui/material/styles';
|
||||||
import { arrayMoveImmutable } from 'array-move';
|
import { arrayMoveImmutable } from 'array-move';
|
||||||
import isEmpty from 'lodash/isEmpty';
|
import isEmpty from 'lodash/isEmpty';
|
||||||
import React, { useCallback, useMemo, useState } from 'react';
|
import React, { useCallback, useMemo, useState } from 'react';
|
||||||
import { SortableContainer } from 'react-sortable-hoc';
|
|
||||||
import { v4 as uuid } from 'uuid';
|
import { v4 as uuid } from 'uuid';
|
||||||
|
|
||||||
import FieldLabel from '@staticcms/core/components/UI/FieldLabel';
|
import FieldLabel from '@staticcms/core/components/UI/FieldLabel';
|
||||||
@ -12,10 +14,15 @@ import transientOptions from '@staticcms/core/lib/util/transientOptions';
|
|||||||
import ListItem from './ListItem';
|
import ListItem from './ListItem';
|
||||||
import { resolveFieldKeyType, TYPES_KEY } from './typedListHelpers';
|
import { resolveFieldKeyType, TYPES_KEY } from './typedListHelpers';
|
||||||
|
|
||||||
|
import type { DragEndEvent } from '@dnd-kit/core';
|
||||||
import type {
|
import type {
|
||||||
|
Entry,
|
||||||
Field,
|
Field,
|
||||||
|
FieldsErrors,
|
||||||
|
I18nSettings,
|
||||||
ListField,
|
ListField,
|
||||||
ObjectValue,
|
ObjectValue,
|
||||||
|
UnknownField,
|
||||||
ValueOrNestedValue,
|
ValueOrNestedValue,
|
||||||
WidgetControlProps,
|
WidgetControlProps,
|
||||||
} from '@staticcms/core/interface';
|
} from '@staticcms/core/interface';
|
||||||
@ -51,17 +58,77 @@ const StyledSortableList = styled(
|
|||||||
`,
|
`,
|
||||||
);
|
);
|
||||||
|
|
||||||
interface SortableListProps {
|
interface SortableItemProps {
|
||||||
items: ObjectValue[];
|
id: string;
|
||||||
collapsed: boolean;
|
item: ObjectValue;
|
||||||
renderItem: (item: ObjectValue, index: number) => JSX.Element;
|
index: number;
|
||||||
|
valueType: ListValueType;
|
||||||
|
handleRemove: (index: number, event: MouseEvent) => void;
|
||||||
|
entry: Entry<ObjectValue>;
|
||||||
|
field: ListField;
|
||||||
|
fieldsErrors: FieldsErrors;
|
||||||
|
submitted: boolean;
|
||||||
|
isFieldDuplicate: ((field: Field<UnknownField>) => boolean) | undefined;
|
||||||
|
isFieldHidden: ((field: Field<UnknownField>) => boolean) | undefined;
|
||||||
|
locale: string | undefined;
|
||||||
|
path: string;
|
||||||
|
value: Record<string, ObjectValue>;
|
||||||
|
i18n: I18nSettings | undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
const SortableList = SortableContainer<SortableListProps>(
|
const SortableItem: FC<SortableItemProps> = ({
|
||||||
({ items, collapsed, renderItem }: SortableListProps) => {
|
id,
|
||||||
return <StyledSortableList $collapsed={collapsed}>{items.map(renderItem)}</StyledSortableList>;
|
item,
|
||||||
},
|
index,
|
||||||
);
|
valueType,
|
||||||
|
handleRemove,
|
||||||
|
entry,
|
||||||
|
field,
|
||||||
|
fieldsErrors,
|
||||||
|
submitted,
|
||||||
|
isFieldDuplicate,
|
||||||
|
isFieldHidden,
|
||||||
|
locale,
|
||||||
|
path,
|
||||||
|
i18n,
|
||||||
|
}) => {
|
||||||
|
const { attributes, listeners, setNodeRef, transform, transition } = useSortable({
|
||||||
|
id,
|
||||||
|
});
|
||||||
|
|
||||||
|
const style = {
|
||||||
|
transform: CSS.Transform.toString(transform),
|
||||||
|
transition,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (valueType === null) {
|
||||||
|
return <div key={id} />;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div ref={setNodeRef} style={style} {...attributes}>
|
||||||
|
<ListItem
|
||||||
|
index={index}
|
||||||
|
id={id}
|
||||||
|
key={`sortable-item-${id}`}
|
||||||
|
valueType={valueType}
|
||||||
|
handleRemove={handleRemove}
|
||||||
|
data-testid={`object-control-${index}`}
|
||||||
|
entry={entry}
|
||||||
|
field={field}
|
||||||
|
fieldsErrors={fieldsErrors}
|
||||||
|
submitted={submitted}
|
||||||
|
isFieldDuplicate={isFieldDuplicate}
|
||||||
|
isFieldHidden={isFieldHidden}
|
||||||
|
locale={locale}
|
||||||
|
path={path}
|
||||||
|
value={item as Record<string, ObjectValue>}
|
||||||
|
i18n={i18n}
|
||||||
|
listeners={listeners}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
export enum ListValueType {
|
export enum ListValueType {
|
||||||
MULTIPLE,
|
MULTIPLE,
|
||||||
@ -200,8 +267,15 @@ const ListControl: FC<WidgetControlProps<ObjectValue[], ListField>> = ({
|
|||||||
[collapsed],
|
[collapsed],
|
||||||
);
|
);
|
||||||
|
|
||||||
const onSortEnd = useCallback(
|
const handleDragEnd = useCallback(
|
||||||
({ oldIndex, newIndex }: { oldIndex: number; newIndex: number }) => {
|
({ active, over }: DragEndEvent) => {
|
||||||
|
if (!over || active.id === over.id) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const oldIndex = keys.indexOf(active.id as string);
|
||||||
|
const newIndex = keys.indexOf(over.id as string);
|
||||||
|
|
||||||
// Update value
|
// Update value
|
||||||
setKeys(arrayMoveImmutable(keys, oldIndex, newIndex));
|
setKeys(arrayMoveImmutable(keys, oldIndex, newIndex));
|
||||||
onChange(arrayMoveImmutable(internalValue, oldIndex, newIndex));
|
onChange(arrayMoveImmutable(internalValue, oldIndex, newIndex));
|
||||||
@ -209,49 +283,6 @@ const ListControl: FC<WidgetControlProps<ObjectValue[], ListField>> = ({
|
|||||||
[onChange, internalValue, keys],
|
[onChange, internalValue, keys],
|
||||||
);
|
);
|
||||||
|
|
||||||
const renderItem = useCallback(
|
|
||||||
(item: ObjectValue, index: number) => {
|
|
||||||
const key = keys[index];
|
|
||||||
if (valueType === null) {
|
|
||||||
return <div key={key} />;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<ListItem
|
|
||||||
index={index}
|
|
||||||
key={key}
|
|
||||||
valueType={valueType}
|
|
||||||
handleRemove={handleRemove}
|
|
||||||
data-testid={`object-control-${index}`}
|
|
||||||
entry={entry}
|
|
||||||
field={field}
|
|
||||||
fieldsErrors={fieldsErrors}
|
|
||||||
submitted={submitted}
|
|
||||||
isFieldDuplicate={isFieldDuplicate}
|
|
||||||
isFieldHidden={isFieldHidden}
|
|
||||||
locale={locale}
|
|
||||||
path={path}
|
|
||||||
value={item as Record<string, ObjectValue>}
|
|
||||||
i18n={i18n}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
},
|
|
||||||
[
|
|
||||||
keys,
|
|
||||||
valueType,
|
|
||||||
handleRemove,
|
|
||||||
entry,
|
|
||||||
field,
|
|
||||||
fieldsErrors,
|
|
||||||
submitted,
|
|
||||||
isFieldDuplicate,
|
|
||||||
isFieldHidden,
|
|
||||||
locale,
|
|
||||||
path,
|
|
||||||
i18n,
|
|
||||||
],
|
|
||||||
);
|
|
||||||
|
|
||||||
if (valueType === null) {
|
if (valueType === null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@ -277,15 +308,33 @@ const ListControl: FC<WidgetControlProps<ObjectValue[], ListField>> = ({
|
|||||||
t={t}
|
t={t}
|
||||||
/>
|
/>
|
||||||
{internalValue.length > 0 ? (
|
{internalValue.length > 0 ? (
|
||||||
<SortableList
|
<DndContext key="dnd-context" onDragEnd={handleDragEnd}>
|
||||||
key="sortable-list"
|
<SortableContext items={keys}>
|
||||||
collapsed={collapsed}
|
<StyledSortableList $collapsed={collapsed}>
|
||||||
items={internalValue}
|
{internalValue.map((item, index) => (
|
||||||
renderItem={renderItem}
|
<SortableItem
|
||||||
onSortEnd={onSortEnd}
|
index={index}
|
||||||
useDragHandle
|
key={keys[index]}
|
||||||
lockAxis="y"
|
id={keys[index]}
|
||||||
/>
|
item={item}
|
||||||
|
valueType={valueType}
|
||||||
|
handleRemove={handleRemove}
|
||||||
|
data-testid={`object-control-${index}`}
|
||||||
|
entry={entry}
|
||||||
|
field={field}
|
||||||
|
fieldsErrors={fieldsErrors}
|
||||||
|
submitted={submitted}
|
||||||
|
isFieldDuplicate={isFieldDuplicate}
|
||||||
|
isFieldHidden={isFieldHidden}
|
||||||
|
locale={locale}
|
||||||
|
path={path}
|
||||||
|
value={item as Record<string, ObjectValue>}
|
||||||
|
i18n={i18n}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</StyledSortableList>
|
||||||
|
</SortableContext>
|
||||||
|
</DndContext>
|
||||||
) : null}
|
) : null}
|
||||||
<Outline key="outline" hasLabel hasError={hasErrors} />
|
<Outline key="outline" hasLabel hasError={hasErrors} />
|
||||||
</StyledListWrapper>
|
</StyledListWrapper>
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
import { styled } from '@mui/material/styles';
|
import { styled } from '@mui/material/styles';
|
||||||
import partial from 'lodash/partial';
|
import partial from 'lodash/partial';
|
||||||
import React, { useCallback, useMemo, useState } from 'react';
|
import React, { useCallback, useMemo, useState } from 'react';
|
||||||
import { SortableElement, SortableHandle } from 'react-sortable-hoc';
|
|
||||||
|
|
||||||
import EditorControl from '@staticcms/core/components/Editor/EditorControlPane/EditorControl';
|
import EditorControl from '@staticcms/core/components/Editor/EditorControlPane/EditorControl';
|
||||||
import ListItemTopBar from '@staticcms/core/components/UI/ListItemTopBar';
|
import ListItemTopBar from '@staticcms/core/components/UI/ListItemTopBar';
|
||||||
@ -15,6 +14,7 @@ import {
|
|||||||
import { ListValueType } from './ListControl';
|
import { ListValueType } from './ListControl';
|
||||||
import { getTypedFieldForValue } from './typedListHelpers';
|
import { getTypedFieldForValue } from './typedListHelpers';
|
||||||
|
|
||||||
|
import type { SyntheticListenerMap } from '@dnd-kit/core/dist/hooks/utilities';
|
||||||
import type {
|
import type {
|
||||||
Entry,
|
Entry,
|
||||||
EntryData,
|
EntryData,
|
||||||
@ -29,8 +29,6 @@ const StyledListItem = styled('div')`
|
|||||||
position: relative;
|
position: relative;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const SortableStyledListItem = SortableElement<{ children: JSX.Element }>(StyledListItem);
|
|
||||||
|
|
||||||
const StyledListItemTopBar = styled(ListItemTopBar)`
|
const StyledListItemTopBar = styled(ListItemTopBar)`
|
||||||
background-color: ${colors.textFieldBorder};
|
background-color: ${colors.textFieldBorder};
|
||||||
`;
|
`;
|
||||||
@ -95,10 +93,13 @@ interface ListItemProps
|
|||||||
> {
|
> {
|
||||||
valueType: ListValueType;
|
valueType: ListValueType;
|
||||||
index: number;
|
index: number;
|
||||||
|
id: string;
|
||||||
|
listeners: SyntheticListenerMap | undefined;
|
||||||
handleRemove: (index: number, event: MouseEvent) => void;
|
handleRemove: (index: number, event: MouseEvent) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
const ListItem: FC<ListItemProps> = ({
|
const ListItem: FC<ListItemProps> = ({
|
||||||
|
id,
|
||||||
index,
|
index,
|
||||||
entry,
|
entry,
|
||||||
field,
|
field,
|
||||||
@ -112,6 +113,7 @@ const ListItem: FC<ListItemProps> = ({
|
|||||||
handleRemove,
|
handleRemove,
|
||||||
value,
|
value,
|
||||||
i18n,
|
i18n,
|
||||||
|
listeners,
|
||||||
}) => {
|
}) => {
|
||||||
const [objectLabel, objectField] = useMemo((): [string, ListField | ObjectField] => {
|
const [objectLabel, objectField] = useMemo((): [string, ListField | ObjectField] => {
|
||||||
const childObjectField: ObjectField = {
|
const childObjectField: ObjectField = {
|
||||||
@ -185,21 +187,21 @@ const ListItem: FC<ListItemProps> = ({
|
|||||||
const isHidden = isFieldHidden && isFieldHidden(field);
|
const isHidden = isFieldHidden && isFieldHidden(field);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<SortableStyledListItem key="sortable-list-item" index={index}>
|
<StyledListItem key="sortable-list-item">
|
||||||
<>
|
<>
|
||||||
<StyledListItemTopBar
|
<StyledListItemTopBar
|
||||||
key="list-item-top-bar"
|
key="list-item-top-bar"
|
||||||
collapsed={collapsed}
|
collapsed={collapsed}
|
||||||
onCollapseToggle={handleCollapseToggle}
|
onCollapseToggle={handleCollapseToggle}
|
||||||
onRemove={partial(handleRemove, index)}
|
onRemove={partial(handleRemove, index)}
|
||||||
dragHandleHOC={SortableHandle}
|
data-testid={`styled-list-item-top-bar-${id}`}
|
||||||
data-testid={`styled-list-item-top-bar-${index}`}
|
|
||||||
title={objectLabel}
|
title={objectLabel}
|
||||||
isVariableTypesList={valueType === ListValueType.MIXED}
|
isVariableTypesList={valueType === ListValueType.MIXED}
|
||||||
|
listeners={listeners}
|
||||||
/>
|
/>
|
||||||
<StyledObjectFieldWrapper $collapsed={collapsed}>
|
<StyledObjectFieldWrapper $collapsed={collapsed}>
|
||||||
<EditorControl
|
<EditorControl
|
||||||
key={index}
|
key={`control-${id}`}
|
||||||
field={objectField}
|
field={objectField}
|
||||||
value={value}
|
value={value}
|
||||||
fieldsErrors={fieldsErrors}
|
fieldsErrors={fieldsErrors}
|
||||||
@ -216,7 +218,7 @@ const ListItem: FC<ListItemProps> = ({
|
|||||||
</StyledObjectFieldWrapper>
|
</StyledObjectFieldWrapper>
|
||||||
<Outline key="outline" />
|
<Outline key="outline" />
|
||||||
</>
|
</>
|
||||||
</SortableStyledListItem>
|
</StyledListItem>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -2,9 +2,9 @@ import { styled } from '@mui/material/styles';
|
|||||||
import { findNodePath, setNodes } from '@udecode/plate';
|
import { findNodePath, setNodes } from '@udecode/plate';
|
||||||
import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
||||||
import Frame from 'react-frame-component';
|
import Frame from 'react-frame-component';
|
||||||
import { v4 as uuid } from 'uuid';
|
|
||||||
|
|
||||||
import Outline from '@staticcms/core/components/UI/Outline';
|
import Outline from '@staticcms/core/components/UI/Outline';
|
||||||
|
import useUUID from '@staticcms/core/lib/hooks/useUUID';
|
||||||
import { useWindowEvent } from '@staticcms/core/lib/util/window.util';
|
import { useWindowEvent } from '@staticcms/core/lib/util/window.util';
|
||||||
import CodeBlockFrame from './CodeBlockFrame';
|
import CodeBlockFrame from './CodeBlockFrame';
|
||||||
|
|
||||||
@ -49,7 +49,7 @@ const CodeBlockElement: FC<PlateRenderElementProps<MdValue, MdCodeBlockElement>>
|
|||||||
const [codeHasFocus, setCodeHasFocus] = useState(false);
|
const [codeHasFocus, setCodeHasFocus] = useState(false);
|
||||||
|
|
||||||
const { attributes, nodeProps, element, editor, children } = props;
|
const { attributes, nodeProps, element, editor, children } = props;
|
||||||
const id = useMemo(() => uuid(), []);
|
const id = useUUID();
|
||||||
|
|
||||||
const lang = ('lang' in element ? element.lang : '') as string | undefined;
|
const lang = ('lang' in element ? element.lang : '') as string | undefined;
|
||||||
const code = ('code' in element ? element.code ?? '' : '') as string;
|
const code = ('code' in element ? element.code ?? '' : '') as string;
|
||||||
|
@ -990,7 +990,7 @@
|
|||||||
"@babel/helper-validator-option" "^7.18.6"
|
"@babel/helper-validator-option" "^7.18.6"
|
||||||
"@babel/plugin-transform-typescript" "^7.18.6"
|
"@babel/plugin-transform-typescript" "^7.18.6"
|
||||||
|
|
||||||
"@babel/runtime@7.20.6", "@babel/runtime@^7.0.0", "@babel/runtime@^7.1.2", "@babel/runtime@^7.10.2", "@babel/runtime@^7.12.1", "@babel/runtime@^7.12.5", "@babel/runtime@^7.13.10", "@babel/runtime@^7.14.8", "@babel/runtime@^7.18.3", "@babel/runtime@^7.18.6", "@babel/runtime@^7.18.9", "@babel/runtime@^7.19.0", "@babel/runtime@^7.2.0", "@babel/runtime@^7.20.1", "@babel/runtime@^7.5.5", "@babel/runtime@^7.7.6", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7", "@babel/runtime@^7.9.2":
|
"@babel/runtime@7.20.6", "@babel/runtime@^7.0.0", "@babel/runtime@^7.1.2", "@babel/runtime@^7.10.2", "@babel/runtime@^7.12.1", "@babel/runtime@^7.12.5", "@babel/runtime@^7.13.10", "@babel/runtime@^7.14.8", "@babel/runtime@^7.18.3", "@babel/runtime@^7.18.6", "@babel/runtime@^7.18.9", "@babel/runtime@^7.19.0", "@babel/runtime@^7.20.1", "@babel/runtime@^7.5.5", "@babel/runtime@^7.7.6", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7", "@babel/runtime@^7.9.2":
|
||||||
version "7.20.6"
|
version "7.20.6"
|
||||||
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.20.6.tgz#facf4879bfed9b5326326273a64220f099b0fce3"
|
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.20.6.tgz#facf4879bfed9b5326326273a64220f099b0fce3"
|
||||||
integrity sha512-Q+8MqP7TiHMWzSfwiJwXCjyf4GYA4Dgw3emg/7xmwsdLJOZUp+nMqcOwOzzYheuM1rhDu8FSj2l0aoMygEuXuA==
|
integrity sha512-Q+8MqP7TiHMWzSfwiJwXCjyf4GYA4Dgw3emg/7xmwsdLJOZUp+nMqcOwOzzYheuM1rhDu8FSj2l0aoMygEuXuA==
|
||||||
@ -1319,6 +1319,37 @@
|
|||||||
resolved "https://registry.yarnpkg.com/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz#1d572bfbbe14b7704e0ba0f39b74815b84870d70"
|
resolved "https://registry.yarnpkg.com/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz#1d572bfbbe14b7704e0ba0f39b74815b84870d70"
|
||||||
integrity sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==
|
integrity sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==
|
||||||
|
|
||||||
|
"@dnd-kit/accessibility@^3.0.0":
|
||||||
|
version "3.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/@dnd-kit/accessibility/-/accessibility-3.0.1.tgz#3ccbefdfca595b0a23a5dc57d3de96bc6935641c"
|
||||||
|
integrity sha512-HXRrwS9YUYQO9lFRc/49uO/VICbM+O+ZRpFDe9Pd1rwVv2PCNkRiTZRdxrDgng/UkvdC3Re9r2vwPpXXrWeFzg==
|
||||||
|
dependencies:
|
||||||
|
tslib "^2.0.0"
|
||||||
|
|
||||||
|
"@dnd-kit/core@6.0.5":
|
||||||
|
version "6.0.5"
|
||||||
|
resolved "https://registry.yarnpkg.com/@dnd-kit/core/-/core-6.0.5.tgz#5670ad0dcc83cd51dbf2fa8c6a5c8af4ac0c1989"
|
||||||
|
integrity sha512-3nL+Zy5cT+1XwsWdlXIvGIFvbuocMyB4NBxTN74DeBaBqeWdH9JsnKwQv7buZQgAHmAH+eIENfS1ginkvW6bCw==
|
||||||
|
dependencies:
|
||||||
|
"@dnd-kit/accessibility" "^3.0.0"
|
||||||
|
"@dnd-kit/utilities" "^3.2.0"
|
||||||
|
tslib "^2.0.0"
|
||||||
|
|
||||||
|
"@dnd-kit/sortable@7.0.1":
|
||||||
|
version "7.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/@dnd-kit/sortable/-/sortable-7.0.1.tgz#99c6012bbab4d8bb726c0eef7b921a338c404fdb"
|
||||||
|
integrity sha512-n77qAzJQtMMywu25sJzhz3gsHnDOUlEjTtnRl8A87rWIhnu32zuP+7zmFjwGgvqfXmRufqiHOSlH7JPC/tnJ8Q==
|
||||||
|
dependencies:
|
||||||
|
"@dnd-kit/utilities" "^3.2.0"
|
||||||
|
tslib "^2.0.0"
|
||||||
|
|
||||||
|
"@dnd-kit/utilities@3.2.0", "@dnd-kit/utilities@^3.2.0":
|
||||||
|
version "3.2.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@dnd-kit/utilities/-/utilities-3.2.0.tgz#b3e956ea63a1347c9d0e1316b037ddcc6140acda"
|
||||||
|
integrity sha512-h65/pn2IPCCIWwdlR2BMLqRkDxpTEONA+HQW3n765HBijLYGyrnTCLa2YQt8VVjjSQD6EfFlTE6aS2Q/b6nb2g==
|
||||||
|
dependencies:
|
||||||
|
tslib "^2.0.0"
|
||||||
|
|
||||||
"@emoji-mart/data@^1.0.8":
|
"@emoji-mart/data@^1.0.8":
|
||||||
version "1.0.8"
|
version "1.0.8"
|
||||||
resolved "https://registry.yarnpkg.com/@emoji-mart/data/-/data-1.0.8.tgz#07f9603878b9a813ba16a6ebbabd8515f3d1b91d"
|
resolved "https://registry.yarnpkg.com/@emoji-mart/data/-/data-1.0.8.tgz#07f9603878b9a813ba16a6ebbabd8515f3d1b91d"
|
||||||
@ -6731,7 +6762,7 @@ interpret@^3.1.1:
|
|||||||
resolved "https://registry.yarnpkg.com/interpret/-/interpret-3.1.1.tgz#5be0ceed67ca79c6c4bc5cf0d7ee843dcea110c4"
|
resolved "https://registry.yarnpkg.com/interpret/-/interpret-3.1.1.tgz#5be0ceed67ca79c6c4bc5cf0d7ee843dcea110c4"
|
||||||
integrity sha512-6xwYfHbajpoF0xLW+iwLkhwgvLoZDfjYfoFNu8ftMoXINzwuymNLd9u/KmwtdT2GbR+/Cz66otEGEVVUHX9QLQ==
|
integrity sha512-6xwYfHbajpoF0xLW+iwLkhwgvLoZDfjYfoFNu8ftMoXINzwuymNLd9u/KmwtdT2GbR+/Cz66otEGEVVUHX9QLQ==
|
||||||
|
|
||||||
invariant@^2.2.2, invariant@^2.2.4:
|
invariant@^2.2.2:
|
||||||
version "2.2.4"
|
version "2.2.4"
|
||||||
resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6"
|
resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6"
|
||||||
integrity sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==
|
integrity sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==
|
||||||
@ -9270,7 +9301,7 @@ prompts@^2.0.1:
|
|||||||
kleur "^3.0.3"
|
kleur "^3.0.3"
|
||||||
sisteransi "^1.0.5"
|
sisteransi "^1.0.5"
|
||||||
|
|
||||||
prop-types@^15.0.0, prop-types@^15.5.10, prop-types@^15.5.7, prop-types@^15.5.8, prop-types@^15.6.2, prop-types@^15.7.2, prop-types@^15.8.1:
|
prop-types@15.8.1, prop-types@^15.0.0, prop-types@^15.5.10, prop-types@^15.5.7, prop-types@^15.5.8, prop-types@^15.6.2, prop-types@^15.7.2, prop-types@^15.8.1:
|
||||||
version "15.8.1"
|
version "15.8.1"
|
||||||
resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.8.1.tgz#67d87bf1a694f48435cf332c24af10214a3140b5"
|
resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.8.1.tgz#67d87bf1a694f48435cf332c24af10214a3140b5"
|
||||||
integrity sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==
|
integrity sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==
|
||||||
@ -9517,15 +9548,6 @@ react-scroll-sync@0.11.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
prop-types "^15.5.7"
|
prop-types "^15.5.7"
|
||||||
|
|
||||||
react-sortable-hoc@2.0.0:
|
|
||||||
version "2.0.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/react-sortable-hoc/-/react-sortable-hoc-2.0.0.tgz#f6780d8aa4b922a21f3e754af542f032677078b7"
|
|
||||||
integrity sha512-JZUw7hBsAHXK7PTyErJyI7SopSBFRcFHDjWW5SWjcugY0i6iH7f+eJkY8cJmGMlZ1C9xz1J3Vjz0plFpavVeRg==
|
|
||||||
dependencies:
|
|
||||||
"@babel/runtime" "^7.2.0"
|
|
||||||
invariant "^2.2.4"
|
|
||||||
prop-types "^15.5.7"
|
|
||||||
|
|
||||||
react-svg-core@^3.0.3:
|
react-svg-core@^3.0.3:
|
||||||
version "3.0.3"
|
version "3.0.3"
|
||||||
resolved "https://registry.yarnpkg.com/react-svg-core/-/react-svg-core-3.0.3.tgz#5d856efeaa4d089b0afeebe885b20b8c9500d162"
|
resolved "https://registry.yarnpkg.com/react-svg-core/-/react-svg-core-3.0.3.tgz#5d856efeaa4d089b0afeebe885b20b8c9500d162"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user