# Select Components

> **Props y API:** Disponibles vía MCP tool `widgets-get-component-props`. Este archivo documenta solo convenciones, gotchas y patrones específicos del proyecto.

> ⚠️ **DSelectNative removed in Dynamic UI 2.x** — Use `DInputSelect` instead (see `inputs.md`)

---

## ⚠️ CRITICAL: DSelect Uses Object-Based API

Unlike other Dynamic UI inputs, DSelect requires the **full option object** for `value`, NOT just the value string.

```tsx
// ❌ WRONG — passing string
<DSelect options={options} value={selectedYear} onChange={(value) => setYear(value)} />

// ✅ CORRECT — pass object, extract value
<DSelect
  options={options}
  value={options.find(opt => opt.value === selectedYear)}  // value → object
  onChange={(option: any) => setYear(option?.value || '')}  // object → value
/>
```

### Pattern with Zustand

```tsx
const vehicleType = useUIStore((s) => s.vehicleType);  // string
const setVehicleType = useUIStore((s) => s.setVehicleType);
const typeOptions = [{ label: 'Sedan', value: 'sedan' }, { label: 'SUV', value: 'suv' }];

<DSelect id="vehicleType" label="Vehicle Type *" options={typeOptions}
  value={typeOptions.find(opt => opt.value === vehicleType)}
  onChange={(option: any) => setVehicleType(option?.value || '')} />
```

---

## ❌ Common Mistakes

```tsx
// ❌ Passing value string instead of object
<DSelect value={selectedValue} />
// ✅ <DSelect value={options.find(opt => opt.value === selectedValue)} />

// ❌ Treating onChange like regular input
<DSelect onChange={(e) => setValue(e.target.value)} />
// ✅ <DSelect onChange={(option: any) => setValue(option?.value || '')} />

// ❌ Forgetting optional chaining (crashes if null)
<DSelect onChange={(option) => setValue(option.value)} />
// ✅ <DSelect onChange={(option: any) => setValue(option?.value || '')} />
```

---

## Multi-Select

`multi` enables multi-select. onChange receives `Array<{label, value}> | null`.

```tsx
<DSelect multi options={options}
  value={selectedTypes.map(val => options.find(opt => opt.value === val)).filter(Boolean)}
  onChange={(opts: any) => setSelectedTypes(opts ? opts.map((o: any) => o.value) : [])} />
```

State should store `string[]`, not option objects.

---

## Best Practices

1. **Store values, not objects** — `useState<string>('')` not `useState<{label, value}>()`
2. **Convert on input** — `value={options.find(opt => opt.value === stateValue)}`
3. **Convert on output** — `onChange={(option: any) => setState(option?.value || '')}`
4. **Never store option objects in Zustand** — store primitives only
5. **Use `any` for onChange parameter** — react-select types are complex
6. **Memoize options** — `useMemo` for i18n-dependent options, `const` for static

---

## DSelectNative — REMOVED in v2.0

Use `DInputSelect` from `inputs.md` instead (native HTML `<select>` with Dynamic UI styling).
