Split variants (#368)
1
.eslintignore
Normal file
|
@ -0,0 +1 @@
|
||||||
|
dist/
|
|
@ -10,6 +10,38 @@ module.exports = {
|
||||||
sourceType: 'module',
|
sourceType: 'module',
|
||||||
},
|
},
|
||||||
rules: {
|
rules: {
|
||||||
|
'padding-line-between-statements': [
|
||||||
|
'error',
|
||||||
|
{
|
||||||
|
blankLine: 'always',
|
||||||
|
prev: [
|
||||||
|
'block',
|
||||||
|
'block-like',
|
||||||
|
'class',
|
||||||
|
'export',
|
||||||
|
'import',
|
||||||
|
'multiline-block-like',
|
||||||
|
'multiline-expression',
|
||||||
|
],
|
||||||
|
next: '*',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
blankLine: 'always',
|
||||||
|
prev: ['const', 'let'],
|
||||||
|
next: ['block', 'block-like', 'class', 'export', 'import'],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
blankLine: 'always',
|
||||||
|
prev: '*',
|
||||||
|
next: ['multiline-block-like', 'multiline-expression', 'return'],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
blankLine: 'any',
|
||||||
|
prev: ['export', 'import'],
|
||||||
|
next: ['export', 'import'],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
|
||||||
'prettier/prettier': ['error'],
|
'prettier/prettier': ['error'],
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
4
.github/workflows/build.yaml
vendored
|
@ -18,8 +18,8 @@ jobs:
|
||||||
- name: Setup
|
- name: Setup
|
||||||
uses: ./.github/actions/setup
|
uses: ./.github/actions/setup
|
||||||
|
|
||||||
- name: Build meta-data and css
|
- name: Build CSS
|
||||||
run: pnpm run build meta-data css
|
run: pnpm run build css
|
||||||
|
|
||||||
- name: Commit changes
|
- name: Commit changes
|
||||||
uses: stefanzweifel/git-auto-commit-action@v4
|
uses: stefanzweifel/git-auto-commit-action@v4
|
||||||
|
|
11
.gitignore
vendored
|
@ -5,11 +5,6 @@ dist/
|
||||||
|
|
||||||
packages/iconoir-flutter/lib/
|
packages/iconoir-flutter/lib/
|
||||||
|
|
||||||
packages/iconoir-react/src/
|
packages/iconoir-vue/src/*
|
||||||
!packages/iconoir-react/src/IconoirContext.tsx
|
!packages/iconoir-vue/src/IconoirProvider.vue
|
||||||
!packages/iconoir-react/src/server/IconoirContext.tsx
|
!packages/iconoir-vue/src/providerKey.ts
|
||||||
|
|
||||||
packages/iconoir-react-native/src/
|
|
||||||
!packages/iconoir-react-native/src/IconoirContext.tsx
|
|
||||||
|
|
||||||
packages/iconoir-vue/src/
|
|
||||||
|
|
1
.prettierignore
Normal file
|
@ -0,0 +1 @@
|
||||||
|
dist/
|
|
@ -1,3 +1,4 @@
|
||||||
{
|
{
|
||||||
"singleQuote": true
|
"singleQuote": true,
|
||||||
|
"quoteProps": "consistent"
|
||||||
}
|
}
|
||||||
|
|
663
bin/build.js
|
@ -1,663 +0,0 @@
|
||||||
import { execa } from 'execa';
|
|
||||||
import { generateTemplateFilesBatch } from 'generate-template-files';
|
|
||||||
import { Listr } from 'listr2';
|
|
||||||
import { existsSync, promises as fs, readFileSync } from 'node:fs';
|
|
||||||
import os from 'node:os';
|
|
||||||
import path, { basename, dirname } from 'node:path';
|
|
||||||
import { fileURLToPath } from 'node:url';
|
|
||||||
import { flutterIncompatibleNames, incompatibleNames } from '../constants.js';
|
|
||||||
import { buildVueIcons } from './buildVue.js';
|
|
||||||
|
|
||||||
// Paths
|
|
||||||
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
||||||
const rootDir = path.join(__dirname, '..');
|
|
||||||
const iconoirIconsDir = path.join(rootDir, 'icons');
|
|
||||||
const ignoreCleanFilenames = ['IconoirContext.tsx', 'server'];
|
|
||||||
|
|
||||||
// Targets for building icons
|
|
||||||
const targets = {
|
|
||||||
'meta-data': { path: 'meta-data.json' },
|
|
||||||
css: { path: 'css/iconoir.css' },
|
|
||||||
'iconoir-flutter': { flutter: true, path: 'packages/iconoir-flutter' },
|
|
||||||
'iconoir-react': { react: true, path: 'packages/iconoir-react' },
|
|
||||||
'iconoir-react-native': {
|
|
||||||
react: true,
|
|
||||||
path: 'packages/iconoir-react-native',
|
|
||||||
},
|
|
||||||
'iconoir-vue': {
|
|
||||||
vue: true,
|
|
||||||
path: 'packages/iconoir-vue',
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
// Get targets from command line arguments
|
|
||||||
// (build all targets if no arguments)
|
|
||||||
const args = process.argv.slice(2);
|
|
||||||
const cliTargets = [];
|
|
||||||
args.forEach((target) => {
|
|
||||||
if (target in targets) {
|
|
||||||
cliTargets.push(target);
|
|
||||||
} else {
|
|
||||||
console.error(`Target '${target}' doesn't exist!\n\nPossible targets are:`);
|
|
||||||
for (const [targetName] of Object.entries(targets)) {
|
|
||||||
console.log(`- ${targetName}`);
|
|
||||||
}
|
|
||||||
process.exit(1);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Build tasks
|
|
||||||
const tasks = new Listr(
|
|
||||||
[
|
|
||||||
{
|
|
||||||
title: 'Fetching icons',
|
|
||||||
task: async (ctx) => {
|
|
||||||
const iconFiles = await fs.readdir(iconoirIconsDir);
|
|
||||||
ctx.iconoirIconsFiles = iconFiles.filter((file) =>
|
|
||||||
file.endsWith('.svg'),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: 'Building targets',
|
|
||||||
skip: (ctx) => !ctx.iconoirIconsFiles,
|
|
||||||
task: (_, task) =>
|
|
||||||
task.newListr(
|
|
||||||
[
|
|
||||||
{
|
|
||||||
title: 'Building meta-data file',
|
|
||||||
enabled: () =>
|
|
||||||
cliTargets.length === 0 || cliTargets.includes('meta-data'),
|
|
||||||
task: async (ctx) => {
|
|
||||||
await fs.writeFile(
|
|
||||||
path.join(rootDir, targets['meta-data'].path),
|
|
||||||
JSON.stringify({ icons: ctx.iconoirIconsFiles }),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: 'Building CSS file',
|
|
||||||
enabled: () =>
|
|
||||||
cliTargets.length === 0 || cliTargets.includes('css'),
|
|
||||||
task: async (ctx) => {
|
|
||||||
const content = [
|
|
||||||
(
|
|
||||||
await fs.readFile(
|
|
||||||
path.join(__dirname, 'header.css'),
|
|
||||||
'utf8',
|
|
||||||
)
|
|
||||||
).replace('[YEAR]', new Date().getFullYear()),
|
|
||||||
];
|
|
||||||
ctx.iconoirIconsFiles.forEach((file) => {
|
|
||||||
const fileContents = readFileSync(
|
|
||||||
path.join(__dirname, '../icons/', file),
|
|
||||||
)
|
|
||||||
.toString()
|
|
||||||
.replace(/\n/g, '')
|
|
||||||
.replace(/(width|height)="[0-9]+px"/g, '')
|
|
||||||
.replace(/[ ]+/g, ' ');
|
|
||||||
content.push(
|
|
||||||
`.iconoir-${
|
|
||||||
path.parse(file).name
|
|
||||||
}::before{mask-image:url('data:image/svg+xml;charset=utf-8,${fileContents}');-webkit-mask-image:url('data:image/svg+xml;charset=utf-8,${fileContents}');}`,
|
|
||||||
);
|
|
||||||
});
|
|
||||||
await fs.writeFile(
|
|
||||||
path.join(rootDir, targets.css.path),
|
|
||||||
content,
|
|
||||||
);
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: 'Building React libraries',
|
|
||||||
enabled: () =>
|
|
||||||
cliTargets.length === 0 ||
|
|
||||||
cliTargets.filter((cliTarget) => targets[cliTarget]?.react)
|
|
||||||
.length > 0,
|
|
||||||
task: (_, task) =>
|
|
||||||
task.newListr(
|
|
||||||
[
|
|
||||||
{
|
|
||||||
title: 'Creating temporary directory',
|
|
||||||
task: async (ctx) => {
|
|
||||||
try {
|
|
||||||
ctx.tmpDir = await fs.mkdtemp(
|
|
||||||
path.join(os.tmpdir(), 'iconoir-'),
|
|
||||||
);
|
|
||||||
} catch (err) {
|
|
||||||
ctx.skip = true;
|
|
||||||
throw new Error(err.message);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title:
|
|
||||||
'Copying icon files to temporary directory, while renaming icons with incompatible names',
|
|
||||||
skip: (ctx) => ctx.skip,
|
|
||||||
task: async (ctx) => {
|
|
||||||
try {
|
|
||||||
const promises = ctx.iconoirIconsFiles.map((file) => {
|
|
||||||
const srcFilePath = path.join(
|
|
||||||
iconoirIconsDir,
|
|
||||||
file,
|
|
||||||
);
|
|
||||||
const iconName = file.split('.')[0];
|
|
||||||
const dstFileName =
|
|
||||||
iconName in incompatibleNames
|
|
||||||
? incompatibleNames[iconName]
|
|
||||||
: iconName;
|
|
||||||
const dstFilePath = path.join(
|
|
||||||
ctx.tmpDir,
|
|
||||||
`${dstFileName}.svg`,
|
|
||||||
);
|
|
||||||
|
|
||||||
return fs.copyFile(srcFilePath, dstFilePath);
|
|
||||||
});
|
|
||||||
return Promise.all(promises).catch((err) => {
|
|
||||||
ctx.skip = true;
|
|
||||||
throw new Error(err.message);
|
|
||||||
});
|
|
||||||
} catch (err) {
|
|
||||||
ctx.skip = true;
|
|
||||||
throw new Error(err.message);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
skip: (ctx) => ctx.skip,
|
|
||||||
task: (_, task) => {
|
|
||||||
const targetsToBuild =
|
|
||||||
cliTargets.length > 0
|
|
||||||
? cliTargets.filter(
|
|
||||||
(cliTarget) => targets[cliTarget]?.react,
|
|
||||||
)
|
|
||||||
: Object.keys(targets).filter(
|
|
||||||
(target) => targets[target].react,
|
|
||||||
);
|
|
||||||
const tasks = targetsToBuild.map((target) => {
|
|
||||||
const builtIconsDir = path.join(
|
|
||||||
rootDir,
|
|
||||||
targets[target].path,
|
|
||||||
'src',
|
|
||||||
);
|
|
||||||
return {
|
|
||||||
title: `Building ${target}`,
|
|
||||||
task: (_, task) =>
|
|
||||||
task.newListr(
|
|
||||||
[
|
|
||||||
{
|
|
||||||
title: 'Cleaning target directory',
|
|
||||||
task: async (ctx) => {
|
|
||||||
try {
|
|
||||||
const files =
|
|
||||||
await fs.readdir(builtIconsDir);
|
|
||||||
const serverFiles = existsSync(
|
|
||||||
path.join(builtIconsDir, 'server'),
|
|
||||||
)
|
|
||||||
? (
|
|
||||||
await fs.readdir(
|
|
||||||
path.join(
|
|
||||||
builtIconsDir,
|
|
||||||
'server',
|
|
||||||
),
|
|
||||||
)
|
|
||||||
).map((file) => `server/${file}`)
|
|
||||||
: [];
|
|
||||||
const promises = [
|
|
||||||
...files,
|
|
||||||
...serverFiles,
|
|
||||||
]
|
|
||||||
.filter(
|
|
||||||
(file) =>
|
|
||||||
!ignoreCleanFilenames.includes(
|
|
||||||
path.basename(file),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
.map((file) => {
|
|
||||||
return fs.unlink(
|
|
||||||
path.join(builtIconsDir, file),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
return Promise.all(promises).catch(
|
|
||||||
(err) => {
|
|
||||||
ctx[target] = { skip: true };
|
|
||||||
throw new Error(err.message);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
} catch (err) {
|
|
||||||
ctx[target] = { skip: true };
|
|
||||||
throw new Error(err.message);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: 'Building icon files',
|
|
||||||
skip: (ctx) => ctx[target]?.skip,
|
|
||||||
task: async (ctx) => {
|
|
||||||
try {
|
|
||||||
await execa(
|
|
||||||
'svgr',
|
|
||||||
[
|
|
||||||
'--config-file',
|
|
||||||
path.join(
|
|
||||||
targets[target].path,
|
|
||||||
'.svgrrc.json',
|
|
||||||
),
|
|
||||||
'--out-dir',
|
|
||||||
builtIconsDir,
|
|
||||||
'--template',
|
|
||||||
'bin/templates/icon-template.cjs',
|
|
||||||
'--index-template',
|
|
||||||
'bin/templates/index-template.cjs',
|
|
||||||
'--',
|
|
||||||
ctx.tmpDir,
|
|
||||||
],
|
|
||||||
{ preferLocal: true },
|
|
||||||
);
|
|
||||||
} catch (err) {
|
|
||||||
throw new Error(err.message);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
|
||||||
...(target === 'iconoir-react'
|
|
||||||
? [
|
|
||||||
{
|
|
||||||
title:
|
|
||||||
'Building icon files (server components)',
|
|
||||||
skip: (ctx) => ctx[target]?.skip,
|
|
||||||
task: async (ctx) => {
|
|
||||||
try {
|
|
||||||
await execa(
|
|
||||||
'svgr',
|
|
||||||
[
|
|
||||||
'--config-file',
|
|
||||||
path.join(
|
|
||||||
targets[target].path,
|
|
||||||
'.svgrrc.json',
|
|
||||||
),
|
|
||||||
'--out-dir',
|
|
||||||
path.join(
|
|
||||||
builtIconsDir,
|
|
||||||
'server',
|
|
||||||
),
|
|
||||||
'--template',
|
|
||||||
'bin/templates/icon-template-server-component.cjs',
|
|
||||||
'--index-template',
|
|
||||||
'bin/templates/index-template.cjs',
|
|
||||||
'--',
|
|
||||||
ctx.tmpDir,
|
|
||||||
],
|
|
||||||
{ preferLocal: true },
|
|
||||||
);
|
|
||||||
} catch (err) {
|
|
||||||
throw new Error(err.message);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
|
||||||
]
|
|
||||||
: []),
|
|
||||||
],
|
|
||||||
{ concurrent: false, exitOnError: false },
|
|
||||||
),
|
|
||||||
};
|
|
||||||
});
|
|
||||||
return task.newListr(tasks, {
|
|
||||||
concurrent: true,
|
|
||||||
rendererOptions: { collapseSubtasks: false },
|
|
||||||
});
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
{ concurrent: false },
|
|
||||||
),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: 'Building Vue library',
|
|
||||||
enabled: () =>
|
|
||||||
cliTargets.length === 0 ||
|
|
||||||
cliTargets.filter((cliTarget) => targets[cliTarget]?.vue)
|
|
||||||
.length > 0,
|
|
||||||
task: (_, task) =>
|
|
||||||
task.newListr(
|
|
||||||
[
|
|
||||||
{
|
|
||||||
title: 'Creating temporary directory',
|
|
||||||
task: async (ctx) => {
|
|
||||||
try {
|
|
||||||
ctx.tmpDir = await fs.mkdtemp(
|
|
||||||
path.join(os.tmpdir(), 'iconoir-'),
|
|
||||||
);
|
|
||||||
} catch (err) {
|
|
||||||
ctx.skip = true;
|
|
||||||
throw new Error(err.message);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title:
|
|
||||||
'Copying icon files to temporary directory, while renaming icons with incompatible names',
|
|
||||||
skip: (ctx) => ctx.skip,
|
|
||||||
task: async (ctx) => {
|
|
||||||
try {
|
|
||||||
const promises = ctx.iconoirIconsFiles.map((file) => {
|
|
||||||
const srcFilePath = path.join(
|
|
||||||
iconoirIconsDir,
|
|
||||||
file,
|
|
||||||
);
|
|
||||||
const iconName = file.split('.')[0];
|
|
||||||
const dstFileName =
|
|
||||||
iconName in incompatibleNames
|
|
||||||
? incompatibleNames[iconName]
|
|
||||||
: iconName;
|
|
||||||
const dstFilePath = path.join(
|
|
||||||
ctx.tmpDir,
|
|
||||||
`${dstFileName}.svg`,
|
|
||||||
);
|
|
||||||
|
|
||||||
return fs.copyFile(srcFilePath, dstFilePath);
|
|
||||||
});
|
|
||||||
return Promise.all(promises).catch((err) => {
|
|
||||||
ctx.skip = true;
|
|
||||||
throw new Error(err.message);
|
|
||||||
});
|
|
||||||
} catch (err) {
|
|
||||||
ctx.skip = true;
|
|
||||||
throw new Error(err.message);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
skip: (ctx) => ctx.skip,
|
|
||||||
task: (_, task) => {
|
|
||||||
const targetsToBuild =
|
|
||||||
cliTargets.length > 0
|
|
||||||
? cliTargets.filter(
|
|
||||||
(cliTarget) => targets[cliTarget]?.vue,
|
|
||||||
)
|
|
||||||
: Object.keys(targets).filter(
|
|
||||||
(target) => targets[target].vue,
|
|
||||||
);
|
|
||||||
const tasks = targetsToBuild.map((target) => {
|
|
||||||
const builtIconsDir = path.join(
|
|
||||||
rootDir,
|
|
||||||
targets[target].path,
|
|
||||||
'src',
|
|
||||||
);
|
|
||||||
return {
|
|
||||||
title: `Building ${target}`,
|
|
||||||
task: (_, task) =>
|
|
||||||
task.newListr(
|
|
||||||
[
|
|
||||||
{
|
|
||||||
title: 'Create target directory',
|
|
||||||
task: async (ctx) => {
|
|
||||||
try {
|
|
||||||
await fs.mkdir(builtIconsDir, {
|
|
||||||
recursive: true,
|
|
||||||
});
|
|
||||||
} catch (err) {
|
|
||||||
ctx[target] = { skip: true };
|
|
||||||
throw new Error(err.message);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: 'Building icon files',
|
|
||||||
skip: (ctx) => ctx[target]?.skip,
|
|
||||||
task: async (ctx) => {
|
|
||||||
try {
|
|
||||||
await buildVueIcons(ctx.tmpDir, {
|
|
||||||
outDir: builtIconsDir,
|
|
||||||
});
|
|
||||||
} catch (err) {
|
|
||||||
throw new Error(err.message);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
{ concurrent: false, exitOnError: false },
|
|
||||||
),
|
|
||||||
};
|
|
||||||
});
|
|
||||||
return task.newListr(tasks, {
|
|
||||||
concurrent: true,
|
|
||||||
rendererOptions: { collapseSubtasks: false },
|
|
||||||
});
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
{ concurrent: false },
|
|
||||||
),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: 'Building Flutter libraries',
|
|
||||||
enabled: () =>
|
|
||||||
cliTargets.length === 0 ||
|
|
||||||
cliTargets.filter((cliTarget) => targets[cliTarget]?.flutter)
|
|
||||||
.length > 0,
|
|
||||||
task: (_, task) =>
|
|
||||||
task.newListr(
|
|
||||||
[
|
|
||||||
{
|
|
||||||
title: 'Creating temporary directory',
|
|
||||||
task: async (ctx) => {
|
|
||||||
try {
|
|
||||||
ctx.flutterTmpDir = await fs.mkdtemp(
|
|
||||||
path.join(os.tmpdir(), 'iconoir-'),
|
|
||||||
);
|
|
||||||
} catch (err) {
|
|
||||||
ctx.skip = true;
|
|
||||||
throw new Error(err.message);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title:
|
|
||||||
'Copying icon files to temporary directory, while renaming icons with incompatible names',
|
|
||||||
skip: (ctx) => ctx.skip,
|
|
||||||
task: async (ctx) => {
|
|
||||||
try {
|
|
||||||
const promises = ctx.iconoirIconsFiles.map((file) => {
|
|
||||||
const srcFilePath = path.join(
|
|
||||||
iconoirIconsDir,
|
|
||||||
file,
|
|
||||||
);
|
|
||||||
const iconName = file.split('.')[0];
|
|
||||||
const dstFileName =
|
|
||||||
iconName in flutterIncompatibleNames
|
|
||||||
? flutterIncompatibleNames[iconName]
|
|
||||||
: iconName;
|
|
||||||
const dstFilePath = path.join(
|
|
||||||
ctx.flutterTmpDir,
|
|
||||||
`${dstFileName}.svg`,
|
|
||||||
);
|
|
||||||
|
|
||||||
ctx.dstFilePaths = [
|
|
||||||
...(ctx.dstFilePaths ?? []),
|
|
||||||
dstFilePath,
|
|
||||||
];
|
|
||||||
|
|
||||||
return fs.copyFile(srcFilePath, dstFilePath);
|
|
||||||
});
|
|
||||||
return Promise.all(promises).catch((err) => {
|
|
||||||
ctx.skip = true;
|
|
||||||
throw new Error(err.message);
|
|
||||||
});
|
|
||||||
} catch (err) {
|
|
||||||
ctx.skip = true;
|
|
||||||
throw new Error(err.message);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
skip: (ctx) => ctx.skip,
|
|
||||||
task: (_, task) => {
|
|
||||||
const targetsToBuild =
|
|
||||||
cliTargets.length > 0
|
|
||||||
? cliTargets.filter(
|
|
||||||
(cliTarget) => targets[cliTarget]?.flutter,
|
|
||||||
)
|
|
||||||
: Object.keys(targets).filter(
|
|
||||||
(target) => targets[target].flutter,
|
|
||||||
);
|
|
||||||
const tasks = targetsToBuild.map((target) => {
|
|
||||||
const builtIconsDir = path.join(
|
|
||||||
rootDir,
|
|
||||||
targets[target].path,
|
|
||||||
'lib',
|
|
||||||
);
|
|
||||||
return {
|
|
||||||
title: `Building ${target}`,
|
|
||||||
task: (_, task) =>
|
|
||||||
task.newListr(
|
|
||||||
[
|
|
||||||
{
|
|
||||||
title: 'Create target directory',
|
|
||||||
task: async (ctx) => {
|
|
||||||
try {
|
|
||||||
await fs.mkdir(builtIconsDir, {
|
|
||||||
recursive: true,
|
|
||||||
});
|
|
||||||
} catch (err) {
|
|
||||||
ctx[target] = { skip: true };
|
|
||||||
throw new Error(err.message);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: 'Create entry file',
|
|
||||||
task: async () => {
|
|
||||||
await fs.writeFile(
|
|
||||||
path.join(
|
|
||||||
builtIconsDir,
|
|
||||||
'iconoir_flutter.dart',
|
|
||||||
),
|
|
||||||
'library iconoir_flutter;\n\n',
|
|
||||||
);
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: 'Building icon files',
|
|
||||||
skip: (ctx) => ctx[target]?.skip,
|
|
||||||
task: async (ctx) => {
|
|
||||||
const finalFileNames = [];
|
|
||||||
try {
|
|
||||||
await Promise.all(
|
|
||||||
ctx.dstFilePaths.map(async (file) => {
|
|
||||||
const svgfilename =
|
|
||||||
path.parse(file).name;
|
|
||||||
// Prefix with Svg if icon name starts with a number
|
|
||||||
const iconname = `${
|
|
||||||
/^\d/.test(svgfilename)
|
|
||||||
? 'Svg'
|
|
||||||
: ''
|
|
||||||
}${svgfilename}`;
|
|
||||||
|
|
||||||
const svgfilecontent = (
|
|
||||||
await fs.readFile(file)
|
|
||||||
).toString();
|
|
||||||
|
|
||||||
await generateTemplateFilesBatch([
|
|
||||||
{
|
|
||||||
option:
|
|
||||||
'Create Icon Flutter Widget',
|
|
||||||
entry: {
|
|
||||||
folderPath:
|
|
||||||
'./bin/templates/__svgfilename__.dart',
|
|
||||||
},
|
|
||||||
dynamicReplacers: [
|
|
||||||
{
|
|
||||||
slot: '__icon__',
|
|
||||||
slotValue: iconname,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
slot: '__svgfilecontent__',
|
|
||||||
slotValue: svgfilecontent,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
slot: '__svgfilename__',
|
|
||||||
slotValue: svgfilename,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
output: {
|
|
||||||
path: './packages/iconoir-flutter/lib/__svgfilename__(snakeCase).dart',
|
|
||||||
pathAndFileNameDefaultCase:
|
|
||||||
'(snakeCase)',
|
|
||||||
},
|
|
||||||
onComplete(results) {
|
|
||||||
finalFileNames.push(
|
|
||||||
results.output.path,
|
|
||||||
);
|
|
||||||
},
|
|
||||||
},
|
|
||||||
]);
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
|
|
||||||
finalFileNames.sort();
|
|
||||||
await fs.appendFile(
|
|
||||||
path.join(
|
|
||||||
builtIconsDir,
|
|
||||||
'iconoir_flutter.dart',
|
|
||||||
),
|
|
||||||
finalFileNames
|
|
||||||
.map(
|
|
||||||
(fileName) =>
|
|
||||||
`export './${basename(
|
|
||||||
fileName,
|
|
||||||
)}';`,
|
|
||||||
)
|
|
||||||
.join('\n'),
|
|
||||||
);
|
|
||||||
} catch (err) {
|
|
||||||
throw new Error(err.message);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
{ concurrent: false, exitOnError: false },
|
|
||||||
),
|
|
||||||
};
|
|
||||||
});
|
|
||||||
return task.newListr(tasks, {
|
|
||||||
concurrent: true,
|
|
||||||
rendererOptions: {
|
|
||||||
collapseSubtasks: false,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
{ concurrent: false },
|
|
||||||
),
|
|
||||||
},
|
|
||||||
],
|
|
||||||
{ concurrent: true },
|
|
||||||
),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: 'Removing React temporary directory',
|
|
||||||
skip: (ctx) => !ctx.tmpDir,
|
|
||||||
task: async (ctx) => {
|
|
||||||
await fs.rm(ctx.tmpDir, { recursive: true });
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: 'Removing Flutter temporary directory',
|
|
||||||
skip: (ctx) => !ctx.flutterTmpDir,
|
|
||||||
task: async (ctx) => {
|
|
||||||
await fs.rm(ctx.flutterTmpDir, { recursive: true });
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
{
|
|
||||||
concurrent: false,
|
|
||||||
exitOnError: false,
|
|
||||||
rendererOptions: {
|
|
||||||
collapseSubtasks: false,
|
|
||||||
collapseErrors: false,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
await tasks.run();
|
|
133
bin/build/index.js
Normal file
|
@ -0,0 +1,133 @@
|
||||||
|
import { Listr } from 'listr2';
|
||||||
|
import fs from 'node:fs/promises';
|
||||||
|
import path from 'node:path';
|
||||||
|
import { fileURLToPath } from 'node:url';
|
||||||
|
import { pascalCase, snakeCase } from 'scule';
|
||||||
|
|
||||||
|
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
||||||
|
|
||||||
|
const rootDir = path.join(__dirname, '..', '..');
|
||||||
|
const iconsDir = path.join(rootDir, 'icons');
|
||||||
|
|
||||||
|
const iconsVariants = ['regular', 'solid'];
|
||||||
|
const defaultVariant = iconsVariants[0];
|
||||||
|
|
||||||
|
const targets = {
|
||||||
|
'css': {
|
||||||
|
title: 'CSS files',
|
||||||
|
path: 'css',
|
||||||
|
},
|
||||||
|
'flutter': {
|
||||||
|
title: 'Flutter library',
|
||||||
|
path: 'packages/iconoir-flutter',
|
||||||
|
},
|
||||||
|
'react': {
|
||||||
|
title: 'React library',
|
||||||
|
path: 'packages/iconoir-react',
|
||||||
|
},
|
||||||
|
'react-native': {
|
||||||
|
title: 'React Native library',
|
||||||
|
target: 'react',
|
||||||
|
native: true,
|
||||||
|
path: 'packages/iconoir-react-native',
|
||||||
|
},
|
||||||
|
'vue': {
|
||||||
|
title: 'Vue library',
|
||||||
|
path: 'packages/iconoir-vue',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const tasks = new Listr(
|
||||||
|
[
|
||||||
|
{
|
||||||
|
title: 'Fetching icons',
|
||||||
|
task: async (ctx) => {
|
||||||
|
ctx.icons = {};
|
||||||
|
|
||||||
|
const iconsVariantsDirs = Object.fromEntries(
|
||||||
|
iconsVariants.map((variant) => [
|
||||||
|
variant,
|
||||||
|
path.join(iconsDir, variant),
|
||||||
|
]),
|
||||||
|
);
|
||||||
|
|
||||||
|
for (const [variant, dir] of Object.entries(iconsVariantsDirs)) {
|
||||||
|
const files = await fs.readdir(dir);
|
||||||
|
|
||||||
|
const icons = files
|
||||||
|
.filter((file) => file.endsWith('.svg'))
|
||||||
|
.map((file) => {
|
||||||
|
const name = path.parse(file).name;
|
||||||
|
const nameVariant = `${name}-${variant}`;
|
||||||
|
|
||||||
|
return {
|
||||||
|
name,
|
||||||
|
nameVariant,
|
||||||
|
pascalName: pascalCase(name),
|
||||||
|
pascalNameVariant: pascalCase(nameVariant),
|
||||||
|
snakeName: snakeCase(name),
|
||||||
|
snakeNameVariant: snakeCase(nameVariant),
|
||||||
|
path: path.join(dir, file),
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
ctx.icons[variant] = icons;
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.global = { defaultVariant };
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Building targets',
|
||||||
|
task: (_, task) =>
|
||||||
|
task.newListr(
|
||||||
|
Object.entries(targets).map(([targetName, targetConfig]) => ({
|
||||||
|
title: targetConfig.title,
|
||||||
|
enabled: () =>
|
||||||
|
cliTargets.length === 0 || cliTargets.includes(targetName),
|
||||||
|
task: async (ctx) => {
|
||||||
|
const { default: task } = await import(
|
||||||
|
`./targets/${targetConfig.target || targetName}/index.js`
|
||||||
|
);
|
||||||
|
|
||||||
|
targetConfig.path = path.join(
|
||||||
|
rootDir,
|
||||||
|
...targetConfig.path.split(path.posix.sep),
|
||||||
|
);
|
||||||
|
|
||||||
|
return task(ctx, targetConfig);
|
||||||
|
},
|
||||||
|
})),
|
||||||
|
{ concurrent: true, exitOnError: false },
|
||||||
|
),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
{
|
||||||
|
rendererOptions: {
|
||||||
|
collapseSubtasks: false,
|
||||||
|
collapseErrors: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
const cliTargets = [];
|
||||||
|
|
||||||
|
// Get targets from command line arguments
|
||||||
|
// (build all targets if no arguments given)
|
||||||
|
for (const arg of process.argv.slice(2)) {
|
||||||
|
if (arg in targets) {
|
||||||
|
cliTargets.push(arg);
|
||||||
|
} else {
|
||||||
|
console.error(
|
||||||
|
`Target '${arg}' doesn't exist!\n\nPossible targets are:\n${Object.keys(
|
||||||
|
targets,
|
||||||
|
)
|
||||||
|
.map((name) => `- ${name}`)
|
||||||
|
.join('\n')}`,
|
||||||
|
);
|
||||||
|
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
await tasks.run();
|
19
bin/build/lib/import-export.js
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
import path from 'node:path';
|
||||||
|
|
||||||
|
export function generateImport(name, from) {
|
||||||
|
if (Array.isArray(name)) name = `{${name.toString()}}`;
|
||||||
|
|
||||||
|
return `import ${name} from "${from}";`;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function generateExport(name, from) {
|
||||||
|
const base = `export {${name.toString()}}`;
|
||||||
|
|
||||||
|
return from ? `${base} from "${from}";` : `${base};`;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function toImportPath(input) {
|
||||||
|
input = input.split(path.sep).join(path.posix.sep);
|
||||||
|
|
||||||
|
return input.charAt(0) !== '.' ? `./${input}` : input;
|
||||||
|
}
|
53
bin/build/lib/ts.js
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
import ts from 'typescript';
|
||||||
|
|
||||||
|
export function getDts(path, content, options) {
|
||||||
|
let output;
|
||||||
|
|
||||||
|
const host = ts.createCompilerHost(options);
|
||||||
|
|
||||||
|
const _readFile = host.readFile;
|
||||||
|
|
||||||
|
host.readFile = (filename) => {
|
||||||
|
if (filename === path) return content;
|
||||||
|
|
||||||
|
return _readFile(filename);
|
||||||
|
};
|
||||||
|
|
||||||
|
const dtsFilename = path.replace(/\.(m|c)?(ts|js)x?$/, '.d.$1ts');
|
||||||
|
|
||||||
|
host.writeFile = (filename, contents) => {
|
||||||
|
if (filename === dtsFilename) output = contents;
|
||||||
|
};
|
||||||
|
|
||||||
|
const program = ts.createProgram([path], options, host);
|
||||||
|
const emitResult = program.emit();
|
||||||
|
|
||||||
|
const allDiagnostics = ts
|
||||||
|
.getPreEmitDiagnostics(program)
|
||||||
|
.concat(emitResult.diagnostics);
|
||||||
|
|
||||||
|
const results = allDiagnostics.map((diagnostic) => {
|
||||||
|
if (diagnostic.file) {
|
||||||
|
const { line, character } = ts.getLineAndCharacterOfPosition(
|
||||||
|
diagnostic.file,
|
||||||
|
diagnostic.start,
|
||||||
|
);
|
||||||
|
const message = ts.flattenDiagnosticMessageText(
|
||||||
|
diagnostic.messageText,
|
||||||
|
'\n',
|
||||||
|
);
|
||||||
|
|
||||||
|
return `${diagnostic.file.fileName} (${line + 1},${
|
||||||
|
character + 1
|
||||||
|
}): ${message}`;
|
||||||
|
} else {
|
||||||
|
return ts.flattenDiagnosticMessageText(diagnostic.messageText, '\n');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (results.length > 0) {
|
||||||
|
throw new Error(results);
|
||||||
|
}
|
||||||
|
|
||||||
|
return output;
|
||||||
|
}
|
|
@ -1,13 +1,13 @@
|
||||||
/*!
|
/*!
|
||||||
* Iconoir
|
* Iconoir
|
||||||
* Copyright (c) [YEAR] Luca Burgio - https://iconoir.com
|
* Copyright (c) [YEAR] Luca Burgio - https://iconoir.com
|
||||||
* License - https://github.com/lucaburgio/iconoir/blob/main/LICENSE (Code: MIT License)
|
* License - https://github.com/iconoir-icons/iconoir/blob/main/LICENSE (Code: MIT License)
|
||||||
* CSS file created by Till Esser (@Wiwaltill) and automated by Pascal Jufer (@paescuj)
|
* CSS file created by Till Esser (@Wiwaltill) and automated by Pascal Jufer (@paescuj)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
*[class^="iconoir-"]::before,
|
*[class^='iconoir-']::before,
|
||||||
*[class*=" iconoir-"]::before {
|
*[class*=' iconoir-']::before {
|
||||||
content: " ";
|
content: ' ';
|
||||||
display: block;
|
display: block;
|
||||||
background: currentColor;
|
background: currentColor;
|
||||||
mask-size: cover;
|
mask-size: cover;
|
||||||
|
@ -15,7 +15,7 @@
|
||||||
width: 1em;
|
width: 1em;
|
||||||
height: 1em;
|
height: 1em;
|
||||||
}
|
}
|
||||||
*[class^="iconoir-"],
|
*[class^='iconoir-'],
|
||||||
*[class*=" iconoir-"] {
|
*[class*=' iconoir-'] {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
}
|
}
|
51
bin/build/targets/css/index.js
Normal file
|
@ -0,0 +1,51 @@
|
||||||
|
import fs from 'node:fs/promises';
|
||||||
|
import path from 'node:path';
|
||||||
|
import { fileURLToPath } from 'node:url';
|
||||||
|
|
||||||
|
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
||||||
|
|
||||||
|
export default async (ctx, target) => {
|
||||||
|
const headerFile = await fs.readFile(
|
||||||
|
path.join(__dirname, 'header.css'),
|
||||||
|
'utf8',
|
||||||
|
);
|
||||||
|
|
||||||
|
const header = headerFile.replace('[YEAR]', new Date().getFullYear());
|
||||||
|
|
||||||
|
const mainCssContent = [header];
|
||||||
|
|
||||||
|
for (const [variant, icons] of Object.entries(ctx.icons)) {
|
||||||
|
const variantCssContent = [header];
|
||||||
|
|
||||||
|
const cssTarget = (icon, suffixed) => {
|
||||||
|
const iconName =
|
||||||
|
suffixed && variant !== ctx.global.defaultVariant
|
||||||
|
? icon.nameVariant
|
||||||
|
: icon.name;
|
||||||
|
|
||||||
|
return `.iconoir-${iconName}::before`;
|
||||||
|
};
|
||||||
|
|
||||||
|
for (const icon of icons) {
|
||||||
|
const fileContent = await fs.readFile(icon.path, 'utf8');
|
||||||
|
|
||||||
|
const transformedContent = fileContent
|
||||||
|
.replace(/\n/g, '')
|
||||||
|
.replace(/(width|height)="[0-9]+px"/g, '')
|
||||||
|
.replace(/[ ]+/g, ' ');
|
||||||
|
|
||||||
|
const cssContent = `{mask-image:url('data:image/svg+xml;charset=utf-8,${transformedContent}');-webkit-mask-image:url('data:image/svg+xml;charset=utf-8,${transformedContent}');}`;
|
||||||
|
|
||||||
|
mainCssContent.push(`${cssTarget(icon)}${cssContent}`);
|
||||||
|
|
||||||
|
variantCssContent.push(`${cssTarget(icon, true)}${cssContent}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
await fs.writeFile(
|
||||||
|
path.join(target.path, `iconoir-${variant}.css`),
|
||||||
|
variantCssContent,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
await fs.writeFile(path.join(target.path, 'iconoir.css'), mainCssContent);
|
||||||
|
};
|
47
bin/build/targets/flutter/index.js
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
import fs from 'node:fs/promises';
|
||||||
|
import path from 'node:path';
|
||||||
|
import iconTemplate from './template.js';
|
||||||
|
|
||||||
|
export default async (ctx, target) => {
|
||||||
|
const promises = [];
|
||||||
|
|
||||||
|
const outDir = path.join(target.path, 'lib');
|
||||||
|
|
||||||
|
const entryContent = ['library iconoir_flutter;'];
|
||||||
|
|
||||||
|
for (const [variant, icons] of Object.entries(ctx.icons)) {
|
||||||
|
const variantOutDir = path.join(outDir, variant);
|
||||||
|
await fs.mkdir(variantOutDir, { recursive: true });
|
||||||
|
|
||||||
|
for (const icon of icons) {
|
||||||
|
const dartFileName = `${icon.snakeName}.dart`;
|
||||||
|
const dartPath = path.join(variant, dartFileName);
|
||||||
|
|
||||||
|
promises.push(
|
||||||
|
generateIconFile(
|
||||||
|
icon.path,
|
||||||
|
path.join(outDir, dartPath),
|
||||||
|
variant !== ctx.global.defaultVariant
|
||||||
|
? icon.pascalNameVariant
|
||||||
|
: icon.pascalName,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
entryContent.push(`export './${dartPath}';`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
promises.push(
|
||||||
|
fs.writeFile(path.join(outDir, 'iconoir_flutter.dart'), entryContent),
|
||||||
|
);
|
||||||
|
|
||||||
|
return Promise.all(promises);
|
||||||
|
};
|
||||||
|
|
||||||
|
async function generateIconFile(src, dest, iconName) {
|
||||||
|
const iconContent = await fs.readFile(src, 'utf8');
|
||||||
|
|
||||||
|
const dartContent = iconTemplate(iconName, iconContent);
|
||||||
|
|
||||||
|
return fs.writeFile(dest, dartContent);
|
||||||
|
}
|
25
bin/build/targets/flutter/template.js
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
const template = (name, svg) => `
|
||||||
|
import 'package:flutter/widgets.dart' as widgets;
|
||||||
|
import 'package:flutter_svg/flutter_svg.dart';
|
||||||
|
|
||||||
|
class ${name} extends widgets.StatelessWidget {
|
||||||
|
final widgets.Color? color;
|
||||||
|
final double? width;
|
||||||
|
final double? height;
|
||||||
|
|
||||||
|
const ${name}({widgets.Key? key, this.color, this.width, this.height})
|
||||||
|
: super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
widgets.Widget build(widgets.BuildContext context) => SvgPicture.string(
|
||||||
|
'''
|
||||||
|
${svg}''',
|
||||||
|
colorFilter:
|
||||||
|
color != null ? widgets.ColorFilter.mode(color!, widgets.BlendMode.srcIn) : null,
|
||||||
|
width: width,
|
||||||
|
height: height,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
export default template;
|
248
bin/build/targets/react/index.js
Normal file
|
@ -0,0 +1,248 @@
|
||||||
|
import * as svgr from '@svgr/core';
|
||||||
|
import * as esbuild from 'esbuild';
|
||||||
|
import fs from 'node:fs/promises';
|
||||||
|
import path from 'node:path';
|
||||||
|
import {
|
||||||
|
generateExport,
|
||||||
|
generateImport,
|
||||||
|
toImportPath,
|
||||||
|
} from '../../lib/import-export.js';
|
||||||
|
import { getDts } from '../../lib/ts.js';
|
||||||
|
import iconoirContextTemplate, {
|
||||||
|
exports as iconoirContextExports,
|
||||||
|
} from './resources/context-template.js';
|
||||||
|
import { getTemplate as getIconTemplate } from './resources/icon-template.js';
|
||||||
|
import { nativeSvgrOptions, svgrOptions } from './resources/svgr-options.js';
|
||||||
|
|
||||||
|
const outDir = 'dist';
|
||||||
|
|
||||||
|
const jsTargets = [
|
||||||
|
{
|
||||||
|
format: 'cjs',
|
||||||
|
module: 'commonjs',
|
||||||
|
dir: '.',
|
||||||
|
ext: 'js',
|
||||||
|
dtsExt: 'd.ts',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
format: 'esm',
|
||||||
|
module: 'esnext',
|
||||||
|
dir: 'esm',
|
||||||
|
ext: 'mjs',
|
||||||
|
dtsExt: 'd.mts',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
/** @type {import('esbuild').TransformOptions} */
|
||||||
|
const defaultEsbuildOptions = { target: 'es6', minify: true };
|
||||||
|
|
||||||
|
/** @type {import('typescript').CompilerOptions} */
|
||||||
|
const defaultTsOptions = {
|
||||||
|
jsx: 'react',
|
||||||
|
declaration: true,
|
||||||
|
emitDeclarationOnly: true,
|
||||||
|
target: 'es6',
|
||||||
|
strict: true,
|
||||||
|
esModuleInterop: true,
|
||||||
|
skipLibCheck: true,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default async (ctx, target) => {
|
||||||
|
const localJsTargets = jsTargets.map((jsTarget) => ({
|
||||||
|
...jsTarget,
|
||||||
|
iconTemplate: getIconTemplate(target.native, jsTarget.ext),
|
||||||
|
}));
|
||||||
|
|
||||||
|
const promises = [];
|
||||||
|
|
||||||
|
const outPath = path.join(target.path, outDir);
|
||||||
|
|
||||||
|
// Preparation
|
||||||
|
// (needs to run in a separate loop, otherwise leads to uncaught exceptions in case of errors in main loop)
|
||||||
|
for (const jsTarget of localJsTargets) {
|
||||||
|
jsTarget.path = path.join(outPath, jsTarget.dir);
|
||||||
|
|
||||||
|
await fs.mkdir(jsTarget.path, { recursive: true });
|
||||||
|
|
||||||
|
const iconoirContext = iconoirContextTemplate(target.native);
|
||||||
|
|
||||||
|
jsTarget.iconoirContextPath = path.join(
|
||||||
|
jsTarget.path,
|
||||||
|
`IconoirContext.${jsTarget.ext}`,
|
||||||
|
);
|
||||||
|
|
||||||
|
await generateJs(
|
||||||
|
jsTarget.iconoirContextPath,
|
||||||
|
iconoirContext,
|
||||||
|
jsTarget.format,
|
||||||
|
);
|
||||||
|
|
||||||
|
const iconoirContextTsxPath = path.join(
|
||||||
|
jsTarget.path,
|
||||||
|
'IconoirContext.tsx',
|
||||||
|
);
|
||||||
|
const iconoirContextDtsPath = path.join(
|
||||||
|
jsTarget.path,
|
||||||
|
`IconoirContext.${jsTarget.dtsExt}`,
|
||||||
|
);
|
||||||
|
|
||||||
|
await generateDts(
|
||||||
|
iconoirContextTsxPath,
|
||||||
|
iconoirContextDtsPath,
|
||||||
|
iconoirContext,
|
||||||
|
jsTarget.module,
|
||||||
|
);
|
||||||
|
|
||||||
|
for (const variant of Object.keys(ctx.icons)) {
|
||||||
|
jsTarget.path = path.join(outPath, jsTarget.dir);
|
||||||
|
|
||||||
|
await fs.mkdir(path.join(jsTarget.path, variant), { recursive: true });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const jsTarget of localJsTargets) {
|
||||||
|
const mainIndex = prepareIndex(jsTarget);
|
||||||
|
|
||||||
|
for (const [variant, icons] of Object.entries(ctx.icons)) {
|
||||||
|
const variantIndex = prepareIndex(jsTarget, variant);
|
||||||
|
|
||||||
|
for (const icon of icons) {
|
||||||
|
const mainIndexComponentName =
|
||||||
|
variant === ctx.global.defaultVariant
|
||||||
|
? icon.pascalName
|
||||||
|
: icon.pascalNameVariant;
|
||||||
|
|
||||||
|
const jsPath = path.join(
|
||||||
|
jsTarget.path,
|
||||||
|
variant,
|
||||||
|
`${icon.pascalName}.${jsTarget.ext}`,
|
||||||
|
);
|
||||||
|
|
||||||
|
mainIndex.add(mainIndexComponentName, jsPath);
|
||||||
|
variantIndex.add(icon.pascalName, jsPath);
|
||||||
|
|
||||||
|
const reactComponent = getReactComponent(
|
||||||
|
icon.path,
|
||||||
|
target.native,
|
||||||
|
jsTarget.iconTemplate,
|
||||||
|
);
|
||||||
|
|
||||||
|
// Only run for first icon, type is same and can be reused for all the others
|
||||||
|
if (!jsTarget.iconDts) {
|
||||||
|
jsTarget.iconDts = true;
|
||||||
|
|
||||||
|
// Virtual input path
|
||||||
|
const tsxPath = path.join(jsTarget.path, variant, 'icon.tsx');
|
||||||
|
|
||||||
|
const dtsPath = path.join(jsTarget.path, `icon.${jsTarget.dtsExt}`);
|
||||||
|
|
||||||
|
const iconDts = generateDts(
|
||||||
|
tsxPath,
|
||||||
|
dtsPath,
|
||||||
|
reactComponent,
|
||||||
|
jsTarget.module,
|
||||||
|
);
|
||||||
|
|
||||||
|
promises.push(iconDts);
|
||||||
|
}
|
||||||
|
|
||||||
|
const iconJs = generateJs(jsPath, reactComponent, jsTarget.format);
|
||||||
|
|
||||||
|
promises.push(iconJs);
|
||||||
|
}
|
||||||
|
|
||||||
|
promises.push(variantIndex.generate());
|
||||||
|
}
|
||||||
|
|
||||||
|
promises.push(mainIndex.generate());
|
||||||
|
}
|
||||||
|
|
||||||
|
return Promise.all(promises);
|
||||||
|
};
|
||||||
|
|
||||||
|
async function getReactComponent(iconPath, native, template) {
|
||||||
|
const iconContent = await fs.readFile(iconPath, 'utf8');
|
||||||
|
|
||||||
|
const options = native ? nativeSvgrOptions : svgrOptions;
|
||||||
|
options.template = template;
|
||||||
|
|
||||||
|
return svgr.transform(iconContent, options);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function generateDts(inputPath, outputPath, input, module) {
|
||||||
|
const dts = getDts(inputPath, await input, {
|
||||||
|
...defaultTsOptions,
|
||||||
|
module,
|
||||||
|
});
|
||||||
|
|
||||||
|
return fs.writeFile(outputPath, dts);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function generateJs(outputPath, input, format) {
|
||||||
|
const { code } = await esbuild.transform(await input, {
|
||||||
|
...defaultEsbuildOptions,
|
||||||
|
loader: 'tsx',
|
||||||
|
format,
|
||||||
|
});
|
||||||
|
|
||||||
|
return fs.writeFile(outputPath, code);
|
||||||
|
}
|
||||||
|
|
||||||
|
function prepareIndex(jsTarget, variant) {
|
||||||
|
const outputPath = path.join(jsTarget.path, variant ?? '');
|
||||||
|
|
||||||
|
const iconoirContextPath = toImportPath(
|
||||||
|
path.relative(outputPath, jsTarget.iconoirContextPath),
|
||||||
|
);
|
||||||
|
|
||||||
|
const iconoirContext = generateExport(
|
||||||
|
iconoirContextExports,
|
||||||
|
iconoirContextPath,
|
||||||
|
);
|
||||||
|
|
||||||
|
const content = [iconoirContext];
|
||||||
|
|
||||||
|
const iconJsPath = toImportPath(
|
||||||
|
path.relative(outputPath, path.join(jsTarget.path, `icon.${jsTarget.ext}`)),
|
||||||
|
);
|
||||||
|
|
||||||
|
const iconDtsImport = generateImport('Icon', iconJsPath);
|
||||||
|
|
||||||
|
const dtsContent = [iconoirContext, iconDtsImport, 'type I = typeof Icon;'];
|
||||||
|
|
||||||
|
function add(name, iconPath) {
|
||||||
|
const iconImportPath = toImportPath(path.relative(outputPath, iconPath));
|
||||||
|
|
||||||
|
content.push(generateExport(`default as ${name}`, iconImportPath));
|
||||||
|
|
||||||
|
dtsContent.push(`export declare const ${name}: I;`);
|
||||||
|
}
|
||||||
|
|
||||||
|
function generate() {
|
||||||
|
const indexJs = generateIndexJs(
|
||||||
|
outputPath,
|
||||||
|
content,
|
||||||
|
jsTarget.format,
|
||||||
|
jsTarget.ext,
|
||||||
|
);
|
||||||
|
|
||||||
|
const indexDts = generateIndexDts(outputPath, dtsContent, jsTarget.dtsExt);
|
||||||
|
|
||||||
|
return Promise.all([indexJs, indexDts]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return { add, generate };
|
||||||
|
}
|
||||||
|
|
||||||
|
async function generateIndexJs(outputDir, content, format, ext) {
|
||||||
|
const { code } = await esbuild.transform(content.join(''), {
|
||||||
|
minify: true,
|
||||||
|
format,
|
||||||
|
});
|
||||||
|
|
||||||
|
return fs.writeFile(path.join(outputDir, `index.${ext}`), code);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function generateIndexDts(outputDir, content, dtsExt) {
|
||||||
|
return fs.writeFile(path.join(outputDir, `index.${dtsExt}`), content);
|
||||||
|
}
|
36
bin/build/targets/react/resources/context-template.js
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
const template = (native) => {
|
||||||
|
const useClientDirective = native ? '' : '"use client";';
|
||||||
|
|
||||||
|
const imports = [
|
||||||
|
'import React from "react";',
|
||||||
|
...(native ? ['import type { SvgProps } from "react-native-svg";'] : []),
|
||||||
|
].join('\n');
|
||||||
|
|
||||||
|
return `
|
||||||
|
${useClientDirective}
|
||||||
|
${imports}
|
||||||
|
|
||||||
|
type IconoirContextValue = Partial<${
|
||||||
|
native ? 'SvgProps' : 'React.SVGProps<SVGSVGElement>'
|
||||||
|
}>;
|
||||||
|
|
||||||
|
export const IconoirContext = React.createContext<IconoirContextValue>({});
|
||||||
|
|
||||||
|
export interface IconoirProviderProps {
|
||||||
|
iconProps?: Partial<${
|
||||||
|
native ? `Omit<SvgProps, 'children'>` : 'React.SVGProps<SVGSVGElement>'
|
||||||
|
}>;
|
||||||
|
children: React.ReactNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function IconoirProvider({ iconProps, children }: IconoirProviderProps) {
|
||||||
|
return (
|
||||||
|
<IconoirContext.Provider value={iconProps || {}} children={children} />
|
||||||
|
);
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default template;
|
||||||
|
|
||||||
|
export const exports = ['IconoirContext', 'IconoirProvider'];
|
35
bin/build/targets/react/resources/icon-template.js
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
import { generateImport } from '../../../lib/import-export.js';
|
||||||
|
|
||||||
|
export function getTemplate(native, ext) {
|
||||||
|
return (variables, { tpl }) => {
|
||||||
|
variables.props[0].name = 'passedProps';
|
||||||
|
|
||||||
|
// Workaround to fix ref type for React Native
|
||||||
|
if (native) {
|
||||||
|
variables.props[1].typeAnnotation.typeAnnotation.typeParameters.params[0].typeName.name =
|
||||||
|
'Svg';
|
||||||
|
}
|
||||||
|
|
||||||
|
const useClientDirective = native ? '' : '"use client";';
|
||||||
|
const iconoirContextImport = generateImport(
|
||||||
|
['IconoirContext'],
|
||||||
|
`../IconoirContext.${ext}`,
|
||||||
|
);
|
||||||
|
|
||||||
|
return tpl`
|
||||||
|
${useClientDirective}
|
||||||
|
${variables.imports};
|
||||||
|
${iconoirContextImport};
|
||||||
|
|
||||||
|
${variables.interfaces};
|
||||||
|
|
||||||
|
const ${variables.componentName} = (${variables.props}) => {
|
||||||
|
const context = React.useContext(IconoirContext);
|
||||||
|
const props = { ...context, ...passedProps };
|
||||||
|
return ${variables.jsx};
|
||||||
|
};
|
||||||
|
|
||||||
|
${variables.exports};
|
||||||
|
`;
|
||||||
|
};
|
||||||
|
}
|
46
bin/build/targets/react/resources/svgr-options.js
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
/** @type {import('@svgr/core').Config} */
|
||||||
|
export const svgrOptions = {
|
||||||
|
plugins: ['@svgr/plugin-jsx'],
|
||||||
|
icon: true,
|
||||||
|
ref: true,
|
||||||
|
typescript: true,
|
||||||
|
svgProps: {
|
||||||
|
width: '1.5em',
|
||||||
|
height: '1.5em',
|
||||||
|
color: 'currentColor',
|
||||||
|
},
|
||||||
|
jsx: {
|
||||||
|
babelConfig: {
|
||||||
|
plugins: [
|
||||||
|
[
|
||||||
|
'@svgr/babel-plugin-remove-jsx-attribute',
|
||||||
|
{
|
||||||
|
elements: ['path'],
|
||||||
|
attributes: ['strokeWidth'],
|
||||||
|
},
|
||||||
|
'remove-stroke-width',
|
||||||
|
],
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
/** @type {import('@svgr/core').Config} */
|
||||||
|
export const nativeSvgrOptions = {
|
||||||
|
...svgrOptions,
|
||||||
|
native: true,
|
||||||
|
jsx: {
|
||||||
|
babelConfig: {
|
||||||
|
plugins: [
|
||||||
|
...svgrOptions.jsx.babelConfig.plugins,
|
||||||
|
[
|
||||||
|
'@svgr/babel-plugin-remove-jsx-attribute',
|
||||||
|
{
|
||||||
|
elements: ['Svg'],
|
||||||
|
attributes: ['xmlns'],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
72
bin/build/targets/vue/index.js
Normal file
|
@ -0,0 +1,72 @@
|
||||||
|
import { fromHtml } from 'hast-util-from-html';
|
||||||
|
import { toHtml } from 'hast-util-to-html';
|
||||||
|
import fs from 'node:fs/promises';
|
||||||
|
import path from 'node:path';
|
||||||
|
import { generateExport } from '../../lib/import-export.js';
|
||||||
|
import iconTemplate from './template.js';
|
||||||
|
|
||||||
|
export default async (ctx, target) => {
|
||||||
|
const promises = [];
|
||||||
|
|
||||||
|
const outDir = path.join(target.path, 'src');
|
||||||
|
|
||||||
|
const mainIndexContent = [
|
||||||
|
generateExport(`default as IconoirProvider`, `./IconoirProvider.vue`),
|
||||||
|
];
|
||||||
|
|
||||||
|
for (const [variant, icons] of Object.entries(ctx.icons)) {
|
||||||
|
const variantOutDir = path.join(outDir, variant);
|
||||||
|
await fs.mkdir(variantOutDir, { recursive: true });
|
||||||
|
|
||||||
|
const variantIndexContent = [
|
||||||
|
generateExport(`default as IconoirProvider`, `../IconoirProvider.vue`),
|
||||||
|
];
|
||||||
|
|
||||||
|
const generateIconFile = async (src, vueFileName) => {
|
||||||
|
const iconContent = await fs.readFile(src, 'utf8');
|
||||||
|
|
||||||
|
const iconAst = fromHtml(iconContent, { fragment: true });
|
||||||
|
// Bind iconProps of the provider to the svg root
|
||||||
|
iconAst.children[0].properties['v-bind'] = 'context';
|
||||||
|
const transformedIcon = toHtml(iconAst);
|
||||||
|
const componentContent = iconTemplate(transformedIcon);
|
||||||
|
|
||||||
|
const vuePath = path.join(variantOutDir, vueFileName);
|
||||||
|
|
||||||
|
return fs.writeFile(vuePath, componentContent);
|
||||||
|
};
|
||||||
|
|
||||||
|
for (const icon of icons) {
|
||||||
|
const vueFileName = `${icon.pascalName}.vue`;
|
||||||
|
|
||||||
|
promises.push(generateIconFile(icon.path, vueFileName));
|
||||||
|
|
||||||
|
const mainIndexComponentName =
|
||||||
|
variant === ctx.global.defaultVariant
|
||||||
|
? icon.pascalName
|
||||||
|
: icon.pascalNameVariant;
|
||||||
|
|
||||||
|
mainIndexContent.push(
|
||||||
|
generateExport(
|
||||||
|
`default as ${mainIndexComponentName}`,
|
||||||
|
`./${variant}/${vueFileName}`,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
variantIndexContent.push(
|
||||||
|
generateExport(
|
||||||
|
`default as ${mainIndexComponentName}`,
|
||||||
|
`./${vueFileName}`,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
promises.push(
|
||||||
|
fs.writeFile(path.join(variantOutDir, 'index.ts'), variantIndexContent),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
promises.push(fs.writeFile(path.join(outDir, 'index.ts'), mainIndexContent));
|
||||||
|
|
||||||
|
return Promise.all(promises);
|
||||||
|
};
|
|
@ -1,14 +1,16 @@
|
||||||
const template = (svg, keyFileName) => `<script lang="ts">
|
const template = (svg) => `<script lang="ts">
|
||||||
import { defineComponent, inject } from "vue-demi";
|
import { defineComponent, inject } from "vue-demi";
|
||||||
import type { SVGAttributes } from "vue-demi";
|
import type { SVGAttributes } from "vue-demi";
|
||||||
import providerKey from "./${keyFileName}";
|
import providerKey from "../providerKey";
|
||||||
|
|
||||||
export default defineComponent<SVGAttributes>(() => {
|
export default defineComponent<SVGAttributes>(() => {
|
||||||
const context = inject(providerKey);
|
const context = inject(providerKey);
|
||||||
return { context };
|
return { context };
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
${svg}
|
${svg}
|
||||||
</template>`;
|
</template>`;
|
||||||
|
|
||||||
module.exports = template;
|
export default template;
|
|
@ -1,52 +0,0 @@
|
||||||
import { toHtml } from 'hast-util-to-html';
|
|
||||||
import fs from 'node:fs/promises';
|
|
||||||
import path from 'node:path';
|
|
||||||
import { parse } from 'svg-parser';
|
|
||||||
import componentTemplate from './templates/vue/icon-template.cjs';
|
|
||||||
import indexTemplate from './templates/vue/index-template.cjs';
|
|
||||||
import providerKeyTemplate from './templates/vue/provider-key-template.cjs';
|
|
||||||
import providerTemplate from './templates/vue/provider-template.cjs';
|
|
||||||
|
|
||||||
export async function buildVueIcons(srcDir, { outDir = './out/' }) {
|
|
||||||
const files = await fs.readdir(srcDir, 'utf8');
|
|
||||||
|
|
||||||
const providerKeyFileName = 'providerKey';
|
|
||||||
const providerKey = providerKeyTemplate();
|
|
||||||
await fs.writeFile(
|
|
||||||
path.join(outDir, providerKeyFileName + '.ts'),
|
|
||||||
providerKey,
|
|
||||||
'utf8',
|
|
||||||
);
|
|
||||||
|
|
||||||
const fileNames = [];
|
|
||||||
for (const file of files) {
|
|
||||||
const svgRaw = await fs.readFile(path.join(srcDir, file), 'utf8');
|
|
||||||
|
|
||||||
const svgAst = parse(svgRaw);
|
|
||||||
// Bind iconProps of the provider to the svg root
|
|
||||||
svgAst.children[0].properties['v-bind'] = 'context';
|
|
||||||
const svgString = toHtml(svgAst);
|
|
||||||
|
|
||||||
const component = componentTemplate(svgString, providerKeyFileName);
|
|
||||||
const pascalCaseFileName = file
|
|
||||||
.replaceAll(/[\s-]([\w\d])/g, (_, cg1) => cg1.toUpperCase())
|
|
||||||
.replace(/^\w/, (m) => m.toUpperCase())
|
|
||||||
.replace('.svg', '.vue');
|
|
||||||
await fs.writeFile(
|
|
||||||
path.join(outDir, pascalCaseFileName),
|
|
||||||
component,
|
|
||||||
'utf8',
|
|
||||||
);
|
|
||||||
|
|
||||||
fileNames.push(pascalCaseFileName);
|
|
||||||
}
|
|
||||||
|
|
||||||
const providerFileName = 'IconoirProvider.vue';
|
|
||||||
const provider = providerTemplate(providerKeyFileName);
|
|
||||||
await fs.writeFile(path.join(outDir, providerFileName), provider, 'utf8');
|
|
||||||
|
|
||||||
fileNames.push(providerFileName);
|
|
||||||
|
|
||||||
const index = indexTemplate(fileNames);
|
|
||||||
await fs.writeFile(path.join(outDir, 'index.ts'), index, 'utf8');
|
|
||||||
}
|
|
|
@ -7,10 +7,17 @@ const PACKAGE_BASE = '';
|
||||||
|
|
||||||
const newVersion = semver.valid(semver.coerce(process.env.TAG_NAME));
|
const newVersion = semver.valid(semver.coerce(process.env.TAG_NAME));
|
||||||
console.info('New version is %s', newVersion);
|
console.info('New version is %s', newVersion);
|
||||||
|
|
||||||
if (!newVersion) {
|
if (!newVersion) {
|
||||||
throw new Error(`Tag name ${process.env.TAG_NAME} is not valid.`);
|
throw new Error(`Tag name ${process.env.TAG_NAME} is not valid.`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
publishNpmPackage('iconoir');
|
||||||
|
publishNpmPackage('iconoir-react');
|
||||||
|
publishNpmPackage('iconoir-react-native');
|
||||||
|
publishNpmPackage('iconoir-vue');
|
||||||
|
publishPubPackage('iconoir-flutter');
|
||||||
|
|
||||||
function publishNpmPackage(name) {
|
function publishNpmPackage(name) {
|
||||||
console.info('Publishing %s', name);
|
console.info('Publishing %s', name);
|
||||||
|
|
||||||
|
@ -20,9 +27,11 @@ function publishNpmPackage(name) {
|
||||||
: path.join('packages', name, 'package.json');
|
: path.join('packages', name, 'package.json');
|
||||||
const contents = JSON.parse(fs.readFileSync(packageJsonPath).toString());
|
const contents = JSON.parse(fs.readFileSync(packageJsonPath).toString());
|
||||||
contents.version = newVersion;
|
contents.version = newVersion;
|
||||||
|
|
||||||
if (PACKAGE_BASE) {
|
if (PACKAGE_BASE) {
|
||||||
contents.name = `${PACKAGE_BASE}/${name}`;
|
contents.name = `${PACKAGE_BASE}/${name}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
fs.writeFileSync(packageJsonPath, JSON.stringify(contents, undefined, 2));
|
fs.writeFileSync(packageJsonPath, JSON.stringify(contents, undefined, 2));
|
||||||
console.info('package.json updated');
|
console.info('package.json updated');
|
||||||
}
|
}
|
||||||
|
@ -38,9 +47,3 @@ function publishPubPackage(name) {
|
||||||
|
|
||||||
console.info('pubspec.yaml updated');
|
console.info('pubspec.yaml updated');
|
||||||
}
|
}
|
||||||
|
|
||||||
publishNpmPackage('iconoir');
|
|
||||||
publishNpmPackage('iconoir-react');
|
|
||||||
publishNpmPackage('iconoir-react-native');
|
|
||||||
publishNpmPackage('iconoir-vue');
|
|
||||||
publishPubPackage('iconoir-flutter');
|
|
||||||
|
|
|
@ -1,21 +0,0 @@
|
||||||
import 'package:flutter/widgets.dart';
|
|
||||||
import 'package:flutter_svg/flutter_svg.dart';
|
|
||||||
|
|
||||||
class __icon__(pascalCase) extends StatelessWidget {
|
|
||||||
final Color? color;
|
|
||||||
final double? width;
|
|
||||||
final double? height;
|
|
||||||
|
|
||||||
const __icon__(pascalCase)({Key? key, this.color, this.width, this.height})
|
|
||||||
: super(key: key);
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) => SvgPicture.string(
|
|
||||||
'''
|
|
||||||
__svgfilecontent__''',
|
|
||||||
colorFilter:
|
|
||||||
color != null ? ColorFilter.mode(color!, BlendMode.srcIn) : null,
|
|
||||||
width: width,
|
|
||||||
height: height,
|
|
||||||
);
|
|
||||||
}
|
|
|
@ -1,15 +0,0 @@
|
||||||
const template = (variables, { tpl }) => {
|
|
||||||
return tpl`
|
|
||||||
${variables.imports};
|
|
||||||
|
|
||||||
${variables.interfaces};
|
|
||||||
|
|
||||||
const ${variables.componentName} = (${variables.props}) => (
|
|
||||||
${variables.jsx}
|
|
||||||
);
|
|
||||||
|
|
||||||
${variables.exports};
|
|
||||||
`;
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports = template;
|
|
|
@ -1,30 +0,0 @@
|
||||||
const template = (variables, { tpl }) => {
|
|
||||||
variables.props[0].name = 'passedProps';
|
|
||||||
|
|
||||||
// Workaround to fix ref type for React Native
|
|
||||||
const isNative = variables.imports.some(
|
|
||||||
(i) => i.source?.value === 'react-native-svg',
|
|
||||||
);
|
|
||||||
|
|
||||||
if (isNative) {
|
|
||||||
variables.props[1].typeAnnotation.typeAnnotation.typeParameters.params[0].typeName.name =
|
|
||||||
'Svg';
|
|
||||||
}
|
|
||||||
|
|
||||||
return tpl`
|
|
||||||
${variables.imports};
|
|
||||||
import { IconoirContext } from './IconoirContext';
|
|
||||||
|
|
||||||
${variables.interfaces};
|
|
||||||
|
|
||||||
const ${variables.componentName} = (${variables.props}) => {
|
|
||||||
const context = React.useContext(IconoirContext);
|
|
||||||
const props = { ...context, ...passedProps };
|
|
||||||
return ${variables.jsx};
|
|
||||||
};
|
|
||||||
|
|
||||||
${variables.exports};
|
|
||||||
`;
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports = template;
|
|
|
@ -1,15 +0,0 @@
|
||||||
const path = require('path');
|
|
||||||
|
|
||||||
function template(filePaths) {
|
|
||||||
const exportEntries = filePaths.map(({ path: filePath }) => {
|
|
||||||
const basename = path.basename(filePath, path.extname(filePath));
|
|
||||||
const exportName = /^\d/.test(basename) ? `Svg${basename}` : basename;
|
|
||||||
return `export { default as ${exportName} } from './${basename}'`;
|
|
||||||
});
|
|
||||||
exportEntries.push(
|
|
||||||
"export { IconoirProvider, IconoirContext, IconoirContextValue } from './IconoirContext'",
|
|
||||||
);
|
|
||||||
return exportEntries.join('\n');
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = template;
|
|
|
@ -1,13 +0,0 @@
|
||||||
const path = require('path');
|
|
||||||
|
|
||||||
function template(filePaths) {
|
|
||||||
const exportEntries = filePaths.map((filePath) => {
|
|
||||||
const basename = path.basename(filePath, path.extname(filePath));
|
|
||||||
const exportName = /^\d/.test(basename) ? `Svg${basename}` : basename;
|
|
||||||
return `export { default as ${exportName} } from './${filePath}'`;
|
|
||||||
});
|
|
||||||
|
|
||||||
return exportEntries.join('\n');
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = template;
|
|
|
@ -1,7 +0,0 @@
|
||||||
const template =
|
|
||||||
() => `import type { InjectionKey, SVGAttributes } from "vue-demi";
|
|
||||||
const providerKey = Symbol() as InjectionKey<SVGAttributes>;
|
|
||||||
export default providerKey;
|
|
||||||
`;
|
|
||||||
|
|
||||||
module.exports = template;
|
|
|
@ -1,15 +0,0 @@
|
||||||
const template = (keyFileName) => `<script setup lang="ts">
|
|
||||||
import { provide } from "vue-demi";
|
|
||||||
import type { SVGAttributes } from "vue-demi";
|
|
||||||
import providerKey from "./${keyFileName}";
|
|
||||||
interface Props {
|
|
||||||
iconProps: SVGAttributes
|
|
||||||
}
|
|
||||||
const props = defineProps<Props>();
|
|
||||||
provide(providerKey, props.iconProps);
|
|
||||||
</script>
|
|
||||||
<template>
|
|
||||||
<slot />
|
|
||||||
</template>`;
|
|
||||||
|
|
||||||
module.exports = template;
|
|
17
constants.js
|
@ -1,17 +0,0 @@
|
||||||
export const incompatibleNames = {
|
|
||||||
'1st-medal': 'medal-1st',
|
|
||||||
'4k-display': 'display-4k',
|
|
||||||
'2x2-cell': 'cell-2x2',
|
|
||||||
'360-view': 'view360',
|
|
||||||
github: 'gitHub',
|
|
||||||
'github-outline': 'gitHubOutline',
|
|
||||||
'gitlab-full': 'gitLabFull',
|
|
||||||
linkedin: 'linkedIn',
|
|
||||||
tiktok: 'tikTok',
|
|
||||||
youtube: 'youTube',
|
|
||||||
};
|
|
||||||
|
|
||||||
export const flutterIncompatibleNames = {
|
|
||||||
...incompatibleNames,
|
|
||||||
'color-filter': 'color-filter-icon',
|
|
||||||
};
|
|
22
css/iconoir-regular.css
Normal file
22
css/iconoir-solid.css
Normal file
36
examples/next/.gitignore
vendored
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
|
||||||
|
|
||||||
|
# dependencies
|
||||||
|
/node_modules
|
||||||
|
/.pnp
|
||||||
|
.pnp.js
|
||||||
|
.yarn/install-state.gz
|
||||||
|
|
||||||
|
# testing
|
||||||
|
/coverage
|
||||||
|
|
||||||
|
# next.js
|
||||||
|
/.next/
|
||||||
|
/out/
|
||||||
|
|
||||||
|
# production
|
||||||
|
/build
|
||||||
|
|
||||||
|
# misc
|
||||||
|
.DS_Store
|
||||||
|
*.pem
|
||||||
|
|
||||||
|
# debug
|
||||||
|
npm-debug.log*
|
||||||
|
yarn-debug.log*
|
||||||
|
yarn-error.log*
|
||||||
|
|
||||||
|
# local env files
|
||||||
|
.env*.local
|
||||||
|
|
||||||
|
# vercel
|
||||||
|
.vercel
|
||||||
|
|
||||||
|
# typescript
|
||||||
|
*.tsbuildinfo
|
||||||
|
next-env.d.ts
|
17
examples/next/app/layout.tsx
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
import type { Metadata } from 'next';
|
||||||
|
|
||||||
|
export const metadata: Metadata = {
|
||||||
|
title: 'Iconoir',
|
||||||
|
};
|
||||||
|
|
||||||
|
export default function RootLayout({
|
||||||
|
children,
|
||||||
|
}: {
|
||||||
|
children: React.ReactNode;
|
||||||
|
}) {
|
||||||
|
return (
|
||||||
|
<html lang="en">
|
||||||
|
<body>{children}</body>
|
||||||
|
</html>
|
||||||
|
);
|
||||||
|
}
|
15
examples/next/app/page.tsx
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
import { Iconoir, Medal1st, Medal1stSolid } from 'iconoir-react';
|
||||||
|
import { AdobeAfterEffects as AdobeAfterEffectsRegular } from 'iconoir-react/regular';
|
||||||
|
import { AdobeAfterEffects as AdobeAfterEffectsSolid } from 'iconoir-react/solid';
|
||||||
|
|
||||||
|
export default function Home() {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Iconoir />
|
||||||
|
<Medal1st />
|
||||||
|
<Medal1stSolid />
|
||||||
|
<AdobeAfterEffectsRegular color="red" />
|
||||||
|
<AdobeAfterEffectsSolid color="green" />
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
8
examples/next/next.config.js
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
/** @type {import('next').NextConfig} */
|
||||||
|
const nextConfig = {
|
||||||
|
experimental: {
|
||||||
|
optimizePackageImports: ['iconoir-react'],
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = nextConfig;
|
22
examples/next/package.json
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
{
|
||||||
|
"name": "next",
|
||||||
|
"private": true,
|
||||||
|
"scripts": {
|
||||||
|
"dev": "next dev",
|
||||||
|
"build": "next build",
|
||||||
|
"start": "next start",
|
||||||
|
"lint": "next lint"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"next": "14.0.0",
|
||||||
|
"react": "^18",
|
||||||
|
"react-dom": "^18"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@types/node": "^20",
|
||||||
|
"@types/react": "^18",
|
||||||
|
"@types/react-dom": "^18",
|
||||||
|
"iconoir-react": "workspace:*",
|
||||||
|
"typescript": "^5"
|
||||||
|
}
|
||||||
|
}
|
1
examples/next/public/next.svg
Normal file
|
@ -0,0 +1 @@
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 394 80"><path fill="#000" d="M262 0h68.5v12.7h-27.2v66.6h-13.6V12.7H262V0ZM149 0v12.7H94v20.4h44.3v12.6H94v21h55v12.6H80.5V0h68.7zm34.3 0h-17.8l63.8 79.4h17.9l-32-39.7 32-39.6h-17.9l-23 28.6-23-28.6zm18.3 56.7-9-11-27.1 33.7h17.8l18.3-22.7z"/><path fill="#000" d="M81 79.3 17 0H0v79.3h13.6V17l50.2 62.3H81Zm252.6-.4c-1 0-1.8-.4-2.5-1s-1.1-1.6-1.1-2.6.3-1.8 1-2.5 1.6-1 2.6-1 1.8.3 2.5 1a3.4 3.4 0 0 1 .6 4.3 3.7 3.7 0 0 1-3 1.8zm23.2-33.5h6v23.3c0 2.1-.4 4-1.3 5.5a9.1 9.1 0 0 1-3.8 3.5c-1.6.8-3.5 1.3-5.7 1.3-2 0-3.7-.4-5.3-1s-2.8-1.8-3.7-3.2c-.9-1.3-1.4-3-1.4-5h6c.1.8.3 1.6.7 2.2s1 1.2 1.6 1.5c.7.4 1.5.5 2.4.5 1 0 1.8-.2 2.4-.6a4 4 0 0 0 1.6-1.8c.3-.8.5-1.8.5-3V45.5zm30.9 9.1a4.4 4.4 0 0 0-2-3.3 7.5 7.5 0 0 0-4.3-1.1c-1.3 0-2.4.2-3.3.5-.9.4-1.6 1-2 1.6a3.5 3.5 0 0 0-.3 4c.3.5.7.9 1.3 1.2l1.8 1 2 .5 3.2.8c1.3.3 2.5.7 3.7 1.2a13 13 0 0 1 3.2 1.8 8.1 8.1 0 0 1 3 6.5c0 2-.5 3.7-1.5 5.1a10 10 0 0 1-4.4 3.5c-1.8.8-4.1 1.2-6.8 1.2-2.6 0-4.9-.4-6.8-1.2-2-.8-3.4-2-4.5-3.5a10 10 0 0 1-1.7-5.6h6a5 5 0 0 0 3.5 4.6c1 .4 2.2.6 3.4.6 1.3 0 2.5-.2 3.5-.6 1-.4 1.8-1 2.4-1.7a4 4 0 0 0 .8-2.4c0-.9-.2-1.6-.7-2.2a11 11 0 0 0-2.1-1.4l-3.2-1-3.8-1c-2.8-.7-5-1.7-6.6-3.2a7.2 7.2 0 0 1-2.4-5.7 8 8 0 0 1 1.7-5 10 10 0 0 1 4.3-3.5c2-.8 4-1.2 6.4-1.2 2.3 0 4.4.4 6.2 1.2 1.8.8 3.2 2 4.3 3.4 1 1.4 1.5 3 1.5 5h-5.8z"/></svg>
|
After Width: | Height: | Size: 1.3 KiB |
1
examples/next/public/vercel.svg
Normal file
|
@ -0,0 +1 @@
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 283 64"><path fill="black" d="M141 16c-11 0-19 7-19 18s9 18 20 18c7 0 13-3 16-7l-7-5c-2 3-6 4-9 4-5 0-9-3-10-7h28v-3c0-11-8-18-19-18zm-9 15c1-4 4-7 9-7s8 3 9 7h-18zm117-15c-11 0-19 7-19 18s9 18 20 18c6 0 12-3 16-7l-8-5c-2 3-5 4-8 4-5 0-9-3-11-7h28l1-3c0-11-8-18-19-18zm-10 15c2-4 5-7 10-7s8 3 9 7h-19zm-39 3c0 6 4 10 10 10 4 0 7-2 9-5l8 5c-3 5-9 8-17 8-11 0-19-7-19-18s8-18 19-18c8 0 14 3 17 8l-8 5c-2-3-5-5-9-5-6 0-10 4-10 10zm83-29v46h-9V5h9zM37 0l37 64H0L37 0zm92 5-27 48L74 5h10l18 30 17-30h10zm59 12v10l-3-1c-6 0-10 4-10 10v15h-9V17h9v9c0-5 6-9 13-9z"/></svg>
|
After Width: | Height: | Size: 629 B |
27
examples/next/tsconfig.json
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"target": "es5",
|
||||||
|
"lib": ["dom", "dom.iterable", "esnext"],
|
||||||
|
"allowJs": true,
|
||||||
|
"skipLibCheck": true,
|
||||||
|
"strict": true,
|
||||||
|
"noEmit": true,
|
||||||
|
"esModuleInterop": true,
|
||||||
|
"module": "esnext",
|
||||||
|
"moduleResolution": "bundler",
|
||||||
|
"resolveJsonModule": true,
|
||||||
|
"isolatedModules": true,
|
||||||
|
"jsx": "preserve",
|
||||||
|
"incremental": true,
|
||||||
|
"plugins": [
|
||||||
|
{
|
||||||
|
"name": "next"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"paths": {
|
||||||
|
"@/*": ["./*"]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
|
||||||
|
"exclude": ["node_modules"]
|
||||||
|
}
|
|
@ -1,5 +1,10 @@
|
||||||
{
|
{
|
||||||
"extends": ["next/core-web-vitals"],
|
"extends": ["next/core-web-vitals"],
|
||||||
|
"settings": {
|
||||||
|
"next": {
|
||||||
|
"rootDir": "iconoir.com"
|
||||||
|
}
|
||||||
|
},
|
||||||
"rules": {
|
"rules": {
|
||||||
"react/no-unescaped-entities": ["off"]
|
"react/no-unescaped-entities": ["off"]
|
||||||
},
|
},
|
||||||
|
|
|
@ -4,19 +4,24 @@ import styled from 'styled-components';
|
||||||
export function Ad() {
|
export function Ad() {
|
||||||
const containerRef = React.useRef<HTMLDivElement>(null);
|
const containerRef = React.useRef<HTMLDivElement>(null);
|
||||||
const addedScript = React.useRef(false);
|
const addedScript = React.useRef(false);
|
||||||
|
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
const container = containerRef.current;
|
const container = containerRef.current;
|
||||||
|
|
||||||
if (container && !addedScript.current) {
|
if (container && !addedScript.current) {
|
||||||
addedScript.current = true;
|
addedScript.current = true;
|
||||||
const script = document.createElement('script');
|
const script = document.createElement('script');
|
||||||
script.async = true;
|
script.async = true;
|
||||||
script.type = 'text/javascript';
|
script.type = 'text/javascript';
|
||||||
|
|
||||||
script.src =
|
script.src =
|
||||||
'//cdn.carbonads.com/carbon.js?serve=CESDK5QJ&placement=iconoircom';
|
'//cdn.carbonads.com/carbon.js?serve=CESDK5QJ&placement=iconoircom';
|
||||||
|
|
||||||
script.id = '_carbonads_js';
|
script.id = '_carbonads_js';
|
||||||
container.appendChild(script);
|
container.appendChild(script);
|
||||||
}
|
}
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
return <AdContainer ref={containerRef} />;
|
return <AdContainer ref={containerRef} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,6 +19,7 @@ function playWithLines1(setInstances: SetInstances): anime.AnimeInstance[] {
|
||||||
}),
|
}),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
function playWithLines2(setInstances: SetInstances): anime.AnimeInstance[] {
|
function playWithLines2(setInstances: SetInstances): anime.AnimeInstance[] {
|
||||||
return [
|
return [
|
||||||
anime({
|
anime({
|
||||||
|
@ -34,6 +35,7 @@ function playWithLines2(setInstances: SetInstances): anime.AnimeInstance[] {
|
||||||
}),
|
}),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
function playWithLines3(setInstances: SetInstances): anime.AnimeInstance[] {
|
function playWithLines3(setInstances: SetInstances): anime.AnimeInstance[] {
|
||||||
return [
|
return [
|
||||||
anime({
|
anime({
|
||||||
|
@ -58,6 +60,7 @@ function playWithLines3(setInstances: SetInstances): anime.AnimeInstance[] {
|
||||||
}),
|
}),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
function playWithLines4(setInstances: SetInstances): anime.AnimeInstance[] {
|
function playWithLines4(setInstances: SetInstances): anime.AnimeInstance[] {
|
||||||
return [
|
return [
|
||||||
anime({
|
anime({
|
||||||
|
@ -76,16 +79,19 @@ function playWithLines4(setInstances: SetInstances): anime.AnimeInstance[] {
|
||||||
|
|
||||||
export function AnimatedSvg() {
|
export function AnimatedSvg() {
|
||||||
const instancesRef = React.useRef<anime.AnimeInstance[] | null>(null);
|
const instancesRef = React.useRef<anime.AnimeInstance[] | null>(null);
|
||||||
|
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
instancesRef.current = playWithLines1((instances) => {
|
instancesRef.current = playWithLines1((instances) => {
|
||||||
instancesRef.current = instances;
|
instancesRef.current = instances;
|
||||||
});
|
});
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
for (const instance of instancesRef.current || []) {
|
for (const instance of instancesRef.current || []) {
|
||||||
instance.pause();
|
instance.pause();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<svg
|
<svg
|
||||||
className="playWithLines2"
|
className="playWithLines2"
|
||||||
|
|
|
@ -10,6 +10,7 @@ import { Text14 } from './Typography';
|
||||||
|
|
||||||
export function AvailableFor() {
|
export function AvailableFor() {
|
||||||
const { ref, width } = useResizeObserver();
|
const { ref, width } = useResizeObserver();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<MobileHeader>Available For</MobileHeader>
|
<MobileHeader>Available For</MobileHeader>
|
||||||
|
|
|
@ -25,6 +25,7 @@ export function ChangelogEntry({
|
||||||
const [expanded, setExpanded] = React.useState(false);
|
const [expanded, setExpanded] = React.useState(false);
|
||||||
const [shouldExpand, setShouldExpand] = React.useState(false);
|
const [shouldExpand, setShouldExpand] = React.useState(false);
|
||||||
const containerRef = React.useRef<HTMLDivElement>(null);
|
const containerRef = React.useRef<HTMLDivElement>(null);
|
||||||
|
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
if (
|
if (
|
||||||
containerRef.current &&
|
containerRef.current &&
|
||||||
|
@ -33,6 +34,7 @@ export function ChangelogEntry({
|
||||||
setShouldExpand(true);
|
setShouldExpand(true);
|
||||||
}
|
}
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Container ref={containerRef}>
|
<Container ref={containerRef}>
|
||||||
<ContainerLeft>
|
<ContainerLeft>
|
||||||
|
|
|
@ -21,6 +21,7 @@ export function CustomizationEditor({
|
||||||
const [strokeWidth, setStrokeWidth] = React.useState(
|
const [strokeWidth, setStrokeWidth] = React.useState(
|
||||||
customizations.strokeWidth,
|
customizations.strokeWidth,
|
||||||
);
|
);
|
||||||
|
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
setColor(customizations.hexColor);
|
setColor(customizations.hexColor);
|
||||||
setSize(customizations.size);
|
setSize(customizations.size);
|
||||||
|
|
|
@ -17,9 +17,11 @@ export function DocumentationNavigation({
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const activePath = router.asPath.replace('/docs/', '');
|
const activePath = router.asPath.replace('/docs/', '');
|
||||||
const [expandedTitles, setExpandedTitles] = React.useState<string[]>([]);
|
const [expandedTitles, setExpandedTitles] = React.useState<string[]>([]);
|
||||||
|
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
const expandedItems = documentationItems.filter((item) => {
|
const expandedItems = documentationItems.filter((item) => {
|
||||||
const normalized = activePath.replace((pathPrefix || []).join('/'), '');
|
const normalized = activePath.replace((pathPrefix || []).join('/'), '');
|
||||||
|
|
||||||
return (
|
return (
|
||||||
normalized === item.path ||
|
normalized === item.path ||
|
||||||
item.children?.some((child) => {
|
item.children?.some((child) => {
|
||||||
|
@ -31,20 +33,24 @@ export function DocumentationNavigation({
|
||||||
});
|
});
|
||||||
setExpandedTitles(expandedItems.map((item) => item.title));
|
setExpandedTitles(expandedItems.map((item) => item.title));
|
||||||
}, [activePath, pathPrefix, documentationItems]);
|
}, [activePath, pathPrefix, documentationItems]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{documentationItems.map((documentationItem) => {
|
{documentationItems.map((documentationItem) => {
|
||||||
const path = [...(pathPrefix || []), documentationItem.path]
|
const path = [...(pathPrefix || []), documentationItem.path]
|
||||||
.filter(Boolean)
|
.filter(Boolean)
|
||||||
.join('/');
|
.join('/');
|
||||||
|
|
||||||
if (documentationItem.children?.length) {
|
if (documentationItem.children?.length) {
|
||||||
const active = expandedTitles.includes(documentationItem.title);
|
const active = expandedTitles.includes(documentationItem.title);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<React.Fragment key={documentationItem.title}>
|
<React.Fragment key={documentationItem.title}>
|
||||||
<HeaderItem
|
<HeaderItem
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setExpandedTitles((et) => {
|
setExpandedTitles((et) => {
|
||||||
const includes = et.includes(documentationItem.title);
|
const includes = et.includes(documentationItem.title);
|
||||||
|
|
||||||
return includes
|
return includes
|
||||||
? et.filter((i) => i !== documentationItem.title)
|
? et.filter((i) => i !== documentationItem.title)
|
||||||
: [...et, documentationItem.title];
|
: [...et, documentationItem.title];
|
||||||
|
|
|
@ -15,6 +15,7 @@ export interface ExploreProps {
|
||||||
export function Explore({ allIcons }: ExploreProps) {
|
export function Explore({ allIcons }: ExploreProps) {
|
||||||
const [filters, setFilters] = React.useState<IconListFilters>({});
|
const [filters, setFilters] = React.useState<IconListFilters>({});
|
||||||
const [customizations, setCustomizations] = useCustomizationPersistence();
|
const [customizations, setCustomizations] = useCustomizationPersistence();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Container>
|
<Container>
|
||||||
<Left>
|
<Left>
|
||||||
|
|
|
@ -14,12 +14,15 @@ export function FiltersEditor({ filters, onChange }: FiltersEditorProps) {
|
||||||
// Keep track if the user hits tab before scrolling, so we can scroll the search
|
// Keep track if the user hits tab before scrolling, so we can scroll the search
|
||||||
// field to the top of the page automatically.
|
// field to the top of the page automatically.
|
||||||
const didScrollRef = React.useRef(false);
|
const didScrollRef = React.useRef(false);
|
||||||
|
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
const scrollEvent = () => {
|
const scrollEvent = () => {
|
||||||
didScrollRef.current = true;
|
didScrollRef.current = true;
|
||||||
window.removeEventListener('scroll', scrollEvent);
|
window.removeEventListener('scroll', scrollEvent);
|
||||||
};
|
};
|
||||||
|
|
||||||
window.addEventListener('scroll', scrollEvent);
|
window.addEventListener('scroll', scrollEvent);
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
window.removeEventListener('scroll', scrollEvent);
|
window.removeEventListener('scroll', scrollEvent);
|
||||||
};
|
};
|
||||||
|
|
|
@ -14,6 +14,7 @@ export interface FooterCategoryProps {
|
||||||
category: string;
|
category: string;
|
||||||
links: { name: string; url: string }[];
|
links: { name: string; url: string }[];
|
||||||
}
|
}
|
||||||
|
|
||||||
function FooterCategory({ category, links }: FooterCategoryProps) {
|
function FooterCategory({ category, links }: FooterCategoryProps) {
|
||||||
return (
|
return (
|
||||||
<FooterCategoryContainer>
|
<FooterCategoryContainer>
|
||||||
|
@ -28,6 +29,7 @@ function FooterCategory({ category, links }: FooterCategoryProps) {
|
||||||
</FooterCategoryContainer>
|
</FooterCategoryContainer>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function Footer() {
|
export function Footer() {
|
||||||
return (
|
return (
|
||||||
<Container>
|
<Container>
|
||||||
|
|
|
@ -15,6 +15,7 @@ export interface HeaderProps {
|
||||||
}
|
}
|
||||||
export function Header({ currentVersion }: HeaderProps) {
|
export function Header({ currentVersion }: HeaderProps) {
|
||||||
const [menuVisible, setMenuVisible] = React.useState(false);
|
const [menuVisible, setMenuVisible] = React.useState(false);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Container>
|
<Container>
|
||||||
<HeaderLeft>
|
<HeaderLeft>
|
||||||
|
@ -69,6 +70,7 @@ export const LogoContainer = styled.div`
|
||||||
transition: 0.2s;
|
transition: 0.2s;
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const MobileMenuButton = styled(ResetButton)`
|
const MobileMenuButton = styled(ResetButton)`
|
||||||
&&& {
|
&&& {
|
||||||
z-index: 101;
|
z-index: 101;
|
||||||
|
@ -156,6 +158,7 @@ const HeaderRight = styled(HeaderItem)`
|
||||||
justify-content: flex-end;
|
justify-content: flex-end;
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export const Logo = styled.img`
|
export const Logo = styled.img`
|
||||||
height: 24px;
|
height: 24px;
|
||||||
margin-top: -4px;
|
margin-top: -4px;
|
||||||
|
@ -171,6 +174,7 @@ export const LogoIcon = styled.div`
|
||||||
height: 36px;
|
height: 36px;
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const BuiltWith = styled(Text15)<{ $isMobile?: boolean }>`
|
const BuiltWith = styled(Text15)<{ $isMobile?: boolean }>`
|
||||||
&&& {
|
&&& {
|
||||||
display: ${(props) => (props.$isMobile ? 'flex' : 'none')};
|
display: ${(props) => (props.$isMobile ? 'flex' : 'none')};
|
||||||
|
|
|
@ -19,10 +19,12 @@ export function HeaderBackground({ children }: HeaderBackgroundProps) {
|
||||||
const handleMouseMove = (event: MouseEvent) => {
|
const handleMouseMove = (event: MouseEvent) => {
|
||||||
const x = event.clientX / window.innerWidth;
|
const x = event.clientX / window.innerWidth;
|
||||||
const y = event.clientY / window.innerHeight;
|
const y = event.clientY / window.innerHeight;
|
||||||
|
|
||||||
parallaxElements.forEach((el) => {
|
parallaxElements.forEach((el) => {
|
||||||
const factor = parseFloat(
|
const factor = parseFloat(
|
||||||
el.getAttribute('data-parallax-factor') || '1',
|
el.getAttribute('data-parallax-factor') || '1',
|
||||||
);
|
);
|
||||||
|
|
||||||
(el as HTMLElement).style.transform = `translate3d(${
|
(el as HTMLElement).style.transform = `translate3d(${
|
||||||
x * factor * 40
|
x * factor * 40
|
||||||
}px, ${y * factor * 80}px, 0)`;
|
}px, ${y * factor * 80}px, 0)`;
|
||||||
|
|
|
@ -6,6 +6,7 @@ import { ResetButton } from './Button';
|
||||||
import { DEFAULT_CUSTOMIZATIONS, Icon as IconType } from './IconList';
|
import { DEFAULT_CUSTOMIZATIONS, Icon as IconType } from './IconList';
|
||||||
|
|
||||||
const HEADER = '<?xml version="1.0" encoding="UTF-8"?>';
|
const HEADER = '<?xml version="1.0" encoding="UTF-8"?>';
|
||||||
|
|
||||||
function bakeSvg(
|
function bakeSvg(
|
||||||
svgString: string,
|
svgString: string,
|
||||||
color: string,
|
color: string,
|
||||||
|
@ -33,12 +34,14 @@ export function Icon({ iconWidth, icon }: IconProps) {
|
||||||
const htmlContentsRef = React.useRef<string>('');
|
const htmlContentsRef = React.useRef<string>('');
|
||||||
const iconContext = React.useContext(AllIcons.IconoirContext);
|
const iconContext = React.useContext(AllIcons.IconoirContext);
|
||||||
const [supportsClipboard, setSupportsClipboard] = React.useState(false);
|
const [supportsClipboard, setSupportsClipboard] = React.useState(false);
|
||||||
|
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
setSupportsClipboard(
|
setSupportsClipboard(
|
||||||
typeof window !== 'undefined' &&
|
typeof window !== 'undefined' &&
|
||||||
typeof window?.navigator?.clipboard?.writeText !== 'undefined',
|
typeof window?.navigator?.clipboard?.writeText !== 'undefined',
|
||||||
);
|
);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
if (iconContainerRef.current) {
|
if (iconContainerRef.current) {
|
||||||
htmlContentsRef.current = bakeSvg(
|
htmlContentsRef.current = bakeSvg(
|
||||||
|
@ -48,16 +51,19 @@ export function Icon({ iconWidth, icon }: IconProps) {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}, [iconContext, supportsClipboard]);
|
}, [iconContext, supportsClipboard]);
|
||||||
|
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
const element =
|
const element =
|
||||||
downloadRef.current ||
|
downloadRef.current ||
|
||||||
(iconContainerRef.current as unknown as HTMLAnchorElement);
|
(iconContainerRef.current as unknown as HTMLAnchorElement);
|
||||||
|
|
||||||
if (element) {
|
if (element) {
|
||||||
element.href = `data:image/svg+xml;base64,${btoa(
|
element.href = `data:image/svg+xml;base64,${btoa(
|
||||||
htmlContentsRef.current,
|
htmlContentsRef.current,
|
||||||
)}`;
|
)}`;
|
||||||
}
|
}
|
||||||
}, [iconContext, supportsClipboard]);
|
}, [iconContext, supportsClipboard]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={'icon-container'}>
|
<div className={'icon-container'}>
|
||||||
<BorderContainer $iconWidth={iconWidth}>
|
<BorderContainer $iconWidth={iconWidth}>
|
||||||
|
@ -75,8 +81,6 @@ export function Icon({ iconWidth, icon }: IconProps) {
|
||||||
<IconComponent />
|
<IconComponent />
|
||||||
|
|
||||||
{icon.filename.includes('-solid') ? <IconTag>SOLID</IconTag> : ''}
|
{icon.filename.includes('-solid') ? <IconTag>SOLID</IconTag> : ''}
|
||||||
|
|
||||||
|
|
||||||
</IconContainer>
|
</IconContainer>
|
||||||
{supportsClipboard ? (
|
{supportsClipboard ? (
|
||||||
<HoverContainer>
|
<HoverContainer>
|
||||||
|
|
|
@ -42,6 +42,7 @@ function filterIcons(allIcons: Icon[], filters: IconListFilters): Icon[] {
|
||||||
if (filters.search) {
|
if (filters.search) {
|
||||||
const normalSearch = normalizeString(filters.search!);
|
const normalSearch = normalizeString(filters.search!);
|
||||||
let result = allIcons;
|
let result = allIcons;
|
||||||
|
|
||||||
for (const term of normalSearch.split(' ')) {
|
for (const term of normalSearch.split(' ')) {
|
||||||
result = result.filter((icon) => {
|
result = result.filter((icon) => {
|
||||||
return (
|
return (
|
||||||
|
@ -51,6 +52,7 @@ function filterIcons(allIcons: Icon[], filters: IconListFilters): Icon[] {
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
} else return allIcons;
|
} else return allIcons;
|
||||||
}
|
}
|
||||||
|
@ -63,6 +65,7 @@ interface IconIconsRow {
|
||||||
icons: Icon[];
|
icons: Icon[];
|
||||||
}
|
}
|
||||||
type IconRow = IconCategoryRow | IconIconsRow;
|
type IconRow = IconCategoryRow | IconIconsRow;
|
||||||
|
|
||||||
function isCategoryRow(iconRow: IconRow): iconRow is IconCategoryRow {
|
function isCategoryRow(iconRow: IconRow): iconRow is IconCategoryRow {
|
||||||
return !!(iconRow as IconCategoryRow).category;
|
return !!(iconRow as IconCategoryRow).category;
|
||||||
}
|
}
|
||||||
|
@ -72,6 +75,7 @@ function getRowsFromIcons(
|
||||||
iconsPerRow: number,
|
iconsPerRow: number,
|
||||||
): IconRow[] {
|
): IconRow[] {
|
||||||
const categoryGroups: Record<string, Icon[]> = {};
|
const categoryGroups: Record<string, Icon[]> = {};
|
||||||
|
|
||||||
for (const icon of filteredIcons) {
|
for (const icon of filteredIcons) {
|
||||||
if (!categoryGroups[icon.category]) categoryGroups[icon.category] = [];
|
if (!categoryGroups[icon.category]) categoryGroups[icon.category] = [];
|
||||||
categoryGroups[icon.category].push(icon);
|
categoryGroups[icon.category].push(icon);
|
||||||
|
@ -79,12 +83,15 @@ function getRowsFromIcons(
|
||||||
|
|
||||||
const result: IconRow[] = [];
|
const result: IconRow[] = [];
|
||||||
const sortedCategories = Object.keys(categoryGroups).sort();
|
const sortedCategories = Object.keys(categoryGroups).sort();
|
||||||
|
|
||||||
for (const sortedCategory of sortedCategories) {
|
for (const sortedCategory of sortedCategories) {
|
||||||
result.push({
|
result.push({
|
||||||
category: sortedCategory,
|
category: sortedCategory,
|
||||||
numIcons: categoryGroups[sortedCategory].length,
|
numIcons: categoryGroups[sortedCategory].length,
|
||||||
});
|
});
|
||||||
|
|
||||||
const iconRows = chunk(categoryGroups[sortedCategory], iconsPerRow);
|
const iconRows = chunk(categoryGroups[sortedCategory], iconsPerRow);
|
||||||
|
|
||||||
for (const iconRow of iconRows) {
|
for (const iconRow of iconRows) {
|
||||||
result.push({ icons: iconRow });
|
result.push({ icons: iconRow });
|
||||||
}
|
}
|
||||||
|
@ -97,6 +104,7 @@ const ICON_BOTTOM_PADDING = 65;
|
||||||
const HEADER_HEIGHT = 150;
|
const HEADER_HEIGHT = 150;
|
||||||
const HEADER_INNER_HEIGHT = 15 + 40;
|
const HEADER_INNER_HEIGHT = 15 + 40;
|
||||||
const HEADER_TOP_PADDING = HEADER_HEIGHT - HEADER_INNER_HEIGHT;
|
const HEADER_TOP_PADDING = HEADER_HEIGHT - HEADER_INNER_HEIGHT;
|
||||||
|
|
||||||
function getItemSize(row: IconRow, iconWidth: number): number {
|
function getItemSize(row: IconRow, iconWidth: number): number {
|
||||||
if (isCategoryRow(row)) {
|
if (isCategoryRow(row)) {
|
||||||
return HEADER_HEIGHT;
|
return HEADER_HEIGHT;
|
||||||
|
@ -129,9 +137,11 @@ export function IconList({ filters, allIcons }: IconListProps) {
|
||||||
const iconWidth = iconsPerRow
|
const iconWidth = iconsPerRow
|
||||||
? Math.floor((width + ICON_SPACE) / iconsPerRow) - ICON_SPACE
|
? Math.floor((width + ICON_SPACE) / iconsPerRow) - ICON_SPACE
|
||||||
: null;
|
: null;
|
||||||
|
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
setHeight(window.innerHeight);
|
setHeight(window.innerHeight);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
if (listRef.current) {
|
if (listRef.current) {
|
||||||
listRef.current.resetAfterIndex(0, true);
|
listRef.current.resetAfterIndex(0, true);
|
||||||
|
@ -140,6 +150,7 @@ export function IconList({ filters, allIcons }: IconListProps) {
|
||||||
|
|
||||||
if (filteredIcons.length && iconsPerRow && width && iconWidth) {
|
if (filteredIcons.length && iconsPerRow && width && iconWidth) {
|
||||||
const iconRows = getRowsFromIcons(filteredIcons, iconsPerRow);
|
const iconRows = getRowsFromIcons(filteredIcons, iconsPerRow);
|
||||||
|
|
||||||
children = (
|
children = (
|
||||||
<IconListContext.Provider value={{ iconsPerRow, iconWidth }}>
|
<IconListContext.Provider value={{ iconsPerRow, iconWidth }}>
|
||||||
<ReactWindowScroller>
|
<ReactWindowScroller>
|
||||||
|
@ -187,6 +198,7 @@ const Row = React.memo(
|
||||||
({ data, index, style }: ListChildComponentProps<IconRow[]>) => {
|
({ data, index, style }: ListChildComponentProps<IconRow[]>) => {
|
||||||
const { iconWidth } = React.useContext(IconListContext)!;
|
const { iconWidth } = React.useContext(IconListContext)!;
|
||||||
const row = data[index];
|
const row = data[index];
|
||||||
|
|
||||||
if (isCategoryRow(row)) {
|
if (isCategoryRow(row)) {
|
||||||
return (
|
return (
|
||||||
<CategoryRow
|
<CategoryRow
|
||||||
|
|
|
@ -12,6 +12,7 @@ export interface NavigationItemProps {
|
||||||
}
|
}
|
||||||
export function NavigationItem({ href, children, style }: NavigationItemProps) {
|
export function NavigationItem({ href, children, style }: NavigationItemProps) {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Link href={href} passHref legacyBehavior>
|
<Link href={href} passHref legacyBehavior>
|
||||||
<NavigationItemContainer
|
<NavigationItemContainer
|
||||||
|
|
|
@ -4,9 +4,11 @@ import { PraiseItem } from './PraiseItem';
|
||||||
import { media } from '../lib/responsive';
|
import { media } from '../lib/responsive';
|
||||||
|
|
||||||
const NUM_PRAISE_ITEMS = 3;
|
const NUM_PRAISE_ITEMS = 3;
|
||||||
|
|
||||||
export function Praise() {
|
export function Praise() {
|
||||||
const containerRef = React.useRef<HTMLDivElement>(null);
|
const containerRef = React.useRef<HTMLDivElement>(null);
|
||||||
const indicatorContainerRef = React.useRef<HTMLDivElement>(null);
|
const indicatorContainerRef = React.useRef<HTMLDivElement>(null);
|
||||||
|
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
if (containerRef.current) {
|
if (containerRef.current) {
|
||||||
const handle = () => {
|
const handle = () => {
|
||||||
|
@ -19,12 +21,14 @@ export function Praise() {
|
||||||
containerRef.current.scrollWidth - window.innerWidth - 100
|
containerRef.current.scrollWidth - window.innerWidth - 100
|
||||||
? indicatorContainerRef.current.children.length - 1
|
? indicatorContainerRef.current.children.length - 1
|
||||||
: Math.round(currentScrollLeft / interval);
|
: Math.round(currentScrollLeft / interval);
|
||||||
|
|
||||||
for (
|
for (
|
||||||
let i = 0;
|
let i = 0;
|
||||||
i < indicatorContainerRef.current.children.length;
|
i < indicatorContainerRef.current.children.length;
|
||||||
i++
|
i++
|
||||||
) {
|
) {
|
||||||
const child = indicatorContainerRef.current.children[i];
|
const child = indicatorContainerRef.current.children[i];
|
||||||
|
|
||||||
if (currentIndex === i) {
|
if (currentIndex === i) {
|
||||||
child.classList.add('active');
|
child.classList.add('active');
|
||||||
} else {
|
} else {
|
||||||
|
@ -33,13 +37,16 @@ export function Praise() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const element = containerRef.current;
|
const element = containerRef.current;
|
||||||
element.addEventListener('scroll', handle);
|
element.addEventListener('scroll', handle);
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
element.removeEventListener('scroll', handle);
|
element.removeEventListener('scroll', handle);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Container ref={containerRef}>
|
<Container ref={containerRef}>
|
||||||
|
|
|
@ -52,6 +52,7 @@ interface ReactWindowScrollerProps<Props extends ListProps | GridProps> {
|
||||||
throttleTime?: number;
|
throttleTime?: number;
|
||||||
isGrid?: boolean;
|
isGrid?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function ReactWindowScroller<
|
export function ReactWindowScroller<
|
||||||
Props extends ListProps | GridProps = ListProps,
|
Props extends ListProps | GridProps = ListProps,
|
||||||
>({
|
>({
|
||||||
|
@ -85,6 +86,7 @@ export function ReactWindowScroller<
|
||||||
}, throttleTime);
|
}, throttleTime);
|
||||||
|
|
||||||
targetElement.addEventListener('scroll', handleWindowScroll);
|
targetElement.addEventListener('scroll', handleWindowScroll);
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
handleWindowScroll.cancel();
|
handleWindowScroll.cancel();
|
||||||
targetElement.removeEventListener('scroll', handleWindowScroll);
|
targetElement.removeEventListener('scroll', handleWindowScroll);
|
||||||
|
@ -98,6 +100,7 @@ export function ReactWindowScroller<
|
||||||
// We have to get rid of the scroll handlers here, because they will cause the list
|
// We have to get rid of the scroll handlers here, because they will cause the list
|
||||||
// to go blank whenever adjusting the number of items.
|
// to go blank whenever adjusting the number of items.
|
||||||
ref.current._onScrollVertical = () => {};
|
ref.current._onScrollVertical = () => {};
|
||||||
|
|
||||||
ref.current._onScrollHorizontal = () => {};
|
ref.current._onScrollHorizontal = () => {};
|
||||||
}, [outerRef]);
|
}, [outerRef]);
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,7 @@ export interface SEOProps {
|
||||||
}
|
}
|
||||||
export function SEO({ title }: SEOProps) {
|
export function SEO({ title }: SEOProps) {
|
||||||
const pageTitle = title ? `${title} | ${TITLE_SUFFIX}` : TITLE_SUFFIX;
|
const pageTitle = title ? `${title} | ${TITLE_SUFFIX}` : TITLE_SUFFIX;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Head>
|
<Head>
|
||||||
<title>{pageTitle}</title>
|
<title>{pageTitle}</title>
|
||||||
|
|
|
@ -47,6 +47,7 @@ interface ThumbProps {
|
||||||
trackRef: React.RefObject<HTMLElement>;
|
trackRef: React.RefObject<HTMLElement>;
|
||||||
index: number;
|
index: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
function Thumb({ state, trackRef, index }: ThumbProps) {
|
function Thumb({ state, trackRef, index }: ThumbProps) {
|
||||||
let inputRef = React.useRef(null);
|
let inputRef = React.useRef(null);
|
||||||
let { thumbProps, inputProps } = useSliderThumb(
|
let { thumbProps, inputProps } = useSliderThumb(
|
||||||
|
@ -59,6 +60,7 @@ function Thumb({ state, trackRef, index }: ThumbProps) {
|
||||||
);
|
);
|
||||||
|
|
||||||
let { focusProps, isFocusVisible } = useFocusRing();
|
let { focusProps, isFocusVisible } = useFocusRing();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ThumbContainer
|
<ThumbContainer
|
||||||
style={{
|
style={{
|
||||||
|
|
|
@ -36,6 +36,7 @@ const StatContainer = styled.div`
|
||||||
margin-bottom: 0;
|
margin-bottom: 0;
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export const StatsContainer = styled.div`
|
export const StatsContainer = styled.div`
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: flex-start;
|
align-items: flex-start;
|
||||||
|
|
|
@ -142,12 +142,14 @@ const CopyContainer = styled.div`
|
||||||
export function Pre({ children, ...props }: React.PropsWithChildren<any>) {
|
export function Pre({ children, ...props }: React.PropsWithChildren<any>) {
|
||||||
const containerRef = React.useRef<HTMLPreElement>(null);
|
const containerRef = React.useRef<HTMLPreElement>(null);
|
||||||
const [supportsClipboard, setSupportsClipboard] = React.useState(false);
|
const [supportsClipboard, setSupportsClipboard] = React.useState(false);
|
||||||
|
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
setSupportsClipboard(
|
setSupportsClipboard(
|
||||||
typeof window !== 'undefined' &&
|
typeof window !== 'undefined' &&
|
||||||
typeof window?.navigator?.clipboard?.writeText !== 'undefined',
|
typeof window?.navigator?.clipboard?.writeText !== 'undefined',
|
||||||
);
|
);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<PreContainer {...props}>
|
<PreContainer {...props}>
|
||||||
<pre ref={containerRef}>{children}</pre>
|
<pre ref={containerRef}>{children}</pre>
|
||||||
|
|
|
@ -11,8 +11,10 @@ export function useCustomizationPersistence(): [
|
||||||
const [customizations, _setCustomizations] = React.useState(
|
const [customizations, _setCustomizations] = React.useState(
|
||||||
DEFAULT_CUSTOMIZATIONS,
|
DEFAULT_CUSTOMIZATIONS,
|
||||||
);
|
);
|
||||||
|
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
const localStorageValue = localStorage.getItem(CUSTOMIZATIONS_KEY);
|
const localStorageValue = localStorage.getItem(CUSTOMIZATIONS_KEY);
|
||||||
|
|
||||||
if (localStorageValue) {
|
if (localStorageValue) {
|
||||||
try {
|
try {
|
||||||
const parsedValue = JSON.parse(localStorageValue);
|
const parsedValue = JSON.parse(localStorageValue);
|
||||||
|
@ -30,6 +32,7 @@ export function useCustomizationPersistence(): [
|
||||||
CUSTOMIZATIONS_KEY,
|
CUSTOMIZATIONS_KEY,
|
||||||
JSON.stringify(newCustomizations),
|
JSON.stringify(newCustomizations),
|
||||||
);
|
);
|
||||||
|
|
||||||
_setCustomizations(newCustomizations);
|
_setCustomizations(newCustomizations);
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
|
@ -4,68 +4,73 @@ const path = require('path');
|
||||||
const previewPath = process.argv[2];
|
const previewPath = process.argv[2];
|
||||||
const resultPath = 'icons.csv';
|
const resultPath = 'icons.csv';
|
||||||
const categoryMap = {
|
const categoryMap = {
|
||||||
actions: 'Actions',
|
'actions': 'Actions',
|
||||||
activities: 'Activities',
|
'activities': 'Activities',
|
||||||
analytics: 'Analytics',
|
'analytics': 'Analytics',
|
||||||
animations: 'Animations',
|
'animations': 'Animations',
|
||||||
audio: 'Audio',
|
'audio': 'Audio',
|
||||||
buildings: 'Buildings',
|
'buildings': 'Buildings',
|
||||||
clothing: 'Clothing',
|
'clothing': 'Clothing',
|
||||||
cloud: 'Cloud',
|
'cloud': 'Cloud',
|
||||||
communication: 'Communication',
|
'communication': 'Communication',
|
||||||
'communication-1': 'Communication',
|
'communication-1': 'Communication',
|
||||||
connectivity: 'Connectivity',
|
'connectivity': 'Connectivity',
|
||||||
database: 'Database',
|
'database': 'Database',
|
||||||
designtools: 'Design Tools',
|
'designtools': 'Design Tools',
|
||||||
development: 'Development',
|
'development': 'Development',
|
||||||
devices: 'Devices',
|
'devices': 'Devices',
|
||||||
docs: 'Docs',
|
'docs': 'Docs',
|
||||||
editor: 'Editor',
|
'editor': 'Editor',
|
||||||
'3deditor': '3D Editor',
|
'3deditor': '3D Editor',
|
||||||
emojis: 'Emojis',
|
'emojis': 'Emojis',
|
||||||
finance: 'Finance',
|
'finance': 'Finance',
|
||||||
food: 'Food',
|
'food': 'Food',
|
||||||
gaming: 'Gaming',
|
'gaming': 'Gaming',
|
||||||
gestures: 'Gestures',
|
'gestures': 'Gestures',
|
||||||
git: 'Git',
|
'git': 'Git',
|
||||||
health: 'Health',
|
'health': 'Health',
|
||||||
home: 'Home',
|
'home': 'Home',
|
||||||
identity: 'Identity',
|
'identity': 'Identity',
|
||||||
layout: 'Layout',
|
'layout': 'Layout',
|
||||||
maps: 'Maps',
|
'maps': 'Maps',
|
||||||
music: 'Music',
|
'music': 'Music',
|
||||||
nature: 'Nature',
|
'nature': 'Nature',
|
||||||
navigation: 'Navigation',
|
'navigation': 'Navigation',
|
||||||
organization: 'Organization',
|
'organization': 'Organization',
|
||||||
other: 'Other',
|
'other': 'Other',
|
||||||
photosvideos: 'Photos and Videos',
|
'photosvideos': 'Photos and Videos',
|
||||||
security: 'Security',
|
'security': 'Security',
|
||||||
shapes: 'Shapes',
|
'shapes': 'Shapes',
|
||||||
shopping: 'Shopping',
|
'shopping': 'Shopping',
|
||||||
science: 'Science',
|
'science': 'Science',
|
||||||
social: 'Social',
|
'social': 'Social',
|
||||||
system: 'System',
|
'system': 'System',
|
||||||
transport: 'Transport',
|
'transport': 'Transport',
|
||||||
users: 'Users',
|
'users': 'Users',
|
||||||
weather: 'Weather',
|
'weather': 'Weather',
|
||||||
};
|
};
|
||||||
|
|
||||||
const allIcons = fs.readdirSync(previewPath);
|
const allIcons = fs.readdirSync(previewPath);
|
||||||
const resultLines = ['filename,category,tags'];
|
const resultLines = ['filename,category,tags'];
|
||||||
|
|
||||||
for (const filename of allIcons) {
|
for (const filename of allIcons) {
|
||||||
const [icon, category] = path
|
const [icon, category] = path
|
||||||
.basename(filename)
|
.basename(filename)
|
||||||
.replace(path.extname(filename), '')
|
.replace(path.extname(filename), '')
|
||||||
.split('@');
|
.split('@');
|
||||||
|
|
||||||
if (!icon || !category) {
|
if (!icon || !category) {
|
||||||
console.error('invalid filename %s', filename);
|
console.error('invalid filename %s', filename);
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
const mappedCategory = categoryMap[category];
|
const mappedCategory = categoryMap[category];
|
||||||
|
|
||||||
if (!mappedCategory) {
|
if (!mappedCategory) {
|
||||||
console.error('category %s does not exist', category);
|
console.error('category %s does not exist', category);
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
resultLines.push(`"${icon}","${mappedCategory}",`);
|
resultLines.push(`"${icon}","${mappedCategory}",`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,17 +4,11 @@ filename,category,tags
|
||||||
"accessibility-tech","System","assistance,assistant,impaired",
|
"accessibility-tech","System","assistance,assistant,impaired",
|
||||||
"activity","Other",
|
"activity","Other",
|
||||||
"adobe-after-effects","Design Tools",
|
"adobe-after-effects","Design Tools",
|
||||||
"adobe-after-effects-solid","Design Tools","",
|
|
||||||
"adobe-illustrator","Design Tools",
|
"adobe-illustrator","Design Tools",
|
||||||
"adobe-illustrator-solid","Design Tools","",
|
|
||||||
"adobe-indesign","Design Tools",
|
"adobe-indesign","Design Tools",
|
||||||
"adobe-indesign-solid","Design Tools","",
|
|
||||||
"adobe-lightroom","Design Tools",
|
"adobe-lightroom","Design Tools",
|
||||||
"adobe-lightroom-solid","Design Tools","",
|
|
||||||
"adobe-photoshop","Design Tools",
|
"adobe-photoshop","Design Tools",
|
||||||
"adobe-photoshop-solid","Design Tools","",
|
|
||||||
"adobe-xd","Design Tools",
|
"adobe-xd","Design Tools",
|
||||||
"adobe-xd-solid","Design Tools","",
|
|
||||||
"african-tree","Nature",
|
"african-tree","Nature",
|
||||||
"agile","Business",
|
"agile","Business",
|
||||||
"air-conditioner","Home",
|
"air-conditioner","Home",
|
||||||
|
@ -24,33 +18,23 @@ filename,category,tags
|
||||||
"airplane-off","Transport","fly,jet",
|
"airplane-off","Transport","fly,jet",
|
||||||
"airplane-rotation","Transport","fly,jet",
|
"airplane-rotation","Transport","fly,jet",
|
||||||
"airplay","Connectivity",
|
"airplay","Connectivity",
|
||||||
"airplay-solid","Connectivity","",
|
|
||||||
"alarm","Other",
|
"alarm","Other",
|
||||||
"alarm-solid","Other","",
|
|
||||||
"album","Music",
|
"album","Music",
|
||||||
"album-carousel","Music",
|
"album-carousel","Music",
|
||||||
"album-list","Music",
|
"album-list","Music",
|
||||||
"album-open","Music",
|
"album-open","Music",
|
||||||
"align-bottom-box","Design Tools",
|
"align-bottom-box","Design Tools",
|
||||||
"align-bottom-box-solid","Design Tools","",
|
|
||||||
"align-center","Editor",
|
"align-center","Editor",
|
||||||
"align-horizontal-centers","Design Tools","figma, design",
|
"align-horizontal-centers","Design Tools","figma, design",
|
||||||
"align-horizontal-centers-solid","Design Tools","figma, design",
|
|
||||||
"align-horizontal-spacing","Design Tools","figma, design",
|
"align-horizontal-spacing","Design Tools","figma, design",
|
||||||
"align-horizontal-spacing-solid","Design Tools","figma, design",
|
|
||||||
"align-justify","Editor",
|
"align-justify","Editor",
|
||||||
"align-left","Editor",
|
"align-left","Editor",
|
||||||
"align-left-box","Design Tools",
|
"align-left-box","Design Tools",
|
||||||
"align-left-box-solid","Design Tools","",
|
|
||||||
"align-right","Editor",
|
"align-right","Editor",
|
||||||
"align-right-box","Design Tools",
|
"align-right-box","Design Tools",
|
||||||
"align-right-box-solid","Design Tools","",
|
|
||||||
"align-top-box","Design Tools",
|
"align-top-box","Design Tools",
|
||||||
"align-top-box-solid","Design Tools","",
|
|
||||||
"align-vertical-centers","Design Tools","figma, design",
|
"align-vertical-centers","Design Tools","figma, design",
|
||||||
"align-vertical-centers-solid","Design Tools","",
|
|
||||||
"align-vertical-spacing","Design Tools","figma, design",
|
"align-vertical-spacing","Design Tools","figma, design",
|
||||||
"align-vertical-spacing-solid","Design Tools","",
|
|
||||||
"angle-tool","Tools",
|
"angle-tool","Tools",
|
||||||
"antenna","Connectivity",
|
"antenna","Connectivity",
|
||||||
"antenna-off","Connectivity",
|
"antenna-off","Connectivity",
|
||||||
|
@ -58,7 +42,6 @@ filename,category,tags
|
||||||
"antenna-signal-tag","Connectivity",
|
"antenna-signal-tag","Connectivity",
|
||||||
"app-notification","Communication",
|
"app-notification","Communication",
|
||||||
"app-store","Social","apple, iphone, ios",
|
"app-store","Social","apple, iphone, ios",
|
||||||
"app-store-solid","Social","",
|
|
||||||
"app-window","System",
|
"app-window","System",
|
||||||
"apple","Food",
|
"apple","Food",
|
||||||
"apple-half","Food",
|
"apple-half","Food",
|
||||||
|
@ -66,7 +49,6 @@ filename,category,tags
|
||||||
"apple-imac-2021-side","Devices",
|
"apple-imac-2021-side","Devices",
|
||||||
"apple-mac","System",
|
"apple-mac","System",
|
||||||
"apple-shortcuts","System",
|
"apple-shortcuts","System",
|
||||||
"apple-shortcuts-solid","System","",
|
|
||||||
"apple-swift","Development",
|
"apple-swift","Development",
|
||||||
"apple-wallet","Finance",
|
"apple-wallet","Finance",
|
||||||
"ar-tag","Devices",
|
"ar-tag","Devices",
|
||||||
|
@ -80,27 +62,21 @@ filename,category,tags
|
||||||
"arrow-archery","Activities","sport,activity,arrows",
|
"arrow-archery","Activities","sport,activity,arrows",
|
||||||
"arrow-down","Navigation",
|
"arrow-down","Navigation",
|
||||||
"arrow-down-circle","Navigation",
|
"arrow-down-circle","Navigation",
|
||||||
"arrow-down-circle-solid","Navigation","",
|
|
||||||
"arrow-down-left","Navigation",
|
"arrow-down-left","Navigation",
|
||||||
"arrow-down-left-circle","Navigation",
|
"arrow-down-left-circle","Navigation",
|
||||||
"arrow-down-left-circle-solid","Navigation","",
|
|
||||||
"arrow-down-left-square","Navigation",
|
"arrow-down-left-square","Navigation",
|
||||||
"arrow-down-right","Navigation",
|
"arrow-down-right","Navigation",
|
||||||
"arrow-down-right-circle","Navigation",
|
"arrow-down-right-circle","Navigation",
|
||||||
"arrow-down-right-circle-solid","Navigation","",
|
|
||||||
"arrow-down-right-square","Navigation",
|
"arrow-down-right-square","Navigation",
|
||||||
"arrow-down-right-square-solid","Navigation","",
|
|
||||||
"arrow-down-tag","Navigation",
|
"arrow-down-tag","Navigation",
|
||||||
"arrow-email-forward","Communication",
|
"arrow-email-forward","Communication",
|
||||||
"arrow-enlarge-tag","Navigation",
|
"arrow-enlarge-tag","Navigation",
|
||||||
"arrow-left","Navigation",
|
"arrow-left","Navigation",
|
||||||
"arrow-left-circle","Navigation",
|
"arrow-left-circle","Navigation",
|
||||||
"arrow-left-circle-solid","Navigation","",
|
|
||||||
"arrow-left-tag","Navigation",
|
"arrow-left-tag","Navigation",
|
||||||
"arrow-reduce-tag","Navigation",
|
"arrow-reduce-tag","Navigation",
|
||||||
"arrow-right","Navigation",
|
"arrow-right","Navigation",
|
||||||
"arrow-right-circle","Navigation",
|
"arrow-right-circle","Navigation",
|
||||||
"arrow-right-circle-solid","Navigation","",
|
|
||||||
"arrow-right-tag","Navigation",
|
"arrow-right-tag","Navigation",
|
||||||
"arrow-separate","Navigation",
|
"arrow-separate","Navigation",
|
||||||
"arrow-separate-vertical","Navigation",
|
"arrow-separate-vertical","Navigation",
|
||||||
|
@ -108,17 +84,12 @@ filename,category,tags
|
||||||
"arrow-union-vertical","Navigation",
|
"arrow-union-vertical","Navigation",
|
||||||
"arrow-up","Navigation",
|
"arrow-up","Navigation",
|
||||||
"arrow-up-circle","Navigation",
|
"arrow-up-circle","Navigation",
|
||||||
"arrow-up-circle-solid","Navigation","",
|
|
||||||
"arrow-up-left","Navigation",
|
"arrow-up-left","Navigation",
|
||||||
"arrow-up-left-circle","Navigation",
|
"arrow-up-left-circle","Navigation",
|
||||||
"arrow-up-left-circle-solid","Navigation","",
|
|
||||||
"arrow-up-left-square","Navigation",
|
"arrow-up-left-square","Navigation",
|
||||||
"arrow-up-left-square-solid","Navigation","",
|
|
||||||
"arrow-up-right","Navigation",
|
"arrow-up-right","Navigation",
|
||||||
"arrow-up-right-circle","Navigation",
|
"arrow-up-right-circle","Navigation",
|
||||||
"arrow-up-right-circle-solid","Navigation","",
|
|
||||||
"arrow-up-right-square","Navigation",
|
"arrow-up-right-square","Navigation",
|
||||||
"arrow-up-right-square-solid","Navigation","",
|
|
||||||
"arrow-up-tag","Navigation",
|
"arrow-up-tag","Navigation",
|
||||||
"arrows-up-from-line","Shopping",
|
"arrows-up-from-line","Shopping",
|
||||||
"asana","Development",
|
"asana","Development",
|
||||||
|
@ -139,7 +110,6 @@ filename,category,tags
|
||||||
"basketball","Activities",
|
"basketball","Activities",
|
||||||
"basketball-field","Activities",
|
"basketball-field","Activities",
|
||||||
"bathroom","Buildings","",
|
"bathroom","Buildings","",
|
||||||
"bathroom-solid","Buildings","",
|
|
||||||
"battery-25","System","energy,source,charge",
|
"battery-25","System","energy,source,charge",
|
||||||
"battery-50","System","energy,source,charge",
|
"battery-50","System","energy,source,charge",
|
||||||
"battery-75","System","energy,source,charge",
|
"battery-75","System","energy,source,charge",
|
||||||
|
@ -169,24 +139,18 @@ filename,category,tags
|
||||||
"bishop","Gaming","game,chess",
|
"bishop","Gaming","game,chess",
|
||||||
"bitbucket","Git","git, repository, github",
|
"bitbucket","Git","git, repository, github",
|
||||||
"bitcoin-circle","Finance",
|
"bitcoin-circle","Finance",
|
||||||
"bitcoin-circle-solid","Finance","",
|
|
||||||
"bitcoin-rotate-out","Finance",
|
"bitcoin-rotate-out","Finance",
|
||||||
"bluetooth","Connectivity",
|
"bluetooth","Connectivity",
|
||||||
"bluetooth-tag","Connectivity",
|
"bluetooth-tag","Connectivity",
|
||||||
"bluetooth-tag-solid","Connectivity","",
|
|
||||||
"bold","Editor",
|
"bold","Editor",
|
||||||
"bold-square","Editor",
|
"bold-square","Editor",
|
||||||
"bold-square-solid","Editor","",
|
|
||||||
"bonfire","Activities",
|
"bonfire","Activities",
|
||||||
"book","Activities",
|
"book","Activities",
|
||||||
"book-lock","Activities",
|
"book-lock","Activities",
|
||||||
"book-solid","Activities","",
|
|
||||||
"book-stack","Activities",
|
"book-stack","Activities",
|
||||||
"bookmark","Organization",
|
"bookmark","Organization",
|
||||||
"bookmark-book","Activities",
|
"bookmark-book","Activities",
|
||||||
"bookmark-circle","Organization",
|
"bookmark-circle","Organization",
|
||||||
"bookmark-circle-solid","Organization","",
|
|
||||||
"bookmark-solid","Organization","",
|
|
||||||
"border-bl","Design Tools",
|
"border-bl","Design Tools",
|
||||||
"border-bottom","Design Tools",
|
"border-bottom","Design Tools",
|
||||||
"border-br","Design Tools",
|
"border-br","Design Tools",
|
||||||
|
@ -221,7 +185,6 @@ filename,category,tags
|
||||||
"bubble-income","Communication",
|
"bubble-income","Communication",
|
||||||
"bubble-outcome","Communication",
|
"bubble-outcome","Communication",
|
||||||
"bubble-search","Communication",
|
"bubble-search","Communication",
|
||||||
"bubble-search-solid","Communication","",
|
|
||||||
"bubble-star","Communication",
|
"bubble-star","Communication",
|
||||||
"bubble-upload","Communication",
|
"bubble-upload","Communication",
|
||||||
"bubble-warning","Communication",
|
"bubble-warning","Communication",
|
||||||
|
@ -232,7 +195,6 @@ filename,category,tags
|
||||||
"bus-stop","Transport","transport,station,track,public,shuttle",
|
"bus-stop","Transport","transport,station,track,public,shuttle",
|
||||||
"c-square","Typography","carbon,element",
|
"c-square","Typography","carbon,element",
|
||||||
"cable-tag","Connectivity",
|
"cable-tag","Connectivity",
|
||||||
"cable-tag-solid","Connectivity","",
|
|
||||||
"calculator","System","math,operation",
|
"calculator","System","math,operation",
|
||||||
"calendar","System","organization,organisation,plan,planning,date,day,month,year",
|
"calendar","System","organization,organisation,plan,planning,date,day,month,year",
|
||||||
"calendar-minus","System",
|
"calendar-minus","System",
|
||||||
|
@ -253,7 +215,6 @@ filename,category,tags
|
||||||
"cell-2x2","Layout",
|
"cell-2x2","Layout",
|
||||||
"cellar","Buildings",
|
"cellar","Buildings",
|
||||||
"center-align","Design Tools",
|
"center-align","Design Tools",
|
||||||
"center-align-solid","Design Tools","",
|
|
||||||
"chat-bubble","Communication",
|
"chat-bubble","Communication",
|
||||||
"chat-bubble-check","Communication",
|
"chat-bubble-check","Communication",
|
||||||
"chat-bubble-empty","Communication",
|
"chat-bubble-empty","Communication",
|
||||||
|
@ -266,7 +227,6 @@ filename,category,tags
|
||||||
"chat-plus-in","Communication",
|
"chat-plus-in","Communication",
|
||||||
"check","Actions",
|
"check","Actions",
|
||||||
"check-circle","Actions",
|
"check-circle","Actions",
|
||||||
"check-circle-solid","Actions","",
|
|
||||||
"chocolate","Food",
|
"chocolate","Food",
|
||||||
"chromecast","Devices",
|
"chromecast","Devices",
|
||||||
"chromecast-active","Devices",
|
"chromecast-active","Devices",
|
||||||
|
@ -280,7 +240,6 @@ filename,category,tags
|
||||||
"clipboard-check","Actions",
|
"clipboard-check","Actions",
|
||||||
"clock","Other",
|
"clock","Other",
|
||||||
"clock-rotate-right","Shopping",
|
"clock-rotate-right","Shopping",
|
||||||
"clock-solid","Other","",
|
|
||||||
"closed-captions-tag","Photos and Videos",
|
"closed-captions-tag","Photos and Videos",
|
||||||
"closet","Home",
|
"closet","Home",
|
||||||
"cloud","Weather",
|
"cloud","Weather",
|
||||||
|
@ -289,7 +248,6 @@ filename,category,tags
|
||||||
"cloud-desync","Cloud",
|
"cloud-desync","Cloud",
|
||||||
"cloud-download","Cloud",
|
"cloud-download","Cloud",
|
||||||
"cloud-square","Cloud",
|
"cloud-square","Cloud",
|
||||||
"cloud-square-solid","Cloud","",
|
|
||||||
"cloud-sunny","Weather","weather,clouds",
|
"cloud-sunny","Weather","weather,clouds",
|
||||||
"cloud-sync","Cloud",
|
"cloud-sync","Cloud",
|
||||||
"cloud-upload","Cloud",
|
"cloud-upload","Cloud",
|
||||||
|
@ -311,17 +269,12 @@ filename,category,tags
|
||||||
"commodity","Finance","gold, ingot, bar",
|
"commodity","Finance","gold, ingot, bar",
|
||||||
"community","Users",
|
"community","Users",
|
||||||
"comp-align-bottom","Design Tools","figma, design",
|
"comp-align-bottom","Design Tools","figma, design",
|
||||||
"comp-align-bottom-solid","Design Tools","",
|
|
||||||
"comp-align-left","Design Tools","figma, design",
|
"comp-align-left","Design Tools","figma, design",
|
||||||
"comp-align-left-solid","Design Tools","",
|
|
||||||
"comp-align-right","Design Tools","figma, design",
|
"comp-align-right","Design Tools","figma, design",
|
||||||
"comp-align-right-solid","Design Tools","",
|
|
||||||
"comp-align-top","Design Tools","figma, design",
|
"comp-align-top","Design Tools","figma, design",
|
||||||
"comp-align-top-solid","Design Tools","",
|
|
||||||
"compact-disc","Music",
|
"compact-disc","Music",
|
||||||
"compass","Navigation",
|
"compass","Navigation",
|
||||||
"component","Design Tools","figma, design",
|
"component","Design Tools","figma, design",
|
||||||
"component-solid","Design Tools","",
|
|
||||||
"compress","Other",
|
"compress","Other",
|
||||||
"compress-lines","Editor",
|
"compress-lines","Editor",
|
||||||
"computer","Devices",
|
"computer","Devices",
|
||||||
|
@ -376,7 +329,6 @@ filename,category,tags
|
||||||
"database","Database","db, storage, repo",
|
"database","Database","db, storage, repo",
|
||||||
"database-backup","Database","db, storage, repo",
|
"database-backup","Database","db, storage, repo",
|
||||||
"database-check","Database","db, storage, repo",
|
"database-check","Database","db, storage, repo",
|
||||||
"database-check-solid","Database","",
|
|
||||||
"database-export","Database","db, storage, repo",
|
"database-export","Database","db, storage, repo",
|
||||||
"database-monitor","Database","db, storage, repo",
|
"database-monitor","Database","db, storage, repo",
|
||||||
"database-restore","Database","db, storage, repo",
|
"database-restore","Database","db, storage, repo",
|
||||||
|
@ -385,20 +337,16 @@ filename,category,tags
|
||||||
"database-script-plus","Database",
|
"database-script-plus","Database",
|
||||||
"database-search","Database","db, storage, repo",
|
"database-search","Database","db, storage, repo",
|
||||||
"database-settings","Database","db, storage, repo",
|
"database-settings","Database","db, storage, repo",
|
||||||
"database-solid","Database","",
|
|
||||||
"database-star","Database","db, storage, repo",
|
"database-star","Database","db, storage, repo",
|
||||||
"database-stats","Database","db, storage, repo",
|
"database-stats","Database","db, storage, repo",
|
||||||
"database-tag","Database","db, storage, repo",
|
"database-tag","Database","db, storage, repo",
|
||||||
"database-tag-solid","Database","",
|
|
||||||
"database-warning","Database","db, storage, repo",
|
"database-warning","Database","db, storage, repo",
|
||||||
"database-xmark","Database","db, storage, repo, error",
|
"database-xmark","Database","db, storage, repo, error",
|
||||||
"database-xmark-solid","Database","",
|
|
||||||
"de-compress","Other",
|
"de-compress","Other",
|
||||||
"delivery","Transport","ship,shipment,amazon",
|
"delivery","Transport","ship,shipment,amazon",
|
||||||
"delivery-truck","Transport","ship,semitruck,shipment,amazon",
|
"delivery-truck","Transport","ship,semitruck,shipment,amazon",
|
||||||
"depth","Science",
|
"depth","Science",
|
||||||
"design-nib","Design Tools",
|
"design-nib","Design Tools",
|
||||||
"design-nib-solid","Design Tools","",
|
|
||||||
"design-pencil","Design Tools",
|
"design-pencil","Design Tools",
|
||||||
"desk","Home",
|
"desk","Home",
|
||||||
"developer","Development",
|
"developer","Development",
|
||||||
|
@ -424,7 +372,6 @@ filename,category,tags
|
||||||
"doc-star","Docs",
|
"doc-star","Docs",
|
||||||
"doc-star-in","Docs",
|
"doc-star-in","Docs",
|
||||||
"dogecoin-circle","Finance",
|
"dogecoin-circle","Finance",
|
||||||
"dogecoin-circle-solid","Finance","",
|
|
||||||
"dogecoin-rotate-out","Finance",
|
"dogecoin-rotate-out","Finance",
|
||||||
"dollar","Finance",
|
"dollar","Finance",
|
||||||
"dollar-circle","Finance",
|
"dollar-circle","Finance",
|
||||||
|
@ -437,10 +384,8 @@ filename,category,tags
|
||||||
"double-check","Actions",
|
"double-check","Actions",
|
||||||
"download","Actions",
|
"download","Actions",
|
||||||
"download-circle","Actions",
|
"download-circle","Actions",
|
||||||
"download-circle-solid","Actions","",
|
|
||||||
"download-data-window","System","browser,os",
|
"download-data-window","System","browser,os",
|
||||||
"download-square","Actions",
|
"download-square","Actions",
|
||||||
"download-square-solid","Actions","",
|
|
||||||
"drag","Navigation",
|
"drag","Navigation",
|
||||||
"drag-hand-gesture","Gestures",
|
"drag-hand-gesture","Gestures",
|
||||||
"drawer","Home",
|
"drawer","Home",
|
||||||
|
@ -457,7 +402,6 @@ filename,category,tags
|
||||||
"droplet","Design Tools",
|
"droplet","Design Tools",
|
||||||
"droplet-check","Nature","check, safe, water, clean, pure",
|
"droplet-check","Nature","check, safe, water, clean, pure",
|
||||||
"droplet-half","Design Tools",
|
"droplet-half","Design Tools",
|
||||||
"droplet-solid","Design Tools","",
|
|
||||||
"ease-curve-control-points","Animations",
|
"ease-curve-control-points","Animations",
|
||||||
"ease-in","Animations",
|
"ease-in","Animations",
|
||||||
"ease-in-control-point","Animations",
|
"ease-in-control-point","Animations",
|
||||||
|
@ -501,9 +445,7 @@ filename,category,tags
|
||||||
"energy-usage-window","System","browser,os,consuption,economy",
|
"energy-usage-window","System","browser,os,consuption,economy",
|
||||||
"enlarge","Photos and Videos",
|
"enlarge","Photos and Videos",
|
||||||
"erase","Actions",
|
"erase","Actions",
|
||||||
"erase-solid","Actions","",
|
|
||||||
"ethereum-circle","Finance",
|
"ethereum-circle","Finance",
|
||||||
"ethereum-circle-solid","Finance","",
|
|
||||||
"ethereum-rotate-out","Finance",
|
"ethereum-rotate-out","Finance",
|
||||||
"euro","Finance",
|
"euro","Finance",
|
||||||
"euro-square","Finance",
|
"euro-square","Finance",
|
||||||
|
@ -520,7 +462,6 @@ filename,category,tags
|
||||||
"extrude","3D Editor",
|
"extrude","3D Editor",
|
||||||
"eye","Actions",
|
"eye","Actions",
|
||||||
"eye-closed","Actions",
|
"eye-closed","Actions",
|
||||||
"eye-solid","Actions","",
|
|
||||||
"f-square","Typography","fluorine,element",
|
"f-square","Typography","fluorine,element",
|
||||||
"face-3d-draft","3D Editor",
|
"face-3d-draft","3D Editor",
|
||||||
"face-id","Identity",
|
"face-id","Identity",
|
||||||
|
@ -546,13 +487,11 @@ filename,category,tags
|
||||||
"figma","Design Tools",
|
"figma","Design Tools",
|
||||||
"file-not-found","Other",
|
"file-not-found","Other",
|
||||||
"fill-color","Design Tools",
|
"fill-color","Design Tools",
|
||||||
"fill-color-solid","Design Tools","",
|
|
||||||
"fillet-3d","3D Editor",
|
"fillet-3d","3D Editor",
|
||||||
"filter","Organization",
|
"filter","Organization",
|
||||||
"filter-alt","Organization",
|
"filter-alt","Organization",
|
||||||
"filter-list","Navigation",
|
"filter-list","Navigation",
|
||||||
"filter-list-circle","Navigation",
|
"filter-list-circle","Navigation",
|
||||||
"filter-solid","Organization","",
|
|
||||||
"finder","System","mac,apple,folder,file,os,operative,system",
|
"finder","System","mac,apple,folder,file,os,operative,system",
|
||||||
"fingerprint","Identity",
|
"fingerprint","Identity",
|
||||||
"fingerprint-check-circle","Identity",
|
"fingerprint-check-circle","Identity",
|
||||||
|
@ -587,7 +526,6 @@ filename,category,tags
|
||||||
"forward","Music",
|
"forward","Music",
|
||||||
"forward-15-seconds","Music",
|
"forward-15-seconds","Music",
|
||||||
"forward-message","Communication",
|
"forward-message","Communication",
|
||||||
"forward-solid","Music","",
|
|
||||||
"frame","Design Tools",
|
"frame","Design Tools",
|
||||||
"frame-alt","Design Tools",
|
"frame-alt","Design Tools",
|
||||||
"frame-alt-empty","Design Tools",
|
"frame-alt-empty","Design Tools",
|
||||||
|
@ -596,7 +534,6 @@ filename,category,tags
|
||||||
"frame-select","Design Tools",
|
"frame-select","Design Tools",
|
||||||
"frame-simple","Design Tools",
|
"frame-simple","Design Tools",
|
||||||
"frame-tool","Design Tools",
|
"frame-tool","Design Tools",
|
||||||
"frame-tool-solid","Design Tools","",
|
|
||||||
"fridge","Home",
|
"fridge","Home",
|
||||||
"fx","Photos and Videos",
|
"fx","Photos and Videos",
|
||||||
"fx-tag","Photos and Videos",
|
"fx-tag","Photos and Videos",
|
||||||
|
@ -659,22 +596,16 @@ filename,category,tags
|
||||||
"hdr","Photos and Videos",
|
"hdr","Photos and Videos",
|
||||||
"headset","Music","earphones,earbuds,listenings,audio",
|
"headset","Music","earphones,earbuds,listenings,audio",
|
||||||
"headset-bolt","Music","charge,energy,electricity,audio,listenings,earphones,earbuds",
|
"headset-bolt","Music","charge,energy,electricity,audio,listenings,earphones,earbuds",
|
||||||
"headset-bolt-solid","Music","",
|
|
||||||
"headset-help","Communication","earphones,earbuds,listenings,audio",
|
"headset-help","Communication","earphones,earbuds,listenings,audio",
|
||||||
"headset-solid","Music","",
|
|
||||||
"headset-warning","Music","earphones,earbuds,listenings,audio,issue,error",
|
"headset-warning","Music","earphones,earbuds,listenings,audio,issue,error",
|
||||||
"headset-warning-solid","Music","",
|
|
||||||
"health-shield","Health",
|
"health-shield","Health",
|
||||||
"healthcare","Health",
|
"healthcare","Health",
|
||||||
"heart","Health",
|
"heart","Health",
|
||||||
"heart-arrow-down","System",
|
"heart-arrow-down","System",
|
||||||
"heart-solid","Health","",
|
|
||||||
"heating-square","Science",
|
"heating-square","Science",
|
||||||
"heavy-rain","Weather","weather,storm",
|
"heavy-rain","Weather","weather,storm",
|
||||||
"help-circle","Actions",
|
"help-circle","Actions",
|
||||||
"help-circle-solid","Actions","",
|
|
||||||
"help-square","Actions",
|
"help-square","Actions",
|
||||||
"help-square-solid","Actions","",
|
|
||||||
"heptagon","Shapes",
|
"heptagon","Shapes",
|
||||||
"hexagon","Shapes",
|
"hexagon","Shapes",
|
||||||
"hexagon-dice","Gaming",
|
"hexagon-dice","Gaming",
|
||||||
|
@ -696,14 +627,11 @@ filename,category,tags
|
||||||
"home-temperature-out","Home",
|
"home-temperature-out","Home",
|
||||||
"home-user","Home",
|
"home-user","Home",
|
||||||
"horiz-distribution-left","Design Tools",
|
"horiz-distribution-left","Design Tools",
|
||||||
"horiz-distribution-left-solid","Design Tools","",
|
|
||||||
"horiz-distribution-right","Design Tools",
|
"horiz-distribution-right","Design Tools",
|
||||||
"horiz-distribution-right-solid","Design Tools","",
|
|
||||||
"horizontal-merge","Navigation",
|
"horizontal-merge","Navigation",
|
||||||
"horizontal-split","Navigation",
|
"horizontal-split","Navigation",
|
||||||
"hospital","Buildings",
|
"hospital","Buildings",
|
||||||
"hospital-circle","Health",
|
"hospital-circle","Health",
|
||||||
"hospital-circle-solid","Health","",
|
|
||||||
"hot-air-balloon","Transport","fly, airship",
|
"hot-air-balloon","Transport","fly, airship",
|
||||||
"hourglass","Activities",
|
"hourglass","Activities",
|
||||||
"house-rooms","Buildings",
|
"house-rooms","Buildings",
|
||||||
|
@ -714,7 +642,6 @@ filename,category,tags
|
||||||
"industry","Buildings",
|
"industry","Buildings",
|
||||||
"infinite","Science","limitless, endless, boundless, unbounded, unlimited",
|
"infinite","Science","limitless, endless, boundless, unbounded, unlimited",
|
||||||
"info-circle","Actions",
|
"info-circle","Actions",
|
||||||
"info-circle-solid","Actions","",
|
|
||||||
"input-field","System","element,ui,textbox",
|
"input-field","System","element,ui,textbox",
|
||||||
"input-output","System",
|
"input-output","System",
|
||||||
"input-search","Organization",
|
"input-search","Organization",
|
||||||
|
@ -727,7 +654,6 @@ filename,category,tags
|
||||||
"iris-scan","Identity",
|
"iris-scan","Identity",
|
||||||
"italic","Editor",
|
"italic","Editor",
|
||||||
"italic-square","Editor",
|
"italic-square","Editor",
|
||||||
"italic-square-solid","Editor","",
|
|
||||||
"jellyfish","Animals",
|
"jellyfish","Animals",
|
||||||
"journal","Docs",
|
"journal","Docs",
|
||||||
"journal-page","Docs",
|
"journal-page","Docs",
|
||||||
|
@ -754,7 +680,6 @@ filename,category,tags
|
||||||
"keyframes-minus","Animations",
|
"keyframes-minus","Animations",
|
||||||
"keyframes-plus","Animations","add",
|
"keyframes-plus","Animations","add",
|
||||||
"label","Organization",
|
"label","Organization",
|
||||||
"label-solid","Organization","",
|
|
||||||
"lamp","Home","light, home, house",
|
"lamp","Home","light, home, house",
|
||||||
"language","Other",
|
"language","Other",
|
||||||
"laptop","Devices",
|
"laptop","Devices",
|
||||||
|
@ -784,7 +709,6 @@ filename,category,tags
|
||||||
"list","Editor",
|
"list","Editor",
|
||||||
"list-select","Editor",
|
"list-select","Editor",
|
||||||
"litecoin-circle","Finance",
|
"litecoin-circle","Finance",
|
||||||
"litecoin-circle-solid","Finance","",
|
|
||||||
"litecoin-rotate-out","Finance",
|
"litecoin-rotate-out","Finance",
|
||||||
"lock","Security",
|
"lock","Security",
|
||||||
"lock-slash","Security",
|
"lock-slash","Security",
|
||||||
|
@ -834,8 +758,6 @@ filename,category,tags
|
||||||
"maximize","Other",
|
"maximize","Other",
|
||||||
"medal","Activities",
|
"medal","Activities",
|
||||||
"medal-1st","Activities","prize,place,first,winner,champion",
|
"medal-1st","Activities","prize,place,first,winner,champion",
|
||||||
"medal-1st-solid","Activities","prize,place,first,winner,champion",
|
|
||||||
"medal-solid","Activities","",
|
|
||||||
"media-image","Photos and Videos",
|
"media-image","Photos and Videos",
|
||||||
"media-image-folder","Photos and Videos",
|
"media-image-folder","Photos and Videos",
|
||||||
"media-image-list","Photos and Videos",
|
"media-image-list","Photos and Videos",
|
||||||
|
@ -856,25 +778,17 @@ filename,category,tags
|
||||||
"metro","Transport","transport,train,station,track,public",
|
"metro","Transport","transport,train,station,track,public",
|
||||||
"microphone","Audio",
|
"microphone","Audio",
|
||||||
"microphone-check","Audio",
|
"microphone-check","Audio",
|
||||||
"microphone-check-solid","Audio","",
|
|
||||||
"microphone-minus","Audio",
|
"microphone-minus","Audio",
|
||||||
"microphone-minus-solid","Audio","",
|
|
||||||
"microphone-mute","Audio",
|
"microphone-mute","Audio",
|
||||||
"microphone-plus","Audio",
|
"microphone-plus","Audio",
|
||||||
"microphone-plus-solid","Audio","",
|
|
||||||
"microphone-solid","Audio","",
|
|
||||||
"microphone-speaking","Audio",
|
"microphone-speaking","Audio",
|
||||||
"microphone-speaking-solid","Audio","",
|
|
||||||
"microphone-warning","Audio",
|
"microphone-warning","Audio",
|
||||||
"microphone-warning-solid","Audio","",
|
|
||||||
"microscope","Science",
|
"microscope","Science",
|
||||||
"minus","Actions",
|
"minus","Actions",
|
||||||
"minus-circle","Actions",
|
"minus-circle","Actions",
|
||||||
"minus-circle-solid","Actions","",
|
|
||||||
"minus-hexagon","Shapes",
|
"minus-hexagon","Shapes",
|
||||||
"minus-square","Actions",
|
"minus-square","Actions",
|
||||||
"minus-square-dashed","Other","remove,selection,select",
|
"minus-square-dashed","Other","remove,selection,select",
|
||||||
"minus-square-solid","Actions","",
|
|
||||||
"mirror","Home",
|
"mirror","Home",
|
||||||
"mobile-dev-mode","Development",
|
"mobile-dev-mode","Development",
|
||||||
"mobile-fingerprint","Identity",
|
"mobile-fingerprint","Identity",
|
||||||
|
@ -905,8 +819,6 @@ filename,category,tags
|
||||||
"music-double-note-plus","Music",
|
"music-double-note-plus","Music",
|
||||||
"music-note","Music",
|
"music-note","Music",
|
||||||
"music-note-plus","Music",
|
"music-note-plus","Music",
|
||||||
"music-note-plus-solid","Music","",
|
|
||||||
"music-note-solid","Music","",
|
|
||||||
"n-square","Typography","nitrogen,element",
|
"n-square","Typography","nitrogen,element",
|
||||||
"nav-arrow-down","Navigation",
|
"nav-arrow-down","Navigation",
|
||||||
"nav-arrow-left","Navigation",
|
"nav-arrow-left","Navigation",
|
||||||
|
@ -917,12 +829,8 @@ filename,category,tags
|
||||||
"neighbourhood","Buildings",
|
"neighbourhood","Buildings",
|
||||||
"network","Connectivity","connection, computer, network, information",
|
"network","Connectivity","connection, computer, network, information",
|
||||||
"network-left","Connectivity","connection, computer, network, information",
|
"network-left","Connectivity","connection, computer, network, information",
|
||||||
"network-left-solid","Connectivity","",
|
|
||||||
"network-reverse","Connectivity","connection, computer, network, information",
|
"network-reverse","Connectivity","connection, computer, network, information",
|
||||||
"network-reverse-solid","Connectivity","",
|
|
||||||
"network-right","Connectivity","connection, computer, network, information",
|
"network-right","Connectivity","connection, computer, network, information",
|
||||||
"network-right-solid","Connectivity","",
|
|
||||||
"network-solid","Connectivity","",
|
|
||||||
"new-tab","System",
|
"new-tab","System",
|
||||||
"nintendo-switch","Gaming","game,console,portable",
|
"nintendo-switch","Gaming","game,console,portable",
|
||||||
"no-smoking-circle","Activities",
|
"no-smoking-circle","Activities",
|
||||||
|
@ -931,25 +839,15 @@ filename,category,tags
|
||||||
"npm","Development",
|
"npm","Development",
|
||||||
"npm-square","Development",
|
"npm-square","Development",
|
||||||
"number-0-square","Other",
|
"number-0-square","Other",
|
||||||
"number-0-square-solid","Other","",
|
|
||||||
"number-1-square","Other",
|
"number-1-square","Other",
|
||||||
"number-1-square-solid","Other","",
|
|
||||||
"number-2-square","Other",
|
"number-2-square","Other",
|
||||||
"number-2-square-solid","Other","",
|
|
||||||
"number-3-square","Other",
|
"number-3-square","Other",
|
||||||
"number-3-square-solid","Other","",
|
|
||||||
"number-4-square","Other",
|
"number-4-square","Other",
|
||||||
"number-4-square-solid","Other","",
|
|
||||||
"number-5-square","Other",
|
"number-5-square","Other",
|
||||||
"number-5-square-solid","Other","",
|
|
||||||
"number-6-square","Other",
|
"number-6-square","Other",
|
||||||
"number-6-square-solid","Other","",
|
|
||||||
"number-7-square","Other",
|
"number-7-square","Other",
|
||||||
"number-7-square-solid","Other","",
|
|
||||||
"number-8-square","Other",
|
"number-8-square","Other",
|
||||||
"number-8-square-solid","Other","",
|
|
||||||
"number-9-square","Other",
|
"number-9-square","Other",
|
||||||
"number-9-square-solid","Other","",
|
|
||||||
"numbered-list-left","Editor",
|
"numbered-list-left","Editor",
|
||||||
"numbered-list-right","Editor",
|
"numbered-list-right","Editor",
|
||||||
"o-square","Typography","oxygen,element",
|
"o-square","Typography","oxygen,element",
|
||||||
|
@ -1001,7 +899,6 @@ filename,category,tags
|
||||||
"paste-clipboard","Actions",
|
"paste-clipboard","Actions",
|
||||||
"path-arrow","Navigation",
|
"path-arrow","Navigation",
|
||||||
"pause","Music",
|
"pause","Music",
|
||||||
"pause-solid","Music","",
|
|
||||||
"pause-window","System","browser,os,hold,wait,freeze",
|
"pause-window","System","browser,os,hold,wait,freeze",
|
||||||
"paypal","Finance",
|
"paypal","Finance",
|
||||||
"pc-check","Security",
|
"pc-check","Security",
|
||||||
|
@ -1020,9 +917,7 @@ filename,category,tags
|
||||||
"percent-rotate-out","Finance",
|
"percent-rotate-out","Finance",
|
||||||
"percentage","Activities",
|
"percentage","Activities",
|
||||||
"percentage-circle","Activities",
|
"percentage-circle","Activities",
|
||||||
"percentage-circle-solid","Activities","",
|
|
||||||
"percentage-square","Activities",
|
"percentage-square","Activities",
|
||||||
"percentage-square-solid","Activities","",
|
|
||||||
"perspective-view","3D Editor",
|
"perspective-view","3D Editor",
|
||||||
"pharmacy-cross-circle","Health","hospital,health,emergency",
|
"pharmacy-cross-circle","Health","hospital,health,emergency",
|
||||||
"pharmacy-cross-tag","Health","hospital,health,emergency",
|
"pharmacy-cross-tag","Health","hospital,health,emergency",
|
||||||
|
@ -1038,8 +933,6 @@ filename,category,tags
|
||||||
"pillow","Home",
|
"pillow","Home",
|
||||||
"pin","Organization",
|
"pin","Organization",
|
||||||
"pin-slash","Organization",
|
"pin-slash","Organization",
|
||||||
"pin-slash-solid","Organization","",
|
|
||||||
"pin-solid","Organization","",
|
|
||||||
"pine-tree","Nature",
|
"pine-tree","Nature",
|
||||||
"pinterest","Social",
|
"pinterest","Social",
|
||||||
"pipe-3d","3D Editor",
|
"pipe-3d","3D Editor",
|
||||||
|
@ -1049,7 +942,6 @@ filename,category,tags
|
||||||
"planet-sat","Science",
|
"planet-sat","Science",
|
||||||
"planimetry","Buildings",
|
"planimetry","Buildings",
|
||||||
"play","Music",
|
"play","Music",
|
||||||
"play-solid","Music","",
|
|
||||||
"playlist","Music",
|
"playlist","Music",
|
||||||
"playlist-play","Music",
|
"playlist-play","Music",
|
||||||
"playlist-plus","Music",
|
"playlist-plus","Music",
|
||||||
|
@ -1060,10 +952,8 @@ filename,category,tags
|
||||||
"plug-type-l","Connectivity","port, access, connection, cable",
|
"plug-type-l","Connectivity","port, access, connection, cable",
|
||||||
"plus","Actions",
|
"plus","Actions",
|
||||||
"plus-circle","Actions","add",
|
"plus-circle","Actions","add",
|
||||||
"plus-circle-solid","Actions","",
|
|
||||||
"plus-square","Actions","add",
|
"plus-square","Actions","add",
|
||||||
"plus-square-dashed","Other",
|
"plus-square-dashed","Other",
|
||||||
"plus-square-solid","Actions","",
|
|
||||||
"png-format","Photos and Videos",
|
"png-format","Photos and Videos",
|
||||||
"pocket","Social","save,tool,app",
|
"pocket","Social","save,tool,app",
|
||||||
"podcast","Communication",
|
"podcast","Communication",
|
||||||
|
@ -1071,22 +961,16 @@ filename,category,tags
|
||||||
"position","Maps",
|
"position","Maps",
|
||||||
"position-align","Design Tools",
|
"position-align","Design Tools",
|
||||||
"post","Social",
|
"post","Social",
|
||||||
"post-solid","Social","",
|
|
||||||
"potion","Gaming","power,superpower,energy",
|
"potion","Gaming","power,superpower,energy",
|
||||||
"pound","Finance",
|
"pound","Finance",
|
||||||
"precision-tool","Design Tools",
|
"precision-tool","Design Tools",
|
||||||
"presentation","Business",
|
"presentation","Business",
|
||||||
"presentation-solid","Business","",
|
|
||||||
"printer","Devices",
|
"printer","Devices",
|
||||||
"printing-page","Devices",
|
"printing-page","Devices",
|
||||||
"priority-down","Business",
|
"priority-down","Business",
|
||||||
"priority-down-solid","Business","",
|
|
||||||
"priority-high","Business",
|
"priority-high","Business",
|
||||||
"priority-high-solid","Business","",
|
|
||||||
"priority-medium","Business",
|
"priority-medium","Business",
|
||||||
"priority-medium-solid","Business","",
|
|
||||||
"priority-up","Business",
|
"priority-up","Business",
|
||||||
"priority-up-solid","Business","",
|
|
||||||
"privacy-policy","Docs",
|
"privacy-policy","Docs",
|
||||||
"private-wifi","Connectivity",
|
"private-wifi","Connectivity",
|
||||||
"profile-circle","Users","user,round,person",
|
"profile-circle","Users","user,round,person",
|
||||||
|
@ -1108,11 +992,9 @@ filename,category,tags
|
||||||
"redo","Actions",
|
"redo","Actions",
|
||||||
"redo-action","Actions",
|
"redo-action","Actions",
|
||||||
"redo-circle","Actions",
|
"redo-circle","Actions",
|
||||||
"redo-circle-solid","Actions","",
|
|
||||||
"reduce","Photos and Videos",
|
"reduce","Photos and Videos",
|
||||||
"refresh","Actions",
|
"refresh","Actions",
|
||||||
"refresh-circle","Actions",
|
"refresh-circle","Actions",
|
||||||
"refresh-circle-solid","Actions","",
|
|
||||||
"refresh-double","Actions",
|
"refresh-double","Actions",
|
||||||
"reload-window","System","refresh,browser,os",
|
"reload-window","System","refresh,browser,os",
|
||||||
"reminder-hand-gesture","Gestures",
|
"reminder-hand-gesture","Gestures",
|
||||||
|
@ -1122,11 +1004,9 @@ filename,category,tags
|
||||||
"reply-to-message","Communication",
|
"reply-to-message","Communication",
|
||||||
"report-columns","Activities",
|
"report-columns","Activities",
|
||||||
"reports","Activities",
|
"reports","Activities",
|
||||||
"reports-solid","Activities","",
|
|
||||||
"repository","Git","git, github",
|
"repository","Git","git, github",
|
||||||
"restart","Actions",
|
"restart","Actions",
|
||||||
"rewind","Music",
|
"rewind","Music",
|
||||||
"rewind-solid","Music","",
|
|
||||||
"rhombus","Shapes",
|
"rhombus","Shapes",
|
||||||
"rings","Activities",
|
"rings","Activities",
|
||||||
"rocket","Science","space, nasa, esa, spacex, missile",
|
"rocket","Science","space, nasa, esa, spacex, missile",
|
||||||
|
@ -1180,12 +1060,9 @@ filename,category,tags
|
||||||
"send-yens","Finance",
|
"send-yens","Finance",
|
||||||
"server","Connectivity","connection, computer, network",
|
"server","Connectivity","connection, computer, network",
|
||||||
"server-connection","Connectivity","connection, computer, network",
|
"server-connection","Connectivity","connection, computer, network",
|
||||||
"server-connection-solid","Connectivity","",
|
|
||||||
"server-solid","Connectivity","",
|
|
||||||
"settings","System",
|
"settings","System",
|
||||||
"settings-profiles","System",
|
"settings-profiles","System",
|
||||||
"share-android","Actions",
|
"share-android","Actions",
|
||||||
"share-android-solid","Actions","",
|
|
||||||
"share-ios","Actions",
|
"share-ios","Actions",
|
||||||
"shield","Security","security,protection,firewall",
|
"shield","Security","security,protection,firewall",
|
||||||
"shield-alert","Security","security,protection,firewall",
|
"shield-alert","Security","security,protection,firewall",
|
||||||
|
@ -1231,9 +1108,7 @@ filename,category,tags
|
||||||
"skateboard","Activities",
|
"skateboard","Activities",
|
||||||
"skateboarding","Activities",
|
"skateboarding","Activities",
|
||||||
"skip-next","Music",
|
"skip-next","Music",
|
||||||
"skip-next-solid","Music","",
|
|
||||||
"skip-prev","Music",
|
"skip-prev","Music",
|
||||||
"skip-prev-solid","Music","",
|
|
||||||
"slash","Development",
|
"slash","Development",
|
||||||
"slash-square","Git","git, github, command",
|
"slash-square","Git","git, github, command",
|
||||||
"sleeper-chair","Home",
|
"sleeper-chair","Home",
|
||||||
|
@ -1259,9 +1134,7 @@ filename,category,tags
|
||||||
"sound-off","Audio",
|
"sound-off","Audio",
|
||||||
"spades","Gaming","poker,game,cards,gambling,vegas",
|
"spades","Gaming","poker,game,cards,gambling,vegas",
|
||||||
"spark","Other","ai, artificial, intelligence",
|
"spark","Other","ai, artificial, intelligence",
|
||||||
"spark-solid","Other","",
|
|
||||||
"sparks","Other","ai, artificial, intelligence",
|
"sparks","Other","ai, artificial, intelligence",
|
||||||
"sparks-solid","Other","",
|
|
||||||
"sphere","3D Editor","modeling,blender,4d,geometry",
|
"sphere","3D Editor","modeling,blender,4d,geometry",
|
||||||
"spiral","3D Editor","modeling,blender,4d,geometry",
|
"spiral","3D Editor","modeling,blender,4d,geometry",
|
||||||
"split-area","Other",
|
"split-area","Other",
|
||||||
|
@ -1273,27 +1146,22 @@ filename,category,tags
|
||||||
"square-3d-from-center","3D Editor","modeling,blender,4d",
|
"square-3d-from-center","3D Editor","modeling,blender,4d",
|
||||||
"square-3d-three-points","3D Editor","modeling,blender,4d",
|
"square-3d-three-points","3D Editor","modeling,blender,4d",
|
||||||
"square-cursor","System",
|
"square-cursor","System",
|
||||||
"square-cursor-solid","System","",
|
|
||||||
"square-dashed","Other","selection",
|
"square-dashed","Other","selection",
|
||||||
"square-wave","Science",
|
"square-wave","Science",
|
||||||
"stackoverflow","Social",
|
"stackoverflow","Social",
|
||||||
"star","Organization",
|
"star","Organization",
|
||||||
"star-dashed","Organization",
|
"star-dashed","Organization",
|
||||||
"star-half-dashed","Organization",
|
"star-half-dashed","Organization",
|
||||||
"star-solid","Organization","",
|
|
||||||
"stat-down","Activities",
|
"stat-down","Activities",
|
||||||
"stat-up","Activities",
|
"stat-up","Activities",
|
||||||
"stats-down-square","Business",
|
"stats-down-square","Business",
|
||||||
"stats-down-square-solid","Business","",
|
|
||||||
"stats-report","Business",
|
"stats-report","Business",
|
||||||
"stats-up-square","Business",
|
"stats-up-square","Business",
|
||||||
"stats-up-square-solid","Business","",
|
|
||||||
"strategy","Business",
|
"strategy","Business",
|
||||||
"stretching","Activities",
|
"stretching","Activities",
|
||||||
"strikethrough","Editor",
|
"strikethrough","Editor",
|
||||||
"stroller","Health",
|
"stroller","Health",
|
||||||
"style-border","Design Tools",
|
"style-border","Design Tools",
|
||||||
"style-border-solid","Design Tools","",
|
|
||||||
"submit-document","Docs",
|
"submit-document","Docs",
|
||||||
"substract","Design Tools",
|
"substract","Design Tools",
|
||||||
"suggestion","Maps",
|
"suggestion","Maps",
|
||||||
|
@ -1335,11 +1203,9 @@ filename,category,tags
|
||||||
"text-magnifying-glass","Editor","search",
|
"text-magnifying-glass","Editor","search",
|
||||||
"text-size","Editor",
|
"text-size","Editor",
|
||||||
"text-square","Editor",
|
"text-square","Editor",
|
||||||
"text-square-solid","Editor","",
|
|
||||||
"threads","Social",
|
"threads","Social",
|
||||||
"three-points-circle","3D Editor",
|
"three-points-circle","3D Editor",
|
||||||
"three-stars","Organization",
|
"three-stars","Organization",
|
||||||
"three-stars-solid","Organization","",
|
|
||||||
"thumbs-down","Social","disapprove,dislike,facebook,fb,meta,no",
|
"thumbs-down","Social","disapprove,dislike,facebook,fb,meta,no",
|
||||||
"thumbs-up","Social","approve,like,facebook,fb,meta,yes",
|
"thumbs-up","Social","approve,like,facebook,fb,meta,yes",
|
||||||
"thunderstorm","Weather",
|
"thunderstorm","Weather",
|
||||||
|
@ -1349,7 +1215,6 @@ filename,category,tags
|
||||||
"time-zone","Communication",
|
"time-zone","Communication",
|
||||||
"timer","Other",
|
"timer","Other",
|
||||||
"timer-off","Other",
|
"timer-off","Other",
|
||||||
"timer-solid","Other","",
|
|
||||||
"tools","Tools",
|
"tools","Tools",
|
||||||
"tournament","Gaming",
|
"tournament","Gaming",
|
||||||
"tower","Security",
|
"tower","Security",
|
||||||
|
@ -1365,7 +1230,6 @@ filename,category,tags
|
||||||
"transition-up","Animations",
|
"transition-up","Animations",
|
||||||
"translate","Other",
|
"translate","Other",
|
||||||
"trash","Actions",
|
"trash","Actions",
|
||||||
"trash-solid","Actions","",
|
|
||||||
"treadmill","Activities",
|
"treadmill","Activities",
|
||||||
"tree","Nature",
|
"tree","Nature",
|
||||||
"trekking","Activities",
|
"trekking","Activities",
|
||||||
|
@ -1389,11 +1253,9 @@ filename,category,tags
|
||||||
"umbrella","Clothing",
|
"umbrella","Clothing",
|
||||||
"underline","Editor",
|
"underline","Editor",
|
||||||
"underline-square","Editor",
|
"underline-square","Editor",
|
||||||
"underline-square-solid","Editor","",
|
|
||||||
"undo","Actions",
|
"undo","Actions",
|
||||||
"undo-action","Actions",
|
"undo-action","Actions",
|
||||||
"undo-circle","Actions",
|
"undo-circle","Actions",
|
||||||
"undo-circle-solid","Actions","",
|
|
||||||
"union","Design Tools",
|
"union","Design Tools",
|
||||||
"union-alt","Design Tools",
|
"union-alt","Design Tools",
|
||||||
"union-horiz-alt","Design Tools",
|
"union-horiz-alt","Design Tools",
|
||||||
|
@ -1403,9 +1265,7 @@ filename,category,tags
|
||||||
"upload","Actions","upload,arrow,data,cloud,save",
|
"upload","Actions","upload,arrow,data,cloud,save",
|
||||||
"upload-data-window","System","os,browser",
|
"upload-data-window","System","os,browser",
|
||||||
"upload-square","Actions",
|
"upload-square","Actions",
|
||||||
"upload-square-solid","Actions","",
|
|
||||||
"usb","Connectivity","port, access, connection, cable",
|
"usb","Connectivity","port, access, connection, cable",
|
||||||
"usb-solid","Connectivity","",
|
|
||||||
"user","Users","person,people,ux",
|
"user","Users","person,people,ux",
|
||||||
"user-badge-check","Users","profile,person",
|
"user-badge-check","Users","profile,person",
|
||||||
"user-bag","Shopping",
|
"user-bag","Shopping",
|
||||||
|
@ -1447,12 +1307,9 @@ filename,category,tags
|
||||||
"walking","Activities",
|
"walking","Activities",
|
||||||
"wallet","Finance",
|
"wallet","Finance",
|
||||||
"warning-circle","Actions",
|
"warning-circle","Actions",
|
||||||
"warning-circle-solid","Actions","",
|
|
||||||
"warning-hexagon","Devices",
|
"warning-hexagon","Devices",
|
||||||
"warning-square","Actions",
|
"warning-square","Actions",
|
||||||
"warning-square-solid","Actions","",
|
|
||||||
"warning-triangle","Actions",
|
"warning-triangle","Actions",
|
||||||
"warning-triangle-solid","Actions","",
|
|
||||||
"warning-window","System","alert,danger",
|
"warning-window","System","alert,danger",
|
||||||
"wash","Home",
|
"wash","Home",
|
||||||
"washing-machine","Home",
|
"washing-machine","Home",
|
||||||
|
@ -1464,15 +1321,11 @@ filename,category,tags
|
||||||
"weight","Health",
|
"weight","Health",
|
||||||
"weight-alt","Health",
|
"weight-alt","Health",
|
||||||
"white-flag","Other",
|
"white-flag","Other",
|
||||||
"white-flag-solid","Other","",
|
|
||||||
"wifi","Connectivity","signal, connection, network",
|
"wifi","Connectivity","signal, connection, network",
|
||||||
"wifi-off","Connectivity","signal, connection, network",
|
"wifi-off","Connectivity","signal, connection, network",
|
||||||
"wifi-signal-none","Connectivity","signal, connection, network",
|
"wifi-signal-none","Connectivity","signal, connection, network",
|
||||||
"wifi-signal-none-solid","Connectivity","",
|
|
||||||
"wifi-tag","Connectivity","signal, connection, network",
|
"wifi-tag","Connectivity","signal, connection, network",
|
||||||
"wifi-tag-solid","Connectivity","",
|
|
||||||
"wifi-warning","Connectivity","signal, connection, network",
|
"wifi-warning","Connectivity","signal, connection, network",
|
||||||
"wifi-warning-solid","Connectivity","",
|
|
||||||
"wifi-xmark","Connectivity","signal,connection,network,error",
|
"wifi-xmark","Connectivity","signal,connection,network,error",
|
||||||
"wind","Weather","weather,air,fresh",
|
"wind","Weather","weather,air,fresh",
|
||||||
"window-check","System","browser,os",
|
"window-check","System","browser,os",
|
||||||
|
@ -1492,9 +1345,7 @@ filename,category,tags
|
||||||
"xbox-y","Gaming",
|
"xbox-y","Gaming",
|
||||||
"xmark","Actions","cancel,delete,remove",
|
"xmark","Actions","cancel,delete,remove",
|
||||||
"xmark-circle","Actions","delete",
|
"xmark-circle","Actions","delete",
|
||||||
"xmark-circle-solid","Actions","",
|
|
||||||
"xmark-square","Actions","remove",
|
"xmark-square","Actions","remove",
|
||||||
"xmark-square-solid","Actions","",
|
|
||||||
"xray-view","3D Editor",
|
"xray-view","3D Editor",
|
||||||
"y-square","Typography","coordinate,axis",
|
"y-square","Typography","coordinate,axis",
|
||||||
"yelp","Social",
|
"yelp","Social",
|
||||||
|
|
Can't render this file because it has a wrong number of fields in line 2.
|
|
@ -2,6 +2,7 @@ import fs from 'fs';
|
||||||
|
|
||||||
export function getHeaderProps() {
|
export function getHeaderProps() {
|
||||||
const packageJson = JSON.parse(fs.readFileSync('../package.json').toString());
|
const packageJson = JSON.parse(fs.readFileSync('../package.json').toString());
|
||||||
|
|
||||||
return {
|
return {
|
||||||
currentVersion: `v${packageJson.version}`,
|
currentVersion: `v${packageJson.version}`,
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,42 +1,40 @@
|
||||||
import Case from 'case';
|
|
||||||
import csv from 'csvtojson';
|
import csv from 'csvtojson';
|
||||||
import * as AllIcons from 'iconoir-react';
|
import * as AllIcons from 'iconoir-react';
|
||||||
import { incompatibleNames } from '../../constants';
|
import { kebabCase, pascalCase } from 'scule';
|
||||||
import { Icon } from '../components/IconList';
|
import { Icon } from '../components/IconList';
|
||||||
|
|
||||||
const ICONS_PATH = 'icons.csv';
|
const ICONS_PATH = 'icons.csv';
|
||||||
const TAG_SEPARATOR = '|';
|
const TAG_SEPARATOR = '|';
|
||||||
|
|
||||||
const typedIncompatibleNames = incompatibleNames as Record<string, string>;
|
|
||||||
|
|
||||||
function getIconComponentName(filename: string) {
|
|
||||||
const dstFileName =
|
|
||||||
filename in typedIncompatibleNames
|
|
||||||
? typedIncompatibleNames[filename]
|
|
||||||
: filename;
|
|
||||||
return Case.pascal(dstFileName);
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function getAllIcons(): Promise<Icon[]> {
|
export async function getAllIcons(): Promise<Icon[]> {
|
||||||
const rows = await csv().fromFile(ICONS_PATH);
|
const rows = await csv().fromFile(ICONS_PATH);
|
||||||
return rows.map<Icon>((row) => {
|
|
||||||
const iconComponentName = getIconComponentName(row.filename);
|
const icons: Icon[] = [];
|
||||||
// Convert to lowercase to solve for differences in how the names are calculated.
|
|
||||||
const matchingKey = Object.keys(AllIcons).find(
|
for (const row of rows) {
|
||||||
(k) =>
|
const iconComponentName = pascalCase(row.filename);
|
||||||
k.toLowerCase() === iconComponentName.toLowerCase() ||
|
const iconComponentSolidName = pascalCase(`${row.filename}-solid`);
|
||||||
k.toLowerCase() === `svg${iconComponentName.toLowerCase()}`,
|
|
||||||
|
const iconComponents = Object.keys(AllIcons).filter(
|
||||||
|
(icon) => icon === iconComponentName || icon === iconComponentSolidName,
|
||||||
);
|
);
|
||||||
if (!matchingKey)
|
|
||||||
|
if (iconComponents.length === 0)
|
||||||
throw new Error(
|
throw new Error(
|
||||||
`Cannot find icon '${iconComponentName}' in iconoir-react.`,
|
`Couldn't find icons for ${row.filename} (${iconComponentName}) in 'iconoir-react'.`,
|
||||||
);
|
);
|
||||||
return {
|
|
||||||
filename: row.filename,
|
for (const iconComponent of iconComponents) {
|
||||||
category: row.category,
|
icons.push({
|
||||||
tags:
|
filename: kebabCase(iconComponent),
|
||||||
row.tags?.split(TAG_SEPARATOR).map((item: string) => item.trim()) || [],
|
category: row.category,
|
||||||
iconComponentName: matchingKey,
|
tags:
|
||||||
};
|
row.tags?.split(TAG_SEPARATOR).map((item: string) => item.trim()) ||
|
||||||
});
|
[],
|
||||||
|
iconComponentName: iconComponent,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return icons;
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@ export function showNotification(message: string) {
|
||||||
element.classList.add('bottom-notification');
|
element.classList.add('bottom-notification');
|
||||||
element.innerText = message;
|
element.innerText = message;
|
||||||
document.body.appendChild(element);
|
document.body.appendChild(element);
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
element.remove();
|
element.remove();
|
||||||
}, 3000);
|
}, 3000);
|
||||||
|
|
|
@ -20,14 +20,13 @@
|
||||||
"@react-types/slider": "^3.6.1",
|
"@react-types/slider": "^3.6.1",
|
||||||
"@types/animejs": "^3.1.8",
|
"@types/animejs": "^3.1.8",
|
||||||
"@types/lodash": "^4.14.199",
|
"@types/lodash": "^4.14.199",
|
||||||
"@types/node": "^20.7.0",
|
"@types/node": "^20.8.9",
|
||||||
"@types/react": "^18.2.22",
|
"@types/react": "^18.2.33",
|
||||||
"@types/react-dom": "^18.2.7",
|
"@types/react-dom": "^18.2.14",
|
||||||
"@types/react-window": "^1.8.5",
|
"@types/react-window": "^1.8.5",
|
||||||
"animejs": "^3.2.1",
|
"animejs": "^3.2.1",
|
||||||
"case": "^1.6.3",
|
|
||||||
"csvtojson": "^2.0.10",
|
"csvtojson": "^2.0.10",
|
||||||
"eslint": "^8.50.0",
|
"eslint": "^8.52.0",
|
||||||
"eslint-config-next": "^13.5.3",
|
"eslint-config-next": "^13.5.3",
|
||||||
"iconoir-react": "workspace:*",
|
"iconoir-react": "workspace:*",
|
||||||
"lodash": "^4.17.21",
|
"lodash": "^4.17.21",
|
||||||
|
@ -40,6 +39,7 @@
|
||||||
"react-window": "^1.8.9",
|
"react-window": "^1.8.9",
|
||||||
"remark-gfm": "^3.0.1",
|
"remark-gfm": "^3.0.1",
|
||||||
"remark-prism": "^1.3.6",
|
"remark-prism": "^1.3.6",
|
||||||
|
"scule": "^1.0.0",
|
||||||
"styled-components": "^6.0.8",
|
"styled-components": "^6.0.8",
|
||||||
"typescript": "^5.1.6",
|
"typescript": "^5.1.6",
|
||||||
"use-resize-observer": "^9.1.0"
|
"use-resize-observer": "^9.1.0"
|
||||||
|
|
|
@ -21,7 +21,9 @@ export default class IconoirDocument extends Document {
|
||||||
enhanceApp: (App) => (props) =>
|
enhanceApp: (App) => (props) =>
|
||||||
sheet.collectStyles(<App {...props} />),
|
sheet.collectStyles(<App {...props} />),
|
||||||
});
|
});
|
||||||
|
|
||||||
const initialProps = await Document.getInitialProps(ctx);
|
const initialProps = await Document.getInitialProps(ctx);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...initialProps,
|
...initialProps,
|
||||||
styles: (
|
styles: (
|
||||||
|
|
|
@ -25,6 +25,7 @@ interface DocumentationPageProps extends HeaderProps {
|
||||||
navigationItem: DocumentationItem;
|
navigationItem: DocumentationItem;
|
||||||
navigationProps: DocumentationNavigationProps;
|
navigationProps: DocumentationNavigationProps;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function DocumentationPage({
|
export default function DocumentationPage({
|
||||||
source,
|
source,
|
||||||
title,
|
title,
|
||||||
|
@ -183,10 +184,12 @@ function structureItemsToPaths(
|
||||||
): ParsedUrlQuery[] {
|
): ParsedUrlQuery[] {
|
||||||
const result: ParsedUrlQuery[] = [];
|
const result: ParsedUrlQuery[] = [];
|
||||||
const filteredItems = items.filter((item) => !item.skip);
|
const filteredItems = items.filter((item) => !item.skip);
|
||||||
|
|
||||||
for (const item of filteredItems) {
|
for (const item of filteredItems) {
|
||||||
if (item.filepath && item.path) {
|
if (item.filepath && item.path) {
|
||||||
result.push({ slug: [...(slugPrefix || []), item.path].filter(Boolean) });
|
result.push({ slug: [...(slugPrefix || []), item.path].filter(Boolean) });
|
||||||
}
|
}
|
||||||
|
|
||||||
if (item.children?.length) {
|
if (item.children?.length) {
|
||||||
result.push(
|
result.push(
|
||||||
...structureItemsToPaths(
|
...structureItemsToPaths(
|
||||||
|
@ -234,11 +237,13 @@ function itemFromSlug(
|
||||||
const item = flatItems.find((flatItem) => flatItem.path === joinedSlug);
|
const item = flatItems.find((flatItem) => flatItem.path === joinedSlug);
|
||||||
if (!item)
|
if (!item)
|
||||||
throw new Error(`Cannot find item matching slug '${slug.join('/')}'`);
|
throw new Error(`Cannot find item matching slug '${slug.join('/')}'`);
|
||||||
|
|
||||||
return item;
|
return item;
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getStaticPaths(): Promise<GetStaticPathsResult> {
|
export async function getStaticPaths(): Promise<GetStaticPathsResult> {
|
||||||
const structure = getDocumentationStructure();
|
const structure = getDocumentationStructure();
|
||||||
|
|
||||||
return {
|
return {
|
||||||
paths: structureItemsToPaths(structure).map((p) => ({ params: p })),
|
paths: structureItemsToPaths(structure).map((p) => ({ params: p })),
|
||||||
fallback: false,
|
fallback: false,
|
||||||
|
@ -263,6 +268,7 @@ export async function getStaticProps(context: GetStaticPropsContext) {
|
||||||
remarkPlugins: [require('remark-prism'), remarkGfm],
|
remarkPlugins: [require('remark-prism'), remarkGfm],
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
return {
|
return {
|
||||||
props: {
|
props: {
|
||||||
source: mdxSource,
|
source: mdxSource,
|
||||||
|
|
|
@ -62,6 +62,7 @@ export async function getStaticProps() {
|
||||||
...REPO,
|
...REPO,
|
||||||
});
|
});
|
||||||
const entries: ChangelogEntryProps[] = [];
|
const entries: ChangelogEntryProps[] = [];
|
||||||
|
|
||||||
for (const release of releases) {
|
for (const release of releases) {
|
||||||
entries.push({
|
entries.push({
|
||||||
name: release.name || release.tag_name,
|
name: release.name || release.tag_name,
|
||||||
|
@ -76,7 +77,9 @@ export async function getStaticProps() {
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const items = getDocumentationStructure();
|
const items = getDocumentationStructure();
|
||||||
|
|
||||||
return {
|
return {
|
||||||
props: {
|
props: {
|
||||||
entries,
|
entries,
|
||||||
|
|
|
@ -3,8 +3,10 @@ import React from 'react';
|
||||||
|
|
||||||
export default function Index() {
|
export default function Index() {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
router.replace('/docs/introduction');
|
router.replace('/docs/introduction');
|
||||||
}, [router]);
|
}, [router]);
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,6 +24,7 @@ interface HomeProps {
|
||||||
numStars: number;
|
numStars: number;
|
||||||
numDownloads: number;
|
numDownloads: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Home: NextPage<HomeProps> = ({
|
const Home: NextPage<HomeProps> = ({
|
||||||
allIcons,
|
allIcons,
|
||||||
currentVersion,
|
currentVersion,
|
||||||
|
@ -176,6 +177,7 @@ export const HeroDescription = styled(Text18)<{ topMargin?: number }>`
|
||||||
margin-top: ${(props) => props.topMargin || 0}px;
|
margin-top: ${(props) => props.topMargin || 0}px;
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const Supporters = styled.div`
|
const Supporters = styled.div`
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
|
|
|
@ -16,6 +16,7 @@ import { getHeaderProps } from '../lib/getHeaderProps';
|
||||||
import { Praise } from '../components/Praise';
|
import { Praise } from '../components/Praise';
|
||||||
|
|
||||||
interface SupportProps extends HeaderProps {}
|
interface SupportProps extends HeaderProps {}
|
||||||
|
|
||||||
const Support: NextPage<SupportProps> = ({ ...headerProps }) => {
|
const Support: NextPage<SupportProps> = ({ ...headerProps }) => {
|
||||||
return (
|
return (
|
||||||
<Layout>
|
<Layout>
|
||||||
|
@ -192,6 +193,7 @@ const PraiseTitle = styled(Heading2)`
|
||||||
const DonateLeft = styled.div`
|
const DonateLeft = styled.div`
|
||||||
max-width: 800px;
|
max-width: 800px;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export const DonateRight = styled.div`
|
export const DonateRight = styled.div`
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
@ -204,6 +206,7 @@ export const DonateRight = styled.div`
|
||||||
margin-left: 30px;
|
margin-left: 30px;
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const DonateButton = styled(LargeButton)`
|
const DonateButton = styled(LargeButton)`
|
||||||
&&& {
|
&&& {
|
||||||
padding: 0 24px;
|
padding: 0 24px;
|
||||||
|
@ -219,6 +222,7 @@ const CallToAction = styled(LargeButton)`
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export const DonateContainer = styled.div`
|
export const DonateContainer = styled.div`
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
@ -244,6 +248,7 @@ export const DonateHeader = styled.div`
|
||||||
font-size: 22px;
|
font-size: 22px;
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const PraiseContainer = styled.div`
|
const PraiseContainer = styled.div`
|
||||||
margin: 50px 0 64px 0;
|
margin: 50px 0 64px 0;
|
||||||
${media.md} {
|
${media.md} {
|
||||||
|
|
|
@ -5,16 +5,23 @@
|
||||||
"allowJs": true,
|
"allowJs": true,
|
||||||
"skipLibCheck": true,
|
"skipLibCheck": true,
|
||||||
"strict": true,
|
"strict": true,
|
||||||
"forceConsistentCasingInFileNames": true,
|
|
||||||
"noEmit": true,
|
"noEmit": true,
|
||||||
"esModuleInterop": true,
|
"esModuleInterop": true,
|
||||||
"module": "esnext",
|
"module": "esnext",
|
||||||
"moduleResolution": "node",
|
"moduleResolution": "bundler",
|
||||||
"resolveJsonModule": true,
|
"resolveJsonModule": true,
|
||||||
"isolatedModules": true,
|
"isolatedModules": true,
|
||||||
"jsx": "preserve",
|
"jsx": "preserve",
|
||||||
"incremental": true
|
"incremental": true,
|
||||||
|
"plugins": [
|
||||||
|
{
|
||||||
|
"name": "next"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"paths": {
|
||||||
|
"@/*": ["./*"]
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"],
|
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
|
||||||
"exclude": ["node_modules"]
|
"exclude": ["node_modules"]
|
||||||
}
|
}
|
||||||
|
|
Before Width: | Height: | Size: 902 B After Width: | Height: | Size: 902 B |
Before Width: | Height: | Size: 964 B After Width: | Height: | Size: 964 B |
Before Width: | Height: | Size: 681 B After Width: | Height: | Size: 681 B |
Before Width: | Height: | Size: 230 B After Width: | Height: | Size: 230 B |
Before Width: | Height: | Size: 677 B After Width: | Height: | Size: 677 B |
Before Width: | Height: | Size: 677 B After Width: | Height: | Size: 677 B |
Before Width: | Height: | Size: 634 B After Width: | Height: | Size: 634 B |
Before Width: | Height: | Size: 557 B After Width: | Height: | Size: 557 B |
Before Width: | Height: | Size: 807 B After Width: | Height: | Size: 807 B |
Before Width: | Height: | Size: 623 B After Width: | Height: | Size: 623 B |
Before Width: | Height: | Size: 696 B After Width: | Height: | Size: 696 B |
Before Width: | Height: | Size: 667 B After Width: | Height: | Size: 667 B |
Before Width: | Height: | Size: 996 B After Width: | Height: | Size: 996 B |
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 1.8 KiB |
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.5 KiB |
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 1.7 KiB |
Before Width: | Height: | Size: 1,016 B After Width: | Height: | Size: 1,016 B |
Before Width: | Height: | Size: 475 B After Width: | Height: | Size: 475 B |
Before Width: | Height: | Size: 596 B After Width: | Height: | Size: 596 B |
Before Width: | Height: | Size: 586 B After Width: | Height: | Size: 586 B |
Before Width: | Height: | Size: 620 B After Width: | Height: | Size: 620 B |
Before Width: | Height: | Size: 756 B After Width: | Height: | Size: 756 B |
Before Width: | Height: | Size: 522 B After Width: | Height: | Size: 522 B |