UNPKG

@kobalte/core

Version:

Unstyled components and primitives for building accessible web apps and design systems with SolidJS.

148 lines (143 loc) 4.41 kB
import { createNumberFormatter } from './XHJPQEZP.js'; import { createRegisterId } from './E4R2EMM4.js'; import { Polymorphic } from './6Y7B2NEO.js'; import { createComponent, mergeProps, memo } from 'solid-js/web'; import { createContext, useContext, splitProps, createEffect, onCleanup, createUniqueId, createSignal, createMemo } from 'solid-js'; import { combineStyle } from '@solid-primitives/props'; import { mergeDefaultProps, createGenerateId, clamp } from '@kobalte/utils'; var MeterContext = createContext(); function useMeterContext() { const context = useContext(MeterContext); if (context === void 0) { throw new Error("[kobalte]: `useMeterContext` must be used within a `Meter.Root` component"); } return context; } // src/meter/meter-fill.tsx function MeterFill(props) { const context = useMeterContext(); const [local, others] = splitProps(props, ["style"]); return createComponent(Polymorphic, mergeProps({ as: "div", get style() { return combineStyle({ "--kb-meter-fill-width": context.meterFillWidth() }, local.style); } }, () => context.dataset(), others)); } function MeterLabel(props) { const context = useMeterContext(); const mergedProps = mergeDefaultProps({ id: context.generateId("label") }, props); const [local, others] = splitProps(mergedProps, ["id"]); createEffect(() => onCleanup(context.registerLabelId(local.id))); return createComponent(Polymorphic, mergeProps({ as: "span", get id() { return local.id; } }, () => context.dataset(), others)); } function MeterRoot(props) { const defaultId = `meter-${createUniqueId()}`; const mergedProps = mergeDefaultProps({ id: defaultId, value: 0, minValue: 0, maxValue: 100, role: "meter", indeterminate: false }, props); const [local, others] = splitProps(mergedProps, ["value", "minValue", "maxValue", "getValueLabel", "role", "aria-valuetext", "aria-labelledby", "aria-valuemax", "aria-valuemin", "aria-valuenow", "indeterminate"]); const [labelId, setLabelId] = createSignal(); const defaultFormatter = createNumberFormatter(() => ({ style: "percent" })); const value = () => { return clamp(local.value, local.minValue, local.maxValue); }; const valuePercent = () => { return (value() - local.minValue) / (local.maxValue - local.minValue); }; const valueLabel = () => { if (local.indeterminate) { return void 0; } if (local.getValueLabel) { return local.getValueLabel({ value: value(), min: local.minValue, max: local.maxValue }); } return defaultFormatter().format(valuePercent()); }; const meterFillWidth = () => { return `${valuePercent() * 100}%`; }; const dataset = createMemo(() => { return {}; }); const context = { dataset, value, valuePercent, valueLabel, labelId, meterFillWidth, generateId: createGenerateId(() => others.id), registerLabelId: createRegisterId(setLabelId) }; return createComponent(MeterContext.Provider, { value: context, get children() { return createComponent(Polymorphic, mergeProps({ as: "div", get role() { return local.role || "meter"; }, get ["aria-valuenow"]() { return memo(() => !!local.indeterminate)() ? void 0 : value(); }, get ["aria-valuemin"]() { return local.minValue; }, get ["aria-valuemax"]() { return local.maxValue; }, get ["aria-valuetext"]() { return valueLabel(); }, get ["aria-labelledby"]() { return labelId(); } }, dataset, others)); } }); } function MeterTrack(props) { const context = useMeterContext(); return createComponent(Polymorphic, mergeProps({ as: "div" }, () => context.dataset(), props)); } function MeterValueLabel(props) { const context = useMeterContext(); return createComponent(Polymorphic, mergeProps({ as: "div" }, () => context.dataset(), props, { get children() { return context.valueLabel(); } })); } // src/meter/index.tsx var Meter = Object.assign(MeterRoot, { Fill: MeterFill, Label: MeterLabel, Track: MeterTrack, ValueLabel: MeterValueLabel }); export { Meter, MeterFill, MeterLabel, MeterRoot, MeterTrack, MeterValueLabel, useMeterContext };