From 5da253b831b6ea81051b5469ee5daa900d79f7bc Mon Sep 17 00:00:00 2001 From: Robin Malfait Date: Fri, 2 Apr 2021 15:18:47 +0200 Subject: [PATCH] backfill fixes (#299) * fix unique symbol error (#248) * Vue breaking change (#279) * bump Vue * ensure we reference the vite.config.js * fix event name casing Vue broke this in a 3.0.5 release, it still worked in 3.0.4. Fixes: #267 * handle throwing while rendering a better in tests --- CHANGELOG.md | 2 +- packages/@headlessui-react/src/types.ts | 6 +- packages/@headlessui-vue/package.json | 6 +- .../src/components/listbox/listbox.ts | 12 ++-- .../src/components/menu/menu.test.tsx | 49 +++++---------- .../src/components/menu/menu.ts | 12 ++-- .../src/components/switch/switch.ts | 4 +- .../src/test-utils/interactions.test.ts | 36 +++++------ yarn.lock | 59 ++++++++++++++++++- 9 files changed, 113 insertions(+), 73 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3bf2b8b..69fc9da 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,7 +7,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased - React] -- Nothing yet! +- Fix incorrect type error `unique symbol` ([#248](https://github.com/tailwindlabs/headlessui/pull/248), [#240](https://github.com/tailwindlabs/headlessui/issues/240)) ## [Unreleased - Vue] diff --git a/packages/@headlessui-react/src/types.ts b/packages/@headlessui-react/src/types.ts index 6775799..6d91a8b 100644 --- a/packages/@headlessui-react/src/types.ts +++ b/packages/@headlessui-react/src/types.ts @@ -1,7 +1,9 @@ import { ReactNode, ReactElement } from 'react' -// A unique placeholder we can use as some defaults. This is nice because we can use this instead of + +// A unique placeholder we can use as a default. This is nice because we can use this instead of // defaulting to null / never / ... and possibly collide with actual data. -const __: unique symbol = Symbol('__placeholder__') +// Ideally we use a unique symbol here. +let __ = '1D45E01E-AF44-47C4-988A-19A94EBAF55C' as const export type __ = typeof __ export type Expand = T extends infer O ? { [K in keyof O]: O[K] } : never diff --git a/packages/@headlessui-vue/package.json b/packages/@headlessui-vue/package.json index c60903e..4b228e0 100644 --- a/packages/@headlessui-vue/package.json +++ b/packages/@headlessui-vue/package.json @@ -20,7 +20,7 @@ "access": "public" }, "scripts": { - "playground": "vite serve examples", + "playground": "vite --config ./vite.config.js serve examples", "playground:build": "NODE_ENV=production vite build examples", "prepublishOnly": "npm run build", "build": "../../scripts/build.sh", @@ -29,7 +29,7 @@ "lint": "../../scripts/lint.sh" }, "peerDependencies": { - "vue": "^3.0.0-rc.13" + "vue": "^3.0.0" }, "devDependencies": { "@popperjs/core": "^2.5.3", @@ -38,7 +38,7 @@ "@vue/compiler-sfc": "3.0.1", "@vue/test-utils": "^2.0.0-beta.7", "vite": "^1.0.0-rc.4", - "vue": "^3.0.0-rc.13", + "vue": "^3.0.0", "vue-router": "^4.0.0-beta.13" } } diff --git a/packages/@headlessui-vue/src/components/listbox/listbox.ts b/packages/@headlessui-vue/src/components/listbox/listbox.ts index b1421ff..f10d7a5 100644 --- a/packages/@headlessui-vue/src/components/listbox/listbox.ts +++ b/packages/@headlessui-vue/src/components/listbox/listbox.ts @@ -259,7 +259,7 @@ export let ListboxButton = defineComponent({ ? [api.labelRef.value.id, this.id].join(' ') : undefined, disabled: api.disabled, - onKeyDown: this.handleKeyDown, + onKeydown: this.handleKeyDown, onClick: this.handleClick, } @@ -336,7 +336,7 @@ export let ListboxOptions = defineComponent({ : api.options.value[api.activeOptionIndex.value]?.id, 'aria-labelledby': api.labelRef.value?.id ?? api.buttonRef.value?.id, id: this.id, - onKeyDown: this.handleKeyDown, + onKeydown: this.handleKeyDown, role: 'listbox', tabIndex: 0, ref: 'el', @@ -508,10 +508,10 @@ export let ListboxOption = defineComponent({ 'aria-selected': selected.value === true ? selected.value : undefined, onClick: handleClick, onFocus: handleFocus, - onPointerMove: handleMove, - onMouseMove: handleMove, - onPointerLeave: handleLeave, - onMouseLeave: handleLeave, + onPointermove: handleMove, + onMousemove: handleMove, + onPointerleave: handleLeave, + onMouseleave: handleLeave, } return render({ props: { ...props, ...propsWeControl }, slot, attrs, slots }) diff --git a/packages/@headlessui-vue/src/components/menu/menu.test.tsx b/packages/@headlessui-vue/src/components/menu/menu.test.tsx index 993eb04..11f6723 100644 --- a/packages/@headlessui-vue/src/components/menu/menu.test.tsx +++ b/packages/@headlessui-vue/src/components/menu/menu.test.tsx @@ -315,18 +315,7 @@ describe('Rendering', () => { }) it('should yell when we render MenuItems using a template `as` prop that contains multiple children', async () => { - let state = { - resolve(_value: Error | PromiseLike) {}, - done(error: unknown) { - state.resolve(error as Error) - return true - }, - promise: new Promise(() => {}), - } - - state.promise = new Promise(resolve => { - state.resolve = resolve - }) + expect.assertions(1) renderTemplate({ template: ` @@ -339,14 +328,15 @@ describe('Rendering', () => { `, - errorCaptured: state.done, + errorCaptured(err: unknown) { + expect((err as Error).message).toMatchInlineSnapshot( + `"You should only render 1 child or use the \`as=\\"...\\"\` prop"` + ) + return false + }, }) await click(getMenuButton()) - let error = await state.promise - expect(error.message).toMatchInlineSnapshot( - `"You should only render 1 child or use the \`as=\\"...\\"\` prop"` - ) }) it('should be possible to always render the MenuItems if we provide it a `static` prop', () => { @@ -469,18 +459,7 @@ describe('Rendering', () => { }) it('should yell when we render a MenuItem using a template `as` prop that contains multiple children', async () => { - let state = { - resolve(_value: Error | PromiseLike) {}, - done(error: unknown) { - state.resolve(error as Error) - return true - }, - promise: new Promise(() => {}), - } - - state.promise = new Promise(resolve => { - state.resolve = resolve - }) + expect.assertions(1) renderTemplate({ template: ` @@ -496,14 +475,16 @@ describe('Rendering', () => { `, - errorCaptured: state.done, + errorCaptured(err: unknown) { + expect((err as Error).message).toMatchInlineSnapshot( + `"You should only render 1 child or use the \`as=\\"...\\"\` prop"` + ) + + return false + }, }) await click(getMenuButton()) - let error = await state.promise - expect(error.message).toMatchInlineSnapshot( - `"You should only render 1 child or use the \`as=\\"...\\"\` prop"` - ) }) }) }) diff --git a/packages/@headlessui-vue/src/components/menu/menu.ts b/packages/@headlessui-vue/src/components/menu/menu.ts index 68c7350..98a48d1 100644 --- a/packages/@headlessui-vue/src/components/menu/menu.ts +++ b/packages/@headlessui-vue/src/components/menu/menu.ts @@ -178,7 +178,7 @@ export let MenuButton = defineComponent({ 'aria-haspopup': true, 'aria-controls': api.itemsRef.value?.id, 'aria-expanded': api.menuState.value === MenuStates.Open ? true : undefined, - onKeyDown: this.handleKeyDown, + onKeydown: this.handleKeyDown, onClick: this.handleClick, } @@ -257,7 +257,7 @@ export let MenuItems = defineComponent({ : api.items.value[api.activeItemIndex.value]?.id, 'aria-labelledby': api.buttonRef.value?.id, id: this.id, - onKeyDown: this.handleKeyDown, + onKeydown: this.handleKeyDown, role: 'menu', tabIndex: 0, ref: 'el', @@ -428,10 +428,10 @@ export let MenuItem = defineComponent({ 'aria-disabled': disabled === true ? true : undefined, onClick: handleClick, onFocus: handleFocus, - onPointerMove: handleMove, - onMouseMove: handleMove, - onPointerLeave: handleLeave, - onMouseLeave: handleLeave, + onPointermove: handleMove, + onMousemove: handleMove, + onPointerleave: handleLeave, + onMouseleave: handleLeave, } return render({ props: { ...props, ...propsWeControl }, slot, attrs, slots }) diff --git a/packages/@headlessui-vue/src/components/switch/switch.ts b/packages/@headlessui-vue/src/components/switch/switch.ts index a2521ac..2560dfe 100644 --- a/packages/@headlessui-vue/src/components/switch/switch.ts +++ b/packages/@headlessui-vue/src/components/switch/switch.ts @@ -71,8 +71,8 @@ export let Switch = defineComponent({ 'aria-checked': this.$props.modelValue, 'aria-labelledby': labelledby.value, onClick: this.handleClick, - onKeyUp: this.handleKeyUp, - onKeyPress: this.handleKeyPress, + onKeyup: this.handleKeyUp, + onKeypress: this.handleKeyPress, } if (this.$props.as === 'button') { diff --git a/packages/@headlessui-vue/src/test-utils/interactions.test.ts b/packages/@headlessui-vue/src/test-utils/interactions.test.ts index 88e265f..3dab1e8 100644 --- a/packages/@headlessui-vue/src/test-utils/interactions.test.ts +++ b/packages/@headlessui-vue/src/test-utils/interactions.test.ts @@ -3,8 +3,8 @@ import { render } from './vue-testing-library' import { type, shift, Keys } from './interactions' import { defineComponent, h } from 'vue' -type Events = 'onKeyDown' | 'onKeyUp' | 'onKeyPress' | 'onClick' | 'onBlur' | 'onFocus' -let events: Events[] = ['onKeyDown', 'onKeyUp', 'onKeyPress', 'onClick', 'onBlur', 'onFocus'] +type Events = 'onKeydown' | 'onKeyup' | 'onKeypress' | 'onClick' | 'onBlur' | 'onFocus' +let events: Events[] = ['onKeydown', 'onKeyup', 'onKeypress', 'onClick', 'onBlur', 'onFocus'] function renderTemplate(input: string | Partial[0]>) { let defaultComponents = {} @@ -81,16 +81,16 @@ describe('Keyboard', () => { ], // Canceling keydown - ['a', ['keydown', 'keyup'], new Set(['onKeyDown'])], - [Keys.Space, ['keydown', 'keyup'], new Set(['onKeyDown'])], - [Keys.Enter, ['keydown', 'keyup'], new Set(['onKeyDown'])], - [Keys.Tab, ['keydown', 'keyup'], new Set(['onKeyDown'])], - [shift(Keys.Tab), ['keydown', 'keyup'], new Set(['onKeyDown'])], + ['a', ['keydown', 'keyup'], new Set(['onKeydown'])], + [Keys.Space, ['keydown', 'keyup'], new Set(['onKeydown'])], + [Keys.Enter, ['keydown', 'keyup'], new Set(['onKeydown'])], + [Keys.Tab, ['keydown', 'keyup'], new Set(['onKeydown'])], + [shift(Keys.Tab), ['keydown', 'keyup'], new Set(['onKeydown'])], // Canceling keypress - ['a', ['keydown', 'keypress', 'keyup'], new Set(['onKeyPress'])], - [Keys.Space, ['keydown', 'keypress', 'keyup', 'click'], new Set(['onKeyPress'])], - [Keys.Enter, ['keydown', 'keypress', 'keyup'], new Set(['onKeyPress'])], + ['a', ['keydown', 'keypress', 'keyup'], new Set(['onKeypress'])], + [Keys.Space, ['keydown', 'keypress', 'keyup', 'click'], new Set(['onKeypress'])], + [Keys.Enter, ['keydown', 'keypress', 'keyup'], new Set(['onKeypress'])], [ Keys.Tab, [ @@ -99,7 +99,7 @@ describe('Keyboard', () => { event('focus', 'after'), event('keyup', 'after'), ], - new Set(['onKeyPress']), + new Set(['onKeypress']), ], [ shift(Keys.Tab), @@ -109,13 +109,13 @@ describe('Keyboard', () => { event('focus', 'before'), event('keyup', 'before'), ], - new Set(['onKeyPress']), + new Set(['onKeypress']), ], // Canceling keyup - ['a', ['keydown', 'keypress', 'keyup'], new Set(['onKeyUp'])], - [Keys.Space, ['keydown', 'keypress', 'keyup'], new Set(['onKeyUp'])], - [Keys.Enter, ['keydown', 'keypress', 'click', 'keyup'], new Set(['onKeyUp'])], + ['a', ['keydown', 'keypress', 'keyup'], new Set(['onKeyup'])], + [Keys.Space, ['keydown', 'keypress', 'keyup'], new Set(['onKeyup'])], + [Keys.Enter, ['keydown', 'keypress', 'click', 'keyup'], new Set(['onKeyup'])], [ Keys.Tab, [ @@ -124,7 +124,7 @@ describe('Keyboard', () => { event('focus', 'after'), event('keyup', 'after'), ], - new Set(['onKeyUp']), + new Set(['onKeyup']), ], [ shift(Keys.Tab), @@ -134,7 +134,7 @@ describe('Keyboard', () => { event('focus', 'before'), event('keyup', 'before'), ], - new Set(['onKeyUp']), + new Set(['onKeyup']), ], // Cancelling blur @@ -189,7 +189,7 @@ describe('Keyboard', () => { Button: defineComponent({ setup(_props, { slots, attrs }) { return () => { - return h('button', createProps(attrs.id as string), slots.default()) + return h('button', createProps(attrs.id as string), slots.default!()) } }, }), diff --git a/yarn.lock b/yarn.lock index d329437..d31a1a0 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1878,6 +1878,17 @@ estree-walker "^2.0.1" source-map "^0.6.1" +"@vue/compiler-core@3.0.7": + version "3.0.7" + resolved "https://registry.yarnpkg.com/@vue/compiler-core/-/compiler-core-3.0.7.tgz#421782a4c67cc3f2b7c30457ef446d74f8524f74" + integrity sha512-JFohgBXoyUc3mdeI2WxlhjQZ5fakfemJkZHX8Gu/nFbEg3+lKVUZmNKWmmnp9aOzJQZKoj77LjmFxiP+P+7lMQ== + dependencies: + "@babel/parser" "^7.12.0" + "@babel/types" "^7.12.0" + "@vue/shared" "3.0.7" + estree-walker "^2.0.1" + source-map "^0.6.1" + "@vue/compiler-dom@3.0.0", "@vue/compiler-dom@^3.0.0-rc.5": version "3.0.0" resolved "https://registry.yarnpkg.com/@vue/compiler-dom/-/compiler-dom-3.0.0.tgz#4cbb48fcf1f852daef2babcf9953b681ac463526" @@ -1894,6 +1905,14 @@ "@vue/compiler-core" "3.0.1" "@vue/shared" "3.0.1" +"@vue/compiler-dom@3.0.7": + version "3.0.7" + resolved "https://registry.yarnpkg.com/@vue/compiler-dom/-/compiler-dom-3.0.7.tgz#54d2e12fb9a7aff53abd19dac2c2679533f0c919" + integrity sha512-VnIH9EbWQm/Tkcp+8dCaNVsVvhm/vxCrIKWRkXY9215hTqOqQOvejT8IMjd2kc++nIsYMsdQk6H9qqBvoLe/Cw== + dependencies: + "@vue/compiler-core" "3.0.7" + "@vue/shared" "3.0.7" + "@vue/compiler-sfc@3.0.1": version "3.0.1" resolved "https://registry.yarnpkg.com/@vue/compiler-sfc/-/compiler-sfc-3.0.1.tgz#f340f8f75b5c1c4509e0f3a12c79d1544899b663" @@ -1961,6 +1980,13 @@ dependencies: "@vue/shared" "3.0.0" +"@vue/reactivity@3.0.7": + version "3.0.7" + resolved "https://registry.yarnpkg.com/@vue/reactivity/-/reactivity-3.0.7.tgz#e6ccc7bef7fc10b0972e4d974bad71679d3b26ad" + integrity sha512-FotWcNNaKhqpFZrdgsUOZ1enlJ5lhTt01CNTtLSyK7jYFgZBTuw8vKsEutZKDYZ1XKotOfoeO8N3pZQqmM6Etw== + dependencies: + "@vue/shared" "3.0.7" + "@vue/runtime-core@3.0.0": version "3.0.0" resolved "https://registry.yarnpkg.com/@vue/runtime-core/-/runtime-core-3.0.0.tgz#480febf1bfe32798b6abbd71a88f8e8b473a51c2" @@ -1969,6 +1995,14 @@ "@vue/reactivity" "3.0.0" "@vue/shared" "3.0.0" +"@vue/runtime-core@3.0.7": + version "3.0.7" + resolved "https://registry.yarnpkg.com/@vue/runtime-core/-/runtime-core-3.0.7.tgz#d44c0b0a57d7e392912a87362a4430ccf446ecea" + integrity sha512-DBAZAwVvdmMXuyd6/9qqj/kYr/GaLTmn1L2/QLxLwP+UfhIboiTSBc/tUUb8MRk7Bb98GzNeAWkkT6AfooS3dQ== + dependencies: + "@vue/reactivity" "3.0.7" + "@vue/shared" "3.0.7" + "@vue/runtime-dom@3.0.0": version "3.0.0" resolved "https://registry.yarnpkg.com/@vue/runtime-dom/-/runtime-dom-3.0.0.tgz#e0d1f7c7e22e1318696014cc3501e06b288c2e11" @@ -1978,6 +2012,15 @@ "@vue/shared" "3.0.0" csstype "^2.6.8" +"@vue/runtime-dom@3.0.7": + version "3.0.7" + resolved "https://registry.yarnpkg.com/@vue/runtime-dom/-/runtime-dom-3.0.7.tgz#b70668d729020bc4ad608c20367223f259576ba6" + integrity sha512-Oij4ruOtnpQpCj+/Q3JPzgpTJ1Q7+N67pA53A8KVITEtxfvKL46NN6dhAZ5NGqwX6RWZpYqWQNewITeF0pHr8g== + dependencies: + "@vue/runtime-core" "3.0.7" + "@vue/shared" "3.0.7" + csstype "^2.6.8" + "@vue/shared@3.0.0": version "3.0.0" resolved "https://registry.yarnpkg.com/@vue/shared/-/shared-3.0.0.tgz#ec089236629ecc0f10346b92f101ff4339169f1a" @@ -1988,6 +2031,11 @@ resolved "https://registry.yarnpkg.com/@vue/shared/-/shared-3.0.1.tgz#48196c056726aa7466d0182698524c84f203006b" integrity sha512-/X6AUbTFCyD2BcJnBoacUct8qcv1A5uk1+N+3tbzDVuhGPRmoYrTSnNUuF53C/GIsTkChrEiXaJh2kyo/0tRvw== +"@vue/shared@3.0.7": + version "3.0.7" + resolved "https://registry.yarnpkg.com/@vue/shared/-/shared-3.0.7.tgz#96d52988efc07444c108c7c6803ba7cc93e40045" + integrity sha512-dn5FyfSc4ky424jH4FntiHno7Ss5yLkqKNmM/NXwANRnlkmqu74pnGetexDFVG5phMk9/FhwovUZCWGxsotVKg== + "@vue/test-utils@^1.0.3", "@vue/test-utils@^1.1.0": version "1.1.0" resolved "https://registry.yarnpkg.com/@vue/test-utils/-/test-utils-1.1.0.tgz#76305e73a786c921ede1352849614e26c7113f94" @@ -10692,7 +10740,16 @@ vue@^2.6.10: resolved "https://registry.yarnpkg.com/vue/-/vue-2.6.12.tgz#f5ebd4fa6bd2869403e29a896aed4904456c9123" integrity sha512-uhmLFETqPPNyuLLbsKz6ioJ4q7AZHzD8ZVFNATNyICSZouqP2Sz0rotWQC8UNBF6VGSCs5abnKJoStA6JbCbfg== -vue@^3.0.0-rc.13, vue@^3.0.0-rc.5: +vue@^3.0.0: + version "3.0.7" + resolved "https://registry.yarnpkg.com/vue/-/vue-3.0.7.tgz#8bcff51f8be570f9e4ce8cc5f52e2ab0fe3c74a1" + integrity sha512-8h4TikD+JabbMK9aRlBO4laG0AtNHRPHynxYgWZ9sq1YUPfzynd9Jeeb27XNyZytC7aCQRX9xe1+TQJuc181Tw== + dependencies: + "@vue/compiler-dom" "3.0.7" + "@vue/runtime-dom" "3.0.7" + "@vue/shared" "3.0.7" + +vue@^3.0.0-rc.5: version "3.0.0" resolved "https://registry.yarnpkg.com/vue/-/vue-3.0.0.tgz#cfb5df5c34efce319b113a1667d12b74dcfd9c90" integrity sha512-ZMrAARZ32sGIaYKr7Fk2GZEBh/VhulSrGxcGBiAvbN4fhjl3tuJyNFbbbLFqGjndbLoBW66I2ECq8ICdvkKdJw==