modified: src/components/NewProjectModal.tsx

This commit is contained in:
Anderson 2026-01-18 02:10:11 +00:00 committed by GitHub
parent 6ee00e0299
commit 751f6ae7cd
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
20 changed files with 1069 additions and 712 deletions

View file

@ -4,11 +4,10 @@ import { CodeEditor } from '@/components/CodeEditor';
import { AIChat } from '@/components/AIChat'; import { AIChat } from '@/components/AIChat';
import { Toolbar } from '@/components/Toolbar'; import { Toolbar } from '@/components/Toolbar';
import { TemplatesDrawer } from '@/components/TemplatesDrawer'; import { TemplatesDrawer } from '@/components/TemplatesDrawer';
import { WelcomeDialog } from '@/components/WelcomeDialog';
import { FileTree, FileNode } from '@/components/FileTree'; import { FileTree, FileNode } from '@/components/FileTree';
import { FileTabs } from '@/components/FileTabs'; import { FileTabs } from '@/components/FileTabs';
import { PreviewModal } from '@/components/PreviewModal'; import { PreviewModal } from '@/components/PreviewModal';
import { NewProjectModal, ProjectConfig } from '@/components/NewProjectModal'; // Removed named imports for WelcomeDialog and NewProjectModal. Use lazy-loaded versions from src/App.tsx.
import { ConsolePanel } from '@/components/ConsolePanel'; import { ConsolePanel } from '@/components/ConsolePanel';
import { ResizablePanelGroup, ResizablePanel, ResizableHandle } from '@/components/ui/resizable'; import { ResizablePanelGroup, ResizablePanel, ResizableHandle } from '@/components/ui/resizable';
import { useKV } from '@github/spark/hooks'; import { useKV } from '@github/spark/hooks';

BIN
github-spark-0.44.15.tgz Normal file

Binary file not shown.

View file

@ -1,7 +1,13 @@
/** @type {import('next').NextConfig} */ /** @type {import('next').NextConfig} */
const path = require('path');
const nextConfig = { const nextConfig = {
reactStrictMode: true, reactStrictMode: true,
swcMinify: true, swcMinify: true,
webpack: (config) => {
config.resolve.alias['@'] = path.resolve(__dirname, 'src');
return config;
},
} }
module.exports = nextConfig module.exports = nextConfig

