@octaviaflow/icon-build-helpers 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +50 -0
- package/package.json +55 -0
- package/src/builders/index.js +33 -0
- package/src/builders/plugins/virtual.js +51 -0
- package/src/builders/react/builder.js +313 -0
- package/src/builders/react/components/CarbonIcon.d.ts +18 -0
- package/src/builders/react/components/Icon.tsx +87 -0
- package/src/builders/react/next/babel.js +37 -0
- package/src/builders/react/next/convert.js +107 -0
- package/src/builders/react/next/templates.js +71 -0
- package/src/builders/react/next/typescript.js +87 -0
- package/src/builders/react/next.js +382 -0
- package/src/builders/svg.js +28 -0
- package/src/builders/vanilla.js +115 -0
- package/src/index.js +21 -0
- package/src/metadata/README.md +37 -0
- package/src/metadata/adapters/index.js +34 -0
- package/src/metadata/adapters/memory.js +55 -0
- package/src/metadata/adapters/yml.js +92 -0
- package/src/metadata/extension.js +92 -0
- package/src/metadata/extensions/assets.js +45 -0
- package/src/metadata/extensions/categories.js +141 -0
- package/src/metadata/extensions/deprecated.js +73 -0
- package/src/metadata/extensions/icons.js +152 -0
- package/src/metadata/extensions/index.js +48 -0
- package/src/metadata/extensions/module-info.js +154 -0
- package/src/metadata/extensions/module-name.js +54 -0
- package/src/metadata/extensions/output/getModuleName.js +52 -0
- package/src/metadata/extensions/output/index.js +251 -0
- package/src/metadata/extensions/output/optimizer.js +226 -0
- package/src/metadata/extensions/pictograms.js +85 -0
- package/src/metadata/index.js +178 -0
- package/src/metadata/migrations/2020-01-27.js +78 -0
- package/src/metadata/migrations/2020-02-17-remove-usage-fields.js +45 -0
- package/src/metadata/migrations/2020-02-17-update-pictogram-files.js +79 -0
- package/src/metadata/migrations/README.md +12 -0
- package/src/metadata/storage.js +68 -0
- package/src/metadata/validate.js +54 -0
- package/src/registry.js +158 -0
- package/src/tools.js +18 -0
package/README.md
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# @octaviaflow/icon-build-helpers
|
|
2
|
+
|
|
3
|
+
> Build helpers for the Carbon Design System icon library
|
|
4
|
+
|
|
5
|
+
## Getting started
|
|
6
|
+
|
|
7
|
+
To install `@octaviaflow/icon-build-helpers` in your project, you will need to run
|
|
8
|
+
the following command using [npm](https://www.npmjs.com/):
|
|
9
|
+
|
|
10
|
+
```bash
|
|
11
|
+
npm install -S @octaviaflow/icon-build-helpers
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
If you prefer [Yarn](https://yarnpkg.com/en/), use the following command
|
|
15
|
+
instead:
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
yarn add @octaviaflow/icon-build-helpers
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Usage
|
|
22
|
+
|
|
23
|
+
`@octaviaflow/icon-build-helpers` is a private module in the Carbon Design System
|
|
24
|
+
monorepo. The purpose of this module is to centralize tooling for:
|
|
25
|
+
|
|
26
|
+
- Searching a directory of `.svg` assets and structuring them in terms of size
|
|
27
|
+
and prefixes
|
|
28
|
+
- Custom builders for various libraries, which currently include:
|
|
29
|
+
- Vanilla
|
|
30
|
+
- React
|
|
31
|
+
- Implementing repo status checks in CI around icon metadata files, namely
|
|
32
|
+
`metadata.yml` and `categories.yml`
|
|
33
|
+
|
|
34
|
+
As a result, these file power the generation of the following SVG-based
|
|
35
|
+
projects:
|
|
36
|
+
|
|
37
|
+
- `@octaviaflow/icons`
|
|
38
|
+
- `@octaviaflow/icons-react`
|
|
39
|
+
- `@octaviaflow/pictograms`
|
|
40
|
+
- `@octaviaflow/pictograms-react`
|
|
41
|
+
|
|
42
|
+
## 🙌 Contributing
|
|
43
|
+
|
|
44
|
+
We're always looking for contributors to help us fix bugs, build new features,
|
|
45
|
+
or help us improve the project documentation. If you're interested, definitely
|
|
46
|
+
check out our [Contributing Guide](/.github/CONTRIBUTING.md)! 👀
|
|
47
|
+
|
|
48
|
+
## 📝 License
|
|
49
|
+
|
|
50
|
+
Licensed under the [Apache 2.0 License](/LICENSE).
|
package/package.json
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@octaviaflow/icon-build-helpers",
|
|
3
|
+
"description": "Build helpers for the OctaviaFlow Design System icon library",
|
|
4
|
+
"version": "1.0.0",
|
|
5
|
+
"license": "Apache-2.0",
|
|
6
|
+
"main": "src/index.js",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "https://github.com/octaviaflow-design-system.git",
|
|
10
|
+
"directory": "packages/icon-build-helpers"
|
|
11
|
+
},
|
|
12
|
+
"bugs": "https://github.com/octaviaflow-design-system/issues",
|
|
13
|
+
"keywords": [
|
|
14
|
+
"octaviaflow",
|
|
15
|
+
"icon-build-helpers",
|
|
16
|
+
"components",
|
|
17
|
+
"react"
|
|
18
|
+
],
|
|
19
|
+
"publishConfig": {
|
|
20
|
+
"access": "public"
|
|
21
|
+
},
|
|
22
|
+
"dependencies": {
|
|
23
|
+
"@babel/core": "^7.24.7",
|
|
24
|
+
"@babel/generator": "^7.24.7",
|
|
25
|
+
"@babel/preset-env": "^7.24.7",
|
|
26
|
+
"@babel/preset-react": "^7.24.7",
|
|
27
|
+
"@babel/template": "^7.24.7",
|
|
28
|
+
"@babel/types": "^7.24.7",
|
|
29
|
+
"@hapi/joi": "^17.1.1",
|
|
30
|
+
"@octaviaflow/cli-reporter": "^1.0.0",
|
|
31
|
+
"@octaviaflow/icon-helpers": "^1.0.0",
|
|
32
|
+
"@rollup/plugin-babel": "^6.0.0",
|
|
33
|
+
"@rollup/plugin-replace": "^6.0.0",
|
|
34
|
+
"browserslist-config-octaviaflow": "^1.0.0",
|
|
35
|
+
"change-case": "^4.1.1",
|
|
36
|
+
"core-js": "^3.16.0",
|
|
37
|
+
"fs-extra": "^11.0.0",
|
|
38
|
+
"js-yaml": "^3.12.1",
|
|
39
|
+
"klaw-sync": "^6.0.0",
|
|
40
|
+
"memfs": "^4.0.0",
|
|
41
|
+
"prettier": "^3.3.3",
|
|
42
|
+
"prop-types": "^15.6.2",
|
|
43
|
+
"react": "^19.2.0",
|
|
44
|
+
"react-dom": "^19.2.0",
|
|
45
|
+
"rimraf": "^6.0.0",
|
|
46
|
+
"rollup": "^2.79.1",
|
|
47
|
+
"rollup-plugin-strip-banner": "^3.0.0",
|
|
48
|
+
"svg-parser": "^2.0.4",
|
|
49
|
+
"svgo": "^1.1.1",
|
|
50
|
+
"svgson": "^5.2.1",
|
|
51
|
+
"typescript": "^5.9.3",
|
|
52
|
+
"typescript-config-octaviaflow": "^1.0.0"
|
|
53
|
+
},
|
|
54
|
+
"devDependencies": {}
|
|
55
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright OctaviaFlow
|
|
3
|
+
* Author: Vishal Kumar
|
|
4
|
+
* Created: 11/November/2025
|
|
5
|
+
*
|
|
6
|
+
* This source code is licensed under the Apache-2.0 license found in the
|
|
7
|
+
* LICENSE file in the root directory of this source tree.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
'use strict';
|
|
12
|
+
|
|
13
|
+
const react = require('./react/builder');
|
|
14
|
+
const reactNext = require('./react/next');
|
|
15
|
+
const svg = require('./svg');
|
|
16
|
+
const vanilla = require('./vanilla');
|
|
17
|
+
|
|
18
|
+
const builders = {
|
|
19
|
+
react: {
|
|
20
|
+
run: react,
|
|
21
|
+
},
|
|
22
|
+
reactNext: {
|
|
23
|
+
run: reactNext,
|
|
24
|
+
},
|
|
25
|
+
svg: {
|
|
26
|
+
run: svg,
|
|
27
|
+
},
|
|
28
|
+
vanilla: {
|
|
29
|
+
run: vanilla,
|
|
30
|
+
},
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
module.exports = builders;
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright OctaviaFlow
|
|
3
|
+
* Author: Vishal Kumar
|
|
4
|
+
* Created: 11/November/2025
|
|
5
|
+
*
|
|
6
|
+
* This source code is licensed under the Apache-2.0 license found in the
|
|
7
|
+
* LICENSE file in the root directory of this source tree.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
const path = require('path');
|
|
12
|
+
|
|
13
|
+
// Mirror of: https://github.com/rollup/rollup-plugin-virtual without the \0
|
|
14
|
+
// prefix which noops in a lot of plugins
|
|
15
|
+
const PREFIX = 'virtual:';
|
|
16
|
+
|
|
17
|
+
module.exports = function virtual(modules) {
|
|
18
|
+
const resolvedIds = new Map();
|
|
19
|
+
|
|
20
|
+
Object.keys(modules).forEach((id) => {
|
|
21
|
+
resolvedIds.set(path.resolve(id), modules[id]);
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
return {
|
|
25
|
+
name: 'virtual',
|
|
26
|
+
|
|
27
|
+
resolveId(id, importer) {
|
|
28
|
+
if (id in modules) {
|
|
29
|
+
return PREFIX + id;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
if (importer) {
|
|
33
|
+
if (importer.startsWith(PREFIX)) {
|
|
34
|
+
importer = importer.slice(PREFIX.length);
|
|
35
|
+
}
|
|
36
|
+
const resolved = path.resolve(path.dirname(importer), id);
|
|
37
|
+
if (resolvedIds.has(resolved)) {
|
|
38
|
+
return PREFIX + resolved;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
},
|
|
42
|
+
|
|
43
|
+
load(id) {
|
|
44
|
+
if (id.startsWith(PREFIX)) {
|
|
45
|
+
id = id.slice(PREFIX.length);
|
|
46
|
+
|
|
47
|
+
return id in modules ? modules[id] : resolvedIds.get(id);
|
|
48
|
+
}
|
|
49
|
+
},
|
|
50
|
+
};
|
|
51
|
+
};
|
|
@@ -0,0 +1,313 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright OctaviaFlow
|
|
3
|
+
* Author: Vishal Kumar
|
|
4
|
+
* Created: 11/November/2025
|
|
5
|
+
*
|
|
6
|
+
* This source code is licensed under the Apache-2.0 license found in the
|
|
7
|
+
* LICENSE file in the root directory of this source tree.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
"use strict";
|
|
11
|
+
|
|
12
|
+
const { babel } = require("@rollup/plugin-babel");
|
|
13
|
+
const { camelCase } = require("change-case");
|
|
14
|
+
const fs = require("fs-extra");
|
|
15
|
+
const path = require("path");
|
|
16
|
+
const { rollup } = require("rollup");
|
|
17
|
+
const virtual = require("../plugins/virtual");
|
|
18
|
+
|
|
19
|
+
const BANNER = `/**
|
|
20
|
+
* Copyright IBM Corp. 2019, 2023
|
|
21
|
+
*
|
|
22
|
+
* This source code is licensed under the Apache-2.0 license found in the
|
|
23
|
+
* LICENSE file in the root directory of this source tree.
|
|
24
|
+
*
|
|
25
|
+
* Code generated by @octaviaflow/icon-build-helpers. DO NOT EDIT.
|
|
26
|
+
*/`;
|
|
27
|
+
const external = ["@octaviaflow/icon-helpers", "react", "prop-types"];
|
|
28
|
+
const babelConfig = {
|
|
29
|
+
babelrc: false,
|
|
30
|
+
exclude: /node_modules/,
|
|
31
|
+
presets: [
|
|
32
|
+
[
|
|
33
|
+
"@babel/preset-env",
|
|
34
|
+
{
|
|
35
|
+
targets: {
|
|
36
|
+
browsers: ["extends browserslist-config-octaviaflow"],
|
|
37
|
+
},
|
|
38
|
+
},
|
|
39
|
+
],
|
|
40
|
+
"@babel/preset-react",
|
|
41
|
+
"@babel/preset-typescript",
|
|
42
|
+
],
|
|
43
|
+
plugins: [
|
|
44
|
+
"@babel/plugin-transform-react-constant-elements",
|
|
45
|
+
"babel-plugin-dev-expression",
|
|
46
|
+
],
|
|
47
|
+
babelHelpers: "bundled",
|
|
48
|
+
extensions: [".ts", ".tsx", ".js", ".jsx"],
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
async function builder(metadata, { output }) {
|
|
52
|
+
// Using the metadata, we can build up a list of modules that we want included
|
|
53
|
+
// in the different bundles we ship.
|
|
54
|
+
//
|
|
55
|
+
// For each module, we need to create two ways of consuming it. The first way
|
|
56
|
+
// is as a dedicated module, the second as a single function that we could
|
|
57
|
+
// export in an entrypoint.
|
|
58
|
+
const modules = metadata.icons.flatMap((icon) => {
|
|
59
|
+
return icon.output.map((size) => {
|
|
60
|
+
return {
|
|
61
|
+
source: createIconFlatExport(
|
|
62
|
+
size.moduleName,
|
|
63
|
+
size.descriptor,
|
|
64
|
+
icon.deprecated,
|
|
65
|
+
),
|
|
66
|
+
entrypoint: createIconEntrypoint(
|
|
67
|
+
size.moduleName,
|
|
68
|
+
size.descriptor,
|
|
69
|
+
icon.deprecated,
|
|
70
|
+
),
|
|
71
|
+
filepath: size.filepath,
|
|
72
|
+
moduleName: size.moduleName,
|
|
73
|
+
};
|
|
74
|
+
});
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
// Given the current size of our icons (~5000 modules) we need to split up the
|
|
78
|
+
// entrypoint into chunks. In the past, we tried re-exporting from the source
|
|
79
|
+
// but this ended up causing slowdowns due to module resolution.
|
|
80
|
+
//
|
|
81
|
+
// As a result, we sort our list of modules into buckets and generate
|
|
82
|
+
// entrypoints based on those. Then, the root `index.js` file re-exports from
|
|
83
|
+
// these entrypoints. This is a hybrid approach between a single entrypoint
|
|
84
|
+
// that is too big for most tooling, and a re-export strategy that takes too
|
|
85
|
+
// long due to the number of modules along with the time it takes tooling to
|
|
86
|
+
// process them.
|
|
87
|
+
const BUCKET_SIZE = 250;
|
|
88
|
+
const BUCKET_COUNT = Math.ceil(modules.length / BUCKET_SIZE);
|
|
89
|
+
const buckets = Array(BUCKET_COUNT);
|
|
90
|
+
|
|
91
|
+
for (let i = 0; i < buckets.length; i++) {
|
|
92
|
+
const start = BUCKET_SIZE * i;
|
|
93
|
+
const end = Math.min(start + BUCKET_SIZE, modules.length) - 1;
|
|
94
|
+
const bucket = Array(end - start + 1);
|
|
95
|
+
|
|
96
|
+
for (let j = start; j <= end; j++) {
|
|
97
|
+
bucket[j - start] = modules[j];
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
buckets[i] = bucket;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
const files = {
|
|
104
|
+
"index.ts": `${BANNER}\n\nexport { default as Icon } from './Icon.tsx';`,
|
|
105
|
+
};
|
|
106
|
+
const input = {
|
|
107
|
+
"index.js": "index.ts",
|
|
108
|
+
"Icon.js": "./Icon.tsx",
|
|
109
|
+
};
|
|
110
|
+
for (const m of modules) {
|
|
111
|
+
files[m.filepath] = m.entrypoint;
|
|
112
|
+
input[m.filepath] = m.filepath;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
for (let i = 0; i < buckets.length; i++) {
|
|
116
|
+
const bucket = buckets[i];
|
|
117
|
+
const filename = `__generated__/bucket-${i}.js`;
|
|
118
|
+
|
|
119
|
+
input[filename] = filename;
|
|
120
|
+
files[filename] = `${BANNER}
|
|
121
|
+
|
|
122
|
+
import React from 'react';
|
|
123
|
+
import Icon from './Icon.tsx';
|
|
124
|
+
|
|
125
|
+
const didWarnAboutDeprecation = {};`;
|
|
126
|
+
|
|
127
|
+
for (const m of bucket) {
|
|
128
|
+
files[filename] += `export ${m.source}`;
|
|
129
|
+
files["index.ts"] += `export { ${m.moduleName} } from '${filename}';`;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
const bundle = await rollup({
|
|
134
|
+
input,
|
|
135
|
+
external,
|
|
136
|
+
plugins: [
|
|
137
|
+
virtual({
|
|
138
|
+
"./Icon.tsx": await fs.readFile(
|
|
139
|
+
path.resolve(__dirname, "./components/Icon.tsx"),
|
|
140
|
+
"utf8",
|
|
141
|
+
),
|
|
142
|
+
...files,
|
|
143
|
+
}),
|
|
144
|
+
babel(babelConfig),
|
|
145
|
+
],
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
const bundles = [
|
|
149
|
+
{
|
|
150
|
+
directory: path.join(output, "es"),
|
|
151
|
+
format: "esm",
|
|
152
|
+
},
|
|
153
|
+
{
|
|
154
|
+
directory: path.join(output, "lib"),
|
|
155
|
+
format: "commonjs",
|
|
156
|
+
},
|
|
157
|
+
];
|
|
158
|
+
|
|
159
|
+
for (const { directory, format } of bundles) {
|
|
160
|
+
const outputOptions = {
|
|
161
|
+
dir: directory,
|
|
162
|
+
format,
|
|
163
|
+
entryFileNames: "[name]",
|
|
164
|
+
banner: BANNER,
|
|
165
|
+
exports: "auto",
|
|
166
|
+
};
|
|
167
|
+
|
|
168
|
+
await bundle.write(outputOptions);
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
const umd = await rollup({
|
|
172
|
+
input: "index.ts",
|
|
173
|
+
external,
|
|
174
|
+
plugins: [
|
|
175
|
+
virtual({
|
|
176
|
+
"./Icon.tsx": await fs.readFile(
|
|
177
|
+
path.resolve(__dirname, "./components/Icon.tsx"),
|
|
178
|
+
"utf8",
|
|
179
|
+
),
|
|
180
|
+
...files,
|
|
181
|
+
}),
|
|
182
|
+
babel(babelConfig),
|
|
183
|
+
],
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
await umd.write({
|
|
187
|
+
file: path.join(output, "umd/index.js"),
|
|
188
|
+
format: "umd",
|
|
189
|
+
name: "CarbonIconsReact",
|
|
190
|
+
globals: {
|
|
191
|
+
"@octaviaflow/icon-helpers": "CarbonIconHelpers",
|
|
192
|
+
"prop-types": "PropTypes",
|
|
193
|
+
react: "React",
|
|
194
|
+
},
|
|
195
|
+
});
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* Convert the given node to a JSX string source
|
|
200
|
+
* @param {object} node
|
|
201
|
+
* @returns {string}
|
|
202
|
+
*/
|
|
203
|
+
function convertToJSX(node) {
|
|
204
|
+
const { elem, attrs } = node;
|
|
205
|
+
return `<${elem} ${formatAttributes(attrs)} />`;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
const attributeDenylist = ["data", "aria"];
|
|
209
|
+
|
|
210
|
+
/**
|
|
211
|
+
* Determine if the given attribute should be transformed when being converted
|
|
212
|
+
* to a React prop or if we should pass it through as-is
|
|
213
|
+
* @param {string} attribute
|
|
214
|
+
* @returns {boolean}
|
|
215
|
+
*/
|
|
216
|
+
function shouldTransformAttribute(attribute) {
|
|
217
|
+
return attributeDenylist.every((prefix) => !attribute.startsWith(prefix));
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
/**
|
|
221
|
+
* Serialize a given object of key, value pairs to an JSX-compatible string
|
|
222
|
+
* @param {object} attrs
|
|
223
|
+
* @returns {string}
|
|
224
|
+
*/
|
|
225
|
+
function formatAttributes(attrs) {
|
|
226
|
+
return Object.keys(attrs).reduce((acc, key, index) => {
|
|
227
|
+
const attribute = shouldTransformAttribute(key)
|
|
228
|
+
? `${camelCase(key)}="${attrs[key]}"`
|
|
229
|
+
: `${key}="${attrs[key]}"`;
|
|
230
|
+
|
|
231
|
+
if (index === 0) {
|
|
232
|
+
return attribute;
|
|
233
|
+
}
|
|
234
|
+
return acc + " " + attribute;
|
|
235
|
+
}, "");
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
function createIconFlatExport(moduleName, descriptor, isDeprecated = false) {
|
|
239
|
+
const deprecatedBlock = isDeprecated
|
|
240
|
+
? `
|
|
241
|
+
if (__DEV__) {
|
|
242
|
+
if (!didWarnAboutDeprecation['${moduleName}']) {
|
|
243
|
+
didWarnAboutDeprecation['${moduleName}'] = true;
|
|
244
|
+
console.warn(
|
|
245
|
+
\`The ${moduleName} component has been deprecated and will be \` +
|
|
246
|
+
\`removed in the next major version of @octaviaflow/icons-react.\`
|
|
247
|
+
);
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
`
|
|
251
|
+
: "";
|
|
252
|
+
return createIconSource(moduleName, descriptor, deprecatedBlock);
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
function createIconEntrypoint(moduleName, descriptor, isDeprecated = false) {
|
|
256
|
+
const deprecatedPreamble = isDeprecated
|
|
257
|
+
? "let didWarnAboutDeprecation = false;"
|
|
258
|
+
: "";
|
|
259
|
+
const deprecatedBlock = isDeprecated
|
|
260
|
+
? `
|
|
261
|
+
if (__DEV__) {
|
|
262
|
+
if (!didWarnAboutDeprecation) {
|
|
263
|
+
didWarnAboutDeprecation = true;
|
|
264
|
+
console.warn(
|
|
265
|
+
\`The ${moduleName} component has been deprecated and will be \` +
|
|
266
|
+
\`removed in the next major version of @octaviaflow/icons-react.\`
|
|
267
|
+
);
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
`
|
|
271
|
+
: "";
|
|
272
|
+
const source = createIconSource(moduleName, descriptor, deprecatedBlock);
|
|
273
|
+
return `${BANNER}
|
|
274
|
+
import React from 'react';
|
|
275
|
+
import Icon from './Icon.tsx';
|
|
276
|
+
${deprecatedPreamble}
|
|
277
|
+
${source}
|
|
278
|
+
export default ${moduleName};
|
|
279
|
+
`;
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
/**
|
|
283
|
+
* Generate an icon component, which in our case is the string representation
|
|
284
|
+
* of the component, from a given moduleName and icon descriptor.
|
|
285
|
+
* @param {string} moduleName
|
|
286
|
+
* @param {object} descriptor
|
|
287
|
+
* @param {string} customBlock
|
|
288
|
+
*/
|
|
289
|
+
function createIconSource(moduleName, descriptor, customBlock = "") {
|
|
290
|
+
const { attrs, content } = descriptor;
|
|
291
|
+
const { width, height, viewBox, ...rest } = attrs;
|
|
292
|
+
return `
|
|
293
|
+
const ${moduleName} = /*#__PURE__*/ React.forwardRef(
|
|
294
|
+
function ${moduleName}({ children, ...rest }, ref) {
|
|
295
|
+
${customBlock}
|
|
296
|
+
return (
|
|
297
|
+
<Icon
|
|
298
|
+
width={${width}}
|
|
299
|
+
height={${height}}
|
|
300
|
+
viewBox="${viewBox}"
|
|
301
|
+
${formatAttributes(rest)}
|
|
302
|
+
ref={ref}
|
|
303
|
+
{...rest}>
|
|
304
|
+
${content.map(convertToJSX).join("\n")}
|
|
305
|
+
{children}
|
|
306
|
+
</Icon>
|
|
307
|
+
);
|
|
308
|
+
}
|
|
309
|
+
);
|
|
310
|
+
`;
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
module.exports = builder;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright OctaviaFlow
|
|
3
|
+
* Author: Vishal Kumar
|
|
4
|
+
* Created: 11/November/2025
|
|
5
|
+
*
|
|
6
|
+
* This source code is licensed under the Apache-2.0 license found in the
|
|
7
|
+
* LICENSE file in the root directory of this source tree.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { IconProps } from './Icon';
|
|
11
|
+
|
|
12
|
+
export interface CarbonIconProps extends IconProps {
|
|
13
|
+
size?: number | string;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export type CarbonIconType = React.ForwardRefExoticComponent<
|
|
17
|
+
CarbonIconProps & React.RefAttributes<React.ReactSVGElement>
|
|
18
|
+
>;
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright OctaviaFlow
|
|
3
|
+
* Author: Vishal Kumar
|
|
4
|
+
* Created: 11/November/2025
|
|
5
|
+
*
|
|
6
|
+
* This source code is licensed under the Apache-2.0 license found in the
|
|
7
|
+
* LICENSE file in the root directory of this source tree.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { getAttributes } from '@octaviaflow/icon-helpers';
|
|
11
|
+
import PropTypes from 'prop-types';
|
|
12
|
+
import React from 'react';
|
|
13
|
+
|
|
14
|
+
export interface IconProps
|
|
15
|
+
extends Omit<React.SVGProps<React.ReactSVGElement>, 'ref' | 'tabIndex'> {
|
|
16
|
+
/**
|
|
17
|
+
* @see React.SVGAttributes.tabIndex
|
|
18
|
+
* @todo remove support for string in v12
|
|
19
|
+
*/
|
|
20
|
+
tabIndex?: string | number | undefined;
|
|
21
|
+
|
|
22
|
+
title?: string | undefined;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const Icon = React.forwardRef(function Icon(
|
|
26
|
+
{
|
|
27
|
+
className,
|
|
28
|
+
children,
|
|
29
|
+
tabIndex,
|
|
30
|
+
xmlns = 'http://www.w3.org/2000/svg',
|
|
31
|
+
preserveAspectRatio = 'xMidYMid meet',
|
|
32
|
+
...rest
|
|
33
|
+
}: IconProps,
|
|
34
|
+
ref: React.ForwardedRef<React.ReactSVGElement>
|
|
35
|
+
) {
|
|
36
|
+
const { tabindex, ...attrs } = getAttributes({
|
|
37
|
+
...rest,
|
|
38
|
+
tabindex: tabIndex,
|
|
39
|
+
});
|
|
40
|
+
const props: React.SVGProps<React.ReactSVGElement> = attrs;
|
|
41
|
+
|
|
42
|
+
if (className) {
|
|
43
|
+
props.className = className;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
if (tabindex !== undefined && tabindex !== null) {
|
|
47
|
+
if (typeof tabindex === 'number') {
|
|
48
|
+
props.tabIndex = tabindex;
|
|
49
|
+
} else {
|
|
50
|
+
props.tabIndex = Number(tabIndex);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
if (ref) {
|
|
55
|
+
props.ref = ref;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
if (xmlns) {
|
|
59
|
+
props.xmlns = xmlns;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
if (preserveAspectRatio) {
|
|
63
|
+
props.preserveAspectRatio = preserveAspectRatio;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
return React.createElement('svg', props, children);
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
Icon.displayName = 'Icon';
|
|
70
|
+
Icon.propTypes = {
|
|
71
|
+
'aria-hidden': PropTypes.oneOfType([
|
|
72
|
+
PropTypes.bool,
|
|
73
|
+
PropTypes.oneOf<'true' | 'false'>(['true', 'false']),
|
|
74
|
+
]),
|
|
75
|
+
'aria-label': PropTypes.string,
|
|
76
|
+
'aria-labelledby': PropTypes.string,
|
|
77
|
+
children: PropTypes.node,
|
|
78
|
+
className: PropTypes.string,
|
|
79
|
+
height: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
|
|
80
|
+
preserveAspectRatio: PropTypes.string,
|
|
81
|
+
tabIndex: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
|
|
82
|
+
viewBox: PropTypes.string,
|
|
83
|
+
width: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
|
|
84
|
+
xmlns: PropTypes.string,
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
export default Icon;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright OctaviaFlow
|
|
3
|
+
* Author: Vishal Kumar
|
|
4
|
+
* Created: 11/November/2025
|
|
5
|
+
*
|
|
6
|
+
* This source code is licensed under the Apache-2.0 license found in the
|
|
7
|
+
* LICENSE file in the root directory of this source tree.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
"use strict";
|
|
11
|
+
|
|
12
|
+
const babelConfig = {
|
|
13
|
+
babelrc: false,
|
|
14
|
+
exclude: /node_modules/,
|
|
15
|
+
presets: [
|
|
16
|
+
[
|
|
17
|
+
"@babel/preset-env",
|
|
18
|
+
{
|
|
19
|
+
targets: {
|
|
20
|
+
browsers: ["extends browserslist-config-octaviaflow"],
|
|
21
|
+
},
|
|
22
|
+
},
|
|
23
|
+
],
|
|
24
|
+
"@babel/preset-react",
|
|
25
|
+
"@babel/preset-typescript",
|
|
26
|
+
],
|
|
27
|
+
plugins: [
|
|
28
|
+
"@babel/plugin-transform-react-constant-elements",
|
|
29
|
+
"babel-plugin-dev-expression",
|
|
30
|
+
],
|
|
31
|
+
babelHelpers: "bundled",
|
|
32
|
+
extensions: [".ts", ".tsx", ".js", ".jsx"],
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
module.exports = {
|
|
36
|
+
babelConfig,
|
|
37
|
+
};
|