Skip to content

Commit fa563f6

Browse files
committed
Allow a fallback mount option, to allow keeping a video/etc alive even when no OutputPortal is mounted
1 parent ae9ea47 commit fa563f6

File tree

2 files changed

+117
-0
lines changed

2 files changed

+117
-0
lines changed

src/index.tsx

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ const ELEMENT_TYPE_SVG = 'svg';
77

88
type BaseOptions = {
99
attributes?: { [key: string]: string };
10+
fallbackMountNode?: React.MutableRefObject<Node>;
1011
};
1112

1213
type HtmlOptions = BaseOptions & {
@@ -144,6 +145,16 @@ const createPortalNode = <C extends Component<any>>(
144145
parent = undefined;
145146
lastPlaceholder = undefined;
146147
}
148+
149+
if (parent === undefined && options?.fallbackMountNode?.current) {
150+
const newParent = options?.fallbackMountNode.current;
151+
152+
newParent.appendChild(
153+
portalNode.element
154+
);
155+
156+
parent = newParent;
157+
}
147158
}
148159
} as AnyPortalNode<C>;
149160

@@ -153,6 +164,7 @@ const createPortalNode = <C extends Component<any>>(
153164
interface InPortalProps {
154165
node: AnyPortalNode;
155166
children: React.ReactNode;
167+
keepMounted: boolean;
156168
}
157169

158170
class InPortal extends React.PureComponent<InPortalProps, { nodeProps: {} }> {

stories/html.stories.tsx

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -426,3 +426,108 @@ export const ExampleFromREADME = () => {
426426

427427
return <MyComponent componentToShow='component-a' />
428428
};
429+
430+
export const DefaultToFallbackElementWhenNotInUse = () => {
431+
const fallbackRef = React.useRef(undefined);
432+
const portalNode = React.useMemo(() => createHtmlPortalNode({ fallbackMountNode: fallbackRef }), []);
433+
const [showPortal, setShowPortal] = React.useState(true);
434+
435+
return <div>
436+
<div>
437+
<InPortal node={portalNode} keepMounted>
438+
<video src="https://media.giphy.com/media/l0HlKghz8IvrQ8TYY/giphy.mp4" controls loop autoPlay />
439+
</InPortal>
440+
441+
<p>
442+
The video below should continue playing in the background toggled.
443+
</p>
444+
445+
<button onClick={() => setShowPortal(!showPortal)}>
446+
Click to toggle the OutPortal
447+
</button>
448+
449+
<hr/>
450+
451+
<h2>Regular OutPortal</h2>
452+
<Container>
453+
{ showPortal === true && <OutPortal node={portalNode} /> }
454+
</Container>
455+
456+
<h2>Fallback:</h2>
457+
<Container>
458+
<div ref={fallbackRef}></div>
459+
</Container>
460+
</div>
461+
</div>;
462+
};
463+
464+
export const PersistPlaybackWhilstDispalyedInAHiddenElement = () => {
465+
const fallbackRef = React.useRef(undefined);
466+
const portalNode = React.useMemo(() => createHtmlPortalNode({ fallbackMountNode: fallbackRef }), []);
467+
const [showPortal, setShowPortal] = React.useState(true);
468+
469+
return <div>
470+
<div ref={fallbackRef} style={{display: 'none'}}></div>
471+
<div>
472+
<InPortal node={portalNode} keepMounted>
473+
<video src="https://media.giphy.com/media/l0HlKghz8IvrQ8TYY/giphy.mp4" controls loop autoPlay />
474+
</InPortal>
475+
476+
<p>
477+
The video below should continue playing in the background toggled.
478+
</p>
479+
480+
<button onClick={() => setShowPortal(!showPortal)}>
481+
Click to toggle the OutPortal
482+
</button>
483+
484+
<hr/>
485+
486+
<div>
487+
{ showPortal === true && <OutPortal node={portalNode} /> }
488+
</div>
489+
</div>
490+
</div>;
491+
};
492+
493+
export const CombineFallbackContainerAndSwitchingBetweenTwoPlaces = () => {
494+
const fallbackRef = React.useRef(undefined);
495+
const portalNode = React.useMemo(() => createHtmlPortalNode({ fallbackMountNode: fallbackRef }), []);
496+
const [showPortal, setShowPortal] = React.useState(true);
497+
const [secondPortalSelected, setSecondPortalSelected] = React.useState(true);
498+
499+
return <div>
500+
<div ref={fallbackRef} style={{display: 'none'}}></div>
501+
<div>
502+
<InPortal node={portalNode} keepMounted>
503+
<video src="https://media.giphy.com/media/l0HlKghz8IvrQ8TYY/giphy.mp4" controls loop autoPlay />
504+
</InPortal>
505+
506+
<p>
507+
The video below should continue playing in the background toggled.
508+
</p>
509+
510+
<button onClick={() => setSecondPortalSelected(!secondPortalSelected)}>
511+
Click to switch the OutPortal
512+
</button>
513+
514+
<button onClick={() => setShowPortal(!showPortal)}>
515+
Click to toggle the OutPortals
516+
</button>
517+
518+
<hr/>
519+
520+
{ showPortal === true && <div>
521+
<Container>
522+
<h2>Portal 1:</h2>
523+
{ !secondPortalSelected && <OutPortal node={portalNode} /> }
524+
</Container>
525+
<Container>
526+
<h2>Portal 2:</h2>
527+
{ secondPortalSelected && <OutPortal node={portalNode} /> }
528+
</Container>
529+
</div> }
530+
</div>
531+
</div>;
532+
};
533+

0 commit comments

Comments
 (0)