Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"type": "minor",
"comment": "feat: exports getIntrinsicElementProps method",
"packageName": "@fluentui/react-components",
"email": "[email protected]",
"dependentChangeType": "patch"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"type": "minor",
"comment": "feat: creates getIntrinsicElementProps to replace getNativeElementProps on slots creation",
"packageName": "@fluentui/react-utilities",
"email": "[email protected]",
"dependentChangeType": "patch"
}
Original file line number Diff line number Diff line change
Expand Up @@ -295,6 +295,7 @@ import { FontFamilyTokens } from '@fluentui/react-theme';
import { FontSizeTokens } from '@fluentui/react-theme';
import { FontWeightTokens } from '@fluentui/react-theme';
import { ForwardRefComponent } from '@fluentui/react-utilities';
import { getIntrinsicElementProps } from '@fluentui/react-utilities';
import { getNativeElementProps } from '@fluentui/react-utilities';
import { getPartitionedNativeProps } from '@fluentui/react-utilities';
import { getSlots } from '@fluentui/react-utilities';
Expand Down Expand Up @@ -1776,6 +1777,8 @@ export { FontWeightTokens }

export { ForwardRefComponent }

export { getIntrinsicElementProps }

export { getNativeElementProps }

export { getPartitionedNativeProps }
Expand Down
1 change: 1 addition & 0 deletions packages/react-components/react-components/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ export {
} from '@fluentui/react-shared-contexts';
export {
getNativeElementProps,
getIntrinsicElementProps,
getPartitionedNativeProps,
getSlots,
slot,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,14 +46,17 @@ export type FluentTriggerComponent = {
};

// @public
export type ForwardRefComponent<Props> = ObscureEventName extends keyof Props ? Required<Props>[ObscureEventName] extends React_2.PointerEventHandler<infer Element> ? React_2.ForwardRefExoticComponent<Props & React_2.RefAttributes<Element>> : never : never;
export type ForwardRefComponent<Props> = React_2.ForwardRefExoticComponent<Props & React_2.RefAttributes<InferredElementRefType<Props>>>;

// @public
export function getEventClientCoords(event: TouchOrMouseEvent): {
clientX: number;
clientY: number;
};

// @public
export const getIntrinsicElementProps: <Props extends UnknownSlotProps, ExcludedPropKeys extends Extract<keyof Props, string> = never>(tagName: NonNullable<Props["as"]>, props: Props & React_2.RefAttributes<InferredElementRefType<Props>>, excludedPropNames?: ExcludedPropKeys[] | undefined) => OmitWithoutExpanding<Props, ExcludedPropKeys | Exclude<keyof Props, "as" | keyof HTMLAttributes>>;

// @public
export function getNativeElementProps<TAttributes extends React_2.HTMLAttributes<any>>(tagName: string, props: {}, excludedPropNames?: string[]): TAttributes;

Expand Down Expand Up @@ -93,6 +96,9 @@ export function getTriggerChild<TriggerChildProps>(children: TriggerProps<Trigge
// @public
export const IdPrefixProvider: React_2.Provider<string | undefined>;

// @public
export type InferredElementRefType<Props> = ObscureEventName extends keyof Props ? Required<Props>[ObscureEventName] extends React_2.PointerEventHandler<infer Element> ? Element : never : never;

// @internal
export function isFluentTrigger(element: React_2.ReactElement): element is React_2.ReactElement<TriggerProps>;

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import * as React from 'react';
import { getNativeElementProps } from '../utils/getNativeElementProps';
import type { InferredElementRefType, UnknownSlotProps } from './types';

// eslint-disable-next-line @typescript-eslint/no-explicit-any
type HTMLAttributes = React.HTMLAttributes<any>;

/**
* Given an element tagname and user props, filters the props to only allowed props for the given
* element type.
*
* Equivalent to {@link getNativeElementProps}, but more type-safe.
*/
export const getIntrinsicElementProps = <
Props extends UnknownSlotProps,
ExcludedPropKeys extends Extract<keyof Props, string> = never,
>(
/** The slot's default element type (e.g. 'div') */
tagName: NonNullable<Props['as']>,
/** The component's props object */
props: Props & React.RefAttributes<InferredElementRefType<Props>>,
/** List of native props to exclude from the returned value */
excludedPropNames?: ExcludedPropKeys[],
) => {
return getNativeElementProps<
OmitWithoutExpanding<Props, Exclude<keyof Props, keyof HTMLAttributes | keyof UnknownSlotProps> | ExcludedPropKeys>
>(props.as ?? tagName, props, excludedPropNames);
};

/**
* helper type that avoids the expansion of unions while inferring it,
* should work exactly the same as Omit
*/
type OmitWithoutExpanding<P, K extends string | number | symbol> = P extends unknown ? Omit<P, K> : P;
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ export * from './constants';
export * from './getSlotsNext';
export * from './isSlot';
export * from './assertSlots';
export * from './getIntrinsicElementProps';

export { slot };
export type { SlotOptions } from './slot';
13 changes: 10 additions & 3 deletions packages/react-components/react-utilities/src/compose/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -215,13 +215,20 @@ export type ComponentState<Slots extends SlotPropsRecord> = {
type ObscureEventName = 'onLostPointerCaptureCapture';

/**
* Return type for `React.forwardRef`, including inference of the proper typing for the ref.
* Infers the element type from props that are declared using ComponentProps.
*/
export type ForwardRefComponent<Props> = ObscureEventName extends keyof Props
export type InferredElementRefType<Props> = ObscureEventName extends keyof Props
? Required<Props>[ObscureEventName] extends React.PointerEventHandler<infer Element>
? React.ForwardRefExoticComponent<Props & React.RefAttributes<Element>>
? Element
: never
: never;

/**
* Return type for `React.forwardRef`, including inference of the proper typing for the ref.
*/
export type ForwardRefComponent<Props> = React.ForwardRefExoticComponent<
Props & React.RefAttributes<InferredElementRefType<Props>>
>;
// A definition like this would also work, but typescript is more likely to unnecessarily expand
// the props type with this version (and it's likely much more expensive to evaluate)
// export type ForwardRefComponent<Props> = Props extends React.DOMAttributes<infer Element>
Expand Down
2 changes: 2 additions & 0 deletions packages/react-components/react-utilities/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ export {
assertSlots,
resolveShorthand,
isResolvedShorthand,
getIntrinsicElementProps,
SLOT_ELEMENT_TYPE_SYMBOL,
SLOT_RENDER_FUNCTION_SYMBOL,
} from './compose/index';
Expand All @@ -25,6 +26,7 @@ export type {
UnknownSlotProps,
SlotComponentType,
SlotOptions,
InferredElementRefType,
} from './compose/index';

export {
Expand Down