From 0bedccde1801bbb0aa4a4004991bd170657126a6 Mon Sep 17 00:00:00 2001 From: "codegen-sh[bot]" <131295404+codegen-sh[bot]@users.noreply.github.com> Date: Tue, 23 Sep 2025 19:26:56 +0000 Subject: [PATCH 1/3] feat(Select): support generic value type (T extends React.Key); adjust data attributes and search to string --- packages/components/src/ui/select.tsx | 29 ++++++++++++++------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/packages/components/src/ui/select.tsx b/packages/components/src/ui/select.tsx index e2f475f..14ad93e 100644 --- a/packages/components/src/ui/select.tsx +++ b/packages/components/src/ui/select.tsx @@ -17,9 +17,9 @@ import { useId, useRef, } from 'react'; -export interface SelectOption { +export interface SelectOption { label: string; - value: string; + value: T; } export interface SelectUIComponents { @@ -34,10 +34,11 @@ export interface SelectUIComponents { export type SelectContentProps = Pick, 'align' | 'side' | 'sideOffset'>; -export interface SelectProps extends Omit, 'value' | 'onChange'> { - options: SelectOption[]; - value?: string; - onValueChange?: (value: string) => void; +export interface SelectProps + extends Omit, 'value' | 'onChange'> { + options: SelectOption[]; + value?: T; + onValueChange?: (value: T) => void; placeholder?: string; disabled?: boolean; className?: string; @@ -50,7 +51,7 @@ export interface SelectProps extends Omit; // Creatable behavior creatable?: boolean; - onCreateOption?: (input: string) => SelectOption | Promise; + onCreateOption?: (input: string) => SelectOption | Promise>; createOptionLabel?: (input: string) => string; } @@ -60,7 +61,7 @@ const DefaultSearchInput = forwardRef({ options, value, onValueChange, @@ -77,7 +78,7 @@ export function Select({ onCreateOption, createOptionLabel, ...buttonProps -}: SelectProps) { +}: SelectProps) { const popoverState = useOverlayTriggerState({}); const listboxId = useId(); const triggerRef = useRef(null); @@ -132,7 +133,7 @@ export function Select({ aria-controls={listboxId} {...buttonProps} > - {value !== '' ? (selectedOption?.label ?? value) : placeholder} + {value != null ? (selectedOption?.label ?? String(value)) : placeholder} @@ -175,8 +176,8 @@ export function Select({ const isSelected = option.value === value; const commonProps = { 'data-selected': isSelected ? 'true' : 'false', - 'data-value': option.value, - 'data-testid': `select-option-${option.value}`, + 'data-value': String(option.value), + 'data-testid': `select-option-${String(option.value)}`, } as const; // When a custom Item is provided, use asChild to let it render as the actual item element @@ -240,7 +241,7 @@ export function Select({ const lower = q.toLowerCase(); const hasExactMatch = q.length > 0 && - options.some((o) => o.label.toLowerCase() === lower || o.value.toLowerCase() === lower); + options.some((o) => o.label.toLowerCase() === lower || String(o.value).toLowerCase() === lower); if (!creatable || !q || hasExactMatch) return null; const label = createOptionLabel?.(q) ?? `Select "${q}"`; return ( @@ -252,7 +253,7 @@ export function Select({ onSelect={async () => { if (!onCreateOption) return; const created = await onCreateOption(q); - if (created?.value) onValueChange?.(created.value); + onValueChange?.(created.value); popoverState.close(); }} className={cn( From 06474b15564a279a5b4c5d95084d814114bd7b82 Mon Sep 17 00:00:00 2001 From: "codegen-sh[bot]" <131295404+codegen-sh[bot]@users.noreply.github.com> Date: Tue, 23 Sep 2025 19:29:12 +0000 Subject: [PATCH 2/3] chore(release): patch bump @lambdacurry/forms to v0.22.3 (Select generic value) --- packages/components/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/components/package.json b/packages/components/package.json index ea0f2fb..c977ec2 100644 --- a/packages/components/package.json +++ b/packages/components/package.json @@ -1,6 +1,6 @@ { "name": "@lambdacurry/forms", - "version": "0.22.2", + "version": "0.22.3", "type": "module", "main": "./dist/index.js", "types": "./dist/index.d.ts", From 78b6c818a53c9ff38a7ce5bfa6974e45c6ca11e0 Mon Sep 17 00:00:00 2001 From: "codegen-sh[bot]" <131295404+codegen-sh[bot]@users.noreply.github.com> Date: Tue, 23 Sep 2025 19:38:18 +0000 Subject: [PATCH 3/3] fix(Select): display placeholder when value is empty string The generic Select changes broke placeholder display when form values are initialized with empty strings. The condition 'value != null' returns true for empty strings, causing String(value) to display instead of the placeholder. Fixed by checking both null/undefined AND empty string conditions. Fixes failing test in select.stories.tsx that expected placeholder text to be displayed initially. --- packages/components/src/ui/select.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/components/src/ui/select.tsx b/packages/components/src/ui/select.tsx index 14ad93e..2f05b82 100644 --- a/packages/components/src/ui/select.tsx +++ b/packages/components/src/ui/select.tsx @@ -133,7 +133,7 @@ export function Select({ aria-controls={listboxId} {...buttonProps} > - {value != null ? (selectedOption?.label ?? String(value)) : placeholder} + {value != null && value !== '' ? (selectedOption?.label ?? String(value)) : placeholder}