import type { ButtonHTMLAttributes, HTMLAttributes, ReactNode } from "react";
import { createContext, useContext, useState } from "react";
import { cx } from "../../utils/cx.utils";
import "./segmented.component.css";
interface SegmentedContextValue {
value: string | null;
select: (itemId: string) => void;
}
const SegmentedContext = createContext(null);
/** Props accepted by {@link Segmented}. */
export interface SegmentedProps extends Omit, "onChange"> {
/** `id` of the {@link Segmented.Item} highlighted when the control first renders. */
defaultId?: string;
/** Stretches the control to 100% width, with segments evenly distributed. Defaults to `false`. */
fullWidth?: boolean;
/** Called with the `id` of the segment that was clicked. */
onChange?: (id: string) => void;
}
/** Props accepted by {@link Segmented.Item}. */
export interface SegmentedItemProps extends Omit, "id"> {
/** Identifies this segment; passed to `onChange` and matched against `defaultId`. */
id: string;
/** Segment label. */
children: ReactNode;
}
/**
* Single option of a {@link Segmented} control. Can only be used inside
* {@link Segmented}, which it reads its selected/click behavior from via
* context.
*
* @example
* ```tsx
* Week
* ```
*/
function SegmentedItem({ className, id, children, ...rest }: SegmentedItemProps) {
const context = useContext(SegmentedContext);
const isSelected = context?.value === id;
return (
);
}
/**
* Row of mutually-exclusive {@link Segmented.Item}s, highlighting the
* selected one and reporting clicks via `onChange`.
*
* @example
* ```tsx
* setRange(id)}>
* Day
* Week
* Month
* Year
*
* ```
*/
export function Segmented({
className,
children,
defaultId,
fullWidth = false,
onChange,
...rest
}: SegmentedProps) {
const [value, setValue] = useState(defaultId ?? null);
const select = (itemId: string) => {
setValue(itemId);
onChange?.(itemId);
};
return (
);
}
Segmented.Item = SegmentedItem;