-
@@ -161,7 +224,7 @@ function getStyles(contentDialog: ContentDialog): {
buttonGroup?: React.CSSProperties;
button?: React.CSSProperties;
} {
- const { context, props: { style, defaultShow, background } } = contentDialog;
+ const { context, props: { style, background }, state: { showDialog } } = contentDialog;
const { theme } = context;
const { prepareStyles } = theme;
@@ -171,8 +234,8 @@ function getStyles(contentDialog: ContentDialog): {
margin: 0,
padding: 0,
zIndex: 2000,
- opacity: defaultShow ? 1 : 0,
- pointerEvents: defaultShow ? "all" : "none",
+ opacity: showDialog ? 1 : 0,
+ pointerEvents: showDialog ? "all" : "none",
position: "fixed",
top: 0,
left: 0,
@@ -185,7 +248,7 @@ function getStyles(contentDialog: ContentDialog): {
justifyContent: "center",
color: theme.baseHigh,
background: theme.altMediumHigh,
- transition: `all .25s ${defaultShow ? 0 : 0.25}s ease-in-out`,
+ transition: `all .25s ${showDialog ? 0 : 0.25}s ease-in-out`,
...style
}),
container: prepareStyles({
@@ -195,9 +258,9 @@ function getStyles(contentDialog: ContentDialog): {
width: "80%",
maxWidth: 720,
cursor: "default",
- transform: `scale(${defaultShow ? 1 : 0})`,
- opacity: defaultShow ? 1 : 0,
- transition: `all .25s ${defaultShow ? 0.25 : 0}s ease-in-out`
+ transform: `scale(${showDialog ? 1 : 0})`,
+ opacity: showDialog ? 1 : 0,
+ transition: `all .25s ${showDialog ? 0.25 : 0}s ease-in-out`
}),
statusBarTitle: prepareStyles({
color: "#fff",
diff --git a/src/DatePicker/index.tsx b/src/DatePicker/index.tsx
index bb93a47e..fd3269c2 100644
--- a/src/DatePicker/index.tsx
+++ b/src/DatePicker/index.tsx
@@ -1,6 +1,8 @@
import * as React from "react";
import * as PropTypes from "prop-types";
+import { codes } from "keycode";
+import AddBlurEvent from "../common/AddBlurEvent";
import Separator from "../Separator";
import IconButton from "../IconButton";
import ElementState from "../ElementState";
@@ -62,10 +64,10 @@ export class DatePicker extends React.Component
{
const { pickerItemHeight } = this.props;
scrollToYEasing(this.monthListView.rootElm, this.monthIndex * pickerItemHeight, 0.1);
scrollToYEasing(this.dateListView.rootElm, this.dateIndex * pickerItemHeight, 0.1);
scrollToYEasing(this.yearListView.rootElm, this.yearIndex * pickerItemHeight, 0.1);
+
+ this.addBlurEvent.setConfig({
+ addListener: this.state.showPicker,
+ clickExcludeElm: this.elementState.rootElm,
+ blurCallback: () => {
+ this.setState({
+ showPicker: false
+ });
+ },
+ blurKeyCodes: [codes.esc]
+ });
+ }
+
+ componentDidMount() {
+ this.addBlurEventMethod();
+ }
+
+ componentDidUpdate() {
+ this.addBlurEventMethod();
+ }
+
+ componentWillUnmount() {
+ this.addBlurEvent.cleanEvent();
}
toggleShowPicker = (showPicker?: any) => {
@@ -153,6 +181,7 @@ export class DatePicker extends React.Component this.elementState = elementState}
>
diff --git a/src/DropDownMenu/index.tsx b/src/DropDownMenu/index.tsx
index 76e232d6..f4d9436c 100644
--- a/src/DropDownMenu/index.tsx
+++ b/src/DropDownMenu/index.tsx
@@ -2,8 +2,8 @@ import * as React from "react";
import * as PropTypes from "prop-types";
import { codes } from "keycode";
-import Icon from "../Icon";
import AddBlurEvent from "../common/AddBlurEvent";
+import Icon from "../Icon";
export interface DataProps {
/**
@@ -52,8 +52,6 @@ export interface DropDownMenuState {
currentValues?: string[];
}
-const addBlurEvent = new AddBlurEvent();
-
const emptyFunc = () => {};
export class DropDownMenu extends React.Component
{
static defaultProps: DropDownMenuProps = {
@@ -82,6 +80,7 @@ export class DropDownMenu extends React.Component {
+ this.addBlurEvent.setConfig({
addListener: this.state.showList,
clickExcludeElm: this.rootElm,
blurCallback: () => {
@@ -118,8 +117,16 @@ export class DropDownMenu extends React.Component) => {
diff --git a/src/Menu/MenuItem.tsx b/src/Menu/MenuItem.tsx
index 443ea1fa..23149b8e 100644
--- a/src/Menu/MenuItem.tsx
+++ b/src/Menu/MenuItem.tsx
@@ -1,6 +1,8 @@
import * as React from "react";
import * as PropTypes from "prop-types";
+import { codes } from "keycode";
+import AddBlurEvent from "../common/AddBlurEvent";
import Icon from "../Icon";
import ElementState from "../ElementState";
@@ -55,6 +57,9 @@ export class MenuItem extends React.Component {
expanded: this.props.defaultExpanded
};
+ addBlurEvent = new AddBlurEvent();
+ elementState: ElementState;
+
static contextTypes = { theme: PropTypes.object };
context: { theme: ReactUWP.ThemeType };
@@ -66,6 +71,31 @@ export class MenuItem extends React.Component {
}
}
+ addBlurEventMethod = () => {
+ this.addBlurEvent.setConfig({
+ addListener: this.state.expanded,
+ clickExcludeElm: this.elementState.rootElm,
+ blurCallback: () => {
+ this.setState({
+ expanded: false
+ });
+ },
+ blurKeyCodes: [codes.esc]
+ });
+ }
+
+ componentDidMount() {
+ this.addBlurEventMethod();
+ }
+
+ componentDidUpdate() {
+ this.addBlurEventMethod();
+ }
+
+ componentWillUnmount() {
+ this.addBlurEvent.cleanEvent();
+ }
+
toggleExpanded = (expanded?: any) => {
if (typeof expanded === "boolean") {
if (expanded !== this.state.expanded) {
@@ -105,6 +135,7 @@ export class MenuItem extends React.Component {
hoverStyle={hoverStyle || {
background: theme.listLow
}}
+ ref={(elementState) => this.elementState = elementState}
>
diff --git a/src/NavigationView/index.tsx b/src/NavigationView/index.tsx
index 6bd40ce9..a8a43ef5 100644
--- a/src/NavigationView/index.tsx
+++ b/src/NavigationView/index.tsx
@@ -1,8 +1,9 @@
import * as React from "react";
import * as PropTypes from "prop-types";
+import { codes } from "keycode";
+import AddBlurEvent from "../common/AddBlurEvent";
import shallowEqual from "../common/shallowEqual";
-
import SlideInOut from "../Animate/SlideInOut";
import IconButton from "../IconButton";
import SplitViewCommand from "../SplitViewCommand";
@@ -96,18 +97,39 @@ export class NavigationView extends React.Component {
+ this.addBlurEvent.setConfig({
+ addListener: this.state.expanded,
+ clickExcludeElm: this.paneElm,
+ blurCallback: () => {
+ this.setState({
+ expanded: false
+ });
+ },
+ blurKeyCodes: [codes.esc]
+ });
+ }
+
componentDidMount() {
if (this.props.autoResize) {
this.autoResize();
window.addEventListener("resize", this.autoResize);
}
+ this.addBlurEventMethod();
}
- componentWillMount() {
- this.updateProps2State(this.props);
+ componentDidUpdate() {
+ this.addBlurEventMethod();
}
shouldComponentUpdate(nextProps: NavigationViewProps, nextState: NavigationViewState, nextContext: { theme: ReactUWP.ThemeType }) {
@@ -118,6 +140,7 @@ export class NavigationView extends React.Component {
@@ -201,7 +224,7 @@ export class NavigationView extends React.Component
-
+
this.paneElm = paneElm}>
diff --git a/src/PopupMenu/index.tsx b/src/PopupMenu/index.tsx
deleted file mode 100644
index cb6f4103..00000000
--- a/src/PopupMenu/index.tsx
+++ /dev/null
@@ -1,48 +0,0 @@
-import * as React from "react";
-import * as PropTypes from "prop-types";
-
-export interface DataProps {}
-
-export interface PopupMenuProps extends DataProps, React.HTMLAttributes
{}
-
-export default class PopupMenu extends React.Component {
- static defaultProps: PopupMenuProps = {
- };
-
- static contextTypes = { theme: PropTypes.object };
- context: { theme: ReactUWP.ThemeType };
-
- render() {
- const { ...attributes } = this.props;
- const { theme } = this.context;
- const styles = getStyles(this);
-
- return (
-
- PopupMenu
-
- );
- }
-}
-
-function getStyles(popupMenu: PopupMenu): {
- root?: React.CSSProperties;
-} {
- const {
- context: { theme },
- props: { style }
- } = popupMenu;
- const { prepareStyles } = theme;
-
- return {
- root: prepareStyles({
- fontSize: 14,
- color: theme.baseMediumHigh,
- background: theme.altMediumHigh,
- ...style
- })
- };
-}
diff --git a/src/SplitView/SplitViewPane.tsx b/src/SplitView/SplitViewPane.tsx
index c868855f..7d0f3ed3 100644
--- a/src/SplitView/SplitViewPane.tsx
+++ b/src/SplitView/SplitViewPane.tsx
@@ -8,6 +8,7 @@ export interface SplitViewPaneProps extends DataProps, React.HTMLAttributes {
static contextTypes = { theme: PropTypes.object };
context: { theme: ReactUWP.ThemeType };
+ rootElm: HTMLDivElement;
render() {
const { children, style, ...attributes } = this.props;
@@ -17,6 +18,7 @@ export class SplitViewPane extends React.Component {
this.rootElm = rootElm}
>
{children}
diff --git a/src/SplitView/index.doc.json b/src/SplitView/index.doc.json
index 3674a88d..bb431f21 100644
--- a/src/SplitView/index.doc.json
+++ b/src/SplitView/index.doc.json
@@ -18,6 +18,10 @@
"name": "SplitViewProps",
"documentation": ""
},
+ {
+ "name": "SplitViewState",
+ "documentation": ""
+ },
{
"name": "SplitView",
"documentation": ""
@@ -63,6 +67,12 @@
"documentation": "",
"isRequired": false,
"type": "CSSProperties"
+ },
+ {
+ "name": "onClosePane",
+ "documentation": "",
+ "isRequired": false,
+ "type": "() => void"
}
],
"documentation": ""
@@ -75,6 +85,29 @@
"HTMLAttributes"
]
},
+ {
+ "name": "SplitViewState",
+ "members": [
+ {
+ "name": "expanded",
+ "documentation": "",
+ "isRequired": false,
+ "type": "boolean"
+ }
+ ],
+ "documentation": ""
+ },
+ {
+ "documentation": "",
+ "name": "emptyFunc",
+ "type": "() => void",
+ "initializerText": " () => {}"
+ },
+ {
+ "name": "emptyFunc",
+ "documentation": "",
+ "type": "() => void"
+ },
{
"name": "SplitView",
"exports": [
@@ -85,7 +118,7 @@
},
{
"name": "defaultProps",
- "initializerText": " {\n expandedWidth: 320,\n displayMode: \"compact\",\n panePosition: \"right\"\n }",
+ "initializerText": " {\n expandedWidth: 320,\n displayMode: \"compact\",\n panePosition: \"right\",\n onClosePane: emptyFunc\n }",
"documentation": "",
"type": "SplitViewProps"
},
@@ -97,6 +130,49 @@
}
],
"members": [
+ {
+ "name": "state",
+ "initializerText": " {\n expanded: this.props.defaultExpanded\n }",
+ "documentation": "",
+ "type": "SplitViewState"
+ },
+ {
+ "name": "addBlurEvent",
+ "initializerText": " new AddBlurEvent()",
+ "documentation": "",
+ "type": "AddBlurEvent"
+ },
+ {
+ "name": "splitViewPaneElm",
+ "documentation": "",
+ "type": "HTMLDivElement"
+ },
+ {
+ "name": "componentWillReceiveProps",
+ "documentation": "",
+ "type": "(nextProps: SplitViewProps) => void"
+ },
+ {
+ "name": "addBlurEventMethod",
+ "initializerText": " () => {\n this.addBlurEvent.setConfig({\n addListener: this.state.expanded,\n clickExcludeElm: this.splitViewPaneElm,\n blurCallback: () => {\n this.setState({\n expanded: false\n }, this.props.onClosePane);\n },\n blurKeyCodes: [codes.esc]\n });\n }",
+ "documentation": "",
+ "type": "() => void"
+ },
+ {
+ "name": "componentDidMount",
+ "documentation": "",
+ "type": "() => void"
+ },
+ {
+ "name": "componentDidUpdate",
+ "documentation": "",
+ "type": "() => void"
+ },
+ {
+ "name": "componentWillUnmount",
+ "documentation": "",
+ "type": "() => void"
+ },
{
"name": "context",
"documentation": "",
diff --git a/src/SplitView/index.tsx b/src/SplitView/index.tsx
index 052cc0de..a415a847 100644
--- a/src/SplitView/index.tsx
+++ b/src/SplitView/index.tsx
@@ -1,8 +1,9 @@
import * as React from "react";
import * as PropTypes from "prop-types";
+import { codes } from "keycode";
+import AddBlurEvent from "../common/AddBlurEvent";
import SplitViewPane, { SplitViewPaneProps } from "./SplitViewPane";
-
export { SplitViewPane, SplitViewPaneProps };
export interface DataProps {
@@ -11,17 +12,62 @@ export interface DataProps {
defaultExpanded?: boolean;
panePosition?: "left" | "right";
paneStyle?: React.CSSProperties;
+ onClosePane?: () => void;
}
export interface SplitViewProps extends DataProps, React.HTMLAttributes {}
+export interface SplitViewState {
+ expanded?: boolean;
+}
-
-export class SplitView extends React.Component {
+const emptyFunc = () => {};
+export class SplitView extends React.Component {
static defaultProps: SplitViewProps = {
expandedWidth: 320,
displayMode: "compact",
- panePosition: "right"
+ panePosition: "right",
+ onClosePane: emptyFunc
};
+ state: SplitViewState = {
+ expanded: this.props.defaultExpanded
+ };
+
+ addBlurEvent = new AddBlurEvent();
+ splitViewPaneElm: HTMLDivElement;
+
+ componentWillReceiveProps(nextProps: SplitViewProps) {
+ const { defaultExpanded } = nextProps;
+ if (defaultExpanded !== void 0 && defaultExpanded !== this.state.expanded) {
+ this.setState({
+ expanded: defaultExpanded
+ });
+ }
+ }
+
+ addBlurEventMethod = () => {
+ this.addBlurEvent.setConfig({
+ addListener: this.state.expanded,
+ clickExcludeElm: this.splitViewPaneElm,
+ blurCallback: () => {
+ this.setState({
+ expanded: false
+ }, this.props.onClosePane);
+ },
+ blurKeyCodes: [codes.esc]
+ });
+ }
+
+ componentDidMount() {
+ this.addBlurEventMethod();
+ }
+
+ componentDidUpdate() {
+ this.addBlurEventMethod();
+ }
+
+ componentWillUnmount() {
+ this.addBlurEvent.cleanEvent();
+ }
static contextTypes = { theme: PropTypes.object };
context: { theme: ReactUWP.ThemeType };
@@ -34,6 +80,7 @@ export class SplitView extends React.Component {
panePosition,
children,
paneStyle,
+ onClosePane,
...attributes
} = this.props;
const { theme } = this.context;
@@ -46,6 +93,11 @@ export class SplitView extends React.Component {
if (child.type === SplitViewPane) {
splitViewPanes.push(React.cloneElement(child, {
style: { ...styles.pane, ...child.props.style },
+ ref: (splitViewPane: SplitViewPane) => {
+ if (splitViewPane) {
+ this.splitViewPaneElm = splitViewPane.rootElm;
+ }
+ },
key: index.toString()
}));
} else {
@@ -77,11 +129,13 @@ function getStyles(splitView: SplitView): {
context,
props: {
style,
- defaultExpanded,
expandedWidth,
displayMode,
panePosition,
paneStyle
+ },
+ state: {
+ expanded
}
} = splitView;
const { theme } = context;
@@ -122,7 +176,7 @@ function getStyles(splitView: SplitView): {
...(isCompact ? {
height: "100%",
width: expandedWidth,
- transform: `translate3d(${defaultExpanded ? 0 : expandedWidth}px, 0, 0)`
+ transform: `translate3d(${expanded ? 0 : expandedWidth}px, 0, 0)`
} as React.CSSProperties : void 0),
...(isOverlay ? {
position: "absolute",
@@ -131,7 +185,7 @@ function getStyles(splitView: SplitView): {
left: panePositionIsRight ? void 0 : 0,
height: "100%",
width: expandedWidth,
- transform: `translate3d(${defaultExpanded ? 0 : expandedWidth}px, 0, 0)`
+ transform: `translate3d(${expanded ? 0 : expandedWidth}px, 0, 0)`
} as React.CSSProperties : void 0),
...paneStyle
})
diff --git a/src/TimePicker/index.tsx b/src/TimePicker/index.tsx
index e2f7d607..27084bc4 100644
--- a/src/TimePicker/index.tsx
+++ b/src/TimePicker/index.tsx
@@ -1,6 +1,8 @@
import * as React from "react";
import * as PropTypes from "prop-types";
+import { codes } from "keycode";
+import AddBlurEvent from "../common/AddBlurEvent";
import Separator from "../Separator";
import IconButton from "../IconButton";
import ElementState from "../ElementState";
@@ -63,6 +65,9 @@ export class TimePicker extends React.Component {
+ this.addBlurEvent.setConfig({
+ addListener: this.state.showPicker,
+ clickExcludeElm: this.elementState.rootElm,
+ blurCallback: () => {
+ this.setState({
+ showPicker: false
+ });
+ },
+ blurKeyCodes: [codes.esc]
+ });
+ }
+
+ componentDidMount() {
+ this.addBlurEventMethod();
+ }
+
componentDidUpdate() {
const { pickerItemHeight } = this.props;
scrollToYEasing(this.hourListView.rootElm, this.hourIndex * pickerItemHeight, 0.1);
scrollToYEasing(this.minuteListView.rootElm, this.minuteIndex * pickerItemHeight, 0.1);
scrollToYEasing(this.timeTypeListView.rootElm, this.timeTypeIndex * pickerItemHeight, 0.1);
+
+ this.addBlurEventMethod();
+ }
+
+ componentWillUnmount() {
+ this.addBlurEvent.cleanEvent();
}
toggleShowPicker = (showPicker?: any) => {
@@ -144,6 +172,7 @@ export class TimePicker extends React.Component this.elementState = elementState}
>
diff --git a/src/common/addBlurEvent.ts b/src/common/addBlurEvent.ts
index 70b5afe6..e2a7fcae 100644
--- a/src/common/addBlurEvent.ts
+++ b/src/common/addBlurEvent.ts
@@ -33,7 +33,7 @@ export default class AddBlurEvent {
this.clickListener = (e: Event) => {
if (clickExcludeElm) {
if (clickExcludeElm.contains(e.target as Node)) {
- this.cleanEvent();
+ return;
} else {
this.cleanEvent();
blurCallback(e);