diff --git a/README.md b/README.md
index 6f84219..ca3f4bf 100644
--- a/README.md
+++ b/README.md
@@ -6,6 +6,8 @@ A single app for 45+ common development tasks. Works offline, zero setup.
Base64, JWT, JSON formatting, hashing, encoding, escaping, color conversion, regex testing, cron parsing, diff checking, Unix time conversion, barcode generation, mock data, and 30+ more.
+**Features Spotlight-like Command Palette:** Press `Cmd+Ctrl+M` (macOS) or `Ctrl+Alt+M` (Windows/Linux) from anywhere to open the floating command palette. Works even over fullscreen apps!
+
No browser tabs. No data sent to servers. Just open and use.
diff --git a/docs/plans/2025-03-03-faster-ci-pipeline.md b/docs/plans/2025-03-03-faster-ci-pipeline.md
new file mode 100644
index 0000000..d9a1150
--- /dev/null
+++ b/docs/plans/2025-03-03-faster-ci-pipeline.md
@@ -0,0 +1,949 @@
+# Faster CI Pipeline Implementation Plan
+
+> **For Claude:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task.
+
+**Goal:** Reduce PR check time from ~5-10 minutes to under 2 minutes by adding aggressive caching and frontend test infrastructure.
+
+**Architecture:** Add comprehensive GitHub Actions caching (Go modules, Bun dependencies, Wails CLI binary, APT packages) + Vitest frontend testing setup with utility and component tests. Three independent work streams allow parallel execution by different agents.
+
+**Tech Stack:** GitHub Actions, Vitest, React Testing Library, Bun, Wails v3
+
+---
+
+## Parallel Work Streams
+
+This plan has 3 independent work streams that can be executed by different agents:
+- **Work Stream A:** CI Optimization (GitHub Actions caching)
+- **Work Stream B:** Frontend Testing Setup (Vitest configuration)
+- **Work Stream C:** Frontend Tests (Utility and component tests)
+
+---
+
+## Work Stream A: CI Optimization (GitHub Actions Caching)
+
+**Dependencies:** None - can run independently
+
+### Task A1: Add Go Module Caching to Go Tests Job
+
+**Files:**
+- Modify: `.github/workflows/ci.yml:21-56`
+
+**Step 1: Add Go module caching to go-tests job**
+
+Update the go-tests job to enable caching:
+
+```yaml
+ - name: Setup Go
+ uses: actions/setup-go@v5
+ with:
+ go-version: "1.25.0"
+ check-latest: true
+ cache: true
+ cache-dependency-path: go.sum
+```
+
+**Step 2: Verify the change**
+
+Check that the Setup Go step now includes `cache: true`.
+
+**Step 3: Commit**
+
+```bash
+git add .github/workflows/ci.yml
+git commit -m "ci: add Go module caching to go-tests job"
+```
+
+---
+
+### Task A2: Optimize Wails CLI Installation with Caching
+
+**Files:**
+- Modify: `.github/workflows/ci.yml:79-86`
+- Modify: `.github/workflows/ci.yml:88-90`
+
+**Step 1: Add Wails CLI binary caching**
+
+Replace the Wails CLI installation with cached version:
+
+```yaml
+ - name: Cache Wails CLI
+ id: cache-wails
+ uses: actions/cache@v4
+ with:
+ path: ~/go/bin/wails3
+ key: wails-cli-${{ runner.os }}-${{ hashFiles('go.mod') }}
+
+ - name: Install Wails CLI
+ if: steps.cache-wails.outputs.cache-hit != 'true'
+ run: |
+ go install github.com/wailsapp/wails/v3/cmd/wails3@latest
+
+ - name: Setup Wails CLI PATH
+ run: |
+ mkdir -p /usr/local/bin
+ cp $(go env GOPATH)/bin/wails3 /usr/local/bin/wails
+ chmod +x /usr/local/bin/wails
+ echo "/usr/local/bin" >> $GITHUB_PATH
+```
+
+**Step 2: Verify the change**
+
+Ensure caching logic and conditional installation are correct.
+
+**Step 3: Commit**
+
+```bash
+git add .github/workflows/ci.yml
+git commit -m "ci: cache Wails CLI binary to avoid recompiling"
+```
+
+---
+
+### Task A3: Add APT Package Caching
+
+**Files:**
+- Modify: `.github/workflows/ci.yml:79-86`
+
+**Step 1: Add APT caching for native dependencies**
+
+Add caching before installing APT packages:
+
+```yaml
+ - name: Cache APT packages
+ uses: awalsh128/cache-apt-pkgs-action@latest
+ with:
+ packages: libgtk-3-dev libwebkit2gtk-4.1-dev
+ version: 1.0
+ execute_install_scripts: false
+```
+
+Remove the `apt-get update` and `apt-get install` commands since the cache action handles them.
+
+**Step 2: Remove old APT commands**
+
+Delete these lines:
+```yaml
+ - name: Install dependencies
+ run: |
+ sudo apt-get update
+ sudo apt-get install -y libgtk-3-dev libwebkit2gtk-4.1-dev
+```
+
+**Step 3: Commit**
+
+```bash
+git add .github/workflows/ci.yml
+git commit -m "ci: cache APT packages for faster native deps installation"
+```
+
+---
+
+### Task A4: Add Bun Dependency Caching
+
+**Files:**
+- Modify: `.github/workflows/ci.yml:74-78`
+
+**Step 1: Add Bun cache configuration**
+
+Update Bun setup to enable caching:
+
+```yaml
+ - name: Setup Bun
+ uses: oven-sh/setup-bun@v1
+ with:
+ bun-version: latest
+
+ - name: Cache Bun dependencies
+ uses: actions/cache@v4
+ with:
+ path: |
+ frontend/node_modules
+ ~/.bun/install/cache
+ key: bun-deps-${{ runner.os }}-${{ hashFiles('frontend/bun.lockb') }}
+ restore-keys: |
+ bun-deps-${{ runner.os }}-
+```
+
+**Step 2: Commit**
+
+```bash
+git add .github/workflows/ci.yml
+git commit -m "ci: add Bun dependency caching"
+```
+
+---
+
+### Task A5: Optimize Go Test Execution
+
+**Files:**
+- Modify: `.github/workflows/ci.yml:31-35`
+
+**Step 1: Optimize test execution**
+
+Replace test command with optimized version:
+
+```yaml
+ - name: Run Go Tests
+ run: |
+ go test -race -count=1 ./internal/... -coverprofile=coverage.out
+ go install github.com/boumenot/gocover-cobertura@latest
+ gocover-cobertura < coverage.out > coverage.xml
+```
+
+Changes:
+- Removed `-v` (verbose) flag for cleaner output
+- Added `-count=1` to disable test caching (ensures fresh runs)
+- Kept `-race` for race detection
+
+**Step 2: Commit**
+
+```bash
+git add .github/workflows/ci.yml
+git commit -m "ci: optimize Go test execution"
+```
+
+---
+
+### Task A6: Parallelize Jobs and Add Frontend Checks
+
+**Files:**
+- Modify: `.github/workflows/ci.yml` (restructure jobs)
+
+**Step 1: Rename app-build to frontend-checks and restructure**
+
+```yaml
+ frontend-checks:
+ name: Frontend Checks
+ runs-on: ubuntu-latest
+ permissions:
+ pull-requests: write
+
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v4
+
+ - name: Setup Bun
+ uses: oven-sh/setup-bun@v1
+ with:
+ bun-version: latest
+
+ - name: Cache Bun dependencies
+ uses: actions/cache@v4
+ with:
+ path: |
+ frontend/node_modules
+ ~/.bun/install/cache
+ key: bun-deps-${{ runner.os }}-${{ hashFiles('frontend/bun.lockb') }}
+ restore-keys: |
+ bun-deps-${{ runner.os }}-
+
+ - name: Install frontend dependencies
+ run: |
+ cd frontend && bun install
+
+ - name: Format check
+ run: |
+ cd frontend && bun run format:check
+
+ - name: Build frontend
+ run: |
+ cd frontend && bun run build
+```
+
+**Step 2: Update job name from `app-build` to `frontend-checks`**
+
+**Step 3: Commit**
+
+```bash
+git add .github/workflows/ci.yml
+git commit -m "ci: restructure frontend job and add format checks"
+```
+
+---
+
+## Work Stream B: Frontend Testing Setup (Vitest)
+
+**Dependencies:** None - can run independently
+
+### Task B1: Install Vitest and Testing Dependencies
+
+**Files:**
+- Modify: `frontend/package.json`
+
+**Step 1: Add test scripts and devDependencies**
+
+Add to `scripts` section:
+```json
+"test": "vitest run",
+"test:watch": "vitest",
+"test:coverage": "vitest run --coverage"
+```
+
+Add to `devDependencies`:
+```json
+"@testing-library/react": "^14.2.1",
+"@testing-library/jest-dom": "^6.4.2",
+"@testing-library/user-event": "^14.5.2",
+"@vitest/coverage-v8": "^1.3.1",
+"jsdom": "^24.0.0",
+"vitest": "^1.3.1"
+```
+
+**Step 2: Install dependencies**
+
+```bash
+cd frontend
+bun install
+```
+
+**Step 3: Verify installation**
+
+Check `frontend/node_modules` contains `vitest`, `@testing-library/react`.
+
+**Step 4: Commit**
+
+```bash
+git add frontend/package.json
+bun install
+git add bun.lockb
+git commit -m "chore: install Vitest and React Testing Library"
+```
+
+---
+
+### Task B2: Configure Vitest
+
+**Files:**
+- Create: `frontend/vitest.config.js`
+
+**Step 1: Create Vitest configuration**
+
+```javascript
+import { defineConfig } from 'vitest/config';
+import react from '@vitejs/plugin-react';
+
+export default defineConfig({
+ plugins: [react()],
+ test: {
+ globals: true,
+ environment: 'jsdom',
+ setupFiles: ['./src/test/setup.js'],
+ include: ['src/**/*.{test,spec}.{js,jsx}'],
+ coverage: {
+ provider: 'v8',
+ reporter: ['text', 'json', 'html'],
+ exclude: [
+ 'node_modules/',
+ 'src/test/',
+ 'src/**/*.d.ts',
+ ],
+ },
+ },
+});
+```
+
+**Step 2: Create test setup file**
+
+**Files:**
+- Create: `frontend/src/test/setup.js`
+
+```javascript
+import { expect, afterEach } from 'vitest';
+import { cleanup } from '@testing-library/react';
+import * as matchers from '@testing-library/jest-dom/matchers';
+
+// Extend Vitest's expect with jest-dom matchers
+expect.extend(matchers);
+
+// Cleanup after each test
+afterEach(() => {
+ cleanup();
+});
+```
+
+**Step 3: Verify configuration**
+
+```bash
+cd frontend
+bun run test --help
+```
+
+Expected: Shows Vitest help output without errors.
+
+**Step 4: Commit**
+
+```bash
+git add frontend/vitest.config.js frontend/src/test/setup.js
+git commit -m "chore: configure Vitest with jsdom and testing-library"
+```
+
+---
+
+### Task B3: Add Frontend Tests to CI
+
+**Files:**
+- Modify: `.github/workflows/ci.yml` (frontend-checks job)
+
+**Step 1: Add frontend test step**
+
+Add after the "Build frontend" step in the `frontend-checks` job:
+
+```yaml
+ - name: Run frontend tests
+ run: |
+ cd frontend && bun run test
+```
+
+**Step 2: Update job name to reflect tests**
+
+Change job name from "Frontend Checks" to "Frontend Tests & Build".
+
+**Step 3: Commit**
+
+```bash
+git add .github/workflows/ci.yml
+git commit -m "ci: add frontend test execution to CI"
+```
+
+---
+
+## Work Stream C: Frontend Tests (Utilities and Components)
+
+**Dependencies:** Work Stream B must be complete first
+
+### Task C1: Test Utility - storage.js
+
+**Files:**
+- Create: `frontend/src/utils/storage.test.js`
+
+**Step 1: Write failing tests**
+
+```javascript
+import { describe, it, expect, beforeEach, vi } from 'vitest';
+import storage from './storage';
+
+describe('storage', () => {
+ beforeEach(() => {
+ // Clear localStorage before each test
+ window.localStorage.clear();
+ vi.clearAllMocks();
+ });
+
+ describe('get', () => {
+ it('should return null for non-existent key', () => {
+ expect(storage.get('non-existent')).toBeNull();
+ });
+
+ it('should return parsed value for existing key', () => {
+ window.localStorage.setItem('test-key', JSON.stringify({ foo: 'bar' }));
+ expect(storage.get('test-key')).toEqual({ foo: 'bar' });
+ });
+
+ it('should return null and log error for invalid JSON', () => {
+ window.localStorage.setItem('invalid', 'not-json');
+ const consoleSpy = vi.spyOn(console, 'error').mockImplementation(() => {});
+
+ expect(storage.get('invalid')).toBeNull();
+ expect(consoleSpy).toHaveBeenCalled();
+
+ consoleSpy.mockRestore();
+ });
+ });
+
+ describe('set', () => {
+ it('should store value as JSON', () => {
+ storage.set('test', { data: 'value' });
+ expect(window.localStorage.getItem('test')).toBe('{"data":"value"}');
+ });
+
+ it('should return true on success', () => {
+ expect(storage.set('test', 'value')).toBe(true);
+ });
+
+ it('should return false and log error on failure', () => {
+ const consoleSpy = vi.spyOn(console, 'error').mockImplementation(() => {});
+ vi.spyOn(window.localStorage, 'setItem').mockImplementation(() => {
+ throw new Error('Storage full');
+ });
+
+ expect(storage.set('test', 'value')).toBe(false);
+ expect(consoleSpy).toHaveBeenCalled();
+
+ consoleSpy.mockRestore();
+ });
+ });
+
+ describe('getArray', () => {
+ it('should return empty array for non-existent key', () => {
+ expect(storage.getArray('non-existent')).toEqual([]);
+ });
+
+ it('should return parsed array for existing key', () => {
+ window.localStorage.setItem('array-key', JSON.stringify([1, 2, 3]));
+ expect(storage.getArray('array-key')).toEqual([1, 2, 3]);
+ });
+
+ it('should return empty array for non-array value', () => {
+ window.localStorage.setItem('not-array', JSON.stringify({ foo: 'bar' }));
+ expect(storage.getArray('not-array')).toEqual([]);
+ });
+ });
+
+ describe('setArray', () => {
+ it('should store array as JSON', () => {
+ storage.setArray('test', [1, 2, 3]);
+ expect(window.localStorage.getItem('test')).toBe('[1,2,3]');
+ });
+
+ it('should return false for non-array value', () => {
+ const consoleSpy = vi.spyOn(console, 'error').mockImplementation(() => {});
+ expect(storage.setArray('test', 'not-array')).toBe(false);
+ consoleSpy.mockRestore();
+ });
+ });
+});
+```
+
+**Step 2: Run tests to verify they pass**
+
+```bash
+cd frontend
+bun run test src/utils/storage.test.js
+```
+
+Expected: All 9 tests pass.
+
+**Step 3: Commit**
+
+```bash
+git add frontend/src/utils/storage.test.js
+git commit -m "test: add tests for storage utility"
+```
+
+---
+
+### Task C2: Test Utility - inputUtils.js
+
+**Files:**
+- Create: `frontend/src/utils/inputUtils.test.js`
+
+**Step 1: Write tests**
+
+```javascript
+import { describe, it, expect } from 'vitest';
+import {
+ getMonospaceFontFamily,
+ getDataFontSize,
+ getTextareaResize,
+ validateJson,
+ formatJson,
+ objectToKeyValueString,
+} from './inputUtils';
+
+describe('inputUtils', () => {
+ describe('getMonospaceFontFamily', () => {
+ it('should return IBM Plex Mono font family', () => {
+ expect(getMonospaceFontFamily()).toBe("'IBM Plex Mono', monospace");
+ });
+ });
+
+ describe('getDataFontSize', () => {
+ it('should return 0.875rem', () => {
+ expect(getDataFontSize()).toBe('0.875rem');
+ });
+ });
+
+ describe('getTextareaResize', () => {
+ it('should return none when both are false', () => {
+ expect(getTextareaResize(false, false)).toBe('none');
+ });
+
+ it('should return vertical when only height is true', () => {
+ expect(getTextareaResize(true, false)).toBe('vertical');
+ });
+
+ it('should return horizontal when only width is true', () => {
+ expect(getTextareaResize(false, true)).toBe('horizontal');
+ });
+
+ it('should return both when both are true', () => {
+ expect(getTextareaResize(true, true)).toBe('both');
+ });
+
+ it('should default to vertical resize', () => {
+ expect(getTextareaResize()).toBe('vertical');
+ });
+ });
+
+ describe('validateJson', () => {
+ it('should return valid for empty string', () => {
+ const result = validateJson('');
+ expect(result.isValid).toBe(true);
+ expect(result.data).toBeNull();
+ expect(result.error).toBeNull();
+ });
+
+ it('should return valid for whitespace-only string', () => {
+ const result = validateJson(' ');
+ expect(result.isValid).toBe(true);
+ });
+
+ it('should parse valid JSON object', () => {
+ const result = validateJson('{"key": "value"}');
+ expect(result.isValid).toBe(true);
+ expect(result.data).toEqual({ key: 'value' });
+ expect(result.error).toBeNull();
+ });
+
+ it('should parse valid JSON array', () => {
+ const result = validateJson('[1, 2, 3]');
+ expect(result.isValid).toBe(true);
+ expect(result.data).toEqual([1, 2, 3]);
+ });
+
+ it('should return invalid for malformed JSON', () => {
+ const result = validateJson('{"key": value}');
+ expect(result.isValid).toBe(false);
+ expect(result.data).toBeNull();
+ expect(result.error).toContain('Unexpected token');
+ });
+ });
+
+ describe('formatJson', () => {
+ it('should format object with default indentation', () => {
+ const result = formatJson({ key: 'value' });
+ expect(result).toBe('{\n "key": "value"\n}');
+ });
+
+ it('should format with custom indentation', () => {
+ const result = formatJson({ key: 'value' }, 4);
+ expect(result).toBe('{\n "key": "value"\n}');
+ });
+
+ it('should return empty string for null', () => {
+ expect(formatJson(null)).toBe('');
+ });
+
+ it('should return empty string for undefined', () => {
+ expect(formatJson(undefined)).toBe('');
+ });
+ });
+
+ describe('objectToKeyValueString', () => {
+ it('should convert object to key-value string', () => {
+ const result = objectToKeyValueString({ foo: 'bar', num: 42 });
+ expect(result).toBe('foo: "bar"\nnum: 42');
+ });
+
+ it('should return empty string for null', () => {
+ expect(objectToKeyValueString(null)).toBe('');
+ });
+
+ it('should return empty string for non-object', () => {
+ expect(objectToKeyValueString('string')).toBe('');
+ });
+
+ it('should handle nested objects', () => {
+ const result = objectToKeyValueString({ nested: { a: 1 } });
+ expect(result).toBe('nested: {"a":1}');
+ });
+ });
+});
+```
+
+**Step 2: Run tests**
+
+```bash
+cd frontend
+bun run test src/utils/inputUtils.test.js
+```
+
+Expected: All tests pass.
+
+**Step 3: Commit**
+
+```bash
+git add frontend/src/utils/inputUtils.test.js
+git commit -m "test: add tests for inputUtils utility"
+```
+
+---
+
+### Task C3: Test Utility - layoutUtils.js
+
+**Files:**
+- Read: `frontend/src/utils/layoutUtils.js`
+- Create: `frontend/src/utils/layoutUtils.test.js`
+
+**Step 1: Read existing layoutUtils.js**
+
+Check if file exists and understand its contents.
+
+**Step 2: Create tests**
+
+```javascript
+import { describe, it, expect } from 'vitest';
+// Import functions from layoutUtils.js once you read it
+
+describe('layoutUtils', () => {
+ it('should have tests for layout utilities', () => {
+ // Write tests based on actual functions in layoutUtils.js
+ expect(true).toBe(true);
+ });
+});
+```
+
+**Step 3: Run and commit**
+
+```bash
+cd frontend
+bun run test src/utils/layoutUtils.test.js
+git add frontend/src/utils/layoutUtils.test.js
+git commit -m "test: add tests for layoutUtils utility"
+```
+
+---
+
+### Task C4: Test Component - ToolCopyButton
+
+**Files:**
+- Create: `frontend/src/components/inputs/ToolCopyButton.test.jsx`
+
+**Step 1: Write tests**
+
+```javascript
+import { describe, it, expect, vi } from 'vitest';
+import { render, screen, fireEvent } from '@testing-library/react';
+import ToolCopyButton from './ToolCopyButton';
+
+describe('ToolCopyButton', () => {
+ it('should render copy button', () => {
+ render();
+ expect(screen.getByRole('button')).toBeInTheDocument();
+ });
+
+ it('should have aria-label for accessibility', () => {
+ render();
+ expect(screen.getByLabelText(/copy/i)).toBeInTheDocument();
+ });
+
+ it('should call clipboard API when clicked', async () => {
+ const mockWriteText = vi.fn().mockResolvedValue(undefined);
+ Object.assign(navigator, {
+ clipboard: { writeText: mockWriteText },
+ });
+
+ render();
+ fireEvent.click(screen.getByRole('button'));
+
+ expect(mockWriteText).toHaveBeenCalledWith('test content');
+ });
+
+ it('should show checkmark after successful copy', async () => {
+ vi.useFakeTimers();
+ Object.assign(navigator, {
+ clipboard: {
+ writeText: vi.fn().mockResolvedValue(undefined),
+ },
+ });
+
+ render();
+ fireEvent.click(screen.getByRole('button'));
+
+ // Wait for async operation
+ await vi.advanceTimersByTimeAsync(0);
+
+ // Check that success state is shown (implementation dependent)
+ // This test may need adjustment based on actual component behavior
+
+ vi.useRealTimers();
+ });
+});
+```
+
+**Step 2: Run tests**
+
+```bash
+cd frontend
+bun run test src/components/inputs/ToolCopyButton.test.jsx
+```
+
+**Step 3: Commit**
+
+```bash
+git add frontend/src/components/inputs/ToolCopyButton.test.jsx
+git commit -m "test: add tests for ToolCopyButton component"
+```
+
+---
+
+### Task C5: Test Hook - useLayoutToggle
+
+**Files:**
+- Create: `frontend/src/hooks/useLayoutToggle.test.js`
+
+**Step 1: Write tests**
+
+```javascript
+import { describe, it, expect } from 'vitest';
+import { renderHook, act } from '@testing-library/react';
+import useLayoutToggle from './useLayoutToggle';
+
+describe('useLayoutToggle', () => {
+ it('should initialize with default layout', () => {
+ const { result } = renderHook(() => useLayoutToggle());
+ expect(result.current.layout).toBeDefined();
+ });
+
+ it('should toggle layout', () => {
+ const { result } = renderHook(() => useLayoutToggle());
+ const initialLayout = result.current.layout;
+
+ act(() => {
+ result.current.toggleLayout();
+ });
+
+ expect(result.current.layout).not.toBe(initialLayout);
+ });
+
+ it('should persist layout to storage', () => {
+ const { result } = renderHook(() => useLayoutToggle());
+
+ act(() => {
+ result.current.setLayout('split');
+ });
+
+ // Re-render hook and check if persisted value is loaded
+ const { result: result2 } = renderHook(() => useLayoutToggle());
+ expect(result2.current.layout).toBe('split');
+ });
+});
+```
+
+**Step 2: Run tests**
+
+```bash
+cd frontend
+bun run test src/hooks/useLayoutToggle.test.js
+```
+
+**Step 3: Commit**
+
+```bash
+git add frontend/src/hooks/useLayoutToggle.test.js
+git commit -m "test: add tests for useLayoutToggle hook"
+```
+
+---
+
+## Integration and Validation
+
+### Task I1: Run Full Test Suite Locally
+
+**Step 1: Run all frontend tests**
+
+```bash
+cd frontend
+bun run test
+```
+
+Expected: All tests pass.
+
+**Step 2: Run with coverage**
+
+```bash
+bun run test:coverage
+```
+
+Expected: Coverage report generated.
+
+**Step 3: Verify build still works**
+
+```bash
+bun run build
+```
+
+Expected: Build completes without errors.
+
+---
+
+### Task I2: Validate CI Workflow
+
+**Step 1: Test locally with act (optional)**
+
+If `act` is installed:
+
+```bash
+act -j go-tests
+act -j frontend-checks
+```
+
+**Step 2: Push branch and create PR**
+
+```bash
+git push origin feature/faster-ci
+```
+
+Create PR and observe CI execution times.
+
+---
+
+### Task I3: Performance Validation
+
+**Step 1: Record baseline timing**
+
+Before changes: Note current CI time (~5-10 minutes)
+
+**Step 2: Measure after changes**
+
+With all optimizations, expected times:
+- Go Tests: ~30-60 seconds (cached modules)
+- Frontend Tests & Build: ~45-90 seconds (cached deps)
+- Total PR check: ~1-2 minutes
+
+**Step 3: Document improvements**
+
+Update README or CONTRIBUTING with new CI times.
+
+---
+
+## Summary of Changes
+
+### Files Created:
+- `frontend/vitest.config.js` - Vitest configuration
+- `frontend/src/test/setup.js` - Test setup file
+- `frontend/src/utils/storage.test.js` - Storage utility tests
+- `frontend/src/utils/inputUtils.test.js` - Input utility tests
+- `frontend/src/utils/layoutUtils.test.js` - Layout utility tests
+- `frontend/src/components/inputs/ToolCopyButton.test.jsx` - Component tests
+- `frontend/src/hooks/useLayoutToggle.test.js` - Hook tests
+
+### Files Modified:
+- `frontend/package.json` - Added test dependencies
+- `.github/workflows/ci.yml` - Added caching and frontend tests
+
+### Expected Outcomes:
+- PR check time reduced from 5-10 min to 1-2 min
+- Frontend tests running in CI
+- 15-20+ unit tests covering core utilities and components
+
+---
+
+## Execution Options
+
+**This plan has 3 independent work streams:**
+
+1. **Work Stream A** (CI Optimization) - Modifies `.github/workflows/ci.yml`
+2. **Work Stream B** (Frontend Testing Setup) - Modifies `frontend/package.json` and creates config
+3. **Work Stream C** (Frontend Tests) - Creates test files (depends on Work Stream B)
+
+**Parallel execution:**
+- Agent 1: Work Stream A (independent)
+- Agent 2: Work Stream B (independent)
+- Agent 3: Work Stream C (waits for B)
+
+**Or serial execution:**
+- Complete Work Stream B first
+- Then Work Streams A and C can run in parallel
+
+Choose execution method based on available agents.
diff --git a/docs/plans/2026-03-06-spotlight-improvements-implementation.md b/docs/plans/2026-03-06-spotlight-improvements-implementation.md
new file mode 100644
index 0000000..6835049
--- /dev/null
+++ b/docs/plans/2026-03-06-spotlight-improvements-implementation.md
@@ -0,0 +1,666 @@
+# Spotlight Improvements Implementation Plan
+
+> **For Claude:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task.
+
+**Goal:** Fix global hotkey activation and redesign spotlight results as unified 400px scrollable panel
+
+**Architecture:** Update Go backend to register reliable global hotkey (`Cmd+Shift+Space`/`Ctrl+Shift+Space`), modify window dimensions, and redesign React frontend with unified glassmorphism panel (no gaps) with fixed 400px results area.
+
+**Tech Stack:** Go (Wails v3), React, Carbon Design System, CSS3
+
+---
+
+## Overview
+
+This plan implements three key improvements:
+1. **Global hotkey fix** - Change from `Cmd+Ctrl+M` to `Cmd+Shift+Space` for reliability
+2. **Unified results panel** - Redesign as single glass panel with search box + 400px scrollable results
+3. **Navigation enhancement** - Ensure tool pages open with pre-filled options from query params
+
+---
+
+## Task 1: Update Global Hotkey Registration
+
+**Files:**
+- Modify: `main.go:268-279`
+- Test: Manual testing (hotkey functionality)
+
+**Step 1: Update hotkey accelerator constant**
+
+Current code (lines 268-273):
+```go
+var hotkeyAccelerator string
+if runtime.GOOS == "darwin" {
+ hotkeyAccelerator = "Cmd+Ctrl+M"
+} else {
+ hotkeyAccelerator = "Ctrl+Alt+M"
+}
+```
+
+Replace with:
+```go
+var hotkeyAccelerator string
+if runtime.GOOS == "darwin" {
+ hotkeyAccelerator = "Cmd+Shift+Space"
+} else {
+ hotkeyAccelerator = "Ctrl+Shift+Space"
+}
+```
+
+**Step 2: Update tray menu hotkey label**
+
+Current code (line 256):
+```go
+trayMenu.Add("Open Spotlight (Cmd+Ctrl+M)").OnClick(func(ctx *application.Context) {
+```
+
+Replace with:
+```go
+trayMenu.Add("Open Spotlight (Cmd+Shift+Space)").OnClick(func(ctx *application.Context) {
+```
+
+**Step 3: Verify hotkey registration error handling**
+
+Ensure this comment exists (line 278):
+```go
+// Note: Wails v3 doesn't return an error from KeyBinding.Add - errors are logged internally
+```
+
+**Step 4: Test hotkey**
+
+Run: `go run .` or `wails dev`
+Expected: Application starts without errors
+Test: Press `Cmd+Shift+Space` (macOS) or `Ctrl+Shift+Space` (Windows/Linux)
+Expected: Spotlight window toggles (show/hide)
+
+**Step 5: Commit**
+
+```bash
+git add main.go
+git commit -m "fix(spotlight): change global hotkey to Cmd+Shift+Space for reliability"
+```
+
+---
+
+## Task 2: Update Spotlight Window Dimensions
+
+**Files:**
+- Modify: `main.go:154-180`
+- Modify: `frontend/src/spotlight.css:12`
+- Test: Visual verification
+
+**Step 1: Update window height in main.go**
+
+Current code (line 157):
+```go
+Height: 80,
+```
+
+Replace with:
+```go
+Height: 480, // 80px search + 400px results
+```
+
+**Step 2: Add min/max height constraints**
+
+Add to `application.WebviewWindowOptions` (after line 158):
+```go
+MinHeight: 80,
+MaxHeight: 480,
+```
+
+**Step 3: Update CSS to center spotlight vertically**
+
+Current code (`frontend/src/spotlight.css` line 12):
+```css
+padding-top: 20vh;
+```
+
+Replace with:
+```css
+padding-top: 15vh; /* Adjusted for taller window */
+```
+
+**Step 4: Build and test**
+
+Run: `wails build` or test in dev mode
+Expected: Spotlight window opens at 480px height
+
+**Step 5: Commit**
+
+```bash
+git add main.go frontend/src/spotlight.css
+git commit -m "feat(spotlight): update window height to 480px for results panel"
+```
+
+---
+
+## Task 3: Redesign Results Panel as Unified Component
+
+**Files:**
+- Modify: `frontend/src/components/SpotlightPalette.jsx:333-382`
+- Modify: `frontend/src/components/SpotlightPalette.css:1-157`
+- Test: Visual verification
+
+**Step 1: Update container structure in JSX**
+
+Current code (lines 333-382 in SpotlightPalette.jsx):
+```jsx
+return (
+
+
+ {/* Search input */}
+
+
+
+ {/* Results list */}
+
+
+ );
+```
+
+Replace with:
+```jsx
+return (
+
+
+
+
+
+ {searchQuery && (
+
+ )}
+
+
+
+
+ {commands.length === 0 ? (
+
No commands found matching "{searchQuery}"
+ ) : (
+
+ {commands.map((command, index) => {
+ const Icon = command.icon || null;
+ return (
+
executeCommand(command)}
+ onMouseEnter={() => setSelectedIndex(index)}
+ role="option"
+ aria-selected={index === selectedIndex}
+ >
+
+ {Icon && }
+ {command.label}
+
+
{command.category}
+
+ );
+ })}
+
+ )}
+
+
+ );
+```
+
+**Step 2: Update CSS for unified panel design**
+
+Replace entire content of `frontend/src/components/SpotlightPalette.css`:
+
+```css
+/* Unified spotlight container */
+.spotlight-container {
+ width: 640px;
+ max-width: 90vw;
+ background: rgba(30, 30, 30, 0.35);
+ border: 1px solid rgba(255, 255, 255, 0.08);
+ border-radius: 16px;
+ box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.5), 0 0 0 1px rgba(255, 255, 255, 0.03);
+ overflow: hidden;
+ backdrop-filter: blur(32px) saturate(200%);
+ -webkit-backdrop-filter: blur(32px) saturate(200%);
+ display: flex;
+ flex-direction: column;
+}
+
+/* Search section */
+.spotlight-search-section {
+ padding: 1.25rem 1.5rem;
+ border-bottom: 1px solid rgba(255, 255, 255, 0.06);
+ flex-shrink: 0;
+}
+
+.spotlight-search-box {
+ display: flex;
+ align-items: center;
+ gap: 0.75rem;
+}
+
+.spotlight-search-icon {
+ color: var(--cds-text-secondary);
+ flex-shrink: 0;
+ opacity: 0.7;
+}
+
+.spotlight-input {
+ flex: 1;
+ background: transparent;
+ border: none;
+ color: var(--cds-text-primary);
+ font-size: 1.25rem;
+ font-weight: 400;
+ padding: 0;
+ outline: none;
+ font-family: var(--cds-font-sans);
+ letter-spacing: -0.01em;
+}
+
+.spotlight-input::placeholder {
+ color: var(--cds-text-secondary);
+ opacity: 0.6;
+}
+
+.spotlight-clear-btn {
+ background: transparent;
+ border: none;
+ color: var(--cds-text-secondary);
+ cursor: pointer;
+ padding: 0.25rem;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ border-radius: 4px;
+ transition: all 0.15s ease;
+ opacity: 0.7;
+}
+
+.spotlight-clear-btn:hover {
+ background: var(--cds-layer-hover);
+ opacity: 1;
+}
+
+/* Results section - fixed 400px height */
+.spotlight-results-section {
+ height: 400px;
+ overflow: hidden;
+ flex-shrink: 0;
+}
+
+.spotlight-empty {
+ padding: 2.5rem 1.5rem;
+ text-align: center;
+ color: var(--cds-text-secondary);
+ font-size: 0.875rem;
+ opacity: 0.8;
+ height: 100%;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+}
+
+.spotlight-list {
+ overflow-y: auto;
+ height: 100%;
+ padding: 0.5rem 0;
+}
+
+.spotlight-item {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ padding: 0.625rem 1.5rem;
+ cursor: pointer;
+ transition: all 0.12s ease;
+ margin: 0 0.5rem;
+ border-radius: 6px;
+}
+
+.spotlight-item:hover,
+.spotlight-item.selected {
+ background: var(--cds-layer-hover);
+}
+
+.spotlight-item.selected {
+ background: var(--cds-layer-selected);
+}
+
+.spotlight-item-content {
+ display: flex;
+ align-items: center;
+ gap: 0.875rem;
+ flex: 1;
+ min-width: 0;
+}
+
+.spotlight-item-icon {
+ color: var(--cds-text-secondary);
+ flex-shrink: 0;
+ opacity: 0.8;
+}
+
+.spotlight-item-label {
+ color: var(--cds-text-primary);
+ font-size: 0.9375rem;
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ font-weight: 400;
+}
+
+.spotlight-item-category {
+ color: var(--cds-text-secondary);
+ font-size: 0.6875rem;
+ text-transform: uppercase;
+ letter-spacing: 0.04em;
+ flex-shrink: 0;
+ margin-left: 1rem;
+ padding: 0.25rem 0.625rem;
+ background: var(--cds-layer-active);
+ border-radius: 4px;
+ font-weight: 500;
+ opacity: 0.8;
+}
+
+/* Scrollbar styling */
+.spotlight-list::-webkit-scrollbar {
+ width: 6px;
+}
+
+.spotlight-list::-webkit-scrollbar-track {
+ background: transparent;
+ margin: 0.5rem 0;
+}
+
+.spotlight-list::-webkit-scrollbar-thumb {
+ background: var(--cds-border-subtle);
+ border-radius: 3px;
+}
+
+.spotlight-list::-webkit-scrollbar-thumb:hover {
+ background: var(--cds-text-secondary);
+}
+```
+
+**Step 3: Test visual appearance**
+
+Run: `wails dev`
+Expected:
+- Spotlight window opens at 480px height
+- Search box at top with proper padding
+- Results area below with 400px fixed height
+- No gap between search and results sections
+- Unified glassmorphism effect across both sections
+- Border-radius applies to entire container
+
+**Step 4: Test scroll behavior**
+
+Test: Type "format" to filter results
+Expected:
+- Results list shows matching commands
+- If results exceed visible area, scrollbar appears
+- Scrolling works smoothly with mouse/trackpad
+- Keyboard navigation (↑/↓) scrolls selected item into view
+
+**Step 5: Commit**
+
+```bash
+git add frontend/src/components/SpotlightPalette.jsx frontend/src/components/SpotlightPalette.css
+git commit -m "feat(spotlight): redesign results panel as unified 400px scrollable component"
+```
+
+---
+
+## Task 4: Verify Navigation with Pre-filled Options
+
+**Files:**
+- Review: `main.go:192-203`
+- Review: `frontend/src/components/SpotlightPalette.jsx:267-294`
+- Test: End-to-end functionality
+
+**Step 1: Review existing navigation flow**
+
+Verify `main.go` lines 192-203:
+```go
+// Listen for spotlight navigation events
+app.Event.On("spotlight:command-selected", func(event *application.CustomEvent) {
+ path := event.Data.(string)
+ log.Printf("Spotlight command selected: %s", path)
+
+ // Show and focus main window
+ mainWindow.Show()
+ mainWindow.Focus()
+
+ // Emit navigation event to frontend
+ mainWindow.EmitEvent("navigate:to", path)
+})
+```
+
+**Step 2: Review command path format in SpotlightPalette.jsx**
+
+Verify commands include query params (lines 8-145):
+- `formatter-json` path: `/tool/code-formatter?format=json`
+- `converter-base64` path: `/tool/text-converter?category=Encode%20-%20Decode&method=Base64`
+- etc.
+
+**Step 3: Verify spotlight closes immediately**
+
+Verify `executeCommand` function (lines 267-294):
+```javascript
+const executeCommand = useCallback(
+ (command) => {
+ saveRecentCommand(command.id);
+
+ if (command.action) {
+ // Handle actions...
+ } else if (command.path) {
+ // Emit command selected event with path
+ window.runtime?.EventsEmit?.('spotlight:command-selected', command.path);
+ }
+
+ // Close spotlight
+ window.runtime?.EventsEmit?.('spotlight:close');
+ },
+ [saveRecentCommand]
+);
+```
+
+**Step 4: Test end-to-end navigation**
+
+Run: `wails dev`
+Test:
+1. Open spotlight with hotkey (`Cmd+Shift+Space`)
+2. Type "json" and select "Format JSON"
+3. **Expected behavior:**
+ - Spotlight closes immediately
+ - Main window opens/focuses
+ - Main window navigates to `/tool/code-formatter?format=json`
+ - Code formatter tool opens with "JSON" format pre-selected
+
+**Step 5: Test another command**
+
+Test:
+1. Open spotlight
+2. Select "Base64 Encode/Decode"
+3. **Expected:** Main window opens with Text Converter tool, "Encode - Decode" category and "Base64" method pre-selected
+
+**Step 6: Commit (if any fixes needed)**
+
+If fixes were required:
+```bash
+git add
+git commit -m "fix(spotlight): ensure navigation with pre-filled options works correctly"
+```
+
+Otherwise, no commit needed (functionality already working).
+
+---
+
+## Task 5: Add CSS Transition for Smooth Appearance
+
+**Files:**
+- Modify: `frontend/src/components/SpotlightPalette.css`
+- Test: Visual smoothness
+
+**Step 1: Add transition to container**
+
+Add to `.spotlight-container` in CSS:
+```css
+.spotlight-container {
+ /* ... existing styles ... */
+ transition: all 0.2s ease-out;
+}
+```
+
+**Step 2: Add subtle fade-in for results**
+
+Add to `.spotlight-results-section`:
+```css
+.spotlight-results-section {
+ /* ... existing styles ... */
+ animation: fadeIn 0.15s ease-out;
+}
+
+@keyframes fadeIn {
+ from {
+ opacity: 0;
+ transform: translateY(-4px);
+ }
+ to {
+ opacity: 1;
+ transform: translateY(0);
+ }
+}
+```
+
+**Step 3: Test transitions**
+
+Run: `wails dev`
+Test: Open spotlight, type to filter results
+Expected: Smooth fade-in animation when results appear
+
+**Step 4: Commit**
+
+```bash
+git add frontend/src/components/SpotlightPalette.css
+git commit -m "feat(spotlight): add smooth transitions for panel appearance"
+```
+
+---
+
+## Task 6: Final Integration Testing
+
+**Files:**
+- All modified files
+- Test: Complete user flows
+
+**Step 1: Test complete hotkey flow**
+
+1. Start application fresh
+2. Press `Cmd+Shift+Space` (macOS) or `Ctrl+Shift+Space` (Windows/Linux)
+3. Expected: Spotlight opens centered on screen
+4. Press same hotkey again
+5. Expected: Spotlight closes
+6. Repeat 3 times to ensure reliability
+
+**Step 2: Test search and selection flow**
+
+1. Open spotlight
+2. Type "format"
+3. Use arrow keys to navigate results
+4. Press Enter to select
+5. Expected: Spotlight closes, main window opens with correct tool pre-filled
+
+**Step 3: Test mouse interaction**
+
+1. Open spotlight
+2. Type "base64"
+3. Click on "Base64 Encode/Decode" result
+4. Expected: Same behavior as keyboard selection
+
+**Step 4: Test empty state**
+
+1. Open spotlight
+2. Type "xyz123" (nonsense query)
+3. Expected: "No commands found" message displayed centered in results area
+
+**Step 5: Test Esc key**
+
+1. Open spotlight
+2. Press Escape key
+3. Expected: Spotlight closes
+
+**Step 6: Run build to ensure no errors**
+
+Run: `wails build`
+Expected: Build completes successfully with no errors
+
+**Step 7: Final commit**
+
+```bash
+git add .
+git commit -m "feat(spotlight): complete improvements - reliable hotkey, unified panel, pre-filled navigation"
+```
+
+---
+
+## Testing Checklist
+
+Verify all these before considering complete:
+
+- [ ] Hotkey `Cmd+Shift+Space` / `Ctrl+Shift+Space` toggles spotlight reliably
+- [ ] Tray menu shows updated hotkey label
+- [ ] Spotlight window opens at 480px height
+- [ ] Results panel displays at fixed 400px height
+- [ ] No gap between search and results sections
+- [ ] Unified glassmorphism styling across entire panel
+- [ ] Results scroll smoothly when exceeding visible area
+- [ ] Selecting result closes spotlight immediately
+- [ ] Main window opens/focuses after selection
+- [ ] Tool opens with correct options pre-filled
+- [ ] Keyboard navigation works (↑↓ arrows, Enter, Esc)
+- [ ] Mouse click selection works
+- [ ] Empty state displays correctly
+- [ ] Build completes without errors
+
+---
+
+## Notes
+
+**Query Params Handling:**
+The tool pages should already handle query params (they were designed this way). If pre-filling doesn't work:
+- Check that tools read query params on mount
+- Verify `navigate:to` event is being received in main window
+- Ensure React Router properly parses query strings
+
+**Hotkey Conflicts:**
+If `Cmd+Shift+Space` conflicts with system shortcuts on any platform:
+- Fallback options: `Cmd+Option+Space`, `Ctrl+Option+Space`, `F1`
+- These would require updating both main.go and tray menu label
+
+**Performance:**
+- Command list is static (no API calls)
+- Fuzzy search runs client-side
+- Should be instant even with 50+ commands
+
+---
+
+## Success Criteria
+
+✅ **Done when:**
+1. Global hotkey works reliably on all platforms
+2. Results panel is unified glass panel with no gaps
+3. Fixed 400px scrollable results area
+4. Tool navigation with pre-filled options works end-to-end
+5. All tests pass and build succeeds
diff --git a/docs/spotlight-testing.md b/docs/spotlight-testing.md
new file mode 100644
index 0000000..9147dc7
--- /dev/null
+++ b/docs/spotlight-testing.md
@@ -0,0 +1,26 @@
+# Spotlight Command Palette Testing Guide
+
+## Manual Testing Checklist
+
+### Basic Functionality
+- [ ] Press `Cmd+Ctrl+M` (macOS) or `Ctrl+Alt+M` (Windows/Linux) opens spotlight
+- [ ] Spotlight window appears centered on screen
+- [ ] Spotlight has translucent backdrop
+- [ ] Typing filters commands
+- [ ] Arrow keys navigate the list
+- [ ] Enter selects a command
+- [ ] Escape closes spotlight
+
+### Navigation
+- [ ] Selecting a tool command opens main window and navigates
+- [ ] Selecting "Toggle Dark Mode" toggles theme
+- [ ] Selecting "Show/Hide Main Window" toggles visibility
+- [ ] Selecting "Quit DevToolbox" quits app
+
+### macOS-Specific Features
+- [ ] Spotlight appears on all Spaces
+- [ ] Spotlight overlays fullscreen apps
+
+### Recent Commands
+- [ ] Recently used commands appear at top
+- [ ] Recent commands persist across restarts
diff --git a/frontend/bindings/github.com/wailsapp/wails/v3/internal/eventcreate.js b/frontend/bindings/github.com/wailsapp/wails/v3/internal/eventcreate.js
index 153c9f5..c61a5b2 100644
--- a/frontend/bindings/github.com/wailsapp/wails/v3/internal/eventcreate.js
+++ b/frontend/bindings/github.com/wailsapp/wails/v3/internal/eventcreate.js
@@ -4,14 +4,12 @@
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore: Unused imports
-import { Create as $Create } from '@wailsio/runtime';
+import { Create as $Create } from "@wailsio/runtime";
function configure() {
- Object.freeze(
- Object.assign($Create.Events, {
- 'settings:changed': $$createType0,
- })
- );
+ Object.freeze(Object.assign($Create.Events, {
+ "settings:changed": $$createType0,
+ }));
}
// Private type creation functions
diff --git a/frontend/bindings/github.com/wailsapp/wails/v3/internal/eventdata.d.ts b/frontend/bindings/github.com/wailsapp/wails/v3/internal/eventdata.d.ts
index 4fce6d8..ad776d4 100644
--- a/frontend/bindings/github.com/wailsapp/wails/v3/internal/eventdata.d.ts
+++ b/frontend/bindings/github.com/wailsapp/wails/v3/internal/eventdata.d.ts
@@ -3,16 +3,19 @@
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore: Unused imports
-import type { Events } from '@wailsio/runtime';
+import type { Events } from "@wailsio/runtime";
-declare module '@wailsio/runtime' {
- namespace Events {
- interface CustomEvents {
- 'app:quit': string;
- 'command-palette:open': string;
- 'settings:changed': { [_ in string]?: any };
- time: string;
- 'window:toggle': string;
+declare module "@wailsio/runtime" {
+ namespace Events {
+ interface CustomEvents {
+ "app:quit": string;
+ "command-palette:open": string;
+ "settings:changed": { [_ in string]?: any };
+ "spotlight:close": string;
+ "spotlight:closed": string;
+ "spotlight:command-selected": string;
+ "time": string;
+ "window:toggle": string;
+ }
}
- }
}
diff --git a/frontend/bindings/github.com/wailsapp/wails/v3/pkg/application/index.js b/frontend/bindings/github.com/wailsapp/wails/v3/pkg/application/index.js
new file mode 100644
index 0000000..66677ba
--- /dev/null
+++ b/frontend/bindings/github.com/wailsapp/wails/v3/pkg/application/index.js
@@ -0,0 +1,7 @@
+// @ts-check
+// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL
+// This file is automatically generated. DO NOT EDIT
+
+export {
+ WebviewWindow
+} from "./models.js";
diff --git a/frontend/bindings/github.com/wailsapp/wails/v3/pkg/application/models.js b/frontend/bindings/github.com/wailsapp/wails/v3/pkg/application/models.js
new file mode 100644
index 0000000..858c3ed
--- /dev/null
+++ b/frontend/bindings/github.com/wailsapp/wails/v3/pkg/application/models.js
@@ -0,0 +1,28 @@
+// @ts-check
+// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL
+// This file is automatically generated. DO NOT EDIT
+
+// eslint-disable-next-line @typescript-eslint/ban-ts-comment
+// @ts-ignore: Unused imports
+import { Create as $Create } from "@wailsio/runtime";
+
+export class WebviewWindow {
+ /**
+ * Creates a new WebviewWindow instance.
+ * @param {Partial} [$$source = {}] - The source object to create the WebviewWindow.
+ */
+ constructor($$source = {}) {
+
+ Object.assign(this, $$source);
+ }
+
+ /**
+ * Creates a new WebviewWindow instance from a string or object.
+ * @param {any} [$$source = {}]
+ * @returns {WebviewWindow}
+ */
+ static createFrom($$source = {}) {
+ let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source;
+ return new WebviewWindow(/** @type {Partial} */($$parsedSource));
+ }
+}
diff --git a/frontend/bun.lock b/frontend/bun.lock
index 25c1446..c307cd7 100644
--- a/frontend/bun.lock
+++ b/frontend/bun.lock
@@ -48,6 +48,7 @@
"@types/react-dom": "^18.0.6",
"@vitejs/plugin-react": "^4.0.0",
"@vitest/coverage-v8": "^1.3.1",
+ "esbuild": "^0.27.3",
"jsdom": "^24.0.0",
"prettier": "^3.5.3",
"vite": "^5.4.21",
@@ -172,51 +173,57 @@
"@csstools/css-tokenizer": ["@csstools/css-tokenizer@3.0.4", "", {}, "sha512-Vd/9EVDiu6PPJt9yAh6roZP6El1xHrdvIVGjyBsHR0RYwNHgL7FJPyIIW4fANJNG6FtyZfvlRPpFI4ZM/lubvw=="],
- "@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.21.5", "", { "os": "aix", "cpu": "ppc64" }, "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ=="],
+ "@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.27.3", "", { "os": "aix", "cpu": "ppc64" }, "sha512-9fJMTNFTWZMh5qwrBItuziu834eOCUcEqymSH7pY+zoMVEZg3gcPuBNxH1EvfVYe9h0x/Ptw8KBzv7qxb7l8dg=="],
- "@esbuild/android-arm": ["@esbuild/android-arm@0.21.5", "", { "os": "android", "cpu": "arm" }, "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg=="],
+ "@esbuild/android-arm": ["@esbuild/android-arm@0.27.3", "", { "os": "android", "cpu": "arm" }, "sha512-i5D1hPY7GIQmXlXhs2w8AWHhenb00+GxjxRncS2ZM7YNVGNfaMxgzSGuO8o8SJzRc/oZwU2bcScvVERk03QhzA=="],
- "@esbuild/android-arm64": ["@esbuild/android-arm64@0.21.5", "", { "os": "android", "cpu": "arm64" }, "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A=="],
+ "@esbuild/android-arm64": ["@esbuild/android-arm64@0.27.3", "", { "os": "android", "cpu": "arm64" }, "sha512-YdghPYUmj/FX2SYKJ0OZxf+iaKgMsKHVPF1MAq/P8WirnSpCStzKJFjOjzsW0QQ7oIAiccHdcqjbHmJxRb/dmg=="],
- "@esbuild/android-x64": ["@esbuild/android-x64@0.21.5", "", { "os": "android", "cpu": "x64" }, "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA=="],
+ "@esbuild/android-x64": ["@esbuild/android-x64@0.27.3", "", { "os": "android", "cpu": "x64" }, "sha512-IN/0BNTkHtk8lkOM8JWAYFg4ORxBkZQf9zXiEOfERX/CzxW3Vg1ewAhU7QSWQpVIzTW+b8Xy+lGzdYXV6UZObQ=="],
- "@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.21.5", "", { "os": "darwin", "cpu": "arm64" }, "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ=="],
+ "@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.27.3", "", { "os": "darwin", "cpu": "arm64" }, "sha512-Re491k7ByTVRy0t3EKWajdLIr0gz2kKKfzafkth4Q8A5n1xTHrkqZgLLjFEHVD+AXdUGgQMq+Godfq45mGpCKg=="],
- "@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.21.5", "", { "os": "darwin", "cpu": "x64" }, "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw=="],
+ "@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.27.3", "", { "os": "darwin", "cpu": "x64" }, "sha512-vHk/hA7/1AckjGzRqi6wbo+jaShzRowYip6rt6q7VYEDX4LEy1pZfDpdxCBnGtl+A5zq8iXDcyuxwtv3hNtHFg=="],
- "@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.21.5", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g=="],
+ "@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.27.3", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-ipTYM2fjt3kQAYOvo6vcxJx3nBYAzPjgTCk7QEgZG8AUO3ydUhvelmhrbOheMnGOlaSFUoHXB6un+A7q4ygY9w=="],
- "@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.21.5", "", { "os": "freebsd", "cpu": "x64" }, "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ=="],
+ "@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.27.3", "", { "os": "freebsd", "cpu": "x64" }, "sha512-dDk0X87T7mI6U3K9VjWtHOXqwAMJBNN2r7bejDsc+j03SEjtD9HrOl8gVFByeM0aJksoUuUVU9TBaZa2rgj0oA=="],
- "@esbuild/linux-arm": ["@esbuild/linux-arm@0.21.5", "", { "os": "linux", "cpu": "arm" }, "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA=="],
+ "@esbuild/linux-arm": ["@esbuild/linux-arm@0.27.3", "", { "os": "linux", "cpu": "arm" }, "sha512-s6nPv2QkSupJwLYyfS+gwdirm0ukyTFNl3KTgZEAiJDd+iHZcbTPPcWCcRYH+WlNbwChgH2QkE9NSlNrMT8Gfw=="],
- "@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.21.5", "", { "os": "linux", "cpu": "arm64" }, "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q=="],
+ "@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.27.3", "", { "os": "linux", "cpu": "arm64" }, "sha512-sZOuFz/xWnZ4KH3YfFrKCf1WyPZHakVzTiqji3WDc0BCl2kBwiJLCXpzLzUBLgmp4veFZdvN5ChW4Eq/8Fc2Fg=="],
- "@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.21.5", "", { "os": "linux", "cpu": "ia32" }, "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg=="],
+ "@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.27.3", "", { "os": "linux", "cpu": "ia32" }, "sha512-yGlQYjdxtLdh0a3jHjuwOrxQjOZYD/C9PfdbgJJF3TIZWnm/tMd/RcNiLngiu4iwcBAOezdnSLAwQDPqTmtTYg=="],
- "@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.21.5", "", { "os": "linux", "cpu": "none" }, "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg=="],
+ "@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.27.3", "", { "os": "linux", "cpu": "none" }, "sha512-WO60Sn8ly3gtzhyjATDgieJNet/KqsDlX5nRC5Y3oTFcS1l0KWba+SEa9Ja1GfDqSF1z6hif/SkpQJbL63cgOA=="],
- "@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.21.5", "", { "os": "linux", "cpu": "none" }, "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg=="],
+ "@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.27.3", "", { "os": "linux", "cpu": "none" }, "sha512-APsymYA6sGcZ4pD6k+UxbDjOFSvPWyZhjaiPyl/f79xKxwTnrn5QUnXR5prvetuaSMsb4jgeHewIDCIWljrSxw=="],
- "@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.21.5", "", { "os": "linux", "cpu": "ppc64" }, "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w=="],
+ "@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.27.3", "", { "os": "linux", "cpu": "ppc64" }, "sha512-eizBnTeBefojtDb9nSh4vvVQ3V9Qf9Df01PfawPcRzJH4gFSgrObw+LveUyDoKU3kxi5+9RJTCWlj4FjYXVPEA=="],
- "@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.21.5", "", { "os": "linux", "cpu": "none" }, "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA=="],
+ "@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.27.3", "", { "os": "linux", "cpu": "none" }, "sha512-3Emwh0r5wmfm3ssTWRQSyVhbOHvqegUDRd0WhmXKX2mkHJe1SFCMJhagUleMq+Uci34wLSipf8Lagt4LlpRFWQ=="],
- "@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.21.5", "", { "os": "linux", "cpu": "s390x" }, "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A=="],
+ "@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.27.3", "", { "os": "linux", "cpu": "s390x" }, "sha512-pBHUx9LzXWBc7MFIEEL0yD/ZVtNgLytvx60gES28GcWMqil8ElCYR4kvbV2BDqsHOvVDRrOxGySBM9Fcv744hw=="],
- "@esbuild/linux-x64": ["@esbuild/linux-x64@0.21.5", "", { "os": "linux", "cpu": "x64" }, "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ=="],
+ "@esbuild/linux-x64": ["@esbuild/linux-x64@0.27.3", "", { "os": "linux", "cpu": "x64" }, "sha512-Czi8yzXUWIQYAtL/2y6vogER8pvcsOsk5cpwL4Gk5nJqH5UZiVByIY8Eorm5R13gq+DQKYg0+JyQoytLQas4dA=="],
- "@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.21.5", "", { "os": "none", "cpu": "x64" }, "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg=="],
+ "@esbuild/netbsd-arm64": ["@esbuild/netbsd-arm64@0.27.3", "", { "os": "none", "cpu": "arm64" }, "sha512-sDpk0RgmTCR/5HguIZa9n9u+HVKf40fbEUt+iTzSnCaGvY9kFP0YKBWZtJaraonFnqef5SlJ8/TiPAxzyS+UoA=="],
- "@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.21.5", "", { "os": "openbsd", "cpu": "x64" }, "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow=="],
+ "@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.27.3", "", { "os": "none", "cpu": "x64" }, "sha512-P14lFKJl/DdaE00LItAukUdZO5iqNH7+PjoBm+fLQjtxfcfFE20Xf5CrLsmZdq5LFFZzb5JMZ9grUwvtVYzjiA=="],
- "@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.21.5", "", { "os": "sunos", "cpu": "x64" }, "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg=="],
+ "@esbuild/openbsd-arm64": ["@esbuild/openbsd-arm64@0.27.3", "", { "os": "openbsd", "cpu": "arm64" }, "sha512-AIcMP77AvirGbRl/UZFTq5hjXK+2wC7qFRGoHSDrZ5v5b8DK/GYpXW3CPRL53NkvDqb9D+alBiC/dV0Fb7eJcw=="],
- "@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.21.5", "", { "os": "win32", "cpu": "arm64" }, "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A=="],
+ "@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.27.3", "", { "os": "openbsd", "cpu": "x64" }, "sha512-DnW2sRrBzA+YnE70LKqnM3P+z8vehfJWHXECbwBmH/CU51z6FiqTQTHFenPlHmo3a8UgpLyH3PT+87OViOh1AQ=="],
- "@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.21.5", "", { "os": "win32", "cpu": "ia32" }, "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA=="],
+ "@esbuild/openharmony-arm64": ["@esbuild/openharmony-arm64@0.27.3", "", { "os": "none", "cpu": "arm64" }, "sha512-NinAEgr/etERPTsZJ7aEZQvvg/A6IsZG/LgZy+81wON2huV7SrK3e63dU0XhyZP4RKGyTm7aOgmQk0bGp0fy2g=="],
- "@esbuild/win32-x64": ["@esbuild/win32-x64@0.21.5", "", { "os": "win32", "cpu": "x64" }, "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw=="],
+ "@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.27.3", "", { "os": "sunos", "cpu": "x64" }, "sha512-PanZ+nEz+eWoBJ8/f8HKxTTD172SKwdXebZ0ndd953gt1HRBbhMsaNqjTyYLGLPdoWHy4zLU7bDVJztF5f3BHA=="],
+
+ "@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.27.3", "", { "os": "win32", "cpu": "arm64" }, "sha512-B2t59lWWYrbRDw/tjiWOuzSsFh1Y/E95ofKz7rIVYSQkUYBjfSgf6oeYPNWHToFRr2zx52JKApIcAS/D5TUBnA=="],
+
+ "@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.27.3", "", { "os": "win32", "cpu": "ia32" }, "sha512-QLKSFeXNS8+tHW7tZpMtjlNb7HKau0QDpwm49u0vUp9y1WOF+PEzkU84y9GqYaAVW8aH8f3GcBck26jh54cX4Q=="],
+
+ "@esbuild/win32-x64": ["@esbuild/win32-x64@0.27.3", "", { "os": "win32", "cpu": "x64" }, "sha512-4uJGhsxuptu3OcpVAzli+/gWusVGwZZHTlS63hh++ehExkVT8SgiEf7/uC/PclrPPkLhZqGgCTjd0VWLo6xMqA=="],
"@floating-ui/core": ["@floating-ui/core@1.7.4", "", { "dependencies": { "@floating-ui/utils": "^0.2.10" } }, "sha512-C3HlIdsBxszvm5McXlB8PeOEWfBhcGBTZGkGlWc2U0KFY5IwG5OQEuQ8rq52DZmcHDlPLd+YFBK+cZcytwIFWg=="],
@@ -568,7 +575,7 @@
"es-toolkit": ["es-toolkit@1.44.0", "", {}, "sha512-6penXeZalaV88MM3cGkFZZfOoLGWshWWfdy0tWw/RlVVyhvMaWSBTOvXNeiW3e5FwdS5ePW0LGEu17zT139ktg=="],
- "esbuild": ["esbuild@0.21.5", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.21.5", "@esbuild/android-arm": "0.21.5", "@esbuild/android-arm64": "0.21.5", "@esbuild/android-x64": "0.21.5", "@esbuild/darwin-arm64": "0.21.5", "@esbuild/darwin-x64": "0.21.5", "@esbuild/freebsd-arm64": "0.21.5", "@esbuild/freebsd-x64": "0.21.5", "@esbuild/linux-arm": "0.21.5", "@esbuild/linux-arm64": "0.21.5", "@esbuild/linux-ia32": "0.21.5", "@esbuild/linux-loong64": "0.21.5", "@esbuild/linux-mips64el": "0.21.5", "@esbuild/linux-ppc64": "0.21.5", "@esbuild/linux-riscv64": "0.21.5", "@esbuild/linux-s390x": "0.21.5", "@esbuild/linux-x64": "0.21.5", "@esbuild/netbsd-x64": "0.21.5", "@esbuild/openbsd-x64": "0.21.5", "@esbuild/sunos-x64": "0.21.5", "@esbuild/win32-arm64": "0.21.5", "@esbuild/win32-ia32": "0.21.5", "@esbuild/win32-x64": "0.21.5" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw=="],
+ "esbuild": ["esbuild@0.27.3", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.27.3", "@esbuild/android-arm": "0.27.3", "@esbuild/android-arm64": "0.27.3", "@esbuild/android-x64": "0.27.3", "@esbuild/darwin-arm64": "0.27.3", "@esbuild/darwin-x64": "0.27.3", "@esbuild/freebsd-arm64": "0.27.3", "@esbuild/freebsd-x64": "0.27.3", "@esbuild/linux-arm": "0.27.3", "@esbuild/linux-arm64": "0.27.3", "@esbuild/linux-ia32": "0.27.3", "@esbuild/linux-loong64": "0.27.3", "@esbuild/linux-mips64el": "0.27.3", "@esbuild/linux-ppc64": "0.27.3", "@esbuild/linux-riscv64": "0.27.3", "@esbuild/linux-s390x": "0.27.3", "@esbuild/linux-x64": "0.27.3", "@esbuild/netbsd-arm64": "0.27.3", "@esbuild/netbsd-x64": "0.27.3", "@esbuild/openbsd-arm64": "0.27.3", "@esbuild/openbsd-x64": "0.27.3", "@esbuild/openharmony-arm64": "0.27.3", "@esbuild/sunos-x64": "0.27.3", "@esbuild/win32-arm64": "0.27.3", "@esbuild/win32-ia32": "0.27.3", "@esbuild/win32-x64": "0.27.3" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-8VwMnyGCONIs6cWue2IdpHxHnAjzxnw2Zr7MkVxB2vjmQ2ivqGFb4LEG3SMnv0Gb2F/G/2yA8zUaiL1gywDCCg=="],
"escalade": ["escalade@3.2.0", "", {}, "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA=="],
@@ -1084,6 +1091,8 @@
"test-exclude/glob": ["glob@7.2.3", "", { "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", "minimatch": "^3.1.1", "once": "^1.3.0", "path-is-absolute": "^1.0.0" } }, "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q=="],
+ "vite/esbuild": ["esbuild@0.21.5", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.21.5", "@esbuild/android-arm": "0.21.5", "@esbuild/android-arm64": "0.21.5", "@esbuild/android-x64": "0.21.5", "@esbuild/darwin-arm64": "0.21.5", "@esbuild/darwin-x64": "0.21.5", "@esbuild/freebsd-arm64": "0.21.5", "@esbuild/freebsd-x64": "0.21.5", "@esbuild/linux-arm": "0.21.5", "@esbuild/linux-arm64": "0.21.5", "@esbuild/linux-ia32": "0.21.5", "@esbuild/linux-loong64": "0.21.5", "@esbuild/linux-mips64el": "0.21.5", "@esbuild/linux-ppc64": "0.21.5", "@esbuild/linux-riscv64": "0.21.5", "@esbuild/linux-s390x": "0.21.5", "@esbuild/linux-x64": "0.21.5", "@esbuild/netbsd-x64": "0.21.5", "@esbuild/openbsd-x64": "0.21.5", "@esbuild/sunos-x64": "0.21.5", "@esbuild/win32-arm64": "0.21.5", "@esbuild/win32-ia32": "0.21.5", "@esbuild/win32-x64": "0.21.5" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw=="],
+
"@isaacs/cliui/string-width/emoji-regex": ["emoji-regex@9.2.2", "", {}, "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg=="],
"@isaacs/cliui/strip-ansi/ansi-regex": ["ansi-regex@6.2.2", "", {}, "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg=="],
@@ -1101,5 +1110,51 @@
"editorconfig/minimatch/brace-expansion": ["brace-expansion@2.0.2", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ=="],
"glob/minimatch/brace-expansion": ["brace-expansion@2.0.2", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ=="],
+
+ "vite/esbuild/@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.21.5", "", { "os": "aix", "cpu": "ppc64" }, "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ=="],
+
+ "vite/esbuild/@esbuild/android-arm": ["@esbuild/android-arm@0.21.5", "", { "os": "android", "cpu": "arm" }, "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg=="],
+
+ "vite/esbuild/@esbuild/android-arm64": ["@esbuild/android-arm64@0.21.5", "", { "os": "android", "cpu": "arm64" }, "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A=="],
+
+ "vite/esbuild/@esbuild/android-x64": ["@esbuild/android-x64@0.21.5", "", { "os": "android", "cpu": "x64" }, "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA=="],
+
+ "vite/esbuild/@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.21.5", "", { "os": "darwin", "cpu": "arm64" }, "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ=="],
+
+ "vite/esbuild/@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.21.5", "", { "os": "darwin", "cpu": "x64" }, "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw=="],
+
+ "vite/esbuild/@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.21.5", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g=="],
+
+ "vite/esbuild/@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.21.5", "", { "os": "freebsd", "cpu": "x64" }, "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ=="],
+
+ "vite/esbuild/@esbuild/linux-arm": ["@esbuild/linux-arm@0.21.5", "", { "os": "linux", "cpu": "arm" }, "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA=="],
+
+ "vite/esbuild/@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.21.5", "", { "os": "linux", "cpu": "arm64" }, "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q=="],
+
+ "vite/esbuild/@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.21.5", "", { "os": "linux", "cpu": "ia32" }, "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg=="],
+
+ "vite/esbuild/@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.21.5", "", { "os": "linux", "cpu": "none" }, "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg=="],
+
+ "vite/esbuild/@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.21.5", "", { "os": "linux", "cpu": "none" }, "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg=="],
+
+ "vite/esbuild/@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.21.5", "", { "os": "linux", "cpu": "ppc64" }, "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w=="],
+
+ "vite/esbuild/@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.21.5", "", { "os": "linux", "cpu": "none" }, "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA=="],
+
+ "vite/esbuild/@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.21.5", "", { "os": "linux", "cpu": "s390x" }, "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A=="],
+
+ "vite/esbuild/@esbuild/linux-x64": ["@esbuild/linux-x64@0.21.5", "", { "os": "linux", "cpu": "x64" }, "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ=="],
+
+ "vite/esbuild/@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.21.5", "", { "os": "none", "cpu": "x64" }, "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg=="],
+
+ "vite/esbuild/@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.21.5", "", { "os": "openbsd", "cpu": "x64" }, "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow=="],
+
+ "vite/esbuild/@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.21.5", "", { "os": "sunos", "cpu": "x64" }, "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg=="],
+
+ "vite/esbuild/@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.21.5", "", { "os": "win32", "cpu": "arm64" }, "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A=="],
+
+ "vite/esbuild/@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.21.5", "", { "os": "win32", "cpu": "ia32" }, "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA=="],
+
+ "vite/esbuild/@esbuild/win32-x64": ["@esbuild/win32-x64@0.21.5", "", { "os": "win32", "cpu": "x64" }, "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw=="],
}
}
diff --git a/frontend/package-lock.json b/frontend/package-lock.json
index a8f717e..30e0856 100644
--- a/frontend/package-lock.json
+++ b/frontend/package-lock.json
@@ -8,10 +8,25 @@
"name": "frontend",
"version": "0.0.0",
"dependencies": {
- "@carbon/icons-react": "^11.71.0",
- "@carbon/react": "^1.97.0",
- "@carbon/styles": "^1.96.0",
+ "@carbon/icons-react": "^11.76.0",
+ "@carbon/react": "^1.102.0",
+ "@carbon/styles": "^1.101.0",
+ "@codemirror/commands": "^6.10.2",
+ "@codemirror/lang-css": "^6.3.1",
+ "@codemirror/lang-html": "^6.4.11",
+ "@codemirror/lang-java": "^6.0.2",
+ "@codemirror/lang-javascript": "^6.2.4",
+ "@codemirror/lang-json": "^6.0.2",
+ "@codemirror/lang-sql": "^6.10.0",
+ "@codemirror/lang-xml": "^6.1.0",
+ "@codemirror/language": "^6.12.2",
+ "@codemirror/legacy-modes": "^6.5.2",
+ "@codemirror/rangeset": "^0.19.9",
+ "@codemirror/state": "^6.5.4",
+ "@codemirror/view": "^6.39.15",
+ "@lezer/highlight": "^1.2.3",
"@wailsio/runtime": "^3.0.0-alpha.79",
+ "codemirror": "^6.0.2",
"cronstrue": "^3.9.0",
"diff": "^8.0.2",
"js-beautify": "^1.15.4",
@@ -23,6 +38,7 @@
"qrcode": "^1.5.4",
"react": "^18.2.0",
"react-dom": "^18.2.0",
+ "react-router-dom": "^6.29.0",
"sass": "^1.96.0",
"sql-formatter": "^15.6.11",
"ulid": "^3.0.2",
@@ -32,6 +48,7 @@
"@types/react": "^18.0.17",
"@types/react-dom": "^18.0.6",
"@vitejs/plugin-react": "^4.0.0",
+ "esbuild": "^0.27.3",
"prettier": "^3.5.3",
"vite": "^5.4.21"
}
@@ -288,7 +305,7 @@
}
},
"node_modules/@carbon/colors": {
- "version": "11.46.0",
+ "version": "11.48.0",
"hasInstallScript": true,
"license": "Apache-2.0",
"dependencies": {
@@ -296,7 +313,7 @@
}
},
"node_modules/@carbon/feature-flags": {
- "version": "0.32.0",
+ "version": "1.0.0",
"hasInstallScript": true,
"license": "Apache-2.0",
"dependencies": {
@@ -304,16 +321,16 @@
}
},
"node_modules/@carbon/grid": {
- "version": "11.49.0",
+ "version": "11.51.0",
"hasInstallScript": true,
"license": "Apache-2.0",
"dependencies": {
- "@carbon/layout": "^11.47.0",
+ "@carbon/layout": "^11.49.0",
"@ibm/telemetry-js": "^1.5.0"
}
},
"node_modules/@carbon/icon-helpers": {
- "version": "10.71.0",
+ "version": "10.73.0",
"hasInstallScript": true,
"license": "Apache-2.0",
"dependencies": {
@@ -321,11 +338,11 @@
}
},
"node_modules/@carbon/icons-react": {
- "version": "11.74.0",
+ "version": "11.76.0",
"hasInstallScript": true,
"license": "Apache-2.0",
"dependencies": {
- "@carbon/icon-helpers": "^10.71.0",
+ "@carbon/icon-helpers": "^10.73.0",
"@ibm/telemetry-js": "^1.5.0",
"prop-types": "^15.8.1"
},
@@ -334,7 +351,7 @@
}
},
"node_modules/@carbon/layout": {
- "version": "11.47.0",
+ "version": "11.49.0",
"hasInstallScript": true,
"license": "Apache-2.0",
"dependencies": {
@@ -342,7 +359,7 @@
}
},
"node_modules/@carbon/motion": {
- "version": "11.40.0",
+ "version": "11.42.0",
"hasInstallScript": true,
"license": "Apache-2.0",
"dependencies": {
@@ -350,16 +367,16 @@
}
},
"node_modules/@carbon/react": {
- "version": "1.100.0",
+ "version": "1.102.0",
"hasInstallScript": true,
"license": "Apache-2.0",
"dependencies": {
"@babel/runtime": "^7.27.3",
- "@carbon/feature-flags": ">=0.32.0",
- "@carbon/icons-react": "^11.74.0",
- "@carbon/layout": "^11.47.0",
- "@carbon/styles": "^1.99.0",
- "@carbon/utilities": "^0.15.0",
+ "@carbon/feature-flags": "^1.0.0",
+ "@carbon/icons-react": "^11.76.0",
+ "@carbon/layout": "^11.49.0",
+ "@carbon/styles": "^1.101.0",
+ "@carbon/utilities": "^0.16.0",
"@floating-ui/react": "^0.27.4",
"@ibm/telemetry-js": "^1.5.0",
"classnames": "2.5.1",
@@ -380,17 +397,17 @@
}
},
"node_modules/@carbon/styles": {
- "version": "1.99.0",
+ "version": "1.101.0",
"hasInstallScript": true,
"license": "Apache-2.0",
"dependencies": {
- "@carbon/colors": "^11.46.0",
- "@carbon/feature-flags": ">=0.32.0",
- "@carbon/grid": "^11.49.0",
- "@carbon/layout": "^11.47.0",
- "@carbon/motion": "^11.40.0",
- "@carbon/themes": "^11.67.0",
- "@carbon/type": "^11.53.0",
+ "@carbon/colors": "^11.48.0",
+ "@carbon/feature-flags": "^1.0.0",
+ "@carbon/grid": "^11.51.0",
+ "@carbon/layout": "^11.49.0",
+ "@carbon/motion": "^11.42.0",
+ "@carbon/themes": "^11.69.0",
+ "@carbon/type": "^11.55.0",
"@ibm/plex": "6.0.0-next.6",
"@ibm/plex-mono": "1.1.0",
"@ibm/plex-sans": "1.1.0",
@@ -412,29 +429,29 @@
}
},
"node_modules/@carbon/themes": {
- "version": "11.67.0",
+ "version": "11.69.0",
"hasInstallScript": true,
"license": "Apache-2.0",
"dependencies": {
- "@carbon/colors": "^11.46.0",
- "@carbon/layout": "^11.47.0",
- "@carbon/type": "^11.53.0",
+ "@carbon/colors": "^11.48.0",
+ "@carbon/layout": "^11.49.0",
+ "@carbon/type": "^11.55.0",
"@ibm/telemetry-js": "^1.5.0",
"color": "^4.0.0"
}
},
"node_modules/@carbon/type": {
- "version": "11.53.0",
+ "version": "11.55.0",
"hasInstallScript": true,
"license": "Apache-2.0",
"dependencies": {
- "@carbon/grid": "^11.49.0",
- "@carbon/layout": "^11.47.0",
+ "@carbon/grid": "^11.51.0",
+ "@carbon/layout": "^11.49.0",
"@ibm/telemetry-js": "^1.5.0"
}
},
"node_modules/@carbon/utilities": {
- "version": "0.15.0",
+ "version": "0.16.0",
"hasInstallScript": true,
"license": "Apache-2.0",
"dependencies": {
@@ -442,1715 +459,2832 @@
"@internationalized/number": "^3.6.1"
}
},
- "node_modules/@esbuild/darwin-arm64": {
- "version": "0.21.5",
- "cpu": [
- "arm64"
- ],
- "dev": true,
+ "node_modules/@codemirror/autocomplete": {
+ "version": "6.20.0",
"license": "MIT",
- "optional": true,
- "os": [
- "darwin"
- ],
- "engines": {
- "node": ">=12"
+ "dependencies": {
+ "@codemirror/language": "^6.0.0",
+ "@codemirror/state": "^6.0.0",
+ "@codemirror/view": "^6.17.0",
+ "@lezer/common": "^1.0.0"
}
},
- "node_modules/@floating-ui/core": {
- "version": "1.7.4",
+ "node_modules/@codemirror/commands": {
+ "version": "6.10.2",
"license": "MIT",
"dependencies": {
- "@floating-ui/utils": "^0.2.10"
+ "@codemirror/language": "^6.0.0",
+ "@codemirror/state": "^6.4.0",
+ "@codemirror/view": "^6.27.0",
+ "@lezer/common": "^1.1.0"
}
},
- "node_modules/@floating-ui/dom": {
- "version": "1.7.5",
+ "node_modules/@codemirror/lang-css": {
+ "version": "6.3.1",
"license": "MIT",
"dependencies": {
- "@floating-ui/core": "^1.7.4",
- "@floating-ui/utils": "^0.2.10"
+ "@codemirror/autocomplete": "^6.0.0",
+ "@codemirror/language": "^6.0.0",
+ "@codemirror/state": "^6.0.0",
+ "@lezer/common": "^1.0.2",
+ "@lezer/css": "^1.1.7"
}
},
- "node_modules/@floating-ui/react": {
- "version": "0.27.17",
+ "node_modules/@codemirror/lang-html": {
+ "version": "6.4.11",
"license": "MIT",
"dependencies": {
- "@floating-ui/react-dom": "^2.1.7",
- "@floating-ui/utils": "^0.2.10",
- "tabbable": "^6.0.0"
- },
- "peerDependencies": {
- "react": ">=17.0.0",
- "react-dom": ">=17.0.0"
+ "@codemirror/autocomplete": "^6.0.0",
+ "@codemirror/lang-css": "^6.0.0",
+ "@codemirror/lang-javascript": "^6.0.0",
+ "@codemirror/language": "^6.4.0",
+ "@codemirror/state": "^6.0.0",
+ "@codemirror/view": "^6.17.0",
+ "@lezer/common": "^1.0.0",
+ "@lezer/css": "^1.1.0",
+ "@lezer/html": "^1.3.12"
}
},
- "node_modules/@floating-ui/react-dom": {
- "version": "2.1.7",
+ "node_modules/@codemirror/lang-java": {
+ "version": "6.0.2",
"license": "MIT",
"dependencies": {
- "@floating-ui/dom": "^1.7.5"
- },
- "peerDependencies": {
- "react": ">=16.8.0",
- "react-dom": ">=16.8.0"
- }
- },
- "node_modules/@floating-ui/utils": {
- "version": "0.2.10",
- "license": "MIT"
- },
- "node_modules/@ibm/plex": {
- "version": "6.0.0-next.6",
- "license": "OFL-1.1",
- "engines": {
- "node": ">=14"
+ "@codemirror/language": "^6.0.0",
+ "@lezer/java": "^1.0.0"
}
},
- "node_modules/@ibm/plex-mono": {
- "version": "1.1.0",
- "hasInstallScript": true,
- "license": "OFL-1.1",
+ "node_modules/@codemirror/lang-javascript": {
+ "version": "6.2.4",
+ "license": "MIT",
"dependencies": {
- "@ibm/telemetry-js": "^1.6.1"
+ "@codemirror/autocomplete": "^6.0.0",
+ "@codemirror/language": "^6.6.0",
+ "@codemirror/lint": "^6.0.0",
+ "@codemirror/state": "^6.0.0",
+ "@codemirror/view": "^6.17.0",
+ "@lezer/common": "^1.0.0",
+ "@lezer/javascript": "^1.0.0"
}
},
- "node_modules/@ibm/plex-sans": {
- "version": "1.1.0",
- "hasInstallScript": true,
- "license": "OFL-1.1",
+ "node_modules/@codemirror/lang-json": {
+ "version": "6.0.2",
+ "license": "MIT",
"dependencies": {
- "@ibm/telemetry-js": "^1.6.1"
+ "@codemirror/language": "^6.0.0",
+ "@lezer/json": "^1.0.0"
}
},
- "node_modules/@ibm/plex-sans-arabic": {
- "version": "1.1.0",
- "hasInstallScript": true,
- "license": "OFL-1.1",
+ "node_modules/@codemirror/lang-sql": {
+ "version": "6.10.0",
+ "license": "MIT",
"dependencies": {
- "@ibm/telemetry-js": "^1.6.1"
+ "@codemirror/autocomplete": "^6.0.0",
+ "@codemirror/language": "^6.0.0",
+ "@codemirror/state": "^6.0.0",
+ "@lezer/common": "^1.2.0",
+ "@lezer/highlight": "^1.0.0",
+ "@lezer/lr": "^1.0.0"
}
},
- "node_modules/@ibm/plex-sans-devanagari": {
- "version": "1.1.0",
- "hasInstallScript": true,
- "license": "OFL-1.1",
+ "node_modules/@codemirror/lang-xml": {
+ "version": "6.1.0",
+ "license": "MIT",
"dependencies": {
- "@ibm/telemetry-js": "^1.6.1"
+ "@codemirror/autocomplete": "^6.0.0",
+ "@codemirror/language": "^6.4.0",
+ "@codemirror/state": "^6.0.0",
+ "@codemirror/view": "^6.0.0",
+ "@lezer/common": "^1.0.0",
+ "@lezer/xml": "^1.0.0"
}
},
- "node_modules/@ibm/plex-sans-hebrew": {
- "version": "1.1.0",
- "hasInstallScript": true,
- "license": "OFL-1.1",
+ "node_modules/@codemirror/language": {
+ "version": "6.12.2",
+ "license": "MIT",
"dependencies": {
- "@ibm/telemetry-js": "^1.6.1"
+ "@codemirror/state": "^6.0.0",
+ "@codemirror/view": "^6.23.0",
+ "@lezer/common": "^1.5.0",
+ "@lezer/highlight": "^1.0.0",
+ "@lezer/lr": "^1.0.0",
+ "style-mod": "^4.0.0"
}
},
- "node_modules/@ibm/plex-sans-thai": {
- "version": "1.1.0",
- "hasInstallScript": true,
- "license": "OFL-1.1",
+ "node_modules/@codemirror/legacy-modes": {
+ "version": "6.5.2",
+ "license": "MIT",
"dependencies": {
- "@ibm/telemetry-js": "^1.6.1"
+ "@codemirror/language": "^6.0.0"
}
},
- "node_modules/@ibm/plex-sans-thai-looped": {
- "version": "1.1.0",
- "hasInstallScript": true,
- "license": "OFL-1.1",
+ "node_modules/@codemirror/lint": {
+ "version": "6.9.4",
+ "license": "MIT",
"dependencies": {
- "@ibm/telemetry-js": "^1.6.1"
+ "@codemirror/state": "^6.0.0",
+ "@codemirror/view": "^6.35.0",
+ "crelt": "^1.0.5"
}
},
- "node_modules/@ibm/plex-serif": {
- "version": "1.1.0",
- "hasInstallScript": true,
- "license": "OFL-1.1",
+ "node_modules/@codemirror/rangeset": {
+ "version": "0.19.9",
+ "license": "MIT",
"dependencies": {
- "@ibm/telemetry-js": "^1.6.1"
- }
- },
- "node_modules/@ibm/telemetry-js": {
- "version": "1.11.0",
- "license": "Apache-2.0",
- "bin": {
- "ibmtelemetry": "dist/collect.js"
+ "@codemirror/state": "^0.19.0"
}
},
- "node_modules/@internationalized/number": {
- "version": "3.6.5",
- "license": "Apache-2.0",
+ "node_modules/@codemirror/rangeset/node_modules/@codemirror/state": {
+ "version": "0.19.9",
+ "license": "MIT",
"dependencies": {
- "@swc/helpers": "^0.5.0"
+ "@codemirror/text": "^0.19.0"
}
},
- "node_modules/@isaacs/cliui": {
- "version": "8.0.2",
- "license": "ISC",
+ "node_modules/@codemirror/search": {
+ "version": "6.6.0",
+ "license": "MIT",
"dependencies": {
- "string-width": "^5.1.2",
- "string-width-cjs": "npm:string-width@^4.2.0",
- "strip-ansi": "^7.0.1",
- "strip-ansi-cjs": "npm:strip-ansi@^6.0.1",
- "wrap-ansi": "^8.1.0",
- "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0"
- },
- "engines": {
- "node": ">=12"
+ "@codemirror/state": "^6.0.0",
+ "@codemirror/view": "^6.37.0",
+ "crelt": "^1.0.5"
}
},
- "node_modules/@isaacs/cliui/node_modules/string-width": {
- "version": "5.1.2",
+ "node_modules/@codemirror/state": {
+ "version": "6.5.4",
"license": "MIT",
"dependencies": {
- "eastasianwidth": "^0.2.0",
- "emoji-regex": "^9.2.2",
- "strip-ansi": "^7.0.1"
- },
- "engines": {
- "node": ">=12"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
+ "@marijn/find-cluster-break": "^1.0.0"
}
},
- "node_modules/@isaacs/cliui/node_modules/string-width/node_modules/emoji-regex": {
- "version": "9.2.2",
+ "node_modules/@codemirror/text": {
+ "version": "0.19.6",
"license": "MIT"
},
- "node_modules/@isaacs/cliui/node_modules/strip-ansi": {
- "version": "7.1.2",
+ "node_modules/@codemirror/view": {
+ "version": "6.39.15",
"license": "MIT",
"dependencies": {
- "ansi-regex": "^6.0.1"
- },
- "engines": {
- "node": ">=12"
- },
- "funding": {
- "url": "https://github.com/chalk/strip-ansi?sponsor=1"
+ "@codemirror/state": "^6.5.0",
+ "crelt": "^1.0.6",
+ "style-mod": "^4.1.0",
+ "w3c-keyname": "^2.2.4"
}
},
- "node_modules/@isaacs/cliui/node_modules/strip-ansi/node_modules/ansi-regex": {
- "version": "6.2.2",
- "license": "MIT",
+ "node_modules/@esbuild/aix-ppc64": {
+ "version": "0.27.3",
+ "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.3.tgz",
+ "integrity": "sha512-9fJMTNFTWZMh5qwrBItuziu834eOCUcEqymSH7pY+zoMVEZg3gcPuBNxH1EvfVYe9h0x/Ptw8KBzv7qxb7l8dg==",
+ "cpu": [
+ "ppc64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "aix"
+ ],
"engines": {
- "node": ">=12"
- },
- "funding": {
- "url": "https://github.com/chalk/ansi-regex?sponsor=1"
+ "node": ">=18"
}
},
- "node_modules/@isaacs/cliui/node_modules/wrap-ansi": {
- "version": "8.1.0",
- "license": "MIT",
- "dependencies": {
- "ansi-styles": "^6.1.0",
- "string-width": "^5.0.1",
- "strip-ansi": "^7.0.1"
- },
+ "node_modules/@esbuild/android-arm": {
+ "version": "0.27.3",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.27.3.tgz",
+ "integrity": "sha512-i5D1hPY7GIQmXlXhs2w8AWHhenb00+GxjxRncS2ZM7YNVGNfaMxgzSGuO8o8SJzRc/oZwU2bcScvVERk03QhzA==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "android"
+ ],
"engines": {
- "node": ">=12"
- },
- "funding": {
- "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
+ "node": ">=18"
}
},
- "node_modules/@isaacs/cliui/node_modules/wrap-ansi/node_modules/ansi-styles": {
- "version": "6.2.3",
- "license": "MIT",
+ "node_modules/@esbuild/android-arm64": {
+ "version": "0.27.3",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.27.3.tgz",
+ "integrity": "sha512-YdghPYUmj/FX2SYKJ0OZxf+iaKgMsKHVPF1MAq/P8WirnSpCStzKJFjOjzsW0QQ7oIAiccHdcqjbHmJxRb/dmg==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "android"
+ ],
"engines": {
- "node": ">=12"
- },
- "funding": {
- "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ "node": ">=18"
}
},
- "node_modules/@jridgewell/gen-mapping": {
- "version": "0.3.13",
+ "node_modules/@esbuild/android-x64": {
+ "version": "0.27.3",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.27.3.tgz",
+ "integrity": "sha512-IN/0BNTkHtk8lkOM8JWAYFg4ORxBkZQf9zXiEOfERX/CzxW3Vg1ewAhU7QSWQpVIzTW+b8Xy+lGzdYXV6UZObQ==",
+ "cpu": [
+ "x64"
+ ],
"dev": true,
- "license": "MIT",
- "dependencies": {
- "@jridgewell/sourcemap-codec": "^1.5.0",
- "@jridgewell/trace-mapping": "^0.3.24"
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=18"
}
},
- "node_modules/@jridgewell/remapping": {
- "version": "2.3.5",
+ "node_modules/@esbuild/darwin-arm64": {
+ "version": "0.27.3",
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.27.3.tgz",
+ "integrity": "sha512-Re491k7ByTVRy0t3EKWajdLIr0gz2kKKfzafkth4Q8A5n1xTHrkqZgLLjFEHVD+AXdUGgQMq+Godfq45mGpCKg==",
+ "cpu": [
+ "arm64"
+ ],
"dev": true,
- "license": "MIT",
- "dependencies": {
- "@jridgewell/gen-mapping": "^0.3.5",
- "@jridgewell/trace-mapping": "^0.3.24"
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">=18"
}
},
- "node_modules/@jridgewell/resolve-uri": {
- "version": "3.1.2",
+ "node_modules/@esbuild/darwin-x64": {
+ "version": "0.27.3",
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.27.3.tgz",
+ "integrity": "sha512-vHk/hA7/1AckjGzRqi6wbo+jaShzRowYip6rt6q7VYEDX4LEy1pZfDpdxCBnGtl+A5zq8iXDcyuxwtv3hNtHFg==",
+ "cpu": [
+ "x64"
+ ],
"dev": true,
- "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
"engines": {
- "node": ">=6.0.0"
+ "node": ">=18"
}
},
- "node_modules/@jridgewell/sourcemap-codec": {
- "version": "1.5.5",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/@jridgewell/trace-mapping": {
- "version": "0.3.31",
+ "node_modules/@esbuild/freebsd-arm64": {
+ "version": "0.27.3",
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.3.tgz",
+ "integrity": "sha512-ipTYM2fjt3kQAYOvo6vcxJx3nBYAzPjgTCk7QEgZG8AUO3ydUhvelmhrbOheMnGOlaSFUoHXB6un+A7q4ygY9w==",
+ "cpu": [
+ "arm64"
+ ],
"dev": true,
- "license": "MIT",
- "dependencies": {
- "@jridgewell/resolve-uri": "^3.1.0",
- "@jridgewell/sourcemap-codec": "^1.4.14"
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">=18"
}
},
- "node_modules/@one-ini/wasm": {
- "version": "0.1.1",
- "license": "MIT"
- },
- "node_modules/@parcel/watcher": {
- "version": "2.5.6",
- "hasInstallScript": true,
- "license": "MIT",
+ "node_modules/@esbuild/freebsd-x64": {
+ "version": "0.27.3",
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.27.3.tgz",
+ "integrity": "sha512-dDk0X87T7mI6U3K9VjWtHOXqwAMJBNN2r7bejDsc+j03SEjtD9HrOl8gVFByeM0aJksoUuUVU9TBaZa2rgj0oA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
"optional": true,
- "dependencies": {
- "detect-libc": "^2.0.3",
- "is-glob": "^4.0.3",
- "node-addon-api": "^7.0.0",
- "picomatch": "^4.0.3"
- },
+ "os": [
+ "freebsd"
+ ],
"engines": {
- "node": ">= 10.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/parcel"
- },
- "optionalDependencies": {
- "@parcel/watcher-android-arm64": "2.5.6",
- "@parcel/watcher-darwin-arm64": "2.5.6",
- "@parcel/watcher-darwin-x64": "2.5.6",
- "@parcel/watcher-freebsd-x64": "2.5.6",
- "@parcel/watcher-linux-arm-glibc": "2.5.6",
- "@parcel/watcher-linux-arm-musl": "2.5.6",
- "@parcel/watcher-linux-arm64-glibc": "2.5.6",
- "@parcel/watcher-linux-arm64-musl": "2.5.6",
- "@parcel/watcher-linux-x64-glibc": "2.5.6",
- "@parcel/watcher-linux-x64-musl": "2.5.6",
- "@parcel/watcher-win32-arm64": "2.5.6",
- "@parcel/watcher-win32-ia32": "2.5.6",
- "@parcel/watcher-win32-x64": "2.5.6"
+ "node": ">=18"
}
},
- "node_modules/@parcel/watcher-darwin-arm64": {
- "version": "2.5.6",
+ "node_modules/@esbuild/linux-arm": {
+ "version": "0.27.3",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.27.3.tgz",
+ "integrity": "sha512-s6nPv2QkSupJwLYyfS+gwdirm0ukyTFNl3KTgZEAiJDd+iHZcbTPPcWCcRYH+WlNbwChgH2QkE9NSlNrMT8Gfw==",
"cpu": [
- "arm64"
+ "arm"
],
- "license": "MIT",
+ "dev": true,
"optional": true,
"os": [
- "darwin"
+ "linux"
],
"engines": {
- "node": ">= 10.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/parcel"
+ "node": ">=18"
}
},
- "node_modules/@pkgjs/parseargs": {
- "version": "0.11.0",
- "license": "MIT",
+ "node_modules/@esbuild/linux-arm64": {
+ "version": "0.27.3",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.27.3.tgz",
+ "integrity": "sha512-sZOuFz/xWnZ4KH3YfFrKCf1WyPZHakVzTiqji3WDc0BCl2kBwiJLCXpzLzUBLgmp4veFZdvN5ChW4Eq/8Fc2Fg==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
"optional": true,
+ "os": [
+ "linux"
+ ],
"engines": {
- "node": ">=14"
+ "node": ">=18"
}
},
- "node_modules/@rolldown/pluginutils": {
- "version": "1.0.0-beta.27",
+ "node_modules/@esbuild/linux-ia32": {
+ "version": "0.27.3",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.27.3.tgz",
+ "integrity": "sha512-yGlQYjdxtLdh0a3jHjuwOrxQjOZYD/C9PfdbgJJF3TIZWnm/tMd/RcNiLngiu4iwcBAOezdnSLAwQDPqTmtTYg==",
+ "cpu": [
+ "ia32"
+ ],
"dev": true,
- "license": "MIT"
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
},
- "node_modules/@rollup/rollup-darwin-arm64": {
- "version": "4.57.0",
+ "node_modules/@esbuild/linux-loong64": {
+ "version": "0.27.3",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.27.3.tgz",
+ "integrity": "sha512-WO60Sn8ly3gtzhyjATDgieJNet/KqsDlX5nRC5Y3oTFcS1l0KWba+SEa9Ja1GfDqSF1z6hif/SkpQJbL63cgOA==",
"cpu": [
- "arm64"
+ "loong64"
],
"dev": true,
- "license": "MIT",
"optional": true,
"os": [
- "darwin"
- ]
- },
- "node_modules/@swc/helpers": {
- "version": "0.5.18",
- "license": "Apache-2.0",
- "dependencies": {
- "tslib": "^2.8.0"
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
}
},
- "node_modules/@types/babel__core": {
- "version": "7.20.5",
+ "node_modules/@esbuild/linux-mips64el": {
+ "version": "0.27.3",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.27.3.tgz",
+ "integrity": "sha512-APsymYA6sGcZ4pD6k+UxbDjOFSvPWyZhjaiPyl/f79xKxwTnrn5QUnXR5prvetuaSMsb4jgeHewIDCIWljrSxw==",
+ "cpu": [
+ "mips64el"
+ ],
"dev": true,
- "license": "MIT",
- "dependencies": {
- "@babel/parser": "^7.20.7",
- "@babel/types": "^7.20.7",
- "@types/babel__generator": "*",
- "@types/babel__template": "*",
- "@types/babel__traverse": "*"
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
}
},
- "node_modules/@types/babel__generator": {
- "version": "7.27.0",
+ "node_modules/@esbuild/linux-ppc64": {
+ "version": "0.27.3",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.27.3.tgz",
+ "integrity": "sha512-eizBnTeBefojtDb9nSh4vvVQ3V9Qf9Df01PfawPcRzJH4gFSgrObw+LveUyDoKU3kxi5+9RJTCWlj4FjYXVPEA==",
+ "cpu": [
+ "ppc64"
+ ],
"dev": true,
- "license": "MIT",
- "dependencies": {
- "@babel/types": "^7.0.0"
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
}
},
- "node_modules/@types/babel__template": {
- "version": "7.4.4",
+ "node_modules/@esbuild/linux-riscv64": {
+ "version": "0.27.3",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.27.3.tgz",
+ "integrity": "sha512-3Emwh0r5wmfm3ssTWRQSyVhbOHvqegUDRd0WhmXKX2mkHJe1SFCMJhagUleMq+Uci34wLSipf8Lagt4LlpRFWQ==",
+ "cpu": [
+ "riscv64"
+ ],
"dev": true,
- "license": "MIT",
- "dependencies": {
- "@babel/parser": "^7.1.0",
- "@babel/types": "^7.0.0"
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
}
},
- "node_modules/@types/babel__traverse": {
- "version": "7.28.0",
+ "node_modules/@esbuild/linux-s390x": {
+ "version": "0.27.3",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.27.3.tgz",
+ "integrity": "sha512-pBHUx9LzXWBc7MFIEEL0yD/ZVtNgLytvx60gES28GcWMqil8ElCYR4kvbV2BDqsHOvVDRrOxGySBM9Fcv744hw==",
+ "cpu": [
+ "s390x"
+ ],
"dev": true,
- "license": "MIT",
- "dependencies": {
- "@babel/types": "^7.28.2"
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
}
},
- "node_modules/@types/estree": {
- "version": "1.0.8",
+ "node_modules/@esbuild/linux-x64": {
+ "version": "0.27.3",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.27.3.tgz",
+ "integrity": "sha512-Czi8yzXUWIQYAtL/2y6vogER8pvcsOsk5cpwL4Gk5nJqH5UZiVByIY8Eorm5R13gq+DQKYg0+JyQoytLQas4dA==",
+ "cpu": [
+ "x64"
+ ],
"dev": true,
- "license": "MIT"
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
},
- "node_modules/@types/prop-types": {
- "version": "15.7.15",
+ "node_modules/@esbuild/netbsd-arm64": {
+ "version": "0.27.3",
+ "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.3.tgz",
+ "integrity": "sha512-sDpk0RgmTCR/5HguIZa9n9u+HVKf40fbEUt+iTzSnCaGvY9kFP0YKBWZtJaraonFnqef5SlJ8/TiPAxzyS+UoA==",
+ "cpu": [
+ "arm64"
+ ],
"dev": true,
- "license": "MIT"
+ "optional": true,
+ "os": [
+ "netbsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
},
- "node_modules/@types/react": {
- "version": "18.3.27",
+ "node_modules/@esbuild/netbsd-x64": {
+ "version": "0.27.3",
+ "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.27.3.tgz",
+ "integrity": "sha512-P14lFKJl/DdaE00LItAukUdZO5iqNH7+PjoBm+fLQjtxfcfFE20Xf5CrLsmZdq5LFFZzb5JMZ9grUwvtVYzjiA==",
+ "cpu": [
+ "x64"
+ ],
"dev": true,
- "license": "MIT",
- "dependencies": {
- "@types/prop-types": "*",
- "csstype": "^3.2.2"
+ "optional": true,
+ "os": [
+ "netbsd"
+ ],
+ "engines": {
+ "node": ">=18"
}
},
- "node_modules/@types/react-dom": {
- "version": "18.3.7",
+ "node_modules/@esbuild/openbsd-arm64": {
+ "version": "0.27.3",
+ "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.3.tgz",
+ "integrity": "sha512-AIcMP77AvirGbRl/UZFTq5hjXK+2wC7qFRGoHSDrZ5v5b8DK/GYpXW3CPRL53NkvDqb9D+alBiC/dV0Fb7eJcw==",
+ "cpu": [
+ "arm64"
+ ],
"dev": true,
- "license": "MIT",
- "peerDependencies": {
- "@types/react": "^18.0.0"
+ "optional": true,
+ "os": [
+ "openbsd"
+ ],
+ "engines": {
+ "node": ">=18"
}
},
- "node_modules/@vitejs/plugin-react": {
- "version": "4.7.0",
+ "node_modules/@esbuild/openbsd-x64": {
+ "version": "0.27.3",
+ "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.27.3.tgz",
+ "integrity": "sha512-DnW2sRrBzA+YnE70LKqnM3P+z8vehfJWHXECbwBmH/CU51z6FiqTQTHFenPlHmo3a8UgpLyH3PT+87OViOh1AQ==",
+ "cpu": [
+ "x64"
+ ],
"dev": true,
- "license": "MIT",
- "dependencies": {
- "@babel/core": "^7.28.0",
- "@babel/plugin-transform-react-jsx-self": "^7.27.1",
- "@babel/plugin-transform-react-jsx-source": "^7.27.1",
- "@rolldown/pluginutils": "1.0.0-beta.27",
- "@types/babel__core": "^7.20.5",
- "react-refresh": "^0.17.0"
- },
+ "optional": true,
+ "os": [
+ "openbsd"
+ ],
"engines": {
- "node": "^14.18.0 || >=16.0.0"
- },
- "peerDependencies": {
- "vite": "^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0"
+ "node": ">=18"
}
},
- "node_modules/@wailsio/runtime": {
- "version": "3.0.0-alpha.79",
- "license": "MIT"
- },
- "node_modules/abbrev": {
- "version": "2.0.0",
- "license": "ISC",
+ "node_modules/@esbuild/openharmony-arm64": {
+ "version": "0.27.3",
+ "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.3.tgz",
+ "integrity": "sha512-NinAEgr/etERPTsZJ7aEZQvvg/A6IsZG/LgZy+81wON2huV7SrK3e63dU0XhyZP4RKGyTm7aOgmQk0bGp0fy2g==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "openharmony"
+ ],
"engines": {
- "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
+ "node": ">=18"
}
},
- "node_modules/ansi-regex": {
- "version": "5.0.1",
- "license": "MIT",
+ "node_modules/@esbuild/sunos-x64": {
+ "version": "0.27.3",
+ "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.27.3.tgz",
+ "integrity": "sha512-PanZ+nEz+eWoBJ8/f8HKxTTD172SKwdXebZ0ndd953gt1HRBbhMsaNqjTyYLGLPdoWHy4zLU7bDVJztF5f3BHA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "sunos"
+ ],
"engines": {
- "node": ">=8"
+ "node": ">=18"
}
},
- "node_modules/ansi-styles": {
- "version": "4.3.0",
- "license": "MIT",
- "dependencies": {
- "color-convert": "^2.0.1"
- },
+ "node_modules/@esbuild/win32-arm64": {
+ "version": "0.27.3",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.27.3.tgz",
+ "integrity": "sha512-B2t59lWWYrbRDw/tjiWOuzSsFh1Y/E95ofKz7rIVYSQkUYBjfSgf6oeYPNWHToFRr2zx52JKApIcAS/D5TUBnA==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "win32"
+ ],
"engines": {
- "node": ">=8"
- },
- "funding": {
- "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ "node": ">=18"
}
},
- "node_modules/argparse": {
- "version": "2.0.1",
- "license": "Python-2.0"
- },
- "node_modules/balanced-match": {
- "version": "1.0.2",
- "license": "MIT"
+ "node_modules/@esbuild/win32-ia32": {
+ "version": "0.27.3",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.27.3.tgz",
+ "integrity": "sha512-QLKSFeXNS8+tHW7tZpMtjlNb7HKau0QDpwm49u0vUp9y1WOF+PEzkU84y9GqYaAVW8aH8f3GcBck26jh54cX4Q==",
+ "cpu": [
+ "ia32"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
},
- "node_modules/baseline-browser-mapping": {
- "version": "2.9.19",
+ "node_modules/@esbuild/win32-x64": {
+ "version": "0.27.3",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.27.3.tgz",
+ "integrity": "sha512-4uJGhsxuptu3OcpVAzli+/gWusVGwZZHTlS63hh++ehExkVT8SgiEf7/uC/PclrPPkLhZqGgCTjd0VWLo6xMqA==",
+ "cpu": [
+ "x64"
+ ],
"dev": true,
- "license": "Apache-2.0",
- "bin": {
- "baseline-browser-mapping": "dist/cli.js"
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=18"
}
},
- "node_modules/brace-expansion": {
- "version": "2.0.2",
+ "node_modules/@floating-ui/core": {
+ "version": "1.7.4",
"license": "MIT",
"dependencies": {
- "balanced-match": "^1.0.0"
+ "@floating-ui/utils": "^0.2.10"
}
},
- "node_modules/browserslist": {
- "version": "4.28.1",
- "dev": true,
- "funding": [
- {
- "type": "opencollective",
- "url": "https://opencollective.com/browserslist"
- },
- {
- "type": "tidelift",
- "url": "https://tidelift.com/funding/github/npm/browserslist"
- },
- {
- "type": "github",
- "url": "https://github.com/sponsors/ai"
- }
- ],
+ "node_modules/@floating-ui/dom": {
+ "version": "1.7.5",
"license": "MIT",
"dependencies": {
- "baseline-browser-mapping": "^2.9.0",
- "caniuse-lite": "^1.0.30001759",
- "electron-to-chromium": "^1.5.263",
- "node-releases": "^2.0.27",
- "update-browserslist-db": "^1.2.0"
- },
- "bin": {
- "browserslist": "cli.js"
- },
- "engines": {
- "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"
+ "@floating-ui/core": "^1.7.4",
+ "@floating-ui/utils": "^0.2.10"
}
},
- "node_modules/camelcase": {
- "version": "5.3.1",
+ "node_modules/@floating-ui/react": {
+ "version": "0.27.17",
"license": "MIT",
- "engines": {
- "node": ">=6"
+ "dependencies": {
+ "@floating-ui/react-dom": "^2.1.7",
+ "@floating-ui/utils": "^0.2.10",
+ "tabbable": "^6.0.0"
+ },
+ "peerDependencies": {
+ "react": ">=17.0.0",
+ "react-dom": ">=17.0.0"
}
},
- "node_modules/caniuse-lite": {
- "version": "1.0.30001766",
- "dev": true,
- "funding": [
- {
- "type": "opencollective",
- "url": "https://opencollective.com/browserslist"
- },
- {
- "type": "tidelift",
- "url": "https://tidelift.com/funding/github/npm/caniuse-lite"
- },
- {
- "type": "github",
- "url": "https://github.com/sponsors/ai"
- }
- ],
- "license": "CC-BY-4.0"
- },
- "node_modules/chokidar": {
- "version": "4.0.3",
+ "node_modules/@floating-ui/react-dom": {
+ "version": "2.1.7",
"license": "MIT",
"dependencies": {
- "readdirp": "^4.0.1"
- },
- "engines": {
- "node": ">= 14.16.0"
+ "@floating-ui/dom": "^1.7.5"
},
- "funding": {
- "url": "https://paulmillr.com/funding/"
+ "peerDependencies": {
+ "react": ">=16.8.0",
+ "react-dom": ">=16.8.0"
}
},
- "node_modules/classnames": {
- "version": "2.5.1",
+ "node_modules/@floating-ui/utils": {
+ "version": "0.2.10",
"license": "MIT"
},
- "node_modules/cliui": {
- "version": "6.0.0",
- "license": "ISC",
- "dependencies": {
- "string-width": "^4.2.0",
- "strip-ansi": "^6.0.0",
- "wrap-ansi": "^6.2.0"
+ "node_modules/@ibm/plex": {
+ "version": "6.0.0-next.6",
+ "license": "OFL-1.1",
+ "engines": {
+ "node": ">=14"
}
},
- "node_modules/color": {
- "version": "4.2.3",
- "license": "MIT",
+ "node_modules/@ibm/plex-mono": {
+ "version": "1.1.0",
+ "hasInstallScript": true,
+ "license": "OFL-1.1",
"dependencies": {
- "color-convert": "^2.0.1",
- "color-string": "^1.9.0"
- },
- "engines": {
- "node": ">=12.5.0"
+ "@ibm/telemetry-js": "^1.6.1"
}
},
- "node_modules/color-convert": {
- "version": "2.0.1",
- "license": "MIT",
+ "node_modules/@ibm/plex-sans": {
+ "version": "1.1.0",
+ "hasInstallScript": true,
+ "license": "OFL-1.1",
"dependencies": {
- "color-name": "~1.1.4"
- },
- "engines": {
- "node": ">=7.0.0"
+ "@ibm/telemetry-js": "^1.6.1"
}
},
- "node_modules/color-name": {
- "version": "1.1.4",
- "license": "MIT"
- },
- "node_modules/color-string": {
- "version": "1.9.1",
- "license": "MIT",
+ "node_modules/@ibm/plex-sans-arabic": {
+ "version": "1.1.0",
+ "hasInstallScript": true,
+ "license": "OFL-1.1",
"dependencies": {
- "color-name": "^1.0.0",
- "simple-swizzle": "^0.2.2"
+ "@ibm/telemetry-js": "^1.6.1"
}
},
- "node_modules/commander": {
- "version": "10.0.1",
- "license": "MIT",
- "engines": {
- "node": ">=14"
+ "node_modules/@ibm/plex-sans-devanagari": {
+ "version": "1.1.0",
+ "hasInstallScript": true,
+ "license": "OFL-1.1",
+ "dependencies": {
+ "@ibm/telemetry-js": "^1.6.1"
}
},
- "node_modules/compute-scroll-into-view": {
- "version": "3.1.1",
- "license": "MIT"
+ "node_modules/@ibm/plex-sans-hebrew": {
+ "version": "1.1.0",
+ "hasInstallScript": true,
+ "license": "OFL-1.1",
+ "dependencies": {
+ "@ibm/telemetry-js": "^1.6.1"
+ }
},
- "node_modules/config-chain": {
- "version": "1.1.13",
- "license": "MIT",
+ "node_modules/@ibm/plex-sans-thai": {
+ "version": "1.1.0",
+ "hasInstallScript": true,
+ "license": "OFL-1.1",
"dependencies": {
- "ini": "^1.3.4",
- "proto-list": "~1.2.1"
+ "@ibm/telemetry-js": "^1.6.1"
}
},
- "node_modules/convert-source-map": {
- "version": "2.0.0",
- "dev": true,
- "license": "MIT"
+ "node_modules/@ibm/plex-sans-thai-looped": {
+ "version": "1.1.0",
+ "hasInstallScript": true,
+ "license": "OFL-1.1",
+ "dependencies": {
+ "@ibm/telemetry-js": "^1.6.1"
+ }
},
- "node_modules/copy-to-clipboard": {
- "version": "3.3.3",
- "license": "MIT",
+ "node_modules/@ibm/plex-serif": {
+ "version": "1.1.0",
+ "hasInstallScript": true,
+ "license": "OFL-1.1",
"dependencies": {
- "toggle-selection": "^1.0.6"
+ "@ibm/telemetry-js": "^1.6.1"
}
},
- "node_modules/cronstrue": {
- "version": "3.9.0",
- "license": "MIT",
+ "node_modules/@ibm/telemetry-js": {
+ "version": "1.11.0",
+ "license": "Apache-2.0",
"bin": {
- "cronstrue": "bin/cli.js"
+ "ibmtelemetry": "dist/collect.js"
}
},
- "node_modules/cross-spawn": {
- "version": "7.0.6",
- "license": "MIT",
+ "node_modules/@internationalized/number": {
+ "version": "3.6.5",
+ "license": "Apache-2.0",
"dependencies": {
- "path-key": "^3.1.0",
- "shebang-command": "^2.0.0",
- "which": "^2.0.1"
+ "@swc/helpers": "^0.5.0"
+ }
+ },
+ "node_modules/@isaacs/cliui": {
+ "version": "8.0.2",
+ "license": "ISC",
+ "dependencies": {
+ "string-width": "^5.1.2",
+ "string-width-cjs": "npm:string-width@^4.2.0",
+ "strip-ansi": "^7.0.1",
+ "strip-ansi-cjs": "npm:strip-ansi@^6.0.1",
+ "wrap-ansi": "^8.1.0",
+ "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0"
},
"engines": {
- "node": ">= 8"
+ "node": ">=12"
}
},
- "node_modules/csstype": {
- "version": "3.2.3",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/debug": {
- "version": "4.4.3",
- "dev": true,
+ "node_modules/@isaacs/cliui/node_modules/string-width": {
+ "version": "5.1.2",
"license": "MIT",
"dependencies": {
- "ms": "^2.1.3"
+ "eastasianwidth": "^0.2.0",
+ "emoji-regex": "^9.2.2",
+ "strip-ansi": "^7.0.1"
},
"engines": {
- "node": ">=6.0"
+ "node": ">=12"
},
- "peerDependenciesMeta": {
- "supports-color": {
- "optional": true
- }
- }
- },
- "node_modules/decamelize": {
- "version": "1.2.0",
- "license": "MIT",
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/detect-libc": {
- "version": "2.1.2",
- "license": "Apache-2.0",
- "optional": true,
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/diff": {
- "version": "8.0.3",
- "license": "BSD-3-Clause",
- "engines": {
- "node": ">=0.3.1"
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
}
},
- "node_modules/dijkstrajs": {
- "version": "1.0.3",
- "license": "MIT"
- },
- "node_modules/discontinuous-range": {
- "version": "1.0.0",
+ "node_modules/@isaacs/cliui/node_modules/string-width/node_modules/emoji-regex": {
+ "version": "9.2.2",
"license": "MIT"
},
- "node_modules/downshift": {
- "version": "9.0.10",
+ "node_modules/@isaacs/cliui/node_modules/strip-ansi": {
+ "version": "7.1.2",
"license": "MIT",
"dependencies": {
- "@babel/runtime": "^7.24.5",
- "compute-scroll-into-view": "^3.1.0",
- "prop-types": "^15.8.1",
- "react-is": "18.2.0",
- "tslib": "^2.6.2"
+ "ansi-regex": "^6.0.1"
},
- "peerDependencies": {
- "react": ">=16.12.0"
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/strip-ansi?sponsor=1"
}
},
- "node_modules/downshift/node_modules/react-is": {
- "version": "18.2.0",
- "license": "MIT"
- },
- "node_modules/eastasianwidth": {
- "version": "0.2.0",
- "license": "MIT"
+ "node_modules/@isaacs/cliui/node_modules/strip-ansi/node_modules/ansi-regex": {
+ "version": "6.2.2",
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-regex?sponsor=1"
+ }
},
- "node_modules/editorconfig": {
- "version": "1.0.4",
+ "node_modules/@isaacs/cliui/node_modules/wrap-ansi": {
+ "version": "8.1.0",
"license": "MIT",
"dependencies": {
- "@one-ini/wasm": "0.1.1",
- "commander": "^10.0.0",
- "minimatch": "9.0.1",
- "semver": "^7.5.3"
- },
- "bin": {
- "editorconfig": "bin/editorconfig"
+ "ansi-styles": "^6.1.0",
+ "string-width": "^5.0.1",
+ "strip-ansi": "^7.0.1"
},
"engines": {
- "node": ">=14"
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
}
},
- "node_modules/editorconfig/node_modules/semver": {
- "version": "7.7.3",
- "license": "ISC",
- "bin": {
- "semver": "bin/semver.js"
- },
+ "node_modules/@isaacs/cliui/node_modules/wrap-ansi/node_modules/ansi-styles": {
+ "version": "6.2.3",
+ "license": "MIT",
"engines": {
- "node": ">=10"
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
}
},
- "node_modules/electron-to-chromium": {
- "version": "1.5.279",
+ "node_modules/@jridgewell/gen-mapping": {
+ "version": "0.3.13",
"dev": true,
- "license": "ISC"
- },
- "node_modules/emoji-regex": {
- "version": "8.0.0",
- "license": "MIT"
- },
- "node_modules/es-toolkit": {
- "version": "1.44.0",
"license": "MIT",
- "workspaces": [
- "docs",
- "benchmarks"
- ]
+ "dependencies": {
+ "@jridgewell/sourcemap-codec": "^1.5.0",
+ "@jridgewell/trace-mapping": "^0.3.24"
+ }
},
- "node_modules/esbuild": {
- "version": "0.21.5",
+ "node_modules/@jridgewell/remapping": {
+ "version": "2.3.5",
"dev": true,
- "hasInstallScript": true,
"license": "MIT",
- "bin": {
- "esbuild": "bin/esbuild"
- },
- "engines": {
- "node": ">=12"
- },
- "optionalDependencies": {
- "@esbuild/aix-ppc64": "0.21.5",
- "@esbuild/android-arm": "0.21.5",
- "@esbuild/android-arm64": "0.21.5",
- "@esbuild/android-x64": "0.21.5",
- "@esbuild/darwin-arm64": "0.21.5",
- "@esbuild/darwin-x64": "0.21.5",
- "@esbuild/freebsd-arm64": "0.21.5",
- "@esbuild/freebsd-x64": "0.21.5",
- "@esbuild/linux-arm": "0.21.5",
- "@esbuild/linux-arm64": "0.21.5",
- "@esbuild/linux-ia32": "0.21.5",
- "@esbuild/linux-loong64": "0.21.5",
- "@esbuild/linux-mips64el": "0.21.5",
- "@esbuild/linux-ppc64": "0.21.5",
- "@esbuild/linux-riscv64": "0.21.5",
- "@esbuild/linux-s390x": "0.21.5",
- "@esbuild/linux-x64": "0.21.5",
- "@esbuild/netbsd-x64": "0.21.5",
- "@esbuild/openbsd-x64": "0.21.5",
- "@esbuild/sunos-x64": "0.21.5",
- "@esbuild/win32-arm64": "0.21.5",
- "@esbuild/win32-ia32": "0.21.5",
- "@esbuild/win32-x64": "0.21.5"
+ "dependencies": {
+ "@jridgewell/gen-mapping": "^0.3.5",
+ "@jridgewell/trace-mapping": "^0.3.24"
}
},
- "node_modules/escalade": {
- "version": "3.2.0",
+ "node_modules/@jridgewell/resolve-uri": {
+ "version": "3.1.2",
"dev": true,
"license": "MIT",
"engines": {
- "node": ">=6"
+ "node": ">=6.0.0"
}
},
- "node_modules/find-up": {
- "version": "4.1.0",
+ "node_modules/@jridgewell/sourcemap-codec": {
+ "version": "1.5.5",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@jridgewell/trace-mapping": {
+ "version": "0.3.31",
+ "dev": true,
"license": "MIT",
"dependencies": {
- "locate-path": "^5.0.0",
- "path-exists": "^4.0.0"
- },
- "engines": {
- "node": ">=8"
+ "@jridgewell/resolve-uri": "^3.1.0",
+ "@jridgewell/sourcemap-codec": "^1.4.14"
}
},
- "node_modules/flatpickr": {
- "version": "4.6.13",
+ "node_modules/@lezer/common": {
+ "version": "1.5.1",
"license": "MIT"
},
- "node_modules/foreground-child": {
- "version": "3.3.1",
- "license": "ISC",
+ "node_modules/@lezer/css": {
+ "version": "1.3.1",
+ "license": "MIT",
"dependencies": {
- "cross-spawn": "^7.0.6",
- "signal-exit": "^4.0.1"
- },
- "engines": {
- "node": ">=14"
- },
- "funding": {
- "url": "https://github.com/sponsors/isaacs"
+ "@lezer/common": "^1.2.0",
+ "@lezer/highlight": "^1.0.0",
+ "@lezer/lr": "^1.3.0"
}
},
- "node_modules/fsevents": {
- "version": "2.3.3",
- "dev": true,
+ "node_modules/@lezer/highlight": {
+ "version": "1.2.3",
"license": "MIT",
- "optional": true,
- "os": [
- "darwin"
- ],
- "engines": {
- "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
+ "dependencies": {
+ "@lezer/common": "^1.3.0"
}
},
- "node_modules/gensync": {
- "version": "1.0.0-beta.2",
- "dev": true,
+ "node_modules/@lezer/html": {
+ "version": "1.3.13",
"license": "MIT",
- "engines": {
- "node": ">=6.9.0"
+ "dependencies": {
+ "@lezer/common": "^1.2.0",
+ "@lezer/highlight": "^1.0.0",
+ "@lezer/lr": "^1.0.0"
}
},
- "node_modules/get-caller-file": {
- "version": "2.0.5",
- "license": "ISC",
- "engines": {
- "node": "6.* || 8.* || >= 10.*"
+ "node_modules/@lezer/java": {
+ "version": "1.1.3",
+ "license": "MIT",
+ "dependencies": {
+ "@lezer/common": "^1.2.0",
+ "@lezer/highlight": "^1.0.0",
+ "@lezer/lr": "^1.0.0"
}
},
- "node_modules/glob": {
- "version": "10.5.0",
- "license": "ISC",
+ "node_modules/@lezer/javascript": {
+ "version": "1.5.4",
+ "license": "MIT",
"dependencies": {
- "foreground-child": "^3.1.0",
- "jackspeak": "^3.1.2",
- "minimatch": "^9.0.4",
- "minipass": "^7.1.2",
- "package-json-from-dist": "^1.0.0",
- "path-scurry": "^1.11.1"
- },
- "bin": {
- "glob": "dist/esm/bin.mjs"
- },
- "funding": {
- "url": "https://github.com/sponsors/isaacs"
+ "@lezer/common": "^1.2.0",
+ "@lezer/highlight": "^1.1.3",
+ "@lezer/lr": "^1.3.0"
}
},
- "node_modules/glob/node_modules/minimatch": {
- "version": "9.0.5",
- "license": "ISC",
+ "node_modules/@lezer/json": {
+ "version": "1.0.3",
+ "license": "MIT",
"dependencies": {
- "brace-expansion": "^2.0.1"
- },
- "engines": {
- "node": ">=16 || 14 >=14.17"
- },
- "funding": {
- "url": "https://github.com/sponsors/isaacs"
+ "@lezer/common": "^1.2.0",
+ "@lezer/highlight": "^1.0.0",
+ "@lezer/lr": "^1.0.0"
}
},
- "node_modules/immutable": {
- "version": "5.1.4",
- "license": "MIT"
- },
- "node_modules/ini": {
- "version": "1.3.8",
- "license": "ISC"
- },
- "node_modules/invariant": {
- "version": "2.2.4",
+ "node_modules/@lezer/lr": {
+ "version": "1.4.8",
"license": "MIT",
"dependencies": {
- "loose-envify": "^1.0.0"
+ "@lezer/common": "^1.0.0"
}
},
- "node_modules/is-arrayish": {
- "version": "0.3.4",
- "license": "MIT"
- },
- "node_modules/is-extglob": {
- "version": "2.1.1",
+ "node_modules/@lezer/xml": {
+ "version": "1.0.6",
"license": "MIT",
- "optional": true,
- "engines": {
- "node": ">=0.10.0"
+ "dependencies": {
+ "@lezer/common": "^1.2.0",
+ "@lezer/highlight": "^1.0.0",
+ "@lezer/lr": "^1.0.0"
}
},
- "node_modules/is-fullwidth-code-point": {
- "version": "3.0.0",
- "license": "MIT",
- "engines": {
- "node": ">=8"
- }
+ "node_modules/@marijn/find-cluster-break": {
+ "version": "1.0.2",
+ "license": "MIT"
},
- "node_modules/is-glob": {
- "version": "4.0.3",
+ "node_modules/@one-ini/wasm": {
+ "version": "0.1.1",
+ "license": "MIT"
+ },
+ "node_modules/@parcel/watcher": {
+ "version": "2.5.6",
+ "hasInstallScript": true,
"license": "MIT",
"optional": true,
"dependencies": {
- "is-extglob": "^2.1.1"
+ "detect-libc": "^2.0.3",
+ "is-glob": "^4.0.3",
+ "node-addon-api": "^7.0.0",
+ "picomatch": "^4.0.3"
},
"engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/isexe": {
- "version": "2.0.0",
- "license": "ISC"
- },
- "node_modules/jackspeak": {
- "version": "3.4.3",
- "license": "BlueOak-1.0.0",
- "dependencies": {
- "@isaacs/cliui": "^8.0.2"
+ "node": ">= 10.0.0"
},
"funding": {
- "url": "https://github.com/sponsors/isaacs"
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
},
"optionalDependencies": {
- "@pkgjs/parseargs": "^0.11.0"
+ "@parcel/watcher-android-arm64": "2.5.6",
+ "@parcel/watcher-darwin-arm64": "2.5.6",
+ "@parcel/watcher-darwin-x64": "2.5.6",
+ "@parcel/watcher-freebsd-x64": "2.5.6",
+ "@parcel/watcher-linux-arm-glibc": "2.5.6",
+ "@parcel/watcher-linux-arm-musl": "2.5.6",
+ "@parcel/watcher-linux-arm64-glibc": "2.5.6",
+ "@parcel/watcher-linux-arm64-musl": "2.5.6",
+ "@parcel/watcher-linux-x64-glibc": "2.5.6",
+ "@parcel/watcher-linux-x64-musl": "2.5.6",
+ "@parcel/watcher-win32-arm64": "2.5.6",
+ "@parcel/watcher-win32-ia32": "2.5.6",
+ "@parcel/watcher-win32-x64": "2.5.6"
}
},
- "node_modules/js-beautify": {
- "version": "1.15.4",
+ "node_modules/@parcel/watcher-darwin-arm64": {
+ "version": "2.5.6",
+ "cpu": [
+ "arm64"
+ ],
"license": "MIT",
- "dependencies": {
- "config-chain": "^1.1.13",
- "editorconfig": "^1.0.4",
- "glob": "^10.4.2",
- "js-cookie": "^3.0.5",
- "nopt": "^7.2.1"
- },
- "bin": {
- "css-beautify": "js/bin/css-beautify.js",
- "html-beautify": "js/bin/html-beautify.js",
- "js-beautify": "js/bin/js-beautify.js"
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">= 10.0.0"
},
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/@pkgjs/parseargs": {
+ "version": "0.11.0",
+ "license": "MIT",
+ "optional": true,
"engines": {
"node": ">=14"
}
},
- "node_modules/js-cookie": {
- "version": "3.0.5",
+ "node_modules/@remix-run/router": {
+ "version": "1.23.2",
"license": "MIT",
"engines": {
- "node": ">=14"
+ "node": ">=14.0.0"
}
},
- "node_modules/js-tokens": {
- "version": "4.0.0",
+ "node_modules/@rolldown/pluginutils": {
+ "version": "1.0.0-beta.27",
+ "dev": true,
"license": "MIT"
},
- "node_modules/js-yaml": {
- "version": "4.1.1",
+ "node_modules/@rollup/rollup-darwin-arm64": {
+ "version": "4.57.0",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
"license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ]
+ },
+ "node_modules/@swc/helpers": {
+ "version": "0.5.18",
+ "license": "Apache-2.0",
"dependencies": {
- "argparse": "^2.0.1"
- },
- "bin": {
- "js-yaml": "bin/js-yaml.js"
+ "tslib": "^2.8.0"
}
},
- "node_modules/jsesc": {
- "version": "3.1.0",
+ "node_modules/@types/babel__core": {
+ "version": "7.20.5",
"dev": true,
"license": "MIT",
- "bin": {
- "jsesc": "bin/jsesc"
- },
- "engines": {
- "node": ">=6"
+ "dependencies": {
+ "@babel/parser": "^7.20.7",
+ "@babel/types": "^7.20.7",
+ "@types/babel__generator": "*",
+ "@types/babel__template": "*",
+ "@types/babel__traverse": "*"
}
},
- "node_modules/json5": {
- "version": "2.2.3",
+ "node_modules/@types/babel__generator": {
+ "version": "7.27.0",
"dev": true,
"license": "MIT",
- "bin": {
- "json5": "lib/cli.js"
- },
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/jwt-decode": {
- "version": "4.0.0",
- "license": "MIT",
- "engines": {
- "node": ">=18"
+ "dependencies": {
+ "@babel/types": "^7.0.0"
}
},
- "node_modules/locate-path": {
- "version": "5.0.0",
+ "node_modules/@types/babel__template": {
+ "version": "7.4.4",
+ "dev": true,
"license": "MIT",
"dependencies": {
- "p-locate": "^4.1.0"
- },
- "engines": {
- "node": ">=8"
+ "@babel/parser": "^7.1.0",
+ "@babel/types": "^7.0.0"
}
},
- "node_modules/loose-envify": {
- "version": "1.4.0",
+ "node_modules/@types/babel__traverse": {
+ "version": "7.28.0",
+ "dev": true,
"license": "MIT",
"dependencies": {
- "js-tokens": "^3.0.0 || ^4.0.0"
- },
- "bin": {
- "loose-envify": "cli.js"
+ "@babel/types": "^7.28.2"
}
},
- "node_modules/lru-cache": {
- "version": "5.1.1",
+ "node_modules/@types/estree": {
+ "version": "1.0.8",
"dev": true,
- "license": "ISC",
+ "license": "MIT"
+ },
+ "node_modules/@types/prop-types": {
+ "version": "15.7.15",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@types/react": {
+ "version": "18.3.27",
+ "dev": true,
+ "license": "MIT",
"dependencies": {
- "yallist": "^3.0.2"
+ "@types/prop-types": "*",
+ "csstype": "^3.2.2"
}
},
- "node_modules/marked": {
- "version": "17.0.1",
+ "node_modules/@types/react-dom": {
+ "version": "18.3.7",
+ "dev": true,
"license": "MIT",
- "bin": {
- "marked": "bin/marked.js"
- },
- "engines": {
- "node": ">= 20"
+ "peerDependencies": {
+ "@types/react": "^18.0.0"
}
},
- "node_modules/minimatch": {
- "version": "9.0.1",
- "license": "ISC",
+ "node_modules/@vitejs/plugin-react": {
+ "version": "4.7.0",
+ "dev": true,
+ "license": "MIT",
"dependencies": {
- "brace-expansion": "^2.0.1"
+ "@babel/core": "^7.28.0",
+ "@babel/plugin-transform-react-jsx-self": "^7.27.1",
+ "@babel/plugin-transform-react-jsx-source": "^7.27.1",
+ "@rolldown/pluginutils": "1.0.0-beta.27",
+ "@types/babel__core": "^7.20.5",
+ "react-refresh": "^0.17.0"
},
"engines": {
- "node": ">=16 || 14 >=14.17"
+ "node": "^14.18.0 || >=16.0.0"
},
- "funding": {
- "url": "https://github.com/sponsors/isaacs"
+ "peerDependencies": {
+ "vite": "^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0"
}
},
- "node_modules/minipass": {
- "version": "7.1.2",
+ "node_modules/@wailsio/runtime": {
+ "version": "3.0.0-alpha.79",
+ "license": "MIT"
+ },
+ "node_modules/abbrev": {
+ "version": "2.0.0",
"license": "ISC",
"engines": {
- "node": ">=16 || 14 >=14.17"
+ "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
}
},
- "node_modules/moo": {
- "version": "0.5.2",
- "license": "BSD-3-Clause"
- },
- "node_modules/ms": {
- "version": "2.1.3",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/nanoid": {
- "version": "3.3.11",
- "dev": true,
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/ai"
- }
- ],
+ "node_modules/ansi-regex": {
+ "version": "5.0.1",
"license": "MIT",
- "bin": {
- "nanoid": "bin/nanoid.cjs"
- },
"engines": {
- "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
+ "node": ">=8"
}
},
- "node_modules/nearley": {
- "version": "2.20.1",
+ "node_modules/ansi-styles": {
+ "version": "4.3.0",
"license": "MIT",
"dependencies": {
- "commander": "^2.19.0",
- "moo": "^0.5.0",
- "railroad-diagrams": "^1.0.0",
- "randexp": "0.4.6"
+ "color-convert": "^2.0.1"
},
- "bin": {
- "nearley-railroad": "bin/nearley-railroad.js",
- "nearley-test": "bin/nearley-test.js",
- "nearley-unparse": "bin/nearley-unparse.js",
- "nearleyc": "bin/nearleyc.js"
+ "engines": {
+ "node": ">=8"
},
"funding": {
- "type": "individual",
- "url": "https://nearley.js.org/#give-to-nearley"
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
}
},
- "node_modules/nearley/node_modules/commander": {
- "version": "2.20.3",
+ "node_modules/argparse": {
+ "version": "2.0.1",
+ "license": "Python-2.0"
+ },
+ "node_modules/balanced-match": {
+ "version": "1.0.2",
"license": "MIT"
},
- "node_modules/node-addon-api": {
- "version": "7.1.1",
+ "node_modules/baseline-browser-mapping": {
+ "version": "2.9.19",
+ "dev": true,
+ "license": "Apache-2.0",
+ "bin": {
+ "baseline-browser-mapping": "dist/cli.js"
+ }
+ },
+ "node_modules/brace-expansion": {
+ "version": "2.0.2",
"license": "MIT",
- "optional": true
+ "dependencies": {
+ "balanced-match": "^1.0.0"
+ }
},
- "node_modules/node-releases": {
- "version": "2.0.27",
+ "node_modules/browserslist": {
+ "version": "4.28.1",
"dev": true,
- "license": "MIT"
- },
- "node_modules/nopt": {
- "version": "7.2.1",
- "license": "ISC",
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/browserslist"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/browserslist"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "MIT",
"dependencies": {
- "abbrev": "^2.0.0"
+ "baseline-browser-mapping": "^2.9.0",
+ "caniuse-lite": "^1.0.30001759",
+ "electron-to-chromium": "^1.5.263",
+ "node-releases": "^2.0.27",
+ "update-browserslist-db": "^1.2.0"
},
"bin": {
- "nopt": "bin/nopt.js"
+ "browserslist": "cli.js"
},
"engines": {
- "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
+ "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"
}
},
- "node_modules/object-assign": {
- "version": "4.1.1",
+ "node_modules/camelcase": {
+ "version": "5.3.1",
"license": "MIT",
"engines": {
- "node": ">=0.10.0"
+ "node": ">=6"
}
},
- "node_modules/p-limit": {
- "version": "2.3.0",
+ "node_modules/caniuse-lite": {
+ "version": "1.0.30001766",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/browserslist"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/caniuse-lite"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "CC-BY-4.0"
+ },
+ "node_modules/chokidar": {
+ "version": "4.0.3",
"license": "MIT",
"dependencies": {
- "p-try": "^2.0.0"
+ "readdirp": "^4.0.1"
},
"engines": {
- "node": ">=6"
+ "node": ">= 14.16.0"
},
"funding": {
- "url": "https://github.com/sponsors/sindresorhus"
+ "url": "https://paulmillr.com/funding/"
}
},
- "node_modules/p-locate": {
- "version": "4.1.0",
+ "node_modules/classnames": {
+ "version": "2.5.1",
+ "license": "MIT"
+ },
+ "node_modules/cliui": {
+ "version": "6.0.0",
+ "license": "ISC",
+ "dependencies": {
+ "string-width": "^4.2.0",
+ "strip-ansi": "^6.0.0",
+ "wrap-ansi": "^6.2.0"
+ }
+ },
+ "node_modules/codemirror": {
+ "version": "6.0.2",
"license": "MIT",
"dependencies": {
- "p-limit": "^2.2.0"
+ "@codemirror/autocomplete": "^6.0.0",
+ "@codemirror/commands": "^6.0.0",
+ "@codemirror/language": "^6.0.0",
+ "@codemirror/lint": "^6.0.0",
+ "@codemirror/search": "^6.0.0",
+ "@codemirror/state": "^6.0.0",
+ "@codemirror/view": "^6.0.0"
+ }
+ },
+ "node_modules/color": {
+ "version": "4.2.3",
+ "license": "MIT",
+ "dependencies": {
+ "color-convert": "^2.0.1",
+ "color-string": "^1.9.0"
},
"engines": {
- "node": ">=8"
+ "node": ">=12.5.0"
}
},
- "node_modules/p-try": {
- "version": "2.2.0",
+ "node_modules/color-convert": {
+ "version": "2.0.1",
"license": "MIT",
+ "dependencies": {
+ "color-name": "~1.1.4"
+ },
"engines": {
- "node": ">=6"
+ "node": ">=7.0.0"
}
},
- "node_modules/package-json-from-dist": {
- "version": "1.0.1",
- "license": "BlueOak-1.0.0"
- },
- "node_modules/papaparse": {
- "version": "5.5.3",
+ "node_modules/color-name": {
+ "version": "1.1.4",
"license": "MIT"
},
- "node_modules/path-exists": {
- "version": "4.0.0",
+ "node_modules/color-string": {
+ "version": "1.9.1",
"license": "MIT",
- "engines": {
- "node": ">=8"
+ "dependencies": {
+ "color-name": "^1.0.0",
+ "simple-swizzle": "^0.2.2"
}
},
- "node_modules/path-key": {
- "version": "3.1.1",
+ "node_modules/commander": {
+ "version": "10.0.1",
"license": "MIT",
"engines": {
- "node": ">=8"
+ "node": ">=14"
}
},
- "node_modules/path-scurry": {
- "version": "1.11.1",
- "license": "BlueOak-1.0.0",
+ "node_modules/compute-scroll-into-view": {
+ "version": "3.1.1",
+ "license": "MIT"
+ },
+ "node_modules/config-chain": {
+ "version": "1.1.13",
+ "license": "MIT",
"dependencies": {
- "lru-cache": "^10.2.0",
- "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0"
- },
- "engines": {
- "node": ">=16 || 14 >=14.18"
- },
- "funding": {
- "url": "https://github.com/sponsors/isaacs"
+ "ini": "^1.3.4",
+ "proto-list": "~1.2.1"
}
},
- "node_modules/path-scurry/node_modules/lru-cache": {
- "version": "10.4.3",
- "license": "ISC"
+ "node_modules/convert-source-map": {
+ "version": "2.0.0",
+ "dev": true,
+ "license": "MIT"
},
- "node_modules/php-serialize": {
- "version": "5.1.3",
+ "node_modules/copy-to-clipboard": {
+ "version": "3.3.3",
"license": "MIT",
- "engines": {
- "node": ">= 8"
+ "dependencies": {
+ "toggle-selection": "^1.0.6"
}
},
- "node_modules/picocolors": {
- "version": "1.1.1",
- "dev": true,
- "license": "ISC"
+ "node_modules/crelt": {
+ "version": "1.0.6",
+ "license": "MIT"
},
- "node_modules/picomatch": {
- "version": "4.0.3",
+ "node_modules/cronstrue": {
+ "version": "3.9.0",
"license": "MIT",
- "optional": true,
- "engines": {
- "node": ">=12"
- },
- "funding": {
- "url": "https://github.com/sponsors/jonschlinkert"
+ "bin": {
+ "cronstrue": "bin/cli.js"
}
},
- "node_modules/pngjs": {
- "version": "5.0.0",
+ "node_modules/cross-spawn": {
+ "version": "7.0.6",
"license": "MIT",
+ "dependencies": {
+ "path-key": "^3.1.0",
+ "shebang-command": "^2.0.0",
+ "which": "^2.0.1"
+ },
"engines": {
- "node": ">=10.13.0"
+ "node": ">= 8"
}
},
- "node_modules/postcss": {
- "version": "8.5.6",
+ "node_modules/csstype": {
+ "version": "3.2.3",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/debug": {
+ "version": "4.4.3",
"dev": true,
- "funding": [
- {
- "type": "opencollective",
- "url": "https://opencollective.com/postcss/"
- },
- {
- "type": "tidelift",
- "url": "https://tidelift.com/funding/github/npm/postcss"
- },
- {
- "type": "github",
- "url": "https://github.com/sponsors/ai"
- }
- ],
"license": "MIT",
"dependencies": {
- "nanoid": "^3.3.11",
- "picocolors": "^1.1.1",
- "source-map-js": "^1.2.1"
+ "ms": "^2.1.3"
},
"engines": {
- "node": "^10 || ^12 || >=14"
+ "node": ">=6.0"
+ },
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
}
},
- "node_modules/prettier": {
- "version": "3.8.1",
- "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.8.1.tgz",
- "integrity": "sha512-UOnG6LftzbdaHZcKoPFtOcCKztrQ57WkHDeRD9t/PTQtmT0NHSeWWepj6pS0z/N7+08BHFDQVUrfmfMRcZwbMg==",
- "dev": true,
- "bin": {
- "prettier": "bin/prettier.cjs"
- },
+ "node_modules/decamelize": {
+ "version": "1.2.0",
+ "license": "MIT",
"engines": {
- "node": ">=14"
- },
- "funding": {
- "url": "https://github.com/prettier/prettier?sponsor=1"
+ "node": ">=0.10.0"
}
},
- "node_modules/prop-types": {
- "version": "15.8.1",
+ "node_modules/detect-libc": {
+ "version": "2.1.2",
+ "license": "Apache-2.0",
+ "optional": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/diff": {
+ "version": "8.0.3",
+ "license": "BSD-3-Clause",
+ "engines": {
+ "node": ">=0.3.1"
+ }
+ },
+ "node_modules/dijkstrajs": {
+ "version": "1.0.3",
+ "license": "MIT"
+ },
+ "node_modules/discontinuous-range": {
+ "version": "1.0.0",
+ "license": "MIT"
+ },
+ "node_modules/downshift": {
+ "version": "9.0.10",
"license": "MIT",
"dependencies": {
- "loose-envify": "^1.4.0",
- "object-assign": "^4.1.1",
- "react-is": "^16.13.1"
+ "@babel/runtime": "^7.24.5",
+ "compute-scroll-into-view": "^3.1.0",
+ "prop-types": "^15.8.1",
+ "react-is": "18.2.0",
+ "tslib": "^2.6.2"
+ },
+ "peerDependencies": {
+ "react": ">=16.12.0"
}
},
- "node_modules/proto-list": {
- "version": "1.2.4",
- "license": "ISC"
+ "node_modules/downshift/node_modules/react-is": {
+ "version": "18.2.0",
+ "license": "MIT"
},
- "node_modules/qrcode": {
- "version": "1.5.4",
+ "node_modules/eastasianwidth": {
+ "version": "0.2.0",
+ "license": "MIT"
+ },
+ "node_modules/editorconfig": {
+ "version": "1.0.4",
"license": "MIT",
"dependencies": {
- "dijkstrajs": "^1.0.1",
- "pngjs": "^5.0.0",
- "yargs": "^15.3.1"
+ "@one-ini/wasm": "0.1.1",
+ "commander": "^10.0.0",
+ "minimatch": "9.0.1",
+ "semver": "^7.5.3"
},
"bin": {
- "qrcode": "bin/qrcode"
+ "editorconfig": "bin/editorconfig"
},
"engines": {
- "node": ">=10.13.0"
+ "node": ">=14"
}
},
- "node_modules/railroad-diagrams": {
- "version": "1.0.0",
- "license": "CC0-1.0"
+ "node_modules/editorconfig/node_modules/semver": {
+ "version": "7.7.3",
+ "license": "ISC",
+ "bin": {
+ "semver": "bin/semver.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
},
- "node_modules/randexp": {
- "version": "0.4.6",
+ "node_modules/electron-to-chromium": {
+ "version": "1.5.279",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/emoji-regex": {
+ "version": "8.0.0",
+ "license": "MIT"
+ },
+ "node_modules/es-toolkit": {
+ "version": "1.44.0",
"license": "MIT",
- "dependencies": {
- "discontinuous-range": "1.0.0",
- "ret": "~0.1.10"
+ "workspaces": [
+ "docs",
+ "benchmarks"
+ ]
+ },
+ "node_modules/esbuild": {
+ "version": "0.27.3",
+ "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.3.tgz",
+ "integrity": "sha512-8VwMnyGCONIs6cWue2IdpHxHnAjzxnw2Zr7MkVxB2vjmQ2ivqGFb4LEG3SMnv0Gb2F/G/2yA8zUaiL1gywDCCg==",
+ "dev": true,
+ "hasInstallScript": true,
+ "bin": {
+ "esbuild": "bin/esbuild"
},
"engines": {
- "node": ">=0.12"
+ "node": ">=18"
+ },
+ "optionalDependencies": {
+ "@esbuild/aix-ppc64": "0.27.3",
+ "@esbuild/android-arm": "0.27.3",
+ "@esbuild/android-arm64": "0.27.3",
+ "@esbuild/android-x64": "0.27.3",
+ "@esbuild/darwin-arm64": "0.27.3",
+ "@esbuild/darwin-x64": "0.27.3",
+ "@esbuild/freebsd-arm64": "0.27.3",
+ "@esbuild/freebsd-x64": "0.27.3",
+ "@esbuild/linux-arm": "0.27.3",
+ "@esbuild/linux-arm64": "0.27.3",
+ "@esbuild/linux-ia32": "0.27.3",
+ "@esbuild/linux-loong64": "0.27.3",
+ "@esbuild/linux-mips64el": "0.27.3",
+ "@esbuild/linux-ppc64": "0.27.3",
+ "@esbuild/linux-riscv64": "0.27.3",
+ "@esbuild/linux-s390x": "0.27.3",
+ "@esbuild/linux-x64": "0.27.3",
+ "@esbuild/netbsd-arm64": "0.27.3",
+ "@esbuild/netbsd-x64": "0.27.3",
+ "@esbuild/openbsd-arm64": "0.27.3",
+ "@esbuild/openbsd-x64": "0.27.3",
+ "@esbuild/openharmony-arm64": "0.27.3",
+ "@esbuild/sunos-x64": "0.27.3",
+ "@esbuild/win32-arm64": "0.27.3",
+ "@esbuild/win32-ia32": "0.27.3",
+ "@esbuild/win32-x64": "0.27.3"
}
},
- "node_modules/react": {
- "version": "18.3.1",
+ "node_modules/escalade": {
+ "version": "3.2.0",
+ "dev": true,
"license": "MIT",
- "dependencies": {
- "loose-envify": "^1.1.0"
- },
"engines": {
- "node": ">=0.10.0"
+ "node": ">=6"
}
},
- "node_modules/react-dom": {
- "version": "18.3.1",
+ "node_modules/find-up": {
+ "version": "4.1.0",
"license": "MIT",
"dependencies": {
- "loose-envify": "^1.1.0",
- "scheduler": "^0.23.2"
+ "locate-path": "^5.0.0",
+ "path-exists": "^4.0.0"
},
- "peerDependencies": {
- "react": "^18.3.1"
+ "engines": {
+ "node": ">=8"
}
},
- "node_modules/react-fast-compare": {
- "version": "3.2.2",
- "license": "MIT"
- },
- "node_modules/react-is": {
- "version": "16.13.1",
+ "node_modules/flatpickr": {
+ "version": "4.6.13",
"license": "MIT"
},
- "node_modules/react-refresh": {
- "version": "0.17.0",
- "dev": true,
- "license": "MIT",
+ "node_modules/foreground-child": {
+ "version": "3.3.1",
+ "license": "ISC",
+ "dependencies": {
+ "cross-spawn": "^7.0.6",
+ "signal-exit": "^4.0.1"
+ },
"engines": {
- "node": ">=0.10.0"
+ "node": ">=14"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
}
},
- "node_modules/readdirp": {
- "version": "4.1.2",
+ "node_modules/fsevents": {
+ "version": "2.3.3",
+ "dev": true,
"license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
"engines": {
- "node": ">= 14.18.0"
- },
- "funding": {
- "type": "individual",
- "url": "https://paulmillr.com/funding/"
+ "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
}
},
- "node_modules/require-directory": {
- "version": "2.1.1",
+ "node_modules/gensync": {
+ "version": "1.0.0-beta.2",
+ "dev": true,
"license": "MIT",
"engines": {
- "node": ">=0.10.0"
+ "node": ">=6.9.0"
}
},
- "node_modules/require-main-filename": {
- "version": "2.0.0",
- "license": "ISC"
- },
- "node_modules/ret": {
- "version": "0.1.15",
- "license": "MIT",
+ "node_modules/get-caller-file": {
+ "version": "2.0.5",
+ "license": "ISC",
"engines": {
- "node": ">=0.12"
+ "node": "6.* || 8.* || >= 10.*"
}
},
- "node_modules/rollup": {
- "version": "4.57.0",
- "dev": true,
- "license": "MIT",
+ "node_modules/glob": {
+ "version": "10.5.0",
+ "license": "ISC",
"dependencies": {
- "@types/estree": "1.0.8"
+ "foreground-child": "^3.1.0",
+ "jackspeak": "^3.1.2",
+ "minimatch": "^9.0.4",
+ "minipass": "^7.1.2",
+ "package-json-from-dist": "^1.0.0",
+ "path-scurry": "^1.11.1"
},
"bin": {
- "rollup": "dist/bin/rollup"
- },
- "engines": {
- "node": ">=18.0.0",
- "npm": ">=8.0.0"
+ "glob": "dist/esm/bin.mjs"
},
- "optionalDependencies": {
- "@rollup/rollup-android-arm-eabi": "4.57.0",
- "@rollup/rollup-android-arm64": "4.57.0",
- "@rollup/rollup-darwin-arm64": "4.57.0",
- "@rollup/rollup-darwin-x64": "4.57.0",
- "@rollup/rollup-freebsd-arm64": "4.57.0",
- "@rollup/rollup-freebsd-x64": "4.57.0",
- "@rollup/rollup-linux-arm-gnueabihf": "4.57.0",
- "@rollup/rollup-linux-arm-musleabihf": "4.57.0",
- "@rollup/rollup-linux-arm64-gnu": "4.57.0",
- "@rollup/rollup-linux-arm64-musl": "4.57.0",
- "@rollup/rollup-linux-loong64-gnu": "4.57.0",
- "@rollup/rollup-linux-loong64-musl": "4.57.0",
- "@rollup/rollup-linux-ppc64-gnu": "4.57.0",
- "@rollup/rollup-linux-ppc64-musl": "4.57.0",
- "@rollup/rollup-linux-riscv64-gnu": "4.57.0",
- "@rollup/rollup-linux-riscv64-musl": "4.57.0",
- "@rollup/rollup-linux-s390x-gnu": "4.57.0",
- "@rollup/rollup-linux-x64-gnu": "4.57.0",
- "@rollup/rollup-linux-x64-musl": "4.57.0",
- "@rollup/rollup-openbsd-x64": "4.57.0",
- "@rollup/rollup-openharmony-arm64": "4.57.0",
- "@rollup/rollup-win32-arm64-msvc": "4.57.0",
- "@rollup/rollup-win32-ia32-msvc": "4.57.0",
- "@rollup/rollup-win32-x64-gnu": "4.57.0",
- "@rollup/rollup-win32-x64-msvc": "4.57.0",
- "fsevents": "~2.3.2"
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
}
},
- "node_modules/sass": {
- "version": "1.97.3",
- "license": "MIT",
+ "node_modules/glob/node_modules/minimatch": {
+ "version": "9.0.5",
+ "license": "ISC",
"dependencies": {
- "chokidar": "^4.0.0",
- "immutable": "^5.0.2",
- "source-map-js": ">=0.6.2 <2.0.0"
- },
- "bin": {
- "sass": "sass.js"
+ "brace-expansion": "^2.0.1"
},
"engines": {
- "node": ">=14.0.0"
+ "node": ">=16 || 14 >=14.17"
},
- "optionalDependencies": {
- "@parcel/watcher": "^2.4.1"
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
}
},
- "node_modules/scheduler": {
- "version": "0.23.2",
+ "node_modules/immutable": {
+ "version": "5.1.4",
+ "license": "MIT"
+ },
+ "node_modules/ini": {
+ "version": "1.3.8",
+ "license": "ISC"
+ },
+ "node_modules/invariant": {
+ "version": "2.2.4",
"license": "MIT",
"dependencies": {
- "loose-envify": "^1.1.0"
- }
- },
- "node_modules/semver": {
- "version": "6.3.1",
- "dev": true,
- "license": "ISC",
- "bin": {
- "semver": "bin/semver.js"
+ "loose-envify": "^1.0.0"
}
},
- "node_modules/set-blocking": {
- "version": "2.0.0",
- "license": "ISC"
+ "node_modules/is-arrayish": {
+ "version": "0.3.4",
+ "license": "MIT"
},
- "node_modules/shebang-command": {
- "version": "2.0.0",
+ "node_modules/is-extglob": {
+ "version": "2.1.1",
"license": "MIT",
- "dependencies": {
- "shebang-regex": "^3.0.0"
- },
+ "optional": true,
"engines": {
- "node": ">=8"
+ "node": ">=0.10.0"
}
},
- "node_modules/shebang-regex": {
+ "node_modules/is-fullwidth-code-point": {
"version": "3.0.0",
"license": "MIT",
"engines": {
"node": ">=8"
}
},
- "node_modules/signal-exit": {
- "version": "4.1.0",
- "license": "ISC",
+ "node_modules/is-glob": {
+ "version": "4.0.3",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "is-extglob": "^2.1.1"
+ },
"engines": {
- "node": ">=14"
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/isexe": {
+ "version": "2.0.0",
+ "license": "ISC"
+ },
+ "node_modules/jackspeak": {
+ "version": "3.4.3",
+ "license": "BlueOak-1.0.0",
+ "dependencies": {
+ "@isaacs/cliui": "^8.0.2"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
+ },
+ "optionalDependencies": {
+ "@pkgjs/parseargs": "^0.11.0"
}
},
- "node_modules/simple-swizzle": {
- "version": "0.2.4",
+ "node_modules/js-beautify": {
+ "version": "1.15.4",
"license": "MIT",
"dependencies": {
- "is-arrayish": "^0.3.1"
+ "config-chain": "^1.1.13",
+ "editorconfig": "^1.0.4",
+ "glob": "^10.4.2",
+ "js-cookie": "^3.0.5",
+ "nopt": "^7.2.1"
+ },
+ "bin": {
+ "css-beautify": "js/bin/css-beautify.js",
+ "html-beautify": "js/bin/html-beautify.js",
+ "js-beautify": "js/bin/js-beautify.js"
+ },
+ "engines": {
+ "node": ">=14"
}
},
- "node_modules/source-map-js": {
- "version": "1.2.1",
- "license": "BSD-3-Clause",
+ "node_modules/js-cookie": {
+ "version": "3.0.5",
+ "license": "MIT",
"engines": {
- "node": ">=0.10.0"
+ "node": ">=14"
}
},
- "node_modules/sql-formatter": {
- "version": "15.7.0",
+ "node_modules/js-tokens": {
+ "version": "4.0.0",
+ "license": "MIT"
+ },
+ "node_modules/js-yaml": {
+ "version": "4.1.1",
"license": "MIT",
"dependencies": {
- "argparse": "^2.0.1",
- "nearley": "^2.20.1"
+ "argparse": "^2.0.1"
},
"bin": {
- "sql-formatter": "bin/sql-formatter-cli.cjs"
+ "js-yaml": "bin/js-yaml.js"
}
},
- "node_modules/string-width": {
- "version": "4.2.3",
+ "node_modules/jsesc": {
+ "version": "3.1.0",
+ "dev": true,
"license": "MIT",
- "dependencies": {
- "emoji-regex": "^8.0.0",
- "is-fullwidth-code-point": "^3.0.0",
- "strip-ansi": "^6.0.1"
+ "bin": {
+ "jsesc": "bin/jsesc"
},
"engines": {
- "node": ">=8"
+ "node": ">=6"
}
},
- "node_modules/string-width-cjs": {
- "name": "string-width",
- "version": "4.2.3",
+ "node_modules/json5": {
+ "version": "2.2.3",
+ "dev": true,
"license": "MIT",
- "dependencies": {
- "emoji-regex": "^8.0.0",
- "is-fullwidth-code-point": "^3.0.0",
- "strip-ansi": "^6.0.1"
+ "bin": {
+ "json5": "lib/cli.js"
},
"engines": {
- "node": ">=8"
+ "node": ">=6"
}
},
- "node_modules/strip-ansi": {
- "version": "6.0.1",
+ "node_modules/jwt-decode": {
+ "version": "4.0.0",
"license": "MIT",
- "dependencies": {
- "ansi-regex": "^5.0.1"
- },
"engines": {
- "node": ">=8"
+ "node": ">=18"
}
},
- "node_modules/strip-ansi-cjs": {
- "name": "strip-ansi",
- "version": "6.0.1",
+ "node_modules/locate-path": {
+ "version": "5.0.0",
"license": "MIT",
"dependencies": {
- "ansi-regex": "^5.0.1"
+ "p-locate": "^4.1.0"
},
"engines": {
"node": ">=8"
}
},
- "node_modules/tabbable": {
- "version": "6.4.0",
- "license": "MIT"
- },
- "node_modules/toggle-selection": {
- "version": "1.0.6",
- "license": "MIT"
- },
- "node_modules/tslib": {
- "version": "2.8.1",
- "license": "0BSD"
- },
- "node_modules/ulid": {
- "version": "3.0.2",
+ "node_modules/loose-envify": {
+ "version": "1.4.0",
"license": "MIT",
+ "dependencies": {
+ "js-tokens": "^3.0.0 || ^4.0.0"
+ },
"bin": {
- "ulid": "dist/cli.js"
+ "loose-envify": "cli.js"
}
},
- "node_modules/update-browserslist-db": {
- "version": "1.2.3",
+ "node_modules/lru-cache": {
+ "version": "5.1.1",
"dev": true,
- "funding": [
- {
- "type": "opencollective",
- "url": "https://opencollective.com/browserslist"
- },
- {
- "type": "tidelift",
- "url": "https://tidelift.com/funding/github/npm/browserslist"
- },
- {
- "type": "github",
- "url": "https://github.com/sponsors/ai"
- }
- ],
- "license": "MIT",
+ "license": "ISC",
"dependencies": {
- "escalade": "^3.2.0",
- "picocolors": "^1.1.1"
- },
- "bin": {
- "update-browserslist-db": "cli.js"
- },
- "peerDependencies": {
- "browserslist": ">= 4.21.0"
+ "yallist": "^3.0.2"
}
},
- "node_modules/vite": {
- "version": "5.4.21",
- "dev": true,
+ "node_modules/marked": {
+ "version": "17.0.1",
"license": "MIT",
- "dependencies": {
- "esbuild": "^0.21.3",
- "postcss": "^8.4.43",
- "rollup": "^4.20.0"
- },
"bin": {
- "vite": "bin/vite.js"
+ "marked": "bin/marked.js"
},
"engines": {
- "node": "^18.0.0 || >=20.0.0"
+ "node": ">= 20"
+ }
+ },
+ "node_modules/minimatch": {
+ "version": "9.0.1",
+ "license": "ISC",
+ "dependencies": {
+ "brace-expansion": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=16 || 14 >=14.17"
},
"funding": {
- "url": "https://github.com/vitejs/vite?sponsor=1"
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/minipass": {
+ "version": "7.1.2",
+ "license": "ISC",
+ "engines": {
+ "node": ">=16 || 14 >=14.17"
+ }
+ },
+ "node_modules/moo": {
+ "version": "0.5.2",
+ "license": "BSD-3-Clause"
+ },
+ "node_modules/ms": {
+ "version": "2.1.3",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/nanoid": {
+ "version": "3.3.11",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "MIT",
+ "bin": {
+ "nanoid": "bin/nanoid.cjs"
},
- "optionalDependencies": {
- "fsevents": "~2.3.3"
+ "engines": {
+ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
+ }
+ },
+ "node_modules/nearley": {
+ "version": "2.20.1",
+ "license": "MIT",
+ "dependencies": {
+ "commander": "^2.19.0",
+ "moo": "^0.5.0",
+ "railroad-diagrams": "^1.0.0",
+ "randexp": "0.4.6"
},
- "peerDependencies": {
- "@types/node": "^18.0.0 || >=20.0.0",
- "less": "*",
- "lightningcss": "^1.21.0",
- "sass": "*",
- "sass-embedded": "*",
- "stylus": "*",
- "sugarss": "*",
- "terser": "^5.4.0"
+ "bin": {
+ "nearley-railroad": "bin/nearley-railroad.js",
+ "nearley-test": "bin/nearley-test.js",
+ "nearley-unparse": "bin/nearley-unparse.js",
+ "nearleyc": "bin/nearleyc.js"
},
- "peerDependenciesMeta": {
- "@types/node": {
- "optional": true
- },
- "less": {
- "optional": true
- },
- "lightningcss": {
- "optional": true
- },
- "sass": {
- "optional": true
- },
- "sass-embedded": {
- "optional": true
- },
- "stylus": {
- "optional": true
+ "funding": {
+ "type": "individual",
+ "url": "https://nearley.js.org/#give-to-nearley"
+ }
+ },
+ "node_modules/nearley/node_modules/commander": {
+ "version": "2.20.3",
+ "license": "MIT"
+ },
+ "node_modules/node-addon-api": {
+ "version": "7.1.1",
+ "license": "MIT",
+ "optional": true
+ },
+ "node_modules/node-releases": {
+ "version": "2.0.27",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/nopt": {
+ "version": "7.2.1",
+ "license": "ISC",
+ "dependencies": {
+ "abbrev": "^2.0.0"
+ },
+ "bin": {
+ "nopt": "bin/nopt.js"
+ },
+ "engines": {
+ "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
+ }
+ },
+ "node_modules/object-assign": {
+ "version": "4.1.1",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/p-limit": {
+ "version": "2.3.0",
+ "license": "MIT",
+ "dependencies": {
+ "p-try": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/p-locate": {
+ "version": "4.1.0",
+ "license": "MIT",
+ "dependencies": {
+ "p-limit": "^2.2.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/p-try": {
+ "version": "2.2.0",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/package-json-from-dist": {
+ "version": "1.0.1",
+ "license": "BlueOak-1.0.0"
+ },
+ "node_modules/papaparse": {
+ "version": "5.5.3",
+ "license": "MIT"
+ },
+ "node_modules/path-exists": {
+ "version": "4.0.0",
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/path-key": {
+ "version": "3.1.1",
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/path-scurry": {
+ "version": "1.11.1",
+ "license": "BlueOak-1.0.0",
+ "dependencies": {
+ "lru-cache": "^10.2.0",
+ "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0"
+ },
+ "engines": {
+ "node": ">=16 || 14 >=14.18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/path-scurry/node_modules/lru-cache": {
+ "version": "10.4.3",
+ "license": "ISC"
+ },
+ "node_modules/php-serialize": {
+ "version": "5.1.3",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/picocolors": {
+ "version": "1.1.1",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/picomatch": {
+ "version": "4.0.3",
+ "license": "MIT",
+ "optional": true,
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/jonschlinkert"
+ }
+ },
+ "node_modules/pngjs": {
+ "version": "5.0.0",
+ "license": "MIT",
+ "engines": {
+ "node": ">=10.13.0"
+ }
+ },
+ "node_modules/postcss": {
+ "version": "8.5.6",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/postcss/"
},
- "sugarss": {
- "optional": true
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/postcss"
},
- "terser": {
- "optional": true
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
}
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "nanoid": "^3.3.11",
+ "picocolors": "^1.1.1",
+ "source-map-js": "^1.2.1"
+ },
+ "engines": {
+ "node": "^10 || ^12 || >=14"
}
},
+ "node_modules/prettier": {
+ "version": "3.8.1",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "prettier": "bin/prettier.cjs"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "funding": {
+ "url": "https://github.com/prettier/prettier?sponsor=1"
+ }
+ },
+ "node_modules/prop-types": {
+ "version": "15.8.1",
+ "license": "MIT",
+ "dependencies": {
+ "loose-envify": "^1.4.0",
+ "object-assign": "^4.1.1",
+ "react-is": "^16.13.1"
+ }
+ },
+ "node_modules/proto-list": {
+ "version": "1.2.4",
+ "license": "ISC"
+ },
+ "node_modules/qrcode": {
+ "version": "1.5.4",
+ "license": "MIT",
+ "dependencies": {
+ "dijkstrajs": "^1.0.1",
+ "pngjs": "^5.0.0",
+ "yargs": "^15.3.1"
+ },
+ "bin": {
+ "qrcode": "bin/qrcode"
+ },
+ "engines": {
+ "node": ">=10.13.0"
+ }
+ },
+ "node_modules/railroad-diagrams": {
+ "version": "1.0.0",
+ "license": "CC0-1.0"
+ },
+ "node_modules/randexp": {
+ "version": "0.4.6",
+ "license": "MIT",
+ "dependencies": {
+ "discontinuous-range": "1.0.0",
+ "ret": "~0.1.10"
+ },
+ "engines": {
+ "node": ">=0.12"
+ }
+ },
+ "node_modules/react": {
+ "version": "18.3.1",
+ "license": "MIT",
+ "dependencies": {
+ "loose-envify": "^1.1.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/react-dom": {
+ "version": "18.3.1",
+ "license": "MIT",
+ "dependencies": {
+ "loose-envify": "^1.1.0",
+ "scheduler": "^0.23.2"
+ },
+ "peerDependencies": {
+ "react": "^18.3.1"
+ }
+ },
+ "node_modules/react-fast-compare": {
+ "version": "3.2.2",
+ "license": "MIT"
+ },
+ "node_modules/react-is": {
+ "version": "16.13.1",
+ "license": "MIT"
+ },
+ "node_modules/react-refresh": {
+ "version": "0.17.0",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/react-router": {
+ "version": "6.30.3",
+ "license": "MIT",
+ "dependencies": {
+ "@remix-run/router": "1.23.2"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ },
+ "peerDependencies": {
+ "react": ">=16.8"
+ }
+ },
+ "node_modules/react-router-dom": {
+ "version": "6.30.3",
+ "license": "MIT",
+ "dependencies": {
+ "@remix-run/router": "1.23.2",
+ "react-router": "6.30.3"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ },
+ "peerDependencies": {
+ "react": ">=16.8",
+ "react-dom": ">=16.8"
+ }
+ },
+ "node_modules/readdirp": {
+ "version": "4.1.2",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 14.18.0"
+ },
+ "funding": {
+ "type": "individual",
+ "url": "https://paulmillr.com/funding/"
+ }
+ },
+ "node_modules/require-directory": {
+ "version": "2.1.1",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/require-main-filename": {
+ "version": "2.0.0",
+ "license": "ISC"
+ },
+ "node_modules/ret": {
+ "version": "0.1.15",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.12"
+ }
+ },
+ "node_modules/rollup": {
+ "version": "4.57.0",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/estree": "1.0.8"
+ },
+ "bin": {
+ "rollup": "dist/bin/rollup"
+ },
+ "engines": {
+ "node": ">=18.0.0",
+ "npm": ">=8.0.0"
+ },
+ "optionalDependencies": {
+ "@rollup/rollup-android-arm-eabi": "4.57.0",
+ "@rollup/rollup-android-arm64": "4.57.0",
+ "@rollup/rollup-darwin-arm64": "4.57.0",
+ "@rollup/rollup-darwin-x64": "4.57.0",
+ "@rollup/rollup-freebsd-arm64": "4.57.0",
+ "@rollup/rollup-freebsd-x64": "4.57.0",
+ "@rollup/rollup-linux-arm-gnueabihf": "4.57.0",
+ "@rollup/rollup-linux-arm-musleabihf": "4.57.0",
+ "@rollup/rollup-linux-arm64-gnu": "4.57.0",
+ "@rollup/rollup-linux-arm64-musl": "4.57.0",
+ "@rollup/rollup-linux-loong64-gnu": "4.57.0",
+ "@rollup/rollup-linux-loong64-musl": "4.57.0",
+ "@rollup/rollup-linux-ppc64-gnu": "4.57.0",
+ "@rollup/rollup-linux-ppc64-musl": "4.57.0",
+ "@rollup/rollup-linux-riscv64-gnu": "4.57.0",
+ "@rollup/rollup-linux-riscv64-musl": "4.57.0",
+ "@rollup/rollup-linux-s390x-gnu": "4.57.0",
+ "@rollup/rollup-linux-x64-gnu": "4.57.0",
+ "@rollup/rollup-linux-x64-musl": "4.57.0",
+ "@rollup/rollup-openbsd-x64": "4.57.0",
+ "@rollup/rollup-openharmony-arm64": "4.57.0",
+ "@rollup/rollup-win32-arm64-msvc": "4.57.0",
+ "@rollup/rollup-win32-ia32-msvc": "4.57.0",
+ "@rollup/rollup-win32-x64-gnu": "4.57.0",
+ "@rollup/rollup-win32-x64-msvc": "4.57.0",
+ "fsevents": "~2.3.2"
+ }
+ },
+ "node_modules/sass": {
+ "version": "1.97.3",
+ "license": "MIT",
+ "dependencies": {
+ "chokidar": "^4.0.0",
+ "immutable": "^5.0.2",
+ "source-map-js": ">=0.6.2 <2.0.0"
+ },
+ "bin": {
+ "sass": "sass.js"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ },
+ "optionalDependencies": {
+ "@parcel/watcher": "^2.4.1"
+ }
+ },
+ "node_modules/scheduler": {
+ "version": "0.23.2",
+ "license": "MIT",
+ "dependencies": {
+ "loose-envify": "^1.1.0"
+ }
+ },
+ "node_modules/semver": {
+ "version": "6.3.1",
+ "dev": true,
+ "license": "ISC",
+ "bin": {
+ "semver": "bin/semver.js"
+ }
+ },
+ "node_modules/set-blocking": {
+ "version": "2.0.0",
+ "license": "ISC"
+ },
+ "node_modules/shebang-command": {
+ "version": "2.0.0",
+ "license": "MIT",
+ "dependencies": {
+ "shebang-regex": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/shebang-regex": {
+ "version": "3.0.0",
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/signal-exit": {
+ "version": "4.1.0",
+ "license": "ISC",
+ "engines": {
+ "node": ">=14"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/simple-swizzle": {
+ "version": "0.2.4",
+ "license": "MIT",
+ "dependencies": {
+ "is-arrayish": "^0.3.1"
+ }
+ },
+ "node_modules/source-map-js": {
+ "version": "1.2.1",
+ "license": "BSD-3-Clause",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/sql-formatter": {
+ "version": "15.7.0",
+ "license": "MIT",
+ "dependencies": {
+ "argparse": "^2.0.1",
+ "nearley": "^2.20.1"
+ },
+ "bin": {
+ "sql-formatter": "bin/sql-formatter-cli.cjs"
+ }
+ },
+ "node_modules/string-width": {
+ "version": "4.2.3",
+ "license": "MIT",
+ "dependencies": {
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/string-width-cjs": {
+ "name": "string-width",
+ "version": "4.2.3",
+ "license": "MIT",
+ "dependencies": {
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/strip-ansi": {
+ "version": "6.0.1",
+ "license": "MIT",
+ "dependencies": {
+ "ansi-regex": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/strip-ansi-cjs": {
+ "name": "strip-ansi",
+ "version": "6.0.1",
+ "license": "MIT",
+ "dependencies": {
+ "ansi-regex": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/style-mod": {
+ "version": "4.1.3",
+ "license": "MIT"
+ },
+ "node_modules/tabbable": {
+ "version": "6.4.0",
+ "license": "MIT"
+ },
+ "node_modules/toggle-selection": {
+ "version": "1.0.6",
+ "license": "MIT"
+ },
+ "node_modules/tslib": {
+ "version": "2.8.1",
+ "license": "0BSD"
+ },
+ "node_modules/ulid": {
+ "version": "3.0.2",
+ "license": "MIT",
+ "bin": {
+ "ulid": "dist/cli.js"
+ }
+ },
+ "node_modules/update-browserslist-db": {
+ "version": "1.2.3",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/browserslist"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/browserslist"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "escalade": "^3.2.0",
+ "picocolors": "^1.1.1"
+ },
+ "bin": {
+ "update-browserslist-db": "cli.js"
+ },
+ "peerDependencies": {
+ "browserslist": ">= 4.21.0"
+ }
+ },
+ "node_modules/vite": {
+ "version": "5.4.21",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "esbuild": "^0.21.3",
+ "postcss": "^8.4.43",
+ "rollup": "^4.20.0"
+ },
+ "bin": {
+ "vite": "bin/vite.js"
+ },
+ "engines": {
+ "node": "^18.0.0 || >=20.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/vitejs/vite?sponsor=1"
+ },
+ "optionalDependencies": {
+ "fsevents": "~2.3.3"
+ },
+ "peerDependencies": {
+ "@types/node": "^18.0.0 || >=20.0.0",
+ "less": "*",
+ "lightningcss": "^1.21.0",
+ "sass": "*",
+ "sass-embedded": "*",
+ "stylus": "*",
+ "sugarss": "*",
+ "terser": "^5.4.0"
+ },
+ "peerDependenciesMeta": {
+ "@types/node": {
+ "optional": true
+ },
+ "less": {
+ "optional": true
+ },
+ "lightningcss": {
+ "optional": true
+ },
+ "sass": {
+ "optional": true
+ },
+ "sass-embedded": {
+ "optional": true
+ },
+ "stylus": {
+ "optional": true
+ },
+ "sugarss": {
+ "optional": true
+ },
+ "terser": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/vite/node_modules/@esbuild/aix-ppc64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz",
+ "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==",
+ "cpu": [
+ "ppc64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "aix"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/vite/node_modules/@esbuild/android-arm": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.5.tgz",
+ "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/vite/node_modules/@esbuild/android-arm64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz",
+ "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/vite/node_modules/@esbuild/android-x64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.5.tgz",
+ "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/vite/node_modules/@esbuild/darwin-arm64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz",
+ "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/vite/node_modules/@esbuild/darwin-x64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz",
+ "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/vite/node_modules/@esbuild/freebsd-arm64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz",
+ "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/vite/node_modules/@esbuild/freebsd-x64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz",
+ "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/vite/node_modules/@esbuild/linux-arm": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz",
+ "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/vite/node_modules/@esbuild/linux-arm64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz",
+ "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/vite/node_modules/@esbuild/linux-ia32": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz",
+ "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==",
+ "cpu": [
+ "ia32"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/vite/node_modules/@esbuild/linux-loong64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz",
+ "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==",
+ "cpu": [
+ "loong64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/vite/node_modules/@esbuild/linux-mips64el": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz",
+ "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==",
+ "cpu": [
+ "mips64el"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/vite/node_modules/@esbuild/linux-ppc64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz",
+ "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==",
+ "cpu": [
+ "ppc64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/vite/node_modules/@esbuild/linux-riscv64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz",
+ "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==",
+ "cpu": [
+ "riscv64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/vite/node_modules/@esbuild/linux-s390x": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz",
+ "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==",
+ "cpu": [
+ "s390x"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/vite/node_modules/@esbuild/linux-x64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz",
+ "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/vite/node_modules/@esbuild/netbsd-x64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz",
+ "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "netbsd"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/vite/node_modules/@esbuild/openbsd-x64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz",
+ "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "openbsd"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/vite/node_modules/@esbuild/sunos-x64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz",
+ "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "sunos"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/vite/node_modules/@esbuild/win32-arm64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz",
+ "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/vite/node_modules/@esbuild/win32-ia32": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz",
+ "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==",
+ "cpu": [
+ "ia32"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/vite/node_modules/@esbuild/win32-x64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz",
+ "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/vite/node_modules/esbuild": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz",
+ "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==",
+ "dev": true,
+ "hasInstallScript": true,
+ "bin": {
+ "esbuild": "bin/esbuild"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "optionalDependencies": {
+ "@esbuild/aix-ppc64": "0.21.5",
+ "@esbuild/android-arm": "0.21.5",
+ "@esbuild/android-arm64": "0.21.5",
+ "@esbuild/android-x64": "0.21.5",
+ "@esbuild/darwin-arm64": "0.21.5",
+ "@esbuild/darwin-x64": "0.21.5",
+ "@esbuild/freebsd-arm64": "0.21.5",
+ "@esbuild/freebsd-x64": "0.21.5",
+ "@esbuild/linux-arm": "0.21.5",
+ "@esbuild/linux-arm64": "0.21.5",
+ "@esbuild/linux-ia32": "0.21.5",
+ "@esbuild/linux-loong64": "0.21.5",
+ "@esbuild/linux-mips64el": "0.21.5",
+ "@esbuild/linux-ppc64": "0.21.5",
+ "@esbuild/linux-riscv64": "0.21.5",
+ "@esbuild/linux-s390x": "0.21.5",
+ "@esbuild/linux-x64": "0.21.5",
+ "@esbuild/netbsd-x64": "0.21.5",
+ "@esbuild/openbsd-x64": "0.21.5",
+ "@esbuild/sunos-x64": "0.21.5",
+ "@esbuild/win32-arm64": "0.21.5",
+ "@esbuild/win32-ia32": "0.21.5",
+ "@esbuild/win32-x64": "0.21.5"
+ }
+ },
+ "node_modules/w3c-keyname": {
+ "version": "2.2.8",
+ "license": "MIT"
+ },
"node_modules/which": {
"version": "2.0.2",
"license": "ISC",
diff --git a/frontend/package.json b/frontend/package.json
index 9fdbab5..586886a 100644
--- a/frontend/package.json
+++ b/frontend/package.json
@@ -59,6 +59,7 @@
"@types/react-dom": "^18.0.6",
"@vitejs/plugin-react": "^4.0.0",
"@vitest/coverage-v8": "^1.3.1",
+ "esbuild": "^0.27.3",
"jsdom": "^24.0.0",
"prettier": "^3.5.3",
"vite": "^5.4.21",
diff --git a/frontend/spotlight.html b/frontend/spotlight.html
new file mode 100644
index 0000000..1b1dde6
--- /dev/null
+++ b/frontend/spotlight.html
@@ -0,0 +1,34 @@
+
+
+
+
+
+ DevToolbox Spotlight
+
+
+
+
+
+
+
diff --git a/frontend/src/App.css b/frontend/src/App.css
index be74ba5..3ff6b3a 100644
--- a/frontend/src/App.css
+++ b/frontend/src/App.css
@@ -37,7 +37,6 @@
display: flex;
flex-direction: column;
transition:
- margin-left 0.3s ease,
width 0.3s ease,
opacity 0.3s ease;
overflow: hidden;
@@ -46,8 +45,26 @@
}
.sidebar.hidden {
- margin-left: -260px;
+ width: 48px;
+}
+
+.sidebar.hidden .nav-scroll-area,
+.sidebar.hidden .sidebar-section-header {
opacity: 0;
+ pointer-events: none;
+}
+
+.sidebar-footer {
+ padding: 12px 8px;
+ border-top: 1px solid var(--border-color);
+ display: flex;
+ justify-content: flex-end;
+ flex-shrink: 0;
+}
+
+.sidebar.hidden .sidebar-footer {
+ padding: 12px 8px;
+ justify-content: center;
}
.nav-scroll-area {
diff --git a/frontend/src/App.jsx b/frontend/src/App.jsx
index ce41c25..a52ed66 100644
--- a/frontend/src/App.jsx
+++ b/frontend/src/App.jsx
@@ -1,10 +1,12 @@
import React, { useState, useEffect, useCallback } from 'react';
-import { Routes, Route, Navigate } from 'react-router-dom';
+import { Routes, Route, Navigate, useNavigate } from 'react-router-dom';
import './App.css';
import { Sidebar } from './components/Sidebar';
import { TitleBar } from './components/TitleBar';
import { CommandPalette } from './components/CommandPalette';
+import { SettingsModal } from './components/SettingsModal';
import { Theme } from '@carbon/react';
+import { Events } from '@wailsio/runtime';
import ToolRouter from './ToolRouter';
// Error boundary for catching React rendering errors
@@ -54,12 +56,16 @@ class ErrorBoundary extends React.Component {
function App() {
console.log('App mounting');
+ const navigate = useNavigate();
const [isSidebarOpen, setIsSidebarOpen] = useState(true);
const [isCommandPaletteOpen, setIsCommandPaletteOpen] = useState(false);
+ const [isSettingsOpen, setIsSettingsOpen] = useState(false);
const [theme, setTheme] = useState('g100'); // 'white', 'g10', 'g90', 'g100'
const [themeMode, setThemeMode] = useState('dark'); // 'system', 'light', 'dark'
const toggleSidebar = () => setIsSidebarOpen(!isSidebarOpen);
+ const openSettings = () => setIsSettingsOpen(true);
+ const closeSettings = () => setIsSettingsOpen(false);
const toggleCommandPalette = useCallback(() => {
setIsCommandPaletteOpen((prev) => !prev);
}, []);
@@ -103,15 +109,72 @@ function App() {
// Listen for command palette toggle event from backend (global hotkey)
useEffect(() => {
- const unsubscribe = window.runtime?.EventsOn?.('command-palette:open', () => {
- toggleCommandPalette();
- });
+ let unsubscribe = null;
+ try {
+ unsubscribe = Events.On('command-palette:open', () => {
+ toggleCommandPalette();
+ });
+ } catch (err) {
+ console.error('Failed to listen to command-palette:open', err);
+ }
return () => {
if (unsubscribe) unsubscribe();
};
}, [toggleCommandPalette]);
+ // Listen for navigation from spotlight
+ useEffect(() => {
+ const handleNavigation = (data) => {
+ // In Wails V3, data might be the path string OR an event object with path in data
+ let path = '';
+ if (typeof data === 'string') {
+ path = data;
+ } else if (data && typeof data === 'object') {
+ if (data.data) {
+ path = typeof data.data === 'string' ? data.data : data.data[0];
+ }
+ }
+
+ if (path) {
+ console.log('App navigating to path:', path);
+ navigate(path);
+ } else {
+ console.warn('App received empty/invalid path via navigate:to:', data);
+ }
+ };
+
+ let unsubscribe = null;
+ try {
+ unsubscribe = Events.On('navigate:to', (event) => {
+ console.log('Received navigate:to event', event);
+ handleNavigation(event);
+ });
+ } catch (err) {
+ console.error('Failed to listen to navigate:to', err);
+ }
+
+ return () => {
+ if (unsubscribe) unsubscribe();
+ };
+ }, [navigate]);
+
+ // Listen for theme toggle from spotlight
+ useEffect(() => {
+ let unsubscribe = null;
+ try {
+ unsubscribe = Events.On('theme:toggle', () => {
+ setThemeMode((prev) => (prev === 'dark' ? 'light' : 'dark'));
+ });
+ } catch (err) {
+ console.error('Failed to listen to theme:toggle', err);
+ }
+
+ return () => {
+ if (unsubscribe) unsubscribe();
+ };
+ }, [setThemeMode]);
+
return (
@@ -124,7 +187,7 @@ function App() {
/>
-
+
@@ -143,6 +206,13 @@ function App() {
themeMode={themeMode}
setThemeMode={setThemeMode}
/>
+
+
diff --git a/frontend/src/components/Sidebar.jsx b/frontend/src/components/Sidebar.jsx
index cb1d8c8..d2007fb 100644
--- a/frontend/src/components/Sidebar.jsx
+++ b/frontend/src/components/Sidebar.jsx
@@ -1,7 +1,9 @@
import React, { useState, useEffect } from 'react';
import { NavLink } from 'react-router-dom';
+import { IconButton } from '@carbon/react';
+import { Settings } from '@carbon/icons-react';
-export function Sidebar({ isVisible }) {
+export function Sidebar({ isVisible, onOpenSettings }) {
const [searchTerm, setSearchTerm] = useState('');
const [pinned, setPinned] = useState(() => {
try {
@@ -135,6 +137,19 @@ export function Sidebar({ isVisible }) {
)}
+
+ {/* Settings button at bottom */}
+
+
+
+
+
);
}
diff --git a/frontend/src/components/SpotlightPalette.css b/frontend/src/components/SpotlightPalette.css
new file mode 100644
index 0000000..6a258d7
--- /dev/null
+++ b/frontend/src/components/SpotlightPalette.css
@@ -0,0 +1,112 @@
+.spotlight-container {
+ width: 100%;
+ height: 100%;
+ background: #161616;
+ border: none;
+ border-radius: 0;
+ box-shadow: none;
+ overflow: hidden;
+}
+
+.spotlight-search-box {
+ display: flex;
+ align-items: center;
+ gap: 0.75rem;
+ padding: 1rem;
+ border-bottom: 1px solid var(--cds-border-subtle);
+}
+
+.spotlight-search-icon {
+ color: var(--cds-text-secondary);
+ flex-shrink: 0;
+}
+
+.spotlight-input {
+ flex: 1;
+ background: transparent;
+ border: none;
+ color: #f4f4f4; /* g100 text primary */
+ font-size: 1.125rem;
+ padding: 0;
+ outline: none;
+}
+
+.spotlight-input::placeholder {
+ color: #c6c6c6; /* g100 text secondary */
+}
+
+.spotlight-clear-btn {
+ background: transparent;
+ border: none;
+ color: var(--cds-text-secondary);
+ cursor: pointer;
+ padding: 0.25rem;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ border-radius: 4px;
+ transition: background-color 0.15s ease;
+}
+
+.spotlight-clear-btn:hover {
+ background: var(--cds-layer-hover);
+}
+
+.spotlight-results {
+ height: 416px;
+ overflow: hidden;
+}
+
+.spotlight-empty {
+ padding: 2rem;
+ text-align: center;
+ color: #c6c6c6;
+ font-size: 0.875rem;
+}
+
+.spotlight-list {
+ overflow-y: auto;
+ max-height: 400px;
+}
+
+.spotlight-item {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ padding: 0.75rem 1rem;
+ cursor: pointer;
+ transition: background-color 0.15s ease;
+}
+
+.spotlight-item:hover,
+.spotlight-item.selected {
+ background: #262626; /* g100 layer hover */
+}
+
+.spotlight-item.selected {
+ background: #353535; /* g100 layer selected */
+ border-left: 3px solid #78a9ff;
+}
+
+.spotlight-item-content {
+ display: flex;
+ align-items: center;
+ gap: 0.75rem;
+ flex: 1;
+}
+
+.spotlight-item-icon {
+ color: #c6c6c6;
+}
+
+.spotlight-item-label {
+ color: #f4f4f4;
+ font-size: 0.9375rem;
+}
+
+.spotlight-item-category {
+ color: #c6c6c6;
+ font-size: 0.75rem;
+ text-transform: uppercase;
+ letter-spacing: 0.05em;
+}
diff --git a/frontend/src/components/SpotlightPalette.jsx b/frontend/src/components/SpotlightPalette.jsx
new file mode 100644
index 0000000..80509d7
--- /dev/null
+++ b/frontend/src/components/SpotlightPalette.jsx
@@ -0,0 +1,389 @@
+import React, { useState, useEffect, useRef, useCallback } from 'react';
+import { useNavigate } from 'react-router-dom';
+import { Search, Close, Moon, Application } from '@carbon/icons-react';
+import { Events } from '@wailsio/runtime';
+import './SpotlightPalette.css';
+
+// Command definitions with tool presets matching the main app
+const COMMANDS = [
+ // Code Formatter presets
+ {
+ id: 'formatter-json',
+ label: 'Code Formatter > JSON',
+ path: '/tool/code-formatter?format=json',
+ category: 'Formatter',
+ },
+ {
+ id: 'formatter-xml',
+ label: 'Code Formatter > XML',
+ path: '/tool/code-formatter?format=xml',
+ category: 'Formatter',
+ },
+ {
+ id: 'formatter-html',
+ label: 'Code Formatter > HTML',
+ path: '/tool/code-formatter?format=html',
+ category: 'Formatter',
+ },
+ {
+ id: 'formatter-sql',
+ label: 'Code Formatter > SQL',
+ path: '/tool/code-formatter?format=sql',
+ category: 'Formatter',
+ },
+ {
+ id: 'formatter-css',
+ label: 'Code Formatter > CSS',
+ path: '/tool/code-formatter?format=css',
+ category: 'Formatter',
+ },
+ {
+ id: 'formatter-js',
+ label: 'Code Formatter > JavaScript',
+ path: '/tool/code-formatter?format=javascript',
+ category: 'Formatter',
+ },
+
+ // Text Converter - Encoding
+ {
+ id: 'converter-base64',
+ label: 'Text Converter > Base64',
+ path: '/tool/text-converter?category=Encode%20-%20Decode&method=Base64',
+ category: 'Converter',
+ },
+ {
+ id: 'converter-url',
+ label: 'Text Converter > URL Encode',
+ path: '/tool/text-converter?category=Encode%20-%20Decode&method=URL',
+ category: 'Converter',
+ },
+ {
+ id: 'converter-hex',
+ label: 'Text Converter > Hex',
+ path: '/tool/text-converter?category=Encode%20-%20Decode&method=Base16%20(Hex)',
+ category: 'Converter',
+ },
+ {
+ id: 'converter-html',
+ label: 'Text Converter > HTML Entities',
+ path: '/tool/text-converter?category=Encode%20-%20Decode&method=HTML%20Entities',
+ category: 'Converter',
+ },
+
+ // Text Converter - Hashing
+ {
+ id: 'converter-md5',
+ label: 'Text Converter > MD5',
+ path: '/tool/text-converter?category=Hash&method=MD5',
+ category: 'Converter',
+ },
+ {
+ id: 'converter-sha256',
+ label: 'Text Converter > SHA-256',
+ path: '/tool/text-converter?category=Hash&method=SHA-256',
+ category: 'Converter',
+ },
+ {
+ id: 'converter-sha512',
+ label: 'Text Converter > SHA-512',
+ path: '/tool/text-converter?category=Hash&method=SHA-512',
+ category: 'Converter',
+ },
+ {
+ id: 'converter-all-hashes',
+ label: 'Text Converter > All Hashes',
+ path: '/tool/text-converter?category=Hash&method=All',
+ category: 'Converter',
+ },
+
+ // Text Converter - Conversions
+ {
+ id: 'converter-json-yaml',
+ label: 'Text Converter > JSON ↔ YAML',
+ path: '/tool/text-converter?category=Convert&method=JSON%20%E2%86%94%20YAML',
+ category: 'Converter',
+ },
+ {
+ id: 'converter-json-xml',
+ label: 'Text Converter > JSON ↔ XML',
+ path: '/tool/text-converter?category=Convert&method=JSON%20%E2%86%94%20XML',
+ category: 'Converter',
+ },
+ {
+ id: 'converter-markdown-html',
+ label: 'Text Converter > Markdown ↔ HTML',
+ path: '/tool/text-converter?category=Convert&method=Markdown%20%E2%86%94%20HTML',
+ category: 'Converter',
+ },
+ {
+ id: 'converter-csv-tsv',
+ label: 'Text Converter > CSV ↔ TSV',
+ path: '/tool/text-converter?category=Convert&method=CSV%20%E2%86%94%20TSV',
+ category: 'Converter',
+ },
+ {
+ id: 'converter-case-swap',
+ label: 'Text Converter > Case Swap',
+ path: '/tool/text-converter?category=Convert&method=Case%20Swapping',
+ category: 'Converter',
+ },
+
+ // Direct navigation
+ { id: 'jwt', label: 'JWT Debugger', path: '/tool/jwt', category: 'Tools' },
+ { id: 'barcode', label: 'Barcode Generator', path: '/tool/barcode', category: 'Tools' },
+ { id: 'regexp', label: 'RegExp Tester', path: '/tool/regexp', category: 'Tools' },
+ { id: 'cron', label: 'Cron Job Parser', path: '/tool/cron', category: 'Tools' },
+ { id: 'diff', label: 'Text Diff Checker', path: '/tool/diff', category: 'Tools' },
+ { id: 'number', label: 'Number Converter', path: '/tool/number-converter', category: 'Tools' },
+ { id: 'color', label: 'Color Converter', path: '/tool/color-converter', category: 'Tools' },
+ { id: 'string', label: 'String Utilities', path: '/tool/string-utilities', category: 'Tools' },
+ {
+ id: 'datetime',
+ label: 'DateTime Converter',
+ path: '/tool/datetime-converter',
+ category: 'Tools',
+ },
+ { id: 'text', label: 'Text Converter', path: '/tool/text-converter', category: 'Tools' },
+
+ // Data Generator
+ {
+ id: 'data-user',
+ label: 'Data Generator > User',
+ path: '/tool/data-generator?preset=User',
+ category: 'Generator',
+ },
+ {
+ id: 'data-address',
+ label: 'Data Generator > Address',
+ path: '/tool/data-generator?preset=Address',
+ category: 'Generator',
+ },
+
+ // System commands
+ {
+ id: 'theme-toggle',
+ label: 'Toggle Dark Mode',
+ action: 'toggle-theme',
+ category: 'System',
+ icon: Moon,
+ },
+ {
+ id: 'window-toggle',
+ label: 'Show/Hide Main Window',
+ action: 'toggle-window',
+ category: 'System',
+ icon: Application,
+ },
+];
+
+export function SpotlightPalette() {
+ const [searchQuery, setSearchQuery] = useState('');
+ const [selectedIndex, setSelectedIndex] = useState(0);
+ const [commands, setCommands] = useState(COMMANDS);
+ const [recentCommands, setRecentCommands] = useState(() => {
+ try {
+ return JSON.parse(localStorage.getItem('spotlightRecent')) || [];
+ } catch {
+ return [];
+ }
+ });
+ const inputRef = useRef(null);
+ const listRef = useRef(null);
+
+ // Calculate fuzzy match score
+ const fuzzyScore = (target, query) => {
+ if (!query) return 0;
+ const targetLower = target.toLowerCase();
+ const queryLower = query.toLowerCase();
+ if (targetLower === queryLower) return -1000;
+ if (targetLower.startsWith(queryLower)) return -100;
+ const words = targetLower.split(/[\s>]/);
+ for (let word of words) {
+ if (word.startsWith(queryLower)) return -50;
+ }
+ let targetIndex = 0;
+ let queryIndex = 0;
+ let score = 0;
+ let lastMatchIndex = -1;
+ while (targetIndex < targetLower.length && queryIndex < queryLower.length) {
+ if (targetLower[targetIndex] === queryLower[queryIndex]) {
+ if (lastMatchIndex !== -1) {
+ score += targetIndex - lastMatchIndex - 1;
+ }
+ lastMatchIndex = targetIndex;
+ queryIndex++;
+ }
+ targetIndex++;
+ }
+ if (queryIndex < queryLower.length) return 9999;
+ return score;
+ };
+
+ // Filter commands based on search query
+ useEffect(() => {
+ if (!searchQuery.trim()) {
+ const recentIds = new Set(recentCommands);
+ const sortedCommands = [...COMMANDS].sort((a, b) => {
+ const aRecent = recentIds.has(a.id) ? 1 : 0;
+ const bRecent = recentIds.has(b.id) ? 1 : 0;
+ return bRecent - aRecent;
+ });
+ setCommands(sortedCommands);
+ return;
+ }
+ const query = searchQuery.toLowerCase();
+ const scored = COMMANDS.map((cmd) => {
+ const labelScore = fuzzyScore(cmd.label, query);
+ const categoryScore = fuzzyScore(cmd.category, query);
+ const bestScore = Math.min(labelScore, categoryScore);
+ return { cmd, score: bestScore };
+ }).filter((item) => item.score < 9999);
+ scored.sort((a, b) => a.score - b.score);
+ setCommands(scored.map((item) => item.cmd));
+ setSelectedIndex(0);
+ }, [searchQuery, recentCommands]);
+
+ // Focus input on mount
+ useEffect(() => {
+ setTimeout(() => inputRef.current?.focus(), 100);
+ }, []);
+
+ // Listen for spotlight opened event
+ useEffect(() => {
+ const unsubscribe = window.runtime?.EventsOn?.('spotlight:opened', () => {
+ setSearchQuery('');
+ setSelectedIndex(0);
+ setTimeout(() => inputRef.current?.focus(), 100);
+ });
+ return () => {
+ if (unsubscribe) unsubscribe();
+ };
+ }, []);
+
+ // Save recent command
+ const saveRecentCommand = useCallback((commandId) => {
+ setRecentCommands((prev) => {
+ const updated = [commandId, ...prev.filter((id) => id !== commandId)].slice(0, 10);
+ localStorage.setItem('spotlightRecent', JSON.stringify(updated));
+ return updated;
+ });
+ }, []);
+
+ // Execute command
+ const executeCommand = useCallback(
+ (command) => {
+ saveRecentCommand(command.id);
+
+ if (command.action) {
+ switch (command.action) {
+ case 'toggle-theme':
+ try {
+ Events.Emit('spotlight:theme:toggle');
+ } catch (e) {}
+ break;
+ case 'toggle-window':
+ try {
+ Events.Emit('window:toggle');
+ } catch (e) {}
+ break;
+ default:
+ break;
+ }
+ } else if (command.path) {
+ console.log('[Spotlight] Selected path command:', command.id, command.path);
+ const path = command.path;
+ try {
+ Events.Emit('spotlight:command-selected', path);
+ console.log('[Spotlight] Emitted spotlight:command-selected with path:', path);
+ } catch (err) {
+ console.error('[Spotlight] Failed to emit event:', err);
+ }
+ }
+ },
+ [saveRecentCommand]
+ );
+
+ // Handle keyboard navigation
+ const handleKeyDown = useCallback(
+ (e) => {
+ if (e.key === 'ArrowDown') {
+ e.preventDefault();
+ setSelectedIndex((prev) => (prev + 1) % commands.length);
+ } else if (e.key === 'ArrowUp') {
+ e.preventDefault();
+ setSelectedIndex((prev) => (prev - 1 + commands.length) % commands.length);
+ } else if (e.key === 'Enter') {
+ e.preventDefault();
+ if (commands[selectedIndex]) {
+ executeCommand(commands[selectedIndex]);
+ }
+ } else if (e.key === 'Escape') {
+ e.preventDefault();
+ console.log('[Spotlight] Escape pressed, closing...');
+ try {
+ Events.Emit('spotlight:close');
+ } catch (err) {
+ console.error('Failed to emit spotlight:close', err);
+ }
+ }
+ },
+ [commands, selectedIndex, executeCommand]
+ );
+
+ // Scroll selected item into view
+ useEffect(() => {
+ const selectedElement = listRef.current?.children[selectedIndex];
+ if (selectedElement) {
+ selectedElement.scrollIntoView({ block: 'nearest', behavior: 'smooth' });
+ }
+ }, [selectedIndex]);
+
+ return (
+
+
+
+ setSearchQuery(e.target.value)}
+ onKeyDown={handleKeyDown}
+ autoComplete="off"
+ />
+ {searchQuery && (
+
+ )}
+
+
+
+ {commands.length === 0 ? (
+
No commands found matching "{searchQuery}"
+ ) : (
+
+ {commands.map((command, index) => {
+ const Icon = command.icon || null;
+ return (
+
executeCommand(command)}
+ onMouseEnter={() => setSelectedIndex(index)}
+ >
+
+ {Icon && }
+ {command.label}
+
+
{command.category}
+
+ );
+ })}
+
+ )}
+
+
+ );
+}
diff --git a/frontend/src/pages/CodeFormatter/index.jsx b/frontend/src/pages/CodeFormatter/index.jsx
index 6d1e0bd..e9b0cbd 100644
--- a/frontend/src/pages/CodeFormatter/index.jsx
+++ b/frontend/src/pages/CodeFormatter/index.jsx
@@ -104,12 +104,14 @@ export default function CodeFormatter() {
}
});
- // Clear URL params after using preset
+ // React to URL format changes even when already mounted
useEffect(() => {
- if (urlFormat) {
+ if (urlFormat && validFormats.includes(urlFormat)) {
+ setFormatType(urlFormat);
+ // Clear URL params after using preset to avoid re-triggering on reload
setSearchParams({}, { replace: true });
}
- }, [urlFormat, setSearchParams]);
+ }, [urlFormat, setSearchParams, validFormats]);
// Cache for per-language inputs and filters (in memory only)
const inputCacheRef = useRef({});
diff --git a/frontend/src/pages/DataGenerator/index.jsx b/frontend/src/pages/DataGenerator/index.jsx
index f0e74a1..f3176f7 100644
--- a/frontend/src/pages/DataGenerator/index.jsx
+++ b/frontend/src/pages/DataGenerator/index.jsx
@@ -80,12 +80,32 @@ export default function DataGenerator() {
loadPresets();
}, []);
- // Clear URL params after using preset
+ // Sync preset if URL param changes
useEffect(() => {
- if (urlPreset) {
- setSearchParams({}, { replace: true });
+ if (urlPreset && state.presets.length > 0) {
+ const preset = state.presets.find(
+ (p) =>
+ p.id.toLowerCase() === urlPreset.toLowerCase() ||
+ p.name.toLowerCase() === urlPreset.toLowerCase()
+ );
+ if (preset) {
+ const defaultVars = {};
+ preset.variables.forEach((v) => {
+ defaultVars[v.name] = v.default;
+ });
+ dispatch({
+ type: 'SELECT_PRESET',
+ payload: {
+ id: preset.id,
+ template: preset.template,
+ defaultVars,
+ },
+ });
+ // Clear URL params after using preset
+ setSearchParams({}, { replace: true });
+ }
}
- }, [urlPreset, setSearchParams]);
+ }, [urlPreset, state.presets, setSearchParams]);
// Handle preset selection
const handlePresetChange = useCallback(
diff --git a/frontend/src/pages/TextConverter/components/MultiHashOutput.jsx b/frontend/src/pages/TextConverter/components/MultiHashOutput.jsx
index e22794f..846d8e9 100644
--- a/frontend/src/pages/TextConverter/components/MultiHashOutput.jsx
+++ b/frontend/src/pages/TextConverter/components/MultiHashOutput.jsx
@@ -1,4 +1,4 @@
-import { useState } from 'react';
+import React, { useState } from 'react';
import { CopyButton, TextInput } from '@carbon/react';
const HASH_DISPLAY_ORDER = [
diff --git a/frontend/src/pages/TextConverter/index.jsx b/frontend/src/pages/TextConverter/index.jsx
index cbdfba8..3ebcccf 100644
--- a/frontend/src/pages/TextConverter/index.jsx
+++ b/frontend/src/pages/TextConverter/index.jsx
@@ -46,12 +46,18 @@ export default function TextBasedConverter() {
() => localStorage.getItem(STORAGE_KEYS.SUBMODE) || DEFAULTS.SUBMODE
);
- // Clear URL params after using preset
+ // React to URL preset changes even when already mounted
useEffect(() => {
- if (urlCategory || urlMethod) {
+ if (urlCategory && validCategories.includes(urlCategory)) {
+ setCategory(urlCategory);
+ const methodsForCategory = CONVERTER_MAP[urlCategory] || [];
+ if (urlMethod && methodsForCategory.includes(urlMethod)) {
+ setMethod(urlMethod);
+ }
+ // Clear URL params after using preset
setSearchParams({}, { replace: true });
}
- }, [urlCategory, urlMethod, setSearchParams]);
+ }, [urlCategory, urlMethod, setSearchParams, validCategories]);
const [input, setInput] = useState('');
const [output, setOutput] = useState('');
diff --git a/frontend/src/spotlight.css b/frontend/src/spotlight.css
new file mode 100644
index 0000000..0467917
--- /dev/null
+++ b/frontend/src/spotlight.css
@@ -0,0 +1,19 @@
+/* Spotlight window specific styles */
+:root,
+html,
+body,
+#root,
+[class*='cds--theme-'],
+.app-container {
+ background: #161616 !important;
+ background-color: #161616 !important;
+ color: #f4f4f4 !important;
+}
+
+#root {
+ display: block;
+ width: 100vw;
+ height: 100vh;
+ margin: 0 !important;
+ padding: 0 !important;
+}
diff --git a/frontend/src/spotlight.jsx b/frontend/src/spotlight.jsx
new file mode 100644
index 0000000..07e7353
--- /dev/null
+++ b/frontend/src/spotlight.jsx
@@ -0,0 +1,30 @@
+import React from 'react';
+import ReactDOM from 'react-dom/client';
+import { BrowserRouter } from 'react-router-dom';
+import { Theme } from '@carbon/react';
+import { SpotlightPalette } from './components/SpotlightPalette';
+import './index.scss'; // Import global styles and Carbon tokens
+import './spotlight.css';
+
+// Force g100 theme for Spotlight as per project guidelines
+const getInitialTheme = () => 'g100';
+
+function SpotlightApp() {
+ return (
+
+
+
+
+
+ );
+}
+
+const root = ReactDOM.createRoot(document.getElementById('root'));
+root.render(
+
+
+
+);
diff --git a/go.mod b/go.mod
index 07f0776..da1690c 100644
--- a/go.mod
+++ b/go.mod
@@ -14,6 +14,7 @@ require (
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e
github.com/stretchr/testify v1.11.1
github.com/wailsapp/wails/v3 v3.0.0-alpha.68
+ golang.design/x/hotkey v0.4.1
golang.org/x/crypto v0.47.0
golang.org/x/net v0.49.0
gopkg.in/yaml.v3 v3.0.1
diff --git a/go.sum b/go.sum
index 4b72903..ee5ca09 100644
--- a/go.sum
+++ b/go.sum
@@ -200,6 +200,10 @@ github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM
github.com/xanzy/ssh-agent v0.3.3/go.mod h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI1Bc68Uw=
go.uber.org/mock v0.5.0 h1:KAMbZvZPyBPWgD14IrIQ38QCyjwpvVVV6K/bHl1IwQU=
go.uber.org/mock v0.5.0/go.mod h1:ge71pBPLYDk7QIi1LupWxdAykm7KIEFchiOqd6z7qMM=
+golang.design/x/hotkey v0.4.1 h1:zLP/2Pztl4WjyxURdW84GoZ5LUrr6hr69CzJFJ5U1go=
+golang.design/x/hotkey v0.4.1/go.mod h1:M8SGcwFYHnKRa83FpTFQoZvPO5vVT+kWPztFqTQKmXA=
+golang.design/x/mainthread v0.3.0 h1:UwFus0lcPodNpMOGoQMe87jSFwbSsEY//CA7yVmu4j8=
+golang.design/x/mainthread v0.3.0/go.mod h1:vYX7cF2b3pTJMGM/hc13NmN6kblKnf4/IyvHeu259L0=
golang.org/x/arch v0.20.0 h1:dx1zTU0MAE98U+TQ8BLl7XsJbgze2WnNKF/8tGp/Q6c=
golang.org/x/arch v0.20.0/go.mod h1:bdwinDaKcfZUGpH09BB7ZmOfhalA8lQdzl62l8gGWsk=
golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
diff --git a/main.go b/main.go
index d761f2b..8ff8d9e 100644
--- a/main.go
+++ b/main.go
@@ -15,6 +15,8 @@ import (
"github.com/gin-gonic/gin"
"github.com/wailsapp/wails/v3/pkg/application"
"github.com/wailsapp/wails/v3/pkg/events"
+ "github.com/wailsapp/wails/v3/pkg/icons"
+ "golang.design/x/hotkey"
)
//go:embed all:frontend/dist
@@ -33,6 +35,11 @@ func init() {
// Register settings changed event
application.RegisterEvent[map[string]interface{}]("settings:changed")
+
+ // Register spotlight events
+ application.RegisterEvent[string]("spotlight:closed")
+ application.RegisterEvent[string]("spotlight:close")
+ application.RegisterEvent[string]("spotlight:command-selected") // Event triggered when user selects a command from spotlight - used for navigation from spotlight to main window
}
func main() {
@@ -93,7 +100,12 @@ func main() {
app.RegisterService(application.NewService(service.NewDataGeneratorService(app)))
app.RegisterService(application.NewService(service.NewCodeFormatterService(app)))
app.RegisterService(application.NewService(service.NewSettingsService(app, settingsManager)))
- // WindowControls service will be registered after window creation
+
+ // Create and register spotlight service
+ spotlightService := service.NewSpotlightService(app)
+ app.RegisterService(application.NewService(spotlightService))
+
+ // WindowControls service must be registered after main window creation (see line 149)
// Start HTTP server for browser support (background)
go func() {
@@ -102,6 +114,7 @@ func main() {
// Create main window
mainWindow := app.Window.NewWithOptions(application.WebviewWindowOptions{
+ Name: "main",
Title: "DevToolbox",
Width: 1024,
Height: 768,
@@ -112,9 +125,11 @@ func main() {
Alpha: 1,
},
Mac: application.MacWindow{
- InvisibleTitleBarHeight: 50,
- Backdrop: application.MacBackdropTranslucent,
- TitleBar: application.MacTitleBarHiddenInset,
+ Backdrop: application.MacBackdropTranslucent,
+ TitleBar: application.MacTitleBar{
+ AppearsTransparent: false,
+ Hide: false,
+ },
},
URL: "/",
})
@@ -138,33 +153,144 @@ func main() {
// Register WindowControls service after window creation
app.RegisterService(application.NewService(service.NewWindowControls(mainWindow)))
+ // Create spotlight window with special behaviors
+ // Note: MacWindowLevelFloating and ActivationPolicyAccessory may require
+ // platform-specific code. CollectionBehaviors provide most spotlight functionality.
+ spotlightWindow := app.Window.NewWithOptions(application.WebviewWindowOptions{
+ Title: "Spotlight",
+ Width: 640,
+ Height: 480,
+ MinHeight: 480,
+ MaxHeight: 480,
+ Frameless: true,
+ Hidden: true,
+ BackgroundColour: application.RGBA{Red: 22, Green: 22, Blue: 22, Alpha: 255},
+ // Center the window
+ InitialPosition: application.WindowCentered,
+ // Prevent resizing
+ DisableResize: true,
+ Mac: application.MacWindow{
+ // Combine multiple behaviors using bitwise OR:
+ // - CanJoinAllSpaces: window appears on ALL Spaces (virtual desktops)
+ // - FullScreenAuxiliary: window can overlay fullscreen applications
+ CollectionBehavior: application.MacWindowCollectionBehaviorCanJoinAllSpaces |
+ application.MacWindowCollectionBehaviorFullScreenAuxiliary,
+ // Float above other windows
+ WindowLevel: application.MacWindowLevelFloating,
+ // Hidden title bar for clean look
+ TitleBar: application.MacTitleBar{
+ AppearsTransparent: true,
+ Hide: true,
+ },
+ },
+ URL: "/spotlight",
+ })
+
+ // Set the window in spotlight service
+ spotlightService.SetWindow(spotlightWindow)
+
+ // Handle spotlight window close - hide instead of close
+ spotlightWindow.OnWindowEvent(events.Common.WindowClosing, func(event *application.WindowEvent) {
+ event.Cancel()
+ spotlightWindow.Hide()
+ spotlightWindow.EmitEvent("spotlight:closed", "")
+ })
+
+ // Listen for spotlight navigation events
+ app.Event.On("spotlight:command-selected", func(event *application.CustomEvent) {
+ log.Printf("[Spotlight] Received command-selected event with data: %#v", event.Data)
+
+ var path string
+ switch v := event.Data.(type) {
+ case string:
+ path = v
+ case []interface{}:
+ if len(v) > 0 {
+ path, _ = v[0].(string)
+ }
+ case map[string]interface{}:
+ if p, ok := v["path"].(string); ok {
+ path = p
+ } else if d, ok := v["data"].(string); ok {
+ path = d
+ }
+ }
+
+ if path == "" {
+ log.Printf("[Spotlight] Command selected with empty path")
+ return
+ }
+
+ log.Printf("[Spotlight] Navigating main window to: %s", path)
+
+ // Switch to main app context
+ mainWindow.Show()
+ mainWindow.Focus()
+
+ // Hide spotlight window asynchronously to prevent macOS from reverting focus
+ // to the previously active non-DevToolbox app
+ go func() {
+ time.Sleep(100 * time.Millisecond)
+ spotlightWindow.Hide()
+ }()
+
+ // Tell the frontend to navigate
+ mainWindow.EmitEvent("navigate:to", path)
+ })
+
+ // Close spotlight window
+ app.Event.On("spotlight:close", func(_ *application.CustomEvent) {
+ log.Printf("[Spotlight] Spotlight close requested")
+ spotlightWindow.Hide()
+ })
+
+ // Proxy these events to the main window
+ app.Event.On("spotlight:theme:toggle", func(_ *application.CustomEvent) {
+ log.Printf("[Spotlight] Relaying theme:toggle to main window")
+ mainWindow.EmitEvent("theme:toggle", nil)
+ })
+
+ app.Event.On("window:toggle", func(_ *application.CustomEvent) {
+ log.Printf("[Spotlight] Window toggle requested")
+ if mainWindow.IsVisible() {
+ mainWindow.Hide()
+ } else {
+ mainWindow.Show()
+ mainWindow.Focus()
+ }
+ })
+
+ app.Event.On("app:quit", func(_ *application.CustomEvent) {
+ log.Printf("[Spotlight] App quit requested via spotlight")
+ app.Quit()
+ })
+
// Setup system tray
systray := app.SystemTray.New()
+ // Set system tray icon
+ if runtime.GOOS == "darwin" {
+ systray.SetTemplateIcon(icons.SystrayMacTemplate)
+ } else {
+ systray.SetDarkModeIcon(icons.SystrayDark)
+ systray.SetIcon(icons.SystrayLight)
+ }
+
// Create tray menu
trayMenu := app.NewMenu()
trayMenu.Add("Show DevToolbox").OnClick(func(ctx *application.Context) {
log.Println("Tray menu 'Show DevToolbox' clicked")
- log.Printf("Window visible: %v, minimized: %v", mainWindow.IsVisible(), mainWindow.IsMinimised())
-
- // On macOS, we need to activate the app first before showing the window
- log.Println("Activating application")
- app.Show()
-
- // On macOS, we need to handle hidden windows differently
if !mainWindow.IsVisible() {
- log.Println("Window is not visible, showing it")
mainWindow.Show()
}
-
if mainWindow.IsMinimised() {
- log.Println("Restoring minimized window")
mainWindow.Restore()
}
-
- log.Println("Focusing window")
mainWindow.Focus()
- log.Printf("After show - Window visible: %v, minimized: %v", mainWindow.IsVisible(), mainWindow.IsMinimised())
+ })
+ trayMenu.Add("Open Spotlight (Cmd+Shift+Space)").OnClick(func(ctx *application.Context) {
+ log.Println("Tray menu 'Open Spotlight' clicked")
+ spotlightService.Toggle()
})
trayMenu.AddSeparator()
trayMenu.Add("Quit").OnClick(func(ctx *application.Context) {
@@ -172,23 +298,37 @@ func main() {
})
systray.SetMenu(trayMenu)
- // Register global hotkey for command palette
- // macOS: Cmd+Ctrl+M, Windows/Linux: Ctrl+Alt+M
- var hotkeyAccelerator string
+ // Register global hotkey using golang-design/hotkey for system-wide shortcuts
+ go registerGlobalHotkey(spotlightService)
+
+ if err := app.Run(); err != nil {
+ panic(err)
+ }
+}
+
+// registerGlobalHotkey registers a system-wide global hotkey
+func registerGlobalHotkey(spotlightService *service.SpotlightService) {
+ // Use Cmd+Shift+Space for macOS, Ctrl+Shift+Space for others
+ var hk *hotkey.Hotkey
if runtime.GOOS == "darwin" {
- hotkeyAccelerator = "Cmd+Ctrl+M"
+ hk = hotkey.New([]hotkey.Modifier{hotkey.ModCmd, hotkey.ModShift}, hotkey.KeySpace)
} else {
- hotkeyAccelerator = "Ctrl+Alt+M"
+ hk = hotkey.New([]hotkey.Modifier{hotkey.ModCtrl, hotkey.ModShift}, hotkey.KeySpace)
}
- app.KeyBinding.Add(hotkeyAccelerator, func(window application.Window) {
- mainWindow.Show()
- mainWindow.Focus()
- mainWindow.EmitEvent("command-palette:open", "")
- })
+ log.Printf("Registering global hotkey: %s", hk)
- if err := app.Run(); err != nil {
- panic(err)
+ if err := hk.Register(); err != nil {
+ log.Printf("Failed to register hotkey: %v", err)
+ return
+ }
+
+ log.Println("Global hotkey registered successfully. Press Cmd/Ctrl+Shift+Space to toggle spotlight.")
+
+ // Listen for hotkey events
+ for range hk.Keydown() {
+ log.Println("Global hotkey pressed, toggling spotlight")
+ spotlightService.Toggle()
}
}
diff --git a/service/spotlight.go b/service/spotlight.go
new file mode 100644
index 0000000..bc04cd2
--- /dev/null
+++ b/service/spotlight.go
@@ -0,0 +1,71 @@
+package service
+
+import (
+ "github.com/wailsapp/wails/v3/pkg/application"
+)
+
+// SpotlightService manages the spotlight command palette window
+type SpotlightService struct {
+ window *application.WebviewWindow
+ app *application.App
+}
+
+// NewSpotlightService creates a new spotlight service
+func NewSpotlightService(app *application.App) *SpotlightService {
+ return &SpotlightService{
+ app: app,
+ }
+}
+
+// SetWindow sets the spotlight window (called after window creation)
+func (s *SpotlightService) SetWindow(window *application.WebviewWindow) {
+ s.window = window
+}
+
+// Show shows the spotlight window and focuses it
+func (s *SpotlightService) Show() {
+ if s.window == nil {
+ return
+ }
+
+ s.window.Show()
+ s.window.Focus()
+ s.window.EmitEvent("spotlight:opened", "")
+}
+
+// Hide hides the spotlight window
+func (s *SpotlightService) Hide() {
+ if s.window == nil {
+ return
+ }
+
+ s.window.Hide()
+}
+
+// Toggle shows or hides the spotlight window
+func (s *SpotlightService) Toggle() {
+ if s.window == nil {
+ return
+ }
+
+ if s.window.IsVisible() {
+ s.Hide()
+ } else {
+ s.Show()
+ }
+}
+
+// IsVisible returns whether the spotlight window is visible
+func (s *SpotlightService) IsVisible() bool {
+ if s.window == nil {
+ return false
+ }
+ return s.window.IsVisible()
+}
+
+// Close closes the spotlight window
+func (s *SpotlightService) Close() {
+ if s.window != nil {
+ s.window.Close()
+ }
+}
diff --git a/service/spotlight_test.go b/service/spotlight_test.go
new file mode 100644
index 0000000..a3bff3b
--- /dev/null
+++ b/service/spotlight_test.go
@@ -0,0 +1,63 @@
+package service
+
+import (
+ "testing"
+
+ "github.com/stretchr/testify/assert"
+)
+
+func TestNewSpotlightService(t *testing.T) {
+ t.Run("creates new service", func(t *testing.T) {
+ service := NewSpotlightService(nil)
+ assert.NotNil(t, service)
+ })
+}
+
+func TestSpotlightService_Operations(t *testing.T) {
+ tests := []struct {
+ name string
+ test func(t *testing.T, s *SpotlightService)
+ }{
+ {
+ name: "Toggle with nil window",
+ test: func(t *testing.T, s *SpotlightService) {
+ // Initially not visible
+ assert.False(t, s.IsVisible())
+
+ // Toggle should not panic with nil window
+ s.Toggle()
+ assert.False(t, s.IsVisible())
+ },
+ },
+ {
+ name: "Show with nil window",
+ test: func(t *testing.T, s *SpotlightService) {
+ // Should not panic with nil window
+ s.Show()
+ assert.False(t, s.IsVisible())
+ },
+ },
+ {
+ name: "Hide with nil window",
+ test: func(t *testing.T, s *SpotlightService) {
+ // Should not panic with nil window
+ s.Hide()
+ assert.False(t, s.IsVisible())
+ },
+ },
+ {
+ name: "IsVisible with nil window",
+ test: func(t *testing.T, s *SpotlightService) {
+ // Should return false with nil window
+ assert.False(t, s.IsVisible())
+ },
+ },
+ }
+
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ service := NewSpotlightService(nil)
+ tt.test(t, service)
+ })
+ }
+}
diff --git a/vite.config.js b/vite.config.js
index 96bd637..85c7b67 100644
--- a/vite.config.js
+++ b/vite.config.js
@@ -33,5 +33,13 @@ export default defineConfig({
// Ensure @ibm/plex can be resolved
'@ibm/plex': path.resolve(__dirname, 'node_modules/@ibm/plex')
}
+ },
+ build: {
+ rollupOptions: {
+ input: {
+ main: path.resolve(__dirname, 'frontend/index.html'),
+ spotlight: path.resolve(__dirname, 'frontend/spotlight.html'),
+ },
+ },
}
})
\ No newline at end of file