mirror of
https://github.com/whscullin/apple2js.git
synced 2024-01-12 14:14:38 +00:00
303838f63d
* Use CSS modules * Fix tests * Feedback
169 lines
4.3 KiB
TypeScript
169 lines
4.3 KiB
TypeScript
import { h, Fragment, JSX } from 'preact';
|
|
import { useCallback, useContext } from 'preact/hooks';
|
|
import { Modal, ModalContent, ModalFooter } from './Modal';
|
|
import { OptionsContext } from './OptionsContext';
|
|
import {
|
|
BOOLEAN_OPTION,
|
|
SELECT_OPTION,
|
|
BooleanOption,
|
|
Option,
|
|
OptionSection,
|
|
SelectOption,
|
|
} from '../options';
|
|
|
|
import styles from './css/OptionsModal.module.css';
|
|
|
|
/**
|
|
* Boolean property interface
|
|
*/
|
|
interface BooleanProps {
|
|
option: BooleanOption;
|
|
value: boolean;
|
|
setValue: (name: string, value: boolean) => void;
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @param option Boolean option
|
|
* @param value Current value
|
|
* @param setValue Value setter
|
|
* @returns Boolean component
|
|
*/
|
|
const Boolean = ({ option, value, setValue } : BooleanProps) => {
|
|
const { label, name } = option;
|
|
const onChange = useCallback(
|
|
(event: JSX.TargetedMouseEvent<HTMLInputElement>) =>
|
|
setValue(name, event.currentTarget.checked)
|
|
, [name, setValue]
|
|
);
|
|
|
|
return (
|
|
<li>
|
|
<input
|
|
type="checkbox"
|
|
checked={value}
|
|
onChange={onChange}
|
|
/>
|
|
<label>{label}</label>
|
|
</li>
|
|
);
|
|
};
|
|
|
|
/**
|
|
* Select property interface
|
|
*/
|
|
interface SelectProps {
|
|
option: SelectOption;
|
|
value: string;
|
|
setValue: (name: string, value: string) => void;
|
|
}
|
|
|
|
/**
|
|
* Select component that provides a dropdown to choose between
|
|
* options.
|
|
*
|
|
* @param option Select option
|
|
* @param value Current value
|
|
* @param setValue Value setter
|
|
* @returns Select component
|
|
*/
|
|
const Select = ({ option, value, setValue } : SelectProps) => {
|
|
const { label, name } = option;
|
|
const onChange = useCallback(
|
|
(event: JSX.TargetedMouseEvent<HTMLSelectElement>) => {
|
|
setValue(name, event.currentTarget.value);
|
|
},
|
|
[name, setValue]
|
|
);
|
|
|
|
const makeOption = (option: { name: string; value: string }) => (
|
|
<option selected={option.value === value} value={option.value}>
|
|
{option.name}
|
|
</option>
|
|
);
|
|
|
|
return (
|
|
<li>
|
|
<select onChange={onChange}>
|
|
{option.values.map(makeOption)}
|
|
</select>
|
|
<label>{label}</label>
|
|
</li>
|
|
);
|
|
};
|
|
|
|
/**
|
|
* OptionsModal properties
|
|
*/
|
|
export interface OptionsModalProps {
|
|
isOpen: boolean;
|
|
onClose: (closeBox?: boolean) => void;
|
|
}
|
|
|
|
/**
|
|
* Modal to allow editing of various component provided
|
|
* options, like screen and cpu type
|
|
*
|
|
* @param Modal params
|
|
* @returns OptionsModal component
|
|
*/
|
|
export const OptionsModal = ({ isOpen, onClose }: OptionsModalProps) => {
|
|
const options = useContext(OptionsContext);
|
|
const sections = options.getSections();
|
|
const setValue = useCallback(( name: string, value: string | boolean ) => {
|
|
options.setOption(name, value);
|
|
}, [options]);
|
|
|
|
const makeOption = (option: Option) => {
|
|
const { name, type } = option;
|
|
const value = options.getOption(name);
|
|
switch (type) {
|
|
case BOOLEAN_OPTION:
|
|
return (
|
|
<Boolean
|
|
option={option as BooleanOption}
|
|
value={value as boolean}
|
|
setValue={setValue}
|
|
/>
|
|
);
|
|
case SELECT_OPTION:
|
|
return (
|
|
<Select
|
|
option={option as SelectOption}
|
|
value={value as string}
|
|
setValue={setValue}
|
|
/>
|
|
);
|
|
default:
|
|
break;
|
|
}
|
|
};
|
|
|
|
const makeSection = (section: OptionSection) => {
|
|
return (
|
|
<>
|
|
<h3>{section.name}</h3>
|
|
<ul>
|
|
{section.options.map(makeOption)}
|
|
</ul>
|
|
</>
|
|
);
|
|
};
|
|
|
|
const doClose = useCallback(() => onClose(), [onClose]);
|
|
|
|
return (
|
|
<Modal title="Options" isOpen={isOpen} onClose={onClose}>
|
|
<ModalContent>
|
|
<div className={styles.optionsModal}>
|
|
{sections.map(makeSection)}
|
|
</div>
|
|
<i>* Reload page to take effect</i>
|
|
</ModalContent>
|
|
<ModalFooter>
|
|
<button onClick={doClose}>Close</button>
|
|
</ModalFooter>
|
|
</Modal>
|
|
);
|
|
};
|