// ~/src/siteplane/components/meter/meter.tsx "use client"; import { Meter as MeterPrimitive } from "@base-ui/react/meter"; import { cva, type VariantProps } from "class-variance-authority"; import * as React from "react"; import { type SiteplaneControlSize, siteplaneUIDefaults, useResolvedControlSize, } from "../../system/provider/siteplane-ui-provider"; import { linearIndicatorClassNames, linearIndicatorSizeClassNames, } from "../../system/styles/surface"; import { cn, type WithStringClassName } from "../../system/utils/cn"; import { slotClass } from "../../system/utils/slot-class"; const METER_DEFAULT_LOCALE = "en-US"; const meterRootVariants = cva(linearIndicatorClassNames.root, { defaultVariants: { size: siteplaneUIDefaults.controlSize }, variants: { size: linearIndicatorSizeClassNames.root }, }); const meterLabelVariants = cva(cn(linearIndicatorClassNames.label, ""), { defaultVariants: { size: siteplaneUIDefaults.controlSize }, variants: { size: linearIndicatorSizeClassNames.label }, }); const meterTrackVariants = cva(linearIndicatorClassNames.track, { defaultVariants: { size: siteplaneUIDefaults.controlSize }, variants: { size: linearIndicatorSizeClassNames.track }, }); const meterValueVariants = cva(linearIndicatorClassNames.value, { defaultVariants: { size: siteplaneUIDefaults.controlSize }, variants: { size: linearIndicatorSizeClassNames.value }, }); const MeterSizeContext = React.createContext(null); export type MeterTone = "accent" | "success" | "warning" | "error"; /** * @deprecated The earlier names of two tones: `default` is `accent` and * `destructive` is `error`. */ export type MeterDeprecatedTone = "default" | "destructive"; export interface MeterProps extends Omit, "size">, VariantProps { /** * Colours the filled part with a status tone, for example by strength. * `accent`, the default, keeps the progress fill; the fill's value * transition also carries a change of tone. `default` and `destructive` are * the deprecated earlier names of `accent` and `error`. */ tone?: MeterTone | MeterDeprecatedTone | undefined; } export function Meter({ className, children, locale = METER_DEFAULT_LOCALE, size, tone = "accent", ...props }: MeterProps): React.ReactElement { const resolvedTone: MeterTone = tone === "default" ? "accent" : tone === "destructive" ? "error" : tone; const resolvedSize = useResolvedControlSize(size); // At its minimum a meter is empty and shows no fill; above it, the fill keeps // a minimum width so a small value stays visible. // NaN counts as empty, as Base UI draws it at the minimum. const empty = !(props.value > (props.min ?? 0)); return ( {children ? ( children ) : ( )} ); } export interface MeterLabelProps extends Omit, "size">, VariantProps {} export function MeterLabel({ className, size, ...props }: MeterLabelProps): React.ReactElement { const groupSize = React.useContext(MeterSizeContext); const resolvedSize = useResolvedControlSize(size ?? groupSize); return ( ); } export interface MeterTrackProps extends Omit, "size">, VariantProps {} export function MeterTrack({ className, size, ...props }: MeterTrackProps): React.ReactElement { const groupSize = React.useContext(MeterSizeContext); const resolvedSize = useResolvedControlSize(size ?? groupSize); return ( ); } export function MeterIndicator({ className, ...props }: WithStringClassName): React.ReactElement { return ( ); } export interface MeterValueProps extends Omit, "size">, VariantProps {} export function MeterValue({ className, size, ...props }: MeterValueProps): React.ReactElement { const groupSize = React.useContext(MeterSizeContext); const resolvedSize = useResolvedControlSize(size ?? groupSize); return ( ); } export { MeterPrimitive }; // ~/src/siteplane/components/meter/index.ts export * from "./meter";