Skip to content

Commit c89f328

Browse files
committed
Implement <svg> support
1 parent c8f9de8 commit c89f328

File tree

20 files changed

+3151
-34
lines changed

20 files changed

+3151
-34
lines changed

apps/examples/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
"react": "~18.3.1",
1919
"react-dom": "~18.3.1",
2020
"react-native": "~0.76.1",
21+
"react-native-svg": "15.8.0",
2122
"react-native-web": "~0.19.13",
2223
"react-strict-dom": "*"
2324
},

package-lock.json

Lines changed: 63 additions & 31 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/react-strict-dom/package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,8 @@
4444
"peerDependencies": {
4545
"react": "^18.2.0",
4646
"react-dom": "^18.2.0",
47-
"react-native": ">=0.75.2"
47+
"react-native": ">=0.75.2",
48+
"react-native-svg": "^15.8.0"
4849
},
4950
"engines": {
5051
"node": ">=20.11.0"

packages/react-strict-dom/src/dom/index.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import type {
1616
} from '@stylexjs/stylex';
1717

1818
import * as html from './html';
19+
import * as svg from './svg';
1920
import * as css from '@stylexjs/stylex';
2021

2122
type StyleTheme<V, T> = Theme<V, T>;
@@ -25,4 +26,4 @@ type StylesWithout<T> = StyleXStylesWithout<T>;
2526

2627
export type { StaticStyles, StyleTheme, StyleVars, Styles, StylesWithout };
2728

28-
export { css, html };
29+
export { css, html, svg };
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
/**
2+
* Copyright (c) Meta Platforms, Inc. and affiliates.
3+
*
4+
* This source code is licensed under the MIT license found in the
5+
* LICENSE file in the root directory of this source tree.
6+
*
7+
* @flow strict
8+
*/
9+
10+
import type { CompiledStyles } from '@stylexjs/stylex/lib/StyleXTypes';
11+
import type { ReactDOMStyleProps } from '../../types/renderer.web';
12+
import type { StrictSvgProps } from '../../../dist/types/StrictSvgProps';
13+
14+
import * as React from 'react';
15+
import * as stylex from '@stylexjs/stylex';
16+
import { errorMsg } from '../../shared/logUtils';
17+
import { isSvgPropAllowed } from '../../shared/isSvgPropAllowed';
18+
19+
// $FlowFixMe[unclear-type]
20+
function validateStrictProps(props: any) {
21+
Object.keys(props).forEach((key) => {
22+
const isValid = isSvgPropAllowed(key);
23+
if (!isValid) {
24+
errorMsg(`invalid prop "${key}"`);
25+
delete props[key];
26+
}
27+
});
28+
}
29+
30+
export function createStrictDOMSvgComponent<T, P: StrictSvgProps>(
31+
TagName: string,
32+
defaultStyle: StrictSvgProps['style']
33+
): component(ref?: React.RefSetter<T>, ...P) {
34+
// NOTE: `debug-style` is not generated by `stylex.create`
35+
// so it needs a type-cast
36+
const debugStyle: CompiledStyles = {
37+
$$css: true,
38+
'debug::name': `svg-${TagName}` as $FlowFixMe
39+
};
40+
41+
const component: React.AbstractComponent<P, T> = React.forwardRef(
42+
function (props, forwardedRef) {
43+
/**
44+
* get host props
45+
*/
46+
const { style, ...hostProps } = props;
47+
validateStrictProps(hostProps);
48+
49+
if (props.role != null) {
50+
// "presentation" synonym has wider browser support
51+
// $FlowFixMe
52+
hostProps.role = props.role === 'none' ? 'presentation' : props.role;
53+
}
54+
55+
/**
56+
* get host style props
57+
*/
58+
// Waiting on a diff so we can remove this indirection.
59+
const hostStyleProps: ReactDOMStyleProps = stylex.props([
60+
debugStyle,
61+
defaultStyle,
62+
style
63+
]);
64+
65+
/**
66+
* Construct tree
67+
*
68+
* Intentional flow error as we are asking for a more specific type
69+
* than React itself.
70+
*/
71+
const element = (
72+
<TagName
73+
{...hostProps}
74+
{...hostStyleProps}
75+
ref={forwardedRef as $FlowFixMe}
76+
/>
77+
);
78+
return element;
79+
}
80+
);
81+
82+
component.displayName = `svg.${TagName}`;
83+
return component;
84+
}

packages/react-strict-dom/src/dom/runtime.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,7 @@ const span: StrictReactDOMPropsStyle = styles.inline;
120120
const strong: StrictReactDOMPropsStyle = [styles.inline, styles.strong];
121121
const sub: StrictReactDOMPropsStyle = styles.inline;
122122
const sup: StrictReactDOMPropsStyle = styles.inline;
123+
const svg: StrictReactDOMPropsStyle = styles.img;
123124
const textarea: StrictReactDOMPropsStyle = [
124125
styles.inlineblock,
125126
styles.textarea
@@ -174,6 +175,7 @@ export const defaultStyles = {
174175
strong: strong as typeof strong,
175176
sub: sub as typeof sub,
176177
sup: sup as typeof sup,
178+
svg: svg as typeof svg,
177179
textarea: textarea as typeof textarea,
178180
u: u as typeof u,
179181
ul: ul as typeof ul

0 commit comments

Comments
 (0)