1502
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -14,6 +14,7 @@
}, },
"dependencies": { "dependencies": {
"@monaco-editor/react": "^4.6.0", "@monaco-editor/react": "^4.6.0",
"@phosphor-icons/react": "^2.1.10",
"@radix-ui/react-accordion": "^1.2.2", "@radix-ui/react-accordion": "^1.2.2",
"@radix-ui/react-alert-dialog": "^1.1.4", "@radix-ui/react-alert-dialog": "^1.1.4",
"@radix-ui/react-avatar": "^1.1.2", "@radix-ui/react-avatar": "^1.1.2",
@ -32,15 +33,19 @@
"@radix-ui/react-tabs": "^1.1.2", "@radix-ui/react-tabs": "^1.1.2",
"@radix-ui/react-toast": "^1.2.4", "@radix-ui/react-toast": "^1.2.4",
"@radix-ui/react-tooltip": "^1.1.6", "@radix-ui/react-tooltip": "^1.1.6",
"@sentry/browser": "^10.34.0",
"class-variance-authority": "^0.7.1", "class-variance-authority": "^0.7.1",
"clsx": "^2.1.1", "clsx": "^2.1.1",
"framer-motion": "^11.15.0", "framer-motion": "^11.15.0",
"lucide-react": "^0.462.0", "lucide-react": "^0.462.0",
"monaco-editor": "^0.52.2", "monaco-editor": "^0.52.2",
"next": "14.2.15", "next": "14.2.15",
"next-themes": "^0.4.6",
"posthog-js": "^1.328.0",
"react": "^18.3.1", "react": "^18.3.1",
"react-dom": "^18.3.1", "react-dom": "^18.3.1",
"react-error-boundary": "^6.1.0", "react-error-boundary": "^6.1.0",
"react-resizable-panels": "^4.4.1",
"socket.io-client": "^4.8.1", "socket.io-client": "^4.8.1",
"sonner": "^2.0.7", "sonner": "^2.0.7",
"tailwind-merge": "^2.6.0", "tailwind-merge": "^2.6.0",
@ -48,8 +53,8 @@
"zustand": "^5.0.3" "zustand": "^5.0.3"
}, },
"devDependencies": { "devDependencies": {
"@types/node": "^22", "@types/node": "22.19.7",
"@types/react": "^18", "@types/react": "18.3.27",
"@types/react-dom": "^18", "@types/react-dom": "^18",
"autoprefixer": "^10.4.20", "autoprefixer": "^10.4.20",
"eslint": "^8", "eslint": "^8",

View file

@ -21,6 +21,7 @@ import { initSentry, captureError } from './lib/sentry';
import { LoadingSpinner } from './components/ui/loading-spinner'; import { LoadingSpinner } from './components/ui/loading-spinner';
import { PlatformId } from './lib/platforms'; import { PlatformId } from './lib/platforms';
import { ProjectConfig } from './components/NewProjectModal';
// Lazy load heavy/modal components for code splitting and better initial load // Lazy load heavy/modal components for code splitting and better initial load
const TemplatesDrawer = lazy(() => import('./components/TemplatesDrawer').then(m => ({ default: m.TemplatesDrawer }))); const TemplatesDrawer = lazy(() => import('./components/TemplatesDrawer').then(m => ({ default: m.TemplatesDrawer })));
@ -513,7 +514,7 @@ end)`,
) : ( ) : (
<> <>
<div className="flex-1 overflow-hidden"> <div className="flex-1 overflow-hidden">
<ResizablePanelGroup direction="horizontal"> <ResizablePanelGroup orientation="horizontal">
<ResizablePanel defaultSize={15} minSize={10} maxSize={25}> <ResizablePanel defaultSize={15} minSize={10} maxSize={25}>
<FileTree <FileTree
files={files || []} files={files || []}

View file

@ -1,5 +1,5 @@
import Editor from '@monaco-editor/react'; import Editor from '@monaco-editor/react';
import { useKV } from '@github/spark/hooks'; import { usePersistentState } from '@/lib/usePersistentState';
import { useEffect, useMemo } from 'react'; import { useEffect, useMemo } from 'react';
import { LoadingSpinner } from './ui/loading-spinner'; import { LoadingSpinner } from './ui/loading-spinner';
import { toast } from 'sonner'; import { toast } from 'sonner';
@ -19,7 +19,7 @@ export function CodeEditor({ onCodeChange, platform = 'roblox' }: CodeEditorProp
}), []); }), []);
const editorLanguage = languageMap[platform]; const editorLanguage = languageMap[platform];
const [code, setCode] = useKV('aethex-current-code', `-- Welcome to AeThex Studio! const [code, setCode] = usePersistentState('aethex-current-code', `-- Welcome to AeThex Studio!
-- Write your Roblox Lua code here -- Write your Roblox Lua code here
local Players = game:GetService("Players") local Players = game:GetService("Players")

View file

@ -1,13 +1,13 @@
import { useState } from 'react'; import { useState } from 'react';
import { Dialog, DialogContent, DialogHeader, DialogTitle } from '@/components/ui/dialog'; import { Dialog, DialogContent, DialogHeader, DialogTitle } from './ui/dialog';
import { Button } from '@/components/ui/button'; import { Button } from './ui/button';
import { Input } from '@/components/ui/input'; import { Input } from './ui/input';
import { Label } from '@/components/ui/label'; import { Label } from './ui/label';
import { Card } from '@/components/ui/card'; import { Card } from './ui/card';
import { Badge } from '@/components/ui/badge'; import { Badge } from './ui/badge';
import { Checkbox } from '@/components/ui/checkbox'; import { Checkbox } from './ui/checkbox';
import { Switch } from '@/components/ui/switch'; import { Switch } from './ui/switch';
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '@/components/ui/tooltip'; import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from './ui/tooltip';
import { GameController, Globe, DeviceMobile, FileCode, Info, Check } from '@phosphor-icons/react'; import { GameController, Globe, DeviceMobile, FileCode, Info, Check } from '@phosphor-icons/react';
import { toast } from 'sonner'; import { toast } from 'sonner';
@ -205,7 +205,7 @@ export function NewProjectModal({ open, onClose, onCreateProject }: NewProjectMo
<Checkbox <Checkbox
id="platform-roblox" id="platform-roblox"
checked={platforms.roblox} checked={platforms.roblox}
onCheckedChange={(checked) => onCheckedChange={(checked: boolean) =>
setPlatforms((p) => ({ ...p, roblox: checked === true })) setPlatforms((p) => ({ ...p, roblox: checked === true }))
} }
/> />
@ -218,7 +218,7 @@ export function NewProjectModal({ open, onClose, onCreateProject }: NewProjectMo
<Checkbox <Checkbox
id="platform-web" id="platform-web"
checked={platforms.web} checked={platforms.web}
onCheckedChange={(checked) => onCheckedChange={(checked: boolean) =>
setPlatforms((p) => ({ ...p, web: checked === true })) setPlatforms((p) => ({ ...p, web: checked === true }))
} }
/> />
@ -231,7 +231,7 @@ export function NewProjectModal({ open, onClose, onCreateProject }: NewProjectMo
<Checkbox <Checkbox
id="platform-mobile" id="platform-mobile"
checked={platforms.mobile} checked={platforms.mobile}
onCheckedChange={(checked) => onCheckedChange={(checked: boolean) =>
setPlatforms((p) => ({ ...p, mobile: checked === true })) setPlatforms((p) => ({ ...p, mobile: checked === true }))
} }
/> />

View file

@ -1,6 +1,5 @@
import { Button } from '@/components/ui/button'; import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from './ui/tooltip';
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '@/components/ui/tooltip'; import { Avatar, AvatarFallback, AvatarImage } from './ui/avatar';
import { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar';
import { import {
DropdownMenu, DropdownMenu,
DropdownMenuContent, DropdownMenuContent,
@ -11,10 +10,11 @@ import {
import { Copy, FileCode, Download, Info, Play, FolderPlus, User, SignOut, List, ArrowsLeftRight } from '@phosphor-icons/react'; import { Copy, FileCode, Download, Info, Play, FolderPlus, User, SignOut, List, ArrowsLeftRight } from '@phosphor-icons/react';
import { toast } from 'sonner'; import { toast } from 'sonner';
import { useState, useEffect, useCallback, memo } from 'react'; import { useState, useEffect, useCallback, memo } from 'react';
import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle } from '@/components/ui/dialog'; import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle } from './ui/dialog';
import { ThemeSwitcher } from './ThemeSwitcher'; import { ThemeSwitcher } from './ThemeSwitcher';
import { PlatformSelector } from './PlatformSelector'; import { PlatformSelector } from './PlatformSelector';
import { PlatformId } from '@/lib/platforms'; import { PlatformId } from '../lib/platforms';
import { Button } from './ui/button';
interface ToolbarProps { interface ToolbarProps {
code: string; code: string;

View file

@ -8,10 +8,10 @@ import {
} from '@/components/ui/dialog'; } from '@/components/ui/dialog';
import { Button } from '@/components/ui/button'; import { Button } from '@/components/ui/button';
import { Sparkle, Code, FileCode } from '@phosphor-icons/react'; import { Sparkle, Code, FileCode } from '@phosphor-icons/react';
import { useKV } from '@github/spark/hooks'; import { usePersistentState } from '@/lib/usePersistentState';
export function WelcomeDialog() { export function WelcomeDialog() {
const [hasSeenWelcome, setHasSeenWelcome] = useKV('aethex-welcome-seen', 'false'); const [hasSeenWelcome, setHasSeenWelcome] = usePersistentState('aethex-welcome-seen', 'false');
const [open, setOpen] = useState(false); const [open, setOpen] = useState(false);
useEffect(() => { useEffect(() => {

View file

@ -7,9 +7,9 @@ import { cn } from "@/lib/utils"
function ResizablePanelGroup({ function ResizablePanelGroup({
className, className,
...props ...props
}: ComponentProps<typeof ResizablePrimitive.PanelGroup>) { }: ComponentProps<typeof ResizablePrimitive.Group>) {
return ( return (
<ResizablePrimitive.PanelGroup <ResizablePrimitive.Group
data-slot="resizable-panel-group" data-slot="resizable-panel-group"
className={cn( className={cn(
"flex h-full w-full data-[panel-group-direction=vertical]:flex-col", "flex h-full w-full data-[panel-group-direction=vertical]:flex-col",
@ -30,11 +30,11 @@ function ResizableHandle({
withHandle, withHandle,
className, className,
...props ...props
}: ComponentProps<typeof ResizablePrimitive.PanelResizeHandle> & { }: ComponentProps<typeof ResizablePrimitive.Separator> & {
withHandle?: boolean withHandle?: boolean
}) { }) {
return ( return (
<ResizablePrimitive.PanelResizeHandle <ResizablePrimitive.Separator
data-slot="resizable-handle" data-slot="resizable-handle"
className={cn( className={cn(
"bg-border focus-visible:ring-ring relative flex w-px items-center justify-center after:absolute after:inset-y-0 after:left-1/2 after:w-1 after:-translate-x-1/2 focus-visible:ring-1 focus-visible:ring-offset-1 focus-visible:outline-hidden data-[panel-group-direction=vertical]:h-px data-[panel-group-direction=vertical]:w-full data-[panel-group-direction=vertical]:after:left-0 data-[panel-group-direction=vertical]:after:h-1 data-[panel-group-direction=vertical]:after:w-full data-[panel-group-direction=vertical]:after:-translate-y-1/2 data-[panel-group-direction=vertical]:after:translate-x-0 [&[data-panel-group-direction=vertical]>div]:rotate-90", "bg-border focus-visible:ring-ring relative flex w-px items-center justify-center after:absolute after:inset-y-0 after:left-1/2 after:w-1 after:-translate-x-1/2 focus-visible:ring-1 focus-visible:ring-offset-1 focus-visible:outline-hidden data-[panel-group-direction=vertical]:h-px data-[panel-group-direction=vertical]:w-full data-[panel-group-direction=vertical]:after:left-0 data-[panel-group-direction=vertical]:after:h-1 data-[panel-group-direction=vertical]:after:w-full data-[panel-group-direction=vertical]:after:-translate-y-1/2 data-[panel-group-direction=vertical]:after:translate-x-0 [&[data-panel-group-direction=vertical]>div]:rotate-90",
@ -47,7 +47,7 @@ function ResizableHandle({
<GripVerticalIcon className="size-2.5" /> <GripVerticalIcon className="size-2.5" />
</div> </div>
)} )}
</ResizablePrimitive.PanelResizeHandle> </ResizablePrimitive.Separator>
) )
} }

View file

@ -3,51 +3,196 @@ export const chapters = [
{ {
id: 1, id: 1,
title: 'Introduction to Roblox Scripting', title: 'Introduction to Roblox Scripting',
content: `# Chapter 1: Introduction to Roblox Scripting\n\nWelcome to Roblox development!\n\n**Learning Objectives:**\n- Understand what Roblox Studio is\n- Learn why Lua is used\n- Write your first script\n\n**What is Roblox Studio?**\nRoblox Studio is the official IDE for creating Roblox games. It lets you build worlds, write scripts, and publish games.\n\n**Why Lua?**\nLua is a lightweight scripting language used for game logic in Roblox.\n\n**Your First Script:**\nPaste this in a Script object:\n\n\n```lua\nprint('Hello, Roblox!')\n```\n\nTry running your game to see the output!` content: `# Chapter 1: Introduction to Roblox Scripting
Welcome to Roblox development!
**Learning Objectives:**
- Understand what Roblox Studio is
- Learn why Lua is used
- Write your first script
**What is Roblox Studio?**
Roblox Studio is the official IDE for creating Roblox games. It lets you build worlds, write scripts, and publish games.
**Why Lua?**
Lua is a lightweight scripting language used for game logic in Roblox.
**Your First Script:**
Paste this in a Script object:
\`\`\`lua
print('Hello, Roblox!')
\`\`\`
Try running your game to see the output!`
}, },
{ {
id: 2, id: 2,
title: 'Variables and Data Types', title: 'Variables and Data Types',
content: `# Chapter 2: Variables and Data Types\n\n**Learning Objectives:**\n- Use variables to store data\n- Understand numbers, strings, tables\n\n**Variables:**\n```lua\nlocal score = 10\nlocal playerName = "Alex"\n```\n\n**Tables:**\n```lua\nlocal inventory = {"Sword", "Shield"}\nprint(inventory[1]) -- Sword\n```\n` content: `# Chapter 2: Variables and Data Types
**Learning Objectives:**
- Use variables to store data
- Understand numbers, strings, tables
**Variables:**
\`\`\`lua
local score = 10
local playerName = "Alex"
\`\`\`
**Tables:**
\`\`\`lua
local inventory = {"Sword", "Shield"}
print(inventory[1]) -- Sword
\`\`\`
`
}, },
{ {
id: 3, id: 3,
title: 'Functions and Events', title: 'Functions and Events',
content: `# Chapter 3: Functions and Events\n\n**Learning Objectives:**\n- Write reusable functions\n- Respond to game events\n\n**Functions:**\n```lua\nfunction greet(name)\n print("Hello, " .. name)\nend\ngreet("Alex")\n```\n\n**Events:**\n```lua\nlocal Players = game:GetService("Players")\nPlayers.PlayerAdded:Connect(function(player)\n print(player.Name .. " joined!")\nend)\n```\n` content: `# Chapter 3: Functions and Events
**Learning Objectives:**
- Write reusable functions
- Respond to game events
**Functions:**
\`\`\`lua
function greet(name)
print("Hello, " .. name)
end
greet("Alex")
\`\`\`
**Events:**
\`\`\`lua
local Players = game:GetService("Players")
Players.PlayerAdded:Connect(function(player)
print(player.Name .. " joined!")
end)
\`\`\`
`
}, },
{ {
id: 4, id: 4,
title: 'Game Objects and Hierarchy', title: 'Game Objects and Hierarchy',
content: `# Chapter 4: Game Objects and Hierarchy\n\n**Learning Objectives:**\n- Explore Roblox object hierarchy\n- Access and modify game objects\n\n**Example:**\n```lua\nlocal workspace = game.Workspace\nlocal part = workspace.Part\npart.BrickColor = BrickColor.new("Bright red")\n```\n` content: `# Chapter 4: Game Objects and Hierarchy
**Learning Objectives:**
- Explore Roblox object hierarchy
- Access and modify game objects
**Example:**
\`\`\`lua
local workspace = game.Workspace
local part = workspace.Part
part.BrickColor = BrickColor.new("Bright red")
\`\`\`
`
}, },
{ {
id: 5, id: 5,
title: 'Player Interaction', title: 'Player Interaction',
content: `# Chapter 5: Player Interaction\n\n**Learning Objectives:**\n- Detect player actions\n- Respond to input\n\n**Example:**\n```lua\nlocal Players = game:GetService("Players")\nPlayers.PlayerAdded:Connect(function(player)\n player.Chatted:Connect(function(message)\n print(player.Name .. " said: " .. message)\n end)\nend)\n```\n` content: `# Chapter 5: Player Interaction
**Learning Objectives:**
- Detect player actions
- Respond to input
**Example:**
\`\`\`lua
local Players = game:GetService("Players")
Players.PlayerAdded:Connect(function(player)
player.Chatted:Connect(function(message)
print(player.Name .. " said: " .. message)
end)
end)
\`\`\`
`
}, },
{ {
id: 6, id: 6,
title: 'Building Game Logic', title: 'Building Game Logic',
content: `# Chapter 6: Building Game Logic\n\n**Learning Objectives:**\n- Create rules and mechanics\n- Use conditions and loops\n\n**Example:**\n```lua\nlocal score = 0\nwhile score < 10 do\n score = score + 1\n print("Score:", score)\nend\n```\n` content: `# Chapter 6: Building Game Logic
**Learning Objectives:**
- Create rules and mechanics
- Use conditions and loops
**Example:**
\`\`\`lua
local score = 0
while score < 10 do
score = score + 1
print("Score:", score)
end
\`\`\`
`
}, },
{ {
id: 7, id: 7,
title: 'Saving Data', title: 'Saving Data',
content: `# Chapter 7: Saving Data\n\n**Learning Objectives:**\n- Store player progress\n- Use DataStore service\n\n**Example:**\n```lua\nlocal DataStoreService = game:GetService("DataStoreService")\nlocal scoreStore = DataStoreService:GetDataStore("Scores")\n\n-- Save score\nscoreStore:SetAsync("player_123", 100)\n-- Load score\nlocal score = scoreStore:GetAsync("player_123")\nprint(score)\n```\n` content: `# Chapter 7: Saving Data
**Learning Objectives:**
- Store player progress
- Use DataStore service
**Example:**
\`\`\`lua
local DataStoreService = game:GetService("DataStoreService")
local scoreStore = DataStoreService:GetDataStore("Scores")
-- Save score
scoreStore:SetAsync("player_123", 100)
-- Load score
local score = scoreStore:GetAsync("player_123")
print(score)
\`\`\`
`
}, },
{ {
id: 8, id: 8,
title: 'Deploying Your Game', title: 'Deploying Your Game',
content: `# Chapter 8: Deploying Your Game\n\n**Learning Objectives:**\n- Publish your game to Roblox\n- Update and manage releases\n\n**Steps:**\n1. Click "File > Publish to Roblox As..."\n2. Choose a name and description\n3. Set permissions and publish\n` content: `# Chapter 8: Deploying Your Game
**Learning Objectives:**
- Publish your game to Roblox
- Update and manage releases
**Steps:**
1. Click "File > Publish to Roblox As..."
2. Choose a name and description
3. Set permissions and publish
`
}, },
{ {
id: 9, id: 9,
title: 'Debugging and Testing', title: 'Debugging and Testing',
content: `# Chapter 9: Debugging and Testing\n\n**Learning Objectives:**\n- Find and fix bugs\n- Use print statements and breakpoints\n\n**Example:**\n```lua\nprint("Debug: Player joined")\n-- Use breakpoints in Studio to pause and inspect\n```\n` content: `# Chapter 9: Debugging and Testing
**Learning Objectives:**
- Find and fix bugs
- Use print statements and breakpoints
**Example:**
\`\`\`lua
print("Debug: Player joined")
-- Use breakpoints in Studio to pause and inspect
\`\`\`
`
}, },
{ {
id: 10, id: 10,
title: 'Next Steps and Resources', title: 'Next Steps and Resources',
content: `# Chapter 10: Next Steps and Resources\n\n**Continue Learning:**\n- Join the [Roblox Developer Forum](https://devforum.roblox.com/)\n- Explore [Roblox Education](https://education.roblox.com/)\n- Try building your own game!\n` content: `# Chapter 10: Next Steps and Resources
**Continue Learning:**
- Join the [Roblox Developer Forum](https://devforum.roblox.com/)
- Explore [Roblox Education](https://education.roblox.com/)
- Try building your own game!
`
} }
]; ];

