67 lines
1.7 KiB
TypeScript
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>
|
|
);
|
|
}
|