mirror of
https://github.com/temetro/temetro.git
synced 2026-08-10 10:37:43 +00:00
321a6298a4
- Pharmacy: the sidebar entry now expands into Pharmacy + a new Inventory page (searchable medication stock with derived in-stock/low/out availability, backed by /api/inventory). Fix the dispensing-queue "Expiring" badge so it only flags courses ending within the next 7 days, not ones already elapsed. - Lab "Add analysis result": the patient picker no longer lists patients until you type and supports arrow-key + Enter selection; the test field offers a catalog of common analyses with an Advanced option (custom analysis + ref range); submitted results now show immediately in a Recent results feed. - Analysis: add a Live panel (real-time line chart) and replace the flat trend sparklines with bklit-ui area + bar charts (installed from the @bklit shadcn registry; chart CSS variables wired into the theme for light and dark). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
65 lines
1.5 KiB
TypeScript
65 lines
1.5 KiB
TypeScript
export type IndicatorFadeEdges = "both" | "none" | "top" | "bottom";
|
|
|
|
export interface VerticalFadeSides {
|
|
top: boolean;
|
|
bottom: boolean;
|
|
any: boolean;
|
|
}
|
|
|
|
export function resolveVerticalFadeSides(
|
|
fade: IndicatorFadeEdges | boolean
|
|
): VerticalFadeSides {
|
|
if (fade === false || fade === "none") {
|
|
return { top: false, bottom: false, any: false };
|
|
}
|
|
if (fade === true || fade === "both") {
|
|
return { top: true, bottom: true, any: true };
|
|
}
|
|
if (fade === "top") {
|
|
return { top: true, bottom: false, any: true };
|
|
}
|
|
return { top: false, bottom: true, any: true };
|
|
}
|
|
|
|
export interface IndicatorFadeGradientStop {
|
|
offset: string;
|
|
opacity: number;
|
|
}
|
|
|
|
/** Opacity stops for the crosshair vertical gradient. */
|
|
export function indicatorFadeGradientStops(
|
|
sides: VerticalFadeSides,
|
|
fadeLengthPercent = 10
|
|
): IndicatorFadeGradientStop[] {
|
|
const fade = Math.min(40, Math.max(2, fadeLengthPercent));
|
|
const innerEnd = 100 - fade;
|
|
|
|
if (!sides.any) {
|
|
return [{ offset: "0%", opacity: 1 }];
|
|
}
|
|
|
|
if (sides.top && sides.bottom) {
|
|
return [
|
|
{ offset: "0%", opacity: 0 },
|
|
{ offset: `${fade}%`, opacity: 1 },
|
|
{ offset: "50%", opacity: 1 },
|
|
{ offset: `${innerEnd}%`, opacity: 1 },
|
|
{ offset: "100%", opacity: 0 },
|
|
];
|
|
}
|
|
|
|
if (sides.top) {
|
|
return [
|
|
{ offset: "0%", opacity: 0 },
|
|
{ offset: `${fade}%`, opacity: 1 },
|
|
{ offset: "100%", opacity: 1 },
|
|
];
|
|
}
|
|
|
|
return [
|
|
{ offset: "0%", opacity: 1 },
|
|
{ offset: `${innerEnd}%`, opacity: 1 },
|
|
{ offset: "100%", opacity: 0 },
|
|
];
|
|
}
|