Commit Graph

3 Commits

Author SHA1 Message Date
Robin Malfait e662f12398 2.0.0 Alpha prep (#2887)
* bump React & React DOM dependencies

* fix typo `TOmitableProps` → `TOmittableProps`

* bump prettier

* run prettier after prettier version bump

* bump TypeScript

* run prettier after TypeScript version bump

* enable `verbatimModuleSyntax`

This ensures all imported types are using the `type` keyword.

* add `type` to type related imports

* add common testing scenarios

Will be used in the new and existing components.

* add script to make Next.js happy

Right now Next.js does barrel file optimization and re-writing imports
to a real path in the `dist` folder. Most of those rewrites don't
actually exist because they have an assumption:

```js
import { FooBar } from '@headlessui/react'
```

is rewritten as:
```js
import { FooBar } from '@headlessui/react/dist/components/foo-bar/foo-bar'
```

This script will make sure these paths exist...

* improve `by` prop, introduce `useByComparator`

This hook has a default implementation when comparing objects. If the
object contains an `id`, then we will compare the objects by their
`id`'s without the user of the library needing to specify `by="id"`.

If the objects don't have an `id` prop, then the default is still to
compare by reference (unless specicified otherwise).

* sync yarn.lock

* rename `Features` to `HiddenFeatures` for `Hidden` component

* rename `Features` to `FocusTrapFeatures` in `FocusTrap` component

* rename `Features` to `RenderFeatures` in `render` util

* add `floating-ui` as a dependency + introduce internal floating related components

* bump Vue dependencies

* ensure scroll bar calculations can't go negative

* improve types in `@headlessui/vue`

* use snapshot tests for `Transition` tests in `@headlessui/vue`

* use snapshot tests for `portal` tests in `@headlessui/vue`

* rename `src/components/transitions/` to `src/components/transition/` (singular)

This is so that we can be consistent with the other components.

* drop custom `toMatchFormattedCss`, prefer snapshot tests instead

* use snapshot tests for `Label` tests in `@headlessui/vue`

* use snapshot tests for `Description` tests in `@headlessui/vue`

* sort exported components in tests for `@headlessui/vue`

* use snapshot tests in `@headlessui/tailwindcss`

* rename `mergeProps` to `mergePropsAdvanced`

This is a more complex version of a soon to be exported `mergeProps`
that we will be using in our components.

* do not expose `aria-labelledby` if it is only referencing itself

* expose boolean state as `kebab-case` instead of `camelCase`

These are the ones being exposed inside `data-headlessui-state="..."`

* expose boolean data attributes

A slot with `{active,focus,hover}` will be exposed as:
```html
<span data-headlessui-state="active focus hover"></span>
```

But also as boolean attributes:
```html
<span data-active data-focus data-hover></span>
```

* improve internal types for `className` in `render` util

* ensure we keep exposed data attributes into account when trying to forward them to the component inside the `Fragment`

* add small typescript type fix

This is internal code, and the public API is not influenced by this
`:any`. It does make TypeScript happy.

* introduce `mergeProps` util to be used in our components

This will help us to merge props, when event handlers are available they
will be merged by wrapping them in a function such that both (or more)
event handlers are called for the same `event`.

* add new internal `Modal` component

* fix: when using `Focus.Previous` with `activeIndex = -1` should start at the end

* prefer `window.scrollY` instead of `window.pageYOffset`

Because `window.pageYOffset` is deprecated.

* add `'use client'` directives on client only components

These components use hooks that won't work in server components and you
will receive an error otherwise.

* drop `import 'client-only'` in favor of the `'use client'` directive

* add React Aria dependencies

* pin beta dependencies

* prettier bump formatting

* improve TypeScript types in tests

* use new Jest matchers instead of deprecated ones

* improve typescript types in Vue

* prefer `useLabelledBy` and `useDescribedBy`

* add internal `DisabledProvider`

* add internal `IdProvider`

* add internal `useDidElementMove` hook

* add internal `useElementSize` hook

* add internal `useIsTouchDevice` hook

* add internal `useActivePress` hook

* use snapshot tests for `Description` tests

* use snapshot tests for `Label` tests

* use snapshot tests for `Portal` tests

* use snapshot tests for `render` tests

* add (private) `Tooltip` component

Currently this one is not ready yet, so its not publicly exposed yet.

* add internal `FormFields` component

This one adds a component to render (hidden) inputs for native form
support. It also ensures that form fields can be hoisted to the end of
the nearest `Field`. If the components are not inside a `Field` they
will be rendered in place.

* add new `Button` component

* add new `Checkbox` component

* add new `DataInteractive` component

* add new `Field` component

* add new `Fieldset` component

* add new `Legend` component

* add new `Input` component

* add new `Select` component

* add new `Textarea` component

* export new components

* WIP

* remove `within: true`

This only makes sense if anything inside the current element receives
focus, which is not the case for `input`, `select`, `textarea` or
`Radio/RadioOption`.

* group focus/hover/active hooks together

* conditionally link anchor panel

* immediately focus the container

* prevent premature disabling of `Listbox`'s floating integration

+ Track whether the button moved or not when disabling such that we can
  disable the transitions earlier.

* improve scroll locking on iOS

* skip hydration tests for now

* skip certain focus trap tests for now

* update CHANGELOG.md

* add missing requires

* drop unused `@ts-expect-error`

* ignore type issues in playgrounds

These playgrounds are mainly test playgrounds. Lower priority for now,
we will get back to them.

* add yarn resolutions to solve swc bug
2023-12-20 19:57:57 +01:00
Robin Malfait f016dc51db Add virtual prop to Combobox component (#2740)
* type timezones in playground data

* add `@tanstack/react-virtual` and `@tanstack/vue-virtual`

* use latest stable Tailwind CSS version

* add Combobox with virtual prop example

* add `virtual` prop to `Combobox`

Co-authored-by: Jordan Pittman <jordan@cryptica.me>

* add tests for `virtual` prop

- Also wrap `click` helpers in `act` for React (use `rawClick` without
  `act` in tests related to `Transition`)

* update changelog

---------

Co-authored-by: Jordan Pittman <jordan@cryptica.me>
2023-09-15 14:29:18 +02:00
Robin Malfait 17b2d34fe6 Improve performance of Combobox component (#2574)
* add countries data and combobox example

* directly push to the options array

No need to spread here because this will slow things down tremendously.
If you add 5 options, then this will happen:

```js
let options = []
options = [...options, 1]
options = [...options, 2]
options = [...options, 3]
options = [...options, 4]
options = [...options, 5]
```

It's making a lot of copies and has to spread everything it just copied
again. Instead, let's just push to the array:

```js
let options = []
options.push(1)
options.push(2)
options.push(3)
options.push(4)
options.push(5)
```

* only sort options by DOM node once

When registering 50 options, we will re-sort the options based on the DOM
node position for every option that gets registered. This is overkill
and unnecessary. The re-sorting is useful if an option is injected
between 2 options. When we sort the full list for _every_ `registerOption`
call then the result after the last `registerOption` will be the same if
we only sorted after the last `registerOption` call only.

This will ensure that we are skipping a ton of work and only do the work
once at the end where it matters.

* debounce the `goToOption` call until the next frame

This will allow us to perform the task of `goToOption` once instead of
`n` times if they happen really fast after eachother.

This can happen when you are leaving option B and going to option A.
Then the following steps happen:

- Leaving Option B `goToOption(Nothing)`
- Entering Option A `goToOption(A)`

Both will re-render everything because the internal active option index
would be changed. But only the last `goToOption(A)` is the interesting
version here.

We could also move the `goToOption(Nothing)` to the `ComboboxOptions`
(wrapper) itself instead of adding these listeners on each individual
`ComboboxOption`. However, if you add an additional visual piece of DOM
above or between the options, hovering that would not leave the
`ComboboxOptions` and therefore the last `ComboboxOption` would still be
active which we don't want.

* update changelog
2023-07-05 11:10:19 +02:00