diff --git a/package-lock.json b/package-lock.json
index 4c2e013223..ed9f8defe9 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -30,7 +30,7 @@
"prettier-plugin-tailwindcss": "^0.5.7",
"rimraf": "^3.0.2",
"tslib": "^2.3.1",
- "typescript": "^5.3.2"
+ "typescript": "^5.4.3"
}
},
"node_modules/@adobe/css-tools": {
@@ -100,6 +100,19 @@
"node": ">=18"
}
},
+ "node_modules/@arethetypeswrong/core/node_modules/typescript": {
+ "version": "5.3.3",
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.3.3.tgz",
+ "integrity": "sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==",
+ "dev": true,
+ "bin": {
+ "tsc": "bin/tsc",
+ "tsserver": "bin/tsserver"
+ },
+ "engines": {
+ "node": ">=14.17"
+ }
+ },
"node_modules/@babel/code-frame": {
"version": "7.23.5",
"dev": true,
@@ -9653,9 +9666,10 @@
}
},
"node_modules/typescript": {
- "version": "5.3.3",
+ "version": "5.4.3",
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.3.tgz",
+ "integrity": "sha512-KrPd3PKaCLr78MalgiwJnA25Nm8HAmdwN3mYUYZgG/wizIo9EainNVQI9/yDavtVFRN2h3k8uf3GLHuhDMgEHg==",
"devOptional": true,
- "license": "Apache-2.0",
"bin": {
"tsc": "bin/tsc",
"tsserver": "bin/tsserver"
diff --git a/package.json b/package.json
index 8f89cf0c7d..68164048dd 100644
--- a/package.json
+++ b/package.json
@@ -63,6 +63,6 @@
"prettier-plugin-tailwindcss": "^0.5.7",
"rimraf": "^3.0.2",
"tslib": "^2.3.1",
- "typescript": "^5.3.2"
+ "typescript": "^5.4.3"
}
}
diff --git a/packages/@headlessui-react/CHANGELOG.md b/packages/@headlessui-react/CHANGELOG.md
index c8291c4ebc..9086dd5168 100644
--- a/packages/@headlessui-react/CHANGELOG.md
+++ b/packages/@headlessui-react/CHANGELOG.md
@@ -25,6 +25,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Changed
- Attempt form submission when pressing `Enter` on the `` component ([#2972](https://github.com/tailwindlabs/headlessui/pull/2972))
+- Make the `Combobox` component `nullable` by default ([#3064](https://github.com/tailwindlabs/headlessui/pull/3064))
### Added
diff --git a/packages/@headlessui-react/src/components/combobox/combobox.test.tsx b/packages/@headlessui-react/src/components/combobox/combobox.test.tsx
index 8e24d69d0e..0e824d8562 100644
--- a/packages/@headlessui-react/src/components/combobox/combobox.test.tsx
+++ b/packages/@headlessui-react/src/components/combobox/combobox.test.tsx
@@ -387,10 +387,13 @@ describe('Rendering', () => {
'should be possible to use completely new objects while rendering (single mode)',
suppressConsoleLogs(async () => {
function Example() {
- let [value, setValue] = useState({ id: 2, name: 'Bob' })
+ let [value, setValue] = useState<{ id: number; name: string } | null>({
+ id: 2,
+ name: 'Bob',
+ })
return (
- setValue(value)} by="id">
+
Trigger
alice
@@ -432,7 +435,7 @@ describe('Rendering', () => {
let [value, setValue] = useState([{ id: 2, name: 'Bob' }])
return (
- setValue(value)} by="id" multiple>
+
Trigger
alice
@@ -472,7 +475,7 @@ describe('Rendering', () => {
]
render(
-
+ name="assignee" by="id">
value.name}
onChange={NOOP}
@@ -499,7 +502,7 @@ describe('Rendering', () => {
]
function Example() {
- let [person, setPerson] = useState(data[1])
+ let [person, setPerson] = useState<(typeof data)[number] | null>(data[1])
return (
@@ -546,7 +549,7 @@ describe('Rendering', () => {
]
render(
-
+ name="assignee" by="id">
@@ -647,7 +650,7 @@ describe('Rendering', () => {
'selecting an option puts the display value into Combobox.Input when displayValue is provided (when value is undefined)',
suppressConsoleLogs(async () => {
function Example() {
- let [value, setValue] = useState(undefined)
+ let [value, setValue] = useState(undefined)
return (
@@ -692,7 +695,7 @@ describe('Rendering', () => {
return (
<>
-
+
@@ -766,7 +769,7 @@ describe('Rendering', () => {
'should reflect the value in the input when the value changes and when you are typing',
suppressConsoleLogs(async () => {
function Example() {
- let [value, setValue] = useState('bob')
+ let [value, setValue] = useState('bob')
let [_query, setQuery] = useState('')
return (
@@ -1608,7 +1611,11 @@ describe('Rendering', () => {
handleSubmission(Object.fromEntries(new FormData(e.target as HTMLFormElement)))
}}
>
-
+
+ name="assignee"
+ defaultValue={{ id: 2, name: 'bob', label: 'Bob' }}
+ by="id"
+ >
{({ value }) => value?.name ?? 'Trigger'}
{
it(
- 'should reset the value when the last character is removed, when in `nullable` mode',
+ 'should reset the value when the last character is removed',
suppressConsoleLogs(async () => {
let handleChange = jest.fn()
function Example() {
let [value, setValue] = useState('bob')
let [, setQuery] = useState('')
- // return (
- // {
- // setValue(value)
- // handleChange(value)
- // },
- // nullable: true,
- // }}
- // inputProps={{
- // onChange: (event: any) => setQuery(event.target.value),
- // }}
- // />
- // )
-
return (
setQuery(event.target.value)} />
Trigger
@@ -4175,7 +4160,7 @@ describe.each([{ virtual: true }, { virtual: false }])(
await press(Keys.Backspace)
expect(getComboboxInput()?.value).toBe('')
- // Verify that we don't have an selected option anymore since we are in `nullable` mode
+ // Verify that we don't have an selected option anymore
assertNotActiveComboboxOption(options[1])
assertNoSelectedComboboxOption()
@@ -4189,7 +4174,7 @@ describe.each([{ virtual: true }, { virtual: false }])(
describe('`Any` key aka search', () => {
type Option = { value: string; name: string; disabled: boolean }
function Example(props: { people: { value: string; name: string; disabled: boolean }[] }) {
- let [value, setValue] = useState