@@ -18,6 +18,7 @@ import {
18
18
Show ,
19
19
useContext ,
20
20
} from 'solid-js'
21
+ import { createStore } from 'solid-js/store'
21
22
22
23
import { commandScore } from './command-score'
23
24
@@ -131,6 +132,7 @@ interface Context {
131
132
interface State {
132
133
search : string
133
134
value : string
135
+ enter : string
134
136
filtered : { count : number ; items : Map < string , number > ; groups : Set < string > }
135
137
}
136
138
interface Store {
@@ -150,7 +152,6 @@ const GROUP_ITEMS_SELECTOR = '[cmdk-group-items=""]'
150
152
const GROUP_HEADING_SELECTOR = '[cmdk-group-heading=""]'
151
153
const ITEM_SELECTOR = '[cmdk-item=""]'
152
154
const VALID_ITEM_SELECTOR = `${ ITEM_SELECTOR } :not([aria-disabled="true"])`
153
- const SELECT_EVENT = 'cmdk-item-select'
154
155
const VALUE_ATTR = 'data-value'
155
156
const defaultFilter : CommandProps [ 'filter' ] = ( value , search ) => commandScore ( value , search )
156
157
@@ -163,6 +164,8 @@ const StoreContext = createContext<Store>({
163
164
search : '' ,
164
165
/** Currently selected item value. */
165
166
value : '' ,
167
+ /** Currently item value when press key enter. */
168
+ enter : '' ,
166
169
filtered : {
167
170
/** The count of all visible items. */
168
171
count : 0 ,
@@ -216,6 +219,7 @@ export const Command = (props: CommandProps) => {
216
219
search : '' ,
217
220
/** Currently selected item value. */
218
221
value : props . value ?? props . defaultValue ?. toLowerCase ( ) ?? '' ,
222
+ enter : '' ,
219
223
filtered : {
220
224
/** The count of all visible items. */
221
225
count : 0 ,
@@ -240,7 +244,7 @@ export const Command = (props: CommandProps) => {
240
244
const schedule = useScheduleLayoutEffect ( )
241
245
242
246
// TODO
243
- const [ store ] = createSignal < Store > ( {
247
+ const [ store ] = createStore < Store > ( {
244
248
subscribe : ( cb ) => {
245
249
listeners . current ?. add ( cb )
246
250
return ( ) => listeners . current ?. delete ( cb )
@@ -273,7 +277,7 @@ export const Command = (props: CommandProps) => {
273
277
}
274
278
275
279
// Notify subscribers that state has changed
276
- store ( ) . emit ( )
280
+ store . emit ( )
277
281
} ,
278
282
emit : ( ) => {
279
283
listeners . current . forEach ( l => l ( ) )
@@ -286,19 +290,19 @@ export const Command = (props: CommandProps) => {
286
290
const v = value . trim ( ) . toLowerCase ( )
287
291
state . current . value = v
288
292
schedule ( 6 , scrollSelectedIntoView )
289
- store ( ) . emit ( )
293
+ store . emit ( )
290
294
}
291
295
} , [ value ] )
292
296
293
- const [ context ] = createSignal < Context > ( {
297
+ const [ context ] = createStore < Context > ( {
294
298
// Keep id → value mapping up-to-date
295
299
value : ( id , value ) => {
296
300
if ( value !== ids . current . get ( id ) ) {
297
301
ids . current . set ( id , value )
298
302
state . current . filtered . items . set ( id , score ( value ) )
299
303
schedule ( 2 , ( ) => {
300
304
sort ( )
301
- store ( ) . emit ( )
305
+ store . emit ( )
302
306
} )
303
307
}
304
308
} ,
@@ -326,7 +330,7 @@ export const Command = (props: CommandProps) => {
326
330
selectFirstItem ( )
327
331
}
328
332
329
- store ( ) . emit ( )
333
+ store . emit ( )
330
334
} )
331
335
332
336
return ( ) => {
@@ -345,7 +349,7 @@ export const Command = (props: CommandProps) => {
345
349
selectFirstItem ( )
346
350
}
347
351
348
- store ( ) . emit ( )
352
+ store . emit ( )
349
353
} )
350
354
}
351
355
} ,
@@ -436,7 +440,7 @@ export const Command = (props: CommandProps) => {
436
440
function selectFirstItem ( ) {
437
441
const item = getValidItems ( ) . find ( item => ! item . ariaDisabled ) !
438
442
const value = item . getAttribute ( VALUE_ATTR ) !
439
- store ( ) . setState ( 'value' , value || undefined )
443
+ store . setState ( 'value' , value || undefined )
440
444
}
441
445
442
446
/** Filters the current items. */
@@ -508,7 +512,7 @@ export const Command = (props: CommandProps) => {
508
512
const items = getValidItems ( )
509
513
const item = items [ index ]
510
514
if ( item ) {
511
- store ( ) . setState ( 'value' , item . getAttribute ( VALUE_ATTR ) )
515
+ store . setState ( 'value' , item . getAttribute ( VALUE_ATTR ) )
512
516
}
513
517
}
514
518
@@ -530,7 +534,7 @@ export const Command = (props: CommandProps) => {
530
534
}
531
535
532
536
if ( newSelected ) {
533
- store ( ) . setState ( 'value' , newSelected . getAttribute ( VALUE_ATTR ) )
537
+ store . setState ( 'value' , newSelected . getAttribute ( VALUE_ATTR ) )
534
538
}
535
539
}
536
540
@@ -545,7 +549,7 @@ export const Command = (props: CommandProps) => {
545
549
}
546
550
547
551
if ( item ) {
548
- store ( ) . setState ( 'value' , item . getAttribute ( VALUE_ATTR ) ! )
552
+ store . setState ( 'value' , item . getAttribute ( VALUE_ATTR ) ! )
549
553
} else {
550
554
updateSelectedByChange ( change )
551
555
}
@@ -634,8 +638,8 @@ export const Command = (props: CommandProps) => {
634
638
e . preventDefault ( )
635
639
const item = getSelectedItem ( )
636
640
if ( item ) {
637
- const event = new Event ( SELECT_EVENT )
638
- item . dispatchEvent ( event )
641
+ const value = item . getAttribute ( VALUE_ATTR ) !
642
+ store . setState ( 'enter' , value )
639
643
}
640
644
}
641
645
}
@@ -644,15 +648,15 @@ export const Command = (props: CommandProps) => {
644
648
>
645
649
< label
646
650
cmdk-label = ""
647
- for = { context ( ) . inputId }
648
- id = { context ( ) . labelId }
651
+ for = { context . inputId }
652
+ id = { context . labelId }
649
653
// Screen reader only
650
654
style = { srOnlyStyles }
651
655
>
652
656
{ label }
653
657
</ label >
654
- < StoreContext . Provider value = { store ( ) } >
655
- < CommandContext . Provider value = { context ( ) } > { props . children } </ CommandContext . Provider >
658
+ < StoreContext . Provider value = { store } >
659
+ < CommandContext . Provider value = { context } > { props . children } </ CommandContext . Provider >
656
660
</ StoreContext . Provider >
657
661
</ div >
658
662
)
@@ -678,27 +682,34 @@ export const CommandItem = (props: ItemProps) => {
678
682
const value = useValue ( id , ref , [ props . value , props . children , ref ] )
679
683
680
684
const store = useStore ( ) !
681
- const selected = useCmdk ( state => state ?. value && state ?. value === value . current )
682
- const render = useCmdk ( state =>
683
- forceMount ? true : context . filter ?.( ) === false ? true : ! state . search ? true : ( state . filtered ?. items ?. get ?.( id ) as number ) > 0 ,
684
- )
685
+ const selected = useCmdk ( ( state ) => {
686
+ return state ?. value && state ?. value === value ( )
687
+ } )
688
+ const entered = useCmdk ( state => state ?. enter )
689
+ const render = useCmdk ( ( state ) => {
690
+ return forceMount
691
+ ? true
692
+ : context . filter ?.( ) === false
693
+ ? true
694
+ : ! state . search
695
+ ? true
696
+ : ( state . filtered ?. items ?. get ?.( id ) as number ) > 0
697
+ } )
685
698
686
699
createEffect ( ( ) => {
687
- const element = ref . current
688
- if ( ! element || props . disabled ) {
689
- return
700
+ if ( entered ( ) === value ( ) ) {
701
+ onSelect ( )
702
+ store . setState ( 'enter' , '' )
690
703
}
691
- element . addEventListener ( SELECT_EVENT , onSelect )
692
- onCleanup ( ( ) => element . removeEventListener ( SELECT_EVENT , onSelect ) )
693
704
} )
694
705
695
706
function onSelect ( ) {
696
707
select ( )
697
- propsRef . current ?. onSelect ?.( value . current ! )
708
+ propsRef . current ?. onSelect ?.( value ( ) ! )
698
709
}
699
710
700
711
function select ( ) {
701
- store . setState ( 'value' , value . current ! , true )
712
+ store . setState ( 'value' , value ( ) ! , true )
702
713
}
703
714
704
715
const { disabled, value : _ , onSelect : __ , forwardedRef, ...etc } = props
@@ -717,6 +728,7 @@ export const CommandItem = (props: ItemProps) => {
717
728
data-selected = { selected ( ) || undefined }
718
729
onPointerMove = { disabled ? undefined : select }
719
730
onClick = { disabled ? undefined : onSelect }
731
+ data-value = { value ( ) }
720
732
>
721
733
{ props . children }
722
734
</ div >
@@ -1016,7 +1028,7 @@ function useValue(
1016
1028
ref : ReactRef < HTMLElement > ,
1017
1029
deps : ( JSX . Element | ReactRef < HTMLElement > | string ) [ ] ,
1018
1030
) {
1019
- const valueRef : ReactRef < string > = { }
1031
+ const [ v , setValue ] = createSignal < string > ( )
1020
1032
const context = useCommand ( )
1021
1033
1022
1034
onMount ( ( ) => {
@@ -1033,9 +1045,10 @@ function useValue(
1033
1045
} ) ( )
1034
1046
1035
1047
context . value ?.( id , value ! )
1048
+ // TODO: looks like we do not need update ref data-value
1036
1049
ref . current ?. setAttribute ( VALUE_ATTR , value ! )
1037
- valueRef . current = value
1050
+ setValue ( value )
1038
1051
} )
1039
1052
1040
- return valueRef
1053
+ return v
1041
1054
}
0 commit comments