chonky
Version:
A File Browser component for React
451 lines (432 loc) • 8.15 kB
text/typescript
/**
* @author Timur Kuzhagaliyev <tim.kuzh@gmail.com>
* @copyright 2019
* @license MIT
*/
import { createContext, ElementType, useMemo } from 'react';
import ExactTrie from 'exact-trie';
import { Nullable } from 'tsdef';
import { ChonkyIconPlaceholder } from '../components/internal/ChonkyIconPlaceholder';
import { FileData } from '../types/file.types';
import { ChonkyIconName, ChonkyIconProps, FileIconData } from '../types/icons.types';
export const ChonkyIconContext = createContext<ElementType<ChonkyIconProps>>(ChonkyIconPlaceholder);
export const VideoExtensions: string[] = [
'3g2',
'3gp',
'3gpp',
'asf',
'asx',
'avi',
'dvb',
'f4v',
'fli',
'flv',
'fvt',
'h261',
'h263',
'h264',
'jpgm',
'jpgv',
'jpm',
'm1v',
'm2v',
'm4u',
'm4v',
'mj2',
'mjp2',
'mk3d',
'mks',
'mkv',
'mng',
'mov',
'movie',
'mp4',
'mp4v',
'mpe',
'mpeg',
'mpg',
'mpg4',
'mxu',
'ogv',
'pyv',
'qt',
'smv',
'ts',
'uvh',
'uvm',
'uvp',
'uvs',
'uvu',
'uvv',
'uvvh',
'uvvm',
'uvvp',
'uvvs',
'uvvu',
'uvvv',
'viv',
'vob',
'webm',
'wm',
'wmv',
'wmx',
'wvx',
];
export const ImageExtensions: string[] = [
'3ds',
'apng',
'azv',
'bmp',
'bmp',
'btif',
'cgm',
'cmx',
'djv',
'djvu',
'drle',
'dwg',
'dxf',
'emf',
'exr',
'fbs',
'fh',
'fh4',
'fh5',
'fh7',
'fhc',
'fits',
'fpx',
'fst',
'g3',
'gif',
'heic',
'heics',
'heif',
'heifs',
'ico',
'ico',
'ief',
'jls',
'jng',
'jp2',
'jpe',
'jpeg',
'jpf',
'jpg',
'jpg2',
'jpm',
'jpx',
'jxr',
'ktx',
'mdi',
'mmr',
'npx',
'pbm',
'pct',
'pcx',
'pcx',
'pgm',
'pic',
'png',
'pnm',
'ppm',
'psd',
'pti',
'ras',
'rgb',
'rlc',
'sgi',
'sid',
'sub',
'svg',
'svgz',
't38',
'tap',
'tfx',
'tga',
'tif',
'tiff',
'uvg',
'uvi',
'uvvg',
'uvvi',
'vtf',
'wbmp',
'wdp',
'webp',
'wmf',
'xbm',
'xif',
'xpm',
'xwd',
];
export const AudioExtensions: string[] = [
'3gpp',
'aac',
'adp',
'aif',
'aifc',
'aiff',
'au',
'caf',
'dra',
'dts',
'dtshd',
'ecelp4800',
'ecelp7470',
'ecelp9600',
'eol',
'flac',
'kar',
'lvp',
'm2a',
'm3a',
'm3u',
'm4a',
'm4a',
'mid',
'midi',
'mka',
'mp2',
'mp2a',
'mp3',
'mp3',
'mp4a',
'mpga',
'oga',
'ogg',
'pya',
'ra',
'ra',
'ram',
'rip',
'rmi',
'rmp',
's3m',
'sil',
'snd',
'spx',
'uva',
'uvva',
'wav',
'wav',
'wav',
'wax',
'weba',
'wma',
'xm',
];
export const ColorsLight: string[] = [
'#bbbbbb',
'#d65c5c',
'#d6665c',
'#d6705c',
'#d67a5c',
'#d6855c',
'#d68f5c',
'#d6995c',
'#d6a35c',
'#d6ad5c',
'#d6b85c',
'#d6c25c',
'#d6cc5c',
'#d6d65c',
'#ccd65c',
'#c2d65c',
'#b8d65c',
'#add65c',
'#a3d65c',
'#99d65c',
'#8fd65c',
'#85d65c',
'#7ad65c',
'#70d65c',
'#66d65c',
'#5cd65c',
'#5cd666',
'#5cd670',
'#5cd67a',
'#5cd685',
'#5cd68f',
'#5cd699',
'#5cd6a3',
'#5cd6ad',
'#5cd6b8',
'#5cd6c2',
'#5cd6cc',
'#5cd6d6',
'#5cccd6',
'#5cc2d6',
'#5cb8d6',
'#5cadd6',
'#5ca3d6',
'#5c99d6',
'#5c8fd6',
'#5c85d6',
'#5c7ad6',
'#5c70d6',
'#5c66d6',
'#5c5cd6',
'#665cd6',
'#705cd6',
'#7a5cd6',
'#855cd6',
'#8f5cd6',
'#995cd6',
'#a35cd6',
'#ad5cd6',
'#b85cd6',
'#c25cd6',
'#cc5cd6',
'#d65cd6',
'#d65ccc',
'#d65cc2',
'#d65cb8',
'#d65cad',
'#d65ca3',
'#d65c99',
'#d65c8f',
'#d65c85',
'#d65c7a',
'#d65c70',
'#d65c66',
];
export const ColorsDark: string[] = [
'#777',
'#8f3d3d',
'#8f443d',
'#8f4b3d',
'#8f523d',
'#8f583d',
'#8f5f3d',
'#8f663d',
'#8f6d3d',
'#8f743d',
'#8f7a3d',
'#8f813d',
'#8f883d',
'#8f8f3d',
'#888f3d',
'#818f3d',
'#7a8f3d',
'#748f3d',
'#6d8f3d',
'#668f3d',
'#5f8f3d',
'#588f3d',
'#528f3d',
'#4b8f3d',
'#448f3d',
'#3d8f3d',
'#3d8f44',
'#3d8f4b',
'#3d8f52',
'#3d8f58',
'#3d8f5f',
'#3d8f66',
'#3d8f6d',
'#3d8f74',
'#3d8f7a',
'#3d8f81',
'#3d8f88',
'#3d8f8f',
'#3d888f',
'#3d818f',
'#3d7a8f',
'#3d748f',
'#3d6d8f',
'#3d668f',
'#3d5f8f',
'#3d588f',
'#3d528f',
'#3d4b8f',
'#3d448f',
'#3d3d8f',
'#443d8f',
'#4b3d8f',
'#523d8f',
'#583d8f',
'#5f3d8f',
'#663d8f',
'#6d3d8f',
'#743d8f',
'#7a3d8f',
'#813d8f',
'#883d8f',
'#8f3d8f',
'#8f3d88',
'#8f3d81',
'#8f3d7a',
'#8f3d74',
'#8f3d6d',
'#8f3d66',
'#8f3d5f',
'#8f3d58',
'#8f3d52',
'#8f3d4b',
'#8f3d44',
];
const getIconTrie = () => {
let colourIndex = 0;
const step = 5;
const IconsToExtensions = [
// Generic file types
[ChonkyIconName.license, ['license']],
[ChonkyIconName.config, ['sfk', 'ini', 'yml', 'toml', 'iml']],
[ChonkyIconName.model, ['3ds', 'obj', 'ply', 'fbx']],
[ChonkyIconName.database, ['csv', 'json', 'sql', 'sqlite', 'sqlite3', 'npy', 'npz', 'rec', 'idx', 'hdf5']],
[ChonkyIconName.text, ['txt', 'md', 'mdx']],
[ChonkyIconName.archive, ['zip', 'rar', 'tar', 'tar.gz', '7z']],
[ChonkyIconName.image, ImageExtensions],
[ChonkyIconName.video, VideoExtensions],
[ChonkyIconName.code, ['html', 'php', 'css', 'sass', 'scss', 'less', 'cpp', 'h', 'hpp', 'c', 'xml']],
[ChonkyIconName.info, ['bib', 'readme', 'nfo']],
[ChonkyIconName.key, ['pem', 'pub']],
[ChonkyIconName.lock, ['lock', 'lock.json', 'shrinkwrap.json']],
[ChonkyIconName.music, AudioExtensions],
[ChonkyIconName.terminal, ['run', 'sh']],
[ChonkyIconName.trash, ['.Trashes']],
[ChonkyIconName.users, ['authors', 'contributors']],
// OS file types
[ChonkyIconName.linux, ['AppImage']],
[ChonkyIconName.ubuntu, ['deb']],
[ChonkyIconName.windows, ['exe']],
// Programming language file types
[ChonkyIconName.rust, ['rs', 'rlib']],
[ChonkyIconName.python, ['py', 'ipynb']],
[ChonkyIconName.nodejs, ['js', 'jsx', 'ts', 'tsx', 'd.ts']],
[ChonkyIconName.php, ['php']],
// Development tools file types
[ChonkyIconName.git, ['.gitignore']],
// Brands file types
[ChonkyIconName.adobe, ['psd']],
// Other program file types
[ChonkyIconName.pdf, ['pdf']],
[ChonkyIconName.excel, ['xls', 'xlsx']],
[ChonkyIconName.word, ['doc', 'docx', 'odt']],
[ChonkyIconName.flash, ['swf']],
] as const;
const exactTrie = new ExactTrie({ ignoreCase: true });
for (const pair of IconsToExtensions) {
const [icon, extensions] = pair;
for (let i = 0; i < extensions.length; ++i) {
colourIndex += step;
const colorCode = (colourIndex % (ColorsLight.length - 1)) + 1;
const iconData: FileIconData = {
icon,
colorCode,
};
exactTrie.put(extensions[i], iconData, true);
}
}
return exactTrie;
};
const iconTrie = getIconTrie();
export const useIconData = (file: Nullable<FileData>): FileIconData => {
return useMemo(() => {
if (!file) return { icon: ChonkyIconName.loading, colorCode: 0 };
if (file.isDir === true) return { icon: ChonkyIconName.folder, colorCode: 0 };
const match = iconTrie.getWithCheckpoints(file.name, '.', true);
return match ? match : { icon: ChonkyIconName.file, colorCode: 32 };
}, [file]);
};