Private
Public Access
1
0

feat: Fluent UI Outlook Lite + connections mockup

This commit is contained in:
2026-04-14 18:52:25 +00:00
parent 1199eff6c3
commit dfa4010406
34820 changed files with 1003813 additions and 205 deletions

View File

@@ -0,0 +1,64 @@
import * as React from 'react';
import { SLOT_ELEMENT_TYPE_SYMBOL } from './constants';
import { isSlot } from './isSlot';
import * as slot from './slot';
/**
* @internal
* Assertion method to ensure state slots properties are properly declared.
* A properly declared slot must be declared by using the `slot` method.
*
* @example
* ```tsx
* export const renderInput_unstable = (state: InputState): JSXElement => {
assertSlots<InputSlots>(state);
return (
<state.root>
{state.contentBefore && <state.contentBefore />}
<state.input />
{state.contentAfter && <state.contentAfter />}
</state.root>
);
};
* ```
*/ export function assertSlots(state) {
/**
* This verification is not necessary in production
* as we're verifying static properties that will not change between environments
*/ if (process.env.NODE_ENV !== 'production') {
const typedState = state;
// eslint-disable-next-line @typescript-eslint/no-deprecated
for (const slotName of Object.keys(typedState.components)){
const slotElement = typedState[slotName];
if (slotElement === undefined) {
continue;
}
// this means a slot is being declared without using, slot.always or slot.optional or even resolveShorthand on the state hook,
// but the render method is using the new `assertSlots` method. That scenario can be solved by simply updating the slot element with the proper element type
// FIXME: this slot will still fail to support child render function scenario
if (!isSlot(slotElement)) {
typedState[slotName] = slot.always(slotElement, {
// eslint-disable-next-line @typescript-eslint/no-deprecated
elementType: typedState.components[slotName]
});
// eslint-disable-next-line no-console
console.warn(`@fluentui/react-utilities [${assertSlots.name}]:
"state.${slotName}" is not a slot!
Be sure to create slots properly by using "slot.always" or "slot.optional".`);
} else {
// This means a slot is being declared by using resolveShorthand on the state hook,
// but the render method is using the new `assertSlots` method. That scenario can be solved by simply updating the slot element with the proper element type
const { [SLOT_ELEMENT_TYPE_SYMBOL]: elementType } = slotElement;
// eslint-disable-next-line @typescript-eslint/no-deprecated
if (elementType !== typedState.components[slotName]) {
// eslint-disable-next-line @typescript-eslint/no-deprecated
slotElement[SLOT_ELEMENT_TYPE_SYMBOL] = typedState.components[slotName];
// eslint-disable-next-line no-console
console.warn(`@fluentui/react-utilities [${assertSlots.name}]:
"state.${slotName}" element type differs from "state.components.${slotName}",
${elementType} !== ${typedState.components[slotName]}.
Be sure to create slots properly by using "slot.always" or "slot.optional" with the correct elementType.`);
}
}
}
}
}

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,12 @@
/**
* @internal
* Internal reference for the render function
*/ export const SLOT_RENDER_FUNCTION_SYMBOL = Symbol.for('fui.slotRenderFunction');
/**
* @internal
* Internal reference for the render function
*/ export const SLOT_ELEMENT_TYPE_SYMBOL = Symbol.for('fui.slotElementType');
/**
* @internal
* Internal cache of the original className prop for the slot, before being modified by the useStyles hook.
*/ export const SLOT_CLASS_NAME_PROP_SYMBOL = Symbol.for('fui.slotClassNameProp');

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../src/compose/constants.ts"],"sourcesContent":["/**\n * @internal\n * Internal reference for the render function\n */\nexport const SLOT_RENDER_FUNCTION_SYMBOL = Symbol.for('fui.slotRenderFunction');\n/**\n * @internal\n * Internal reference for the render function\n */\nexport const SLOT_ELEMENT_TYPE_SYMBOL = Symbol.for('fui.slotElementType');\n/**\n * @internal\n * Internal cache of the original className prop for the slot, before being modified by the useStyles hook.\n */\nexport const SLOT_CLASS_NAME_PROP_SYMBOL = Symbol.for('fui.slotClassNameProp');\n"],"names":["SLOT_RENDER_FUNCTION_SYMBOL","Symbol","for","SLOT_ELEMENT_TYPE_SYMBOL","SLOT_CLASS_NAME_PROP_SYMBOL"],"mappings":"AAAA;;;CAGC,GACD,OAAO,MAAMA,8BAA8BC,OAAOC,GAAG,CAAC,0BAA0B;AAChF;;;CAGC,GACD,OAAO,MAAMC,2BAA2BF,OAAOC,GAAG,CAAC,uBAAuB;AAC1E;;;CAGC,GACD,OAAO,MAAME,8BAA8BH,OAAOC,GAAG,CAAC,yBAAyB"}

View File

