@@ -14,10 +14,11 @@ import { useHistoryServiceDispatch } from '../global-state/HistoryServiceProvide
14
14
export function Header ( ) {
15
15
const search = useQueryContext ( ) ;
16
16
const term = useComputed ( ( ) => search . value . term ) ;
17
+ const range = useComputed ( ( ) => search . value . range ) ;
17
18
const domain = useComputed ( ( ) => search . value . domain ) ;
18
19
return (
19
20
< div class = { styles . root } >
20
- < Controls term = { term } />
21
+ < Controls term = { term } range = { range } />
21
22
< div class = { styles . search } >
22
23
< SearchForm term = { term } domain = { domain } />
23
24
</ div >
@@ -30,22 +31,52 @@ export function Header() {
30
31
*
31
32
* @param {Object } props - Properties passed to the component.
32
33
* @param {import("@preact/signals").Signal<string|null> } props.term
34
+ * @param {import("@preact/signals").Signal<string|null> } props.range
33
35
*/
34
- function Controls ( { term } ) {
36
+ function Controls ( { term, range } ) {
35
37
const { t } = useTypedTranslation ( ) ;
38
+ const { results } = useData ( ) ;
36
39
const selected = useSelected ( ) ;
37
40
const dispatch = useHistoryServiceDispatch ( ) ;
41
+
42
+ /**
43
+ * Aria labels + title text is derived from the current result set.
44
+ */
45
+ const ariaDisabled = useComputed ( ( ) => ( results . value . items . length === 0 ? 'true' : 'false' ) ) ;
46
+ const title = useComputed ( ( ) => ( results . value . items . length === 0 ? t ( 'delete_none' ) : '' ) ) ;
47
+
48
+ /**
49
+ * The button text should alternate between 'delete' and 'delete all' depending on the
50
+ * state of the current query. It should only read 'delete all' when the query is the default one
51
+ * and there are no selections
52
+ */
38
53
const buttonTxt = useComputed ( ( ) => {
39
54
const hasTerm = term . value !== null && term . value . trim ( ) !== '' ;
40
55
const hasSelections = selected . value . size > 0 ;
41
- return hasTerm || hasSelections ? t ( 'delete_some' ) : t ( 'delete_all' ) ;
56
+ const hasRange = range . value !== null ;
57
+ return hasTerm || hasSelections || hasRange ? t ( 'delete_some' ) : t ( 'delete_all' ) ;
42
58
} ) ;
43
- const { results } = useData ( ) ;
44
- const ariaDisabled = useComputed ( ( ) => ( results . value . items . length === 0 ? 'true' : 'false' ) ) ;
45
- const title = useComputed ( ( ) => ( results . value . items . length === 0 ? t ( 'delete_none' ) : '' ) ) ;
59
+
60
+ /**
61
+ * Which action should the delete button take?
62
+ *
63
+ * - if there are selections, they should be deleted
64
+ * - if there's a range selected, that should be deleted
65
+ * - or fallback to deleting all
66
+ */
67
+ function onClick ( ) {
68
+ if ( selected . value . size > 0 ) {
69
+ return dispatch ( { kind : 'delete-entries-by-index' , value : [ ...selected . value ] } ) ;
70
+ }
71
+ if ( range . value !== null ) {
72
+ return dispatch ( { kind : 'delete-range' , value : range . value } ) ;
73
+ }
74
+ dispatch ( { kind : 'delete-all' } ) ;
75
+ }
76
+
46
77
return (
47
78
< div class = { styles . controls } >
48
- < button class = { styles . largeButton } onClick = { ( ) => dispatch ( { kind : 'delete-all' } ) } aria-disabled = { ariaDisabled } title = { title } >
79
+ < button class = { styles . largeButton } onClick = { onClick } aria-disabled = { ariaDisabled } title = { title } >
49
80
< Trash />
50
81
< span > { buttonTxt } </ span >
51
82
</ button >
0 commit comments