Skip to content

Commit 3e744f4

Browse files
committed
refactor: enhance typings for provideEmbeddedHeaders + add 3d param
1 parent 050e09b commit 3e744f4

File tree

11 files changed

+174
-46
lines changed

11 files changed

+174
-46
lines changed

doc-tools/doc-pages/src/pages/PageContentImages.tsx

Lines changed: 27 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import Page from '../Page';
44
import useToolkit from '../toolkit/useToolkit';
55
import customImageRendererConfig from './cards/customImageRendererConfig';
66
import internalImageRendererConfig from './cards/internalImageRendererConfig';
7+
import imagesWithHeadersConfig from './cards/imagesWithHeadersConfig';
78
import InternalRendererAdmonition from '../components/InternalRendererAdmonition';
89

910
const inlineExample = `<img
@@ -248,13 +249,32 @@ export default function PageContentImages() {
248249
</Section>
249250
</Chapter>
250251
<Chapter title="Configuring">
251-
<Paragraph>
252-
We can take advantage of the{' '}
253-
<RefRenderHtmlProp name="renderersProps" /> to customize images
254-
behavior (see{' '}
255-
<RefRenderHTMLExport name="RenderersProps" member="img" full />
256-
).
257-
</Paragraph>
252+
<Section title="Providing headers">
253+
<Paragraph>
254+
You can take advantage of the{' '}
255+
<RefRenderHtmlProp name="provideEmbeddedHeaders" />
256+
prop to pass headers to the image fetching conditionnaly. For
257+
example:
258+
</Paragraph>
259+
<RenderHtmlCard {...imagesWithHeadersConfig} />
260+
<Admonition type="tip">
261+
In this example, we are using a Bearer token to access a restricted
262+
resource. We could also use headers to take advantage of the new{' '}
263+
<Hyperlink url="https://wicg.github.io/responsive-image-client-hints/">
264+
Responsive Image Client Hints
265+
</Hyperlink>{' '}
266+
standard.
267+
</Admonition>
268+
</Section>
269+
<Section title="Advanced configuration">
270+
<Paragraph>
271+
We can take advantage of the{' '}
272+
<RefRenderHtmlProp name="renderersProps" /> to customize images
273+
behavior (see{' '}
274+
<RefRenderHTMLExport name="RenderersProps" member="img" full />
275+
).
276+
</Paragraph>
277+
</Section>
258278
</Chapter>
259279
</Page>
260280
);
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import { UIRenderHtmlCardProps } from '../../toolkit/toolkit-types';
2+
3+
const html = `<img src="https://www.fillmurray.com/200/100" />`;
4+
5+
function provideEmbeddedHeaders(uri: string, tagName: string) {
6+
if (tagName === 'img') {
7+
return {
8+
Authorization: 'Bearer XYZ'
9+
};
10+
}
11+
}
12+
13+
const imagesWithHeadersConfig: UIRenderHtmlCardProps = {
14+
title: 'Providing headers to images',
15+
caption:
16+
'provideEmbeddedHeaders lets you pick headers for specific domains and works with multiple tags. For example, it can be used with the iframe plugin.',
17+
props: {
18+
source: {
19+
html
20+
},
21+
provideEmbeddedHeaders
22+
},
23+
preferHtmlSrc: false,
24+
config: {
25+
importStatements: [
26+
{ package: 'react-native', named: ['Platform', 'PixelRatio'] }
27+
],
28+
fnSrcMap: {
29+
provideEmbeddedHeaders: `function provideEmbeddedHeaders(uri, tagName) {
30+
if (tagName === 'img') {
31+
return {
32+
Authorization: "Bearer XYZ",
33+
};
34+
}
35+
}`
36+
}
37+
}
38+
};
39+
40+
export default imagesWithHeadersConfig;

packages/render-html/src/context/SharedPropsProvider.tsx

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,15 @@ import selectSharedProps from '../helpers/selectSharedProps';
44
import { RenderHTMLSharedProps, RendererBaseProps } from '../shared-types';
55
import defaultSharedProps from './defaultSharedProps';
66

7-
const SharedPropsContext =
8-
React.createContext<Required<RenderHTMLSharedProps>>(defaultSharedProps);
7+
const SharedPropsContext = React.createContext(defaultSharedProps);
98

109
/**
1110
* Use shared props. See {@link RenderHTMLSharedProps}.
1211
*
1312
* @public
1413
*/
1514
export function useSharedProps() {
16-
return React.useContext(
17-
SharedPropsContext
18-
) as Required<RenderHTMLSharedProps>;
15+
return React.useContext(SharedPropsContext);
1916
}
2017

2118
/**

packages/render-html/src/context/defaultSharedProps.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { DEFAULT_PRESSABLE_RIPPLE_COLOR } from '../constants';
2-
import { RenderHTMLSharedProps } from '../shared-types';
2+
import { RenderHTMLAmbiantSharedProps } from '../shared-types';
33

44
function WebViewPlaceholder() {
55
/* istanbul ignore else */
@@ -12,7 +12,7 @@ function WebViewPlaceholder() {
1212
return null;
1313
}
1414

15-
const defaultSharedProps: Required<RenderHTMLSharedProps> = {
15+
const defaultSharedProps: RenderHTMLAmbiantSharedProps = {
1616
bypassAnonymousTPhrasingNodes: true,
1717
debug: false,
1818
defaultTextProps: {
@@ -24,12 +24,12 @@ const defaultSharedProps: Required<RenderHTMLSharedProps> = {
2424
enableExperimentalGhostLinesPrevention: false,
2525
enableExperimentalMarginCollapsing: false,
2626
computeEmbeddedMaxWidth: (contentWidth) => contentWidth,
27-
provideEmbeddedHeaders: () => null,
28-
GenericPressable: undefined as any,
2927
WebView: WebViewPlaceholder,
3028
defaultWebViewProps: {},
3129
pressableHightlightColor: DEFAULT_PRESSABLE_RIPPLE_COLOR,
32-
customListStyleSpecs: undefined as any
30+
provideEmbeddedHeaders: undefined,
31+
GenericPressable: undefined,
32+
customListStyleSpecs: undefined
3333
};
3434

3535
export default defaultSharedProps;

packages/render-html/src/elements/__tests__/useIMGElementStateWithCache.test.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@ const props = {
55
contentWidth: 300,
66
source: { uri: 'https://foo.bar/600x300' },
77
initialDimensions: { width: 30, height: 30 },
8-
computeMaxWidth: (contentWidth: number) => contentWidth
8+
computeMaxWidth: (contentWidth: number) => contentWidth,
9+
tnode: {} as any
910
};
1011

1112
describe('useIMGElementStateWithCache', () => {

packages/render-html/src/elements/useIMGElementState.ts

Lines changed: 6 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
1-
import { useEffect, useMemo } from 'react';
1+
import { useEffect } from 'react';
22
import { Image } from 'react-native';
33
import type { UseIMGElementStateProps, IMGElementState } from './img-types';
44
import useImageNaturalDimensions from './useImageNaturalDimensions';
55
import useImageConcreteDimensions from './useImageConcreteDimensions';
66
import defaultImageInitialDimensions from './defaultInitialImageDimensions';
77
import { ImageDimensions } from '../shared-types';
88
import { getIMGState } from './getIMGState';
9-
import { useSharedProps } from '../context/SharedPropsProvider';
9+
import useIMGNormalizedSource from './useIMGNormalizedSource';
1010

1111
function getImageSizeAsync({
1212
uri,
@@ -89,26 +89,17 @@ export default function useIMGElementState(
8989
} = props;
9090
const { naturalDimensions, specifiedDimensions, flatStyle, onError, error } =
9191
useFetchedNaturalDimensions(props);
92-
const { provideEmbeddedHeaders } = useSharedProps();
93-
const nomalizedSource = useMemo(() => {
94-
if (source.uri) {
95-
const headers = provideEmbeddedHeaders(source.uri, 'img');
96-
if (headers) {
97-
return {
98-
headers,
99-
...source
100-
};
101-
}
102-
}
103-
return source;
104-
}, [provideEmbeddedHeaders, source]);
10592
const concreteDimensions = useImageConcreteDimensions({
10693
flatStyle,
10794
naturalDimensions,
10895
specifiedDimensions,
10996
computeMaxWidth,
11097
contentWidth
11198
});
99+
const nomalizedSource = useIMGNormalizedSource({
100+
concreteDimensions,
101+
source
102+
});
112103
return getIMGState({
113104
error,
114105
alt,

packages/render-html/src/elements/useIMGElementStateWithCache.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import type {
77
} from './img-types';
88
import useImageConcreteDimensions from './useImageConcreteDimensions';
99
import useImageNaturalDimensions from './useImageNaturalDimensions';
10+
import useIMGNormalizedSource from './useIMGNormalizedSource';
1011

1112
/**
1213
* This hook is useful when one has access to image natural dimensions prior to
@@ -34,14 +35,18 @@ export default function useIMGElementStateWithCache(
3435
computeMaxWidth,
3536
contentWidth
3637
});
38+
const nomalizedSource = useIMGNormalizedSource({
39+
concreteDimensions,
40+
source
41+
});
3742
return getIMGState({
3843
error,
3944
concreteDimensions,
4045
containerStyle: flatStyle,
4146
initialDimensions,
4247
objectFit,
4348
onError,
44-
source,
49+
source: nomalizedSource,
4550
alt,
4651
altColor
4752
});
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import { useMemo, useRef } from 'react';
2+
import { useSharedProps } from '../context/SharedPropsProvider';
3+
import { ImageDimensions } from '../shared-types';
4+
import { UseIMGElementStateProps } from './img-types';
5+
6+
export default function useIMGNormalizedSource({
7+
source,
8+
concreteDimensions
9+
}: Pick<UseIMGElementStateProps, 'source'> & {
10+
concreteDimensions: ImageDimensions | null;
11+
}) {
12+
const cachedDimensions = useRef(concreteDimensions);
13+
const { provideEmbeddedHeaders } = useSharedProps();
14+
return useMemo(() => {
15+
if (source.uri && typeof provideEmbeddedHeaders === 'function') {
16+
const headers = provideEmbeddedHeaders(source.uri, 'img', {
17+
printWidth: cachedDimensions.current?.width,
18+
printHeight: cachedDimensions.current?.height
19+
});
20+
if (headers) {
21+
return {
22+
headers,
23+
...source
24+
};
25+
}
26+
}
27+
return source;
28+
}, [provideEmbeddedHeaders, source]);
29+
}

packages/render-html/src/helpers/selectSharedProps.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,12 @@ import pickBy from 'ramda/src/pickBy';
22
import pick from 'ramda/src/pick';
33
import pipe from 'ramda/src/pipe';
44
import mergeRight from 'ramda/src/mergeRight';
5-
import { RenderHTMLSharedProps, RenderHTMLProps } from '../shared-types';
5+
import { RenderHTMLProps, RenderHTMLAmbiantSharedProps } from '../shared-types';
66
import defaultSharedProps from '../context/defaultSharedProps';
77

88
const selectSharedProps: (
99
props: Partial<RenderHTMLProps>
10-
) => Required<RenderHTMLSharedProps> = pipe(
10+
) => RenderHTMLAmbiantSharedProps = pipe(
1111
pick(Object.keys(defaultSharedProps)),
1212
pickBy((val) => val != null),
1313
mergeRight(defaultSharedProps) as any

packages/render-html/src/internal-types.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { Document, Element } from '@native-html/transient-render-engine';
33
import {
44
RenderHTMLProps,
55
TNodeRendererProps,
6-
RenderHTMLSharedProps
6+
RenderHTMLAmbiantSharedProps
77
} from './shared-types';
88

99
export type SourceLoaderProps = Pick<
@@ -26,5 +26,5 @@ export interface TNodeSubRendererProps<T extends TNode>
2626
/**
2727
* Props shared across the whole render tree.
2828
*/
29-
sharedProps: Required<RenderHTMLSharedProps>;
29+
sharedProps: RenderHTMLAmbiantSharedProps;
3030
}

0 commit comments

Comments
 (0)