studiokit-scaffolding-js 5.1.0 → 5.1.1

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.
@@ -1,26 +1,64 @@
1
- import { ComponentClass, ComponentType } from 'react';
1
+ import React, { ComponentClass, ComponentType } from 'react';
2
+ import { ModalsState } from '../../redux/reducers/modalsReducer';
3
+ import { BaseReduxState } from '../../types';
2
4
  import { GuidComponentWrappedProps } from '../HOC/GuidComponent';
3
5
  export interface ConnectedModalWrappedProps {
4
6
  onEntering: () => void;
5
7
  onExited: () => void;
8
+ isTopOpenFullscreenModal?: boolean;
6
9
  }
7
10
  export interface ConnectedModalState {
8
11
  isModalOpen: boolean;
9
12
  }
13
+ export declare type ConnectedModalReduxProps = {
14
+ modals: ModalsState;
15
+ };
16
+ export declare const configureMapStateToProps: () => (state: BaseReduxState) => ConnectedModalReduxProps;
10
17
  /**
11
18
  * HOC that provides modal lifecycle event methods to coordinate modal state in redux.
12
19
  *
13
20
  * NOTE: Meant for testing. Should be wrapped in `guidComponent` to provide the `guid` prop normally.
14
21
  *
15
22
  * @param {*} WrappedComponent The component to wrap.
23
+ * @param {*} isFullscreen Are we rendering a fullscreen modal?
16
24
  */
17
- export declare function configureConnectedModalComponent<TOwnProps extends {}>(WrappedComponent: ComponentType<TOwnProps & ConnectedModalWrappedProps & GuidComponentWrappedProps>): ComponentClass<TOwnProps & GuidComponentWrappedProps>;
25
+ export declare function configureConnectedModalComponent<TOwnProps extends {}>(WrappedComponent: ComponentType<TOwnProps & ConnectedModalWrappedProps & GuidComponentWrappedProps>, isFullscreen?: boolean): {
26
+ new (props: TOwnProps & ConnectedModalWrappedProps & GuidComponentWrappedProps & ConnectedModalReduxProps): {
27
+ componentWillUnmount(): void;
28
+ onEntering: () => void;
29
+ onExited: () => void;
30
+ render(): JSX.Element;
31
+ context: any;
32
+ setState<K extends "isModalOpen">(state: ConnectedModalState | ((prevState: Readonly<ConnectedModalState>, props: Readonly<TOwnProps & ConnectedModalWrappedProps & GuidComponentWrappedProps & ConnectedModalReduxProps>) => ConnectedModalState | Pick<ConnectedModalState, K> | null) | Pick<ConnectedModalState, K> | null, callback?: (() => void) | undefined): void;
33
+ forceUpdate(callback?: (() => void) | undefined): void;
34
+ readonly props: Readonly<TOwnProps & ConnectedModalWrappedProps & GuidComponentWrappedProps & ConnectedModalReduxProps> & Readonly<{
35
+ children?: React.ReactNode;
36
+ }>;
37
+ state: Readonly<ConnectedModalState>;
38
+ refs: {
39
+ [key: string]: React.ReactInstance;
40
+ };
41
+ componentDidMount?(): void;
42
+ shouldComponentUpdate?(nextProps: Readonly<TOwnProps & ConnectedModalWrappedProps & GuidComponentWrappedProps & ConnectedModalReduxProps>, nextState: Readonly<ConnectedModalState>, nextContext: any): boolean;
43
+ componentDidCatch?(error: Error, errorInfo: React.ErrorInfo): void;
44
+ getSnapshotBeforeUpdate?(prevProps: Readonly<TOwnProps & ConnectedModalWrappedProps & GuidComponentWrappedProps & ConnectedModalReduxProps>, prevState: Readonly<ConnectedModalState>): any;
45
+ componentDidUpdate?(prevProps: Readonly<TOwnProps & ConnectedModalWrappedProps & GuidComponentWrappedProps & ConnectedModalReduxProps>, prevState: Readonly<ConnectedModalState>, snapshot?: any): void;
46
+ componentWillMount?(): void;
47
+ UNSAFE_componentWillMount?(): void;
48
+ componentWillReceiveProps?(nextProps: Readonly<TOwnProps & ConnectedModalWrappedProps & GuidComponentWrappedProps & ConnectedModalReduxProps>, nextContext: any): void;
49
+ UNSAFE_componentWillReceiveProps?(nextProps: Readonly<TOwnProps & ConnectedModalWrappedProps & GuidComponentWrappedProps & ConnectedModalReduxProps>, nextContext: any): void;
50
+ componentWillUpdate?(nextProps: Readonly<TOwnProps & ConnectedModalWrappedProps & GuidComponentWrappedProps & ConnectedModalReduxProps>, nextState: Readonly<ConnectedModalState>, nextContext: any): void;
51
+ UNSAFE_componentWillUpdate?(nextProps: Readonly<TOwnProps & ConnectedModalWrappedProps & GuidComponentWrappedProps & ConnectedModalReduxProps>, nextState: Readonly<ConnectedModalState>, nextContext: any): void;
52
+ };
53
+ contextType?: React.Context<any> | undefined;
54
+ };
18
55
  /**
19
56
  * HOC that provides modal lifecycle event methods to coordinate modal state in redux.
20
57
  *
21
58
  * Uses `guidComponent`.
22
59
  *
23
60
  * @param {*} WrappedComponent The component to wrap.
61
+ * @param {*} isFullscreen Are we rendering a fullscreen modal?
24
62
  */
