Fix error when transition classes contain new lines (#2871)

* fix DOMException when remove class with '\n' character in react 'transition' component

* Split classes on all whitespace

* Revert "fix DOMException when remove class with '\n' character in react 'transition' component"

This reverts commit 76e835441b9cb84a1d867e1a37496c55cae86179.

* fix typo

* Add test

* Fix CS

* Update changelog

---------

Co-authored-by: Jordan Pittman <jordan@cryptica.me>
This commit is contained in:
Евгений
2023-12-13 00:09:55 +04:00
committed by GitHub
parent c25e2e6036
commit c24ba868bd
5 changed files with 69 additions and 2 deletions
+1
View File
@@ -19,6 +19,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Fix infinite render-loop for `<Disclosure.Panel>` and `<Popover.Panel>` when `as={Fragment}` ([#2760](https://github.com/tailwindlabs/headlessui/pull/2760))
- Fix VoiceOver bug for `Listbox` component in Chrome ([#2824](https://github.com/tailwindlabs/headlessui/pull/2824))
- Fix outside click detection when component is mounted in the Shadow DOM ([#2866](https://github.com/tailwindlabs/headlessui/pull/2866))
- Fix error when transition classes contain new lines ([#2871](https://github.com/tailwindlabs/headlessui/pull/2871))
### Added
@@ -1,6 +1,8 @@
import { act as _act, fireEvent, render } from '@testing-library/react'
import React, { Fragment, useEffect, useLayoutEffect, useRef, useState } from 'react'
import { getByText } from '../../test-utils/accessibility-assertions'
import { executeTimeline } from '../../test-utils/execute-timeline'
import { click } from '../../test-utils/interactions'
import { createSnapshot } from '../../test-utils/snapshot'
import { suppressConsoleLogs } from '../../test-utils/suppress-console-logs'
import { Transition } from './transition'
@@ -402,6 +404,57 @@ describe('Setup API', () => {
})
describe('transition classes', () => {
it('should support new lines in class lists', async () => {
function Example() {
let [show, setShow] = useState(true)
return (
<div>
<button onClick={() => setShow((v) => !v)}>toggle</button>
<Transition show={show} as="div" className={`foo1\nfoo2`} enter="enter" leave="leave">
Children
</Transition>
</div>
)
}
let { container } = await act(() => render(<Example />))
expect(container.firstChild).toMatchInlineSnapshot(`
<div>
<button>
toggle
</button>
<div
class="foo1
foo2"
>
Children
</div>
</div>
`)
await click(getByText('toggle'))
// TODO: This is not quite right
// The `foo1\nfoo2` should be gone
// I think this is a qurk of JSDOM
expect(container.firstChild).toMatchInlineSnapshot(`
<div>
<button>
toggle
</button>
<div
class="foo1
foo2 foo1 foo2 leave"
>
Children
</div>
</div>
`)
})
it('should be possible to passthrough the transition classes', () => {
let { container } = render(
<Transition
@@ -37,8 +37,14 @@ type ContainerElement = MutableRefObject<HTMLElement | null>
type TransitionDirection = 'enter' | 'leave' | 'idle'
/**
* Split class lists by whitespace
*
* We can't check for just spaces as all whitespace characters are
* invalid in a class name, so we have to split on ANY whitespace.
*/
function splitClasses(classes: string = '') {
return classes.split(' ').filter((className) => className.trim().length > 1)
return classes.split(/\s+/).filter((className) => className.length > 1)
}
interface TransitionContextValues {
+1
View File
@@ -19,6 +19,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Fix missing `data-headlessui-state` attribute when `as="template"` ([#2787](https://github.com/tailwindlabs/headlessui/pull/2787))
- Fix VoiceOver bug for `Listbox` component in Chrome ([#2824](https://github.com/tailwindlabs/headlessui/pull/2824))
- Fix outside click detection when component is mounted in the Shadow DOM ([6846231](https://github.com/tailwindlabs/headlessui/commit/684623131b99d9e75dfc1c1f6d27244c334a95d9))
- Fix error when transition classes contain new lines ([#2871](https://github.com/tailwindlabs/headlessui/pull/2871))
### Added
@@ -29,8 +29,14 @@ import { Reason, transition } from './utils/transition'
type ID = ReturnType<typeof useId>
/**
* Split class lists by whitespace
*
* We can't check for just spaces as all whitespace characters are
* invalid in a class name, so we have to split on ANY whitespace.
*/
function splitClasses(classes: string = '') {
return classes.split(' ').filter((className) => className.trim().length > 1)
return classes.split(/\s+/).filter((className) => className.length > 1)
}
interface TransitionContextValues {