UNPKG

chonky

Version:

A File Browser component for React

451 lines (432 loc) 8.15 kB
/** * @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]); };