From ac64a80a463b7b573b4f347fe585a3f74cfa9a7c Mon Sep 17 00:00:00 2001 From: Robin Malfait Date: Mon, 8 Jan 2024 14:57:55 +0100 Subject: [PATCH] disable `immediate` and `virtual` feature for `Combobox` component in patch release --- .../src/components/combobox/combobox.test.tsx | 282 ++++++++-------- .../src/components/combobox/combobox.tsx | 21 +- .../src/components/combobox/combobox.test.ts | 314 +++++++++--------- .../src/components/combobox/combobox.ts | 23 +- 4 files changed, 327 insertions(+), 313 deletions(-) diff --git a/packages/@headlessui-react/src/components/combobox/combobox.test.tsx b/packages/@headlessui-react/src/components/combobox/combobox.test.tsx index 7a9bb90e50..505c85f1ad 100644 --- a/packages/@headlessui-react/src/components/combobox/combobox.test.tsx +++ b/packages/@headlessui-react/src/components/combobox/combobox.test.tsx @@ -1832,7 +1832,7 @@ describe('Composition', () => { ) }) -describe.each([{ virtual: true }, { virtual: false }])( +describe.each([{ virtual: false }, { virtual: false }])( 'Keyboard interactions %s', ({ virtual }) => { let data = ['Option A', 'Option B', 'Option C'] @@ -4309,7 +4309,7 @@ describe.each([{ virtual: true }, { virtual: false }])( } ) -describe.each([{ virtual: true }, { virtual: false }])('Mouse interactions %s', ({ virtual }) => { +describe.each([{ virtual: false }, { virtual: false }])('Mouse interactions %s', ({ virtual }) => { let data = ['Option A', 'Option B', 'Option C'] function MyCombobox({ options = data.slice() as T[], @@ -4411,126 +4411,126 @@ describe.each([{ virtual: true }, { virtual: false }])('Mouse interactions %s', }) ) - it( - 'should be possible to open the combobox by focusing the input with immediate mode enabled', - suppressConsoleLogs(async () => { - render() - - assertComboboxButton({ - state: ComboboxState.InvisibleUnmounted, - attributes: { id: 'headlessui-combobox-button-2' }, - }) - assertComboboxList({ state: ComboboxState.InvisibleUnmounted }) - - // Focus the input - await focus(getComboboxInput()) - - // Verify it is visible - assertComboboxButton({ state: ComboboxState.Visible }) - assertComboboxList({ - state: ComboboxState.Visible, - attributes: { id: 'headlessui-combobox-options-3' }, - }) - assertActiveElement(getComboboxInput()) - assertComboboxButtonLinkedWithCombobox() - - // Verify we have combobox options - let options = getComboboxOptions() - expect(options).toHaveLength(3) - options.forEach((option) => assertComboboxOption(option)) - }) - ) - - it( - 'should not be possible to open the combobox by focusing the input with immediate mode disabled', - suppressConsoleLogs(async () => { - render() - - assertComboboxButton({ - state: ComboboxState.InvisibleUnmounted, - attributes: { id: 'headlessui-combobox-button-3' }, - }) - assertComboboxList({ state: ComboboxState.InvisibleUnmounted }) - - // Focus the input - await focus(getComboboxInput()) - - // Verify it is invisible - assertComboboxButton({ - state: ComboboxState.InvisibleUnmounted, - attributes: { id: 'headlessui-combobox-button-3' }, - }) - assertComboboxList({ state: ComboboxState.InvisibleUnmounted }) - }) - ) - - it( - 'should not be possible to open the combobox by focusing the input with immediate mode enabled when button is disabled', - suppressConsoleLogs(async () => { - render() - - assertComboboxButton({ - state: ComboboxState.InvisibleUnmounted, - attributes: { id: 'headlessui-combobox-button-3' }, - }) - assertComboboxList({ state: ComboboxState.InvisibleUnmounted }) - - // Focus the input - await focus(getComboboxInput()) - - // Verify it is invisible - assertComboboxButton({ - state: ComboboxState.InvisibleUnmounted, - attributes: { id: 'headlessui-combobox-button-3' }, - }) - assertComboboxList({ state: ComboboxState.InvisibleUnmounted }) - }) - ) - - it( - 'should be possible to close a combobox on click with immediate mode enabled', - suppressConsoleLogs(async () => { - render() - - // Open combobox - await click(getComboboxButton()) - - // Verify it is visible - assertComboboxButton({ state: ComboboxState.Visible }) - - // Click to close - await click(getComboboxButton()) - - // Verify it is closed - assertComboboxButton({ state: ComboboxState.InvisibleUnmounted }) - assertComboboxList({ state: ComboboxState.InvisibleUnmounted }) - assertActiveElement(getComboboxInput()) - }) - ) - - it( - 'should be possible to close a focused combobox on click with immediate mode enabled', - suppressConsoleLogs(async () => { - render() - assertComboboxButton({ state: ComboboxState.InvisibleUnmounted }) - - // Open combobox by focusing input - await focus(getComboboxInput()) - assertActiveElement(getComboboxInput()) - - // Verify it is visible - assertComboboxButton({ state: ComboboxState.Visible }) - - // Click to close - await click(getComboboxButton()) - - // Verify it is closed - assertComboboxButton({ state: ComboboxState.InvisibleUnmounted }) - assertComboboxList({ state: ComboboxState.InvisibleUnmounted }) - assertActiveElement(getComboboxInput()) - }) - ) - + // it( + // 'should be possible to open the combobox by focusing the input with immediate mode enabled', + // suppressConsoleLogs(async () => { + // render() + // + // assertComboboxButton({ + // state: ComboboxState.InvisibleUnmounted, + // attributes: { id: 'headlessui-combobox-button-2' }, + // }) + // assertComboboxList({ state: ComboboxState.InvisibleUnmounted }) + // + // // Focus the input + // await focus(getComboboxInput()) + // + // // Verify it is visible + // assertComboboxButton({ state: ComboboxState.Visible }) + // assertComboboxList({ + // state: ComboboxState.Visible, + // attributes: { id: 'headlessui-combobox-options-3' }, + // }) + // assertActiveElement(getComboboxInput()) + // assertComboboxButtonLinkedWithCombobox() + // + // // Verify we have combobox options + // let options = getComboboxOptions() + // expect(options).toHaveLength(3) + // options.forEach((option) => assertComboboxOption(option)) + // }) + // ) + // + // it( + // 'should not be possible to open the combobox by focusing the input with immediate mode disabled', + // suppressConsoleLogs(async () => { + // render() + // + // assertComboboxButton({ + // state: ComboboxState.InvisibleUnmounted, + // attributes: { id: 'headlessui-combobox-button-3' }, + // }) + // assertComboboxList({ state: ComboboxState.InvisibleUnmounted }) + // + // // Focus the input + // await focus(getComboboxInput()) + // + // // Verify it is invisible + // assertComboboxButton({ + // state: ComboboxState.InvisibleUnmounted, + // attributes: { id: 'headlessui-combobox-button-3' }, + // }) + // assertComboboxList({ state: ComboboxState.InvisibleUnmounted }) + // }) + // ) + // + // it( + // 'should not be possible to open the combobox by focusing the input with immediate mode enabled when button is disabled', + // suppressConsoleLogs(async () => { + // render() + // + // assertComboboxButton({ + // state: ComboboxState.InvisibleUnmounted, + // attributes: { id: 'headlessui-combobox-button-3' }, + // }) + // assertComboboxList({ state: ComboboxState.InvisibleUnmounted }) + // + // // Focus the input + // await focus(getComboboxInput()) + // + // // Verify it is invisible + // assertComboboxButton({ + // state: ComboboxState.InvisibleUnmounted, + // attributes: { id: 'headlessui-combobox-button-3' }, + // }) + // assertComboboxList({ state: ComboboxState.InvisibleUnmounted }) + // }) + // ) + // + // it( + // 'should be possible to close a combobox on click with immediate mode enabled', + // suppressConsoleLogs(async () => { + // render() + // + // // Open combobox + // await click(getComboboxButton()) + // + // // Verify it is visible + // assertComboboxButton({ state: ComboboxState.Visible }) + // + // // Click to close + // await click(getComboboxButton()) + // + // // Verify it is closed + // assertComboboxButton({ state: ComboboxState.InvisibleUnmounted }) + // assertComboboxList({ state: ComboboxState.InvisibleUnmounted }) + // assertActiveElement(getComboboxInput()) + // }) + // ) + // + // it( + // 'should be possible to close a focused combobox on click with immediate mode enabled', + // suppressConsoleLogs(async () => { + // render() + // assertComboboxButton({ state: ComboboxState.InvisibleUnmounted }) + // + // // Open combobox by focusing input + // await focus(getComboboxInput()) + // assertActiveElement(getComboboxInput()) + // + // // Verify it is visible + // assertComboboxButton({ state: ComboboxState.Visible }) + // + // // Click to close + // await click(getComboboxButton()) + // + // // Verify it is closed + // assertComboboxButton({ state: ComboboxState.InvisibleUnmounted }) + // assertComboboxList({ state: ComboboxState.InvisibleUnmounted }) + // assertActiveElement(getComboboxInput()) + // }) + // ) + // it( 'should be possible to open the combobox on click', suppressConsoleLogs(async () => { @@ -5031,25 +5031,25 @@ describe.each([{ virtual: true }, { virtual: false }])('Mouse interactions %s', assertActiveComboboxOption(getComboboxOptions()[1]) }) ) - - it( - 'should be possible to click a combobox option, which closes the combobox with immediate mode enabled', - suppressConsoleLogs(async () => { - render() - - // Open combobox by focusing input - await focus(getComboboxInput()) - assertActiveElement(getComboboxInput()) - - assertComboboxList({ state: ComboboxState.Visible }) - - let options = getComboboxOptions() - - // We should be able to click the first option - await click(options[1]) - assertComboboxList({ state: ComboboxState.InvisibleUnmounted }) - }) - ) + // + // it( + // 'should be possible to click a combobox option, which closes the combobox with immediate mode enabled', + // suppressConsoleLogs(async () => { + // render() + // + // // Open combobox by focusing input + // await focus(getComboboxInput()) + // assertActiveElement(getComboboxInput()) + // + // assertComboboxList({ state: ComboboxState.Visible }) + // + // let options = getComboboxOptions() + // + // // We should be able to click the first option + // await click(options[1]) + // assertComboboxList({ state: ComboboxState.InvisibleUnmounted }) + // }) + // ) it( 'should be possible to click a disabled combobox option, which is a no-op', diff --git a/packages/@headlessui-react/src/components/combobox/combobox.tsx b/packages/@headlessui-react/src/components/combobox/combobox.tsx index 05cc76dc2e..bdacf6d1ca 100644 --- a/packages/@headlessui-react/src/components/combobox/combobox.tsx +++ b/packages/@headlessui-react/src/components/combobox/combobox.tsx @@ -605,11 +605,6 @@ export type ComboboxProps< __demoMode?: boolean form?: string name?: string - immediate?: boolean - virtual?: { - options: TValue[] - disabled?: (value: TValue) => boolean - } | null } function ComboboxFn( @@ -644,10 +639,22 @@ function ComboboxFn boolean + } | null + let [value = multiple ? [] : undefined, theirOnChange] = useControllable( controlledValue, controlledOnChange, diff --git a/packages/@headlessui-vue/src/components/combobox/combobox.test.ts b/packages/@headlessui-vue/src/components/combobox/combobox.test.ts index d7349f2631..0b2cdbbc62 100644 --- a/packages/@headlessui-vue/src/components/combobox/combobox.test.ts +++ b/packages/@headlessui-vue/src/components/combobox/combobox.test.ts @@ -1964,7 +1964,7 @@ describe('Composition', () => { ) }) -describe.each([{ virtual: true }, { virtual: false }])( +describe.each([{ virtual: false }, { virtual: false }])( 'Keyboard interactions %s', ({ virtual }) => { let data = ['Option A', 'Option B', 'Option C'] @@ -4674,7 +4674,7 @@ describe.each([{ virtual: true }, { virtual: false }])( } ) -describe.each([{ virtual: true }, { virtual: false }])('Mouse interactions %s', ({ virtual }) => { +describe.each([{ virtual: false }, { virtual: false }])('Mouse interactions %s', ({ virtual }) => { let data = ['Option A', 'Option B', 'Option C'] let MyCombobox = defineComponent({ components: getDefaultComponents(), @@ -4788,140 +4788,140 @@ describe.each([{ virtual: true }, { virtual: false }])('Mouse interactions %s', }) ) - it( - 'should be possible to open the combobox by focusing the input with immediate mode enabled', - suppressConsoleLogs(async () => { - renderTemplate({ - components: { MyCombobox }, - template: html``, - }) - - assertComboboxButton({ - state: ComboboxState.InvisibleUnmounted, - attributes: { id: 'headlessui-combobox-button-2' }, - }) - assertComboboxList({ state: ComboboxState.InvisibleUnmounted }) - - // Focus the input - await focus(getComboboxInput()) - - // Verify it is visible - assertComboboxButton({ state: ComboboxState.Visible }) - assertComboboxList({ - state: ComboboxState.Visible, - attributes: { id: 'headlessui-combobox-options-3' }, - }) - assertActiveElement(getComboboxInput()) - assertComboboxButtonLinkedWithCombobox() - - // Verify we have combobox options - let options = getComboboxOptions() - expect(options).toHaveLength(3) - options.forEach((option) => assertComboboxOption(option)) - }) - ) - - it( - 'should not be possible to open the combobox by focusing the input with immediate mode disabled', - suppressConsoleLogs(async () => { - renderTemplate({ - components: { MyCombobox }, - template: html``, - }) - - assertComboboxButton({ - state: ComboboxState.InvisibleUnmounted, - attributes: { id: 'headlessui-combobox-button-3' }, - }) - assertComboboxList({ state: ComboboxState.InvisibleUnmounted }) - - // Focus the input - await focus(getComboboxInput()) - - // Verify it is invisible - assertComboboxButton({ state: ComboboxState.InvisibleUnmounted }) - assertComboboxList({ - state: ComboboxState.InvisibleUnmounted, - attributes: { id: 'headlessui-combobox-options-3' }, - }) - }) - ) - - it( - 'should not be possible to open the combobox by focusing the input with immediate mode enabled when button is disabled', - suppressConsoleLogs(async () => { - renderTemplate({ - components: { MyCombobox }, - template: html``, - }) - - assertComboboxButton({ - state: ComboboxState.InvisibleUnmounted, - attributes: { id: 'headlessui-combobox-button-3' }, - }) - assertComboboxList({ state: ComboboxState.InvisibleUnmounted }) - - // Focus the input - await focus(getComboboxInput()) - - // Verify it is invisible - assertComboboxButton({ state: ComboboxState.InvisibleUnmounted }) - assertComboboxList({ - state: ComboboxState.InvisibleUnmounted, - attributes: { id: 'headlessui-combobox-options-3' }, - }) - }) - ) - - it( - 'should be possible to close a combobox on click with immediate mode enabled', - suppressConsoleLogs(async () => { - renderTemplate({ - components: { MyCombobox }, - template: html``, - }) - - // Open combobox - await click(getComboboxButton()) - - // Verify it is visible - assertComboboxButton({ state: ComboboxState.Visible }) - - // Click to close - await click(getComboboxButton()) - - // Verify it is closed - assertComboboxButton({ state: ComboboxState.InvisibleUnmounted }) - assertComboboxList({ state: ComboboxState.InvisibleUnmounted }) - assertActiveElement(getComboboxInput()) - }) - ) - - it( - 'should be possible to close a focused combobox on click with immediate mode enabled', - suppressConsoleLogs(async () => { - renderTemplate({ - components: { MyCombobox }, - template: html``, - }) - assertComboboxButton({ state: ComboboxState.InvisibleUnmounted }) - - // Open combobox by focusing input - await focus(getComboboxInput()) - assertActiveElement(getComboboxInput()) - - // Verify it is visible - assertComboboxButton({ state: ComboboxState.Visible }) - - // Click to close - await click(getComboboxButton()) - - // Verify it is closed - assertComboboxButton({ state: ComboboxState.InvisibleUnmounted }) - assertComboboxList({ state: ComboboxState.InvisibleUnmounted }) - assertActiveElement(getComboboxInput()) - }) - ) + // it( + // 'should be possible to open the combobox by focusing the input with immediate mode enabled', + // suppressConsoleLogs(async () => { + // renderTemplate({ + // components: { MyCombobox }, + // template: html``, + // }) + // + // assertComboboxButton({ + // state: ComboboxState.InvisibleUnmounted, + // attributes: { id: 'headlessui-combobox-button-2' }, + // }) + // assertComboboxList({ state: ComboboxState.InvisibleUnmounted }) + // + // // Focus the input + // await focus(getComboboxInput()) + // + // // Verify it is visible + // assertComboboxButton({ state: ComboboxState.Visible }) + // assertComboboxList({ + // state: ComboboxState.Visible, + // attributes: { id: 'headlessui-combobox-options-3' }, + // }) + // assertActiveElement(getComboboxInput()) + // assertComboboxButtonLinkedWithCombobox() + // + // // Verify we have combobox options + // let options = getComboboxOptions() + // expect(options).toHaveLength(3) + // options.forEach((option) => assertComboboxOption(option)) + // }) + // ) + // + // it( + // 'should not be possible to open the combobox by focusing the input with immediate mode disabled', + // suppressConsoleLogs(async () => { + // renderTemplate({ + // components: { MyCombobox }, + // template: html``, + // }) + // + // assertComboboxButton({ + // state: ComboboxState.InvisibleUnmounted, + // attributes: { id: 'headlessui-combobox-button-3' }, + // }) + // assertComboboxList({ state: ComboboxState.InvisibleUnmounted }) + // + // // Focus the input + // await focus(getComboboxInput()) + // + // // Verify it is invisible + // assertComboboxButton({ state: ComboboxState.InvisibleUnmounted }) + // assertComboboxList({ + // state: ComboboxState.InvisibleUnmounted, + // attributes: { id: 'headlessui-combobox-options-3' }, + // }) + // }) + // ) + // + // it( + // 'should not be possible to open the combobox by focusing the input with immediate mode enabled when button is disabled', + // suppressConsoleLogs(async () => { + // renderTemplate({ + // components: { MyCombobox }, + // template: html``, + // }) + // + // assertComboboxButton({ + // state: ComboboxState.InvisibleUnmounted, + // attributes: { id: 'headlessui-combobox-button-3' }, + // }) + // assertComboboxList({ state: ComboboxState.InvisibleUnmounted }) + // + // // Focus the input + // await focus(getComboboxInput()) + // + // // Verify it is invisible + // assertComboboxButton({ state: ComboboxState.InvisibleUnmounted }) + // assertComboboxList({ + // state: ComboboxState.InvisibleUnmounted, + // attributes: { id: 'headlessui-combobox-options-3' }, + // }) + // }) + // ) + // + // it( + // 'should be possible to close a combobox on click with immediate mode enabled', + // suppressConsoleLogs(async () => { + // renderTemplate({ + // components: { MyCombobox }, + // template: html``, + // }) + // + // // Open combobox + // await click(getComboboxButton()) + // + // // Verify it is visible + // assertComboboxButton({ state: ComboboxState.Visible }) + // + // // Click to close + // await click(getComboboxButton()) + // + // // Verify it is closed + // assertComboboxButton({ state: ComboboxState.InvisibleUnmounted }) + // assertComboboxList({ state: ComboboxState.InvisibleUnmounted }) + // assertActiveElement(getComboboxInput()) + // }) + // ) + // + // it( + // 'should be possible to close a focused combobox on click with immediate mode enabled', + // suppressConsoleLogs(async () => { + // renderTemplate({ + // components: { MyCombobox }, + // template: html``, + // }) + // assertComboboxButton({ state: ComboboxState.InvisibleUnmounted }) + // + // // Open combobox by focusing input + // await focus(getComboboxInput()) + // assertActiveElement(getComboboxInput()) + // + // // Verify it is visible + // assertComboboxButton({ state: ComboboxState.Visible }) + // + // // Click to close + // await click(getComboboxButton()) + // + // // Verify it is closed + // assertComboboxButton({ state: ComboboxState.InvisibleUnmounted }) + // assertComboboxList({ state: ComboboxState.InvisibleUnmounted }) + // assertActiveElement(getComboboxInput()) + // }) + // ) it( 'should be possible to open the combobox on click', @@ -5476,27 +5476,27 @@ describe.each([{ virtual: true }, { virtual: false }])('Mouse interactions %s', }) ) - it( - 'should be possible to click a combobox option, which closes the combobox with immediate mode enabled', - suppressConsoleLogs(async () => { - renderTemplate({ - components: { MyCombobox }, - template: html``, - }) - - // Open combobox by focusing input - await focus(getComboboxInput()) - assertActiveElement(getComboboxInput()) - - assertComboboxList({ state: ComboboxState.Visible }) - - let options = getComboboxOptions() - - // We should be able to click the first option - await click(options[1]) - assertComboboxList({ state: ComboboxState.InvisibleUnmounted }) - }) - ) + // it( + // 'should be possible to click a combobox option, which closes the combobox with immediate mode enabled', + // suppressConsoleLogs(async () => { + // renderTemplate({ + // components: { MyCombobox }, + // template: html``, + // }) + // + // // Open combobox by focusing input + // await focus(getComboboxInput()) + // assertActiveElement(getComboboxInput()) + // + // assertComboboxList({ state: ComboboxState.Visible }) + // + // let options = getComboboxOptions() + // + // // We should be able to click the first option + // await click(options[1]) + // assertComboboxList({ state: ComboboxState.InvisibleUnmounted }) + // }) + // ) it( 'should be possible to click a disabled combobox option, which is a no-op', diff --git a/packages/@headlessui-vue/src/components/combobox/combobox.ts b/packages/@headlessui-vue/src/components/combobox/combobox.ts index 8555c76b55..bec824c78c 100644 --- a/packages/@headlessui-vue/src/components/combobox/combobox.ts +++ b/packages/@headlessui-vue/src/components/combobox/combobox.ts @@ -365,7 +365,10 @@ export let Combobox = defineComponent({ }) } - let virtualOptions = computed(() => props.virtual?.options) + let virtualOptions = computed(() => { + return undefined as unknown[] | undefined + // return props.virtual?.options + }) watch([virtualOptions], ([newOptions], [oldOptions]) => { if (!api.virtual.value) return if (!newOptions) return @@ -410,14 +413,18 @@ export let Combobox = defineComponent({ }, defaultValue: computed(() => props.defaultValue), nullable, - immediate: computed(() => props.immediate), + immediate: computed(() => { + return false + // return props.immediate + }), virtual: computed(() => { - return props.virtual - ? { - options: props.virtual.options, - disabled: props.virtual.disabled ?? (() => false), - } - : null + return null + // return props.virtual + // ? { + // options: props.virtual.options, + // disabled: props.virtual.disabled ?? (() => false), + // } + // : null }), inputRef, labelRef,