mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
95 lines
2.2 KiB
TypeScript
95 lines
2.2 KiB
TypeScript
/**
|
|
* Copyright (c) OpenLens Authors. All rights reserved.
|
|
* Licensed under MIT License. See LICENSE in root directory for more information.
|
|
*/
|
|
|
|
import "./radio.scss";
|
|
import React, { useContext, useRef } from "react";
|
|
import type { SingleOrMany } from "../../utils";
|
|
import { cssNames, noop } from "../../utils";
|
|
|
|
export interface RadioGroupProps<T> {
|
|
className?: string;
|
|
value?: T;
|
|
asButtons?: boolean;
|
|
disabled?: boolean;
|
|
onChange: (value: T) => void;
|
|
children: SingleOrMany<React.ReactElement<RadioProps<T>>>;
|
|
}
|
|
|
|
interface RadioGroupContext {
|
|
disabled: boolean;
|
|
value: any | undefined;
|
|
onSelect: (newValue: any) => void;
|
|
}
|
|
|
|
const radioGroupContext = React.createContext<RadioGroupContext>({
|
|
disabled: false,
|
|
value: undefined,
|
|
onSelect: noop,
|
|
});
|
|
|
|
export function RadioGroup<T>({
|
|
value,
|
|
asButtons,
|
|
disabled = false,
|
|
onChange,
|
|
className,
|
|
children,
|
|
}: RadioGroupProps<T>) {
|
|
return (
|
|
<div
|
|
className={cssNames("RadioGroup", { buttonsView: asButtons }, className)}
|
|
>
|
|
<radioGroupContext.Provider value={{ disabled, onSelect: onChange, value }}>
|
|
{children}
|
|
</radioGroupContext.Provider>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
export interface RadioProps<T> {
|
|
className?: string;
|
|
label: React.ReactNode;
|
|
value: T;
|
|
disabled?: boolean;
|
|
}
|
|
|
|
export function Radio<T>({
|
|
className,
|
|
label,
|
|
value,
|
|
disabled = false,
|
|
}: RadioProps<T>) {
|
|
const ctx = useContext(radioGroupContext);
|
|
const ref = useRef<HTMLLabelElement | null>(null);
|
|
const checked = ctx.value === value;
|
|
|
|
return (
|
|
<label
|
|
className={cssNames("Radio flex align-center", className, {
|
|
checked,
|
|
disabled: disabled || ctx.disabled,
|
|
})}
|
|
tabIndex={checked ? undefined : 0}
|
|
onKeyDown={event => {
|
|
// Spacebar or Enter key
|
|
if (event.key === " " || event.key === "Enter") {
|
|
ref.current?.click();
|
|
event.preventDefault();
|
|
}
|
|
}}
|
|
ref={ref}
|
|
>
|
|
<input
|
|
type="radio"
|
|
checked={checked}
|
|
onChange={() => ctx.onSelect(value)}
|
|
disabled={disabled || ctx.disabled}
|
|
/>
|
|
<i className="tick flex center"/>
|
|
{label ? <div className="label">{label}</div> : null}
|
|
</label>
|
|
);
|
|
}
|