|
- import * as React from 'react';
- import {formatFileSize, formatNumeral} from 'packages/web-kitchensink-reactnext/src/utils/numeral';
- import {useFileMetadata, useFileUrl} from 'src/index';
- import {augmentTextFile, getMimeTypeDescription} from 'packages/web-kitchensink-reactnext/src/utils/blob';
- import clsx from 'clsx';
- import {KeyValueTable} from 'categories/information/react';
- import {Refractor} from 'packages/web-kitchensink-reactnext/src/packages/react-refractor';
- import {useClientSide} from 'packages/react-utils';
- import type {CommonPreviewProps} from '../../../../../categories/blob/react/src/components/FileSelectBox';
-
- type TextFilePreviewDerivedComponent = HTMLDivElement;
-
- export interface TextFilePreviewProps<F extends Partial<File> = Partial<File>>
- extends React.HTMLProps<TextFilePreviewDerivedComponent>, CommonPreviewProps<F> {}
-
- export const TextFilePreview = React.forwardRef<TextFilePreviewDerivedComponent, TextFilePreviewProps>(({
- file,
- className,
- style,
- enhanced: enhancedProp = false,
- ...etcProps
- }, forwardedRef) => {
- const { fileWithUrl } = useFileUrl({ file });
- const { fileWithMetadata, error } = useFileMetadata({
- file: fileWithUrl,
- augmentFunction: augmentTextFile,
- });
- const { clientSide } = useClientSide({ clientSide: enhancedProp });
-
- if (!fileWithMetadata) {
- return null;
- }
-
- return (
- <div
- className={clsx(
- 'flex flex-col sm:grid sm:grid-cols-3 gap-8 w-full',
- className,
- )}
- style={style}
- >
- <div className="h-full relative col-span-2">
- <div className="absolute top-0 left-0 w-full h-full">
- {
- typeof fileWithMetadata.metadata?.contents === 'string'
- && (
- <div
- {...etcProps}
- data-testid="preview"
- role="presentation"
- className="w-full h-full select-none overflow-hidden text-xs"
- ref={forwardedRef}
- key={`${fileWithMetadata.url}:${fileWithMetadata.type}`}
- >
- <Refractor
- code={fileWithMetadata.metadata.contents}
- language={fileWithMetadata.metadata.scheme}
- lineNumbers={Boolean(fileWithMetadata.metadata.scheme)}
- />
- </div>
- )
- }
- </div>
- </div>
- <div className="flex-shrink-0 m-0 flex flex-col gap-4 justify-between">
- <KeyValueTable
- hiddenKeys
- data-testid="infoBox"
- properties={[
- Boolean(fileWithMetadata.name) && {
- key: 'Name',
- className: 'font-bold',
- valueProps: {
- children: fileWithMetadata.name,
- title: fileWithMetadata.name,
- },
- },
- (clientSide && Boolean(getMimeTypeDescription(fileWithMetadata.type, fileWithMetadata.name) || '(Loading)') || Boolean(fileWithMetadata.type)) && {
- key: 'Type',
- valueProps: {
- children: typeof fileWithMetadata.metadata?.schemeTitle === 'string' ? `${fileWithMetadata.metadata.schemeTitle} Source` : 'Text File',
- },
- },
- (clientSide && Boolean(formatFileSize(fileWithMetadata.size) || '(Loading)') || Boolean(fileWithMetadata.size)) && {
- key: 'Size',
- valueProps: {
- className: clsx(
- !formatFileSize(fileWithMetadata.size) && 'opacity-50'
- ),
- title: `${formatNumeral(fileWithMetadata.size ?? 0)} byte(s)`,
- children: formatFileSize(fileWithMetadata.size) || '(Loading)',
- },
- },
- typeof fileWithMetadata.metadata?.lineCount === 'number'
- && typeof fileWithMetadata.metadata?.linesOfCode !== 'number'
- && {
- key: 'Lines',
- valueProps: {
- children: `${formatNumeral(fileWithMetadata.metadata.lineCount)} line(s)`
- },
- },
- typeof fileWithMetadata.metadata?.lineCount === 'number'
- && typeof fileWithMetadata.metadata?.linesOfCode === 'number'
- && {
- key: 'Lines',
- valueProps: {
- children: `${formatNumeral(fileWithMetadata.metadata.lineCount)} line(s), ${formatNumeral(fileWithMetadata.metadata.linesOfCode)} loc`,
- },
- },
- Array.isArray(fileWithMetadata.metadata?.languageMatches)
- && {
- key: 'Language',
- valueProps: {
- children: (
- <dl
- className="text-sm"
- >
- {fileWithMetadata.metadata!.languageMatches.slice(0, 3).map(([language, probability], index) => {
- return (
- <div key={index} className="flex justify-between">
- <dt>
- {language.slice(0, 1).toUpperCase()}
- {language.slice(1)}
- </dt>
- <dd className="tabular-nums">
- {(probability * 100).toFixed(3)}%
- {' '}
- <abbr title="probability">prob.</abbr>
- </dd>
- </div>
- );
- })}
- </dl>
- ),
- },
- },
- ]}
- />
- </div>
- </div>
- );
- });
-
- TextFilePreview.displayName = 'TextFilePreview';
|