function Dialog({
className, isOpen, title, onAfterOpen, onAfterClose,
contentOptions, onRequestClose, closeFromOutside, children,
+ invisibleScroll,
}) {
return (
<RawModal
{contentOptions}
</Header>
<div className="dialog__content__wrapper">
- <ScrollView autoHide>
+ <ScrollView autoHide invisible={invisibleScroll}>
<div className="dialog__content-container">
{children}
</div>
onAfterClose: null,
onRequestClose: null,
closeFromOutside: true,
+ invisibleScroll: false,
};
Dialog.propTypes = {
onRequestClose: PropTypes.func,
closeFromOutside: PropTypes.bool,
children: PropTypes.node.isRequired,
+ invisibleScroll: PropTypes.bool,
};
export default Dialog;
flex-direction: column;
}
}
-
-.dialog__content-container {
- padding-top: var(--sp-extra-tight);
- padding-bottom: var(--sp-extra-loose);
-}
\ No newline at end of file
--- /dev/null
+import React, { useState, useEffect } from 'react';
+
+import cons from '../../../client/state/cons';
+
+import navigation from '../../../client/state/navigation';
+import IconButton from '../../atoms/button/IconButton';
+import Dialog from './Dialog';
+
+import CrossIC from '../../../../public/res/ic/outlined/cross.svg';
+
+function ReusableDialog() {
+ const [isOpen, setIsOpen] = useState(false);
+ const [data, setData] = useState(null);
+
+ useEffect(() => {
+ const handleOpen = (title, render, afterClose) => {
+ setIsOpen(true);
+ setData({ title, render, afterClose });
+ };
+ navigation.on(cons.events.navigation.REUSABLE_DIALOG_OPENED, handleOpen);
+ return () => {
+ navigation.removeListener(cons.events.navigation.REUSABLE_DIALOG_OPENED, handleOpen);
+ };
+ }, []);
+
+ const handleAfterClose = () => {
+ data.afterClose();
+ setData(null);
+ };
+
+ const handleRequestClose = () => {
+ setIsOpen(false);
+ };
+
+ return (
+ <Dialog
+ isOpen={isOpen}
+ title={data?.title || ''}
+ onAfterClose={handleAfterClose}
+ onRequestClose={handleRequestClose}
+ contentOptions={<IconButton src={CrossIC} onClick={handleRequestClose} tooltip="Close" />}
+ invisibleScroll
+ >
+ {data?.render(handleRequestClose) || <div />}
+ </Dialog>
+ );
+}
+
+export default ReusableDialog;
@use '../../partials/dir';
.create-room {
+ margin: var(--sp-normal);
@include dir.side(margin, var(--sp-normal), var(--sp-extra-tight));
&__form > * {
import ViewSource from '../view-source/ViewSource';
import CreateRoom from '../create-room/CreateRoom';
+import ReusableDialog from '../../molecules/dialog/ReusableDialog';
+
function Dialogs() {
return (
<>
<CreateRoom />
<SpaceAddExisting />
<Search />
+
+ <ReusableDialog />
</>
);
}
onRequestClose={() => setIsOpen(false)}
contentOptions={<IconButton src={CrossIC} onClick={() => setIsOpen(false)} tooltip="Close" />}
>
- {
- readers.map(renderPeople)
- }
+ <div style={{ marginTop: 'var(--sp-tight)', marginBottom: 'var(--sp-extra-loose)' }}>
+ {
+ readers.map(renderPeople)
+ }
+ </div>
</Dialog>
);
}
afterClose,
});
}
+
+export function openReusableDialog(title, render, afterClose) {
+ appDispatcher.dispatch({
+ type: cons.actions.navigation.OPEN_REUSABLE_DIALOG,
+ title,
+ render,
+ afterClose,
+ });
+}
CLICK_REPLY_TO: 'CLICK_REPLY_TO',
OPEN_SEARCH: 'OPEN_SEARCH',
OPEN_REUSABLE_CONTEXT_MENU: 'OPEN_REUSABLE_CONTEXT_MENU',
+ OPEN_REUSABLE_DIALOG: 'OPEN_REUSABLE_DIALOG',
},
room: {
JOIN: 'JOIN',
REPLY_TO_CLICKED: 'REPLY_TO_CLICKED',
SEARCH_OPENED: 'SEARCH_OPENED',
REUSABLE_CONTEXT_MENU_OPENED: 'REUSABLE_CONTEXT_MENU_OPENED',
+ REUSABLE_DIALOG_OPENED: 'REUSABLE_DIALOG_OPENED',
},
roomList: {
ROOMLIST_UPDATED: 'ROOMLIST_UPDATED',
action.afterClose,
);
},
+ [cons.actions.navigation.OPEN_REUSABLE_DIALOG]: () => {
+ this.emit(
+ cons.events.navigation.REUSABLE_DIALOG_OPENED,
+ action.title,
+ action.render,
+ action.afterClose,
+ );
+ },
};
actions[action.type]?.();
}