Skip to content
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

Hoist dialog #1497

Closed
wants to merge 54 commits into from
Closed
Changes from 1 commit
Commits
Show all changes
54 commits
Select commit Hold shift + click to select a range
471594f
First cut of hoist dialog with isDraggable option.
cnrudd Dec 26, 2019
7da244f
Removed unused imports.
cnrudd Dec 26, 2019
2bab03f
Added canMaskClickClose prop and maskClick handler
cnrudd Dec 27, 2019
8a90e0f
Fix maskclick handler
cnrudd Dec 27, 2019
ec01ac3
added todo
cnrudd Dec 27, 2019
73ccc65
Support autoFocus: true on dialog children
cnrudd Jan 2, 2020
107c490
Replaced react-draggable with react-rnd, which uses react-draggable.
cnrudd Jan 3, 2020
90f5f42
Added --xh-dialog-box-shadow
cnrudd Jan 3, 2020
d6650a3
Support for resizing
cnrudd Jan 3, 2020
9a7f05b
Fix repaint bug
cnrudd Jan 6, 2020
b3fe561
Remove redundant use of splitLayoutProps
cnrudd Jan 6, 2020
2a65a78
Remove bug comment and fix. Bug existed only on chrome 78.3x . Upgr…
cnrudd Jan 6, 2020
c8f401b
Refactored with elementfactory.
cnrudd Jan 6, 2020
8e347e3
Remove need for constructor.
cnrudd Jan 6, 2020
3af10ed
Converted Dialog from class comp to function comp.
cnrudd Jan 7, 2020
a3b640b
Support resizable config
cnrudd Jan 7, 2020
d583d76
Refactor, with dialogHeader impl
cnrudd Jan 7, 2020
fad1660
Linting.
cnrudd Jan 8, 2020
88b0d45
Let dialogs autocenter based on content dimensions;
cnrudd Jan 8, 2020
c06514e
Use given width and height props if resizeable
cnrudd Jan 14, 2020
42a4d00
throw if no dims props with resizable = true
cnrudd Jan 14, 2020
d7d7a10
Add Maximize Minimize toggle if resizable.
cnrudd Jan 14, 2020
41c129c
Implemented localstorage statemodel on dialog.
cnrudd Jan 17, 2020
cfaa2af
Improve handling of 0 position values.
cnrudd Jan 17, 2020
e3169c1
Improve safe state loading on dialog.
cnrudd Jan 18, 2020
1d57410
Remove unnecessary setting of defaults on RnD, fix unMaximize.
cnrudd Jan 18, 2020
21f9f5d
Support x, y props.
cnrudd Jan 18, 2020
10f08c2
Merge branch 'develop' into hoistDialog
cnrudd Jan 21, 2020
40c27b5
Merge branch 'develop' into hoistDialog
cnrudd Jan 21, 2020
28c1175
Cleanup setState on render logic
cnrudd Jan 23, 2020
ffb7b14
Unifiied dialog sub component with mask and closeOnOutsideClick props.
cnrudd Feb 2, 2020
f320af6
added --xh-dialog-box-shadow
cnrudd Feb 9, 2020
34475a7
Support style passthrough and zIndex prop
cnrudd Feb 9, 2020
07fb4bb
Merge branch 'hoistDialog' of github.com:exhi/hoist-react into hoistD…
cnrudd Feb 9, 2020
4c38c76
--xh-dialog-box-shadow dark theme
cnrudd Feb 9, 2020
321de51
Improve takeup of style & zIndex & rndoptions
cnrudd Feb 10, 2020
2f934ec
Cleanup prop and model passing.
cnrudd Feb 15, 2020
cf7e6c4
Remove unused zIndex
cnrudd Feb 15, 2020
b2bdf02
Support static base zindex for all dialogs
cnrudd Feb 15, 2020
4753e87
Better method name: calcPos -> calcCenteredPos.
cnrudd Feb 16, 2020
cc5a41c
React-rnd semver tweak.
cnrudd Feb 16, 2020
633563b
Put scss var decl on one line.
cnrudd Feb 16, 2020
8ed6342
Merge branch 'develop' into hoistDialog
cnrudd Feb 16, 2020
ea94ab1
Latest deps in yarn.lock
cnrudd Feb 16, 2020
8b8283a
Model passing cleanup.
cnrudd Feb 16, 2020
372a8c7
Fix setPositionState
cnrudd Feb 16, 2020
65816e0
Move showCloseButton to prop
cnrudd Feb 17, 2020
7e6d049
Rework as controlled component;
cnrudd Feb 18, 2020
9ac3175
Fix closeOnEscape handling
cnrudd Feb 19, 2020
ede3e35
convert closeOnEscape to prop
cnrudd Feb 19, 2020
3fdf152
Fix handling of specified size and width when not resizable.
cnrudd Feb 21, 2020
5f5c8b8
Merge branch 'develop' into hoistDialog
cnrudd Feb 21, 2020
272a2b0
Use Hoist Dialog for messages.
cnrudd Feb 21, 2020
3d7d0c8
Match dialog styles to current hoist/bp dialog styles.
cnrudd Feb 21, 2020
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
Next Next commit
First cut of hoist dialog with isDraggable option.
cnrudd committed Dec 26, 2019

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
commit 471594f5a5d5f64ead7863b5a94f1643cc0a86b5
143 changes: 143 additions & 0 deletions desktop/cmp/dialog/Dialog.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
/*
* This file belongs to Hoist, an application development toolkit
* developed by Extremely Heavy Industries (www.xh.io | [email protected])
*
* Copyright © 2019 Extremely Heavy Industries Inc.
*/

