11'use client'
22
3- import { Badge , Button , ChipInput , cn } from '@sim/emcn'
3+ import { Button , ChipInput } from '@sim/emcn'
44import { Plus , Trash } from '@sim/emcn/icons'
55import { generateShortId } from '@sim/utils/id'
6- import type { SelectColor , SelectOption } from '@/lib/table'
7- import { SELECT_COLOR_LABELS , SELECT_COLOR_ORDER } from './select-colors'
6+ import type { SelectOption } from '@/lib/table'
87
98interface SelectOptionsEditorProps {
109 options : SelectOption [ ]
1110 onChange : ( options : SelectOption [ ] ) => void
1211}
1312
14- /** Default color for a freshly added option — cycles through the palette. */
15- function nextColor ( count : number ) : SelectColor {
16- return SELECT_COLOR_ORDER [ count % SELECT_COLOR_ORDER . length ]
17- }
18-
19- interface ColorSwatchesProps {
20- value : SelectColor
21- onChange : ( color : SelectColor ) => void
22- }
23-
24- /** Inline row of color squircles; the active color is ringed. */
25- function ColorSwatches ( { value, onChange } : ColorSwatchesProps ) {
26- return (
27- < div className = 'flex flex-wrap items-center gap-1.5' >
28- { SELECT_COLOR_ORDER . map ( ( color ) => (
29- < button
30- key = { color }
31- type = 'button'
32- aria-label = { SELECT_COLOR_LABELS [ color ] }
33- aria-pressed = { color === value }
34- onClick = { ( ) => onChange ( color ) }
35- className = { cn (
36- 'rounded-[6px] transition-shadow' ,
37- color === value &&
38- 'ring-2 ring-[var(--text-icon)] ring-offset-1 ring-offset-[var(--bg)]'
39- ) }
40- >
41- { /* Reuse the Badge palette as the swatch fill so colors stay single-sourced. */ }
42- < Badge variant = { color } size = 'sm' className = 'size-5 rounded-[6px] p-0' />
43- </ button >
44- ) ) }
45- </ div >
46- )
47- }
48-
4913/**
50- * Add/remove/rename/recolor the options of a `select`/`multiselect` column.
51- * Option ids are stable across edits so existing cell data survives renames.
14+ * Add/remove/rename the options of a `select`/`multiselect` column. Option ids
15+ * are stable across edits so existing cell data survives renames. Options
16+ * default to the neutral `gray` pill — per-option colors are not yet exposed
17+ * (the `color` field stays in the model so a picker can be re-added later).
5218 */
5319export function SelectOptionsEditor ( { options, onChange } : SelectOptionsEditorProps ) {
5420 const update = ( id : string , patch : Partial < SelectOption > ) => {
@@ -60,33 +26,30 @@ export function SelectOptionsEditor({ options, onChange }: SelectOptionsEditorPr
6026 }
6127
6228 const add = ( ) => {
63- onChange ( [ ...options , { id : generateShortId ( ) , name : '' , color : nextColor ( options . length ) } ] )
29+ onChange ( [ ...options , { id : generateShortId ( ) , name : '' , color : 'gray' } ] )
6430 }
6531
6632 return (
67- < div className = 'flex flex-col gap-3 ' >
33+ < div className = 'flex flex-col gap-2 ' >
6834 { options . map ( ( option ) => (
69- < div key = { option . id } className = 'flex flex-col gap-1.5' >
70- < div className = 'flex items-center gap-1.5' >
71- < ChipInput
72- value = { option . name }
73- onChange = { ( e ) => update ( option . id , { name : e . target . value } ) }
74- placeholder = 'Option name'
75- spellCheck = { false }
76- autoComplete = 'off'
77- className = 'min-w-0 flex-1'
78- />
79- < Button
80- variant = 'ghost'
81- size = 'sm'
82- onClick = { ( ) => remove ( option . id ) }
83- className = '!p-1 size-7 shrink-0'
84- aria-label = { `Remove ${ option . name || 'option' } ` }
85- >
86- < Trash className = 'size-[14px]' />
87- </ Button >
88- </ div >
89- < ColorSwatches value = { option . color } onChange = { ( color ) => update ( option . id , { color } ) } />
35+ < div key = { option . id } className = 'flex items-center gap-1.5' >
36+ < ChipInput
37+ value = { option . name }
38+ onChange = { ( e ) => update ( option . id , { name : e . target . value } ) }
39+ placeholder = 'Option name'
40+ spellCheck = { false }
41+ autoComplete = 'off'
42+ className = 'min-w-0 flex-1'
43+ />
44+ < Button
45+ variant = 'ghost'
46+ size = 'sm'
47+ onClick = { ( ) => remove ( option . id ) }
48+ className = '!p-1 size-7 shrink-0'
49+ aria-label = { `Remove ${ option . name || 'option' } ` }
50+ >
51+ < Trash className = 'size-[14px]' />
52+ </ Button >
9053 </ div >
9154 ) ) }
9255 < Button variant = 'default' size = 'sm' onClick = { add } className = 'self-start' >
0 commit comments