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
This commit is contained in:
parent
763f33ef5e
commit
766009aa0d
@ -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
|
||||
|
@ -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",
|
||||
|
@ -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) {
|
||||
|
@ -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<AppProps>) => {
|
||||
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);
|
||||
|
@ -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<Collection | null>(null);
|
||||
const [preSlug, setPrevSlug] = useState<string | undefined | null>(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 (
|
||||
<div>
|
||||
|
@ -117,7 +117,7 @@ interface ControlHintProps {
|
||||
$error: boolean;
|
||||
}
|
||||
|
||||
export const ControlHint = styled(
|
||||
const ControlHint = styled(
|
||||
'p',
|
||||
transientOptions,
|
||||
)<ControlHintProps>(
|
||||
|
@ -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 = (
|
||||
<div>
|
||||
<div key={field.name}>
|
||||
<>
|
||||
<strong>{field.label ?? field.name}:</strong> {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);
|
||||
|
8
core/src/formats/FileFormatter.ts
Normal file
8
core/src/formats/FileFormatter.ts
Normal file
@ -0,0 +1,8 @@
|
||||
export abstract class FileFormatter {
|
||||
abstract fromFile(content: string): object;
|
||||
abstract toFile(
|
||||
data: object,
|
||||
sortedKeys?: string[],
|
||||
comments?: Record<string, string>,
|
||||
): string;
|
||||
}
|
13
core/src/formats/JsonFormatter.ts
Normal file
13
core/src/formats/JsonFormatter.ts
Normal file
@ -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();
|
@ -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();
|
@ -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<Pair>, comments: Record<string, string>, 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<string, string> = {}) {
|
||||
const contents = yaml.createNode(data) as YAMLMap | YAMLSeq;
|
||||
@ -38,5 +39,7 @@ export default {
|
||||
doc.contents = contents;
|
||||
|
||||
return doc.toString();
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export default new YamlFormatter();
|
@ -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<string, FileFormatter> = {
|
||||
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<string, FileFormatter> = {
|
||||
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.
|
||||
|
@ -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<string, string> },
|
||||
) => {
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -1,9 +0,0 @@
|
||||
export default {
|
||||
fromFile(content: string) {
|
||||
return JSON.parse(content);
|
||||
},
|
||||
|
||||
toFile(data: object) {
|
||||
return JSON.stringify(data, null, 2);
|
||||
},
|
||||
};
|
@ -75,13 +75,13 @@ export type ValueOrNestedValue =
|
||||
|
||||
export type EntryData = ObjectValue | undefined | null;
|
||||
|
||||
export interface Entry {
|
||||
export interface Entry<T = ObjectValue> {
|
||||
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<T = unknown, F extends Field = Field> =
|
||||
| React.ReactElement<unknown, string | React.JSXElementConstructor<any>>
|
||||
| ComponentType<WidgetPreviewProps<T, F>>;
|
||||
|
||||
export interface TemplatePreviewProps {
|
||||
export interface TemplatePreviewProps<T = unknown> {
|
||||
collection: Collection;
|
||||
fields: Field[];
|
||||
entry: Entry;
|
||||
entry: Entry<T>;
|
||||
document: Document | undefined | null;
|
||||
window: Window | undefined | null;
|
||||
getAsset: GetAssetFunction;
|
||||
|
@ -49,7 +49,6 @@ function entryDraftReducer(
|
||||
switch (action.type) {
|
||||
case DRAFT_CREATE_FROM_ENTRY: {
|
||||
const newState = { ...state };
|
||||
delete newState.localBackup;
|
||||
|
||||
// Existing Entry
|
||||
return {
|
||||
|
@ -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();
|
||||
|
||||
|
@ -19,8 +19,11 @@ const MarkdownPreview = ({
|
||||
const mediaHolder = useMemo(() => new MediaHolder(), []);
|
||||
const media = useMedia({ value, getAsset, field });
|
||||
|
||||
const viewer = useRef<Viewer | null>(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<Viewer | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
viewer.current?.getInstance().setMarkdown(value ?? '');
|
||||
}, [value, media]);
|
||||
|
||||
return useMemo(() => {
|
||||
if (!value) {
|
||||
return null;
|
||||
|
@ -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) {
|
||||
|
@ -113,6 +113,7 @@ const RelationControl = ({
|
||||
query,
|
||||
locale,
|
||||
label,
|
||||
hasErrors
|
||||
}: WidgetControlProps<string | string[], RelationField>) => {
|
||||
const [internalValue, setInternalValue] = useState(value);
|
||||
const [initialOptions, setInitialOptions] = useState<HitOption[]>([]);
|
||||
@ -227,6 +228,7 @@ const RelationControl = ({
|
||||
key="relation-control-input"
|
||||
{...params}
|
||||
label={label}
|
||||
error={hasErrors}
|
||||
InputProps={{
|
||||
...params.InputProps,
|
||||
endAdornment: (
|
||||
|
@ -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"
|
||||
|
Loading…
x
Reference in New Issue
Block a user