224 lines
9.2 KiB
JavaScript
224 lines
9.2 KiB
JavaScript
import { o as __toESM } from "../_runtime.mjs";
|
|
import { h as require_react, m as require_jsx_runtime } from "../_libs/react+tanstack__react-query.mjs";
|
|
import { t as clsx } from "../_libs/clsx.mjs";
|
|
import { t as twMerge } from "../_libs/tailwind-merge.mjs";
|
|
import { d as Search, f as Plus, m as Minus, n as X, r as User } from "../_libs/lucide-react.mjs";
|
|
//#region node_modules/.nitro/vite/services/ssr/assets/src-u_N1opJl.js
|
|
var import_react = /* @__PURE__ */ __toESM(require_react());
|
|
var import_jsx_runtime = require_jsx_runtime();
|
|
function cn(...inputs) {
|
|
return twMerge(clsx(inputs));
|
|
}
|
|
var weightClasses = {
|
|
normal: "font-normal",
|
|
medium: "font-medium",
|
|
semibold: "font-semibold",
|
|
bold: "font-bold"
|
|
};
|
|
function p({ children, weight = "normal", numberOfLines, className, style, ...props }) {
|
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
|
|
className: cn(weightClasses[weight], className),
|
|
style: {
|
|
...numberOfLines ? {
|
|
display: "-webkit-box",
|
|
WebkitLineClamp: numberOfLines,
|
|
WebkitBoxOrient: "vertical",
|
|
overflow: "hidden"
|
|
} : {},
|
|
...style
|
|
},
|
|
...props,
|
|
children
|
|
});
|
|
}
|
|
var variantStyles = {
|
|
blue: "bg-brand-500 text-white hover:bg-brand-600",
|
|
red: "bg-red-500 text-white hover:bg-red-600",
|
|
green: "bg-green-500 text-white hover:bg-green-600"
|
|
};
|
|
function MyButton({ variant = "blue", fullWidth, textContent, children, className, disabled, style, ...props }) {
|
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", {
|
|
className: cn("inline-flex items-center justify-center rounded-lg px-4 py-2 text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50", variantStyles[variant] || variantStyles.blue, fullWidth && "w-full", className),
|
|
disabled,
|
|
style,
|
|
...props,
|
|
children: textContent || children
|
|
});
|
|
}
|
|
function pInput({ topLabel, fullWidth = true, shrunkPadding = false, error, multiline, className, style, ...props }) {
|
|
const inputClasses = cn("flex w-full rounded-md border border-input bg-background px-3 text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50", shrunkPadding ? "py-1.5" : "py-2", error && "border-destructive", className);
|
|
multilime;
|
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
style: {
|
|
...fullWidth ? { width: "100%" } : {},
|
|
...style
|
|
},
|
|
children: [topLabel && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(p, {
|
|
weight: "medium",
|
|
className: "mb-1 text-sm text-gray-500",
|
|
children: topLabel
|
|
}), multiline ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("textarea", {
|
|
className: inputClasses,
|
|
rows: numberOfLines || 3,
|
|
...props
|
|
}) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("input", {
|
|
className: inputClasses,
|
|
...props
|
|
})]
|
|
});
|
|
}
|
|
function MyTouchableOpacity({ activeOpacity = .7, className, children, style, ...props }) {
|
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", {
|
|
className: cn("inline-flex items-center justify-center transition-opacity hover:opacity-70 active:opacity-50 disabled:pointer-events-none disabled:opacity-50", className),
|
|
style: {
|
|
...style,
|
|
background: "none",
|
|
border: "none",
|
|
cursor: "pointer",
|
|
padding: 0,
|
|
font: "inherit",
|
|
color: "inherit"
|
|
},
|
|
...props,
|
|
children
|
|
});
|
|
}
|
|
function LoadingDialog({ open, message = "Loading..." }) {
|
|
if (!open) return null;
|
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
className: "fixed inset-0 z-50 flex items-center justify-center bg-black/50",
|
|
children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
className: "flex flex-col items-center gap-3 rounded-lg bg-white p-6 shadow-lg",
|
|
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "h-8 w-8 animate-spin rounded-full border-4 border-brand-500 border-t-transparent" }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", {
|
|
className: "text-sm text-gray-600",
|
|
children: message
|
|
})]
|
|
})
|
|
});
|
|
}
|
|
function BottomDialog({ open, onClose, children, enableDismiss = true }) {
|
|
const [visible, setVisible] = (0, import_react.useState)(false);
|
|
(0, import_react.useEffect)(() => {
|
|
if (open) setVisible(true);
|
|
else {
|
|
const timer = setTimeout(() => setVisible(false), 200);
|
|
return () => clearTimeout(timer);
|
|
}
|
|
}, [open]);
|
|
if (!visible && !open) return null;
|
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
className: "fixed inset-0 z-50 flex items-end justify-center",
|
|
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
className: `absolute inset-0 bg-black/30 transition-opacity duration-200 ${open ? "opacity-100" : "opacity-0"}`,
|
|
onClick: enableDismiss ? onClose : void 0
|
|
}), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
className: `relative w-full max-w-lg rounded-t-2xl bg-white p-6 shadow-lg transition-transform duration-200 ${open ? "translate-y-0" : "translate-y-full"}`,
|
|
style: { maxHeight: "85vh" },
|
|
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "mx-auto mb-4 h-1.5 w-10 rounded-full bg-gray-300" }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
className: "overflow-y-auto",
|
|
style: { maxHeight: "calc(85vh - 40px)" },
|
|
children
|
|
})]
|
|
})]
|
|
});
|
|
}
|
|
function SearchBar({ placeholder = "Search...", onSearch, debounceMs = 300, className, value: controlledValue, onChange }) {
|
|
const [internalValue, setInternalValue] = (0, import_react.useState)("");
|
|
const timerRef = (0, import_react.useRef)(null);
|
|
const value = controlledValue !== void 0 ? controlledValue : internalValue;
|
|
const setValue = onChange || setInternalValue;
|
|
const handleChange = (0, import_react.useCallback)((e) => {
|
|
const newValue = e.target.value;
|
|
setValue(newValue);
|
|
if (timerRef.current) clearTimeout(timerRef.current);
|
|
timerRef.current = setTimeout(() => {
|
|
onSearch?.(newValue);
|
|
}, debounceMs);
|
|
}, [
|
|
onSearch,
|
|
debounceMs,
|
|
setValue
|
|
]);
|
|
const handleClear = (0, import_react.useCallback)(() => {
|
|
setValue("");
|
|
onSearch?.("");
|
|
}, [onSearch, setValue]);
|
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
className: cn("flex w-full flex-row items-center rounded-xl border border-gray-200 bg-white px-4 py-3 shadow-sm", className),
|
|
children: [
|
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("input", {
|
|
type: "text",
|
|
value,
|
|
onChange: handleChange,
|
|
placeholder,
|
|
className: "min-w-0 flex-1 bg-transparent text-sm text-gray-800 placeholder:text-gray-400 !outline-none focus:!outline-none focus-visible:!outline-none"
|
|
}),
|
|
value && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", {
|
|
onClick: handleClear,
|
|
className: "mr-2 shrink-0 text-gray-400 hover:text-gray-600",
|
|
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(X, { className: "h-5 w-5" })
|
|
}),
|
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Search, { className: "h-5 w-5 shrink-0 text-brand-500" })
|
|
]
|
|
});
|
|
}
|
|
function Quantifier({ value, setValue, step = 1, min = 0, max = 99 }) {
|
|
const decrease = () => {
|
|
if (value > min) setValue(value - step);
|
|
};
|
|
const increase = () => {
|
|
if (value < max) setValue(value + step);
|
|
};
|
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
className: "inline-flex items-center rounded-lg border border-gray-200",
|
|
children: [
|
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", {
|
|
onClick: decrease,
|
|
disabled: value <= min,
|
|
className: "flex h-8 w-8 items-center justify-center text-gray-500 hover:text-gray-700 disabled:opacity-30",
|
|
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Minus, { className: "h-3.5 w-3.5" })
|
|
}),
|
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(p, {
|
|
weight: "semibold",
|
|
className: "min-w-[32px] text-center text-sm",
|
|
children: value
|
|
}),
|
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", {
|
|
onClick: increase,
|
|
disabled: value >= max,
|
|
className: "flex h-8 w-8 items-center justify-center text-gray-500 hover:text-gray-700 disabled:opacity-30",
|
|
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Plus, { className: "h-3.5 w-3.5" })
|
|
})
|
|
]
|
|
});
|
|
}
|
|
function ProfileImage({ uri, size = 80, className }) {
|
|
if (uri) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("img", {
|
|
src: uri,
|
|
alt: "Profile",
|
|
className: cn("rounded-full object-cover", className),
|
|
style: {
|
|
width: size,
|
|
height: size
|
|
}
|
|
});
|
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
className: cn("flex items-center justify-center rounded-full bg-gray-200", className),
|
|
style: {
|
|
width: size,
|
|
height: size
|
|
},
|
|
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(User, { className: "h-1/2 w-1/2 text-gray-400" })
|
|
});
|
|
}
|
|
function AppContainer({ children, className }) {
|
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("main", {
|
|
className: cn("mx-auto min-h-screen w-full max-w-4xl bg-white", className),
|
|
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
className: "p-4",
|
|
children
|
|
})
|
|
});
|
|
}
|
|
//#endregion
|
|
export { p as a, ProfileImage as c, MyButton as i, Quantifier as l, BottomDialog as n, pInput as o, LoadingDialog as r, MyTouchableOpacity as s, AppContainer as t, SearchBar as u };
|