From 0655f5c382d9263e59695f60728b20188bc18961 Mon Sep 17 00:00:00 2001 From: Daniel Lautzenheiser Date: Mon, 5 Dec 2022 12:06:19 -0500 Subject: [PATCH] Feature/update dnd (#190) * Add prop types * Remove react-sortable-hoc --- core/package.json | 5 +- core/src/components/Editor/Editor.tsx | 2 - .../EditorControlPane/EditorControl.tsx | 28 ++- core/src/components/UI/ListItemTopBar.tsx | 22 +-- core/src/lib/hooks/useUUID.ts | 6 + core/src/lib/util/validation.util.ts | 3 - core/src/reducers/entryDraft.ts | 5 + core/src/widgets/code/CodeControl.tsx | 4 +- core/src/widgets/file/withFileControl.tsx | 144 ++++++-------- core/src/widgets/list/ListControl.tsx | 177 +++++++++++------- core/src/widgets/list/ListItem.tsx | 18 +- .../nodes/code-block/CodeBlockElement.tsx | 4 +- core/yarn.lock | 46 +++-- 13 files changed, 262 insertions(+), 202 deletions(-) create mode 100644 core/src/lib/hooks/useUUID.ts diff --git a/core/package.json b/core/package.json index b9d25175..38d61289 100644 --- a/core/package.json +++ b/core/package.json @@ -54,6 +54,9 @@ "@codemirror/state": "6.1.4", "@codemirror/theme-one-dark": "6.1.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/css": "11.10.5", "@emotion/react": "11.10.5", @@ -121,7 +124,6 @@ "react-redux": "8.0.5", "react-router-dom": "6.4.4", "react-scroll-sync": "0.11.0", - "react-sortable-hoc": "2.0.0", "react-textarea-autosize": "8.4.0", "react-topbar-progress-indicator": "4.1.1", "react-virtualized-auto-sizer": "1.0.7", @@ -235,6 +237,7 @@ "postcss-scss": "4.0.6", "prettier": "2.8.0", "process": "0.11.10", + "prop-types": "15.8.1", "react-refresh": "0.14.0", "react-svg-loader": "3.0.3", "rimraf": "3.0.2", diff --git a/core/src/components/Editor/Editor.tsx b/core/src/components/Editor/Editor.tsx index bdf7a139..c20f7479 100644 --- a/core/src/components/Editor/Editor.tsx +++ b/core/src/components/Editor/Editor.tsx @@ -5,7 +5,6 @@ import { connect } from 'react-redux'; import { logoutUser as logoutUserAction } from '@staticcms/core/actions/auth'; import { - changeDraftFieldValidation as changeDraftFieldValidationAction, createDraftDuplicateFromEntry as createDraftDuplicateFromEntryAction, createEmptyDraft as createEmptyDraftAction, deleteDraftLocalBackup as deleteDraftLocalBackupAction, @@ -385,7 +384,6 @@ const mapDispatchToProps = { retrieveLocalBackup: retrieveLocalBackupAction, persistLocalBackup: persistLocalBackupAction, deleteLocalBackup: deleteLocalBackupAction, - changeDraftFieldValidation: changeDraftFieldValidationAction, createDraftDuplicateFromEntry: createDraftDuplicateFromEntryAction, createEmptyDraft: createEmptyDraftAction, discardDraft: discardDraftAction, diff --git a/core/src/components/Editor/EditorControlPane/EditorControl.tsx b/core/src/components/Editor/EditorControlPane/EditorControl.tsx index 549cf3c9..3345fd85 100644 --- a/core/src/components/Editor/EditorControlPane/EditorControl.tsx +++ b/core/src/components/Editor/EditorControlPane/EditorControl.tsx @@ -7,7 +7,7 @@ import { connect } from 'react-redux'; import { changeDraftField as changeDraftFieldAction, - changeDraftFieldValidation as changeDraftFieldValidationAction, + changeDraftFieldValidation, } from '@staticcms/core/actions/entries'; import { getAsset as getAssetAction } from '@staticcms/core/actions/media'; 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 { transientOptions } from '@staticcms/core/lib'; import useMemoCompare from '@staticcms/core/lib/hooks/useMemoCompare'; +import useUUID from '@staticcms/core/lib/hooks/useUUID'; import { resolveWidget } from '@staticcms/core/lib/registry'; import { getFieldLabel } from '@staticcms/core/lib/util/field.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 { useAppDispatch, useAppSelector } from '@staticcms/core/store/hooks'; import type { Field, @@ -146,7 +149,6 @@ const EditorControl = ({ isHidden = false, locale, mediaPaths, - changeDraftFieldValidation, openMediaLibrary, parentPath, query, @@ -158,6 +160,10 @@ const EditorControl = ({ changeDraftField, i18n, }: TranslatedProps) => { + const dispatch = useAppDispatch(); + + const id = useUUID(); + const widgetName = field.widget; const widget = resolveWidget(widgetName) as Widget; const fieldHint = field.hint; @@ -168,8 +174,10 @@ const EditorControl = ({ ); 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 handleGetAsset: GetAssetFunction = useMemo( @@ -181,12 +189,17 @@ const EditorControl = ({ ); useEffect(() => { + if (!dirty && !submitted) { + return; + } + const validateValue = async () => { - await validate(path, field, value, widget, changeDraftFieldValidation, t); + const errors = await validate(field, value, widget, t); + dispatch(changeDraftFieldValidation(path, errors)); }; validateValue(); - }, [field, value, changeDraftFieldValidation, path, t, widget, dirty]); + }, [dispatch, field, path, t, value, widget, dirty, submitted]); const handleChangeDraftField = useCallback( (value: ValueOrNestedValue) => { @@ -209,7 +222,7 @@ const EditorControl = ({ <> {createElement(widget.control, { - key: `field_${path}`, + key: id, collection, config, entry, @@ -318,7 +331,6 @@ function mapStateToProps(state: RootState, ownProps: EditorControlOwnProps) { const mapDispatchToProps = { changeDraftField: changeDraftFieldAction, - changeDraftFieldValidation: changeDraftFieldValidationAction, openMediaLibrary: openMediaLibraryAction, clearMediaControl: clearMediaControlAction, removeMediaControl: removeMediaControlAction, diff --git a/core/src/components/UI/ListItemTopBar.tsx b/core/src/components/UI/ListItemTopBar.tsx index f9745327..bd1be7dc 100644 --- a/core/src/components/UI/ListItemTopBar.tsx +++ b/core/src/components/UI/ListItemTopBar.tsx @@ -1,14 +1,15 @@ -import { styled } from '@mui/material/styles'; import CloseIcon from '@mui/icons-material/Close'; import DragHandleIcon from '@mui/icons-material/DragHandle'; import ExpandMoreIcon from '@mui/icons-material/ExpandMore'; import IconButton from '@mui/material/IconButton'; +import { styled } from '@mui/material/styles'; import React from 'react'; import { transientOptions } from '@staticcms/core/lib/util'; 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 { $isVariableTypesList: boolean; @@ -74,16 +75,15 @@ const DragIconContainer = styled(TopBarButtonSpan)` `; export interface DragHandleProps { - dragHandleHOC: (render: () => ReactNode) => ComponentClass; + listeners: SyntheticListenerMap | undefined; } -const DragHandle = ({ dragHandleHOC }: DragHandleProps) => { - const Handle = dragHandleHOC(() => ( - +const DragHandle = ({ listeners }: DragHandleProps) => { + return ( + - )); - return ; + ); }; export interface ListItemTopBarProps { @@ -92,8 +92,8 @@ export interface ListItemTopBarProps { collapsed?: boolean; onCollapseToggle?: (event: MouseEvent) => void; onRemove: (event: MouseEvent) => void; - dragHandleHOC: (render: () => ReactNode) => ComponentClass; isVariableTypesList?: boolean; + listeners: SyntheticListenerMap | undefined; } const ListItemTopBar = ({ @@ -102,8 +102,8 @@ const ListItemTopBar = ({ collapsed = false, onCollapseToggle, onRemove, - dragHandleHOC, isVariableTypesList = false, + listeners, }: ListItemTopBarProps) => { return ( @@ -120,7 +120,7 @@ const ListItemTopBar = ({ {title} - {dragHandleHOC ? : null} + {listeners ? : null} {onRemove ? ( diff --git a/core/src/lib/hooks/useUUID.ts b/core/src/lib/hooks/useUUID.ts new file mode 100644 index 00000000..3e0eaa1c --- /dev/null +++ b/core/src/lib/hooks/useUUID.ts @@ -0,0 +1,6 @@ +import { useMemo } from 'react'; +import { v4 as uuid } from 'uuid'; + +export default function useUUID() { + return useMemo(() => uuid(), []); +} diff --git a/core/src/lib/util/validation.util.ts b/core/src/lib/util/validation.util.ts index 37b626b7..7f53f9f2 100644 --- a/core/src/lib/util/validation.util.ts +++ b/core/src/lib/util/validation.util.ts @@ -78,11 +78,9 @@ export function validatePattern({ } export async function validate( - path: string, field: Field, value: ValueOrNestedValue, widget: Widget, - onValidate: (path: string, errors: FieldError[]) => void, t: t, ): Promise { const validValue = widget.getValidValue(value); @@ -100,6 +98,5 @@ export async function validate( } } - onValidate(path, errors); return errors; } diff --git a/core/src/reducers/entryDraft.ts b/core/src/reducers/entryDraft.ts index 1d6ae01e..4d8bd2dd 100644 --- a/core/src/reducers/entryDraft.ts +++ b/core/src/reducers/entryDraft.ts @@ -24,6 +24,7 @@ import { set } from '../lib/util/object.util'; import type { EntriesAction } from '../actions/entries'; import type { Entry, FieldsErrors } from '../interface'; +import type { RootState } from '../store'; export interface EntryDraftState { original?: Entry; @@ -300,3 +301,7 @@ function entryDraftReducer( } export default entryDraftReducer; + +export const selectFieldErrors = (path: string) => (state: RootState) => { + return state.entryDraft.fieldsErrors[path] ?? []; +}; diff --git a/core/src/widgets/code/CodeControl.tsx b/core/src/widgets/code/CodeControl.tsx index 1e63af96..cb71536c 100644 --- a/core/src/widgets/code/CodeControl.tsx +++ b/core/src/widgets/code/CodeControl.tsx @@ -2,10 +2,10 @@ import { styled } from '@mui/material/styles'; import { loadLanguage } from '@uiw/codemirror-extensions-langs'; import CodeMirror from '@uiw/react-codemirror'; import React, { useCallback, useMemo, useState } from 'react'; -import { v4 as uuid } from 'uuid'; import ObjectWidgetTopBar from '@staticcms/core/components/UI/ObjectWidgetTopBar'; 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 languages from './data/languages'; import SettingsButton from './SettingsButton'; @@ -146,7 +146,7 @@ const CodeControl: FC uuid(), []); + const uniqueId = useUUID(); // If `allow_language_selection` is not set, default to true. Otherwise, use its value. const allowLanguageSelection = useMemo( diff --git a/core/src/widgets/file/withFileControl.tsx b/core/src/widgets/file/withFileControl.tsx index c4e1202e..e21613e7 100644 --- a/core/src/widgets/file/withFileControl.tsx +++ b/core/src/widgets/file/withFileControl.tsx @@ -3,15 +3,13 @@ import PhotoIcon from '@mui/icons-material/Photo'; import Button from '@mui/material/Button'; import IconButton from '@mui/material/IconButton'; import { styled } from '@mui/material/styles'; -import { arrayMoveImmutable } from 'array-move'; 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 Outline from '@staticcms/core/components/UI/Outline'; import { borders, effects, lengths, shadows } from '@staticcms/core/components/UI/styles'; 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 { isEmpty } from '@staticcms/core/lib/util/string.util'; @@ -137,67 +135,43 @@ interface SortableImageProps { onReplace: MouseEventHandler; } -const SortableImage = SortableElement( - ({ itemValue, getAsset, field, onRemove, onReplace }: SortableImageProps) => { - const [assetSource, setAssetSource] = useState(''); - useEffect(() => { - const getImage = async () => { - const asset = (await getAsset(itemValue, field))?.toString() ?? ''; - setAssetSource(asset); - }; +const SortableImage: FC = ({ + itemValue, + getAsset, + field, + onRemove, + onReplace, +}: SortableImageProps) => { + const [assetSource, setAssetSource] = useState(''); + useEffect(() => { + const getImage = async () => { + const asset = (await getAsset(itemValue, field))?.toString() ?? ''; + setAssetSource(asset); + }; - getImage(); - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [itemValue]); + getImage(); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [itemValue]); - return ( -
- - - - -
- ); - }, -); + return ( +
+ + + + +
+ ); +}; -const StyledSortableMultiImageWrapper = styled('div')` +const StyledMultiImageWrapper = styled('div')` display: flex; flex-wrap: wrap; `; -interface SortableMultiImageWrapperProps { - items: string[]; - getAsset: GetAssetFunction; - field: FileOrImageField; - onRemoveOne: (index: number) => MouseEventHandler; - onReplaceOne: (index: number) => MouseEventHandler; -} - -const SortableMultiImageWrapper = SortableContainer( - ({ items, getAsset, field, onRemoveOne, onReplaceOne }: SortableMultiImageWrapperProps) => { - return ( - - {items.map((itemValue, index) => ( - - ))} - - ); - }, -); - const FileLink = styled('a')` margin-bottom: 20px; font-weight: normal; @@ -247,7 +221,7 @@ const withFileControl = ({ forImage = false }: WithFileControlProps = {}) => { hasErrors, t, }) => { - const controlID = useMemo(() => uuid(), []); + const controlID = useUUID(); const [collapsed, setCollapsed] = useState(false); const [internalValue, setInternalValue] = useState(value ?? ''); @@ -345,15 +319,16 @@ const withFileControl = ({ forImage = false }: WithFileControlProps = {}) => { [config, controlID, field, openMediaLibrary, internalValue], ); - const onSortEnd = useCallback( - ({ oldIndex, newIndex }: { oldIndex: number; newIndex: number }) => { - if (Array.isArray(internalValue)) { - const newValue = arrayMoveImmutable(internalValue, oldIndex, newIndex); - handleOnChange(newValue); - } - }, - [handleOnChange, internalValue], - ); + // TODO Readd when multiple uploads is supported + // const onSortEnd = useCallback( + // ({ oldIndex, newIndex }: { oldIndex: number; newIndex: number }) => { + // if (Array.isArray(internalValue)) { + // const newValue = arrayMoveImmutable(internalValue, oldIndex, newIndex); + // handleOnChange(newValue); + // } + // }, + // [handleOnChange, internalValue], + // ); const renderFileLink = useCallback((link: string | undefined | null) => { const size = MAX_DISPLAY_LENGTH; @@ -393,18 +368,18 @@ const withFileControl = ({ forImage = false }: WithFileControlProps = {}) => { if (isMultiple(internalValue)) { return ( - + + {internalValue.map((itemValue, index) => ( + + ))} + ); } @@ -428,16 +403,7 @@ const withFileControl = ({ forImage = false }: WithFileControlProps = {}) => { } return {renderFileLink(internalValue)}; - }, [ - assetSource, - field, - getAsset, - internalValue, - onRemoveOne, - onReplaceOne, - onSortEnd, - renderFileLink, - ]); + }, [assetSource, field, getAsset, internalValue, onRemoveOne, onReplaceOne, renderFileLink]); const content = useMemo(() => { const subject = forImage ? 'image' : 'file'; diff --git a/core/src/widgets/list/ListControl.tsx b/core/src/widgets/list/ListControl.tsx index 818b6ef7..101dfd44 100644 --- a/core/src/widgets/list/ListControl.tsx +++ b/core/src/widgets/list/ListControl.tsx @@ -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 { arrayMoveImmutable } from 'array-move'; import isEmpty from 'lodash/isEmpty'; import React, { useCallback, useMemo, useState } from 'react'; -import { SortableContainer } from 'react-sortable-hoc'; import { v4 as uuid } from 'uuid'; 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 { resolveFieldKeyType, TYPES_KEY } from './typedListHelpers'; +import type { DragEndEvent } from '@dnd-kit/core'; import type { + Entry, Field, + FieldsErrors, + I18nSettings, ListField, ObjectValue, + UnknownField, ValueOrNestedValue, WidgetControlProps, } from '@staticcms/core/interface'; @@ -51,17 +58,77 @@ const StyledSortableList = styled( `, ); -interface SortableListProps { - items: ObjectValue[]; - collapsed: boolean; - renderItem: (item: ObjectValue, index: number) => JSX.Element; +interface SortableItemProps { + id: string; + item: ObjectValue; + index: number; + valueType: ListValueType; + handleRemove: (index: number, event: MouseEvent) => void; + entry: Entry; + field: ListField; + fieldsErrors: FieldsErrors; + submitted: boolean; + isFieldDuplicate: ((field: Field) => boolean) | undefined; + isFieldHidden: ((field: Field) => boolean) | undefined; + locale: string | undefined; + path: string; + value: Record; + i18n: I18nSettings | undefined; } -const SortableList = SortableContainer( - ({ items, collapsed, renderItem }: SortableListProps) => { - return {items.map(renderItem)}; - }, -); +const SortableItem: FC = ({ + id, + 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
; + } + + return ( +
+ } + i18n={i18n} + listeners={listeners} + /> +
+ ); +}; export enum ListValueType { MULTIPLE, @@ -200,8 +267,15 @@ const ListControl: FC> = ({ [collapsed], ); - const onSortEnd = useCallback( - ({ oldIndex, newIndex }: { oldIndex: number; newIndex: number }) => { + const handleDragEnd = useCallback( + ({ 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 setKeys(arrayMoveImmutable(keys, oldIndex, newIndex)); onChange(arrayMoveImmutable(internalValue, oldIndex, newIndex)); @@ -209,49 +283,6 @@ const ListControl: FC> = ({ [onChange, internalValue, keys], ); - const renderItem = useCallback( - (item: ObjectValue, index: number) => { - const key = keys[index]; - if (valueType === null) { - return
; - } - - return ( - } - i18n={i18n} - /> - ); - }, - [ - keys, - valueType, - handleRemove, - entry, - field, - fieldsErrors, - submitted, - isFieldDuplicate, - isFieldHidden, - locale, - path, - i18n, - ], - ); - if (valueType === null) { return null; } @@ -277,15 +308,33 @@ const ListControl: FC> = ({ t={t} /> {internalValue.length > 0 ? ( - + + + + {internalValue.map((item, index) => ( + } + i18n={i18n} + /> + ))} + + + ) : null} diff --git a/core/src/widgets/list/ListItem.tsx b/core/src/widgets/list/ListItem.tsx index 8ff7037a..97bc6b1b 100644 --- a/core/src/widgets/list/ListItem.tsx +++ b/core/src/widgets/list/ListItem.tsx @@ -1,7 +1,6 @@ import { styled } from '@mui/material/styles'; import partial from 'lodash/partial'; import React, { useCallback, useMemo, useState } from 'react'; -import { SortableElement, SortableHandle } from 'react-sortable-hoc'; import EditorControl from '@staticcms/core/components/Editor/EditorControlPane/EditorControl'; import ListItemTopBar from '@staticcms/core/components/UI/ListItemTopBar'; @@ -15,6 +14,7 @@ import { import { ListValueType } from './ListControl'; import { getTypedFieldForValue } from './typedListHelpers'; +import type { SyntheticListenerMap } from '@dnd-kit/core/dist/hooks/utilities'; import type { Entry, EntryData, @@ -29,8 +29,6 @@ const StyledListItem = styled('div')` position: relative; `; -const SortableStyledListItem = SortableElement<{ children: JSX.Element }>(StyledListItem); - const StyledListItemTopBar = styled(ListItemTopBar)` background-color: ${colors.textFieldBorder}; `; @@ -95,10 +93,13 @@ interface ListItemProps > { valueType: ListValueType; index: number; + id: string; + listeners: SyntheticListenerMap | undefined; handleRemove: (index: number, event: MouseEvent) => void; } const ListItem: FC = ({ + id, index, entry, field, @@ -112,6 +113,7 @@ const ListItem: FC = ({ handleRemove, value, i18n, + listeners, }) => { const [objectLabel, objectField] = useMemo((): [string, ListField | ObjectField] => { const childObjectField: ObjectField = { @@ -185,21 +187,21 @@ const ListItem: FC = ({ const isHidden = isFieldHidden && isFieldHidden(field); return ( - + <> = ({ - + ); }; diff --git a/core/src/widgets/markdown/plate/components/nodes/code-block/CodeBlockElement.tsx b/core/src/widgets/markdown/plate/components/nodes/code-block/CodeBlockElement.tsx index f9344182..bf5e6791 100644 --- a/core/src/widgets/markdown/plate/components/nodes/code-block/CodeBlockElement.tsx +++ b/core/src/widgets/markdown/plate/components/nodes/code-block/CodeBlockElement.tsx @@ -2,9 +2,9 @@ import { styled } from '@mui/material/styles'; import { findNodePath, setNodes } from '@udecode/plate'; import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react'; import Frame from 'react-frame-component'; -import { v4 as uuid } from 'uuid'; 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 CodeBlockFrame from './CodeBlockFrame'; @@ -49,7 +49,7 @@ const CodeBlockElement: FC> const [codeHasFocus, setCodeHasFocus] = useState(false); 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 code = ('code' in element ? element.code ?? '' : '') as string; diff --git a/core/yarn.lock b/core/yarn.lock index 8ccbd523..0ad483f2 100644 --- a/core/yarn.lock +++ b/core/yarn.lock @@ -990,7 +990,7 @@ "@babel/helper-validator-option" "^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" resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.20.6.tgz#facf4879bfed9b5326326273a64220f099b0fce3" 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" 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": version "1.0.8" 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" integrity sha512-6xwYfHbajpoF0xLW+iwLkhwgvLoZDfjYfoFNu8ftMoXINzwuymNLd9u/KmwtdT2GbR+/Cz66otEGEVVUHX9QLQ== -invariant@^2.2.2, invariant@^2.2.4: +invariant@^2.2.2: version "2.2.4" resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6" integrity sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA== @@ -9270,7 +9301,7 @@ prompts@^2.0.1: kleur "^3.0.3" 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" resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.8.1.tgz#67d87bf1a694f48435cf332c24af10214a3140b5" integrity sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg== @@ -9517,15 +9548,6 @@ react-scroll-sync@0.11.0: dependencies: 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: version "3.0.3" resolved "https://registry.yarnpkg.com/react-svg-core/-/react-svg-core-3.0.3.tgz#5d856efeaa4d089b0afeebe885b20b8c9500d162"