feat: upgrade to Emotion 10 (#2166)
This commit is contained in:
parent
7d6992e464
commit
ccef446d72
17
.eslintrc
17
.eslintrc
@ -17,6 +17,19 @@
|
|||||||
},
|
},
|
||||||
"rules": {
|
"rules": {
|
||||||
"no-console": [0],
|
"no-console": [0],
|
||||||
"react/prop-types": [1]
|
"react/prop-types": [1],
|
||||||
}
|
"no-duplicate-imports": "error",
|
||||||
|
"emotion/jsx-import": "error",
|
||||||
|
"emotion/no-vanilla": "error",
|
||||||
|
"emotion/import-from-emotion": "error",
|
||||||
|
"emotion/styled-import": "error"
|
||||||
|
},
|
||||||
|
"plugins": [
|
||||||
|
"emotion",
|
||||||
|
],
|
||||||
|
"settings": {
|
||||||
|
"react": {
|
||||||
|
"version": "detect",
|
||||||
|
},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
19
.stylelintrc
19
.stylelintrc
@ -1,14 +1,23 @@
|
|||||||
{
|
{
|
||||||
"processors": ["stylelint-processor-styled-components"],
|
"processors": [
|
||||||
|
["stylelint-processor-styled-components", {
|
||||||
|
"parserPlugins": [
|
||||||
|
"jsx",
|
||||||
|
"objectRestSpread",
|
||||||
|
"exportDefaultFrom",
|
||||||
|
"classProperties",
|
||||||
|
],
|
||||||
|
}],
|
||||||
|
],
|
||||||
"extends": [
|
"extends": [
|
||||||
"stylelint-config-recommended",
|
"stylelint-config-recommended",
|
||||||
"stylelint-config-styled-components"
|
"stylelint-config-styled-components",
|
||||||
],
|
],
|
||||||
"rules": {
|
"rules": {
|
||||||
"block-no-empty": null,
|
"block-no-empty": null,
|
||||||
"no-duplicate-selectors": null,
|
"no-duplicate-selectors": null,
|
||||||
"selector-type-no-unknown": [true, {
|
"selector-type-no-unknown": [true, {
|
||||||
"ignoreTypes": ["$dummyValue"]
|
"ignoreTypes": ["$dummyValue"],
|
||||||
}]
|
}],
|
||||||
}
|
},
|
||||||
}
|
}
|
@ -1,5 +1,5 @@
|
|||||||
module.exports = {
|
module.exports = {
|
||||||
setupTestFrameworkScriptFile: '<rootDir>/setupTestFramework.js',
|
setupFilesAfterEnv: ['<rootDir>/setupTestFramework.js'],
|
||||||
transform: {
|
transform: {
|
||||||
'\\.js$': '<rootDir>/custom-preprocessor.js',
|
'\\.js$': '<rootDir>/custom-preprocessor.js',
|
||||||
},
|
},
|
||||||
|
54
package.json
54
package.json
@ -62,50 +62,54 @@
|
|||||||
"last 2 ChromeAndroid versions"
|
"last 2 ChromeAndroid versions"
|
||||||
],
|
],
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/cli": "^7.1.2",
|
"@babel/cli": "^7.2.3",
|
||||||
"@babel/core": "^7.1.2",
|
"@babel/core": "^7.3.4",
|
||||||
"@babel/plugin-proposal-class-properties": "^7.1.0",
|
"@babel/plugin-proposal-class-properties": "^7.3.4",
|
||||||
"@babel/plugin-proposal-export-default-from": "^7.0.0",
|
"@babel/plugin-proposal-export-default-from": "^7.2.0",
|
||||||
"@babel/plugin-proposal-object-rest-spread": "^7.0.0",
|
"@babel/plugin-proposal-object-rest-spread": "^7.3.4",
|
||||||
"@babel/preset-env": "^7.1.0",
|
"@babel/preset-env": "^7.3.4",
|
||||||
"@babel/preset-react": "^7.0.0",
|
"@babel/preset-react": "^7.0.0",
|
||||||
"all-contributors-cli": "^4.4.0",
|
"all-contributors-cli": "^4.4.0",
|
||||||
"babel-core": "^7.0.0-bridge.0",
|
"babel-core": "^7.0.0-bridge.0",
|
||||||
"babel-eslint": "^10.0.1",
|
"babel-eslint": "^10.0.1",
|
||||||
"babel-jest": "^23.6.0",
|
"babel-jest": "^24.5.0",
|
||||||
"babel-loader": "^8.0.4",
|
"babel-loader": "^8.0.5",
|
||||||
"babel-plugin-emotion": "^9.2.11",
|
"babel-plugin-emotion": "^10.0.9",
|
||||||
"babel-plugin-inline-svg": "^1.0.0",
|
"babel-plugin-inline-svg": "^1.0.0",
|
||||||
"babel-plugin-lodash": "^3.3.4",
|
"babel-plugin-lodash": "^3.3.4",
|
||||||
"babel-plugin-module-resolver": "^3.1.1",
|
"babel-plugin-module-resolver": "^3.2.0",
|
||||||
"babel-plugin-transform-builtin-extend": "^1.1.2",
|
"babel-plugin-transform-builtin-extend": "^1.1.2",
|
||||||
"babel-plugin-transform-export-extensions": "^6.22.0",
|
"babel-plugin-transform-export-extensions": "^6.22.0",
|
||||||
"babel-plugin-transform-inline-environment-variables": "^0.4.3",
|
"babel-plugin-transform-inline-environment-variables": "^0.4.3",
|
||||||
"cache-me-outside": "^0.0.4",
|
"cache-me-outside": "^0.0.4",
|
||||||
"cross-env": "^5.1.4",
|
"cross-env": "^5.1.4",
|
||||||
"cypress": "^3.0.3",
|
"cypress": "^3.1.5",
|
||||||
"dom-testing-library": "^3.13.0",
|
"dom-testing-library": "^3.17.1",
|
||||||
"eslint": "^5.3.0",
|
"eslint": "^5.15.1",
|
||||||
"eslint-plugin-react": "^7.10.0",
|
"eslint-plugin-emotion": "^10.0.7",
|
||||||
|
"eslint-plugin-react": "^7.12.4",
|
||||||
"friendly-errors-webpack-plugin": "^1.7.0",
|
"friendly-errors-webpack-plugin": "^1.7.0",
|
||||||
"http-server": "^0.11.1",
|
"http-server": "^0.11.1",
|
||||||
"jest": "^23.4.0",
|
"jest": "^24.5.0",
|
||||||
"jest-cli": "^23.4.0",
|
"jest-cli": "^24.5.0",
|
||||||
"jest-emotion": "^9.2.7",
|
"jest-emotion": "^10.0.9",
|
||||||
"lerna": "^3.4.0",
|
"lerna": "^3.13.1",
|
||||||
"npm-run-all": "^4.1.5",
|
"npm-run-all": "^4.1.5",
|
||||||
"prettier": "1.14.0",
|
"prettier": "1.16.4",
|
||||||
"react-test-renderer": "^16.0.0",
|
"react-test-renderer": "^16.8.4",
|
||||||
"rimraf": "^2.6.2",
|
"rimraf": "^2.6.3",
|
||||||
"start-server-and-test": "^1.7.0",
|
"start-server-and-test": "^1.7.11",
|
||||||
"stylelint": "^9.4.0",
|
"stylelint": "^9.10.1",
|
||||||
"stylelint-config-recommended": "^2.1.0",
|
"stylelint-config-recommended": "^2.1.0",
|
||||||
"stylelint-config-styled-components": "^0.1.1",
|
"stylelint-config-styled-components": "^0.1.1",
|
||||||
"stylelint-processor-styled-components": "^1.3.1",
|
"stylelint-processor-styled-components": "^1.5.2",
|
||||||
"svg-inline-loader": "^0.8.0"
|
"svg-inline-loader": "^0.8.0"
|
||||||
},
|
},
|
||||||
"workspaces": [
|
"workspaces": [
|
||||||
"packages/*"
|
"packages/*"
|
||||||
],
|
],
|
||||||
"private": true
|
"private": true,
|
||||||
|
"dependencies": {
|
||||||
|
"emotion": "^10.0.9"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,23 +19,23 @@
|
|||||||
"build": "cross-env NODE_ENV=production webpack"
|
"build": "cross-env NODE_ENV=production webpack"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"js-base64": "^2.4.8",
|
"js-base64": "^2.5.1",
|
||||||
"semaphore": "^1.1.0"
|
"semaphore": "^1.1.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"cross-env": "^5.2.0",
|
"cross-env": "^5.2.0",
|
||||||
"webpack": "^4.16.1",
|
"webpack": "^4.29.6",
|
||||||
"webpack-cli": "^3.1.0"
|
"webpack-cli": "^3.2.3"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"emotion": "^9.2.6",
|
"@emotion/core": "^10.0.9",
|
||||||
|
"@emotion/styled": "^10.0.9",
|
||||||
"immutable": "^3.7.6",
|
"immutable": "^3.7.6",
|
||||||
"lodash": "^4.17.10",
|
"lodash": "^4.17.10",
|
||||||
"netlify-cms-lib-auth": "^2.0.4",
|
"netlify-cms-lib-auth": "^2.0.4",
|
||||||
"netlify-cms-lib-util": "^2.1.0",
|
"netlify-cms-lib-util": "^2.1.0",
|
||||||
"netlify-cms-ui-default": "^2.0.6",
|
"netlify-cms-ui-default": "^2.0.6",
|
||||||
"prop-types": "^15.6.2",
|
"prop-types": "^15.6.2",
|
||||||
"react": "^16.4.1",
|
"react": "^16.4.1"
|
||||||
"react-emotion": "^9.2.6"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||||
import styled from 'react-emotion';
|
import styled from '@emotion/styled';
|
||||||
import { NetlifyAuthenticator } from 'netlify-cms-lib-auth';
|
import { NetlifyAuthenticator } from 'netlify-cms-lib-auth';
|
||||||
import { AuthenticationPage, Icon } from 'netlify-cms-ui-default';
|
import { AuthenticationPage, Icon } from 'netlify-cms-ui-default';
|
||||||
|
|
||||||
|
@ -20,18 +20,19 @@
|
|||||||
"build": "cross-env NODE_ENV=production webpack"
|
"build": "cross-env NODE_ENV=production webpack"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"gotrue-js": "^0.9.22",
|
"gotrue-js": "^0.9.24",
|
||||||
"ini": "^1.3.5",
|
"ini": "^1.3.5",
|
||||||
"jwt-decode": "^2.2.0",
|
"jwt-decode": "^2.2.0",
|
||||||
"minimatch": "^3.0.4"
|
"minimatch": "^3.0.4"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"cross-env": "^5.2.0",
|
"cross-env": "^5.2.0",
|
||||||
"webpack": "^4.16.1",
|
"webpack": "^4.29.6",
|
||||||
"webpack-cli": "^3.1.0"
|
"webpack-cli": "^3.2.3"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"emotion": "^9.2.6",
|
"@emotion/core": "^10.0.9",
|
||||||
|
"@emotion/styled": "^10.0.9",
|
||||||
"immutable": "^3.7.6",
|
"immutable": "^3.7.6",
|
||||||
"lodash": "^4.17.10",
|
"lodash": "^4.17.10",
|
||||||
"netlify-cms-backend-bitbucket": "^2.0.0",
|
"netlify-cms-backend-bitbucket": "^2.0.0",
|
||||||
@ -41,7 +42,6 @@
|
|||||||
"netlify-cms-lib-util": "^2.0.0",
|
"netlify-cms-lib-util": "^2.0.0",
|
||||||
"netlify-cms-ui-default": "^2.0.0",
|
"netlify-cms-ui-default": "^2.0.0",
|
||||||
"prop-types": "^15.6.2",
|
"prop-types": "^15.6.2",
|
||||||
"react": "^16.4.1",
|
"react": "^16.4.1"
|
||||||
"react-emotion": "^9.2.6"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import styled from 'react-emotion';
|
import styled from '@emotion/styled';
|
||||||
import { partial } from 'lodash';
|
import { partial } from 'lodash';
|
||||||
import {
|
import {
|
||||||
AuthenticationPage,
|
AuthenticationPage,
|
||||||
|
@ -20,22 +20,22 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"common-tags": "^1.8.0",
|
"common-tags": "^1.8.0",
|
||||||
"js-base64": "^2.4.8",
|
"js-base64": "^2.5.1",
|
||||||
"semaphore": "^1.1.0"
|
"semaphore": "^1.1.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"cross-env": "^5.2.0",
|
"cross-env": "^5.2.0",
|
||||||
"webpack": "^4.16.1",
|
"webpack": "^4.29.6",
|
||||||
"webpack-cli": "^3.1.0"
|
"webpack-cli": "^3.2.3"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"emotion": "^9.2.6",
|
"@emotion/core": "^10.0.9",
|
||||||
|
"@emotion/styled": "^10.0.9",
|
||||||
"lodash": "^4.17.10",
|
"lodash": "^4.17.10",
|
||||||
"netlify-cms-lib-auth": "^2.0.0",
|
"netlify-cms-lib-auth": "^2.0.0",
|
||||||
"netlify-cms-lib-util": "^2.0.0",
|
"netlify-cms-lib-util": "^2.0.0",
|
||||||
"netlify-cms-ui-default": "^2.0.0",
|
"netlify-cms-ui-default": "^2.0.0",
|
||||||
"prop-types": "^15.6.2",
|
"prop-types": "^15.6.2",
|
||||||
"react": "^16.4.1",
|
"react": "^16.4.1"
|
||||||
"react-emotion": "^9.2.6"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,12 @@
|
|||||||
import { localForage } from 'netlify-cms-lib-util';
|
|
||||||
import { Base64 } from 'js-base64';
|
import { Base64 } from 'js-base64';
|
||||||
import { uniq, initial, last, get, find, hasIn, partial, result } from 'lodash';
|
import { uniq, initial, last, get, find, hasIn, partial, result } from 'lodash';
|
||||||
import { filterPromises, resolvePromiseProperties } from 'netlify-cms-lib-util';
|
import {
|
||||||
import { APIError, EditorialWorkflowError } from 'netlify-cms-lib-util';
|
localForage,
|
||||||
|
filterPromises,
|
||||||
|
resolvePromiseProperties,
|
||||||
|
APIError,
|
||||||
|
EditorialWorkflowError,
|
||||||
|
} from 'netlify-cms-lib-util';
|
||||||
|
|
||||||
const CMS_BRANCH_PREFIX = 'cms/';
|
const CMS_BRANCH_PREFIX = 'cms/';
|
||||||
|
|
||||||
@ -222,8 +226,8 @@ export default class API {
|
|||||||
}
|
}
|
||||||
|
|
||||||
readUnpublishedBranchFile(contentKey) {
|
readUnpublishedBranchFile(contentKey) {
|
||||||
const metaDataPromise = this.retrieveMetadata(contentKey).then(
|
const metaDataPromise = this.retrieveMetadata(contentKey).then(data =>
|
||||||
data => (data.objects.entry.path ? data : Promise.reject(null)),
|
data.objects.entry.path ? data : Promise.reject(null),
|
||||||
);
|
);
|
||||||
return resolvePromiseProperties({
|
return resolvePromiseProperties({
|
||||||
metaData: metaDataPromise,
|
metaData: metaDataPromise,
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||||
import styled from 'react-emotion';
|
import styled from '@emotion/styled';
|
||||||
import { NetlifyAuthenticator } from 'netlify-cms-lib-auth';
|
import { NetlifyAuthenticator } from 'netlify-cms-lib-auth';
|
||||||
import { AuthenticationPage, Icon } from 'netlify-cms-ui-default';
|
import { AuthenticationPage, Icon } from 'netlify-cms-ui-default';
|
||||||
|
|
||||||
|
@ -19,23 +19,23 @@
|
|||||||
"build": "cross-env NODE_ENV=production webpack"
|
"build": "cross-env NODE_ENV=production webpack"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"js-base64": "^2.4.8",
|
"js-base64": "^2.5.1",
|
||||||
"semaphore": "^1.1.0"
|
"semaphore": "^1.1.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"cross-env": "^5.2.0",
|
"cross-env": "^5.2.0",
|
||||||
"webpack": "^4.16.1",
|
"webpack": "^4.29.6",
|
||||||
"webpack-cli": "^3.1.0"
|
"webpack-cli": "^3.2.3"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"emotion": "^9.2.6",
|
"@emotion/core": "^10.0.9",
|
||||||
|
"@emotion/styled": "^10.0.9",
|
||||||
"immutable": "^3.7.6",
|
"immutable": "^3.7.6",
|
||||||
"lodash": "^4.17.10",
|
"lodash": "^4.17.10",
|
||||||
"netlify-cms-lib-auth": "^2.0.0",
|
"netlify-cms-lib-auth": "^2.0.0",
|
||||||
"netlify-cms-lib-util": "^2.0.0",
|
"netlify-cms-lib-util": "^2.0.0",
|
||||||
"netlify-cms-ui-default": "^2.0.0",
|
"netlify-cms-ui-default": "^2.0.0",
|
||||||
"prop-types": "^15.6.2",
|
"prop-types": "^15.6.2",
|
||||||
"react": "^16.4.1",
|
"react": "^16.4.1"
|
||||||
"react-emotion": "^9.2.6"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -129,14 +129,13 @@ export default class API {
|
|||||||
.update(list => Map(list));
|
.update(list => Map(list));
|
||||||
const actions = links
|
const actions = links
|
||||||
.keySeq()
|
.keySeq()
|
||||||
.flatMap(
|
.flatMap(key =>
|
||||||
key =>
|
(key === 'prev' && index > 0) ||
|
||||||
(key === 'prev' && index > 0) ||
|
(key === 'next' && index < pageCount) ||
|
||||||
(key === 'next' && index < pageCount) ||
|
(key === 'first' && index > 0) ||
|
||||||
(key === 'first' && index > 0) ||
|
(key === 'last' && index < pageCount)
|
||||||
(key === 'last' && index < pageCount)
|
? [key]
|
||||||
? [key]
|
: [],
|
||||||
: [],
|
|
||||||
);
|
);
|
||||||
return Cursor.create({
|
return Cursor.create({
|
||||||
actions,
|
actions,
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||||
import styled from 'react-emotion';
|
import styled from '@emotion/styled';
|
||||||
import { NetlifyAuthenticator, ImplicitAuthenticator } from 'netlify-cms-lib-auth';
|
import { NetlifyAuthenticator, ImplicitAuthenticator } from 'netlify-cms-lib-auth';
|
||||||
import { AuthenticationPage, Icon } from 'netlify-cms-ui-default';
|
import { AuthenticationPage, Icon } from 'netlify-cms-ui-default';
|
||||||
|
|
||||||
|
@ -22,18 +22,18 @@
|
|||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"cross-env": "^5.2.0",
|
"cross-env": "^5.2.0",
|
||||||
"webpack": "^4.16.1",
|
"webpack": "^4.29.6",
|
||||||
"webpack-cli": "^3.1.0"
|
"webpack-cli": "^3.2.3"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"emotion": "^9.2.6",
|
"@emotion/core": "^10.0.9",
|
||||||
|
"@emotion/styled": "^10.0.9",
|
||||||
"immutable": "^3.8.2",
|
"immutable": "^3.8.2",
|
||||||
"lodash": "^4.17.10",
|
"lodash": "^4.17.10",
|
||||||
"netlify-cms-lib-util": "^2.0.0",
|
"netlify-cms-lib-util": "^2.0.0",
|
||||||
"netlify-cms-ui-default": "^2.0.0",
|
"netlify-cms-ui-default": "^2.0.0",
|
||||||
"prop-types": "^15.6.2",
|
"prop-types": "^15.6.2",
|
||||||
"react": "^16.4.1",
|
"react": "^16.4.1",
|
||||||
"react-emotion": "^9.2.6",
|
|
||||||
"react-immutable-proptypes": "^2.1.0"
|
"react-immutable-proptypes": "^2.1.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||||
import styled from 'react-emotion';
|
import styled from '@emotion/styled';
|
||||||
import { Icon, buttons, shadows } from 'netlify-cms-ui-default';
|
import { Icon, buttons, shadows } from 'netlify-cms-ui-default';
|
||||||
|
|
||||||
const StyledAuthenticationPage = styled.section`
|
const StyledAuthenticationPage = styled.section`
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
import { attempt, isError, take } from 'lodash';
|
import { attempt, isError, take } from 'lodash';
|
||||||
import uuid from 'uuid/v4';
|
import uuid from 'uuid/v4';
|
||||||
import { EditorialWorkflowError } from 'netlify-cms-lib-util';
|
import { EditorialWorkflowError, Cursor, CURSOR_COMPATIBILITY_SYMBOL } from 'netlify-cms-lib-util';
|
||||||
import { Cursor, CURSOR_COMPATIBILITY_SYMBOL } from 'netlify-cms-lib-util';
|
|
||||||
import AuthenticationPage from './AuthenticationPage';
|
import AuthenticationPage from './AuthenticationPage';
|
||||||
|
|
||||||
window.repoFiles = window.repoFiles || {};
|
window.repoFiles = window.repoFiles || {};
|
||||||
|
@ -19,44 +19,44 @@
|
|||||||
],
|
],
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"ajv": "^6.4.0",
|
"@emotion/core": "^10.0.9",
|
||||||
"ajv-errors": "^1.0.0",
|
"@emotion/styled": "^10.0.9",
|
||||||
"copy-text-to-clipboard": "^1.0.4",
|
"ajv": "^6.10.0",
|
||||||
|
"ajv-errors": "^1.0.1",
|
||||||
|
"copy-text-to-clipboard": "^2.0.0",
|
||||||
"diacritics": "^1.3.0",
|
"diacritics": "^1.3.0",
|
||||||
"emotion": "^9.2.6",
|
|
||||||
"fuzzy": "^0.1.1",
|
"fuzzy": "^0.1.1",
|
||||||
"gotrue-js": "^0.9.15",
|
"gotrue-js": "^0.9.24",
|
||||||
"gray-matter": "^4.0.1",
|
"gray-matter": "^4.0.2",
|
||||||
"history": "^4.7.2",
|
"history": "^4.7.2",
|
||||||
"immutable": "^3.7.6",
|
"immutable": "^3.7.6",
|
||||||
"js-base64": "^2.1.9",
|
"js-base64": "^2.5.1",
|
||||||
"js-yaml": "^3.10.0",
|
"js-yaml": "^3.12.2",
|
||||||
"jwt-decode": "^2.1.0",
|
"jwt-decode": "^2.1.0",
|
||||||
"lodash": "^4.17.10",
|
"lodash": "^4.17.11",
|
||||||
"moment": "^2.11.2",
|
"moment": "^2.24.0",
|
||||||
"netlify-cms-editor-component-image": "^2.2.0",
|
"netlify-cms-editor-component-image": "^2.2.0",
|
||||||
"netlify-cms-lib-auth": "^2.0.5",
|
"netlify-cms-lib-auth": "^2.0.5",
|
||||||
"netlify-cms-lib-util": "^2.1.2",
|
"netlify-cms-lib-util": "^2.1.2",
|
||||||
"netlify-cms-ui-default": "^2.4.1-alpha.0",
|
"netlify-cms-ui-default": "^2.4.1-alpha.0",
|
||||||
"node-polyglot": "^2.3.0",
|
"node-polyglot": "^2.3.0",
|
||||||
"prop-types": "^15.5.10",
|
"prop-types": "^15.7.2",
|
||||||
"react": "^16.8.1",
|
"react": "^16.8.4",
|
||||||
"react-dnd": "^7.0.0",
|
"react-dnd": "^7.3.2",
|
||||||
"react-dnd-html5-backend": "^7.0.0",
|
"react-dnd-html5-backend": "^7.2.0",
|
||||||
"react-dom": "^16.8.1",
|
"react-dom": "^16.8.4",
|
||||||
"react-emotion": "^9.2.5",
|
"react-frame-component": "^4.1.0",
|
||||||
"react-frame-component": "^4.0.2",
|
"react-hot-loader": "^4.8.0",
|
||||||
"react-hot-loader": "^4.0.0",
|
|
||||||
"react-immutable-proptypes": "^2.1.0",
|
"react-immutable-proptypes": "^2.1.0",
|
||||||
"react-is": "16.3.1",
|
"react-is": "16.8.4",
|
||||||
"react-modal": "^3.1.5",
|
"react-modal": "^3.8.1",
|
||||||
"react-polyglot": "^0.2.6",
|
"react-polyglot": "^0.2.6",
|
||||||
"react-redux": "^5.1.1",
|
"react-redux": "^5.1.1",
|
||||||
"react-router-dom": "^4.2.2",
|
"react-router-dom": "^4.2.2",
|
||||||
"react-router-redux": "^5.0.0-alpha.8",
|
"react-router-redux": "^5.0.0-alpha.8",
|
||||||
"react-scroll-sync": "^0.6.0",
|
"react-scroll-sync": "^0.6.0",
|
||||||
"react-sortable-hoc": "^0.6.8",
|
"react-sortable-hoc": "^0.6.8",
|
||||||
"react-split-pane": "^0.1.82",
|
"react-split-pane": "^0.1.85",
|
||||||
"react-topbar-progress-indicator": "^2.0.0",
|
"react-topbar-progress-indicator": "^2.0.0",
|
||||||
"react-waypoint": "^8.1.0",
|
"react-waypoint": "^8.1.0",
|
||||||
"redux": "^4.0.1",
|
"redux": "^4.0.1",
|
||||||
@ -68,13 +68,13 @@
|
|||||||
"toml-j0.4": "^1.1.1",
|
"toml-j0.4": "^1.1.1",
|
||||||
"tomlify-j0.4": "^3.0.0-alpha.0",
|
"tomlify-j0.4": "^3.0.0-alpha.0",
|
||||||
"url": "^0.11.0",
|
"url": "^0.11.0",
|
||||||
"what-input": "^5.0.3"
|
"what-input": "^5.1.4"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"cross-env": "^5.2.0",
|
"cross-env": "^5.2.0",
|
||||||
"css-loader": "^1.0.0",
|
"css-loader": "^2.1.1",
|
||||||
"to-string-loader": "^1.1.5",
|
"to-string-loader": "^1.1.5",
|
||||||
"webpack": "^4.16.1",
|
"webpack": "^4.29.6",
|
||||||
"webpack-cli": "^3.1.0"
|
"webpack-cli": "^3.2.3"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,6 @@ import { Map } from 'immutable';
|
|||||||
import { stripIndent } from 'common-tags';
|
import { stripIndent } from 'common-tags';
|
||||||
import moment from 'moment';
|
import moment from 'moment';
|
||||||
import fuzzy from 'fuzzy';
|
import fuzzy from 'fuzzy';
|
||||||
import { localForage } from 'netlify-cms-lib-util';
|
|
||||||
import { resolveFormat } from 'Formats/formats';
|
import { resolveFormat } from 'Formats/formats';
|
||||||
import { selectIntegration } from 'Reducers/integrations';
|
import { selectIntegration } from 'Reducers/integrations';
|
||||||
import {
|
import {
|
||||||
@ -19,7 +18,7 @@ import {
|
|||||||
import { createEntry } from 'ValueObjects/Entry';
|
import { createEntry } from 'ValueObjects/Entry';
|
||||||
import { sanitizeSlug } from 'Lib/urlHelper';
|
import { sanitizeSlug } from 'Lib/urlHelper';
|
||||||
import { getBackend } from 'Lib/registry';
|
import { getBackend } from 'Lib/registry';
|
||||||
import { Cursor, CURSOR_COMPATIBILITY_SYMBOL } from 'netlify-cms-lib-util';
|
import { localForage, Cursor, CURSOR_COMPATIBILITY_SYMBOL } from 'netlify-cms-lib-util';
|
||||||
import { EDITORIAL_WORKFLOW, status } from 'Constants/publishModes';
|
import { EDITORIAL_WORKFLOW, status } from 'Constants/publishModes';
|
||||||
|
|
||||||
class LocalStorageAuthStore {
|
class LocalStorageAuthStore {
|
||||||
|
22
packages/netlify-cms-core/src/bootstrap.js
vendored
22
packages/netlify-cms-core/src/bootstrap.js
vendored
@ -8,6 +8,7 @@ import store from 'Redux';
|
|||||||
import { mergeConfig } from 'Actions/config';
|
import { mergeConfig } from 'Actions/config';
|
||||||
import { getPhrases } from 'Constants/defaultPhrases';
|
import { getPhrases } from 'Constants/defaultPhrases';
|
||||||
import { I18n } from 'react-polyglot';
|
import { I18n } from 'react-polyglot';
|
||||||
|
import { GlobalStyles } from 'netlify-cms-ui-default';
|
||||||
import { ErrorBoundary } from 'UI';
|
import { ErrorBoundary } from 'UI';
|
||||||
import App from 'App/App';
|
import App from 'App/App';
|
||||||
import 'EditorWidgets';
|
import 'EditorWidgets';
|
||||||
@ -62,15 +63,18 @@ function bootstrap(opts = {}) {
|
|||||||
* Create connected root component.
|
* Create connected root component.
|
||||||
*/
|
*/
|
||||||
const Root = () => (
|
const Root = () => (
|
||||||
<I18n locale={'en'} messages={getPhrases()}>
|
<>
|
||||||
<ErrorBoundary showBackup>
|
<GlobalStyles />
|
||||||
<Provider store={store}>
|
<I18n locale={'en'} messages={getPhrases()}>
|
||||||
<ConnectedRouter history={history}>
|
<ErrorBoundary showBackup>
|
||||||
<Route component={App} />
|
<Provider store={store}>
|
||||||
</ConnectedRouter>
|
<ConnectedRouter history={history}>
|
||||||
</Provider>
|
<Route component={App} />
|
||||||
</ErrorBoundary>
|
</ConnectedRouter>
|
||||||
</I18n>
|
</Provider>
|
||||||
|
</ErrorBoundary>
|
||||||
|
</I18n>
|
||||||
|
</>
|
||||||
);
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -3,7 +3,7 @@ import React from 'react';
|
|||||||
import { hot } from 'react-hot-loader';
|
import { hot } from 'react-hot-loader';
|
||||||
import { translate } from 'react-polyglot';
|
import { translate } from 'react-polyglot';
|
||||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||||
import styled from 'react-emotion';
|
import styled from '@emotion/styled';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { Route, Switch, Redirect } from 'react-router-dom';
|
import { Route, Switch, Redirect } from 'react-router-dom';
|
||||||
import { Notifs } from 'redux-notifications';
|
import { Notifs } from 'redux-notifications';
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
|
/** @jsx jsx */
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||||
import styled, { css } from 'react-emotion';
|
import styled from '@emotion/styled';
|
||||||
|
import { jsx, css } from '@emotion/core';
|
||||||
import { translate } from 'react-polyglot';
|
import { translate } from 'react-polyglot';
|
||||||
import { NavLink } from 'react-router-dom';
|
import { NavLink } from 'react-router-dom';
|
||||||
import {
|
import {
|
||||||
@ -22,15 +24,20 @@ const styles = {
|
|||||||
`,
|
`,
|
||||||
};
|
};
|
||||||
|
|
||||||
const AppHeader = styled.header`
|
const AppHeader = props => (
|
||||||
${shadows.dropMain};
|
<header
|
||||||
position: sticky;
|
css={css`
|
||||||
width: 100%;
|
${shadows.dropMain};
|
||||||
top: 0;
|
position: sticky;
|
||||||
background-color: ${colors.foreground};
|
width: 100%;
|
||||||
z-index: 300;
|
top: 0;
|
||||||
height: ${lengths.topBarHeight};
|
background-color: ${colors.foreground};
|
||||||
`;
|
z-index: 300;
|
||||||
|
height: ${lengths.topBarHeight};
|
||||||
|
`}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
|
||||||
const AppHeaderContent = styled.div`
|
const AppHeaderContent = styled.div`
|
||||||
display: flex;
|
display: flex;
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import styled from 'react-emotion';
|
import styled from '@emotion/styled';
|
||||||
import { translate } from 'react-polyglot';
|
import { translate } from 'react-polyglot';
|
||||||
import { lengths } from 'netlify-cms-ui-default';
|
import { lengths } from 'netlify-cms-ui-default';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||||
import styled from 'react-emotion';
|
import styled from '@emotion/styled';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { lengths } from 'netlify-cms-ui-default';
|
import { lengths } from 'netlify-cms-ui-default';
|
||||||
import { getNewEntryUrl } from 'Lib/urlHelper';
|
import { getNewEntryUrl } from 'Lib/urlHelper';
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import styled from 'react-emotion';
|
import styled from '@emotion/styled';
|
||||||
import { translate } from 'react-polyglot';
|
import { translate } from 'react-polyglot';
|
||||||
import { Link } from 'react-router-dom';
|
import { Link } from 'react-router-dom';
|
||||||
import { Icon, components, buttons, shadows, colors } from 'netlify-cms-ui-default';
|
import { Icon, components, buttons, shadows, colors } from 'netlify-cms-ui-default';
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import styled from 'react-emotion';
|
import styled from '@emotion/styled';
|
||||||
import { Link } from 'react-router-dom';
|
import { Link } from 'react-router-dom';
|
||||||
import { resolvePath } from 'netlify-cms-lib-util';
|
import { resolvePath } from 'netlify-cms-lib-util';
|
||||||
import { colors, colorsRaw, components, lengths } from 'netlify-cms-ui-default';
|
import { colors, colorsRaw, components, lengths } from 'netlify-cms-ui-default';
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||||
import styled from 'react-emotion';
|
import styled from '@emotion/styled';
|
||||||
import Waypoint from 'react-waypoint';
|
import Waypoint from 'react-waypoint';
|
||||||
import { Map } from 'immutable';
|
import { Map } from 'immutable';
|
||||||
import { Cursor } from 'netlify-cms-lib-util';
|
import { Cursor } from 'netlify-cms-lib-util';
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||||
import styled, { css } from 'react-emotion';
|
import styled from '@emotion/styled';
|
||||||
|
import { css } from '@emotion/core';
|
||||||
import { translate } from 'react-polyglot';
|
import { translate } from 'react-polyglot';
|
||||||
import { NavLink } from 'react-router-dom';
|
import { NavLink } from 'react-router-dom';
|
||||||
import { Icon, components, colors, colorsRaw, lengths } from 'netlify-cms-ui-default';
|
import { Icon, components, colors, colorsRaw, lengths } from 'netlify-cms-ui-default';
|
||||||
|
@ -31,8 +31,7 @@ import { loadDeployPreview } from 'Actions/deploys';
|
|||||||
import { deserializeValues } from 'Lib/serializeEntryValues';
|
import { deserializeValues } from 'Lib/serializeEntryValues';
|
||||||
import { selectEntry, selectUnpublishedEntry, selectDeployPreview, getAsset } from 'Reducers';
|
import { selectEntry, selectUnpublishedEntry, selectDeployPreview, getAsset } from 'Reducers';
|
||||||
import { selectFields } from 'Reducers/collections';
|
import { selectFields } from 'Reducers/collections';
|
||||||
import { status } from 'Constants/publishModes';
|
import { status, EDITORIAL_WORKFLOW } from 'Constants/publishModes';
|
||||||
import { EDITORIAL_WORKFLOW } from 'Constants/publishModes';
|
|
||||||
import EditorInterface from './EditorInterface';
|
import EditorInterface from './EditorInterface';
|
||||||
import withWorkflow from './withWorkflow';
|
import withWorkflow from './withWorkflow';
|
||||||
|
|
||||||
|
@ -1,16 +1,17 @@
|
|||||||
|
/** @jsx jsx */
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||||
import { translate } from 'react-polyglot';
|
import { translate } from 'react-polyglot';
|
||||||
import styled, { css, cx } from 'react-emotion';
|
import { jsx, ClassNames, Global, css as coreCss } from '@emotion/core';
|
||||||
|
import styled from '@emotion/styled';
|
||||||
import { partial, uniqueId } from 'lodash';
|
import { partial, uniqueId } from 'lodash';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { colors, colorsRaw, transitions, lengths, borders } from 'netlify-cms-ui-default';
|
import { colors, colorsRaw, transitions, lengths, borders } from 'netlify-cms-ui-default';
|
||||||
import { resolveWidget, getEditorComponents } from 'Lib/registry';
|
import { resolveWidget, getEditorComponents } from 'Lib/registry';
|
||||||
import { clearFieldErrors } from 'Actions/entries';
|
import { clearFieldErrors, loadEntry } from 'Actions/entries';
|
||||||
import { addAsset } from 'Actions/media';
|
import { addAsset } from 'Actions/media';
|
||||||
import { query, clearSearch } from 'Actions/search';
|
import { query, clearSearch } from 'Actions/search';
|
||||||
import { loadEntry } from 'Actions/entries';
|
|
||||||
import {
|
import {
|
||||||
openMediaLibrary,
|
openMediaLibrary,
|
||||||
removeInsertedMedia,
|
removeInsertedMedia,
|
||||||
@ -20,8 +21,13 @@ import {
|
|||||||
import { getAsset } from 'Reducers';
|
import { getAsset } from 'Reducers';
|
||||||
import Widget from './Widget';
|
import Widget from './Widget';
|
||||||
|
|
||||||
const styles = {
|
/**
|
||||||
label: css`
|
* This is a necessary bridge as we are still passing classnames to widgets
|
||||||
|
* for styling. Once that changes we can stop storing raw style strings like
|
||||||
|
* this.
|
||||||
|
*/
|
||||||
|
const styleStrings = {
|
||||||
|
label: `
|
||||||
color: ${colors.controlLabel};
|
color: ${colors.controlLabel};
|
||||||
background-color: ${colors.textFieldBorder};
|
background-color: ${colors.textFieldBorder};
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
@ -55,15 +61,15 @@ const styles = {
|
|||||||
background-color: #fff;
|
background-color: #fff;
|
||||||
}
|
}
|
||||||
`,
|
`,
|
||||||
labelActive: css`
|
labelActive: `
|
||||||
background-color: ${colors.active};
|
background-color: ${colors.active};
|
||||||
color: ${colors.textLight};
|
color: ${colors.textLight};
|
||||||
`,
|
`,
|
||||||
labelError: css`
|
labelError: `
|
||||||
background-color: ${colors.errorText};
|
background-color: ${colors.errorText};
|
||||||
color: ${colorsRaw.white};
|
color: ${colorsRaw.white};
|
||||||
`,
|
`,
|
||||||
widget: css`
|
widget: `
|
||||||
display: block;
|
display: block;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
padding: ${lengths.inputPadding};
|
padding: ${lengths.inputPadding};
|
||||||
@ -85,10 +91,10 @@ const styles = {
|
|||||||
height: 58px;
|
height: 58px;
|
||||||
}
|
}
|
||||||
`,
|
`,
|
||||||
widgetActive: css`
|
widgetActive: `
|
||||||
border-color: ${colors.active};
|
border-color: ${colors.active};
|
||||||
`,
|
`,
|
||||||
widgetError: css`
|
widgetError: `
|
||||||
border-color: ${colors.errorText};
|
border-color: ${colors.errorText};
|
||||||
`,
|
`,
|
||||||
};
|
};
|
||||||
@ -96,7 +102,7 @@ const styles = {
|
|||||||
const ControlContainer = styled.div`
|
const ControlContainer = styled.div`
|
||||||
margin-top: 16px;
|
margin-top: 16px;
|
||||||
|
|
||||||
&:first-child {
|
&:first-of-type {
|
||||||
margin-top: 36px;
|
margin-top: 36px;
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
@ -117,8 +123,8 @@ export const ControlHint = styled.p`
|
|||||||
margin-bottom: 0;
|
margin-bottom: 0;
|
||||||
padding: 3px 0;
|
padding: 3px 0;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
color: ${({ active, error }) =>
|
color: ${props =>
|
||||||
error ? colors.errorText : active ? colors.active : colors.controlLabel};
|
props.error ? colors.errorText : props.active ? colors.active : colors.controlLabel};
|
||||||
transition: color ${transitions.main};
|
transition: color ${transitions.main};
|
||||||
`;
|
`;
|
||||||
|
|
||||||
@ -191,75 +197,108 @@ class EditorControl extends React.Component {
|
|||||||
const metadata = fieldsMetaData && fieldsMetaData.get(fieldName);
|
const metadata = fieldsMetaData && fieldsMetaData.get(fieldName);
|
||||||
const errors = fieldsErrors && fieldsErrors.get(this.uniqueFieldId);
|
const errors = fieldsErrors && fieldsErrors.get(this.uniqueFieldId);
|
||||||
return (
|
return (
|
||||||
<ControlContainer>
|
<ClassNames>
|
||||||
<ControlErrorsList>
|
{({ css, cx }) => (
|
||||||
{errors &&
|
<ControlContainer>
|
||||||
errors.map(
|
{widget.globalStyles && <Global styles={coreCss`${widget.globalStyles}`} />}
|
||||||
error =>
|
<ControlErrorsList>
|
||||||
error.message &&
|
{errors &&
|
||||||
typeof error.message === 'string' && (
|
errors.map(
|
||||||
<li key={error.message.trim().replace(/[^a-z0-9]+/gi, '-')}>{error.message}</li>
|
error =>
|
||||||
),
|
error.message &&
|
||||||
|
typeof error.message === 'string' && (
|
||||||
|
<li key={error.message.trim().replace(/[^a-z0-9]+/gi, '-')}>
|
||||||
|
{error.message}
|
||||||
|
</li>
|
||||||
|
),
|
||||||
|
)}
|
||||||
|
</ControlErrorsList>
|
||||||
|
<label
|
||||||
|
className={cx(
|
||||||
|
css`
|
||||||
|
${styleStrings.label};
|
||||||
|
`,
|
||||||
|
this.state.styleActive &&
|
||||||
|
css`
|
||||||
|
${styleStrings.labelActive};
|
||||||
|
`,
|
||||||
|
!!errors &&
|
||||||
|
css`
|
||||||
|
${styleStrings.labelError};
|
||||||
|
`,
|
||||||
|
)}
|
||||||
|
htmlFor={this.uniqueFieldId}
|
||||||
|
>
|
||||||
|
{`${field.get('label', field.get('name'))}${isFieldOptional ? ' (optional)' : ''}`}
|
||||||
|
</label>
|
||||||
|
<Widget
|
||||||
|
classNameWrapper={cx(
|
||||||
|
css`
|
||||||
|
${styleStrings.widget};
|
||||||
|
`,
|
||||||
|
{
|
||||||
|
[css`
|
||||||
|
${styleStrings.widgetActive};
|
||||||
|
`]: this.state.styleActive,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
[css`
|
||||||
|
${styleStrings.widgetError};
|
||||||
|
`]: !!errors,
|
||||||
|
},
|
||||||
|
)}
|
||||||
|
classNameWidget={css`
|
||||||
|
${styleStrings.widget};
|
||||||
|
`}
|
||||||
|
classNameWidgetActive={css`
|
||||||
|
${styleStrings.widgetActive};
|
||||||
|
`}
|
||||||
|
classNameLabel={css`
|
||||||
|
${styleStrings.label};
|
||||||
|
`}
|
||||||
|
classNameLabelActive={css`
|
||||||
|
${styleStrings.labelActive};
|
||||||
|
`}
|
||||||
|
controlComponent={widget.control}
|
||||||
|
field={field}
|
||||||
|
uniqueFieldId={this.uniqueFieldId}
|
||||||
|
value={value}
|
||||||
|
mediaPaths={mediaPaths}
|
||||||
|
metadata={metadata}
|
||||||
|
onChange={(newValue, newMetadata) => onChange(fieldName, newValue, newMetadata)}
|
||||||
|
onValidate={onValidate && partial(onValidate, this.uniqueFieldId)}
|
||||||
|
onOpenMediaLibrary={openMediaLibrary}
|
||||||
|
onClearMediaControl={clearMediaControl}
|
||||||
|
onRemoveMediaControl={removeMediaControl}
|
||||||
|
onRemoveInsertedMedia={removeInsertedMedia}
|
||||||
|
onAddAsset={addAsset}
|
||||||
|
getAsset={boundGetAsset}
|
||||||
|
hasActiveStyle={this.state.styleActive}
|
||||||
|
setActiveStyle={() => this.setState({ styleActive: true })}
|
||||||
|
setInactiveStyle={() => this.setState({ styleActive: false })}
|
||||||
|
resolveWidget={resolveWidget}
|
||||||
|
getEditorComponents={getEditorComponents}
|
||||||
|
ref={processControlRef && partial(processControlRef, field)}
|
||||||
|
controlRef={controlRef}
|
||||||
|
editorControl={ConnectedEditorControl}
|
||||||
|
query={query}
|
||||||
|
loadEntry={loadEntry}
|
||||||
|
queryHits={queryHits}
|
||||||
|
clearSearch={clearSearch}
|
||||||
|
clearFieldErrors={clearFieldErrors}
|
||||||
|
isFetching={isFetching}
|
||||||
|
fieldsErrors={fieldsErrors}
|
||||||
|
onValidateObject={onValidateObject}
|
||||||
|
t={t}
|
||||||
|
/>
|
||||||
|
{fieldHint && (
|
||||||
|
<ControlHint active={this.state.styleActive} error={!!errors}>
|
||||||
|
{fieldHint}
|
||||||
|
</ControlHint>
|
||||||
)}
|
)}
|
||||||
</ControlErrorsList>
|
</ControlContainer>
|
||||||
<label
|
|
||||||
className={cx(
|
|
||||||
styles.label,
|
|
||||||
{ [styles.labelActive]: this.state.styleActive },
|
|
||||||
{ [styles.labelError]: !!errors },
|
|
||||||
)}
|
|
||||||
htmlFor={this.uniqueFieldId}
|
|
||||||
>
|
|
||||||
{`${field.get('label', field.get('name'))}${isFieldOptional ? ' (optional)' : ''}`}
|
|
||||||
</label>
|
|
||||||
<Widget
|
|
||||||
classNameWrapper={cx(
|
|
||||||
styles.widget,
|
|
||||||
{ [styles.widgetActive]: this.state.styleActive },
|
|
||||||
{ [styles.widgetError]: !!errors },
|
|
||||||
)}
|
|
||||||
classNameWidget={styles.widget}
|
|
||||||
classNameWidgetActive={styles.widgetActive}
|
|
||||||
classNameLabel={styles.label}
|
|
||||||
classNameLabelActive={styles.labelActive}
|
|
||||||
controlComponent={widget.control}
|
|
||||||
field={field}
|
|
||||||
uniqueFieldId={this.uniqueFieldId}
|
|
||||||
value={value}
|
|
||||||
mediaPaths={mediaPaths}
|
|
||||||
metadata={metadata}
|
|
||||||
onChange={(newValue, newMetadata) => onChange(fieldName, newValue, newMetadata)}
|
|
||||||
onValidate={onValidate && partial(onValidate, this.uniqueFieldId)}
|
|
||||||
onOpenMediaLibrary={openMediaLibrary}
|
|
||||||
onClearMediaControl={clearMediaControl}
|
|
||||||
onRemoveMediaControl={removeMediaControl}
|
|
||||||
onRemoveInsertedMedia={removeInsertedMedia}
|
|
||||||
onAddAsset={addAsset}
|
|
||||||
getAsset={boundGetAsset}
|
|
||||||
hasActiveStyle={this.state.styleActive}
|
|
||||||
setActiveStyle={() => this.setState({ styleActive: true })}
|
|
||||||
setInactiveStyle={() => this.setState({ styleActive: false })}
|
|
||||||
resolveWidget={resolveWidget}
|
|
||||||
getEditorComponents={getEditorComponents}
|
|
||||||
ref={processControlRef && partial(processControlRef, field)}
|
|
||||||
controlRef={controlRef}
|
|
||||||
editorControl={ConnectedEditorControl}
|
|
||||||
query={query}
|
|
||||||
loadEntry={loadEntry}
|
|
||||||
queryHits={queryHits}
|
|
||||||
clearSearch={clearSearch}
|
|
||||||
clearFieldErrors={clearFieldErrors}
|
|
||||||
isFetching={isFetching}
|
|
||||||
fieldsErrors={fieldsErrors}
|
|
||||||
onValidateObject={onValidateObject}
|
|
||||||
t={t}
|
|
||||||
/>
|
|
||||||
{fieldHint && (
|
|
||||||
<ControlHint active={this.state.styleActive} error={!!errors}>
|
|
||||||
{fieldHint}
|
|
||||||
</ControlHint>
|
|
||||||
)}
|
)}
|
||||||
</ControlContainer>
|
</ClassNames>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,17 +1,14 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||||
import styled from 'react-emotion';
|
import styled from '@emotion/styled';
|
||||||
import EditorControl, { ControlHint } from './EditorControl';
|
import EditorControl from './EditorControl';
|
||||||
|
|
||||||
const ControlPaneContainer = styled.div`
|
const ControlPaneContainer = styled.div`
|
||||||
max-width: 800px;
|
max-width: 800px;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
padding-bottom: 16px;
|
padding-bottom: 16px;
|
||||||
|
font-size: 16px;
|
||||||
p:not(${ControlHint}) {
|
|
||||||
font-size: 16px;
|
|
||||||
}
|
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export default class ControlPane extends React.Component {
|
export default class ControlPane extends React.Component {
|
||||||
@ -56,21 +53,20 @@ export default class ControlPane extends React.Component {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<ControlPaneContainer>
|
<ControlPaneContainer>
|
||||||
{fields.map(
|
{fields.map((field, i) =>
|
||||||
(field, i) =>
|
field.get('widget') === 'hidden' ? null : (
|
||||||
field.get('widget') === 'hidden' ? null : (
|
<EditorControl
|
||||||
<EditorControl
|
key={i}
|
||||||
key={i}
|
field={field}
|
||||||
field={field}
|
value={entry.getIn(['data', field.get('name')])}
|
||||||
value={entry.getIn(['data', field.get('name')])}
|
fieldsMetaData={fieldsMetaData}
|
||||||
fieldsMetaData={fieldsMetaData}
|
fieldsErrors={fieldsErrors}
|
||||||
fieldsErrors={fieldsErrors}
|
onChange={onChange}
|
||||||
onChange={onChange}
|
onValidate={onValidate}
|
||||||
onValidate={onValidate}
|
processControlRef={this.controlRef.bind(this)}
|
||||||
processControlRef={this.controlRef.bind(this)}
|
controlRef={this.controlRef}
|
||||||
controlRef={this.controlRef}
|
/>
|
||||||
/>
|
),
|
||||||
),
|
|
||||||
)}
|
)}
|
||||||
</ControlPaneContainer>
|
</ControlPaneContainer>
|
||||||
);
|
);
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||||
import styled, { css, injectGlobal } from 'react-emotion';
|
import { css, Global } from '@emotion/core';
|
||||||
|
import styled from '@emotion/styled';
|
||||||
import SplitPane from 'react-split-pane';
|
import SplitPane from 'react-split-pane';
|
||||||
import { colors, colorsRaw, components, transitions } from 'netlify-cms-ui-default';
|
import { colors, colorsRaw, components, transitions } from 'netlify-cms-ui-default';
|
||||||
import { ScrollSync, ScrollSyncPane } from 'react-scroll-sync';
|
import { ScrollSync, ScrollSyncPane } from 'react-scroll-sync';
|
||||||
@ -25,33 +26,33 @@ const styles = {
|
|||||||
`,
|
`,
|
||||||
};
|
};
|
||||||
|
|
||||||
injectGlobal`
|
const ReactSplitPaneGlobalStyles = () => (
|
||||||
/**
|
<Global
|
||||||
* React Split Pane
|
styles={css`
|
||||||
*/
|
.Resizer.vertical {
|
||||||
.Resizer.vertical {
|
width: 21px;
|
||||||
width: 21px;
|
cursor: col-resize;
|
||||||
cursor: col-resize;
|
position: relative;
|
||||||
position: relative;
|
transition: background-color ${transitions.main};
|
||||||
transition: background-color ${transitions.main};
|
|
||||||
|
|
||||||
&:before {
|
&:before {
|
||||||
content: '';
|
content: '';
|
||||||
width: 1px;
|
width: 1px;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
position: relative;
|
position: relative;
|
||||||
left: 10px;
|
left: 10px;
|
||||||
background-color: ${colors.textFieldBorder};
|
background-color: ${colors.textFieldBorder};
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
|
|
||||||
&:hover,
|
&:hover,
|
||||||
&:active {
|
&:active {
|
||||||
background-color: ${colorsRaw.GrayLight};
|
background-color: ${colorsRaw.GrayLight};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
`}
|
||||||
`;
|
/>
|
||||||
|
);
|
||||||
|
|
||||||
const StyledSplitPane = styled(SplitPane)`
|
const StyledSplitPane = styled(SplitPane)`
|
||||||
${styles.splitPane};
|
${styles.splitPane};
|
||||||
@ -195,6 +196,7 @@ class EditorInterface extends Component {
|
|||||||
const editorWithPreview = (
|
const editorWithPreview = (
|
||||||
<ScrollSync enabled={this.state.scrollSyncEnabled}>
|
<ScrollSync enabled={this.state.scrollSyncEnabled}>
|
||||||
<div>
|
<div>
|
||||||
|
<ReactSplitPaneGlobalStyles />
|
||||||
<StyledSplitPane
|
<StyledSplitPane
|
||||||
maxSize={-100}
|
maxSize={-100}
|
||||||
defaultSize="50%"
|
defaultSize="50%"
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||||
import styled from 'react-emotion';
|
import styled from '@emotion/styled';
|
||||||
|
|
||||||
function isVisible(field) {
|
function isVisible(field) {
|
||||||
return field.get('widget') !== 'hidden';
|
return field.get('widget') !== 'hidden';
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import styled from 'react-emotion';
|
import styled from '@emotion/styled';
|
||||||
import { List, Map } from 'immutable';
|
import { List, Map } from 'immutable';
|
||||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||||
import Frame from 'react-frame-component';
|
import Frame from 'react-frame-component';
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import styled from 'react-emotion';
|
import styled from '@emotion/styled';
|
||||||
import { Icon, colors, colorsRaw, shadows, buttons } from 'netlify-cms-ui-default';
|
import { Icon, colors, colorsRaw, shadows, buttons } from 'netlify-cms-ui-default';
|
||||||
|
|
||||||
const EditorToggleButton = styled.button`
|
const EditorToggleButton = styled.button`
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||||
import styled, { css } from 'react-emotion';
|
import { css } from '@emotion/core';
|
||||||
|
import styled from '@emotion/styled';
|
||||||
import { translate } from 'react-polyglot';
|
import { translate } from 'react-polyglot';
|
||||||
import { Map } from 'immutable';
|
import { Map } from 'immutable';
|
||||||
import { Link } from 'react-router-dom';
|
import { Link } from 'react-router-dom';
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import styled from 'react-emotion';
|
import styled from '@emotion/styled';
|
||||||
import { colors } from 'netlify-cms-ui-default';
|
import { colors } from 'netlify-cms-ui-default';
|
||||||
|
|
||||||
const EmptyMessageContainer = styled.div`
|
const EmptyMessageContainer = styled.div`
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import styled, { css } from 'react-emotion';
|
import { css } from '@emotion/core';
|
||||||
|
import styled from '@emotion/styled';
|
||||||
import { FileUploadButton } from 'UI';
|
import { FileUploadButton } from 'UI';
|
||||||
import { buttons, shadows } from 'netlify-cms-ui-default';
|
import { buttons, shadows } from 'netlify-cms-ui-default';
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||||
import styled from 'react-emotion';
|
import styled from '@emotion/styled';
|
||||||
import { colors, borders, lengths, shadows, effects } from 'netlify-cms-ui-default';
|
import { colors, borders, lengths, shadows, effects } from 'netlify-cms-ui-default';
|
||||||
|
|
||||||
const IMAGE_HEIGHT = 160;
|
const IMAGE_HEIGHT = 160;
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import styled from 'react-emotion';
|
import styled from '@emotion/styled';
|
||||||
import Waypoint from 'react-waypoint';
|
import Waypoint from 'react-waypoint';
|
||||||
import MediaLibraryCard from './MediaLibraryCard';
|
import MediaLibraryCard from './MediaLibraryCard';
|
||||||
import { Map } from 'immutable';
|
import { Map } from 'immutable';
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import styled from 'react-emotion';
|
import styled from '@emotion/styled';
|
||||||
import { Icon, shadows, colors, buttons } from 'netlify-cms-ui-default';
|
import { Icon, shadows, colors, buttons } from 'netlify-cms-ui-default';
|
||||||
|
|
||||||
const CloseButton = styled.button`
|
const CloseButton = styled.button`
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import styled from 'react-emotion';
|
import styled from '@emotion/styled';
|
||||||
import { isEmpty } from 'lodash';
|
import { isEmpty } from 'lodash';
|
||||||
import { translate } from 'react-polyglot';
|
import { translate } from 'react-polyglot';
|
||||||
import { Modal } from 'UI';
|
import { Modal } from 'UI';
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import styled from 'react-emotion';
|
import styled from '@emotion/styled';
|
||||||
import { Icon, lengths, colors } from 'netlify-cms-ui-default';
|
import { Icon, lengths, colors } from 'netlify-cms-ui-default';
|
||||||
|
|
||||||
const SearchContainer = styled.div`
|
const SearchContainer = styled.div`
|
||||||
|
@ -1,42 +1,42 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { translate } from 'react-polyglot';
|
import { translate } from 'react-polyglot';
|
||||||
import styled, { css } from 'react-emotion';
|
import styled from '@emotion/styled';
|
||||||
import copyToClipboard from 'copy-text-to-clipboard';
|
import copyToClipboard from 'copy-text-to-clipboard';
|
||||||
import { localForage } from 'netlify-cms-lib-util';
|
import { localForage } from 'netlify-cms-lib-util';
|
||||||
import { buttons, colors } from 'netlify-cms-ui-default';
|
import { buttons, colors } from 'netlify-cms-ui-default';
|
||||||
|
|
||||||
const ISSUE_URL = 'https://github.com/netlify/netlify-cms/issues/new?template=bug_report.md';
|
const ISSUE_URL = 'https://github.com/netlify/netlify-cms/issues/new?template=bug_report.md';
|
||||||
|
|
||||||
const styles = {
|
const ErrorBoundaryContainer = styled.div`
|
||||||
errorBoundary: css`
|
padding: 40px;
|
||||||
padding: 40px;
|
|
||||||
|
|
||||||
h1 {
|
h1 {
|
||||||
font-size: 28px;
|
font-size: 28px;
|
||||||
}
|
color: ${colors.text};
|
||||||
|
}
|
||||||
|
|
||||||
h2 {
|
h2 {
|
||||||
font-size: 20px;
|
font-size: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
strong {
|
strong {
|
||||||
color: ${colors.textLead};
|
color: ${colors.textLead};
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
}
|
}
|
||||||
|
|
||||||
hr {
|
hr {
|
||||||
width: 200px;
|
width: 200px;
|
||||||
margin: 30px 0;
|
margin: 30px 0;
|
||||||
border: 0;
|
border: 0;
|
||||||
height: 1px;
|
height: 1px;
|
||||||
background-color: ${colors.text};
|
background-color: ${colors.text};
|
||||||
}
|
}
|
||||||
`,
|
|
||||||
errorText: css`
|
a {
|
||||||
color: ${colors.errorText};
|
color: ${colors.text};
|
||||||
`,
|
}
|
||||||
};
|
`;
|
||||||
|
|
||||||
const CopyButton = styled.button`
|
const CopyButton = styled.button`
|
||||||
${buttons.button};
|
${buttons.button};
|
||||||
@ -104,16 +104,11 @@ class ErrorBoundary extends React.Component {
|
|||||||
return this.props.children;
|
return this.props.children;
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<div className={styles.errorBoundary}>
|
<ErrorBoundaryContainer>
|
||||||
<h1 className={styles.errorBoundaryText}>{t('ui.errorBoundary.title')}</h1>
|
<h1>{t('ui.errorBoundary.title')}</h1>
|
||||||
<p>
|
<p>
|
||||||
<span>{t('ui.errorBoundary.details')}</span>
|
<span>{t('ui.errorBoundary.details')}</span>
|
||||||
<a
|
<a href={ISSUE_URL} target="_blank" rel="noopener noreferrer">
|
||||||
href={ISSUE_URL}
|
|
||||||
target="_blank"
|
|
||||||
rel="noopener noreferrer"
|
|
||||||
className={styles.errorBoundaryText}
|
|
||||||
>
|
|
||||||
{t('ui.errorBoundary.reportIt')}
|
{t('ui.errorBoundary.reportIt')}
|
||||||
</a>
|
</a>
|
||||||
</p>
|
</p>
|
||||||
@ -121,7 +116,7 @@ class ErrorBoundary extends React.Component {
|
|||||||
<h2>{t('ui.errorBoundary.detailsHeading')}</h2>
|
<h2>{t('ui.errorBoundary.detailsHeading')}</h2>
|
||||||
<p>{errorMessage}</p>
|
<p>{errorMessage}</p>
|
||||||
{backup && showBackup && <RecoveredEntry entry={backup} t={t} />}
|
{backup && showBackup && <RecoveredEntry entry={backup} t={t} />}
|
||||||
</div>
|
</ErrorBoundaryContainer>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,17 +1,21 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { css, cx, injectGlobal } from 'react-emotion';
|
import { css, Global, ClassNames } from '@emotion/core';
|
||||||
import ReactModal from 'react-modal';
|
import ReactModal from 'react-modal';
|
||||||
import { transitions, shadows, lengths } from 'netlify-cms-ui-default';
|
import { transitions, shadows, lengths } from 'netlify-cms-ui-default';
|
||||||
|
|
||||||
injectGlobal`
|
const ReactModalGlobalStyles = () => (
|
||||||
.ReactModal__Body--open {
|
<Global
|
||||||
overflow: hidden;
|
styles={css`
|
||||||
}
|
.ReactModal__Body--open {
|
||||||
`;
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
`}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
|
||||||
const styles = {
|
const styleStrings = {
|
||||||
modalBody: css`
|
modalBody: `
|
||||||
${shadows.dropDeep};
|
${shadows.dropDeep};
|
||||||
background-color: #fff;
|
background-color: #fff;
|
||||||
border-radius: ${lengths.borderRadius};
|
border-radius: ${lengths.borderRadius};
|
||||||
@ -24,7 +28,7 @@ const styles = {
|
|||||||
outline: none;
|
outline: none;
|
||||||
}
|
}
|
||||||
`,
|
`,
|
||||||
overlay: css`
|
overlay: `
|
||||||
z-index: 99999;
|
z-index: 99999;
|
||||||
position: fixed;
|
position: fixed;
|
||||||
top: 0;
|
top: 0;
|
||||||
@ -38,11 +42,11 @@ const styles = {
|
|||||||
background-color: rgba(0, 0, 0, 0);
|
background-color: rgba(0, 0, 0, 0);
|
||||||
transition: background-color ${transitions.main}, opacity ${transitions.main};
|
transition: background-color ${transitions.main}, opacity ${transitions.main};
|
||||||
`,
|
`,
|
||||||
overlayAfterOpen: css`
|
overlayAfterOpen: `
|
||||||
background-color: rgba(0, 0, 0, 0.6);
|
background-color: rgba(0, 0, 0, 0.6);
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
`,
|
`,
|
||||||
overlayBeforeClose: css`
|
overlayBeforeClose: `
|
||||||
background-color: rgba(0, 0, 0, 0);
|
background-color: rgba(0, 0, 0, 0);
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
`,
|
`,
|
||||||
@ -63,23 +67,41 @@ export class Modal extends React.Component {
|
|||||||
render() {
|
render() {
|
||||||
const { isOpen, children, className, onClose } = this.props;
|
const { isOpen, children, className, onClose } = this.props;
|
||||||
return (
|
return (
|
||||||
<ReactModal
|
<>
|
||||||
isOpen={isOpen}
|
<ReactModalGlobalStyles />
|
||||||
onRequestClose={onClose}
|
<ClassNames>
|
||||||
closeTimeoutMS={300}
|
{({ css, cx }) => (
|
||||||
className={{
|
<ReactModal
|
||||||
base: cx(styles.modalBody, className),
|
isOpen={isOpen}
|
||||||
afterOpen: '',
|
onRequestClose={onClose}
|
||||||
beforeClose: '',
|
closeTimeoutMS={300}
|
||||||
}}
|
className={{
|
||||||
overlayClassName={{
|
base: cx(
|
||||||
base: styles.overlay,
|
css`
|
||||||
afterOpen: styles.overlayAfterOpen,
|
${styleStrings.modalBody};
|
||||||
beforeClose: styles.overlayBeforeClose,
|
`,
|
||||||
}}
|
className,
|
||||||
>
|
),
|
||||||
{children}
|
afterOpen: '',
|
||||||
</ReactModal>
|
beforeClose: '',
|
||||||
|
}}
|
||||||
|
overlayClassName={{
|
||||||
|
base: css`
|
||||||
|
${styleStrings.overlay};
|
||||||
|
`,
|
||||||
|
afterOpen: css`
|
||||||
|
${styleStrings.overlayAfterOpen};
|
||||||
|
`,
|
||||||
|
beforeClose: css`
|
||||||
|
${styleStrings.overlayBeforeClose};
|
||||||
|
`,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
</ReactModal>
|
||||||
|
)}
|
||||||
|
</ClassNames>
|
||||||
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import styled, { css } from 'react-emotion';
|
import { css } from '@emotion/core';
|
||||||
|
import styled from '@emotion/styled';
|
||||||
import { translate } from 'react-polyglot';
|
import { translate } from 'react-polyglot';
|
||||||
import { Icon, Dropdown, DropdownItem, DropdownButton, colors } from 'netlify-cms-ui-default';
|
import { Icon, Dropdown, DropdownItem, DropdownButton, colors } from 'netlify-cms-ui-default';
|
||||||
import { stripProtocol } from 'Lib/urlHelper';
|
import { stripProtocol } from 'Lib/urlHelper';
|
||||||
|
@ -1,18 +1,24 @@
|
|||||||
|
/** @jsx jsx */
|
||||||
|
// eslint-disable-next-line no-unused-vars
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { css, injectGlobal, cx } from 'react-emotion';
|
import { jsx, css, Global } from '@emotion/core';
|
||||||
import { translate } from 'react-polyglot';
|
import { translate } from 'react-polyglot';
|
||||||
import reduxNotificationsStyles from 'redux-notifications/lib/styles.css';
|
import reduxNotificationsStyles from 'redux-notifications/lib/styles.css';
|
||||||
import { shadows, colors, lengths } from 'netlify-cms-ui-default';
|
import { shadows, colors, lengths } from 'netlify-cms-ui-default';
|
||||||
|
|
||||||
injectGlobal`
|
const ReduxNotificationsGlobalStyles = () => (
|
||||||
${reduxNotificationsStyles};
|
<Global
|
||||||
|
styles={css`
|
||||||
|
${reduxNotificationsStyles};
|
||||||
|
|
||||||
.notif__container {
|
.notif__container {
|
||||||
z-index: 10000;
|
z-index: 10000;
|
||||||
white-space: pre-wrap;
|
white-space: pre-wrap;
|
||||||
}
|
}
|
||||||
`;
|
`}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
|
||||||
const styles = {
|
const styles = {
|
||||||
toast: css`
|
toast: css`
|
||||||
@ -43,7 +49,8 @@ const styles = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const Toast = ({ kind, message, t }) => (
|
const Toast = ({ kind, message, t }) => (
|
||||||
<div className={cx(styles.toast, styles[kind])}>
|
<div css={[styles.toast, styles[kind]]}>
|
||||||
|
<ReduxNotificationsGlobalStyles />
|
||||||
{t(message.key, { details: message.details })}
|
{t(message.key, { details: message.details })}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||||
import styled from 'react-emotion';
|
import styled from '@emotion/styled';
|
||||||
import { OrderedMap } from 'immutable';
|
import { OrderedMap } from 'immutable';
|
||||||
import { translate } from 'react-polyglot';
|
import { translate } from 'react-polyglot';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import styled, { css } from 'react-emotion';
|
import { css } from '@emotion/core';
|
||||||
|
import styled from '@emotion/styled';
|
||||||
import { translate } from 'react-polyglot';
|
import { translate } from 'react-polyglot';
|
||||||
import { Link } from 'react-router-dom';
|
import { Link } from 'react-router-dom';
|
||||||
import { components, colors, colorsRaw, transitions, buttons } from 'netlify-cms-ui-default';
|
import { components, colors, colorsRaw, transitions, buttons } from 'netlify-cms-ui-default';
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
|
/** @jsx jsx */
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||||
import styled, { css, cx } from 'react-emotion';
|
import { jsx, css } from '@emotion/core';
|
||||||
|
import styled from '@emotion/styled';
|
||||||
import moment from 'moment';
|
import moment from 'moment';
|
||||||
import { translate } from 'react-polyglot';
|
import { translate } from 'react-polyglot';
|
||||||
import { colors, lengths } from 'netlify-cms-ui-default';
|
import { colors, lengths } from 'netlify-cms-ui-default';
|
||||||
@ -16,22 +18,16 @@ const WorkflowListContainer = styled.div`
|
|||||||
`;
|
`;
|
||||||
|
|
||||||
const styles = {
|
const styles = {
|
||||||
column: css`
|
columnPosition: idx =>
|
||||||
margin: 0 20px;
|
(idx === 0 &&
|
||||||
transition: background-color 0.5s ease;
|
css`
|
||||||
border: 2px dashed transparent;
|
margin-left: 0;
|
||||||
border-radius: 4px;
|
`) ||
|
||||||
position: relative;
|
(idx === 2 &&
|
||||||
|
css`
|
||||||
&:first-child {
|
margin-right: 0;
|
||||||
margin-left: 0;
|
`) ||
|
||||||
}
|
css`
|
||||||
|
|
||||||
&:last-child {
|
|
||||||
margin-right: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:not(:first-child):not(:last-child) {
|
|
||||||
&:before,
|
&:before,
|
||||||
&:after {
|
&:after {
|
||||||
content: '';
|
content: '';
|
||||||
@ -50,7 +46,14 @@ const styles = {
|
|||||||
&:after {
|
&:after {
|
||||||
right: -23px;
|
right: -23px;
|
||||||
}
|
}
|
||||||
}
|
`,
|
||||||
|
column: css`
|
||||||
|
margin: 0 20px;
|
||||||
|
transition: background-color 0.5s ease;
|
||||||
|
border: 2px dashed transparent;
|
||||||
|
border-radius: 4px;
|
||||||
|
position: relative;
|
||||||
|
height: 100%;
|
||||||
`,
|
`,
|
||||||
columnHovered: css`
|
columnHovered: css`
|
||||||
border-color: ${colors.active};
|
border-color: ${colors.active};
|
||||||
@ -140,11 +143,12 @@ class WorkflowList extends React.Component {
|
|||||||
this.props.handlePublish(collection, slug);
|
this.props.handlePublish(collection, slug);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// eslint-disable-next-line react/display-name
|
||||||
renderColumns = (entries, column) => {
|
renderColumns = (entries, column) => {
|
||||||
if (!entries) return null;
|
if (!entries) return null;
|
||||||
|
|
||||||
if (!column) {
|
if (!column) {
|
||||||
return entries.entrySeq().map(([currColumn, currEntries]) => (
|
return entries.entrySeq().map(([currColumn, currEntries], idx) => (
|
||||||
<DropTarget
|
<DropTarget
|
||||||
namespace={DNDNamespace}
|
namespace={DNDNamespace}
|
||||||
key={currColumn}
|
key={currColumn}
|
||||||
@ -152,16 +156,24 @@ class WorkflowList extends React.Component {
|
|||||||
>
|
>
|
||||||
{(connect, { isHovered }) =>
|
{(connect, { isHovered }) =>
|
||||||
connect(
|
connect(
|
||||||
<div className={cx(styles.column, { [styles.columnHovered]: isHovered })}>
|
<div style={{ height: '100%' }}>
|
||||||
<ColumnHeader name={currColumn}>
|
<div
|
||||||
{getColumnHeaderText(currColumn, this.props.t)}
|
css={[
|
||||||
</ColumnHeader>
|
styles.column,
|
||||||
<ColumnCount>
|
styles.columnPosition(idx),
|
||||||
{this.props.t('workflow.workflowList.currentEntries', {
|
isHovered && styles.columnHovered,
|
||||||
smart_count: currEntries.size,
|
]}
|
||||||
})}
|
>
|
||||||
</ColumnCount>
|
<ColumnHeader name={currColumn}>
|
||||||
{this.renderColumns(currEntries, currColumn)}
|
{getColumnHeaderText(currColumn, this.props.t)}
|
||||||
|
</ColumnHeader>
|
||||||
|
<ColumnCount>
|
||||||
|
{this.props.t('workflow.workflowList.currentEntries', {
|
||||||
|
smart_count: currEntries.size,
|
||||||
|
})}
|
||||||
|
</ColumnCount>
|
||||||
|
{this.renderColumns(currEntries, currColumn)}
|
||||||
|
</div>
|
||||||
</div>,
|
</div>,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -84,7 +84,7 @@ describe('config', () => {
|
|||||||
media_folder: 'baz',
|
media_folder: 'baz',
|
||||||
collections: [],
|
collections: [],
|
||||||
});
|
});
|
||||||
}).toThrowError("'collections' should NOT have less than 1 items");
|
}).toThrowError("'collections' should NOT have fewer than 1 items");
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should throw if collections is an array with a single null element in config', () => {
|
it('should throw if collections is an array with a single null element in config', () => {
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import { Map } from 'immutable';
|
import { Map } from 'immutable';
|
||||||
|
import { oneLine } from 'common-tags';
|
||||||
import EditorComponent from 'ValueObjects/EditorComponent';
|
import EditorComponent from 'ValueObjects/EditorComponent';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -59,10 +60,39 @@ export function getPreviewTemplate(name) {
|
|||||||
* Editor Widgets
|
* Editor Widgets
|
||||||
*/
|
*/
|
||||||
export function registerWidget(name, control, preview) {
|
export function registerWidget(name, control, preview) {
|
||||||
// A registered widget control can be reused by a new widget, allowing
|
if (Array.isArray(name)) {
|
||||||
// multiple copies with different previews.
|
name.forEach(widget => {
|
||||||
const newControl = typeof control === 'string' ? registry.widgets[control].control : control;
|
if (typeof widget !== 'object') {
|
||||||
registry.widgets[name] = { control: newControl, preview };
|
console.error(`Cannot register widget: ${widget}`);
|
||||||
|
} else {
|
||||||
|
registerWidget(widget);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else if (typeof name === 'string') {
|
||||||
|
// A registered widget control can be reused by a new widget, allowing
|
||||||
|
// multiple copies with different previews.
|
||||||
|
const newControl = typeof control === 'string' ? registry.widgets[control].control : control;
|
||||||
|
registry.widgets[name] = { control: newControl, preview };
|
||||||
|
} else if (typeof name === 'object') {
|
||||||
|
const {
|
||||||
|
name: widgetName,
|
||||||
|
controlComponent: control,
|
||||||
|
previewComponent: preview,
|
||||||
|
globalStyles,
|
||||||
|
} = name;
|
||||||
|
if (registry.widgets[widgetName]) {
|
||||||
|
console.error(oneLine`
|
||||||
|
Multiple widgets registered with name "${widgetName}". Only the last widget registered with
|
||||||
|
this name will be used.
|
||||||
|
`);
|
||||||
|
}
|
||||||
|
if (!control) {
|
||||||
|
throw Error(`Widget "${widgetName}" registered without \`controlComponent\`.`);
|
||||||
|
}
|
||||||
|
registry.widgets[widgetName] = { control, preview, globalStyles };
|
||||||
|
} else {
|
||||||
|
console.error('`registerWidget` failed, called with incorrect arguments.');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
export function getWidget(name) {
|
export function getWidget(name) {
|
||||||
return registry.widgets[name];
|
return registry.widgets[name];
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { Map } from 'immutable';
|
import { Map } from 'immutable';
|
||||||
/*
|
/*
|
||||||
* Reducer for some global UI state that we want to share between components
|
* Reducer for some global UI state that we want to share between components
|
||||||
* */
|
* */
|
||||||
const globalUI = (state = Map({ isFetching: false }), action) => {
|
const globalUI = (state = Map({ isFetching: false }), action) => {
|
||||||
// Generic, global loading indicator
|
// Generic, global loading indicator
|
||||||
if (action.type.indexOf('REQUEST') > -1) {
|
if (action.type.indexOf('REQUEST') > -1) {
|
||||||
|
@ -20,8 +20,8 @@
|
|||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"cross-env": "^5.2.0",
|
"cross-env": "^5.2.0",
|
||||||
"webpack": "^4.16.1",
|
"webpack": "^4.29.6",
|
||||||
"webpack-cli": "^3.1.0"
|
"webpack-cli": "^3.2.3"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"react": "^16.4.1"
|
"react": "^16.4.1"
|
||||||
|
@ -24,8 +24,8 @@
|
|||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"cross-env": "^5.2.0",
|
"cross-env": "^5.2.0",
|
||||||
"webpack": "^4.16.1",
|
"webpack": "^4.29.6",
|
||||||
"webpack-cli": "^3.1.0"
|
"webpack-cli": "^3.2.3"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"immutable": "^3.7.6",
|
"immutable": "^3.7.6",
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import trim from 'lodash/trim';
|
import trim from 'lodash/trim';
|
||||||
import trimEnd from 'lodash/trim';
|
import trimEnd from 'lodash/trimEnd';
|
||||||
|
|
||||||
const NETLIFY_API = 'https://api.netlify.com';
|
const NETLIFY_API = 'https://api.netlify.com';
|
||||||
const AUTH_ENDPOINT = 'auth';
|
const AUTH_ENDPOINT = 'auth';
|
||||||
|
@ -17,12 +17,12 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"js-sha256": "^0.9.0",
|
"js-sha256": "^0.9.0",
|
||||||
"localforage": "^1.4.2"
|
"localforage": "^1.7.3"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"cross-env": "^5.2.0",
|
"cross-env": "^5.2.0",
|
||||||
"webpack": "^4.16.1",
|
"webpack": "^4.29.6",
|
||||||
"webpack-cli": "^3.1.0"
|
"webpack-cli": "^3.2.3"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"immutable": "^3.7.6",
|
"immutable": "^3.7.6",
|
||||||
|
@ -25,8 +25,8 @@
|
|||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"cross-env": "^5.2.0",
|
"cross-env": "^5.2.0",
|
||||||
"webpack": "^4.16.1",
|
"webpack": "^4.29.6",
|
||||||
"webpack-cli": "^3.1.0"
|
"webpack-cli": "^3.2.3"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"netlify-cms-lib-util": "^2.0.4"
|
"netlify-cms-lib-util": "^2.0.4"
|
||||||
|
@ -23,11 +23,11 @@
|
|||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"cross-env": "^5.2.0",
|
"cross-env": "^5.2.0",
|
||||||
"webpack": "^4.16.1",
|
"webpack": "^4.29.6",
|
||||||
"webpack-cli": "^3.1.0"
|
"webpack-cli": "^3.2.3"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"uploadcare-widget": "^3.6.2",
|
"uploadcare-widget": "^3.7.0",
|
||||||
"uploadcare-widget-tab-effects": "^1.3.0"
|
"uploadcare-widget-tab-effects": "^1.4.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,18 +18,18 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"react-aria-menubutton": "^5.1.0",
|
"react-aria-menubutton": "^5.1.0",
|
||||||
"react-toggled": "^1.1.2",
|
"react-toggled": "^1.1.2",
|
||||||
"react-transition-group": "^2.2.1"
|
"react-transition-group": "^2.6.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"cross-env": "^5.2.0",
|
"cross-env": "^5.2.0",
|
||||||
"webpack": "^4.16.1",
|
"webpack": "^4.29.6",
|
||||||
"webpack-cli": "^3.1.0"
|
"webpack-cli": "^3.2.3"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"emotion": "^9.2.6",
|
"@emotion/core": "^10.0.9",
|
||||||
|
"@emotion/styled": "^10.0.9",
|
||||||
"lodash": "^4.13.1",
|
"lodash": "^4.13.1",
|
||||||
"prop-types": "^15.5.10",
|
"prop-types": "^15.5.10",
|
||||||
"react": "^16.4.1",
|
"react": "^16.4.1"
|
||||||
"react-emotion": "^9.2.6"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import styled from 'react-emotion';
|
import styled from '@emotion/styled';
|
||||||
import Icon from './Icon';
|
import Icon from './Icon';
|
||||||
import { buttons, shadows } from './styles';
|
import { buttons, shadows } from './styles';
|
||||||
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import styled, { css } from 'react-emotion';
|
import { css } from '@emotion/core';
|
||||||
|
import styled from '@emotion/styled';
|
||||||
import { Wrapper, Button as DropdownButton, Menu, MenuItem } from 'react-aria-menubutton';
|
import { Wrapper, Button as DropdownButton, Menu, MenuItem } from 'react-aria-menubutton';
|
||||||
import { buttons, components } from './styles';
|
import { buttons, components } from './styles';
|
||||||
import Icon from './Icon';
|
import Icon from './Icon';
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import styled from 'react-emotion';
|
import styled from '@emotion/styled';
|
||||||
import icons from './Icon/icons';
|
import icons from './Icon/icons';
|
||||||
|
|
||||||
const IconWrapper = styled.span`
|
const IconWrapper = styled.span`
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import styled from 'react-emotion';
|
import styled from '@emotion/styled';
|
||||||
import Icon from './Icon';
|
import Icon from './Icon';
|
||||||
import { colors, lengths, buttons } from './styles';
|
import { colors, lengths, buttons } from './styles';
|
||||||
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import styled, { css, keyframes } from 'react-emotion';
|
import styled from '@emotion/styled';
|
||||||
|
import { css, keyframes } from '@emotion/core';
|
||||||
import CSSTransition from 'react-transition-group/CSSTransition';
|
import CSSTransition from 'react-transition-group/CSSTransition';
|
||||||
import { colors } from './styles';
|
import { colors } from './styles';
|
||||||
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import styled, { css } from 'react-emotion';
|
import styled from '@emotion/styled';
|
||||||
|
import { css } from '@emotion/core';
|
||||||
import Icon from './Icon';
|
import Icon from './Icon';
|
||||||
import { colors, buttons } from './styles';
|
import { colors, buttons } from './styles';
|
||||||
import Dropdown, { StyledDropdownButton, DropdownItem } from './Dropdown';
|
import Dropdown, { StyledDropdownButton, DropdownItem } from './Dropdown';
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import styled, { css } from 'react-emotion';
|
import styled from '@emotion/styled';
|
||||||
|
import { css } from '@emotion/core';
|
||||||
import ReactToggled from 'react-toggled';
|
import ReactToggled from 'react-toggled';
|
||||||
import { colors, colorsRaw, shadows, transitions } from './styles';
|
import { colors, colorsRaw, shadows, transitions } from './styles';
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import styled from 'react-emotion';
|
import styled from '@emotion/styled';
|
||||||
|
|
||||||
const WidgetPreviewContainer = styled.div`
|
const WidgetPreviewContainer = styled.div`
|
||||||
margin: 15px 2px;
|
margin: 15px 2px;
|
||||||
|
@ -18,4 +18,5 @@ export {
|
|||||||
transitions,
|
transitions,
|
||||||
effects,
|
effects,
|
||||||
reactSelectStyles,
|
reactSelectStyles,
|
||||||
|
GlobalStyles,
|
||||||
} from './styles';
|
} from './styles';
|
||||||
|
@ -1,18 +1,5 @@
|
|||||||
import { css, injectGlobal } from 'react-emotion';
|
import React from 'react';
|
||||||
|
import { css, Global } from '@emotion/core';
|
||||||
export {
|
|
||||||
fonts,
|
|
||||||
colorsRaw,
|
|
||||||
colors,
|
|
||||||
lengths,
|
|
||||||
components,
|
|
||||||
buttons,
|
|
||||||
shadows,
|
|
||||||
borders,
|
|
||||||
transitions,
|
|
||||||
effects,
|
|
||||||
reactSelectStyles,
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Font Stacks
|
* Font Stacks
|
||||||
@ -102,6 +89,7 @@ const lengths = {
|
|||||||
borderWidth: '2px',
|
borderWidth: '2px',
|
||||||
topCardWidth: '682px',
|
topCardWidth: '682px',
|
||||||
pageMargin: '28px 18px',
|
pageMargin: '28px 18px',
|
||||||
|
objectWidgetTopBarContainerPadding: '0 14px 14px',
|
||||||
};
|
};
|
||||||
|
|
||||||
const borders = {
|
const borders = {
|
||||||
@ -130,27 +118,25 @@ const shadows = {
|
|||||||
`,
|
`,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const gradients = {
|
||||||
|
checkerboard: `
|
||||||
|
linear-gradient(
|
||||||
|
45deg,
|
||||||
|
${colors.checkerboardDark} 25%,
|
||||||
|
transparent 25%,
|
||||||
|
transparent 75%,
|
||||||
|
${colors.checkerboardDark} 75%,
|
||||||
|
${colors.checkerboardDark}
|
||||||
|
)
|
||||||
|
`,
|
||||||
|
};
|
||||||
|
|
||||||
const effects = {
|
const effects = {
|
||||||
checkerboard: css`
|
checkerboard: css`
|
||||||
background-color: ${colors.checkerboardLight};
|
background-color: ${colors.checkerboardLight};
|
||||||
background-size: 16px 16px;
|
background-size: 16px 16px;
|
||||||
background-position: 0 0, 8px 8px;
|
background-position: 0 0, 8px 8px;
|
||||||
background-image: linear-gradient(
|
background-image: ${gradients.checkerboard}, ${gradients.checkerboard};
|
||||||
45deg,
|
|
||||||
${colors.checkerboardDark} 25%,
|
|
||||||
transparent 25%,
|
|
||||||
transparent 75%,
|
|
||||||
${colors.checkerboardDark} 75%,
|
|
||||||
${colors.checkerboardDark}
|
|
||||||
),
|
|
||||||
linear-gradient(
|
|
||||||
45deg,
|
|
||||||
${colors.checkerboardDark} 25%,
|
|
||||||
transparent 25%,
|
|
||||||
transparent 75%,
|
|
||||||
${colors.checkerboardDark} 75%,
|
|
||||||
${colors.checkerboardDark}
|
|
||||||
);
|
|
||||||
`,
|
`,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -305,7 +291,7 @@ const components = {
|
|||||||
margin-top: 8px;
|
margin-top: 8px;
|
||||||
`,
|
`,
|
||||||
objectWidgetTopBarContainer: css`
|
objectWidgetTopBarContainer: css`
|
||||||
padding: 0 14px 14px;
|
padding: ${lengths.objectWidgetTopBarContainerPadding};
|
||||||
`,
|
`,
|
||||||
dropdownList: css`
|
dropdownList: css`
|
||||||
${shadows.dropDeep};
|
${shadows.dropDeep};
|
||||||
@ -350,8 +336,8 @@ const reactSelectStyles = {
|
|||||||
backgroundColor: state.isSelected
|
backgroundColor: state.isSelected
|
||||||
? `${colors.active}`
|
? `${colors.active}`
|
||||||
: state.isFocused
|
: state.isFocused
|
||||||
? `${colors.activeBackground}`
|
? `${colors.activeBackground}`
|
||||||
: 'transparent',
|
: 'transparent',
|
||||||
paddingLeft: '22px',
|
paddingLeft: '22px',
|
||||||
}),
|
}),
|
||||||
menu: styles => ({ ...styles, right: 0, zIndex: 2 }),
|
menu: styles => ({ ...styles, right: 0, zIndex: 2 }),
|
||||||
@ -381,73 +367,105 @@ const reactSelectStyles = {
|
|||||||
}),
|
}),
|
||||||
};
|
};
|
||||||
|
|
||||||
injectGlobal`
|
const GlobalStyles = () => (
|
||||||
*, *:before, *:after {
|
<Global
|
||||||
box-sizing: border-box;
|
styles={css`
|
||||||
}
|
*,
|
||||||
|
*:before,
|
||||||
|
*:after {
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
:focus {
|
:focus {
|
||||||
outline: -webkit-focus-ring-color auto ${lengths.borderRadius};
|
outline: -webkit-focus-ring-color auto ${lengths.borderRadius};
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Don't show outlines if the user is utilizing mouse rather than keyboard.
|
* Don't show outlines if the user is utilizing mouse rather than keyboard.
|
||||||
*/
|
*/
|
||||||
[data-whatintent="mouse"] *:focus {
|
[data-whatintent='mouse'] *:focus {
|
||||||
outline: none;
|
outline: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
input {
|
||||||
|
border: 0;
|
||||||
|
}
|
||||||
|
|
||||||
input {
|
body {
|
||||||
border: 0;
|
font-family: ${fonts.primary};
|
||||||
}
|
font-weight: normal;
|
||||||
|
background-color: ${colors.background};
|
||||||
|
color: ${colors.text};
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
body {
|
ul,
|
||||||
font-family: ${fonts.primary};
|
ol {
|
||||||
font-weight: normal;
|
padding-left: 0;
|
||||||
background-color: ${colors.background};
|
}
|
||||||
color: ${colors.text};
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
ul, ol {
|
h1,
|
||||||
padding-left: 0;
|
h2,
|
||||||
}
|
h3,
|
||||||
|
h4,
|
||||||
|
h5,
|
||||||
|
h6,
|
||||||
|
p {
|
||||||
|
font-family: ${fonts.primary};
|
||||||
|
color: ${colors.textLead};
|
||||||
|
font-size: 15px;
|
||||||
|
line-height: 1.5;
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
h1, h2, h3, h4, h5, h6, p {
|
h1,
|
||||||
font-family: ${fonts.primary};
|
h2,
|
||||||
color: ${colors.textLead};
|
h3,
|
||||||
font-size: 15px;
|
h4,
|
||||||
line-height: 1.5;
|
h5,
|
||||||
margin-top: 0;
|
h6 {
|
||||||
}
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
h1, h2, h3, h4, h5, h6 {
|
h1 {
|
||||||
font-weight: 500;
|
font-size: 24px;
|
||||||
}
|
letter-spacing: 0.4px;
|
||||||
|
color: ${colors.textLead};
|
||||||
|
}
|
||||||
|
|
||||||
h1 {
|
a,
|
||||||
font-size: 24px;
|
button {
|
||||||
letter-spacing: 0.4px;
|
font-size: 14px;
|
||||||
color: ${colors.textLead};
|
font-weight: 500;
|
||||||
}
|
}
|
||||||
|
|
||||||
a,
|
a {
|
||||||
button {
|
color: ${colors.text};
|
||||||
font-size: 14px;
|
text-decoration: none;
|
||||||
font-weight: 500;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
a {
|
img {
|
||||||
color: ${colors.text};
|
max-width: 100%;
|
||||||
text-decoration: none;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
img {
|
textarea {
|
||||||
max-width: 100%;
|
resize: none;
|
||||||
}
|
}
|
||||||
|
`}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
|
||||||
textarea {
|
export {
|
||||||
resize: none;
|
fonts,
|
||||||
}
|
colorsRaw,
|
||||||
`;
|
colors,
|
||||||
|
lengths,
|
||||||
|
components,
|
||||||
|
buttons,
|
||||||
|
shadows,
|
||||||
|
borders,
|
||||||
|
transitions,
|
||||||
|
effects,
|
||||||
|
reactSelectStyles,
|
||||||
|
GlobalStyles,
|
||||||
|
};
|
||||||
|
@ -21,11 +21,11 @@
|
|||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"cross-env": "^5.2.0",
|
"cross-env": "^5.2.0",
|
||||||
"webpack": "^4.16.1",
|
"webpack": "^4.29.6",
|
||||||
"webpack-cli": "^3.1.0"
|
"webpack-cli": "^3.2.3"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"emotion": "^9.2.6",
|
"@emotion/core": "^10.0.9",
|
||||||
"lodash": "^4.17.10",
|
"lodash": "^4.17.10",
|
||||||
"netlify-cms-ui-default": "^2.0.0",
|
"netlify-cms-ui-default": "^2.0.0",
|
||||||
"prop-types": "^15.5.10",
|
"prop-types": "^15.5.10",
|
||||||
|
@ -1,12 +1,18 @@
|
|||||||
|
/** @jsx jsx */
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||||
import styled from 'react-emotion';
|
import { jsx, css } from '@emotion/core';
|
||||||
import { Toggle, ToggleBackground, colors } from 'netlify-cms-ui-default';
|
import { Toggle, ToggleBackground, colors } from 'netlify-cms-ui-default';
|
||||||
|
|
||||||
const BooleanBackground = styled(ToggleBackground)`
|
const BooleanBackground = ({ isActive, ...props }) => (
|
||||||
background-color: ${props => (props.isActive ? colors.active : colors.textFieldBorder)};
|
<ToggleBackground
|
||||||
`;
|
css={css`
|
||||||
|
background-color: ${isActive ? colors.active : colors.textFieldBorder};
|
||||||
|
`}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
|
||||||
export default class BooleanControl extends React.Component {
|
export default class BooleanControl extends React.Component {
|
||||||
render() {
|
render() {
|
||||||
|
@ -21,21 +21,21 @@
|
|||||||
"build": "cross-env NODE_ENV=production webpack"
|
"build": "cross-env NODE_ENV=production webpack"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"react-datetime": "^2.11.0"
|
"react-datetime": "^2.16.3"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"cross-env": "^5.2.0",
|
"cross-env": "^5.2.0",
|
||||||
"css-loader": "^1.0.0",
|
"css-loader": "^2.1.1",
|
||||||
"to-string-loader": "^1.1.5",
|
"to-string-loader": "^1.1.5",
|
||||||
"webpack": "^4.16.1",
|
"webpack": "^4.29.6",
|
||||||
"webpack-cli": "^3.1.0"
|
"webpack-cli": "^3.2.3"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"emotion": "^9.2.6",
|
"@emotion/core": "^10.0.9",
|
||||||
|
"@emotion/styled": "^10.0.9",
|
||||||
"moment": "^2.11.2",
|
"moment": "^2.11.2",
|
||||||
"netlify-cms-ui-default": "^2.0.0",
|
"netlify-cms-ui-default": "^2.0.0",
|
||||||
"prop-types": "^15.5.10",
|
"prop-types": "^15.5.10",
|
||||||
"react": "^16.4.1",
|
"react": "^16.4.1"
|
||||||
"react-emotion": "^9.2.6"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,14 +1,11 @@
|
|||||||
|
/** @jsx jsx */
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { injectGlobal } from 'react-emotion';
|
import { jsx, css } from '@emotion/core';
|
||||||
|
import reactDateTimeStyles from 'react-datetime/css/react-datetime.css';
|
||||||
import DateTime from 'react-datetime';
|
import DateTime from 'react-datetime';
|
||||||
import dateTimeStyles from 'react-datetime/css/react-datetime.css';
|
|
||||||
import moment from 'moment';
|
import moment from 'moment';
|
||||||
|
|
||||||
injectGlobal`
|
|
||||||
${dateTimeStyles}
|
|
||||||
`;
|
|
||||||
|
|
||||||
export default class DateControl extends React.Component {
|
export default class DateControl extends React.Component {
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
field: PropTypes.object.isRequired,
|
field: PropTypes.object.isRequired,
|
||||||
@ -106,15 +103,21 @@ export default class DateControl extends React.Component {
|
|||||||
const { forID, value, classNameWrapper, setActiveStyle } = this.props;
|
const { forID, value, classNameWrapper, setActiveStyle } = this.props;
|
||||||
const { format, dateFormat, timeFormat } = this.formats;
|
const { format, dateFormat, timeFormat } = this.formats;
|
||||||
return (
|
return (
|
||||||
<DateTime
|
<div
|
||||||
dateFormat={dateFormat}
|
css={css`
|
||||||
timeFormat={timeFormat}
|
${reactDateTimeStyles};
|
||||||
value={moment(value, format)}
|
`}
|
||||||
onChange={this.handleChange}
|
>
|
||||||
onFocus={setActiveStyle}
|
<DateTime
|
||||||
onBlur={this.onBlur}
|
dateFormat={dateFormat}
|
||||||
inputProps={{ className: classNameWrapper, id: forID }}
|
timeFormat={timeFormat}
|
||||||
/>
|
value={moment(value, format)}
|
||||||
|
onChange={this.handleChange}
|
||||||
|
onFocus={setActiveStyle}
|
||||||
|
onBlur={this.onBlur}
|
||||||
|
inputProps={{ className: classNameWrapper, id: forID }}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,2 +1,11 @@
|
|||||||
export DateControl from './DateControl';
|
import controlComponent from './DateControl';
|
||||||
export DatePreview from './DatePreview';
|
import previewComponent from './DatePreview';
|
||||||
|
|
||||||
|
const Widget = (opts = {}) => ({
|
||||||
|
name: 'date',
|
||||||
|
controlComponent,
|
||||||
|
previewComponent,
|
||||||
|
...opts,
|
||||||
|
});
|
||||||
|
|
||||||
|
export { Widget as default, controlComponent, previewComponent };
|
||||||
|
@ -26,11 +26,11 @@
|
|||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"cross-env": "^5.2.0",
|
"cross-env": "^5.2.0",
|
||||||
"webpack": "^4.16.1",
|
"webpack": "^4.29.6",
|
||||||
"webpack-cli": "^3.1.0"
|
"webpack-cli": "^3.2.3"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"emotion": "^9.2.6",
|
"@emotion/core": "^10.0.9",
|
||||||
"react": "^16.4.1"
|
"react": "^16.4.1"
|
||||||
},
|
},
|
||||||
"localExternals": [
|
"localExternals": [
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { DateControl } from 'netlify-cms-widget-date';
|
import { controlComponent as DateControl } from 'netlify-cms-widget-date';
|
||||||
|
|
||||||
export default class DateTimeControl extends React.Component {
|
export default class DateTimeControl extends React.Component {
|
||||||
render() {
|
render() {
|
||||||
|
@ -1,2 +1,11 @@
|
|||||||
export DateTimeControl from './DateTimeControl';
|
import controlComponent from './DateTimeControl';
|
||||||
export { DatePreview as DateTimePreview } from 'netlify-cms-widget-date';
|
import { previewComponent } from 'netlify-cms-widget-date';
|
||||||
|
|
||||||
|
const Widget = (opts = {}) => ({
|
||||||
|
name: 'datetime',
|
||||||
|
controlComponent,
|
||||||
|
previewComponent,
|
||||||
|
...opts,
|
||||||
|
});
|
||||||
|
|
||||||
|
export { Widget as default, controlComponent, previewComponent };
|
||||||
|
@ -27,16 +27,16 @@
|
|||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"cross-env": "^5.2.0",
|
"cross-env": "^5.2.0",
|
||||||
"webpack": "^4.16.1",
|
"webpack": "^4.29.6",
|
||||||
"webpack-cli": "^3.1.0"
|
"webpack-cli": "^3.2.3"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"emotion": "^9.2.6",
|
"@emotion/core": "^10.0.9",
|
||||||
|
"@emotion/styled": "^10.0.9",
|
||||||
"immutable": "^3.7.6",
|
"immutable": "^3.7.6",
|
||||||
"netlify-cms-ui-default": "^2.0.0",
|
"netlify-cms-ui-default": "^2.0.0",
|
||||||
"prop-types": "^15.5.10",
|
"prop-types": "^15.5.10",
|
||||||
"react": "^16.4.1",
|
"react": "^16.4.1",
|
||||||
"react-emotion": "^9.2.6",
|
|
||||||
"react-immutable-proptypes": "^2.1.0"
|
"react-immutable-proptypes": "^2.1.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import styled from 'react-emotion';
|
import styled from '@emotion/styled';
|
||||||
import { List } from 'immutable';
|
import { List } from 'immutable';
|
||||||
import { WidgetPreviewContainer } from 'netlify-cms-ui-default';
|
import { WidgetPreviewContainer } from 'netlify-cms-ui-default';
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||||
import styled from 'react-emotion';
|
import styled from '@emotion/styled';
|
||||||
import { Map, List } from 'immutable';
|
import { Map, List } from 'immutable';
|
||||||
import { once } from 'lodash';
|
import { once } from 'lodash';
|
||||||
import uuid from 'uuid/v4';
|
import uuid from 'uuid/v4';
|
||||||
@ -33,12 +33,6 @@ const MultiImageWrapper = styled.div`
|
|||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const FileInfo = styled.div`
|
|
||||||
button:not(:first-child) {
|
|
||||||
margin-top: 12px;
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
|
|
||||||
const FileLink = styled.a`
|
const FileLink = styled.a`
|
||||||
margin-bottom: 20px;
|
margin-bottom: 20px;
|
||||||
font-weight: normal;
|
font-weight: normal;
|
||||||
@ -51,6 +45,10 @@ const FileLink = styled.a`
|
|||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
const FileLinks = styled.div`
|
||||||
|
margin-bottom: 12px;
|
||||||
|
`;
|
||||||
|
|
||||||
const FileLinkList = styled.ul`
|
const FileLinkList = styled.ul`
|
||||||
list-style-type: none;
|
list-style-type: none;
|
||||||
`;
|
`;
|
||||||
@ -63,6 +61,7 @@ const FileWidgetButton = styled.button`
|
|||||||
const FileWidgetButtonRemove = styled.button`
|
const FileWidgetButtonRemove = styled.button`
|
||||||
${buttons.button};
|
${buttons.button};
|
||||||
${components.badgeDanger};
|
${components.badgeDanger};
|
||||||
|
margin-top: 12px;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
function isMultiple(value) {
|
function isMultiple(value) {
|
||||||
@ -192,14 +191,16 @@ export default function withFileControl({ forImage } = {}) {
|
|||||||
|
|
||||||
if (isMultiple(value)) {
|
if (isMultiple(value)) {
|
||||||
return (
|
return (
|
||||||
<FileLinkList>
|
<FileLinks>
|
||||||
{value.map(val => (
|
<FileLinkList>
|
||||||
<li key={val}>{this.renderFileLink(val)}</li>
|
{value.map(val => (
|
||||||
))}
|
<li key={val}>{this.renderFileLink(val)}</li>
|
||||||
</FileLinkList>
|
))}
|
||||||
|
</FileLinkList>
|
||||||
|
</FileLinks>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return this.renderFileLink(value);
|
return <FileLinks>{this.renderFileLink(value)}</FileLinks>;
|
||||||
};
|
};
|
||||||
|
|
||||||
renderImages = () => {
|
renderImages = () => {
|
||||||
@ -225,7 +226,7 @@ export default function withFileControl({ forImage } = {}) {
|
|||||||
renderSelection = subject => (
|
renderSelection = subject => (
|
||||||
<div>
|
<div>
|
||||||
{forImage ? this.renderImages() : null}
|
{forImage ? this.renderImages() : null}
|
||||||
<FileInfo>
|
<div>
|
||||||
{forImage ? null : this.renderFileLinks()}
|
{forImage ? null : this.renderFileLinks()}
|
||||||
<FileWidgetButton onClick={this.handleChange}>
|
<FileWidgetButton onClick={this.handleChange}>
|
||||||
Choose different {subject}
|
Choose different {subject}
|
||||||
@ -233,7 +234,7 @@ export default function withFileControl({ forImage } = {}) {
|
|||||||
<FileWidgetButtonRemove onClick={this.handleRemove}>
|
<FileWidgetButtonRemove onClick={this.handleRemove}>
|
||||||
Remove {subject}
|
Remove {subject}
|
||||||
</FileWidgetButtonRemove>
|
</FileWidgetButtonRemove>
|
||||||
</FileInfo>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -26,15 +26,16 @@
|
|||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"cross-env": "^5.2.0",
|
"cross-env": "^5.2.0",
|
||||||
"webpack": "^4.16.1",
|
"webpack": "^4.29.6",
|
||||||
"webpack-cli": "^3.1.0"
|
"webpack-cli": "^3.2.3"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
|
"@emotion/core": "^10.0.9",
|
||||||
|
"@emotion/styled": "^10.0.9",
|
||||||
"immutable": "^3.7.6",
|
"immutable": "^3.7.6",
|
||||||
"netlify-cms-ui-default": "^2.0.0",
|
"netlify-cms-ui-default": "^2.0.0",
|
||||||
"prop-types": "^15.5.10",
|
"prop-types": "^15.5.10",
|
||||||
"react": "^16.4.1",
|
"react": "^16.4.1"
|
||||||
"react-emotion": "^9.2.6"
|
|
||||||
},
|
},
|
||||||
"localExternals": [
|
"localExternals": [
|
||||||
"netlify-cms-widget-file"
|
"netlify-cms-widget-file"
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import styled from 'react-emotion';
|
import styled from '@emotion/styled';
|
||||||
import { List } from 'immutable';
|
import { List } from 'immutable';
|
||||||
import { WidgetPreviewContainer } from 'netlify-cms-ui-default';
|
import { WidgetPreviewContainer } from 'netlify-cms-ui-default';
|
||||||
|
|
||||||
|
@ -26,17 +26,17 @@
|
|||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"cross-env": "^5.2.0",
|
"cross-env": "^5.2.0",
|
||||||
"webpack": "^4.16.1",
|
"webpack": "^4.29.6",
|
||||||
"webpack-cli": "^3.1.0"
|
"webpack-cli": "^3.2.3"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"emotion": "^9.2.6",
|
"@emotion/core": "^10.0.9",
|
||||||
|
"@emotion/styled": "^10.0.9",
|
||||||
"immutable": "^3.7.6",
|
"immutable": "^3.7.6",
|
||||||
"lodash": "^4.17.10",
|
"lodash": "^4.17.10",
|
||||||
"netlify-cms-ui-default": "^2.0.0",
|
"netlify-cms-ui-default": "^2.0.0",
|
||||||
"prop-types": "^15.5.10",
|
"prop-types": "^15.5.10",
|
||||||
"react": "^16.4.1",
|
"react": "^16.4.1",
|
||||||
"react-emotion": "^9.2.6",
|
|
||||||
"react-immutable-proptypes": "^2.1.0"
|
"react-immutable-proptypes": "^2.1.0"
|
||||||
},
|
},
|
||||||
"localExternals": [
|
"localExternals": [
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
|
/** @jsx jsx */
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||||
import styled, { cx, css } from 'react-emotion';
|
import styled from '@emotion/styled';
|
||||||
|
import { jsx, css, ClassNames } from '@emotion/core';
|
||||||
import { List, Map } from 'immutable';
|
import { List, Map } from 'immutable';
|
||||||
import { partial } from 'lodash';
|
import { partial } from 'lodash';
|
||||||
import { SortableContainer, SortableElement, SortableHandle } from 'react-sortable-hoc';
|
import { SortableContainer, SortableElement, SortableHandle } from 'react-sortable-hoc';
|
||||||
@ -12,13 +14,7 @@ import {
|
|||||||
resolveFieldKeyType,
|
resolveFieldKeyType,
|
||||||
getErrorMessageForTypedFieldAndValue,
|
getErrorMessageForTypedFieldAndValue,
|
||||||
} from './typedListHelpers';
|
} from './typedListHelpers';
|
||||||
import {
|
import { ListItemTopBar, ObjectWidgetTopBar, colors, lengths } from 'netlify-cms-ui-default';
|
||||||
ListItemTopBar,
|
|
||||||
ObjectWidgetTopBar,
|
|
||||||
colors,
|
|
||||||
lengths,
|
|
||||||
components,
|
|
||||||
} from 'netlify-cms-ui-default';
|
|
||||||
|
|
||||||
function valueToString(value) {
|
function valueToString(value) {
|
||||||
return value ? value.join(',').replace(/,([^\s]|$)/g, ', $1') : '';
|
return value ? value.join(',').replace(/,([^\s]|$)/g, ', $1') : '';
|
||||||
@ -41,10 +37,16 @@ const NestedObjectLabel = styled.div`
|
|||||||
border-radius: 0 0 ${lengths.borderRadius} ${lengths.borderRadius};
|
border-radius: 0 0 ${lengths.borderRadius} ${lengths.borderRadius};
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const styles = {
|
const styleStrings = {
|
||||||
collapsedObjectControl: css`
|
collapsedObjectControl: `
|
||||||
display: none;
|
display: none;
|
||||||
`,
|
`,
|
||||||
|
objectWidgetTopBarContainer: `
|
||||||
|
padding: ${lengths.objectWidgetTopBarContainerPadding};
|
||||||
|
`,
|
||||||
|
};
|
||||||
|
|
||||||
|
const styles = {
|
||||||
listControlItem: css`
|
listControlItem: css`
|
||||||
margin-top: 18px;
|
margin-top: 18px;
|
||||||
|
|
||||||
@ -275,6 +277,7 @@ export default class ListControl extends React.Component {
|
|||||||
this.setState({ itemsCollapsed: updatedItemsCollapsed });
|
this.setState({ itemsCollapsed: updatedItemsCollapsed });
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// eslint-disable-next-line react/display-name
|
||||||
renderItem = (item, index) => {
|
renderItem = (item, index) => {
|
||||||
const {
|
const {
|
||||||
classNameWrapper,
|
classNameWrapper,
|
||||||
@ -300,7 +303,7 @@ export default class ListControl extends React.Component {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<SortableListItem
|
<SortableListItem
|
||||||
className={cx(styles.listControlItem, { [styles.listControlItemCollapsed]: collapsed })}
|
css={[styles.listControlItem, collapsed && styles.listControlItemCollapsed]}
|
||||||
index={index}
|
index={index}
|
||||||
key={`item-${index}`}
|
key={`item-${index}`}
|
||||||
>
|
>
|
||||||
@ -311,21 +314,29 @@ export default class ListControl extends React.Component {
|
|||||||
dragHandleHOC={SortableHandle}
|
dragHandleHOC={SortableHandle}
|
||||||
/>
|
/>
|
||||||
<NestedObjectLabel collapsed={collapsed}>{this.objectLabel(item)}</NestedObjectLabel>
|
<NestedObjectLabel collapsed={collapsed}>{this.objectLabel(item)}</NestedObjectLabel>
|
||||||
<ObjectControl
|
<ClassNames>
|
||||||
classNameWrapper={cx(classNameWrapper, { [styles.collapsedObjectControl]: collapsed })}
|
{({ css, cx }) => (
|
||||||
value={item}
|
<ObjectControl
|
||||||
field={field}
|
classNameWrapper={cx(classNameWrapper, {
|
||||||
onChangeObject={this.handleChangeFor(index)}
|
[css`
|
||||||
editorControl={editorControl}
|
${styleStrings.collapsedObjectControl};
|
||||||
resolveWidget={resolveWidget}
|
`]: collapsed,
|
||||||
metadata={metadata}
|
})}
|
||||||
forList
|
value={item}
|
||||||
onValidateObject={onValidateObject}
|
field={field}
|
||||||
clearFieldErrors={clearFieldErrors}
|
onChangeObject={this.handleChangeFor(index)}
|
||||||
fieldsErrors={fieldsErrors}
|
editorControl={editorControl}
|
||||||
ref={this.processControlRef}
|
resolveWidget={resolveWidget}
|
||||||
controlRef={controlRef}
|
metadata={metadata}
|
||||||
/>
|
forList
|
||||||
|
onValidateObject={onValidateObject}
|
||||||
|
clearFieldErrors={clearFieldErrors}
|
||||||
|
fieldsErrors={fieldsErrors}
|
||||||
|
ref={this.processControlRef}
|
||||||
|
controlRef={controlRef}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</ClassNames>
|
||||||
</SortableListItem>
|
</SortableListItem>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
@ -335,7 +346,7 @@ export default class ListControl extends React.Component {
|
|||||||
const errorMessage = getErrorMessageForTypedFieldAndValue(field, item);
|
const errorMessage = getErrorMessageForTypedFieldAndValue(field, item);
|
||||||
return (
|
return (
|
||||||
<SortableListItem
|
<SortableListItem
|
||||||
className={cx(styles.listControlItem, styles.listControlItemCollapsed)}
|
css={[styles.listControlItem, styles.listControlItemCollapsed]}
|
||||||
index={index}
|
index={index}
|
||||||
key={`item-${index}`}
|
key={`item-${index}`}
|
||||||
>
|
>
|
||||||
@ -360,25 +371,37 @@ export default class ListControl extends React.Component {
|
|||||||
const listLabel = items.size === 1 ? labelSingular.toLowerCase() : label.toLowerCase();
|
const listLabel = items.size === 1 ? labelSingular.toLowerCase() : label.toLowerCase();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div id={forID} className={cx(classNameWrapper, components.objectWidgetTopBarContainer)}>
|
<ClassNames>
|
||||||
<ObjectWidgetTopBar
|
{({ cx, css }) => (
|
||||||
allowAdd={field.get('allow_add', true)}
|
<div
|
||||||
onAdd={this.handleAdd}
|
id={forID}
|
||||||
types={field.get(TYPES_KEY, null)}
|
className={cx(
|
||||||
onAddType={type => this.handleAddType(type, resolveFieldKeyType(field))}
|
classNameWrapper,
|
||||||
heading={`${items.size} ${listLabel}`}
|
css`
|
||||||
label={labelSingular.toLowerCase()}
|
${styleStrings.objectWidgetTopBarContainer}
|
||||||
onCollapseToggle={this.handleCollapseAllToggle}
|
`,
|
||||||
collapsed={itemsCollapsed.every(val => val === true)}
|
)}
|
||||||
/>
|
>
|
||||||
<SortableList
|
<ObjectWidgetTopBar
|
||||||
items={items}
|
allowAdd={field.get('allow_add', true)}
|
||||||
renderItem={this.renderItem}
|
onAdd={this.handleAdd}
|
||||||
onSortEnd={this.onSortEnd}
|
types={field.get(TYPES_KEY, null)}
|
||||||
useDragHandle
|
onAddType={type => this.handleAddType(type, resolveFieldKeyType(field))}
|
||||||
lockAxis="y"
|
heading={`${items.size} ${listLabel}`}
|
||||||
/>
|
label={labelSingular.toLowerCase()}
|
||||||
</div>
|
onCollapseToggle={this.handleCollapseAllToggle}
|
||||||
|
collapsed={itemsCollapsed.every(val => val === true)}
|
||||||
|
/>
|
||||||
|
<SortableList
|
||||||
|
items={items}
|
||||||
|
renderItem={this.renderItem}
|
||||||
|
onSortEnd={this.onSortEnd}
|
||||||
|
useDragHandle
|
||||||
|
lockAxis="y"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</ClassNames>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,13 +22,13 @@
|
|||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"cross-env": "^5.2.0",
|
"cross-env": "^5.2.0",
|
||||||
"css-loader": "^2.1.0",
|
"css-loader": "^2.1.1",
|
||||||
"to-string-loader": "^1.1.5",
|
"to-string-loader": "^1.1.5",
|
||||||
"webpack": "^4.16.1",
|
"webpack": "^4.29.6",
|
||||||
"webpack-cli": "^3.1.0"
|
"webpack-cli": "^3.2.3"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"emotion": "^9.2.6",
|
"@emotion/core": "^10.0.9",
|
||||||
"lodash": "^4.17.10",
|
"lodash": "^4.17.10",
|
||||||
"netlify-cms-ui-default": "^2.0.0",
|
"netlify-cms-ui-default": "^2.0.0",
|
||||||
"prop-types": "^15.5.10",
|
"prop-types": "^15.5.10",
|
||||||
@ -36,6 +36,6 @@
|
|||||||
"react-immutable-proptypes": "^2.1.0"
|
"react-immutable-proptypes": "^2.1.0"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"ol": "^5.3.0"
|
"ol": "^5.3.1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,6 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import { ClassNames } from '@emotion/core';
|
||||||
import olStyles from 'ol/ol.css';
|
import olStyles from 'ol/ol.css';
|
||||||
import Map from 'ol/Map.js';
|
import Map from 'ol/Map.js';
|
||||||
import View from 'ol/View.js';
|
import View from 'ol/View.js';
|
||||||
@ -7,13 +10,6 @@ import TileLayer from 'ol/layer/Tile.js';
|
|||||||
import VectorLayer from 'ol/layer/Vector.js';
|
import VectorLayer from 'ol/layer/Vector.js';
|
||||||
import OSMSource from 'ol/source/OSM.js';
|
import OSMSource from 'ol/source/OSM.js';
|
||||||
import VectorSource from 'ol/source/Vector.js';
|
import VectorSource from 'ol/source/Vector.js';
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
import React from 'react';
|
|
||||||
import { injectGlobal } from 'react-emotion';
|
|
||||||
|
|
||||||
injectGlobal`
|
|
||||||
${olStyles}
|
|
||||||
`;
|
|
||||||
|
|
||||||
const formatOptions = {
|
const formatOptions = {
|
||||||
dataProjection: 'EPSG:4326',
|
dataProjection: 'EPSG:4326',
|
||||||
@ -70,7 +66,23 @@ export default function withMapControl({ getFormat, getMap } = {}) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
return <div ref={this.mapContainer}> </div>;
|
return (
|
||||||
|
<ClassNames>
|
||||||
|
{({ cx, css }) => (
|
||||||
|
<div
|
||||||
|
className={cx(
|
||||||
|
this.props.classNameWrapper,
|
||||||
|
css`
|
||||||
|
${olStyles};
|
||||||
|
padding: 0;
|
||||||
|
overflow: hidden;
|
||||||
|
`,
|
||||||
|
)}
|
||||||
|
ref={this.mapContainer}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</ClassNames>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -21,9 +21,9 @@
|
|||||||
"build": "cross-env NODE_ENV=production webpack"
|
"build": "cross-env NODE_ENV=production webpack"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"is-hotkey": "^0.1.1",
|
"is-hotkey": "^0.1.4",
|
||||||
"mdast-util-definitions": "^1.2.2",
|
"mdast-util-definitions": "^1.2.3",
|
||||||
"mdast-util-to-string": "^1.0.4",
|
"mdast-util-to-string": "^1.0.5",
|
||||||
"rehype-parse": "^3.1.0",
|
"rehype-parse": "^3.1.0",
|
||||||
"rehype-remark": "^2.0.0",
|
"rehype-remark": "^2.0.0",
|
||||||
"rehype-stringify": "^3.0.0",
|
"rehype-stringify": "^3.0.0",
|
||||||
@ -42,18 +42,18 @@
|
|||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"cross-env": "^5.2.0",
|
"cross-env": "^5.2.0",
|
||||||
"webpack": "^4.16.1",
|
"webpack": "^4.29.6",
|
||||||
"webpack-cli": "^3.1.0"
|
"webpack-cli": "^3.2.3"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"emotion": "^9.2.6",
|
"@emotion/core": "^10.0.9",
|
||||||
|
"@emotion/styled": "^10.0.9",
|
||||||
"immutable": "^3.7.6",
|
"immutable": "^3.7.6",
|
||||||
"lodash": "^4.17.10",
|
"lodash": "^4.17.10",
|
||||||
"netlify-cms-ui-default": "^2.0.0",
|
"netlify-cms-ui-default": "^2.0.0",
|
||||||
"prop-types": "^15.5.10",
|
"prop-types": "^15.5.10",
|
||||||
"react": "^16.4.1",
|
"react": "^16.4.1",
|
||||||
"react-dom": "^16.0.0",
|
"react-dom": "^16.0.0",
|
||||||
"react-emotion": "^9.2.5",
|
|
||||||
"react-immutable-proptypes": "^2.1.0"
|
"react-immutable-proptypes": "^2.1.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||||
import styled, { css, cx } from 'react-emotion';
|
import styled from '@emotion/styled';
|
||||||
|
import { ClassNames } from '@emotion/core';
|
||||||
import { Editor as Slate } from 'slate-react';
|
import { Editor as Slate } from 'slate-react';
|
||||||
import Plain from 'slate-plain-serializer';
|
import Plain from 'slate-plain-serializer';
|
||||||
import { debounce } from 'lodash';
|
import { debounce } from 'lodash';
|
||||||
@ -9,8 +10,8 @@ import { lengths, fonts } from 'netlify-cms-ui-default';
|
|||||||
import { editorStyleVars, EditorControlBar } from '../styles';
|
import { editorStyleVars, EditorControlBar } from '../styles';
|
||||||
import Toolbar from './Toolbar';
|
import Toolbar from './Toolbar';
|
||||||
|
|
||||||
const styles = {
|
const styleStrings = {
|
||||||
slateRaw: css`
|
slateRaw: `
|
||||||
position: relative;
|
position: relative;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
overflow-x: auto;
|
overflow-x: auto;
|
||||||
@ -83,12 +84,21 @@ export default class RawEditor extends React.Component {
|
|||||||
rawMode
|
rawMode
|
||||||
/>
|
/>
|
||||||
</EditorControlBar>
|
</EditorControlBar>
|
||||||
<Slate
|
<ClassNames>
|
||||||
className={cx(className, styles.slateRaw)}
|
{({ css, cx }) => (
|
||||||
value={this.state.value}
|
<Slate
|
||||||
onChange={this.handleChange}
|
className={cx(
|
||||||
onPaste={this.handlePaste}
|
className,
|
||||||
/>
|
css`
|
||||||
|
${styleStrings.slateRaw}
|
||||||
|
`,
|
||||||
|
)}
|
||||||
|
value={this.state.value}
|
||||||
|
onChange={this.handleChange}
|
||||||
|
onPaste={this.handlePaste}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</ClassNames>
|
||||||
</RawEditorContainer>
|
</RawEditorContainer>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,8 @@
|
|||||||
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { Map } from 'immutable';
|
import { Map } from 'immutable';
|
||||||
import styled, { css } from 'react-emotion';
|
import styled from '@emotion/styled';
|
||||||
|
import { css } from '@emotion/core';
|
||||||
import { partial, capitalize } from 'lodash';
|
import { partial, capitalize } from 'lodash';
|
||||||
import { ListItemTopBar, components, colors, lengths } from 'netlify-cms-ui-default';
|
import { ListItemTopBar, components, colors, lengths } from 'netlify-cms-ui-default';
|
||||||
import { getEditorControl, getEditorComponents } from './index';
|
import { getEditorControl, getEditorComponents } from './index';
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||||
import styled, { css } from 'react-emotion';
|
import styled from '@emotion/styled';
|
||||||
|
import { css } from '@emotion/core';
|
||||||
import { List } from 'immutable';
|
import { List } from 'immutable';
|
||||||
import {
|
import {
|
||||||
Toggle,
|
Toggle,
|
||||||
@ -24,6 +25,7 @@ const ToolbarContainer = styled.div`
|
|||||||
padding: 11px 14px;
|
padding: 11px 14px;
|
||||||
min-height: 58px;
|
min-height: 58px;
|
||||||
transition: background-color ${transitions.main}, color ${transitions.main};
|
transition: background-color ${transitions.main}, color ${transitions.main};
|
||||||
|
color: ${colors.text};
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const ToolbarDropdownWrapper = styled.div`
|
const ToolbarDropdownWrapper = styled.div`
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import styled from 'react-emotion';
|
import styled from '@emotion/styled';
|
||||||
import { Icon, buttons } from 'netlify-cms-ui-default';
|
import { Icon, buttons } from 'netlify-cms-ui-default';
|
||||||
|
|
||||||
const StyledToolbarButton = styled.button`
|
const StyledToolbarButton = styled.button`
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||||
import styled, { cx } from 'react-emotion';
|
import styled from '@emotion/styled';
|
||||||
|
import { ClassNames } from '@emotion/core';
|
||||||
import { get, isEmpty, debounce, uniq } from 'lodash';
|
import { get, isEmpty, debounce, uniq } from 'lodash';
|
||||||
import { List } from 'immutable';
|
import { List } from 'immutable';
|
||||||
import { Value, Document, Block, Text } from 'slate';
|
import { Value, Document, Block, Text } from 'slate';
|
||||||
@ -259,19 +260,28 @@ export default class Editor extends React.Component {
|
|||||||
buttons={field.get('buttons')}
|
buttons={field.get('buttons')}
|
||||||
/>
|
/>
|
||||||
</EditorControlBar>
|
</EditorControlBar>
|
||||||
<Slate
|
<ClassNames>
|
||||||
className={cx(className, visualEditorStyles)}
|
{({ css, cx }) => (
|
||||||
value={this.state.value}
|
<Slate
|
||||||
renderNode={renderNode}
|
className={cx(
|
||||||
renderMark={renderMark}
|
className,
|
||||||
validateNode={validateNode}
|
css`
|
||||||
plugins={plugins}
|
${visualEditorStyles}
|
||||||
onChange={this.handleChange}
|
`,
|
||||||
onKeyDown={onKeyDown}
|
)}
|
||||||
onPaste={this.handlePaste}
|
value={this.state.value}
|
||||||
ref={this.processRef}
|
renderNode={renderNode}
|
||||||
spellCheck
|
renderMark={renderMark}
|
||||||
/>
|
validateNode={validateNode}
|
||||||
|
plugins={plugins}
|
||||||
|
onChange={this.handleChange}
|
||||||
|
onKeyDown={onKeyDown}
|
||||||
|
onPaste={this.handlePaste}
|
||||||
|
ref={this.processRef}
|
||||||
|
spellCheck
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</ClassNames>
|
||||||
</VisualEditorContainer>
|
</VisualEditorContainer>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,7 @@
|
|||||||
import { css } from 'react-emotion';
|
|
||||||
import { colors, lengths, fonts } from 'netlify-cms-ui-default';
|
import { colors, lengths, fonts } from 'netlify-cms-ui-default';
|
||||||
import { editorStyleVars } from '../styles';
|
import { editorStyleVars } from '../styles';
|
||||||
|
|
||||||
export default css`
|
export default `
|
||||||
position: relative;
|
position: relative;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
overflow-x: auto;
|
overflow-x: auto;
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import styled from 'react-emotion';
|
import styled from '@emotion/styled';
|
||||||
|
|
||||||
export const editorStyleVars = {
|
export const editorStyleVars = {
|
||||||
stickyDistanceBottom: '100px',
|
stickyDistanceBottom: '100px',
|
||||||
|
@ -21,11 +21,10 @@
|
|||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"cross-env": "^5.2.0",
|
"cross-env": "^5.2.0",
|
||||||
"webpack": "^4.16.1",
|
"webpack": "^4.29.6",
|
||||||
"webpack-cli": "^3.1.0"
|
"webpack-cli": "^3.2.3"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"emotion": "^9.2.6",
|
|
||||||
"netlify-cms-ui-default": "^2.0.0",
|
"netlify-cms-ui-default": "^2.0.0",
|
||||||
"prop-types": "^15.5.10",
|
"prop-types": "^15.5.10",
|
||||||
"react": "^16.4.1"
|
"react": "^16.4.1"
|
||||||
|
@ -23,17 +23,17 @@
|
|||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"cross-env": "^5.2.0",
|
"cross-env": "^5.2.0",
|
||||||
"webpack": "^4.16.1",
|
"webpack": "^4.29.6",
|
||||||
"webpack-cli": "^3.1.0"
|
"webpack-cli": "^3.2.3"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"emotion": "^9.2.6",
|
"@emotion/core": "^10.0.9",
|
||||||
|
"@emotion/styled": "^10.0.9",
|
||||||
"immutable": "^3.7.6",
|
"immutable": "^3.7.6",
|
||||||
"lodash": "^4.17.10",
|
"lodash": "^4.17.10",
|
||||||
"netlify-cms-ui-default": "^2.0.0",
|
"netlify-cms-ui-default": "^2.0.0",
|
||||||
"prop-types": "^15.5.10",
|
"prop-types": "^15.5.10",
|
||||||
"react": "^16.4.1",
|
"react": "^16.4.1",
|
||||||
"react-emotion": "^9.2.6",
|
|
||||||
"react-immutable-proptypes": "^2.1.0"
|
"react-immutable-proptypes": "^2.1.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,20 +1,23 @@
|
|||||||
import React, { Component } from 'react';
|
import React from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||||
import { css, cx } from 'react-emotion';
|
import { ClassNames } from '@emotion/core';
|
||||||
import { Map, List } from 'immutable';
|
import { Map, List } from 'immutable';
|
||||||
import { ObjectWidgetTopBar, components } from 'netlify-cms-ui-default';
|
import { ObjectWidgetTopBar, lengths } from 'netlify-cms-ui-default';
|
||||||
|
|
||||||
const styles = {
|
const styleStrings = {
|
||||||
nestedObjectControl: css`
|
nestedObjectControl: `
|
||||||
padding: 6px 14px 14px;
|
padding: 6px 14px 14px;
|
||||||
border-top: 0;
|
border-top: 0;
|
||||||
border-top-left-radius: 0;
|
border-top-left-radius: 0;
|
||||||
border-top-right-radius: 0;
|
border-top-right-radius: 0;
|
||||||
`,
|
`,
|
||||||
|
objectWidgetTopBarContainer: `
|
||||||
|
padding: ${lengths.objectWidgetTopBarContainerPadding}
|
||||||
|
`,
|
||||||
};
|
};
|
||||||
|
|
||||||
export default class ObjectControl extends Component {
|
export default class ObjectControl extends React.Component {
|
||||||
componentValidate = {};
|
componentValidate = {};
|
||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
@ -116,20 +119,32 @@ export default class ObjectControl extends Component {
|
|||||||
|
|
||||||
if (multiFields || singleField) {
|
if (multiFields || singleField) {
|
||||||
return (
|
return (
|
||||||
<div
|
<ClassNames>
|
||||||
id={forID}
|
{({ css, cx }) => (
|
||||||
className={cx(classNameWrapper, components.objectWidgetTopBarContainer, {
|
<div
|
||||||
[styles.nestedObjectControl]: forList,
|
id={forID}
|
||||||
})}
|
className={cx(
|
||||||
>
|
classNameWrapper,
|
||||||
{forList ? null : (
|
css`
|
||||||
<ObjectWidgetTopBar
|
${styleStrings.objectWidgetTopBarContainer}
|
||||||
collapsed={collapsed}
|
`,
|
||||||
onCollapseToggle={this.handleCollapseToggle}
|
{
|
||||||
/>
|
[css`
|
||||||
|
${styleStrings.nestedObjectControl}
|
||||||
|
`]: forList,
|
||||||
|
},
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
{forList ? null : (
|
||||||
|
<ObjectWidgetTopBar
|
||||||
|
collapsed={collapsed}
|
||||||
|
onCollapseToggle={this.handleCollapseToggle}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
{collapsed ? null : this.renderFields(multiFields, singleField)}
|
||||||
|
</div>
|
||||||
)}
|
)}
|
||||||
{collapsed ? null : this.renderFields(multiFields, singleField)}
|
</ClassNames>
|
||||||
</div>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,21 +21,21 @@
|
|||||||
"build": "cross-env NODE_ENV=production webpack"
|
"build": "cross-env NODE_ENV=production webpack"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"react-select": "^2.3.0"
|
"react-select": "^2.4.2"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"cross-env": "^5.2.0",
|
"cross-env": "^5.2.0",
|
||||||
"webpack": "^4.16.1",
|
"webpack": "^4.29.6",
|
||||||
"webpack-cli": "^3.1.0"
|
"webpack-cli": "^3.2.3"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"emotion": "^9.2.6",
|
"@emotion/core": "^10.0.9",
|
||||||
|
"@emotion/styled": "^10.0.9",
|
||||||
"immutable": "^3.7.6",
|
"immutable": "^3.7.6",
|
||||||
"lodash": "^4.17.10",
|
"lodash": "^4.17.10",
|
||||||
"netlify-cms-ui-default": "^2.0.0",
|
"netlify-cms-ui-default": "^2.0.0",
|
||||||
"prop-types": "^15.5.10",
|
"prop-types": "^15.5.10",
|
||||||
"react": "^16.4.1",
|
"react": "^16.4.1",
|
||||||
"react-emotion": "^9.2.5",
|
|
||||||
"uuid": "^3.1.0"
|
"uuid": "^3.1.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,207 +1,206 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { fromJS, Map } from 'immutable';
|
import { fromJS, Map } from 'immutable';
|
||||||
import { last } from 'lodash';
|
import { last } from 'lodash';
|
||||||
import { render, fireEvent, wait } from 'react-testing-library';
|
import { render, fireEvent, wait } from 'react-testing-library';
|
||||||
import 'react-testing-library/cleanup-after-each';
|
import 'react-testing-library/cleanup-after-each';
|
||||||
import 'jest-dom/extend-expect';
|
import 'jest-dom/extend-expect';
|
||||||
import { RelationControl } from '../';
|
import { RelationControl } from '../';
|
||||||
|
|
||||||
const fieldConfig = {
|
const fieldConfig = {
|
||||||
name: 'post',
|
name: 'post',
|
||||||
collection: 'posts',
|
collection: 'posts',
|
||||||
displayFields: ['title', 'slug'],
|
displayFields: ['title', 'slug'],
|
||||||
searchFields: ['title', 'body'],
|
searchFields: ['title', 'body'],
|
||||||
valueField: 'title',
|
valueField: 'title',
|
||||||
};
|
};
|
||||||
|
|
||||||
const generateHits = length => {
|
const generateHits = length => {
|
||||||
const hits = Array.from({ length }, (val, idx) => {
|
const hits = Array.from({ length }, (val, idx) => {
|
||||||
const title = `Post # ${idx + 1}`;
|
const title = `Post # ${idx + 1}`;
|
||||||
const slug = `post-number-${idx + 1}`;
|
const slug = `post-number-${idx + 1}`;
|
||||||
return { collection: 'posts', data: { title, slug } };
|
return { collection: 'posts', data: { title, slug } };
|
||||||
});
|
});
|
||||||
|
|
||||||
return [
|
return [
|
||||||
...hits,
|
...hits,
|
||||||
{
|
{
|
||||||
collection: 'posts',
|
collection: 'posts',
|
||||||
data: { title: 'YAML post', slug: 'post-yaml', body: 'Body yaml' },
|
data: { title: 'YAML post', slug: 'post-yaml', body: 'Body yaml' },
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
|
||||||
class RelationController extends React.Component {
|
class RelationController extends React.Component {
|
||||||
state = {
|
state = {
|
||||||
value: this.props.value,
|
value: this.props.value,
|
||||||
queryHits: Map(),
|
queryHits: Map(),
|
||||||
};
|
};
|
||||||
|
|
||||||
handleOnChange = jest.fn(value => {
|
handleOnChange = jest.fn(value => {
|
||||||
this.setState({ ...this.state, value });
|
this.setState({ ...this.state, value });
|
||||||
});
|
});
|
||||||
|
|
||||||
setQueryHits = jest.fn(hits => {
|
setQueryHits = jest.fn(hits => {
|
||||||
const queryHits = Map().set('relation-field', hits);
|
const queryHits = Map().set('relation-field', hits);
|
||||||
this.setState({ ...this.state, queryHits });
|
this.setState({ ...this.state, queryHits });
|
||||||
});
|
});
|
||||||
|
|
||||||
query = jest.fn((...args) => {
|
query = jest.fn((...args) => {
|
||||||
const queryHits = generateHits(25);
|
const queryHits = generateHits(25);
|
||||||
if (last(args) === 'YAML') {
|
if (last(args) === 'YAML') {
|
||||||
return Promise.resolve({ payload: { response: { hits: [last(queryHits)] } } });
|
return Promise.resolve({ payload: { response: { hits: [last(queryHits)] } } });
|
||||||
}
|
}
|
||||||
return Promise.resolve({ payload: { response: { hits: queryHits } } });
|
return Promise.resolve({ payload: { response: { hits: queryHits } } });
|
||||||
});
|
});
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
return this.props.children({
|
return this.props.children({
|
||||||
value: this.state.value,
|
value: this.state.value,
|
||||||
handleOnChange: this.handleOnChange,
|
handleOnChange: this.handleOnChange,
|
||||||
query: this.query,
|
query: this.query,
|
||||||
queryHits: this.state.queryHits,
|
queryHits: this.state.queryHits,
|
||||||
setQueryHits: this.setQueryHits,
|
setQueryHits: this.setQueryHits,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function setup({ field, value }) {
|
function setup({ field, value }) {
|
||||||
let renderArgs;
|
let renderArgs;
|
||||||
const setActiveSpy = jest.fn();
|
const setActiveSpy = jest.fn();
|
||||||
const setInactiveSpy = jest.fn();
|
const setInactiveSpy = jest.fn();
|
||||||
|
|
||||||
const helpers = render(
|
const helpers = render(
|
||||||
<RelationController value={value}>
|
<RelationController value={value}>
|
||||||
{({ handleOnChange, value, query, queryHits, setQueryHits }) => {
|
{({ handleOnChange, value, query, queryHits, setQueryHits }) => {
|
||||||
renderArgs = { value, onChangeSpy: handleOnChange, setQueryHitsSpy: setQueryHits };
|
renderArgs = { value, onChangeSpy: handleOnChange, setQueryHitsSpy: setQueryHits };
|
||||||
return (
|
return (
|
||||||
<RelationControl
|
<RelationControl
|
||||||
field={field}
|
field={field}
|
||||||
value={value}
|
value={value}
|
||||||
query={query}
|
query={query}
|
||||||
queryHits={queryHits}
|
queryHits={queryHits}
|
||||||
onChange={handleOnChange}
|
onChange={handleOnChange}
|
||||||
forID="relation-field"
|
forID="relation-field"
|
||||||
classNameWrapper=""
|
classNameWrapper=""
|
||||||
setActiveStyle={setActiveSpy}
|
setActiveStyle={setActiveSpy}
|
||||||
setInactiveStyle={setInactiveSpy}
|
setInactiveStyle={setInactiveSpy}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}}
|
}}
|
||||||
</RelationController>,
|
</RelationController>,
|
||||||
);
|
);
|
||||||
|
|
||||||
const input = helpers.container.querySelector('input');
|
const input = helpers.container.querySelector('input');
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...helpers,
|
...helpers,
|
||||||
...renderArgs,
|
...renderArgs,
|
||||||
setActiveSpy,
|
setActiveSpy,
|
||||||
setInactiveSpy,
|
setInactiveSpy,
|
||||||
input,
|
input,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
describe('Relation widget', () => {
|
describe('Relation widget', () => {
|
||||||
it('should list the first 20 option hits on initial load', async () => {
|
it('should list the first 20 option hits on initial load', async () => {
|
||||||
const field = fromJS(fieldConfig);
|
const field = fromJS(fieldConfig);
|
||||||
const { getAllByRole, input } = setup({ field });
|
const { getAllByText, input } = setup({ field });
|
||||||
|
fireEvent.keyDown(input, { key: 'ArrowDown' });
|
||||||
await wait(() => {
|
|
||||||
fireEvent.keyDown(input, { key: 'ArrowDown' });
|
await wait(() => {
|
||||||
expect(getAllByRole('option')).toHaveLength(20);
|
expect(getAllByText(/^Post # (\d{1,2}) post-number-\1$/)).toHaveLength(20);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should update option list based on search term', async () => {
|
it('should update option list based on search term', async () => {
|
||||||
const field = fromJS(fieldConfig);
|
const field = fromJS(fieldConfig);
|
||||||
const { getAllByRole, getByText, input } = setup({ field });
|
const { getAllByText, input } = setup({ field });
|
||||||
|
fireEvent.change(input, { target: { value: 'YAML' } });
|
||||||
await wait(() => {
|
|
||||||
fireEvent.change(input, { target: { value: 'YAML' } });
|
await wait(() => {
|
||||||
expect(getAllByRole('option')).toHaveLength(1);
|
expect(getAllByText('YAML post post-yaml')).toHaveLength(1);
|
||||||
expect(getByText('YAML post post-yaml')).toBeInTheDocument();
|
});
|
||||||
});
|
});
|
||||||
});
|
|
||||||
|
it('should call onChange with correct selectedItem value and metadata', async () => {
|
||||||
it('should call onChange with correct selectedItem value and metadata', async () => {
|
const field = fromJS(fieldConfig);
|
||||||
const field = fromJS(fieldConfig);
|
const { getByText, input, onChangeSpy } = setup({ field });
|
||||||
const { getByText, input, onChangeSpy } = setup({ field });
|
const value = 'Post # 1';
|
||||||
const value = 'Post # 1';
|
const label = 'Post # 1 post-number-1';
|
||||||
const label = 'Post # 1 post-number-1';
|
const metadata = {
|
||||||
const metadata = {
|
post: { posts: { 'Post # 1': { title: 'Post # 1', slug: 'post-number-1' } } },
|
||||||
post: { posts: { 'Post # 1': { title: 'Post # 1', slug: 'post-number-1' } } },
|
};
|
||||||
};
|
|
||||||
|
await wait(() => {
|
||||||
await wait(() => {
|
fireEvent.keyDown(input, { key: 'ArrowDown' });
|
||||||
fireEvent.keyDown(input, { key: 'ArrowDown' });
|
fireEvent.click(getByText(label));
|
||||||
fireEvent.click(getByText(label));
|
expect(onChangeSpy).toHaveBeenCalledTimes(1);
|
||||||
expect(onChangeSpy).toHaveBeenCalledTimes(1);
|
expect(onChangeSpy).toHaveBeenCalledWith(value, metadata);
|
||||||
expect(onChangeSpy).toHaveBeenCalledWith(value, metadata);
|
});
|
||||||
});
|
});
|
||||||
});
|
|
||||||
|
it('should update metadata for initial preview', async () => {
|
||||||
it('should update metadata for initial preview', async () => {
|
const field = fromJS(fieldConfig);
|
||||||
const field = fromJS(fieldConfig);
|
const value = 'Post # 1';
|
||||||
const value = 'Post # 1';
|
const { getByText, onChangeSpy, setQueryHitsSpy } = setup({ field, value });
|
||||||
const { getByText, onChangeSpy, setQueryHitsSpy } = setup({ field, value });
|
const label = 'Post # 1 post-number-1';
|
||||||
const label = 'Post # 1 post-number-1';
|
const metadata = {
|
||||||
const metadata = {
|
post: { posts: { 'Post # 1': { title: 'Post # 1', slug: 'post-number-1' } } },
|
||||||
post: { posts: { 'Post # 1': { title: 'Post # 1', slug: 'post-number-1' } } },
|
};
|
||||||
};
|
|
||||||
|
setQueryHitsSpy(generateHits(1));
|
||||||
setQueryHitsSpy(generateHits(1));
|
|
||||||
|
await wait(() => {
|
||||||
await wait(() => {
|
expect(getByText(label)).toBeInTheDocument();
|
||||||
expect(getByText(label)).toBeInTheDocument();
|
expect(onChangeSpy).toHaveBeenCalledTimes(1);
|
||||||
expect(onChangeSpy).toHaveBeenCalledTimes(1);
|
expect(onChangeSpy).toHaveBeenCalledWith(value, metadata);
|
||||||
expect(onChangeSpy).toHaveBeenCalledWith(value, metadata);
|
});
|
||||||
});
|
});
|
||||||
});
|
|
||||||
|
describe('with multiple', () => {
|
||||||
describe('with multiple', () => {
|
it('should call onChange with correct selectedItem value and metadata', async () => {
|
||||||
it('should call onChange with correct selectedItem value and metadata', async () => {
|
const field = fromJS({ ...fieldConfig, multiple: true });
|
||||||
const field = fromJS({ ...fieldConfig, multiple: true });
|
const { getByText, input, onChangeSpy } = setup({ field });
|
||||||
const { getByText, input, onChangeSpy } = setup({ field });
|
const metadata1 = {
|
||||||
const metadata1 = {
|
post: { posts: { 'Post # 1': { title: 'Post # 1', slug: 'post-number-1' } } },
|
||||||
post: { posts: { 'Post # 1': { title: 'Post # 1', slug: 'post-number-1' } } },
|
};
|
||||||
};
|
const metadata2 = {
|
||||||
const metadata2 = {
|
post: { posts: { 'Post # 2': { title: 'Post # 2', slug: 'post-number-2' } } },
|
||||||
post: { posts: { 'Post # 2': { title: 'Post # 2', slug: 'post-number-2' } } },
|
};
|
||||||
};
|
|
||||||
|
await wait(() => {
|
||||||
await wait(() => {
|
fireEvent.keyDown(input, { key: 'ArrowDown' });
|
||||||
fireEvent.keyDown(input, { key: 'ArrowDown' });
|
fireEvent.click(getByText('Post # 1 post-number-1'));
|
||||||
fireEvent.click(getByText('Post # 1 post-number-1'));
|
fireEvent.keyDown(input, { key: 'ArrowDown' });
|
||||||
fireEvent.keyDown(input, { key: 'ArrowDown' });
|
fireEvent.click(getByText('Post # 2 post-number-2'));
|
||||||
fireEvent.click(getByText('Post # 2 post-number-2'));
|
|
||||||
|
expect(onChangeSpy).toHaveBeenCalledTimes(2);
|
||||||
expect(onChangeSpy).toHaveBeenCalledTimes(2);
|
expect(onChangeSpy).toHaveBeenCalledWith(fromJS(['Post # 1']), metadata1);
|
||||||
expect(onChangeSpy).toHaveBeenCalledWith(fromJS(['Post # 1']), metadata1);
|
expect(onChangeSpy).toHaveBeenCalledWith(fromJS(['Post # 1', 'Post # 2']), metadata2);
|
||||||
expect(onChangeSpy).toHaveBeenCalledWith(fromJS(['Post # 1', 'Post # 2']), metadata2);
|
});
|
||||||
});
|
});
|
||||||
});
|
|
||||||
|
it('should update metadata for initial preview', async () => {
|
||||||
it('should update metadata for initial preview', async () => {
|
const field = fromJS({ ...fieldConfig, multiple: true });
|
||||||
const field = fromJS({ ...fieldConfig, multiple: true });
|
const value = fromJS(['Post # 1', 'Post # 2']);
|
||||||
const value = fromJS(['Post # 1', 'Post # 2']);
|
const { getByText, onChangeSpy, setQueryHitsSpy } = setup({ field, value });
|
||||||
const { getByText, onChangeSpy, setQueryHitsSpy } = setup({ field, value });
|
const metadata1 = {
|
||||||
const metadata1 = {
|
post: { posts: { 'Post # 1': { title: 'Post # 1', slug: 'post-number-1' } } },
|
||||||
post: { posts: { 'Post # 1': { title: 'Post # 1', slug: 'post-number-1' } } },
|
};
|
||||||
};
|
const metadata2 = {
|
||||||
const metadata2 = {
|
post: { posts: { 'Post # 2': { title: 'Post # 2', slug: 'post-number-2' } } },
|
||||||
post: { posts: { 'Post # 2': { title: 'Post # 2', slug: 'post-number-2' } } },
|
};
|
||||||
};
|
|
||||||
|
setQueryHitsSpy(generateHits(2));
|
||||||
setQueryHitsSpy(generateHits(2));
|
|
||||||
|
await wait(() => {
|
||||||
await wait(() => {
|
expect(getByText('Post # 1 post-number-1')).toBeInTheDocument();
|
||||||
expect(getByText('Post # 1 post-number-1')).toBeInTheDocument();
|
expect(getByText('Post # 2 post-number-2')).toBeInTheDocument();
|
||||||
expect(getByText('Post # 2 post-number-2')).toBeInTheDocument();
|
|
||||||
|
expect(onChangeSpy).toHaveBeenCalledTimes(2);
|
||||||
expect(onChangeSpy).toHaveBeenCalledTimes(2);
|
expect(onChangeSpy).toHaveBeenCalledWith(value, metadata1);
|
||||||
expect(onChangeSpy).toHaveBeenCalledWith(value, metadata1);
|
expect(onChangeSpy).toHaveBeenCalledWith(value, metadata2);
|
||||||
expect(onChangeSpy).toHaveBeenCalledWith(value, metadata2);
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
|
||||||
|
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