Skip to content

Commit

Permalink
Support <slot> children when using as="template" (#1548)
Browse files Browse the repository at this point in the history
* Extract renderTemplate logic

* Flatten Fragments when rendering

* Update changelog
  • Loading branch information
thecrypticace committed Jun 3, 2022
1 parent 4e13a0e commit 70333a9
Show file tree
Hide file tree
Showing 16 changed files with 147 additions and 216 deletions.
4 changes: 4 additions & 0 deletions packages/@headlessui-vue/CHANGELOG.md
Expand Up @@ -12,6 +12,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Add `by` prop for `Listbox`, `Combobox` and `RadioGroup` ([#1482](https://github.com/tailwindlabs/headlessui/pull/1482))
- Add `@headlessui/tailwindcss` plugin ([#1487](https://github.com/tailwindlabs/headlessui/pull/1487))

### Fixed

- Support `<slot>` children when using `as="template"` ([#1548](https://github.com/tailwindlabs/headlessui/pull/1548))

## [1.6.4] - 2022-05-29

### Fixed
Expand Down
18 changes: 2 additions & 16 deletions packages/@headlessui-vue/src/components/combobox/combobox.test.ts
Expand Up @@ -9,7 +9,7 @@ import {
computed,
PropType,
} from 'vue'
import { render } from '../../test-utils/vue-testing-library'
import { createRenderTemplate, render } from '../../test-utils/vue-testing-library'
import {
Combobox,
ComboboxInput,
Expand Down Expand Up @@ -89,21 +89,7 @@ function getDefaultComponents() {
}
}

function renderTemplate(input: string | Partial<DefineComponent>) {
let defaultComponents = getDefaultComponents()

if (typeof input === 'string') {
return render(defineComponent({ template: input, components: defaultComponents }))
}

return render(
defineComponent(
Object.assign({}, input, {
components: { ...defaultComponents, ...input.components },
}) as Parameters<typeof defineComponent>[0]
)
)
}
const renderTemplate = createRenderTemplate(getDefaultComponents())

describe('safeguards', () => {
it.each([
Expand Down
34 changes: 10 additions & 24 deletions packages/@headlessui-vue/src/components/dialog/dialog.test.ts
Expand Up @@ -7,7 +7,7 @@ import {
ConcreteComponent,
onMounted,
} from 'vue'
import { render } from '../../test-utils/vue-testing-library'
import { createRenderTemplate, render } from '../../test-utils/vue-testing-library'

import {
Dialog,
Expand Down Expand Up @@ -58,29 +58,15 @@ beforeAll(() => {

afterAll(() => jest.restoreAllMocks())

function renderTemplate(input: string | ComponentOptionsWithoutProps) {
let defaultComponents = {
Dialog,
DialogOverlay,
DialogBackdrop,
DialogPanel,
DialogTitle,
DialogDescription,
TabSentinel,
}

if (typeof input === 'string') {
return render(defineComponent({ template: input, components: defaultComponents }))
}

return render(
defineComponent(
Object.assign({}, input, {
components: { ...defaultComponents, ...input.components },
}) as Parameters<typeof defineComponent>[0]
)
)
}
const renderTemplate = createRenderTemplate({
Dialog,
DialogOverlay,
DialogBackdrop,
DialogPanel,
DialogTitle,
DialogDescription,
TabSentinel,
})

describe('Safe guards', () => {
it.each([
Expand Down
@@ -1,5 +1,5 @@
import { defineComponent, nextTick, ref, watch, h, ComponentOptionsWithoutProps } from 'vue'
import { render } from '../../test-utils/vue-testing-library'
import { createRenderTemplate, render } from '../../test-utils/vue-testing-library'
import { Disclosure, DisclosureButton, DisclosurePanel } from './disclosure'
import { suppressConsoleLogs } from '../../test-utils/suppress-console-logs'
import {
Expand All @@ -19,21 +19,11 @@ jest.mock('../../hooks/use-id')

afterAll(() => jest.restoreAllMocks())

function renderTemplate(input: string | ComponentOptionsWithoutProps) {
let defaultComponents = { Disclosure, DisclosureButton, DisclosurePanel }

if (typeof input === 'string') {
return render(defineComponent({ template: input, components: defaultComponents }))
}

return render(
defineComponent(
Object.assign({}, input, {
components: { ...defaultComponents, ...input.components },
}) as Parameters<typeof defineComponent>[0]
)
)
}
const renderTemplate = createRenderTemplate({
Disclosure,
DisclosureButton,
DisclosurePanel,
})

describe('Safe guards', () => {
it.each([
Expand Down
Expand Up @@ -3,7 +3,7 @@ import { defineComponent, ref, nextTick, onMounted, ComponentOptionsWithoutProps
import { FocusTrap } from './focus-trap'
import { assertActiveElement, getByText } from '../../test-utils/accessibility-assertions'
import { suppressConsoleLogs } from '../../test-utils/suppress-console-logs'
import { render } from '../../test-utils/vue-testing-library'
import { createRenderTemplate, render } from '../../test-utils/vue-testing-library'
import { click, press, shift, Keys } from '../../test-utils/interactions'
import { html } from '../../test-utils/html'

Expand All @@ -16,21 +16,9 @@ beforeAll(() => {

afterAll(() => jest.restoreAllMocks())

function renderTemplate(input: string | ComponentOptionsWithoutProps) {
let defaultComponents = { FocusTrap }

if (typeof input === 'string') {
return render(defineComponent({ template: input, components: defaultComponents }))
}

return render(
defineComponent(
Object.assign({}, input, {
components: { ...defaultComponents, ...input.components },
}) as Parameters<typeof defineComponent>[0]
)
)
}
const renderTemplate = createRenderTemplate({
FocusTrap,
})

it('should focus the first focusable element inside the FocusTrap', async () => {
renderTemplate(
Expand Down
24 changes: 8 additions & 16 deletions packages/@headlessui-vue/src/components/listbox/listbox.test.tsx
Expand Up @@ -7,7 +7,7 @@ import {
reactive,
ComponentOptionsWithoutProps,
} from 'vue'
import { render } from '../../test-utils/vue-testing-library'
import { createRenderTemplate, render } from '../../test-utils/vue-testing-library'
import { Listbox, ListboxLabel, ListboxButton, ListboxOptions, ListboxOption } from './listbox'
import { suppressConsoleLogs } from '../../test-utils/suppress-console-logs'
import {
Expand Down Expand Up @@ -66,21 +66,13 @@ function nextFrame() {
})
}

function renderTemplate(input: string | ComponentOptionsWithoutProps) {
let defaultComponents = { Listbox, ListboxLabel, ListboxButton, ListboxOptions, ListboxOption }

if (typeof input === 'string') {
return render(defineComponent({ template: input, components: defaultComponents }))
}

return render(
defineComponent(
Object.assign({}, input, {
components: { ...defaultComponents, ...input.components },
}) as Parameters<typeof defineComponent>[0]
)
)
}
const renderTemplate = createRenderTemplate({
Listbox,
ListboxLabel,
ListboxButton,
ListboxOptions,
ListboxOption,
})

describe('safeguards', () => {
it.each([
Expand Down
18 changes: 2 additions & 16 deletions packages/@headlessui-vue/src/components/menu/menu.test.tsx
Expand Up @@ -7,7 +7,7 @@ import {
ref,
watch,
} from 'vue'
import { render } from '../../test-utils/vue-testing-library'
import { createRenderTemplate, render } from '../../test-utils/vue-testing-library'
import { Menu, MenuButton, MenuItems, MenuItem } from './menu'
import { TransitionChild } from '../transitions/transition'
import { suppressConsoleLogs } from '../../test-utils/suppress-console-logs'
Expand Down Expand Up @@ -61,21 +61,7 @@ function nextFrame() {
})
}

function renderTemplate(input: string | ComponentOptionsWithoutProps) {
let defaultComponents = { Menu, MenuButton, MenuItems, MenuItem }

if (typeof input === 'string') {
return render(defineComponent({ template: input, components: defaultComponents }))
}

return render(
defineComponent(
Object.assign({}, input, {
components: { ...defaultComponents, ...input.components },
}) as Parameters<typeof defineComponent>[0]
)
)
}
const renderTemplate = createRenderTemplate({ Menu, MenuButton, MenuItems, MenuItem })

describe('Safe guards', () => {
it.each([
Expand Down
20 changes: 5 additions & 15 deletions packages/@headlessui-vue/src/components/popover/popover.test.ts
@@ -1,5 +1,5 @@
import { defineComponent, nextTick, ref, watch, h, ComponentOptionsWithoutProps } from 'vue'
import { render } from '../../test-utils/vue-testing-library'
import { createRenderTemplate, render } from '../../test-utils/vue-testing-library'

import { Popover, PopoverGroup, PopoverButton, PopoverPanel, PopoverOverlay } from './popover'
import { Portal } from '../portal/portal'
Expand Down Expand Up @@ -28,29 +28,19 @@ beforeAll(() => {

afterAll(() => jest.restoreAllMocks())

function renderTemplate(input: string | ComponentOptionsWithoutProps) {
let defaultComponents = {
function getDefaultComponents() {
return {
Popover,
PopoverGroup,
PopoverButton,
PopoverPanel,
PopoverOverlay,
Portal,
}

if (typeof input === 'string') {
return render(defineComponent({ template: input, components: defaultComponents }))
}

return render(
defineComponent(
Object.assign({}, input, {
components: { ...defaultComponents, ...input.components },
}) as Parameters<typeof defineComponent>[0]
)
)
}

const renderTemplate = createRenderTemplate(getDefaultComponents())

describe('Safe guards', () => {
it.each([
['PopoverButton', PopoverButton],
Expand Down
18 changes: 2 additions & 16 deletions packages/@headlessui-vue/src/components/portal/portal.test.ts
@@ -1,6 +1,6 @@
import { h, defineComponent, ref, nextTick, ComponentOptionsWithoutProps, createSSRApp } from 'vue'

import { render } from '../../test-utils/vue-testing-library'
import { createRenderTemplate, render } from '../../test-utils/vue-testing-library'
import { renderToString } from 'vue/server-renderer'
import { Portal, PortalGroup } from './portal'
import { click } from '../../test-utils/interactions'
Expand All @@ -23,21 +23,7 @@ beforeAll(() => {

afterAll(() => jest.restoreAllMocks())

function renderTemplate(input: string | ComponentOptionsWithoutProps) {
let defaultComponents = { Portal, PortalGroup }

if (typeof input === 'string') {
return render(defineComponent({ template: input, components: defaultComponents }))
}

return render(
defineComponent(
Object.assign({}, input, {
components: { ...defaultComponents, ...input.components },
}) as Parameters<typeof defineComponent>[0]
)
)
}
const renderTemplate = createRenderTemplate({ Portal, PortalGroup })

async function ssrRenderTemplate(input: string | ComponentOptionsWithoutProps) {
let defaultComponents = { Portal, PortalGroup }
Expand Down
@@ -1,5 +1,5 @@
import { defineComponent, nextTick, ref, watch, reactive, ComponentOptionsWithoutProps } from 'vue'
import { render } from '../../test-utils/vue-testing-library'
import { createRenderTemplate, render } from '../../test-utils/vue-testing-library'

import { RadioGroup, RadioGroupOption, RadioGroupLabel, RadioGroupDescription } from './radio-group'

Expand Down Expand Up @@ -34,21 +34,12 @@ function nextFrame() {
})
}

function renderTemplate(input: string | ComponentOptionsWithoutProps) {
let defaultComponents = { RadioGroup, RadioGroupOption, RadioGroupLabel, RadioGroupDescription }

if (typeof input === 'string') {
return render(defineComponent({ template: input, components: defaultComponents }))
}

return render(
defineComponent(
Object.assign({}, input, {
components: { ...defaultComponents, ...input.components },
}) as Parameters<typeof defineComponent>[0]
)
)
}
const renderTemplate = createRenderTemplate({
RadioGroup,
RadioGroupOption,
RadioGroupLabel,
RadioGroupDescription,
})

describe('Safe guards', () => {
it.each([['RadioGroupOption', RadioGroupOption]])(
Expand Down
18 changes: 2 additions & 16 deletions packages/@headlessui-vue/src/components/switch/switch.test.tsx
@@ -1,5 +1,5 @@
import { defineComponent, ref, watch, h, ComponentOptionsWithoutProps } from 'vue'
import { render } from '../../test-utils/vue-testing-library'
import { createRenderTemplate, render } from '../../test-utils/vue-testing-library'

import { Switch, SwitchLabel, SwitchDescription, SwitchGroup } from './switch'
import {
Expand All @@ -16,21 +16,7 @@ import { suppressConsoleLogs } from '../../test-utils/suppress-console-logs'

jest.mock('../../hooks/use-id')

function renderTemplate(input: string | ComponentOptionsWithoutProps) {
let defaultComponents = { Switch, SwitchLabel, SwitchDescription, SwitchGroup }

if (typeof input === 'string') {
return render(defineComponent({ template: input, components: defaultComponents }))
}

return render(
defineComponent(
Object.assign({}, input, {
components: { ...defaultComponents, ...input.components },
}) as Parameters<typeof defineComponent>[0]
)
)
}
const renderTemplate = createRenderTemplate({ Switch, SwitchLabel, SwitchDescription, SwitchGroup })

describe('Safe guards', () => {
it('should be possible to render a Switch without crashing', () => {
Expand Down
18 changes: 2 additions & 16 deletions packages/@headlessui-vue/src/components/tabs/tabs.test.ts
@@ -1,5 +1,5 @@
import { ComponentOptionsWithoutProps, defineComponent, nextTick, ref } from 'vue'
import { render } from '../../test-utils/vue-testing-library'
import { createRenderTemplate, render } from '../../test-utils/vue-testing-library'
import { TabGroup, TabList, Tab, TabPanels, TabPanel } from './tabs'
import { suppressConsoleLogs } from '../../test-utils/suppress-console-logs'
import {
Expand All @@ -20,21 +20,7 @@ beforeAll(() => {

afterAll(() => jest.restoreAllMocks())

function renderTemplate(input: string | ComponentOptionsWithoutProps) {
let defaultComponents = { TabGroup, TabList, Tab, TabPanels, TabPanel }

if (typeof input === 'string') {
return render(defineComponent({ template: input, components: defaultComponents }))
}

return render(
defineComponent(
Object.assign({}, input, {
components: { ...defaultComponents, ...input.components },
}) as Parameters<typeof defineComponent>[0]
)
)
}
const renderTemplate = createRenderTemplate({ TabGroup, TabList, Tab, TabPanels, TabPanel })

describe('safeguards', () => {
it.each([
Expand Down

0 comments on commit 70333a9

Please sign in to comment.