@airplane/views
Version:
A React library for building Airplane views. Views components are optimized in style and functionality to produce internal apps that are easy to build and maintain.
113 lines (112 loc) • 5.13 kB
JavaScript
import { jsxs, jsx } from "react/jsx-runtime";
import { createStyles } from "@mantine/core";
import { useState, useEffect } from "react";
import { Button } from "../button/Button.js";
import { ChevronUpIconSolid, ChevronDownIconSolid } from "@airplane/views/icons/index.js";
import { Stack } from "../stack/Stack.js";
import { Text } from "../text/Text.js";
import { TextInput } from "../textinput/TextInput.js";
const useStyles = createStyles((theme) => ({
AMPMButton: {
border: theme.other.borderStyles.default,
"&:disabled": {
backgroundColor: theme.colors.gray[1],
color: theme.colors.gray[4],
border: theme.other.borderStyles.light
}
}
}));
const IncDec = (props) => /* @__PURE__ */ jsx(Button, { variant: "subtle", compact: props.compact, disabled: props.disabled, onMouseDown: (e) => e.preventDefault(), onClick: props.onClick, children: props.isInc ? props.compact ? props.byFive ? /* @__PURE__ */ jsx(Text, { color: "gray.4", size: "sm", disableMarkdown: true, children: "+5" }) : /* @__PURE__ */ jsx(Text, { color: "gray.4", size: "lg", disableMarkdown: true, children: "+" }) : /* @__PURE__ */ jsx(ChevronUpIconSolid, { color: "gray" }) : props.compact ? props.byFive ? /* @__PURE__ */ jsx(Text, { color: "gray.4", size: "sm", disableMarkdown: true, children: "-5" }) : /* @__PURE__ */ jsx(Text, { color: "gray.4", size: "lg", disableMarkdown: true, children: "-" }) : /* @__PURE__ */ jsx(ChevronDownIconSolid, { color: "gray" }) });
const mod = (n, m) => (n % m + m) % m;
const TimeInput = ({
readOnly,
min,
max,
preventFocus,
...props
}) => {
const base = max - min + 1;
const def = mod(-min, base) + min;
const digits = 2;
const increment = props.incByFive ? 5 : 1;
const pad = (n) => String(n).padStart(digits, "0");
const [value, setValue] = useState(props.value);
const [raw, setRaw] = useState(pad(value ?? def));
useEffect(() => {
if (props.value !== value) {
setRaw(pad(props.value ?? min));
setValue(props.value);
}
}, [props.value, value, min]);
const onChange = (value2) => {
setValue(value2);
if (value2 !== void 0 && value2 >= min && value2 <= max) {
props.onChange(value2);
}
};
const onBlur = () => {
let v = value;
if (v === void 0) {
v = def;
} else if (v < min) {
v = min;
} else if (v > max) {
v = max;
}
setRaw(pad(v));
onChange(v);
};
return /* @__PURE__ */ jsxs(Stack, { spacing: preventFocus ? 0 : "xs", align: "center", children: [
/* @__PURE__ */ jsx(IncDec, { isInc: true, disabled: readOnly, onClick: (e) => {
const v = mod((value === void 0 ? def : value) - min + increment, base) + min;
setRaw(pad(v));
onChange(v);
}, byFive: props.incByFive, compact: preventFocus }),
preventFocus ? /* @__PURE__ */ jsx(Text, { size: "xl", onMouseDown: preventFocus ? (e) => e.preventDefault() : void 0, sx: {
margin: 10,
minWidth: "3ch",
textAlign: "center"
}, weight: "bold", children: raw }) : /* @__PURE__ */ jsx(TextInput, { value: raw, disabled: readOnly, size: "lg", sx: {
width: 60
}, onBlur, onMouseDown: preventFocus ? (e) => e.preventDefault() : void 0, onChange: (e) => {
let v = e.target.value.replace(/[^0-9]/g, "");
v = v.substring(Math.max(0, v.length - digits));
setRaw(v);
onChange(v == "" ? void 0 : Number(v));
} }),
/* @__PURE__ */ jsx(IncDec, { isInc: false, disabled: readOnly, onClick: (e) => {
const v = mod((value === void 0 ? def : value) - min - increment, base) + min;
setRaw(pad(v));
onChange(v);
}, byFive: props.incByFive, compact: preventFocus })
] });
};
const TimePicker = (props) => {
var _a;
const hour = props.value ? mod(props.value.hour() - 1, 12) + 1 : void 0;
const isAM = props.value && props.value.hour() < 12;
const readOnly = props.readOnly;
const {
classes
} = useStyles();
return /* @__PURE__ */ jsxs(Stack, { direction: "row", spacing: "sm", align: "center", children: [
/* @__PURE__ */ jsx(TimeInput, { value: hour, readOnly, onChange: (value) => {
var _a2;
props.onChange((_a2 = props.value) == null ? void 0 : _a2.set("hours", (isAM ? 0 : 12) + mod(value, 12)));
}, preventFocus: true, min: 1, max: 12 }),
/* @__PURE__ */ jsx(Text, { size: "xl", children: ":" }),
/* @__PURE__ */ jsx(TimeInput, { value: (_a = props.value) == null ? void 0 : _a.minute(), readOnly, onChange: (value) => {
var _a2;
props.onChange((_a2 = props.value) == null ? void 0 : _a2.set("minutes", mod(value, 60)));
}, preventFocus: true, incByFive: true, min: 0, max: 59 }),
/* @__PURE__ */ jsx(Button, { size: "xs", variant: "outline", color: "gray", disabled: readOnly, onMouseDown: (e) => e.preventDefault(), onClick: (e) => {
var _a2;
props.onChange((_a2 = props.value) == null ? void 0 : _a2.set("hours", isAM ? props.value.hour() + 12 : props.value.hour() - 12));
}, className: classes.AMPMButton, children: isAM ? "AM" : "PM" })
] });
};
export {
TimePicker,
useStyles
};
//# sourceMappingURL=TimePicker.js.map