1- import { Checkbox , Label } from '@/components/emcn'
1+ import { Info } from 'lucide-react'
2+ import { Checkbox , Label , Tooltip } from '@/components/emcn'
23import { useSubBlockValue } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/hooks/use-sub-block-value'
34
5+ interface CheckboxListOption {
6+ label : string
7+ id : string
8+ defaultChecked ?: boolean
9+ description ?: string
10+ }
11+
412interface CheckboxListProps {
513 blockId : string
6- subBlockId : string
7- title : string
8- options : { label : string ; id : string } [ ]
14+ options : CheckboxListOption [ ]
915 isPreview ?: boolean
1016 subBlockValues ?: Record < string , any >
1117 disabled ?: boolean
1218}
1319
1420interface CheckboxItemProps {
1521 blockId : string
16- option : { label : string ; id : string }
22+ option : CheckboxListOption
1723 isPreview : boolean
1824 subBlockValues ?: Record < string , any >
1925 disabled : boolean
2026}
2127
2228/**
23- * Individual checkbox item component that calls useSubBlockValue hook at top level
29+ * Individual checkbox item component that calls useSubBlockValue hook at top level.
30+ *
31+ * @remarks
32+ * A `null` store value means the user has never toggled the checkbox, in which
33+ * case we fall back to `option.defaultChecked` for the displayed state. Any
34+ * explicit boolean (including `false`) takes precedence over the default.
2435 */
2536function CheckboxItem ( { blockId, option, isPreview, subBlockValues, disabled } : CheckboxItemProps ) {
26- const [ storeValue , setStoreValue ] = useSubBlockValue ( blockId , option . id )
37+ const [ storeValue , setStoreValue ] = useSubBlockValue < boolean > ( blockId , option . id )
2738
28- // Get preview value for this specific option
2939 const previewValue = isPreview && subBlockValues ? subBlockValues [ option . id ] ?. value : undefined
30-
31- // Use preview value when in preview mode, otherwise use store value
32- const value = isPreview ? previewValue : storeValue
40+ const rawValue = isPreview ? previewValue : storeValue
41+ const effectiveValue = rawValue ?? option . defaultChecked ?? false
3342
3443 const handleChange = ( checked : boolean ) => {
35- // Only update store when not in preview mode or disabled
3644 if ( ! isPreview && ! disabled ) {
3745 setStoreValue ( checked )
3846 }
3947 }
4048
4149 return (
42- < div className = 'flex items-center space-x -2' >
50+ < div className = 'flex items-center gap -2' >
4351 < Checkbox
4452 id = { `${ blockId } -${ option . id } ` }
45- checked = { Boolean ( value ) }
53+ checked = { Boolean ( effectiveValue ) }
4654 onCheckedChange = { handleChange }
4755 disabled = { isPreview || disabled }
4856 />
@@ -52,21 +60,29 @@ function CheckboxItem({ blockId, option, isPreview, subBlockValues, disabled }:
5260 >
5361 { option . label }
5462 </ Label >
63+ { option . description && (
64+ < Tooltip . Root >
65+ < Tooltip . Trigger asChild >
66+ < Info className = 'h-[14px] w-[14px] cursor-default text-[var(--text-muted)]' />
67+ </ Tooltip . Trigger >
68+ < Tooltip . Content side = 'top' align = 'start' className = 'max-w-xs' >
69+ < p > { option . description } </ p >
70+ </ Tooltip . Content >
71+ </ Tooltip . Root >
72+ ) }
5573 </ div >
5674 )
5775}
5876
5977export function CheckboxList ( {
6078 blockId,
61- subBlockId,
62- title,
6379 options,
6480 isPreview = false ,
6581 subBlockValues,
6682 disabled = false ,
6783} : CheckboxListProps ) {
6884 return (
69- < div className = 'grid grid-cols-1 gap-4 pt-1' >
85+ < div className = 'flex flex-col gap-y-2.5 pt-1' >
7086 { options . map ( ( option ) => (
7187 < CheckboxItem
7288 key = { option . id }
0 commit comments