diff --git a/apps/examples/package.json b/apps/examples/package.json index 6153a62f..ca7b52c2 100644 --- a/apps/examples/package.json +++ b/apps/examples/package.json @@ -18,6 +18,7 @@ "react": "~18.3.1", "react-dom": "~18.3.1", "react-native": "~0.76.1", + "react-native-svg": "15.8.0", "react-native-web": "~0.19.13", "react-strict-dom": "*" }, diff --git a/package-lock.json b/package-lock.json index 3238bb34..b61279c8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -60,6 +60,7 @@ "react": "~18.3.1", "react-dom": "~18.3.1", "react-native": "~0.76.1", + "react-native-svg": "15.8.0", "react-native-web": "~0.19.13", "react-strict-dom": "*" }, @@ -747,18 +748,6 @@ "@babel/core": "^7.0.0" } }, - "node_modules/@babel/helper-simple-access": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.24.7.tgz", - "integrity": "sha512-zBAIvbCMh5Ts+b86r/CjU+4XGYIs+R1j951gxI3KmmxBMhCg4oQMsv6ZXQ64XOm/cvzfU1FmoCyt6+owc5QMYg==", - "dependencies": { - "@babel/traverse": "^7.24.7", - "@babel/types": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, "node_modules/@babel/helper-skip-transparent-expression-wrappers": { "version": "7.25.9", "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.25.9.tgz", @@ -1174,11 +1163,12 @@ } }, "node_modules/@babel/plugin-syntax-jsx": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.24.7.tgz", - "integrity": "sha512-6ddciUPe/mpMnOKv/U+RSd2vvVy+Yw/JfBB0ZHYjEZt9NLHmCUylNYlsbqCCS1Bffjlb0fCwC9Vqz+sBz6PsiQ==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.25.9.tgz", + "integrity": "sha512-ld6oezHQMZsZfp6pWtbjaNDF2tiiCYYDqQszHt5VV437lewP9aSi2Of99CK0D0XB21k7FLgnLcmQKyKzynfeAA==", + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7" + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1684,13 +1674,13 @@ } }, "node_modules/@babel/plugin-transform-modules-commonjs": { - "version": "7.24.8", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.24.8.tgz", - "integrity": "sha512-WHsk9H8XxRs3JXKWFiqtQebdh9b/pTk4EgueygFzYlTKAg0Ud985mSevdNjdXdFBATSKVJGQXP1tv6aGbssLKA==", + "version": "7.26.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.26.3.tgz", + "integrity": "sha512-MgR55l4q9KddUDITEzEFYn5ZsGDXMSsU9E+kh7fjRXTIC3RHqfCo8RPRbyReYJh44HQ/yomFkqbOFohXvDCiIQ==", + "license": "MIT", "dependencies": { - "@babel/helper-module-transforms": "^7.24.8", - "@babel/helper-plugin-utils": "^7.24.8", - "@babel/helper-simple-access": "^7.24.7" + "@babel/helper-module-transforms": "^7.26.0", + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -2361,15 +2351,16 @@ } }, "node_modules/@babel/preset-typescript": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.23.3.tgz", - "integrity": "sha512-17oIGVlqz6CchO9RFYn5U6ZpWRZIngayYCtrPRSgANSwC2V1Jb+iP74nVxzzXJte8b8BYxrL1yY96xfhTBrNNQ==", + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.26.0.tgz", + "integrity": "sha512-NMk1IGZ5I/oHhoXEElcm+xUnL/szL6xflkFZmoEU9xj1qSJXpiS7rsspYo92B4DRCDvZn2erT5LdsCeXAKNCkg==", + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/helper-validator-option": "^7.22.15", - "@babel/plugin-syntax-jsx": "^7.23.3", - "@babel/plugin-transform-modules-commonjs": "^7.23.3", - "@babel/plugin-transform-typescript": "^7.23.3" + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/helper-validator-option": "^7.25.9", + "@babel/plugin-syntax-jsx": "^7.25.9", + "@babel/plugin-transform-modules-commonjs": "^7.25.9", + "@babel/plugin-transform-typescript": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -26669,6 +26660,40 @@ } } }, + "node_modules/react-native-svg": { + "version": "15.8.0", + "resolved": "https://registry.npmjs.org/react-native-svg/-/react-native-svg-15.8.0.tgz", + "integrity": "sha512-KHJzKpgOjwj1qeZzsBjxNdoIgv2zNCO9fVcoq2TEhTRsVV5DGTZ9JzUZwybd7q4giT/H3RdtqC3u44dWdO0Ffw==", + "license": "MIT", + "dependencies": { + "css-select": "^5.1.0", + "css-tree": "^1.1.3", + "warn-once": "0.1.1" + }, + "peerDependencies": { + "react": "*", + "react-native": "*" + } + }, + "node_modules/react-native-svg/node_modules/css-tree": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.1.3.tgz", + "integrity": "sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q==", + "license": "MIT", + "dependencies": { + "mdn-data": "2.0.14", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/react-native-svg/node_modules/mdn-data": { + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.14.tgz", + "integrity": "sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==", + "license": "CC0-1.0" + }, "node_modules/react-native-web": { "version": "0.19.13", "resolved": "https://registry.npmjs.org/react-native-web/-/react-native-web-0.19.13.tgz", @@ -30633,6 +30658,12 @@ "makeerror": "1.0.12" } }, + "node_modules/warn-once": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/warn-once/-/warn-once-0.1.1.tgz", + "integrity": "sha512-VkQZJbO8zVImzYFteBXvBOZEl1qL175WH8VmZcxF2fZAoudNhNDvHi+doCaAEdU2l2vtcIwa2zn0QK5+I1HQ3Q==", + "license": "MIT" + }, "node_modules/watchpack": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.2.tgz", @@ -31609,7 +31640,8 @@ "peerDependencies": { "react": "^18.2.0", "react-dom": "^18.2.0", - "react-native": ">=0.75.2" + "react-native": ">=0.75.2", + "react-native-svg": "^15.8.0" } }, "packages/scripts": { diff --git a/packages/react-strict-dom/package.json b/packages/react-strict-dom/package.json index b1838926..f8266892 100644 --- a/packages/react-strict-dom/package.json +++ b/packages/react-strict-dom/package.json @@ -44,7 +44,8 @@ "peerDependencies": { "react": "^18.2.0", "react-dom": "^18.2.0", - "react-native": ">=0.75.2" + "react-native": ">=0.75.2", + "react-native-svg": "^15.8.0" }, "engines": { "node": ">=20.11.0" diff --git a/packages/react-strict-dom/src/dom/index.js b/packages/react-strict-dom/src/dom/index.js index 36fe2c9f..24c82cce 100644 --- a/packages/react-strict-dom/src/dom/index.js +++ b/packages/react-strict-dom/src/dom/index.js @@ -16,6 +16,7 @@ import type { } from '@stylexjs/stylex'; import * as html from './html'; +import * as svg from './svg'; import * as css from '@stylexjs/stylex'; type StyleTheme = Theme; @@ -25,4 +26,4 @@ type StylesWithout = StyleXStylesWithout; export type { StaticStyles, StyleTheme, StyleVars, Styles, StylesWithout }; -export { css, html }; +export { css, html, svg }; diff --git a/packages/react-strict-dom/src/dom/modules/createStrictDOMSvgComponent.js b/packages/react-strict-dom/src/dom/modules/createStrictDOMSvgComponent.js new file mode 100644 index 00000000..950840e6 --- /dev/null +++ b/packages/react-strict-dom/src/dom/modules/createStrictDOMSvgComponent.js @@ -0,0 +1,84 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @flow strict + */ + +import type { CompiledStyles } from '@stylexjs/stylex/lib/StyleXTypes'; +import type { ReactDOMStyleProps } from '../../types/renderer.web'; +import type { StrictSvgProps } from '../../../dist/types/StrictSvgProps'; + +import * as React from 'react'; +import * as stylex from '@stylexjs/stylex'; +import { errorMsg } from '../../shared/logUtils'; +import { isSvgPropAllowed } from '../../shared/isSvgPropAllowed'; + +// $FlowFixMe[unclear-type] +function validateStrictProps(props: any) { + Object.keys(props).forEach((key) => { + const isValid = isSvgPropAllowed(key); + if (!isValid) { + errorMsg(`invalid prop "${key}"`); + delete props[key]; + } + }); +} + +export function createStrictDOMSvgComponent( + TagName: string, + defaultStyle: StrictSvgProps['style'] +): component(ref?: React.RefSetter, ...P) { + // NOTE: `debug-style` is not generated by `stylex.create` + // so it needs a type-cast + const debugStyle: CompiledStyles = { + $$css: true, + 'debug::name': `svg-${TagName}` as $FlowFixMe + }; + + const component: React.AbstractComponent = React.forwardRef( + function (props, forwardedRef) { + /** + * get host props + */ + const { style, ...hostProps } = props; + validateStrictProps(hostProps); + + if (props.role != null) { + // "presentation" synonym has wider browser support + // $FlowFixMe + hostProps.role = props.role === 'none' ? 'presentation' : props.role; + } + + /** + * get host style props + */ + // Waiting on a diff so we can remove this indirection. + const hostStyleProps: ReactDOMStyleProps = stylex.props([ + debugStyle, + defaultStyle, + style + ]); + + /** + * Construct tree + * + * Intentional flow error as we are asking for a more specific type + * than React itself. + */ + const element = ( + + ); + return element; + } + ); + + component.displayName = `svg.${TagName}`; + return component; +} diff --git a/packages/react-strict-dom/src/dom/runtime.js b/packages/react-strict-dom/src/dom/runtime.js index 7a455371..d13cf378 100644 --- a/packages/react-strict-dom/src/dom/runtime.js +++ b/packages/react-strict-dom/src/dom/runtime.js @@ -120,6 +120,7 @@ const span: StrictReactDOMPropsStyle = styles.inline; const strong: StrictReactDOMPropsStyle = [styles.inline, styles.strong]; const sub: StrictReactDOMPropsStyle = styles.inline; const sup: StrictReactDOMPropsStyle = styles.inline; +const svg: StrictReactDOMPropsStyle = styles.img; const textarea: StrictReactDOMPropsStyle = [ styles.inlineblock, styles.textarea @@ -174,6 +175,7 @@ export const defaultStyles = { strong: strong as typeof strong, sub: sub as typeof sub, sup: sup as typeof sup, + svg: svg as typeof svg, textarea: textarea as typeof textarea, u: u as typeof u, ul: ul as typeof ul diff --git a/packages/react-strict-dom/src/dom/svg.js b/packages/react-strict-dom/src/dom/svg.js new file mode 100644 index 00000000..e8aed756 --- /dev/null +++ b/packages/react-strict-dom/src/dom/svg.js @@ -0,0 +1,464 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @flow strict + */ + +import type { + StrictReactDOMCircleProps, + StrictReactDOMClipPathProps, + StrictReactDOMDefsProps, + StrictReactDOMEllipseProps, + StrictReactDOMFeBlendProps, + StrictReactDOMFeColorMatrixProps, + StrictReactDOMFeComponentTransferProps, + StrictReactDOMFeCompositeProps, + StrictReactDOMFeConvolveMatrixProps, + StrictReactDOMFeDiffuseLightingProps, + StrictReactDOMFeDisplacementMapProps, + StrictReactDOMFeDistantLightProps, + StrictReactDOMFeDropShadowProps, + StrictReactDOMFeFloodProps, + StrictReactDOMFeFuncAProps, + StrictReactDOMFeFuncBProps, + StrictReactDOMFeFuncGProps, + StrictReactDOMFeFuncRProps, + StrictReactDOMFeGaussianBlurProps, + StrictReactDOMFeImageProps, + StrictReactDOMFeMergeNodeProps, + StrictReactDOMFeMergeProps, + StrictReactDOMFeMorphologyProps, + StrictReactDOMFeOffsetProps, + StrictReactDOMFePointLightProps, + StrictReactDOMFeSpecularLightingProps, + StrictReactDOMFeSpotLightProps, + StrictReactDOMFeTileProps, + StrictReactDOMFeTurbulenceProps, + StrictReactDOMFilterProps, + StrictReactDOMForeignObjectProps, + StrictReactDOMGProps, + StrictReactDOMImageProps, + StrictReactDOMLinearGradientProps, + StrictReactDOMLineProps, + StrictReactDOMMarkerProps, + StrictReactDOMMaskProps, + StrictReactDOMPathProps, + StrictReactDOMPatternProps, + StrictReactDOMPolygonProps, + StrictReactDOMPolylineProps, + StrictReactDOMRadialGradientProps, + StrictReactDOMRectProps, + StrictReactDOMStopProps, + StrictReactDOMSvgProps, + StrictReactDOMSymbolProps, + StrictReactDOMTextPathProps, + StrictReactDOMTextProps, + StrictReactDOMTSpanProps, + StrictReactDOMUseProps +} from '../types/StrictReactDOMSvgProps'; + +import { createStrictDOMSvgComponent as createStrictSvg } from './modules/createStrictDOMSvgComponent'; +import { defaultStyles } from './runtime'; + +/** + * "circle" + */ +export const circle: component( + ref?: React.RefSetter, + ...StrictReactDOMCircleProps +) = createStrictSvg('circle'); + +/** + * "clipPath" + */ +export const clipPath: component( + ref?: React.RefSetter, + ...StrictReactDOMClipPathProps +) = createStrictSvg('clipPath'); + +/** + * "defs" + */ +export const defs: component( + ref?: React.RefSetter, + ...StrictReactDOMDefsProps +) = createStrictSvg('defs'); + +/** + * "ellipse" + */ +export const ellipse: component( + ref?: React.RefSetter, + ...StrictReactDOMEllipseProps +) = createStrictSvg('ellipse'); + +/** + * "feBlend" + */ +export const feBlend: component( + ref?: React.RefSetter, + ...StrictReactDOMFeBlendProps +) = createStrictSvg('feBlend'); + +/** + * "feColorMatrix" + */ +export const feColorMatrix: component( + ref?: React.RefSetter, + ...StrictReactDOMFeColorMatrixProps +) = createStrictSvg('feColorMatrix'); + +/** + * "feComponentTransfer" + */ +export const feComponentTransfer: component( + ref?: React.RefSetter, + ...StrictReactDOMFeComponentTransferProps +) = createStrictSvg('feComponentTransfer'); + +/** + * "feFuncA" + */ +export const feFuncA: component( + ref?: React.RefSetter, + ...StrictReactDOMFeFuncAProps +) = createStrictSvg('feFuncA'); + +/** + * "feFuncB" + */ +export const feFuncB: component( + ref?: React.RefSetter, + ...StrictReactDOMFeFuncBProps +) = createStrictSvg('feFuncB'); + +/** + * "feFuncG" + */ +export const feFuncG: component( + ref?: React.RefSetter, + ...StrictReactDOMFeFuncGProps +) = createStrictSvg('feFuncG'); + +/** + * "feFuncR" + */ +export const feFuncR: component( + ref?: React.RefSetter, + ...StrictReactDOMFeFuncRProps +) = createStrictSvg('feFuncR'); + +/** + * "feComposite" + */ +export const feComposite: component( + ref?: React.RefSetter, + ...StrictReactDOMFeCompositeProps +) = createStrictSvg('feComposite'); + +/** + * "feConvolveMatrix" + */ +export const feConvolveMatrix: component( + ref?: React.RefSetter, + ...StrictReactDOMFeConvolveMatrixProps +) = createStrictSvg('feConvolveMatrix'); + +/** + * "feDiffuseLighting" + */ +export const feDiffuseLighting: component( + ref?: React.RefSetter, + ...StrictReactDOMFeDiffuseLightingProps +) = createStrictSvg('feDiffuseLighting'); + +/** + * "feDisplacementMap" + */ +export const feDisplacementMap: component( + ref?: React.RefSetter, + ...StrictReactDOMFeDisplacementMapProps +) = createStrictSvg('feDisplacementMap'); + +/** + * "feDistantLight" + */ +export const feDistantLight: component( + ref?: React.RefSetter, + ...StrictReactDOMFeDistantLightProps +) = createStrictSvg('feDistantLight'); + +/** + * "feDropShadow" + */ +export const feDropShadow: component( + ref?: React.RefSetter, + ...StrictReactDOMFeDropShadowProps +) = createStrictSvg('feDropShadow'); + +/** + * "feFlood" + */ +export const feFlood: component( + ref?: React.RefSetter, + ...StrictReactDOMFeFloodProps +) = createStrictSvg('feFlood'); + +/** + * "feGaussianBlur" + */ +export const feGaussianBlur: component( + ref?: React.RefSetter, + ...StrictReactDOMFeGaussianBlurProps +) = createStrictSvg('feGaussianBlur'); + +/** + * "feImage" + */ +export const feImage: component( + ref?: React.RefSetter, + ...StrictReactDOMFeImageProps +) = createStrictSvg('feImage'); + +/** + * "feMerge" + */ +export const feMerge: component( + ref?: React.RefSetter, + ...StrictReactDOMFeMergeProps +) = createStrictSvg('feMerge'); + +/** + * "feMergeNode" + */ +export const feMergeNode: component( + ref?: React.RefSetter, + ...StrictReactDOMFeMergeNodeProps +) = createStrictSvg('feMergeNode'); + +/** + * "feMorphology" + */ +export const feMorphology: component( + ref?: React.RefSetter, + ...StrictReactDOMFeMorphologyProps +) = createStrictSvg('feMorphology'); + +/** + * "feOffset" + */ +export const feOffset: component( + ref?: React.RefSetter, + ...StrictReactDOMFeOffsetProps +) = createStrictSvg('feOffset'); + +/** + * "fePointLight" + */ +export const fePointLight: component( + ref?: React.RefSetter, + ...StrictReactDOMFePointLightProps +) = createStrictSvg('fePointLight'); + +/** + * "feSpecularLighting" + */ +export const feSpecularLighting: component( + ref?: React.RefSetter, + ...StrictReactDOMFeSpecularLightingProps +) = createStrictSvg('feSpecularLighting'); + +/** + * "feSpotLight" + */ +export const feSpotLight: component( + ref?: React.RefSetter, + ...StrictReactDOMFeSpotLightProps +) = createStrictSvg('feSpotLight'); + +/** + * "feTile" + */ +export const feTile: component( + ref?: React.RefSetter, + ...StrictReactDOMFeTileProps +) = createStrictSvg('feTile'); + +/** + * "feTurbulence" + */ +export const feTurbulence: component( + ref?: React.RefSetter, + ...StrictReactDOMFeTurbulenceProps +) = createStrictSvg('feTurbulence'); + +/** + * "filter" + */ +export const filter: component( + ref?: React.RefSetter, + ...StrictReactDOMFilterProps +) = createStrictSvg('filter'); + +/** + * "foreignObject" + */ +export const foreignObject: component( + ref?: React.RefSetter, + ...StrictReactDOMForeignObjectProps +) = createStrictSvg('foreignObject'); + +/** + * "g" + */ +export const g: component( + ref?: React.RefSetter, + ...StrictReactDOMGProps +) = createStrictSvg('g'); + +/** + * "image" + */ +export const image: component( + ref?: React.RefSetter, + ...StrictReactDOMImageProps +) = createStrictSvg('image'); + +/** + * "line" + */ +export const line: component( + ref?: React.RefSetter, + ...StrictReactDOMLineProps +) = createStrictSvg('line'); + +/** + * "linearGradient" + */ +export const linearGradient: component( + ref?: React.RefSetter, + ...StrictReactDOMLinearGradientProps +) = createStrictSvg('linearGradient'); + +/** + * "marker" + */ +export const marker: component( + ref?: React.RefSetter, + ...StrictReactDOMMarkerProps +) = createStrictSvg('marker'); + +/** + * "mask" + */ +export const mask: component( + ref?: React.RefSetter, + ...StrictReactDOMMaskProps +) = createStrictSvg('mask'); + +/** + * "path" + */ +export const path: component( + ref?: React.RefSetter, + ...StrictReactDOMPathProps +) = createStrictSvg('path'); + +/** + * "pattern" + */ +export const pattern: component( + ref?: React.RefSetter, + ...StrictReactDOMPatternProps +) = createStrictSvg('pattern'); + +/** + * "polygon" + */ +export const polygon: component( + ref?: React.RefSetter, + ...StrictReactDOMPolygonProps +) = createStrictSvg('polygon'); + +/** + * "polyline" + */ +export const polyline: component( + ref?: React.RefSetter, + ...StrictReactDOMPolylineProps +) = createStrictSvg('polyline'); + +/** + * "radialGradient" + */ +export const radialGradient: component( + ref?: React.RefSetter, + ...StrictReactDOMRadialGradientProps +) = createStrictSvg('radialGradient'); + +/** + * "rect" + */ +export const rect: component( + ref?: React.RefSetter, + ...StrictReactDOMRectProps +) = createStrictSvg('rect'); + +/** + * "stop" + */ +export const stop: component( + ref?: React.RefSetter, + ...StrictReactDOMStopProps +) = createStrictSvg('stop'); + +/** + * "svg" (inline) + */ +export const svg: component( + ref?: React.RefSetter, + ...StrictReactDOMSvgProps +) = createStrictSvg('svg', defaultStyles.svg); + +/** + * "symbol" + */ +export const symbol: component( + ref?: React.RefSetter, + ...StrictReactDOMSymbolProps +) = createStrictSvg('symbol'); + +/** + * "tspan" + */ +export const tspan: component( + ref?: React.RefSetter, + ...StrictReactDOMTSpanProps +) = createStrictSvg('tSpan'); + +/** + * "text" + */ +export const text: component( + ref?: React.RefSetter, + ...StrictReactDOMTextProps +) = createStrictSvg('text'); + +/** + * "textPath" + */ +export const textPath: component( + ref?: React.RefSetter, + ...StrictReactDOMTextPathProps +) = createStrictSvg('textPath'); + +/** + * "use" + */ +export const use: component( + ref?: React.RefSetter, + ...StrictReactDOMUseProps +) = createStrictSvg('use'); diff --git a/packages/react-strict-dom/src/native/index.js b/packages/react-strict-dom/src/native/index.js index 6eb983ac..0ae7d214 100644 --- a/packages/react-strict-dom/src/native/index.js +++ b/packages/react-strict-dom/src/native/index.js @@ -21,6 +21,7 @@ import * as React from 'react'; import * as compat from './compat'; import * as html from './html'; import * as stylex from './stylex'; +import * as svg from './svg'; import { ProvideCustomProperties } from './modules/ContextCustomProperties'; type StyleTheme = Theme; @@ -54,4 +55,4 @@ const contexts = { // Export using StyleX types as the shim has divergent types internally. const css: TStyleX = stylex as $FlowFixMe; -export { contexts, compat, css, html }; +export { contexts, compat, css, html, svg }; diff --git a/packages/react-strict-dom/src/native/modules/createStrictDOMSvgComponent.js b/packages/react-strict-dom/src/native/modules/createStrictDOMSvgComponent.js new file mode 100644 index 00000000..8449e082 --- /dev/null +++ b/packages/react-strict-dom/src/native/modules/createStrictDOMSvgComponent.js @@ -0,0 +1,897 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @flow strict-local + */ + +import type { StrictSvgProps } from '../../types/StrictSvgProps'; + +import * as React from 'react'; +import { Animated } from 'react-native'; +import { + Circle, + ClipPath, + Defs, + Ellipse, + FeBlend, + FeColorMatrix, + FeComponentTransfer, + FeComposite, + FeConvolveMatrix, + FeDiffuseLighting, + FeDisplacementMap, + FeDistantLight, + FeDropShadow, + FeFlood, + FeFuncA, + FeFuncB, + FeFuncG, + FeFuncR, + FeGaussianBlur, + FeImage, + FeMerge, + FeMergeNode, + FeMorphology, + FeOffset, + FePointLight, + FeSpecularLighting, + FeSpotLight, + FeTile, + FeTurbulence, + Filter, + ForeignObject, + G, + Image, + Line, + LinearGradient, + Marker, + Mask, + Path, + Pattern, + Polygon, + Polyline, + RadialGradient, + Rect, + Stop, + Svg, + Symbol, + Text, + TextPath, + TSpan, + Use +} from 'react-native-svg'; +import { mergeRefs } from '../../shared/mergeRefs'; +import { useNativeProps } from './useNativeProps'; +import { useStrictDOMElement } from './useStrictDOMElement'; +import * as stylex from '../stylex'; + +const RE_CAPTURE_VAR_NAME = /^var\(--(.*)\)$/; + +const nativeComponents: $ReadOnly<{ + [string]: React.AbstractComponent +}> = { + circle: Circle, + clipPath: ClipPath, + defs: Defs, + ellipse: Ellipse, + feBlend: FeBlend, + feColorMatrix: FeColorMatrix, + feComponentTransfer: FeComponentTransfer, + feComposite: FeComposite, + feConvolveMatrix: FeConvolveMatrix, + feDiffuseLighting: FeDiffuseLighting, + feDisplacementMap: FeDisplacementMap, + feDistantLight: FeDistantLight, + feDropShadow: FeDropShadow, + feFlood: FeFlood, + feFuncA: FeFuncA, + feFuncB: FeFuncB, + feFuncG: FeFuncG, + feFuncR: FeFuncR, + feGaussianBlur: FeGaussianBlur, + feImage: FeImage, + feMerge: FeMerge, + feMergeNode: FeMergeNode, + feMorphology: FeMorphology, + feOffset: FeOffset, + fePointLight: FePointLight, + feSpecularLighting: FeSpecularLighting, + feSpotLight: FeSpotLight, + feTile: FeTile, + feTurbulence: FeTurbulence, + filter: Filter, + foreignObject: ForeignObject, + g: G, + image: Image, + line: Line, + linearGradient: LinearGradient, + marker: Marker, + mask: Mask, + path: Path, + pattern: Pattern, + polygon: Polygon, + polyline: Polyline, + radialGradient: RadialGradient, + rect: Rect, + stop: Stop, + svg: Svg, + symbol: Symbol, + text: Text, + textPath: TextPath, + tspan: TSpan, + use: Use +}; + +export function createStrictDOMSvgComponent( + tagName: string, + _defaultProps?: P +): component(ref?: React.RefSetter, ...P) { + const component: React.AbstractComponent = React.forwardRef( + function (props, forwardedRef) { + let NativeComponent = nativeComponents[tagName]; + const elementRef = useStrictDOMElement({ tagName }); + + const { + alignmentBaseline, + amplitude, + azimuth, + baseFrequency, + baselineShift, + bias, + clipPath, + clipRule, + color, + crossOrigin, + cx, + cy, + d, + diffuseConstant, + divisor, + dx, + dy, + edgeMode, + elevation, + exponent, + fill, + fillOpacity, + fillRule, + filter, + filterUnits, + floodColor, + floodOpacity, + fontFamily, + fontFeatureSettings, + fontSize, + fontStyle, + fontVariant, + fontWeight, + fx, + fy, + gradientTransform, + gradientUnits, + height, + in: _in, + in2, + inlineSize, + intercept, + k1, + k2, + k3, + k4, + kernelMatrix, + kernelUnitLength, + kerning, + lengthAdjust, + letterSpacing, + limitingConeAngle, + marker, + markerEnd, + markerHeight, + markerMid, + markerStart, + markerUnits, + markerWidth, + mask, + maskContentUnits, + maskType, + maskUnits, + method, + midLine, + mode, + numOctaves, + offset, + onLoad, + opacity, + operator, + order, + orient, + patternContentUnits, + patternTransform, + patternUnits, + points, + pointsAtX, + pointsAtY, + pointsAtZ, + preserveAlpha, + preserveAspectRatio, + primitiveUnits, + r, + radius, + refX, + refY, + rotate, + rx, + ry, + scale, + seed, + side, + slope, + spacing, + specularConstant, + specularExponent, + startOffset, + stdDeviation, + stitchTiles, + stopColor, + stopOpacity, + stroke, + strokeDasharray, + strokeDashoffset, + strokeLinecap, + strokeLinejoin, + strokeMiterlimit, + strokeOpacity, + strokeWidth, + surfaceScale, + tableValues, + targetX, + targetY, + textAnchor, + textDecoration, + textLength, + title, + transform, + transformOrigin, + values, + vectorEffect, + verticalAlign, + viewBox, + width, + wordSpacing, + x, + x1, + x2, + xChannelSelector, + xlinkHref, + xmlns, + xmlnsXlink, + y, + y1, + y2, + yChannelSelector, + z + } = props; + + /** + * Resolve global SVG and style props + */ + + const defaultProps = { + style: [ + _defaultProps?.style, + typeof height === 'number' && + typeof width === 'number' && + styles.aspectRatio(width, height) + ] + }; + + const { customProperties, nativeProps } = useNativeProps( + defaultProps, + // $FlowFixMe + props, + { + provideInheritableStyle: false, + withInheritedStyle: false, + withTextStyle: false + } + ); + + // Tag-specific props + + if (alignmentBaseline != null) { + // $FlowFixMe + nativeProps.alignmentBaseline = alignmentBaseline; + } + if (amplitude != null) { + // $FlowFixMe + nativeProps.amplitude = amplitude; + } + if (azimuth != null) { + // $FlowFixMe + nativeProps.azimuth = azimuth; + } + if (baseFrequency != null) { + // $FlowFixMe + nativeProps.baseFrequency = baseFrequency; + } + if (baselineShift != null) { + // $FlowFixMe + nativeProps.baselineShift = baselineShift; + } + if (bias != null) { + // $FlowFixMe + nativeProps.bias = bias; + } + if (clipPath != null) { + // $FlowFixMe + nativeProps.clipPath = clipPath; + } + if (clipRule != null) { + // $FlowFixMe + nativeProps.clipRule = clipRule; + } + if (color != null) { + // $FlowFixMe + nativeProps.color = color.startsWith('var(') + ? customProperties?.[color.replace(RE_CAPTURE_VAR_NAME, '$1')] + : color; + } + if (crossOrigin != null) { + // $FlowFixMe + nativeProps.crossOrigin = crossOrigin; + } + if (cx != null) { + // $FlowFixMe + nativeProps.cx = cx; + } + if (cy != null) { + // $FlowFixMe + nativeProps.cy = cy; + } + if (d != null) { + // $FlowFixMe + nativeProps.d = d; + } + if (diffuseConstant != null) { + // $FlowFixMe + nativeProps.diffuseConstant = diffuseConstant; + } + if (divisor != null) { + // $FlowFixMe + nativeProps.divisor = divisor; + } + if (dx != null) { + // $FlowFixMe + nativeProps.dx = dx; + } + if (dy != null) { + // $FlowFixMe + nativeProps.dy = dy; + } + if (edgeMode != null) { + // $FlowFixMe + nativeProps.edgeMode = edgeMode; + } + if (elevation != null) { + // $FlowFixMe + nativeProps.elevation = elevation; + } + if (exponent != null) { + // $FlowFixMe + nativeProps.exponent = exponent; + } + if (fill != null) { + // $FlowFixMe + nativeProps.fill = fill.startsWith('var(') + ? customProperties?.[fill.replace(RE_CAPTURE_VAR_NAME, '$1')] + : fill; + } + if (fillOpacity != null) { + // $FlowFixMe + nativeProps.fillOpacity = fillOpacity; + } + if (fillRule != null) { + // $FlowFixMe + nativeProps.fillRule = fillRule; + } + if (filter != null) { + // $FlowFixMe + nativeProps.filter = filter; + } + if (filterUnits != null) { + // $FlowFixMe + nativeProps.filterUnits = filterUnits; + } + if (floodColor != null) { + // $FlowFixMe + nativeProps.floodColor = floodColor; + } + if (floodOpacity != null) { + // $FlowFixMe + nativeProps.floodOpacity = floodOpacity; + } + if (fontFamily != null) { + // $FlowFixMe + nativeProps.fontFamily = fontFamily; + } + if (fontFeatureSettings != null) { + // $FlowFixMe + nativeProps.fontFeatureSettings = fontFeatureSettings; + } + if (fontSize != null) { + // $FlowFixMe + nativeProps.fontSize = fontSize; + } + if (fontStyle != null) { + // $FlowFixMe + nativeProps.fontStyle = fontStyle; + } + if (fontVariant != null) { + // $FlowFixMe + nativeProps.fontVariant = fontVariant; + } + if (fontWeight != null) { + // $FlowFixMe + nativeProps.fontWeight = fontWeight; + } + if (fx != null) { + // $FlowFixMe + nativeProps.fx = fx; + } + if (fy != null) { + // $FlowFixMe + nativeProps.fy = fy; + } + if (gradientTransform != null) { + // $FlowFixMe + nativeProps.gradientTransform = gradientTransform; + } + if (gradientUnits != null) { + // $FlowFixMe + nativeProps.gradientUnits = gradientUnits; + } + if (height != null) { + // $FlowFixMe + nativeProps.height = height; + } + if (_in != null) { + // $FlowFixMe + nativeProps.in = _in; + } + if (in2 != null) { + // $FlowFixMe + nativeProps.in2 = in2; + } + if (inlineSize != null) { + // $FlowFixMe + nativeProps.inlineSize = inlineSize; + } + if (intercept != null) { + // $FlowFixMe + nativeProps.intercept = intercept; + } + if (k1 != null) { + // $FlowFixMe + nativeProps.k1 = k1; + } + if (k2 != null) { + // $FlowFixMe + nativeProps.k2 = k2; + } + if (k3 != null) { + // $FlowFixMe + nativeProps.k3 = k3; + } + if (k4 != null) { + // $FlowFixMe + nativeProps.k4 = k4; + } + if (kernelMatrix != null) { + // $FlowFixMe + nativeProps.kernelMatrix = kernelMatrix; + } + if (kernelUnitLength != null) { + // $FlowFixMe + nativeProps.kernelUnitLength = kernelUnitLength; + } + if (kerning != null) { + // $FlowFixMe + nativeProps.kerning = kerning; + } + if (lengthAdjust != null) { + // $FlowFixMe + nativeProps.lengthAdjust = lengthAdjust; + } + if (letterSpacing != null) { + // $FlowFixMe + nativeProps.letterSpacing = letterSpacing; + } + if (limitingConeAngle != null) { + // $FlowFixMe + nativeProps.limitingConeAngle = limitingConeAngle; + } + if (marker != null) { + // $FlowFixMe + nativeProps.marker = marker; + } + if (markerEnd != null) { + // $FlowFixMe + nativeProps.markerEnd = markerEnd; + } + if (markerHeight != null) { + // $FlowFixMe + nativeProps.markerHeight = markerHeight; + } + if (markerMid != null) { + // $FlowFixMe + nativeProps.markerMid = markerMid; + } + if (markerStart != null) { + // $FlowFixMe + nativeProps.markerStart = markerStart; + } + if (markerUnits != null) { + // $FlowFixMe + nativeProps.markerUnits = markerUnits; + } + if (markerWidth != null) { + // $FlowFixMe + nativeProps.markerWidth = markerWidth; + } + if (mask != null) { + // $FlowFixMe + nativeProps.mask = mask; + } + if (maskContentUnits != null) { + // $FlowFixMe + nativeProps.maskContentUnits = maskContentUnits; + } + if (maskType != null) { + // $FlowFixMe + nativeProps.maskType = maskType; + } + if (maskUnits != null) { + // $FlowFixMe + nativeProps.maskUnits = maskUnits; + } + if (method != null) { + // $FlowFixMe + nativeProps.method = method; + } + if (midLine != null) { + // $FlowFixMe + nativeProps.midLine = midLine; + } + if (mode != null) { + // $FlowFixMe + nativeProps.mode = mode; + } + if (numOctaves != null) { + // $FlowFixMe + nativeProps.numOctaves = numOctaves; + } + if (offset != null) { + // $FlowFixMe + nativeProps.offset = offset; + } + if (onLoad != null) { + // $FlowFixMe + nativeProps.onLoad = onLoad; + } + if (opacity != null) { + // $FlowFixMe + nativeProps.opacity = opacity; + } + if (operator != null) { + // $FlowFixMe + nativeProps.operator = operator; + } + if (order != null) { + // $FlowFixMe + nativeProps.order = order; + } + if (orient != null) { + // $FlowFixMe + nativeProps.orient = orient; + } + if (patternContentUnits != null) { + // $FlowFixMe + nativeProps.patternContentUnits = patternContentUnits; + } + if (patternTransform != null) { + // $FlowFixMe + nativeProps.patternTransform = patternTransform; + } + if (patternUnits != null) { + // $FlowFixMe + nativeProps.patternUnits = patternUnits; + } + if (points != null) { + // $FlowFixMe + nativeProps.points = points; + } + if (pointsAtX != null) { + // $FlowFixMe + nativeProps.pointsAtX = pointsAtX; + } + if (pointsAtY != null) { + // $FlowFixMe + nativeProps.pointsAtY = pointsAtY; + } + if (pointsAtZ != null) { + // $FlowFixMe + nativeProps.pointsAtZ = pointsAtZ; + } + if (preserveAlpha != null) { + // $FlowFixMe + nativeProps.preserveAlpha = preserveAlpha; + } + if (preserveAspectRatio != null) { + // $FlowFixMe + nativeProps.preserveAspectRatio = preserveAspectRatio; + } + if (primitiveUnits != null) { + // $FlowFixMe + nativeProps.primitiveUnits = primitiveUnits; + } + if (r != null) { + // $FlowFixMe + nativeProps.r = r; + } + if (radius != null) { + // $FlowFixMe + nativeProps.radius = radius; + } + if (refX != null) { + // $FlowFixMe + nativeProps.refX = refX; + } + if (refY != null) { + // $FlowFixMe + nativeProps.refY = refY; + } + if (rotate != null) { + // $FlowFixMe + nativeProps.rotate = rotate; + } + if (rx != null) { + // $FlowFixMe + nativeProps.rx = rx; + } + if (ry != null) { + // $FlowFixMe + nativeProps.ry = ry; + } + if (scale != null) { + // $FlowFixMe + nativeProps.scale = scale; + } + if (seed != null) { + // $FlowFixMe + nativeProps.seed = seed; + } + if (side != null) { + // $FlowFixMe + nativeProps.side = side; + } + if (slope != null) { + // $FlowFixMe + nativeProps.slope = slope; + } + if (spacing != null) { + // $FlowFixMe + nativeProps.spacing = spacing; + } + if (specularConstant != null) { + // $FlowFixMe + nativeProps.specularConstant = specularConstant; + } + if (specularExponent != null) { + // $FlowFixMe + nativeProps.specularExponent = specularExponent; + } + if (startOffset != null) { + // $FlowFixMe + nativeProps.startOffset = startOffset; + } + if (stdDeviation != null) { + // $FlowFixMe + nativeProps.stdDeviation = stdDeviation; + } + if (stitchTiles != null) { + // $FlowFixMe + nativeProps.stitchTiles = stitchTiles; + } + if (stopColor != null) { + // $FlowFixMe + nativeProps.stopColor = stopColor; + } + if (stopOpacity != null) { + // $FlowFixMe + nativeProps.stopOpacity = stopOpacity; + } + if (stroke != null) { + // $FlowFixMe + nativeProps.stroke = stroke.startsWith('var(') + ? customProperties?.[stroke.replace(RE_CAPTURE_VAR_NAME, '$1')] + : stroke; + } + if (strokeDasharray != null) { + // $FlowFixMe + nativeProps.strokeDasharray = strokeDasharray; + } + if (strokeDashoffset != null) { + // $FlowFixMe + nativeProps.strokeDashoffset = strokeDashoffset; + } + if (strokeLinecap != null) { + // $FlowFixMe + nativeProps.strokeLinecap = strokeLinecap; + } + if (strokeLinejoin != null) { + // $FlowFixMe + nativeProps.strokeLinejoin = strokeLinejoin; + } + if (strokeMiterlimit != null) { + // $FlowFixMe + nativeProps.strokeMiterlimit = strokeMiterlimit; + } + if (strokeOpacity != null) { + // $FlowFixMe + nativeProps.strokeOpacity = strokeOpacity; + } + if (strokeWidth != null) { + // $FlowFixMe + nativeProps.strokeWidth = strokeWidth; + } + if (surfaceScale != null) { + // $FlowFixMe + nativeProps.surfaceScale = surfaceScale; + } + if (tableValues != null) { + // $FlowFixMe + nativeProps.tableValues = tableValues; + } + if (targetX != null) { + // $FlowFixMe + nativeProps.targetX = targetX; + } + if (targetY != null) { + // $FlowFixMe + nativeProps.targetY = targetY; + } + if (textAnchor != null) { + // $FlowFixMe + nativeProps.textAnchor = textAnchor; + } + if (textDecoration != null) { + // $FlowFixMe + nativeProps.textDecoration = textDecoration; + } + if (textLength != null) { + // $FlowFixMe + nativeProps.textLength = textLength; + } + if (title != null) { + // $FlowFixMe + nativeProps.title = title; + } + if (transform != null) { + // $FlowFixMe + nativeProps.transform = transform; + } + if (transformOrigin != null) { + // $FlowFixMe + nativeProps.origin = transformOrigin; + } + if (values != null) { + // $FlowFixMe + nativeProps.values = values; + } + if (vectorEffect != null) { + // $FlowFixMe + nativeProps.vectorEffect = vectorEffect; + } + if (verticalAlign != null) { + // $FlowFixMe + nativeProps.verticalAlign = verticalAlign; + } + if (viewBox != null) { + // $FlowFixMe + nativeProps.viewBox = viewBox; + } + if (width != null) { + // $FlowFixMe + nativeProps.width = width; + } + if (wordSpacing != null) { + // $FlowFixMe + nativeProps.wordSpacing = wordSpacing; + } + if (x != null) { + // $FlowFixMe + nativeProps.x = x; + } + if (x1 != null) { + // $FlowFixMe + nativeProps.x1 = x1; + } + if (x2 != null) { + // $FlowFixMe + nativeProps.x2 = x2; + } + if (xChannelSelector != null) { + // $FlowFixMe + nativeProps.xChannelSelector = xChannelSelector; + } + if (xlinkHref != null) { + // $FlowFixMe + nativeProps.xlinkHref = xlinkHref; + } + if (xmlns != null) { + // $FlowFixMe + nativeProps.xmlns = xmlns; + } + if (xmlnsXlink != null) { + // $FlowFixMe + nativeProps.xmlnsXlink = xmlnsXlink; + } + if (y != null) { + // $FlowFixMe + nativeProps.y = y; + } + if (y1 != null) { + // $FlowFixMe + nativeProps.y1 = y1; + } + if (y2 != null) { + // $FlowFixMe + nativeProps.y2 = y2; + } + if (yChannelSelector != null) { + // $FlowFixMe + nativeProps.yChannelSelector = yChannelSelector; + } + if (z != null) { + // $FlowFixMe + nativeProps.z = z; + } + + // Component-specific props + + nativeProps.ref = React.useMemo( + () => mergeRefs(elementRef, forwardedRef), + [elementRef, forwardedRef] + ); + + // Use Animated components if necessary + if (nativeProps.animated === true) { + NativeComponent = Animated.createAnimatedComponent(NativeComponent); + } + + const element: React.Node = + typeof props.children === 'function' ? ( + props.children(nativeProps) + ) : ( + // $FlowFixMe + + ); + + return element; + } + ); + + component.displayName = `svg.${tagName}`; + return component; +} + +const styles = stylex.create({ + aspectRatio: (width: number, height: number) => ({ + aspectRatio: width / height, + width, + height + }) +}); diff --git a/packages/react-strict-dom/src/native/svg.js b/packages/react-strict-dom/src/native/svg.js new file mode 100644 index 00000000..92f877c0 --- /dev/null +++ b/packages/react-strict-dom/src/native/svg.js @@ -0,0 +1,464 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @flow strict + */ + +import type { + StrictReactDOMCircleProps, + StrictReactDOMClipPathProps, + StrictReactDOMDefsProps, + StrictReactDOMEllipseProps, + StrictReactDOMFeBlendProps, + StrictReactDOMFeColorMatrixProps, + StrictReactDOMFeComponentTransferProps, + StrictReactDOMFeCompositeProps, + StrictReactDOMFeConvolveMatrixProps, + StrictReactDOMFeDiffuseLightingProps, + StrictReactDOMFeDisplacementMapProps, + StrictReactDOMFeDistantLightProps, + StrictReactDOMFeDropShadowProps, + StrictReactDOMFeFloodProps, + StrictReactDOMFeFuncAProps, + StrictReactDOMFeFuncBProps, + StrictReactDOMFeFuncGProps, + StrictReactDOMFeFuncRProps, + StrictReactDOMFeGaussianBlurProps, + StrictReactDOMFeImageProps, + StrictReactDOMFeMergeNodeProps, + StrictReactDOMFeMergeProps, + StrictReactDOMFeMorphologyProps, + StrictReactDOMFeOffsetProps, + StrictReactDOMFePointLightProps, + StrictReactDOMFeSpecularLightingProps, + StrictReactDOMFeSpotLightProps, + StrictReactDOMFeTileProps, + StrictReactDOMFeTurbulenceProps, + StrictReactDOMFilterProps, + StrictReactDOMForeignObjectProps, + StrictReactDOMGProps, + StrictReactDOMImageProps, + StrictReactDOMLinearGradientProps, + StrictReactDOMLineProps, + StrictReactDOMMarkerProps, + StrictReactDOMMaskProps, + StrictReactDOMPathProps, + StrictReactDOMPatternProps, + StrictReactDOMPolygonProps, + StrictReactDOMPolylineProps, + StrictReactDOMRadialGradientProps, + StrictReactDOMRectProps, + StrictReactDOMStopProps, + StrictReactDOMSvgProps, + StrictReactDOMSymbolProps, + StrictReactDOMTextPathProps, + StrictReactDOMTextProps, + StrictReactDOMTSpanProps, + StrictReactDOMUseProps +} from '../types/StrictReactDOMSvgProps'; + +// $FlowFixMe[nonstrict-import] +import { createStrictDOMSvgComponent as createStrictSvg } from './modules/createStrictDOMSvgComponent'; + +/** + * "circle" + */ +export const circle: component( + ref?: React.RefSetter, + ...StrictReactDOMCircleProps +) = createStrictSvg('circle'); + +/** + * "clipPath" + */ +export const clipPath: component( + ref?: React.RefSetter, + ...StrictReactDOMClipPathProps +) = createStrictSvg('clipPath'); + +/** + * "defs" + */ +export const defs: component( + ref?: React.RefSetter, + ...StrictReactDOMDefsProps +) = createStrictSvg('defs'); + +/** + * "ellipse" + */ +export const ellipse: component( + ref?: React.RefSetter, + ...StrictReactDOMEllipseProps +) = createStrictSvg('ellipse'); + +/** + * "feBlend" + */ +export const feBlend: component( + ref?: React.RefSetter, + ...StrictReactDOMFeBlendProps +) = createStrictSvg('feBlend'); + +/** + * "feColorMatrix" + */ +export const feColorMatrix: component( + ref?: React.RefSetter, + ...StrictReactDOMFeColorMatrixProps +) = createStrictSvg('feColorMatrix'); + +/** + * "feComponentTransfer" + */ +export const feComponentTransfer: component( + ref?: React.RefSetter, + ...StrictReactDOMFeComponentTransferProps +) = createStrictSvg('feComponentTransfer'); + +/** + * "feFuncA" + */ +export const feFuncA: component( + ref?: React.RefSetter, + ...StrictReactDOMFeFuncAProps +) = createStrictSvg('feFuncA'); + +/** + * "feFuncB" + */ +export const feFuncB: component( + ref?: React.RefSetter, + ...StrictReactDOMFeFuncBProps +) = createStrictSvg('feFuncB'); + +/** + * "feFuncG" + */ +export const feFuncG: component( + ref?: React.RefSetter, + ...StrictReactDOMFeFuncGProps +) = createStrictSvg('feFuncG'); + +/** + * "feFuncR" + */ +export const feFuncR: component( + ref?: React.RefSetter, + ...StrictReactDOMFeFuncRProps +) = createStrictSvg('feFuncR'); + +/** + * "feComposite" + */ +export const feComposite: component( + ref?: React.RefSetter, + ...StrictReactDOMFeCompositeProps +) = createStrictSvg('feComposite'); + +/** + * "feConvolveMatrix" + */ +export const feConvolveMatrix: component( + ref?: React.RefSetter, + ...StrictReactDOMFeConvolveMatrixProps +) = createStrictSvg('feConvolveMatrix'); + +/** + * "feDiffuseLighting" + */ +export const feDiffuseLighting: component( + ref?: React.RefSetter, + ...StrictReactDOMFeDiffuseLightingProps +) = createStrictSvg('feDiffuseLighting'); + +/** + * "feDisplacementMap" + */ +export const feDisplacementMap: component( + ref?: React.RefSetter, + ...StrictReactDOMFeDisplacementMapProps +) = createStrictSvg('feDisplacementMap'); + +/** + * "feDistantLight" + */ +export const feDistantLight: component( + ref?: React.RefSetter, + ...StrictReactDOMFeDistantLightProps +) = createStrictSvg('feDistantLight'); + +/** + * "feDropShadow" + */ +export const feDropShadow: component( + ref?: React.RefSetter, + ...StrictReactDOMFeDropShadowProps +) = createStrictSvg('feDropShadow'); + +/** + * "feFlood" + */ +export const feFlood: component( + ref?: React.RefSetter, + ...StrictReactDOMFeFloodProps +) = createStrictSvg('feFlood'); + +/** + * "feGaussianBlur" + */ +export const feGaussianBlur: component( + ref?: React.RefSetter, + ...StrictReactDOMFeGaussianBlurProps +) = createStrictSvg('feGaussianBlur'); + +/** + * "feImage" + */ +export const feImage: component( + ref?: React.RefSetter, + ...StrictReactDOMFeImageProps +) = createStrictSvg('feImage'); + +/** + * "feMerge" + */ +export const feMerge: component( + ref?: React.RefSetter, + ...StrictReactDOMFeMergeProps +) = createStrictSvg('feMerge'); + +/** + * "feMergeNode" + */ +export const feMergeNode: component( + ref?: React.RefSetter, + ...StrictReactDOMFeMergeNodeProps +) = createStrictSvg('feMergeNode'); + +/** + * "feMorphology" + */ +export const feMorphology: component( + ref?: React.RefSetter, + ...StrictReactDOMFeMorphologyProps +) = createStrictSvg('feMorphology'); + +/** + * "feOffset" + */ +export const feOffset: component( + ref?: React.RefSetter, + ...StrictReactDOMFeOffsetProps +) = createStrictSvg('feOffset'); + +/** + * "fePointLight" + */ +export const fePointLight: component( + ref?: React.RefSetter, + ...StrictReactDOMFePointLightProps +) = createStrictSvg('fePointLight'); + +/** + * "feSpecularLighting" + */ +export const feSpecularLighting: component( + ref?: React.RefSetter, + ...StrictReactDOMFeSpecularLightingProps +) = createStrictSvg('feSpecularLighting'); + +/** + * "feSpotLight" + */ +export const feSpotLight: component( + ref?: React.RefSetter, + ...StrictReactDOMFeSpotLightProps +) = createStrictSvg('feSpotLight'); + +/** + * "feTile" + */ +export const feTile: component( + ref?: React.RefSetter, + ...StrictReactDOMFeTileProps +) = createStrictSvg('feTile'); + +/** + * "feTurbulence" + */ +export const feTurbulence: component( + ref?: React.RefSetter, + ...StrictReactDOMFeTurbulenceProps +) = createStrictSvg('feTurbulence'); + +/** + * "filter" + */ +export const filter: component( + ref?: React.RefSetter, + ...StrictReactDOMFilterProps +) = createStrictSvg('filter'); + +/** + * "foreignObject" + */ +export const foreignObject: component( + ref?: React.RefSetter, + ...StrictReactDOMForeignObjectProps +) = createStrictSvg('foreignObject'); + +/** + * "g" + */ +export const g: component( + ref?: React.RefSetter, + ...StrictReactDOMGProps +) = createStrictSvg('g'); + +/** + * "image" + */ +export const image: component( + ref?: React.RefSetter, + ...StrictReactDOMImageProps +) = createStrictSvg('image'); + +/** + * "line" + */ +export const line: component( + ref?: React.RefSetter, + ...StrictReactDOMLineProps +) = createStrictSvg('line'); + +/** + * "linearGradient" + */ +export const linearGradient: component( + ref?: React.RefSetter, + ...StrictReactDOMLinearGradientProps +) = createStrictSvg('linearGradient'); + +/** + * "marker" + */ +export const marker: component( + ref?: React.RefSetter, + ...StrictReactDOMMarkerProps +) = createStrictSvg('marker'); + +/** + * "mask" + */ +export const mask: component( + ref?: React.RefSetter, + ...StrictReactDOMMaskProps +) = createStrictSvg('mask'); + +/** + * "path" + */ +export const path: component( + ref?: React.RefSetter, + ...StrictReactDOMPathProps +) = createStrictSvg('path'); + +/** + * "pattern" + */ +export const pattern: component( + ref?: React.RefSetter, + ...StrictReactDOMPatternProps +) = createStrictSvg('pattern'); + +/** + * "polygon" + */ +export const polygon: component( + ref?: React.RefSetter, + ...StrictReactDOMPolygonProps +) = createStrictSvg('polygon'); + +/** + * "polyline" + */ +export const polyline: component( + ref?: React.RefSetter, + ...StrictReactDOMPolylineProps +) = createStrictSvg('polyline'); + +/** + * "radialGradient" + */ +export const radialGradient: component( + ref?: React.RefSetter, + ...StrictReactDOMRadialGradientProps +) = createStrictSvg('radialGradient'); + +/** + * "rect" + */ +export const rect: component( + ref?: React.RefSetter, + ...StrictReactDOMRectProps +) = createStrictSvg('rect'); + +/** + * "stop" + */ +export const stop: component( + ref?: React.RefSetter, + ...StrictReactDOMStopProps +) = createStrictSvg('stop'); + +/** + * "svg" (inline) + */ +export const svg: component( + ref?: React.RefSetter, + ...StrictReactDOMSvgProps +) = createStrictSvg('svg'); + +/** + * "symbol" + */ +export const symbol: component( + ref?: React.RefSetter, + ...StrictReactDOMSymbolProps +) = createStrictSvg('symbol'); + +/** + * "tspan" + */ +export const tspan: component( + ref?: React.RefSetter, + ...StrictReactDOMTSpanProps +) = createStrictSvg('tSpan'); + +/** + * "text" + */ +export const text: component( + ref?: React.RefSetter, + ...StrictReactDOMTextProps +) = createStrictSvg('text'); + +/** + * "textPath" + */ +export const textPath: component( + ref?: React.RefSetter, + ...StrictReactDOMTextPathProps +) = createStrictSvg('textPath'); + +/** + * "use" + */ +export const use: component( + ref?: React.RefSetter, + ...StrictReactDOMUseProps +) = createStrictSvg('use'); diff --git a/packages/react-strict-dom/src/shared/isSvgPropAllowed.js b/packages/react-strict-dom/src/shared/isSvgPropAllowed.js new file mode 100644 index 00000000..af424215 --- /dev/null +++ b/packages/react-strict-dom/src/shared/isSvgPropAllowed.js @@ -0,0 +1,170 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @flow strict + */ + +import { isPropAllowed } from './isPropAllowed'; + +const strictAttributeSet: Set = new Set([ + 'children', + 'color', + 'crossOrigin', + 'height', + 'id', + 'lang', + 'max', + 'media', + 'method', + 'min', + 'name', + 'role', + 'style', + 'tabIndex', + 'target', + 'type', + 'width', + + 'alignmentBaseline', + 'amplitude', + 'azimuth', + 'baseFrequency', + 'baselineShift', + 'bias', + 'clipPath', + 'clipRule', + 'cx', + 'cy', + 'd', + 'diffuseConstant', + 'divisor', + 'dx', + 'dy', + 'edgeMode', + 'elevation', + 'exponent', + 'fill', + 'fillOpacity', + 'fillRule', + 'filter', + 'filterUnits', + 'floodColor', + 'floodOpacity', + 'fontFamily', + 'fontFeatureSettings', + 'fontSize', + 'fontStyle', + 'fontVariant', + 'fontWeight', + 'fx', + 'fy', + 'gradientTransform', + 'gradientUnits', + 'href', + 'in', + 'in2', + 'inlineSize', + 'intercept', + 'k1', + 'k2', + 'k3', + 'k4', + 'kernelMatrix', + 'kernelUnitLength', + 'kerning', + 'lengthAdjust', + 'letterSpacing', + 'limitingConeAngle', + 'marker', + 'markerEnd', + 'markerHeight', + 'markerMid', + 'markerStart', + 'markerUnits', + 'markerWidth', + 'mask', + 'maskContentUnits', + 'maskType', + 'maskUnits', + 'midLine', + 'mode', + 'numOctaves', + 'offset', + 'onLoad', + 'onLoad', + 'opacity', + 'operator', + 'order', + 'orient', + 'patternContentUnits', + 'patternTransform', + 'patternUnits', + 'points', + 'pointsAtX', + 'pointsAtY', + 'pointsAtZ', + 'preserveAlpha', + 'preserveAspectRatio', + 'primitiveUnits', + 'r', + 'radius', + 'refX', + 'refY', + 'rotate', + 'rx', + 'ry', + 'scale', + 'seed', + 'side', + 'slope', + 'spacing', + 'specularConstant', + 'specularExponent', + 'startOffset', + 'stdDeviation', + 'stitchTiles', + 'stopColor', + 'stopOpacity', + 'stroke', + 'strokeDasharray', + 'strokeDashoffset', + 'strokeLinecap', + 'strokeLinejoin', + 'strokeMiterlimit', + 'strokeOpacity', + 'strokeWidth', + 'surfaceScale', + 'tableValues', + 'targetX', + 'targetY', + 'textAnchor', + 'textDecoration', + 'textLength', + 'title', + 'transform', + 'transformOrigin', + 'values', + 'vectorEffect', + 'verticalAlign', + 'viewBox', + 'wordSpacing', + 'x', + 'x1', + 'x2', + 'xChannelSelector', + 'xlinkHref', + 'xmlns', + 'xmlnsXlink', + 'y', + 'y1', + 'y2', + 'yChannelSelector', + 'z' +]); + +export function isSvgPropAllowed(key: string): boolean { + return isPropAllowed(key) || strictAttributeSet.has(key); +} diff --git a/packages/react-strict-dom/src/types/StrictProps.js b/packages/react-strict-dom/src/types/StrictProps.js index 1f974a1c..ee501281 100644 --- a/packages/react-strict-dom/src/types/StrictProps.js +++ b/packages/react-strict-dom/src/types/StrictProps.js @@ -17,6 +17,7 @@ import type { StrictReactDOMLabelProps } from './StrictReactDOMLabelProps'; import type { StrictReactDOMListItemProps } from './StrictReactDOMListItemProps'; import type { StrictReactDOMOptionProps } from './StrictReactDOMOptionProps'; import type { StrictReactDOMSelectProps } from './StrictReactDOMSelectProps'; +import type { StrictReactDOMSvgProps } from './StrictReactDOMSvgProps'; import type { StrictReactDOMTextAreaProps } from './StrictReactDOMTextAreaProps'; export type StrictProps = $ReadOnly<{ @@ -29,5 +30,6 @@ export type StrictProps = $ReadOnly<{ ...StrictReactDOMListItemProps, ...StrictReactDOMOptionProps, ...StrictReactDOMSelectProps, + ...StrictReactDOMSvgProps, ...StrictReactDOMTextAreaProps }>; diff --git a/packages/react-strict-dom/src/types/StrictReactDOMSvgProps.js b/packages/react-strict-dom/src/types/StrictReactDOMSvgProps.js new file mode 100644 index 00000000..a81d0a37 --- /dev/null +++ b/packages/react-strict-dom/src/types/StrictReactDOMSvgProps.js @@ -0,0 +1,488 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @flow strict + */ + +import type { StrictReactDOMProps } from './StrictReactDOMProps'; +import type { Styles } from './styles'; + +type Units = 'userSpaceOnUse' | 'objectBoundingBox'; + +type FontProps = $ReadOnly<{ + fontFamily?: string, + fontSize?: string | number, + fontStyle?: 'normal' | 'italic' | 'oblique', + fontVariant?: 'normal' | 'small-caps', + fontWeight?: string | number, + kerning?: string | number, + letterSpacing?: string | number, + textAnchor?: 'start' | 'middle' | 'end', + textDecoration?: 'none' | 'underline' | 'overline' | 'line-through' | 'blink', + wordSpacing?: string | number +}>; + +type TransformProps = $ReadOnly<{ + transform?: string, + transformOrigin?: string, + x?: string | number, + y?: string | number +}>; + +type PathProps = $ReadOnly<{ + ...TransformProps, + ...Pick, + clipPath?: string, + clipRule?: 'evenodd' | 'nonzero', + color?: string, + fill?: string, + fillOpacity?: string | number, + fillRule?: 'evenodd' | 'nonzero', + filter?: string, + id?: ?string, + marker?: string, + markerEnd?: string, + markerMid?: string, + markerStart?: string, + mask?: string, + stroke?: string, + strokeDasharray?: string | number, + strokeDashoffset?: string | number, + strokeLinecap?: 'butt' | 'square' | 'round', + strokeLinejoin?: 'miter' | 'bevel' | 'round', + strokeMiterlimit?: string | number, + strokeOpacity?: string | number, + strokeWidth?: string | number, + vectorEffect?: 'none' | 'non-scaling-stroke' | 'default' | 'inherit' | 'uri' +}>; + +type TextProps = $ReadOnly<{ + ...PathProps, + ...FontProps, + alignmentBaseline?: + | 'baseline' + | 'before-edge' + | 'text-before-edge' + | 'middle' + | 'central' + | 'after-edge' + | 'text-after-edge' + | 'ideographic' + | 'alphabetic' + | 'hanging' + | 'mathematical', + baselineShift?: string | number, + fontFeatureSettings?: string, + lengthAdjust?: 'spacing' | 'spacingAndGlyphs', + textLength?: string | number, + verticalAlign?: string | number +}>; + +export type StrictReactDOMSvgProps = $ReadOnly<{ + ...StrictReactDOMProps, + ...StrictReactDOMGProps, + height?: string | number, + preserveAspectRatio?: string, + title?: string, + viewBox?: string, + width?: string | number, + xmlns?: string, + xmlnsXlink?: string +}>; + +export type StrictReactDOMCircleProps = $ReadOnly<{ + ...PathProps, + cx?: string | number, + cy?: string | number, + opacity?: string | number, + r?: string | number +}>; + +export type StrictReactDOMClipPathProps = $ReadOnly<{ + children?: React.Node, + id?: ?string +}>; + +export type StrictReactDOMDefsProps = $ReadOnly<{ + children?: React.Node, + id?: ?string +}>; + +export type StrictReactDOMEllipseProps = $ReadOnly<{ + ...PathProps, + cx?: string | number, + cy?: string | number, + opacity?: string | number, + rx?: string | number, + ry?: string | number +}>; + +export type StrictReactDOMForeignObjectProps = $ReadOnly<{ + children?: React.Node, + height?: string | number, + width?: string | number, + x?: string | number, + y?: string | number +}>; + +export type StrictReactDOMGProps = $ReadOnly<{ + ...PathProps, + ...FontProps, + children?: React.Node, + opacity?: string | number +}>; + +export type StrictReactDOMImageProps = $ReadOnly<{ + ...PathProps, + height?: string | number, + href?: string, + onLoad?: $FlowFixMe, + opacity?: string | number, + preserveAspectRatio?: string, + width?: string | number, + x?: string | number, + xlinkHref?: string, + y?: string | number +}>; + +export type StrictReactDOMLineProps = $ReadOnly<{ + ...PathProps, + opacity?: string | number, + x1?: string | number, + x2?: string | number, + y1?: string | number, + y2?: string | number +}>; + +export type StrictReactDOMLinearGradientProps = $ReadOnly<{ + children?: React.Node, + gradientTransform?: string, + gradientUnits?: Units, + id?: ?string, + x1?: string | number, + x2?: string | number, + y1?: string | number, + y2?: string | number +}>; + +export type StrictReactDOMMarkerProps = $ReadOnly<{ + children?: React.Node, + id?: ?string, + markerHeight?: string | number, + markerUnits?: 'strokeWidth' | 'userSpaceOnUse', + markerWidth?: string | number, + orient?: string | number, + preserveAspectRatio?: string, + refX?: string | number, + refY?: string | number, + viewBox?: string +}>; + +export type StrictReactDOMMaskProps = $ReadOnly<{ + ...PathProps, + children?: React.Node, + height?: string | number, + id?: ?string, + maskContentUnits?: Units, + maskType?: string | number, + maskUnits?: Units, + style?: ?Styles, + width?: string | number, + x?: string | number, + y?: string | number +}>; + +export type StrictReactDOMPathProps = $ReadOnly<{ + ...PathProps, + d?: string, + opacity?: string | number +}>; + +export type StrictReactDOMPatternProps = $ReadOnly<{ + ...TransformProps, + children?: React.Node, + height?: string | number, + id?: ?string, + patternContentUnits?: Units, + patternTransform?: string, + patternUnits?: Units, + preserveAspectRatio?: string, + viewBox?: string, + width?: string | number, + x?: string | number, + y?: string | number +}>; + +export type StrictReactDOMPolygonProps = $ReadOnly<{ + ...PathProps, + opacity?: string | number, + points?: string +}>; + +export type StrictReactDOMPolylineProps = $ReadOnly<{ + ...PathProps, + opacity?: string | number, + points?: string +}>; + +export type StrictReactDOMRadialGradientProps = $ReadOnly<{ + children?: React.Node, + cx?: string | number, + cy?: string | number, + fx?: string | number, + fy?: string | number, + gradientTransform?: string, + gradientUnits?: Units, + id?: ?string, + r?: string | number, + rx?: string | number, + ry?: string | number +}>; + +export type StrictReactDOMRectProps = $ReadOnly<{ + ...PathProps, + height?: string | number, + opacity?: string | number, + rx?: string | number, + ry?: string | number, + width?: string | number, + x?: string | number, + y?: string | number +}>; + +export type StrictReactDOMStopProps = $ReadOnly<{ + offset?: string | number, + stopColor?: string, + stopOpacity?: string | number +}>; + +export type StrictReactDOMSymbolProps = $ReadOnly<{ + children?: React.Node, + id?: ?string, + opacity?: string | number, + preserveAspectRatio?: string, + viewBox?: string +}>; + +export type StrictReactDOMTSpanProps = $ReadOnly<{ + ...PathProps, + ...FontProps, + children?: React.Node, + dx?: string | number, + dy?: string | number, + inlineSize?: string | number, + rotate?: string | number, + x?: string | number, + y?: string | number +}>; + +export type StrictReactDOMTextProps = $ReadOnly<{ + ...TextProps, + children?: React.Node, + dx?: string | number, + dy?: string | number, + inlineSize?: string | number, + opacity?: string | number, + rotate?: string | number, + style?: ?Styles, + x?: string | number, + y?: string | number +}>; + +export type StrictReactDOMTextPathProps = $ReadOnly<{ + ...TextProps, + children?: React.Node, + href?: string, + method?: 'align' | 'stretch', + midLine?: 'sharp' | 'smooth', + side?: string, + spacing?: 'auto' | 'exact', + startOffset?: string | number, + xlinkHref?: string +}>; + +export type StrictReactDOMUseProps = $ReadOnly<{ + ...PathProps, + children?: React.Node, + height?: string | number, + href?: string, + opacity?: string | number, + width?: string | number, + x?: string | number, + xlinkHref?: string, + y?: string | number +}>; + +export type StrictReactDOMFeBlendProps = $ReadOnly<{ + in?: string, + in2?: string, + mode?: 'normal' | 'multiply' | 'screen' | 'darken' | 'lighten' +}>; + +export type StrictReactDOMFeColorMatrixProps = $ReadOnly<{ + in?: string, + type?: 'matrix' | 'saturate' | 'hueRotate' | 'luminanceToAlpha', + values?: string +}>; + +export type StrictReactDOMFeComponentTransferProps = $ReadOnly<{ + children?: React.Node, + in?: string +}>; + +export type StrictReactDOMFeFuncAProps = $ReadOnly<{ + amplitude?: string | number, + exponent?: string | number, + intercept?: string | number, + offset?: string | number, + slope?: string | number, + tableValues?: string | number, + type?: 'identity' | 'table' | 'discrete' | 'linear' | 'gamma' +}>; + +export type StrictReactDOMFeFuncBProps = StrictReactDOMFeFuncAProps; + +export type StrictReactDOMFeFuncGProps = StrictReactDOMFeFuncAProps; + +export type StrictReactDOMFeFuncRProps = StrictReactDOMFeFuncAProps; + +export type StrictReactDOMFeCompositeProps = $ReadOnly<{ + in?: string, + in2?: string, + k1?: string | number, + k2?: string | number, + k3?: string | number, + k4?: string | number, + operator?: 'over' | 'in' | 'out' | 'atop' | 'xor' | 'arithmetic' +}>; + +export type StrictReactDOMFeConvolveMatrixProps = $ReadOnly<{ + bias?: string | number, + divisor?: string | number, + edgeMode?: 'duplicate' | 'wrap' | 'none', + in?: string, + kernelMatrix?: string | number, + kernelUnitLength?: string | number, + order?: string | number, + preserveAlpha?: boolean | 'true' | 'false', + targetX?: string | number, + targetY?: string | number +}>; + +export type StrictReactDOMFeDiffuseLightingProps = $ReadOnly<{ + diffuseConstant?: string | number, + in?: string, + kernelUnitLength?: string | number, + surfaceScale?: string | number +}>; + +export type StrictReactDOMFeDisplacementMapProps = $ReadOnly<{ + in?: string, + in2?: string, + scale?: string | number, + xChannelSelector?: 'R' | 'G' | 'B' | 'A', + yChannelSelector?: 'R' | 'G' | 'B' | 'A' +}>; + +export type StrictReactDOMFeDistantLightProps = $ReadOnly<{ + azimuth?: string | number, + elevation?: string | number +}>; + +export type StrictReactDOMFeDropShadowProps = $ReadOnly<{ + dx?: string | number, + dy?: string | number, + floodColor?: string, + floodOpacity?: string | number, + in?: string, + stdDeviation?: string | number +}>; + +export type StrictReactDOMFeFloodProps = $ReadOnly<{ + floodColor?: string, + floodOpacity?: string | number, + in?: string +}>; + +export type StrictReactDOMFeGaussianBlurProps = $ReadOnly<{ + edgeMode?: 'duplicate' | 'wrap' | 'none', + in?: string, + stdDeviation?: string | number +}>; + +export type StrictReactDOMFeImageProps = $ReadOnly<{ + crossOrigin?: 'anonymous' | 'use-credentials' | '', + href?: string, + preserveAspectRatio?: string +}>; + +export type StrictReactDOMFeMergeProps = $ReadOnly<{ + children?: React.Node +}>; + +export type StrictReactDOMFeMergeNodeProps = $ReadOnly<{ + in?: string +}>; + +export type StrictReactDOMFeMorphologyProps = $ReadOnly<{ + in?: string, + operator?: 'erode' | 'dilate', + radius?: string | number +}>; + +export type StrictReactDOMFeOffsetProps = $ReadOnly<{ + dx?: string | number, + dy?: string | number, + in?: string +}>; + +export type StrictReactDOMFePointLightProps = $ReadOnly<{ + x?: string | number, + y?: string | number, + z?: string | number +}>; + +export type StrictReactDOMFeSpecularLightingProps = $ReadOnly<{ + in?: string, + kernelUnitLength?: string | number, + specularConstant?: string | number, + specularExponent?: string | number, + surfaceScale?: string | number +}>; + +export type StrictReactDOMFeSpotLightProps = $ReadOnly<{ + limitingConeAngle?: string | number, + pointsAtX?: string | number, + pointsAtY?: string | number, + pointsAtZ?: string | number, + specularExponent?: string | number, + x?: string | number, + y?: string | number, + z?: string | number +}>; + +export type StrictReactDOMFeTileProps = $ReadOnly<{ + in?: string +}>; + +export type StrictReactDOMFeTurbulenceProps = $ReadOnly<{ + baseFrequency?: string | number, + numOctaves?: string | number, + seed?: string | number, + stitchTiles?: 'stitch' | 'noStitch', + type?: 'fractalNoise' | 'turbulence' +}>; + +export type StrictReactDOMFilterProps = $ReadOnly<{ + children?: React.Node, + filterUnits?: Units, + height?: string | number, + id?: ?string, + primitiveUnits?: Units, + width?: string | number, + x?: string | number, + y?: string | number +}>; diff --git a/packages/react-strict-dom/src/types/StrictSvgProps.js b/packages/react-strict-dom/src/types/StrictSvgProps.js new file mode 100644 index 00000000..c31e6654 --- /dev/null +++ b/packages/react-strict-dom/src/types/StrictSvgProps.js @@ -0,0 +1,114 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @flow strict + */ + +import type { + StrictReactDOMCircleProps, + StrictReactDOMClipPathProps, + StrictReactDOMDefsProps, + StrictReactDOMEllipseProps, + StrictReactDOMFeBlendProps, + StrictReactDOMFeColorMatrixProps, + StrictReactDOMFeComponentTransferProps, + StrictReactDOMFeCompositeProps, + StrictReactDOMFeConvolveMatrixProps, + StrictReactDOMFeDiffuseLightingProps, + StrictReactDOMFeDisplacementMapProps, + StrictReactDOMFeDistantLightProps, + StrictReactDOMFeDropShadowProps, + StrictReactDOMFeFloodProps, + StrictReactDOMFeFuncAProps, + StrictReactDOMFeFuncBProps, + StrictReactDOMFeFuncGProps, + StrictReactDOMFeFuncRProps, + StrictReactDOMFeGaussianBlurProps, + StrictReactDOMFeImageProps, + StrictReactDOMFeMergeNodeProps, + StrictReactDOMFeMergeProps, + StrictReactDOMFeMorphologyProps, + StrictReactDOMFeOffsetProps, + StrictReactDOMFePointLightProps, + StrictReactDOMFeSpecularLightingProps, + StrictReactDOMFeSpotLightProps, + StrictReactDOMFeTileProps, + StrictReactDOMFeTurbulenceProps, + StrictReactDOMFilterProps, + StrictReactDOMForeignObjectProps, + StrictReactDOMGProps, + StrictReactDOMImageProps, + StrictReactDOMLinearGradientProps, + StrictReactDOMLineProps, + StrictReactDOMMarkerProps, + StrictReactDOMMaskProps, + StrictReactDOMPathProps, + StrictReactDOMPatternProps, + StrictReactDOMPolygonProps, + StrictReactDOMPolylineProps, + StrictReactDOMRadialGradientProps, + StrictReactDOMRectProps, + StrictReactDOMStopProps, + StrictReactDOMSvgProps, + StrictReactDOMSymbolProps, + StrictReactDOMTextPathProps, + StrictReactDOMTextProps, + StrictReactDOMTSpanProps, + StrictReactDOMUseProps +} from './StrictReactDOMSvgProps'; + +export type StrictSvgProps = $ReadOnly<{ + ...StrictReactDOMCircleProps, + ...StrictReactDOMClipPathProps, + ...StrictReactDOMDefsProps, + ...StrictReactDOMEllipseProps, + ...StrictReactDOMFeBlendProps, + ...StrictReactDOMFeColorMatrixProps, + ...StrictReactDOMFeComponentTransferProps, + ...StrictReactDOMFeCompositeProps, + ...StrictReactDOMFeConvolveMatrixProps, + ...StrictReactDOMFeDiffuseLightingProps, + ...StrictReactDOMFeDisplacementMapProps, + ...StrictReactDOMFeDistantLightProps, + ...StrictReactDOMFeDropShadowProps, + ...StrictReactDOMFeFloodProps, + ...StrictReactDOMFeFuncAProps, + ...StrictReactDOMFeFuncBProps, + ...StrictReactDOMFeFuncGProps, + ...StrictReactDOMFeFuncRProps, + ...StrictReactDOMFeGaussianBlurProps, + ...StrictReactDOMFeImageProps, + ...StrictReactDOMFeMergeNodeProps, + ...StrictReactDOMFeMergeProps, + ...StrictReactDOMFeMorphologyProps, + ...StrictReactDOMFeOffsetProps, + ...StrictReactDOMFePointLightProps, + ...StrictReactDOMFeSpecularLightingProps, + ...StrictReactDOMFeSpotLightProps, + ...StrictReactDOMFeTileProps, + ...StrictReactDOMFeTurbulenceProps, + ...StrictReactDOMFilterProps, + ...StrictReactDOMForeignObjectProps, + ...StrictReactDOMGProps, + ...StrictReactDOMImageProps, + ...StrictReactDOMLinearGradientProps, + ...StrictReactDOMLineProps, + ...StrictReactDOMMarkerProps, + ...StrictReactDOMMaskProps, + ...StrictReactDOMPathProps, + ...StrictReactDOMPatternProps, + ...StrictReactDOMPolygonProps, + ...StrictReactDOMPolylineProps, + ...StrictReactDOMRadialGradientProps, + ...StrictReactDOMRectProps, + ...StrictReactDOMStopProps, + ...StrictReactDOMSvgProps, + ...StrictReactDOMSymbolProps, + ...StrictReactDOMTextPathProps, + ...StrictReactDOMTextProps, + ...StrictReactDOMTSpanProps, + ...StrictReactDOMUseProps +}>; diff --git a/packages/react-strict-dom/tests/__mocks__/react-native-svg/index.js b/packages/react-strict-dom/tests/__mocks__/react-native-svg/index.js new file mode 100644 index 00000000..d0b852e7 --- /dev/null +++ b/packages/react-strict-dom/tests/__mocks__/react-native-svg/index.js @@ -0,0 +1,106 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +export const Circle = 'Circle'; + +export const ClipPath = 'ClipPath'; + +export const Defs = 'Defs'; + +export const Ellipse = 'Ellipse'; + +export const FeBlend = 'FeBlend'; + +export const FeColorMatrix = 'FeColorMatrix'; + +export const FeComponentTransfer = 'FeComponentTransfer'; + +export const FeComposite = 'FeComposite'; + +export const FeConvolveMatrix = 'FeConvolveMatrix'; + +export const FeDiffuseLighting = 'FeDiffuseLighting'; + +export const FeDisplacementMap = 'FeDisplacementMap'; + +export const FeDistantLight = 'FeDistantLight'; + +export const FeDropShadow = 'FeDropShadow'; + +export const FeFlood = 'FeFlood'; + +export const FeFuncA = 'FeFuncA'; + +export const FeFuncB = 'FeFuncB'; + +export const FeFuncG = 'FeFuncG'; + +export const FeFuncR = 'FeFuncR'; + +export const FeGaussianBlur = 'FeGaussianBlur'; + +export const FeImage = 'FeImage'; + +export const FeMerge = 'FeMerge'; + +export const FeMergeNode = 'FeMergeNode'; + +export const FeMorphology = 'FeMorphology'; + +export const FeOffset = 'FeOffset'; + +export const FePointLight = 'FePointLight'; + +export const FeSpecularLighting = 'FeSpecularLighting'; + +export const FeSpotLight = 'FeSpotLight'; + +export const FeTile = 'FeTile'; + +export const FeTurbulence = 'FeTurbulence'; + +export const Filter = 'Filter'; + +export const ForeignObject = 'ForeignObject'; + +export const G = 'G'; + +export const Image = 'Image'; + +export const Line = 'Line'; + +export const LinearGradient = 'LinearGradient'; + +export const Marker = 'Marker'; + +export const Mask = 'Mask'; + +export const Path = 'Path'; + +export const Pattern = 'Pattern'; + +export const Polygon = 'Polygon'; + +export const Polyline = 'Polyline'; + +export const RadialGradient = 'RadialGradient'; + +export const Rect = 'Rect'; + +export const Stop = 'Stop'; + +export const Svg = 'Svg'; + +export const Symbol = 'Symbol'; + +export const Text = 'Text'; + +export const TextPath = 'TextPath'; + +export const TSpan = 'TSpan'; + +export const Use = 'Use'; diff --git a/tools/flow-typed/npm/react-native-svg_vx.x.x.js b/tools/flow-typed/npm/react-native-svg_vx.x.x.js new file mode 100644 index 00000000..779b2c61 --- /dev/null +++ b/tools/flow-typed/npm/react-native-svg_vx.x.x.js @@ -0,0 +1,12 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @flow strict + */ + +declare module 'react-native-svg' { + declare module.exports: any; +} diff --git a/tools/flow-typed/react-strict-dom.js b/tools/flow-typed/react-strict-dom.js index 3cb785d5..1bea0d27 100644 --- a/tools/flow-typed/react-strict-dom.js +++ b/tools/flow-typed/react-strict-dom.js @@ -18,3 +18,54 @@ declare type ReactStrictDOMDataProps = { // internationalization type which is a string at runtime… // but Flow doesn't know that. declare type Stringish = string; + +declare type SVGCircleElement = {}; +declare type SVGClipPathElement = {}; +declare type SVGDefsElement = {}; +declare type SVGEllipseElement = {}; +declare type SVGFEBlendElement = {}; +declare type SVGFEColorMatrixElement = {}; +declare type SVGFEComponentTransferElement = {}; +declare type SVGFECompositeElement = {}; +declare type SVGFEConvolveMatrixElement = {}; +declare type SVGFEDiffuseLightingElement = {}; +declare type SVGFEDisplacementMapElement = {}; +declare type SVGFEDistantLightElement = {}; +declare type SVGFEDropShadowElement = {}; +declare type SVGFEFloodElement = {}; +declare type SVGFEFuncAElement = {}; +declare type SVGFEFuncBElement = {}; +declare type SVGFEFuncGElement = {}; +declare type SVGFEFuncRElement = {}; +declare type SVGFEGaussianBlurElement = {}; +declare type SVGFEImageElement = {}; +declare type SVGFEMergeElement = {}; +declare type SVGFEMergeNodeElement = {}; +declare type SVGFEMorphologyElement = {}; +declare type SVGFEOffsetElement = {}; +declare type SVGFEPointLightElement = {}; +declare type SVGFESpecularLightingElement = {}; +declare type SVGFESpotLightElement = {}; +declare type SVGFETileElement = {}; +declare type SVGFETurbulenceElement = {}; +declare type SVGFilterElement = {}; +declare type SVGForeignObjectElement = {}; +declare type SVGGElement = {}; +declare type SVGImageElement = {}; +declare type SVGLineElement = {}; +declare type SVGLinearGradientElement = {}; +declare type SVGMarkerElement = {}; +declare type SVGMaskElement = {}; +declare type SVGPathElement = {}; +declare type SVGPatternElement = {}; +declare type SVGPolygonElement = {}; +declare type SVGPolylineElement = {}; +declare type SVGRadialGradientElement = {}; +declare type SVGRectElement = {}; +declare type SVGStopElement = {}; +declare type SVGSVGElement = {}; +declare type SVGSymbolElement = {}; +declare type SVGTextElement = {}; +declare type SVGTextPathElement = {}; +declare type SVGTSpanElement = {}; +declare type SVGUseElement = {};