25
- export declare function connectedModalComponent<TOwnProps extends {}>(WrappedComponent: ComponentType<TOwnProps & ConnectedModalWrappedProps & GuidComponentWrappedProps>): ComponentClass<TOwnProps>;
63
+ export declare function connectedModalComponent<TOwnProps extends {}>(WrappedComponent: ComponentType<TOwnProps & ConnectedModalWrappedProps & GuidComponentWrappedProps>, isFullscreen?: boolean): ComponentClass<TOwnProps>;
26
64
  export default connectedModalComponent;
@@ -46,26 +46,39 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
46
46
  return (mod && mod.__esModule) ? mod : { "default": mod };
47
47
  };
48
48
  Object.defineProperty(exports, "__esModule", { value: true });
49
- exports.connectedModalComponent = exports.configureConnectedModalComponent = void 0;
49
+ exports.connectedModalComponent = exports.configureConnectedModalComponent = exports.configureMapStateToProps = void 0;
50
+ var lodash_1 = require("lodash");
50
51
  var react_1 = __importStar(require("react"));
52
+ var react_redux_1 = require("react-redux");
51
53
  var actionCreator_1 = require("../../redux/actionCreator");
52
54
  var actions_1 = require("../../redux/actions");
53
55
  var GuidComponent_1 = __importDefault(require("../HOC/GuidComponent"));
56
+ var configureMapStateToProps = function () { return function (state) {
57
+ return {
58
+ modals: state.modals
59
+ };
60
+ }; };
61
+ exports.configureMapStateToProps = configureMapStateToProps;
54
62
  /**
55
63
  * HOC that provides modal lifecycle event methods to coordinate modal state in redux.
56
64
  *
57
65
  * NOTE: Meant for testing. Should be wrapped in `guidComponent` to provide the `guid` prop normally.
58
66
  *
59
67
  * @param {*} WrappedComponent The component to wrap.
68
+ * @param {*} isFullscreen Are we rendering a fullscreen modal?
60
69
  */
