From 766009aa0daa506fb1b9d17ea4fbc1ad9a117a98 Mon Sep 17 00:00:00 2001 From: Daniel Lautzenheiser Date: Wed, 2 Nov 2022 08:54:30 -0400 Subject: [PATCH] Bugfixes (#61) - Fix react key issue with typed list preview children - Added error outline to relation widget - Added typing support to template previews - Discard draft entry from store when navigating away from editor (This fixes an issue with the media library thinking it was still in the editor, causing it to upload media as draft) - Properly type file formatters - Fix local backup not working --- core/dev-test/backends/github/config.yml | 8 ++-- core/package.json | 1 - core/src/backend.ts | 5 ++- core/src/components/App/App.tsx | 14 ++++++- core/src/components/Editor/Editor.tsx | 15 +++---- .../EditorControlPane/EditorControl.tsx | 2 +- .../EditorPreviewPane/EditorPreviewPane.tsx | 8 +++- core/src/formats/FileFormatter.ts | 8 ++++ core/src/formats/JsonFormatter.ts | 13 ++++++ .../src/formats/{toml.ts => TomlFormatter.ts} | 17 ++++---- .../src/formats/{yaml.ts => YamlFormatter.ts} | 11 +++-- core/src/formats/formats.ts | 41 ++++++++++--------- core/src/formats/frontmatter.ts | 22 +++++----- core/src/formats/json.ts | 9 ---- core/src/interface.ts | 8 ++-- core/src/reducers/entryDraft.ts | 1 - core/src/widgets/markdown/MarkdownControl.tsx | 10 +++-- core/src/widgets/markdown/MarkdownPreview.tsx | 9 ++-- core/src/widgets/markdown/hooks/useMedia.ts | 2 +- core/src/widgets/relation/RelationControl.tsx | 2 + core/yarn.lock | 23 +---------- 21 files changed, 120 insertions(+), 109 deletions(-) create mode 100644 core/src/formats/FileFormatter.ts create mode 100644 core/src/formats/JsonFormatter.ts rename core/src/formats/{toml.ts => TomlFormatter.ts} (72%) rename core/src/formats/{yaml.ts => YamlFormatter.ts} (89%) delete mode 100644 core/src/formats/json.ts diff --git a/core/dev-test/backends/github/config.yml b/core/dev-test/backends/github/config.yml index 9a489331..21c1ef09 100644 --- a/core/dev-test/backends/github/config.yml +++ b/core/dev-test/backends/github/config.yml @@ -1,10 +1,10 @@ backend: name: github - branch: master - repo: owner/repo + branch: main + repo: staticjscms/static-cms-github -media_folder: static/media -public_folder: /media +media_folder: assets/upload +public_folder: /assets/upload collections: - name: posts label: Posts diff --git a/core/package.json b/core/package.json index d6ed46ea..82eab2b3 100644 --- a/core/package.json +++ b/core/package.json @@ -102,7 +102,6 @@ "react-router-dom": "6.4.1", "react-scroll-sync": "0.9.0", "react-sortable-hoc": "2.0.0", - "react-split-pane": "0.1.92", "react-textarea-autosize": "8.3.4", "react-topbar-progress-indicator": "4.1.1", "react-virtualized-auto-sizer": "1.0.7", diff --git a/core/src/backend.ts b/core/src/backend.ts index 7de38136..4eb89b80 100644 --- a/core/src/backend.ts +++ b/core/src/backend.ts @@ -767,7 +767,8 @@ export class Backend { } return Object.assign(entry, { data: isError(data) ? {} : data }); } - return format.fromFile(entry); + + return entry; }; } @@ -967,7 +968,7 @@ export class Backend { const format = resolveFormat(collection, entry); const fieldsOrder = this.fieldsOrder(collection, entry); const fieldsComments = selectFieldsComments(collection, entry); - return format && format.toFile(entry.data, fieldsOrder, fieldsComments); + return format ? format.toFile(entry.data ?? {}, fieldsOrder, fieldsComments) : ''; } fieldsOrder(collection: Collection, entry: Entry) { diff --git a/core/src/components/App/App.tsx b/core/src/components/App/App.tsx index e781771c..23b14de6 100644 --- a/core/src/components/App/App.tsx +++ b/core/src/components/App/App.tsx @@ -4,11 +4,12 @@ import { styled } from '@mui/material/styles'; import React, { useCallback, useMemo } from 'react'; import { translate } from 'react-polyglot'; import { connect } from 'react-redux'; -import { Navigate, Route, Routes, useParams } from 'react-router-dom'; +import { Navigate, Route, Routes, useLocation, useParams } from 'react-router-dom'; import { ScrollSync } from 'react-scroll-sync'; import TopBarProgress from 'react-topbar-progress-indicator'; import { loginUser as loginUserAction } from '../../actions/auth'; +import { discardDraft as discardDraftAction } from '../../actions/entries'; import { currentBackend } from '../../backend'; import { colors, GlobalStyles } from '../../components/UI/styles'; import { history } from '../../routing/history'; @@ -26,6 +27,7 @@ import type { ComponentType } from 'react'; import type { ConnectedProps } from 'react-redux'; import type { Collections, Credentials, TranslatedProps } from '../../interface'; import type { RootState } from '../../store'; + TopBarProgress.config({ barColors: { 0: colors.active, @@ -91,6 +93,7 @@ const App = ({ useMediaLibrary, t, scrollSyncEnabled, + discardDraft, }: TranslatedProps) => { const configError = useCallback( (error?: string) => { @@ -157,6 +160,14 @@ const App = ({ const defaultPath = useMemo(() => getDefaultPath(collections), [collections]); + const { pathname } = useLocation(); + React.useEffect(() => { + if (!/\/collections\/[a-zA-Z0-9_-]+\/entries\/[a-zA-Z0-9_-]+/g.test(pathname)) { + discardDraft(); + } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [pathname]); + const content = useMemo(() => { if (!user) { return authenticationPage; @@ -264,6 +275,7 @@ function mapStateToProps(state: RootState) { const mapDispatchToProps = { loginUser: loginUserAction, + discardDraft: discardDraftAction, }; const connector = connect(mapStateToProps, mapDispatchToProps); diff --git a/core/src/components/Editor/Editor.tsx b/core/src/components/Editor/Editor.tsx index 11fd85ca..135a9dd2 100644 --- a/core/src/components/Editor/Editor.tsx +++ b/core/src/components/Editor/Editor.tsx @@ -75,7 +75,8 @@ const Editor = ({ debounce(function (entry: Entry, collection: Collection) { persistLocalBackup(entry, collection); }, 2000), - [persistLocalBackup], + // eslint-disable-next-line react-hooks/exhaustive-deps + [], ); const deleteBackup = useCallback(() => { @@ -84,7 +85,8 @@ const Editor = ({ deleteLocalBackup(collection, slug); } deleteDraftLocalBackup(); - }, [collection, createBackup, deleteDraftLocalBackup, deleteLocalBackup, slug]); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [collection, createBackup, slug]); const [submitted, setSubmitted] = useState(false); const handlePersistEntry = useCallback( @@ -195,14 +197,12 @@ const Editor = ({ useEffect(() => { if (hasChanged && entryDraft.entry) { createBackup(entryDraft.entry, collection); - } else if (localBackup) { - deleteBackup(); } return () => { createBackup.flush(); }; - }, [collection, createBackup, deleteBackup, entryDraft.entry, hasChanged, localBackup]); + }, [collection, createBackup, entryDraft.entry, hasChanged]); const [prevCollection, setPrevCollection] = useState(null); const [preSlug, setPrevSlug] = useState(null); @@ -280,11 +280,6 @@ const Editor = ({ }; }, [collection.name, deleteBackup, discardDraft, navigationBlocker]); - // TODO Is this needed? - // if (!collectionEntriesLoaded) { - // loadEntries(collection); - // } - if (entry && entry.error) { return (
diff --git a/core/src/components/Editor/EditorControlPane/EditorControl.tsx b/core/src/components/Editor/EditorControlPane/EditorControl.tsx index ec555f35..3c2fefe5 100644 --- a/core/src/components/Editor/EditorControlPane/EditorControl.tsx +++ b/core/src/components/Editor/EditorControlPane/EditorControl.tsx @@ -117,7 +117,7 @@ interface ControlHintProps { $error: boolean; } -export const ControlHint = styled( +const ControlHint = styled( 'p', transientOptions, )( diff --git a/core/src/components/Editor/EditorPreviewPane/EditorPreviewPane.tsx b/core/src/components/Editor/EditorPreviewPane/EditorPreviewPane.tsx index 7579fa36..d9ae5ace 100644 --- a/core/src/components/Editor/EditorPreviewPane/EditorPreviewPane.tsx +++ b/core/src/components/Editor/EditorPreviewPane/EditorPreviewPane.tsx @@ -94,6 +94,7 @@ function getWidgetFor( getAsset: GetAssetFunction, widgetFields: Field[] = fields, values: EntryData = entry.data, + idx: number | null = null, ): ReactNode { // We retrieve the field by name so that this function can also be used in // custom preview templates, where the field object can't be passed in. @@ -157,7 +158,7 @@ function getWidgetFor( value.toString().length < 50 ) { renderedValue = ( -
+
<> {field.label ?? field.name}: {value} @@ -165,7 +166,7 @@ function getWidgetFor( ); } return renderedValue - ? getWidget(config, fieldWithWidgets, collection, renderedValue, entry, getAsset) + ? getWidget(config, fieldWithWidgets, collection, renderedValue, entry, getAsset, idx) : null; } @@ -237,6 +238,7 @@ function widgetsForNestedFields( getAsset: GetAssetFunction, widgetFields: Field[], values: EntryData, + idx: number | null = null, ) { return widgetFields .map(field => @@ -250,6 +252,7 @@ function widgetsForNestedFields( getAsset, widgetFields, values, + idx, ), ) .filter(widget => Boolean(widget)) as JSX.Element[]; @@ -283,6 +286,7 @@ function getTypedNestedWidgets( getAsset, itemType.fields, value, + index, ); }) .filter(Boolean); diff --git a/core/src/formats/FileFormatter.ts b/core/src/formats/FileFormatter.ts new file mode 100644 index 00000000..5adea6f3 --- /dev/null +++ b/core/src/formats/FileFormatter.ts @@ -0,0 +1,8 @@ +export abstract class FileFormatter { + abstract fromFile(content: string): object; + abstract toFile( + data: object, + sortedKeys?: string[], + comments?: Record, + ): string; +} diff --git a/core/src/formats/JsonFormatter.ts b/core/src/formats/JsonFormatter.ts new file mode 100644 index 00000000..4c684a0d --- /dev/null +++ b/core/src/formats/JsonFormatter.ts @@ -0,0 +1,13 @@ +import { FileFormatter } from './FileFormatter'; + +class JsonFormatter extends FileFormatter { + fromFile(content: string) { + return JSON.parse(content); + } + + toFile(data: object) { + return JSON.stringify(data, null, 2); + } +} + +export default new JsonFormatter(); diff --git a/core/src/formats/toml.ts b/core/src/formats/TomlFormatter.ts similarity index 72% rename from core/src/formats/toml.ts rename to core/src/formats/TomlFormatter.ts index a1b8a141..6d05bfb9 100644 --- a/core/src/formats/toml.ts +++ b/core/src/formats/TomlFormatter.ts @@ -1,9 +1,10 @@ import toml from '@iarna/toml'; -import tomlify from 'tomlify-j0.4'; import moment from 'moment'; +import tomlify from 'tomlify-j0.4'; import AssetProxy from '../valueObjects/AssetProxy'; import { sortKeys } from './helpers'; +import { FileFormatter } from './FileFormatter'; function outputReplacer(_key: string, value: unknown) { if (moment.isMoment(value)) { @@ -22,12 +23,14 @@ function outputReplacer(_key: string, value: unknown) { return false; } -export default { +class TomlFormatter extends FileFormatter { fromFile(content: string) { return toml.parse(content); - }, + } - toFile(data: object, sortedKeys: string[] = []) { - return tomlify.toToml(data, { replace: outputReplacer, sort: sortKeys(sortedKeys) }); - }, -}; + toFile(data: object, sortedKeys: string[] = []): string { + return tomlify.toToml(data as object, { replace: outputReplacer, sort: sortKeys(sortedKeys) }); + } +} + +export default new TomlFormatter(); diff --git a/core/src/formats/yaml.ts b/core/src/formats/YamlFormatter.ts similarity index 89% rename from core/src/formats/yaml.ts rename to core/src/formats/YamlFormatter.ts index 3d6004f3..086597a2 100644 --- a/core/src/formats/yaml.ts +++ b/core/src/formats/YamlFormatter.ts @@ -1,6 +1,7 @@ import yaml from 'yaml'; import { sortKeys } from './helpers'; +import { FileFormatter } from './FileFormatter'; import type { Pair, YAMLMap, YAMLSeq } from 'yaml/types'; @@ -20,13 +21,13 @@ function addComments(items: Array, comments: Record, prefi }); } -export default { +class YamlFormatter extends FileFormatter { fromFile(content: string) { if (content && content.trim().endsWith('---')) { content = content.trim().slice(0, -3); } return yaml.parse(content); - }, + } toFile(data: object, sortedKeys: string[] = [], comments: Record = {}) { const contents = yaml.createNode(data) as YAMLMap | YAMLSeq; @@ -38,5 +39,7 @@ export default { doc.contents = contents; return doc.toString(); - }, -}; + } +} + +export default new YamlFormatter(); diff --git a/core/src/formats/formats.ts b/core/src/formats/formats.ts index 8202675b..d64acc05 100644 --- a/core/src/formats/formats.ts +++ b/core/src/formats/formats.ts @@ -1,12 +1,11 @@ -import get from 'lodash/get'; - -import yamlFormatter from './yaml'; -import tomlFormatter from './toml'; -import jsonFormatter from './json'; +import YamlFormatter from './YamlFormatter'; +import TomlFormatter from './TomlFormatter'; +import JsonFormatter from './JsonFormatter'; import { FrontmatterInfer, frontmatterJSON, frontmatterTOML, frontmatterYAML } from './frontmatter'; import type { Delimiter } from './frontmatter'; import type { Collection, Entry, Format } from '../interface'; +import type { FileFormatter } from './FileFormatter'; export const frontmatterFormats = ['yaml-frontmatter', 'toml-frontmatter', 'json-frontmatter']; @@ -21,30 +20,32 @@ export const formatExtensions = { 'yaml-frontmatter': 'md', }; -export const extensionFormatters = { - yml: yamlFormatter, - yaml: yamlFormatter, - toml: tomlFormatter, - json: jsonFormatter, +export const extensionFormatters: Record = { + yml: YamlFormatter, + yaml: YamlFormatter, + toml: TomlFormatter, + json: JsonFormatter, md: FrontmatterInfer, markdown: FrontmatterInfer, html: FrontmatterInfer, }; -function formatByName(name: Format, customDelimiter?: Delimiter) { - return { - yml: yamlFormatter, - yaml: yamlFormatter, - toml: tomlFormatter, - json: jsonFormatter, +function formatByName(name: Format, customDelimiter?: Delimiter): FileFormatter { + const fileFormatter: Record = { + yml: YamlFormatter, + yaml: YamlFormatter, + toml: TomlFormatter, + json: JsonFormatter, frontmatter: FrontmatterInfer, 'json-frontmatter': frontmatterJSON(customDelimiter), 'toml-frontmatter': frontmatterTOML(customDelimiter), 'yaml-frontmatter': frontmatterYAML(customDelimiter), - }[name]; + }; + + return fileFormatter[name]; } -export function resolveFormat(collection: Collection, entry: Entry) { +export function resolveFormat(collection: Collection, entry: Entry): FileFormatter | undefined { // Check for custom delimiter const frontmatter_delimiter = collection.frontmatter_delimiter; @@ -59,7 +60,7 @@ export function resolveFormat(collection: Collection, entry: Entry) { if (filePath) { const fileExtension = filePath.split('.').pop(); if (fileExtension) { - return get(extensionFormatters, fileExtension); + return extensionFormatters[fileExtension]; } } @@ -67,7 +68,7 @@ export function resolveFormat(collection: Collection, entry: Entry) { // collection config, infer the format from that extension. const extension = collection.extension; if (extension) { - return get(extensionFormatters, extension); + return extensionFormatters[extension]; } // If no format is specified and it cannot be inferred, return the default. diff --git a/core/src/formats/frontmatter.ts b/core/src/formats/frontmatter.ts index 5f9fa775..71c7f3ae 100644 --- a/core/src/formats/frontmatter.ts +++ b/core/src/formats/frontmatter.ts @@ -1,8 +1,9 @@ import matter from 'gray-matter'; -import tomlFormatter from './toml'; -import yamlFormatter from './yaml'; -import jsonFormatter from './json'; +import TomlFormatter from './TomlFormatter'; +import YamlFormatter from './YamlFormatter'; +import JsonFormatter from './JsonFormatter'; +import { FileFormatter } from './FileFormatter'; const Languages = { YAML: 'yaml', @@ -17,10 +18,10 @@ type Format = { language: Language; delimiters: Delimiter }; const parsers = { toml: { - parse: (input: string) => tomlFormatter.fromFile(input), + parse: (input: string) => TomlFormatter.fromFile(input), stringify: (metadata: object, opts?: { sortedKeys?: string[] }) => { const { sortedKeys } = opts || {}; - return tomlFormatter.toFile(metadata, sortedKeys); + return TomlFormatter.toFile(metadata, sortedKeys); }, }, json: { @@ -30,10 +31,10 @@ const parsers = { if (JSONinput.slice(0, 1) !== '{') { JSONinput = '{' + JSONinput + '}'; } - return jsonFormatter.fromFile(JSONinput); + return JsonFormatter.fromFile(JSONinput); }, stringify: (metadata: object) => { - let JSONoutput = jsonFormatter.toFile(metadata).trim(); + let JSONoutput = JsonFormatter.toFile(metadata).trim(); // Trim leading and trailing brackets. if (JSONoutput.slice(0, 1) === '{' && JSONoutput.slice(-1) === '}') { JSONoutput = JSONoutput.slice(1, -1); @@ -42,13 +43,13 @@ const parsers = { }, }, yaml: { - parse: (input: string) => yamlFormatter.fromFile(input), + parse: (input: string) => YamlFormatter.fromFile(input), stringify: ( metadata: object, opts?: { sortedKeys?: string[]; comments?: Record }, ) => { const { sortedKeys, comments } = opts || {}; - return yamlFormatter.toFile(metadata, sortedKeys, comments); + return YamlFormatter.toFile(metadata, sortedKeys, comments); }, }, }; @@ -91,10 +92,11 @@ export function getFormatOpts(format?: Language, customDelimiter?: Delimiter) { }; } -export class FrontmatterFormatter { +export class FrontmatterFormatter extends FileFormatter { format?: Format; constructor(format?: Language, customDelimiter?: Delimiter) { + super(); this.format = getFormatOpts(format, customDelimiter); } diff --git a/core/src/formats/json.ts b/core/src/formats/json.ts deleted file mode 100644 index 518f85d4..00000000 --- a/core/src/formats/json.ts +++ /dev/null @@ -1,9 +0,0 @@ -export default { - fromFile(content: string) { - return JSON.parse(content); - }, - - toFile(data: object) { - return JSON.stringify(data, null, 2); - }, -}; diff --git a/core/src/interface.ts b/core/src/interface.ts index d3462974..176078fd 100644 --- a/core/src/interface.ts +++ b/core/src/interface.ts @@ -75,13 +75,13 @@ export type ValueOrNestedValue = export type EntryData = ObjectValue | undefined | null; -export interface Entry { +export interface Entry { collection: string; slug: string; path: string; partial: boolean; raw: string; - data: EntryData; + data: T | undefined | null; label: string | null; isModification: boolean | null; mediaFiles: MediaFile[]; @@ -277,10 +277,10 @@ export type WidgetPreviewComponent = | React.ReactElement> | ComponentType>; -export interface TemplatePreviewProps { +export interface TemplatePreviewProps { collection: Collection; fields: Field[]; - entry: Entry; + entry: Entry; document: Document | undefined | null; window: Window | undefined | null; getAsset: GetAssetFunction; diff --git a/core/src/reducers/entryDraft.ts b/core/src/reducers/entryDraft.ts index 924eff20..5fe2f74d 100644 --- a/core/src/reducers/entryDraft.ts +++ b/core/src/reducers/entryDraft.ts @@ -49,7 +49,6 @@ function entryDraftReducer( switch (action.type) { case DRAFT_CREATE_FROM_ENTRY: { const newState = { ...state }; - delete newState.localBackup; // Existing Entry return { diff --git a/core/src/widgets/markdown/MarkdownControl.tsx b/core/src/widgets/markdown/MarkdownControl.tsx index febc5544..e0faebd1 100644 --- a/core/src/widgets/markdown/MarkdownControl.tsx +++ b/core/src/widgets/markdown/MarkdownControl.tsx @@ -66,9 +66,11 @@ const MarkdownControl = ({ const handleOnChange = useCallback(() => { const newValue = editorRef.current?.getInstance().getMarkdown() ?? ''; - setInternalValue(newValue); - onChange(newValue); - }, [editorRef, onChange]); + if (newValue !== internalValue) { + setInternalValue(newValue); + onChange(newValue); + } + }, [editorRef, internalValue, onChange]); const handleLabelClick = useCallback(() => { editorRef.current?.getInstance().focus(); @@ -151,7 +153,7 @@ const MarkdownControl = ({ addMedia(); // eslint-disable-next-line react-hooks/exhaustive-deps - }, [field, mediaPath]); + }, [mediaPath]); const { initialEditType, height, ...markdownEditorOptions } = useEditorOptions(); diff --git a/core/src/widgets/markdown/MarkdownPreview.tsx b/core/src/widgets/markdown/MarkdownPreview.tsx index faffcea0..e73c9e02 100644 --- a/core/src/widgets/markdown/MarkdownPreview.tsx +++ b/core/src/widgets/markdown/MarkdownPreview.tsx @@ -19,8 +19,11 @@ const MarkdownPreview = ({ const mediaHolder = useMemo(() => new MediaHolder(), []); const media = useMedia({ value, getAsset, field }); + const viewer = useRef(null); + useEffect(() => { mediaHolder.setBulkMedia(media); + viewer.current?.getInstance().setMarkdown(value ?? ''); // eslint-disable-next-line react-hooks/exhaustive-deps }, [media]); @@ -31,12 +34,6 @@ const MarkdownPreview = ({ mode: 'preview', }); - const viewer = useRef(null); - - useEffect(() => { - viewer.current?.getInstance().setMarkdown(value ?? ''); - }, [value, media]); - return useMemo(() => { if (!value) { return null; diff --git a/core/src/widgets/markdown/hooks/useMedia.ts b/core/src/widgets/markdown/hooks/useMedia.ts index 0335b335..370990f6 100644 --- a/core/src/widgets/markdown/hooks/useMedia.ts +++ b/core/src/widgets/markdown/hooks/useMedia.ts @@ -48,7 +48,7 @@ const useMedia = ({ value, getAsset, field }: UseMediaProps) => { } const uniqueMediaToLoad = mediaToLoad.filter( - (value, index, self) => self.indexOf(value) === index, + (value, index, self) => self.indexOf(value) === index && !(value in media), ); for (const url of uniqueMediaToLoad) { diff --git a/core/src/widgets/relation/RelationControl.tsx b/core/src/widgets/relation/RelationControl.tsx index dc78f1bd..d20b23cd 100644 --- a/core/src/widgets/relation/RelationControl.tsx +++ b/core/src/widgets/relation/RelationControl.tsx @@ -113,6 +113,7 @@ const RelationControl = ({ query, locale, label, + hasErrors }: WidgetControlProps) => { const [internalValue, setInternalValue] = useState(value); const [initialOptions, setInitialOptions] = useState([]); @@ -227,6 +228,7 @@ const RelationControl = ({ key="relation-control-input" {...params} label={label} + error={hasErrors} InputProps={{ ...params.InputProps, endAdornment: ( diff --git a/core/yarn.lock b/core/yarn.lock index e714f7c7..e097eb12 100644 --- a/core/yarn.lock +++ b/core/yarn.lock @@ -7207,7 +7207,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.4, 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.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== @@ -7458,11 +7458,6 @@ react-is@^16.13.1, react-is@^16.7.0: resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ== -react-lifecycles-compat@^3.0.4: - version "3.0.4" - resolved "https://registry.yarnpkg.com/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz#4f1a273afdfc8f3488a8c516bfda78f872352362" - integrity sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA== - react-polyglot@0.7.2: version "0.7.2" resolved "https://registry.yarnpkg.com/react-polyglot/-/react-polyglot-0.7.2.tgz#b0277688c6d26eaff3312774738859cac53a227c" @@ -7519,22 +7514,6 @@ react-sortable-hoc@2.0.0: invariant "^2.2.4" prop-types "^15.5.7" -react-split-pane@0.1.92: - version "0.1.92" - resolved "https://registry.yarnpkg.com/react-split-pane/-/react-split-pane-0.1.92.tgz#68242f72138aed95dd5910eeb9d99822c4fc3a41" - integrity sha512-GfXP1xSzLMcLJI5BM36Vh7GgZBpy+U/X0no+VM3fxayv+p1Jly5HpMofZJraeaMl73b3hvlr+N9zJKvLB/uz9w== - dependencies: - prop-types "^15.7.2" - react-lifecycles-compat "^3.0.4" - react-style-proptype "^3.2.2" - -react-style-proptype@^3.2.2: - version "3.2.2" - resolved "https://registry.yarnpkg.com/react-style-proptype/-/react-style-proptype-3.2.2.tgz#d8e998e62ce79ec35b087252b90f19f1c33968a0" - integrity sha512-ywYLSjNkxKHiZOqNlso9PZByNEY+FTyh3C+7uuziK0xFXu9xzdyfHwg4S9iyiRRoPCR4k2LqaBBsWVmSBwCWYQ== - dependencies: - prop-types "^15.5.4" - 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"