@plone/volto 17.0.0-alpha.13 → 17.0.0-alpha.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.yarn/install-state.gz +0 -0
- package/CHANGELOG.md +68 -0
- package/README.md +2 -2
- package/docker-compose.yml +1 -1
- package/locales/ca/LC_MESSAGES/volto.po +5 -0
- package/locales/ca.json +1 -1
- package/locales/de/LC_MESSAGES/volto.po +5 -0
- package/locales/de.json +1 -1
- package/locales/en/LC_MESSAGES/volto.po +5 -0
- package/locales/en.json +1 -1
- package/locales/es/LC_MESSAGES/volto.po +49 -44
- package/locales/es.json +1 -1
- package/locales/eu/LC_MESSAGES/volto.po +5 -0
- package/locales/eu.json +1 -1
- package/locales/fi/LC_MESSAGES/volto.po +5 -0
- package/locales/fi.json +1 -1
- package/locales/fr/LC_MESSAGES/volto.po +5 -0
- package/locales/fr.json +1 -1
- package/locales/it/LC_MESSAGES/volto.po +5 -0
- package/locales/it.json +1 -1
- package/locales/ja/LC_MESSAGES/volto.po +5 -0
- package/locales/ja.json +1 -1
- package/locales/nl/LC_MESSAGES/volto.po +5 -0
- package/locales/nl.json +1 -1
- package/locales/pt/LC_MESSAGES/volto.po +5 -0
- package/locales/pt.json +1 -1
- package/locales/pt_BR/LC_MESSAGES/volto.po +5 -0
- package/locales/pt_BR.json +1 -1
- package/locales/ro/LC_MESSAGES/volto.po +5 -0
- package/locales/ro.json +1 -1
- package/locales/volto.pot +5 -0
- package/locales/zh_CN/LC_MESSAGES/volto.po +5 -0
- package/locales/zh_CN.json +1 -1
- package/package.json +2 -1
- package/packages/volto-slate/package.json +1 -1
- package/packages/volto-slate/src/actions/index.js +1 -1
- package/packages/volto-slate/src/blocks/Text/TextBlockView.jsx +20 -16
- package/packages/volto-slate/src/blocks/Text/index.js +2 -2
- package/packages/volto-slate/src/editor/config.jsx +5 -4
- package/packages/volto-slate/src/editor/index.js +4 -4
- package/packages/volto-slate/src/editor/less/slate.less +28 -0
- package/packages/volto-slate/src/editor/render.jsx +68 -8
- package/packages/volto-slate/src/editor/ui/SlateContextToolbar.jsx +2 -2
- package/packages/volto-slate/src/editor/ui/index.js +15 -15
- package/packages/volto-slate/src/index.js +2 -2
- package/src/components/manage/AnchorPlugin/index.jsx +2 -2
- package/src/components/manage/AnchorPlugin/utils/EditorUtils.js +3 -1
- package/src/components/manage/Blocks/Block/Style.jsx +2 -2
- package/src/components/manage/Blocks/Listing/DefaultTemplate.jsx +18 -3
- package/src/components/manage/Blocks/Listing/ListingBody.jsx +30 -8
- package/src/components/manage/Blocks/Listing/getAsyncData.js +3 -5
- package/src/components/manage/Blocks/Search/components/index.js +13 -13
- package/src/components/manage/Blocks/Search/hocs/index.js +2 -2
- package/src/components/manage/Blocks/Search/hocs/withQueryString.jsx +2 -2
- package/src/components/manage/Blocks/Title/View.jsx +15 -5
- package/src/components/manage/Blocks/Title/View.test.jsx +16 -1
- package/src/components/manage/Blocks/ToC/View.jsx +8 -1
- package/src/components/manage/Blocks/ToC/variations/DefaultTocRenderer.jsx +17 -4
- package/src/components/manage/Blocks/ToC/variations/HorizontalMenu.jsx +6 -2
- package/src/components/manage/Blocks/ToC/variations/index.js +3 -1
- package/src/components/theme/Anontools/Anontools.jsx +45 -72
- package/src/components/theme/Anontools/Anontools.stories.jsx +16 -6
- package/src/components/theme/Anontools/Anontools.test.jsx +16 -2
- package/src/config/RichTextEditor/Blocks.jsx +2 -2
- package/src/config/RichTextEditor/FromHTML.jsx +2 -2
- package/src/config/RichTextEditor/Styles.jsx +1 -1
- package/src/constants/Indexes.js +3 -1
- package/src/express-middleware/devproxy.js +1 -1
- package/src/express-middleware/files.js +3 -3
- package/src/express-middleware/images.js +4 -4
- package/src/express-middleware/robotstxt.js +1 -1
- package/src/express-middleware/sitemap.js +1 -1
- package/src/express-middleware/static.js +3 -3
- package/src/helpers/Extensions/index.js +2 -1
- package/src/helpers/MessageLabels/MessageLabels.js +4 -0
- package/src/helpers/ScrollToTop/ScrollToTop.jsx +5 -3
- package/src/helpers/Utils/UseDetectClickOutside.stories.jsx +191 -0
- package/src/helpers/index.js +9 -10
- package/src/hooks/clipboard/useClipboard.js +26 -0
- package/src/hooks/content/useContent.js +31 -0
- package/src/hooks/index.js +2 -0
- package/src/middleware/index.js +2 -2
- package/src/start-server.js +2 -2
- package/theme/themes/pastanaga/extras/blocks.less +3 -1
|
@@ -9,15 +9,19 @@ import { map } from 'lodash';
|
|
|
9
9
|
import { Menu } from 'semantic-ui-react';
|
|
10
10
|
import { FormattedMessage, injectIntl } from 'react-intl';
|
|
11
11
|
import AnchorLink from 'react-anchor-link-smooth-scroll';
|
|
12
|
+
import Slugger from 'github-slugger';
|
|
12
13
|
|
|
13
14
|
const RenderMenuItems = ({ items }) => {
|
|
14
15
|
return map(items, (item) => {
|
|
15
|
-
const { id, level, title } = item;
|
|
16
|
+
const { id, level, title, override_toc, plaintext } = item;
|
|
17
|
+
const slug = override_toc
|
|
18
|
+
? Slugger.slug(plaintext)
|
|
19
|
+
: Slugger.slug(title) || id;
|
|
16
20
|
return (
|
|
17
21
|
item && (
|
|
18
22
|
<React.Fragment key={id}>
|
|
19
23
|
<Menu.Item className={`headline-${level}`}>
|
|
20
|
-
<AnchorLink href={`#${
|
|
24
|
+
<AnchorLink href={`#${slug}`}>{title}</AnchorLink>
|
|
21
25
|
</Menu.Item>
|
|
22
26
|
{item.items?.length > 0 && <RenderMenuItems items={item.items} />}
|
|
23
27
|
</React.Fragment>
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import DefaultTocRenderer from './DefaultTocRenderer';
|
|
2
2
|
import HorizontalMenu from './HorizontalMenu';
|
|
3
3
|
|
|
4
|
-
|
|
4
|
+
const ToCVariations = [
|
|
5
5
|
{
|
|
6
6
|
id: 'default',
|
|
7
7
|
title: 'Listing (default)',
|
|
@@ -14,3 +14,5 @@ export default [
|
|
|
14
14
|
view: HorizontalMenu,
|
|
15
15
|
},
|
|
16
16
|
];
|
|
17
|
+
|
|
18
|
+
export default ToCVariations;
|
|
@@ -1,83 +1,56 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Anontools component.
|
|
3
|
-
* @module components/theme/Anontools/Anontools
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import React, { Component } from 'react';
|
|
7
1
|
import PropTypes from 'prop-types';
|
|
8
|
-
import { connect } from 'react-redux';
|
|
9
2
|
import { Link } from 'react-router-dom';
|
|
10
3
|
import { Menu } from 'semantic-ui-react';
|
|
11
4
|
import { FormattedMessage } from 'react-intl';
|
|
5
|
+
import { flattenToAppURL } from '@plone/volto/helpers';
|
|
6
|
+
import { useToken } from '@plone/volto/hooks/userSession/useToken';
|
|
7
|
+
import { useContent } from '@plone/volto/hooks/content/useContent';
|
|
12
8
|
import config from '@plone/volto/registry';
|
|
13
9
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
export class Anontools extends Component {
|
|
18
|
-
/**
|
|
19
|
-
* Property types.
|
|
20
|
-
* @property {Object} propTypes Property types.
|
|
21
|
-
* @static
|
|
22
|
-
*/
|
|
23
|
-
static propTypes = {
|
|
24
|
-
token: PropTypes.string,
|
|
25
|
-
content: PropTypes.shape({
|
|
26
|
-
'@id': PropTypes.string,
|
|
27
|
-
}),
|
|
28
|
-
};
|
|
29
|
-
|
|
30
|
-
/**
|
|
31
|
-
* Default properties.
|
|
32
|
-
* @property {Object} defaultProps Default properties.
|
|
33
|
-
* @static
|
|
34
|
-
*/
|
|
35
|
-
static defaultProps = {
|
|
36
|
-
token: null,
|
|
37
|
-
content: {
|
|
38
|
-
'@id': null,
|
|
39
|
-
},
|
|
40
|
-
};
|
|
10
|
+
const Anontools = () => {
|
|
11
|
+
const token = useToken();
|
|
12
|
+
const { data: content } = useContent();
|
|
41
13
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
14
|
+
const { settings } = config;
|
|
15
|
+
return (
|
|
16
|
+
!token && (
|
|
17
|
+
<Menu pointing secondary floated="right">
|
|
18
|
+
<Menu.Item>
|
|
19
|
+
<Link
|
|
20
|
+
aria-label="login"
|
|
21
|
+
to={`/login${
|
|
22
|
+
content?.['@id']
|
|
23
|
+
? `?return_url=${flattenToAppURL(content['@id'])}`
|
|
24
|
+
: ''
|
|
25
|
+
}`}
|
|
26
|
+
>
|
|
27
|
+
<FormattedMessage id="Log in" defaultMessage="Log in" />
|
|
28
|
+
</Link>
|
|
29
|
+
</Menu.Item>
|
|
30
|
+
{settings.showSelfRegistration && (
|
|
52
31
|
<Menu.Item>
|
|
53
|
-
<Link
|
|
54
|
-
|
|
55
|
-
to={`/login${
|
|
56
|
-
this.props.content?.['@id']
|
|
57
|
-
? `?return_url=${this.props.content['@id'].replace(
|
|
58
|
-
settings.apiPath,
|
|
59
|
-
'',
|
|
60
|
-
)}`
|
|
61
|
-
: ''
|
|
62
|
-
}`}
|
|
63
|
-
>
|
|
64
|
-
<FormattedMessage id="Log in" defaultMessage="Log in" />
|
|
32
|
+
<Link aria-label="register" to="/register">
|
|
33
|
+
<FormattedMessage id="Register" defaultMessage="Register" />
|
|
65
34
|
</Link>
|
|
66
35
|
</Menu.Item>
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
36
|
+
)}
|
|
37
|
+
</Menu>
|
|
38
|
+
)
|
|
39
|
+
);
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
export default Anontools;
|
|
43
|
+
|
|
44
|
+
Anontools.propTypes = {
|
|
45
|
+
token: PropTypes.string,
|
|
46
|
+
content: PropTypes.shape({
|
|
47
|
+
'@id': PropTypes.string,
|
|
48
|
+
}),
|
|
49
|
+
};
|
|
79
50
|
|
|
80
|
-
|
|
81
|
-
token:
|
|
82
|
-
content:
|
|
83
|
-
|
|
51
|
+
Anontools.defaultProps = {
|
|
52
|
+
token: null,
|
|
53
|
+
content: {
|
|
54
|
+
'@id': null,
|
|
55
|
+
},
|
|
56
|
+
};
|
|
@@ -1,15 +1,25 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import
|
|
2
|
+
import AnontoolsDefault from './Anontools';
|
|
3
3
|
import Wrapper from '@plone/volto/storybook';
|
|
4
4
|
|
|
5
5
|
const AnontoolsComponent = ({ children, ...args }) => {
|
|
6
6
|
return (
|
|
7
|
-
<Wrapper
|
|
7
|
+
<Wrapper
|
|
8
|
+
anonymous
|
|
9
|
+
location={{ pathname: '/folder2/folder21/doc212' }}
|
|
10
|
+
customStore={{
|
|
11
|
+
content: {
|
|
12
|
+
data: { '@id': 'http://myreturnURL' },
|
|
13
|
+
get: {
|
|
14
|
+
loaded: false,
|
|
15
|
+
loading: false,
|
|
16
|
+
error: null,
|
|
17
|
+
},
|
|
18
|
+
},
|
|
19
|
+
}}
|
|
20
|
+
>
|
|
8
21
|
<div className="ui segment form attached" style={{ width: '400px' }}>
|
|
9
|
-
<AnontoolsDefault
|
|
10
|
-
userSession={{ token: null }}
|
|
11
|
-
content={{ '@id': 'myid' }}
|
|
12
|
-
/>
|
|
22
|
+
<AnontoolsDefault />
|
|
13
23
|
</div>
|
|
14
24
|
</Wrapper>
|
|
15
25
|
);
|
|
@@ -12,7 +12,14 @@ describe('Anontools', () => {
|
|
|
12
12
|
it('renders an anontools component when no token is specified', () => {
|
|
13
13
|
const store = mockStore({
|
|
14
14
|
userSession: { token: null },
|
|
15
|
-
content: {
|
|
15
|
+
content: {
|
|
16
|
+
data: { '@id': 'myid' },
|
|
17
|
+
get: {
|
|
18
|
+
loading: false,
|
|
19
|
+
loaded: true,
|
|
20
|
+
error: null,
|
|
21
|
+
},
|
|
22
|
+
},
|
|
16
23
|
intl: {
|
|
17
24
|
locale: 'en',
|
|
18
25
|
messages: {},
|
|
@@ -32,7 +39,14 @@ describe('Anontools', () => {
|
|
|
32
39
|
it('should not render an anontools component when a token is specified', () => {
|
|
33
40
|
const store = mockStore({
|
|
34
41
|
userSession: { token: '1234' },
|
|
35
|
-
content: {
|
|
42
|
+
content: {
|
|
43
|
+
data: {},
|
|
44
|
+
get: {
|
|
45
|
+
loading: false,
|
|
46
|
+
loaded: true,
|
|
47
|
+
error: null,
|
|
48
|
+
},
|
|
49
|
+
},
|
|
36
50
|
intl: {
|
|
37
51
|
locale: 'en',
|
|
38
52
|
messages: {},
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export default (props)
|
|
1
|
+
export default function Blocks(props) {
|
|
2
2
|
const { draftJs, immutableLib } = props;
|
|
3
3
|
const { DefaultDraftBlockRenderMap } = draftJs;
|
|
4
4
|
const { Map } = immutableLib;
|
|
@@ -27,4 +27,4 @@ export default (props) => {
|
|
|
27
27
|
const listBlockTypes = ['unordered-list-item', 'ordered-list-item'];
|
|
28
28
|
|
|
29
29
|
return { extendedBlockRenderMap, blockStyleFn, listBlockTypes };
|
|
30
|
-
}
|
|
30
|
+
}
|
|
@@ -13,7 +13,7 @@ import orderedListSVG from '@plone/volto/icons/list-numbered.svg';
|
|
|
13
13
|
import blockquoteSVG from '@plone/volto/icons/quote.svg';
|
|
14
14
|
import calloutSVG from '@plone/volto/icons/megaphone.svg';
|
|
15
15
|
|
|
16
|
-
export default function (props) {
|
|
16
|
+
export default function Styles(props) {
|
|
17
17
|
const createInlineStyleButton = props.draftJsCreateInlineStyleButton.default;
|
|
18
18
|
const createBlockStyleButton = props.draftJsCreateBlockStyleButton.default;
|
|
19
19
|
|
package/src/constants/Indexes.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* @module constants/indexes
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
const Indexes = {
|
|
7
7
|
sortable_title: { label: 'Title', type: 'string', sort_on: 'sortable_title' },
|
|
8
8
|
review_state: { label: 'Review state', type: 'string' },
|
|
9
9
|
ModificationDate: {
|
|
@@ -35,6 +35,8 @@ export default {
|
|
|
35
35
|
Type: { label: 'Type', type: 'string' },
|
|
36
36
|
};
|
|
37
37
|
|
|
38
|
+
export default Indexes;
|
|
39
|
+
|
|
38
40
|
export const defaultIndexes = [
|
|
39
41
|
'review_state',
|
|
40
42
|
'ModificationDate',
|
|
@@ -9,7 +9,7 @@ const HEADERS = [
|
|
|
9
9
|
'Content-Type',
|
|
10
10
|
];
|
|
11
11
|
|
|
12
|
-
function
|
|
12
|
+
function filesMiddlewareFn(req, res, next) {
|
|
13
13
|
getAPIResourceWithAuth(req)
|
|
14
14
|
.then((resource) => {
|
|
15
15
|
// Just forward the headers that we need
|
|
@@ -24,10 +24,10 @@ function fileMiddleware(req, res, next) {
|
|
|
24
24
|
.catch(next);
|
|
25
25
|
}
|
|
26
26
|
|
|
27
|
-
export default function () {
|
|
27
|
+
export default function filesMiddleware() {
|
|
28
28
|
const middleware = express.Router();
|
|
29
29
|
|
|
30
|
-
middleware.all(['**/@@download/*', '**/@@display-file/*'],
|
|
30
|
+
middleware.all(['**/@@download/*', '**/@@display-file/*'], filesMiddlewareFn);
|
|
31
31
|
middleware.id = 'filesResourcesProcessor';
|
|
32
32
|
return middleware;
|
|
33
33
|
}
|
|
@@ -3,7 +3,7 @@ import { getAPIResourceWithAuth } from '@plone/volto/helpers';
|
|
|
3
3
|
|
|
4
4
|
const HEADERS = ['content-type', 'content-disposition', 'cache-control'];
|
|
5
5
|
|
|
6
|
-
function
|
|
6
|
+
function imageMiddlewareFn(req, res, next) {
|
|
7
7
|
getAPIResourceWithAuth(req)
|
|
8
8
|
.then((resource) => {
|
|
9
9
|
// Just forward the headers that we need
|
|
@@ -17,11 +17,11 @@ function imageMiddleware(req, res, next) {
|
|
|
17
17
|
.catch(next);
|
|
18
18
|
}
|
|
19
19
|
|
|
20
|
-
export default function () {
|
|
20
|
+
export default function imagesMiddleware() {
|
|
21
21
|
const middleware = express.Router();
|
|
22
22
|
|
|
23
|
-
middleware.all(['**/@@images/*'],
|
|
24
|
-
middleware.all(['/@portrait/*'],
|
|
23
|
+
middleware.all(['**/@@images/*'], imageMiddlewareFn);
|
|
24
|
+
middleware.all(['/@portrait/*'], imageMiddlewareFn);
|
|
25
25
|
middleware.id = 'imageResourcesProcessor';
|
|
26
26
|
return middleware;
|
|
27
27
|
}
|
|
@@ -22,7 +22,7 @@ const envRobots = function (req, res, next) {
|
|
|
22
22
|
res.send(process.env.VOLTO_ROBOTSTXT);
|
|
23
23
|
};
|
|
24
24
|
|
|
25
|
-
export default function () {
|
|
25
|
+
export default function robotstxtMiddleware() {
|
|
26
26
|
const middleware = express.Router();
|
|
27
27
|
if (process.env.VOLTO_ROBOTSTXT) {
|
|
28
28
|
middleware.all('**/robots.txt', envRobots);
|
|
@@ -2,7 +2,7 @@ import express from 'express';
|
|
|
2
2
|
import path from 'path';
|
|
3
3
|
import config from '@plone/volto/registry';
|
|
4
4
|
|
|
5
|
-
const
|
|
5
|
+
const staticMiddlewareFn = express.static(
|
|
6
6
|
process.env.BUILD_DIR
|
|
7
7
|
? path.join(process.env.BUILD_DIR, 'public')
|
|
8
8
|
: process.env.RAZZLE_PUBLIC_DIR,
|
|
@@ -24,9 +24,9 @@ const staticMiddleware = express.static(
|
|
|
24
24
|
},
|
|
25
25
|
);
|
|
26
26
|
|
|
27
|
-
export default function () {
|
|
27
|
+
export default function staticsMiddleware() {
|
|
28
28
|
const middleware = express.Router();
|
|
29
|
-
middleware.all('*',
|
|
29
|
+
middleware.all('*', staticMiddlewareFn);
|
|
30
30
|
middleware.id = 'staticResourcesProcessor';
|
|
31
31
|
return middleware;
|
|
32
32
|
}
|
|
@@ -260,6 +260,10 @@ export const messages = defineMessages({
|
|
|
260
260
|
id: 'Show groups of users below',
|
|
261
261
|
defaultMessage: 'Show groups of users below',
|
|
262
262
|
},
|
|
263
|
+
urlClipboardCopy: {
|
|
264
|
+
id: 'Link copied to clipboard',
|
|
265
|
+
defaultMessage: 'Link copied to clipboard',
|
|
266
|
+
},
|
|
263
267
|
inspectRelations: {
|
|
264
268
|
id: 'Inspect relations',
|
|
265
269
|
defaultMessage: 'Inspect relations',
|
|
@@ -28,15 +28,17 @@ class ScrollToTop extends React.Component {
|
|
|
28
28
|
* @memberof ScrollToTop
|
|
29
29
|
*/
|
|
30
30
|
componentDidUpdate(prevProps) {
|
|
31
|
+
const { location } = this.props;
|
|
31
32
|
const noInitialBlocksFocus = // Do not scroll on /edit
|
|
32
33
|
config.blocks?.initialBlocksFocus === null
|
|
33
34
|
? this.props.location?.pathname.slice(-5) !== '/edit'
|
|
34
35
|
: true;
|
|
36
|
+
|
|
37
|
+
const isHash = location?.hash || location?.pathname.hash;
|
|
35
38
|
if (
|
|
36
|
-
!
|
|
37
|
-
!this.props.location?.pathname.hash &&
|
|
39
|
+
!isHash &&
|
|
38
40
|
noInitialBlocksFocus &&
|
|
39
|
-
|
|
41
|
+
location?.pathname !== prevProps.location?.pathname
|
|
40
42
|
) {
|
|
41
43
|
window.scrollTo(0, 0);
|
|
42
44
|
}
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { useDetectClickOutside } from './useDetectClickOutside';
|
|
3
|
+
import { Portal } from 'react-portal';
|
|
4
|
+
import { usePopper } from 'react-popper';
|
|
5
|
+
import { BlockChooser } from '@plone/volto/components';
|
|
6
|
+
|
|
7
|
+
function OpenedChooser(props) {
|
|
8
|
+
const blockChooserRef = useDetectClickOutside({
|
|
9
|
+
onTriggered: () => props.setOpenMenu(false),
|
|
10
|
+
triggerKeys: ['Escape'],
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
return (
|
|
14
|
+
<div ref={blockChooserRef} style={{ marginLeft: '20px' }}>
|
|
15
|
+
Hello
|
|
16
|
+
</div>
|
|
17
|
+
);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function TestComponent(props) {
|
|
21
|
+
const [isOpenMenu, setOpenMenu] = React.useState(false);
|
|
22
|
+
|
|
23
|
+
return (
|
|
24
|
+
<div style={{ display: 'flex', marginBottom: '20px' }}>
|
|
25
|
+
<button onClick={() => setOpenMenu(true)}>Click me</button>
|
|
26
|
+
{isOpenMenu && <OpenedChooser setOpenMenu={setOpenMenu} />}
|
|
27
|
+
</div>
|
|
28
|
+
);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function StoryComponent(args) {
|
|
32
|
+
return (
|
|
33
|
+
<>
|
|
34
|
+
<TestComponent />
|
|
35
|
+
<TestComponent />
|
|
36
|
+
<TestComponent />
|
|
37
|
+
</>
|
|
38
|
+
);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function OpenedChooserWithPortal(props) {
|
|
42
|
+
const blockChooserRef = useDetectClickOutside({
|
|
43
|
+
onTriggered: () => props.setOpenMenu(false),
|
|
44
|
+
triggerKeys: ['Escape'],
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
return (
|
|
48
|
+
<Portal node={document.getElementById('body')}>
|
|
49
|
+
<div ref={blockChooserRef}>{`Hello ${props.id}`}</div>
|
|
50
|
+
</Portal>
|
|
51
|
+
);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function TestComponentWithPortal(props) {
|
|
55
|
+
const [isOpenMenu, setOpenMenu] = React.useState(false);
|
|
56
|
+
|
|
57
|
+
return (
|
|
58
|
+
<div style={{ display: 'flex', marginBottom: '20px' }}>
|
|
59
|
+
<button
|
|
60
|
+
onClick={() => setOpenMenu(true)}
|
|
61
|
+
>{`Click me ${props.id}`}</button>
|
|
62
|
+
{isOpenMenu && (
|
|
63
|
+
<OpenedChooserWithPortal {...props} setOpenMenu={setOpenMenu} />
|
|
64
|
+
)}
|
|
65
|
+
</div>
|
|
66
|
+
);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function StoryComponentWithPortal(args) {
|
|
70
|
+
return (
|
|
71
|
+
<>
|
|
72
|
+
<TestComponentWithPortal id={1} />
|
|
73
|
+
<TestComponentWithPortal id={2} />
|
|
74
|
+
<TestComponentWithPortal id={3} />
|
|
75
|
+
</>
|
|
76
|
+
);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
function OpenedChooserWithPortalAndPopper(props) {
|
|
80
|
+
const { showBlockChooser } = props;
|
|
81
|
+
|
|
82
|
+
const blockChooserRef = useDetectClickOutside({
|
|
83
|
+
onTriggered: () => props.setOpenMenu(false),
|
|
84
|
+
triggerKeys: ['Escape'],
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
return showBlockChooser ? (
|
|
88
|
+
<BlockChooser
|
|
89
|
+
// onMutateBlock={onMutateBlock}
|
|
90
|
+
// currentBlock={block}
|
|
91
|
+
showRestricted
|
|
92
|
+
// blocksConfig={blocksConfig}
|
|
93
|
+
ref={blockChooserRef}
|
|
94
|
+
/>
|
|
95
|
+
) : (
|
|
96
|
+
<div ref={blockChooserRef}>{`Hello ${props.id}`}</div>
|
|
97
|
+
);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
function TestComponentWithPortalAndPopper(props) {
|
|
101
|
+
const [isOpenMenu, setOpenMenu] = React.useState(false);
|
|
102
|
+
const [referenceElement, setReferenceElement] = React.useState(null);
|
|
103
|
+
const [popperElement, setPopperElement] = React.useState(null);
|
|
104
|
+
const { styles, attributes } = usePopper(referenceElement, popperElement, {
|
|
105
|
+
placement: 'right',
|
|
106
|
+
modifiers: [
|
|
107
|
+
{
|
|
108
|
+
name: 'offset',
|
|
109
|
+
options: {
|
|
110
|
+
offset: [-10, 10],
|
|
111
|
+
},
|
|
112
|
+
},
|
|
113
|
+
{
|
|
114
|
+
name: 'flip',
|
|
115
|
+
options: {
|
|
116
|
+
fallbackPlacements: ['top-start'],
|
|
117
|
+
},
|
|
118
|
+
},
|
|
119
|
+
],
|
|
120
|
+
});
|
|
121
|
+
return (
|
|
122
|
+
<div style={{ display: 'flex', marginBottom: '20px' }}>
|
|
123
|
+
<button
|
|
124
|
+
ref={setReferenceElement}
|
|
125
|
+
onClick={() => setOpenMenu(true)}
|
|
126
|
+
>{`Click me ${props.id}`}</button>
|
|
127
|
+
<Portal node={document.getElementById('body')}>
|
|
128
|
+
<div
|
|
129
|
+
ref={setPopperElement}
|
|
130
|
+
style={styles.popper}
|
|
131
|
+
{...attributes.popper}
|
|
132
|
+
>
|
|
133
|
+
{isOpenMenu && (
|
|
134
|
+
<OpenedChooserWithPortalAndPopper
|
|
135
|
+
{...props}
|
|
136
|
+
setOpenMenu={setOpenMenu}
|
|
137
|
+
/>
|
|
138
|
+
)}
|
|
139
|
+
</div>
|
|
140
|
+
</Portal>
|
|
141
|
+
</div>
|
|
142
|
+
);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
function StoryComponentWithPortalAndPopper(args) {
|
|
146
|
+
const { showBlockChooser } = args;
|
|
147
|
+
return (
|
|
148
|
+
<>
|
|
149
|
+
<TestComponentWithPortalAndPopper
|
|
150
|
+
id={1}
|
|
151
|
+
showBlockChooser={showBlockChooser}
|
|
152
|
+
/>
|
|
153
|
+
<TestComponentWithPortalAndPopper
|
|
154
|
+
id={2}
|
|
155
|
+
showBlockChooser={showBlockChooser}
|
|
156
|
+
/>
|
|
157
|
+
<TestComponentWithPortalAndPopper
|
|
158
|
+
id={3}
|
|
159
|
+
showBlockChooser={showBlockChooser}
|
|
160
|
+
/>
|
|
161
|
+
</>
|
|
162
|
+
);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
export const Default = StoryComponent.bind({});
|
|
166
|
+
Default.args = {};
|
|
167
|
+
|
|
168
|
+
export const WithPortal = StoryComponentWithPortal.bind({});
|
|
169
|
+
WithPortal.args = {};
|
|
170
|
+
|
|
171
|
+
export const WithPortalAndPopper = StoryComponentWithPortalAndPopper.bind({});
|
|
172
|
+
WithPortalAndPopper.args = {};
|
|
173
|
+
|
|
174
|
+
export const WithPortalAndPopperUsingBlockChooser = StoryComponentWithPortalAndPopper.bind(
|
|
175
|
+
{},
|
|
176
|
+
);
|
|
177
|
+
WithPortalAndPopperUsingBlockChooser.args = {
|
|
178
|
+
showBlockChooser: true,
|
|
179
|
+
};
|
|
180
|
+
|
|
181
|
+
export default {
|
|
182
|
+
title: 'Internal Components/useDetectClickOutside',
|
|
183
|
+
component: TestComponent,
|
|
184
|
+
decorators: [
|
|
185
|
+
(Story) => (
|
|
186
|
+
<div style={{ width: '600px' }}>
|
|
187
|
+
<Story />
|
|
188
|
+
</div>
|
|
189
|
+
),
|
|
190
|
+
],
|
|
191
|
+
};
|
package/src/helpers/index.js
CHANGED
|
@@ -5,9 +5,9 @@
|
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
// export { injectLazyLibs } from './Loadable/Loadable';
|
|
8
|
-
export Api from '@plone/volto/helpers/Api/Api';
|
|
8
|
+
export { default as Api } from '@plone/volto/helpers/Api/Api';
|
|
9
9
|
export { getAPIResourceWithAuth } from '@plone/volto/helpers/Api/APIResourceWithAuth';
|
|
10
|
-
export Html from '@plone/volto/helpers/Html/Html';
|
|
10
|
+
export { default as Html } from '@plone/volto/helpers/Html/Html';
|
|
11
11
|
export {
|
|
12
12
|
getAuthToken,
|
|
13
13
|
persistAuthToken,
|
|
@@ -58,8 +58,8 @@ export {
|
|
|
58
58
|
buildStyleClassNamesExtenders,
|
|
59
59
|
getPreviousNextBlock,
|
|
60
60
|
} from '@plone/volto/helpers/Blocks/Blocks';
|
|
61
|
-
export BodyClass from '@plone/volto/helpers/BodyClass/BodyClass';
|
|
62
|
-
export ScrollToTop from '@plone/volto/helpers/ScrollToTop/ScrollToTop';
|
|
61
|
+
export { default as BodyClass } from '@plone/volto/helpers/BodyClass/BodyClass';
|
|
62
|
+
export { default as ScrollToTop } from '@plone/volto/helpers/ScrollToTop/ScrollToTop';
|
|
63
63
|
export {
|
|
64
64
|
getBoolean,
|
|
65
65
|
getVocabName,
|
|
@@ -69,11 +69,10 @@ export {
|
|
|
69
69
|
getFieldsVocabulary,
|
|
70
70
|
} from '@plone/volto/helpers/Vocabularies/Vocabularies';
|
|
71
71
|
|
|
72
|
-
export langmap from './LanguageMap/LanguageMap';
|
|
73
|
-
export Helmet from './Helmet/Helmet';
|
|
74
|
-
export FormValidation
|
|
75
|
-
|
|
76
|
-
} from './FormValidation/FormValidation';
|
|
72
|
+
export { default as langmap } from './LanguageMap/LanguageMap';
|
|
73
|
+
export { default as Helmet } from './Helmet/Helmet';
|
|
74
|
+
export { default as FormValidation } from './FormValidation/FormValidation';
|
|
75
|
+
export { validateFileUploadSize } from './FormValidation/FormValidation';
|
|
77
76
|
export {
|
|
78
77
|
difference,
|
|
79
78
|
getColor,
|
|
@@ -111,7 +110,7 @@ export { useDetectClickOutside } from './Utils/useDetectClickOutside';
|
|
|
111
110
|
export { useEvent } from './Utils/useEvent';
|
|
112
111
|
export { usePrevious } from './Utils/usePrevious';
|
|
113
112
|
export { usePagination } from './Utils/usePagination';
|
|
114
|
-
export useUndoManager from './UndoManager/useUndoManager';
|
|
113
|
+
export { default as useUndoManager } from './UndoManager/useUndoManager';
|
|
115
114
|
export { getCookieOptions } from './Cookies/cookies';
|
|
116
115
|
export { getWidgetView } from './Widget/widget';
|
|
117
116
|
export {
|