Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 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
16 changes: 16 additions & 0 deletions babel-build.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
const rootBabel = require('./babel.config');

// TODO: Remove this once https://github.com/storybookjs/storybook/issues/11246 is fixed
const popper2AliasRemovalPlugin = [
'babel-plugin-module-resolver',
{
alias: {
'react-popper-2': 'react-popper'
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm jumping through hoops to get the generated output to look like

var _reactPopper = require("react-popper");

instead of

var _reactPopper = require("react-popper-2");

and still have the examples work in storybook

}
}
];

module.exports = {
...rootBabel,
plugins: [...rootBabel.plugins, popper2AliasRemovalPlugin]
};
4 changes: 4 additions & 0 deletions devtools/buildIndexFiles.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@ const path = require('path');

const srcPath = path.join(__dirname, '../src');

// Ignore errors from the browser API not being defined in node
// eslint-disable-next-line no-undefined
global.Element = undefined;

const isComponentDirectory = (source) => {
const ignoredDirectories = ['utils', 'Docs'];
return lstatSync(source).isDirectory() && !ignoredDirectories.some(ignored => source.includes(ignored));
Expand Down
61 changes: 60 additions & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
"scripts": {
"build:index": "babel-node devtools/buildIndexFiles.js",
"build:storybook": "babel-node devtools/buildVisualStories.js && babel-node scripts/copy-assets.js",
"build:cjs": "cross-env NODE_ENV=production BABEL_ENV=cjs babel src --ignore \"src/**/*.test.js\",\"src/**/*.stories.js\",\"src/Docs/*.stories.mdx\" --out-dir lib",
"build:cjs": "cross-env NODE_ENV=production BABEL_ENV=cjs babel src --config-file ./babel-build.config.js --ignore \"src/**/*.test.js\",\"src/**/*.stories.js\",\"src/Docs/*.stories.mdx\" --out-dir lib",
"build": "npm run build:index && rm -rf lib && npm run build:cjs",
"deploy": "gh-pages -d storybook-static",
"dry-run": "npm run build && npm publish --dry-run",
Expand Down Expand Up @@ -59,7 +59,6 @@
"react-focus-lock": "^2.3.1",
"react-overlays": "^3.2.0",
"react-popper": "^2.2.3",
"react-popper-2": "npm:react-popper@^2.2.3",
"shortid": "^2.2.14",
"tabbable": "^4.0.0"
},
Expand Down Expand Up @@ -92,6 +91,7 @@
"babel-jest": "^24.8.0",
"babel-loader": "8.1.0",
"babel-plugin-client-only-require": "^1.0.1",
"babel-plugin-module-resolver": "^4.0.0",
"babel-plugin-named-asset-import": "^0.3.2",
"babel-plugin-require-context-hook": "^1.0.0",
"babel-plugin-transform-react-remove-prop-types": "^0.4.23",
Expand Down Expand Up @@ -123,6 +123,7 @@
"puppeteer": "^3.3.0",
"react": "^16.8.0",
"react-dom": "^16.8.0",
"react-popper-2": "npm:react-popper@^2.2.3",
"react-router-dom": "^5.2.0",
"react-syntax-highlighter": "^12.2.1",
"react-test-renderer": "^16.8.0",
Expand Down
27 changes: 26 additions & 1 deletion src/DatePicker/__stories__/DatePicker.stories.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import DatePicker from '../DatePicker';
import FormLabel from '../../Forms/FormLabel';
import LayoutGrid from '../../LayoutGrid/LayoutGrid';
import moment from 'moment';
import React from 'react';
import {
boolean,
date,
Expand All @@ -13,6 +12,7 @@ import {
text,
withKnobs
} from '@storybook/addon-knobs';
import React, { useEffect, useRef, useState } from 'react';

export default {
title: 'Component API/DatePicker',
Expand Down Expand Up @@ -72,6 +72,31 @@ export const compact = () => (

compact.storyName = 'Compact';

export const withCustomFlipContainer = () => {
const containerRef = useRef();
const [flipContainer, setFlipContainer] = useState();

useEffect(() => {
setFlipContainer(containerRef.current);
});

return (
<div style={{ alignItems: 'center', display: 'flex' }}>
<div ref={containerRef} style={{
border: '1px solid black',
padding: '420px 40px 450px 240px'
}}>
<DatePicker popoverProps={{ flipContainer }} />
</div>
<div style={{
backgroundColor: '#444',
width: '180px',
height: '120px'
}} />
</div>
);
};

export const disabled = () => (
<DatePicker disabled />
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1426,3 +1426,83 @@ exports[`Storyshots Component API/DatePicker Weekday Start (Monday Start) 1`] =
</div>
</div>
`;

exports[`Storyshots Component API/DatePicker With Custom Flip Container 1`] = `
<div
dir="ltr"
>
<div
style={
Object {
"alignItems": "center",
"display": "flex",
}
}
>
<div
style={
Object {
"border": "1px solid black",
"padding": "420px 40px 450px 240px",
}
}
>
<div
defaultValue=""
onChange={[Function]}
onFocus={[Function]}
>
<div
className="fd-popover"
>
<div
onFocus={[Function]}
onMouseDown={[Function]}
onTouchStart={[Function]}
>
<div
className="fd-popover__control"
>
<div
aria-expanded={false}
aria-haspopup="true"
className="fd-input-group--control fd-input-group"
>
<input
className="fd-input fd-input-group__input"
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
onKeyPress={[Function]}
placeholder="MM/DD/YYYY"
type="text"
value=""
/>
<span
className="fd-input-group__addon fd-input-group__addon--button"
>
<button
aria-label="Choose date"
className="fd-button fd-button--transparent sap-icon--calendar fd-input-group__button"
onClick={[Function]}
type="button"
/>
</span>
</div>
</div>
</div>
</div>
</div>
</div>
<div
style={
Object {
"backgroundColor": "#444",
"height": "120px",
"width": "180px",
}
}
/>
</div>
</div>
`;
11 changes: 11 additions & 0 deletions src/Popover/Popover.js
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,8 @@ class Popover extends Component {
disableEdgeDetection,
disableKeyPressHandler,
disableTriggerOnClick,
fallbackPlacements,
flipContainer,
firstFocusIndex,
onClickOutside,
onEscapeKey,
Expand Down Expand Up @@ -167,6 +169,8 @@ class Popover extends Component {
<Popper
cssBlock='fd-popover'
disableEdgeDetection={disableEdgeDetection}
fallbackPlacements={fallbackPlacements}
flipContainer={flipContainer}
innerRef={innerRef}
noArrow={noArrow}
onClickOutside={chain(this.handleOutsideClick, onClickOutside)}
Expand Down Expand Up @@ -205,8 +209,15 @@ Popover.propTypes = {
/** Set to **true** to remove default triggerBody handler used in onClick.
* Useful for when a custom method is desired to open the Popover */
disableTriggerOnClick: PropTypes.bool,
/** Where else to position the popover when the original placement is out of bounds */
fallbackPlacements: PropTypes.arrayOf(PropTypes.oneOf(POPPER_PLACEMENTS)),
/** Index of the focusable item to focus first within the Popover */
firstFocusIndex: PropTypes.number,
/** The bounding container to use when determining if the popover is out of bounds */
flipContainer: PropTypes.oneOfType([
PropTypes.arrayOf(PropTypes.instanceOf(Element)),
PropTypes.instanceOf(Element)
]),
/** Set to **true** to render a popover without an arrow */
noArrow: PropTypes.bool,
/** 'bottom-start',
Expand Down
46 changes: 46 additions & 0 deletions src/Popover/Popover.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import Icon from '../Icon/Icon';
import Menu from '../Menu/Menu';
import { mount } from 'enzyme';
import Popover from './Popover';
import Popper from '../utils/_Popper';
import React from 'react';
import { Popper as ReactPopper } from 'react-popper-2';

Expand Down Expand Up @@ -234,6 +235,51 @@ describe('<Popover />', () => {
});
});

describe('flip modifiers', () => {
test('disableEdgeDetection props', () => {
const popoverWithParent = mount(popOver).setProps({ disableEdgeDetection: true });
const popperComponent = popoverWithParent.find(ReactPopper);
const flipModifier = popperComponent.props().modifiers.find(m => m.name === 'flip');
expect(flipModifier.enabled).toBe(false);
});

test('disableEdgeDetection default', () => {
const popoverWithParent = mount(popOver).setProps({ });
const popperComponent = popoverWithParent.find(ReactPopper);
const flipModifier = popperComponent.props().modifiers.find(m => m.name === 'flip');
expect(flipModifier.enabled).not.toBeDefined();
});

test('fallback placements props', () => {
const popoverWithParent = mount(popOver).setProps({ fallbackPlacements: ['top'] });
const popperComponent = popoverWithParent.find(ReactPopper);
const flipModifier = popperComponent.props().modifiers.find(m => m.name === 'flip');
expect(flipModifier.options.fallbackPlacements).toEqual(['top']);
});

test('fallback placements default', () => {
const popoverWithParent = mount(popOver).setProps({ });
const popperComponent = popoverWithParent.find(ReactPopper);
const flipModifier = popperComponent.props().modifiers.find(m => m.name === 'flip');
expect(flipModifier.options.fallbackPlacements).toEqual(Popper.defaultProps.fallbackPlacements);
});

test('flip container props', () => {
const boundary = document.createElement('div');
const popoverWithParent = mount(popOver).setProps({ flipContainer: boundary });
const popperComponent = popoverWithParent.find(ReactPopper);
const flipModifier = popperComponent.props().modifiers.find(m => m.name === 'flip');
expect(flipModifier.options.boundary).toBe(boundary);
});

test('flip container default', () => {
const popoverWithParent = mount(popOver).setProps({ });
const popperComponent = popoverWithParent.find(ReactPopper);
const flipModifier = popperComponent.props().modifiers.find(m => m.name === 'flip');
expect(flipModifier.options.boundary).not.toBeDefined();
});
});

describe('Callback handler', () => {
test('should dispatch the onClickOutside callback with the event', () => {
let f = jest.fn();
Expand Down
Loading