@@ -0,0 +1,75 @@
import * as React from 'react';
import { omit } from '../../utils/omit';
import { isSlot } from '../isSlot';
import { SLOT_RENDER_FUNCTION_SYMBOL } from '../constants';
/**
* Given the state and an array of slot names, will break out `slots` and `slotProps`
* collections.
*
* The root is derived from a mix of `components` props and `as` prop.
*
* Slots will render as null if they are rendered as primitives with undefined children.
*
* The slotProps will always omit the `as` prop within them, and for slots that are string
* primitives, the props will be filtered according to the slot type by the type system.
* For example, if the slot is rendered `as: 'a'`, the props will be filtered for acceptable
* anchor props. Note that this is only enforced at build time by Typescript -- there is no
* runtime code filtering props in this function.
*
* @deprecated use slot.always or slot.optional combined with assertSlots instead
*
* @param state - State including slot definitions
* @returns An object containing the `slots` map and `slotProps` map.
*/ export function getSlots(state) {
const typeState = state;
// eslint-disable-next-line @typescript-eslint/no-deprecated
const slots = {};
const slotProps = {};
// eslint-disable-next-line @typescript-eslint/no-deprecated
const slotNames = Object.keys(typeState.components);
for (const slotName of slotNames){
const [slot, props] = getSlot(typeState, slotName);
// eslint-disable-next-line @typescript-eslint/no-deprecated
slots[slotName] = slot;
slotProps[slotName] = props;
}
// eslint-disable-next-line @typescript-eslint/no-deprecated
return {
slots,
slotProps: slotProps
};
}
function getSlot(state, slotName) {
var _state_components, _state_components1;
const props = state[slotName];
if (props === undefined) {
return [
null,
undefined
];
}
// TS Error: Property 'as' does not exist on type 'UnknownSlotProps | undefined'.ts(2339)
const { as: asProp, children, ...rest } = props;
const renderFunction = isSlot(props) ? props[SLOT_RENDER_FUNCTION_SYMBOL] : undefined;
const slot = ((_state_components = state.components) === null || _state_components === void 0 ? void 0 : _state_components[slotName]) === undefined || // eslint-disable-line @typescript-eslint/no-deprecated
// eslint-disable-next-line @typescript-eslint/no-deprecated
typeof state.components[slotName] === 'string' ? asProp || ((_state_components1 = state.components) === null || _state_components1 === void 0 ? void 0 : _state_components1[slotName]) || 'div' : state.components[slotName];
const asserted = slot;
if (renderFunction || typeof children === 'function') {
const render = renderFunction || children;
return [
React.Fragment,
{
children: render(asserted, rest)
}
];
}
const shouldOmitAsProp = typeof slot === 'string' && asProp;
const slotProps = shouldOmitAsProp ? omit(props, [
'as'
]) : props;
return [
asserted,
slotProps
];
}

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,53 @@
import * as React from 'react';
/**
* Similar to `getSlots`, main difference is that it's compatible with new custom jsx pragma
*
* @internal
* This is an internal temporary method, this method will cease to exist eventually!
*
* * ❗️❗️ **DO NOT USE IT EXTERNALLY** ❗️❗️
*
* @deprecated use slot.always or slot.optional combined with assertSlots instead
*/ export function getSlotsNext(state) {
const typedState = state;
// eslint-disable-next-line @typescript-eslint/no-deprecated
const slots = {};
const slotProps = {};
// eslint-disable-next-line @typescript-eslint/no-deprecated
const slotNames = Object.keys(typedState.components);
for (const slotName of slotNames){
// eslint-disable-next-line @typescript-eslint/no-deprecated
const [slot, props] = getSlotNext(typedState, slotName);
// eslint-disable-next-line @typescript-eslint/no-deprecated
slots[slotName] = slot;
slotProps[slotName] = props;
}
// eslint-disable-next-line @typescript-eslint/no-deprecated
return {
slots,
slotProps: slotProps
};
}
/**
* @deprecated use slot.always or slot.optional combined with assertSlots instead
*/ function getSlotNext(state, slotName) {
var _state_components, _state_components1;
const props = state[slotName];
if (props === undefined) {
return [
null,
undefined
];
}
// TS Error: Property 'as' does not exist on type 'UnknownSlotProps | undefined'.ts(2339)
const { as: asProp, ...propsWithoutAs } = props;
const slot = ((_state_components = state.components) === null || _state_components === void 0 ? void 0 : _state_components[slotName]) === undefined || // eslint-disable-line @typescript-eslint/no-deprecated
// eslint-disable-next-line @typescript-eslint/no-deprecated
typeof state.components[slotName] === 'string' ? asProp || ((_state_components1 = state.components) === null || _state_components1 === void 0 ? void 0 : _state_components1[slotName]) || 'div' : state.components[slotName];
const shouldOmitAsProp = typeof slot === 'string' && asProp;
const slotProps = shouldOmitAsProp ? propsWithoutAs : props;
return [
slot,
slotProps
];
}

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../src/compose/deprecated/getSlotsNext.ts"],"sourcesContent":["import * as React from 'react';\nimport type { ComponentState, SlotPropsRecord, UnknownSlotProps } from '../types';\nimport { ObjectSlotProps, Slots } from './getSlots';\n\n/**\n * Similar to `getSlots`, main difference is that it's compatible with new custom jsx pragma\n *\n * @internal\n * This is an internal temporary method, this method will cease to exist eventually!\n *\n * * ❗️❗️ **DO NOT USE IT EXTERNALLY** ❗️❗️\n *\n * @deprecated use slot.always or slot.optional combined with assertSlots instead\n */\nexport function getSlotsNext<R extends SlotPropsRecord>(\n state: unknown,\n): {\n // eslint-disable-next-line @typescript-eslint/no-deprecated\n slots: Slots<R>;\n // eslint-disable-next-line @typescript-eslint/no-deprecated\n slotProps: ObjectSlotProps<R>;\n} {\n const typedState = state as ComponentState<R>;\n // eslint-disable-next-line @typescript-eslint/no-deprecated\n const slots = {} as Slots<R>;\n const slotProps = {} as R;\n\n // eslint-disable-next-line @typescript-eslint/no-deprecated\n const slotNames: (keyof R)[] = Object.keys(typedState.components);\n for (const slotName of slotNames) {\n // eslint-disable-next-line @typescript-eslint/no-deprecated\n const [slot, props] = getSlotNext(typedState, slotName);\n // eslint-disable-next-line @typescript-eslint/no-deprecated\n slots[slotName] = slot as Slots<R>[typeof slotName];\n slotProps[slotName] = props;\n }\n // eslint-disable-next-line @typescript-eslint/no-deprecated\n return { slots, slotProps: slotProps as unknown as ObjectSlotProps<R> };\n}\n\n/**\n * @deprecated use slot.always or slot.optional combined with assertSlots instead\n */\nfunction getSlotNext<R extends SlotPropsRecord, K extends keyof R>(\n state: ComponentState<R>,\n slotName: K,\n): readonly [React.ElementType<R[K]> | null, R[K]] {\n const props = state[slotName];\n\n if (props === undefined) {\n return [null, undefined as R[K]];\n }\n\n type NonUndefined<T> = T extends undefined ? never : T;\n // TS Error: Property 'as' does not exist on type 'UnknownSlotProps | undefined'.ts(2339)\n const { as: asProp, ...propsWithoutAs } = props as NonUndefined<typeof props>;\n\n const slot = (\n state.components?.[slotName] === undefined || // eslint-disable-line @typescript-eslint/no-deprecated\n // eslint-disable-next-line @typescript-eslint/no-deprecated\n typeof state.components[slotName] === 'string'\n ? // eslint-disable-next-line @typescript-eslint/no-deprecated\n asProp || state.components?.[slotName] || 'div'\n : // eslint-disable-next-line @typescript-eslint/no-deprecated\n state.components[slotName]\n ) as React.ElementType<R[K]>;\n\n const shouldOmitAsProp = typeof slot === 'string' && asProp;\n const slotProps: UnknownSlotProps = shouldOmitAsProp ? propsWithoutAs : props;\n\n return [slot as React.ElementType<R[K]>, slotProps as R[K]];\n}\n"],"names":["React","getSlotsNext","state","typedState","slots","slotProps","slotNames","Object","keys","components","slotName","slot","props","getSlotNext","undefined","as","asProp","propsWithoutAs","shouldOmitAsProp"],"mappings":"AAAA,YAAYA,WAAW,QAAQ;AAI/B;;;;;;;;;CASC,GACD,OAAO,SAASC,aACdC,KAAc;IAOd,MAAMC,aAAaD;IACnB,4DAA4D;IAC5D,MAAME,QAAQ,CAAC;IACf,MAAMC,YAAY,CAAC;IAEnB,4DAA4D;IAC5D,MAAMC,YAAyBC,OAAOC,IAAI,CAACL,WAAWM,UAAU;IAChE,KAAK,MAAMC,YAAYJ,UAAW;QAChC,4DAA4D;QAC5D,MAAM,CAACK,MAAMC,MAAM,GAAGC,YAAYV,YAAYO;QAC9C,4DAA4D;QAC5DN,KAAK,CAACM,SAAS,GAAGC;QAClBN,SAAS,CAACK,SAAS,GAAGE;IACxB;IACA,4DAA4D;IAC5D,OAAO;QAAER;QAAOC,WAAWA;IAA2C;AACxE;AAEA;;CAEC,GACD,SAASQ,YACPX,KAAwB,EACxBQ,QAAW;QAaTR,mBAIcA;IAfhB,MAAMU,QAAQV,KAAK,CAACQ,SAAS;IAE7B,IAAIE,UAAUE,WAAW;QACvB,OAAO;YAAC;YAAMA;SAAkB;IAClC;IAGA,yFAAyF;IACzF,MAAM,EAAEC,IAAIC,MAAM,EAAE,GAAGC,gBAAgB,GAAGL;IAE1C,MAAMD,OACJT,EAAAA,oBAAAA,MAAMO,UAAU,cAAhBP,wCAAAA,iBAAkB,CAACQ,SAAS,MAAKI,aAAa,uDAAuD;IACrG,4DAA4D;IAC5D,OAAOZ,MAAMO,UAAU,CAACC,SAAS,KAAK,WAElCM,YAAUd,qBAAAA,MAAMO,UAAU,cAAhBP,yCAAAA,kBAAkB,CAACQ,SAAS,KAAI,QAE1CR,MAAMO,UAAU,CAACC,SAAS;IAGhC,MAAMQ,mBAAmB,OAAOP,SAAS,YAAYK;IACrD,MAAMX,YAA8Ba,mBAAmBD,iBAAiBL;IAExE,OAAO;QAACD;QAAiCN;KAAkB;AAC7D"}

View File

@@ -0,0 +1,17 @@
import * as slot from '../slot';
/**
*
* Resolves shorthands into slot props, to ensure normalization of the signature
* being passed down to getSlots method
* @param value - the base shorthand props
* @param options - options to resolve shorthand props
*
* @deprecated use slot.always, slot.optional, slot.resolveShorthand combined with assertSlots instead
*/ // eslint-disable-next-line @typescript-eslint/no-deprecated
export const resolveShorthand = (value, options)=>slot.optional(value, {
...options,
renderByDefault: options === null || options === void 0 ? void 0 : options.required,
// elementType as undefined is the way to identify between a slot and a resolveShorthand call
// in the case elementType is undefined assertSlots will fail, ensuring it'll only work with slot method.
elementType: undefined
});

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../src/compose/deprecated/resolveShorthand.ts"],"sourcesContent":["import * as slot from '../slot';\nimport type { UnknownSlotProps, SlotShorthandValue, WithoutSlotRenderFunction } from '../types';\n\n/**\n * @deprecated - use slot.always or slot.optional combined with assertSlots instead\n */\nexport type ResolveShorthandOptions<Props, Required extends boolean = false> = Required extends true\n ? { required: true; defaultProps?: Props }\n : { required?: Required; defaultProps?: Props };\n\n/**\n * @deprecated use slot.always or slot.optional combined with assertSlots instead\n */\nexport type ResolveShorthandFunction<Props extends UnknownSlotProps = UnknownSlotProps> = {\n <P extends Props>(\n value: P | SlotShorthandValue | undefined,\n // eslint-disable-next-line @typescript-eslint/no-deprecated\n options: ResolveShorthandOptions<P, true>,\n ): WithoutSlotRenderFunction<P>;\n // eslint-disable-next-line @typescript-eslint/no-deprecated\n <P extends Props>(value: P | SlotShorthandValue | null | undefined, options?: ResolveShorthandOptions<P, boolean>):\n | WithoutSlotRenderFunction<P>\n | undefined;\n};\n\n/**\n *\n * Resolves shorthands into slot props, to ensure normalization of the signature\n * being passed down to getSlots method\n * @param value - the base shorthand props\n * @param options - options to resolve shorthand props\n *\n * @deprecated use slot.always, slot.optional, slot.resolveShorthand combined with assertSlots instead\n */\n// eslint-disable-next-line @typescript-eslint/no-deprecated\nexport const resolveShorthand: ResolveShorthandFunction<UnknownSlotProps> = (value, options) =>\n slot.optional<UnknownSlotProps>(value, {\n ...options,\n renderByDefault: options?.required,\n // elementType as undefined is the way to identify between a slot and a resolveShorthand call\n // in the case elementType is undefined assertSlots will fail, ensuring it'll only work with slot method.\n elementType: undefined!,\n }) as WithoutSlotRenderFunction<UnknownSlotProps>;\n"],"names":["slot","resolveShorthand","value","options","optional","renderByDefault","required","elementType","undefined"],"mappings":"AAAA,YAAYA,UAAU,UAAU;AAyBhC;;;;;;;;CAQC,GACD,4DAA4D;AAC5D,OAAO,MAAMC,mBAA+D,CAACC,OAAOC,UAClFH,KAAKI,QAAQ,CAAmBF,OAAO;QACrC,GAAGC,OAAO;QACVE,eAAe,EAAEF,oBAAAA,8BAAAA,QAASG,QAAQ;QAClC,6FAA6F;QAC7F,yGAAyG;QACzGC,aAAaC;IACf,GAAkD"}

View File

@@ -0,0 +1,17 @@
import * as React from 'react';
import { getNativeElementProps } from '../utils/getNativeElementProps';
/**
* 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.
*
* @param tagName - The slot's default element type (e.g. 'div')
* @param props - The component's props object
* @param excludedPropNames - List of native props to exclude from the returned value
*/ export const getIntrinsicElementProps = (tagName, // eslint-disable-next-line @typescript-eslint/no-restricted-types -- in order to not introduce Type Restriction CHANGe which is kinda "breaking change from Types POV", we don't enforce our custom `RefAttributes` in this API, to be compatible with scenarios where non v9 interfaces might be used. This may/will change with React 19
props, excludedPropNames)=>{
var _props_as;
// eslint-disable-next-line @typescript-eslint/no-deprecated
return getNativeElementProps((_props_as = props.as) !== null && _props_as !== void 0 ? _props_as : tagName, props, excludedPropNames);
};

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../src/compose/getIntrinsicElementProps.ts"],"sourcesContent":["import * as React from 'react';\nimport { getNativeElementProps } from '../utils/getNativeElementProps';\nimport type { InferredElementRefType, UnknownSlotProps } from './types';\nimport type { DistributiveOmit } from '../utils/types';\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype HTMLAttributes = React.HTMLAttributes<any>;\n\n/**\n * Given an element tagname and user props, filters the props to only allowed props for the given\n * element type.\n *\n * Equivalent to {@link getNativeElementProps}, but more type-safe.\n *\n * @param tagName - The slot's default element type (e.g. 'div')\n * @param props - The component's props object\n * @param excludedPropNames - List of native props to exclude from the returned value\n */\nexport const getIntrinsicElementProps = <\n Props extends UnknownSlotProps,\n ExcludedPropKeys extends Extract<keyof Props, string> = never,\n>(\n tagName: NonNullable<Props['as']>,\n // eslint-disable-next-line @typescript-eslint/no-restricted-types -- in order to not introduce Type Restriction CHANGe which is kinda \"breaking change from Types POV\", we don't enforce our custom `RefAttributes` in this API, to be compatible with scenarios where non v9 interfaces might be used. This may/will change with React 19\n props: Props & React.RefAttributes<InferredElementRefType<Props>>,\n excludedPropNames?: ExcludedPropKeys[],\n): DistributiveOmit<Props, ExcludedPropKeys | Exclude<keyof Props, 'as' | keyof HTMLAttributes>> => {\n // eslint-disable-next-line @typescript-eslint/no-deprecated\n return getNativeElementProps<\n DistributiveOmit<Props, Exclude<keyof Props, keyof HTMLAttributes | keyof UnknownSlotProps> | ExcludedPropKeys>\n >(props.as ?? tagName, props, excludedPropNames);\n};\n"],"names":["React","getNativeElementProps","getIntrinsicElementProps","tagName","props","excludedPropNames","as"],"mappings":"AAAA,YAAYA,WAAW,QAAQ;AAC/B,SAASC,qBAAqB,QAAQ,iCAAiC;AAOvE;;;;;;;;;CASC,GACD,OAAO,MAAMC,2BAA2B,CAItCC,SACA,2UAA2U;AAC3UC,OACAC;QAKED;IAHF,4DAA4D;IAC5D,OAAOH,sBAELG,CAAAA,YAAAA,MAAME,EAAE,cAARF,uBAAAA,YAAYD,SAASC,OAAOC;AAChC,EAAE"}

View File

@@ -0,0 +1,21 @@
import { SLOT_CLASS_NAME_PROP_SYMBOL } from '../compose/constants';
/**
* Get the className prop set on the slot by the user, without including the default classes added by the component.
* Custom style hooks should merge this className _after_ any additional classes added by the hook, to ensure that
* classes added by the user take precedence over the custom style hook.
*
* Example usage in a custom style hook:
* ```ts
* state.root.className = mergeClasses(
* state.root.className,
* customStyles.root,
* getSlotClassNameProp_unstable(state.root));
* ```
*
* @returns The className prop set on the slot by the user, or undefined if not set.
*/ export const getSlotClassNameProp = (slot)=>{
if (SLOT_CLASS_NAME_PROP_SYMBOL in slot && typeof slot[SLOT_CLASS_NAME_PROP_SYMBOL] === 'string') {
return slot[SLOT_CLASS_NAME_PROP_SYMBOL];
}
return undefined;
};

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../src/compose/getSlotClassNameProp.ts"],"sourcesContent":["import { SLOT_CLASS_NAME_PROP_SYMBOL } from '../compose/constants';\nimport type { UnknownSlotProps } from '../compose/types';\n\n/**\n * Get the className prop set on the slot by the user, without including the default classes added by the component.\n * Custom style hooks should merge this className _after_ any additional classes added by the hook, to ensure that\n * classes added by the user take precedence over the custom style hook.\n *\n * Example usage in a custom style hook:\n * ```ts\n * state.root.className = mergeClasses(\n * state.root.className,\n * customStyles.root,\n * getSlotClassNameProp_unstable(state.root));\n * ```\n *\n * @returns The className prop set on the slot by the user, or undefined if not set.\n */\nexport const getSlotClassNameProp = (slot: UnknownSlotProps): string | undefined => {\n if (SLOT_CLASS_NAME_PROP_SYMBOL in slot && typeof slot[SLOT_CLASS_NAME_PROP_SYMBOL] === 'string') {\n return slot[SLOT_CLASS_NAME_PROP_SYMBOL];\n }\n return undefined;\n};\n"],"names":["SLOT_CLASS_NAME_PROP_SYMBOL","getSlotClassNameProp","slot","undefined"],"mappings":"AAAA,SAASA,2BAA2B,QAAQ,uBAAuB;AAGnE;;;;;;;;;;;;;;CAcC,GACD,OAAO,MAAMC,uBAAuB,CAACC;IACnC,IAAIF,+BAA+BE,QAAQ,OAAOA,IAAI,CAACF,4BAA4B,KAAK,UAAU;QAChG,OAAOE,IAAI,CAACF,4BAA4B;IAC1C;IACA,OAAOG;AACT,EAAE"}

View File

@@ -0,0 +1,14 @@
import * as slot from './slot';
export { isResolvedShorthand } from './isResolvedShorthand';
export { SLOT_CLASS_NAME_PROP_SYMBOL, SLOT_ELEMENT_TYPE_SYMBOL, SLOT_RENDER_FUNCTION_SYMBOL } from './constants';
export { isSlot } from './isSlot';
export { assertSlots } from './assertSlots';
export { getIntrinsicElementProps } from './getIntrinsicElementProps';
export { getSlotClassNameProp as getSlotClassNameProp_unstable } from './getSlotClassNameProp';
// eslint-disable-next-line @typescript-eslint/no-deprecated
export { getSlots } from './deprecated/getSlots';
// eslint-disable-next-line @typescript-eslint/no-deprecated
export { resolveShorthand } from './deprecated/resolveShorthand';
// eslint-disable-next-line @typescript-eslint/no-deprecated
export { getSlotsNext } from './deprecated/getSlotsNext';
export { slot };

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../src/compose/index.ts"],"sourcesContent":["import * as slot from './slot';\n\nexport type {\n AsIntrinsicElement,\n ComponentProps,\n ComponentState,\n EventData,\n EventHandler,\n ExtractSlotProps,\n ForwardRefComponent,\n RefAttributes,\n InferredElementRefType,\n IsSingleton,\n Slot,\n SlotClassNames,\n SlotComponentType,\n SlotPropsRecord,\n SlotRenderFunction,\n SlotShorthandValue,\n UnknownSlotProps,\n} from './types';\n\nexport { isResolvedShorthand } from './isResolvedShorthand';\nexport { SLOT_CLASS_NAME_PROP_SYMBOL, SLOT_ELEMENT_TYPE_SYMBOL, SLOT_RENDER_FUNCTION_SYMBOL } from './constants';\nexport { isSlot } from './isSlot';\nexport { assertSlots } from './assertSlots';\nexport { getIntrinsicElementProps } from './getIntrinsicElementProps';\nexport { getSlotClassNameProp as getSlotClassNameProp_unstable } from './getSlotClassNameProp';\n\n// eslint-disable-next-line @typescript-eslint/no-deprecated\nexport type { ObjectSlotProps, Slots } from './deprecated/getSlots';\n// eslint-disable-next-line @typescript-eslint/no-deprecated\nexport { getSlots } from './deprecated/getSlots';\n// eslint-disable-next-line @typescript-eslint/no-deprecated\nexport type { ResolveShorthandFunction, ResolveShorthandOptions } from './deprecated/resolveShorthand';\n// eslint-disable-next-line @typescript-eslint/no-deprecated\nexport { resolveShorthand } from './deprecated/resolveShorthand';\n// eslint-disable-next-line @typescript-eslint/no-deprecated\nexport { getSlotsNext } from './deprecated/getSlotsNext';\n\nexport { slot };\nexport type { SlotOptions } from './slot';\nexport type { PropsWithoutChildren, PropsWithoutRef } from '../utils/types';\n"],"names":["slot","isResolvedShorthand","SLOT_CLASS_NAME_PROP_SYMBOL","SLOT_ELEMENT_TYPE_SYMBOL","SLOT_RENDER_FUNCTION_SYMBOL","isSlot","assertSlots","getIntrinsicElementProps","getSlotClassNameProp","getSlotClassNameProp_unstable","getSlots","resolveShorthand","getSlotsNext"],"mappings":"AAAA,YAAYA,UAAU,SAAS;AAsB/B,SAASC,mBAAmB,QAAQ,wBAAwB;AAC5D,SAASC,2BAA2B,EAAEC,wBAAwB,EAAEC,2BAA2B,QAAQ,cAAc;AACjH,SAASC,MAAM,QAAQ,WAAW;AAClC,SAASC,WAAW,QAAQ,gBAAgB;AAC5C,SAASC,wBAAwB,QAAQ,6BAA6B;AACtE,SAASC,wBAAwBC,6BAA6B,QAAQ,yBAAyB;AAI/F,4DAA4D;AAC5D,SAASC,QAAQ,QAAQ,wBAAwB;AAGjD,4DAA4D;AAC5D,SAASC,gBAAgB,QAAQ,gCAAgC;AACjE,4DAA4D;AAC5D,SAASC,YAAY,QAAQ,4BAA4B;AAEzD,SAASZ,IAAI,GAAG"}

View File

@@ -0,0 +1,33 @@
import * as React from 'react';
/**
* Guard method that validates if a shorthand is a slot
* can be used to extends properties provided by a slot
*
* @example
* ```
* const backdropSlot = resolveShorthand(backdrop, {
* defaultProps: {
* onClick: useEventCallback(event => {
* if (isResolvedShorthand(backdrop)) {
* backdrop.onClick?.(event)
* }
* // do something after passing click down the line
* }),
* },
* })
* ```
* @example
* ```
* const handleBackDropClick = (event) => {
* // do your thing
* }
* const backdropSlot = resolveShorthand(backdrop, {
* defaultProps: {
* onClick: useEventCallback(
* mergeCallbacks(isResolvedShorthand(backdrop) ? backdrop.onClick : undefined, handleBackdropClick)
* )
* })
* ```
*/ export function isResolvedShorthand(shorthand) {
return shorthand !== null && typeof shorthand === 'object' && !Array.isArray(shorthand) && !React.isValidElement(shorthand);
}

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../src/compose/isResolvedShorthand.ts"],"sourcesContent":["import * as React from 'react';\nimport type { ExtractSlotProps, Slot, UnknownSlotProps } from './types';\n\n/**\n * Guard method that validates if a shorthand is a slot\n * can be used to extends properties provided by a slot\n *\n * @example\n * ```\n * const backdropSlot = resolveShorthand(backdrop, {\n * defaultProps: {\n * onClick: useEventCallback(event => {\n * if (isResolvedShorthand(backdrop)) {\n * backdrop.onClick?.(event)\n * }\n * // do something after passing click down the line\n * }),\n * },\n * })\n * ```\n * @example\n * ```\n * const handleBackDropClick = (event) => {\n * // do your thing\n * }\n * const backdropSlot = resolveShorthand(backdrop, {\n * defaultProps: {\n * onClick: useEventCallback(\n * mergeCallbacks(isResolvedShorthand(backdrop) ? backdrop.onClick : undefined, handleBackdropClick)\n * )\n * })\n * ```\n */\nexport function isResolvedShorthand<Shorthand extends Slot<UnknownSlotProps>>(\n shorthand?: Shorthand,\n): shorthand is ExtractSlotProps<Shorthand> {\n return (\n shorthand !== null && typeof shorthand === 'object' && !Array.isArray(shorthand) && !React.isValidElement(shorthand)\n );\n}\n"],"names":["React","isResolvedShorthand","shorthand","Array","isArray","isValidElement"],"mappings":"AAAA,YAAYA,WAAW,QAAQ;AAG/B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA6BC,GACD,OAAO,SAASC,oBACdC,SAAqB;IAErB,OACEA,cAAc,QAAQ,OAAOA,cAAc,YAAY,CAACC,MAAMC,OAAO,CAACF,cAAc,CAACF,MAAMK,cAAc,CAACH;AAE9G"}

View File

@@ -0,0 +1,7 @@
import { SLOT_ELEMENT_TYPE_SYMBOL } from './constants';
/**
* Guard method to ensure a given element is a slot.
* This is mainly used internally to ensure a slot is being used as a component.
*/ export function isSlot(element) {
return Boolean(element === null || element === void 0 ? void 0 : element.hasOwnProperty(SLOT_ELEMENT_TYPE_SYMBOL));
}

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../src/compose/isSlot.ts"],"sourcesContent":["import { SLOT_ELEMENT_TYPE_SYMBOL } from './constants';\nimport { SlotComponentType } from './types';\n\n/**\n * Guard method to ensure a given element is a slot.\n * This is mainly used internally to ensure a slot is being used as a component.\n */\nexport function isSlot<Props extends {}>(element: unknown): element is SlotComponentType<Props> {\n return Boolean((element as {} | undefined)?.hasOwnProperty(SLOT_ELEMENT_TYPE_SYMBOL));\n}\n"],"names":["SLOT_ELEMENT_TYPE_SYMBOL","isSlot","element","Boolean","hasOwnProperty"],"mappings":"AAAA,SAASA,wBAAwB,QAAQ,cAAc;AAGvD;;;CAGC,GACD,OAAO,SAASC,OAAyBC,OAAgB;IACvD,OAAOC,QAASD,oBAAAA,8BAAD,AAACA,QAA4BE,cAAc,CAACJ;AAC7D"}

View File

@@ -0,0 +1,70 @@
import * as React from 'react';
import { SLOT_CLASS_NAME_PROP_SYMBOL, SLOT_ELEMENT_TYPE_SYMBOL, SLOT_RENDER_FUNCTION_SYMBOL } from './constants';
/**
* Creates a slot from a slot shorthand or properties (`props.SLOT_NAME` or `props` itself)
* @param value - the value of the slot, it can be a slot shorthand, a slot component or a slot properties
* @param options - values you can pass to alter the signature of a slot, those values are:
*
* * `elementType` - the base element type of a slot, defaults to `'div'`
* * `defaultProps` - similar to a React component declaration, you can provide a slot default properties to be merged with the shorthand/properties provided.
*/ export function always(value, options) {
const { defaultProps, elementType } = options;
const props = resolveShorthand(value);
/**
* Casting is required here as SlotComponentType is a function, not an object.
* Although SlotComponentType has a function signature, it is still just an object.
* This is required to make a slot callable (JSX compatible), this is the exact same approach
* that is used on `@types/react` components
*/ const propsWithMetadata = {
...defaultProps,
...props,
[SLOT_ELEMENT_TYPE_SYMBOL]: elementType,
[SLOT_CLASS_NAME_PROP_SYMBOL]: (props === null || props === void 0 ? void 0 : props.className) || (defaultProps === null || defaultProps === void 0 ? void 0 : defaultProps.className)
};
if (props && typeof props.children === 'function') {
propsWithMetadata[SLOT_RENDER_FUNCTION_SYMBOL] = props.children;
propsWithMetadata.children = defaultProps === null || defaultProps === void 0 ? void 0 : defaultProps.children;
}
return propsWithMetadata;
}
/**
* Creates a slot from a slot shorthand or properties (`props.SLOT_NAME` or `props` itself)
* @param value - the value of the slot, it can be a slot shorthand, a slot component or a slot properties
* @param options - values you can pass to alter the signature of a slot, those values are:
*
* * `elementType` - the base element type of a slot, defaults to `'div'`
* * `defaultProps` - similar to a React component declaration, you can provide a slot default properties to be merged with the shorthand/properties provided
* * `renderByDefault` - a boolean that indicates if a slot will be rendered even if it's base value is `undefined`.
* By default if `props.SLOT_NAME` is `undefined` then `state.SLOT_NAME` becomes `undefined`
* and nothing will be rendered, but if `renderByDefault = true` then `state.SLOT_NAME` becomes an object
* with the values provided by `options.defaultProps` (or `{}`). This is useful for cases such as providing a default content
* in case no shorthand is provided, like the case of the `expandIcon` slot for the `AccordionHeader`
*/ export function optional(value, options) {
if (value === null || value === undefined && !options.renderByDefault) {
return undefined;
}
return always(value, options);
}
/**
* Helper function that converts a slot shorthand or properties to a slot properties object
* The main difference between this function and `slot` is that this function does not return the metadata required for a slot to be considered a properly renderable slot, it only converts the value to a slot properties object
* @param value - the value of the slot, it can be a slot shorthand or a slot properties object
*/ export function resolveShorthand(value) {
if (typeof value === 'string' || typeof value === 'number' || isIterable(value) || // eslint-disable-next-line @typescript-eslint/no-explicit-any
React.isValidElement(value)) {
return {
children: value
};
}
if (value && typeof value !== 'object' && process.env.NODE_ENV !== 'production') {
// TODO: would be nice to have a link to slot documentation in this error message
// eslint-disable-next-line no-console
console.error(`@fluentui/react-utilities [slot.${resolveShorthand.name}]:
A slot got an invalid value "${value}" (${typeof value}).
A valid value for a slot is a slot shorthand or slot properties object.
Slot shorthands can be strings, numbers, arrays or JSX elements`);
}
return value;
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const isIterable = (value)=>typeof value === 'object' && value !== null && Symbol.iterator in value;

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1 @@
import * as React from 'react';

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1 @@
export { getEventClientCoords, isMouseEvent, isTouchEvent } from './mouseTouchHelpers';

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../src/events/index.ts"],"sourcesContent":["export type { NativeTouchOrMouseEvent, ReactTouchOrMouseEvent, TouchOrMouseEvent } from './mouseTouchHelpers';\nexport { getEventClientCoords, isMouseEvent, isTouchEvent } from './mouseTouchHelpers';\n"],"names":["getEventClientCoords","isMouseEvent","isTouchEvent"],"mappings":"AACA,SAASA,oBAAoB,EAAEC,YAAY,EAAEC,YAAY,QAAQ,sBAAsB"}

View File

@@ -0,0 +1,39 @@
import * as React from 'react';
/**
* Returns true if event is a touch event. Useful when sharing logic between touch and mouse interactions.
*/ export function isTouchEvent(event) {
return event.type.startsWith('touch');
}
/**
* Returns true if event is a mouse event. Useful when sharing logic between touch and mouse interactions.
*/ export function isMouseEvent(event) {
return event.type.startsWith('mouse') || [
'click',
'contextmenu',
'dblclick'
].indexOf(event.type) > -1;
}
/**
* Returns an object with clientX, clientY for TouchOrMouseEvent.
* Returns zeros in case the event is not a mouse or a touch event.
*/ export function getEventClientCoords(event) {
if (isMouseEvent(event)) {
return {
clientX: event.clientX,
clientY: event.clientY
};
} else if (isTouchEvent(event)) {
return {
clientX: event.touches[0].clientX,
clientY: event.touches[0].clientY
};
} else {
if (process.env.NODE_ENV !== 'production') {
throw new Error('@fluentui/react-utilities]: Unable to get clientX. Unknown event type.');
}
return {
clientX: 0,
clientY: 0
};
}
}

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../src/events/mouseTouchHelpers.ts"],"sourcesContent":["import * as React from 'react';\n\nexport type NativeTouchOrMouseEvent = MouseEvent | TouchEvent;\n\nexport type ReactTouchOrMouseEvent = React.MouseEvent | React.TouchEvent;\n\nexport type TouchOrMouseEvent = NativeTouchOrMouseEvent | ReactTouchOrMouseEvent;\n\n/**\n * Returns true if event is a touch event. Useful when sharing logic between touch and mouse interactions.\n */\nexport function isTouchEvent(event: TouchOrMouseEvent): event is TouchEvent | React.TouchEvent {\n return event.type.startsWith('touch');\n}\n\n/**\n * Returns true if event is a mouse event. Useful when sharing logic between touch and mouse interactions.\n */\nexport function isMouseEvent(event: TouchOrMouseEvent): event is MouseEvent | React.MouseEvent {\n return event.type.startsWith('mouse') || ['click', 'contextmenu', 'dblclick'].indexOf(event.type) > -1;\n}\n\n/**\n * Returns an object with clientX, clientY for TouchOrMouseEvent.\n * Returns zeros in case the event is not a mouse or a touch event.\n */\nexport function getEventClientCoords(event: TouchOrMouseEvent): { clientX: number; clientY: number } {\n if (isMouseEvent(event)) {\n return { clientX: event.clientX, clientY: event.clientY };\n } else if (isTouchEvent(event)) {\n return { clientX: event.touches[0].clientX, clientY: event.touches[0].clientY };\n } else {\n if (process.env.NODE_ENV !== 'production') {\n throw new Error('@fluentui/react-utilities]: Unable to get clientX. Unknown event type.');\n }\n return { clientX: 0, clientY: 0 };\n }\n}\n"],"names":["React","isTouchEvent","event","type","startsWith","isMouseEvent","indexOf","getEventClientCoords","clientX","clientY","touches","process","env","NODE_ENV","Error"],"mappings":"AAAA,YAAYA,WAAW,QAAQ;AAQ/B;;CAEC,GACD,OAAO,SAASC,aAAaC,KAAwB;IACnD,OAAOA,MAAMC,IAAI,CAACC,UAAU,CAAC;AAC/B;AAEA;;CAEC,GACD,OAAO,SAASC,aAAaH,KAAwB;IACnD,OAAOA,MAAMC,IAAI,CAACC,UAAU,CAAC,YAAY;QAAC;QAAS;QAAe;KAAW,CAACE,OAAO,CAACJ,MAAMC,IAAI,IAAI,CAAC;AACvG;AAEA;;;CAGC,GACD,OAAO,SAASI,qBAAqBL,KAAwB;IAC3D,IAAIG,aAAaH,QAAQ;QACvB,OAAO;YAAEM,SAASN,MAAMM,OAAO;YAAEC,SAASP,MAAMO,OAAO;QAAC;IAC1D,OAAO,IAAIR,aAAaC,QAAQ;QAC9B,OAAO;YAAEM,SAASN,MAAMQ,OAAO,CAAC,EAAE,CAACF,OAAO;YAAEC,SAASP,MAAMQ,OAAO,CAAC,EAAE,CAACD,OAAO;QAAC;IAChF,OAAO;QACL,IAAIE,QAAQC,GAAG,CAACC,QAAQ,KAAK,cAAc;YACzC,MAAM,IAAIC,MAAM;QAClB;QACA,OAAO;YAAEN,SAAS;YAAGC,SAAS;QAAE;IAClC;AACF"}

View File

@@ -0,0 +1,14 @@
export { useAnimationFrame } from './useAnimationFrame';
export { useApplyScrollbarWidth } from './useApplyScrollbarWidth';
export { useControllableState } from './useControllableState';
export { useEventCallback } from './useEventCallback';
export { useFirstMount } from './useFirstMount';
export { useForceUpdate } from './useForceUpdate';
export { IdPrefixProvider, resetIdsForTests, useId } from './useId';
export { useIsomorphicLayoutEffect } from './useIsomorphicLayoutEffect';
export { useMergedRefs } from './useMergedRefs';
export { useOnClickOutside } from './useOnClickOutside';
export { useOnScrollOutside } from './useOnScrollOutside';
export { usePrevious } from './usePrevious';
export { useScrollbarWidth } from './useScrollbarWidth';
export { useTimeout } from './useTimeout';

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../src/hooks/index.ts"],"sourcesContent":["export { useAnimationFrame } from './useAnimationFrame';\nexport { useApplyScrollbarWidth } from './useApplyScrollbarWidth';\nexport type { UseControllableStateOptions } from './useControllableState';\nexport { useControllableState } from './useControllableState';\nexport { useEventCallback } from './useEventCallback';\nexport { useFirstMount } from './useFirstMount';\nexport { useForceUpdate } from './useForceUpdate';\nexport { IdPrefixProvider, resetIdsForTests, useId } from './useId';\nexport { useIsomorphicLayoutEffect } from './useIsomorphicLayoutEffect';\nexport type { RefObjectFunction } from './useMergedRefs';\nexport { useMergedRefs } from './useMergedRefs';\nexport type { UseOnClickOrScrollOutsideOptions } from './useOnClickOutside';\nexport { useOnClickOutside } from './useOnClickOutside';\nexport { useOnScrollOutside } from './useOnScrollOutside';\nexport { usePrevious } from './usePrevious';\nexport { useScrollbarWidth } from './useScrollbarWidth';\nexport { useTimeout } from './useTimeout';\n"],"names":["useAnimationFrame","useApplyScrollbarWidth","useControllableState","useEventCallback","useFirstMount","useForceUpdate","IdPrefixProvider","resetIdsForTests","useId","useIsomorphicLayoutEffect","useMergedRefs","useOnClickOutside","useOnScrollOutside","usePrevious","useScrollbarWidth","useTimeout"],"mappings":"AAAA,SAASA,iBAAiB,QAAQ,sBAAsB;AACxD,SAASC,sBAAsB,QAAQ,2BAA2B;AAElE,SAASC,oBAAoB,QAAQ,yBAAyB;AAC9D,SAASC,gBAAgB,QAAQ,qBAAqB;AACtD,SAASC,aAAa,QAAQ,kBAAkB;AAChD,SAASC,cAAc,QAAQ,mBAAmB;AAClD,SAASC,gBAAgB,EAAEC,gBAAgB,EAAEC,KAAK,QAAQ,UAAU;AACpE,SAASC,yBAAyB,QAAQ,8BAA8B;AAExE,SAASC,aAAa,QAAQ,kBAAkB;AAEhD,SAASC,iBAAiB,QAAQ,sBAAsB;AACxD,SAASC,kBAAkB,QAAQ,uBAAuB;AAC1D,SAASC,WAAW,QAAQ,gBAAgB;AAC5C,SAASC,iBAAiB,QAAQ,sBAAsB;AACxD,SAASC,UAAU,QAAQ,eAAe"}

View File

@@ -0,0 +1,22 @@
'use client';
import { useBrowserTimer } from './useBrowserTimer';
import { useFluent_unstable as useFluent } from '@fluentui/react-shared-contexts';
const setAnimationFrameNoop = (callback)=>{
callback(0);
return 0;
};
const cancelAnimationFrameNoop = (handle)=>handle;
/**
* @internal
* Helper to manage a browser requestAnimationFrame.
* Ensures that the requestAnimationFrame isn't set multiple times at once and is cleaned up
* when the component is unloaded.
*
* @returns A pair of [requestAnimationFrame, cancelAnimationFrame] that are stable between renders.
*/ export function useAnimationFrame() {
const { targetDocument } = useFluent();
const win = targetDocument === null || targetDocument === void 0 ? void 0 : targetDocument.defaultView;
const setAnimationFrame = win ? win.requestAnimationFrame : setAnimationFrameNoop;
const clearAnimationFrame = win ? win.cancelAnimationFrame : cancelAnimationFrameNoop;
return useBrowserTimer(setAnimationFrame, clearAnimationFrame);
}

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../src/hooks/useAnimationFrame.ts"],"sourcesContent":["'use client';\n\nimport { useBrowserTimer } from './useBrowserTimer';\nimport { useFluent_unstable as useFluent } from '@fluentui/react-shared-contexts';\n\nconst setAnimationFrameNoop = (callback: FrameRequestCallback) => {\n callback(0);\n return 0;\n};\nconst cancelAnimationFrameNoop = (handle: number) => handle;\n\n/**\n * @internal\n * Helper to manage a browser requestAnimationFrame.\n * Ensures that the requestAnimationFrame isn't set multiple times at once and is cleaned up\n * when the component is unloaded.\n *\n * @returns A pair of [requestAnimationFrame, cancelAnimationFrame] that are stable between renders.\n */\nexport function useAnimationFrame(): readonly [(fn: FrameRequestCallback) => number, () => void] {\n const { targetDocument } = useFluent();\n const win = targetDocument?.defaultView;\n\n const setAnimationFrame = win ? win.requestAnimationFrame : setAnimationFrameNoop;\n const clearAnimationFrame = win ? win.cancelAnimationFrame : cancelAnimationFrameNoop;\n\n return useBrowserTimer(setAnimationFrame, clearAnimationFrame) as [(fn: FrameRequestCallback) => number, () => void];\n}\n"],"names":["useBrowserTimer","useFluent_unstable","useFluent","setAnimationFrameNoop","callback","cancelAnimationFrameNoop","handle","useAnimationFrame","targetDocument","win","defaultView","setAnimationFrame","requestAnimationFrame","clearAnimationFrame","cancelAnimationFrame"],"mappings":"AAAA;AAEA,SAASA,eAAe,QAAQ,oBAAoB;AACpD,SAASC,sBAAsBC,SAAS,QAAQ,kCAAkC;AAElF,MAAMC,wBAAwB,CAACC;IAC7BA,SAAS;IACT,OAAO;AACT;AACA,MAAMC,2BAA2B,CAACC,SAAmBA;AAErD;;;;;;;CAOC,GACD,OAAO,SAASC;IACd,MAAM,EAAEC,cAAc,EAAE,GAAGN;IAC3B,MAAMO,MAAMD,2BAAAA,qCAAAA,eAAgBE,WAAW;IAEvC,MAAMC,oBAAoBF,MAAMA,IAAIG,qBAAqB,GAAGT;IAC5D,MAAMU,sBAAsBJ,MAAMA,IAAIK,oBAAoB,GAAGT;IAE7D,OAAOL,gBAAgBW,mBAAmBE;AAC5C"}

View File

@@ -0,0 +1,40 @@
'use client';
import * as React from 'react';
import { measureScrollbarWidth } from '../utils/measureScrollBarWidth';
const cache = new WeakMap();
/**
* A React hook that provides a ref for applying the browser's scrollbar width as a CSS property.
*
* This hook is SSR-safe and caches measurements per document to avoid redundant calculations.
* When the ref is attached to an element, the hook automatically applies the measured scrollbar
* width to the specified CSS property (defaults to 'width').
*
* @example
* ```tsx
* const scrollbarRef = useApplyScrollbarWidth({ targetDocument: document });
* return <div ref={scrollbarRef} />;
* ```
*/ export function useApplyScrollbarWidth(options = {}) {
const { force, property = 'width' } = options;
const applyScrollbarWidth = React.useCallback((element)=>{
if (!element) {
return;
}
// If we have a cached value, use it
if (!force && cache.has(element.ownerDocument)) {
const cachedWidth = cache.get(element.ownerDocument);
if (cachedWidth !== undefined) {
element.style.setProperty(property, `${cachedWidth}px`);
return;
}
}
// Measure the scrollbar width and apply it to the element
const scrollbarWidth = measureScrollbarWidth(element.ownerDocument);
cache.set(element.ownerDocument, scrollbarWidth);
element.style.setProperty(property, `${scrollbarWidth}px`);
}, [
force,
property
]);
return applyScrollbarWidth;
}

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../src/hooks/useApplyScrollbarWidth.ts"],"sourcesContent":["'use client';\n\nimport * as React from 'react';\nimport { measureScrollbarWidth } from '../utils/measureScrollBarWidth';\n\nconst cache = new WeakMap<Document, number>();\n\ninterface UseApplyScrollbarWidthOptions {\n /**\n * Does not use the cache and recalculates the scrollbar width\n */\n force?: boolean;\n\n /**\n * CSS property to apply the scrollbar width to.\n * @default 'width'\n */\n property?: string;\n}\n\n/**\n * A React hook that provides a ref for applying the browser's scrollbar width as a CSS property.\n *\n * This hook is SSR-safe and caches measurements per document to avoid redundant calculations.\n * When the ref is attached to an element, the hook automatically applies the measured scrollbar\n * width to the specified CSS property (defaults to 'width').\n *\n * @example\n * ```tsx\n * const scrollbarRef = useApplyScrollbarWidth({ targetDocument: document });\n * return <div ref={scrollbarRef} />;\n * ```\n */\nexport function useApplyScrollbarWidth<T extends HTMLElement>(\n options: UseApplyScrollbarWidthOptions = {},\n): React.RefCallback<T> {\n const { force, property = 'width' } = options;\n\n const applyScrollbarWidth = React.useCallback(\n (element: T | null) => {\n if (!element) {\n return;\n }\n\n // If we have a cached value, use it\n if (!force && cache.has(element.ownerDocument)) {\n const cachedWidth = cache.get(element.ownerDocument);\n if (cachedWidth !== undefined) {\n element.style.setProperty(property, `${cachedWidth}px`);\n return;\n }\n }\n\n // Measure the scrollbar width and apply it to the element\n const scrollbarWidth = measureScrollbarWidth(element.ownerDocument);\n cache.set(element.ownerDocument, scrollbarWidth);\n element.style.setProperty(property, `${scrollbarWidth}px`);\n },\n [force, property],\n );\n\n return applyScrollbarWidth;\n}\n"],"names":["React","measureScrollbarWidth","cache","WeakMap","useApplyScrollbarWidth","options","force","property","applyScrollbarWidth","useCallback","element","has","ownerDocument","cachedWidth","get","undefined","style","setProperty","scrollbarWidth","set"],"mappings":"AAAA;AAEA,YAAYA,WAAW,QAAQ;AAC/B,SAASC,qBAAqB,QAAQ,iCAAiC;AAEvE,MAAMC,QAAQ,IAAIC;AAelB;;;;;;;;;;;;CAYC,GACD,OAAO,SAASC,uBACdC,UAAyC,CAAC,CAAC;IAE3C,MAAM,EAAEC,KAAK,EAAEC,WAAW,OAAO,EAAE,GAAGF;IAEtC,MAAMG,sBAAsBR,MAAMS,WAAW,CAC3C,CAACC;QACC,IAAI,CAACA,SAAS;YACZ;QACF;QAEA,oCAAoC;QACpC,IAAI,CAACJ,SAASJ,MAAMS,GAAG,CAACD,QAAQE,aAAa,GAAG;YAC9C,MAAMC,cAAcX,MAAMY,GAAG,CAACJ,QAAQE,aAAa;YACnD,IAAIC,gBAAgBE,WAAW;gBAC7BL,QAAQM,KAAK,CAACC,WAAW,CAACV,UAAU,GAAGM,YAAY,EAAE,CAAC;gBACtD;YACF;QACF;QAEA,0DAA0D;QAC1D,MAAMK,iBAAiBjB,sBAAsBS,QAAQE,aAAa;QAClEV,MAAMiB,GAAG,CAACT,QAAQE,aAAa,EAAEM;QACjCR,QAAQM,KAAK,CAACC,WAAW,CAACV,UAAU,GAAGW,eAAe,EAAE,CAAC;IAC3D,GACA;QAACZ;QAAOC;KAAS;IAGnB,OAAOC;AACT"}

View File

@@ -0,0 +1,46 @@
'use client';
import * as React from 'react';
/**
* @internal
* Helper to manage a browser timer.
* Ensures that the timer isn't set multiple times at once,
* and is cleaned up when the component is unloaded.
*
* @param setTimer - The timer setter function
* @param cancelTimer - The timer cancel function
* @returns A pair of [setTimer, cancelTimer] that are stable between renders.
*
* @example
* const [setTimer, cancelTimer] = useBrowserTimer(setTimeout, cancelTimeout);
*
* setTimer(() => console.log('Hello world!'), 1000);
* cancelTimer();
*/ export function useBrowserTimer(setTimer, cancelTimer) {
const id = React.useRef(undefined);
const set = React.useCallback((fn, delay)=>{
if (id.current !== undefined) {
cancelTimer(id.current);
}
id.current = setTimer(fn, delay);
return id.current;
}, [
cancelTimer,
setTimer
]);
const cancel = React.useCallback(()=>{
if (id.current !== undefined) {
cancelTimer(id.current);
id.current = undefined;
}
}, [
cancelTimer
]);
// Clean up the timeout when the component is unloaded
React.useEffect(()=>cancel, [
cancel
]);
return [
set,
cancel
];
}

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../src/hooks/useBrowserTimer.ts"],"sourcesContent":["'use client';\n\nimport * as React from 'react';\n\ntype BrowserTimerSetter =\n | ((fn: () => void, duration?: number, ...args: Record<string, unknown>[]) => number)\n | ((fn: () => void) => number);\n\n/**\n * @internal\n * Helper to manage a browser timer.\n * Ensures that the timer isn't set multiple times at once,\n * and is cleaned up when the component is unloaded.\n *\n * @param setTimer - The timer setter function\n * @param cancelTimer - The timer cancel function\n * @returns A pair of [setTimer, cancelTimer] that are stable between renders.\n *\n * @example\n * const [setTimer, cancelTimer] = useBrowserTimer(setTimeout, cancelTimeout);\n *\n * setTimer(() => console.log('Hello world!'), 1000);\n * cancelTimer();\n */\nexport function useBrowserTimer(\n setTimer: BrowserTimerSetter,\n cancelTimer: (id: number) => void,\n): [(fn: () => void, delay?: number) => number, () => void] {\n const id = React.useRef<number | undefined>(undefined);\n\n const set = React.useCallback(\n (fn: () => void, delay?: number) => {\n if (id.current !== undefined) {\n cancelTimer(id.current);\n }\n\n id.current = setTimer(fn, delay);\n return id.current;\n },\n [cancelTimer, setTimer],\n );\n\n const cancel = React.useCallback(() => {\n if (id.current !== undefined) {\n cancelTimer(id.current);\n id.current = undefined;\n }\n }, [cancelTimer]);\n\n // Clean up the timeout when the component is unloaded\n React.useEffect(() => cancel, [cancel]);\n\n return [set, cancel] as const;\n}\n"],"names":["React","useBrowserTimer","setTimer","cancelTimer","id","useRef","undefined","set","useCallback","fn","delay","current","cancel","useEffect"],"mappings":"AAAA;AAEA,YAAYA,WAAW,QAAQ;AAM/B;;;;;;;;;;;;;;;CAeC,GACD,OAAO,SAASC,gBACdC,QAA4B,EAC5BC,WAAiC;IAEjC,MAAMC,KAAKJ,MAAMK,MAAM,CAAqBC;IAE5C,MAAMC,MAAMP,MAAMQ,WAAW,CAC3B,CAACC,IAAgBC;QACf,IAAIN,GAAGO,OAAO,KAAKL,WAAW;YAC5BH,YAAYC,GAAGO,OAAO;QACxB;QAEAP,GAAGO,OAAO,GAAGT,SAASO,IAAIC;QAC1B,OAAON,GAAGO,OAAO;IACnB,GACA;QAACR;QAAaD;KAAS;IAGzB,MAAMU,SAASZ,MAAMQ,WAAW,CAAC;QAC/B,IAAIJ,GAAGO,OAAO,KAAKL,WAAW;YAC5BH,YAAYC,GAAGO,OAAO;YACtBP,GAAGO,OAAO,GAAGL;QACf;IACF,GAAG;QAACH;KAAY;IAEhB,sDAAsD;IACtDH,MAAMa,SAAS,CAAC,IAAMD,QAAQ;QAACA;KAAO;IAEtC,OAAO;QAACL;QAAKK;KAAO;AACtB"}

View File

@@ -0,0 +1,92 @@
'use client';
import * as React from 'react';
function isFactoryDispatch(newState) {
return typeof newState === 'function';
}
/**
* @internal
*
* A [`useState`](https://reactjs.org/docs/hooks-reference.html#usestate)-like hook
* to manage a value that could be either `controlled` or `uncontrolled`,
* such as a checked state or text input string.
*
* @see https://react.dev/learn/sharing-state-between-components#controlled-and-uncontrolled-components for more details on `controlled`/`uncontrolled`
*
* @returns an array of the current value and an updater (dispatcher) function.
* The updater function is referentially stable (won't change during the component's lifecycle).
* It can take either a new value, or a function which is passed the previous value and returns the new value.
*
* ❗️❗️ Calls to the dispatcher will only modify the state if the state is `uncontrolled`.
* Meaning that if a state is `controlled`, calls to the dispatcher do not modify the state.
*
*/ export const useControllableState = (options)=>{
'use no memo';
if (process.env.NODE_ENV !== 'production') {
if (options.state !== undefined && options.defaultState !== undefined) {
// eslint-disable-next-line no-console
console.error(`@fluentui/react-utilities [useControllableState]:
A component must be either controlled or uncontrolled (specify either the state or the defaultState, but not both).
Decide between using a controlled or uncontrolled component and remove one of this props.
More info: https://reactjs.org/link/controlled-components
${new Error().stack}`);
}
}
const [internalState, setInternalState] = React.useState(()=>{
if (options.defaultState === undefined) {
return options.initialState;
}
return isInitializer(options.defaultState) ? options.defaultState() : options.defaultState;
});
// Heads up!
// This part is specific for controlled mode and mocks behavior of React dispatcher function.
const stateValueRef = React.useRef(options.state);
React.useEffect(()=>{
stateValueRef.current = options.state;
}, [
options.state
]);
const setControlledState = React.useCallback((newState)=>{
if (isFactoryDispatch(newState)) {
newState(stateValueRef.current);
}
}, []);
return useIsControlled(options.state) ? [
options.state,
setControlledState
] : [
internalState,
setInternalState
];
};
function isInitializer(value) {
return typeof value === 'function';
}
/**
* Helper hook to handle previous comparison of controlled/uncontrolled
* Prints an error when isControlled value switches between subsequent renders
* @returns - whether the value is controlled
*/ const useIsControlled = (controlledValue)=>{
'use no memo';
const [isControlled] = React.useState(()=>controlledValue !== undefined);
if (process.env.NODE_ENV !== 'production') {
// We don't want these warnings in production even though it is against native behaviour
// eslint-disable-next-line react-hooks/rules-of-hooks
React.useEffect(()=>{
if (isControlled !== (controlledValue !== undefined)) {
const error = new Error();
const controlWarning = isControlled ? 'a controlled value to be uncontrolled' : 'an uncontrolled value to be controlled';
const undefinedWarning = isControlled ? 'defined to an undefined' : 'undefined to a defined';
// eslint-disable-next-line no-console
console.error(`@fluentui/react-utilities [useControllableState]:
A component is changing ${controlWarning}. This is likely caused by the value changing from ${undefinedWarning} value, which should not happen.
Decide between using a controlled or uncontrolled input element for the lifetime of the component.
More info: https://reactjs.org/link/controlled-components
${error.stack}`);
}
}, [
isControlled,
controlledValue
]);
}
return isControlled;
};

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,31 @@
'use client';
import * as React from 'react';
import { useIsomorphicLayoutEffect } from './useIsomorphicLayoutEffect';
/**
* @internal
* https://reactjs.org/docs/hooks-faq.html#how-to-read-an-often-changing-value-from-usecallback
*
* Modified `useCallback` that can be used when dependencies change too frequently. Can occur when
* e.g. user props are dependencies which could change on every render
* e.g. volatile values (i.e. useState/useDispatch) are dependencies which could change frequently
*
* This should not be used often, but can be a useful re-render optimization since the callback is a ref and
* will not be invalidated between re-renders
*
* @param fn - The callback function that will be used
*/ export const useEventCallback = (fn)=>{
const callbackRef = React.useRef(()=>{
throw new Error('Cannot call an event handler while rendering');
});
useIsomorphicLayoutEffect(()=>{
callbackRef.current = fn;
}, [
fn
]);
return React.useCallback((...args)=>{
const callback = callbackRef.current;
return callback(...args);
}, [
callbackRef
]);
};

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../src/hooks/useEventCallback.ts"],"sourcesContent":["'use client';\n\nimport * as React from 'react';\nimport { useIsomorphicLayoutEffect } from './useIsomorphicLayoutEffect';\n\n/**\n * @internal\n * https://reactjs.org/docs/hooks-faq.html#how-to-read-an-often-changing-value-from-usecallback\n *\n * Modified `useCallback` that can be used when dependencies change too frequently. Can occur when\n * e.g. user props are dependencies which could change on every render\n * e.g. volatile values (i.e. useState/useDispatch) are dependencies which could change frequently\n *\n * This should not be used often, but can be a useful re-render optimization since the callback is a ref and\n * will not be invalidated between re-renders\n *\n * @param fn - The callback function that will be used\n */\nexport const useEventCallback = <Args extends unknown[], Return>(\n fn: (...args: Args) => Return,\n): ((...args: Args) => Return) => {\n const callbackRef = React.useRef<typeof fn>(() => {\n throw new Error('Cannot call an event handler while rendering');\n });\n\n useIsomorphicLayoutEffect(() => {\n callbackRef.current = fn;\n }, [fn]);\n\n return React.useCallback(\n (...args: Args) => {\n const callback = callbackRef.current;\n return callback(...args);\n },\n [callbackRef],\n );\n};\n"],"names":["React","useIsomorphicLayoutEffect","useEventCallback","fn","callbackRef","useRef","Error","current","useCallback","args","callback"],"mappings":"AAAA;AAEA,YAAYA,WAAW,QAAQ;AAC/B,SAASC,yBAAyB,QAAQ,8BAA8B;AAExE;;;;;;;;;;;;CAYC,GACD,OAAO,MAAMC,mBAAmB,CAC9BC;IAEA,MAAMC,cAAcJ,MAAMK,MAAM,CAAY;QAC1C,MAAM,IAAIC,MAAM;IAClB;IAEAL,0BAA0B;QACxBG,YAAYG,OAAO,GAAGJ;IACxB,GAAG;QAACA;KAAG;IAEP,OAAOH,MAAMQ,WAAW,CACtB,CAAC,GAAGC;QACF,MAAMC,WAAWN,YAAYG,OAAO;QACpC,OAAOG,YAAYD;IACrB,GACA;QAACL;KAAY;AAEjB,EAAE"}

View File

@@ -0,0 +1,19 @@
'use client';
import * as React from 'react';
/**
* @internal
* Checks if components was mounted the first time.
* Supports React concurrent/strict mode by using `useEffect`
* to track the first mount instead of mutating refs during render.
*
* @example
* const isFirstMount = useFirstMount();
*/ export function useFirstMount() {
const isFirst = React.useRef(true);
React.useEffect(()=>{
if (isFirst.current) {
isFirst.current = false;
}
}, []);
return isFirst.current;
}

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../src/hooks/useFirstMount.ts"],"sourcesContent":["'use client';\n\nimport * as React from 'react';\n\n/**\n * @internal\n * Checks if components was mounted the first time.\n * Supports React concurrent/strict mode by using `useEffect`\n * to track the first mount instead of mutating refs during render.\n *\n * @example\n * const isFirstMount = useFirstMount();\n */\nexport function useFirstMount(): boolean {\n const isFirst = React.useRef(true);\n\n React.useEffect(() => {\n if (isFirst.current) {\n isFirst.current = false;\n }\n }, []);\n\n return isFirst.current;\n}\n"],"names":["React","useFirstMount","isFirst","useRef","useEffect","current"],"mappings":"AAAA;AAEA,YAAYA,WAAW,QAAQ;AAE/B;;;;;;;;CAQC,GACD,OAAO,SAASC;IACd,MAAMC,UAAUF,MAAMG,MAAM,CAAC;IAE7BH,MAAMI,SAAS,CAAC;QACd,IAAIF,QAAQG,OAAO,EAAE;YACnBH,QAAQG,OAAO,GAAG;QACpB;IACF,GAAG,EAAE;IAEL,OAAOH,QAAQG,OAAO;AACxB"}

View File

@@ -0,0 +1,8 @@
'use client';
import * as React from 'react';
/**
* @internal
* Forces a re-render, similar to `forceUpdate` in class components.
*/ export function useForceUpdate() {
return React.useReducer((x)=>x + 1, 0)[1];
}

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../src/hooks/useForceUpdate.ts"],"sourcesContent":["'use client';\n\nimport * as React from 'react';\n/**\n * @internal\n * Forces a re-render, similar to `forceUpdate` in class components.\n */\nexport function useForceUpdate(): React.DispatchWithoutAction {\n return React.useReducer(x => x + 1, 0)[1];\n}\n"],"names":["React","useForceUpdate","useReducer","x"],"mappings":"AAAA;AAEA,YAAYA,WAAW,QAAQ;AAC/B;;;CAGC,GACD,OAAO,SAASC;IACd,OAAOD,MAAME,UAAU,CAACC,CAAAA,IAAKA,IAAI,GAAG,EAAE,CAAC,EAAE;AAC3C"}

View File

@@ -0,0 +1,53 @@
'use client';
import * as React from 'react';
import { defaultSSRContextValue, useSSRContext } from '../ssr/index';
const IdPrefixContext = React.createContext(undefined);
/**
* Allows to define a prefix that will be used for all IDs generated by useId() hook. It's useful to avoid collisions
* between different bundles.
*/ export const IdPrefixProvider = IdPrefixContext.Provider;
function useIdPrefix() {
return React.useContext(IdPrefixContext) || '';
}
/**
* Resets generated IDs, should be used only in tests.
*/ export function resetIdsForTests() {
defaultSSRContextValue.current = 0;
}
/**
* Hook to generate a unique ID.
*
* @param prefix - Optional prefix for the ID. Defaults to 'fui-'.
* @param providedId - Optional id provided by a parent component. Defaults to the provided value if present,
* without conditioning the hook call
* @returns The ID
*/ export function useId(prefix = 'fui-', providedId) {
'use no memo';
const contextValue = useSSRContext();
const idPrefix = useIdPrefix();
// Checking if useId is available on React, if it is, we use it to generate the id. String concatenation is used to
// prevent bundlers from complaining with older versions of React.
const _useId = React['use' + 'Id'];
if (_useId) {
const generatedId = _useId();
// eslint-disable-next-line react-hooks/rules-of-hooks
const escapedId = React.useMemo(()=>generatedId.replace(/:/g, ''), [
generatedId
]);
return providedId || `${idPrefix}${prefix}${escapedId}`;
}
// Hooks appear to be running conditionally, but they will always run in the same order since it's based on
// the version of React being used. This is safe to ignore.
// eslint-disable-next-line react-hooks/rules-of-hooks
return React.useMemo(()=>{
if (providedId) {
return providedId;
}
return `${idPrefix}${prefix}${++contextValue.current}`;
}, [
idPrefix,
prefix,
providedId,
contextValue
]);
}

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../src/hooks/useId.ts"],"sourcesContent":["'use client';\n\nimport * as React from 'react';\nimport { defaultSSRContextValue, useSSRContext } from '../ssr/index';\n\nconst IdPrefixContext = React.createContext<string | undefined>(undefined);\n\n/**\n * Allows to define a prefix that will be used for all IDs generated by useId() hook. It's useful to avoid collisions\n * between different bundles.\n */\nexport const IdPrefixProvider = IdPrefixContext.Provider;\n\nfunction useIdPrefix(): string {\n return React.useContext(IdPrefixContext) || '';\n}\n\n/**\n * Resets generated IDs, should be used only in tests.\n */\nexport function resetIdsForTests(): void {\n defaultSSRContextValue.current = 0;\n}\n\n/**\n * Hook to generate a unique ID.\n *\n * @param prefix - Optional prefix for the ID. Defaults to 'fui-'.\n * @param providedId - Optional id provided by a parent component. Defaults to the provided value if present,\n * without conditioning the hook call\n * @returns The ID\n */\nexport function useId(prefix: string = 'fui-', providedId?: string): string {\n 'use no memo';\n\n const contextValue = useSSRContext();\n const idPrefix = useIdPrefix();\n\n // Checking if useId is available on React, if it is, we use it to generate the id. String concatenation is used to\n // prevent bundlers from complaining with older versions of React.\n const _useId = (React as never)['use' + 'Id'] as (() => string) | undefined;\n\n if (_useId) {\n const generatedId = _useId();\n\n // eslint-disable-next-line react-hooks/rules-of-hooks\n const escapedId = React.useMemo(() => generatedId.replace(/:/g, ''), [generatedId]);\n\n return providedId || `${idPrefix}${prefix}${escapedId}`;\n }\n\n // Hooks appear to be running conditionally, but they will always run in the same order since it's based on\n // the version of React being used. This is safe to ignore.\n // eslint-disable-next-line react-hooks/rules-of-hooks\n return React.useMemo(() => {\n if (providedId) {\n return providedId;\n }\n\n return `${idPrefix}${prefix}${++contextValue.current}`;\n }, [idPrefix, prefix, providedId, contextValue]);\n}\n"],"names":["React","defaultSSRContextValue","useSSRContext","IdPrefixContext","createContext","undefined","IdPrefixProvider","Provider","useIdPrefix","useContext","resetIdsForTests","current","useId","prefix","providedId","contextValue","idPrefix","_useId","generatedId","escapedId","useMemo","replace"],"mappings":"AAAA;AAEA,YAAYA,WAAW,QAAQ;AAC/B,SAASC,sBAAsB,EAAEC,aAAa,QAAQ,eAAe;AAErE,MAAMC,kBAAkBH,MAAMI,aAAa,CAAqBC;AAEhE;;;CAGC,GACD,OAAO,MAAMC,mBAAmBH,gBAAgBI,QAAQ,CAAC;AAEzD,SAASC;IACP,OAAOR,MAAMS,UAAU,CAACN,oBAAoB;AAC9C;AAEA;;CAEC,GACD,OAAO,SAASO;IACdT,uBAAuBU,OAAO,GAAG;AACnC;AAEA;;;;;;;CAOC,GACD,OAAO,SAASC,MAAMC,SAAiB,MAAM,EAAEC,UAAmB;IAChE;IAEA,MAAMC,eAAeb;IACrB,MAAMc,WAAWR;IAEjB,mHAAmH;IACnH,kEAAkE;IAClE,MAAMS,SAAS,AAACjB,KAAe,CAAC,QAAQ,KAAK;IAE7C,IAAIiB,QAAQ;QACV,MAAMC,cAAcD;QAEpB,sDAAsD;QACtD,MAAME,YAAYnB,MAAMoB,OAAO,CAAC,IAAMF,YAAYG,OAAO,CAAC,MAAM,KAAK;YAACH;SAAY;QAElF,OAAOJ,cAAc,GAAGE,WAAWH,SAASM,WAAW;IACzD;IAEA,2GAA2G;IAC3G,2DAA2D;IAC3D,sDAAsD;IACtD,OAAOnB,MAAMoB,OAAO,CAAC;QACnB,IAAIN,YAAY;YACd,OAAOA;QACT;QAEA,OAAO,GAAGE,WAAWH,SAAS,EAAEE,aAAaJ,OAAO,EAAE;IACxD,GAAG;QAACK;QAAUH;QAAQC;QAAYC;KAAa;AACjD"}

View File

@@ -0,0 +1,13 @@
'use client';
import * as React from 'react';
import { canUseDOM } from '../ssr/index';
/**
* React currently throws a warning when using useLayoutEffect on the server. To get around it, we can conditionally
* useEffect on the server (no-op) and useLayoutEffect in the browser. We occasionally need useLayoutEffect to
* ensure we don't get a render flash for certain operations, but we may also need affected components to render on
* the server.
*
* https://gist.github.com/gaearon/e7d97cdf38a2907924ea12e4ebdf3c85
* https://github.com/reduxjs/react-redux/blob/master/src/utils/useIsomorphicLayoutEffect.js
*/ // eslint-disable-next-line no-restricted-properties
export const useIsomorphicLayoutEffect = canUseDOM() ? React.useLayoutEffect : React.useEffect;

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../src/hooks/useIsomorphicLayoutEffect.ts"],"sourcesContent":["'use client';\n\nimport * as React from 'react';\nimport { canUseDOM } from '../ssr/index';\n\n/**\n * React currently throws a warning when using useLayoutEffect on the server. To get around it, we can conditionally\n * useEffect on the server (no-op) and useLayoutEffect in the browser. We occasionally need useLayoutEffect to\n * ensure we don't get a render flash for certain operations, but we may also need affected components to render on\n * the server.\n *\n * https://gist.github.com/gaearon/e7d97cdf38a2907924ea12e4ebdf3c85\n * https://github.com/reduxjs/react-redux/blob/master/src/utils/useIsomorphicLayoutEffect.js\n */\n// eslint-disable-next-line no-restricted-properties\nexport const useIsomorphicLayoutEffect: typeof React.useEffect = canUseDOM() ? React.useLayoutEffect : React.useEffect;\n"],"names":["React","canUseDOM","useIsomorphicLayoutEffect","useLayoutEffect","useEffect"],"mappings":"AAAA;AAEA,YAAYA,WAAW,QAAQ;AAC/B,SAASC,SAAS,QAAQ,eAAe;AAEzC;;;;;;;;CAQC,GACD,oDAAoD;AACpD,OAAO,MAAMC,4BAAoDD,cAAcD,MAAMG,eAAe,GAAGH,MAAMI,SAAS,CAAC"}

View File

@@ -0,0 +1,34 @@
'use client';
import * as React from 'react';
/**
* React hook to merge multiple React refs (either MutableRefObjects or ref callbacks) into a single ref callback that
* updates all provided refs
* @param refs - Refs to collectively update with one ref value.
* @returns A function with an attached "current" prop, so that it can be treated like a RefObject.
*/ // LegacyRef is actually not supported, but in React v18 types this is leaking directly from forwardRef component declaration
export function useMergedRefs(...refs) {
'use no memo';
const mergedCallback = React.useCallback((value)=>{
// Update the "current" prop hanging on the function.
mergedCallback.current = value;
for (const ref of refs){
if (typeof ref === 'string' && process.env.NODE_ENV !== 'production') {
// eslint-disable-next-line no-console
console.error(`@fluentui/react-utilities [useMergedRefs]:
This hook does not support the usage of string refs. Please use React.useRef instead.
For more info on 'React.useRef', see https://react.dev/reference/react/useRef.
For more info on string refs, see https://react.dev/blog/2024/04/25/react-19-upgrade-guide#removed-string-refs.`);
}
if (typeof ref === 'function') {
ref(value);
} else if (ref) {
ref.current = value;
}
}
}, // eslint-disable-next-line react-hooks/exhaustive-deps -- already exhaustive
[
...refs
]);
return mergedCallback;
}

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../src/hooks/useMergedRefs.ts"],"sourcesContent":["'use client';\n\nimport * as React from 'react';\n\n/**\n * A Ref function which can be treated like a ref object in that it has an attached\n * current property, which will be updated as the ref is evaluated.\n */\nexport type RefObjectFunction<T> = React.RefObject<T | null> & ((value: T | null) => void);\n\n/**\n * React hook to merge multiple React refs (either MutableRefObjects or ref callbacks) into a single ref callback that\n * updates all provided refs\n * @param refs - Refs to collectively update with one ref value.\n * @returns A function with an attached \"current\" prop, so that it can be treated like a RefObject.\n */\n// LegacyRef is actually not supported, but in React v18 types this is leaking directly from forwardRef component declaration\nexport function useMergedRefs<T>(...refs: (React.Ref<T> | undefined)[]): RefObjectFunction<T> {\n 'use no memo';\n\n const mergedCallback = React.useCallback(\n (value: T | null) => {\n // Update the \"current\" prop hanging on the function.\n mergedCallback.current = value;\n\n for (const ref of refs) {\n if (typeof ref === 'string' && process.env.NODE_ENV !== 'production') {\n // eslint-disable-next-line no-console\n console.error(/** #__DE-INDENT__ */ `\n @fluentui/react-utilities [useMergedRefs]:\n This hook does not support the usage of string refs. Please use React.useRef instead.\n\n For more info on 'React.useRef', see https://react.dev/reference/react/useRef.\n For more info on string refs, see https://react.dev/blog/2024/04/25/react-19-upgrade-guide#removed-string-refs.\n `);\n }\n if (typeof ref === 'function') {\n ref(value);\n } else if (ref) {\n ref.current = value;\n }\n }\n },\n // eslint-disable-next-line react-hooks/exhaustive-deps -- already exhaustive\n [...refs],\n ) as RefObjectFunction<T>;\n\n return mergedCallback;\n}\n"],"names":["React","useMergedRefs","refs","mergedCallback","useCallback","value","current","ref","process","env","NODE_ENV","console","error"],"mappings":"AAAA;AAEA,YAAYA,WAAW,QAAQ;AAQ/B;;;;;CAKC,GACD,6HAA6H;AAC7H,OAAO,SAASC,cAAiB,GAAGC,IAAkC;IACpE;IAEA,MAAMC,iBAAiBH,MAAMI,WAAW,CACtC,CAACC;QACC,qDAAqD;QACrDF,eAAeG,OAAO,GAAGD;QAEzB,KAAK,MAAME,OAAOL,KAAM;YACtB,IAAI,OAAOK,QAAQ,YAAYC,QAAQC,GAAG,CAACC,QAAQ,KAAK,cAAc;gBACpE,sCAAsC;gBACtCC,QAAQC,KAAK,CAAuB,CAAC;;;;+GAMrC,CAAC;YACH;YACA,IAAI,OAAOL,QAAQ,YAAY;gBAC7BA,IAAIF;YACN,OAAO,IAAIE,KAAK;gBACdA,IAAID,OAAO,GAAGD;YAChB;QACF;IACF,GACA,6EAA6E;IAC7E;WAAIH;KAAK;IAGX,OAAOC;AACT"}

View File

@@ -0,0 +1,150 @@
'use client';
import * as React from 'react';
import { useEventCallback } from './useEventCallback';
import { useFluent_unstable as useFluent } from '@fluentui/react-shared-contexts';
const DEFAULT_CONTAINS = (parent, child)=>!!(parent === null || parent === void 0 ? void 0 : parent.contains(child));
/**
* @internal
* Utility to perform checks where a click/touch event was made outside a component
*/ export const useOnClickOutside = (options)=>{
const { targetDocument } = useFluent();
const win = targetDocument === null || targetDocument === void 0 ? void 0 : targetDocument.defaultView;
const { refs, callback, element, disabled, disabledFocusOnIframe, contains = DEFAULT_CONTAINS } = options;
const timeoutId = React.useRef(undefined);
useIFrameFocus({
element,
disabled: disabledFocusOnIframe || disabled,
callback,
refs,
contains
});
const isMouseDownInsideRef = React.useRef(false);
const listener = useEventCallback((ev)=>{
if (isMouseDownInsideRef.current) {
isMouseDownInsideRef.current = false;
return;
}
const target = ev.composedPath()[0];
const isOutside = refs.every((ref)=>!contains(ref.current || null, target));
if (isOutside && !disabled) {
callback(ev);
}
});
const handleMouseDown = useEventCallback((ev)=>{
// Selecting text from inside to outside will rigger click event.
// In this case click event target is outside but mouse down event target is inside.
// And this click event should be considered as inside click.
isMouseDownInsideRef.current = refs.some((ref)=>contains(ref.current || null, ev.target));
});
React.useEffect(()=>{
if (disabled) {
return;
}
// Store the current event to avoid triggering handlers immediately
// Note this depends on a deprecated but extremely well supported quirk of the web platform
// https://github.com/facebook/react/issues/20074
let currentEvent = getWindowEvent(win);
const conditionalHandler = (event)=>{
// Skip if this event is the same as the one running when we added the handlers
if (event === currentEvent) {
currentEvent = undefined;
return;
}
listener(event);
};
// use capture phase because React can update DOM before the event bubbles to the document
element === null || element === void 0 ? void 0 : element.addEventListener('click', conditionalHandler, true);
element === null || element === void 0 ? void 0 : element.addEventListener('touchstart', conditionalHandler, true);
element === null || element === void 0 ? void 0 : element.addEventListener('contextmenu', conditionalHandler, true);
element === null || element === void 0 ? void 0 : element.addEventListener('mousedown', handleMouseDown, true);
// Garbage collect this event after it's no longer useful to avoid memory leaks
timeoutId.current = win === null || win === void 0 ? void 0 : win.setTimeout(()=>{
currentEvent = undefined;
}, 1);
return ()=>{
element === null || element === void 0 ? void 0 : element.removeEventListener('click', conditionalHandler, true);
element === null || element === void 0 ? void 0 : element.removeEventListener('touchstart', conditionalHandler, true);
element === null || element === void 0 ? void 0 : element.removeEventListener('contextmenu', conditionalHandler, true);
element === null || element === void 0 ? void 0 : element.removeEventListener('mousedown', handleMouseDown, true);
win === null || win === void 0 ? void 0 : win.clearTimeout(timeoutId.current);
currentEvent = undefined;
};
}, [
listener,
element,
disabled,
handleMouseDown,
win
]);
};
const getWindowEvent = (target)=>{
if (target) {
var _target_ownerDocument_defaultView, _target_ownerDocument;
if (typeof target.window === 'object' && target.window === target) {
// eslint-disable-next-line @typescript-eslint/no-deprecated
return target.event;
}
var _target_ownerDocument_defaultView_event;
// eslint-disable-next-line @typescript-eslint/no-deprecated
return (_target_ownerDocument_defaultView_event = (_target_ownerDocument = target.ownerDocument) === null || _target_ownerDocument === void 0 ? void 0 : (_target_ownerDocument_defaultView = _target_ownerDocument.defaultView) === null || _target_ownerDocument_defaultView === void 0 ? void 0 : _target_ownerDocument_defaultView.event) !== null && _target_ownerDocument_defaultView_event !== void 0 ? _target_ownerDocument_defaultView_event : undefined;
}
return undefined;
};
const FUI_FRAME_EVENT = 'fuiframefocus';
/**
* Since click events do not propagate past iframes, we use focus to detect if a
* click has happened inside an iframe, since the only ways of focusing inside an
* iframe are:
* - clicking inside
* - tabbing inside
*
* Polls the value of `document.activeElement`. If it is an iframe, then dispatch
* a custom DOM event. When the custom event is received call the provided callback
*/ const useIFrameFocus = (options)=>{
const { disabled, element: targetDocument, callback, contains = DEFAULT_CONTAINS, pollDuration = 100, refs } = options;
const timeoutRef = React.useRef(undefined);
const listener = useEventCallback((e)=>{
const isOutside = refs.every((ref)=>!contains(ref.current || null, e.target));
if (isOutside && !disabled) {
callback(e);
}
});
// Adds listener to the custom iframe focus event
React.useEffect(()=>{
if (disabled) {
return;
}
targetDocument === null || targetDocument === void 0 ? void 0 : targetDocument.addEventListener(FUI_FRAME_EVENT, listener, true);
return ()=>{
targetDocument === null || targetDocument === void 0 ? void 0 : targetDocument.removeEventListener(FUI_FRAME_EVENT, listener, true);
};
}, [
targetDocument,
disabled,
listener
]);
// Starts polling for the active element
React.useEffect(()=>{
var _targetDocument_defaultView;
if (disabled) {
return;
}
timeoutRef.current = targetDocument === null || targetDocument === void 0 ? void 0 : (_targetDocument_defaultView = targetDocument.defaultView) === null || _targetDocument_defaultView === void 0 ? void 0 : _targetDocument_defaultView.setInterval(()=>{
const activeElement = targetDocument === null || targetDocument === void 0 ? void 0 : targetDocument.activeElement;
if ((activeElement === null || activeElement === void 0 ? void 0 : activeElement.tagName) === 'IFRAME' || (activeElement === null || activeElement === void 0 ? void 0 : activeElement.tagName) === 'WEBVIEW') {
const event = new CustomEvent(FUI_FRAME_EVENT, {
bubbles: true
});
activeElement.dispatchEvent(event);
}
}, pollDuration);
return ()=>{
var _targetDocument_defaultView;
targetDocument === null || targetDocument === void 0 ? void 0 : (_targetDocument_defaultView = targetDocument.defaultView) === null || _targetDocument_defaultView === void 0 ? void 0 : _targetDocument_defaultView.clearInterval(timeoutRef.current);
};
}, [
targetDocument,
disabled,
pollDuration
]);
};

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,32 @@
'use client';
import * as React from 'react';
import { useEventCallback } from './useEventCallback';
/**
* @internal
* Utility to perform checks where a click/touch event was made outside a component
*/ export const useOnScrollOutside = (options)=>{
const { refs, callback, element, disabled, contains: containsProp } = options;
const listener = useEventCallback((ev)=>{
const contains = containsProp || ((parent, child)=>!!(parent === null || parent === void 0 ? void 0 : parent.contains(child)));
const target = ev.composedPath()[0];
const isOutside = refs.every((ref)=>!contains(ref.current || null, target));
if (isOutside && !disabled) {
callback(ev);
}
});
React.useEffect(()=>{
if (disabled) {
return;
}
element === null || element === void 0 ? void 0 : element.addEventListener('wheel', listener);
element === null || element === void 0 ? void 0 : element.addEventListener('touchmove', listener);
return ()=>{
element === null || element === void 0 ? void 0 : element.removeEventListener('wheel', listener);
element === null || element === void 0 ? void 0 : element.removeEventListener('touchmove', listener);
};
}, [
listener,
element,
disabled
]);
};

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../src/hooks/useOnScrollOutside.ts"],"sourcesContent":["'use client';\n\nimport * as React from 'react';\nimport { useEventCallback } from './useEventCallback';\nimport type { UseOnClickOrScrollOutsideOptions } from './useOnClickOutside';\n\n/**\n * @internal\n * Utility to perform checks where a click/touch event was made outside a component\n */\nexport const useOnScrollOutside = (options: UseOnClickOrScrollOutsideOptions): void => {\n const { refs, callback, element, disabled, contains: containsProp } = options;\n\n const listener = useEventCallback((ev: MouseEvent | TouchEvent) => {\n const contains: UseOnClickOrScrollOutsideOptions['contains'] =\n containsProp || ((parent, child) => !!parent?.contains(child));\n\n const target = ev.composedPath()[0] as HTMLElement;\n const isOutside = refs.every(ref => !contains(ref.current || null, target));\n\n if (isOutside && !disabled) {\n callback(ev);\n }\n });\n\n React.useEffect(() => {\n if (disabled) {\n return;\n }\n\n element?.addEventListener('wheel', listener);\n element?.addEventListener('touchmove', listener);\n\n return () => {\n element?.removeEventListener('wheel', listener);\n element?.removeEventListener('touchmove', listener);\n };\n }, [listener, element, disabled]);\n};\n"],"names":["React","useEventCallback","useOnScrollOutside","options","refs","callback","element","disabled","contains","containsProp","listener","ev","parent","child","target","composedPath","isOutside","every","ref","current","useEffect","addEventListener","removeEventListener"],"mappings":"AAAA;AAEA,YAAYA,WAAW,QAAQ;AAC/B,SAASC,gBAAgB,QAAQ,qBAAqB;AAGtD;;;CAGC,GACD,OAAO,MAAMC,qBAAqB,CAACC;IACjC,MAAM,EAAEC,IAAI,EAAEC,QAAQ,EAAEC,OAAO,EAAEC,QAAQ,EAAEC,UAAUC,YAAY,EAAE,GAAGN;IAEtE,MAAMO,WAAWT,iBAAiB,CAACU;QACjC,MAAMH,WACJC,gBAAiB,CAAA,CAACG,QAAQC,QAAU,CAAC,EAACD,mBAAAA,6BAAAA,OAAQJ,QAAQ,CAACK,OAAK;QAE9D,MAAMC,SAASH,GAAGI,YAAY,EAAE,CAAC,EAAE;QACnC,MAAMC,YAAYZ,KAAKa,KAAK,CAACC,CAAAA,MAAO,CAACV,SAASU,IAAIC,OAAO,IAAI,MAAML;QAEnE,IAAIE,aAAa,CAACT,UAAU;YAC1BF,SAASM;QACX;IACF;IAEAX,MAAMoB,SAAS,CAAC;QACd,IAAIb,UAAU;YACZ;QACF;QAEAD,oBAAAA,8BAAAA,QAASe,gBAAgB,CAAC,SAASX;QACnCJ,oBAAAA,8BAAAA,QAASe,gBAAgB,CAAC,aAAaX;QAEvC,OAAO;YACLJ,oBAAAA,8BAAAA,QAASgB,mBAAmB,CAAC,SAASZ;YACtCJ,oBAAAA,8BAAAA,QAASgB,mBAAmB,CAAC,aAAaZ;QAC5C;IACF,GAAG;QAACA;QAAUJ;QAASC;KAAS;AAClC,EAAE"}

View File

@@ -0,0 +1,13 @@
'use client';
import * as React from 'react';
/**
* @internal
*/ export const usePrevious = (value)=>{
const ref = React.useRef(null);
React.useEffect(()=>{
ref.current = value;
}, [
value
]);
return ref.current;
};

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../src/hooks/usePrevious.ts"],"sourcesContent":["'use client';\n\nimport * as React from 'react';\n\n/**\n * @internal\n */\nexport const usePrevious = <ValueType = unknown>(value: ValueType): ValueType | null => {\n const ref = React.useRef<ValueType | null>(null);\n React.useEffect(() => {\n ref.current = value;\n }, [value]);\n return ref.current;\n};\n"],"names":["React","usePrevious","value","ref","useRef","useEffect","current"],"mappings":"AAAA;AAEA,YAAYA,WAAW,QAAQ;AAE/B;;CAEC,GACD,OAAO,MAAMC,cAAc,CAAsBC;IAC/C,MAAMC,MAAMH,MAAMI,MAAM,CAAmB;IAC3CJ,MAAMK,SAAS,CAAC;QACdF,IAAIG,OAAO,GAAGJ;IAChB,GAAG;QAACA;KAAM;IACV,OAAOC,IAAIG,OAAO;AACpB,EAAE"}

View File

@@ -0,0 +1,24 @@
'use client';
import * as React from 'react';
import { measureScrollbarWidth } from '../utils/measureScrollBarWidth';
const cache = new WeakMap();
/**
* @returns The width in pixels of the scrollbar in the user agent
* @remarks This hook is not SSR-safe. For SSR-safe scrollbar width application, use the `useApplyScrollbarWidth` from {@link file://./useApplyScrollbarWidth.ts} instead.
*/ export function useScrollbarWidth(options) {
const { targetDocument, force } = options;
return React.useMemo(()=>{
if (!targetDocument) {
return 0;
}
if (!force && cache.has(targetDocument)) {
return cache.get(targetDocument);
}
const scrollbarWidth = measureScrollbarWidth(targetDocument);
cache.set(targetDocument, scrollbarWidth);
return scrollbarWidth;
}, [
targetDocument,
force
]);
}

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../src/hooks/useScrollbarWidth.ts"],"sourcesContent":["'use client';\n\nimport * as React from 'react';\nimport { measureScrollbarWidth } from '../utils/measureScrollBarWidth';\n\nconst cache = new WeakMap<Document, number>();\n\ninterface UseScrollbarWidthOptions {\n /**\n * Reference document to measure the scrollbar width\n */\n targetDocument: Document | null | undefined;\n\n /**\n * Does not use the cache and recalculates the scrollbar width\n */\n force?: boolean;\n}\n\n/**\n * @returns The width in pixels of the scrollbar in the user agent\n * @remarks This hook is not SSR-safe. For SSR-safe scrollbar width application, use the `useApplyScrollbarWidth` from {@link file://./useApplyScrollbarWidth.ts} instead.\n */\nexport function useScrollbarWidth(options: UseScrollbarWidthOptions): number | undefined {\n const { targetDocument, force } = options;\n\n return React.useMemo(() => {\n if (!targetDocument) {\n return 0;\n }\n\n if (!force && cache.has(targetDocument)) {\n return cache.get(targetDocument);\n }\n\n const scrollbarWidth = measureScrollbarWidth(targetDocument);\n cache.set(targetDocument, scrollbarWidth);\n\n return scrollbarWidth;\n }, [targetDocument, force]);\n}\n"],"names":["React","measureScrollbarWidth","cache","WeakMap","useScrollbarWidth","options","targetDocument","force","useMemo","has","get","scrollbarWidth","set"],"mappings":"AAAA;AAEA,YAAYA,WAAW,QAAQ;AAC/B,SAASC,qBAAqB,QAAQ,iCAAiC;AAEvE,MAAMC,QAAQ,IAAIC;AAclB;;;CAGC,GACD,OAAO,SAASC,kBAAkBC,OAAiC;IACjE,MAAM,EAAEC,cAAc,EAAEC,KAAK,EAAE,GAAGF;IAElC,OAAOL,MAAMQ,OAAO,CAAC;QACnB,IAAI,CAACF,gBAAgB;YACnB,OAAO;QACT;QAEA,IAAI,CAACC,SAASL,MAAMO,GAAG,CAACH,iBAAiB;YACvC,OAAOJ,MAAMQ,GAAG,CAACJ;QACnB;QAEA,MAAMK,iBAAiBV,sBAAsBK;QAC7CJ,MAAMU,GAAG,CAACN,gBAAgBK;QAE1B,OAAOA;IACT,GAAG;QAACL;QAAgBC;KAAM;AAC5B"}

View File

@@ -0,0 +1,19 @@
'use client';
import { useBrowserTimer } from './useBrowserTimer';
import { useFluent_unstable as useFluent } from '@fluentui/react-shared-contexts';
const setTimeoutNoop = (_callback)=>-1;
const clearTimeoutNoop = (_handle)=>undefined;
/**
* @internal
* Helper to manage a browser timeout.
* Ensures that the timeout isn't set multiple times at once and is cleaned up
* when the component is unloaded.
*
* @returns A pair of [setTimeout, clearTimeout] that are stable between renders.
*/ export function useTimeout() {
const { targetDocument } = useFluent();
const win = targetDocument === null || targetDocument === void 0 ? void 0 : targetDocument.defaultView;
const setTimerFn = win ? win.setTimeout : setTimeoutNoop;
const clearTimerFn = win ? win.clearTimeout : clearTimeoutNoop;
return useBrowserTimer(setTimerFn, clearTimerFn);
}

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../src/hooks/useTimeout.ts"],"sourcesContent":["'use client';\n\nimport { useBrowserTimer } from './useBrowserTimer';\nimport { useFluent_unstable as useFluent } from '@fluentui/react-shared-contexts';\n\nconst setTimeoutNoop = (_callback: Function) => -1;\nconst clearTimeoutNoop = (_handle: number) => undefined;\n\n/**\n * @internal\n * Helper to manage a browser timeout.\n * Ensures that the timeout isn't set multiple times at once and is cleaned up\n * when the component is unloaded.\n *\n * @returns A pair of [setTimeout, clearTimeout] that are stable between renders.\n */\nexport function useTimeout(): readonly [(fn: () => void, delay?: number) => number, () => void] {\n const { targetDocument } = useFluent();\n const win = targetDocument?.defaultView;\n\n const setTimerFn = win ? win.setTimeout : setTimeoutNoop;\n const clearTimerFn = win ? win.clearTimeout : clearTimeoutNoop;\n\n return useBrowserTimer(setTimerFn, clearTimerFn);\n}\n"],"names":["useBrowserTimer","useFluent_unstable","useFluent","setTimeoutNoop","_callback","clearTimeoutNoop","_handle","undefined","useTimeout","targetDocument","win","defaultView","setTimerFn","setTimeout","clearTimerFn","clearTimeout"],"mappings":"AAAA;AAEA,SAASA,eAAe,QAAQ,oBAAoB;AACpD,SAASC,sBAAsBC,SAAS,QAAQ,kCAAkC;AAElF,MAAMC,iBAAiB,CAACC,YAAwB,CAAC;AACjD,MAAMC,mBAAmB,CAACC,UAAoBC;AAE9C;;;;;;;CAOC,GACD,OAAO,SAASC;IACd,MAAM,EAAEC,cAAc,EAAE,GAAGP;IAC3B,MAAMQ,MAAMD,2BAAAA,qCAAAA,eAAgBE,WAAW;IAEvC,MAAMC,aAAaF,MAAMA,IAAIG,UAAU,GAAGV;IAC1C,MAAMW,eAAeJ,MAAMA,IAAIK,YAAY,GAAGV;IAE9C,OAAOL,gBAAgBY,YAAYE;AACrC"}

12
node_modules/@fluentui/react-utilities/lib/index.js generated vendored Normal file
View File

@@ -0,0 +1,12 @@
export { slot, isSlot, // eslint-disable-next-line @typescript-eslint/no-deprecated
getSlots, // eslint-disable-next-line @typescript-eslint/no-deprecated
getSlotsNext, assertSlots, // eslint-disable-next-line @typescript-eslint/no-deprecated
resolveShorthand, isResolvedShorthand, getIntrinsicElementProps, getSlotClassNameProp_unstable, SLOT_CLASS_NAME_PROP_SYMBOL, SLOT_ELEMENT_TYPE_SYMBOL, SLOT_RENDER_FUNCTION_SYMBOL } from './compose/index';
export { IdPrefixProvider, resetIdsForTests, useAnimationFrame, useApplyScrollbarWidth, useControllableState, useEventCallback, useFirstMount, useForceUpdate, useId, useIsomorphicLayoutEffect, useMergedRefs, useOnClickOutside, useOnScrollOutside, usePrevious, useScrollbarWidth, useTimeout } from './hooks/index';
export { canUseDOM, useIsSSR, SSRProvider } from './ssr/index';
export { clamp, // eslint-disable-next-line @typescript-eslint/no-deprecated
getNativeElementProps, getPartitionedNativeProps, getReactElementRef, getRTLSafeKey, mergeCallbacks, isHTMLElement, isInteractiveHTMLElement, omit, createPriorityQueue } from './utils/index';
export { applyTriggerPropsToChildren, getTriggerChild, isFluentTrigger } from './trigger/index';
export { isTouchEvent, isMouseEvent, getEventClientCoords } from './events/index';
export { useSelection } from './selection/index';
export { elementContains, setVirtualParent, getParent } from './virtualParent/index';

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["export {\n slot,\n isSlot,\n // eslint-disable-next-line @typescript-eslint/no-deprecated\n getSlots,\n // eslint-disable-next-line @typescript-eslint/no-deprecated\n getSlotsNext,\n assertSlots,\n // eslint-disable-next-line @typescript-eslint/no-deprecated\n resolveShorthand,\n isResolvedShorthand,\n getIntrinsicElementProps,\n getSlotClassNameProp_unstable,\n SLOT_CLASS_NAME_PROP_SYMBOL,\n SLOT_ELEMENT_TYPE_SYMBOL,\n SLOT_RENDER_FUNCTION_SYMBOL,\n} from './compose/index';\nexport type {\n ExtractSlotProps,\n ComponentProps,\n ComponentState,\n ForwardRefComponent,\n RefAttributes,\n // eslint-disable-next-line @typescript-eslint/no-deprecated\n ResolveShorthandFunction,\n // eslint-disable-next-line @typescript-eslint/no-deprecated\n ResolveShorthandOptions,\n Slot,\n // eslint-disable-next-line @typescript-eslint/no-deprecated\n Slots,\n SlotClassNames,\n SlotPropsRecord,\n SlotRenderFunction,\n SlotShorthandValue,\n UnknownSlotProps,\n SlotComponentType,\n SlotOptions,\n InferredElementRefType,\n EventData,\n EventHandler,\n} from './compose/index';\n\nexport {\n IdPrefixProvider,\n resetIdsForTests,\n useAnimationFrame,\n useApplyScrollbarWidth,\n useControllableState,\n useEventCallback,\n useFirstMount,\n useForceUpdate,\n useId,\n useIsomorphicLayoutEffect,\n useMergedRefs,\n useOnClickOutside,\n useOnScrollOutside,\n usePrevious,\n useScrollbarWidth,\n useTimeout,\n} from './hooks/index';\nexport type { RefObjectFunction, UseControllableStateOptions, UseOnClickOrScrollOutsideOptions } from './hooks/index';\n\nexport { canUseDOM, useIsSSR, SSRProvider } from './ssr/index';\n\nexport {\n clamp,\n // eslint-disable-next-line @typescript-eslint/no-deprecated\n getNativeElementProps,\n getPartitionedNativeProps,\n getReactElementRef,\n getRTLSafeKey,\n mergeCallbacks,\n isHTMLElement,\n isInteractiveHTMLElement,\n omit,\n createPriorityQueue,\n} from './utils/index';\n\nexport type {\n DistributiveOmit,\n UnionToIntersection,\n JSXElement,\n JSXIntrinsicElement,\n JSXIntrinsicElementKeys,\n} from './utils/types';\n\nexport type { PriorityQueue } from './utils/priorityQueue';\n\nexport { applyTriggerPropsToChildren, getTriggerChild, isFluentTrigger } from './trigger/index';\n\nexport type { FluentTriggerComponent, TriggerProps } from './trigger/index';\n\n/**\n * Event utils\n */\nexport type { NativeTouchOrMouseEvent, ReactTouchOrMouseEvent, TouchOrMouseEvent } from './events/index';\nexport { isTouchEvent, isMouseEvent, getEventClientCoords } from './events/index';\n\nexport type {\n SelectionMode,\n OnSelectionChangeCallback,\n OnSelectionChangeData,\n SelectionItemId,\n SelectionHookParams,\n SelectionMethods,\n} from './selection/index';\nexport { useSelection } from './selection/index';\n\nexport { elementContains, setVirtualParent, getParent } from './virtualParent/index';\n"],"names":["slot","isSlot","getSlots","getSlotsNext","assertSlots","resolveShorthand","isResolvedShorthand","getIntrinsicElementProps","getSlotClassNameProp_unstable","SLOT_CLASS_NAME_PROP_SYMBOL","SLOT_ELEMENT_TYPE_SYMBOL","SLOT_RENDER_FUNCTION_SYMBOL","IdPrefixProvider","resetIdsForTests","useAnimationFrame","useApplyScrollbarWidth","useControllableState","useEventCallback","useFirstMount","useForceUpdate","useId","useIsomorphicLayoutEffect","useMergedRefs","useOnClickOutside","useOnScrollOutside","usePrevious","useScrollbarWidth","useTimeout","canUseDOM","useIsSSR","SSRProvider","clamp","getNativeElementProps","getPartitionedNativeProps","getReactElementRef","getRTLSafeKey","mergeCallbacks","isHTMLElement","isInteractiveHTMLElement","omit","createPriorityQueue","applyTriggerPropsToChildren","getTriggerChild","isFluentTrigger","isTouchEvent","isMouseEvent","getEventClientCoords","useSelection","elementContains","setVirtualParent","getParent"],"mappings":"AAAA,SACEA,IAAI,EACJC,MAAM,EACN,4DAA4D;AAC5DC,QAAQ,EACR,4DAA4D;AAC5DC,YAAY,EACZC,WAAW,EACX,4DAA4D;AAC5DC,gBAAgB,EAChBC,mBAAmB,EACnBC,wBAAwB,EACxBC,6BAA6B,EAC7BC,2BAA2B,EAC3BC,wBAAwB,EACxBC,2BAA2B,QACtB,kBAAkB;AA0BzB,SACEC,gBAAgB,EAChBC,gBAAgB,EAChBC,iBAAiB,EACjBC,sBAAsB,EACtBC,oBAAoB,EACpBC,gBAAgB,EAChBC,aAAa,EACbC,cAAc,EACdC,KAAK,EACLC,yBAAyB,EACzBC,aAAa,EACbC,iBAAiB,EACjBC,kBAAkB,EAClBC,WAAW,EACXC,iBAAiB,EACjBC,UAAU,QACL,gBAAgB;AAGvB,SAASC,SAAS,EAAEC,QAAQ,EAAEC,WAAW,QAAQ,cAAc;AAE/D,SACEC,KAAK,EACL,4DAA4D;AAC5DC,qBAAqB,EACrBC,yBAAyB,EACzBC,kBAAkB,EAClBC,aAAa,EACbC,cAAc,EACdC,aAAa,EACbC,wBAAwB,EACxBC,IAAI,EACJC,mBAAmB,QACd,gBAAgB;AAYvB,SAASC,2BAA2B,EAAEC,eAAe,EAAEC,eAAe,QAAQ,kBAAkB;AAQhG,SAASC,YAAY,EAAEC,YAAY,EAAEC,oBAAoB,QAAQ,iBAAiB;AAUlF,SAASC,YAAY,QAAQ,oBAAoB;AAEjD,SAASC,eAAe,EAAEC,gBAAgB,EAAEC,SAAS,QAAQ,wBAAwB"}

View File

@@ -0,0 +1 @@
export { useSelection } from './useSelection';

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../src/selection/index.ts"],"sourcesContent":["export type {\n OnSelectionChangeCallback,\n OnSelectionChangeData,\n SelectionHookParams,\n SelectionItemId,\n SelectionMethods,\n SelectionMode,\n} from './types';\nexport { useSelection } from './useSelection';\n"],"names":["useSelection"],"mappings":"AAQA,SAASA,YAAY,QAAQ,iBAAiB"}

View File

@@ -0,0 +1 @@
import * as React from 'react';

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../src/selection/types.ts"],"sourcesContent":["import * as React from 'react';\n\nexport type SelectionMode = 'single' | 'multiselect';\n\nexport interface SelectionMethods {\n toggleItem(event: React.SyntheticEvent, id: SelectionItemId): void;\n selectItem(event: React.SyntheticEvent, id: SelectionItemId): void;\n deselectItem(event: React.SyntheticEvent, id: SelectionItemId): void;\n clearItems(event: React.SyntheticEvent): void;\n isSelected(id: SelectionItemId): boolean;\n toggleAllItems(event: React.SyntheticEvent, itemIds: SelectionItemId[]): void;\n}\n\nexport type SelectionItemId = string | number;\n\nexport type OnSelectionChangeCallback = (event: React.SyntheticEvent, selectedItems: Set<SelectionItemId>) => void;\n\nexport type OnSelectionChangeData = {\n selectedItems: Set<SelectionItemId>;\n};\n\nexport type SelectionHookParams = {\n selectionMode: SelectionMode;\n /**\n * Used in uncontrolled mode to set initial selected items on mount\n */\n defaultSelectedItems?: Iterable<SelectionItemId>;\n /**\n * Used to control selected items\n */\n selectedItems?: Iterable<SelectionItemId>;\n /**\n * Called when selection changes\n */\n onSelectionChange?(event: React.SyntheticEvent, data: OnSelectionChangeData): void;\n};\n"],"names":["React"],"mappings":"AAAA,YAAYA,WAAW,QAAQ"}

View File

@@ -0,0 +1,105 @@
'use client';
import * as React from 'react';
import { useControllableState } from '../hooks/useControllableState';
import { createSetFromIterable } from '../utils/createSetFromIterable';
function useSelectionState(params) {
const [selected, setSelected] = useControllableState({
initialState: new Set(),
defaultState: React.useMemo(()=>params.defaultSelectedItems && createSetFromIterable(params.defaultSelectedItems), [
params.defaultSelectedItems
]),
state: React.useMemo(()=>params.selectedItems && createSetFromIterable(params.selectedItems), [
params.selectedItems
])
});
const changeSelection = (event, nextSelectedItems)=>{
var _params_onSelectionChange;
(_params_onSelectionChange = params.onSelectionChange) === null || _params_onSelectionChange === void 0 ? void 0 : _params_onSelectionChange.call(params, event, {
selectedItems: nextSelectedItems
});
setSelected(nextSelectedItems);
};
return [
selected,
changeSelection
];
}
function useSingleSelection(params) {
const [selected, changeSelection] = useSelectionState(params);
const methods = {
deselectItem: (event)=>changeSelection(event, new Set()),
selectItem: (event, itemId)=>changeSelection(event, new Set([
itemId
])),
toggleAllItems: ()=>{
if (process.env.NODE_ENV !== 'production') {
throw new Error('[react-utilities]: `toggleAllItems` should not be used in single selection mode');
}
},
toggleItem: (event, itemId)=>changeSelection(event, new Set([
itemId
])),
clearItems: (event)=>changeSelection(event, new Set()),
isSelected: (itemId)=>{
var _selected_has;
return (_selected_has = selected.has(itemId)) !== null && _selected_has !== void 0 ? _selected_has : false;
}
};
return [
selected,
methods
];
}
function useMultipleSelection(params) {
const [selected, changeSelection] = useSelectionState(params);
const methods = {
toggleItem: (event, itemId)=>{
const nextSelectedItems = new Set(selected);
if (selected.has(itemId)) {
nextSelectedItems.delete(itemId);
} else {
nextSelectedItems.add(itemId);
}
changeSelection(event, nextSelectedItems);
},
selectItem: (event, itemId)=>{
const nextSelectedItems = new Set(selected);
nextSelectedItems.add(itemId);
changeSelection(event, nextSelectedItems);
},
deselectItem: (event, itemId)=>{
const nextSelectedItems = new Set(selected);
nextSelectedItems.delete(itemId);
changeSelection(event, nextSelectedItems);
},
clearItems: (event)=>{
changeSelection(event, new Set());
},
isSelected: (itemId)=>selected.has(itemId),
toggleAllItems: (event, itemIds)=>{
const allItemsSelected = itemIds.every((itemId)=>selected.has(itemId));
const nextSelectedItems = new Set(selected);
if (allItemsSelected) {
nextSelectedItems.clear();
} else {
itemIds.forEach((itemId)=>nextSelectedItems.add(itemId));
}
changeSelection(event, nextSelectedItems);
}
};
return [
selected,
methods
];
}
export function useSelection(params) {
'use no memo';
if (params.selectionMode === 'multiselect') {
// selectionMode is a static value, so we can safely ignore rules-of-hooks
// eslint-disable-next-line react-hooks/rules-of-hooks
return useMultipleSelection(params);
}
// selectionMode is a static value, so we can safely ignore rules-of-hooks
// eslint-disable-next-line react-hooks/rules-of-hooks
return useSingleSelection(params);
}

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,60 @@
'use client';
import * as React from 'react';
import { canUseDOM } from './canUseDOM';
/**
* Default context value to use in case there is no SSRProvider. This is fine for client-only apps.
*
* @internal
*/ export const defaultSSRContextValue = {
current: 0
};
export const SSRContext = /*#__PURE__*/ React.createContext(undefined);
/**
* @internal
*/ export function useSSRContext() {
var _React_useContext;
return (_React_useContext = React.useContext(SSRContext)) !== null && _React_useContext !== void 0 ? _React_useContext : defaultSSRContextValue;
}
/**
* When using SSR with Fluent UI, applications must be wrapped in an SSRProvider. This ensures that auto generated ids
* are consistent between the client and server.
*
* @public
*/ export const SSRProvider = (props)=>{
const [value] = React.useState(()=>({
current: 0
}));
return /*#__PURE__*/ React.createElement(SSRContext.Provider, {
value: value
}, props.children);
};
/**
* Returns whether the component is currently being server side rendered or hydrated on the client. Can be used to delay
* browser-specific rendering until after hydration. May cause re-renders on a client when is used within SSRProvider.
*/ export function useIsSSR() {
const isInSSRContext = useSSRContext() !== defaultSSRContextValue;
const [isSSR, setIsSSR] = React.useState(isInSSRContext);
// If we are rendering in a non-DOM environment, and there's no SSRProvider, provide a warning to hint to the
// developer to add one.
if (process.env.NODE_ENV !== 'production') {
if (!isInSSRContext && !canUseDOM()) {
// eslint-disable-next-line no-console
console.error(`@fluentui/react-components [${useIsSSR.name}]:
When server rendering, you must wrap your application in an <SSRProvider> to ensure consistent ids are generated between the client and server.
Check documentation at https://aka.ms/fluentui-ssr.`);
}
}
// If on the client, and the component was initially server rendered, then schedule a layout effect to update the
// component after hydration.
if (canUseDOM() && isInSSRContext) {
// This if statement technically breaks the rules of hooks, but is safe because the condition never changes after
// mounting.
// eslint-disable-next-line
React.useLayoutEffect(()=>{
setIsSSR(false);
}, []);
}
return isSSR;
}

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../src/ssr/SSRContext.tsx"],"sourcesContent":["'use client';\n\nimport * as React from 'react';\nimport { canUseDOM } from './canUseDOM';\n\n/**\n * To support SSR, the auto incrementing id counter is stored in a context. This allows it to be reset on every request\n * to ensure the client and server are consistent.\n *\n * @internal\n */\nexport type SSRContextValue = {\n current: number;\n};\n\n/**\n * Default context value to use in case there is no SSRProvider. This is fine for client-only apps.\n *\n * @internal\n */\nexport const defaultSSRContextValue: SSRContextValue = {\n current: 0,\n};\n\nexport const SSRContext = React.createContext<SSRContextValue | undefined>(undefined) as React.Context<SSRContextValue>;\n\n/**\n * @internal\n */\nexport function useSSRContext(): SSRContextValue {\n return React.useContext(SSRContext) ?? defaultSSRContextValue;\n}\n\n/**\n * When using SSR with Fluent UI, applications must be wrapped in an SSRProvider. This ensures that auto generated ids\n * are consistent between the client and server.\n *\n * @public\n */\nexport const SSRProvider: React.FC<{ children: React.ReactNode }> = props => {\n const [value] = React.useState<SSRContextValue>(() => ({ current: 0 }));\n\n return <SSRContext.Provider value={value}>{props.children}</SSRContext.Provider>;\n};\n\n/**\n * Returns whether the component is currently being server side rendered or hydrated on the client. Can be used to delay\n * browser-specific rendering until after hydration. May cause re-renders on a client when is used within SSRProvider.\n */\nexport function useIsSSR(): boolean {\n const isInSSRContext = useSSRContext() !== defaultSSRContextValue;\n const [isSSR, setIsSSR] = React.useState(isInSSRContext);\n\n // If we are rendering in a non-DOM environment, and there's no SSRProvider, provide a warning to hint to the\n // developer to add one.\n if (process.env.NODE_ENV !== 'production') {\n if (!isInSSRContext && !canUseDOM()) {\n // eslint-disable-next-line no-console\n console.error(/** #__DE-INDENT__ */ `\n @fluentui/react-components [${useIsSSR.name}]:\n When server rendering, you must wrap your application in an <SSRProvider> to ensure consistent ids are generated between the client and server.\n\n\n Check documentation at https://aka.ms/fluentui-ssr.\n `);\n }\n }\n\n // If on the client, and the component was initially server rendered, then schedule a layout effect to update the\n // component after hydration.\n if (canUseDOM() && isInSSRContext) {\n // This if statement technically breaks the rules of hooks, but is safe because the condition never changes after\n // mounting.\n // eslint-disable-next-line\n React.useLayoutEffect(() => {\n setIsSSR(false);\n }, []);\n }\n\n return isSSR;\n}\n"],"names":["React","canUseDOM","defaultSSRContextValue","current","SSRContext","createContext","undefined","useSSRContext","useContext","SSRProvider","props","value","useState","Provider","children","useIsSSR","isInSSRContext","isSSR","setIsSSR","process","env","NODE_ENV","console","error","name","useLayoutEffect"],"mappings":"AAAA;AAEA,YAAYA,WAAW,QAAQ;AAC/B,SAASC,SAAS,QAAQ,cAAc;AAYxC;;;;CAIC,GACD,OAAO,MAAMC,yBAA0C;IACrDC,SAAS;AACX,EAAE;AAEF,OAAO,MAAMC,2BAAaJ,MAAMK,aAAa,CAA8BC,WAA6C;AAExH;;CAEC,GACD,OAAO,SAASC;QACPP;IAAP,OAAOA,CAAAA,oBAAAA,MAAMQ,UAAU,CAACJ,yBAAjBJ,+BAAAA,oBAAgCE;AACzC;AAEA;;;;;CAKC,GACD,OAAO,MAAMO,cAAuDC,CAAAA;IAClE,MAAM,CAACC,MAAM,GAAGX,MAAMY,QAAQ,CAAkB,IAAO,CAAA;YAAET,SAAS;QAAE,CAAA;IAEpE,qBAAO,oBAACC,WAAWS,QAAQ;QAACF,OAAOA;OAAQD,MAAMI,QAAQ;AAC3D,EAAE;AAEF;;;CAGC,GACD,OAAO,SAASC;IACd,MAAMC,iBAAiBT,oBAAoBL;IAC3C,MAAM,CAACe,OAAOC,SAAS,GAAGlB,MAAMY,QAAQ,CAACI;IAEzC,6GAA6G;IAC7G,wBAAwB;IACxB,IAAIG,QAAQC,GAAG,CAACC,QAAQ,KAAK,cAAc;QACzC,IAAI,CAACL,kBAAkB,CAACf,aAAa;YACnC,sCAAsC;YACtCqB,QAAQC,KAAK,CAAuB,CAAC,4BACP,EAAER,SAASS,IAAI,CAAC;;;;mDAK9C,CAAC;QACH;IACF;IAEA,iHAAiH;IACjH,6BAA6B;IAC7B,IAAIvB,eAAee,gBAAgB;QACjC,iHAAiH;QACjH,YAAY;QACZ,2BAA2B;QAC3BhB,MAAMyB,eAAe,CAAC;YACpBP,SAAS;QACX,GAAG,EAAE;IACP;IAEA,OAAOD;AACT"}

View File

@@ -0,0 +1,7 @@
'use client';
/**
* Verifies if an application can use DOM.
*/ export function canUseDOM() {
return /* eslint-disable @nx/workspace-no-restricted-globals -- expected ignore ( SSR friendly acquisition of globals )*/ typeof window !== 'undefined' && !!(window.document && // eslint-disable-next-line @typescript-eslint/no-deprecated
window.document.createElement);
}

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../src/ssr/canUseDOM.ts"],"sourcesContent":["'use client';\n\n/**\n * Verifies if an application can use DOM.\n */\nexport function canUseDOM(): boolean {\n return (\n /* eslint-disable @nx/workspace-no-restricted-globals -- expected ignore ( SSR friendly acquisition of globals )*/\n typeof window !== 'undefined' &&\n !!(\n window.document &&\n // eslint-disable-next-line @typescript-eslint/no-deprecated\n window.document.createElement\n )\n /* eslint-enable @nx/workspace-no-restricted-globals */\n );\n}\n"],"names":["canUseDOM","window","document","createElement"],"mappings":"AAAA;AAEA;;CAEC,GACD,OAAO,SAASA;IACd,OACE,gHAAgH,GAChH,OAAOC,WAAW,eAClB,CAAC,CACCA,CAAAA,OAAOC,QAAQ,IACf,4DAA4D;IAC5DD,OAAOC,QAAQ,CAACC,aAAa,AAAD;AAIlC"}

View File

@@ -0,0 +1,2 @@
export { canUseDOM } from './canUseDOM';
export { SSRContext, SSRProvider, defaultSSRContextValue, useIsSSR, useSSRContext } from './SSRContext';

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../src/ssr/index.ts"],"sourcesContent":["export { canUseDOM } from './canUseDOM';\nexport type { SSRContextValue } from './SSRContext';\nexport { SSRContext, SSRProvider, defaultSSRContextValue, useIsSSR, useSSRContext } from './SSRContext';\n"],"names":["canUseDOM","SSRContext","SSRProvider","defaultSSRContextValue","useIsSSR","useSSRContext"],"mappings":"AAAA,SAASA,SAAS,QAAQ,cAAc;AAExC,SAASC,UAAU,EAAEC,WAAW,EAAEC,sBAAsB,EAAEC,QAAQ,EAAEC,aAAa,QAAQ,eAAe"}

View File

@@ -0,0 +1,30 @@
import * as React from 'react';
import { isFluentTrigger } from './isFluentTrigger';
/**
* @internal
* resolve the trigger props to the children, either by calling the render function, or cloning with the new props.
*/ export function applyTriggerPropsToChildren(children, triggerChildProps) {
if (typeof children === 'function') {
return children(triggerChildProps);
} else if (children) {
return cloneTriggerTree(children, triggerChildProps);
}
// Components in React should return either JSX elements or "null", otherwise React will throw:
// Nothing was returned from render.
// This usually means a return statement is missing. Or, to render nothing, return null.
return children || null;
}
/**
* Clones a React element tree, and applies the given props to the first grandchild that is not
* a FluentTriggerComponent or React Fragment (the same element returned by {@link getTriggerChild}).
*/ function cloneTriggerTree(child, triggerProps) {
if (!React.isValidElement(child) || child.type === React.Fragment) {
throw new Error('A trigger element must be a single element for this component. ' + "Please ensure that you're not using React Fragments.");
}
if (isFluentTrigger(child)) {
const grandchild = cloneTriggerTree(child.props.children, triggerProps);
return React.cloneElement(child, undefined, grandchild);
} else {
return React.cloneElement(child, triggerProps);
}
}

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../src/trigger/applyTriggerPropsToChildren.ts"],"sourcesContent":["import * as React from 'react';\nimport { isFluentTrigger } from './isFluentTrigger';\nimport type { TriggerProps } from './types';\n\n/**\n * @internal\n * resolve the trigger props to the children, either by calling the render function, or cloning with the new props.\n */\nexport function applyTriggerPropsToChildren<TriggerChildProps>(\n children: TriggerProps<TriggerChildProps>['children'],\n triggerChildProps: TriggerChildProps,\n): React.ReactElement | null {\n if (typeof children === 'function') {\n return children(triggerChildProps);\n } else if (children) {\n return cloneTriggerTree(children, triggerChildProps);\n }\n\n // Components in React should return either JSX elements or \"null\", otherwise React will throw:\n // Nothing was returned from render.\n // This usually means a return statement is missing. Or, to render nothing, return null.\n return children || null;\n}\n\n/**\n * Clones a React element tree, and applies the given props to the first grandchild that is not\n * a FluentTriggerComponent or React Fragment (the same element returned by {@link getTriggerChild}).\n */\nfunction cloneTriggerTree<TriggerChildProps>(\n child: TriggerProps['children'],\n triggerProps: TriggerChildProps,\n): React.ReactElement {\n if (!React.isValidElement(child) || child.type === React.Fragment) {\n throw new Error(\n 'A trigger element must be a single element for this component. ' +\n \"Please ensure that you're not using React Fragments.\",\n );\n }\n\n if (isFluentTrigger(child)) {\n const grandchild = cloneTriggerTree(child.props.children, triggerProps);\n return React.cloneElement(child, undefined, grandchild);\n } else {\n return React.cloneElement(child, triggerProps as TriggerChildProps & React.Attributes);\n }\n}\n"],"names":["React","isFluentTrigger","applyTriggerPropsToChildren","children","triggerChildProps","cloneTriggerTree","child","triggerProps","isValidElement","type","Fragment","Error","grandchild","props","cloneElement","undefined"],"mappings":"AAAA,YAAYA,WAAW,QAAQ;AAC/B,SAASC,eAAe,QAAQ,oBAAoB;AAGpD;;;CAGC,GACD,OAAO,SAASC,4BACdC,QAAqD,EACrDC,iBAAoC;IAEpC,IAAI,OAAOD,aAAa,YAAY;QAClC,OAAOA,SAASC;IAClB,OAAO,IAAID,UAAU;QACnB,OAAOE,iBAAiBF,UAAUC;IACpC;IAEA,+FAA+F;IAC/F,sCAAsC;IACtC,0FAA0F;IAC1F,OAAOD,YAAY;AACrB;AAEA;;;CAGC,GACD,SAASE,iBACPC,KAA+B,EAC/BC,YAA+B;IAE/B,IAAI,CAACP,MAAMQ,cAAc,CAACF,UAAUA,MAAMG,IAAI,KAAKT,MAAMU,QAAQ,EAAE;QACjE,MAAM,IAAIC,MACR,oEACE;IAEN;IAEA,IAAIV,gBAAgBK,QAAQ;QAC1B,MAAMM,aAAaP,iBAAiBC,MAAMO,KAAK,CAACV,QAAQ,EAAEI;QAC1D,OAAOP,MAAMc,YAAY,CAACR,OAAOS,WAAWH;IAC9C,OAAO;QACL,OAAOZ,MAAMc,YAAY,CAACR,OAAOC;IACnC;AACF"}

View File

@@ -0,0 +1,31 @@
import * as React from 'react';
import { isFluentTrigger } from './isFluentTrigger';
/**
* @internal
* Gets the trigger element of a FluentTriggerComponent (such as Tooltip or MenuTrigger).
*
* In the case where the immediate child is itself a FluentTriggerComponent and/or React Fragment,
* it returns the first descendant that is _not_ a FluentTriggerComponent or Fragment.
* This allows multiple triggers to be stacked, and still apply their props to the actual trigger element.
*
* For example, the following returns `<div id="child" />`:
* ```jsx
* getTriggerChild(
* <Tooltip>
* <MenuTrigger>
* <div id="child" />
* </MenuTrigger>
* </Tooltip>
* );
* ```
*
* In the case where the immediate child is not a valid element,
* null is returned
*/ export function getTriggerChild(children) {
if (!React.isValidElement(children)) {
return null;
}
return isFluentTrigger(children) ? getTriggerChild(// FIXME: This casting should be unnecessary as isFluentTrigger is a guard type method,
// but for some reason it's failing on build
children.props.children) : children;
}

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../src/trigger/getTriggerChild.ts"],"sourcesContent":["import * as React from 'react';\nimport { isFluentTrigger } from './isFluentTrigger';\nimport type { TriggerProps } from './types';\n\n/**\n * @internal\n * Gets the trigger element of a FluentTriggerComponent (such as Tooltip or MenuTrigger).\n *\n * In the case where the immediate child is itself a FluentTriggerComponent and/or React Fragment,\n * it returns the first descendant that is _not_ a FluentTriggerComponent or Fragment.\n * This allows multiple triggers to be stacked, and still apply their props to the actual trigger element.\n *\n * For example, the following returns `<div id=\"child\" />`:\n * ```jsx\n * getTriggerChild(\n * <Tooltip>\n * <MenuTrigger>\n * <div id=\"child\" />\n * </MenuTrigger>\n * </Tooltip>\n * );\n * ```\n *\n * In the case where the immediate child is not a valid element,\n * null is returned\n */\nexport function getTriggerChild<TriggerChildProps>(\n children: TriggerProps<TriggerChildProps>['children'],\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n): (React.ReactElement<Partial<TriggerChildProps>> & { ref?: React.Ref<any> }) | null {\n if (!React.isValidElement<TriggerChildProps>(children)) {\n return null;\n }\n return isFluentTrigger(children)\n ? getTriggerChild(\n // FIXME: This casting should be unnecessary as isFluentTrigger is a guard type method,\n // but for some reason it's failing on build\n (children.props as TriggerProps).children,\n )\n : children;\n}\n"],"names":["React","isFluentTrigger","getTriggerChild","children","isValidElement","props"],"mappings":"AAAA,YAAYA,WAAW,QAAQ;AAC/B,SAASC,eAAe,QAAQ,oBAAoB;AAGpD;;;;;;;;;;;;;;;;;;;;;CAqBC,GACD,OAAO,SAASC,gBACdC,QAAqD;IAGrD,IAAI,CAACH,MAAMI,cAAc,CAAoBD,WAAW;QACtD,OAAO;IACT;IACA,OAAOF,gBAAgBE,YACnBD,gBAGE,AAFA,uFAAuF;IACvF,4CAA4C;IAC3CC,SAASE,KAAK,CAAkBF,QAAQ,IAE3CA;AACN"}

View File

@@ -0,0 +1,3 @@
export { applyTriggerPropsToChildren } from './applyTriggerPropsToChildren';
export { getTriggerChild } from './getTriggerChild';
export { isFluentTrigger } from './isFluentTrigger';

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../src/trigger/index.ts"],"sourcesContent":["export { applyTriggerPropsToChildren } from './applyTriggerPropsToChildren';\nexport { getTriggerChild } from './getTriggerChild';\nexport { isFluentTrigger } from './isFluentTrigger';\nexport type { FluentTriggerComponent, TriggerProps } from './types';\n"],"names":["applyTriggerPropsToChildren","getTriggerChild","isFluentTrigger"],"mappings":"AAAA,SAASA,2BAA2B,QAAQ,gCAAgC;AAC5E,SAASC,eAAe,QAAQ,oBAAoB;AACpD,SAASC,eAAe,QAAQ,oBAAoB"}

View File

@@ -0,0 +1,8 @@
import * as React from 'react';
/**
* @internal
* Checks if a given element is a FluentUI trigger (e.g. `MenuTrigger` or `Tooltip`).
* See the {@link FluentTriggerComponent} type for more info.
*/ export function isFluentTrigger(element) {
return Boolean(element.type.isFluentTriggerComponent);
}

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../src/trigger/isFluentTrigger.ts"],"sourcesContent":["import * as React from 'react';\nimport type { FluentTriggerComponent, TriggerProps } from './types';\n\n/**\n * @internal\n * Checks if a given element is a FluentUI trigger (e.g. `MenuTrigger` or `Tooltip`).\n * See the {@link FluentTriggerComponent} type for more info.\n */\nexport function isFluentTrigger(element: React.ReactElement): element is React.ReactElement<TriggerProps> {\n return Boolean((element.type as FluentTriggerComponent).isFluentTriggerComponent);\n}\n"],"names":["React","isFluentTrigger","element","Boolean","type","isFluentTriggerComponent"],"mappings":"AAAA,YAAYA,WAAW,QAAQ;AAG/B;;;;CAIC,GACD,OAAO,SAASC,gBAAgBC,OAA2B;IACzD,OAAOC,QAAQ,AAACD,QAAQE,IAAI,CAA4BC,wBAAwB;AAClF"}

View File

@@ -0,0 +1 @@
import * as React from 'react';

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../src/trigger/types.ts"],"sourcesContent":["import * as React from 'react';\n\n/**\n * @internal\n * Allows a component to be tagged as a FluentUI trigger component.\n *\n * Triggers are special-case components: they attach event listeners and other props on their child,\n * and use them to trigger another component to show. Examples include `MenuTrigger` and `Tooltip`.\n *\n * A component can be tagged as a trigger as follows:\n * ```ts\n * const MyComponent: React.FC<MyComponentProps> & FluentTriggerComponent = ...;\n *\n * MyComponent.isFluentTriggerComponent = true; // MUST also set this to true\n * ```\n */\nexport type FluentTriggerComponent = {\n isFluentTriggerComponent?: boolean;\n};\n\n/**\n * A trigger may have a children that could be either:\n * 1. A single element\n * 2. A render function that will receive properties and must return a valid element or null\n * 3. null or undefined\n */\nexport type TriggerProps<TriggerChildProps = unknown> = {\n children?: React.ReactElement | ((props: TriggerChildProps) => React.ReactElement | null) | null;\n};\n"],"names":["React"],"mappings":"AAAA,YAAYA,WAAW,QAAQ"}

View File

@@ -0,0 +1,8 @@
/**
* @internal
* Clamps `value` to a number between the min and max.
*
* @param value - the value to be clamped
* @param min - the lowest valid value
* @param max - the highest valid value
*/ export const clamp = (value, min, max)=>Math.max(min, Math.min(max, value || 0));

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../src/utils/clamp.ts"],"sourcesContent":["/**\n * @internal\n * Clamps `value` to a number between the min and max.\n *\n * @param value - the value to be clamped\n * @param min - the lowest valid value\n * @param max - the highest valid value\n */\nexport const clamp = (value: number, min: number, max: number): number => Math.max(min, Math.min(max, value || 0));\n"],"names":["clamp","value","min","max","Math"],"mappings":"AAAA;;;;;;;CAOC,GACD,OAAO,MAAMA,QAAQ,CAACC,OAAeC,KAAaC,MAAwBC,KAAKD,GAAG,CAACD,KAAKE,KAAKF,GAAG,CAACC,KAAKF,SAAS,IAAI"}

View File

@@ -0,0 +1,5 @@
/**
* Creates a set from a given iterable, in case the iterable is a set itself, returns the given set instead.
*/ export function createSetFromIterable(iterable) {
return iterable instanceof Set ? iterable : new Set(iterable);
}

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../src/utils/createSetFromIterable.ts"],"sourcesContent":["/**\n * Creates a set from a given iterable, in case the iterable is a set itself, returns the given set instead.\n */\nexport function createSetFromIterable<V>(iterable: Iterable<V>): Set<V> {\n return iterable instanceof Set ? iterable : new Set(iterable);\n}\n"],"names":["createSetFromIterable","iterable","Set"],"mappings":"AAAA;;CAEC,GACD,OAAO,SAASA,sBAAyBC,QAAqB;IAC5D,OAAOA,oBAAoBC,MAAMD,WAAW,IAAIC,IAAID;AACtD"}

View File

@@ -0,0 +1,62 @@
import * as React from 'react';
import { labelProperties, audioProperties, videoProperties, olProperties, liProperties, anchorProperties, buttonProperties, inputProperties, textAreaProperties, selectProperties, optionProperties, tableProperties, trProperties, thProperties, tdProperties, colGroupProperties, colProperties, fieldsetProperties, formProperties, iframeProperties, imgProperties, htmlElementProperties, getNativeProps, timeProperties, dialogProperties } from './properties';
const nativeElementMap = {
label: labelProperties,
audio: audioProperties,
video: videoProperties,
ol: olProperties,
li: liProperties,
a: anchorProperties,
button: buttonProperties,
input: inputProperties,
textarea: textAreaProperties,
select: selectProperties,
option: optionProperties,
table: tableProperties,
tr: trProperties,
th: thProperties,
td: tdProperties,
colGroup: colGroupProperties,
col: colProperties,
fieldset: fieldsetProperties,
form: formProperties,
iframe: iframeProperties,
img: imgProperties,
time: timeProperties,
dialog: dialogProperties
};
/**
* Given an element tagname and user props, filters the props to only allowed props for the given
* element type.
* @param tagName - Tag name (e.g. "div")
* @param props - Props object
* @param excludedPropNames - List of props to disallow
*
* @deprecated use getIntrinsicElementProps instead, it is a type-safe version of this method
*/ // eslint-disable-next-line @typescript-eslint/no-explicit-any
export function getNativeElementProps(tagName, props, excludedPropNames) {
const allowedPropNames = tagName && nativeElementMap[tagName] || htmlElementProperties;
allowedPropNames.as = 1;
return getNativeProps(props, allowedPropNames, excludedPropNames);
}
/**
* Splits the native props into ones that go to the `root` slot, and ones that go to the primary slot.
*
* This function is only for use with components that have a primary slot other than `root`.
* Most components should use {@link getNativeElementProps} for their root slot if it is the primary slot.
*
* @returns An object containing the native props for the `root` and primary slots.
*/ export const getPartitionedNativeProps = ({ primarySlotTagName, props, excludedPropNames })=>{
return {
root: {
style: props.style,
className: props.className
},
// eslint-disable-next-line @typescript-eslint/no-deprecated
primary: getNativeElementProps(primarySlotTagName, props, [
...excludedPropNames || [],
'style',
'className'
])
};
};

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,18 @@
/**
* @internal
* Finds and swaps a provided key for it's right to left format.
*/ export const getRTLSafeKey = (key, dir)=>{
if (dir === 'rtl') {
switch(key){
case 'ArrowLeft':
{
return 'ArrowRight';
}
case 'ArrowRight':
{
return 'ArrowLeft';
}
}
}
return key;
};

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../src/utils/getRTLSafeKey.ts"],"sourcesContent":["/**\n * @internal\n * Finds and swaps a provided key for it's right to left format.\n */\nexport const getRTLSafeKey = (key: string, dir: 'ltr' | 'rtl'): string => {\n if (dir === 'rtl') {\n switch (key) {\n case 'ArrowLeft': {\n return 'ArrowRight';\n }\n\n case 'ArrowRight': {\n return 'ArrowLeft';\n }\n }\n }\n\n return key;\n};\n"],"names":["getRTLSafeKey","key","dir"],"mappings":"AAAA;;;CAGC,GACD,OAAO,MAAMA,gBAAgB,CAACC,KAAaC;IACzC,IAAIA,QAAQ,OAAO;QACjB,OAAQD;YACN,KAAK;gBAAa;oBAChB,OAAO;gBACT;YAEA,KAAK;gBAAc;oBACjB,OAAO;gBACT;QACF;IACF;IAEA,OAAOA;AACT,EAAE"}

View File

@@ -0,0 +1,23 @@
import * as React from 'react';
/**
* React.SyntheticEvent contains name of a callback that should be fired, this function returns it.
*
* Ideally, it should also distinguish regular and "capture" callbacks, but it's possible only with React 17 as
* ".eventPhase" there has proper value, see https://github.com/facebook/react/pull/19244. In React 16 all events
* are handled in bubble phase.
*/ export function getReactCallbackName(event) {
if (event._reactName) {
return event._reactName;
}
if (event.dispatchConfig) {
if (event.dispatchConfig.registrationName) {
return event.dispatchConfig.registrationName;
}
return event.dispatchConfig.phasedRegistrationNames.bubbled;
}
if (process.env.NODE_ENV !== 'production') {
// eslint-disable-next-line no-console
console.error(`@fluentui/react-utilities [${getReactCallbackName.name}]:
Passed React.SyntheticEvent does not contain ".dispatchConfig" or "._reactName". This should not happen, please report it to https://github.com/microsoft/fluentui.`);
}
}

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../src/utils/getReactCallbackName.ts"],"sourcesContent":["import * as React from 'react';\n\ninterface ReactSyntheticEvent extends React.SyntheticEvent<unknown> {\n // React 17/18\n // See https://github.com/facebook/react/pull/19236\n _reactName?: string;\n\n // React 16\n dispatchConfig?: {\n registrationName: string;\n phasedRegistrationNames: {\n bubbled: string;\n captured: string;\n };\n };\n}\n\ntype NonUndefined<A> = A extends undefined ? never : A;\ntype FunctionKeys<T extends object> = {\n [K in keyof T]-?: NonUndefined<T[K]> extends Function ? K : never;\n}[keyof T];\n\nexport type ReactCallbackName = FunctionKeys<React.DOMAttributes<unknown>>;\n\n/**\n * React.SyntheticEvent contains name of a callback that should be fired, this function returns it.\n *\n * Ideally, it should also distinguish regular and \"capture\" callbacks, but it's possible only with React 17 as\n * \".eventPhase\" there has proper value, see https://github.com/facebook/react/pull/19244. In React 16 all events\n * are handled in bubble phase.\n */\nexport function getReactCallbackName(event: ReactSyntheticEvent): ReactCallbackName | undefined {\n if (event._reactName) {\n return event._reactName as ReactCallbackName;\n }\n\n if (event.dispatchConfig) {\n if (event.dispatchConfig.registrationName) {\n return event.dispatchConfig.registrationName as ReactCallbackName;\n }\n\n return event.dispatchConfig.phasedRegistrationNames.bubbled as ReactCallbackName;\n }\n\n if (process.env.NODE_ENV !== 'production') {\n // eslint-disable-next-line no-console\n console.error(/** #__DE-INDENT__ */ `\n @fluentui/react-utilities [${getReactCallbackName.name}]:\n Passed React.SyntheticEvent does not contain \".dispatchConfig\" or \"._reactName\". This should not happen, please report it to https://github.com/microsoft/fluentui.\n `);\n }\n}\n"],"names":["React","getReactCallbackName","event","_reactName","dispatchConfig","registrationName","phasedRegistrationNames","bubbled","process","env","NODE_ENV","console","error","name"],"mappings":"AAAA,YAAYA,WAAW,QAAQ;AAwB/B;;;;;;CAMC,GACD,OAAO,SAASC,qBAAqBC,KAA0B;IAC7D,IAAIA,MAAMC,UAAU,EAAE;QACpB,OAAOD,MAAMC,UAAU;IACzB;IAEA,IAAID,MAAME,cAAc,EAAE;QACxB,IAAIF,MAAME,cAAc,CAACC,gBAAgB,EAAE;YACzC,OAAOH,MAAME,cAAc,CAACC,gBAAgB;QAC9C;QAEA,OAAOH,MAAME,cAAc,CAACE,uBAAuB,CAACC,OAAO;IAC7D;IAEA,IAAIC,QAAQC,GAAG,CAACC,QAAQ,KAAK,cAAc;QACzC,sCAAsC;QACtCC,QAAQC,KAAK,CAAuB,CAAC,2BACR,EAAEX,qBAAqBY,IAAI,CAAC;mKAEzD,CAAC;IACH;AACF"}

View File

@@ -0,0 +1,16 @@
import * as React from 'react';
const IS_REACT_19_OR_HIGHER = parseInt(React.version, 10) >= 19;
/**
* Returns a ref for the React element in a backwards-compatible way.
*
* @param element - The element to get the ref for.
* @returns The ref for the element.
*/ export function getReactElementRef(element) {
if (!element) {
return undefined;
}
if (IS_REACT_19_OR_HIGHER) {
return element.props.ref;
}
return element.ref;
}

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../src/utils/getReactElementRef.ts"],"sourcesContent":["import * as React from 'react';\n\nconst IS_REACT_19_OR_HIGHER = parseInt(React.version, 10) >= 19;\n\n/**\n * Returns a ref for the React element in a backwards-compatible way.\n *\n * @param element - The element to get the ref for.\n * @returns The ref for the element.\n */\nexport function getReactElementRef<T>(element: React.ReactElement | null | undefined): React.Ref<T> | undefined {\n if (!element) {\n return undefined;\n }\n\n if (IS_REACT_19_OR_HIGHER) {\n return (element as React.ReactElement<{ ref?: React.Ref<T> }>).props.ref;\n }\n\n return (element as React.ReactElement & { ref: React.Ref<T> | undefined }).ref;\n}\n"],"names":["React","IS_REACT_19_OR_HIGHER","parseInt","version","getReactElementRef","element","undefined","props","ref"],"mappings":"AAAA,YAAYA,WAAW,QAAQ;AAE/B,MAAMC,wBAAwBC,SAASF,MAAMG,OAAO,EAAE,OAAO;AAE7D;;;;;CAKC,GACD,OAAO,SAASC,mBAAsBC,OAA8C;IAClF,IAAI,CAACA,SAAS;QACZ,OAAOC;IACT;IAEA,IAAIL,uBAAuB;QACzB,OAAO,AAACI,QAAuDE,KAAK,CAACC,GAAG;IAC1E;IAEA,OAAO,AAACH,QAAmEG,GAAG;AAChF"}

View File

@@ -0,0 +1,12 @@
export { clamp } from './clamp';
export { // eslint-disable-next-line @typescript-eslint/no-deprecated
getNativeElementProps, getPartitionedNativeProps } from './getNativeElementProps';
export { getReactElementRef } from './getReactElementRef';
export { getRTLSafeKey } from './getRTLSafeKey';
export { mergeCallbacks } from './mergeCallbacks';
export { omit } from './omit';
export { anchorProperties, audioProperties, baseElementEvents, baseElementProperties, buttonProperties, colGroupProperties, colProperties, dialogProperties, divProperties, fieldsetProperties, formProperties, getNativeProps, htmlElementProperties, iframeProperties, imgProperties, inputProperties, labelProperties, liProperties, microdataProperties, olProperties, optionProperties, selectProperties, tableProperties, tdProperties, textAreaProperties, thProperties, timeProperties, trProperties, videoProperties } from './properties';
export { isHTMLElement } from './isHTMLElement';
export { isInteractiveHTMLElement } from './isInteractiveHTMLElement';
export { createPriorityQueue } from './priorityQueue';
export { measureScrollbarWidth } from './measureScrollBarWidth';

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../src/utils/index.ts"],"sourcesContent":["export { clamp } from './clamp';\nexport {\n // eslint-disable-next-line @typescript-eslint/no-deprecated\n getNativeElementProps,\n getPartitionedNativeProps,\n} from './getNativeElementProps';\nexport { getReactElementRef } from './getReactElementRef';\nexport { getRTLSafeKey } from './getRTLSafeKey';\nexport { mergeCallbacks } from './mergeCallbacks';\nexport { omit } from './omit';\nexport {\n anchorProperties,\n audioProperties,\n baseElementEvents,\n baseElementProperties,\n buttonProperties,\n colGroupProperties,\n colProperties,\n dialogProperties,\n divProperties,\n fieldsetProperties,\n formProperties,\n getNativeProps,\n htmlElementProperties,\n iframeProperties,\n imgProperties,\n inputProperties,\n labelProperties,\n liProperties,\n microdataProperties,\n olProperties,\n optionProperties,\n selectProperties,\n tableProperties,\n tdProperties,\n textAreaProperties,\n thProperties,\n timeProperties,\n trProperties,\n videoProperties,\n} from './properties';\nexport { isHTMLElement } from './isHTMLElement';\nexport { isInteractiveHTMLElement } from './isInteractiveHTMLElement';\nexport type { PriorityQueue, PriorityQueueCompareFn } from './priorityQueue';\nexport { createPriorityQueue } from './priorityQueue';\nexport { measureScrollbarWidth } from './measureScrollBarWidth';\n"],"names":["clamp","getNativeElementProps","getPartitionedNativeProps","getReactElementRef","getRTLSafeKey","mergeCallbacks","omit","anchorProperties","audioProperties","baseElementEvents","baseElementProperties","buttonProperties","colGroupProperties","colProperties","dialogProperties","divProperties","fieldsetProperties","formProperties","getNativeProps","htmlElementProperties","iframeProperties","imgProperties","inputProperties","labelProperties","liProperties","microdataProperties","olProperties","optionProperties","selectProperties","tableProperties","tdProperties","textAreaProperties","thProperties","timeProperties","trProperties","videoProperties","isHTMLElement","isInteractiveHTMLElement","createPriorityQueue","measureScrollbarWidth"],"mappings":"AAAA,SAASA,KAAK,QAAQ,UAAU;AAChC,SACE,4DAA4D;AAC5DC,qBAAqB,EACrBC,yBAAyB,QACpB,0BAA0B;AACjC,SAASC,kBAAkB,QAAQ,uBAAuB;AAC1D,SAASC,aAAa,QAAQ,kBAAkB;AAChD,SAASC,cAAc,QAAQ,mBAAmB;AAClD,SAASC,IAAI,QAAQ,SAAS;AAC9B,SACEC,gBAAgB,EAChBC,eAAe,EACfC,iBAAiB,EACjBC,qBAAqB,EACrBC,gBAAgB,EAChBC,kBAAkB,EAClBC,aAAa,EACbC,gBAAgB,EAChBC,aAAa,EACbC,kBAAkB,EAClBC,cAAc,EACdC,cAAc,EACdC,qBAAqB,EACrBC,gBAAgB,EAChBC,aAAa,EACbC,eAAe,EACfC,eAAe,EACfC,YAAY,EACZC,mBAAmB,EACnBC,YAAY,EACZC,gBAAgB,EAChBC,gBAAgB,EAChBC,eAAe,EACfC,YAAY,EACZC,kBAAkB,EAClBC,YAAY,EACZC,cAAc,EACdC,YAAY,EACZC,eAAe,QACV,eAAe;AACtB,SAASC,aAAa,QAAQ,kBAAkB;AAChD,SAASC,wBAAwB,QAAQ,6BAA6B;AAEtE,SAASC,mBAAmB,QAAQ,kBAAkB;AACtD,SAASC,qBAAqB,QAAQ,0BAA0B"}

View File

@@ -0,0 +1,19 @@
/**
* Verifies if a given node is an HTMLElement,
* this method works seamlessly with frames and elements from different documents
*
* This is preferred over simply using `instanceof`.
* Since `instanceof` might be problematic while operating with [multiple realms](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/instanceof#instanceof_and_multiple_realms)
*
* @example
* ```ts
* isHTMLElement(event.target) && event.target.focus()
* isHTMLElement(event.target, {constructorName: 'HTMLInputElement'}) && event.target.value // some value
* ```
*
*/ export function isHTMLElement(element, options) {
var _typedElement_ownerDocument;
const typedElement = element;
var _options_constructorName;
return Boolean((typedElement === null || typedElement === void 0 ? void 0 : (_typedElement_ownerDocument = typedElement.ownerDocument) === null || _typedElement_ownerDocument === void 0 ? void 0 : _typedElement_ownerDocument.defaultView) && typedElement instanceof typedElement.ownerDocument.defaultView[(_options_constructorName = options === null || options === void 0 ? void 0 : options.constructorName) !== null && _options_constructorName !== void 0 ? _options_constructorName : 'HTMLElement']);
}

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../src/utils/isHTMLElement.ts"],"sourcesContent":["/**\n * Verifies if a given node is an HTMLElement,\n * this method works seamlessly with frames and elements from different documents\n *\n * This is preferred over simply using `instanceof`.\n * Since `instanceof` might be problematic while operating with [multiple realms](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/instanceof#instanceof_and_multiple_realms)\n *\n * @example\n * ```ts\n * isHTMLElement(event.target) && event.target.focus()\n * isHTMLElement(event.target, {constructorName: 'HTMLInputElement'}) && event.target.value // some value\n * ```\n *\n */\nexport function isHTMLElement<ConstructorName extends HTMLElementConstructorName = 'HTMLElement'>(\n element?: unknown,\n options?: {\n /**\n * Can be used to provide a custom constructor instead of `HTMLElement`,\n * Like `HTMLInputElement` for example.\n */\n constructorName?: ConstructorName;\n },\n): element is InstanceType<(typeof globalThis)[ConstructorName]> {\n const typedElement = element as Node | null | undefined;\n return Boolean(\n typedElement?.ownerDocument?.defaultView &&\n typedElement instanceof typedElement.ownerDocument.defaultView[options?.constructorName ?? 'HTMLElement'],\n );\n}\n\ntype HTMLElementConstructorName =\n | 'HTMLElement'\n | 'HTMLAnchorElement'\n | 'HTMLAreaElement'\n | 'HTMLAudioElement'\n | 'HTMLBaseElement'\n | 'HTMLBodyElement'\n | 'HTMLBRElement'\n | 'HTMLButtonElement'\n | 'HTMLCanvasElement'\n | 'HTMLDataElement'\n | 'HTMLDataListElement'\n | 'HTMLDetailsElement'\n // NOTE: dialog is not supported in safari 14, also it was removed from lib-dom starting typescript 4.4\n // | 'HTMLDialogElement'\n | 'HTMLDivElement'\n | 'HTMLDListElement'\n | 'HTMLEmbedElement'\n | 'HTMLFieldSetElement'\n | 'HTMLFormElement'\n | 'HTMLHeadingElement'\n | 'HTMLHeadElement'\n | 'HTMLHRElement'\n | 'HTMLHtmlElement'\n | 'HTMLIFrameElement'\n | 'HTMLImageElement'\n | 'HTMLInputElement'\n | 'HTMLModElement'\n | 'HTMLLabelElement'\n | 'HTMLLegendElement'\n | 'HTMLLIElement'\n | 'HTMLLinkElement'\n | 'HTMLMapElement'\n | 'HTMLMetaElement'\n | 'HTMLMeterElement'\n | 'HTMLObjectElement'\n | 'HTMLOListElement'\n | 'HTMLOptGroupElement'\n | 'HTMLOptionElement'\n | 'HTMLOutputElement'\n | 'HTMLParagraphElement'\n | 'HTMLParamElement'\n | 'HTMLPreElement'\n | 'HTMLProgressElement'\n | 'HTMLQuoteElement'\n | 'HTMLSlotElement'\n | 'HTMLScriptElement'\n | 'HTMLSelectElement'\n | 'HTMLSourceElement'\n | 'HTMLSpanElement'\n | 'HTMLStyleElement'\n | 'HTMLTableElement'\n | 'HTMLTableColElement'\n | 'HTMLTableRowElement'\n | 'HTMLTableSectionElement'\n | 'HTMLTemplateElement'\n | 'HTMLTextAreaElement'\n | 'HTMLTimeElement'\n | 'HTMLTitleElement'\n | 'HTMLTrackElement'\n | 'HTMLUListElement'\n | 'HTMLVideoElement';\n"],"names":["isHTMLElement","element","options","typedElement","Boolean","ownerDocument","defaultView","constructorName"],"mappings":"AAAA;;;;;;;;;;;;;CAaC,GACD,OAAO,SAASA,cACdC,OAAiB,EACjBC,OAMC;QAICC;IAFF,MAAMA,eAAeF;QAG8CC;IAFnE,OAAOE,QACLD,CAAAA,yBAAAA,oCAAAA,8BAAAA,aAAcE,aAAa,cAA3BF,kDAAAA,4BAA6BG,WAAW,KACtCH,wBAAwBA,aAAaE,aAAa,CAACC,WAAW,CAACJ,CAAAA,2BAAAA,oBAAAA,8BAAAA,QAASK,eAAe,cAAxBL,sCAAAA,2BAA4B,cAAc;AAE/G"}

Some files were not shown because too many files have changed in this diff Show More