diff --git a/src/alert/index.tsx b/src/alert/index.tsx index da58a55c52..a9216fcc1c 100644 --- a/src/alert/index.tsx +++ b/src/alert/index.tsx @@ -1,9 +1,9 @@ // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 'use client'; -import React, { useEffect } from 'react'; +import React, { useEffect, useRef } from 'react'; -import { useUniqueId } from '@cloudscape-design/component-toolkit/internal'; +import { useMergeRefs, useUniqueId } from '@cloudscape-design/component-toolkit/internal'; import { getAnalyticsMetadataAttribute } from '@cloudscape-design/component-toolkit/internal/analytics-metadata'; import { FunnelMetrics } from '../internal/analytics'; @@ -23,13 +23,16 @@ export { AlertProps }; const Alert = React.forwardRef( ({ type = 'info', visible = true, style, ...props }: AlertProps, ref: React.Ref) => { const analyticsMetadata = getAnalyticsMetadataProps(props as BasePropsWithAnalyticsMetadata); - const baseComponentProps = useBaseComponent( + + const baseComponentProps = useBaseComponent( 'Alert', { props: { type, visible, dismissible: props.dismissible }, }, analyticsMetadata ); + const rootRef = useRef(null); + const __internalRootRef = useMergeRefs(rootRef, baseComponentProps.__internalRootRef); const { funnelIdentifier, funnelInteractionId, funnelErrorContext, submissionAttempt, funnelState, errorCount } = useFunnel(); @@ -47,7 +50,7 @@ const Alert = React.forwardRef( errorCount.current++; // We don't want to report an error if it is hidden, e.g. inside an Expandable Section. - const errorIsVisible = (baseComponentProps.__internalRootRef.current?.getBoundingClientRect()?.width ?? 0) > 0; + const errorIsVisible = (rootRef.current?.getBoundingClientRect()?.width ?? 0) > 0; if (errorIsVisible) { if (subStepSelector) { @@ -72,7 +75,7 @@ const Alert = React.forwardRef( stepNameSelector, stepName, stepIdentifier, - currentDocument: baseComponentProps.__internalRootRef.current?.ownerDocument, + currentDocument: rootRef.current?.ownerDocument, totalSubSteps: subStepCount.current, funnelIdentifier, subStepAllSelector: getSubStepAllSelector(), @@ -112,6 +115,7 @@ const Alert = React.forwardRef( visible={visible} {...props} {...baseComponentProps} + __internalRootRef={__internalRootRef} ref={ref} messageSlotId={messageSlotId} style={style} diff --git a/src/alert/internal.tsx b/src/alert/internal.tsx index 9757c5ccb7..d90bae6274 100644 --- a/src/alert/internal.tsx +++ b/src/alert/internal.tsx @@ -38,7 +38,7 @@ const typeToIcon: Record = { }; type InternalAlertProps = SomeRequired & - InternalBaseComponentProps & { + InternalBaseComponentProps & { messageSlotId?: string; style?: AlertProps['style']; }; @@ -59,7 +59,7 @@ const InternalAlert = React.forwardRef( action, onDismiss, onButtonClick, - __internalRootRef = null, + __internalRootRef, statusIconAriaLabel: deprecatedStatusIconAriaLabel, dismissAriaLabel: deprecatedDismissAriaLabel, messageSlotId, diff --git a/src/anchor-navigation/internal.tsx b/src/anchor-navigation/internal.tsx index c56a5d48fe..7beb92f1d3 100644 --- a/src/anchor-navigation/internal.tsx +++ b/src/anchor-navigation/internal.tsx @@ -19,7 +19,7 @@ export default function InternalAnchorNavigation({ onFollow, onActiveHrefChange, activeHref = '', - __internalRootRef = null, + __internalRootRef, scrollSpyOffset = 0, ...props }: AnchorNavigationProps & InternalBaseComponentProps) { diff --git a/src/app-layout-toolbar/index.tsx b/src/app-layout-toolbar/index.tsx index 1739b9bc30..564649c906 100644 --- a/src/app-layout-toolbar/index.tsx +++ b/src/app-layout-toolbar/index.tsx @@ -54,7 +54,7 @@ const AppLayoutToolbar = React.forwardRef( ); } } - const { __internalRootRef } = useBaseComponent( + const { __internalRootRef } = useBaseComponent( 'AppLayoutToolbar', { props: { diff --git a/src/app-layout/index.tsx b/src/app-layout/index.tsx index 71536e2f51..ab26a65223 100644 --- a/src/app-layout/index.tsx +++ b/src/app-layout/index.tsx @@ -46,7 +46,7 @@ const AppLayout = React.forwardRef( ); } } - const { __internalRootRef } = useBaseComponent( + const { __internalRootRef } = useBaseComponent( 'AppLayout', { props: { diff --git a/src/area-chart/internal.tsx b/src/area-chart/internal.tsx index 86e4c1eae9..a6f79565a0 100644 --- a/src/area-chart/internal.tsx +++ b/src/area-chart/internal.tsx @@ -64,7 +64,7 @@ export default function InternalAreaChart({ loadingText, recoveryText, onRecoveryClick, - __internalRootRef = null, + __internalRootRef, ...props }: InternalAreaChartProps) { const baseProps = getBaseProps(props); diff --git a/src/attribute-editor/internal.tsx b/src/attribute-editor/internal.tsx index 0bbfc5b308..8caa901c61 100644 --- a/src/attribute-editor/internal.tsx +++ b/src/attribute-editor/internal.tsx @@ -43,7 +43,7 @@ const InternalAttributeEditor = React.forwardRef( i18nStrings, onAddButtonClick, onRemoveButtonClick, - __internalRootRef = null, + __internalRootRef, ...props }: InternalAttributeEditorProps, ref: React.Ref diff --git a/src/box/internal.tsx b/src/box/internal.tsx index 514f7c11e2..99df646f17 100644 --- a/src/box/internal.tsx +++ b/src/box/internal.tsx @@ -23,7 +23,7 @@ export default function InternalBox({ fontWeight, color, children, - __internalRootRef = null, + __internalRootRef, ...props }: InternalBoxProps) { const baseProps = getBaseProps(props); diff --git a/src/button-group/internal.tsx b/src/button-group/internal.tsx index 64d3750f1e..0d42a18bfb 100644 --- a/src/button-group/internal.tsx +++ b/src/button-group/internal.tsx @@ -30,7 +30,7 @@ const InternalButtonGroup = forwardRef( onFilesChange, ariaLabel, dropdownExpandToViewport, - __internalRootRef = null, + __internalRootRef, ...props }: InternalButtonGroupProps, ref: React.Ref diff --git a/src/button/internal.tsx b/src/button/internal.tsx index cd14ed24c4..0c956476da 100644 --- a/src/button/internal.tsx +++ b/src/button/internal.tsx @@ -57,7 +57,7 @@ export type InternalButtonProps = Omit & { __title?: string; __emitPerformanceMarks?: boolean; __skipNativeAttributesWarnings?: boolean; -} & InternalBaseComponentProps; +} & InternalBaseComponentProps; export const InternalButton = React.forwardRef( ( @@ -93,7 +93,7 @@ export const InternalButton = React.forwardRef( style, nativeButtonAttributes, nativeAnchorAttributes, - __internalRootRef = null, + __internalRootRef, __focusable = false, __injectAnalyticsComponentMetadata = false, __title, diff --git a/src/container/internal.tsx b/src/container/internal.tsx index 12c205d8e5..32ce40117c 100644 --- a/src/container/internal.tsx +++ b/src/container/internal.tsx @@ -70,7 +70,7 @@ export default function InternalContainer({ __stickyOffset, __mobileStickyOffset, __stickyHeader = false, - __internalRootRef = null, + __internalRootRef, __disableFooterDivider = false, __hiddenContent = false, __headerRef, diff --git a/src/copy-to-clipboard/internal.tsx b/src/copy-to-clipboard/internal.tsx index de13589754..49f5339ba0 100644 --- a/src/copy-to-clipboard/internal.tsx +++ b/src/copy-to-clipboard/internal.tsx @@ -26,7 +26,7 @@ export default function InternalCopyToClipboard({ popoverRenderWithPortal, disabled, disabledReason, - __internalRootRef = null, + __internalRootRef, ...restProps }: InternalCopyToClipboardProps) { const [status, setStatus] = useState<'pending' | 'success' | 'error'>('pending'); diff --git a/src/date-input/internal.tsx b/src/date-input/internal.tsx index 2219e5c659..d81c205773 100644 --- a/src/date-input/internal.tsx +++ b/src/date-input/internal.tsx @@ -29,7 +29,7 @@ const InternalDateInput = React.forwardRef( locale, format = 'slashed', inputFormat = 'slashed', - __internalRootRef = null, + __internalRootRef, ...props }: InternalDateInputProps, ref: Ref diff --git a/src/file-dropzone/internal.tsx b/src/file-dropzone/internal.tsx index d6b5ae7820..a67f52651d 100644 --- a/src/file-dropzone/internal.tsx +++ b/src/file-dropzone/internal.tsx @@ -14,7 +14,7 @@ import styles from './styles.css.js'; export default function InternalFileDropzone({ onChange, children, - __internalRootRef = null, + __internalRootRef, ...restProps }: FileDropzoneProps & InternalBaseComponentProps) { const [isDropzoneHovered, setDropzoneHovered] = useState(false); diff --git a/src/file-input/internal.tsx b/src/file-input/internal.tsx index c09d776f11..967c3be44d 100644 --- a/src/file-input/internal.tsx +++ b/src/file-input/internal.tsx @@ -42,7 +42,7 @@ const InternalFileInput = React.forwardRef( onChange, variant = 'button', children, - __internalRootRef = null, + __internalRootRef, __inputClassName, __inputNativeAttributes, __injectAnalyticsComponentMetadata, diff --git a/src/file-upload/internal.tsx b/src/file-upload/internal.tsx index ab486f4c73..960fedbb39 100644 --- a/src/file-upload/internal.tsx +++ b/src/file-upload/internal.tsx @@ -44,7 +44,7 @@ function InternalFileUpload( showFileLastModified, showFileThumbnail, i18nStrings, - __internalRootRef = null, + __internalRootRef, constraintText, errorText, warningText, diff --git a/src/form-field/interfaces.ts b/src/form-field/interfaces.ts index 6e3ce185d4..3d1b91b6f7 100644 --- a/src/form-field/interfaces.ts +++ b/src/form-field/interfaces.ts @@ -108,7 +108,7 @@ export namespace FormFieldProps { } } -export interface InternalFormFieldProps extends FormFieldProps, InternalBaseComponentProps { +export interface InternalFormFieldProps extends FormFieldProps, InternalBaseComponentProps { /** * Visually hide the label. */ diff --git a/src/form-field/internal.tsx b/src/form-field/internal.tsx index f897d4b9b8..a932c5a3a2 100644 --- a/src/form-field/internal.tsx +++ b/src/form-field/internal.tsx @@ -3,7 +3,7 @@ import React, { useEffect, useRef } from 'react'; import clsx from 'clsx'; -import { useUniqueId, warnOnce } from '@cloudscape-design/component-toolkit/internal'; +import { useMergeRefs, useUniqueId, warnOnce } from '@cloudscape-design/component-toolkit/internal'; import { copyAnalyticsMetadataAttribute } from '@cloudscape-design/component-toolkit/internal/analytics-metadata'; import InternalGrid from '../grid/internal'; @@ -117,12 +117,14 @@ export default function InternalFormField({ errorText, warningText, __hideLabel, - __internalRootRef = null, + __internalRootRef, __disableGutters = false, __analyticsMetadata = undefined, __style = {}, ...rest }: InternalFormFieldProps) { + const rootRef = useRef(); + const ref = useMergeRefs(rootRef, __internalRootRef); const baseProps = getBaseProps(rest); const isRefresh = useVisualRefresh(); @@ -180,7 +182,7 @@ export default function InternalFormField({ errorCount.current++; // We don't want to report an error if it is hidden, e.g. inside an Expandable Section. - const errorIsVisible = (__internalRootRef?.current?.getBoundingClientRect()?.width ?? 0) > 0; + const errorIsVisible = (rootRef.current?.getBoundingClientRect()?.width ?? 0) > 0; if (errorIsVisible) { FunnelMetrics.funnelSubStepError({ @@ -216,7 +218,7 @@ export default function InternalFormField({ {...baseProps} className={clsx(baseProps.className, styles.root)} style={__style} - ref={__internalRootRef} + ref={ref} {...analyticsAttributes} {...copyAnalyticsMetadataAttribute(rest)} > diff --git a/src/form/index.tsx b/src/form/index.tsx index a7ad4c2735..c98ab08618 100644 --- a/src/form/index.tsx +++ b/src/form/index.tsx @@ -1,9 +1,9 @@ // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 'use client'; -import React, { useEffect } from 'react'; +import React, { useEffect, useRef } from 'react'; -import { useUniqueId } from '@cloudscape-design/component-toolkit/internal'; +import { useMergeRefs, useUniqueId } from '@cloudscape-design/component-toolkit/internal'; import { FunnelMetrics } from '../internal/analytics'; import { AnalyticsFunnel, AnalyticsFunnelStep } from '../internal/analytics/components/analytics-funnel'; @@ -11,7 +11,7 @@ import { useFunnel, useFunnelNameSelector, useFunnelStepRef } from '../internal/ import { getSubStepAllSelector, getTextFromSelector } from '../internal/analytics/selectors'; import { BasePropsWithAnalyticsMetadata, getAnalyticsMetadataProps } from '../internal/base-component'; import { ButtonContext, ButtonContextProps } from '../internal/context/button-context'; -import useBaseComponent from '../internal/hooks/use-base-component'; +import useBaseComponent, { InternalBaseComponentProps } from '../internal/hooks/use-base-component'; import { applyDisplayName } from '../internal/utils/apply-display-name'; import { FormProps } from './interfaces'; import InternalForm from './internal'; @@ -27,7 +27,9 @@ const FormWithAnalytics = ({ errorText, __internalRootRef, ...props -}: FormProps & ReturnType>) => { +}: FormProps & InternalBaseComponentProps) => { + const rootRef = useRef(null); + const ref = useMergeRefs(rootRef, __internalRootRef); const { funnelIdentifier, funnelInteractionId, @@ -62,7 +64,7 @@ const FormWithAnalytics = ({ stepNameSelector: funnelStepInfo.current.stepNameSelector, stepName, stepIdentifier: funnelStepInfo.current.stepIdentifier, - currentDocument: __internalRootRef.current?.ownerDocument, + currentDocument: rootRef.current?.ownerDocument, totalSubSteps: funnelStepInfo.current.subStepCount.current, funnelIdentifier, subStepAllSelector: getSubStepAllSelector(), @@ -86,7 +88,6 @@ const FormWithAnalytics = ({ errorCount, funnelErrorContext, errorSlotId, - __internalRootRef, funnelStepInfo, ]); @@ -100,7 +101,7 @@ const FormWithAnalytics = ({ {...props} {...funnelProps} {...funnelStepInfo.current.funnelStepProps} - __internalRootRef={__internalRootRef} + __internalRootRef={ref} __injectAnalyticsComponentMetadata={true} /> @@ -109,7 +110,7 @@ const FormWithAnalytics = ({ export default function Form({ variant = 'full-page', ...props }: FormProps) { const analyticsMetadata = getAnalyticsMetadataProps(props as BasePropsWithAnalyticsMetadata); - const baseComponentProps = useBaseComponent( + const baseComponentProps = useBaseComponent( 'Form', { props: { diff --git a/src/grid/internal.tsx b/src/grid/internal.tsx index 2f840677b3..cc7c05881c 100644 --- a/src/grid/internal.tsx +++ b/src/grid/internal.tsx @@ -37,7 +37,7 @@ const InternalGrid = React.forwardRef( children, __tagOverride, __responsiveClassName, - __internalRootRef = null, + __internalRootRef, ...restProps }: InternalGridProps, ref: React.Ref diff --git a/src/header/internal.tsx b/src/header/internal.tsx index 5ccb94a9db..f9d6f3cd70 100644 --- a/src/header/internal.tsx +++ b/src/header/internal.tsx @@ -36,7 +36,7 @@ export default function InternalHeader({ counter, description, info, - __internalRootRef = null, + __internalRootRef, __disableActionsWrapping, __headingTagRef, __headingTagTabIndex, diff --git a/src/icon/internal.tsx b/src/icon/internal.tsx index 78e9d86d10..73c1a3d5e0 100644 --- a/src/icon/internal.tsx +++ b/src/icon/internal.tsx @@ -46,7 +46,7 @@ const InternalIcon = ({ ariaLabel, svg, badge, - __internalRootRef = null, + __internalRootRef, ...props }: InternalIconProps) => { const icons = useContext(InternalIconContext); diff --git a/src/internal/hooks/use-base-component/index.ts b/src/internal/hooks/use-base-component/index.ts index 0300b5612c..63a0ec9dd6 100644 --- a/src/internal/hooks/use-base-component/index.ts +++ b/src/internal/hooks/use-base-component/index.ts @@ -1,6 +1,6 @@ // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 -import React, { MutableRefObject } from 'react'; +import React from 'react'; import { ComponentConfiguration, @@ -15,8 +15,12 @@ import { getVisualTheme } from '../../utils/get-visual-theme'; import { useVisualRefresh } from '../use-visual-mode'; import { useMissingStylesCheck } from './styles-check'; -export interface InternalBaseComponentProps { - __internalRootRef?: MutableRefObject | null; +export interface InternalBaseComponentProps { + // Typescript requires Ref type to be exact DOM element type it is assigned to, e.g. HTMLDivElement + // Typical community practice is explicit type casting: https://stackoverflow.com/questions/61102101/cannot-assign-refobjecthtmldivelement-to-refobjecthtmlelement-instance + // To avoid doing this, we use any to skip type checks. Treat this type as pass through, never + // read `__internalRootRef.current`, use your own refs if you need + __internalRootRef?: React.Ref; } /** @@ -24,7 +28,7 @@ export interface InternalBaseComponentProps { * attached to the (internal) component's root DOM node. The hook takes care of attaching the metadata to this * root DOM node and emits the telemetry for this component. */ -export default function useBaseComponent( +export default function useBaseComponent( componentName: string, config?: ComponentConfiguration, analyticsMetadata?: AnalyticsMetadata @@ -32,12 +36,12 @@ export default function useBaseComponent( const isVisualRefresh = useVisualRefresh(); const theme = getVisualTheme(THEME, isVisualRefresh); useComponentMetrics(componentName, { packageSource: PACKAGE_SOURCE, packageVersion: PACKAGE_VERSION, theme }, config); - const elementRef = useComponentMetadata( + const elementRef = useComponentMetadata( componentName, { packageName: PACKAGE_SOURCE, version: PACKAGE_VERSION, theme }, analyticsMetadata as any ); - useMissingStylesCheck(elementRef as React.RefObject); - useFocusVisible(elementRef as React.RefObject); + useMissingStylesCheck(elementRef); + useFocusVisible(elementRef); return { __internalRootRef: elementRef }; } diff --git a/src/link/internal.tsx b/src/link/internal.tsx index 4cc3acb44b..8afe330cb3 100644 --- a/src/link/internal.tsx +++ b/src/link/internal.tsx @@ -30,7 +30,7 @@ import { getLinkStyles } from './style'; import styles from './styles.css.js'; -type InternalLinkProps = InternalBaseComponentProps & +type InternalLinkProps = InternalBaseComponentProps & Omit & { variant?: LinkProps['variant'] | 'top-navigation' | 'link' | 'recovery'; }; @@ -50,7 +50,7 @@ const InternalLink = React.forwardRef( onFollow, onClick, children, - __internalRootRef = null, + __internalRootRef, style, ...props }: InternalLinkProps, @@ -163,7 +163,6 @@ const InternalLink = React.forwardRef( const sharedProps = { id: linkId, ...baseProps, - // https://github.com/microsoft/TypeScript/issues/36659 ref: useMergeRefs(linkRef, __internalRootRef), className: clsx( styles.link, diff --git a/src/list/internal.tsx b/src/list/internal.tsx index bb7d91a3d5..0ba04cfabb 100644 --- a/src/list/internal.tsx +++ b/src/list/internal.tsx @@ -42,7 +42,7 @@ export default function InternalList({ i18nStrings, disablePaddings, disableItemPaddings, - __internalRootRef = null, + __internalRootRef, ...rest }: InternalListProps) { const baseProps = getBaseProps(rest); diff --git a/src/mixed-line-bar-chart/internal.tsx b/src/mixed-line-bar-chart/internal.tsx index 1240297e65..4dfa9612ba 100644 --- a/src/mixed-line-bar-chart/internal.tsx +++ b/src/mixed-line-bar-chart/internal.tsx @@ -77,7 +77,7 @@ export default function InternalMixedLineBarChart) { const baseProps = getBaseProps(props); diff --git a/src/modal/internal.tsx b/src/modal/internal.tsx index d7727903fb..16a04ed58d 100644 --- a/src/modal/internal.tsx +++ b/src/modal/internal.tsx @@ -94,7 +94,7 @@ function PortaledModal({ disableContentPaddings, onButtonClick = () => {}, onDismiss, - __internalRootRef = null, + __internalRootRef, __injectAnalyticsComponentMetadata, __funnelProps, __funnelStepProps, diff --git a/src/multiselect/internal.tsx b/src/multiselect/internal.tsx index 71f48f589f..f20dbb958f 100644 --- a/src/multiselect/internal.tsx +++ b/src/multiselect/internal.tsx @@ -56,7 +56,7 @@ const InternalMultiselect = React.forwardRef( expandToViewport, tokenLimitShowFewerAriaLabel, tokenLimitShowMoreAriaLabel, - __internalRootRef = null, + __internalRootRef, autoFocus, enableSelectAll, ...restProps diff --git a/src/pagination/internal.tsx b/src/pagination/internal.tsx index aa60adb931..ec6ecad9b3 100644 --- a/src/pagination/internal.tsx +++ b/src/pagination/internal.tsx @@ -109,7 +109,7 @@ export default function InternalPagination({ onChange, onNextPageClick, onPreviousPageClick, - __internalRootRef = null, + __internalRootRef, ...rest }: InternalPaginationProps) { const baseProps = getBaseProps(rest); diff --git a/src/popover/internal.tsx b/src/popover/internal.tsx index 8041f08805..92dbe0c4ac 100644 --- a/src/popover/internal.tsx +++ b/src/popover/internal.tsx @@ -51,7 +51,7 @@ function InternalPopover( renderWithPortal = false, __onOpen, - __internalRootRef = null, + __internalRootRef, __closeAnalyticsAction, ...restProps diff --git a/src/prompt-input/internal.tsx b/src/prompt-input/internal.tsx index 3cae0ae896..db737d11cc 100644 --- a/src/prompt-input/internal.tsx +++ b/src/prompt-input/internal.tsx @@ -55,7 +55,7 @@ const InternalPromptInput = React.forwardRef( secondaryContent, disableSecondaryActionsPaddings, disableSecondaryContentPaddings, - __internalRootRef = null, + __internalRootRef, ...rest }: InternalPromptInputProps, ref: Ref diff --git a/src/radio-group/internal.tsx b/src/radio-group/internal.tsx index a179f22d99..e5419b1fbe 100644 --- a/src/radio-group/internal.tsx +++ b/src/radio-group/internal.tsx @@ -29,7 +29,7 @@ const InternalRadioGroup = React.forwardRef( ariaControls, onChange, readOnly, - __internalRootRef = null, + __internalRootRef, ...props }: InternalRadioGroupProps, ref: React.Ref diff --git a/src/segmented-control/internal.tsx b/src/segmented-control/internal.tsx index 2151c4de30..015d4790cd 100644 --- a/src/segmented-control/internal.tsx +++ b/src/segmented-control/internal.tsx @@ -21,7 +21,7 @@ export default function InternalSegmentedControl({ label, ariaLabelledby, onChange, - __internalRootRef = null, + __internalRootRef, ...props }: InternalSegmentedControlProps) { const baseProps = getBaseProps(props); diff --git a/src/select/internal.tsx b/src/select/internal.tsx index 882d7a4e48..2043c27e7e 100644 --- a/src/select/internal.tsx +++ b/src/select/internal.tsx @@ -67,7 +67,7 @@ const InternalSelect = React.forwardRef( expandToViewport, autoFocus, __inFilteringToken, - __internalRootRef = null, + __internalRootRef, ...restProps }: InternalSelectProps, externalRef: React.Ref diff --git a/src/slider/internal.tsx b/src/slider/internal.tsx index 1dea592c31..c5d53fbac6 100644 --- a/src/slider/internal.tsx +++ b/src/slider/internal.tsx @@ -43,7 +43,7 @@ export default function InternalSlider({ hideFillLine, valueFormatter, i18nStrings, - __internalRootRef = null, + __internalRootRef, ...rest }: InternalSliderProps) { const baseProps = getBaseProps(rest); diff --git a/src/steps/internal.tsx b/src/steps/internal.tsx index 892198aac4..7dd9af8626 100644 --- a/src/steps/internal.tsx +++ b/src/steps/internal.tsx @@ -10,7 +10,7 @@ import { StepsProps } from './interfaces'; import styles from './styles.css.js'; -type InternalStepsProps = SomeRequired & InternalBaseComponentProps; +type InternalStepsProps = SomeRequired & InternalBaseComponentProps; const InternalStep = ({ status, statusIconAriaLabel, header, details }: StepsProps.Step) => { return ( diff --git a/src/tiles/internal.tsx b/src/tiles/internal.tsx index bdd77fcf15..a1a372dc18 100644 --- a/src/tiles/internal.tsx +++ b/src/tiles/internal.tsx @@ -34,7 +34,7 @@ const InternalTiles = React.forwardRef( columns, onChange, readOnly, - __internalRootRef = null, + __internalRootRef, ...rest }: InternalTilesProps, ref: React.Ref diff --git a/src/time-input/internal.tsx b/src/time-input/internal.tsx index 6e0c266f48..e575416851 100644 --- a/src/time-input/internal.tsx +++ b/src/time-input/internal.tsx @@ -28,13 +28,7 @@ type InternalTimeInputProps = TimeInputProps & InternalBaseComponentProps; const InternalTimeInput = React.forwardRef( ( - { - format = 'hh:mm:ss', - use24Hour = true, - autoComplete = true, - __internalRootRef = null, - ...props - }: InternalTimeInputProps, + { format = 'hh:mm:ss', use24Hour = true, autoComplete = true, __internalRootRef, ...props }: InternalTimeInputProps, ref: Ref ) => { const inputRef = useRef(null); diff --git a/src/toggle/internal.tsx b/src/toggle/internal.tsx index a959e6e727..35e9d7c682 100644 --- a/src/toggle/internal.tsx +++ b/src/toggle/internal.tsx @@ -38,7 +38,7 @@ const InternalToggle = React.forwardRef( onFocus, onBlur, onChange, - __internalRootRef = null, + __internalRootRef, __injectAnalyticsComponentMetadata, ...rest }, diff --git a/src/wizard/wizard-form.tsx b/src/wizard/wizard-form.tsx index a7fc42a860..389d8463c2 100644 --- a/src/wizard/wizard-form.tsx +++ b/src/wizard/wizard-form.tsx @@ -3,7 +3,7 @@ import React, { MutableRefObject, useEffect, useRef } from 'react'; import clsx from 'clsx'; -import { useComponentMetadata, useUniqueId } from '@cloudscape-design/component-toolkit/internal'; +import { useComponentMetadata, useMergeRefs, useUniqueId } from '@cloudscape-design/component-toolkit/internal'; import { AnalyticsMetadata } from '@cloudscape-design/component-toolkit/internal/base-component/metrics/interfaces'; import InternalForm from '../form/internal'; @@ -86,6 +86,8 @@ function WizardForm({ onPrimaryClick, onSkipToClick, }: WizardFormProps & { stepHeaderRef: MutableRefObject }) { + const rootRef = useRef(); + const ref = useMergeRefs(rootRef, __internalRootRef); const { title, info, description, content, errorText, isOptional } = steps[activeStepIndex] || {}; const isLastStep = activeStepIndex >= steps.length - 1; const skipToTargetIndex = findSkipToTargetIndex(steps, activeStepIndex); @@ -112,7 +114,7 @@ function WizardForm({ stepNameSelector: funnelStepInfo.current.stepNameSelector, stepName, stepIdentifier: funnelStepInfo.current.stepIdentifier, - currentDocument: __internalRootRef?.current?.ownerDocument, + currentDocument: rootRef.current?.ownerDocument, totalSubSteps: funnelStepInfo.current.subStepCount.current, funnelIdentifier, subStepAllSelector: getSubStepAllSelector(), @@ -147,7 +149,7 @@ function WizardForm({