Skip to content

Commit

Permalink
remove intersection observer logic from mathml (#36794)
Browse files Browse the repository at this point in the history
* require consumers to provide styling for formula dimensions
  • Loading branch information
kvchari committed Nov 10, 2021
1 parent 9339ce1 commit d13bbc1
Show file tree
Hide file tree
Showing 7 changed files with 105 additions and 301 deletions.
61 changes: 5 additions & 56 deletions extensions/amp-mathml/1.0/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,44 +50,19 @@ defineBentoMathml();
<body>
<h2>The Quadratic Formula</h2>
<bento-mathml
style="height: 40px"
style="height: 40px;"
data-formula="\[x = {-b \pm \sqrt{b^2-4ac} \over 2a}.\]"
></bento-mathml>

<h2>Cauchy's Integral Formula</h2>
<bento-mathml
style="height: 41px"
data-formula="\[f(a) = \frac{1}{2\pi i} \oint\frac{f(z)}{z-a}dz\]"
></bento-mathml>

<h2>Double angle formula for Cosines</h2>
<bento-mathml
style="height: 19px"
data-formula="\[cos(θ+φ)=\cos(θ)\cos(φ)−\sin(θ)\sin(φ)\]"
></bento-mathml>

<h2>Inline formula</h2>
<p>
This is an example of a formula of
<bento-mathml
style="height: 11px; width: 8px"
inline
data-formula="`x`"
></bento-mathml
>,
This is an example of a formula,
<bento-mathml
style="height: 40px; width: 147px"
inline
data-formula="\[x = {-b \pm \sqrt{b^2-4ac} \over 2a}.\]"
></bento-mathml>
placed inline in the middle of a block of text.
<bento-mathml
style="height: 19px; width: 72px"
inline
data-formula="\( \cos(θ+φ) \)"
></bento-mathml>
This shows how the formula will fit inside a block of text and can be
styled with CSS.
</p>
</body>
</html>
Expand Down Expand Up @@ -159,40 +134,15 @@ function App() {
formula="\[x = {-b \pm \sqrt{b^2-4ac} \over 2a}.\]"
></BentoMathml>

<h2>Cauchy's Integral Formula</h2>
<BentoMathml
style={{height: 41}}
formula="\[f(a) = \frac{1}{2\pi i} \oint\frac{f(z)}{z-a}dz\]"
></BentoMathml>
<h2>Double angle formula for Cosines</h2>
<BentoMathml
style={{height: 19}}
formula="\[cos(θ+φ)=\cos(θ)\cos(φ)−\sin(θ)\sin(φ)\]"
></BentoMathml>
<h2>Inline formula</h2>
<p>
This is an example of a formula of{' '}
<BentoMathml
style={{height: 11, width: 8}}
inline
formula="`x`"
></BentoMathml>
,{' '}
This is an example of a formula,{' '}
<BentoMathml
style={{height: 40, width: 147}}
inline
formula="\[x = {-b \pm \sqrt{b^2-4ac} \over 2a}.\]"
></BentoMathml>{' '}
placed inline in the middle of a block of text.{' '}
<BentoMathml
style={{height: 19, width: 72}}
inline
formula="\( \cos(θ+φ) \)"
></BentoMathml>{' '}
This shows how the formula will fit inside a block of text and can be
styled with CSS.
></BentoMathml>
, placed inline in the middle of a block of text. This shows how the formula will fit inside a block of text and can be styled with CSS.
</p>
</>
);
Expand All @@ -217,7 +167,6 @@ Or via `className`:

```css
.custom-styles {
background-color: red;
height: 40px;
width: 147px;
}
Expand Down
11 changes: 0 additions & 11 deletions extensions/amp-mathml/1.0/amp-mathml.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import {dict} from '#core/types/object';

import {isExperimentOn} from '#experiments';

import {userAssert} from '#utils/log';
Expand Down Expand Up @@ -27,15 +25,6 @@ class AmpMathml extends BaseElement {
return urls;
}

/** @override */
init() {
return dict({
'requestResize': ({height, width}) => {
return this.attemptChangeSize(height, width);
},
});
}

/** @override */
isLayoutSupported(layout) {
userAssert(
Expand Down
56 changes: 5 additions & 51 deletions extensions/amp-mathml/1.0/component.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,10 @@ import {MessageType, deserializeMessage} from '#core/3p-frame-messaging';
import {tryParseJson} from '#core/types/object/json';

import * as Preact from '#preact';
import {useCallback, useEffect, useMemo, useState} from '#preact';
import {useCallback, useMemo} from '#preact';
import {forwardRef} from '#preact/compat';
import {useIntersectionObserver, useValueRef} from '#preact/component';
import {useValueRef} from '#preact/component';
import {ProxyIframeEmbed} from '#preact/component/3p-frame';
import {useMergeRefs} from '#preact/utils';

import {useStyles} from './component.jss';
import {TYPE} from './utils';
Expand All @@ -25,68 +24,24 @@ function BentoMathmlWithRef(props, ref) {
formula,
inline = false,
onLoad,
requestResize,
style: bentoMathmlStyles,
title = 'MathML formula',
...rest
} = props;
const [dimensions, setDimensions] = useState(null);
// to avoid layout shifts, hide correct dimensions until the content is offscreen to avoid a Layout Shift
const [allowDimensions, setAllowDimensions] = useState(false);
const onLoadRef = useValueRef(onLoad);
const requestResizeRef = useValueRef(requestResize);
const classes = useStyles();

useEffect(() => {
if (allowDimensions && dimensions) {
onLoadRef.current?.();
requestResizeRef.current?.(dimensions);
}
}, [onLoadRef, requestResizeRef, allowDimensions, dimensions]);

const messageHandler = useCallback(
(e) => {
const data = tryParseJson(e.data) ?? deserializeMessage(e.data);
if (data['type'] == MessageType.EMBED_SIZE) {
const {height, width: w} = data;
const width = inline ? w : undefined;
setDimensions({height, width});
onLoadRef.current?.();
}
},
[inline]
[onLoadRef]
);

// eslint-disable-next-line prefer-const
let observerCb;
const ioCallback = useCallback(
({isIntersecting}) => {
if (!isIntersecting) {
setAllowDimensions(true);
// unobserve element once it's rendered
observerCb(null);
}
},
[setAllowDimensions, observerCb]
);
observerCb = useIntersectionObserver(ioCallback);
// Need to create custom callback ref because ProxyIframeEmbed uses an imperative handle with an property for the node.
const observerCbRef = (proxyIframeEmbedHandle) => {
const {node: iframeNode} = proxyIframeEmbedHandle;
// Observe grandparent div instead of iframe because iframe keeps changing height
observerCb(iframeNode?.parentNode.parentNode);
};

const styles = useMemo(() => {
return {
...(allowDimensions && dimensions),
...bentoMathmlStyles,
};
}, [allowDimensions, dimensions, bentoMathmlStyles]);

const iframeOptions = useMemo(() => ({formula}), [formula]);

const proxyIframeEmbedRef = useMergeRefs([ref, observerCbRef]);

if (!validProps(props)) {
return null;
}
Expand All @@ -96,9 +51,8 @@ function BentoMathmlWithRef(props, ref) {
class={objStr({
[classes.inline]: inline,
})}
style={styles}
allowFullscreen
ref={proxyIframeEmbedRef}
ref={ref}
type={TYPE}
title={title}
options={iframeOptions}
Expand Down
64 changes: 17 additions & 47 deletions extensions/amp-mathml/1.0/storybook/Basic.amp.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,62 +30,32 @@ export const Default = (args) => {
);
};

export const WithScroll = (args) => {
return (
<>
<p>Should lazily render formula when formulas are offscreen</p>
<TestDemo withScroll={true} {...args}></TestDemo>
<TestDemoInline {...args}></TestDemoInline>
</>
);
};

export const WithCustomDimensions = (args) => {
return (
<>
<p>
Should render everything, using manual sizes for onscreen elements and
dynamic resizing for offscreen elements
</p>
<TestDemo withScroll={true} height="40" {...args}></TestDemo>
<TestDemoInline {...args}></TestDemoInline>
</>
);
};

function TestDemo({formulas, withScroll, ...args}) {
const {cauchy, doubleAngle, quadratic} = formulas;
return (
<>
<h2>The Quadratic Formula</h2>
<amp-mathml data-formula={quadratic} {...args}></amp-mathml>

<h2>Cauchy's Integral Formula</h2>
<amp-mathml data-formula={cauchy} {...args}></amp-mathml>

{withScroll ? (
<div style={{height: 1000, border: '1px solid black'}}>
long stuff to create scroll
</div>
) : null}

<h2>Double angle formula for Cosines</h2>
<amp-mathml data-formula={doubleAngle} {...args}></amp-mathml>
</>
);
}

function TestDemoInline({formulas, ...args}) {
const {quadratic} = formulas;
return (
<>
<h2>Inline formula</h2>
<p>
This is an example of a formula of{' '}
<amp-mathml inline data-formula={'`x`'} {...args}></amp-mathml>,{' '}
<amp-mathml inline data-formula={quadratic} {...args}></amp-mathml>{' '}
<amp-mathml
height="13"
width="9"
inline
data-formula={'`x`'}
{...args}
></amp-mathml>
,{' '}
<amp-mathml
height="47"
width="146"
inline
data-formula={quadratic}
{...args}
></amp-mathml>{' '}
placed inline in the middle of a block of text.{' '}
<amp-mathml
height="19"
width="71"
inline
data-formula={'\\( \\cos(θ+φ) \\)'}
{...args}
Expand Down
67 changes: 31 additions & 36 deletions extensions/amp-mathml/1.0/storybook/Basic.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,47 +26,30 @@ export const Default = (args) => {
);
};

export const WithScroll = (args) => {
return (
<>
<p>Should lazily render formula when formulas are offscreen</p>
<TestDemo withScroll={true} {...args}></TestDemo>
<TestDemoInline {...args}></TestDemoInline>
</>
);
};

export const WithCustomDimensions = (args) => {
return (
<>
<p>
Should render everything, using manual sizes for onscreen elements and
dynamic resizing for offscreen elements
</p>
<TestDemo withScroll={true} style={{height: 40}} {...args}></TestDemo>
<TestDemoInline {...args}></TestDemoInline>
</>
);
};

function TestDemo({formulas, withScroll, ...args}) {
function TestDemo({formulas, ...args}) {
const {cauchy, doubleAngle, quadratic} = formulas;
return (
<>
<h2>The Quadratic Formula</h2>
<BentoMathml formula={quadratic} {...args}></BentoMathml>
<BentoMathml
style={{height: 40}}
formula={quadratic}
{...args}
></BentoMathml>

<h2>Cauchy's Integral Formula</h2>
<BentoMathml formula={cauchy} {...args}></BentoMathml>

{withScroll ? (
<div style={{height: 1000, border: '1px solid black'}}>
long stuff to create scroll
</div>
) : null}
<BentoMathml
style={{height: 40}}
formula={cauchy}
{...args}
></BentoMathml>

<h2>Double angle formula for Cosines</h2>
<BentoMathml formula={doubleAngle} {...args}></BentoMathml>
<BentoMathml
style={{height: 23}}
formula={doubleAngle}
{...args}
></BentoMathml>
</>
);
}
Expand All @@ -78,10 +61,22 @@ function TestDemoInline({formulas, ...args}) {
<h2>Inline formula</h2>
<p>
This is an example of a formula of{' '}
<BentoMathml inline formula={'`x`'} {...args}></BentoMathml>,{' '}
<BentoMathml inline formula={quadratic} {...args}></BentoMathml> placed
inline in the middle of a block of text.{' '}
<BentoMathml
style={{height: 13, width: 9}}
inline
formula={'`x`'}
{...args}
></BentoMathml>
,{' '}
<BentoMathml
style={{height: 47, width: 146}}
inline
formula={quadratic}
{...args}
></BentoMathml>{' '}
placed inline in the middle of a block of text.{' '}
<BentoMathml
style={{height: 19, width: 71}}
inline
formula={'\\( \\cos(θ+φ) \\)'}
{...args}
Expand Down

0 comments on commit d13bbc1

Please sign in to comment.