import React, {Component} from 'react';
import ReactDOM from 'react-dom';
import Draggable from 'react-draggable';
// import {isNil} from 'lodash';

// import {action, bindable} from '@xh/hoist/mobx';
import {HoistComponent, LayoutSupport, elemFactory} from '@xh/hoist/core';
import {createObservableRef} from '@xh/hoist/utils/react';

import {div, hbox, vbox, span, filler} from '@xh/hoist/cmp/layout';
import {splitLayoutProps} from '@xh/hoist/utils/react';

import './DialogStyles.scss';

// to add:
// click outside to close option?
// centered with backmask (traditional modal)

// see https://reactjs.org/docs/portals.html#event-bubbling-through-portals
// and
// https://github.com/palantir/blueprint/blob/develop/packages/core/src/components/portal/portal.tsx

export class Dialog extends Component {

dialogRootId = 'xh-dialog-root';

dialogWrapperRef = createObservableRef();

constructor(props) {
super(props);
this.dialogRoot = document.getElementById(this.dialogRootId);
if (!this.dialogRoot) {
this.dialogRoot = document.createElement('div');
this.dialogRoot.setAttribute('id', this.dialogRootId);
document.body.appendChild(this.dialogRoot);
}

this.el = document.createElement('div');
}

componentDidMount() {
// The portal element is inserted in the DOM tree after
// the Modal's children are mounted, meaning that children
// will be mounted on a detached DOM node. If a child
// component requires to be attached to the DOM tree
// immediately when mounted, for example to measure a
// DOM node, or uses 'autoFocus' in a descendant, add
// state to Modal and only render the children when Modal
// is inserted in the DOM tree.
this.dialogRoot.appendChild(this.el);

}

componentDidUpdate() {
this.dialogWrapperRef.current?.focus();
}

componentWillUnmount() {
this.dialogRoot.removeChild(this.el);
}

render() {
const {dragOptions, isDraggable, isOpen} = this.props;

if (isOpen === false) return null;

return ReactDOM.createPortal(
dragOptions || isDraggable ?
this.makeDraggable() :
this.makeDialog(),
this.el
);
}

makeDraggable() {
const [layoutProps, nonLayoutProps] = splitLayoutProps(this.props),
{minHeight, height, minWidth, width, ...restLayoutProps} = layoutProps,
{dragOptions = {}} = nonLayoutProps;

if (!dragOptions.handle && this.props.children?.type?.displayName == 'Panel') {
dragOptions.handle = '.xh-panel-header__title';
}

return <Draggable
bounds='body'
{...dragOptions}
>
{
div({
onKeyDown: (evt) => this.handleKeyDown(evt),
tabIndex: '0',
ref: this.dialogWrapperRef,
className: 'xh-dialog-root__draggable xh-dialog-root__content',
style: {
top: height || minHeight ? 'calc(50vh - ' + parseFloat(height || minHeight)/2 + 'px)' : null,
left: width || minWidth ? 'calc(50vw - ' + parseFloat(width || minWidth)/2 + 'px)' : null,
...restLayoutProps
},
items: this.props.children
})
}
</Draggable>;
}

makeDialog() {
const [layoutProps] = splitLayoutProps(this.props);

return div({
onKeyDown: (evt) => this.handleKeyDown(evt),
tabIndex: '0',
ref: this.dialogWrapperRef,
className: 'xh-dialog-root__fixed',
item: div({
className: 'xh-dialog-root__content',
style: {
...layoutProps
},
items: this.props.children
})
});
}

handleKeyDown(evt) {
switch (evt.key) {
case 'Escape':
this.handleEscapKey(evt); break;
}
}

handleEscapKey(evt) {
const {canEscapeKeyClose, close} = this.props;
if (canEscapeKeyClose) close(evt);
}
}

