Properly merge incoming props (#1265)

* rename inconsistent `passThroughProps` and `passthroughProps` to more
concise `incomingProps`

This is going to make a bit more sense in the next commits of this
branch, hold on!

* split props into `propsWeControl` and `propsTheyControl`

This will allow us to merge the props with a bit more control. Instead
of overriding every prop from the user' props with our props, we can now
merge event listeners.

* update `render` API to accept `propsWeControl` and `propsTheyControl`

* improve the merge logic

This will essentially do the exact same thing we were doing before:
```js
let props = { ...propsTheyControl, ...propsWeControl }
```

But instead of overriding everything, we will merge the event listener
related props like `onClick`, `onKeyDown`, ...

* fix typo in tests

* simplify naming

- Rename `propsWeControl` to `ourProps`
- Rename `propsTheyControl` to `theirProps`

* update changelog
This commit is contained in:
Robin Malfait
2022-03-22 17:32:11 +01:00
committed by GitHub
parent 4f8c615245
commit 3e19aa5c97
37 changed files with 398 additions and 283 deletions
@@ -88,22 +88,28 @@ export let Label = forwardRefWithAs(function Label<
},
ref: Ref<HTMLLabelElement>
) {
let { passive = false, ...passThroughProps } = props
let { passive = false, ...theirProps } = props
let context = useLabelContext()
let id = `headlessui-label-${useId()}`
let labelRef = useSyncRefs(ref)
useIsoMorphicEffect(() => context.register(id), [id, context.register])
let propsWeControl = { ref: labelRef, ...context.props, id }
let ourProps = { ref: labelRef, ...context.props, id }
let allProps = { ...passThroughProps, ...propsWeControl }
// @ts-expect-error props are dynamic via context, some components will
// provide an onClick then we can delete it.
if (passive) delete allProps['onClick']
if (passive) {
if ('onClick' in ourProps) {
delete (ourProps as any)['onClick']
}
if ('onClick' in theirProps) {
delete (theirProps as any)['onClick']
}
}
return render({
props: allProps,
ourProps,
theirProps,
slot: context.slot || {},
defaultTag: DEFAULT_LABEL_TAG,
name: context.name || 'Label',