diff --git a/packages/babel-plugin-transform-react-native-svg/src/index.js b/packages/babel-plugin-transform-react-native-svg/src/index.js
index 93f21649..2ec96c6a 100644
--- a/packages/babel-plugin-transform-react-native-svg/src/index.js
+++ b/packages/babel-plugin-transform-react-native-svg/src/index.js
@@ -23,7 +23,15 @@ const elementToComponent = {
image: 'Image',
}
-const plugin = ({ types: t }) => {
+const expoPrefix = (component, expo) => {
+ // Prefix with 'Svg.' in the case we're transforming for Expo
+ if (!expo) {
+ return component
+ }
+ return (component !== 'Svg' ? 'Svg.' : '') + component
+}
+
+const plugin = ({ types: t }, { expo }) => {
function replaceElement(path, state) {
const { name } = path.node.openingElement.name
@@ -31,13 +39,14 @@ const plugin = ({ types: t }) => {
const component = elementToComponent[name]
if (component) {
+ const prefixedComponent = expoPrefix(component, expo)
const openingElementName = path.get('openingElement.name')
- openingElementName.replaceWith(t.jsxIdentifier(component))
+ openingElementName.replaceWith(t.jsxIdentifier(prefixedComponent))
if (path.has('closingElement')) {
const closingElementName = path.get('closingElement.name')
- closingElementName.replaceWith(t.jsxIdentifier(component))
+ closingElementName.replaceWith(t.jsxIdentifier(prefixedComponent))
}
- state.replacedComponents.add(component)
+ state.replacedComponents.add(prefixedComponent)
return
}
@@ -65,26 +74,31 @@ const plugin = ({ types: t }) => {
const importDeclarationVisitor = {
ImportDeclaration(path, state) {
- if (!path.get('source').isStringLiteral({ value: 'react-native-svg' })) {
- return
- }
-
- state.replacedComponents.forEach(component => {
- if (
- path
- .get('specifiers')
- .some(specifier =>
- specifier.get('local').isIdentifier({ name: component }),
- )
- ) {
- return
- }
+ if (path.get('source').isStringLiteral({ value: 'react-native-svg' })) {
+ state.replacedComponents.forEach(component => {
+ if (
+ path
+ .get('specifiers')
+ .some(specifier =>
+ specifier.get('local').isIdentifier({ name: component }),
+ )
+ ) {
+ return
+ }
+ path.pushContainer(
+ 'specifiers',
+ t.importSpecifier(t.identifier(component), t.identifier(component)),
+ )
+ })
+ } else if (path.get('source').isStringLiteral({ value: 'expo' })) {
path.pushContainer(
'specifiers',
- t.importSpecifier(t.identifier(component), t.identifier(component)),
+ t.importSpecifier(t.identifier('Svg'), t.identifier('Svg')),
)
- })
+ } else {
+ return
+ }
if (state.unsupportedComponents.size && !path.has('trailingComments')) {
const componentList = [...state.unsupportedComponents].join(', ')
diff --git a/packages/babel-plugin-transform-react-native-svg/src/index.test.js b/packages/babel-plugin-transform-react-native-svg/src/index.test.js
index 0f634b97..35d004e2 100644
--- a/packages/babel-plugin-transform-react-native-svg/src/index.test.js
+++ b/packages/babel-plugin-transform-react-native-svg/src/index.test.js
@@ -25,6 +25,19 @@ describe('plugin', () => {
/* SVGR has dropped some elements not supported by react-native-svg: div */
;"
+`)
+ })
+
+ it('should transform for expo import', () => {
+ const { code } = testPlugin(`import 'expo'; ;`, {
+ expo: true,
+ })
+
+ expect(code).toMatchInlineSnapshot(`
+"import { Svg } from 'expo';
+/* SVGR has dropped some elements not supported by react-native-svg: div */
+
+;"
`)
})
})
diff --git a/packages/babel-plugin-transform-svg-component/src/index.test.js b/packages/babel-plugin-transform-svg-component/src/index.test.js
index 1120de00..7cece3a1 100644
--- a/packages/babel-plugin-transform-svg-component/src/index.test.js
+++ b/packages/babel-plugin-transform-svg-component/src/index.test.js
@@ -20,6 +20,36 @@ describe('plugin', () => {
const SvgComponent = () => ;
+export default SvgComponent;"
+`)
+ })
+
+ it('should add import for react-native-svg', () => {
+ const { code } = testPlugin('', {
+ state: { componentName: 'SvgComponent' },
+ native: true,
+ })
+ expect(code).toMatchInlineSnapshot(`
+"import React from \\"react\\";
+import Svg from \\"react-native-svg\\";
+
+const SvgComponent = () => ;
+
+export default SvgComponent;"
+`)
+ })
+
+ it('should import for expo', () => {
+ const { code } = testPlugin('', {
+ state: { componentName: 'SvgComponent' },
+ native: { expo: true },
+ })
+ expect(code).toMatchInlineSnapshot(`
+"import React from \\"react\\";
+import \\"expo\\";
+
+const SvgComponent = () => ;
+
export default SvgComponent;"
`)
})
diff --git a/packages/babel-plugin-transform-svg-component/src/util.js b/packages/babel-plugin-transform-svg-component/src/util.js
index 0ca060b5..18870b6f 100644
--- a/packages/babel-plugin-transform-svg-component/src/util.js
+++ b/packages/babel-plugin-transform-svg-component/src/util.js
@@ -47,12 +47,16 @@ export const getImport = ({ types: t }, opts) => {
]
if (opts.native) {
- importDeclarations.push(
- t.importDeclaration(
- [t.importDefaultSpecifier(t.identifier('Svg'))],
- t.stringLiteral('react-native-svg'),
- ),
- )
+ if (opts.native.expo) {
+ importDeclarations.push(t.importDeclaration([], t.stringLiteral('expo')))
+ } else {
+ importDeclarations.push(
+ t.importDeclaration(
+ [t.importDefaultSpecifier(t.identifier('Svg'))],
+ t.stringLiteral('react-native-svg'),
+ ),
+ )
+ }
}
return importDeclarations
diff --git a/packages/babel-preset/src/index.js b/packages/babel-preset/src/index.js
index cc1c40a7..ef28b66d 100644
--- a/packages/babel-preset/src/index.js
+++ b/packages/babel-preset/src/index.js
@@ -90,7 +90,11 @@ const plugin = (api, opts) => {
}
if (opts.native) {
- plugins.push(transformReactNativeSVG)
+ if (opts.native.expo) {
+ plugins.push([transformReactNativeSVG, opts.native])
+ } else {
+ plugins.push(transformReactNativeSVG)
+ }
}
return { plugins }
diff --git a/packages/babel-preset/src/index.test.js b/packages/babel-preset/src/index.test.js
index 857ff534..a10f3609 100644
--- a/packages/babel-preset/src/index.test.js
+++ b/packages/babel-preset/src/index.test.js
@@ -29,6 +29,24 @@ describe('preset', () => {
const SvgComponent = () => ;
+export default SvgComponent;"
+`)
+ })
+
+ it('should handle native expo option', () => {
+ expect(
+ testPreset('', {
+ native: { expo: true },
+ state: {
+ componentName: 'SvgComponent',
+ },
+ }),
+ ).toMatchInlineSnapshot(`
+"import React from \\"react\\";
+import { Svg } from \\"expo\\";
+
+const SvgComponent = () => ;
+
export default SvgComponent;"
`)
})
diff --git a/packages/core/src/__snapshots__/convert.test.js.snap b/packages/core/src/__snapshots__/convert.test.js.snap
index 92f31af3..3cef5e7b 100644
--- a/packages/core/src/__snapshots__/convert.test.js.snap
+++ b/packages/core/src/__snapshots__/convert.test.js.snap
@@ -106,6 +106,28 @@ export default SvgComponent
"
`;
+exports[`convert config should support options { native: { expo: true } } 1`] = `
+"import React from 'react'
+import { Svg } from 'expo'
+
+const SvgComponent = props => (
+
+)
+
+export default SvgComponent
+"
+`;
+
exports[`convert config should support options { native: true, expandProps: false } 1`] = `
"import React from 'react'
import Svg, { G, Path } from 'react-native-svg'
diff --git a/packages/core/src/convert.test.js b/packages/core/src/convert.test.js
index afdf2406..cfde68c0 100644
--- a/packages/core/src/convert.test.js
+++ b/packages/core/src/convert.test.js
@@ -293,6 +293,7 @@ describe('convert', () => {
{ expandProps: 'start' },
{ icon: true },
{ native: true },
+ { native: { expo: true } },
{ native: true, icon: true },
{ native: true, expandProps: false },
{ native: true, ref: true },
diff --git a/website/src/pages/docs/options.mdx b/website/src/pages/docs/options.mdx
index 468bf5de..10ae5d2a 100644
--- a/website/src/pages/docs/options.mdx
+++ b/website/src/pages/docs/options.mdx
@@ -47,9 +47,11 @@ inherits from text size.
Modify all SVG nodes with uppercase and use a specific template with
[`react-native-svg`](https://github.com/react-native-community/react-native-svg) imports. **All unsupported nodes will be removed.**
+Override using the API with `native: { expo: true }` to template SVG nodes with the [ExpoKit SVG package](https://docs.expo.io/versions/latest/sdk/svg/). This is only necessary for 'ejected' ExpoKit projects where `import 'react-native-svg'` results in an error.
+
| Default | CLI Override | API Override |
| ------- | ------------ | ---------------- |
-| `false` | `--native` | `native: ` |
+| `false` | `--native` | `native: ` or `native: { expo: true }` |
## Dimensions