mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-14 14:40:52 +00:00
chore(release): v1.4.27
v1.4.27 — Mobile capability and maintainer-finding cleanup. ResponsiveSheet primitive (bottom-sheet on narrow viewports, centred dialog on desktop) applied to BD, Weight, Glucose, Mood, Activity forms. Maintainer-finding cleanups across Coach, Insights, Reports, Privacy. GeoLite2 offline geocoding with resilience layer (graceful fallback when EULA not yet propagated). E2E gap-fill coverage. 450-line release notes attached to the GitHub Release.
This commit is contained in:
1 parent
d98e85cd03
commit
4f09c3f862
314 files changed
+26801
-4419
No files matched your search
@@ -19,25 +19,55 @@ import { cn } from "@/lib/utils";
|
||||
* `autoComplete` is anything other than `"off"`, the LastPass /
|
||||
* 1Password ignore attrs are dropped so password managers fill the
|
||||
* field normally.
|
||||
*
|
||||
* v1.4.27 mobile pass: derive a sensible `inputMode` default from the
|
||||
* `type` prop so every numeric / email / tel / url / search field
|
||||
* surfaces the right on-screen keyboard on iOS Safari and Android
|
||||
* Chrome without each call site having to repeat the attribute. Most
|
||||
* `type="number"` fields in HealthLog accept decimals (kg, mmol/L,
|
||||
* sleep hours), so the default is `"decimal"`; integer-only call
|
||||
* sites can still pass `inputMode="numeric"` explicitly.
|
||||
*/
|
||||
function deriveInputMode(
|
||||
type: React.HTMLInputTypeAttribute | undefined,
|
||||
): React.HTMLAttributes<HTMLInputElement>["inputMode"] | undefined {
|
||||
switch (type) {
|
||||
case "number":
|
||||
return "decimal";
|
||||
case "tel":
|
||||
return "tel";
|
||||
case "email":
|
||||
return "email";
|
||||
case "url":
|
||||
return "url";
|
||||
case "search":
|
||||
return "search";
|
||||
default:
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
function Input({
|
||||
className,
|
||||
type,
|
||||
autoComplete,
|
||||
inputMode,
|
||||
...props
|
||||
}: React.ComponentProps<"input">) {
|
||||
const resolvedAutoComplete = autoComplete ?? "off";
|
||||
const skipAutofill = resolvedAutoComplete === "off";
|
||||
const resolvedInputMode = inputMode ?? deriveInputMode(type);
|
||||
|
||||
return (
|
||||
<input
|
||||
type={type}
|
||||
data-slot="input"
|
||||
autoComplete={resolvedAutoComplete}
|
||||
inputMode={resolvedInputMode}
|
||||
data-lpignore={skipAutofill ? "true" : undefined}
|
||||
data-1p-ignore={skipAutofill ? "true" : undefined}
|
||||
className={cn(
|
||||
"file:text-foreground placeholder:text-muted-foreground selection:bg-primary selection:text-primary-foreground dark:bg-input/30 border-input h-9 w-full min-w-0 rounded-md border bg-transparent px-3 py-1 text-base shadow-xs transition-[color,box-shadow] outline-none file:inline-flex file:h-7 file:border-0 file:bg-transparent file:text-sm file:font-medium disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
|
||||
"file:text-foreground placeholder:text-muted-foreground selection:bg-primary selection:text-primary-foreground dark:bg-input/30 border-input h-10 w-full min-w-0 rounded-md border bg-transparent px-3 py-1 text-base shadow-xs transition-[color,box-shadow] outline-none file:inline-flex file:h-7 file:border-0 file:bg-transparent file:text-sm file:font-medium disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
|
||||
"focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px]",
|
||||
"aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive",
|
||||
className,
|
||||
|
||||
Reference in new issue
Block a user