Skip to content

Commit

Permalink
feat(icons-vue): add vue 3 support (#7545)
Browse files Browse the repository at this point in the history
* fix: carbon icons vue for vue 3

* fix(icon-build-helpers): add vue as external

* chore(ci): update build concurrency to 1

* chore(ci): increase heap size for Node.js

* chore(project): revert ci heap space change

* feat(icon-build-helpers): update rollup to latest versions

* chore(ci): update heap space for Node.js

* chore(project): debug icons-vue build

* chore(icons): add rimraf devDependency

* chore(icons): update to include workspace dependencies

* fix: smal refactor

* fix: big refactor

* fix: correct handling of children

* chore(project): revert changes to circleci

Co-authored-by: Lee Chase <lee.chase@uk.ibm.com>
Co-authored-by: Josh Black <josh@josh.black>
Co-authored-by: Dave Clark <dave.clark@uk.ibm.com>
Co-authored-by: Andrea N. Cardona <andreancardona@gmail.com>
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
  • Loading branch information
6 people authored Jan 22, 2021
1 parent 7133b68 commit aebf79e
Show file tree
Hide file tree
Showing 14 changed files with 136 additions and 119 deletions.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file removed .yarn/cache/vlq-npm-0.2.3-292fe9aaa1-48055a9675.zip
Binary file not shown.
8 changes: 4 additions & 4 deletions packages/icon-build-helpers/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@
"@babel/preset-react": "^7.10.0",
"@carbon/cli-reporter": "^10.4.0",
"@carbon/icon-helpers": "^10.12.0-rc.0",
"@rollup/plugin-babel": "^5.2.2",
"@rollup/plugin-replace": "^2.3.4",
"browserslist-config-carbon": "^10.6.0",
"change-case": "^4.1.1",
"core-js": "^3.6.5",
Expand All @@ -39,10 +41,8 @@
"react": "^16.6.0",
"react-dom": "^16.6.0",
"rimraf": "^3.0.0",
"rollup": "^1.15.1",
"rollup-plugin-babel": "^4.4.0",
"rollup-plugin-replace": "^2.2.0",
"rollup-plugin-strip-banner": "^0.2.0",
"rollup": "^2.36.1",
"rollup-plugin-strip-banner": "^2.0.0",
"svgo": "^1.1.1"
}
}
2 changes: 1 addition & 1 deletion packages/icon-build-helpers/src/builders/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
const react = require('./react/builder');
const svg = require('./svg');
const vanilla = require('./vanilla');
const vue = require('./vue');
const vue = require('./vue/builder');

