Skip to content

WIP:Native mouse enter/leave with portal support #10269

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions fixtures/dom/src/components/Header.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ class Header extends React.Component {
<option value="/">Select a Fixture</option>
<option value="/range-inputs">Range Inputs</option>
<option value="/text-inputs">Text Inputs</option>
<option value="/mouse-events">Mouse Events</option>
<option value="/number-inputs">Number Input</option>
<option value="/password-inputs">Password Input</option>
<option value="/selects">Selects</option>
Expand Down
3 changes: 3 additions & 0 deletions fixtures/dom/src/components/fixtures/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import TextInputFixtures from './text-inputs';
import SelectFixtures from './selects';
import TextAreaFixtures from './textareas';
import InputChangeEvents from './input-change-events';
import MouseEventsFixtures from './mouse-events';
import NumberInputFixtures from './number-inputs';
import PasswordInputFixtures from './password-inputs';
import ButtonFixtures from './buttons';
Expand All @@ -25,6 +26,8 @@ function FixturesPage() {
return <TextAreaFixtures />;
case '/input-change-events':
return <InputChangeEvents />;
case '/mouse-events':
return <MouseEventsFixtures />;
case '/number-inputs':
return <NumberInputFixtures />;
case '/password-inputs':
Expand Down
128 changes: 128 additions & 0 deletions fixtures/dom/src/components/fixtures/mouse-events/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
const React = window.React;
const ReactDOM = window.ReactDOM;

const Rectangle = ({style, nodeRef, ...props}) => (
<div
{...props}
ref={nodeRef}
style={{border: '1px solid black', padding: 40, ...style}}
/>
);

const Overlay = ({position, ...props}) => (
<div
{...props}
style={{
width: 100,
position: 'fixed',
border: '1px solid blue',
padding: 10,
...position,
}}
/>
);

var portalContainer = document.createElement('div');
document.body.appendChild(portalContainer);

class MouseEventsFixtures extends React.Component {
state = {log: [], box: null};

log = msg => {
this.setState(({log}) => ({
log: log.concat(msg),
}));
};
clearLog = () => {
this.setState({log: []});
};

componentDidMount() {
this.getDimensions();
}
componentDidUpdate() {
this.getDimensions();
}

getDimensions() {
if (!this.state.box && this.node) {
const {left, bottom} = this.node.getBoundingClientRect();
this.setState({
box: {left: left + 10, top: bottom - 10},
});
} else if (this.state.box && !this.node) {
this.setState({box: null});
}
}

render() {
const {box} = this.state;

let getLogger = prefix => e => this.log(`${prefix}: ${e.type}`);
let outerLogger = getLogger('outer');
let innerLogger = getLogger('inner');
let portalALogger = getLogger('portal A');
let portalBLogger = getLogger('portal B');

return (
<div>
<div className="container">
<p>
Mouse the mouse between the two rectangles. The console should
only log for a given box when the mouse crosses into the box the first
time and again when the mouse exits the
{' '}
<em>outer</em>
{' '}
bounds of each box.
</p>
<Rectangle onMouseEnter={outerLogger} onMouseLeave={outerLogger}>
<Rectangle onMouseEnter={innerLogger} onMouseLeave={innerLogger} />
</Rectangle>

<p>
Moving from the outer rectangle to the inner blue Portal should not trigger a
mouseleave on the outer rectangle.
</p>
<Rectangle onMouseEnter={outerLogger} onMouseLeave={outerLogger}>
<Rectangle
onMouseEnter={innerLogger}
onMouseLeave={innerLogger}
nodeRef={n => (this.node = n)}>

{box &&
ReactDOM.unstable_createPortal(
<Overlay
position={box}
onMouseEnter={portalALogger}
onMouseLeave={portalALogger}>
portal A
</Overlay>,
portalContainer,
)}
{box &&
ReactDOM.unstable_createPortal(
<Overlay
position={{...box, left: box.left + 100}}
onMouseEnter={portalBLogger}
onMouseLeave={portalBLogger}>
portal B
</Overlay>,
portalContainer,
)}
</Rectangle>
</Rectangle>
</div>

<div className="container">
<h4>Console: <button onClick={this.clearLog}>clear</button></h4>
<pre className="output">
{this.state.log.join('\n')}
</pre>
</div>
</div>
);
}
}

module.exports = MouseEventsFixtures;
Loading