export const dialog = elemFactory(Dialog);
53 changes: 53 additions & 0 deletions desktop/cmp/dialog/DialogStyles.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
/*
* This file belongs to Hoist, an application development toolkit
* developed by Extremely Heavy Industries (www.xh.io | [email protected])
*
* Copyright © 2019 Extremely Heavy Industries Inc.
*/


#xh-dialog-root {
.xh-dialog-root__content {
box-shadow: 0 0 0 1px rgba(16, 22, 26, 0.1),
0 4px 8px rgba(16, 22, 26, 0.2),
0 18px 46px 6px rgba(16, 22, 26, 0.2);
border: var(--xh-border-solid);

> .xh-panel > .xh-panel-header {
padding-right: 0px;
}
}

.xh-dialog-root__draggable {
z-index: 1;
position: absolute;

&.xh-dialog-root__content {
> .xh-panel > .xh-panel-header {
.xh-panel-header__title {
cursor: pointer;
}
}
}
}

.xh-dialog-root__fixed {
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
opacity: 1;
background-color: rgba(16, 22, 26, 0.7);
overflow: auto;
-webkit-user-select: none;
-ms-user-select: none;
user-select: none;

display: flex;
align-items: center;
justify-content: center;
}
}


7 changes: 7 additions & 0 deletions desktop/cmp/dialog/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
/*
* This file belongs to Hoist, an application development toolkit
* developed by Extremely Heavy Industries (www.xh.io | [email protected])
*
* Copyright © 2019 Extremely Heavy Industries Inc.
*/
export * from './Dialog';
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -56,6 +56,7 @@
"qs": "~6.9.1",
"react-beautiful-dnd": "~11.0.5",
"react-dates": "~21.5.0",
"react-draggable": "^4.2.0",
"react-dropzone": "~10.1.9",
"react-onsenui": "~1.11.2",
"react-select": "~3.0.8",
10 changes: 9 additions & 1 deletion yarn.lock
Original file line number Diff line number Diff line change
@@ -2749,7 +2749,7 @@ class-utils@^0.3.5:
isobject "^3.0.0"
static-extend "^0.1.1"

classnames@^2.2, classnames@~2.2.6:
classnames@^2.2, classnames@^2.2.5, classnames@~2.2.6:
version "2.2.6"
resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.2.6.tgz#43935bffdd291f326dad0a205309b38d00f650ce"
integrity sha512-JR/iSQOSt+LQIWwrwEzJ9uk0xfN3mTVYMwt1Ir5mUcSN6pU+V4zQFFaJsclJbPuAUQH+yfWef6tm7l1quW3C8Q==
@@ -8389,6 +8389,14 @@ react-dom@~16.8.0:
prop-types "^15.6.2"
scheduler "^0.13.6"

react-draggable@^4.2.0:
version "4.2.0"
resolved "https://registry.yarnpkg.com/react-draggable/-/react-draggable-4.2.0.tgz#40cc5209082ca7d613104bf6daf31372cc0e1114"
integrity sha512-5wFq//gEoeTYprnd4ze8GrFc+Rbnx+9RkOMR3vk4EbWxj02U6L6T3yrlKeiw4X5CtjD2ma2+b3WujghcXNRzkw==
dependencies:
classnames "^2.2.5"
prop-types "^15.6.0"

react-dropzone@~10.1.9:
version "10.1.10"
resolved "https://registry.yarnpkg.com/react-dropzone/-/react-dropzone-10.1.10.tgz#f340290dfc26ac09ad68abc020ab6232c23d6cf3"