Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/cold-drinks-breathe.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@cube-dev/ui-kit': patch
---

Add DatabaseIcon.
1 change: 1 addition & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -107,4 +107,5 @@ module.exports = /** @type {import('eslint').Linter.Config} */ ({
},
},
],
ignorePatterns: ['*.js'],
});
19 changes: 19 additions & 0 deletions src/icons/DatabaseIcon.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { wrapIcon } from './wrap-icon';

export const DatabaseIcon = wrapIcon(
'DatabaseIcon',
<svg
viewBox="0 0 16 16"
xmlns="http://www.w3.org/2000/svg"
width="16"
height="16"
fill="none"
>
<path
fill="currentColor"
fillRule="evenodd"
d="M3.75 2.085c-1.111.505-1.49 1.07-1.49 1.462s.379.957 1.49 1.462c1.055.478 2.556.79 4.25.79s3.195-.312 4.25-.79c1.111-.505 1.49-1.07 1.49-1.462s-.379-.957-1.49-1.462c-1.055-.478-2.556-.791-4.25-.791s-3.195.313-4.25.791M3.212.908C4.471.336 6.164 0 8 0s3.53.336 4.789.908c1.2.545 2.252 1.43 2.252 2.639l-.003.105q.003.03.003.059v8.578c0 1.236-1.024 2.167-2.24 2.75C11.54 15.644 9.841 16 8 16c-1.84 0-3.539-.356-4.801-.961-1.216-.583-2.24-1.514-2.24-2.75V3.711l.003-.06-.003-.104c0-1.21 1.051-2.094 2.252-2.64M2.26 5.65v2.352c.002.446.405 1.04 1.502 1.562 1.051.5 2.55.827 4.239.827s3.188-.327 4.239-.827c1.098-.522 1.501-1.117 1.502-1.563V5.65a6 6 0 0 1-.952.536c-1.26.571-2.953.908-4.789.908s-3.53-.337-4.789-.908a6 6 0 0 1-.952-.536m11.482 4.528a6 6 0 0 1-.942.554c-1.262.6-2.96.953-4.799.953s-3.537-.353-4.8-.953a6 6 0 0 1-.94-.554v2.11c0 .457.406 1.059 1.503 1.585 1.05.504 2.548.833 4.237.833s3.186-.33 4.237-.833c1.097-.526 1.504-1.127 1.504-1.584z"
clipRule="evenodd"
/>
</svg>,
);
144 changes: 144 additions & 0 deletions src/icons/add-new-icon.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
#!/usr/bin/env node

const { execSync } = require('child_process');
const fs = require('fs');
const path = require('path');
const prettier = require('prettier');

(async function main() {
// Run svgo on all svg files in this folder
try {
console.log('Optimizing SVGs with svgo...');
execSync('svgo *.svg', { stdio: 'inherit' });
} catch (err) {
console.error('Error running svgo:', err);
process.exit(1);
}

// Get all .svg files in the current directory
const allFiles = fs.readdirSync(process.cwd());
const svgFiles = allFiles.filter((file) => file.endsWith('.svg'));

for (const svgFile of svgFiles) {
const name = path.basename(svgFile, '.svg');
const tsxFileName = `${name}Icon.tsx`;

// Read the original SVG file
let svgContent = fs.readFileSync(svgFile, 'utf8');

// Replace '#43436B' with 'currentColor'
svgContent = svgContent.replace(/#43436B/g, 'currentColor');

// Ensure the <svg> tag has a viewBox attribute; if not, add one.
const svgTagMatch = svgContent.match(/<svg\b([^>]*)>/);
if (svgTagMatch) {
const svgTag = svgTagMatch[0];
if (!/viewBox=/.test(svgTag)) {
// Insert viewBox attribute right after <svg
const newSvgTag = svgTag.replace('<svg', '<svg viewBox="0 0 16 16"');
svgContent = svgContent.replace(svgTag, newSvgTag);
}
} else {
console.warn(`No <svg> tag found in ${svgFile}. Skipping file.`);
continue;
}

// Convert dash-case attributes to camelCase (e.g. fill-rule -> fillRule)
svgContent = svgContent.replace(
/(\s+)([a-z]+-[a-z0-9-]+)(\s*=)/gi,
(match, pre, attrName, post) => {
const camelAttr = attrName.replace(/-([a-z])/g, (_, letter) =>
letter.toUpperCase(),
);
return pre + camelAttr + post;
},
);

// Build the TSX content using the template.
const tsxTemplate = `
import { wrapIcon } from './wrap-icon';

export const ${name}Icon = wrapIcon(
'${name}Icon',
(
${svgContent.trim()}
),
);
`;

// Format the content with local Prettier configuration (using babel-ts parser)
let formattedTSX;
try {
formattedTSX = await prettier.format(tsxTemplate, { parser: 'babel-ts' });
} catch (err) {
console.error(`Error formatting ${tsxFileName} with Prettier:`, err);
formattedTSX = tsxTemplate; // Fallback to unformatted version
}

// Write the new TSX file
fs.writeFileSync(tsxFileName, formattedTSX, 'utf8');
console.log(`Created ${tsxFileName}`);
}

// Update index.ts to add new exports and sort them
const indexPath = path.join(process.cwd(), 'index.ts');
if (!fs.existsSync(indexPath)) {
console.error('index.ts not found in the current directory.');
process.exit(1);
}

let indexContent = fs.readFileSync(indexPath, 'utf8');
const lines = indexContent.split('\n');

// Locate the line with "export { wrapIcon } from './wrap-icon';"
const wrapIconLineIndex = lines.findIndex((line) =>
line.includes("export { wrapIcon } from './wrap-icon';"),
);
if (wrapIconLineIndex === -1) {
console.error("Couldn't find the export { wrapIcon } line in index.ts.");
process.exit(1);
}

// Get the export block above the wrapIcon export
let headerLines = lines.slice(0, wrapIconLineIndex);
const footerLines = lines.slice(wrapIconLineIndex);

// Ensure that for each SVG file there is an export line
svgFiles.forEach((svgFile) => {
const name = path.basename(svgFile, '.svg');
const exportLine = `export { ${name}Icon } from './${name}Icon';`;
// Add if not already present (ignoring extra whitespace)
if (!headerLines.some((line) => line.trim() === exportLine)) {
headerLines.push(exportLine);
}
});

// Remove empty lines and sort the export lines alphabetically
headerLines = headerLines
.filter((line) => line.trim() !== '')
.sort((a, b) => a.localeCompare(b));

// Reassemble the file content
const newIndexContent = [...headerLines, ...footerLines].join('\n');

// Format the updated index.ts with Prettier
let formattedIndex;
try {
formattedIndex = await prettier.format(newIndexContent, {
parser: 'babel-ts',
});
} catch (err) {
console.error('Error formatting index.ts with Prettier:', err);
formattedIndex = newIndexContent;
}

// Write the updated index.ts
fs.writeFileSync(indexPath, formattedIndex, 'utf8');
console.log('Updated index.ts');

// Remove all initial SVG files
for (const svgFile of svgFiles) {
fs.unlinkSync(svgFile);
console.log(`Removed ${svgFile}`);
}
})();
1 change: 1 addition & 0 deletions src/icons/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ export { CountIcon } from './CountIcon';
export { CubeIcon } from './CubeIcon';
export { DangerIcon } from './DangerIcon';
export { DashboardIcon } from './DashboardIcon';
export { DatabaseIcon } from './DatabaseIcon';
export { DirectionIcon } from './DirectionIcon';
export { DonutIcon } from './DonutIcon';
export { DownIcon } from './DownIcon';
Expand Down
Loading