Skip to content

Commit aac4769

Browse files
committed
fix: listbox updates
1 parent 2b17dd5 commit aac4769

File tree

4 files changed

+40
-13
lines changed

4 files changed

+40
-13
lines changed
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
---
2+
"@zag-js/listbox": patch
3+
---
4+
5+
- Fix issue in React where filtering items with an input would throw a
6+
`flushSync was called from inside a lifecycle method` warning.
7+
- Fix issue where `data-highlighted` wasn't applied to the first item when using `autoHighlight` with input filtering.

packages/machines/listbox/src/listbox.connect.ts

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ export function connect<T extends PropTypes, V extends CollectionItem = Collecti
3030

3131
const focused = context.get("focused")
3232
const focusVisible = refs.get("focusVisible") && focused
33+
const inputState = refs.get("inputState")
3334

3435
const value = context.get("value")
3536
const selectedItems = context.get("selectedItems")
@@ -53,7 +54,7 @@ export function connect<T extends PropTypes, V extends CollectionItem = Collecti
5354
focused: highlighted && focused,
5455
focusVisible: highlighted && focusVisible,
5556
// deprecated
56-
highlighted: highlighted && focusVisible,
57+
highlighted: highlighted && (inputState.focused ? focused : focusVisible),
5758
selected: context.get("value").includes(value),
5859
}
5960
}
@@ -122,21 +123,17 @@ export function connect<T extends PropTypes, V extends CollectionItem = Collecti
122123
enterKeyHint: "go",
123124
onFocus() {
124125
queueMicrotask(() => {
125-
send({ type: "INPUT.FOCUS" })
126+
send({ type: "INPUT.FOCUS", autoHighlight: !!props?.autoHighlight })
126127
})
127128
},
128129
onBlur() {
129130
send({ type: "CONTENT.BLUR", src: "input" })
130131
},
131132
onInput(event) {
132-
if (!props.autoHighlight) return
133-
const node = event.currentTarget
133+
if (!props?.autoHighlight) return
134+
if (event.currentTarget.value.trim()) return
134135
queueMicrotask(() => {
135-
if (!node.isConnected) return
136-
send({
137-
type: "HIGHLIGHTED_VALUE.SET",
138-
value: node.value ? prop("collection").firstValue : null,
139-
})
136+
send({ type: "HIGHLIGHTED_VALUE.SET", value: null })
140137
})
141138
},
142139
onKeyDown(event) {

packages/machines/listbox/src/listbox.machine.ts

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ export const machine = createMachine({
7373
return {
7474
typeahead: { ...getByTypeahead.defaultOptions },
7575
focusVisible: false,
76+
inputState: { autoHighlight: false, focused: false },
7677
}
7778
},
7879

@@ -131,7 +132,7 @@ export const machine = createMachine({
131132
effects: ["scrollToHighlightedItem"],
132133
on: {
133134
"INPUT.FOCUS": {
134-
actions: ["setFocused"],
135+
actions: ["setFocused", "setInputState"],
135136
},
136137
"CONTENT.FOCUS": [
137138
{
@@ -143,7 +144,7 @@ export const machine = createMachine({
143144
},
144145
],
145146
"CONTENT.BLUR": {
146-
actions: ["clearFocused"],
147+
actions: ["clearFocused", "clearInputState"],
147148
},
148149
"ITEM.CLICK": {
149150
actions: ["setHighlightedItem", "selectHighlightedItem"],
@@ -326,11 +327,24 @@ export const machine = createMachine({
326327
context.set("highlightedItem", highlightedItem)
327328
},
328329

329-
syncHighlightedValue({ context, prop }) {
330+
syncHighlightedValue({ context, prop, refs }) {
330331
const collection = prop("collection")
331332
const highlightedValue = context.get("highlightedValue")
333+
const { autoHighlight } = refs.get("inputState")
334+
335+
// when autoHighlight is enabled, always highlight first item on collection change
336+
if (autoHighlight) {
337+
queueMicrotask(() => {
338+
context.set("highlightedValue", prop("collection").firstValue ?? null)
339+
})
340+
return
341+
}
342+
343+
// if highlighted value is no longer in collection, clear it
332344
if (highlightedValue != null && !collection.has(highlightedValue)) {
333-
context.set("highlightedValue", null)
345+
queueMicrotask(() => {
346+
context.set("highlightedValue", null)
347+
})
334348
}
335349
},
336350

@@ -349,6 +363,14 @@ export const machine = createMachine({
349363
clearFocused({ context }) {
350364
context.set("focused", false)
351365
},
366+
367+
setInputState({ refs, event }) {
368+
refs.set("inputState", { autoHighlight: !!event.autoHighlight, focused: true })
369+
},
370+
371+
clearInputState({ refs }) {
372+
refs.set("inputState", { autoHighlight: false, focused: false })
373+
},
352374
},
353375
},
354376
})

packages/machines/listbox/src/listbox.types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,7 @@ export interface ListboxSchema<T extends CollectionItem = CollectionItem> {
151151
refs: {
152152
typeahead: TypeaheadState
153153
focusVisible: boolean
154+
inputState: { autoHighlight: boolean; focused: boolean }
154155
}
155156
action: string
156157
guard: string

0 commit comments

Comments
 (0)