mirror of
https://github.com/Hopiu/wagtail.git
synced 2026-04-27 10:04:49 +00:00
Move Draftail tooltips portal closer to the editor to prevent background flickering
This commit is contained in:
parent
6c714b1537
commit
9861c2a0d4
15 changed files with 258 additions and 92 deletions
|
|
@ -71,6 +71,11 @@ $draftail-editor-font-family: $font-serif;
|
|||
|
||||
.Draftail-Editor {
|
||||
border-radius: 0;
|
||||
|
||||
&__wrapper {
|
||||
// Ensure elements within the editor are positioned according to this container.
|
||||
position: relative;
|
||||
}
|
||||
}
|
||||
|
||||
// When in a .full container, the editor has a specific appearance
|
||||
|
|
|
|||
|
|
@ -27,13 +27,27 @@ class MediaBlock extends Component {
|
|||
}
|
||||
|
||||
openTooltip(e) {
|
||||
const trigger = e.target;
|
||||
const trigger = e.target.closest('[data-draftail-trigger]');
|
||||
|
||||
// Click is within the tooltip.
|
||||
if (!trigger) {
|
||||
return;
|
||||
}
|
||||
|
||||
const container = trigger.closest('[data-draftail-editor-wrapper]');
|
||||
const containerRect = container.getBoundingClientRect();
|
||||
const rect = trigger.getBoundingClientRect();
|
||||
const maxWidth = trigger.parentNode.offsetWidth - rect.width;
|
||||
|
||||
this.setState({
|
||||
// Warning: overriding native DOM object. Proceed with caution.
|
||||
showTooltipAt: Object.assign(trigger.getBoundingClientRect(), {
|
||||
containerWidth: trigger.parentNode.offsetWidth,
|
||||
}),
|
||||
showTooltipAt: {
|
||||
container: container,
|
||||
top: rect.top - containerRect.top - (document.documentElement.scrollTop || document.body.scrollTop),
|
||||
left: rect.left - containerRect.left - (document.documentElement.scrollLeft || document.body.scrollLeft),
|
||||
width: rect.width,
|
||||
height: rect.height,
|
||||
direction: maxWidth >= TOOLTIP_MAX_WIDTH ? 'left' : 'top-left',
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -44,17 +58,16 @@ class MediaBlock extends Component {
|
|||
renderTooltip() {
|
||||
const { children } = this.props;
|
||||
const { showTooltipAt } = this.state;
|
||||
const maxWidth = showTooltipAt.containerWidth - showTooltipAt.width;
|
||||
const direction = maxWidth >= TOOLTIP_MAX_WIDTH ? 'left' : 'top-left';
|
||||
|
||||
return (
|
||||
<Portal
|
||||
node={showTooltipAt.container}
|
||||
onClose={this.closeTooltip}
|
||||
closeOnClick
|
||||
closeOnType
|
||||
closeOnResize
|
||||
>
|
||||
<Tooltip target={showTooltipAt} direction={direction}>
|
||||
<Tooltip target={showTooltipAt} direction={showTooltipAt.direction}>
|
||||
<div style={{ maxWidth: OPTIONS_MAX_WIDTH }}>{children}</div>
|
||||
</Tooltip>
|
||||
</Portal>
|
||||
|
|
@ -71,7 +84,8 @@ class MediaBlock extends Component {
|
|||
type="button"
|
||||
tabIndex={-1}
|
||||
className="MediaBlock"
|
||||
onMouseUp={this.openTooltip}
|
||||
onClick={this.openTooltip}
|
||||
data-draftail-trigger
|
||||
>
|
||||
<span className="MediaBlock__icon-wrapper" aria-hidden>
|
||||
<Icon icon={entityType.icon} className="MediaBlock__icon" />
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import React from 'react';
|
||||
import { shallow } from 'enzyme';
|
||||
import { shallow, mount } from 'enzyme';
|
||||
|
||||
import MediaBlock from '../blocks/MediaBlock';
|
||||
|
||||
|
|
@ -49,10 +49,16 @@ describe('MediaBlock', () => {
|
|||
});
|
||||
|
||||
describe('tooltip', () => {
|
||||
let target;
|
||||
let wrapper;
|
||||
|
||||
beforeEach(() => {
|
||||
wrapper = shallow(
|
||||
target = document.createElement('div');
|
||||
target.setAttribute('data-draftail-trigger', true);
|
||||
document.body.appendChild(target);
|
||||
document.body.setAttribute('data-draftail-editor-wrapper', true);
|
||||
|
||||
wrapper = mount(
|
||||
<MediaBlock
|
||||
src="example.png"
|
||||
alt=""
|
||||
|
|
@ -67,28 +73,32 @@ describe('MediaBlock', () => {
|
|||
},
|
||||
}}
|
||||
>
|
||||
Test
|
||||
<div id="test">Test</div>
|
||||
</MediaBlock>
|
||||
);
|
||||
});
|
||||
|
||||
it('opens', () => {
|
||||
const target = document.createElement('div');
|
||||
document.body.appendChild(target);
|
||||
|
||||
wrapper.simulate('mouseup', { target });
|
||||
wrapper.simulate('click', { target });
|
||||
|
||||
expect(
|
||||
wrapper
|
||||
.find('Portal')
|
||||
.dive()
|
||||
.instance().portal
|
||||
).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('click in tooltip', () => {
|
||||
wrapper.simulate('click', { target });
|
||||
|
||||
jest.spyOn(target, 'getBoundingClientRect');
|
||||
|
||||
wrapper.simulate('click', { target: document.querySelector('#test') });
|
||||
|
||||
expect(target.getBoundingClientRect).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('large viewport', () => {
|
||||
const target = document.createElement('div');
|
||||
document.body.appendChild(target);
|
||||
target.getBoundingClientRect = () => ({
|
||||
top: 0,
|
||||
left: 0,
|
||||
|
|
@ -96,26 +106,22 @@ describe('MediaBlock', () => {
|
|||
height: 0,
|
||||
});
|
||||
|
||||
wrapper.simulate('mouseup', { target });
|
||||
wrapper.simulate('click', { target });
|
||||
|
||||
expect(
|
||||
wrapper
|
||||
.find('Portal')
|
||||
.dive()
|
||||
.instance()
|
||||
.portal.querySelector('.Tooltip').className
|
||||
).toBe('Tooltip Tooltip--left');
|
||||
});
|
||||
|
||||
it('closes', () => {
|
||||
const target = document.createElement('div');
|
||||
document.body.appendChild(target);
|
||||
|
||||
jest.spyOn(target, 'getBoundingClientRect');
|
||||
|
||||
expect(wrapper.state('showTooltipAt')).toBe(null);
|
||||
|
||||
wrapper.simulate('mouseup', { target });
|
||||
wrapper.simulate('click', { target });
|
||||
|
||||
expect(wrapper.state('showTooltipAt')).toMatchObject({
|
||||
top: 0,
|
||||
|
|
|
|||
|
|
@ -3,7 +3,8 @@
|
|||
exports[`MediaBlock no data 1`] = `
|
||||
<button
|
||||
className="MediaBlock"
|
||||
onMouseUp={[Function]}
|
||||
data-draftail-trigger={true}
|
||||
onClick={[Function]}
|
||||
tabIndex={-1}
|
||||
type="button"
|
||||
>
|
||||
|
|
@ -29,7 +30,8 @@ exports[`MediaBlock no data 1`] = `
|
|||
exports[`MediaBlock renders 1`] = `
|
||||
<button
|
||||
className="MediaBlock"
|
||||
onMouseUp={[Function]}
|
||||
data-draftail-trigger={true}
|
||||
onClick={[Function]}
|
||||
tabIndex={-1}
|
||||
type="button"
|
||||
>
|
||||
|
|
@ -54,14 +56,16 @@ exports[`MediaBlock renders 1`] = `
|
|||
|
||||
exports[`MediaBlock tooltip opens 1`] = `
|
||||
<div>
|
||||
<div>
|
||||
<div
|
||||
class="Tooltip Tooltip--top-left"
|
||||
role="tooltip"
|
||||
style="top: 0px; left: 0px;"
|
||||
>
|
||||
<div
|
||||
class="Tooltip Tooltip--top-left"
|
||||
role="tooltip"
|
||||
style="top: 0px; left: 0px;"
|
||||
style="max-width: 300px;"
|
||||
>
|
||||
<div
|
||||
style="max-width: 300px;"
|
||||
id="test"
|
||||
>
|
||||
Test
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -22,13 +22,49 @@ class TooltipEntity extends Component {
|
|||
showTooltipAt: null,
|
||||
};
|
||||
|
||||
this.onEdit = this.onEdit.bind(this);
|
||||
this.onRemove = this.onRemove.bind(this);
|
||||
this.openTooltip = this.openTooltip.bind(this);
|
||||
this.closeTooltip = this.closeTooltip.bind(this);
|
||||
}
|
||||
|
||||
onEdit(e) {
|
||||
const { onEdit, entityKey } = this.props;
|
||||
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
onEdit(entityKey);
|
||||
}
|
||||
|
||||
onRemove(e) {
|
||||
const { onRemove, entityKey } = this.props;
|
||||
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
onRemove(entityKey);
|
||||
}
|
||||
|
||||
openTooltip(e) {
|
||||
const trigger = e.target;
|
||||
this.setState({ showTooltipAt: trigger.getBoundingClientRect() });
|
||||
const trigger = e.target.closest('[data-draftail-trigger]');
|
||||
|
||||
// Click is within the tooltip.
|
||||
if (!trigger) {
|
||||
return;
|
||||
}
|
||||
|
||||
const container = trigger.closest('[data-draftail-editor-wrapper]');
|
||||
const containerRect = container.getBoundingClientRect();
|
||||
const rect = trigger.getBoundingClientRect();
|
||||
|
||||
this.setState({
|
||||
showTooltipAt: {
|
||||
container: container,
|
||||
top: rect.top - containerRect.top - (document.documentElement.scrollTop || document.body.scrollTop),
|
||||
left: rect.left - containerRect.left - (document.documentElement.scrollLeft || document.body.scrollLeft),
|
||||
width: rect.width,
|
||||
height: rect.height,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
closeTooltip() {
|
||||
|
|
@ -37,10 +73,7 @@ class TooltipEntity extends Component {
|
|||
|
||||
render() {
|
||||
const {
|
||||
entityKey,
|
||||
children,
|
||||
onEdit,
|
||||
onRemove,
|
||||
icon,
|
||||
label,
|
||||
url,
|
||||
|
|
@ -50,11 +83,18 @@ class TooltipEntity extends Component {
|
|||
// Contrary to what JSX A11Y says, this should be a button but it shouldn't be focusable.
|
||||
/* eslint-disable springload/jsx-a11y/interactive-supports-focus */
|
||||
return (
|
||||
<a role="button" onMouseUp={this.openTooltip} className="TooltipEntity">
|
||||
<a
|
||||
role="button"
|
||||
// Use onMouseUp to preserve focus in the text even after clicking.
|
||||
onMouseUp={this.openTooltip}
|
||||
className="TooltipEntity"
|
||||
data-draftail-trigger
|
||||
>
|
||||
<Icon icon={icon} className="TooltipEntity__icon" />
|
||||
{children}
|
||||
{showTooltipAt && (
|
||||
<Portal
|
||||
node={showTooltipAt.container}
|
||||
onClose={this.closeTooltip}
|
||||
closeOnClick
|
||||
closeOnType
|
||||
|
|
@ -75,14 +115,14 @@ class TooltipEntity extends Component {
|
|||
|
||||
<button
|
||||
className="button Tooltip__button"
|
||||
onClick={onEdit.bind(null, entityKey)}
|
||||
onClick={this.onEdit}
|
||||
>
|
||||
Edit
|
||||
</button>
|
||||
|
||||
<button
|
||||
className="button button-secondary no Tooltip__button"
|
||||
onClick={onRemove.bind(null, entityKey)}
|
||||
onClick={this.onRemove}
|
||||
>
|
||||
Remove
|
||||
</button>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import React from 'react';
|
||||
import { shallow } from 'enzyme';
|
||||
import { shallow, mount } from 'enzyme';
|
||||
|
||||
import TooltipEntity from './TooltipEntity';
|
||||
|
||||
|
|
@ -51,8 +51,13 @@ describe('TooltipEntity', () => {
|
|||
</TooltipEntity>
|
||||
));
|
||||
|
||||
const target = document.createElement('div');
|
||||
target.setAttribute('data-draftail-trigger', true);
|
||||
document.body.appendChild(target);
|
||||
document.body.setAttribute('data-draftail-editor-wrapper', true);
|
||||
|
||||
wrapper.find('.TooltipEntity').simulate('mouseup', {
|
||||
target: document.createElement('div'),
|
||||
target: target,
|
||||
});
|
||||
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
|
|
@ -82,4 +87,46 @@ describe('TooltipEntity', () => {
|
|||
showTooltipAt: null,
|
||||
});
|
||||
});
|
||||
|
||||
it('#onEdit', () => {
|
||||
const onEdit = jest.fn();
|
||||
|
||||
const wrapper = shallow((
|
||||
<TooltipEntity
|
||||
entityKey="1"
|
||||
onEdit={onEdit}
|
||||
onRemove={() => {}}
|
||||
icon="#icon-test"
|
||||
url="https://www.example.com/"
|
||||
label="www.example.com"
|
||||
>
|
||||
test
|
||||
</TooltipEntity>
|
||||
));
|
||||
|
||||
wrapper.instance().onEdit(new Event('click'));
|
||||
|
||||
expect(onEdit).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('#onRemove', () => {
|
||||
const onRemove = jest.fn();
|
||||
|
||||
const wrapper = shallow((
|
||||
<TooltipEntity
|
||||
entityKey="1"
|
||||
onEdit={() => {}}
|
||||
onRemove={onRemove}
|
||||
icon="#icon-test"
|
||||
url="https://www.example.com/"
|
||||
label="www.example.com"
|
||||
>
|
||||
test
|
||||
</TooltipEntity>
|
||||
));
|
||||
|
||||
wrapper.instance().onRemove(new Event('click'));
|
||||
|
||||
expect(onRemove).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
exports[`TooltipEntity #openTooltip 1`] = `
|
||||
<a
|
||||
className="TooltipEntity"
|
||||
data-draftail-trigger={true}
|
||||
onMouseUp={[Function]}
|
||||
role="button"
|
||||
>
|
||||
|
|
@ -16,16 +17,30 @@ exports[`TooltipEntity #openTooltip 1`] = `
|
|||
closeOnClick={true}
|
||||
closeOnResize={true}
|
||||
closeOnType={true}
|
||||
node={
|
||||
<body
|
||||
data-draftail-editor-wrapper="true"
|
||||
>
|
||||
<div
|
||||
data-draftail-trigger="true"
|
||||
/>
|
||||
</body>
|
||||
}
|
||||
onClose={[Function]}
|
||||
>
|
||||
<Tooltip
|
||||
direction="top"
|
||||
target={
|
||||
Object {
|
||||
"bottom": 0,
|
||||
"container": <body
|
||||
data-draftail-editor-wrapper="true"
|
||||
>
|
||||
<div
|
||||
data-draftail-trigger="true"
|
||||
/>
|
||||
</body>,
|
||||
"height": 0,
|
||||
"left": 0,
|
||||
"right": 0,
|
||||
"top": 0,
|
||||
"width": 0,
|
||||
}
|
||||
|
|
@ -60,6 +75,7 @@ exports[`TooltipEntity #openTooltip 1`] = `
|
|||
exports[`TooltipEntity works 1`] = `
|
||||
<a
|
||||
className="TooltipEntity"
|
||||
data-draftail-trigger={true}
|
||||
onMouseUp={[Function]}
|
||||
role="button"
|
||||
>
|
||||
|
|
|
|||
|
|
@ -45,7 +45,11 @@ export const wrapWagtailIcon = type => {
|
|||
*/
|
||||
const initEditor = (fieldName, options) => {
|
||||
const field = document.querySelector(`[name="${fieldName}"]`);
|
||||
|
||||
const editorWrapper = document.createElement('div');
|
||||
editorWrapper.className = 'Draftail-Editor__wrapper';
|
||||
editorWrapper.setAttribute('data-draftail-editor-wrapper', true);
|
||||
|
||||
field.parentNode.appendChild(editorWrapper);
|
||||
|
||||
const serialiseInputValue = rawContentState => {
|
||||
|
|
|
|||
|
|
@ -1,11 +1,18 @@
|
|||
import PropTypes from 'prop-types';
|
||||
import React, { Component } from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import { Component } from 'react';
|
||||
import { createPortal } from 'react-dom';
|
||||
|
||||
/**
|
||||
* A Portal component which automatically closes itself
|
||||
* when certain events happen outside.
|
||||
* See https://reactjs.org/docs/portals.html.
|
||||
*/
|
||||
class Portal extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.portal = document.createElement('div');
|
||||
|
||||
this.onCloseEvent = this.onCloseEvent.bind(this);
|
||||
}
|
||||
|
||||
|
|
@ -18,40 +25,27 @@ class Portal extends Component {
|
|||
}
|
||||
|
||||
componentDidMount() {
|
||||
const { onClose, closeOnClick, closeOnType, closeOnResize } = this.props;
|
||||
const { node, onClose, closeOnClick, closeOnType, closeOnResize } = this.props;
|
||||
|
||||
if (!this.portal) {
|
||||
this.portal = document.createElement('div');
|
||||
document.body.appendChild(this.portal);
|
||||
node.appendChild(this.portal);
|
||||
|
||||
if (onClose) {
|
||||
if (closeOnClick) {
|
||||
document.addEventListener('mouseup', this.onCloseEvent);
|
||||
}
|
||||
|
||||
if (closeOnType) {
|
||||
document.addEventListener('keyup', this.onCloseEvent);
|
||||
}
|
||||
|
||||
if (closeOnResize) {
|
||||
window.addEventListener('resize', onClose);
|
||||
}
|
||||
}
|
||||
if (closeOnClick) {
|
||||
document.addEventListener('mouseup', this.onCloseEvent);
|
||||
}
|
||||
|
||||
this.componentDidUpdate();
|
||||
}
|
||||
if (closeOnType) {
|
||||
document.addEventListener('keyup', this.onCloseEvent);
|
||||
}
|
||||
|
||||
componentDidUpdate() {
|
||||
const { children } = this.props;
|
||||
|
||||
ReactDOM.render(<div>{children}</div>, this.portal);
|
||||
if (closeOnResize) {
|
||||
window.addEventListener('resize', onClose);
|
||||
}
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
const { onClose } = this.props;
|
||||
const { node, onClose } = this.props;
|
||||
|
||||
document.body.removeChild(this.portal);
|
||||
node.removeChild(this.portal);
|
||||
|
||||
document.removeEventListener('mouseup', this.onCloseEvent);
|
||||
document.removeEventListener('keyup', this.onCloseEvent);
|
||||
|
|
@ -59,12 +53,15 @@ class Portal extends Component {
|
|||
}
|
||||
|
||||
render() {
|
||||
return null;
|
||||
const { children } = this.props;
|
||||
|
||||
return createPortal(children, this.portal);
|
||||
}
|
||||
}
|
||||
|
||||
Portal.propTypes = {
|
||||
onClose: PropTypes.func,
|
||||
onClose: PropTypes.func.isRequired,
|
||||
node: PropTypes.instanceOf(Element),
|
||||
children: PropTypes.node,
|
||||
closeOnClick: PropTypes.bool,
|
||||
closeOnType: PropTypes.bool,
|
||||
|
|
@ -72,7 +69,7 @@ Portal.propTypes = {
|
|||
};
|
||||
|
||||
Portal.defaultProps = {
|
||||
onClose: null,
|
||||
node: document.body,
|
||||
children: null,
|
||||
closeOnClick: false,
|
||||
closeOnType: false,
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import React from 'react';
|
||||
import { shallow } from 'enzyme';
|
||||
import { shallow, mount } from 'enzyme';
|
||||
import Portal from './Portal';
|
||||
|
||||
const func = expect.any(Function);
|
||||
|
|
@ -10,27 +10,21 @@ describe('Portal', () => {
|
|||
});
|
||||
|
||||
it('empty', () => {
|
||||
expect(shallow(<Portal />)).toMatchSnapshot();
|
||||
expect(mount(<Portal onClose={() => {}} />)).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('#children', () => {
|
||||
expect(shallow(<Portal>Test!</Portal>)).toMatchSnapshot();
|
||||
expect(mount(<Portal onClose={() => {}}>Test!</Portal>)).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('component lifecycle', () => {
|
||||
document.removeEventListener = jest.fn();
|
||||
window.removeEventListener = jest.fn();
|
||||
|
||||
const wrapper = shallow(<Portal onClose={() => {}}>Test!</Portal>);
|
||||
|
||||
wrapper.instance().componentDidMount();
|
||||
const wrapper = mount(<Portal onClose={() => {}}>Test!</Portal>);
|
||||
|
||||
expect(document.body.innerHTML).toMatchSnapshot();
|
||||
|
||||
expect(wrapper.instance().portal).toBe(document.body.children[0]);
|
||||
|
||||
wrapper.instance().componentDidMount();
|
||||
|
||||
wrapper.instance().componentWillUnmount();
|
||||
|
||||
expect(document.body.innerHTML).toBe('');
|
||||
|
|
@ -81,14 +75,14 @@ describe('Portal', () => {
|
|||
Test!
|
||||
</Portal>
|
||||
);
|
||||
expect(window.addEventListener).toHaveBeenCalledWith('error', func);
|
||||
expect(window.addEventListener).toHaveBeenCalledWith('resize', func);
|
||||
});
|
||||
});
|
||||
|
||||
describe('onCloseEvent', () => {
|
||||
it('shouldClose', () => {
|
||||
it('should close', () => {
|
||||
const onClose = jest.fn();
|
||||
const wrapper = shallow(<Portal onClose={onClose}>Test!</Portal>);
|
||||
const wrapper = mount(<Portal onClose={onClose}>Test!</Portal>);
|
||||
const target = document.createElement('div');
|
||||
|
||||
wrapper.instance().onCloseEvent({ target });
|
||||
|
|
@ -96,9 +90,9 @@ describe('Portal', () => {
|
|||
expect(onClose).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('not shouldClose', () => {
|
||||
it('not should close', () => {
|
||||
const onClose = jest.fn();
|
||||
const wrapper = shallow(
|
||||
const wrapper = mount(
|
||||
<Portal onClose={onClose}>
|
||||
<div id="test">Test</div>
|
||||
</Portal>
|
||||
|
|
|
|||
|
|
@ -1,7 +1,35 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`Portal #children 1`] = `""`;
|
||||
exports[`Portal #children 1`] = `
|
||||
<Portal
|
||||
closeOnClick={false}
|
||||
closeOnResize={false}
|
||||
closeOnType={false}
|
||||
node={
|
||||
<body>
|
||||
<div>
|
||||
Test!
|
||||
</div>
|
||||
</body>
|
||||
}
|
||||
onClose={[Function]}
|
||||
>
|
||||
Test!
|
||||
</Portal>
|
||||
`;
|
||||
|
||||
exports[`Portal component lifecycle 1`] = `"<div><div>Test!</div></div>"`;
|
||||
exports[`Portal component lifecycle 1`] = `"<div>Test!</div>"`;
|
||||
|
||||
exports[`Portal empty 1`] = `""`;
|
||||
exports[`Portal empty 1`] = `
|
||||
<Portal
|
||||
closeOnClick={false}
|
||||
closeOnResize={false}
|
||||
closeOnType={false}
|
||||
node={
|
||||
<body>
|
||||
<div />
|
||||
</body>
|
||||
}
|
||||
onClose={[Function]}
|
||||
/>
|
||||
`;
|
||||
|
|
|
|||
|
|
@ -2,5 +2,9 @@
|
|||
* Polyfills for Wagtail's admin.
|
||||
*/
|
||||
|
||||
// IE11.
|
||||
import 'core-js/shim';
|
||||
// IE11, old iOS Safari.
|
||||
import 'whatwg-fetch';
|
||||
// IE11.
|
||||
import 'element-closest';
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
* Those variables usually come from the back-end via templates.
|
||||
* See /wagtailadmin/templates/wagtailadmin/admin_base.html.
|
||||
*/
|
||||
import 'element-closest';
|
||||
|
||||
global.wagtailConfig = {
|
||||
ADMIN_API: {
|
||||
|
|
|
|||
5
package-lock.json
generated
5
package-lock.json
generated
|
|
@ -2688,6 +2688,11 @@
|
|||
"integrity": "sha1-elgja5VGjD52YAkTSFItZddzazY=",
|
||||
"dev": true
|
||||
},
|
||||
"element-closest": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/element-closest/-/element-closest-2.0.2.tgz",
|
||||
"integrity": "sha1-cqdAoQdFM4LijfnOXbtajfD5Zuw="
|
||||
},
|
||||
"elliptic": {
|
||||
"version": "6.4.0",
|
||||
"resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.4.0.tgz",
|
||||
|
|
|
|||
|
|
@ -88,6 +88,7 @@
|
|||
"core-js": "^2.5.3",
|
||||
"draft-js": "0.10.5",
|
||||
"draftail": "^0.16.0",
|
||||
"element-closest": "^2.0.2",
|
||||
"focus-trap-react": "^3.1.0",
|
||||
"prop-types": "^15.6.0",
|
||||
"react": "^16.2.0",
|
||||
|
|
|
|||
Loading…
Reference in a new issue