diff --git a/debug-screenshot.png b/debug-screenshot.png deleted file mode 100644 index b759061..0000000 Binary files a/debug-screenshot.png and /dev/null differ diff --git a/overtype-debug.png b/overtype-debug.png deleted file mode 100644 index 1198b75..0000000 Binary files a/overtype-debug.png and /dev/null differ diff --git a/package.json b/package.json index 3031d16..1b18fe4 100644 --- a/package.json +++ b/package.json @@ -11,6 +11,7 @@ }, "dependencies": { "@heroui/button": "^2.2.24", + "@heroui/card": "^2.2.23", "@heroui/code": "^2.2.18", "@heroui/dropdown": "^2.3.24", "@heroui/input": "^2.4.25", @@ -20,6 +21,7 @@ "@heroui/snippet": "^2.2.25", "@heroui/switch": "^2.2.22", "@heroui/system": "^2.4.20", + "@heroui/table": "^2.2.24", "@heroui/theme": "^2.4.20", "@heroui/use-theme": "2.1.10", "@react-aria/visually-hidden": "3.8.26", diff --git a/playwright-report/index.html b/playwright-report/index.html deleted file mode 100644 index bf8880f..0000000 --- a/playwright-report/index.html +++ /dev/null @@ -1,76 +0,0 @@ - - - - - - - - - Playwright Test Report - - - - -
- - - \ No newline at end of file diff --git a/playwright.config.ts b/playwright.config.ts index 3bb564a..25658bc 100644 --- a/playwright.config.ts +++ b/playwright.config.ts @@ -1,29 +1,29 @@ -import { defineConfig, devices } from '@playwright/test'; +import { defineConfig, devices } from "@playwright/test"; export default defineConfig({ - testDir: './tests', + testDir: "./tests", timeout: 30 * 1000, expect: { - timeout: 5000 + timeout: 5000, }, fullyParallel: true, forbidOnly: !!process.env.CI, retries: process.env.CI ? 2 : 0, workers: process.env.CI ? 1 : undefined, - reporter: 'html', + reporter: "html", use: { - baseURL: 'http://localhost:5176', - trace: 'on-first-retry', + baseURL: "http://localhost:5176", + trace: "on-first-retry", }, projects: [ { - name: 'chromium', - use: { ...devices['Desktop Chrome'] }, + name: "chromium", + use: { ...devices["Desktop Chrome"] }, }, ], webServer: { - command: 'yarn dev', + command: "yarn dev", port: 5176, reuseExistingServer: !process.env.CI, }, -}); \ No newline at end of file +}); diff --git a/src/components/editor.tsx b/src/components/editor.tsx index e0cda41..ae5f539 100644 --- a/src/components/editor.tsx +++ b/src/components/editor.tsx @@ -1,5 +1,8 @@ import { useEffect, useRef, useState } from "react"; import { Button } from "@heroui/button"; +import { Card, CardBody } from "@heroui/card"; +import { useTheme } from "@heroui/use-theme"; + import { vietnameseInput, InputMethod } from "@/utils/vietnamese-input"; // Extend window object to include OverType @@ -19,51 +22,103 @@ interface EditorProps { onContentChange?: (content: string) => void; } -export default function Editor({ initialContent = "", onContentChange }: EditorProps) { +export default function Editor({ + initialContent = "", + onContentChange, +}: EditorProps) { const editorRef = useRef(null); - const [inputMethod, setInputMethod] = useState('AUTO'); + const [inputMethod, setInputMethod] = useState("AUTO"); const [isVietnameseEnabled, setIsVietnameseEnabled] = useState(true); const [editorInstance, setEditorInstance] = useState(null); const [content, setContent] = useState(initialContent); + const { theme } = useTheme(); + + // Check if user is visiting for the first time + const isFirstVisit = !localStorage.getItem("vinakey2-visited"); + + // Modern and elegant custom theme configuration + const customTheme = { + name: 'vinakey-modern', + colors: { + bgPrimary: theme === 'dark' ? '#0f0f23' : '#fefefe', + bgSecondary: theme === 'dark' ? '#1a1a2e' : '#f8fafc', + text: theme === 'dark' ? '#e2e8f0' : '#1e293b', + h1: theme === 'dark' ? '#f97316' : '#f97316', // Orange primary for both themes + h2: theme === 'dark' ? '#fb923c' : '#ea580c', // Orange variants + h3: theme === 'dark' ? '#fdba74' : '#c2410c', + strong: theme === 'dark' ? '#fb923c' : '#ea580c', + em: theme === 'dark' ? '#f97316' : '#f97316', + link: theme === 'dark' ? '#60a5fa' : '#2563eb', // Modern blue + code: theme === 'dark' ? '#a78bfa' : '#7c3aed', // Modern purple + codeBg: theme === 'dark' ? 'rgba(167, 139, 250, 0.1)' : 'rgba(249, 115, 22, 0.1)', + blockquote: theme === 'dark' ? '#64748b' : '#475569', // Modern gray + hr: theme === 'dark' ? '#374151' : '#d1d5db', + syntaxMarker: theme === 'dark' ? 'rgba(226, 232, 240, 0.4)' : 'rgba(30, 41, 59, 0.4)', + cursor: '#f97316', // Orange cursor for both themes + selection: theme === 'dark' ? 'rgba(249, 115, 22, 0.3)' : 'rgba(249, 115, 22, 0.2)' + } + }; useEffect(() => { const initializeEditor = () => { if (editorRef.current && window.OverType) { try { // Initialize OverType editor using the default export - const OverTypeClass = (window.OverType as any).default || window.OverType; + const OverTypeClass = + (window.OverType as any).default || window.OverType; + const sampleContent = `# Chào mừng đến với VinKey! + +## Hướng dẫn sử dụng + +1. **Chọn kiểu gõ**: OFF, AUTO, TELEX, VNI, hoặc VIQR +2. **Bắt đầu gõ**: Thử gõ "xin chao" hoặc "cam on ban" +3. **Sử dụng markdown**: **in đậm**, *in nghiêng*, [liên kết](https://example.com) +4. **Xóa nội dung này** và bắt đầu viết! + +> **Ví dụ**: Hãy thử gõ "Toi yeu Viet Nam" với TELEX!`; + const instances = new OverTypeClass(editorRef.current, { - value: initialContent, - placeholder: 'Bắt đầu viết markdown với tiếng Việt...', + value: isFirstVisit ? sampleContent : initialContent, + placeholder: "Bắt đầu viết markdown với tiếng Việt...", toolbar: true, - theme: 'solar', - fontSize: '16px', - padding: '20px', + theme: customTheme, + fontSize: "16px", + padding: "24px", autoResize: true, - minHeight: '400px', + minHeight: "600px", onChange: (value: string) => { setContent(value); onContentChange?.(value); - } + }, }); if (instances && instances.length > 0) { const instance = instances[0]; setEditorInstance(instance); + // Mark user as visited and set initial content + if (isFirstVisit) { + localStorage.setItem("vinakey2-visited", "true"); + setContent(sampleContent); + } + // Get the textarea element from OverType and attach Vietnamese input setTimeout(() => { - const textarea = editorRef.current?.querySelector('textarea'); + const textarea = editorRef.current?.querySelector("textarea"); + if (textarea) { vietnameseInput.attach(textarea as HTMLTextAreaElement); - console.log('✓ Vietnamese input attached to textarea'); + console.log("✓ Vietnamese input attached to textarea"); } else { - console.log('❌ No textarea found after OverType initialization'); + console.log( + "❌ No textarea found after OverType initialization", + ); } - }, 500); // Increased timeout + }, 500); return () => { - const textarea = editorRef.current?.querySelector('textarea'); + const textarea = editorRef.current?.querySelector("textarea"); + if (textarea) { vietnameseInput.detach(textarea as HTMLTextAreaElement); } @@ -71,7 +126,7 @@ export default function Editor({ initialContent = "", onContentChange }: EditorP }; } } catch (error) { - console.error('Error initializing OverType:', error); + console.error("Error initializing OverType:", error); } } }; @@ -97,168 +152,115 @@ export default function Editor({ initialContent = "", onContentChange }: EditorP vietnameseInput.setEnabled(isVietnameseEnabled); }, [inputMethod, isVietnameseEnabled]); + // Handle theme changes for OverType editor + useEffect(() => { + if (window.OverType && editorInstance) { + const OverTypeClass = (window.OverType as any).default || window.OverType; + // Use static method to change theme globally + OverTypeClass.setTheme(customTheme); + } + }, [theme, editorInstance]); + const handleMethodChange = (method: InputMethod) => { setInputMethod(method); }; - const handleToggleVietnamese = () => { - setIsVietnameseEnabled(!isVietnameseEnabled); + const handleOffClick = () => { + setIsVietnameseEnabled(false); + setInputMethod("AUTO"); // Reset to AUTO when turning off }; const handleClear = () => { if (editorInstance) { - editorInstance.setValue(''); - setContent(''); + editorInstance.setValue(""); + setContent(""); } }; - const handleSampleText = () => { - const sampleText = `# Chào mừng đến với VinaKey 2 - -## Tính năng chính - -- **Gõ tiếng Việt**: Hỗ trợ các kiểu gõ phổ biến (AUTO, TELEX, VNI, VIQR) -- **Markdown Editor**: Soạn thảo markdown với giao diện WYSIWYG -- **Toolbar**: Các công cụ định dạng tiện lợi -- **Responsive**: Tương thích với mobile và desktop - -## Hướng dẫn sử dụng - -1. Chọn kiểu gõ tiếng Việt từ các nút bên trên -2. Bắt đầu viết nội dung markdown -3. Sử dụng toolbar để định dạng nhanh -4. Bấm nút "Copy" để sao chép nội dung - -### Ví dụ văn bản - -> "Có công mài sắt có ngày nên kim" - -**Danh sách công việc:** -- [x] Tích hợp Vietnamese input -- [x] Tích hợp Overtype editor -- [ ] Thêm tính năng export -- [ ] Thêm themes - -\`\`\`javascript -// Code example -const vietnameseText = "Xin chào thế giới!"; -console.log(vietnameseText); -\`\`\` - ---- - -*Tạo bởi [VinaKey](https://github.com/vinakey/vinakey2) - công cụ gõ tiếng Việt hiện đại.*`; - - if (editorInstance) { - editorInstance.setValue(sampleText); - setContent(sampleText); - } - }; const handleCopy = async () => { if (content) { try { await navigator.clipboard.writeText(content); // Could add a toast notification here - console.log('Content copied to clipboard'); + console.log("Content copied to clipboard"); } catch (err) { - console.error('Failed to copy content:', err); + console.error("Failed to copy content:", err); } } }; return ( -
-
-
-
-

