select props update

This commit is contained in:
Nate Kelley 2025-07-10 14:50:01 -06:00
parent 9ed1ed5eef
commit cc2a45e7d1
No known key found for this signature in database
GPG Key ID: FD90372AB8D98B4F
2 changed files with 57 additions and 31 deletions

View File

@ -5,7 +5,7 @@ import { Select, type SelectItem, type SelectProps } from './Select';
import { User, Gear, PowerOff } from '@/components/ui/icons/NucleoIconOutlined';
const meta = {
title: 'UI/select/Select2',
title: 'UI/select/Select',
component: Select,
parameters: {
layout: 'centered'
@ -42,10 +42,10 @@ const meta = {
</div>
)
]
} satisfies Meta<typeof Select>;
} satisfies Meta<SelectProps<string>>;
export default meta;
type Story = StoryObj<typeof meta>;
type Story = StoryObj<SelectProps<string>>;
// Basic select with simple string options
export const BasicSelect: Story = {
@ -63,16 +63,21 @@ export const BasicSelect: Story = {
] as SelectItem<string>[],
onChange: fn()
},
render: function RenderBasicSelect(args) {
render: function RenderBasicSelect(args: SelectProps<string>) {
const [value, setValue] = React.useState<string | undefined>();
return (
<Select
{...args}
items={args.items}
placeholder={args.placeholder}
disabled={args.disabled}
loading={args.loading}
showIndex={args.showIndex}
search={args.search}
value={value}
onChange={(newValue) => {
setValue(newValue as string);
args.onChange(newValue);
onChange={(newValue: string) => {
setValue(newValue);
(args.onChange as (value: string) => void)?.(newValue);
}}
/>
);
@ -120,7 +125,7 @@ export const AdvancedSelect: Story = {
]
}
],
search: (item, searchTerm) => {
search: (item: SelectItem<string>, searchTerm: string) => {
// Custom search that also searches in secondary labels
const term = searchTerm.toLowerCase();
const labelText = typeof item.label === 'string' ? item.label.toLowerCase() : '';
@ -129,16 +134,21 @@ export const AdvancedSelect: Story = {
},
onChange: fn()
},
render: function RenderAdvancedSelect(args) {
render: function RenderAdvancedSelect(args: SelectProps<string>) {
const [value, setValue] = React.useState<string | undefined>();
return (
<Select
{...args}
items={args.items}
placeholder={args.placeholder}
disabled={args.disabled}
loading={args.loading}
showIndex={args.showIndex}
search={args.search}
value={value}
onChange={(newValue) => {
setValue(newValue as string);
args.onChange(newValue);
onChange={(newValue: string) => {
setValue(newValue);
(args.onChange as (value: string) => void)?.(newValue);
}}
/>
);
@ -160,16 +170,21 @@ export const NoSearchSelect: Story = {
] as SelectItem<string>[],
onChange: fn()
},
render: function RenderNoSearchSelect(args) {
render: function RenderNoSearchSelect(args: SelectProps<string>) {
const [value, setValue] = React.useState<string | undefined>();
return (
<Select
{...args}
items={args.items}
placeholder={args.placeholder}
disabled={args.disabled}
loading={args.loading}
showIndex={args.showIndex}
search={args.search}
value={value}
onChange={(newValue) => {
setValue(newValue as string);
args.onChange(newValue);
onChange={(newValue: string) => {
setValue(newValue);
(args.onChange as (value: string) => void)?.(newValue);
}}
/>
);
@ -189,16 +204,21 @@ export const PreSelectedValue: Story = {
] as SelectItem<string>[],
onChange: fn()
},
render: function RenderPreSelectedValue(args) {
render: function RenderPreSelectedValue(args: SelectProps<string>) {
const [value, setValue] = React.useState<string | undefined>('m');
return (
<Select
{...args}
items={args.items}
placeholder={args.placeholder}
disabled={args.disabled}
loading={args.loading}
showIndex={args.showIndex}
search={args.search}
value={value}
onChange={(newValue) => {
setValue(newValue as string);
args.onChange(newValue);
onChange={(newValue: string) => {
setValue(newValue);
(args.onChange as (value: string) => void)?.(newValue);
}}
/>
);
@ -219,16 +239,22 @@ export const ClearableSelect: Story = {
] as SelectItem<string>[],
onChange: fn()
},
render: function RenderClearableSelect(args) {
render: function RenderClearableSelect(args: SelectProps<string>) {
const [value, setValue] = React.useState<string | undefined>('option2');
return (
<Select
{...args}
items={args.items}
placeholder={args.placeholder}
disabled={args.disabled}
loading={args.loading}
showIndex={args.showIndex}
search={args.search}
clearable={true}
value={value}
onChange={(newValue) => {
onChange={(newValue: string | null) => {
setValue(newValue as string | undefined);
args.onChange(newValue);
(args.onChange as (value: string | null) => void)?.(newValue);
}}
/>
);

View File

@ -46,19 +46,19 @@ interface BaseSelectProps<T> {
}
// Clearable version - onChange can return null
interface ClearableSelectProps<T> extends BaseSelectProps<T> {
interface ClearableSelectProps<T = string> extends BaseSelectProps<T> {
clearable: true;
onChange: (value: T | null) => void;
}
// Non-clearable version - onChange cannot return null
interface NonClearableSelectProps<T> extends BaseSelectProps<T> {
interface NonClearableSelectProps<T = string> extends BaseSelectProps<T> {
clearable?: false;
onChange: (value: T) => void;
}
// Union type for type-safe props
export type SelectProps<T> = ClearableSelectProps<T> | NonClearableSelectProps<T>;
export type SelectProps<T = string> = ClearableSelectProps<T> | NonClearableSelectProps<T>;
function isGroupedItems<T>(
items: SelectItem<T>[] | SelectItemGroup<T>[]