Files
SystemSimulationApp/frontend/src/componentSymbols/primitives.tsx
T

67 lines
1.7 KiB
TypeScript

import { createContext, useContext, type ReactNode } from "react";
import type { ComponentSymbolViewBox } from "./types";
export type SymbolDomain =
| "neutral"
| "pneumatic"
| "mechanical"
| "signal"
| "medium";
type SymbolSvgProps = {
children: ReactNode;
className?: string;
domain?: SymbolDomain;
strokeScaling?: "independent" | "geometry";
};
type SymbolViewBoxProviderProps = {
children: ReactNode;
viewBox: ComponentSymbolViewBox;
};
const SymbolViewBoxContext = createContext("0 -8 64 64");
export const SYMBOL_STROKE = "var(--component-symbol-stroke, currentColor)";
export const SYMBOL_FILL = "var(--component-symbol-fill, #ffffff)";
export const SYMBOL_ACCENT = "var(--component-symbol-accent, currentColor)";
export const SYMBOL_MUTED = "var(--component-symbol-muted, #64748b)";
/** 由图标注册表统一提供 SVG 画布,避免渲染器与接口布局分别维护 viewBox。 */
export function SymbolViewBoxProvider({
children,
viewBox,
}: SymbolViewBoxProviderProps) {
return (
<SymbolViewBoxContext.Provider
value={`${viewBox.x} ${viewBox.y} ${viewBox.width} ${viewBox.height}`}
>
{children}
</SymbolViewBoxContext.Provider>
);
}
export function SymbolSvg({
children,
className,
domain = "neutral",
strokeScaling = "independent",
}: SymbolSvgProps) {
const viewBox = useContext(SymbolViewBoxContext);
return (
<svg
aria-hidden="true"
className={["component-symbol-svg", className].filter(Boolean).join(" ")}
data-symbol-domain={domain}
data-symbol-stroke-scaling={strokeScaling}
fill="none"
focusable="false"
viewBox={viewBox}
xmlns="http://www.w3.org/2000/svg"
>
{children}
</svg>
);
}