mirror of
https://github.com/whscullin/apple2js.git
synced 2024-01-12 14:14:38 +00:00
189 lines
4.1 KiB
TypeScript
189 lines
4.1 KiB
TypeScript
import { h, FunctionalComponent } from 'preact';
|
|
import { useCallback } from 'preact/hooks';
|
|
import { useHotKey } from './hooks/useHotKey';
|
|
|
|
/**
|
|
* Temporary JS styling while I figure out how I really want
|
|
* to do it.
|
|
*/
|
|
const modalOverlayStyle = {
|
|
position: 'fixed',
|
|
left: '0',
|
|
right: '0',
|
|
top: '0',
|
|
bottom: '0',
|
|
display: 'flex',
|
|
alignItems: 'center',
|
|
justifyContent: 'center',
|
|
background: 'rgba(0,0,0,0.6)',
|
|
zIndex: 1,
|
|
};
|
|
|
|
const modalStyle = {
|
|
backgroundColor: '#c4c1a0',
|
|
padding: '10px',
|
|
maxHeight: '100vh',
|
|
borderRadius: '4px',
|
|
overflowY: 'auto',
|
|
boxSizing: 'border-box',
|
|
};
|
|
|
|
const modalHeaderStyle = {
|
|
display: 'flex',
|
|
fontSize: '14px',
|
|
justifyContent: 'space-between',
|
|
alignItems: 'center',
|
|
background: '#44372C',
|
|
color: '#fff',
|
|
padding: '5px 11px',
|
|
border: '1px outset #66594E',
|
|
borderRadius: '3px',
|
|
};
|
|
|
|
const modalTitleStyle = {
|
|
marginTop: 0,
|
|
marginBottom: 0,
|
|
fontWeight: 600,
|
|
fontSize: '1.25rem',
|
|
lineHeight: 1.25,
|
|
color: '#fff',
|
|
boxSizing: 'border-box',
|
|
};
|
|
|
|
const modalContentStyle = {
|
|
marginTop: '10px',
|
|
marginBottom: '10px',
|
|
lineHeight: 1.5,
|
|
color: '#000'
|
|
};
|
|
|
|
const modalFooterStyle = {
|
|
textAlign: 'right'
|
|
};
|
|
|
|
/**
|
|
* ModalOverlay creates a semi-transparent overlay in which the
|
|
* modal is centered.
|
|
*
|
|
* @returns ModalOverlay component
|
|
*/
|
|
export const ModalOverlay: FunctionalComponent = ({ children }) => {
|
|
return (
|
|
<div style={modalOverlayStyle}>
|
|
{children}
|
|
</div>
|
|
);
|
|
};
|
|
|
|
/**
|
|
* ModalContent provides a styled container for modal content
|
|
*
|
|
* @returns ModalContent component
|
|
*/
|
|
export const ModalContent: FunctionalComponent = ({ children }) => {
|
|
return (
|
|
<div style={modalContentStyle}>
|
|
{children}
|
|
</div>
|
|
);
|
|
};
|
|
|
|
/**
|
|
* ModalFooter provides a right-aligned container for modal buttons.
|
|
*
|
|
* @returns ModalFooter component
|
|
*/
|
|
export const ModalFooter: FunctionalComponent = ({ children }) => {
|
|
return (
|
|
<div style={modalFooterStyle}>
|
|
{children}
|
|
</div>
|
|
);
|
|
};
|
|
|
|
/**
|
|
* ModalCloseButton component properties
|
|
*/
|
|
interface ModalCloseButtonProp {
|
|
onClose: (closeBox?: boolean) => void;
|
|
}
|
|
|
|
/**
|
|
* Renders a close button and registers a global Escape key
|
|
* hook to trigger it.
|
|
*
|
|
* @param onClose Close callback
|
|
* @returns ModalClose component
|
|
*/
|
|
export const ModalCloseButton = ({ onClose }: ModalCloseButtonProp) => {
|
|
const doClose = useCallback(() => onClose(true), [onClose]);
|
|
useHotKey('Escape', doClose);
|
|
|
|
return (
|
|
<button onClick={doClose} title="Close">
|
|
{'\u2715'}
|
|
</button>
|
|
);
|
|
};
|
|
|
|
/**
|
|
* ModalHeader component properties
|
|
*/
|
|
export interface ModalHeaderProps {
|
|
onClose?: (closeBox?: boolean) => void;
|
|
title: string;
|
|
}
|
|
|
|
/**
|
|
* Header used internally for Modal component
|
|
*
|
|
* @param onClose Close callback
|
|
* @param title Modal title
|
|
* @returns ModalHeader component
|
|
*/
|
|
export const ModalHeader = ({ onClose, title }: ModalHeaderProps) => {
|
|
return (
|
|
<div style={modalHeaderStyle}>
|
|
<span style={modalTitleStyle}>{title}</span>
|
|
{onClose && <ModalCloseButton onClose={onClose} />}
|
|
</div>
|
|
);
|
|
};
|
|
|
|
/**
|
|
* Modal component properties
|
|
*/
|
|
export interface ModalProps {
|
|
onClose?: (closeBox?: boolean) => void;
|
|
isOpen: boolean;
|
|
title: string;
|
|
}
|
|
|
|
/**
|
|
* Very simple modal component, provides a transparent overlay, title bar
|
|
* with optional close box if onClose is provided. ModalContent and
|
|
* ModalFooter components are provided for convenience but not required.
|
|
*
|
|
* @param isOpen true to show modal
|
|
* @param title Modal title
|
|
* @onClose Close callback
|
|
* @returns Modal component
|
|
*/
|
|
export const Modal: FunctionalComponent<ModalProps> = ({
|
|
isOpen,
|
|
title,
|
|
children,
|
|
onClose
|
|
}) => {
|
|
return (
|
|
isOpen ? (
|
|
<ModalOverlay>
|
|
<div style={modalStyle}>
|
|
{title && <ModalHeader onClose={onClose} title={title} />}
|
|
{children}
|
|
</div>
|
|
</ModalOverlay>
|
|
) : null
|
|
);
|
|
};
|