const builders = {
react: {
Expand Down
4 changes: 3 additions & 1 deletion packages/icon-build-helpers/src/builders/react/builder.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@

'use strict';

const { babel } = require('@rollup/plugin-babel');
const { camelCase } = require('change-case');
const fs = require('fs-extra');
const path = require('path');
const { rollup } = require('rollup');
const babel = require('rollup-plugin-babel');
const virtual = require('../plugins/virtual');

const BANNER = `/**
Expand Down Expand Up @@ -41,6 +41,7 @@ const babelConfig = {
'@babel/plugin-transform-react-constant-elements',
'babel-plugin-dev-expression',
],
babelHelpers: 'bundled',
};

async function builder(metadata, { output }) {
Expand Down Expand Up @@ -156,6 +157,7 @@ const didWarnAboutDeprecation = {};`;
format,
entryFileNames: '[name]',
banner: BANNER,
exports: 'auto',
};

await bundle.write(outputOptions);
Expand Down
4 changes: 3 additions & 1 deletion packages/icon-build-helpers/src/builders/vanilla.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@
* LICENSE file in the root directory of this source tree.
*/

const { babel } = require('@rollup/plugin-babel');
const path = require('path');
const { rollup } = require('rollup');
const babel = require('rollup-plugin-babel');
const virtual = require('./plugins/virtual');

const BANNER = `/**
Expand All @@ -32,6 +32,7 @@ const babelConfig = {
},
],
],
babelHelpers: 'bundled',
};

async function builder(metadata, { output }) {
Expand Down Expand Up @@ -83,6 +84,7 @@ async function builder(metadata, { output }) {
format,
entryFileNames: '[name]',
banner: BANNER,
exports: 'auto',
};

await bundle.write(outputOptions);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,11 @@

'use strict';

const { babel } = require('@rollup/plugin-babel');
const fs = require('fs-extra');
const path = require('path');
const { rollup } = require('rollup');
const babel = require('rollup-plugin-babel');
const virtual = require('./plugins/virtual');
const virtual = require('../plugins/virtual');

const BANNER = `/**
* Copyright IBM Corp. 2019, 2020
Expand All @@ -20,7 +21,7 @@ const BANNER = `/**
*
* Code generated by @carbon/icon-build-helpers. DO NOT EDIT.
*/`;
const external = ['@carbon/icon-helpers'];
const external = ['@carbon/icon-helpers', 'vue'];
const babelConfig = {
babelrc: false,
exclude: /node_modules/,
Expand All @@ -34,6 +35,7 @@ const babelConfig = {
},
],
],
babelHelpers: 'bundled',
};

async function builder(metadata, { output }) {
Expand All @@ -59,6 +61,10 @@ async function builder(metadata, { output }) {
},
};
`,
'./utils.js': await fs.readFile(
path.resolve(__dirname, './utils.js'),
'utf8'
),
};
const input = {
'index.js': 'index.js',
Expand Down Expand Up @@ -95,6 +101,7 @@ async function builder(metadata, { output }) {
format,
entryFileNames: '[name]',
banner: BANNER,
exports: 'auto',
};

await bundle.write(outputOptions);
Expand All @@ -112,6 +119,7 @@ async function builder(metadata, { output }) {
name: 'CarbonIconsVue',
globals: {
'@carbon/icon-helpers': 'CarbonIconHelpers',
vue: 'Vue',
},
});
}
Expand All @@ -123,66 +131,17 @@ async function builder(metadata, { output }) {
* @param {object} descriptor
* @returns {object}
*/
function createIconComponent(moduleName, descriptor) {
const { attrs, content } = descriptor;
const attrsAsString = Object.keys(attrs)
.map((attr) => `${attr}: "${attrs[attr]}"`)
.join(',');
const source = `${BANNER}
import { getAttributes } from '@carbon/icon-helpers';
export default {
name: '${moduleName}',
functional: true,
// We use title as the prop name as it is not a valid attribute for an SVG
// HTML element
props: ['title'],
render(createElement, context) {
const { children, data, listeners, props } = context;
const attrs = getAttributes({
${attrsAsString},
preserveAspectRatio: 'xMidYMid meet',
xmlns: 'http://www.w3.org/2000/svg',
// Special case here, we need to coordinate that we are using title,
// potentially, to get the right focus attributes
title: props.title,
...data.attrs
});
const svgData = {
attrs,
on: listeners,
};
if (data.staticClass) {
svgData.class = {
[data.staticClass]: true,
};
}
if (data.class) {
svgData.class = svgData.class || {}; // may be no static class
svgData.class[data.class] = true;
}
// remove style set by getAttributes
delete svgData.attrs.style;
// combine incoming staticStyle, style with default willChange
svgData.style = { ...data.staticStyle, ...data.style };
return createElement('svg', svgData, [
props.title && createElement('title', null, props.title),
${content.map(convertToVue).join(', ')},
children,
]);
},
};`;

return source;
}
function createIconComponent(moduleName, { attrs, content }) {
return `import createSVGComponent from './utils.js';
/**
* Convert the given node to a Vue string source
* @param {object} node
* @returns {string}
*/
function convertToVue(node) {
const { elem, attrs } = node;
return `createElement('${elem}', { attrs: ${JSON.stringify(attrs)} })`;
const attrs = ${JSON.stringify(attrs)};
const content = ${JSON.stringify(content)};
const ${moduleName} = createSVGComponent(${moduleName}, ${JSON.stringify(
attrs
)}, ${JSON.stringify(content)});
export default ${moduleName};
`;
}

module.exports = builder;
84 changes: 84 additions & 0 deletions packages/icon-build-helpers/src/builders/vue/utils.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
/**
* Copyright IBM Corp. 2018, 2018
*
* This source code is licensed under the Apache-2.0 license found in the
* LICENSE file in the root directory of this source tree.
*/

import { getAttributes } from '@carbon/icon-helpers';
import { h } from 'vue';

const getSvgAttrs = (title, svgAttrs, componentAttrs) => {
return getAttributes({
...svgAttrs,
preserveAspectRatio: 'xMidYMid meet',
xmlns: 'http://www.w3.org/2000/svg',
// Special case here, we need to coordinate that we are using title,
// potentially, to get the right focus attributes
title,
...componentAttrs,
});
};

const getVue2SvgAttrs = (title, svgAttrs, data, listeners) => {
const result = {
attrs: getSvgAttrs(title, svgAttrs, data.attrs),
on: listeners,
style: { ...data.staticStyle, ...data.style },
};

// remove style set by getAttributes
delete result.attrs.style;

if (data.staticClass || data.class) {
result.class = {};

if (data.staticClass) {
result.class[data.staticClass] = true;
}

if (data.class) {
result.class[data.class] = true;
}
}

return result;
};

const createSVGComponent = (name, svgAttrs, svgContent) => ({
// We use title as a prop name for the component
// as it is not a valid attribute for an SVG HTML element
props: { title: String },
name: name,
...(h
? {
// Vue 3 component
setup({ title }, { attrs: componentAttrs, slots }) {
return () =>
h('svg', getSvgAttrs(title, svgAttrs, componentAttrs), [
...(title ? [h('title', title)] : []),
...svgContent.map(({ elem, attrs }) => h(elem, attrs)),
...(slots.default ? slots.default() : []),
]);
},
}
: {
// Vue 2 component
functional: true,
render(createElement, { props: { title }, children, data, listeners }) {
return createElement(
'svg',
getVue2SvgAttrs(title, svgAttrs, data, listeners),
[
...(title ? [createElement('title', null, title)] : []),
...svgContent.map(({ elem, attrs }) =>
createElement(elem, { attrs: attrs })
),
...(children || []),
]
);
},
}),
});

export default createSVGComponent;
3 changes: 2 additions & 1 deletion packages/icons/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
},
"devDependencies": {
"@carbon/cli": "^10.18.0-rc.0",
"@carbon/icon-build-helpers": "^0.14.0-rc.0"
"@carbon/icon-build-helpers": "^0.14.0-rc.0",
"rimraf": "^3.0.2"
}
}
Loading

0 comments on commit aebf79e

Please sign in to comment.