61
- function configureConnectedModalComponent(WrappedComponent) {
70
+ function configureConnectedModalComponent(WrappedComponent, isFullscreen) {
71
+ if (isFullscreen === void 0) { isFullscreen = false; }
62
72
  return /** @class */ (function (_super) {
63
73
  __extends(ConnectedModalComponent, _super);
64
74
  function ConnectedModalComponent(props) {
65
75
  var _this = _super.call(this, props) || this;
66
76
  _this.onEntering = function () {
67
- var guid = _this.props.guid;
68
- actionCreator_1.dispatchAction(actions_1.ACTION.MODAL_ENTERING, { guid: guid });
77
+ var _a;
78
+ var _b = _this.props, guid = _b.guid, modals = _b.modals;
79
+ // Store each modal's GUID in redux with a zero-based index to determine the order in which they were opened
80
+ var maxModal = lodash_1.maxBy(Object.values(modals), function (modal) { return modal.index; });
81
+ actionCreator_1.dispatchAction(actions_1.ACTION.MODAL_ENTERING, { guid: guid, index: ((_a = maxModal === null || maxModal === void 0 ? void 0 : maxModal.index) !== null && _a !== void 0 ? _a : -1) + 1, isFullscreen: isFullscreen });
69
82
  _this.setState({
70
83
  isModalOpen: true
71
84
  });
@@ -89,7 +102,12 @@ function configureConnectedModalComponent(WrappedComponent) {
89
102
  this.onExited();
90
103
  };
91
104
  ConnectedModalComponent.prototype.render = function () {
92
- return react_1.default.createElement(WrappedComponent, __assign({}, this.props, { onEntering: this.onEntering, onExited: this.onExited }));
105
+ var _a, _b;
106
+ var _c = this.props, modals = _c.modals, guid = _c.guid;
107
+ var topOpenFullscreenModal = lodash_1.maxBy(Object.values(modals).filter(function (m) { return m.isFullscreen; }), function (modal) { return modal.index; });
108
+ var thisModalIndex = (_b = (_a = modals[guid]) === null || _a === void 0 ? void 0 : _a.index) !== null && _b !== void 0 ? _b : null;
109
+ var isTopOpenFullscreenModal = (topOpenFullscreenModal === null || topOpenFullscreenModal === void 0 ? void 0 : topOpenFullscreenModal.index) === thisModalIndex;
110
+ return (react_1.default.createElement(WrappedComponent, __assign({}, this.props, { onEntering: this.onEntering, onExited: this.onExited, isTopOpenFullscreenModal: isTopOpenFullscreenModal })));
93
111
  };
94
112
  return ConnectedModalComponent;
95
113
  }(react_1.Component));
@@ -101,10 +119,14 @@ exports.configureConnectedModalComponent = configureConnectedModalComponent;
101
119
  * Uses `guidComponent`.
102
120
  *
103
121
  * @param {*} WrappedComponent The component to wrap.
122
+ * @param {*} isFullscreen Are we rendering a fullscreen modal?
104
123
  */
105
- function connectedModalComponent(WrappedComponent) {
106
- var component = configureConnectedModalComponent(WrappedComponent);
107
- return GuidComponent_1.default(component);
124
+ function connectedModalComponent(WrappedComponent, isFullscreen) {
125
+ if (isFullscreen === void 0) { isFullscreen = false; }
126
+ var component = configureConnectedModalComponent(WrappedComponent, isFullscreen);
127
+ var mapStateToProps = exports.configureMapStateToProps();
128
+ // @ts-ignore: could not match inferred type from the `connect` HOC
129
+ return react_redux_1.connect(mapStateToProps)(GuidComponent_1.default(component));
108
130
  }
109
131
  exports.connectedModalComponent = connectedModalComponent;
110
132
  exports.default = connectedModalComponent;
@@ -122,7 +122,7 @@ function configureFullscreenModalComponent(WrappedComponent) {
122
122
  });
123
123
  };
124
124
  FullscreenModalComponent.prototype.render = function () {
125
- var contentLabel = this.props.contentLabel;
125
+ var _a = this.props, contentLabel = _a.contentLabel, isTopOpenFullscreenModal = _a.isTopOpenFullscreenModal;
126
126
  var isOpen = this.state.isOpen;
127
127
  return (react_1.default.createElement(react_modal_1.default, { isOpen: isOpen, contentLabel: contentLabel, style: {
128
128
  content: {
@@ -144,7 +144,9 @@ function configureFullscreenModalComponent(WrappedComponent) {
144
144
  bottom: 0,
145
145
  zIndex: 2000
146
146
  }
147
- }, shouldCloseOnOverlayClick: false },
147
+ },
148
+ // hide the rendered portal if this is not the top open fullscreen modal
149
+ portalClassName: "ReactModalPortal" + (!isTopOpenFullscreenModal ? ' dn' : ''), shouldCloseOnOverlayClick: false },
148
150
  react_1.default.createElement(WrappedComponent, __assign({}, this.props, { closeModal: this.closeModal }))));
149
151
  };
150
152
  return FullscreenModalComponent;
@@ -167,7 +169,7 @@ exports.configureFullscreenModalComponent = configureFullscreenModalComponent;
167
169
  */
168
170
  function fullscreenModalComponent(WrappedComponent) {
169
171
  var component = configureFullscreenModalComponent(WrappedComponent);
170
- return ConnectedModalComponent_1.connectedModalComponent(component);
172
+ return ConnectedModalComponent_1.connectedModalComponent(component, true);
171
173
  }
172
174
  exports.fullscreenModalComponent = fullscreenModalComponent;
173
175
  exports.default = fullscreenModalComponent;
@@ -1,8 +1,12 @@
1
1
  import { Dictionary } from 'lodash';
2
2
  import { Action } from 'redux';
3
- export interface ModalAction extends Action {
3
+ export interface ModalActionValue {
4
+ index: number;
5
+ isFullscreen: boolean;
6
+ }
7
+ export interface ModalAction extends Action, ModalActionValue {
4
8
  guid: string;
5
9
  }
6
- export interface ModalsState extends Dictionary<boolean> {
10
+ export interface ModalsState extends Dictionary<ModalActionValue> {
7
11
  }
8
12
  export default function modalsReducer(state: ModalsState | undefined, action: ModalAction): ModalsState;
@@ -29,13 +29,17 @@ function modalsReducer(state, action) {
29
29
  var _a;
30
30
  if (state === void 0) { state = initialState; }
31
31
  var guid;
32
+ var index;
33
+ var isFullscreen;
32
34
  switch (action.type) {
33
35
  case actions_1.ACTION.MODAL_ENTERING: {
34
36
  guid = action.guid;
37
+ index = action.index;
38
+ isFullscreen = action.isFullscreen;
35
39
  if (state[guid]) {
36
40
  return state;
37
41
  }
38
- var newState = __assign(__assign({}, state), (_a = {}, _a["" + guid] = true, _a));
42
+ var newState = __assign(__assign({}, state), (_a = {}, _a["" + guid] = { index: index, isFullscreen: isFullscreen }, _a));
39
43
  return newState;
40
44
  }
41
45
  case actions_1.ACTION.MODAL_EXITED: {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "studiokit-scaffolding-js",
3
- "version": "5.1.0",
3
+ "version": "5.1.1",
4
4
  "description": "Common scaffolding for Studio apps at Purdue",
5
5
  "repository": "https://gitlab.com/purdue-informatics/studiokit/studiokit-scaffolding-js",
6
6
  "license": "MIT",