mirror of
https://github.com/temetro/temetro.git
synced 2026-07-26 11:58:14 +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>
73 lines
2.0 KiB
TypeScript
73 lines
2.0 KiB
TypeScript
import {
|
|
Children,
|
|
isValidElement,
|
|
type ReactElement,
|
|
type ReactNode,
|
|
} from "react";
|
|
|
|
export function getChartChildComponentName(child: ReactElement): string {
|
|
const childType = child.type as { displayName?: string; name?: string };
|
|
return typeof child.type === "function"
|
|
? childType.displayName || childType.name || ""
|
|
: "";
|
|
}
|
|
|
|
const VISX_PATTERN_COMPONENT_NAMES = new Set([
|
|
"Lines",
|
|
"Circles",
|
|
"Waves",
|
|
"Hexagons",
|
|
"Path",
|
|
"Pattern",
|
|
]);
|
|
|
|
/** @visx/pattern default exports use short names (e.g. `Lines`); also match *Pattern* displayNames. */
|
|
export function isPatternDefComponent(child: ReactElement): boolean {
|
|
const name = getChartChildComponentName(child);
|
|
return name.includes("Pattern") || VISX_PATTERN_COMPONENT_NAMES.has(name);
|
|
}
|
|
|
|
export function isGradientDefComponent(child: ReactElement): boolean {
|
|
const name = getChartChildComponentName(child);
|
|
return (
|
|
name.includes("Gradient") ||
|
|
name === "LinearGradient" ||
|
|
name === "RadialGradient"
|
|
);
|
|
}
|
|
|
|
export function isChartDefsComponent(child: ReactElement): boolean {
|
|
return isPatternDefComponent(child) || isGradientDefComponent(child);
|
|
}
|
|
|
|
/** Split hoisted defs: @visx/pattern nodes already wrap `<defs>` and render at the svg root. */
|
|
export function partitionChartDefNodes(defNodes: ReactElement[]): {
|
|
patternDefNodes: ReactElement[];
|
|
gradientDefNodes: ReactElement[];
|
|
} {
|
|
const patternDefNodes: ReactElement[] = [];
|
|
const gradientDefNodes: ReactElement[] = [];
|
|
|
|
for (const node of defNodes) {
|
|
if (isPatternDefComponent(node)) {
|
|
patternDefNodes.push(node);
|
|
} else {
|
|
gradientDefNodes.push(node);
|
|
}
|
|
}
|
|
|
|
return { patternDefNodes, gradientDefNodes };
|
|
}
|
|
|
|
export function collectChartDefsChildren(children: ReactNode): ReactElement[] {
|
|
const defNodes: ReactElement[] = [];
|
|
|
|
Children.forEach(children, (child) => {
|
|
if (isValidElement(child) && isChartDefsComponent(child)) {
|
|
defNodes.push(child);
|
|
}
|
|
});
|
|
|
|
return defNodes;
|
|
}
|