mirror of
https://github.com/getpaseo/paseo.git
synced 2026-07-29 12:01:31 +00:00
chore(lint): hoist jsx-as-prop in app components batch 1
Memoize inline JSX icons passed as props across add-host-modal, branch-switcher, composer, pair-link-modal, pr-pane, and sidebar-workspace-list to satisfy react-perf/jsx-no-jsx-as-prop.
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import { useCallback, useRef, useState } from "react";
|
||||
import { useCallback, useMemo, useRef, useState } from "react";
|
||||
import { Alert, Text, TextInput, View } from "react-native";
|
||||
import { StyleSheet, useUnistyles } from "react-native-unistyles";
|
||||
import { useIsCompactFormFactor } from "@/constants/layout";
|
||||
@@ -160,6 +160,11 @@ export function AddHostModal({ visible, onClose, onCancel, onSaved }: AddHostMod
|
||||
hostInputRef.current?.clear();
|
||||
}, []);
|
||||
|
||||
const connectIcon = useMemo(
|
||||
() => <Link2 size={16} color={theme.colors.palette.white} />,
|
||||
[theme.colors.palette.white],
|
||||
);
|
||||
|
||||
const handleClose = useCallback(() => {
|
||||
if (isSaving) return;
|
||||
clearInput();
|
||||
@@ -289,7 +294,7 @@ export function AddHostModal({ visible, onClose, onCancel, onSaved }: AddHostMod
|
||||
variant="default"
|
||||
onPress={handleSavePress}
|
||||
disabled={isSaving}
|
||||
leftIcon={<Link2 size={16} color={theme.colors.palette.white} />}
|
||||
leftIcon={connectIcon}
|
||||
testID="direct-host-submit"
|
||||
>
|
||||
{isSaving ? "Connecting..." : "Connect"}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { useCallback, useRef } from "react";
|
||||
import { useCallback, useMemo, useRef } from "react";
|
||||
import { Pressable, View, type PressableStateCallbackType } from "react-native";
|
||||
import { useQueryClient } from "@tanstack/react-query";
|
||||
import { ChevronDown, GitBranch } from "lucide-react-native";
|
||||
@@ -62,6 +62,11 @@ export function BranchSwitcher({
|
||||
[],
|
||||
);
|
||||
|
||||
const branchLeadingSlot = useMemo(
|
||||
() => <GitBranch size={14} color={theme.colors.foregroundMuted} />,
|
||||
[theme.colors.foregroundMuted],
|
||||
);
|
||||
|
||||
const renderBranchOption = useCallback<NonNullable<ComboboxProps["renderOption"]>>(
|
||||
({ option, selected, active, onPress }) => (
|
||||
<ComboboxItem
|
||||
@@ -69,10 +74,10 @@ export function BranchSwitcher({
|
||||
selected={selected}
|
||||
active={active}
|
||||
onPress={onPress}
|
||||
leadingSlot={<GitBranch size={14} color={theme.colors.foregroundMuted} />}
|
||||
leadingSlot={branchLeadingSlot}
|
||||
/>
|
||||
),
|
||||
[theme.colors.foregroundMuted],
|
||||
[branchLeadingSlot],
|
||||
);
|
||||
|
||||
if (!currentBranchName) {
|
||||
|
||||
@@ -235,6 +235,15 @@ function GithubPickerOption({
|
||||
const handlePress = useCallback(() => {
|
||||
onToggle(item);
|
||||
}, [onToggle, item]);
|
||||
const leadingSlot = useMemo(
|
||||
() =>
|
||||
item.kind === "pr" ? (
|
||||
<GitPullRequest size={theme.iconSize.sm} color={theme.colors.foregroundMuted} />
|
||||
) : (
|
||||
<CircleDot size={theme.iconSize.sm} color={theme.colors.foregroundMuted} />
|
||||
),
|
||||
[item.kind, theme.iconSize.sm, theme.colors.foregroundMuted],
|
||||
);
|
||||
return (
|
||||
<ComboboxItem
|
||||
testID={testID}
|
||||
@@ -242,13 +251,7 @@ function GithubPickerOption({
|
||||
selected={selected}
|
||||
active={active}
|
||||
onPress={handlePress}
|
||||
leadingSlot={
|
||||
item.kind === "pr" ? (
|
||||
<GitPullRequest size={theme.iconSize.sm} color={theme.colors.foregroundMuted} />
|
||||
) : (
|
||||
<CircleDot size={theme.iconSize.sm} color={theme.colors.foregroundMuted} />
|
||||
)
|
||||
}
|
||||
leadingSlot={leadingSlot}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { useCallback, useRef, useState } from "react";
|
||||
import { useCallback, useMemo, useRef, useState } from "react";
|
||||
import { Alert, Text, TextInput, View } from "react-native";
|
||||
import { StyleSheet, useUnistyles } from "react-native-unistyles";
|
||||
import { useIsCompactFormFactor } from "@/constants/layout";
|
||||
@@ -74,6 +74,11 @@ export function PairLinkModal({ visible, onClose, onCancel, onSaved }: PairLinkM
|
||||
inputRef.current?.clear();
|
||||
}, []);
|
||||
|
||||
const pairIcon = useMemo(
|
||||
() => <Link size={16} color={theme.colors.palette.white} />,
|
||||
[theme.colors.palette.white],
|
||||
);
|
||||
|
||||
const handleClose = useCallback(() => {
|
||||
if (isSaving) return;
|
||||
clearInput();
|
||||
@@ -209,7 +214,7 @@ export function PairLinkModal({ visible, onClose, onCancel, onSaved }: PairLinkM
|
||||
testID="pair-link-submit"
|
||||
accessibilityRole="button"
|
||||
accessibilityLabel="Pair"
|
||||
leftIcon={<Link size={16} color={theme.colors.palette.white} />}
|
||||
leftIcon={pairIcon}
|
||||
>
|
||||
{isSaving ? "Pairing..." : "Pair"}
|
||||
</Button>
|
||||
|
||||
@@ -72,6 +72,23 @@ export function PrPane({ data }: { data: PrPaneData }) {
|
||||
[data.activity],
|
||||
);
|
||||
|
||||
const checkSuccessIcon = useMemo(
|
||||
() => <CircleCheck size={12} color={theme.colors.statusSuccess} />,
|
||||
[theme.colors.statusSuccess],
|
||||
);
|
||||
const checkDangerIcon = useMemo(
|
||||
() => <CircleX size={12} color={theme.colors.statusDanger} />,
|
||||
[theme.colors.statusDanger],
|
||||
);
|
||||
const checkWarningIcon = useMemo(
|
||||
() => <CircleDot size={12} color={theme.colors.statusWarning} />,
|
||||
[theme.colors.statusWarning],
|
||||
);
|
||||
const commentIcon = useMemo(
|
||||
() => <MessageSquare size={11} color={theme.colors.foregroundMuted} />,
|
||||
[theme.colors.foregroundMuted],
|
||||
);
|
||||
|
||||
return (
|
||||
<View style={styles.root}>
|
||||
<Pressable onPress={handleOpenPrUrl} style={styles.header}>
|
||||
@@ -105,17 +122,13 @@ export function PrPane({ data }: { data: PrPaneData }) {
|
||||
<SummaryPill
|
||||
count={passed}
|
||||
color={theme.colors.statusSuccess}
|
||||
icon={<CircleCheck size={12} color={theme.colors.statusSuccess} />}
|
||||
/>
|
||||
<SummaryPill
|
||||
count={failed}
|
||||
color={theme.colors.statusDanger}
|
||||
icon={<CircleX size={12} color={theme.colors.statusDanger} />}
|
||||
icon={checkSuccessIcon}
|
||||
/>
|
||||
<SummaryPill count={failed} color={theme.colors.statusDanger} icon={checkDangerIcon} />
|
||||
<SummaryPill
|
||||
count={pending}
|
||||
color={theme.colors.statusWarning}
|
||||
icon={<CircleDot size={12} color={theme.colors.statusWarning} />}
|
||||
icon={checkWarningIcon}
|
||||
/>
|
||||
</>
|
||||
}
|
||||
@@ -136,17 +149,17 @@ export function PrPane({ data }: { data: PrPaneData }) {
|
||||
<SummaryPill
|
||||
count={approvals}
|
||||
color={theme.colors.statusSuccess}
|
||||
icon={<CircleCheck size={12} color={theme.colors.statusSuccess} />}
|
||||
icon={checkSuccessIcon}
|
||||
/>
|
||||
<SummaryPill
|
||||
count={changesRequested}
|
||||
color={theme.colors.statusDanger}
|
||||
icon={<CircleX size={12} color={theme.colors.statusDanger} />}
|
||||
icon={checkDangerIcon}
|
||||
/>
|
||||
<SummaryPill
|
||||
count={commentCount}
|
||||
color={theme.colors.foregroundMuted}
|
||||
icon={<MessageSquare size={11} color={theme.colors.foregroundMuted} />}
|
||||
icon={commentIcon}
|
||||
/>
|
||||
</>
|
||||
}
|
||||
|
||||
@@ -884,6 +884,11 @@ function ProjectHeaderRow({
|
||||
[isDragging, selected, isHovered],
|
||||
);
|
||||
|
||||
const removeProjectLeadingIcon = useMemo(
|
||||
() => <Trash2 size={14} color={theme.colors.foregroundMuted} />,
|
||||
[theme.colors.foregroundMuted],
|
||||
);
|
||||
|
||||
const rowChildren = (
|
||||
<>
|
||||
<View style={styles.projectRowLeft}>
|
||||
@@ -938,7 +943,7 @@ function ProjectHeaderRow({
|
||||
<DropdownMenuContent align="end" width={220}>
|
||||
<DropdownMenuItem
|
||||
testID={`sidebar-project-menu-remove-${project.projectKey}`}
|
||||
leading={<Trash2 size={14} color={theme.colors.foregroundMuted} />}
|
||||
leading={removeProjectLeadingIcon}
|
||||
status={removeProjectStatus}
|
||||
pendingLabel="Removing..."
|
||||
onSelect={onRemoveProject}
|
||||
@@ -1078,6 +1083,18 @@ function WorkspaceRowInner({
|
||||
],
|
||||
[isHovered, isCreating],
|
||||
);
|
||||
const copyLeadingIcon = useMemo(
|
||||
() => <Copy size={14} color={theme.colors.foregroundMuted} />,
|
||||
[theme.colors.foregroundMuted],
|
||||
);
|
||||
const archiveLeadingIcon = useMemo(
|
||||
() => <Archive size={14} color={theme.colors.foregroundMuted} />,
|
||||
[theme.colors.foregroundMuted],
|
||||
);
|
||||
const archiveTrailing = useMemo(
|
||||
() => (archiveShortcutKeys ? <Shortcut chord={archiveShortcutKeys} /> : null),
|
||||
[archiveShortcutKeys],
|
||||
);
|
||||
|
||||
return (
|
||||
<WorkspaceHoverCard workspace={workspace} prHint={prHint} isDragging={isDragging}>
|
||||
@@ -1143,7 +1160,7 @@ function WorkspaceRowInner({
|
||||
{onCopyPath ? (
|
||||
<DropdownMenuItem
|
||||
testID={`sidebar-workspace-menu-copy-path-${workspace.workspaceKey}`}
|
||||
leading={<Copy size={14} color={theme.colors.foregroundMuted} />}
|
||||
leading={copyLeadingIcon}
|
||||
onSelect={onCopyPath}
|
||||
>
|
||||
Copy path
|
||||
@@ -1152,7 +1169,7 @@ function WorkspaceRowInner({
|
||||
{onCopyBranchName ? (
|
||||
<DropdownMenuItem
|
||||
testID={`sidebar-workspace-menu-copy-branch-name-${workspace.workspaceKey}`}
|
||||
leading={<Copy size={14} color={theme.colors.foregroundMuted} />}
|
||||
leading={copyLeadingIcon}
|
||||
onSelect={onCopyBranchName}
|
||||
>
|
||||
Copy branch name
|
||||
@@ -1160,10 +1177,8 @@ function WorkspaceRowInner({
|
||||
) : null}
|
||||
<DropdownMenuItem
|
||||
testID={`sidebar-workspace-menu-archive-${workspace.workspaceKey}`}
|
||||
leading={<Archive size={14} color={theme.colors.foregroundMuted} />}
|
||||
trailing={
|
||||
archiveShortcutKeys ? <Shortcut chord={archiveShortcutKeys} /> : null
|
||||
}
|
||||
leading={archiveLeadingIcon}
|
||||
trailing={archiveTrailing}
|
||||
status={archiveStatus}
|
||||
pendingLabel={archivePendingLabel}
|
||||
onSelect={onArchive}
|
||||
|
||||
Reference in New Issue
Block a user