parent
f3c4337268
commit
147592a8b8
@ -55,6 +55,24 @@ module.exports = {
|
||||
caughtErrorsIgnorePattern: '^_',
|
||||
},
|
||||
],
|
||||
'@typescript-eslint/no-restricted-imports': [
|
||||
'error',
|
||||
{
|
||||
patterns: [
|
||||
{
|
||||
group: ['@mui/*/*/*', '!@mui/material/test-utils/*'],
|
||||
message: 'Do not import material imports as 3rd level imports',
|
||||
allowTypeImports: true,
|
||||
},
|
||||
{
|
||||
group: ['@mui/material', '!@mui/material/'],
|
||||
message: 'Please import material imports as defaults or 2nd level imports',
|
||||
allowTypeImports: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
'import/prefer-default-export': 'error',
|
||||
},
|
||||
plugins: ['babel', '@emotion', 'cypress', 'unicorn', 'react-hooks'],
|
||||
settings: {
|
||||
@ -62,9 +80,7 @@ module.exports = {
|
||||
version: 'detect',
|
||||
},
|
||||
'import/resolver': {
|
||||
node: {
|
||||
extensions: ['.js', '.jsx', '.ts', '.tsx'],
|
||||
},
|
||||
typescript: {}, // this loads <rootdir>/tsconfig.json to eslint
|
||||
},
|
||||
'import/core-modules': ['src'],
|
||||
},
|
||||
|
@ -68,9 +68,7 @@
|
||||
content: '{}',
|
||||
},
|
||||
'image.json': {
|
||||
content: `{
|
||||
"required": "/assets/uploads/moby-dick.jpg"
|
||||
}`,
|
||||
content: `{}`,
|
||||
},
|
||||
'map.json': {
|
||||
content: '{}',
|
||||
@ -125,7 +123,71 @@
|
||||
dateString +
|
||||
'T00:00:00.000Z\n---\n# The post is number ' +
|
||||
i +
|
||||
'\n\nAnd this is yet another identical post body',
|
||||
`\n\n
|
||||
|
||||
# Awesome Editor!
|
||||
|
||||
It was _released as open source in 2022_ and is **_continually_** evolving to be the **best editor experience** available for static site generators.
|
||||
|
||||
## MDX
|
||||
|
||||
The output out this widget is \`mdx\`, a mixture of \`markdown\` and \`javascript components\`. See [MDX documentation](https://mdxjs.com/docs/).
|
||||
|
||||
\`\`\`yaml
|
||||
name: body
|
||||
label: Blog post content
|
||||
widget: markdown
|
||||
\`\`\`
|
||||
|
||||
\`\`\`js
|
||||
name: 'body',
|
||||
label: 'Blog post content',
|
||||
widget: 'markdown',
|
||||
\`\`\`
|
||||
|
||||
> See the table below for default options
|
||||
> More API information can be found in the document
|
||||
|
||||
| Name | Type | Default | Description |
|
||||
| ------------- | --------------------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| default | string | \`''\` | _Optional_. The default value for the field. Accepts markdown content |
|
||||
| media_library | Media Library Options | \`{}\` | _Optional_. Media library settings to apply when a media library is opened by the current widget. See [Media Library Options](#media-library-options) |
|
||||
| media_folder | string | | _Optional_. Specifies the folder path where uploaded files should be saved, relative to the base of the repo |
|
||||
| public_folder | string | | _Optional_. Specifies the folder path where the files uploaded by the media library will be accessed, relative to the base of the built site |
|
||||
|
||||
### Media Library Options
|
||||
|
||||
| Name | Type | Default | Description |
|
||||
| -------------- | ---------------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| allow_multiple | boolean | \`true\` | _Optional_. When set to \`false\`, prevents multiple selection for any media library extension, but must be supported by the extension in use |
|
||||
| config | string | \`{}\` | _Optional_. A configuration object that will be passed directly to the media library being used - available options are determined by the library |
|
||||
| choose_url | string<br />\\| boolean | \`true\` | _Optional_. When set to \`false\`, the "Insert from URL" button will be hidden
|
||||
|
||||
## Features
|
||||
|
||||
* CommonMark + GFM Specifications
|
||||
* Live \`Preview\`
|
||||
* Auto Indent
|
||||
* Syntax Highlight
|
||||
1. Rich Editor
|
||||
2. Preview
|
||||
|
||||
## Formatting
|
||||
|
||||
<font style={{ color: 'red', backgroundColor: 'black' }}>Colored Text</font>
|
||||
|
||||
<p align="center">Centered Text</p>
|
||||
|
||||
**Bold**, *Italic*, ***both***, <u>Underlined</u>
|
||||
|
||||
~~Strikethrough~~, <sub>subscript</sub>, <sup>superscript</sup>
|
||||
|
||||
## Support
|
||||
|
||||
> * Supports remark plugins
|
||||
> * Supports wrappers
|
||||
> 1. [x] React
|
||||
> 2. [ ] More coming soon`,
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -41,30 +41,41 @@
|
||||
"last 2 Safari versions"
|
||||
],
|
||||
"dependencies": {
|
||||
"@codemirror/commands": "6.1.2",
|
||||
"@codemirror/view": "6.6.0",
|
||||
"@emotion/babel-preset-css-prop": "11.10.0",
|
||||
"@emotion/css": "11.10.0",
|
||||
"@emotion/react": "11.10.4",
|
||||
"@emotion/styled": "11.10.4",
|
||||
"@ltd/j-toml": "1.35.3",
|
||||
"@mdx-js/mdx": "2.1.5",
|
||||
"@mdx-js/react": "2.1.5",
|
||||
"@mui/icons-material": "5.10.6",
|
||||
"@mui/material": "5.10.10",
|
||||
"@mui/system": "5.4.1",
|
||||
"@mui/x-date-pickers": "5.0.9",
|
||||
"@reduxjs/toolkit": "1.8.5",
|
||||
"@toast-ui/react-editor": "3.2.2",
|
||||
"@reduxjs/toolkit": "1.9.1",
|
||||
"@styled-icons/fluentui-system-regular": "10.46.0",
|
||||
"@styled-icons/remix-editor": "10.46.0",
|
||||
"@udecode/plate": "18.9.0",
|
||||
"@udecode/plate-juice": "18.9.0",
|
||||
"@udecode/plate-serializer-md": "18.9.0",
|
||||
"@uiw/codemirror-extensions-langs": "4.14.2",
|
||||
"@uiw/react-codemirror": "4.14.2",
|
||||
"ajv": "8.11.2",
|
||||
"ajv-errors": "3.0.0",
|
||||
"ajv-keywords": "5.1.0",
|
||||
"array-move": "4.0.0",
|
||||
"buffer": "6.0.3",
|
||||
"clean-stack": "4.2.0",
|
||||
"codemirror": "5.65.9",
|
||||
"codemirror": "6.0.1",
|
||||
"common-tags": "1.8.1",
|
||||
"copy-text-to-clipboard": "3.0.1",
|
||||
"create-react-class": "15.7.0",
|
||||
"date-fns": "2.29.3",
|
||||
"deepmerge": "4.2.2",
|
||||
"diacritics": "1.3.0",
|
||||
"escape-html": "1.0.3",
|
||||
"eslint-config-prettier": "8.5.0",
|
||||
"eslint-plugin-babel": "5.3.1",
|
||||
"fuzzy": "0.1.3",
|
||||
@ -74,7 +85,7 @@
|
||||
"graphql-tag": "2.12.6",
|
||||
"gray-matter": "4.0.3",
|
||||
"history": "4.10.1",
|
||||
"immer": "9.0.15",
|
||||
"immer": "9.0.16",
|
||||
"ini": "2.0.0",
|
||||
"is-hotkey": "0.2.0",
|
||||
"js-base64": "3.7.2",
|
||||
@ -88,15 +99,14 @@
|
||||
"ol": "6.15.1",
|
||||
"path-browserify": "1.0.1",
|
||||
"react": "18.2.0",
|
||||
"react-codemirror2": "7.2.1",
|
||||
"react-color": "2.19.3",
|
||||
"react-dnd": "14.0.5",
|
||||
"react-dnd-html5-backend": "14.1.0",
|
||||
"react-dnd": "16.0.1",
|
||||
"react-dnd-html5-backend": "16.0.1",
|
||||
"react-dom": "18.2.0",
|
||||
"react-frame-component": "5.2.3",
|
||||
"react-is": "18.2.0",
|
||||
"react-polyglot": "0.7.2",
|
||||
"react-redux": "8.0.4",
|
||||
"react-redux": "8.0.5",
|
||||
"react-router-dom": "6.4.1",
|
||||
"react-scroll-sync": "0.9.0",
|
||||
"react-sortable-hoc": "2.0.0",
|
||||
@ -105,17 +115,31 @@
|
||||
"react-virtualized-auto-sizer": "1.0.7",
|
||||
"react-waypoint": "10.3.0",
|
||||
"react-window": "1.8.7",
|
||||
"remark-gfm": "3.0.1",
|
||||
"remark-html": "15.0.1",
|
||||
"remark-mdx": "2.1.5",
|
||||
"remark-parse": "10.0.1",
|
||||
"sanitize-filename": "1.6.3",
|
||||
"semaphore": "1.1.0",
|
||||
"slate": "0.85.0",
|
||||
"slate-history": "0.85.0",
|
||||
"slate-hyperscript": "0.77.0",
|
||||
"slate-react": "0.83.2",
|
||||
"stream-browserify": "3.0.0",
|
||||
"styled-components": "5.3.6",
|
||||
"symbol-observable": "4.0.0",
|
||||
"ts-loader": "9.4.1",
|
||||
"unified": "10.1.2",
|
||||
"unist-util-visit": "4.1.1",
|
||||
"uploadcare-widget": "3.19.0",
|
||||
"uploadcare-widget-tab-effects": "1.5.0",
|
||||
"url": "0.11.0",
|
||||
"url-join": "4.0.1",
|
||||
"uuid": "3.4.0",
|
||||
"validate-color": "2.2.1",
|
||||
"vfile": "5.3.6",
|
||||
"vfile-message": "3.1.3",
|
||||
"vfile-statistics": "2.0.0",
|
||||
"what-input": "5.2.12",
|
||||
"what-the-diff": "0.6.0",
|
||||
"yaml": "1.10.2"
|
||||
@ -137,7 +161,7 @@
|
||||
"@octokit/core": "4.1.0",
|
||||
"@octokit/rest": "16.43.2",
|
||||
"@pmmmwh/react-refresh-webpack-plugin": "0.5.10",
|
||||
"@types/codemirror": "5.60.5",
|
||||
"@simbathesailor/use-what-changed": "2.0.0",
|
||||
"@types/common-tags": "1.8.0",
|
||||
"@types/create-react-class": "15.6.3",
|
||||
"@types/fs-extra": "9.0.13",
|
||||
@ -149,6 +173,7 @@
|
||||
"@types/jwt-decode": "2.2.1",
|
||||
"@types/lodash": "4.14.191",
|
||||
"@types/minimatch": "5.1.2",
|
||||
"@types/node": "16.18.4",
|
||||
"@types/node-fetch": "2.6.2",
|
||||
"@types/react": "18.0.25",
|
||||
"@types/react-color": "3.0.6",
|
||||
@ -156,6 +181,7 @@
|
||||
"@types/react-scroll-sync": "0.8.4",
|
||||
"@types/react-virtualized-auto-sizer": "1.0.1",
|
||||
"@types/react-window": "1.8.5",
|
||||
"@types/styled-components": "5.1.26",
|
||||
"@types/url-join": "4.0.1",
|
||||
"@types/uuid": "3.4.10",
|
||||
"@typescript-eslint/eslint-plugin": "5.38.0",
|
||||
@ -179,6 +205,7 @@
|
||||
"css-loader": "3.6.0",
|
||||
"dotenv": "10.0.0",
|
||||
"eslint": "8.24.0",
|
||||
"eslint-import-resolver-typescript": "3.5.2",
|
||||
"eslint-plugin-cypress": "2.12.1",
|
||||
"eslint-plugin-import": "2.26.0",
|
||||
"eslint-plugin-prettier": "4.2.1",
|
||||
@ -208,6 +235,7 @@
|
||||
"source-map-loader": "4.0.0",
|
||||
"style-loader": "3.3.1",
|
||||
"to-string-loader": "1.2.0",
|
||||
"tsconfig-paths-webpack-plugin": "4.0.0",
|
||||
"typescript": "4.8.4",
|
||||
"webpack": "5.74.0",
|
||||
"webpack-cli": "4.10.0",
|
||||
|
@ -5,7 +5,7 @@ import trimStart from 'lodash/trimStart';
|
||||
import yaml from 'yaml';
|
||||
|
||||
import { resolveBackend } from '../backend';
|
||||
import { validateConfig } from '../constants/configSchema';
|
||||
import validateConfig from '../constants/configSchema';
|
||||
import { I18N, I18N_FIELD, I18N_STRUCTURE } from '../lib/i18n';
|
||||
import { selectDefaultSortableFields } from '../lib/util/collection.util';
|
||||
import { getIntegrations, selectIntegration } from '../reducers/integrations';
|
||||
|
@ -14,7 +14,7 @@ import { selectEntriesSortFields, selectIsFetching } from '../reducers/entries';
|
||||
import { navigateToEntry } from '../routing/history';
|
||||
import { addSnackbar } from '../store/slices/snackbars';
|
||||
import { createAssetProxy } from '../valueObjects/AssetProxy';
|
||||
import { createEntry } from '../valueObjects/Entry';
|
||||
import createEntry from '../valueObjects/createEntry';
|
||||
import { addAssets, getAsset } from './media';
|
||||
import { loadMedia, waitForMediaLibraryToLoad } from './mediaLibrary';
|
||||
import { waitUntil } from './waitUntil';
|
||||
@ -475,18 +475,16 @@ export function changeDraftField({
|
||||
path,
|
||||
field,
|
||||
value,
|
||||
entry,
|
||||
i18n,
|
||||
}: {
|
||||
path: string;
|
||||
field: Field;
|
||||
value: ValueOrNestedValue;
|
||||
entry?: Entry | null;
|
||||
i18n?: I18nSettings;
|
||||
}) {
|
||||
return {
|
||||
type: DRAFT_CHANGE_FIELD,
|
||||
payload: { path, field, value, entry, i18n },
|
||||
payload: { path, field, value, i18n },
|
||||
} as const;
|
||||
}
|
||||
|
||||
@ -884,7 +882,7 @@ export function createEmptyDraftData(
|
||||
fields: Field[],
|
||||
skipField: (field: Field) => boolean = () => false,
|
||||
) {
|
||||
return fields.reduce((acc, item) => {
|
||||
const ddd = fields.reduce((acc, item) => {
|
||||
if (skipField(item)) {
|
||||
return acc;
|
||||
}
|
||||
@ -904,7 +902,7 @@ export function createEmptyDraftData(
|
||||
} else {
|
||||
const asList = Array.isArray(subfields) ? subfields : [subfields];
|
||||
|
||||
const subDefaultValue = Array.isArray(subfields)
|
||||
const subDefaultValue = list
|
||||
? [createEmptyDraftData(asList, skipField)]
|
||||
: createEmptyDraftData(asList, skipField);
|
||||
|
||||
@ -921,6 +919,8 @@ export function createEmptyDraftData(
|
||||
|
||||
return acc;
|
||||
}, {} as ObjectValue);
|
||||
|
||||
return ddd;
|
||||
}
|
||||
|
||||
function createEmptyDraftI18nData(collection: Collection, dataFields: Field[]) {
|
||||
|
@ -42,7 +42,7 @@ export function loadAssetFailure(path: string, error: Error) {
|
||||
return { type: LOAD_ASSET_FAILURE, payload: { path, error } } as const;
|
||||
}
|
||||
|
||||
const emptyAsset = createAssetProxy({
|
||||
export const emptyAsset = createAssetProxy({
|
||||
path: 'empty.svg',
|
||||
file: new File([`<svg xmlns="http://www.w3.org/2000/svg"></svg>`], 'empty.svg', {
|
||||
type: 'image/svg+xml',
|
||||
@ -84,7 +84,7 @@ async function loadAsset(
|
||||
const promiseCache: Record<string, Promise<AssetProxy>> = {};
|
||||
|
||||
export function getAsset<F extends BaseField = UnknownField>(
|
||||
collection: Collection | null | undefined,
|
||||
collection: Collection<F> | null | undefined,
|
||||
entry: Entry | null | undefined,
|
||||
path: string,
|
||||
field?: F,
|
||||
@ -104,7 +104,7 @@ export function getAsset<F extends BaseField = UnknownField>(
|
||||
|
||||
const resolvedPath = selectMediaFilePath(
|
||||
state.config.config,
|
||||
collection,
|
||||
collection as Collection,
|
||||
entry,
|
||||
path,
|
||||
field as Field,
|
||||
|
@ -41,7 +41,7 @@ import {
|
||||
import { selectMediaFilePath } from './lib/util/media.util';
|
||||
import { set } from './lib/util/object.util';
|
||||
import { dateParsers, expandPath, extractTemplateVars } from './lib/widgets/stringTemplate';
|
||||
import { createEntry } from './valueObjects/Entry';
|
||||
import createEntry from './valueObjects/createEntry';
|
||||
|
||||
import type {
|
||||
BackendClass,
|
||||
|
@ -15,11 +15,11 @@ import {
|
||||
then,
|
||||
throwOnConflictingBranches,
|
||||
unsentRequest,
|
||||
} from '../../lib/util';
|
||||
} from '@staticcms/core/lib/util';
|
||||
|
||||
import type { DataFile, PersistOptions } from '../../interface';
|
||||
import type { ApiRequest, FetchError } from '../../lib/util';
|
||||
import type AssetProxy from '../../valueObjects/AssetProxy';
|
||||
import type { DataFile, PersistOptions } from '@staticcms/core/interface';
|
||||
import type { ApiRequest, FetchError } from '@staticcms/core/lib/util';
|
||||
import type AssetProxy from '@staticcms/core/valueObjects/AssetProxy';
|
||||
|
||||
interface Config {
|
||||
apiRoot?: string;
|
||||
|
@ -1,12 +1,12 @@
|
||||
import { styled } from '@mui/material/styles';
|
||||
import React, { useCallback, useMemo, useState } from 'react';
|
||||
|
||||
import AuthenticationPage from '../../components/UI/AuthenticationPage';
|
||||
import Icon from '../../components/UI/Icon';
|
||||
import { ImplicitAuthenticator, NetlifyAuthenticator } from '../../lib/auth';
|
||||
import AuthenticationPage from '@staticcms/core/components/UI/AuthenticationPage';
|
||||
import Icon from '@staticcms/core/components/UI/Icon';
|
||||
import { ImplicitAuthenticator, NetlifyAuthenticator } from '@staticcms/core/lib/auth';
|
||||
|
||||
import type { MouseEvent } from 'react';
|
||||
import type { AuthenticationPageProps, TranslatedProps } from '../../interface';
|
||||
import type { AuthenticationPageProps, TranslatedProps } from '@staticcms/core/interface';
|
||||
|
||||
const LoginButtonIcon = styled(Icon)`
|
||||
margin-right: 18px;
|
||||
|
@ -1,8 +1,8 @@
|
||||
import minimatch from 'minimatch';
|
||||
|
||||
import { unsentRequest } from '../../lib/util';
|
||||
import { unsentRequest } from '@staticcms/core/lib/util';
|
||||
|
||||
import type { ApiRequest, PointerFile } from '../../lib/util';
|
||||
import type { ApiRequest, PointerFile } from '@staticcms/core/lib/util';
|
||||
|
||||
type MakeAuthorizedRequest = (req: ApiRequest) => Promise<Response>;
|
||||
|
||||
@ -37,7 +37,7 @@ interface LfsBatchUploadResponse {
|
||||
objects: (LfsBatchObjectUpload | LfsBatchObjectError)[];
|
||||
}
|
||||
|
||||
export class GitLfsClient {
|
||||
export default class GitLfsClient {
|
||||
private static defaultContentHeaders = {
|
||||
Accept: 'application/vnd.git-lfs+json',
|
||||
['Content-Type']: 'application/vnd.git-lfs+json',
|
||||
|
@ -2,7 +2,7 @@ import { stripIndent } from 'common-tags';
|
||||
import trimStart from 'lodash/trimStart';
|
||||
import semaphore from 'semaphore';
|
||||
|
||||
import { NetlifyAuthenticator } from '../../lib/auth';
|
||||
import { NetlifyAuthenticator } from '@staticcms/core/lib/auth';
|
||||
import {
|
||||
AccessTokenError,
|
||||
allEntriesByFolder,
|
||||
@ -22,10 +22,10 @@ import {
|
||||
localForage,
|
||||
runWithLock,
|
||||
unsentRequest,
|
||||
} from '../../lib/util';
|
||||
} from '@staticcms/core/lib/util';
|
||||
import API, { API_NAME } from './API';
|
||||
import AuthenticationPage from './AuthenticationPage';
|
||||
import { GitLfsClient } from './git-lfs-client';
|
||||
import GitLfsClient from './git-lfs-client';
|
||||
|
||||
import type { Semaphore } from 'semaphore';
|
||||
import type {
|
||||
@ -37,9 +37,9 @@ import type {
|
||||
ImplementationFile,
|
||||
PersistOptions,
|
||||
User,
|
||||
} from '../../interface';
|
||||
import type { ApiRequest, AsyncLock, Cursor, FetchError } from '../../lib/util';
|
||||
import type AssetProxy from '../../valueObjects/AssetProxy';
|
||||
} from '@staticcms/core/interface';
|
||||
import type { ApiRequest, AsyncLock, Cursor, FetchError } from '@staticcms/core/lib/util';
|
||||
import type AssetProxy from '@staticcms/core/valueObjects/AssetProxy';
|
||||
|
||||
const MAX_CONCURRENT_DOWNLOADS = 10;
|
||||
|
||||
|
@ -1,8 +1,8 @@
|
||||
import React, { useCallback, useEffect, useMemo, useState } from 'react';
|
||||
|
||||
import AuthenticationPage from '../../components/UI/AuthenticationPage';
|
||||
import AuthenticationPage from '@staticcms/core/components/UI/AuthenticationPage';
|
||||
|
||||
import type { AuthenticationPageProps, TranslatedProps, User } from '../../interface';
|
||||
import type { AuthenticationPageProps, TranslatedProps, User } from '@staticcms/core/interface';
|
||||
|
||||
function useNetlifyIdentifyEvent(eventName: 'login', callback: (login: User) => void): void;
|
||||
function useNetlifyIdentifyEvent(eventName: 'logout', callback: () => void): void;
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { APIError } from '../../lib/util';
|
||||
import { APIError } from '@staticcms/core/lib/util';
|
||||
import { API as GithubAPI } from '../github';
|
||||
|
||||
import type { FetchError } from '../../lib/util';
|
||||
import type { FetchError } from '@staticcms/core/lib/util';
|
||||
import type { Config as GitHubConfig } from '../github/API';
|
||||
|
||||
type Config = GitHubConfig & {
|
||||
|
@ -1,8 +1,8 @@
|
||||
import { unsentRequest } from '../../lib/util';
|
||||
import { unsentRequest } from '@staticcms/core/lib/util';
|
||||
import { API as GitlabAPI } from '../gitlab';
|
||||
|
||||
import type { Config as GitLabConfig, CommitAuthor } from '../gitlab/API';
|
||||
import type { ApiRequest } from '../../lib/util';
|
||||
import type { ApiRequest } from '@staticcms/core/lib/util';
|
||||
|
||||
type Config = GitLabConfig & { tokenPromise: () => Promise<string>; commitAuthor: CommitAuthor };
|
||||
|
||||
|
@ -15,7 +15,7 @@ import {
|
||||
getPointerFileForMediaFileObj,
|
||||
parsePointerFile,
|
||||
unsentRequest,
|
||||
} from '../../lib/util';
|
||||
} from '@staticcms/core/lib/util';
|
||||
import { API as BitBucketAPI, BitbucketBackend } from '../bitbucket';
|
||||
import { GitHubBackend } from '../github';
|
||||
import { GitLabBackend } from '../gitlab';
|
||||
@ -36,9 +36,9 @@ import type {
|
||||
PersistOptions,
|
||||
TranslatedProps,
|
||||
User,
|
||||
} from '../../interface';
|
||||
import type { ApiRequest, Cursor } from '../../lib/util';
|
||||
import type AssetProxy from '../../valueObjects/AssetProxy';
|
||||
} from '@staticcms/core/interface';
|
||||
import type { ApiRequest, Cursor } from '@staticcms/core/lib/util';
|
||||
import type AssetProxy from '@staticcms/core/valueObjects/AssetProxy';
|
||||
import type { Client } from './netlify-lfs-client';
|
||||
|
||||
const STATUS_PAGE = 'https://www.netlifystatus.com';
|
||||
|
@ -3,9 +3,9 @@ import isPlainObject from 'lodash/isPlainObject';
|
||||
import isEmpty from 'lodash/isEmpty';
|
||||
import minimatch from 'minimatch';
|
||||
|
||||
import { unsentRequest } from '../../lib/util';
|
||||
import { unsentRequest } from '@staticcms/core/lib/util';
|
||||
|
||||
import type { ApiRequest, PointerFile } from '../../lib/util';
|
||||
import type { ApiRequest, PointerFile } from '@staticcms/core/lib/util';
|
||||
|
||||
type MakeAuthorizedRequest = (req: ApiRequest) => Promise<Response>;
|
||||
|
||||
|
@ -17,13 +17,13 @@ import {
|
||||
readFileMetadata,
|
||||
requestWithBackoff,
|
||||
unsentRequest,
|
||||
} from '../../lib/util';
|
||||
} from '@staticcms/core/lib/util';
|
||||
|
||||
import type { Octokit } from '@octokit/rest';
|
||||
import type { Semaphore } from 'semaphore';
|
||||
import type { DataFile, PersistOptions } from '../../interface';
|
||||
import type { ApiRequest, FetchError } from '../../lib/util';
|
||||
import type AssetProxy from '../../valueObjects/AssetProxy';
|
||||
import type { DataFile, PersistOptions } from '@staticcms/core/interface';
|
||||
import type { ApiRequest, FetchError } from '@staticcms/core/lib/util';
|
||||
import type AssetProxy from '@staticcms/core/valueObjects/AssetProxy';
|
||||
|
||||
type GitHubUser = Octokit.UsersGetAuthenticatedResponse;
|
||||
type GitCreateTreeParamsTree = Octokit.GitCreateTreeParamsTree;
|
||||
|
@ -1,12 +1,12 @@
|
||||
import { styled } from '@mui/material/styles';
|
||||
import React, { useCallback, useState } from 'react';
|
||||
|
||||
import AuthenticationPage from '../../components/UI/AuthenticationPage';
|
||||
import Icon from '../../components/UI/Icon';
|
||||
import { NetlifyAuthenticator } from '../../lib/auth';
|
||||
import AuthenticationPage from '@staticcms/core/components/UI/AuthenticationPage';
|
||||
import Icon from '@staticcms/core/components/UI/Icon';
|
||||
import { NetlifyAuthenticator } from '@staticcms/core/lib/auth';
|
||||
|
||||
import type { MouseEvent } from 'react';
|
||||
import type { AuthenticationPageProps, TranslatedProps } from '../../interface';
|
||||
import type { AuthenticationPageProps, TranslatedProps } from '@staticcms/core/interface';
|
||||
|
||||
const LoginButtonIcon = styled(Icon)`
|
||||
margin-right: 18px;
|
||||
|
@ -16,7 +16,7 @@ import {
|
||||
getMediaDisplayURL,
|
||||
runWithLock,
|
||||
unsentRequest,
|
||||
} from '../../lib/util';
|
||||
} from '@staticcms/core/lib/util';
|
||||
import API, { API_NAME } from './API';
|
||||
import AuthenticationPage from './AuthenticationPage';
|
||||
|
||||
@ -31,9 +31,9 @@ import type {
|
||||
ImplementationFile,
|
||||
PersistOptions,
|
||||
User,
|
||||
} from '../../interface';
|
||||
import type { AsyncLock } from '../../lib/util';
|
||||
import type AssetProxy from '../../valueObjects/AssetProxy';
|
||||
} from '@staticcms/core/interface';
|
||||
import type { AsyncLock } from '@staticcms/core/lib/util';
|
||||
import type AssetProxy from '@staticcms/core/valueObjects/AssetProxy';
|
||||
|
||||
type GitHubUser = Octokit.UsersGetAuthenticatedResponse;
|
||||
|
||||
|
@ -1,3 +1,4 @@
|
||||
/* eslint-disable import/prefer-default-export */
|
||||
import { gql } from 'graphql-tag';
|
||||
|
||||
import * as fragments from './fragments';
|
||||
|
@ -15,11 +15,11 @@ import {
|
||||
responseParser,
|
||||
throwOnConflictingBranches,
|
||||
unsentRequest,
|
||||
} from '../../lib/util';
|
||||
} from '@staticcms/core/lib/util';
|
||||
|
||||
import type { DataFile, PersistOptions } from '../../interface';
|
||||
import type { ApiRequest, FetchError } from '../../lib/util';
|
||||
import type AssetProxy from '../../valueObjects/AssetProxy';
|
||||
import type { DataFile, PersistOptions } from '@staticcms/core/interface';
|
||||
import type { ApiRequest, FetchError } from '@staticcms/core/lib/util';
|
||||
import type AssetProxy from '@staticcms/core/valueObjects/AssetProxy';
|
||||
|
||||
export const API_NAME = 'GitLab';
|
||||
|
||||
|
@ -1,17 +1,17 @@
|
||||
import { styled } from '@mui/material/styles';
|
||||
import React, { useCallback, useMemo, useState } from 'react';
|
||||
|
||||
import AuthenticationPage from '../../components/UI/AuthenticationPage';
|
||||
import Icon from '../../components/UI/Icon';
|
||||
import { NetlifyAuthenticator, PkceAuthenticator } from '../../lib/auth';
|
||||
import { isNotEmpty } from '../../lib/util/string.util';
|
||||
import AuthenticationPage from '@staticcms/core/components/UI/AuthenticationPage';
|
||||
import Icon from '@staticcms/core/components/UI/Icon';
|
||||
import { NetlifyAuthenticator, PkceAuthenticator } from '@staticcms/core/lib/auth';
|
||||
import { isNotEmpty } from '@staticcms/core/lib/util/string.util';
|
||||
|
||||
import type { MouseEvent } from 'react';
|
||||
import type {
|
||||
AuthenticationPageProps,
|
||||
AuthenticatorConfig,
|
||||
TranslatedProps,
|
||||
} from '../../interface';
|
||||
} from '@staticcms/core/interface';
|
||||
|
||||
const LoginButtonIcon = styled(Icon)`
|
||||
margin-right: 18px;
|
||||
|
@ -17,12 +17,12 @@ import {
|
||||
getMediaDisplayURL,
|
||||
localForage,
|
||||
runWithLock,
|
||||
} from '../../lib/util';
|
||||
} from '@staticcms/core/lib/util';
|
||||
import API, { API_NAME } from './API';
|
||||
import AuthenticationPage from './AuthenticationPage';
|
||||
|
||||
import type { Semaphore } from 'semaphore';
|
||||
import type { AsyncLock, Cursor } from '../../lib/util';
|
||||
import type { AsyncLock, Cursor } from '@staticcms/core/lib/util';
|
||||
import type {
|
||||
Config,
|
||||
Credentials,
|
||||
@ -32,8 +32,8 @@ import type {
|
||||
ImplementationFile,
|
||||
PersistOptions,
|
||||
User,
|
||||
} from '../../interface';
|
||||
import type AssetProxy from '../../valueObjects/AssetProxy';
|
||||
} from '@staticcms/core/interface';
|
||||
import type AssetProxy from '@staticcms/core/valueObjects/AssetProxy';
|
||||
|
||||
const MAX_CONCURRENT_DOWNLOADS = 10;
|
||||
|
||||
|
@ -2,11 +2,11 @@ import Button from '@mui/material/Button';
|
||||
import { styled } from '@mui/material/styles';
|
||||
import React, { useCallback } from 'react';
|
||||
|
||||
import GoBackButton from '../../components/UI/GoBackButton';
|
||||
import Icon from '../../components/UI/Icon';
|
||||
import GoBackButton from '@staticcms/core/components/UI/GoBackButton';
|
||||
import Icon from '@staticcms/core/components/UI/Icon';
|
||||
|
||||
import type { MouseEvent } from 'react';
|
||||
import type { AuthenticationPageProps, TranslatedProps } from '../../interface';
|
||||
import type { AuthenticationPageProps, TranslatedProps } from '@staticcms/core/interface';
|
||||
|
||||
const StyledAuthenticationPage = styled('section')`
|
||||
display: flex;
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { APIError, basename, blobToFileObj, unsentRequest } from '../../lib/util';
|
||||
import { APIError, basename, blobToFileObj, unsentRequest } from '@staticcms/core/lib/util';
|
||||
import AuthenticationPage from './AuthenticationPage';
|
||||
|
||||
import type {
|
||||
@ -10,9 +10,9 @@ import type {
|
||||
ImplementationFile,
|
||||
PersistOptions,
|
||||
User,
|
||||
} from '../../interface';
|
||||
import type { Cursor } from '../../lib/util';
|
||||
import type AssetProxy from '../../valueObjects/AssetProxy';
|
||||
} from '@staticcms/core/interface';
|
||||
import type { Cursor } from '@staticcms/core/lib/util';
|
||||
import type AssetProxy from '@staticcms/core/valueObjects/AssetProxy';
|
||||
|
||||
async function serializeAsset(assetProxy: AssetProxy) {
|
||||
const base64content = await assetProxy.toBase64!();
|
||||
|
@ -2,11 +2,11 @@ import Button from '@mui/material/Button';
|
||||
import { styled } from '@mui/material/styles';
|
||||
import React, { useCallback, useEffect } from 'react';
|
||||
|
||||
import GoBackButton from '../../components/UI/GoBackButton';
|
||||
import Icon from '../../components/UI/Icon';
|
||||
import GoBackButton from '@staticcms/core/components/UI/GoBackButton';
|
||||
import Icon from '@staticcms/core/components/UI/Icon';
|
||||
|
||||
import type { MouseEvent } from 'react';
|
||||
import type { AuthenticationPageProps, TranslatedProps } from '../../interface';
|
||||
import type { AuthenticationPageProps, TranslatedProps } from '@staticcms/core/interface';
|
||||
|
||||
const StyledAuthenticationPage = styled('section')`
|
||||
display: flex;
|
||||
|
@ -5,7 +5,7 @@ import unset from 'lodash/unset';
|
||||
import { extname } from 'path';
|
||||
import uuid from 'uuid/v4';
|
||||
|
||||
import { basename, Cursor, CURSOR_COMPATIBILITY_SYMBOL } from '../../lib/util';
|
||||
import { basename, Cursor, CURSOR_COMPATIBILITY_SYMBOL } from '@staticcms/core/lib/util';
|
||||
import AuthenticationPage from './AuthenticationPage';
|
||||
|
||||
import type {
|
||||
@ -16,8 +16,8 @@ import type {
|
||||
ImplementationEntry,
|
||||
ImplementationFile,
|
||||
User,
|
||||
} from '../../interface';
|
||||
import type AssetProxy from '../../valueObjects/AssetProxy';
|
||||
} from '@staticcms/core/interface';
|
||||
import type AssetProxy from '@staticcms/core/valueObjects/AssetProxy';
|
||||
|
||||
type RepoFile = { path: string; content: string | AssetProxy };
|
||||
type RepoTree = { [key: string]: RepoFile | RepoTree };
|
||||
|
@ -12,7 +12,7 @@ import { loadConfig } from './actions/config';
|
||||
import App from './components/App/App';
|
||||
import './components/EditorWidgets';
|
||||
import { ErrorBoundary } from './components/UI';
|
||||
import { addExtensions } from './extensions';
|
||||
import addExtensions from './extensions';
|
||||
import { getPhrases } from './lib/phrases';
|
||||
import './mediaLibrary';
|
||||
import { selectLocale } from './reducers/config';
|
||||
|
@ -1,18 +1,18 @@
|
||||
import KeyboardArrowUpIcon from '@mui/icons-material/KeyboardArrowUp';
|
||||
import Fab from '@mui/material/Fab';
|
||||
import { styled } from '@mui/material/styles';
|
||||
import React, { useCallback, useMemo } from 'react';
|
||||
import React, { useCallback, useEffect, useMemo } from 'react';
|
||||
import { translate } from 'react-polyglot';
|
||||
import { connect } from 'react-redux';
|
||||
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';
|
||||
import { loginUser as loginUserAction } from '@staticcms/core/actions/auth';
|
||||
import { discardDraft as discardDraftAction } from '@staticcms/core/actions/entries';
|
||||
import { currentBackend } from '@staticcms/core/backend';
|
||||
import { colors, GlobalStyles } from '@staticcms/core/components/UI/styles';
|
||||
import { history } from '@staticcms/core/routing/history';
|
||||
import CollectionRoute from '../Collection/CollectionRoute';
|
||||
import EditorRoute from '../Editor/EditorRoute';
|
||||
import MediaLibrary from '../MediaLibrary/MediaLibrary';
|
||||
@ -24,10 +24,10 @@ import Loader from '../UI/Loader';
|
||||
import ScrollTop from '../UI/ScrollTop';
|
||||
import NotFoundPage from './NotFoundPage';
|
||||
|
||||
import type { Collections, Credentials, TranslatedProps } from '@staticcms/core/interface';
|
||||
import type { RootState } from '@staticcms/core/store';
|
||||
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: {
|
||||
@ -162,7 +162,7 @@ const App = ({
|
||||
const defaultPath = useMemo(() => getDefaultPath(collections), [collections]);
|
||||
|
||||
const { pathname } = useLocation();
|
||||
React.useEffect(() => {
|
||||
useEffect(() => {
|
||||
if (!/\/collections\/[a-zA-Z0-9_-]+\/entries\/[a-zA-Z0-9_-]+/g.test(pathname)) {
|
||||
discardDraft();
|
||||
}
|
||||
|
@ -1,4 +1,3 @@
|
||||
import { styled } from '@mui/material/styles';
|
||||
import DescriptionIcon from '@mui/icons-material/Description';
|
||||
import ImageIcon from '@mui/icons-material/Image';
|
||||
import KeyboardArrowDownIcon from '@mui/icons-material/KeyboardArrowDown';
|
||||
@ -8,24 +7,25 @@ import Button from '@mui/material/Button';
|
||||
import Link from '@mui/material/Link';
|
||||
import Menu from '@mui/material/Menu';
|
||||
import MenuItem from '@mui/material/MenuItem';
|
||||
import { styled } from '@mui/material/styles';
|
||||
import Toolbar from '@mui/material/Toolbar';
|
||||
import React, { useCallback, useEffect, useMemo } from 'react';
|
||||
import React, { useCallback, useEffect, useMemo, useState } from 'react';
|
||||
import { translate } from 'react-polyglot';
|
||||
import { connect } from 'react-redux';
|
||||
|
||||
import { logoutUser as logoutUserAction } from '../../actions/auth';
|
||||
import { createNewEntry } from '../../actions/collections';
|
||||
import { openMediaLibrary as openMediaLibraryAction } from '../../actions/mediaLibrary';
|
||||
import { checkBackendStatus as checkBackendStatusAction } from '../../actions/status';
|
||||
import { buttons, colors } from '../../components/UI/styles';
|
||||
import { stripProtocol } from '../../lib/urlHelper';
|
||||
import { logoutUser as logoutUserAction } from '@staticcms/core/actions/auth';
|
||||
import { createNewEntry } from '@staticcms/core/actions/collections';
|
||||
import { openMediaLibrary as openMediaLibraryAction } from '@staticcms/core/actions/mediaLibrary';
|
||||
import { checkBackendStatus as checkBackendStatusAction } from '@staticcms/core/actions/status';
|
||||
import { buttons, colors } from '@staticcms/core/components/UI/styles';
|
||||
import { stripProtocol } from '@staticcms/core/lib/urlHelper';
|
||||
import NavLink from '../UI/NavLink';
|
||||
import SettingsDropdown from '../UI/SettingsDropdown';
|
||||
|
||||
import type { ComponentType } from 'react';
|
||||
import type { TranslatedProps } from '@staticcms/core/interface';
|
||||
import type { RootState } from '@staticcms/core/store';
|
||||
import type { ComponentType, MouseEvent } from 'react';
|
||||
import type { ConnectedProps } from 'react-redux';
|
||||
import type { TranslatedProps } from '../../interface';
|
||||
import type { RootState } from '../../store';
|
||||
|
||||
const StyledAppBar = styled(AppBar)`
|
||||
background-color: ${colors.foreground};
|
||||
@ -73,9 +73,9 @@ const Header = ({
|
||||
showMediaButton,
|
||||
checkBackendStatus,
|
||||
}: TranslatedProps<HeaderProps>) => {
|
||||
const [anchorEl, setAnchorEl] = React.useState<null | HTMLElement>(null);
|
||||
const [anchorEl, setAnchorEl] = useState<null | HTMLElement>(null);
|
||||
const open = Boolean(anchorEl);
|
||||
const handleClick = useCallback((event: React.MouseEvent<HTMLButtonElement>) => {
|
||||
const handleClick = useCallback((event: MouseEvent<HTMLButtonElement>) => {
|
||||
setAnchorEl(event.currentTarget);
|
||||
}, []);
|
||||
const handleClose = useCallback(() => {
|
||||
|
@ -2,7 +2,7 @@ import { styled } from '@mui/material/styles';
|
||||
import React from 'react';
|
||||
import TopBarProgress from 'react-topbar-progress-indicator';
|
||||
|
||||
import { colors } from '../../components/UI/styles';
|
||||
import { colors } from '@staticcms/core/components/UI/styles';
|
||||
import Header from './Header';
|
||||
|
||||
import type { ReactNode } from 'react';
|
||||
|
@ -2,7 +2,7 @@ import { styled } from '@mui/material/styles';
|
||||
import React from 'react';
|
||||
import { translate } from 'react-polyglot';
|
||||
|
||||
import { lengths } from '../../components/UI/styles';
|
||||
import { lengths } from '@staticcms/core/components/UI/styles';
|
||||
|
||||
import type { ComponentType } from 'react';
|
||||
import type { TranslateProps } from 'react-polyglot';
|
||||
|
@ -8,21 +8,21 @@ import {
|
||||
filterByField as filterByFieldAction,
|
||||
groupByField as groupByFieldAction,
|
||||
sortByField as sortByFieldAction,
|
||||
} from '../../actions/entries';
|
||||
import { components } from '../../components/UI/styles';
|
||||
import { SORT_DIRECTION_ASCENDING } from '../../constants';
|
||||
import { getNewEntryUrl } from '../../lib/urlHelper';
|
||||
} from '@staticcms/core/actions/entries';
|
||||
import { components } from '@staticcms/core/components/UI/styles';
|
||||
import { SORT_DIRECTION_ASCENDING } from '@staticcms/core/constants';
|
||||
import { getNewEntryUrl } from '@staticcms/core/lib/urlHelper';
|
||||
import {
|
||||
selectSortableFields,
|
||||
selectViewFilters,
|
||||
selectViewGroups,
|
||||
} from '../../lib/util/collection.util';
|
||||
} from '@staticcms/core/lib/util/collection.util';
|
||||
import {
|
||||
selectEntriesFilter,
|
||||
selectEntriesGroup,
|
||||
selectEntriesSort,
|
||||
selectViewStyle,
|
||||
} from '../../reducers/entries';
|
||||
} from '@staticcms/core/reducers/entries';
|
||||
import CollectionControls from './CollectionControls';
|
||||
import CollectionTop from './CollectionTop';
|
||||
import EntriesCollection from './Entries/EntriesCollection';
|
||||
@ -37,8 +37,8 @@ import type {
|
||||
TranslatedProps,
|
||||
ViewFilter,
|
||||
ViewGroup,
|
||||
} from '../../interface';
|
||||
import type { RootState } from '../../store';
|
||||
} from '@staticcms/core/interface';
|
||||
import type { RootState } from '@staticcms/core/store';
|
||||
|
||||
const CollectionMain = styled('main')`
|
||||
width: 100%;
|
||||
|
@ -6,7 +6,7 @@ import GroupControl from './GroupControl';
|
||||
import SortControl from './SortControl';
|
||||
import ViewStyleControl from './ViewStyleControl';
|
||||
|
||||
import type { CollectionViewStyle } from '../../constants/collectionViews';
|
||||
import type { CollectionViewStyle } from '@staticcms/core/constants/collectionViews';
|
||||
import type {
|
||||
FilterMap,
|
||||
GroupMap,
|
||||
@ -16,7 +16,7 @@ import type {
|
||||
TranslatedProps,
|
||||
ViewFilter,
|
||||
ViewGroup,
|
||||
} from '../../interface';
|
||||
} from '@staticcms/core/interface';
|
||||
|
||||
const CollectionControlsContainer = styled('div')`
|
||||
display: flex;
|
||||
|
@ -4,7 +4,7 @@ import { Navigate, useParams } from 'react-router-dom';
|
||||
import MainView from '../App/MainView';
|
||||
import Collection from './Collection';
|
||||
|
||||
import type { Collections } from '../../interface';
|
||||
import type { Collections } from '@staticcms/core/interface';
|
||||
|
||||
function getDefaultPath(collections: Collections) {
|
||||
const first = Object.values(collections).filter(collection => collection.hide !== true)[0];
|
||||
|
@ -6,11 +6,11 @@ import TextField from '@mui/material/TextField';
|
||||
import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
||||
import { translate } from 'react-polyglot';
|
||||
|
||||
import { colors, colorsRaw, lengths } from '../../components/UI/styles';
|
||||
import { transientOptions } from '../../lib';
|
||||
import { colors, colorsRaw, lengths } from '@staticcms/core/components/UI/styles';
|
||||
import { transientOptions } from '@staticcms/core/lib';
|
||||
|
||||
import type { ChangeEvent, FocusEvent, KeyboardEvent, MouseEvent } from 'react';
|
||||
import type { Collection, Collections, TranslatedProps } from '../../interface';
|
||||
import type { Collection, Collections, TranslatedProps } from '@staticcms/core/interface';
|
||||
|
||||
const SearchContainer = styled('div')`
|
||||
position: relative;
|
||||
|
@ -6,9 +6,9 @@ import React, { useCallback } from 'react';
|
||||
import { translate } from 'react-polyglot';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
|
||||
import { components } from '../../components/UI/styles';
|
||||
import { components } from '@staticcms/core/components/UI/styles';
|
||||
|
||||
import type { Collection, TranslatedProps } from '../../interface';
|
||||
import type { Collection, TranslatedProps } from '@staticcms/core/interface';
|
||||
|
||||
const CollectionTopRow = styled('div')`
|
||||
display: flex;
|
||||
|
@ -2,12 +2,12 @@ import { styled } from '@mui/material/styles';
|
||||
import React from 'react';
|
||||
import { translate } from 'react-polyglot';
|
||||
|
||||
import Loader from '../../UI/Loader';
|
||||
import Loader from '@staticcms/core/components/UI/Loader';
|
||||
import EntryListing from './EntryListing';
|
||||
|
||||
import type { CollectionViewStyle } from '../../../constants/collectionViews';
|
||||
import type { Collection, Collections, Entry, TranslatedProps } from '../../../interface';
|
||||
import type Cursor from '../../../lib/util/Cursor';
|
||||
import type { CollectionViewStyle } from '@staticcms/core/constants/collectionViews';
|
||||
import type { Collection, Collections, Entry, TranslatedProps } from '@staticcms/core/interface';
|
||||
import type Cursor from '@staticcms/core/lib/util/Cursor';
|
||||
|
||||
const PaginationMessage = styled('div')`
|
||||
padding: 16px;
|
||||
|
@ -6,24 +6,24 @@ import { connect } from 'react-redux';
|
||||
import {
|
||||
loadEntries as loadEntriesAction,
|
||||
traverseCollectionCursor as traverseCollectionCursorAction,
|
||||
} from '../../../actions/entries';
|
||||
import { colors } from '../../../components/UI/styles';
|
||||
import { Cursor } from '../../../lib/util';
|
||||
import { selectCollectionEntriesCursor } from '../../../reducers/cursors';
|
||||
} from '@staticcms/core/actions/entries';
|
||||
import { colors } from '@staticcms/core/components/UI/styles';
|
||||
import { Cursor } from '@staticcms/core/lib/util';
|
||||
import { selectCollectionEntriesCursor } from '@staticcms/core/reducers/cursors';
|
||||
import {
|
||||
selectEntries,
|
||||
selectEntriesLoaded,
|
||||
selectGroups,
|
||||
selectIsFetching,
|
||||
} from '../../../reducers/entries';
|
||||
} from '@staticcms/core/reducers/entries';
|
||||
import Entries from './Entries';
|
||||
|
||||
import type { ComponentType } from 'react';
|
||||
import type { t } from 'react-polyglot';
|
||||
import type { ConnectedProps } from 'react-redux';
|
||||
import type { CollectionViewStyle } from '../../../constants/collectionViews';
|
||||
import type { Collection, Entry, GroupOfEntries, TranslatedProps } from '../../../interface';
|
||||
import type { RootState } from '../../../store';
|
||||
import type { CollectionViewStyle } from '@staticcms/core/constants/collectionViews';
|
||||
import type { Collection, Entry, GroupOfEntries, TranslatedProps } from '@staticcms/core/interface';
|
||||
import type { RootState } from '@staticcms/core/store';
|
||||
|
||||
const GroupHeading = styled('h2')`
|
||||
font-size: 23px;
|
||||
|
@ -5,15 +5,15 @@ import { connect } from 'react-redux';
|
||||
import {
|
||||
clearSearch as clearSearchAction,
|
||||
searchEntries as searchEntriesAction,
|
||||
} from '../../../actions/search';
|
||||
import { Cursor } from '../../../lib/util';
|
||||
import { selectSearchedEntries } from '../../../reducers';
|
||||
} from '@staticcms/core/actions/search';
|
||||
import { Cursor } from '@staticcms/core/lib/util';
|
||||
import { selectSearchedEntries } from '@staticcms/core/reducers';
|
||||
import Entries from './Entries';
|
||||
|
||||
import type { ConnectedProps } from 'react-redux';
|
||||
import type { CollectionViewStyle } from '../../../constants/collectionViews';
|
||||
import type { Collections } from '../../../interface';
|
||||
import type { RootState } from '../../../store';
|
||||
import type { CollectionViewStyle } from '@staticcms/core/constants/collectionViews';
|
||||
import type { Collections } from '@staticcms/core/interface';
|
||||
import type { RootState } from '@staticcms/core/store';
|
||||
|
||||
const EntriesSearch = ({
|
||||
collections,
|
||||
|
@ -7,15 +7,15 @@ import React, { useEffect, useMemo, useState } from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import { Link } from 'react-router-dom';
|
||||
|
||||
import { getAsset as getAssetAction } from '../../../actions/media';
|
||||
import { VIEW_STYLE_GRID, VIEW_STYLE_LIST } from '../../../constants/collectionViews';
|
||||
import { selectEntryCollectionTitle } from '../../../lib/util/collection.util';
|
||||
import { selectIsLoadingAsset } from '../../../reducers/medias';
|
||||
import { getAsset as getAssetAction } from '@staticcms/core/actions/media';
|
||||
import { VIEW_STYLE_GRID, VIEW_STYLE_LIST } from '@staticcms/core/constants/collectionViews';
|
||||
import { selectEntryCollectionTitle } from '@staticcms/core/lib/util/collection.util';
|
||||
import { selectIsLoadingAsset } from '@staticcms/core/reducers/medias';
|
||||
|
||||
import type { ConnectedProps } from 'react-redux';
|
||||
import type { CollectionViewStyle } from '../../../constants/collectionViews';
|
||||
import type { Field, Collection, Entry } from '../../../interface';
|
||||
import type { RootState } from '../../../store';
|
||||
import type { CollectionViewStyle } from '@staticcms/core/constants/collectionViews';
|
||||
import type { Field, Collection, Entry } from '@staticcms/core/interface';
|
||||
import type { RootState } from '@staticcms/core/store';
|
||||
|
||||
const EntryCard = ({
|
||||
collection,
|
||||
|
@ -2,14 +2,14 @@ import { styled } from '@mui/material/styles';
|
||||
import React, { useCallback, useMemo } from 'react';
|
||||
import { Waypoint } from 'react-waypoint';
|
||||
|
||||
import { VIEW_STYLE_LIST } from '../../../constants/collectionViews';
|
||||
import { transientOptions } from '../../../lib';
|
||||
import { selectFields, selectInferedField } from '../../../lib/util/collection.util';
|
||||
import { VIEW_STYLE_LIST } from '@staticcms/core/constants/collectionViews';
|
||||
import { transientOptions } from '@staticcms/core/lib';
|
||||
import { selectFields, selectInferedField } from '@staticcms/core/lib/util/collection.util';
|
||||
import EntryCard from './EntryCard';
|
||||
|
||||
import type { CollectionViewStyle } from '../../../constants/collectionViews';
|
||||
import type { Field, Collection, Collections, Entry } from '../../../interface';
|
||||
import type Cursor from '../../../lib/util/Cursor';
|
||||
import type { CollectionViewStyle } from '@staticcms/core/constants/collectionViews';
|
||||
import type { Field, Collection, Collections, Entry } from '@staticcms/core/interface';
|
||||
import type Cursor from '@staticcms/core/lib/util/Cursor';
|
||||
|
||||
interface CardsGridProps {
|
||||
$layout: CollectionViewStyle;
|
||||
|
@ -5,10 +5,11 @@ import ListItemIcon from '@mui/material/ListItemIcon';
|
||||
import ListItemText from '@mui/material/ListItemText';
|
||||
import Menu from '@mui/material/Menu';
|
||||
import MenuItem from '@mui/material/MenuItem';
|
||||
import React, { useCallback, useMemo } from 'react';
|
||||
import React, { useCallback, useMemo, useState } from 'react';
|
||||
import { translate } from 'react-polyglot';
|
||||
|
||||
import type { FilterMap, TranslatedProps, ViewFilter } from '../../interface';
|
||||
import type { FilterMap, TranslatedProps, ViewFilter } from '@staticcms/core/interface';
|
||||
import type { MouseEvent } from 'react';
|
||||
|
||||
interface FilterControlProps {
|
||||
filter: Record<string, FilterMap>;
|
||||
@ -22,9 +23,9 @@ const FilterControl = ({
|
||||
onFilterClick,
|
||||
filter,
|
||||
}: TranslatedProps<FilterControlProps>) => {
|
||||
const [anchorEl, setAnchorEl] = React.useState<null | HTMLElement>(null);
|
||||
const [anchorEl, setAnchorEl] = useState<null | HTMLElement>(null);
|
||||
const open = Boolean(anchorEl);
|
||||
const handleClick = useCallback((event: React.MouseEvent<HTMLButtonElement>) => {
|
||||
const handleClick = useCallback((event: MouseEvent<HTMLButtonElement>) => {
|
||||
setAnchorEl(event.currentTarget);
|
||||
}, []);
|
||||
const handleClose = useCallback(() => {
|
||||
|
@ -1,14 +1,15 @@
|
||||
import CheckIcon from '@mui/icons-material/Check';
|
||||
import KeyboardArrowDownIcon from '@mui/icons-material/KeyboardArrowDown';
|
||||
import Button from '@mui/material/Button/Button';
|
||||
import Button from '@mui/material/Button';
|
||||
import ListItemText from '@mui/material/ListItemText';
|
||||
import Menu from '@mui/material/Menu';
|
||||
import MenuItem from '@mui/material/MenuItem';
|
||||
import React, { useCallback, useMemo } from 'react';
|
||||
import { translate } from 'react-polyglot';
|
||||
import CheckIcon from '@mui/icons-material/Check';
|
||||
import { styled } from '@mui/material/styles';
|
||||
import React, { useCallback, useMemo, useState } from 'react';
|
||||
import { translate } from 'react-polyglot';
|
||||
|
||||
import type { GroupMap, TranslatedProps, ViewGroup } from '../../interface';
|
||||
import type { GroupMap, TranslatedProps, ViewGroup } from '@staticcms/core/interface';
|
||||
import type { MouseEvent } from 'react';
|
||||
|
||||
const StyledMenuIconWrapper = styled('div')`
|
||||
width: 32px;
|
||||
@ -30,9 +31,9 @@ const GroupControl = ({
|
||||
t,
|
||||
onGroupClick,
|
||||
}: TranslatedProps<GroupControlProps>) => {
|
||||
const [anchorEl, setAnchorEl] = React.useState<null | HTMLElement>(null);
|
||||
const [anchorEl, setAnchorEl] = useState<null | HTMLElement>(null);
|
||||
const open = Boolean(anchorEl);
|
||||
const handleClick = useCallback((event: React.MouseEvent<HTMLButtonElement>) => {
|
||||
const handleClick = useCallback((event: MouseEvent<HTMLButtonElement>) => {
|
||||
setAnchorEl(event.currentTarget);
|
||||
}, []);
|
||||
const handleClose = useCallback(() => {
|
||||
|
@ -1,20 +1,20 @@
|
||||
import { styled } from '@mui/material/styles';
|
||||
import ArticleIcon from '@mui/icons-material/Article';
|
||||
import { styled } from '@mui/material/styles';
|
||||
import sortBy from 'lodash/sortBy';
|
||||
import { dirname, sep } from 'path';
|
||||
import React, { useCallback, useEffect, useState } from 'react';
|
||||
import React, { Fragment, useCallback, useEffect, useState } from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import { NavLink } from 'react-router-dom';
|
||||
|
||||
import { colors, components } from '../../components/UI/styles';
|
||||
import { transientOptions } from '../../lib';
|
||||
import { selectEntryCollectionTitle } from '../../lib/util/collection.util';
|
||||
import { stringTemplate } from '../../lib/widgets';
|
||||
import { selectEntries } from '../../reducers/entries';
|
||||
import { colors, components } from '@staticcms/core/components/UI/styles';
|
||||
import { transientOptions } from '@staticcms/core/lib';
|
||||
import { selectEntryCollectionTitle } from '@staticcms/core/lib/util/collection.util';
|
||||
import { stringTemplate } from '@staticcms/core/lib/widgets';
|
||||
import { selectEntries } from '@staticcms/core/reducers/entries';
|
||||
|
||||
import type { Collection, Entry } from '@staticcms/core/interface';
|
||||
import type { RootState } from '@staticcms/core/store';
|
||||
import type { ConnectedProps } from 'react-redux';
|
||||
import type { Collection, Entry } from '../../interface';
|
||||
import type { RootState } from '../../store';
|
||||
|
||||
const { addFileTemplateFields } = stringTemplate;
|
||||
|
||||
@ -124,7 +124,7 @@ const TreeNode = ({ collection, treeData, depth = 0, onToggle }: TreeNodeProps)
|
||||
const hasChildren = depth === 0 || node.children.some(c => c.children.some(c => c.isDir));
|
||||
|
||||
return (
|
||||
<React.Fragment key={node.path}>
|
||||
<Fragment key={node.path}>
|
||||
<TreeNavLink
|
||||
to={to}
|
||||
$activeClassName="sidebar-active"
|
||||
@ -146,7 +146,7 @@ const TreeNode = ({ collection, treeData, depth = 0, onToggle }: TreeNodeProps)
|
||||
onToggle={onToggle}
|
||||
/>
|
||||
)}
|
||||
</React.Fragment>
|
||||
</Fragment>
|
||||
);
|
||||
})}
|
||||
</>
|
||||
|
@ -11,15 +11,15 @@ import Typography from '@mui/material/Typography';
|
||||
import React, { useMemo } from 'react';
|
||||
import { translate } from 'react-polyglot';
|
||||
|
||||
import { searchCollections } from '../../actions/collections';
|
||||
import { colors } from '../../components/UI/styles';
|
||||
import { getAdditionalLinks, getIcon } from '../../lib/registry';
|
||||
import { searchCollections } from '@staticcms/core/actions/collections';
|
||||
import { colors } from '@staticcms/core/components/UI/styles';
|
||||
import { getAdditionalLinks, getIcon } from '@staticcms/core/lib/registry';
|
||||
import NavLink from '../UI/NavLink';
|
||||
import CollectionSearch from './CollectionSearch';
|
||||
import NestedCollection from './NestedCollection';
|
||||
|
||||
import type { ReactNode } from 'react';
|
||||
import type { Collection, Collections, TranslatedProps } from '../../interface';
|
||||
import type { Collection, Collections, TranslatedProps } from '@staticcms/core/interface';
|
||||
|
||||
const StyledSidebar = styled('div')`
|
||||
position: sticky;
|
||||
|
@ -1,20 +1,26 @@
|
||||
import KeyboardArrowDownIcon from '@mui/icons-material/KeyboardArrowDown';
|
||||
import KeyboardArrowUpIcon from '@mui/icons-material/KeyboardArrowUp';
|
||||
import { styled } from '@mui/material';
|
||||
import Button from '@mui/material/Button';
|
||||
import ListItemText from '@mui/material/ListItemText';
|
||||
import Menu from '@mui/material/Menu';
|
||||
import MenuItem from '@mui/material/MenuItem';
|
||||
import React, { useCallback, useMemo } from 'react';
|
||||
import { styled } from '@mui/material/styles';
|
||||
import React, { useCallback, useMemo, useState } from 'react';
|
||||
import { translate } from 'react-polyglot';
|
||||
|
||||
import {
|
||||
SORT_DIRECTION_ASCENDING,
|
||||
SORT_DIRECTION_DESCENDING,
|
||||
SORT_DIRECTION_NONE,
|
||||
} from '../../constants';
|
||||
} from '@staticcms/core/constants';
|
||||
|
||||
import type { SortableField, SortDirection, SortMap, TranslatedProps } from '../../interface';
|
||||
import type {
|
||||
SortableField,
|
||||
SortDirection,
|
||||
SortMap,
|
||||
TranslatedProps,
|
||||
} from '@staticcms/core/interface';
|
||||
import type { MouseEvent } from 'react';
|
||||
|
||||
const StyledMenuIconWrapper = styled('div')`
|
||||
width: 32px;
|
||||
@ -42,9 +48,9 @@ interface SortControlProps {
|
||||
}
|
||||
|
||||
const SortControl = ({ t, fields, onSortClick, sort }: TranslatedProps<SortControlProps>) => {
|
||||
const [anchorEl, setAnchorEl] = React.useState<null | HTMLElement>(null);
|
||||
const [anchorEl, setAnchorEl] = useState<null | HTMLElement>(null);
|
||||
const open = Boolean(anchorEl);
|
||||
const handleClick = useCallback((event: React.MouseEvent<HTMLButtonElement>) => {
|
||||
const handleClick = useCallback((event: MouseEvent<HTMLButtonElement>) => {
|
||||
setAnchorEl(event.currentTarget);
|
||||
}, []);
|
||||
const handleClose = useCallback(() => {
|
||||
|
@ -4,9 +4,9 @@ import ReorderSharpIcon from '@mui/icons-material/ReorderSharp';
|
||||
import IconButton from '@mui/material/IconButton';
|
||||
import React from 'react';
|
||||
|
||||
import { VIEW_STYLE_GRID, VIEW_STYLE_LIST } from '../../constants/collectionViews';
|
||||
import { VIEW_STYLE_GRID, VIEW_STYLE_LIST } from '@staticcms/core/constants/collectionViews';
|
||||
|
||||
import type { CollectionViewStyle } from '../../constants/collectionViews';
|
||||
import type { CollectionViewStyle } from '@staticcms/core/constants/collectionViews';
|
||||
|
||||
const ViewControlsSection = styled('div')`
|
||||
margin-left: 24px;
|
||||
|
@ -3,7 +3,7 @@ import React, { useCallback, useEffect, useMemo, useState } from 'react';
|
||||
import { translate } from 'react-polyglot';
|
||||
import { connect } from 'react-redux';
|
||||
|
||||
import { logoutUser as logoutUserAction } from '../../actions/auth';
|
||||
import { logoutUser as logoutUserAction } from '@staticcms/core/actions/auth';
|
||||
import {
|
||||
changeDraftFieldValidation as changeDraftFieldValidationAction,
|
||||
createDraftDuplicateFromEntry as createDraftDuplicateFromEntryAction,
|
||||
@ -18,15 +18,15 @@ import {
|
||||
persistEntry as persistEntryAction,
|
||||
persistLocalBackup as persistLocalBackupAction,
|
||||
retrieveLocalBackup as retrieveLocalBackupAction,
|
||||
} from '../../actions/entries';
|
||||
} from '@staticcms/core/actions/entries';
|
||||
import {
|
||||
loadScroll as loadScrollAction,
|
||||
toggleScroll as toggleScrollAction,
|
||||
} from '../../actions/scroll';
|
||||
import { selectFields } from '../../lib/util/collection.util';
|
||||
import { useWindowEvent } from '../../lib/util/window.util';
|
||||
import { selectEntry } from '../../reducers';
|
||||
import { history, navigateToCollection, navigateToNewEntry } from '../../routing/history';
|
||||
} from '@staticcms/core/actions/scroll';
|
||||
import { selectFields } from '@staticcms/core/lib/util/collection.util';
|
||||
import { useWindowEvent } from '@staticcms/core/lib/util/window.util';
|
||||
import { selectEntry } from '@staticcms/core/reducers';
|
||||
import { history, navigateToCollection, navigateToNewEntry } from '@staticcms/core/routing/history';
|
||||
import confirm from '../UI/Confirm';
|
||||
import Loader from '../UI/Loader';
|
||||
import EditorInterface from './EditorInterface';
|
||||
@ -34,8 +34,13 @@ import EditorInterface from './EditorInterface';
|
||||
import type { TransitionPromptHook } from 'history';
|
||||
import type { ComponentType } from 'react';
|
||||
import type { ConnectedProps } from 'react-redux';
|
||||
import type { Collection, EditorPersistOptions, Entry, TranslatedProps } from '../../interface';
|
||||
import type { RootState } from '../../store';
|
||||
import type {
|
||||
Collection,
|
||||
EditorPersistOptions,
|
||||
Entry,
|
||||
TranslatedProps,
|
||||
} from '@staticcms/core/interface';
|
||||
import type { RootState } from '@staticcms/core/store';
|
||||
|
||||
const Editor = ({
|
||||
entry,
|
||||
|
@ -1,30 +1,30 @@
|
||||
import { styled } from '@mui/material/styles';
|
||||
import { isEqual } from 'lodash';
|
||||
import isEmpty from 'lodash/isEmpty';
|
||||
import React, { useCallback, useEffect, useMemo, useState } from 'react';
|
||||
import React, { createElement, useCallback, useEffect, useMemo, useState } from 'react';
|
||||
import { translate } from 'react-polyglot';
|
||||
import { connect } from 'react-redux';
|
||||
|
||||
import {
|
||||
changeDraftField as changeDraftFieldAction,
|
||||
changeDraftFieldValidation as changeDraftFieldValidationAction,
|
||||
} from '../../../actions/entries';
|
||||
import { getAsset as getAssetAction } from '../../../actions/media';
|
||||
} from '@staticcms/core/actions/entries';
|
||||
import { getAsset as getAssetAction } from '@staticcms/core/actions/media';
|
||||
import {
|
||||
clearMediaControl as clearMediaControlAction,
|
||||
openMediaLibrary as openMediaLibraryAction,
|
||||
removeInsertedMedia as removeInsertedMediaAction,
|
||||
removeMediaControl as removeMediaControlAction,
|
||||
} from '../../../actions/mediaLibrary';
|
||||
import { query as queryAction } from '../../../actions/search';
|
||||
import { borders, colors, lengths, transitions } from '../../../components/UI/styles';
|
||||
import { transientOptions } from '../../../lib';
|
||||
import { resolveWidget } from '../../../lib/registry';
|
||||
import { getFieldLabel } from '../../../lib/util/field.util';
|
||||
import { validate } from '../../../lib/util/validation.util';
|
||||
import { selectIsLoadingAsset } from '../../../reducers/medias';
|
||||
} from '@staticcms/core/actions/mediaLibrary';
|
||||
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 { 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 { selectIsLoadingAsset } from '@staticcms/core/reducers/medias';
|
||||
|
||||
import type { ComponentType } from 'react';
|
||||
import type { ConnectedProps } from 'react-redux';
|
||||
import type {
|
||||
Field,
|
||||
FieldsErrors,
|
||||
@ -34,8 +34,10 @@ import type {
|
||||
UnknownField,
|
||||
ValueOrNestedValue,
|
||||
Widget,
|
||||
} from '../../../interface';
|
||||
import type { RootState } from '../../../store';
|
||||
} from '@staticcms/core/interface';
|
||||
import type { RootState } from '@staticcms/core/store';
|
||||
import type { ComponentType } from 'react';
|
||||
import type { ConnectedProps } from 'react-redux';
|
||||
|
||||
/**
|
||||
* This is a necessary bridge as we are still passing classnames to widgets
|
||||
@ -130,7 +132,6 @@ const ControlHint = styled(
|
||||
);
|
||||
|
||||
const EditorControl = ({
|
||||
className,
|
||||
clearMediaControl,
|
||||
collection,
|
||||
config: configState,
|
||||
@ -167,7 +168,8 @@ const EditorControl = ({
|
||||
);
|
||||
|
||||
const [dirty, setDirty] = useState(!isEmpty(value));
|
||||
const errors = useMemo(() => fieldsErrors[path] ?? [], [fieldsErrors, path]);
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
const errors = useMemo(() => fieldsErrors[path] ?? [], [fieldsErrors[path]]);
|
||||
const hasErrors = (submitted || dirty) && Boolean(errors.length);
|
||||
|
||||
const handleGetAsset: GetAssetFunction = useMemo(
|
||||
@ -189,71 +191,101 @@ const EditorControl = ({
|
||||
const handleChangeDraftField = useCallback(
|
||||
(value: ValueOrNestedValue) => {
|
||||
setDirty(true);
|
||||
changeDraftField({ path, field, value, entry, i18n });
|
||||
changeDraftField({ path, field, value, i18n });
|
||||
},
|
||||
[changeDraftField, entry, field, i18n, path],
|
||||
[changeDraftField, field, i18n, path],
|
||||
);
|
||||
|
||||
const config = useMemo(() => configState.config, [configState.config]);
|
||||
if (!collection || !entry || !config) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<ControlContainer className={className} $isHidden={isHidden}>
|
||||
<>
|
||||
{React.createElement(widget.control, {
|
||||
key: `field_${path}`,
|
||||
collection,
|
||||
config,
|
||||
entry,
|
||||
field: field as UnknownField,
|
||||
fieldsErrors,
|
||||
submitted,
|
||||
getAsset: handleGetAsset,
|
||||
isDisabled: isDisabled ?? false,
|
||||
isFieldDuplicate,
|
||||
isFieldHidden,
|
||||
label: getFieldLabel(field, t),
|
||||
locale,
|
||||
mediaPaths,
|
||||
onChange: handleChangeDraftField,
|
||||
clearMediaControl,
|
||||
openMediaLibrary,
|
||||
removeInsertedMedia,
|
||||
removeMediaControl,
|
||||
path,
|
||||
query,
|
||||
t,
|
||||
value,
|
||||
forList,
|
||||
i18n,
|
||||
hasErrors,
|
||||
})}
|
||||
{fieldHint ? (
|
||||
<ControlHint key="hint" $error={hasErrors}>
|
||||
{fieldHint}
|
||||
</ControlHint>
|
||||
) : null}
|
||||
{hasErrors ? (
|
||||
<ControlErrorsList key="errors">
|
||||
{errors.map(error => {
|
||||
return (
|
||||
error.message &&
|
||||
typeof error.message === 'string' && (
|
||||
<li key={error.message.trim().replace(/[^a-z0-9]+/gi, '-')}>{error.message}</li>
|
||||
)
|
||||
);
|
||||
})}
|
||||
</ControlErrorsList>
|
||||
) : null}
|
||||
</>
|
||||
</ControlContainer>
|
||||
);
|
||||
const finalValue = useMemoCompare(value, isEqual);
|
||||
|
||||
return useMemo(() => {
|
||||
if (!collection || !entry || !config) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<ControlContainer $isHidden={isHidden}>
|
||||
<>
|
||||
{createElement(widget.control, {
|
||||
key: `field_${path}`,
|
||||
collection,
|
||||
config,
|
||||
entry,
|
||||
field: field as UnknownField,
|
||||
fieldsErrors,
|
||||
submitted,
|
||||
getAsset: handleGetAsset,
|
||||
isDisabled: isDisabled ?? false,
|
||||
isFieldDuplicate,
|
||||
isFieldHidden,
|
||||
label: getFieldLabel(field, t),
|
||||
locale,
|
||||
mediaPaths,
|
||||
onChange: handleChangeDraftField,
|
||||
clearMediaControl,
|
||||
openMediaLibrary,
|
||||
removeInsertedMedia,
|
||||
removeMediaControl,
|
||||
path,
|
||||
query,
|
||||
t,
|
||||
value: finalValue,
|
||||
forList,
|
||||
i18n,
|
||||
hasErrors,
|
||||
})}
|
||||
{fieldHint ? (
|
||||
<ControlHint key="hint" $error={hasErrors}>
|
||||
{fieldHint}
|
||||
</ControlHint>
|
||||
) : null}
|
||||
{hasErrors ? (
|
||||
<ControlErrorsList key="errors">
|
||||
{errors.map(error => {
|
||||
return (
|
||||
error.message &&
|
||||
typeof error.message === 'string' && (
|
||||
<li key={error.message.trim().replace(/[^a-z0-9]+/gi, '-')}>{error.message}</li>
|
||||
)
|
||||
);
|
||||
})}
|
||||
</ControlErrorsList>
|
||||
) : null}
|
||||
</>
|
||||
</ControlContainer>
|
||||
);
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [
|
||||
collection,
|
||||
config,
|
||||
path,
|
||||
errors,
|
||||
isHidden,
|
||||
widget.control,
|
||||
field,
|
||||
submitted,
|
||||
handleGetAsset,
|
||||
isDisabled,
|
||||
t,
|
||||
locale,
|
||||
mediaPaths,
|
||||
handleChangeDraftField,
|
||||
clearMediaControl,
|
||||
openMediaLibrary,
|
||||
removeInsertedMedia,
|
||||
removeMediaControl,
|
||||
query,
|
||||
finalValue,
|
||||
forList,
|
||||
i18n,
|
||||
hasErrors,
|
||||
fieldHint,
|
||||
]);
|
||||
};
|
||||
|
||||
interface EditorControlOwnProps {
|
||||
className?: string;
|
||||
field: Field;
|
||||
fieldsErrors: FieldsErrors;
|
||||
submitted: boolean;
|
||||
|
@ -3,11 +3,11 @@ import Menu from '@mui/material/Menu';
|
||||
import MenuItem from '@mui/material/MenuItem';
|
||||
import { styled } from '@mui/material/styles';
|
||||
import get from 'lodash/get';
|
||||
import React, { useCallback, useMemo } from 'react';
|
||||
import React, { useCallback, useMemo, useState } from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
|
||||
import { changeDraftField as changeDraftFieldAction } from '../../../actions/entries';
|
||||
import confirm from '../../../components/UI/Confirm';
|
||||
import { changeDraftField as changeDraftFieldAction } from '@staticcms/core/actions/entries';
|
||||
import confirm from '@staticcms/core/components/UI/Confirm';
|
||||
import {
|
||||
getI18nInfo,
|
||||
getLocaleDataPath,
|
||||
@ -15,10 +15,9 @@ import {
|
||||
isFieldDuplicate,
|
||||
isFieldHidden,
|
||||
isFieldTranslatable,
|
||||
} from '../../../lib/i18n';
|
||||
} from '@staticcms/core/lib/i18n';
|
||||
import EditorControl from './EditorControl';
|
||||
|
||||
import type { ConnectedProps } from 'react-redux';
|
||||
import type {
|
||||
Collection,
|
||||
Entry,
|
||||
@ -27,8 +26,10 @@ import type {
|
||||
I18nSettings,
|
||||
TranslatedProps,
|
||||
ValueOrNestedValue,
|
||||
} from '../../../interface';
|
||||
import type { RootState } from '../../../store';
|
||||
} from '@staticcms/core/interface';
|
||||
import type { RootState } from '@staticcms/core/store';
|
||||
import type { MouseEvent } from 'react';
|
||||
import type { ConnectedProps } from 'react-redux';
|
||||
|
||||
const ControlPaneContainer = styled('div')`
|
||||
max-width: 1000px;
|
||||
@ -50,9 +51,9 @@ interface LocaleDropdownProps {
|
||||
}
|
||||
|
||||
const LocaleDropdown = ({ locales, dropdownText, onLocaleChange }: LocaleDropdownProps) => {
|
||||
const [anchorEl, setAnchorEl] = React.useState<null | HTMLElement>(null);
|
||||
const [anchorEl, setAnchorEl] = useState<null | HTMLElement>(null);
|
||||
const open = Boolean(anchorEl);
|
||||
const handleClick = useCallback((event: React.MouseEvent<HTMLButtonElement>) => {
|
||||
const handleClick = useCallback((event: MouseEvent<HTMLButtonElement>) => {
|
||||
setAnchorEl(event.currentTarget);
|
||||
}, []);
|
||||
const handleClose = useCallback(() => {
|
||||
@ -154,7 +155,7 @@ const EditorControlPane = ({
|
||||
sourceLocale !== i18n?.defaultLocale,
|
||||
sourceLocale,
|
||||
);
|
||||
changeDraftField({ path: field.name, field, value: copyValue, entry, i18n });
|
||||
changeDraftField({ path: field.name, field, value: copyValue, i18n });
|
||||
}
|
||||
});
|
||||
},
|
||||
|
@ -6,10 +6,10 @@ import { styled } from '@mui/material/styles';
|
||||
import React, { useCallback, useEffect, useMemo, useState } from 'react';
|
||||
import { ScrollSync, ScrollSyncPane } from 'react-scroll-sync';
|
||||
|
||||
import { colorsRaw, components, zIndex } from '../../components/UI/styles';
|
||||
import { transientOptions } from '../../lib';
|
||||
import { getI18nInfo, getPreviewEntry, hasI18n } from '../../lib/i18n';
|
||||
import { getFileFromSlug } from '../../lib/util/collection.util';
|
||||
import { colorsRaw, components, zIndex } from '@staticcms/core/components/UI/styles';
|
||||
import { transientOptions } from '@staticcms/core/lib';
|
||||
import { getI18nInfo, getPreviewEntry, hasI18n } from '@staticcms/core/lib/i18n';
|
||||
import { getFileFromSlug } from '@staticcms/core/lib/util/collection.util';
|
||||
import EditorControlPane from './EditorControlPane/EditorControlPane';
|
||||
import EditorPreviewPane from './EditorPreviewPane/EditorPreviewPane';
|
||||
import EditorToolbar from './EditorToolbar';
|
||||
@ -22,7 +22,7 @@ import type {
|
||||
FieldsErrors,
|
||||
TranslatedProps,
|
||||
User,
|
||||
} from '../../interface';
|
||||
} from '@staticcms/core/interface';
|
||||
|
||||
const PREVIEW_VISIBLE = 'cms.preview-visible';
|
||||
const I18N_VISIBLE = 'cms.i18n-visible';
|
||||
|
@ -1,7 +1,7 @@
|
||||
import React from 'react';
|
||||
import { styled } from '@mui/material/styles';
|
||||
|
||||
import type { Field, TemplatePreviewProps } from '../../../interface';
|
||||
import type { Field, TemplatePreviewProps } from '@staticcms/core/interface';
|
||||
|
||||
function isVisible(field: Field) {
|
||||
return field.widget !== 'hidden';
|
||||
|
@ -1,6 +1,6 @@
|
||||
import React, { memo } from 'react';
|
||||
import { createElement, memo } from 'react';
|
||||
|
||||
import type { TemplatePreviewComponent, TemplatePreviewProps } from '../../../interface';
|
||||
import type { TemplatePreviewComponent, TemplatePreviewProps } from '@staticcms/core/interface';
|
||||
|
||||
interface EditorPreviewContentProps {
|
||||
previewComponent?: TemplatePreviewComponent;
|
||||
@ -13,7 +13,7 @@ const EditorPreviewContent = memo(
|
||||
return null;
|
||||
}
|
||||
|
||||
return React.createElement(previewComponent, previewProps);
|
||||
return createElement(previewComponent, previewProps);
|
||||
},
|
||||
);
|
||||
|
||||
|
@ -1,26 +1,24 @@
|
||||
import { styled } from '@mui/material/styles';
|
||||
import React, { isValidElement, useCallback, useMemo } from 'react';
|
||||
import React, { Fragment, isValidElement, useCallback, useMemo } from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import Frame, { FrameContextConsumer } from 'react-frame-component';
|
||||
import { translate } from 'react-polyglot';
|
||||
import { connect } from 'react-redux';
|
||||
import { ScrollSyncPane } from 'react-scroll-sync';
|
||||
|
||||
import { getAsset as getAssetAction } from '../../../actions/media';
|
||||
import { lengths } from '../../../components/UI/styles';
|
||||
import { getPreviewStyles, getPreviewTemplate, resolveWidget } from '../../../lib/registry';
|
||||
import { selectTemplateName, useInferedFields } from '../../../lib/util/collection.util';
|
||||
import { selectField } from '../../../lib/util/field.util';
|
||||
import { selectIsLoadingAsset } from '../../../reducers/medias';
|
||||
import { getTypedFieldForValue } from '../../../widgets/list/typedListHelpers';
|
||||
import { ErrorBoundary } from '../../UI';
|
||||
import { getAsset as getAssetAction } from '@staticcms/core/actions/media';
|
||||
import { ErrorBoundary } from '@staticcms/core/components/UI';
|
||||
import { lengths } from '@staticcms/core/components/UI/styles';
|
||||
import { getPreviewStyles, getPreviewTemplate, resolveWidget } from '@staticcms/core/lib/registry';
|
||||
import { selectTemplateName, useInferedFields } from '@staticcms/core/lib/util/collection.util';
|
||||
import { selectField } from '@staticcms/core/lib/util/field.util';
|
||||
import { selectIsLoadingAsset } from '@staticcms/core/reducers/medias';
|
||||
import { getTypedFieldForValue } from '@staticcms/list/typedListHelpers';
|
||||
import EditorPreview from './EditorPreview';
|
||||
import EditorPreviewContent from './EditorPreviewContent';
|
||||
import PreviewHOC from './PreviewHOC';
|
||||
|
||||
import type { ComponentType, ReactFragment, ReactNode } from 'react';
|
||||
import type { ConnectedProps } from 'react-redux';
|
||||
import type { InferredField } from '../../../constants/fieldInference';
|
||||
import type { InferredField } from '@staticcms/core/constants/fieldInference';
|
||||
import type {
|
||||
Collection,
|
||||
Config,
|
||||
@ -35,8 +33,10 @@ import type {
|
||||
TranslatedProps,
|
||||
ValueOrNestedValue,
|
||||
WidgetPreviewComponent,
|
||||
} from '../../../interface';
|
||||
import type { RootState } from '../../../store';
|
||||
} from '@staticcms/core/interface';
|
||||
import type { RootState } from '@staticcms/core/store';
|
||||
import type { ComponentType, ReactFragment, ReactNode } from 'react';
|
||||
import type { ConnectedProps } from 'react-redux';
|
||||
|
||||
const PreviewPaneFrame = styled(Frame)`
|
||||
width: 100%;
|
||||
@ -180,10 +180,10 @@ function isJsxElement(value: any): value is JSX.Element {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
function isReactFragment(value: any): value is ReactFragment {
|
||||
if (value.type) {
|
||||
return value.type === React.Fragment;
|
||||
return value.type === Fragment;
|
||||
}
|
||||
|
||||
return value === React.Fragment;
|
||||
return value === Fragment;
|
||||
}
|
||||
|
||||
function getWidget(
|
||||
@ -478,7 +478,9 @@ const PreviewPane = (props: TranslatedProps<EditorPreviewPaneProps>) => {
|
||||
() => `
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head><base target="_blank"/></head>
|
||||
<head>
|
||||
<base target="_blank"/>
|
||||
</head>
|
||||
<body><div></div></body>
|
||||
</html>
|
||||
`,
|
||||
|
@ -1,6 +1,6 @@
|
||||
import React from 'react';
|
||||
import { cloneElement, createElement, isValidElement } from 'react';
|
||||
|
||||
import type { WidgetPreviewComponent, WidgetPreviewProps } from '../../../interface';
|
||||
import type { WidgetPreviewComponent, WidgetPreviewProps } from '@staticcms/core/interface';
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
interface PreviewHOCProps extends Omit<WidgetPreviewProps, 'widgetFor'> {
|
||||
@ -11,10 +11,10 @@ interface PreviewHOCProps extends Omit<WidgetPreviewProps, 'widgetFor'> {
|
||||
const PreviewHOC = ({ previewComponent, ...props }: PreviewHOCProps) => {
|
||||
if (!previewComponent) {
|
||||
return null;
|
||||
} else if (React.isValidElement(previewComponent)) {
|
||||
return React.cloneElement(previewComponent, props);
|
||||
} else if (isValidElement(previewComponent)) {
|
||||
return cloneElement(previewComponent, props);
|
||||
} else {
|
||||
return React.createElement(previewComponent, props);
|
||||
return createElement(previewComponent, props);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -3,7 +3,7 @@ import { Navigate, useParams } from 'react-router-dom';
|
||||
|
||||
import Editor from './Editor';
|
||||
|
||||
import type { Collections } from '../../interface';
|
||||
import type { Collections } from '@staticcms/core/interface';
|
||||
|
||||
function getDefaultPath(collections: Collections) {
|
||||
const first = Object.values(collections).filter(collection => collection.hide !== true)[0];
|
||||
|
@ -3,7 +3,7 @@ import KeyboardArrowDownIcon from '@mui/icons-material/KeyboardArrowDown';
|
||||
import AppBar from '@mui/material/AppBar';
|
||||
import Button from '@mui/material/Button';
|
||||
import CircularProgress from '@mui/material/CircularProgress';
|
||||
import green from '@mui/material/colors/green';
|
||||
import { green } from '@mui/material/colors';
|
||||
import Menu from '@mui/material/Menu';
|
||||
import MenuItem from '@mui/material/MenuItem';
|
||||
import { styled } from '@mui/material/styles';
|
||||
@ -11,13 +11,18 @@ import Toolbar from '@mui/material/Toolbar';
|
||||
import React, { useCallback, useMemo, useState } from 'react';
|
||||
import { translate } from 'react-polyglot';
|
||||
|
||||
import { colors, components, zIndex } from '../../components/UI/styles';
|
||||
import { selectAllowDeletion } from '../../lib/util/collection.util';
|
||||
import { colors, components, zIndex } from '@staticcms/core/components/UI/styles';
|
||||
import { selectAllowDeletion } from '@staticcms/core/lib/util/collection.util';
|
||||
import { SettingsDropdown } from '../UI';
|
||||
import NavLink from '../UI/NavLink';
|
||||
|
||||
import type { MouseEvent } from 'react';
|
||||
import type { Collection, EditorPersistOptions, TranslatedProps, User } from '../../interface';
|
||||
import type {
|
||||
Collection,
|
||||
EditorPersistOptions,
|
||||
TranslatedProps,
|
||||
User,
|
||||
} from '@staticcms/core/interface';
|
||||
|
||||
const StyledAppBar = styled(AppBar)`
|
||||
background-color: ${colors.foreground};
|
||||
|
@ -1,7 +1,7 @@
|
||||
import React from 'react';
|
||||
import { translate } from 'react-polyglot';
|
||||
|
||||
import type { WidgetControlProps, TranslatedProps } from '../../../interface';
|
||||
import type { WidgetControlProps, TranslatedProps } from '@staticcms/core/interface';
|
||||
|
||||
const UnknownControl = ({ field, t }: TranslatedProps<WidgetControlProps<unknown>>) => {
|
||||
return <div>{t('editor.editorWidgets.unknownControl.noControl', { widget: field.widget })}</div>;
|
||||
|
@ -1,7 +1,7 @@
|
||||
import React from 'react';
|
||||
import { translate } from 'react-polyglot';
|
||||
|
||||
import type { WidgetPreviewProps, TranslatedProps } from '../../../interface';
|
||||
import type { WidgetPreviewProps, TranslatedProps } from '@staticcms/core/interface';
|
||||
|
||||
const UnknownPreview = ({ field, t }: TranslatedProps<WidgetPreviewProps>) => {
|
||||
return (
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { registerWidget } from '../../lib/registry';
|
||||
import { registerWidget } from '@staticcms/core/lib/registry';
|
||||
import UnknownControl from './Unknown/UnknownControl';
|
||||
import UnknownPreview from './Unknown/UnknownPreview';
|
||||
|
||||
|
@ -10,17 +10,17 @@ import {
|
||||
loadMedia as loadMediaAction,
|
||||
loadMediaDisplayURL as loadMediaDisplayURLAction,
|
||||
persistMedia as persistMediaAction,
|
||||
} from '../../actions/mediaLibrary';
|
||||
import { fileExtension } from '../../lib/util';
|
||||
import { selectMediaFiles } from '../../reducers/mediaLibrary';
|
||||
} from '@staticcms/core/actions/mediaLibrary';
|
||||
import { fileExtension } from '@staticcms/core/lib/util';
|
||||
import { selectMediaFiles } from '@staticcms/core/reducers/mediaLibrary';
|
||||
import alert from '../UI/Alert';
|
||||
import confirm from '../UI/Confirm';
|
||||
import MediaLibraryModal from './MediaLibraryModal';
|
||||
|
||||
import type { ChangeEvent, KeyboardEvent } from 'react';
|
||||
import type { ConnectedProps } from 'react-redux';
|
||||
import type { MediaFile, TranslatedProps } from '../../interface';
|
||||
import type { RootState } from '../../store';
|
||||
import type { MediaFile, TranslatedProps } from '@staticcms/core/interface';
|
||||
import type { RootState } from '@staticcms/core/store';
|
||||
|
||||
/**
|
||||
* Extensions used to determine which files to show when the media library is
|
||||
|
@ -2,9 +2,9 @@ import Button from '@mui/material/Button';
|
||||
import copyToClipboard from 'copy-text-to-clipboard';
|
||||
import React, { useCallback, useEffect, useState } from 'react';
|
||||
|
||||
import { isAbsolutePath } from '../../lib/util';
|
||||
import { isAbsolutePath } from '@staticcms/core/lib/util';
|
||||
|
||||
import type { TranslatedProps } from '../../interface';
|
||||
import type { TranslatedProps } from '@staticcms/core/interface';
|
||||
|
||||
export interface CopyToClipBoardButtonProps {
|
||||
disabled: boolean;
|
||||
|
@ -1,10 +1,10 @@
|
||||
import { styled } from '@mui/material/styles';
|
||||
import React, { useEffect, useMemo } from 'react';
|
||||
|
||||
import { borders, colors, effects, lengths, shadows } from '../../components/UI/styles';
|
||||
import { transientOptions } from '../../lib';
|
||||
import { borders, colors, effects, lengths, shadows } from '@staticcms/core/components/UI/styles';
|
||||
import { transientOptions } from '@staticcms/core/lib';
|
||||
|
||||
import type { MediaLibraryDisplayURL } from '../../reducers/mediaLibrary';
|
||||
import type { MediaLibraryDisplayURL } from '@staticcms/core/reducers/mediaLibrary';
|
||||
|
||||
const IMAGE_HEIGHT = 160;
|
||||
|
||||
|
@ -7,8 +7,11 @@ import { FixedSizeGrid as Grid } from 'react-window';
|
||||
import MediaLibraryCard from './MediaLibraryCard';
|
||||
|
||||
import type { GridChildComponentProps } from 'react-window';
|
||||
import type { MediaFile } from '../../interface';
|
||||
import type { MediaLibraryDisplayURL, MediaLibraryState } from '../../reducers/mediaLibrary';
|
||||
import type { MediaFile } from '@staticcms/core/interface';
|
||||
import type {
|
||||
MediaLibraryDisplayURL,
|
||||
MediaLibraryState,
|
||||
} from '@staticcms/core/reducers/mediaLibrary';
|
||||
|
||||
export interface MediaLibraryCardItem {
|
||||
displayURL?: MediaLibraryDisplayURL;
|
||||
|
@ -12,8 +12,8 @@ import MediaLibraryCardGrid from './MediaLibraryCardGrid';
|
||||
import MediaLibraryTop from './MediaLibraryTop';
|
||||
|
||||
import type { ChangeEvent, ChangeEventHandler, KeyboardEventHandler } from 'react';
|
||||
import type { MediaFile, TranslatedProps } from '../../interface';
|
||||
import type { MediaLibraryState } from '../../reducers/mediaLibrary';
|
||||
import type { MediaFile, TranslatedProps } from '@staticcms/core/interface';
|
||||
import type { MediaLibraryState } from '@staticcms/core/reducers/mediaLibrary';
|
||||
|
||||
const StyledFab = styled(Fab)`
|
||||
position: absolute;
|
||||
|
@ -5,11 +5,11 @@ import React from 'react';
|
||||
|
||||
import { CopyToClipBoardButton } from './MediaLibraryButtons';
|
||||
import MediaLibrarySearch from './MediaLibrarySearch';
|
||||
import { buttons, shadows, zIndex } from '../../components/UI/styles';
|
||||
import { buttons, shadows, zIndex } from '@staticcms/core/components/UI/styles';
|
||||
import FileUploadButton from '../UI/FileUploadButton';
|
||||
|
||||
import type { ChangeEvent, ChangeEventHandler, KeyboardEventHandler } from 'react';
|
||||
import type { MediaFile, TranslatedProps } from '../../interface';
|
||||
import type { MediaFile, TranslatedProps } from '@staticcms/core/interface';
|
||||
|
||||
const LibraryTop = styled('div')`
|
||||
position: relative;
|
||||
|
@ -7,8 +7,8 @@ import DialogTitle from '@mui/material/DialogTitle';
|
||||
import React, { useCallback, useMemo, useState } from 'react';
|
||||
import { translate } from 'react-polyglot';
|
||||
|
||||
import AlertEvent from '../../lib/util/events/AlertEvent';
|
||||
import { useWindowEvent } from '../../lib/util/window.util';
|
||||
import AlertEvent from '@staticcms/core/lib/util/events/AlertEvent';
|
||||
import { useWindowEvent } from '@staticcms/core/lib/util/window.util';
|
||||
|
||||
import type { TranslateProps } from 'react-polyglot';
|
||||
|
||||
|
@ -6,7 +6,7 @@ import GoBackButton from './GoBackButton';
|
||||
import Icon from './Icon';
|
||||
|
||||
import type { MouseEventHandler, ReactNode } from 'react';
|
||||
import type { TranslatedProps } from '../../interface';
|
||||
import type { TranslatedProps } from '@staticcms/core/interface';
|
||||
|
||||
const StyledAuthenticationPage = styled('section')`
|
||||
display: flex;
|
||||
|
@ -7,8 +7,8 @@ import DialogTitle from '@mui/material/DialogTitle';
|
||||
import React, { useCallback, useMemo, useState } from 'react';
|
||||
import { translate } from 'react-polyglot';
|
||||
|
||||
import ConfirmEvent from '../../lib/util/events/ConfirmEvent';
|
||||
import { useWindowEvent } from '../../lib/util/window.util';
|
||||
import ConfirmEvent from '@staticcms/core/lib/util/events/ConfirmEvent';
|
||||
import { useWindowEvent } from '@staticcms/core/lib/util/window.util';
|
||||
|
||||
import type { TranslateProps } from 'react-polyglot';
|
||||
|
||||
|
@ -2,15 +2,15 @@ import { styled } from '@mui/material/styles';
|
||||
import cleanStack from 'clean-stack';
|
||||
import copyToClipboard from 'copy-text-to-clipboard';
|
||||
import truncate from 'lodash/truncate';
|
||||
import React from 'react';
|
||||
import React, { Component } from 'react';
|
||||
import { translate } from 'react-polyglot';
|
||||
import yaml from 'yaml';
|
||||
|
||||
import { localForage } from '../../lib/util';
|
||||
import { buttons, colors } from '../../components/UI/styles';
|
||||
import { buttons, colors } from '@staticcms/core/components/UI/styles';
|
||||
import { localForage } from '@staticcms/core/lib/util';
|
||||
|
||||
import type { Config, TranslatedProps } from '@staticcms/core/interface';
|
||||
import type { ReactNode } from 'react';
|
||||
import type { Config, TranslatedProps } from '../../interface';
|
||||
|
||||
const ISSUE_URL = 'https://github.com/StaticJsCMS/static-cms/issues/new?';
|
||||
|
||||
@ -45,7 +45,7 @@ function buildIssueTemplate(config: Config) {
|
||||
}
|
||||
const template = getIssueTemplate(
|
||||
version,
|
||||
config.backend.name,
|
||||
config?.backend?.name,
|
||||
navigator.userAgent,
|
||||
yaml.stringify(config),
|
||||
);
|
||||
@ -145,7 +145,7 @@ interface ErrorBoundaryState {
|
||||
backup: string;
|
||||
}
|
||||
|
||||
export class ErrorBoundary extends React.Component<
|
||||
export class ErrorBoundary extends Component<
|
||||
TranslatedProps<ErrorBoundaryProps>,
|
||||
ErrorBoundaryState
|
||||
> {
|
||||
|
@ -1,10 +1,12 @@
|
||||
import Button from '@mui/material/Button';
|
||||
import React from 'react';
|
||||
|
||||
import type { ChangeEventHandler } from 'react';
|
||||
|
||||
export interface FileUploadButtonProps {
|
||||
label: string;
|
||||
imagesOnly?: boolean;
|
||||
onChange: React.ChangeEventHandler<HTMLInputElement>;
|
||||
onChange: ChangeEventHandler<HTMLInputElement>;
|
||||
disabled?: boolean;
|
||||
}
|
||||
|
||||
|
@ -2,7 +2,7 @@ import ArrowBackIcon from '@mui/icons-material/ArrowBack';
|
||||
import Button from '@mui/material/Button';
|
||||
import React from 'react';
|
||||
|
||||
import type { TranslatedProps } from '../../interface';
|
||||
import type { TranslatedProps } from '@staticcms/core/interface';
|
||||
|
||||
interface GoBackButtonProps {
|
||||
href: string;
|
||||
|
@ -2,7 +2,7 @@ import { styled } from '@mui/material/styles';
|
||||
import React from 'react';
|
||||
|
||||
import icons from './Icon/icons';
|
||||
import transientOptions from '../../lib/util/transientOptions';
|
||||
import transientOptions from '@staticcms/core/lib/util/transientOptions';
|
||||
|
||||
import type { IconType } from './Icon/icons';
|
||||
|
||||
|
@ -5,7 +5,7 @@ import ExpandMoreIcon from '@mui/icons-material/ExpandMore';
|
||||
import IconButton from '@mui/material/IconButton';
|
||||
import React from 'react';
|
||||
|
||||
import { transientOptions } from '../../lib/util';
|
||||
import { transientOptions } from '@staticcms/core/lib/util';
|
||||
import { buttons, colors, lengths, transitions } from './styles';
|
||||
|
||||
import type { ComponentClass, MouseEvent, ReactNode } from 'react';
|
||||
|
@ -2,8 +2,8 @@ import React, { forwardRef } from 'react';
|
||||
import { NavLink as NavLinkBase } from 'react-router-dom';
|
||||
import { styled } from '@mui/material/styles';
|
||||
|
||||
import { colors } from '../../components/UI/styles';
|
||||
import { transientOptions } from '../../lib';
|
||||
import { colors } from '@staticcms/core/components/UI/styles';
|
||||
import { transientOptions } from '@staticcms/core/lib';
|
||||
|
||||
import type { RefAttributes } from 'react';
|
||||
import type { NavLinkProps as RouterNavLinkProps } from 'react-router-dom';
|
||||
|
@ -5,13 +5,13 @@ import IconButton from '@mui/material/IconButton';
|
||||
import Menu from '@mui/material/Menu';
|
||||
import MenuItem from '@mui/material/MenuItem';
|
||||
import { styled } from '@mui/material/styles';
|
||||
import React, { useCallback } from 'react';
|
||||
import React, { useCallback, useState } from 'react';
|
||||
|
||||
import { transientOptions } from '../../lib';
|
||||
import { transientOptions } from '@staticcms/core/lib';
|
||||
import { colors, colorsRaw, transitions } from './styles';
|
||||
|
||||
import type { ObjectField, TranslatedProps } from '@staticcms/core/interface';
|
||||
import type { MouseEvent, ReactNode } from 'react';
|
||||
import type { ObjectField, TranslatedProps } from '../../interface';
|
||||
|
||||
const TopBarContainer = styled('div')`
|
||||
position: relative;
|
||||
@ -67,9 +67,9 @@ const ObjectWidgetTopBar = ({
|
||||
hasError = false,
|
||||
t,
|
||||
}: TranslatedProps<ObjectWidgetTopBarProps>) => {
|
||||
const [anchorEl, setAnchorEl] = React.useState<null | HTMLElement>(null);
|
||||
const [anchorEl, setAnchorEl] = useState<null | HTMLElement>(null);
|
||||
const open = Boolean(anchorEl);
|
||||
const handleClick = useCallback((event: React.MouseEvent<HTMLButtonElement>) => {
|
||||
const handleClick = useCallback((event: MouseEvent<HTMLButtonElement>) => {
|
||||
setAnchorEl(event.currentTarget);
|
||||
}, []);
|
||||
const handleClose = useCallback(() => {
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { styled } from '@mui/material/styles';
|
||||
import React from 'react';
|
||||
|
||||
import transientOptions from '../../lib/util/transientOptions';
|
||||
import transientOptions from '@staticcms/core/lib/util/transientOptions';
|
||||
|
||||
interface StyledOutlineProps {
|
||||
$active: boolean;
|
||||
|
@ -3,6 +3,8 @@ import { styled } from '@mui/material/styles';
|
||||
import useScrollTrigger from '@mui/material/useScrollTrigger';
|
||||
import React, { useCallback } from 'react';
|
||||
|
||||
import type { ReactNode, MouseEvent } from 'react';
|
||||
|
||||
const StyledScrollTop = styled('div')`
|
||||
position: fixed;
|
||||
bottom: 16px;
|
||||
@ -10,7 +12,7 @@ const StyledScrollTop = styled('div')`
|
||||
`;
|
||||
|
||||
interface ScrollTopProps {
|
||||
children: React.ReactNode;
|
||||
children: ReactNode;
|
||||
}
|
||||
|
||||
const ScrollTop = ({ children }: ScrollTopProps) => {
|
||||
@ -19,7 +21,7 @@ const ScrollTop = ({ children }: ScrollTopProps) => {
|
||||
threshold: 100,
|
||||
});
|
||||
|
||||
const handleClick = useCallback((event: React.MouseEvent<HTMLDivElement>) => {
|
||||
const handleClick = useCallback((event: MouseEvent<HTMLDivElement>) => {
|
||||
const anchor = ((event.target as HTMLDivElement).ownerDocument || document).querySelector(
|
||||
'#back-to-top-anchor',
|
||||
);
|
||||
|
@ -1,13 +1,14 @@
|
||||
import PersonIcon from '@mui/icons-material/Person';
|
||||
import Avatar from '@mui/material/Avatar';
|
||||
import IconButton from '@mui/material/IconButton';
|
||||
import Menu from '@mui/material/Menu';
|
||||
import MenuItem from '@mui/material/MenuItem';
|
||||
import Tooltip from '@mui/material/Tooltip';
|
||||
import React, { useCallback } from 'react';
|
||||
import React, { useCallback, useState } from 'react';
|
||||
import { translate } from 'react-polyglot';
|
||||
import PersonIcon from '@mui/icons-material/Person';
|
||||
|
||||
import type { TranslatedProps } from '../../interface';
|
||||
import type { TranslatedProps } from '@staticcms/core/interface';
|
||||
import type { MouseEvent } from 'react';
|
||||
|
||||
interface AvatarImageProps {
|
||||
imageUrl: string | undefined;
|
||||
@ -33,9 +34,9 @@ const SettingsDropdown = ({
|
||||
onLogoutClick,
|
||||
t,
|
||||
}: TranslatedProps<SettingsDropdownProps>) => {
|
||||
const [anchorEl, setAnchorEl] = React.useState<null | HTMLElement>(null);
|
||||
const [anchorEl, setAnchorEl] = useState<null | HTMLElement>(null);
|
||||
const open = Boolean(anchorEl);
|
||||
const handleClick = useCallback((event: React.MouseEvent<HTMLButtonElement>) => {
|
||||
const handleClick = useCallback((event: MouseEvent<HTMLButtonElement>) => {
|
||||
setAnchorEl(event.currentTarget);
|
||||
}, []);
|
||||
const handleClose = useCallback(() => {
|
||||
|
@ -519,10 +519,7 @@ function GlobalStyles() {
|
||||
}
|
||||
|
||||
${quantifier} {
|
||||
font-family: ${fonts.primary};
|
||||
font-weight: normal;
|
||||
background-color: ${colors.background};
|
||||
color: ${colors.text};
|
||||
margin: 0;
|
||||
|
||||
.ol-viewport {
|
||||
|
@ -4,13 +4,13 @@ import { translate } from 'react-polyglot';
|
||||
import { connect } from 'react-redux';
|
||||
import { useParams } from 'react-router-dom';
|
||||
|
||||
import { getAdditionalLink } from '../../lib/registry';
|
||||
import { getAdditionalLink } from '@staticcms/core/lib/registry';
|
||||
import MainView from '../App/MainView';
|
||||
import Sidebar from '../Collection/Sidebar';
|
||||
|
||||
import type { ComponentType } from 'react';
|
||||
import type { ConnectedProps } from 'react-redux';
|
||||
import type { RootState } from '../../store';
|
||||
import type { RootState } from '@staticcms/core/store';
|
||||
|
||||
const StyledPageContent = styled('div')`
|
||||
width: 100%;
|
||||
|
@ -5,17 +5,18 @@ import Snackbar from '@mui/material/Snackbar';
|
||||
import React, { useCallback, useEffect, useState } from 'react';
|
||||
import { translate } from 'react-polyglot';
|
||||
|
||||
import { useAppDispatch, useAppSelector } from '../../store/hooks';
|
||||
import { removeSnackbarById, selectSnackbars } from '../../store/slices/snackbars';
|
||||
import { useAppDispatch, useAppSelector } from '@staticcms/core/store/hooks';
|
||||
import { removeSnackbarById, selectSnackbars } from '@staticcms/core/store/slices/snackbars';
|
||||
|
||||
import type { TranslatedProps } from '../../interface';
|
||||
import type { SnackbarMessage } from '../../store/slices/snackbars';
|
||||
import type { TranslatedProps } from '@staticcms/core/interface';
|
||||
import type { SnackbarMessage } from '@staticcms/core/store/slices/snackbars';
|
||||
import type { SyntheticEvent } from 'react';
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-empty-interface
|
||||
interface SnackbarsProps {}
|
||||
|
||||
const Snackbars = ({ t }: TranslatedProps<SnackbarsProps>) => {
|
||||
const [open, setOpen] = React.useState(false);
|
||||
const [open, setOpen] = useState(false);
|
||||
const [messageInfo, setMessageInfo] = useState<SnackbarMessage | undefined>(undefined);
|
||||
|
||||
const snackbars = useAppSelector(selectSnackbars);
|
||||
@ -34,7 +35,7 @@ const Snackbars = ({ t }: TranslatedProps<SnackbarsProps>) => {
|
||||
}
|
||||
}, [snackbars, messageInfo, open, dispatch]);
|
||||
|
||||
const handleClose = useCallback((_event?: React.SyntheticEvent | Event, reason?: string) => {
|
||||
const handleClose = useCallback((_event?: SyntheticEvent | Event, reason?: string) => {
|
||||
if (reason === 'clickaway') {
|
||||
return;
|
||||
}
|
||||
|
@ -343,7 +343,7 @@ class ConfigError extends Error {
|
||||
* `validateConfig` is a pure function. It does not mutate
|
||||
* the config that is passed in.
|
||||
*/
|
||||
export function validateConfig(config: Config) {
|
||||
export default function validateConfig(config: Config) {
|
||||
const ajv = new AJV({ allErrors: true, allowUnionTypes: true, $data: true });
|
||||
uniqueItemProperties(ajv);
|
||||
select(ajv);
|
||||
|
@ -1,2 +1,3 @@
|
||||
/* eslint-disable import/prefer-default-export */
|
||||
export const IMAGE_EXTENSION_REGEX =
|
||||
/(\.apng|\.avif|\.gif|\.jpg|\.jpeg|\.jfif|\.pjpeg|\.pjp|\.png|\.svg|\.webp)$/g;
|
||||
|
@ -7,7 +7,7 @@ import {
|
||||
TestBackend,
|
||||
} from './backends';
|
||||
import { registerBackend, registerLocale, registerWidget } from './lib/registry';
|
||||
import { locales } from './locales';
|
||||
import locales from './locales';
|
||||
import {
|
||||
BooleanWidget,
|
||||
CodeWidget,
|
||||
@ -26,7 +26,7 @@ import {
|
||||
TextWidget,
|
||||
} from './widgets';
|
||||
|
||||
export function addExtensions() {
|
||||
export default function addExtensions() {
|
||||
// Register all the things
|
||||
registerBackend('git-gateway', GitGatewayBackend);
|
||||
registerBackend('github', GitHubBackend);
|
||||
|
@ -1,4 +1,4 @@
|
||||
export abstract class FileFormatter {
|
||||
export default abstract class FileFormatter {
|
||||
abstract fromFile(content: string): object;
|
||||
abstract toFile(data: object, sortedKeys?: string[], comments?: Record<string, string>): string;
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { FileFormatter } from './FileFormatter';
|
||||
import FileFormatter from './FileFormatter';
|
||||
|
||||
class JsonFormatter extends FileFormatter {
|
||||
fromFile(content: string) {
|
||||
|
@ -1,6 +1,6 @@
|
||||
import toml from '@ltd/j-toml';
|
||||
|
||||
import { FileFormatter } from './FileFormatter';
|
||||
import FileFormatter from './FileFormatter';
|
||||
|
||||
class TomlFormatter extends FileFormatter {
|
||||
fromFile(content: string) {
|
||||
|
@ -1,7 +1,7 @@
|
||||
import yaml from 'yaml';
|
||||
|
||||
import { sortKeys } from './helpers';
|
||||
import { FileFormatter } from './FileFormatter';
|
||||
import FileFormatter from './FileFormatter';
|
||||
|
||||
import type { Pair, YAMLMap, YAMLSeq } from 'yaml/types';
|
||||
|
||||
|
@ -5,7 +5,7 @@ import { FrontmatterInfer, frontmatterJSON, frontmatterTOML, frontmatterYAML } f
|
||||
|
||||
import type { Delimiter } from './frontmatter';
|
||||
import type { Collection, Entry, Format } from '../interface';
|
||||
import type { FileFormatter } from './FileFormatter';
|
||||
import type FileFormatter from './FileFormatter';
|
||||
|
||||
export const frontmatterFormats = ['yaml-frontmatter', 'toml-frontmatter', 'json-frontmatter'];
|
||||
|
||||
|
@ -3,7 +3,7 @@ import matter from 'gray-matter';
|
||||
import YamlFormatter from './YamlFormatter';
|
||||
import TomlFormatter from './TomlFormatter';
|
||||
import JsonFormatter from './JsonFormatter';
|
||||
import { FileFormatter } from './FileFormatter';
|
||||
import FileFormatter from './FileFormatter';
|
||||
|
||||
const Languages = {
|
||||
YAML: 'yaml',
|
||||
|
@ -1,3 +1,4 @@
|
||||
/* eslint-disable import/prefer-default-export */
|
||||
export function sortKeys<Item>(
|
||||
sortedKeys: string[],
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
|
@ -1,5 +1,5 @@
|
||||
import createReactClass from 'create-react-class';
|
||||
import React from 'react';
|
||||
import { createElement, useCallback, useEffect, useMemo, useState } from 'react';
|
||||
|
||||
import bootstrap from './bootstrap';
|
||||
import Registry from './lib/registry';
|
||||
@ -7,7 +7,7 @@ import Registry from './lib/registry';
|
||||
export * from './backends';
|
||||
export * from './widgets';
|
||||
export * from './media-libraries';
|
||||
export * from './locales';
|
||||
export { default as locales } from './locales';
|
||||
export * from './lib';
|
||||
|
||||
export * from './interface';
|
||||
@ -20,11 +20,11 @@ const CMS = {
|
||||
if (typeof window !== 'undefined') {
|
||||
window.CMS = CMS;
|
||||
window.createClass = window.createClass || createReactClass;
|
||||
window.useState = window.useState || React.useState;
|
||||
window.useMemo = window.useMemo || React.useMemo;
|
||||
window.useEffect = window.useEffect || React.useEffect;
|
||||
window.useCallback = window.useCallback || React.useCallback;
|
||||
window.h = window.h || React.createElement;
|
||||
window.useState = window.useState || useState;
|
||||
window.useMemo = window.useMemo || useMemo;
|
||||
window.useEffect = window.useEffect || useEffect;
|
||||
window.useCallback = window.useCallback || useCallback;
|
||||
window.h = window.h || createElement;
|
||||
}
|
||||
|
||||
export default CMS;
|
||||
|
@ -1,10 +1,10 @@
|
||||
import flatten from 'lodash/flatten';
|
||||
|
||||
import { unsentRequest } from '../../../lib/util';
|
||||
import { selectEntrySlug } from '../../../lib/util/collection.util';
|
||||
import { createEntry } from '../../../valueObjects/Entry';
|
||||
import { unsentRequest } from '@staticcms/core/lib/util';
|
||||
import { selectEntrySlug } from '@staticcms/core/lib/util/collection.util';
|
||||
import createEntry from '@staticcms/core/valueObjects/createEntry';
|
||||
|
||||
import type { AlgoliaConfig, Collection, Entry, SearchResponse } from '../../../interface';
|
||||
import type { AlgoliaConfig, Collection, Entry, SearchResponse } from '@staticcms/core/interface';
|
||||
|
||||
const { fetchWithTimeout: fetch } = unsentRequest;
|
||||
|
||||
|
@ -1,10 +1,12 @@
|
||||
import type {
|
||||
EditorPlugin as MarkdownPlugin,
|
||||
EditorType as MarkdownEditorType,
|
||||
} from '@toast-ui/editor/types/editor';
|
||||
import type { ToolbarItemOptions as MarkdownToolbarItemOptions } from '@toast-ui/editor/types/ui';
|
||||
import type { LanguageName } from '@uiw/codemirror-extensions-langs';
|
||||
import type { PropertiesSchema } from 'ajv/dist/types/json-schema';
|
||||
import type { ComponentType, FunctionComponent, ReactNode } from 'react';
|
||||
import type {
|
||||
ComponentType,
|
||||
FunctionComponent,
|
||||
JSXElementConstructor,
|
||||
ReactElement,
|
||||
ReactNode,
|
||||
} from 'react';
|
||||
import type { t, TranslateProps as ReactPolyglotTranslateProps } from 'react-polyglot';
|
||||
import type { MediaFile as BackendMediaFile } from './backend';
|
||||
import type { EditorControlProps } from './components/Editor/EditorControlPane/EditorControl';
|
||||
@ -18,7 +20,6 @@ import type { I18N_STRUCTURE } from './lib/i18n';
|
||||
import type { AllowedEvent } from './lib/registry';
|
||||
import type Cursor from './lib/util/Cursor';
|
||||
import type AssetProxy from './valueObjects/AssetProxy';
|
||||
import type { MediaHolder } from './widgets/markdown/hooks/useMedia';
|
||||
|
||||
export interface Pages {
|
||||
[collection: string]: { isFetching?: boolean; page?: number; ids: string[] };
|
||||
@ -278,7 +279,7 @@ export interface WidgetPreviewProps<T = unknown, F extends BaseField = UnknownFi
|
||||
|
||||
export type WidgetPreviewComponent<T = unknown, F extends BaseField = UnknownField> =
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
| React.ReactElement<unknown, string | React.JSXElementConstructor<any>>
|
||||
| ReactElement<unknown, string | JSXElementConstructor<any>>
|
||||
| ComponentType<WidgetPreviewProps<T, F>>;
|
||||
|
||||
export type WidgetsFor<P = EntryData> = <K extends keyof P>(
|
||||
@ -286,11 +287,11 @@ export type WidgetsFor<P = EntryData> = <K extends keyof P>(
|
||||
) => P[K] extends Array<infer U>
|
||||
? {
|
||||
data: U | null;
|
||||
widgets: Record<keyof U, React.ReactNode>;
|
||||
widgets: Record<keyof U, ReactNode>;
|
||||
}[]
|
||||
: {
|
||||
data: P[K] | null;
|
||||
widgets: Record<keyof P[K], React.ReactNode>;
|
||||
widgets: Record<keyof P[K], ReactNode>;
|
||||
};
|
||||
|
||||
export interface TemplatePreviewProps<T = EntryData, EF extends BaseField = UnknownField> {
|
||||
@ -841,7 +842,7 @@ export interface I18nInfo {
|
||||
export interface ProcessedCodeLanguage {
|
||||
label: string;
|
||||
identifiers: string[];
|
||||
codemirror_mode: string;
|
||||
codemirror_mode: LanguageName;
|
||||
codemirror_mime_type: string;
|
||||
}
|
||||
|
||||
@ -862,22 +863,25 @@ export interface PreviewStyle {
|
||||
export interface MarkdownPluginFactoryProps {
|
||||
config: Config<MarkdownField>;
|
||||
field: MarkdownField;
|
||||
media: MediaHolder;
|
||||
mode: 'editor' | 'preview';
|
||||
}
|
||||
|
||||
export type MarkdownPluginFactory = (props: MarkdownPluginFactoryProps) => MarkdownPlugin;
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
export type MarkdownPluginFactory = (props: MarkdownPluginFactoryProps) => any;
|
||||
|
||||
export interface MarkdownToolbarItemsFactoryProps {
|
||||
imageToolbarButton: MarkdownToolbarItemOptions;
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
imageToolbarButton: any;
|
||||
}
|
||||
|
||||
export type MarkdownToolbarItemsFactory = (
|
||||
props: MarkdownToolbarItemsFactoryProps,
|
||||
) => (string | MarkdownToolbarItemOptions)[][];
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
) => (string | any)[][];
|
||||
|
||||
export interface MarkdownEditorOptions {
|
||||
initialEditType?: MarkdownEditorType;
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
initialEditType?: any;
|
||||
height?: string;
|
||||
toolbarItems?: MarkdownToolbarItemsFactory;
|
||||
plugins?: MarkdownPluginFactory[];
|
||||
|
@ -3,7 +3,7 @@ import trimEnd from 'lodash/trimEnd';
|
||||
|
||||
import { createNonce, isInsecureProtocol, validateNonce } from './utils';
|
||||
|
||||
import type { User, AuthenticatorConfig } from '../../interface';
|
||||
import type { User, AuthenticatorConfig } from '@staticcms/core/interface';
|
||||
import type { NetlifyError } from './netlify-auth';
|
||||
|
||||
export default class ImplicitAuthenticator {
|
||||
|
@ -1,7 +1,7 @@
|
||||
import trim from 'lodash/trim';
|
||||
import trimEnd from 'lodash/trimEnd';
|
||||
|
||||
import type { User, AuthenticatorConfig } from '../../interface';
|
||||
import type { User, AuthenticatorConfig } from '@staticcms/core/interface';
|
||||
|
||||
const NETLIFY_API = 'https://api.netlify.com';
|
||||
const AUTH_ENDPOINT = 'auth';
|
||||
|
@ -3,7 +3,7 @@ import trimEnd from 'lodash/trimEnd';
|
||||
|
||||
import { createNonce, isInsecureProtocol, validateNonce } from './utils';
|
||||
|
||||
import type { User, AuthenticatorConfig } from '../../interface';
|
||||
import type { User, AuthenticatorConfig } from '@staticcms/core/interface';
|
||||
import type { NetlifyError } from './netlify-auth';
|
||||
|
||||
async function sha256(text: string) {
|
||||
|
22
core/src/lib/hooks/useDebounce.ts
Normal file
22
core/src/lib/hooks/useDebounce.ts
Normal file
@ -0,0 +1,22 @@
|
||||
import { useEffect, useState } from 'react';
|
||||
|
||||
export default function useDebounce<T>(value: T, delay: number): T {
|
||||
const [debouncedValue, setDebouncedValue] = useState(value);
|
||||
|
||||
useEffect(() => {
|
||||
if (delay === 0) {
|
||||
setDebouncedValue(value);
|
||||
return;
|
||||
}
|
||||
|
||||
const handler = setTimeout(() => {
|
||||
setDebouncedValue(value);
|
||||
}, delay);
|
||||
|
||||
return () => {
|
||||
clearTimeout(handler);
|
||||
};
|
||||
}, [value, delay]);
|
||||
|
||||
return delay === 0 ? value : debouncedValue;
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user