diff --git a/apps/web/package.json b/apps/web/package.json index 4c9396cc725b..4f9a3a8c80da 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -5,6 +5,8 @@ "type": "module", "scripts": { "build:ghostty-wasm": "bash scripts/build-libghostty-wasm.sh", + "icons:check": "node scripts/generate-icon-barrel.ts --check", + "icons:generate": "node scripts/generate-icon-barrel.ts", "dev": "vp dev", "build": "vp build", "preview": "vp preview", @@ -68,6 +70,7 @@ "compression": "^1.8.1", "react-test-renderer": "19.2.6", "tailwindcss": "^4.0.0", + "typescript": "catalog:", "vite": "catalog:", "vite-plus": "catalog:" } diff --git a/apps/web/scripts/generate-icon-barrel.ts b/apps/web/scripts/generate-icon-barrel.ts new file mode 100644 index 000000000000..2bec684a5f3a --- /dev/null +++ b/apps/web/scripts/generate-icon-barrel.ts @@ -0,0 +1,66 @@ +// @effect-diagnostics nodeBuiltinImport:off - this maintainer script reads and writes source files before the app runtime exists. +/** Regenerates src/icons/index.ts from the Lucide icons the web app actually imports. */ +import * as NodeFS from "node:fs"; +import * as NodePath from "node:path"; + +import { assertKnownIconNames, collectRuntimeIconNames } from "../src/icons/icon-import-parser.ts"; + +// The generator inspects Lucide's exports before it writes the barrel. +// eslint-disable-next-line no-restricted-imports +import * as lucide from "lucide-react"; + +const webRoot = NodePath.resolve(import.meta.dirname, ".."); +const srcRoot = NodePath.join(webRoot, "src"); +const testRoot = NodePath.join(webRoot, "test"); +const iconsRoot = NodePath.join(srcRoot, "icons"); + +function listSourceFiles(dir: string): string[] { + if (!NodeFS.existsSync(dir)) return []; + const files: string[] = []; + for (const entry of NodeFS.readdirSync(dir, { withFileTypes: true })) { + const fullPath = NodePath.join(dir, entry.name); + if (entry.isDirectory()) { + if (fullPath !== iconsRoot) files.push(...listSourceFiles(fullPath)); + } else if (/\.[jt]sx?$/.test(entry.name)) { + files.push(fullPath); + } + } + return files; +} + +const knownNames = new Set(Object.keys(lucide)); +const usedNames = new Set(); + +for (const root of [srcRoot, testRoot]) { + for (const file of listSourceFiles(root)) { + const names = collectRuntimeIconNames(NodeFS.readFileSync(file, "utf8"), file); + assertKnownIconNames(names, knownNames, file); + for (const name of names) usedNames.add(name); + } +} + +const sortedNames = [...usedNames].sort((left, right) => left.localeCompare(right, "en-US")); +const indexFile = `// Generated by scripts/generate-icon-barrel.ts — do not edit by hand. +// Rerun with: node apps/web/scripts/generate-icon-barrel.ts +/* eslint-disable no-restricted-imports -- this barrel owns direct Lucide imports. */ +export { +${sortedNames.map((name) => ` ${name},`).join("\n")} +} from "lucide-react"; + +export type { LucideIcon, LucideProps } from "lucide-react"; +`; +const indexPath = NodePath.join(iconsRoot, "index.ts"); + +if (process.argv.includes("--check")) { + const currentIndex = NodeFS.readFileSync(indexPath, "utf8"); + if (currentIndex !== indexFile) { + throw new Error( + "src/icons/index.ts is stale. Run `vp run --filter @t3tools/web icons:generate`.", + ); + } + console.log(`Verified ${sortedNames.length} generated Lucide exports in src/icons/index.ts.`); +} else { + NodeFS.mkdirSync(iconsRoot, { recursive: true }); + NodeFS.writeFileSync(indexPath, indexFile); + console.log(`Generated ${sortedNames.length} Lucide exports in src/icons/index.ts.`); +} diff --git a/apps/web/src/browser/BrowserDeviceToolbar.tsx b/apps/web/src/browser/BrowserDeviceToolbar.tsx index e8ad80b597ba..e9b6bf4eec7c 100644 --- a/apps/web/src/browser/BrowserDeviceToolbar.tsx +++ b/apps/web/src/browser/BrowserDeviceToolbar.tsx @@ -7,7 +7,7 @@ import { type PreviewViewportSetting, } from "@t3tools/contracts"; import { PREVIEW_VIEWPORT_PRESETS, resolvePreviewViewport } from "@t3tools/shared/previewViewport"; -import { Link2, Unlink2, X } from "lucide-react"; +import { Link2, Unlink2, X } from "~/icons"; import { useState } from "react"; import { Button } from "~/components/ui/button"; diff --git a/apps/web/src/components/AgentsPanel.tsx b/apps/web/src/components/AgentsPanel.tsx index 459506efc78c..05a807d0bd38 100644 --- a/apps/web/src/components/AgentsPanel.tsx +++ b/apps/web/src/components/AgentsPanel.tsx @@ -22,7 +22,7 @@ import { formatSubagentTokenCount, } from "@t3tools/client-runtime/state/subagentRuntime"; import type { EnvironmentId, ThreadId } from "@t3tools/contracts"; -import { Bot, Braces, Check, ChevronDown, ChevronRight, X } from "lucide-react"; +import { Bot, Braces, Check, ChevronDown, ChevronRight, X } from "~/icons"; import { useEffect, useRef, useState } from "react"; import { cn } from "~/lib/utils"; diff --git a/apps/web/src/components/BranchToolbar.tsx b/apps/web/src/components/BranchToolbar.tsx index 07407bcf21b3..dd77e66eb237 100644 --- a/apps/web/src/components/BranchToolbar.tsx +++ b/apps/web/src/components/BranchToolbar.tsx @@ -1,12 +1,6 @@ import { scopeProjectRef, scopeThreadRef } from "@t3tools/client-runtime/environment"; import type { EnvironmentId, ThreadId } from "@t3tools/contracts"; -import { - ChevronDownIcon, - FolderGit2Icon, - FolderGitIcon, - FolderIcon, - HistoryIcon, -} from "lucide-react"; +import { ChevronDownIcon, FolderGit2Icon, FolderGitIcon, FolderIcon, HistoryIcon } from "~/icons"; import { memo, useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState } from "react"; import { useComposerDraftStore, type DraftId } from "../composerDraftStore"; diff --git a/apps/web/src/components/BranchToolbarBranchSelector.tsx b/apps/web/src/components/BranchToolbarBranchSelector.tsx index 27bf2ede9b9a..7173a28c6cd7 100644 --- a/apps/web/src/components/BranchToolbarBranchSelector.tsx +++ b/apps/web/src/components/BranchToolbarBranchSelector.tsx @@ -5,7 +5,7 @@ import { } from "@t3tools/client-runtime/state/runtime"; import type { ContextMenuItem, EnvironmentId, VcsRef, ThreadId } from "@t3tools/contracts"; import { LegendList, type LegendListRef } from "@legendapp/list/react"; -import { ChevronDownIcon, GitBranchIcon, RefreshCwIcon, SearchIcon } from "lucide-react"; +import { ChevronDownIcon, GitBranchIcon, RefreshCwIcon, SearchIcon } from "~/icons"; import { useCallback, useDeferredValue, diff --git a/apps/web/src/components/BranchToolbarEnvModeSelector.tsx b/apps/web/src/components/BranchToolbarEnvModeSelector.tsx index c0fa463fe72a..999d8dcf331d 100644 --- a/apps/web/src/components/BranchToolbarEnvModeSelector.tsx +++ b/apps/web/src/components/BranchToolbarEnvModeSelector.tsx @@ -1,4 +1,4 @@ -import { FolderGit2Icon, FolderGitIcon, FolderIcon, HistoryIcon } from "lucide-react"; +import { FolderGit2Icon, FolderGitIcon, FolderIcon, HistoryIcon } from "~/icons"; import { memo, useMemo } from "react"; import { diff --git a/apps/web/src/components/ChatMarkdown.tsx b/apps/web/src/components/ChatMarkdown.tsx index 614c404d978e..722a1c1151f3 100644 --- a/apps/web/src/components/ChatMarkdown.tsx +++ b/apps/web/src/components/ChatMarkdown.tsx @@ -20,7 +20,7 @@ import { TriangleAlertIcon, WrapTextIcon, type LucideIcon, -} from "lucide-react"; +} from "~/icons"; import type { AssetResource, EnvironmentId, diff --git a/apps/web/src/components/ChatView.tsx b/apps/web/src/components/ChatView.tsx index b27d66c7611d..0d79f055206e 100644 --- a/apps/web/src/components/ChatView.tsx +++ b/apps/web/src/components/ChatView.tsx @@ -193,7 +193,7 @@ import { Minimize2Icon, PaperclipIcon, WifiOffIcon, -} from "lucide-react"; +} from "~/icons"; import { cn, randomHex } from "~/lib/utils"; import { stackedThreadToast, toastManager } from "./ui/toast"; import { decodeProjectScriptKeybindingRule } from "~/lib/projectScriptKeybindings"; diff --git a/apps/web/src/components/CommandPalette.tsx b/apps/web/src/components/CommandPalette.tsx index b0dd3febebcb..4e6fce148279 100644 --- a/apps/web/src/components/CommandPalette.tsx +++ b/apps/web/src/components/CommandPalette.tsx @@ -53,7 +53,7 @@ import { SettingsIcon, SquarePenIcon, TextSearchIcon, -} from "lucide-react"; +} from "~/icons"; import { useCallback, useDeferredValue, diff --git a/apps/web/src/components/CommandPaletteContent.tsx b/apps/web/src/components/CommandPaletteContent.tsx index 8c1a5b0e3c83..3508844b899e 100644 --- a/apps/web/src/components/CommandPaletteContent.tsx +++ b/apps/web/src/components/CommandPaletteContent.tsx @@ -1,4 +1,4 @@ -import { ArrowDownIcon, ArrowUpIcon } from "lucide-react"; +import { ArrowDownIcon, ArrowUpIcon } from "~/icons"; import { type ComponentProps, type ReactNode, useLayoutEffect, useRef } from "react"; import { Command, CommandFooter, CommandInput, CommandPanel } from "./ui/command"; diff --git a/apps/web/src/components/CommandPaletteResults.tsx b/apps/web/src/components/CommandPaletteResults.tsx index bbdbc28b0609..e928e1fe45eb 100644 --- a/apps/web/src/components/CommandPaletteResults.tsx +++ b/apps/web/src/components/CommandPaletteResults.tsx @@ -1,5 +1,5 @@ import { type ResolvedKeybindingsConfig } from "@t3tools/contracts"; -import { ChevronRightIcon } from "lucide-react"; +import { ChevronRightIcon } from "~/icons"; import { shortcutLabelForCommand } from "../keybindings"; import { type CommandPaletteActionItem, diff --git a/apps/web/src/components/DiffFilePathCopyButton.tsx b/apps/web/src/components/DiffFilePathCopyButton.tsx index 49b00ed89b74..185846b88c2a 100644 --- a/apps/web/src/components/DiffFilePathCopyButton.tsx +++ b/apps/web/src/components/DiffFilePathCopyButton.tsx @@ -1,4 +1,4 @@ -import { CheckIcon, CopyIcon } from "lucide-react"; +import { CheckIcon, CopyIcon } from "~/icons"; import { useRef } from "react"; import { useCopyToClipboard } from "../hooks/useCopyToClipboard"; import { diff --git a/apps/web/src/components/DiffPanel.tsx b/apps/web/src/components/DiffPanel.tsx index 87f5f1ba56f8..52729694d1ea 100644 --- a/apps/web/src/components/DiffPanel.tsx +++ b/apps/web/src/components/DiffPanel.tsx @@ -21,7 +21,7 @@ import { Rows3Icon, SearchIcon, TextWrapIcon, -} from "lucide-react"; +} from "~/icons"; import * as Schema from "effect/Schema"; import { useCallback, useEffect, useMemo, useRef, useState } from "react"; import { useCodeViewFileReveal } from "./diffs/useCodeViewFileReveal"; diff --git a/apps/web/src/components/EnvironmentMachineIcon.tsx b/apps/web/src/components/EnvironmentMachineIcon.tsx index 31b7a953a3a4..1b351f65969f 100644 --- a/apps/web/src/components/EnvironmentMachineIcon.tsx +++ b/apps/web/src/components/EnvironmentMachineIcon.tsx @@ -1,5 +1,5 @@ import type { EnvironmentMachineKind } from "@t3tools/contracts"; -import { CloudIcon, LaptopIcon, MonitorIcon, ServerIcon, type LucideProps } from "lucide-react"; +import { CloudIcon, LaptopIcon, MonitorIcon, ServerIcon, type LucideProps } from "~/icons"; import type { FunctionComponent, SVGProps } from "react"; // Lucide has no Apple desktops, so these two are drawn to its grammar (24 diff --git a/apps/web/src/components/GitActionsControl.tsx b/apps/web/src/components/GitActionsControl.tsx index b7fc811d5127..1d067c0d36b9 100644 --- a/apps/web/src/components/GitActionsControl.tsx +++ b/apps/web/src/components/GitActionsControl.tsx @@ -37,7 +37,7 @@ import { InfoIcon, LockIcon, GlobeIcon, -} from "lucide-react"; +} from "~/icons"; import { Radio as RadioPrimitive } from "@base-ui/react/radio"; import { AzureDevOpsIcon, BitbucketIcon, GitHubIcon, GitLabIcon } from "~/components/Icons"; import { RadioGroup } from "~/components/ui/radio-group"; diff --git a/apps/web/src/components/LegacySidebar.tsx b/apps/web/src/components/LegacySidebar.tsx index 650ad12bebcb..574c6865bd87 100644 --- a/apps/web/src/components/LegacySidebar.tsx +++ b/apps/web/src/components/LegacySidebar.tsx @@ -11,7 +11,7 @@ import { SquarePenIcon, TerminalIcon, TriangleAlertIcon, -} from "lucide-react"; +} from "~/icons"; import { ChangeRequestStatusIcon, prStatusIndicator, diff --git a/apps/web/src/components/ProjectFavicon.test.tsx b/apps/web/src/components/ProjectFavicon.test.tsx index bfb5487031b7..d46a4c587c20 100644 --- a/apps/web/src/components/ProjectFavicon.test.tsx +++ b/apps/web/src/components/ProjectFavicon.test.tsx @@ -53,7 +53,7 @@ vi.mock("react", async (importOriginal) => { }); vi.mock("react/compiler-runtime", () => ({ c: hooks.useMemoCache })); -vi.mock("lucide-react/dynamic", () => ({ +vi.mock("~/icons/dynamic", () => ({ DynamicIcon: "dynamic-icon", iconNames: ["alarm-clock", "folder-code"], })); diff --git a/apps/web/src/components/ProjectFavicon.tsx b/apps/web/src/components/ProjectFavicon.tsx index 2ebc6e267443..e5c4e88851b1 100644 --- a/apps/web/src/components/ProjectFavicon.tsx +++ b/apps/web/src/components/ProjectFavicon.tsx @@ -26,8 +26,8 @@ import { SmartphoneIcon, TerminalIcon, VideoIcon, -} from "lucide-react"; -import type { IconName } from "lucide-react/dynamic"; +} from "~/icons"; +import type { IconName } from "~/icons/dynamic"; import type { ComponentType } from "react"; import { lazy, Suspense, useState } from "react"; import { useAssetUrlState } from "../assets/assetUrls"; @@ -37,7 +37,7 @@ import { cn } from "~/lib/utils"; const loadedProjectFaviconSrcs = new Map(); const DynamicIcon = lazy(() => - import("lucide-react/dynamic").then((module) => ({ default: module.DynamicIcon })), + import("~/icons/dynamic").then((module) => ({ default: module.DynamicIcon })), ); function DynamicProjectIconFallback() { diff --git a/apps/web/src/components/ProjectScriptsControl.tsx b/apps/web/src/components/ProjectScriptsControl.tsx index 304922909b0a..592c421d34a5 100644 --- a/apps/web/src/components/ProjectScriptsControl.tsx +++ b/apps/web/src/components/ProjectScriptsControl.tsx @@ -7,7 +7,7 @@ import { isAtomCommandInterrupted, squashAtomCommandFailure, } from "@t3tools/client-runtime/state/runtime"; -import { ChevronDownIcon, DownloadIcon, PlusIcon, SettingsIcon } from "lucide-react"; +import { ChevronDownIcon, DownloadIcon, PlusIcon, SettingsIcon } from "~/icons"; import { useCallback, useMemo, useState } from "react"; import { commandForProjectScript, primaryProjectScript } from "~/projectScripts"; diff --git a/apps/web/src/components/ProviderUpdateEnvironmentRows.tsx b/apps/web/src/components/ProviderUpdateEnvironmentRows.tsx index 56aaa9e96ff0..e7508f96da7f 100644 --- a/apps/web/src/components/ProviderUpdateEnvironmentRows.tsx +++ b/apps/web/src/components/ProviderUpdateEnvironmentRows.tsx @@ -1,4 +1,4 @@ -import { CheckIcon } from "lucide-react"; +import { CheckIcon } from "~/icons"; import { type ReactNode, useCallback, useMemo, useRef, useState } from "react"; import type { EnvironmentId, ServerProvider } from "@t3tools/contracts"; import { diff --git a/apps/web/src/components/ProviderUpdateLaunchNotification.tsx b/apps/web/src/components/ProviderUpdateLaunchNotification.tsx index 2292a2c45103..b4d515be3842 100644 --- a/apps/web/src/components/ProviderUpdateLaunchNotification.tsx +++ b/apps/web/src/components/ProviderUpdateLaunchNotification.tsx @@ -1,5 +1,5 @@ import { useNavigate } from "@tanstack/react-router"; -import { DownloadIcon } from "lucide-react"; +import { DownloadIcon } from "~/icons"; import { useCallback, useEffect, useMemo, useRef, useState } from "react"; import { useEnvironments } from "~/state/environments"; diff --git a/apps/web/src/components/ProviderUpdatePrimaryNotification.tsx b/apps/web/src/components/ProviderUpdatePrimaryNotification.tsx index a0ed3d80467f..18ed961593c8 100644 --- a/apps/web/src/components/ProviderUpdatePrimaryNotification.tsx +++ b/apps/web/src/components/ProviderUpdatePrimaryNotification.tsx @@ -1,6 +1,6 @@ import { useNavigate } from "@tanstack/react-router"; import { useAtomValue } from "@effect/atom-react"; -import { DownloadIcon } from "lucide-react"; +import { DownloadIcon } from "~/icons"; import { useCallback, useEffect, useMemo, useRef } from "react"; import { type ProviderDriverKind, type ProviderInstanceId } from "@t3tools/contracts"; diff --git a/apps/web/src/components/RightPanelTabs.tsx b/apps/web/src/components/RightPanelTabs.tsx index e9dab0c9d2b4..1ed2d3d1b0a8 100644 --- a/apps/web/src/components/RightPanelTabs.tsx +++ b/apps/web/src/components/RightPanelTabs.tsx @@ -19,7 +19,7 @@ import { TerminalSquare, Volume2, VolumeOff, -} from "lucide-react"; +} from "~/icons"; import { type KeyboardEvent as ReactKeyboardEvent, type MouseEvent as ReactMouseEvent, diff --git a/apps/web/src/components/Sidebar.tsx b/apps/web/src/components/Sidebar.tsx index 77b7b0abf0a6..52583c6f5bb5 100644 --- a/apps/web/src/components/Sidebar.tsx +++ b/apps/web/src/components/Sidebar.tsx @@ -57,7 +57,7 @@ import { TerminalIcon, Undo2Icon, XIcon, -} from "lucide-react"; +} from "~/icons"; import { memo, useCallback, diff --git a/apps/web/src/components/ThreadCommandSubtitle.tsx b/apps/web/src/components/ThreadCommandSubtitle.tsx index cd5074518719..66f1c55379b5 100644 --- a/apps/web/src/components/ThreadCommandSubtitle.tsx +++ b/apps/web/src/components/ThreadCommandSubtitle.tsx @@ -1,5 +1,5 @@ import type { EnvironmentId, ProviderDriverKind } from "@t3tools/contracts"; -import { FolderGit2Icon, FolderIcon, GitBranchIcon } from "lucide-react"; +import { FolderGit2Icon, FolderIcon, GitBranchIcon } from "~/icons"; import { ProjectFavicon } from "./ProjectFavicon"; import { ProviderInstanceIcon } from "./chat/ProviderInstanceIcon"; import { cn } from "~/lib/utils"; diff --git a/apps/web/src/components/ThreadStatusIndicators.test.ts b/apps/web/src/components/ThreadStatusIndicators.test.ts index 21949a1d1808..5bb96ffcd9b0 100644 --- a/apps/web/src/components/ThreadStatusIndicators.test.ts +++ b/apps/web/src/components/ThreadStatusIndicators.test.ts @@ -7,7 +7,7 @@ import { GitPullRequestClosedIcon, GitPullRequestDraftIcon, GitPullRequestIcon, -} from "lucide-react"; +} from "~/icons"; import { ChangeRequestStatusIcon, diff --git a/apps/web/src/components/ThreadStatusIndicators.tsx b/apps/web/src/components/ThreadStatusIndicators.tsx index e7b24f80cb71..4c3cc3414743 100644 --- a/apps/web/src/components/ThreadStatusIndicators.tsx +++ b/apps/web/src/components/ThreadStatusIndicators.tsx @@ -11,7 +11,7 @@ import { type VcsStatusResult, } from "@t3tools/contracts"; import { Atom } from "effect/unstable/reactivity"; -import { FolderGit2Icon, TerminalIcon } from "lucide-react"; +import { FolderGit2Icon, TerminalIcon } from "~/icons"; import { useMemo } from "react"; import { appAtomRegistry } from "../rpc/atomRegistry"; import { useEnvironment, usePrimaryEnvironmentId } from "../state/environments"; diff --git a/apps/web/src/components/ThreadTerminalDrawer.tsx b/apps/web/src/components/ThreadTerminalDrawer.tsx index 9f4956aae682..02c59132632f 100644 --- a/apps/web/src/components/ThreadTerminalDrawer.tsx +++ b/apps/web/src/components/ThreadTerminalDrawer.tsx @@ -17,7 +17,7 @@ import { SquareSplitVertical, TerminalSquare, Trash2, -} from "lucide-react"; +} from "~/icons"; import { type ContextMenuItem, type ResolvedKeybindingsConfig, diff --git a/apps/web/src/components/chat/AssistantCitationChip.tsx b/apps/web/src/components/chat/AssistantCitationChip.tsx index 7582bb19c5c6..88692b8541a2 100644 --- a/apps/web/src/components/chat/AssistantCitationChip.tsx +++ b/apps/web/src/components/chat/AssistantCitationChip.tsx @@ -1,7 +1,7 @@ import type { AssistantCitation } from "@t3tools/contracts"; import { serializeAssistantCitation } from "@t3tools/shared/assistantCitations"; import { Link, useNavigate } from "@tanstack/react-router"; -import { PencilIcon, QuoteIcon, XIcon } from "lucide-react"; +import { PencilIcon, QuoteIcon, XIcon } from "~/icons"; import { useEffect, useEffectEvent, useRef, type MouseEvent as ReactMouseEvent } from "react"; import { findAssistantCitationSourceAnchor, diff --git a/apps/web/src/components/chat/AssistantSelectionToolbar.tsx b/apps/web/src/components/chat/AssistantSelectionToolbar.tsx index a7c622ade17a..b7436a6c566f 100644 --- a/apps/web/src/components/chat/AssistantSelectionToolbar.tsx +++ b/apps/web/src/components/chat/AssistantSelectionToolbar.tsx @@ -4,7 +4,7 @@ import { type AssistantCitation, type ScopedThreadRef, } from "@t3tools/contracts"; -import { QuoteIcon } from "lucide-react"; +import { QuoteIcon } from "~/icons"; import { useEffect, useLayoutEffect, useRef, useState } from "react"; import { createPortal } from "react-dom"; import { diff --git a/apps/web/src/components/chat/ChangedFilesTree.tsx b/apps/web/src/components/chat/ChangedFilesTree.tsx index 5ac9f09613f3..138580de2a6c 100644 --- a/apps/web/src/components/chat/ChangedFilesTree.tsx +++ b/apps/web/src/components/chat/ChangedFilesTree.tsx @@ -13,7 +13,7 @@ import { FileDiffIcon, FolderIcon, FolderClosedIcon, -} from "lucide-react"; +} from "~/icons"; import { cn } from "~/lib/utils"; import { DiffStatLabel, hasNonZeroStat } from "./DiffStatLabel"; import { PierreEntryIcon } from "./PierreEntryIcon"; diff --git a/apps/web/src/components/chat/ChatComposer.tsx b/apps/web/src/components/chat/ChatComposer.tsx index 10898e311cef..945b9dd85227 100644 --- a/apps/web/src/components/chat/ChatComposer.tsx +++ b/apps/web/src/components/chat/ChatComposer.tsx @@ -791,7 +791,7 @@ import { RotateCcwIcon, SparklesIcon, XIcon, -} from "lucide-react"; +} from "~/icons"; import { proposedPlanTitle } from "../../proposedPlan"; import { hasProviderSetup } from "./ProviderStatusBanner"; import { diff --git a/apps/web/src/components/chat/ChatHeader.tsx b/apps/web/src/components/chat/ChatHeader.tsx index 98b661bf5ff6..b837fd0957c4 100644 --- a/apps/web/src/components/chat/ChatHeader.tsx +++ b/apps/web/src/components/chat/ChatHeader.tsx @@ -10,7 +10,7 @@ import { isAtomCommandInterrupted, squashAtomCommandFailure, } from "@t3tools/client-runtime/state/runtime"; -import { ChevronDownIcon } from "lucide-react"; +import { ChevronDownIcon } from "~/icons"; import { memo, useCallback, diff --git a/apps/web/src/components/chat/CompactComposerControlsMenu.tsx b/apps/web/src/components/chat/CompactComposerControlsMenu.tsx index 039f12d40873..575a753e51a5 100644 --- a/apps/web/src/components/chat/CompactComposerControlsMenu.tsx +++ b/apps/web/src/components/chat/CompactComposerControlsMenu.tsx @@ -1,6 +1,6 @@ import { ProviderInteractionMode, RuntimeMode } from "@t3tools/contracts"; import { memo, type ReactNode } from "react"; -import { EllipsisIcon } from "lucide-react"; +import { EllipsisIcon } from "~/icons"; import { Menu, MenuPopup, diff --git a/apps/web/src/components/chat/ComposerActivityStatus.tsx b/apps/web/src/components/chat/ComposerActivityStatus.tsx index d9e459bcf9ee..8ee95032c3f4 100644 --- a/apps/web/src/components/chat/ComposerActivityStatus.tsx +++ b/apps/web/src/components/chat/ComposerActivityStatus.tsx @@ -1,4 +1,4 @@ -import { LoaderCircleIcon } from "lucide-react"; +import { LoaderCircleIcon } from "~/icons"; import { observeVisibleAnimation } from "../../lib/visibleAnimation"; import { threadSyncLabel, type ThreadSyncPhase } from "../../threadSync"; import { ComposerBanner } from "./ComposerBanner"; diff --git a/apps/web/src/components/chat/ComposerBanner.tsx b/apps/web/src/components/chat/ComposerBanner.tsx index 092baa0ec8af..4e60b331d68c 100644 --- a/apps/web/src/components/chat/ComposerBanner.tsx +++ b/apps/web/src/components/chat/ComposerBanner.tsx @@ -1,6 +1,6 @@ import { mergeProps } from "@base-ui/react/merge-props"; import { useRender } from "@base-ui/react/use-render"; -import { ChevronDownIcon, XIcon } from "lucide-react"; +import { ChevronDownIcon, XIcon } from "~/icons"; import type { ComponentProps } from "react"; import { cn } from "~/lib/utils"; diff --git a/apps/web/src/components/chat/ComposerBannerStack.tsx b/apps/web/src/components/chat/ComposerBannerStack.tsx index 5de40a0d90d5..4bc5c5db33cf 100644 --- a/apps/web/src/components/chat/ComposerBannerStack.tsx +++ b/apps/web/src/components/chat/ComposerBannerStack.tsx @@ -1,4 +1,4 @@ -import { InfoIcon } from "lucide-react"; +import { InfoIcon } from "~/icons"; import { useEffect, useId, useLayoutEffect, useRef, useState, type ReactNode } from "react"; import { cn } from "~/lib/utils"; diff --git a/apps/web/src/components/chat/ComposerCommandMenu.tsx b/apps/web/src/components/chat/ComposerCommandMenu.tsx index 8e940969e72d..7cbf06a7d751 100644 --- a/apps/web/src/components/chat/ComposerCommandMenu.tsx +++ b/apps/web/src/components/chat/ComposerCommandMenu.tsx @@ -16,7 +16,7 @@ import { SettingsIcon, UserRoundIcon, type LucideIcon, -} from "lucide-react"; +} from "~/icons"; import { memo, useLayoutEffect, useRef } from "react"; import { type ComposerSlashCommand, type ComposerTriggerKind } from "../../composer-logic"; diff --git a/apps/web/src/components/chat/ComposerControl.tsx b/apps/web/src/components/chat/ComposerControl.tsx index 7b233a68ba8d..33f2db80ad22 100644 --- a/apps/web/src/components/chat/ComposerControl.tsx +++ b/apps/web/src/components/chat/ComposerControl.tsx @@ -1,5 +1,5 @@ import type { ComponentProps } from "react"; -import { ChevronDownIcon, type LucideIcon } from "lucide-react"; +import { ChevronDownIcon, type LucideIcon } from "~/icons"; import { cn } from "~/lib/utils"; import { Button } from "../ui/button"; diff --git a/apps/web/src/components/chat/ComposerPendingApprovalActions.tsx b/apps/web/src/components/chat/ComposerPendingApprovalActions.tsx index 33f5afe50d75..2f49b608e5aa 100644 --- a/apps/web/src/components/chat/ComposerPendingApprovalActions.tsx +++ b/apps/web/src/components/chat/ComposerPendingApprovalActions.tsx @@ -4,7 +4,7 @@ import { type ProviderApprovalOption, } from "@t3tools/contracts"; import { memo } from "react"; -import { TriangleAlertIcon } from "lucide-react"; +import { TriangleAlertIcon } from "~/icons"; import { Button } from "../ui/button"; import { Tooltip, TooltipPopup, TooltipTrigger } from "../ui/tooltip"; diff --git a/apps/web/src/components/chat/ComposerPendingElementContexts.tsx b/apps/web/src/components/chat/ComposerPendingElementContexts.tsx index 7373403a7c39..abf6512c3788 100644 --- a/apps/web/src/components/chat/ComposerPendingElementContexts.tsx +++ b/apps/web/src/components/chat/ComposerPendingElementContexts.tsx @@ -1,4 +1,4 @@ -import { MousePointerClick, X } from "lucide-react"; +import { MousePointerClick, X } from "~/icons"; import { COMPOSER_INLINE_CHIP_CLASS_NAME, diff --git a/apps/web/src/components/chat/ComposerPendingReviewComments.tsx b/apps/web/src/components/chat/ComposerPendingReviewComments.tsx index 455e6609175c..23e05944cfea 100644 --- a/apps/web/src/components/chat/ComposerPendingReviewComments.tsx +++ b/apps/web/src/components/chat/ComposerPendingReviewComments.tsx @@ -1,4 +1,4 @@ -import { MessageCircle, X } from "lucide-react"; +import { MessageCircle, X } from "~/icons"; import { COMPOSER_INLINE_CHIP_CLASS_NAME, diff --git a/apps/web/src/components/chat/ComposerPendingUserInputPanel.tsx b/apps/web/src/components/chat/ComposerPendingUserInputPanel.tsx index 2a7df2488233..bbe4f3ef052d 100644 --- a/apps/web/src/components/chat/ComposerPendingUserInputPanel.tsx +++ b/apps/web/src/components/chat/ComposerPendingUserInputPanel.tsx @@ -5,7 +5,7 @@ import { derivePendingUserInputProgress, type PendingUserInputDraftAnswer, } from "../../pendingUserInput"; -import { CheckIcon } from "lucide-react"; +import { CheckIcon } from "~/icons"; import { Collapsible, CollapsiblePanel, CollapsibleTrigger } from "../ui/collapsible"; import { cn } from "~/lib/utils"; import { ComposerBanner } from "./ComposerBanner"; diff --git a/apps/web/src/components/chat/ComposerPreviewAnnotationCards.tsx b/apps/web/src/components/chat/ComposerPreviewAnnotationCards.tsx index 8eb7e9897b8e..48246b276eb6 100644 --- a/apps/web/src/components/chat/ComposerPreviewAnnotationCards.tsx +++ b/apps/web/src/components/chat/ComposerPreviewAnnotationCards.tsx @@ -1,5 +1,5 @@ import type { PreviewAnnotationPayload } from "@t3tools/contracts"; -import { Frame, MousePointerClick, Paintbrush, PenLine, RotateCcw, X } from "lucide-react"; +import { Frame, MousePointerClick, Paintbrush, PenLine, RotateCcw, X } from "~/icons"; import type { ReactNode } from "react"; import type { ComposerImageAttachment } from "~/composerDraftStore"; diff --git a/apps/web/src/components/chat/ComposerPrimaryActions.tsx b/apps/web/src/components/chat/ComposerPrimaryActions.tsx index 46323aa2b09a..d2612e3db28d 100644 --- a/apps/web/src/components/chat/ComposerPrimaryActions.tsx +++ b/apps/web/src/components/chat/ComposerPrimaryActions.tsx @@ -1,5 +1,5 @@ import { memo, type PointerEventHandler } from "react"; -import { ChevronDownIcon, ChevronLeftIcon } from "lucide-react"; +import { ChevronDownIcon, ChevronLeftIcon } from "~/icons"; import { useEnvironmentIdentificationMode } from "~/hooks/useSettings"; import { cn } from "~/lib/utils"; import { StageBackdropButtonArt, useSidebarStageBackdropVariant } from "../SidebarStageBackdrop"; diff --git a/apps/web/src/components/chat/ComposerServerUpdateStatus.tsx b/apps/web/src/components/chat/ComposerServerUpdateStatus.tsx index 4c5aa60ff06a..797d73b7b90f 100644 --- a/apps/web/src/components/chat/ComposerServerUpdateStatus.tsx +++ b/apps/web/src/components/chat/ComposerServerUpdateStatus.tsx @@ -1,5 +1,5 @@ import type { ServerUpdateState } from "@t3tools/client-runtime/state/server"; -import { CircleAlertIcon, DownloadIcon, LoaderCircleIcon } from "lucide-react"; +import { CircleAlertIcon, DownloadIcon, LoaderCircleIcon } from "~/icons"; import { useId, useState } from "react"; import { observeVisibleAnimation } from "../../lib/visibleAnimation"; diff --git a/apps/web/src/components/chat/ComposerStashBadge.tsx b/apps/web/src/components/chat/ComposerStashBadge.tsx index 9a70094669fa..46403d23c17f 100644 --- a/apps/web/src/components/chat/ComposerStashBadge.tsx +++ b/apps/web/src/components/chat/ComposerStashBadge.tsx @@ -1,4 +1,4 @@ -import { BookmarkIcon } from "lucide-react"; +import { BookmarkIcon } from "~/icons"; import { memo } from "react"; import { cn } from "~/lib/utils"; diff --git a/apps/web/src/components/chat/ComposerStashMenu.tsx b/apps/web/src/components/chat/ComposerStashMenu.tsx index 4942b21dd600..6ff260050ed4 100644 --- a/apps/web/src/components/chat/ComposerStashMenu.tsx +++ b/apps/web/src/components/chat/ComposerStashMenu.tsx @@ -1,4 +1,4 @@ -import { BookmarkIcon, FileIcon, FileTextIcon } from "lucide-react"; +import { BookmarkIcon, FileIcon, FileTextIcon } from "~/icons"; import { memo, useEffect, useRef, useState } from "react"; import { assistantCitationsToPlainText } from "@t3tools/shared/assistantCitations"; diff --git a/apps/web/src/components/chat/ComposerTasksBadge.tsx b/apps/web/src/components/chat/ComposerTasksBadge.tsx index ae2f4aa5849a..34b12c380f93 100644 --- a/apps/web/src/components/chat/ComposerTasksBadge.tsx +++ b/apps/web/src/components/chat/ComposerTasksBadge.tsx @@ -1,4 +1,4 @@ -import { ListTodoIcon } from "lucide-react"; +import { ListTodoIcon } from "~/icons"; import { memo, type ComponentProps } from "react"; import { formatDuration } from "../../session-logic"; diff --git a/apps/web/src/components/chat/ContextWindowMeter.tsx b/apps/web/src/components/chat/ContextWindowMeter.tsx index a11f400c0627..f398ef4c03b4 100644 --- a/apps/web/src/components/chat/ContextWindowMeter.tsx +++ b/apps/web/src/components/chat/ContextWindowMeter.tsx @@ -2,7 +2,7 @@ import { Button } from "../ui/button"; import { type ContextWindowSnapshot, formatContextWindowTokens } from "~/lib/contextWindow"; import { Popover, PopoverPopup, PopoverTrigger } from "../ui/popover"; import { formatContextWindowCompactionMessage } from "./ContextWindowMeter.logic"; -import { Minimize2Icon } from "lucide-react"; +import { Minimize2Icon } from "~/icons"; import { composerFloatingLayerProps } from "./composerEventScope"; function formatPercentage(value: number | null): string | null { diff --git a/apps/web/src/components/chat/DraftHeroHeadline.tsx b/apps/web/src/components/chat/DraftHeroHeadline.tsx index 04bbeb6ce49b..367a98cab253 100644 --- a/apps/web/src/components/chat/DraftHeroHeadline.tsx +++ b/apps/web/src/components/chat/DraftHeroHeadline.tsx @@ -2,7 +2,7 @@ import type { DraftId } from "~/composerDraftStore"; import { useComposerDraftStore } from "~/composerDraftStore"; import type { ScopedProjectRef } from "@t3tools/contracts"; import { scopedProjectKey, scopeProjectRef } from "@t3tools/client-runtime/environment"; -import { FolderPlusIcon } from "lucide-react"; +import { FolderPlusIcon } from "~/icons"; import { useCallback, useMemo } from "react"; import { openCommandPalette } from "~/commandPaletteBus"; diff --git a/apps/web/src/components/chat/ExpandedImageDialog.tsx b/apps/web/src/components/chat/ExpandedImageDialog.tsx index a41c34268c22..2feb7ccbb3ee 100644 --- a/apps/web/src/components/chat/ExpandedImageDialog.tsx +++ b/apps/web/src/components/chat/ExpandedImageDialog.tsx @@ -1,6 +1,6 @@ import { memo, useCallback, useEffect, useRef, useState, type ReactNode } from "react"; import { createPortal } from "react-dom"; -import { ChevronLeftIcon, ChevronRightIcon, XIcon } from "lucide-react"; +import { ChevronLeftIcon, ChevronRightIcon, XIcon } from "~/icons"; import { Button } from "../ui/button"; import type { ExpandedImageItem, ExpandedImagePreview } from "./ExpandedImagePreview"; import { resolveExternalWebLinkHost } from "./externalLinkContextMenu"; diff --git a/apps/web/src/components/chat/MessageCopyButton.tsx b/apps/web/src/components/chat/MessageCopyButton.tsx index 86e1a5d3c8d5..361aa127c39e 100644 --- a/apps/web/src/components/chat/MessageCopyButton.tsx +++ b/apps/web/src/components/chat/MessageCopyButton.tsx @@ -1,5 +1,5 @@ import { memo, useRef } from "react"; -import { CopyIcon, CheckIcon } from "lucide-react"; +import { CopyIcon, CheckIcon } from "~/icons"; import { Button } from "../ui/button"; import { useCopyToClipboard } from "~/hooks/useCopyToClipboard"; import { cn } from "~/lib/utils"; diff --git a/apps/web/src/components/chat/MessagesTimeline.tsx b/apps/web/src/components/chat/MessagesTimeline.tsx index 6c6901a08881..b91a3d5e2c3b 100644 --- a/apps/web/src/components/chat/MessagesTimeline.tsx +++ b/apps/web/src/components/chat/MessagesTimeline.tsx @@ -101,7 +101,7 @@ import { WrenchIcon, XIcon, ZapIcon, -} from "lucide-react"; +} from "~/icons"; import { Button } from "../ui/button"; import { useAssetUrlRefresh, useAssetUrls, useAssetUrlState } from "../../assets/assetUrls"; import { MediaVideoPlayer } from "../media/MediaVideoPlayer"; diff --git a/apps/web/src/components/chat/ModelListRow.tsx b/apps/web/src/components/chat/ModelListRow.tsx index caa595dffd86..a412e9d37a79 100644 --- a/apps/web/src/components/chat/ModelListRow.tsx +++ b/apps/web/src/components/chat/ModelListRow.tsx @@ -1,6 +1,6 @@ import { type ProviderDriverKind, type ProviderInstanceId } from "@t3tools/contracts"; import { memo } from "react"; -import { StarIcon } from "lucide-react"; +import { StarIcon } from "~/icons"; import { getDisplayModelName, getTriggerDisplayModelLabel, diff --git a/apps/web/src/components/chat/ModelPickerContent.tsx b/apps/web/src/components/chat/ModelPickerContent.tsx index 63dea7844c46..1bb3d90e4dad 100644 --- a/apps/web/src/components/chat/ModelPickerContent.tsx +++ b/apps/web/src/components/chat/ModelPickerContent.tsx @@ -8,7 +8,7 @@ import { resolveSelectableModel } from "@t3tools/shared/model"; import { useAtomValue } from "@effect/atom-react"; import { LegendList, type LegendListRef } from "@legendapp/list/react"; import { memo, useMemo, useState, useCallback, useEffect, useLayoutEffect, useRef } from "react"; -import { ChevronRightIcon, SearchIcon } from "lucide-react"; +import { ChevronRightIcon, SearchIcon } from "~/icons"; import { ModelListRow } from "./ModelListRow"; import { ModelPickerSidebar } from "./ModelPickerSidebar"; import { getProviderStatusMessage, hasProviderSetup } from "./ProviderStatusBanner"; diff --git a/apps/web/src/components/chat/ModelPickerSidebar.tsx b/apps/web/src/components/chat/ModelPickerSidebar.tsx index dd53270268ba..b3e7d9216403 100644 --- a/apps/web/src/components/chat/ModelPickerSidebar.tsx +++ b/apps/web/src/components/chat/ModelPickerSidebar.tsx @@ -1,6 +1,6 @@ import { type ProviderInstanceId } from "@t3tools/contracts"; import { memo, useLayoutEffect, useRef, useState } from "react"; -import { SparklesIcon, StarIcon } from "lucide-react"; +import { SparklesIcon, StarIcon } from "~/icons"; import { ProviderInstanceIcon } from "./ProviderInstanceIcon"; import { Tooltip, TooltipPopup, TooltipTrigger } from "../ui/tooltip"; import { cn } from "~/lib/utils"; diff --git a/apps/web/src/components/chat/OpenInPicker.tsx b/apps/web/src/components/chat/OpenInPicker.tsx index b9bf831c14d9..29ed7855b8c8 100644 --- a/apps/web/src/components/chat/OpenInPicker.tsx +++ b/apps/web/src/components/chat/OpenInPicker.tsx @@ -15,7 +15,7 @@ import { useRemoteOpenState, } from "../../remoteOpen"; import { useEnvironment } from "../../state/environments"; -import { ChevronDownIcon, FolderClosedIcon } from "lucide-react"; +import { ChevronDownIcon, FolderClosedIcon } from "~/icons"; import { Button } from "../ui/button"; import { Group, GroupSeparator } from "../ui/group"; import { Menu, MenuItem, MenuPopup, MenuShortcut, MenuTrigger } from "../ui/menu"; diff --git a/apps/web/src/components/chat/PanelLayoutControls.tsx b/apps/web/src/components/chat/PanelLayoutControls.tsx index 8e8e640ee83e..9a4025431b46 100644 --- a/apps/web/src/components/chat/PanelLayoutControls.tsx +++ b/apps/web/src/components/chat/PanelLayoutControls.tsx @@ -1,4 +1,4 @@ -import { Maximize2Icon, Minimize2Icon, PanelBottomIcon, PanelRightIcon } from "lucide-react"; +import { Maximize2Icon, Minimize2Icon, PanelBottomIcon, PanelRightIcon } from "~/icons"; import { memo } from "react"; import { Toggle } from "../ui/toggle"; diff --git a/apps/web/src/components/chat/PierreEntryIcon.tsx b/apps/web/src/components/chat/PierreEntryIcon.tsx index df41adb7dd53..e79bb6a75e87 100644 --- a/apps/web/src/components/chat/PierreEntryIcon.tsx +++ b/apps/web/src/components/chat/PierreEntryIcon.tsx @@ -1,4 +1,4 @@ -import { FileIcon, FolderIcon } from "lucide-react"; +import { FileIcon, FolderIcon } from "~/icons"; import { memo, useInsertionEffect, useMemo } from "react"; import { ensurePierreIconSprite, resolvePierreIconForEntry } from "../../pierre-icons"; diff --git a/apps/web/src/components/chat/ProposedPlanCard.tsx b/apps/web/src/components/chat/ProposedPlanCard.tsx index 9746857a8cac..40d8e6c5856c 100644 --- a/apps/web/src/components/chat/ProposedPlanCard.tsx +++ b/apps/web/src/components/chat/ProposedPlanCard.tsx @@ -13,7 +13,7 @@ import { stripDisplayedPlanMarkdown, } from "../../proposedPlan"; import ChatMarkdown from "../ChatMarkdown"; -import { EllipsisIcon } from "lucide-react"; +import { EllipsisIcon } from "~/icons"; import { Button } from "../ui/button"; import { Input } from "../ui/input"; import { Menu, MenuItem, MenuPopup, MenuTrigger } from "../ui/menu"; diff --git a/apps/web/src/components/chat/ProviderStatusBanner.tsx b/apps/web/src/components/chat/ProviderStatusBanner.tsx index 12f9dc04f26a..3919dd280dc6 100644 --- a/apps/web/src/components/chat/ProviderStatusBanner.tsx +++ b/apps/web/src/components/chat/ProviderStatusBanner.tsx @@ -1,6 +1,6 @@ import { type ProviderInstanceId, type ServerProvider } from "@t3tools/contracts"; import { memo } from "react"; -import { InfoIcon, XIcon } from "lucide-react"; +import { InfoIcon, XIcon } from "~/icons"; import { cn } from "~/lib/utils"; import { Button } from "../ui/button"; import { formatProviderDriverKindLabel } from "../../providerModels"; diff --git a/apps/web/src/components/chat/TerminalContextInlineChip.tsx b/apps/web/src/components/chat/TerminalContextInlineChip.tsx index 29eb3bf4db39..5b85026ec18b 100644 --- a/apps/web/src/components/chat/TerminalContextInlineChip.tsx +++ b/apps/web/src/components/chat/TerminalContextInlineChip.tsx @@ -1,4 +1,4 @@ -import { TerminalIcon } from "lucide-react"; +import { TerminalIcon } from "~/icons"; import { cn } from "~/lib/utils"; import { diff --git a/apps/web/src/components/chat/ThreadErrorBanner.tsx b/apps/web/src/components/chat/ThreadErrorBanner.tsx index 29a6a6db1846..118c6e4ab9b3 100644 --- a/apps/web/src/components/chat/ThreadErrorBanner.tsx +++ b/apps/web/src/components/chat/ThreadErrorBanner.tsx @@ -1,7 +1,7 @@ import { memo } from "react"; import { Alert, AlertAction, AlertDescription } from "../ui/alert"; import { Button } from "../ui/button"; -import { CircleAlertIcon, XIcon } from "lucide-react"; +import { CircleAlertIcon, XIcon } from "~/icons"; import { Tooltip, TooltipPopup, TooltipTrigger } from "../ui/tooltip"; export function getThreadErrorBannerKey(threadKey: string, error: string | null): string | null { diff --git a/apps/web/src/components/chat/TraitsPicker.tsx b/apps/web/src/components/chat/TraitsPicker.tsx index 47ce59efde52..83d066b05e4e 100644 --- a/apps/web/src/components/chat/TraitsPicker.tsx +++ b/apps/web/src/components/chat/TraitsPicker.tsx @@ -17,7 +17,7 @@ import { } from "@t3tools/shared/model"; import { memo, useCallback } from "react"; import type { VariantProps } from "class-variance-authority"; -import { ZapIcon } from "lucide-react"; +import { ZapIcon } from "~/icons"; import { buttonVariants } from "../ui/button"; import { Menu, diff --git a/apps/web/src/components/clerk/ClerkUserProfilePage.tsx b/apps/web/src/components/clerk/ClerkUserProfilePage.tsx index 00f20e53fbe1..dca1bed557f9 100644 --- a/apps/web/src/components/clerk/ClerkUserProfilePage.tsx +++ b/apps/web/src/components/clerk/ClerkUserProfilePage.tsx @@ -1,4 +1,4 @@ -import { RefreshCwIcon } from "lucide-react"; +import { RefreshCwIcon } from "~/icons"; import type { ReactNode } from "react"; import { cn } from "../../lib/utils"; diff --git a/apps/web/src/components/clerk/MobileClientsUserProfilePage.tsx b/apps/web/src/components/clerk/MobileClientsUserProfilePage.tsx index 22449c336742..6905c0c2be7d 100644 --- a/apps/web/src/components/clerk/MobileClientsUserProfilePage.tsx +++ b/apps/web/src/components/clerk/MobileClientsUserProfilePage.tsx @@ -1,5 +1,5 @@ import type { RelayClientDeviceRecord } from "@t3tools/contracts/relay"; -import { SmartphoneIcon } from "lucide-react"; +import { SmartphoneIcon } from "~/icons"; import { useManagedRelayDevices } from "../../cloud/managedRelayState"; import { Badge } from "../ui/badge"; diff --git a/apps/web/src/components/clerk/T3ConnectSidebarSignIn.tsx b/apps/web/src/components/clerk/T3ConnectSidebarSignIn.tsx index 9dfd8dce13b1..7379c39fd081 100644 --- a/apps/web/src/components/clerk/T3ConnectSidebarSignIn.tsx +++ b/apps/web/src/components/clerk/T3ConnectSidebarSignIn.tsx @@ -1,5 +1,5 @@ import { UserButton, useAuth } from "@clerk/react"; -import { LogInIcon, ServerIcon, SmartphoneIcon } from "lucide-react"; +import { LogInIcon, ServerIcon, SmartphoneIcon } from "~/icons"; import { hasCloudPublicConfig } from "../../cloud/publicConfig"; import { SidebarMenu, SidebarMenuButton, SidebarMenuItem } from "../ui/sidebar"; diff --git a/apps/web/src/components/clerk/T3ConnectUserProfilePage.tsx b/apps/web/src/components/clerk/T3ConnectUserProfilePage.tsx index 15ed569052be..74b75678b937 100644 --- a/apps/web/src/components/clerk/T3ConnectUserProfilePage.tsx +++ b/apps/web/src/components/clerk/T3ConnectUserProfilePage.tsx @@ -5,7 +5,7 @@ import { } from "@t3tools/client-runtime/state/runtime"; import type { EnvironmentId } from "@t3tools/contracts"; import type { RelayClientEnvironmentRecord } from "@t3tools/contracts/relay"; -import { ServerIcon } from "lucide-react"; +import { ServerIcon } from "~/icons"; import { useRef, useState } from "react"; import { diff --git a/apps/web/src/components/cloud/ConnectOnboardingDialog.tsx b/apps/web/src/components/cloud/ConnectOnboardingDialog.tsx index 6248fb00bcfe..41333e331edb 100644 --- a/apps/web/src/components/cloud/ConnectOnboardingDialog.tsx +++ b/apps/web/src/components/cloud/ConnectOnboardingDialog.tsx @@ -1,6 +1,6 @@ import { useAuth } from "@clerk/react"; import { AuthAdministrativeScopes, AuthRelayWriteScope } from "@t3tools/contracts"; -import { CheckIcon } from "lucide-react"; +import { CheckIcon } from "~/icons"; import { useEffect, useRef, useState } from "react"; import { diff --git a/apps/web/src/components/cloud/RelayClientInstallDialog.tsx b/apps/web/src/components/cloud/RelayClientInstallDialog.tsx index 78282f659151..3c90d5bb5519 100644 --- a/apps/web/src/components/cloud/RelayClientInstallDialog.tsx +++ b/apps/web/src/components/cloud/RelayClientInstallDialog.tsx @@ -1,4 +1,4 @@ -import { DownloadIcon } from "lucide-react"; +import { DownloadIcon } from "~/icons"; import { useSyncExternalStore } from "react"; import type { RelayClientInstallProgressStage } from "@t3tools/contracts"; diff --git a/apps/web/src/components/desktopUpdate.toast.tsx b/apps/web/src/components/desktopUpdate.toast.tsx index 0c4991c17250..b0034879dbf6 100644 --- a/apps/web/src/components/desktopUpdate.toast.tsx +++ b/apps/web/src/components/desktopUpdate.toast.tsx @@ -1,5 +1,5 @@ import type { DesktopBridge, DesktopUpdateState } from "@t3tools/contracts"; -import { ArrowRightIcon } from "lucide-react"; +import { ArrowRightIcon } from "~/icons"; import { getDesktopUpdateDownloadedVersion, diff --git a/apps/web/src/components/diffs/DiffCommentAnnotation.tsx b/apps/web/src/components/diffs/DiffCommentAnnotation.tsx index bce9f7e55f58..cdf9bca221d4 100644 --- a/apps/web/src/components/diffs/DiffCommentAnnotation.tsx +++ b/apps/web/src/components/diffs/DiffCommentAnnotation.tsx @@ -1,4 +1,4 @@ -import { MessageCircle, Trash2 } from "lucide-react"; +import { MessageCircle, Trash2 } from "~/icons"; import { useLayoutEffect, useRef, useState, type ReactNode } from "react"; import { Button } from "~/components/ui/button"; diff --git a/apps/web/src/components/diffs/DiffFileTree.tsx b/apps/web/src/components/diffs/DiffFileTree.tsx index 0d200853bcb4..d1ee02a26917 100644 --- a/apps/web/src/components/diffs/DiffFileTree.tsx +++ b/apps/web/src/components/diffs/DiffFileTree.tsx @@ -1,6 +1,6 @@ import type { GitStatusEntry } from "@pierre/trees"; import { FileTree, useFileTree, useFileTreeSelector } from "@pierre/trees/react"; -import { ChevronsDownUpIcon, ChevronsUpDownIcon } from "lucide-react"; +import { ChevronsDownUpIcon, ChevronsUpDownIcon } from "~/icons"; import { useEffect, useMemo, useRef, type ReactNode } from "react"; import { useTheme } from "~/hooks/useTheme"; diff --git a/apps/web/src/components/files/FileBreadcrumbs.tsx b/apps/web/src/components/files/FileBreadcrumbs.tsx index 7c7bfe8e9ff9..4da0fd719075 100644 --- a/apps/web/src/components/files/FileBreadcrumbs.tsx +++ b/apps/web/src/components/files/FileBreadcrumbs.tsx @@ -1,5 +1,5 @@ import type { EnvironmentId } from "@t3tools/contracts"; -import { ArrowLeftIcon, ChevronRightIcon, LoaderCircleIcon, RotateCwIcon } from "lucide-react"; +import { ArrowLeftIcon, ChevronRightIcon, LoaderCircleIcon, RotateCwIcon } from "~/icons"; import { useEffect, useMemo, useState } from "react"; import { PierreEntryIcon } from "~/components/chat/PierreEntryIcon"; diff --git a/apps/web/src/components/files/FileBrowserPanel.tsx b/apps/web/src/components/files/FileBrowserPanel.tsx index dc3cfcef0137..1182979d3e60 100644 --- a/apps/web/src/components/files/FileBrowserPanel.tsx +++ b/apps/web/src/components/files/FileBrowserPanel.tsx @@ -5,7 +5,7 @@ import type { import type { EnvironmentId, ProjectEntry } from "@t3tools/contracts"; import { FileTree, useFileTree, useFileTreeSearch, useFileTreeSelector } from "@pierre/trees/react"; import { serializeComposerFileLink } from "@t3tools/shared/composerTrigger"; -import { ChevronsDownUpIcon, ChevronsUpDownIcon, RotateCw } from "lucide-react"; +import { ChevronsDownUpIcon, ChevronsUpDownIcon, RotateCw } from "~/icons"; import { useEffect, useMemo, useRef } from "react"; import { Button } from "~/components/ui/button"; diff --git a/apps/web/src/components/files/FilePreviewPanel.tsx b/apps/web/src/components/files/FilePreviewPanel.tsx index 33d4d9a4b6cf..9539731aebae 100644 --- a/apps/web/src/components/files/FilePreviewPanel.tsx +++ b/apps/web/src/components/files/FilePreviewPanel.tsx @@ -18,7 +18,7 @@ import { squashAtomCommandFailure, } from "@t3tools/client-runtime/state/runtime"; import { mediaFileReference } from "@t3tools/client-runtime/media-reference"; -import { Code2, Eye, FolderTree, Globe2, LoaderCircle } from "lucide-react"; +import { Code2, Eye, FolderTree, Globe2, LoaderCircle } from "~/icons"; import * as Schema from "effect/Schema"; import { useCallback, useEffect, useMemo, useRef, useState } from "react"; diff --git a/apps/web/src/components/media/MediaVideoPlayer.tsx b/apps/web/src/components/media/MediaVideoPlayer.tsx index f436beeb3855..a37d43d33bfd 100644 --- a/apps/web/src/components/media/MediaVideoPlayer.tsx +++ b/apps/web/src/components/media/MediaVideoPlayer.tsx @@ -1,4 +1,4 @@ -import { RotateCwIcon, TriangleAlertIcon } from "lucide-react"; +import { RotateCwIcon, TriangleAlertIcon } from "~/icons"; import { useCallback, useEffect, useRef, useState, type CSSProperties } from "react"; import { cn } from "../../lib/utils"; diff --git a/apps/web/src/components/media/OpenMediaLink.tsx b/apps/web/src/components/media/OpenMediaLink.tsx index dd3162ddc8b8..9e816b08abb3 100644 --- a/apps/web/src/components/media/OpenMediaLink.tsx +++ b/apps/web/src/components/media/OpenMediaLink.tsx @@ -1,4 +1,4 @@ -import { DownloadIcon, ExternalLinkIcon } from "lucide-react"; +import { DownloadIcon, ExternalLinkIcon } from "~/icons"; import { resolveExternalWebLinkHost } from "../chat/externalLinkContextMenu"; import { Button } from "../ui/button"; diff --git a/apps/web/src/components/preview/AgentBrowserCursor.tsx b/apps/web/src/components/preview/AgentBrowserCursor.tsx index bc89daee4595..93f5011a0fb3 100644 --- a/apps/web/src/components/preview/AgentBrowserCursor.tsx +++ b/apps/web/src/components/preview/AgentBrowserCursor.tsx @@ -1,7 +1,7 @@ "use client"; import type { DesktopPreviewPointerEvent } from "@t3tools/contracts"; -import { MousePointer2 } from "lucide-react"; +import { MousePointer2 } from "~/icons"; import { useEffect, useState } from "react"; import { useBrowserPointerStore } from "~/browser/browserPointerStore"; diff --git a/apps/web/src/components/preview/PreviewChromeRow.tsx b/apps/web/src/components/preview/PreviewChromeRow.tsx index 8dbf9f0904f0..31d945a403d7 100644 --- a/apps/web/src/components/preview/PreviewChromeRow.tsx +++ b/apps/web/src/components/preview/PreviewChromeRow.tsx @@ -6,7 +6,7 @@ import { MousePointerClick, PictureInPicture2, RotateCw, -} from "lucide-react"; +} from "~/icons"; import { type FormEvent, type KeyboardEvent, diff --git a/apps/web/src/components/preview/PreviewEmptyState.tsx b/apps/web/src/components/preview/PreviewEmptyState.tsx index 163849154000..e3506947f988 100644 --- a/apps/web/src/components/preview/PreviewEmptyState.tsx +++ b/apps/web/src/components/preview/PreviewEmptyState.tsx @@ -1,5 +1,5 @@ import type { EnvironmentId, ScopedThreadRef } from "@t3tools/contracts"; -import { Globe, History, RadioTower } from "lucide-react"; +import { Globe, History, RadioTower } from "~/icons"; import type { BrowserHistoryEntry } from "~/browserHistoryStore"; import { Empty, EmptyDescription, EmptyMedia, EmptyTitle } from "~/components/ui/empty"; diff --git a/apps/web/src/components/preview/PreviewMoreMenu.tsx b/apps/web/src/components/preview/PreviewMoreMenu.tsx index 7080fb5238f4..c525bf2aa26d 100644 --- a/apps/web/src/components/preview/PreviewMoreMenu.tsx +++ b/apps/web/src/components/preview/PreviewMoreMenu.tsx @@ -1,7 +1,7 @@ "use client"; import type { DesktopPreviewColorScheme, EnvironmentId } from "@t3tools/contracts"; -import { Minus, MoreVertical, Plus as PlusIcon, RotateCcw } from "lucide-react"; +import { Minus, MoreVertical, Plus as PlusIcon, RotateCcw } from "~/icons"; import { Button } from "~/components/ui/button"; import { diff --git a/apps/web/src/components/preview/PreviewRecentUrlCard.tsx b/apps/web/src/components/preview/PreviewRecentUrlCard.tsx index 39af63a90616..c6c87dfa672d 100644 --- a/apps/web/src/components/preview/PreviewRecentUrlCard.tsx +++ b/apps/web/src/components/preview/PreviewRecentUrlCard.tsx @@ -1,5 +1,5 @@ import type { ScopedThreadRef } from "@t3tools/contracts"; -import { X } from "lucide-react"; +import { X } from "~/icons"; import { isValidHistoryTimestamp, type BrowserHistoryEntry } from "~/browserHistoryStore"; import { useNowMinute } from "~/hooks/useNowMinute"; diff --git a/apps/web/src/components/preview/ThreadPreviewMiniPlayer.tsx b/apps/web/src/components/preview/ThreadPreviewMiniPlayer.tsx index dc2d9f5a96ea..f280b4418aa1 100644 --- a/apps/web/src/components/preview/ThreadPreviewMiniPlayer.tsx +++ b/apps/web/src/components/preview/ThreadPreviewMiniPlayer.tsx @@ -1,7 +1,7 @@ "use client"; import type { ScopedThreadRef } from "@t3tools/contracts"; -import { PanelRightIcon, PictureInPicture2, XIcon } from "lucide-react"; +import { PanelRightIcon, PictureInPicture2, XIcon } from "~/icons"; import { type PointerEvent as ReactPointerEvent, useLayoutEffect, useRef, useState } from "react"; import { BrowserSurfaceSlot } from "~/browser/BrowserSurfaceSlot"; diff --git a/apps/web/src/components/projectScriptEditor.tsx b/apps/web/src/components/projectScriptEditor.tsx index 4b728c2e07eb..b54e3b018317 100644 --- a/apps/web/src/components/projectScriptEditor.tsx +++ b/apps/web/src/components/projectScriptEditor.tsx @@ -15,7 +15,7 @@ import { ListChecksIcon, PlayIcon, WrenchIcon, -} from "lucide-react"; +} from "~/icons"; import React, { type FormEvent, type KeyboardEvent, useEffect, useState } from "react"; import { diff --git a/apps/web/src/components/pullRequest/PullRequestActivityUnavailableState.tsx b/apps/web/src/components/pullRequest/PullRequestActivityUnavailableState.tsx index d87dfa45b0ff..34a71d3a8ec4 100644 --- a/apps/web/src/components/pullRequest/PullRequestActivityUnavailableState.tsx +++ b/apps/web/src/components/pullRequest/PullRequestActivityUnavailableState.tsx @@ -1,4 +1,4 @@ -import { RefreshCwIcon } from "lucide-react"; +import { RefreshCwIcon } from "~/icons"; import { cn } from "~/lib/utils"; diff --git a/apps/web/src/components/pullRequest/PullRequestCandidatePicker.tsx b/apps/web/src/components/pullRequest/PullRequestCandidatePicker.tsx index c8dd196f299d..5f84cd5d0180 100644 --- a/apps/web/src/components/pullRequest/PullRequestCandidatePicker.tsx +++ b/apps/web/src/components/pullRequest/PullRequestCandidatePicker.tsx @@ -6,7 +6,7 @@ * The same combobox as the project and branch pickers, and dressed the same, rather than a menu: * a menu's typeahead claims every keypress to jump between rows, which a search box cannot share. */ -import { SearchIcon } from "lucide-react"; +import { SearchIcon } from "~/icons"; import type { ReactNode } from "react"; import { Button } from "../ui/button"; diff --git a/apps/web/src/components/pullRequest/PullRequestCodeTab.tsx b/apps/web/src/components/pullRequest/PullRequestCodeTab.tsx index aa2d278ce249..eb2fb57f2f74 100644 --- a/apps/web/src/components/pullRequest/PullRequestCodeTab.tsx +++ b/apps/web/src/components/pullRequest/PullRequestCodeTab.tsx @@ -23,7 +23,7 @@ import { TextWrapIcon, TriangleAlertIcon, XIcon, -} from "lucide-react"; +} from "~/icons"; import { useAtomRefresh } from "@effect/atom-react"; import * as Schema from "effect/Schema"; import { useCallback, useEffect, useMemo, useRef, useState, type ReactNode } from "react"; diff --git a/apps/web/src/components/pullRequest/PullRequestDetailPanel.tsx b/apps/web/src/components/pullRequest/PullRequestDetailPanel.tsx index 76e50b60003b..3e0423f2a332 100644 --- a/apps/web/src/components/pullRequest/PullRequestDetailPanel.tsx +++ b/apps/web/src/components/pullRequest/PullRequestDetailPanel.tsx @@ -39,7 +39,7 @@ import { RefreshCwIcon, RotateCcwIcon, TriangleAlertIcon, -} from "lucide-react"; +} from "~/icons"; import { lazy, Suspense, diff --git a/apps/web/src/components/pullRequest/PullRequestGhosts.tsx b/apps/web/src/components/pullRequest/PullRequestGhosts.tsx index f8c922356548..67fac81d06c6 100644 --- a/apps/web/src/components/pullRequest/PullRequestGhosts.tsx +++ b/apps/web/src/components/pullRequest/PullRequestGhosts.tsx @@ -8,7 +8,7 @@ * number of bars costs one opacity animation. */ import type { PullRequestListEntry } from "@t3tools/contracts"; -import { ArrowLeftIcon } from "lucide-react"; +import { ArrowLeftIcon } from "~/icons"; import { cn } from "~/lib/utils"; import { formatRelativeTimeLabel } from "~/timestampFormat"; diff --git a/apps/web/src/components/pullRequest/PullRequestLabelPicker.tsx b/apps/web/src/components/pullRequest/PullRequestLabelPicker.tsx index f1e5fc6a1da4..42a1a0e74128 100644 --- a/apps/web/src/components/pullRequest/PullRequestLabelPicker.tsx +++ b/apps/web/src/components/pullRequest/PullRequestLabelPicker.tsx @@ -6,7 +6,7 @@ * every pull request they merely open. */ import type { EnvironmentId, PullRequestLabelCandidate, PullRequestRef } from "@t3tools/contracts"; -import { CheckIcon, TagIcon } from "lucide-react"; +import { CheckIcon, TagIcon } from "~/icons"; import { useMemo, useState } from "react"; import { pullRequestEnvironment } from "~/state/pullRequests"; diff --git a/apps/web/src/components/pullRequest/PullRequestListEmptyState.tsx b/apps/web/src/components/pullRequest/PullRequestListEmptyState.tsx index 4dd92dbf2243..59271da3a1d9 100644 --- a/apps/web/src/components/pullRequest/PullRequestListEmptyState.tsx +++ b/apps/web/src/components/pullRequest/PullRequestListEmptyState.tsx @@ -11,7 +11,7 @@ * with no project to read from — leave the button out, since pressing it could only repeat what * is already happening or ask nobody. */ -import { PlusIcon, RefreshCwIcon, SearchIcon } from "lucide-react"; +import { PlusIcon, RefreshCwIcon, SearchIcon } from "~/icons"; import { openCommandPalette } from "../../commandPaletteBus"; import { Button } from "../ui/button"; diff --git a/apps/web/src/components/pullRequest/PullRequestListFilters.test.tsx b/apps/web/src/components/pullRequest/PullRequestListFilters.test.tsx index 7ec2629c77b3..f1c3f0a2d8f8 100644 --- a/apps/web/src/components/pullRequest/PullRequestListFilters.test.tsx +++ b/apps/web/src/components/pullRequest/PullRequestListFilters.test.tsx @@ -1,5 +1,5 @@ import type { EnvironmentId, ProjectId } from "@t3tools/contracts"; -import { CircleIcon } from "lucide-react"; +import { CircleIcon } from "~/icons"; import { Children, isValidElement, type ReactElement, type ReactNode } from "react"; import { describe, expect, it, vi } from "vite-plus/test"; diff --git a/apps/web/src/components/pullRequest/PullRequestListFilters.tsx b/apps/web/src/components/pullRequest/PullRequestListFilters.tsx index f77e2b845082..b923145ad8a0 100644 --- a/apps/web/src/components/pullRequest/PullRequestListFilters.tsx +++ b/apps/web/src/components/pullRequest/PullRequestListFilters.tsx @@ -21,7 +21,7 @@ import { SearchIcon, TagIcon, UserRoundIcon, -} from "lucide-react"; +} from "~/icons"; import { type ElementType, useState } from "react"; import { getSourceControlPresentationForKind } from "~/sourceControlPresentation"; diff --git a/apps/web/src/components/pullRequest/PullRequestMarkdown.tsx b/apps/web/src/components/pullRequest/PullRequestMarkdown.tsx index 5e9db1347ce7..effaa29d0f1f 100644 --- a/apps/web/src/components/pullRequest/PullRequestMarkdown.tsx +++ b/apps/web/src/components/pullRequest/PullRequestMarkdown.tsx @@ -1,4 +1,4 @@ -import { ExternalLinkIcon, PaperclipIcon, PlayIcon } from "lucide-react"; +import { ExternalLinkIcon, PaperclipIcon, PlayIcon } from "~/icons"; import type { EnvironmentId, ScopedThreadRef } from "@t3tools/contracts"; import { createContext, useContext, useMemo } from "react"; import type { Options as ReactMarkdownOptions } from "react-markdown"; diff --git a/apps/web/src/components/pullRequest/PullRequestReactions.tsx b/apps/web/src/components/pullRequest/PullRequestReactions.tsx index 2ef90b09a55c..8ef1992c3247 100644 --- a/apps/web/src/components/pullRequest/PullRequestReactions.tsx +++ b/apps/web/src/components/pullRequest/PullRequestReactions.tsx @@ -4,7 +4,7 @@ import type { PullRequestReactionContent, PullRequestRef, } from "@t3tools/contracts"; -import { SmilePlusIcon } from "lucide-react"; +import { SmilePlusIcon } from "~/icons"; import { useState } from "react"; import { cn } from "~/lib/utils"; diff --git a/apps/web/src/components/pullRequest/PullRequestReviewAnnotation.tsx b/apps/web/src/components/pullRequest/PullRequestReviewAnnotation.tsx index 90a1926d1fad..1fe0db5cc133 100644 --- a/apps/web/src/components/pullRequest/PullRequestReviewAnnotation.tsx +++ b/apps/web/src/components/pullRequest/PullRequestReviewAnnotation.tsx @@ -16,7 +16,7 @@ import { MessageSquareIcon, PencilIcon, Trash2Icon, -} from "lucide-react"; +} from "~/icons"; import { useRef, useState } from "react"; import { formatRelativeTimeLabel } from "~/timestampFormat"; diff --git a/apps/web/src/components/pullRequest/PullRequestReviewBar.tsx b/apps/web/src/components/pullRequest/PullRequestReviewBar.tsx index f32352734685..3d55416e1fde 100644 --- a/apps/web/src/components/pullRequest/PullRequestReviewBar.tsx +++ b/apps/web/src/components/pullRequest/PullRequestReviewBar.tsx @@ -5,7 +5,7 @@ * only contributes its own padding. */ import type { EnvironmentId, PullRequestRef, PullRequestReviewVerdict } from "@t3tools/contracts"; -import { CheckIcon, MessageSquareIcon, XCircleIcon } from "lucide-react"; +import { CheckIcon, MessageSquareIcon, XCircleIcon } from "~/icons"; import { useState, type ReactNode } from "react"; import { pullRequestEnvironment } from "~/state/pullRequests"; diff --git a/apps/web/src/components/pullRequest/PullRequestReviewerPicker.tsx b/apps/web/src/components/pullRequest/PullRequestReviewerPicker.tsx index a4da0d99514d..e9314b90720e 100644 --- a/apps/web/src/components/pullRequest/PullRequestReviewerPicker.tsx +++ b/apps/web/src/components/pullRequest/PullRequestReviewerPicker.tsx @@ -10,7 +10,7 @@ import type { PullRequestRef, PullRequestReviewerCandidate, } from "@t3tools/contracts"; -import { CheckIcon, UserPlusIcon } from "lucide-react"; +import { CheckIcon, UserPlusIcon } from "~/icons"; import { useMemo, useState } from "react"; import { pullRequestEnvironment } from "~/state/pullRequests"; diff --git a/apps/web/src/components/pullRequest/PullRequestRow.tsx b/apps/web/src/components/pullRequest/PullRequestRow.tsx index ae7aee0168f4..3739b481a1b0 100644 --- a/apps/web/src/components/pullRequest/PullRequestRow.tsx +++ b/apps/web/src/components/pullRequest/PullRequestRow.tsx @@ -1,4 +1,4 @@ -import { SearchIcon } from "lucide-react"; +import { SearchIcon } from "~/icons"; import { memo, type RefCallback } from "react"; import { cn } from "~/lib/utils"; diff --git a/apps/web/src/components/pullRequest/PullRequestSummaryTab.tsx b/apps/web/src/components/pullRequest/PullRequestSummaryTab.tsx index b06630f3bd04..ff6f83de9973 100644 --- a/apps/web/src/components/pullRequest/PullRequestSummaryTab.tsx +++ b/apps/web/src/components/pullRequest/PullRequestSummaryTab.tsx @@ -18,7 +18,7 @@ import { SendIcon, TagIcon, UsersIcon, -} from "lucide-react"; +} from "~/icons"; import { useRef, useState, type ReactNode } from "react"; import { useAtomCommand } from "~/state/use-atom-command"; diff --git a/apps/web/src/components/pullRequest/PullRequestTimelineTab.tsx b/apps/web/src/components/pullRequest/PullRequestTimelineTab.tsx index 946f3cdbc54f..592196d278d3 100644 --- a/apps/web/src/components/pullRequest/PullRequestTimelineTab.tsx +++ b/apps/web/src/components/pullRequest/PullRequestTimelineTab.tsx @@ -16,7 +16,7 @@ import { GitPullRequestIcon, MessageSquareIcon, PencilIcon, -} from "lucide-react"; +} from "~/icons"; import { useState, type ReactNode } from "react"; import { cn } from "~/lib/utils"; diff --git a/apps/web/src/components/pullRequest/PullRequestsUnavailableState.tsx b/apps/web/src/components/pullRequest/PullRequestsUnavailableState.tsx index 70f5c845d2ca..3c0daa738251 100644 --- a/apps/web/src/components/pullRequest/PullRequestsUnavailableState.tsx +++ b/apps/web/src/components/pullRequest/PullRequestsUnavailableState.tsx @@ -1,4 +1,4 @@ -import { ExternalLinkIcon, GitPullRequestIcon, RefreshCwIcon } from "lucide-react"; +import { ExternalLinkIcon, GitPullRequestIcon, RefreshCwIcon } from "~/icons"; import { Button } from "../ui/button"; import { diff --git a/apps/web/src/components/pullRequest/pullRequestPresentation.tsx b/apps/web/src/components/pullRequest/pullRequestPresentation.tsx index 8611ddc28dde..e168b6be068a 100644 --- a/apps/web/src/components/pullRequest/pullRequestPresentation.tsx +++ b/apps/web/src/components/pullRequest/pullRequestPresentation.tsx @@ -17,7 +17,7 @@ import { GitPullRequestIcon, LoaderIcon, TriangleAlertIcon, -} from "lucide-react"; +} from "~/icons"; import { Children, isValidElement, type ReactNode } from "react"; import { cn } from "~/lib/utils"; diff --git a/apps/web/src/components/search/ProjectContentSearchDialog.tsx b/apps/web/src/components/search/ProjectContentSearchDialog.tsx index 6be17ed33243..dd5a85a1abd4 100644 --- a/apps/web/src/components/search/ProjectContentSearchDialog.tsx +++ b/apps/web/src/components/search/ProjectContentSearchDialog.tsx @@ -1,5 +1,5 @@ import type { ProjectContentMatch } from "@t3tools/contracts"; -import { LoaderCircle } from "lucide-react"; +import { LoaderCircle } from "~/icons"; import { useCallback, useEffect, useMemo, useState, type ReactNode } from "react"; import { useActiveProjectTarget, type ActiveProjectTarget } from "~/hooks/useActiveProjectTarget"; diff --git a/apps/web/src/components/settings/AddProviderInstanceDialog.tsx b/apps/web/src/components/settings/AddProviderInstanceDialog.tsx index 9671755f8bea..e7803325b4a6 100644 --- a/apps/web/src/components/settings/AddProviderInstanceDialog.tsx +++ b/apps/web/src/components/settings/AddProviderInstanceDialog.tsx @@ -1,7 +1,7 @@ "use client"; import { Radio as RadioPrimitive } from "@base-ui/react/radio"; -import { CheckIcon } from "lucide-react"; +import { CheckIcon } from "~/icons"; import { useMemo, useState } from "react"; import { ProviderInstanceId, diff --git a/apps/web/src/components/settings/AddProviderInstanceWizardSteps.tsx b/apps/web/src/components/settings/AddProviderInstanceWizardSteps.tsx index f209474be6b6..c5b8478787e1 100644 --- a/apps/web/src/components/settings/AddProviderInstanceWizardSteps.tsx +++ b/apps/web/src/components/settings/AddProviderInstanceWizardSteps.tsx @@ -1,4 +1,4 @@ -import { CheckIcon } from "lucide-react"; +import { CheckIcon } from "~/icons"; import { cn } from "../../lib/utils"; import { diff --git a/apps/web/src/components/settings/BrowserImportWizard.tsx b/apps/web/src/components/settings/BrowserImportWizard.tsx index a02bb5dab24e..54bb419c9052 100644 --- a/apps/web/src/components/settings/BrowserImportWizard.tsx +++ b/apps/web/src/components/settings/BrowserImportWizard.tsx @@ -1,6 +1,6 @@ import type { BrowserImportSource } from "@t3tools/contracts"; import { BROWSER_IMPORT_FAILURE_COPY } from "@t3tools/contracts"; -import { ArrowDownIcon, ArrowRightIcon, CheckIcon } from "lucide-react"; +import { ArrowDownIcon, ArrowRightIcon, CheckIcon } from "~/icons"; import { useRef, useState } from "react"; import { cn, randomUUID } from "~/lib/utils"; diff --git a/apps/web/src/components/settings/ConnectionsSettings.tsx b/apps/web/src/components/settings/ConnectionsSettings.tsx index 5a6f3ebd70b0..1e5f2fcb4196 100644 --- a/apps/web/src/components/settings/ConnectionsSettings.tsx +++ b/apps/web/src/components/settings/ConnectionsSettings.tsx @@ -1,4 +1,4 @@ -import { ChevronsLeftRightEllipsisIcon, PlusIcon, QrCodeIcon, TerminalIcon } from "lucide-react"; +import { ChevronsLeftRightEllipsisIcon, PlusIcon, QrCodeIcon, TerminalIcon } from "~/icons"; import { useAtomValue } from "@effect/atom-react"; import { type KeyboardEvent, diff --git a/apps/web/src/components/settings/CustomModelEditor.tsx b/apps/web/src/components/settings/CustomModelEditor.tsx index 9fa65e0bf23e..931a661af500 100644 --- a/apps/web/src/components/settings/CustomModelEditor.tsx +++ b/apps/web/src/components/settings/CustomModelEditor.tsx @@ -1,6 +1,6 @@ "use client"; -import { PlusIcon, XIcon } from "lucide-react"; +import { PlusIcon, XIcon } from "~/icons"; import { useMemo, useState } from "react"; import type { ProviderDriverKind, ServerProviderModel } from "@t3tools/contracts"; import type { CustomModelDefinition } from "@t3tools/shared/model"; diff --git a/apps/web/src/components/settings/DiagnosticsSettings.tsx b/apps/web/src/components/settings/DiagnosticsSettings.tsx index 0b23fb2d2072..ebe8bff74b26 100644 --- a/apps/web/src/components/settings/DiagnosticsSettings.tsx +++ b/apps/web/src/components/settings/DiagnosticsSettings.tsx @@ -6,7 +6,7 @@ import { FolderOpenIcon, InfoIcon, RefreshCwIcon, -} from "lucide-react"; +} from "~/icons"; import { useAtomValue } from "@effect/atom-react"; import { isAtomCommandInterrupted, diff --git a/apps/web/src/components/settings/FontFamilyPicker.tsx b/apps/web/src/components/settings/FontFamilyPicker.tsx index 3fa5087e9dae..7fd7b1b878d6 100644 --- a/apps/web/src/components/settings/FontFamilyPicker.tsx +++ b/apps/web/src/components/settings/FontFamilyPicker.tsx @@ -1,5 +1,5 @@ import { LegendList, type LegendListRef } from "@legendapp/list/react"; -import { CheckIcon, ChevronDownIcon, SearchIcon } from "lucide-react"; +import { CheckIcon, ChevronDownIcon, SearchIcon } from "~/icons"; import { useEffect, useMemo, useRef, useState, useSyncExternalStore } from "react"; import { isMonospaceFamily, queryInstalledFontFamilies } from "../../appearanceFonts"; import { diff --git a/apps/web/src/components/settings/IntegrationsSettings.tsx b/apps/web/src/components/settings/IntegrationsSettings.tsx index a3e96107b29c..eb45fe91b2c1 100644 --- a/apps/web/src/components/settings/IntegrationsSettings.tsx +++ b/apps/web/src/components/settings/IntegrationsSettings.tsx @@ -35,7 +35,7 @@ import { type PreviewViewportSetting, } from "@t3tools/contracts"; import { PREVIEW_VIEWPORT_PRESETS } from "@t3tools/shared/previewViewport"; -import { InfoIcon, MoreVertical, Plus as PlusIcon } from "lucide-react"; +import { InfoIcon, MoreVertical, Plus as PlusIcon } from "~/icons"; import { useCallback, useEffect, useRef, useState, type ReactNode } from "react"; import { ScreenRotationIcon } from "~/browser/ScreenRotationIcon"; diff --git a/apps/web/src/components/settings/KeybindingsSettings.tsx b/apps/web/src/components/settings/KeybindingsSettings.tsx index ad99328647af..7d39032eb5b5 100644 --- a/apps/web/src/components/settings/KeybindingsSettings.tsx +++ b/apps/web/src/components/settings/KeybindingsSettings.tsx @@ -8,7 +8,7 @@ import { SearchIcon, TriangleAlertIcon, XIcon, -} from "lucide-react"; +} from "~/icons"; import { type KeyboardEvent, type ReactNode, diff --git a/apps/web/src/components/settings/ProjectIconPickerDialog.tsx b/apps/web/src/components/settings/ProjectIconPickerDialog.tsx index 7fce7a4fbb5b..0531395cdf3d 100644 --- a/apps/web/src/components/settings/ProjectIconPickerDialog.tsx +++ b/apps/web/src/components/settings/ProjectIconPickerDialog.tsx @@ -1,5 +1,5 @@ import type { ProjectIconColor, ProjectIconOverride } from "@t3tools/contracts"; -import { DynamicIcon, type IconName } from "lucide-react/dynamic"; +import { DynamicIcon, type IconName } from "~/icons/dynamic"; import { useEffect, useMemo, useRef, useState } from "react"; import { filterProjectIconNames, diff --git a/apps/web/src/components/settings/ProjectSettingsPanel.tsx b/apps/web/src/components/settings/ProjectSettingsPanel.tsx index 7be0f15cd5c2..cc6d031996a5 100644 --- a/apps/web/src/components/settings/ProjectSettingsPanel.tsx +++ b/apps/web/src/components/settings/ProjectSettingsPanel.tsx @@ -26,7 +26,7 @@ import { createModelSelection } from "@t3tools/shared/model"; import { DEFAULT_RESOLVED_KEYBINDINGS } from "@t3tools/shared/keybindings"; import { useCanGoBack, useNavigate } from "@tanstack/react-router"; import * as Cause from "effect/Cause"; -import { ChevronDownIcon, CopyIcon, PlusIcon, SettingsIcon, Trash2Icon } from "lucide-react"; +import { ChevronDownIcon, CopyIcon, PlusIcon, SettingsIcon, Trash2Icon } from "~/icons"; import { lazy, Suspense, diff --git a/apps/web/src/components/settings/ProviderAccentColorPicker.tsx b/apps/web/src/components/settings/ProviderAccentColorPicker.tsx index 85cb69e0026c..7eb25f03af8a 100644 --- a/apps/web/src/components/settings/ProviderAccentColorPicker.tsx +++ b/apps/web/src/components/settings/ProviderAccentColorPicker.tsx @@ -1,6 +1,6 @@ "use client"; -import { PipetteIcon, XIcon } from "lucide-react"; +import { PipetteIcon, XIcon } from "~/icons"; import { useCallback, useEffect, useMemo, useRef, useState, type PointerEvent } from "react"; import { Button } from "../ui/button"; diff --git a/apps/web/src/components/settings/ProviderInstanceCard.tsx b/apps/web/src/components/settings/ProviderInstanceCard.tsx index 5c96de9d0545..e51ce2c7aea4 100644 --- a/apps/web/src/components/settings/ProviderInstanceCard.tsx +++ b/apps/web/src/components/settings/ProviderInstanceCard.tsx @@ -10,7 +10,7 @@ import { PlusIcon, Trash2Icon, XIcon, -} from "lucide-react"; +} from "~/icons"; import * as Arr from "effect/Array"; import * as Result from "effect/Result"; import { useEffect, useRef, useState, type ReactNode } from "react"; diff --git a/apps/web/src/components/settings/ProviderModelsSection.tsx b/apps/web/src/components/settings/ProviderModelsSection.tsx index 7866578cfa4a..165a7bad1cbb 100644 --- a/apps/web/src/components/settings/ProviderModelsSection.tsx +++ b/apps/web/src/components/settings/ProviderModelsSection.tsx @@ -1,6 +1,6 @@ "use client"; -import { ArrowDownIcon, ArrowUpIcon, PencilIcon, PlusIcon, StarIcon, XIcon } from "lucide-react"; +import { ArrowDownIcon, ArrowUpIcon, PencilIcon, PlusIcon, StarIcon, XIcon } from "~/icons"; import { useEffect, useMemo, useRef, useState } from "react"; import { ProviderDriverKind, diff --git a/apps/web/src/components/settings/ProviderSettingsPanel.tsx b/apps/web/src/components/settings/ProviderSettingsPanel.tsx index fb4620b054c1..6494bb022ce4 100644 --- a/apps/web/src/components/settings/ProviderSettingsPanel.tsx +++ b/apps/web/src/components/settings/ProviderSettingsPanel.tsx @@ -24,7 +24,7 @@ import * as Arr from "effect/Array"; import * as Duration from "effect/Duration"; import * as Equal from "effect/Equal"; import * as Result from "effect/Result"; -import { PlusIcon, RefreshCwIcon } from "lucide-react"; +import { PlusIcon, RefreshCwIcon } from "~/icons"; import { useCallback, useEffect, useMemo, useRef, useState, type ReactNode } from "react"; import { isDesktopLocalConnectionTarget } from "../../connection/desktopLocal"; diff --git a/apps/web/src/components/settings/ResourceTelemetryDiagnostics.tsx b/apps/web/src/components/settings/ResourceTelemetryDiagnostics.tsx index ca934952f8a9..f115d3870026 100644 --- a/apps/web/src/components/settings/ResourceTelemetryDiagnostics.tsx +++ b/apps/web/src/components/settings/ResourceTelemetryDiagnostics.tsx @@ -11,7 +11,7 @@ import { MemoryStickIcon, RefreshCwIcon, RotateCcwIcon, -} from "lucide-react"; +} from "~/icons"; import type { BackgroundBooleanState, ResourceAttributionEntry, diff --git a/apps/web/src/components/settings/SettingsPanels.tsx b/apps/web/src/components/settings/SettingsPanels.tsx index e79464d1757c..a15e061b3e56 100644 --- a/apps/web/src/components/settings/SettingsPanels.tsx +++ b/apps/web/src/components/settings/SettingsPanels.tsx @@ -1,4 +1,4 @@ -import { ArchiveIcon, ArchiveX, ChevronRightIcon, LoaderIcon, SettingsIcon } from "lucide-react"; +import { ArchiveIcon, ArchiveX, ChevronRightIcon, LoaderIcon, SettingsIcon } from "~/icons"; import { Link, useNavigate } from "@tanstack/react-router"; import type { CSSProperties, ReactNode } from "react"; import { useCallback, useEffect, useMemo, useRef, useState } from "react"; diff --git a/apps/web/src/components/settings/SettingsSidebarNav.tsx b/apps/web/src/components/settings/SettingsSidebarNav.tsx index f8f0254cda61..c63969153c8b 100644 --- a/apps/web/src/components/settings/SettingsSidebarNav.tsx +++ b/apps/web/src/components/settings/SettingsSidebarNav.tsx @@ -21,7 +21,7 @@ import { SearchIcon, Settings2Icon, XIcon, -} from "lucide-react"; +} from "~/icons"; import { useLocation, useNavigate, useRouterState } from "@tanstack/react-router"; import { Button } from "../ui/button"; diff --git a/apps/web/src/components/settings/SharedSettingsMismatchAlert.tsx b/apps/web/src/components/settings/SharedSettingsMismatchAlert.tsx index 2a804cf9aeb2..4d76540a6c31 100644 --- a/apps/web/src/components/settings/SharedSettingsMismatchAlert.tsx +++ b/apps/web/src/components/settings/SharedSettingsMismatchAlert.tsx @@ -1,4 +1,4 @@ -import { TriangleAlertIcon } from "lucide-react"; +import { TriangleAlertIcon } from "~/icons"; import { useSharedSettingsSync } from "../../hooks/useSettings"; import { Alert, AlertAction, AlertDescription } from "../ui/alert"; diff --git a/apps/web/src/components/settings/SourceControlSettings.tsx b/apps/web/src/components/settings/SourceControlSettings.tsx index ee1fa66a3db4..f87fe0c54461 100644 --- a/apps/web/src/components/settings/SourceControlSettings.tsx +++ b/apps/web/src/components/settings/SourceControlSettings.tsx @@ -1,4 +1,4 @@ -import { ChevronDownIcon, GitPullRequestIcon, RefreshCwIcon } from "lucide-react"; +import { ChevronDownIcon, GitPullRequestIcon, RefreshCwIcon } from "~/icons"; import * as Duration from "effect/Duration"; import * as Option from "effect/Option"; import { useEffect, useState, type ReactNode } from "react"; diff --git a/apps/web/src/components/settings/ThemeEditorPanel.tsx b/apps/web/src/components/settings/ThemeEditorPanel.tsx index 02d1dad458f1..3d8680d2a5db 100644 --- a/apps/web/src/components/settings/ThemeEditorPanel.tsx +++ b/apps/web/src/components/settings/ThemeEditorPanel.tsx @@ -5,7 +5,7 @@ import { PaintbrushIcon, PlusIcon, XIcon, -} from "lucide-react"; +} from "~/icons"; import { useCallback, useEffect, diff --git a/apps/web/src/components/settings/ThemeImportDialog.tsx b/apps/web/src/components/settings/ThemeImportDialog.tsx index 891294960028..cc6f68cc923f 100644 --- a/apps/web/src/components/settings/ThemeImportDialog.tsx +++ b/apps/web/src/components/settings/ThemeImportDialog.tsx @@ -1,4 +1,4 @@ -import { DownloadIcon, PlusIcon } from "lucide-react"; +import { DownloadIcon, PlusIcon } from "~/icons"; import type { ChangeEvent, DragEvent, UIEvent } from "react"; import { useCallback, useEffect, useMemo, useRef, useState } from "react"; import { cn } from "../../lib/utils"; diff --git a/apps/web/src/components/settings/ThemePreviewCircles.tsx b/apps/web/src/components/settings/ThemePreviewCircles.tsx index 1ac8fa734921..eecf7ea3ddf8 100644 --- a/apps/web/src/components/settings/ThemePreviewCircles.tsx +++ b/apps/web/src/components/settings/ThemePreviewCircles.tsx @@ -1,4 +1,4 @@ -import { MoonIcon, SunIcon } from "lucide-react"; +import { MoonIcon, SunIcon } from "~/icons"; import type { CSSProperties } from "react"; import { STANDARD_THEME_PREVIEW_COLORS as SHARED_STANDARD_THEME_PREVIEW_COLORS, diff --git a/apps/web/src/components/settings/ThemeSearchSection.tsx b/apps/web/src/components/settings/ThemeSearchSection.tsx index b270bf7b8e4d..4b75ab99eae3 100644 --- a/apps/web/src/components/settings/ThemeSearchSection.tsx +++ b/apps/web/src/components/settings/ThemeSearchSection.tsx @@ -1,10 +1,4 @@ -import { - ExternalLinkIcon, - PackagePlusIcon, - PaletteIcon, - RefreshCwIcon, - SearchIcon, -} from "lucide-react"; +import { ExternalLinkIcon, PackagePlusIcon, PaletteIcon, RefreshCwIcon, SearchIcon } from "~/icons"; import { useCallback, useEffect, useRef, useState } from "react"; import { importOpenVsxThemeExtension, diff --git a/apps/web/src/components/settings/ThemeSettings.tsx b/apps/web/src/components/settings/ThemeSettings.tsx index 6403555c4840..e1bd2fff2257 100644 --- a/apps/web/src/components/settings/ThemeSettings.tsx +++ b/apps/web/src/components/settings/ThemeSettings.tsx @@ -8,7 +8,7 @@ import { SunIcon, Trash2Icon, UploadIcon, -} from "lucide-react"; +} from "~/icons"; import { useCallback, useEffect, useState, type ReactElement } from "react"; import { useEnvironmentThemeDefinitions } from "../../hooks/useEnvironmentTheme"; import { readThemeHalvesRaw } from "../../hooks/useTheme"; diff --git a/apps/web/src/components/settings/UsageProviderSettings.tsx b/apps/web/src/components/settings/UsageProviderSettings.tsx index e7af8337d961..94a5032f8496 100644 --- a/apps/web/src/components/settings/UsageProviderSettings.tsx +++ b/apps/web/src/components/settings/UsageProviderSettings.tsx @@ -1,5 +1,5 @@ import type { EnvironmentId, UnifiedSettings } from "@t3tools/contracts"; -import { PlusIcon } from "lucide-react"; +import { PlusIcon } from "~/icons"; import { useState } from "react"; import { useUpdateEnvironmentSettings } from "../../hooks/useSettings"; diff --git a/apps/web/src/components/settings/settingsLayout.tsx b/apps/web/src/components/settings/settingsLayout.tsx index 82fbed96459f..aefcdc44b99a 100644 --- a/apps/web/src/components/settings/settingsLayout.tsx +++ b/apps/web/src/components/settings/settingsLayout.tsx @@ -1,4 +1,4 @@ -import { InfoIcon, Undo2Icon } from "lucide-react"; +import { InfoIcon, Undo2Icon } from "~/icons"; import { useLocation, useNavigate } from "@tanstack/react-router"; import { createContext, diff --git a/apps/web/src/components/sidebar/DesktopUpdateStatusIcon.tsx b/apps/web/src/components/sidebar/DesktopUpdateStatusIcon.tsx index 60fa379ce30e..4b7c3f2e5cba 100644 --- a/apps/web/src/components/sidebar/DesktopUpdateStatusIcon.tsx +++ b/apps/web/src/components/sidebar/DesktopUpdateStatusIcon.tsx @@ -1,4 +1,4 @@ -import { CheckIcon, DownloadIcon, RefreshCwIcon, RotateCwIcon } from "lucide-react"; +import { CheckIcon, DownloadIcon, RefreshCwIcon, RotateCwIcon } from "~/icons"; import type { AnimationEventHandler } from "react"; import { cn } from "../../lib/utils"; diff --git a/apps/web/src/components/sidebar/SidebarChrome.tsx b/apps/web/src/components/sidebar/SidebarChrome.tsx index 4f115a751422..4f2bb54e05ff 100644 --- a/apps/web/src/components/sidebar/SidebarChrome.tsx +++ b/apps/web/src/components/sidebar/SidebarChrome.tsx @@ -1,9 +1,4 @@ -import { - ArrowLeftIcon, - ChartNoAxesColumnIcon, - GitPullRequestIcon, - SettingsIcon, -} from "lucide-react"; +import { ArrowLeftIcon, ChartNoAxesColumnIcon, GitPullRequestIcon, SettingsIcon } from "~/icons"; import type { ReactNode } from "react"; import { memo, useCallback } from "react"; import { Link, useCanGoBack, useLocation, useNavigate } from "@tanstack/react-router"; diff --git a/apps/web/src/components/sidebar/SidebarProviderUpdatePill.tsx b/apps/web/src/components/sidebar/SidebarProviderUpdatePill.tsx index 84dd7f4b5634..21f530e513ba 100644 --- a/apps/web/src/components/sidebar/SidebarProviderUpdatePill.tsx +++ b/apps/web/src/components/sidebar/SidebarProviderUpdatePill.tsx @@ -1,7 +1,7 @@ import { useNavigate } from "@tanstack/react-router"; import { useAtomValue } from "@effect/atom-react"; import type { ServerProvider } from "@t3tools/contracts"; -import { CircleCheckIcon, DownloadIcon, LoaderIcon, TriangleAlertIcon, XIcon } from "lucide-react"; +import { CircleCheckIcon, DownloadIcon, LoaderIcon, TriangleAlertIcon, XIcon } from "~/icons"; import { useCallback, useEffect, useState, type CSSProperties } from "react"; import { primaryServerProvidersAtom } from "../../state/server"; diff --git a/apps/web/src/components/sidebar/SidebarUpdatePill.tsx b/apps/web/src/components/sidebar/SidebarUpdatePill.tsx index a94b7801ecfd..8c05a0356903 100644 --- a/apps/web/src/components/sidebar/SidebarUpdatePill.tsx +++ b/apps/web/src/components/sidebar/SidebarUpdatePill.tsx @@ -1,5 +1,5 @@ import type { DesktopUpdateState } from "@t3tools/contracts"; -import { TriangleAlertIcon } from "lucide-react"; +import { TriangleAlertIcon } from "~/icons"; import { type ComponentProps, useCallback, useEffect, useId, useRef, useState } from "react"; import { flushSync } from "react-dom"; import { isElectron } from "../../env"; diff --git a/apps/web/src/components/sidebar/SidebarUpdateReleaseNotes.tsx b/apps/web/src/components/sidebar/SidebarUpdateReleaseNotes.tsx index 89204d1bd89b..1ce7b0baa036 100644 --- a/apps/web/src/components/sidebar/SidebarUpdateReleaseNotes.tsx +++ b/apps/web/src/components/sidebar/SidebarUpdateReleaseNotes.tsx @@ -1,5 +1,5 @@ import type { DesktopBridge, DesktopUpdateState } from "@t3tools/contracts"; -import { ExternalLinkIcon } from "lucide-react"; +import { ExternalLinkIcon } from "~/icons"; import { getDesktopUpdateReleaseHistoryUrl, diff --git a/apps/web/src/components/ui/autocomplete.tsx b/apps/web/src/components/ui/autocomplete.tsx index b81701e25925..8cea411e8ca6 100644 --- a/apps/web/src/components/ui/autocomplete.tsx +++ b/apps/web/src/components/ui/autocomplete.tsx @@ -1,7 +1,7 @@ "use client"; import { Autocomplete as AutocompletePrimitive } from "@base-ui/react/autocomplete"; -import { ChevronsUpDownIcon, XIcon } from "lucide-react"; +import { ChevronsUpDownIcon, XIcon } from "~/icons"; import { cn } from "~/lib/utils"; import { Input } from "~/components/ui/input"; diff --git a/apps/web/src/components/ui/combobox.tsx b/apps/web/src/components/ui/combobox.tsx index e2253100d2d8..48393c4cb3da 100644 --- a/apps/web/src/components/ui/combobox.tsx +++ b/apps/web/src/components/ui/combobox.tsx @@ -1,7 +1,7 @@ "use client"; import { Combobox as ComboboxPrimitive } from "@base-ui/react/combobox"; -import { ChevronsUpDownIcon, XIcon } from "lucide-react"; +import { ChevronsUpDownIcon, XIcon } from "~/icons"; import * as React from "react"; import { cn } from "~/lib/utils"; diff --git a/apps/web/src/components/ui/command.tsx b/apps/web/src/components/ui/command.tsx index c1952e9c6f36..ec21552c6164 100644 --- a/apps/web/src/components/ui/command.tsx +++ b/apps/web/src/components/ui/command.tsx @@ -1,7 +1,7 @@ "use client"; import { Dialog as CommandDialogPrimitive } from "@base-ui/react/dialog"; -import { SearchIcon } from "lucide-react"; +import { SearchIcon } from "~/icons"; import type * as React from "react"; import { cn } from "~/lib/utils"; import { diff --git a/apps/web/src/components/ui/dialog.tsx b/apps/web/src/components/ui/dialog.tsx index a96f648803aa..73670a4ccc36 100644 --- a/apps/web/src/components/ui/dialog.tsx +++ b/apps/web/src/components/ui/dialog.tsx @@ -1,7 +1,7 @@ "use client"; import { Dialog as DialogPrimitive } from "@base-ui/react/dialog"; -import { XIcon } from "lucide-react"; +import { XIcon } from "~/icons"; import { cn } from "~/lib/utils"; import { Button } from "~/components/ui/button"; import { diff --git a/apps/web/src/components/ui/menu.tsx b/apps/web/src/components/ui/menu.tsx index fbdcbc03480a..d4f8b2abd9ec 100644 --- a/apps/web/src/components/ui/menu.tsx +++ b/apps/web/src/components/ui/menu.tsx @@ -1,7 +1,7 @@ "use client"; import { Menu as MenuPrimitive } from "@base-ui/react/menu"; -import { CheckIcon, ChevronRightIcon } from "lucide-react"; +import { CheckIcon, ChevronRightIcon } from "~/icons"; import type * as React from "react"; import { cn } from "~/lib/utils"; diff --git a/apps/web/src/components/ui/number-field.tsx b/apps/web/src/components/ui/number-field.tsx index 4b348f2ffed4..a7084f19f5ac 100644 --- a/apps/web/src/components/ui/number-field.tsx +++ b/apps/web/src/components/ui/number-field.tsx @@ -1,7 +1,7 @@ "use client"; import { NumberField as NumberFieldPrimitive } from "@base-ui/react/number-field"; -import { MinusIcon, PlusIcon } from "lucide-react"; +import { MinusIcon, PlusIcon } from "~/icons"; import * as React from "react"; import { cn } from "~/lib/utils"; import { Label } from "~/components/ui/label"; diff --git a/apps/web/src/components/ui/panel-tab-close-button.tsx b/apps/web/src/components/ui/panel-tab-close-button.tsx index 0e17a8f23a38..989c22c3cee9 100644 --- a/apps/web/src/components/ui/panel-tab-close-button.tsx +++ b/apps/web/src/components/ui/panel-tab-close-button.tsx @@ -1,4 +1,4 @@ -import { X } from "lucide-react"; +import { X } from "~/icons"; import type { ReactNode } from "react"; import { Tooltip, TooltipPopup, TooltipTrigger } from "~/components/ui/tooltip"; diff --git a/apps/web/src/components/ui/select.tsx b/apps/web/src/components/ui/select.tsx index 22f5b5763f61..427ea4a8907c 100644 --- a/apps/web/src/components/ui/select.tsx +++ b/apps/web/src/components/ui/select.tsx @@ -4,7 +4,7 @@ import { mergeProps } from "@base-ui/react/merge-props"; import { Select as SelectPrimitive } from "@base-ui/react/select"; import { useRender } from "@base-ui/react/use-render"; import { cva, type VariantProps } from "class-variance-authority"; -import { CheckIcon, ChevronDownIcon, ChevronsUpDownIcon, ChevronUpIcon } from "lucide-react"; +import { CheckIcon, ChevronDownIcon, ChevronsUpDownIcon, ChevronUpIcon } from "~/icons"; import type * as React from "react"; import { cn } from "~/lib/utils"; diff --git a/apps/web/src/components/ui/sheet.tsx b/apps/web/src/components/ui/sheet.tsx index f7711da80038..876e632dd05a 100644 --- a/apps/web/src/components/ui/sheet.tsx +++ b/apps/web/src/components/ui/sheet.tsx @@ -1,7 +1,7 @@ "use client"; import { Dialog as SheetPrimitive } from "@base-ui/react/dialog"; -import { XIcon } from "lucide-react"; +import { XIcon } from "~/icons"; import type { CSSProperties } from "react"; import { cn } from "~/lib/utils"; import { Button } from "~/components/ui/button"; diff --git a/apps/web/src/components/ui/sidebar.tsx b/apps/web/src/components/ui/sidebar.tsx index 624798e19f54..87be629e0ba8 100644 --- a/apps/web/src/components/ui/sidebar.tsx +++ b/apps/web/src/components/ui/sidebar.tsx @@ -1,7 +1,7 @@ import { mergeProps } from "@base-ui/react/merge-props"; import { useRender } from "@base-ui/react/use-render"; import { cva, type VariantProps } from "class-variance-authority"; -import { PanelLeftCloseIcon, PanelLeftIcon } from "lucide-react"; +import { PanelLeftCloseIcon, PanelLeftIcon } from "~/icons"; import * as React from "react"; import { cn } from "~/lib/utils"; import { Button } from "~/components/ui/button"; diff --git a/apps/web/src/components/ui/spinner.tsx b/apps/web/src/components/ui/spinner.tsx index 362b78f95463..7f2e341c1179 100644 --- a/apps/web/src/components/ui/spinner.tsx +++ b/apps/web/src/components/ui/spinner.tsx @@ -1,4 +1,4 @@ -import { Loader2Icon } from "lucide-react"; +import { Loader2Icon } from "~/icons"; import { cn } from "~/lib/utils"; function Spinner({ className, ...props }: React.ComponentProps) { diff --git a/apps/web/src/components/ui/toast.tsx b/apps/web/src/components/ui/toast.tsx index 69fd0ebf3664..8207f3c55f57 100644 --- a/apps/web/src/components/ui/toast.tsx +++ b/apps/web/src/components/ui/toast.tsx @@ -23,7 +23,7 @@ import { LoaderCircleIcon, TriangleAlertIcon, XIcon, -} from "lucide-react"; +} from "~/icons"; import { cn } from "~/lib/utils"; import { Button, buttonVariants } from "~/components/ui/button"; diff --git a/apps/web/src/components/usage/UsageLimits.tsx b/apps/web/src/components/usage/UsageLimits.tsx index 77f85953984c..8509afbbd4e4 100644 --- a/apps/web/src/components/usage/UsageLimits.tsx +++ b/apps/web/src/components/usage/UsageLimits.tsx @@ -21,7 +21,7 @@ import { paceOf, providerLimitsLabel, } from "@t3tools/shared/usageLimits"; -import { GaugeIcon, TrendingDownIcon, TrendingUpIcon } from "lucide-react"; +import { GaugeIcon, TrendingDownIcon, TrendingUpIcon } from "~/icons"; import { Fragment, useState } from "react"; import { usePrimarySettings } from "../../hooks/useSettings"; diff --git a/apps/web/src/components/usage/UsagePage.tsx b/apps/web/src/components/usage/UsagePage.tsx index e957002115ab..fb5be6dbd103 100644 --- a/apps/web/src/components/usage/UsagePage.tsx +++ b/apps/web/src/components/usage/UsagePage.tsx @@ -10,7 +10,7 @@ import { CircleDashedIcon, RefreshCwIcon, SlidersHorizontalIcon, -} from "lucide-react"; +} from "~/icons"; import { useMemo, useState } from "react"; import { diff --git a/apps/web/src/components/usage/UsagePriceOverrides.tsx b/apps/web/src/components/usage/UsagePriceOverrides.tsx index 9f3e5697b5ee..22615c9963dc 100644 --- a/apps/web/src/components/usage/UsagePriceOverrides.tsx +++ b/apps/web/src/components/usage/UsagePriceOverrides.tsx @@ -1,6 +1,6 @@ import { useAtomValue } from "@effect/atom-react"; import type { EnvironmentId } from "@t3tools/contracts"; -import { ChevronDownIcon, PlusIcon, RotateCcwIcon, XIcon } from "lucide-react"; +import { ChevronDownIcon, PlusIcon, RotateCcwIcon, XIcon } from "~/icons"; import * as Option from "effect/Option"; import { AsyncResult, Atom } from "effect/unstable/reactivity"; import { useRef, useState } from "react"; diff --git a/apps/web/src/icons/dynamic.ts b/apps/web/src/icons/dynamic.ts new file mode 100644 index 000000000000..ae674dcd695d --- /dev/null +++ b/apps/web/src/icons/dynamic.ts @@ -0,0 +1,3 @@ +/* eslint-disable no-restricted-imports -- this seam owns Lucide's dynamic icon loader. */ +export { DynamicIcon, iconNames } from "lucide-react/dynamic"; +export type { IconName } from "lucide-react/dynamic"; diff --git a/apps/web/src/icons/icon-import-parser.ts b/apps/web/src/icons/icon-import-parser.ts new file mode 100644 index 000000000000..c374fe66398a --- /dev/null +++ b/apps/web/src/icons/icon-import-parser.ts @@ -0,0 +1,55 @@ +import * as ts from "typescript"; + +const ICON_MODULES = new Set(["lucide-react", "~/icons"]); +const TYPE_ONLY_ICON_EXPORTS = new Set(["LucideIcon", "LucideProps"]); + +export function collectRuntimeIconNames(source: string, sourcePath = "fixture.tsx"): string[] { + const sourceFile = ts.createSourceFile( + sourcePath, + source, + ts.ScriptTarget.Latest, + true, + scriptKindForPath(sourcePath), + ); + const names: string[] = []; + + for (const statement of sourceFile.statements) { + if ( + !ts.isImportDeclaration(statement) || + !ts.isStringLiteral(statement.moduleSpecifier) || + !ICON_MODULES.has(statement.moduleSpecifier.text) + ) { + continue; + } + const importClause = statement.importClause; + if (importClause?.isTypeOnly === true || !importClause?.namedBindings) continue; + if (!ts.isNamedImports(importClause.namedBindings)) continue; + + for (const member of importClause.namedBindings.elements) { + if (member.isTypeOnly) continue; + const importedName = (member.propertyName ?? member.name).text; + if (!TYPE_ONLY_ICON_EXPORTS.has(importedName)) names.push(importedName); + } + } + + return names; +} + +function scriptKindForPath(sourcePath: string): ts.ScriptKind { + if (sourcePath.endsWith(".tsx")) return ts.ScriptKind.TSX; + if (sourcePath.endsWith(".jsx")) return ts.ScriptKind.JSX; + if (sourcePath.endsWith(".js")) return ts.ScriptKind.JS; + return ts.ScriptKind.TS; +} + +export function assertKnownIconNames( + names: readonly string[], + knownNames: ReadonlySet, + sourcePath: string, +): void { + for (const name of names) { + if (!knownNames.has(name)) { + throw new Error(`${sourcePath} imports ${name}, which lucide-react does not export.`); + } + } +} diff --git a/apps/web/src/icons/icon-imports.test.ts b/apps/web/src/icons/icon-imports.test.ts new file mode 100644 index 000000000000..56bf7468944e --- /dev/null +++ b/apps/web/src/icons/icon-imports.test.ts @@ -0,0 +1,56 @@ +import { describe, expect, it } from "vite-plus/test"; + +import { assertKnownIconNames, collectRuntimeIconNames } from "./icon-import-parser"; + +describe("collectRuntimeIconNames", () => { + it("collects runtime imports and ignores declaration and inline types", () => { + const source = ` + import type { LucideIcon } from "~/icons"; + import { CheckIcon, type LucideProps, X as CloseIcon } from "~/icons"; + import { LucideIcon as IconType, LucideProps } from "~/icons"; + import { CircleAlertIcon } from "lucide-react"; + `; + + expect(collectRuntimeIconNames(source)).toEqual(["CheckIcon", "X", "CircleAlertIcon"]); + }); + + it("ignores import-shaped text outside import declarations", () => { + const source = ` + // import { CommentIcon } from "~/icons"; + const string = 'import { StringIcon } from "~/icons"'; + const template = \`import { TemplateIcon } from "~/icons"\`; + const regex = /import { RegexIcon } from "lucide-react"/; + const jsx =

import {JsxTextIcon} from "lucide-react"

; + import { CheckIcon } from "~/icons"; + `; + + expect(collectRuntimeIconNames(source)).toEqual(["CheckIcon"]); + }); + + it("keeps imports after JSX attribute expressions", () => { + const source = ` + const button =