kristerkari / react-native-svg-transformer

Import SVG files in your React Native project the same way that you would in a Web application.
MIT License
1.54k stars 116 forks source link

Additional docs on how to add templates as described in SVGR #365

Closed fcole90 closed 2 days ago

fcole90 commented 4 days ago

SVGR describes how to create Custom Templates https://react-svgr.com/docs/custom-templates/, but when trying to do that, I quickly realized that the params passed to the functions were different from what is described in the docs, when using this plugin. Trying to use babel-plugin-transform-svg-component gave no success, as other issues happened (presumably due to web/native incompatibilities). Also, the main character, the tpl function is missing.

Hoping this can be useful to someone, this is a working implementation, with JSDoc typing (very basic) and with tpl reimplmented from babel-plugin-transform-svg-component.

I don't know if there is a better/simpler way, but I think this can be useful to anyone willing to use custom templates with metro and React Native 😊 I think it would be great if there could be any docs for this in the Readme 😃

// Custom templates code for react-native-svg-transformer
const core = require('@babel/core');

/**
 * Custom template function for SVGR when using react-native-svg-transformer
 *
 * See more: https://react-svgr.com/docs/custom-templates
 *
 * @param {TransformerContext} _ctx
 * @param {SVGROptions} options
 * @param {SVGRVariables} variables
 */
const template = (_ctx, options, variables) => {
  /** Implemented as in `@svgr/babel-plugin-transform-svg-component` */
  const tpl = core.template.smart({
    plugins: options.plugins,
    preserveComments: true,
  }).ast;

  return tpl`
${variables.imports};

${variables.interfaces};

const ${variables.componentName} = (${variables.props}) => (
  ${variables.jsx}
);

${variables.exports};
`
};

module.exports = template;

/**
 * @typedef {Object} TransformerContext
 * @prop {object} DEFAULT_EXTENSIONS
 * @prop {function} File
 * @prop {function} buildExternalHelpers
 * @prop {function} createConfigItem
 * @prop {function} createConfigItemAsync
 * @prop {function} createConfigItemSync
 * @prop {function} getEnv
 * @prop {function} loadOptions
 * @prop {function} loadOptionsAsync
 * @prop {function} loadOptionsSync
 * @prop {function} loadPartialConfig
 * @prop {function} loadPartialConfigAsync
 * @prop {function} loadPartialConfigSync
 * @prop {function} parse
 * @prop {function} parseAsync
 * @prop {function} parseSync
 * @prop {function} resolvePlugin
 * @prop {function} resolvePreset
 * @prop {function} template
 * @prop {object} tokTypes
 * @prop {function} transform
 * @prop {function} transformAsync
 * @prop {function} transformFile
 * @prop {function} transformFileAsync
 * @prop {function} transformFileSync
 * @prop {function} transformFromAst
 * @prop {function} transformFromAstAsync
 * @prop {function} transformFromAstSync
 * @prop {function} transformSync
 * @prop {function} traverse
 * @prop {object} types
 * @prop {string} version
 * @prop {function} OptionManager
 * @prop {function} Plugin
 * @prop {function} cache
 * @prop {function} env
 * @prop {function} async
 * @prop {function} caller
 * @prop {function} assertVersion
 * @prop {function} targets
 * @prop {function} addExternalDependency
 * @prop {function} assumption
 */

/**
 * @typedef {Object} SVGROptions
 * @prop {boolean} dimensions
 * @prop {string} expandProps
 * @prop {boolean} icon
 * @prop {boolean} native
 * @prop {boolean} typescript
 * @prop {boolean} prettier
 * @prop {undefined} prettierConfig
 * @prop {boolean} memo
 * @prop {boolean} ref
 * @prop {undefined} replaceAttrValues
 * @prop {undefined} svgProps
 * @prop {boolean} svgo
 * @prop {object} svgoConfig
 * @prop {function} template
 * @prop {boolean} index
 * @prop {boolean} titleProp
 * @prop {boolean} descProp
 * @prop {boolean} runtimeConfig
 * @prop {string} namedExport
 * @prop {string} exportType
 * @prop {object} plugins
 * @prop {object} state
 */

/**
 * @typedef {Object} SVGRVariables
 * @prop {object} componentName
 * @prop {object} interfaces
 * @prop {object} props
 * @prop {object} imports
 * @prop {object} exports
 * @prop {object} jsx
 */
fcole90 commented 2 days ago

Ok, so, apparently this has nothing to do with it being native, it's rather because I was using an older version of the library. See here for more info: https://react-svgr.com/docs/migrate/#template 😊