Switch to BiomeJS (#306)

This commit is contained in:
Gregory Schier
2025-11-23 08:38:13 -08:00
committed by GitHub
parent 2bac610efe
commit ec3e2e16a9
332 changed files with 3007 additions and 4097 deletions

View File

@@ -11,9 +11,18 @@ import {
import { type } from '@tauri-apps/plugin-os';
import classNames from 'classnames';
import type { ComponentType, MouseEvent, ReactElement, Ref, RefAttributes } from 'react';
import { forwardRef, memo, useCallback, useEffect, useImperativeHandle, useMemo, useRef, useState, } from 'react';
import {
forwardRef,
memo,
useCallback,
useEffect,
useImperativeHandle,
useMemo,
useRef,
useState,
} from 'react';
import { useKey, useKeyPressEvent } from 'react-use';
import type { HotkeyAction, HotKeyOptions } from '../../../hooks/useHotKey';
import type { HotKeyOptions, HotkeyAction } from '../../../hooks/useHotKey';
import { useHotKey } from '../../../hooks/useHotKey';
import { computeSideForDragMove } from '../../../lib/dnd';
import { jotaiStore } from '../../../lib/jotai';
@@ -102,6 +111,7 @@ function TreeInner<T extends { id: string }>(
}, []);
// Select the first item on first render
// biome-ignore lint/correctness/useExhaustiveDependencies: Only used for initial render
useEffect(() => {
const ids = jotaiStore.get(selectedIdsFamily(treeId));
const fallback = selectableItems[0];
@@ -112,7 +122,6 @@ function TreeInner<T extends { id: string }>(
lastId: fallback.node.item.id,
});
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [treeId]);
const handleCloseContextMenu = useCallback(() => {
@@ -129,11 +138,10 @@ function TreeInner<T extends { id: string }>(
);
if ($el == null) {
return false;
} else {
$el.focus();
$el.scrollIntoView({ block: 'nearest' });
return true;
}
$el.focus();
$el.scrollIntoView({ block: 'nearest' });
return true;
}, []);
const ensureTabbableItem = useCallback(() => {
@@ -166,7 +174,7 @@ function TreeInner<T extends { id: string }>(
useEffect(() => {
const unsub = jotaiStore.sub(collapsedFamily(treeId), ensureTabbableItem);
return unsub;
}, [ensureTabbableItem, isTreeFocused, selectableItems, treeId, tryFocus]);
}, [ensureTabbableItem, treeId]);
// Ensure there's always a tabbable item after render
useEffect(() => {
@@ -224,13 +232,12 @@ function TreeInner<T extends { id: string }>(
if (isSelected) {
// If right-clicked an item that was in the multiple-selection, use the entire selection
return getContextMenu(items);
} else {
// If right-clicked an item that was NOT in the multiple-selection, just use that one
// Also update the selection with it
setSelected([item.id], false);
jotaiStore.set(focusIdsFamily(treeId), (prev) => ({ ...prev, lastId: item.id }));
return getContextMenu([item]);
}
// If right-clicked an item that was NOT in the multiple-selection, just use that one
// Also update the selection with it
setSelected([item.id], false);
jotaiStore.set(focusIdsFamily(treeId), (prev) => ({ ...prev, lastId: item.id }));
return getContextMenu([item]);
};
}, [getContextMenu, selectableItems, setSelected, treeId]);
@@ -728,6 +735,7 @@ function DropRegionAfterList({
onContextMenu?: (e: MouseEvent<HTMLDivElement>) => void;
}) {
const { setNodeRef } = useDroppable({ id });
// biome-ignore lint/a11y/noStaticElementInteractions: Meh
return <div ref={setNodeRef} onContextMenu={onContextMenu} />;
}
@@ -758,7 +766,7 @@ function TreeHotKey<T extends { id: string }>({
enable: () => {
if (enable == null) return true;
if (typeof enable === 'function') return enable();
else return enable;
return enable;
},
},
);

View File

@@ -19,7 +19,7 @@ export function TreeDragOverlay<T extends { id: string }>({
return (
<DragOverlay dropAnimation={null}>
<TreeItemList
treeId={treeId + '.dragging'}
treeId={`${treeId}.dragging`}
nodes={selectableItems.filter((i) => draggingItems.includes(i.node.item.id))}
getItemKey={getItemKey}
ItemInner={ItemInner}

View File

@@ -19,6 +19,7 @@ export const TreeIndentGuide = memo(function TreeIndentGuide({
<div className="flex">
{Array.from({ length: depth }).map((_, i) => (
<div
// biome-ignore lint/suspicious/noArrayIndexKey: none
key={i}
className={classNames(
'w-[calc(1rem+0.5px)] border-r border-r-text-subtlest',

View File

@@ -3,14 +3,15 @@ import { useDndContext, useDndMonitor, useDraggable, useDroppable } from '@dnd-k
import classNames from 'classnames';
import { useAtomValue } from 'jotai';
import { selectAtom } from 'jotai/utils';
import type React from 'react';
import type { MouseEvent, PointerEvent } from 'react';
import React, { memo, useCallback, useEffect, useMemo, useRef, useState } from 'react';
import { memo, useCallback, useEffect, useMemo, useRef, useState } from 'react';
import { computeSideForDragMove } from '../../../lib/dnd';
import { jotaiStore } from '../../../lib/jotai';
import type { ContextMenuProps, DropdownItem } from '../Dropdown';
import { ContextMenu } from '../Dropdown';
import { Icon } from '../Icon';
import { collapsedFamily, isCollapsedFamily, isLastFocusedFamily, isSelectedFamily, } from './atoms';
import { collapsedFamily, isCollapsedFamily, isLastFocusedFamily, isSelectedFamily } from './atoms';
import type { TreeNode } from './common';
import { getNodeKey } from './common';
import type { TreeProps } from './Tree';
@@ -84,7 +85,7 @@ function TreeItem_<T extends { id: string }>({
},
scrollIntoView: () => {
listItemRef.current?.scrollIntoView({ block: 'nearest' });
}
},
}),
[editing, getEditOptions],
);
@@ -272,10 +273,6 @@ function TreeItem_<T extends { id: string }>({
return (
<li
ref={listItemRef}
role="treeitem"
aria-level={depth + 1}
aria-expanded={node.children == null ? undefined : !isCollapsed}
aria-selected={isSelected}
onContextMenu={handleContextMenu}
className={classNames(
className,
@@ -304,6 +301,7 @@ function TreeItem_<T extends { id: string }>({
)}
{node.children != null ? (
<button
type="button"
tabIndex={-1}
className="h-full pl-[0.5rem] outline-none"
onClick={toggleCollapsed}

View File

@@ -29,7 +29,7 @@ export function TreeItemList<T extends { id: string }>({
...props
}: TreeItemListProps<T>) {
return (
<ul role="tree" style={style} className={className}>
<ul style={style} className={className}>
<TreeDropMarker node={null} treeId={treeId} index={0} />
{nodes.map((child, i) => (
<Fragment key={getItemKey(child.node.item)}>

View File

@@ -21,7 +21,7 @@ export const focusIdsFamily = atomFamily((_treeId: string) => {
export const isLastFocusedFamily = atomFamily(
({ treeId, itemId }: { treeId: string; itemId: string }) =>
selectAtom(focusIdsFamily(treeId), (v) => v.lastId == itemId, Object.is),
selectAtom(focusIdsFamily(treeId), (v) => v.lastId === itemId, Object.is),
(a, b) => a.treeId === b.treeId && a.itemId === b.itemId,
);

View File

@@ -35,8 +35,13 @@ export function equalSubtree<T extends { id: string }>(
if (getNodeKey(a, getItemKey) !== getNodeKey(b, getItemKey)) return false;
const ak = a.children ?? [];
const bk = b.children ?? [];
if (ak.length !== bk.length) return false;
if (ak.length !== bk.length) {
return false;
}
for (let i = 0; i < ak.length; i++) {
// biome-ignore lint/style/noNonNullAssertion: none
if (!equalSubtree(ak[i]!, bk[i]!, getItemKey)) return false;
}

View File

@@ -6,7 +6,7 @@ export function useSelectableItems<T extends { id: string }>(root: TreeNode<T>)
const selectableItems: SelectableTreeNode<T>[] = [];
// Put requests and folders into a tree structure
const next = (node: TreeNode<T>, depth: number = 0) => {
const next = (node: TreeNode<T>, depth = 0) => {
if (node.children == null) {
return;
}