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) => { assertSlots(state); return ( {state.contentBefore && } {state.contentAfter && } ); }; * ``` */ 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; 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, { 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; if (elementType !== typedState.components[slotName]) { 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.`); } } } } }