View file

@ -0,0 +1,27 @@
import { useState, useEffect } from 'react';
/**
* usePersistentState is a React hook that syncs state with localStorage.
* @param key The key to store the value under in localStorage.
* @param initialValue The initial value to use if nothing is stored.
*/
export function usePersistentState<T>(key: string, initialValue: T): [T, (value: T) => void] {
const [state, setState] = useState<T>(() => {
if (typeof window === 'undefined') return initialValue;
try {
const item = window.localStorage.getItem(key);
return item ? (JSON.parse(item) as T) : initialValue;
} catch {
return initialValue;
}
});
useEffect(() => {
if (typeof window === 'undefined') return;
try {
window.localStorage.setItem(key, JSON.stringify(state));
} catch {}
}, [key, state]);
return [state, setState];
}

View file

@ -0,0 +1,5 @@
declare module 'lucide-react/dist/esm/icons/grip-vertical' {
import { FC, SVGProps } from 'react';
const GripVerticalIcon: FC<SVGProps<SVGSVGElement>>;
export default GripVerticalIcon;
}

1
src/types/phosphor-icons__react.d.ts vendored Normal file
View file

@ -0,0 +1 @@
declare module '@phosphor-icons/react';

1
src/types/sonner.d.ts vendored Normal file
View file

@ -0,0 +1 @@
declare module 'sonner';

3
src/types/window-spark.d.ts vendored Normal file
View file

@ -0,0 +1,3 @@
interface Window {
spark?: any;
}

View file

@ -8,7 +8,7 @@
"noEmit": true, "noEmit": true,
"esModuleInterop": true, "esModuleInterop": true,
"module": "esnext", "module": "esnext",
"moduleResolution": "bundler", "moduleResolution": "node",
"resolveJsonModule": true, "resolveJsonModule": true,
"isolatedModules": true, "isolatedModules": true,
"jsx": "preserve", "jsx": "preserve",

1
types/phosphor-icons__react.d.ts vendored Normal file
View file

@ -0,0 +1 @@
declare module '@phosphor-icons/react';

1
types/sonner.d.ts vendored Normal file
View file

@ -0,0 +1 @@
declare module 'sonner';