VinaKey 2 Editor

-

- Vietnamese typing with markdown support -

-
- -
- - - +
+ {/* Consolidated card with controls and editor */} +
+ + {/* Control bar at the top */} + + {/* First row: Vietnamese input controls */} +
+ + {(["AUTO", "TELEX", "VNI", "VIQR"] as InputMethod[]).map( + (method) => ( + + ), + )} +
- -
-
- -
- -
-
- Vietnamese Input: - -
- -
- {(['AUTO', 'TELEX', 'VNI', 'VIQR'] as InputMethod[]).map((method) => ( + {/* Second row: Action buttons (hidden on small screens when in single row, shown on mobile) */} +
- ))} -
-
-
- -
-
- - {content && ( -
- - Characters: {content.length} | Words: {content.split(/\s+/).filter(Boolean).length} - - - Method: {inputMethod} {isVietnameseEnabled ? '✓' : '✗'} - -
- )} + +
+ + + {/* Editor container */} +
+
); diff --git a/src/components/navbar.tsx b/src/components/navbar.tsx index 0bdc62e..b0d7967 100644 --- a/src/components/navbar.tsx +++ b/src/components/navbar.tsx @@ -1,102 +1,33 @@ import { Link } from "@heroui/link"; -import { - Navbar as HeroUINavbar, - NavbarBrand, - NavbarContent, - NavbarItem, - NavbarMenuToggle, - NavbarMenu, - NavbarMenuItem, -} from "@heroui/navbar"; -import { link as linkStyles } from "@heroui/theme"; -import clsx from "clsx"; -import { siteConfig } from "@/config/site"; import { ThemeSwitch } from "@/components/theme-switch"; -import { - GithubIcon, - DiscordIcon, -} from "@/components/icons"; -import { Logo } from "@/components/icons"; +import { GithubIcon } from "@/components/icons"; export const Navbar = () => { - return ( - - - - - -

VinaKey 2

- -
-
- {siteConfig.navItems.map((item) => ( - - - {item.label} - - - ))} + <> + {/* Title on top-left */} + + + {/* Icons on top-right */} + + ); }; diff --git a/src/config/site.ts b/src/config/site.ts index 1667e16..abecbab 100644 --- a/src/config/site.ts +++ b/src/config/site.ts @@ -2,7 +2,8 @@ export type SiteConfig = typeof siteConfig; export const siteConfig = { name: "VinaKey 2", - description: "Modern Vietnamese typing tool with markdown editor support - online, fast, and free.", + description: + "Modern Vietnamese typing tool with markdown editor support - online, fast, and free.", navItems: [ { label: "Editor", diff --git a/src/layouts/default.tsx b/src/layouts/default.tsx index 4b12dee..eaad653 100644 --- a/src/layouts/default.tsx +++ b/src/layouts/default.tsx @@ -1,5 +1,3 @@ -import { Link } from "@heroui/link"; - import { Navbar } from "@/components/navbar"; export default function DefaultLayout({ @@ -8,22 +6,11 @@ export default function DefaultLayout({ children: React.ReactNode; }) { return ( -
+
-
+
{children}
-
- - Powered by -

HeroUI

- -
); } diff --git a/src/pages/about.tsx b/src/pages/about.tsx index 3dc9580..6da884c 100644 --- a/src/pages/about.tsx +++ b/src/pages/about.tsx @@ -1,5 +1,6 @@ -import { title, subtitle } from "@/components/primitives"; import { Link } from "@heroui/link"; + +import { title, subtitle } from "@/components/primitives"; import DefaultLayout from "@/layouts/default"; export default function AboutPage() { @@ -17,9 +18,10 @@ export default function AboutPage() {

Giới thiệu

- VinaKey 2 là phiên bản hiện đại của công cụ gõ tiếng Việt trực tuyến, - kết hợp với markdown editor mạnh mẽ. Được xây dựng với công nghệ web hiện đại, - VinaKey 2 cung cấp trải nghiệm gõ tiếng Việt mượt mà và các tính năng soạn thảo văn bản tiên tiến. + VinaKey 2 là phiên bản hiện đại của công cụ gõ tiếng Việt trực + tuyến, kết hợp với markdown editor mạnh mẽ. Được xây dựng với công + nghệ web hiện đại, VinaKey 2 cung cấp trải nghiệm gõ tiếng Việt + mượt mà và các tính năng soạn thảo văn bản tiên tiến.

@@ -36,7 +38,9 @@ export default function AboutPage() {
-

📝 Markdown Editor

+

+ 📝 Markdown Editor +

  • WYSIWYG editing với overtype
  • Toolbar tiện lợi
  • @@ -71,38 +75,86 @@ export default function AboutPage() { - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + +
    Kiểu gõSắcHuyềnHỏiNgãNặng + Kiểu gõ + + Sắc + + Huyền + + Hỏi + + Ngã + + Nặng +
    TELEXsfrxj + TELEX + + s + + f + + r + + x + + j +
    VNI12345 + VNI + + 1 + + 2 + + 3 + + 4 + + 5 +
    VIQR'`?~. + VIQR + + ' + + ` + + ? + + ~ + + . +
    @@ -110,10 +162,10 @@ export default function AboutPage() {
- 📖 Xem source code trên GitHub diff --git a/src/pages/index.tsx b/src/pages/index.tsx index 80fafed..a8bbd71 100644 --- a/src/pages/index.tsx +++ b/src/pages/index.tsx @@ -1,42 +1,104 @@ -import { title, subtitle } from "@/components/primitives"; import DefaultLayout from "@/layouts/default"; import Editor from "@/components/editor"; +import { Card, CardBody, CardHeader } from "@heroui/card"; +import { Table, TableHeader, TableColumn, TableBody, TableRow, TableCell } from "@heroui/table"; export default function IndexPage() { return ( -
-
- VinaKey  - -
- - Modern Vietnamese Input & Markdown Editor - -
- Gõ tiếng Việt và soạn thảo markdown dễ dàng, nhanh chóng - hoàn toàn miễn phí -
-
- -
- + {/* Main editor component */} +
+ { // Save to localStorage or handle content changes - localStorage.setItem('vinakey2-content', content); + localStorage.setItem("vinakey2-content", content); }} />
-
-

- Tính năng chính: Hỗ trợ các kiểu gõ phổ biến (AUTO, TELEX, VNI, VIQR), - editor markdown với WYSIWYG, toolbar tiện lợi, và tương thích hoàn toàn với mobile. -

-

- Hướng dẫn: Chọn kiểu gõ từ thanh công cụ, bắt đầu viết nội dung, - sử dụng toolbar để định dạng, và sao chép kết quả khi hoàn thành. -

+ {/* Input method reference tables */} +
+ {/* Tone marks reference table */} + + +

Bảng dấu thanh

+
+ + + + KIỂU GÕ + Sắc + Huyền + Hỏi + Ngã + Nặng + + + + TELEX + s + f + r + x + j + + + VNI + 1 + 2 + 3 + 4 + 5 + + + VIQR + ' + ` + ? + ~ + . + + +
+
+
+ + {/* Sentence example table */} + + +

Câu ví dụ: Học gõ tiếng Việt thật dễ dàng

+
+ + + + KIỂU GÕ + CÁCH GÕ + + + + TELEX + Hocj gox tieesng Vieetj thaatj deer daafng + + + VIQR + Ho.c go~ tie^'ng Vie^.t tha^.t de^~ da~ng + + + VNI + Ho5c go6 tie61ng Vie65t tha65t de65 da4ng + + +
+
+
diff --git a/src/styles/globals.css b/src/styles/globals.css index e012273..2435d58 100644 --- a/src/styles/globals.css +++ b/src/styles/globals.css @@ -1,3 +1,14 @@ @import "tailwindcss"; -@config "../../tailwind.config.js" \ No newline at end of file +@config "../../tailwind.config.js"; + +/* OverType border radius styling */ +.ot-container { + border-radius: 0.75rem !important; /* rounded-xl */ + overflow: hidden !important; +} + +.ot-textarea, +.ot-preview { + border-radius: 0.75rem !important; +} \ No newline at end of file diff --git a/src/utils/vietnamese-input.ts b/src/utils/vietnamese-input.ts index 160a84f..c54304d 100644 --- a/src/utils/vietnamese-input.ts +++ b/src/utils/vietnamese-input.ts @@ -1,5 +1,5 @@ // Vietnamese Input Method wrapper for AVIM.js -export type InputMethod = 'OFF' | 'AUTO' | 'TELEX' | 'VNI' | 'VIQR'; +export type InputMethod = "OFF" | "AUTO" | "TELEX" | "VNI" | "VIQR"; // Extend window object to include AVIM declare global { @@ -13,7 +13,7 @@ declare global { class VietnameseInput { private avimInstance: any = null; private attachedElements = new Set(); - private currentMethod: InputMethod = 'AUTO'; + private currentMethod: InputMethod = "AUTO"; private enabled: boolean = true; constructor() { @@ -24,16 +24,17 @@ class VietnameseInput { private async initializeAVIM() { // Wait for AVIM to be loaded let attempts = 0; + while (!window.AVIM && attempts < 50) { - await new Promise(resolve => setTimeout(resolve, 100)); + await new Promise((resolve) => setTimeout(resolve, 100)); attempts++; } if (window.AVIM) { // Create AVIM instance this.avimInstance = new window.AVIM(); - console.log('✓ AVIM initialized successfully'); - + console.log("✓ AVIM initialized successfully"); + // Configure AVIM for TELEX by default if (window.AVIMGlobalConfig) { window.AVIMGlobalConfig.method = 1; // 1 = TELEX @@ -41,63 +42,63 @@ class VietnameseInput { window.AVIMGlobalConfig.showControl = 0; // Don't show the control panel } } else { - console.error('❌ AVIM failed to load'); + console.error("❌ AVIM failed to load"); } } public attach(element: HTMLTextAreaElement | HTMLInputElement): void { if (this.attachedElements.has(element)) return; - + this.attachedElements.add(element); - + // Use AVIM's attach method if available if (this.avimInstance) { try { this.avimInstance.attach(element); - console.log('✓ AVIM attached to element'); + console.log("✓ AVIM attached to element"); } catch (error) { - console.error('Error attaching AVIM:', error); + console.error("Error attaching AVIM:", error); } } } public detach(element: HTMLTextAreaElement | HTMLInputElement): void { if (!this.attachedElements.has(element)) return; - + this.attachedElements.delete(element); - + // Use AVIM's detach method if available if (this.avimInstance) { try { this.avimInstance.detach(element); - console.log('✓ AVIM detached from element'); + console.log("✓ AVIM detached from element"); } catch (error) { - console.error('Error detaching AVIM:', error); + console.error("Error detaching AVIM:", error); } } } public setMethod(method: InputMethod): void { this.currentMethod = method; - + if (window.AVIMGlobalConfig) { switch (method) { - case 'OFF': + case "OFF": window.AVIMGlobalConfig.onOff = 0; break; - case 'AUTO': + case "AUTO": window.AVIMGlobalConfig.method = 0; window.AVIMGlobalConfig.onOff = 1; break; - case 'TELEX': + case "TELEX": window.AVIMGlobalConfig.method = 1; window.AVIMGlobalConfig.onOff = 1; break; - case 'VNI': + case "VNI": window.AVIMGlobalConfig.method = 2; window.AVIMGlobalConfig.onOff = 1; break; - case 'VIQR': + case "VIQR": window.AVIMGlobalConfig.method = 3; window.AVIMGlobalConfig.onOff = 1; break; @@ -107,7 +108,7 @@ class VietnameseInput { public setEnabled(enabled: boolean): void { this.enabled = enabled; - + if (window.AVIMGlobalConfig) { window.AVIMGlobalConfig.onOff = enabled ? 1 : 0; } @@ -123,4 +124,4 @@ class VietnameseInput { } // Export singleton instance -export const vietnameseInput = new VietnameseInput(); \ No newline at end of file +export const vietnameseInput = new VietnameseInput(); diff --git a/tailwind.config.js b/tailwind.config.js index db470c4..dfa369d 100644 --- a/tailwind.config.js +++ b/tailwind.config.js @@ -13,5 +13,44 @@ export default { extend: {}, }, darkMode: "class", - plugins: [heroui()], + plugins: [heroui({ + themes: { + light: { + colors: { + primary: { + 50: "#fff7ed", + 100: "#ffedd5", + 200: "#fed7aa", + 300: "#fdba74", + 400: "#fb923c", + 500: "#f97316", // Orange-500 as main + 600: "#ea580c", + 700: "#c2410c", + 800: "#9a3412", + 900: "#7c2d12", + DEFAULT: "#f97316", + foreground: "#ffffff" + } + } + }, + dark: { + colors: { + primary: { + 50: "#fff7ed", + 100: "#ffedd5", + 200: "#fed7aa", + 300: "#fdba74", + 400: "#fb923c", + 500: "#f97316", + 600: "#ea580c", + 700: "#c2410c", + 800: "#9a3412", + 900: "#7c2d12", + DEFAULT: "#f97316", + foreground: "#ffffff" + } + } + } + } + })], } diff --git a/test-results/.last-run.json b/test-results/.last-run.json deleted file mode 100644 index cbcc1fb..0000000 --- a/test-results/.last-run.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "status": "passed", - "failedTests": [] -} \ No newline at end of file diff --git a/yarn.lock b/yarn.lock index 4c152dc..6fd6d65 100644 --- a/yarn.lock +++ b/yarn.lock @@ -462,6 +462,37 @@ "@react-aria/interactions" "3.25.4" "@react-types/shared" "3.31.0" +"@heroui/card@^2.2.23": + version "2.2.23" + resolved "https://registry.yarnpkg.com/@heroui/card/-/card-2.2.23.tgz#fd216d045a6c18d161ea73ebb3a0bc06c5e77863" + integrity sha512-oMmZNr2/mGp/S+Ct8iyzAp4H+tLuT3G0dgHyRie7txj8en79RAy+yRPBYdSt3OpIWM/Zv9un3Dnxgmi/UGCo+A== + dependencies: + "@heroui/react-utils" "2.1.12" + "@heroui/ripple" "2.2.18" + "@heroui/shared-utils" "2.1.10" + "@heroui/use-aria-button" "2.2.18" + "@react-aria/focus" "3.21.0" + "@react-aria/interactions" "3.25.4" + "@react-types/shared" "3.31.0" + +"@heroui/checkbox@2.3.24": + version "2.3.24" + resolved "https://registry.yarnpkg.com/@heroui/checkbox/-/checkbox-2.3.24.tgz#07b1a6ad93c5be7951b9568d375dbd9dfbd0cfa3" + integrity sha512-H/bcpYGeWB9WFhkkOPojO4ONrz5GIMzfAMYdaKOUFtLVl7B9yVca7HaKdNryAFtNSBd/QQAm/an7gh/OFxIgew== + dependencies: + "@heroui/form" "2.1.24" + "@heroui/react-utils" "2.1.12" + "@heroui/shared-utils" "2.1.10" + "@heroui/use-callback-ref" "2.1.8" + "@heroui/use-safe-layout-effect" "2.1.8" + "@react-aria/checkbox" "3.16.0" + "@react-aria/focus" "3.21.0" + "@react-aria/interactions" "3.25.4" + "@react-stately/checkbox" "3.7.0" + "@react-stately/toggle" "3.9.0" + "@react-types/checkbox" "3.10.0" + "@react-types/shared" "3.31.0" + "@heroui/code@^2.2.18": version "2.2.18" resolved "https://registry.yarnpkg.com/@heroui/code/-/code-2.2.18.tgz#4d9156b7e6079f27bbbcde2a63cefdfdcf657b70" @@ -658,6 +689,15 @@ "@heroui/use-clipboard" "2.1.9" "@react-aria/focus" "3.21.0" +"@heroui/spacer@2.2.18": + version "2.2.18" + resolved "https://registry.yarnpkg.com/@heroui/spacer/-/spacer-2.2.18.tgz#d52dcda4b1f22d89ae5d9d4fe17dec34f7e3d3fd" + integrity sha512-EHUIyWt2w0viR7oSqhbZPP4fHuILOdcq7ejAhid7rqhsJSjfixQQ/V4OY7D8vpzi7KmlyrkfpkjAZqAApiEbuA== + dependencies: + "@heroui/react-utils" "2.1.12" + "@heroui/shared-utils" "2.1.10" + "@heroui/system-rsc" "2.3.17" + "@heroui/spinner@2.2.21": version "2.2.21" resolved "https://registry.yarnpkg.com/@heroui/spinner/-/spinner-2.2.21.tgz#ae14523d114764d046d119a9594e5af4be42b73e" @@ -700,6 +740,26 @@ "@react-aria/overlays" "3.28.0" "@react-aria/utils" "3.30.0" +"@heroui/table@^2.2.24": + version "2.2.24" + resolved "https://registry.yarnpkg.com/@heroui/table/-/table-2.2.24.tgz#6dfad181fc25026125c40d00e48f18fa76623b75" + integrity sha512-R3jsgmqGqVAI5rxy0MbcL2lOZwJSbaHSDBEPtDj1UCrPlQC7O+VhKMC9D3I0MaX+bCVDfm0wMYmu5mNjmXGXnQ== + dependencies: + "@heroui/checkbox" "2.3.24" + "@heroui/react-utils" "2.1.12" + "@heroui/shared-icons" "2.1.10" + "@heroui/shared-utils" "2.1.10" + "@heroui/spacer" "2.2.18" + "@react-aria/focus" "3.21.0" + "@react-aria/interactions" "3.25.4" + "@react-aria/table" "3.17.6" + "@react-aria/visually-hidden" "3.8.26" + "@react-stately/table" "3.14.4" + "@react-stately/virtualizer" "4.4.2" + "@react-types/grid" "3.3.4" + "@react-types/table" "3.13.2" + "@tanstack/react-virtual" "3.11.3" + "@heroui/theme@2.4.20", "@heroui/theme@^2.4.20": version "2.4.20" resolved "https://registry.yarnpkg.com/@heroui/theme/-/theme-2.4.20.tgz#bb3bba0fd308be70c98942d730df871cd5b2d33d" @@ -764,6 +824,13 @@ "@react-aria/overlays" "3.28.0" "@react-types/shared" "3.31.0" +"@heroui/use-callback-ref@2.1.8": + version "2.1.8" + resolved "https://registry.yarnpkg.com/@heroui/use-callback-ref/-/use-callback-ref-2.1.8.tgz#c586a609949b7bb2e358f4458998dfc242e0fc84" + integrity sha512-D1JDo9YyFAprYpLID97xxQvf86NvyWLay30BeVVZT9kWmar6O9MbCRc7ACi7Ngko60beonj6+amTWkTm7QuY/Q== + dependencies: + "@heroui/use-safe-layout-effect" "2.1.8" + "@heroui/use-clipboard@2.1.9": version "2.1.9" resolved "https://registry.yarnpkg.com/@heroui/use-clipboard/-/use-clipboard-2.1.9.tgz#09654698b929560f8dd68d2d87cfaa37ffa0ea55" @@ -946,6 +1013,23 @@ "@react-types/shared" "^3.31.0" "@swc/helpers" "^0.5.0" +"@react-aria/checkbox@3.16.0": + version "3.16.0" + resolved "https://registry.yarnpkg.com/@react-aria/checkbox/-/checkbox-3.16.0.tgz#775b3c0bde40bcfa8ab28439ba896088ba489d1b" + integrity sha512-XPaMz1/iVBG6EbJOPYlNtvr+q4f0axJeoIvyzWW3ciIdDSX/3jYuFg/sv/b3OQQl389cbQ/WUBQyWre/uXWVEg== + dependencies: + "@react-aria/form" "^3.1.0" + "@react-aria/interactions" "^3.25.4" + "@react-aria/label" "^3.7.20" + "@react-aria/toggle" "^3.12.0" + "@react-aria/utils" "^3.30.0" + "@react-stately/checkbox" "^3.7.0" + "@react-stately/form" "^3.2.0" + "@react-stately/toggle" "^3.9.0" + "@react-types/checkbox" "^3.10.0" + "@react-types/shared" "^3.31.0" + "@swc/helpers" "^0.5.0" + "@react-aria/dialog@3.5.28": version "3.5.28" resolved "https://registry.yarnpkg.com/@react-aria/dialog/-/dialog-3.5.28.tgz#0cc8dcec8399d17baa65f4a325e65c3a93f0a5e1" @@ -980,6 +1064,25 @@ "@react-types/shared" "^3.31.0" "@swc/helpers" "^0.5.0" +"@react-aria/grid@^3.14.3": + version "3.14.3" + resolved "https://registry.yarnpkg.com/@react-aria/grid/-/grid-3.14.3.tgz#660a54b78e3c0b75d5330752c21de8b2f69a1133" + integrity sha512-O4Ius5tJqKcMGfQT6IXD4MnEOeq6f/59nKmfCLTXMREFac/oxafqanUx3zrEVYbaqLOjEmONcd8S61ptQM6aPg== + dependencies: + "@react-aria/focus" "^3.21.0" + "@react-aria/i18n" "^3.12.11" + "@react-aria/interactions" "^3.25.4" + "@react-aria/live-announcer" "^3.4.4" + "@react-aria/selection" "^3.25.0" + "@react-aria/utils" "^3.30.0" + "@react-stately/collections" "^3.12.6" + "@react-stately/grid" "^3.11.4" + "@react-stately/selection" "^3.20.4" + "@react-types/checkbox" "^3.10.0" + "@react-types/grid" "^3.3.4" + "@react-types/shared" "^3.31.0" + "@swc/helpers" "^0.5.0" + "@react-aria/i18n@3.12.11", "@react-aria/i18n@^3.12.11": version "3.12.11" resolved "https://registry.yarnpkg.com/@react-aria/i18n/-/i18n-3.12.11.tgz#839b98baf8b298ccc76b98c5d3ba3a889f61baf7" @@ -1014,6 +1117,13 @@ "@react-types/shared" "^3.31.0" "@swc/helpers" "^0.5.0" +"@react-aria/live-announcer@^3.4.4": + version "3.4.4" + resolved "https://registry.yarnpkg.com/@react-aria/live-announcer/-/live-announcer-3.4.4.tgz#0e6533940222208b323b71d56ac8e115b2121e6a" + integrity sha512-PTTBIjNRnrdJOIRTDGNifY2d//kA7GUAwRFJNOEwSNG4FW+Bq9awqLiflw0JkpyB0VNIwou6lqKPHZVLsGWOXA== + dependencies: + "@swc/helpers" "^0.5.0" + "@react-aria/menu@3.19.0": version "3.19.0" resolved "https://registry.yarnpkg.com/@react-aria/menu/-/menu-3.19.0.tgz#a53d5506545131fbfa4e6848eb7b4fdadec69947" @@ -1082,6 +1192,27 @@ "@react-types/switch" "^3.5.13" "@swc/helpers" "^0.5.0" +"@react-aria/table@3.17.6": + version "3.17.6" + resolved "https://registry.yarnpkg.com/@react-aria/table/-/table-3.17.6.tgz#dc2d645112434371cb50b1a9bcfbfb00f0a49a49" + integrity sha512-PSEaeKOIazVEaykeTLudPbDLytJgOPLZJalS/xXY0/KL+Gi0Olchmz4tvS0WBe87ChmlVi6GQqU+stk23aZVWg== + dependencies: + "@react-aria/focus" "^3.21.0" + "@react-aria/grid" "^3.14.3" + "@react-aria/i18n" "^3.12.11" + "@react-aria/interactions" "^3.25.4" + "@react-aria/live-announcer" "^3.4.4" + "@react-aria/utils" "^3.30.0" + "@react-aria/visually-hidden" "^3.8.26" + "@react-stately/collections" "^3.12.6" + "@react-stately/flags" "^3.1.2" + "@react-stately/table" "^3.14.4" + "@react-types/checkbox" "^3.10.0" + "@react-types/grid" "^3.3.4" + "@react-types/shared" "^3.31.0" + "@react-types/table" "^3.13.2" + "@swc/helpers" "^0.5.0" + "@react-aria/textfield@3.18.0": version "3.18.0" resolved "https://registry.yarnpkg.com/@react-aria/textfield/-/textfield-3.18.0.tgz#fc5e4742559b53b8ec0a5037337743506a6c8071" @@ -1154,6 +1285,17 @@ "@react-types/shared" "^3.31.0" "@swc/helpers" "^0.5.0" +"@react-stately/checkbox@3.7.0", "@react-stately/checkbox@^3.7.0": + version "3.7.0" + resolved "https://registry.yarnpkg.com/@react-stately/checkbox/-/checkbox-3.7.0.tgz#4464adc16148885a3a8e7fbdfb94eace75ee5887" + integrity sha512-opViVhNvxFVHjXhM4nA/E03uvbLazsIKloXX9JtyBCZAQRUag17dpmkekfIkHvP4o7z7AWFoibD8JBFV1IrMcQ== + dependencies: + "@react-stately/form" "^3.2.0" + "@react-stately/utils" "^3.10.8" + "@react-types/checkbox" "^3.10.0" + "@react-types/shared" "^3.31.0" + "@swc/helpers" "^0.5.0" + "@react-stately/collections@3.12.6", "@react-stately/collections@^3.12.6": version "3.12.6" resolved "https://registry.yarnpkg.com/@react-stately/collections/-/collections-3.12.6.tgz#0d8b6d2744dd0c29d31842d39a112d30c27a4387" @@ -1177,6 +1319,17 @@ "@react-types/shared" "^3.31.0" "@swc/helpers" "^0.5.0" +"@react-stately/grid@^3.11.4": + version "3.11.4" + resolved "https://registry.yarnpkg.com/@react-stately/grid/-/grid-3.11.4.tgz#ec5eac6a8641d175ebef0f57c666af2cb18dad1f" + integrity sha512-oaXFSk2eM0PJ0GVniGA0ZlTpAA0AL0O4MQ7V3cHqZAQbwSO0n2pT31GM0bSVnYP/qTF5lQHo3ECmRQCz0fVyMw== + dependencies: + "@react-stately/collections" "^3.12.6" + "@react-stately/selection" "^3.20.4" + "@react-types/grid" "^3.3.4" + "@react-types/shared" "^3.31.0" + "@swc/helpers" "^0.5.0" + "@react-stately/menu@3.9.6", "@react-stately/menu@^3.9.6": version "3.9.6" resolved "https://registry.yarnpkg.com/@react-stately/menu/-/menu-3.9.6.tgz#5f478f2e2f4dedce30e935f95eae0251b5790e3f" @@ -1206,6 +1359,21 @@ "@react-types/shared" "^3.31.0" "@swc/helpers" "^0.5.0" +"@react-stately/table@3.14.4", "@react-stately/table@^3.14.4": + version "3.14.4" + resolved "https://registry.yarnpkg.com/@react-stately/table/-/table-3.14.4.tgz#d12eb43bcdcebc0f6b07e26abc19f3330b8dd31a" + integrity sha512-uhwk8z3DemozD+yHBjSa4WyxKczpDkxhJhW7ZVOY+1jNuTYxc9/JxzPsHICrlDVV8EPWwwyMUz8eO/8rKN7DbA== + dependencies: + "@react-stately/collections" "^3.12.6" + "@react-stately/flags" "^3.1.2" + "@react-stately/grid" "^3.11.4" + "@react-stately/selection" "^3.20.4" + "@react-stately/utils" "^3.10.8" + "@react-types/grid" "^3.3.4" + "@react-types/shared" "^3.31.0" + "@react-types/table" "^3.13.2" + "@swc/helpers" "^0.5.0" + "@react-stately/toggle@3.9.0", "@react-stately/toggle@^3.9.0": version "3.9.0" resolved "https://registry.yarnpkg.com/@react-stately/toggle/-/toggle-3.9.0.tgz#f32db5d0ad5cb382add52a77a9025ce3fdf10fd8" @@ -1243,6 +1411,15 @@ dependencies: "@swc/helpers" "^0.5.0" +"@react-stately/virtualizer@4.4.2": + version "4.4.2" + resolved "https://registry.yarnpkg.com/@react-stately/virtualizer/-/virtualizer-4.4.2.tgz#5b212d6cfc1a69ef86ff9d1137b92bf3b7215602" + integrity sha512-csU/Bbq1+JYCXlF3wKHa690EhV4/uuK5VwZZvi9jTMqjblDiNUwEmIcx78J8aoadjho5wgRw3ddE9NPDGcVElA== + dependencies: + "@react-aria/utils" "^3.30.0" + "@react-types/shared" "^3.31.0" + "@swc/helpers" "^0.5.0" + "@react-types/button@3.13.0", "@react-types/button@^3.13.0": version "3.13.0" resolved "https://registry.yarnpkg.com/@react-types/button/-/button-3.13.0.tgz#a92ce8faa26bb27c7b44480b20dd35d732eaec4a" @@ -1250,7 +1427,7 @@ dependencies: "@react-types/shared" "^3.31.0" -"@react-types/checkbox@^3.10.0": +"@react-types/checkbox@3.10.0", "@react-types/checkbox@^3.10.0": version "3.10.0" resolved "https://registry.yarnpkg.com/@react-types/checkbox/-/checkbox-3.10.0.tgz#999933ee1b81feea80d2d9f2d0685be248cb5127" integrity sha512-DJ84ilBDvZddE/Sul97Otee4M6psrPRaJm2a1Bc7M3Y5UKo6d6RGXdcDarRRpbnS7BeAbVanKiMS2ygI9QHh9g== @@ -1272,6 +1449,13 @@ dependencies: "@react-types/shared" "^3.31.0" +"@react-types/grid@3.3.4", "@react-types/grid@^3.3.4": + version "3.3.4" + resolved "https://registry.yarnpkg.com/@react-types/grid/-/grid-3.3.4.tgz#02f196995a585e650ab9a4d569e20635ba0ddb30" + integrity sha512-8XNn7Czhl+D1b2zRwdO8c3oBJmKgevT/viKJB4qBVFOhK0l/p3HYDZUMdeclvUfSt4wx4ASpI7MD3v1vmN54oA== + dependencies: + "@react-types/shared" "^3.31.0" + "@react-types/link@3.6.3": version "3.6.3" resolved "https://registry.yarnpkg.com/@react-types/link/-/link-3.6.3.tgz#ba223e8a2478c17d344dc286ac7a7a92dc1137d0" @@ -1306,6 +1490,14 @@ dependencies: "@react-types/shared" "^3.31.0" +"@react-types/table@3.13.2", "@react-types/table@^3.13.2": + version "3.13.2" + resolved "https://registry.yarnpkg.com/@react-types/table/-/table-3.13.2.tgz#c4becb119e1ecbe35be2ec9e9d198bbeedf120bd" + integrity sha512-3/BpFIWHXTcGgQEfip87gMNCWPtPNsc3gFkW4qtsevQ+V0577KyNyvQgvFrqMZKnvz3NWFKyshBb7PTevsus4Q== + dependencies: + "@react-types/grid" "^3.3.4" + "@react-types/shared" "^3.31.0" + "@react-types/textfield@3.12.4", "@react-types/textfield@^3.12.4": version "3.12.4" resolved "https://registry.yarnpkg.com/@react-types/textfield/-/textfield-3.12.4.tgz#f95c359c5fef4cd24abf7969d3c28de77c8e1ecf" @@ -1564,6 +1756,18 @@ "@tailwindcss/oxide" "4.1.11" tailwindcss "4.1.11" +"@tanstack/react-virtual@3.11.3": + version "3.11.3" + resolved "https://registry.yarnpkg.com/@tanstack/react-virtual/-/react-virtual-3.11.3.tgz#cd62ecc431043c4a9ca24ea8dfcc2a70f4805380" + integrity sha512-vCU+OTylXN3hdC8RKg68tPlBPjjxtzon7Ys46MgrSLE+JhSjSTPvoQifV6DQJeJmA8Q3KT6CphJbejupx85vFw== + dependencies: + "@tanstack/virtual-core" "3.11.3" + +"@tanstack/virtual-core@3.11.3": + version "3.11.3" + resolved "https://registry.yarnpkg.com/@tanstack/virtual-core/-/virtual-core-3.11.3.tgz#ab92ff899825e2d71fc9914dda2847a099d43862" + integrity sha512-v2mrNSnMwnPJtcVqNvV0c5roGCBqeogN8jDtgtuHCphdwBasOZ17x8UV8qpHUh+u0MLfX43c0uUHKje0s+Zb0w== + "@tybys/wasm-util@^0.10.0": version "0.10.0" resolved "https://registry.yarnpkg.com/@tybys/wasm-util/-/wasm-util-0.10.0.tgz#2fd3cd754b94b378734ce17058d0507c45c88369"