You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

132 lines
3.0 KiB

import "./Blob.sass";
import {WithChildren} from "../Shared";
import {CSSProperties, useCallback, useMemo} from "react";
import {Size} from "../../models/Shared";
interface BlobProps extends WithChildren {
onClick?: () => void
disabled?: boolean
fillOn?: Size
flex?: number
color?: "gray" | "green" | "blue" | "red" | "yellow" | "indigo"
}
function Blob({onClick, fillOn, disabled, flex, color, children}: BlobProps) {
const style: CSSProperties = useMemo(() => {
return flex ? {flex} : {};
}, [flex]);
const classNames = useMemo(() => {
const val = ["Blob"];
if (onClick !== undefined && !disabled) {
val.push("Blob-clickable")
}
if (fillOn) {
val.push(`Blob-fill-on-${fillOn}`);
}
val.push(`Blob-${color || "gray"}`)
return val;
}, [onClick, fillOn, disabled, color]);
return (
<div style={style} className={classNames.join(" ")} onClick={disabled ? undefined : onClick}>
<div className="Blob-body">
{children}
</div>
</div>
);
}
interface BlobTextProps extends WithChildren {
centered?: boolean
flex?: number
}
export function BlobText({centered, children, flex}: BlobTextProps) {
const clazz = useMemo(() => {
const classNames = ["BlobText"];
if (centered) {
classNames.push("BlobText-centered");
}
return classNames.join(" ");
}, [centered]);
return (
<div className={clazz} style={{flex}}>
{children}
</div>
);
}
interface BlobTextLineProps extends WithChildren {
secondary?: boolean
flex?: number
}
export function BlobTextLine({secondary, flex, children}: BlobTextLineProps) {
const clazz = useMemo(() => {
const classNames = ["BlobTextLine"];
if (secondary) {
classNames.push("BlobTextLine-secondary");
}
return classNames.join(" ");
}, [secondary]);
return (
<div className={clazz} style={{flex}}>
{children}
</div>
);
}
type BlobInputProps =
| BaseBlobInputProps<"number", number>
| BaseBlobInputProps<"text" | "password" | undefined, string>
interface BaseBlobInputProps<T, V> {
type: T
name?: string
flex?: number
value: V
disabled?: boolean
onChange?: (newValue: V) => void
placeholder?: string
}
export function BlobInput({type, name, flex, disabled, value, onChange, placeholder}: BlobInputProps) {
const actualOnChange = useCallback((input: string) => {
if (onChange === undefined) return;
if (type === "number") {
onChange(parseInt(input, 10) || 0);
} else {
onChange(input);
}
}, [onChange]);
return (
<input
placeholder={placeholder}
disabled={disabled}
className="BlobInput"
name={name}
type={type || "text"}
value={`${value || ""}`}
style={flex ? {flex} : {width: 50}}
onChange={e => actualOnChange(e.target.value || "")}
/>
);
}
export function BlobGroup({children}: WithChildren) {
return (
<div className="BlobGroup">
{children}
</div>
);
}
export default Blob;