1
- import { $ , QRL , Signal , Slot , component$ , useSignal , useTask$ } from '@builder.io/qwik' ;
2
- import { DropdownItemProps , HDropdownItem } from './dropdown-item' ;
1
+ import {
2
+ $ ,
3
+ QRL ,
4
+ Signal ,
5
+ Slot ,
6
+ component$ ,
7
+ sync$ ,
8
+ useSignal ,
9
+ useTask$ ,
10
+ } from '@builder.io/qwik' ;
3
11
4
- type DropdownCheckboxItemProps = {
5
- /** A signal that controls the current checked state (controlled). */
12
+ import { CheckboxRoot } from '../checkbox/checkbox' ;
13
+ import { DropdownItemProps } from './dropdown-item' ;
14
+ import { useDropdownItem } from './use-dropdown-item' ;
15
+
16
+ export type DropdownCheckboxItemProps = {
17
+ /**
18
+ * A signal that controls the current checked value (controlled).
19
+ */
6
20
'bind:checked' ?: Signal < boolean > ;
7
21
8
22
/**
9
- * QRL handler that runs when the user selects an item .
23
+ * QRL handler that runs when the checked value changes .
10
24
*/
11
25
onChange$ ?: QRL < ( checked : boolean ) => void > ;
12
26
} & Omit < DropdownItemProps , 'onChange$' > ;
13
27
14
28
export const HDropdownCheckboxItem = component$ ( ( props : DropdownCheckboxItemProps ) => {
15
- const { disabled = false , closeOnSelect = false , onChange$ , ...rest } = props ;
29
+ const { disabled, onChange$ , closeOnSelect = false , ...rest } = props ;
16
30
17
31
const checkedSig = useSignal < boolean > ( false ) ;
32
+ const checkboxRef = useSignal < HTMLDivElement > ( ) ;
18
33
19
34
useTask$ ( function reactiveUserChecked ( { track } ) {
20
35
const bindCheckedSig = props [ 'bind:checked' ] ;
@@ -30,26 +45,51 @@ export const HDropdownCheckboxItem = component$((props: DropdownCheckboxItemProp
30
45
onChange$ ?.( checkedSig . value ) ;
31
46
} ) ;
32
47
33
- const onSelect = $ ( ( ) => {
48
+ // Handle the toggle of the checked state when the item is selected trough the keyboard or click.
49
+ const toggleChecked$ = $ ( ( ) => {
34
50
checkedSig . value = ! checkedSig . value ;
35
- props . onSelect$ ?.( ) ;
51
+ } ) ;
52
+
53
+ const {
54
+ handleClick$,
55
+ handleKeyDown$,
56
+ handlePointerOver$,
57
+ itemId,
58
+ itemRef,
59
+ isHighlightedSig,
60
+ } = useDropdownItem ( { ...props , onItemSelect : toggleChecked$ , closeOnSelect } ) ;
61
+
62
+ //Prevent default behavior for certain keys. This needs to be sync to prevent default behavior and can't be implemented in useDropdownItem.
63
+ const handleKeyDownSync$ = sync$ ( ( e : KeyboardEvent ) => {
64
+ const keys = [ 'ArrowUp' , 'ArrowDown' , 'ArrowLeft' , 'Home' , 'End' , 'Enter' , ' ' ] ;
65
+ if ( keys . includes ( e . key ) ) {
66
+ e . preventDefault ( ) ;
67
+ }
36
68
} ) ;
37
69
38
70
return (
39
- < HDropdownItem
40
- { ...rest }
41
- onSelect$ = { onSelect }
42
- role = "menuitemcheckbox"
43
- closeOnSelect = { closeOnSelect }
44
- disabled = { disabled }
45
- aria-checked = { checkedSig . value ? 'true' : 'false' }
46
- aria-disabled = { disabled }
47
- style = { { display : 'flex' , alignItems : 'center' } }
71
+ < div
72
+ onClick$ = { [ handleClick$ , props . onClick$ ] }
73
+ tabIndex = { - 1 }
74
+ id = { itemId }
75
+ onKeyDown$ = { [ handleKeyDownSync$ , handleKeyDown$ , props . onKeyDown$ ] }
76
+ onPointerOver$ = { [ handlePointerOver$ , props . onPointerOver$ ] }
77
+ ref = { itemRef }
78
+ aria-disabled = { disabled === true ? 'true' : 'false' }
48
79
data-disabled = { disabled }
80
+ data-highlighted = { isHighlightedSig . value }
49
81
data-checked = { checkedSig . value }
82
+ data-menu-item
50
83
>
51
- < Slot name = "dropdown-item-indicator" />
52
- < Slot />
53
- </ HDropdownItem >
84
+ < CheckboxRoot
85
+ bind :checked = { checkedSig }
86
+ preventdefault :click
87
+ ref = { checkboxRef }
88
+ style = { { pointerEvents : 'none' } }
89
+ { ...rest }
90
+ >
91
+ < Slot />
92
+ </ CheckboxRoot >
93
+ </ div >
54
94
) ;
55
95
} ) ;
0 commit comments