feat: Refactor utility and component exports, update dependencies, and add Knip for unused code detection.
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import React, { ElementType, ReactNode } from 'react';
|
||||
import composeClassName from './classNames';
|
||||
import { composeClassName } from './classNames';
|
||||
|
||||
type TitleProps = Record<string, unknown>;
|
||||
|
||||
|
||||
@@ -49,7 +49,7 @@ interface FloatingMenuState {
|
||||
|
||||
type CSSVarStyle = CSSProperties & Record<string, string>;
|
||||
|
||||
export interface QuickAddMenuProps {
|
||||
interface QuickAddMenuProps {
|
||||
onSelectOption?: (value: QuickAddOption, normalized: NormalizedOption) => Promise<void> | void;
|
||||
onCreate?: (value: string) => Promise<void> | void;
|
||||
options?: QuickAddOption[];
|
||||
|
||||
@@ -1,4 +1,2 @@
|
||||
export const composeClassName = (base: string, extra?: string | null): string =>
|
||||
extra ? `${base} ${extra}` : base;
|
||||
|
||||
export default composeClassName;
|
||||
|
||||
@@ -12,15 +12,11 @@ import {
|
||||
IconLayoutList,
|
||||
IconLayoutGrid,
|
||||
IconArrowLeft,
|
||||
IconArrowRight,
|
||||
IconArrowUp,
|
||||
IconAnalyze,
|
||||
IconUpload,
|
||||
IconWindowMaximize,
|
||||
IconTextScan2,
|
||||
IconFolderPlus,
|
||||
IconFolder,
|
||||
IconFolderUp,
|
||||
IconFolders,
|
||||
IconFoldersOff,
|
||||
IconRefresh,
|
||||
@@ -37,10 +33,8 @@ import {
|
||||
IconDeviceLaptop,
|
||||
IconLayoutSidebarLeftCollapse,
|
||||
IconLayoutSidebarLeftExpand,
|
||||
IconLayoutSidebarRightCollapse,
|
||||
IconLayoutBottombarCollapse,
|
||||
IconLayoutBottombarExpand,
|
||||
IconClearAll,
|
||||
IconInfoCircle,
|
||||
IconCircleDashedCheck,
|
||||
IconFile,
|
||||
@@ -56,7 +50,7 @@ import {
|
||||
import FolderSvg from '../assets/folder.svg';
|
||||
const logoWebp = new URL('../assets/logo.webp', import.meta.url).toString();
|
||||
const logoSmallWebp = new URL('../assets/logo_small.webp', import.meta.url).toString();
|
||||
import composeClassName from './classNames';
|
||||
import { composeClassName } from './classNames';
|
||||
|
||||
type TablerIconComponent = (props: TablerIconProps) => JSX.Element;
|
||||
|
||||
@@ -223,16 +217,6 @@ export const ArrowLeftIcon: TablerIconComponent = ({ className, size = '1em', st
|
||||
{...rest}
|
||||
/>
|
||||
);
|
||||
|
||||
export const ArrowRightIcon: TablerIconComponent = ({ className, size = '1em', stroke = 1.6, ...rest }) => (
|
||||
<IconArrowRight
|
||||
className={composeClassName('icon', className)}
|
||||
size={size}
|
||||
stroke={stroke}
|
||||
{...rest}
|
||||
/>
|
||||
);
|
||||
|
||||
export const SidebarCollapseIcon: TablerIconComponent = ({ className, size = '1em', stroke = 1.6, ...rest }) => (
|
||||
<IconLayoutSidebarLeftCollapse
|
||||
className={composeClassName('icon', className)}
|
||||
@@ -268,16 +252,6 @@ export const FileInfoIcon: TablerIconComponent = ({ className, size = '1em', str
|
||||
{...rest}
|
||||
/>
|
||||
);
|
||||
|
||||
export const DetailPanelCollapseIcon: TablerIconComponent = ({ className, size = '1em', stroke = 1.6, ...rest }) => (
|
||||
<IconLayoutSidebarRightCollapse
|
||||
className={composeClassName('icon', className)}
|
||||
size={size}
|
||||
stroke={stroke}
|
||||
{...rest}
|
||||
/>
|
||||
);
|
||||
|
||||
export const BottombarCollapseIcon: TablerIconComponent = ({ className, size = '1em', stroke = 1.6, ...rest }) => (
|
||||
<IconLayoutBottombarCollapse
|
||||
className={composeClassName('icon', className)}
|
||||
@@ -295,16 +269,6 @@ export const BottombarExpandIcon: TablerIconComponent = ({ className, size = '1e
|
||||
{...rest}
|
||||
/>
|
||||
);
|
||||
|
||||
export const ClearAllIcon: TablerIconComponent = ({ className, size = '1em', stroke = 1.6, ...rest }) => (
|
||||
<IconClearAll
|
||||
className={composeClassName('icon', className)}
|
||||
size={size}
|
||||
stroke={stroke}
|
||||
{...rest}
|
||||
/>
|
||||
);
|
||||
|
||||
export const FolderPlusIcon: TablerIconComponent = ({ className, size = '1em', stroke = 1.6, ...rest }) => (
|
||||
<IconFolderPlus
|
||||
className={composeClassName('icon', className)}
|
||||
@@ -349,16 +313,6 @@ export const RestoreIcon: TablerIconComponent = ({ className, size = '1em', stro
|
||||
{...rest}
|
||||
/>
|
||||
);
|
||||
|
||||
export const ArrowUpIcon: TablerIconComponent = ({ className, size = '1em', stroke = 1.6, ...rest }) => (
|
||||
<IconArrowUp
|
||||
className={composeClassName('icon', className)}
|
||||
size={size}
|
||||
stroke={stroke}
|
||||
{...rest}
|
||||
/>
|
||||
);
|
||||
|
||||
export const MinusVerticalIcon: TablerIconComponent = ({ className, size = '1em', stroke = 1.6, ...rest }) => (
|
||||
<IconMinusVertical
|
||||
className={composeClassName('icon', className)}
|
||||
@@ -567,16 +521,6 @@ export const ChevronDownIcon: TablerIconComponent = ({ className, size = '1em',
|
||||
{...rest}
|
||||
/>
|
||||
);
|
||||
|
||||
export const FolderUpIcon: TablerIconComponent = ({ className, size = '1em', stroke = 1.6, ...rest }) => (
|
||||
<IconFolderUp
|
||||
className={composeClassName('icon', className)}
|
||||
size={size}
|
||||
stroke={stroke}
|
||||
{...rest}
|
||||
/>
|
||||
);
|
||||
|
||||
export const FolderMoveIcon: TablerIconComponent = ({ className, size = '1em', stroke = 1.6, ...rest }) => (
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
@@ -601,38 +545,3 @@ export const FolderMoveIcon: TablerIconComponent = ({ className, size = '1em', s
|
||||
</g>
|
||||
</svg>
|
||||
);
|
||||
|
||||
export default {
|
||||
ChevronIcon,
|
||||
TrashIcon,
|
||||
EditIcon,
|
||||
FolderIcon,
|
||||
TagIcon,
|
||||
CorrespondentIcon,
|
||||
DownloadIcon,
|
||||
ViewListIcon,
|
||||
ViewGridIcon,
|
||||
SidebarCollapseIcon,
|
||||
SidebarExpandIcon,
|
||||
DetailPanelCollapseIcon,
|
||||
AnalyzeIcon,
|
||||
LoaderIcon,
|
||||
WindowMaximizeIcon,
|
||||
FolderPlusIcon,
|
||||
RefreshIcon,
|
||||
ArrowUpIcon,
|
||||
MinusVerticalIcon,
|
||||
LogoutIcon,
|
||||
ChevronDownIcon,
|
||||
FolderUpIcon,
|
||||
FolderMoveIcon,
|
||||
};
|
||||
|
||||
export const TextScanIcon: TablerIconComponent = ({ className, size = '1em', stroke = 1.6, ...rest }) => (
|
||||
<IconTextScan2
|
||||
className={composeClassName('icon', className)}
|
||||
size={size}
|
||||
stroke={stroke}
|
||||
{...rest}
|
||||
/>
|
||||
);
|
||||
|
||||
@@ -1,94 +0,0 @@
|
||||
import { useCallback, useEffect, useRef } from 'react';
|
||||
import type { PointerEvent as ReactPointerEvent } from 'react';
|
||||
|
||||
export interface PointerTapContext<T = unknown> {
|
||||
clientX: number;
|
||||
clientY: number;
|
||||
pointerType: string;
|
||||
event: PointerEventWithPersist;
|
||||
data?: T;
|
||||
}
|
||||
|
||||
type PointerEventWithPersist = (PointerEvent | ReactPointerEvent) & { persist?: () => void };
|
||||
|
||||
type PointerTapFilter = (event?: PointerEventWithPersist | null) => boolean;
|
||||
|
||||
export interface UsePointerTapOptions<T = unknown> {
|
||||
onSingle?: (context: PointerTapContext<T>) => void;
|
||||
onDouble?: (context: PointerTapContext<T>) => void;
|
||||
delay?: number;
|
||||
filter?: PointerTapFilter;
|
||||
}
|
||||
|
||||
const defaultFilter: PointerTapFilter = (event) => {
|
||||
if (!event) {
|
||||
return false;
|
||||
}
|
||||
const { type, button, pointerType, isPrimary } = event;
|
||||
const isPointerUp = type === 'pointerup';
|
||||
const buttonValid =
|
||||
button == null || button === 0 || (isPointerUp && (button === -1 || button === 0));
|
||||
if (!buttonValid) {
|
||||
return false;
|
||||
}
|
||||
if (pointerType === 'touch' && isPrimary === false) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
const usePointerTap = <T,>({
|
||||
onSingle,
|
||||
onDouble,
|
||||
delay = 240,
|
||||
filter = defaultFilter,
|
||||
}: UsePointerTapOptions<T> = {}) => {
|
||||
const timerRef = useRef<ReturnType<typeof setTimeout> | null>(null);
|
||||
|
||||
useEffect(
|
||||
() => () => {
|
||||
if (timerRef.current) {
|
||||
clearTimeout(timerRef.current);
|
||||
timerRef.current = null;
|
||||
}
|
||||
},
|
||||
[],
|
||||
);
|
||||
|
||||
return useCallback(
|
||||
(event?: PointerEventWithPersist | null, metadata?: T) => {
|
||||
if (!filter(event)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!event) {
|
||||
return;
|
||||
}
|
||||
|
||||
event.persist?.();
|
||||
|
||||
const context: PointerTapContext<T> = {
|
||||
clientX: event.clientX ?? 0,
|
||||
clientY: event.clientY ?? 0,
|
||||
pointerType: event.pointerType ?? 'mouse',
|
||||
event,
|
||||
data: metadata,
|
||||
};
|
||||
|
||||
if (timerRef.current) {
|
||||
clearTimeout(timerRef.current);
|
||||
timerRef.current = null;
|
||||
onDouble?.(context);
|
||||
return;
|
||||
}
|
||||
|
||||
timerRef.current = setTimeout(() => {
|
||||
timerRef.current = null;
|
||||
onSingle?.(context);
|
||||
}, delay);
|
||||
},
|
||||
[delay, filter, onDouble, onSingle],
|
||||
);
|
||||
};
|
||||
|
||||
export default usePointerTap;
|
||||
Reference in New Issue
Block a user