@ionic/react 8.8.11-nightly.20260616 → 8.8.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -549,6 +549,10 @@ const createForwardRef$1 = (ReactComponent, displayName) => {
549
549
  return jsx(ReactComponent, { ...props, forwardedRef: ref });
550
550
  };
551
551
  forwardRef.displayName = displayName;
552
+ // Cast the render function to the type React.forwardRef already infers for it.
553
+ // React 18's `forwardRef` wraps the props in `PropsWithoutRef`, and since
554
+ // `PropType` is unconstrained TypeScript can't prove the round-trip is safe.
555
+ // The cast keeps the inferred component type intact without widening to `any`.
552
556
  return React.forwardRef(forwardRef);
553
557
  };
554
558
  const defineCustomElement = (tagName, customElement) => {
@@ -704,6 +708,10 @@ displayName) => {
704
708
  return jsx(ReactComponent, { ...props, forwardedRef: ref });
705
709
  };
706
710
  forwardRef.displayName = displayName;
711
+ // Cast the render function to the type React.forwardRef already infers for it.
712
+ // React 18's `forwardRef` wraps the props in `PropsWithoutRef`, and since
713
+ // `PropType` is unconstrained TypeScript can't prove the round-trip is safe.
714
+ // The cast keeps the inferred component type intact without widening to `any`.
707
715
  return React.forwardRef(forwardRef);
708
716
  };
709
717
  const isPlatform = (platform) => {
@@ -953,6 +961,42 @@ const createInlineOverlayComponent = (tagName, defineCustomElement, hasDelegateH
953
961
  componentWillUnmount() {
954
962
  this.isUnmounted = true;
955
963
  const node = this.ref.current;
964
+ if (!node) {
965
+ return;
966
+ }
967
+ /**
968
+ * CoreDelegate (or user code in onWillPresent) can move the overlay out
969
+ * of where React rendered it. React's unmount only removes the node from
970
+ * its original React location, so we recover a relocated host here,
971
+ * regardless of open state.
972
+ *
973
+ * We can't gate this on `isOpen`: the overlay can be moved before it
974
+ * finishes presenting (e.g. the React 18 StrictMode mount/unmount cycle,
975
+ * where the present events that flip `isOpen` haven't fired yet), which
976
+ * would orphan the relocated host in the DOM. It also has to run
977
+ * synchronously here, since React's portal `removeChild` runs after
978
+ * `componentWillUnmount` returns and needs the host where it expects it.
979
+ */
980
+ if (node.isConnected) {
981
+ if (this.props.isNested) {
982
+ /**
983
+ * Nested overlays render inline inside a `<template>`. If the host
984
+ * has been moved out of that template, React's unmount won't reach
985
+ * it, so remove it directly. A host still in its template is left
986
+ * for React to remove.
987
+ */
988
+ if (!(node.parentElement instanceof HTMLTemplateElement)) {
989
+ node.remove();
990
+ }
991
+ }
992
+ else if (this.portalTarget && node.parentNode !== this.portalTarget) {
993
+ /**
994
+ * Portaled overlays: move the host back into `portalTarget` so
995
+ * React's portal `removeChild` can find it.
996
+ */
997
+ this.portalTarget.appendChild(node);
998
+ }
999
+ }
956
1000
  /**
957
1001
  * If the overlay is being unmounted, but is still
958
1002
  * open, this means the unmount was triggered outside
@@ -966,31 +1010,13 @@ const createInlineOverlayComponent = (tagName, defineCustomElement, hasDelegateH
966
1010
  * Unmounting the overlay at this stage should skip
967
1011
  * the dismiss lifecycle, including skipping the transition.
968
1012
  *
1013
+ * Detach the local event listener that performs the state updates,
1014
+ * before dismissing the overlay, to prevent the callback handlers
1015
+ * executing after the component has been unmounted. This is to
1016
+ * avoid memory leaks.
969
1017
  */
970
- if (node && this.state.isOpen) {
971
- /**
972
- * Detach the local event listener that performs the state updates,
973
- * before dismissing the overlay, to prevent the callback handlers
974
- * executing after the component has been unmounted. This is to
975
- * avoid memory leaks.
976
- */
1018
+ if (this.state.isOpen) {
977
1019
  node.removeEventListener('didDismiss', this.handleDidDismiss);
978
- if (this.props.isNested) {
979
- /**
980
- * Nested overlays render inline (no portal). CoreDelegate may
981
- * have moved the node out of its React parent, so React's
982
- * unmount won't reach it. Remove it directly.
983
- */
984
- node.remove();
985
- }
986
- else if (node.isConnected && this.portalTarget && node.parentNode !== this.portalTarget) {
987
- /**
988
- * Portaled path: move the overlay back into `portalTarget` so
989
- * React's portal removeChild can find it. CoreDelegate (or user
990
- * code in onWillPresent) may have moved it elsewhere while open.
991
- */
992
- this.portalTarget.appendChild(node);
993
- }
994
1020
  detachProps(node, this.props);
995
1021
  }
996
1022
  }
@@ -1051,7 +1077,11 @@ const createInlineOverlayComponent = (tagName, defineCustomElement, hasDelegateH
1051
1077
  }
1052
1078
  };
1053
1079
  // Forward the nesting context as a prop to avoid contextType on the class.
1054
- const ReactComponentWithNesting = (props) => createElement(NestedOverlayContext.Consumer, null, (isNested) => createElement(ReactComponent, { ...props, isNested }));
1080
+ // The render function is passed via `children` (not as a varargs child) so it
1081
+ // matches `Context.Consumer`'s render-prop signature `(value) => ReactNode`.
1082
+ const ReactComponentWithNesting = (props) => createElement(NestedOverlayContext.Consumer, {
1083
+ children: (isNested) => createElement(ReactComponent, { ...props, isNested }),
1084
+ });
1055
1085
  ReactComponentWithNesting.displayName = displayName;
1056
1086
  return createForwardRef(ReactComponentWithNesting, displayName);
1057
1087
  };