diff --git a/CLI App - Calculator Form/.agents/skills/wds-docs/SKILL.md b/CLI App - Calculator Form/.agents/skills/wds-docs/SKILL.md new file mode 100644 index 0000000..5823999 --- /dev/null +++ b/CLI App - Calculator Form/.agents/skills/wds-docs/SKILL.md @@ -0,0 +1,215 @@ +--- +name: wds-docs +description: Wix Design System component reference. Use when building UI with @wix/design-system, choosing components, or checking props and examples. Triggers on "what component", "how do I make", "WDS", "show me props", component names like Button, Card, Modal, Box, Text, or when importing from @wix/design-system or @wix/wix-ui-icons-common. Also use when looking up spacing tokens (SP1-SP6) or icon names. +compatibility: Requires @wix/design-system package installed in the project. +--- + +# WDS Documentation Navigator + +**Docs path:** `node_modules/@wix/design-system/dist/docs/` + +## CRITICAL: Never Read Entire Files + +Files are 200-900+ lines. Follow the staged discovery flow below. + +--- + +## Stage 1: Find Component + +**Goal:** Search for component by feature/keyword + +```bash +Grep: "table" in components.md +Grep: "form\|input\|validation" in components.md +Grep: "modal\|dialog\|popup" in components.md +``` + +**Output:** Component name + description + do/don'ts + +**Next:** Go to Stage 2 with component name + +--- + +## Stage 2: Get Props + Example List + +**Goal:** Get props AND discover available examples + +```bash +# 2a. Get props (small files OK to read, large files grep) +Read: components/ButtonProps.md # OK if <100 lines +Grep: "### disabled" in components/BoxProps.md -A 3 # Box is huge + +# 2b. List available examples (ALWAYS grep, never read) +Grep: "^### " in components/ButtonExamples.md -n +``` + +**Output from 2b:** +``` +5:### Size +17:### Skin +71:### Affix +123:### Disabled +183:### Loading state +``` + +**Next:** Pick example(s) from list, go to Stage 3 + +--- + +## Stage 3: Fetch Specific Example + +**Goal:** Read only the example you need (~30-50 lines) + +```bash +# Option A: Read with offset (line number from Stage 2) +Read: components/ButtonExamples.md offset=183 limit=40 + +# Option B: Grep with context +Grep: "### Loading state" in components/ButtonExamples.md -A 40 +``` + +**Output:** JSX code example for that specific feature + +--- + +## Stage 4: Icons (when needed) + +```bash +Grep: "Add\|Edit\|Delete\|Search" in icons.md +``` + +--- + +## Flow Summary + +``` +┌─────────────────────────────────────────────────────────┐ +│ Stage 1: Grep components.md for keyword │ +│ → finds: Button, Card, Table... │ +└────────────────────┬────────────────────────────────────┘ + ↓ +┌─────────────────────────────────────────────────────────┐ +│ Stage 2a: Read/Grep {Component}Props.md │ +│ → gets: props with types & descriptions │ +│ │ +│ Stage 2b: Grep "^### " in {Component}Examples.md │ +│ → gets: example names + line numbers │ +│ "5:### Size, 71:### Affix, 183:### Loading" │ +└────────────────────┬────────────────────────────────────┘ + ↓ +┌─────────────────────────────────────────────────────────┐ +│ Stage 3: Read offset=183 limit=40 │ +│ → gets: specific example JSX code │ +└────────────────────────────────────────────────────────┘ +``` + +--- + +## Example Session: Product Page + +```bash +# Stage 1: Find components +Grep: "image\|card\|price" in components.md +→ Image, Card, Text found + +# Stage 2a: Get Card props +Read: components/CardProps.md + +# Stage 2b: List Card examples +Grep: "^### " in components/CardExamples.md -n +→ 5:### Basic, 25:### With media, 60:### Clickable + +# Stage 3: Fetch "With media" example +Read: components/CardExamples.md offset=25 limit=35 +→ Gets Card with Image example code + +# Repeat Stage 2-3 for other components as needed +``` + +**Result:** ~80 lines read instead of 1500+ + +--- + +## Quick Reference + +| Stage | Command | Output | +|-------|---------|--------| +| 1. Find | `Grep: "keyword" in components.md` | Component name | +| 2a. Props | `Read: {Name}Props.md` | Props list | +| 2b. Examples | `Grep: "^### " in {Name}Examples.md` | Example names + lines | +| 3. Fetch | `Read: offset=N limit=40` | Example code | +| 4. Icons | `Grep: "IconName" in icons.md` | Icon exists | + +--- + +## File Sizes + +| File | Lines | Strategy | +|------|-------|----------| +| components.md | ~970 | Grep, never read fully | +| icons.md | ~400 | Grep for specific icon | +| Most Props.md | 30-100 | Read fully OK | +| BoxProps.md | 8000+ | Grep only! | +| Most Examples.md | 100-600 | Grep → offset read | +| PageExamples.md | 940 | Grep → offset read | + +--- + +## Grep Patterns by Use Case + +```bash +# Forms +Grep: "form\|input\|validation" in components.md + +# Layout +Grep: "layout\|page\|card\|box" in components.md + +# Data display +Grep: "table\|list\|badge" in components.md + +# Feedback +Grep: "notification\|toast\|loader" in components.md +``` + +--- + +## Quick Component Mapping (Design → WDS) + +| Design Element | WDS Component | Notes | +|----------------|---------------|-------| +| Rectangle/container | `` | Layout wrapper | +| Text button | `` | Secondary actions | +| Input with label | `` + `` | Wrap inputs | +| Toggle | `` | On/off settings | +| Modal | `` + `` | Use together | +| Grid | `` + `` | Responsive | + +--- + +## Spacing (px → SP conversion) + +When designer specifies pixels, convert to the nearest SP token: + +| Token | Classic | Studio | +|-------|---------|--------| +| `SP1` | 6px | 4px | +| `SP2` | 12px | 8px | +| `SP3` | 18px | 12px | +| `SP4` | 24px | 16px | +| `SP5` | 30px | 20px | +| `SP6` | 36px | 24px | + +```tsx + +``` + +Only use SP tokens for `gap`, `padding`, `margin` - not for width/height. + +--- + +## Imports + +```tsx +import { Button, Card, Image } from '@wix/design-system'; +import { Add, Edit, Delete } from '@wix/wix-ui-icons-common'; +``` diff --git a/CLI App - Calculator Form/.agents/skills/wix-cli-app-validation/SKILL.md b/CLI App - Calculator Form/.agents/skills/wix-cli-app-validation/SKILL.md new file mode 100644 index 0000000..040980a --- /dev/null +++ b/CLI App - Calculator Form/.agents/skills/wix-cli-app-validation/SKILL.md @@ -0,0 +1,176 @@ +--- +name: wix-cli-app-validation +description: Use when testing app readiness, verifying runtime behavior, or validating before releases and after changes in the code. Triggers include validate, test, verify, check readiness, preview validation, build verification, TypeScript compilation. +compatibility: Requires Wix CLI development environment. +--- + +# Wix App Validation + +Validates Wix CLI applications through a four-step sequential workflow: package installation, TypeScript compilation check, build, and preview. + +## Validation Workflow + +Execute these steps sequentially. Stop and report errors if any step fails. + +### Step 1: Package Installation + +Ensure all dependencies are installed before proceeding with the build. + +**Detect package manager:** +- Check for `package-lock.json` → use `npm` +- Check for `yarn.lock` → use `yarn` +- Check for `pnpm-lock.yaml` → use `pnpm` +- Default to `npm` if no lock file is found + +**Run installation command:** + +```bash +# For npm +npm install + +# For yarn +yarn install + +# For pnpm +pnpm install +``` + +**Success criteria:** +- Exit code 0 +- All dependencies installed successfully +- No missing peer dependencies warnings (unless expected) +- `node_modules` directory exists and contains expected packages + +**On failure:** Report the installation errors, [check the debug log](#debug-log-on-errors) for detailed diagnostics, and stop validation. Common issues: +- Network connectivity problems +- Corrupted lock files +- Version conflicts +- Missing Node.js or package manager + +### Step 2: TypeScript Compilation Check + +Run TypeScript compiler to check for type errors. + +**Full project check:** +```bash +npx tsc --noEmit +``` + +**Targeted check (specific files/directories):** + +When validating after implementing a specific extension, you can run TypeScript checks on just those files: + +```bash +# Check specific directory +npx tsc --noEmit src/extensions/dashboard/pages/survey/**/*.ts src/extensions/dashboard/pages/survey/**/*.tsx + +# Check dashboard pages only +npx tsc --noEmit src/extensions/dashboard/pages/**/*.ts src/extensions/dashboard/pages/**/*.tsx + +# Check site widgets only +npx tsc --noEmit src/site/widgets/**/*.ts src/site/widgets/**/*.tsx + +# Check dashboard modals only +npx tsc --noEmit src/extensions/dashboard/modals/**/*.ts src/extensions/dashboard/modals/**/*.tsx + +# Check backend only +npx tsc --noEmit src/backend/**/*.ts +``` + +**When to use targeted checks:** +- After implementing a single extension (faster feedback) +- When debugging type errors in a specific area +- During iterative development + +**When to use full project check:** +- Before final validation +- When changes affect shared types +- Before building/deploying + +**Success criteria:** +- Exit code 0 +- No TypeScript compilation errors +- All type checks pass + +**On failure:** Report the specific TypeScript errors and stop validation. Common issues: +- Type mismatches between expected and actual types +- Missing type declarations for imported modules +- Incorrect generic type parameters +- Properties not existing on declared types +- Incompatible function signatures + +### Step 3: Build Validation + +Run the build command and check for compilation errors: + +```bash +npx wix build +``` + +**Success criteria:** +- Exit code 0 +- No TypeScript errors +- No missing dependencies + +**On failure:** Report the specific compilation errors, [check the debug log](#debug-log-on-errors) for detailed diagnostics, and stop validation. + +### Step 4: Preview Deployment + +Start the preview server: + +```bash +npx wix preview +``` + +**Success criteria:** +- Preview server starts successfully +- Preview URLs are generated (both site and dashboard) + +**URL extraction:** Parse the terminal output to find both preview URLs. Look for patterns like: +- Site preview: `Site preview: https://...` or `Site URL: https://...` +- Dashboard preview: `Dashboard preview: https://...` or `Preview URL: https://...` or `Your app is available at: https://...` + +Extract both URLs and provide them to the user for manual verification. + +**On failure:** Report the preview startup errors, [check the debug log](#debug-log-on-errors) for detailed diagnostics, and stop validation. + +## Validation Report + +After completing all steps, provide a summary: + +**Pass:** +- Dependencies: ✓ All packages installed successfully +- TypeScript: ✓ No compilation errors +- Build: ✓ Compiled successfully +- Preview: ✓ Running at [URL] + +**Fail:** +- Identify which step failed +- Provide specific error messages +- Suggest remediation steps + +## Debug Log on Errors + +When a validation step fails (non-zero exit code, error output, or the CLI crashes/hangs), check `.wix/debug.log` in the project root for the full error trace. **Only read this file when errors occur** — skip it when steps pass or when the terminal output already makes the error clear (e.g. a straightforward TypeScript type error). + +The `.wix/` directory is automatically created by the Wix CLI and contains internal configuration and log files. Don't edit it, but reading `debug.log` for troubleshooting is expected. + +``` +Read: .wix/debug.log + +# If the file is large, read the last 100 lines for the most recent errors +Read: .wix/debug.log (with offset to the end) +``` + +## Common Issues + +| Issue | Cause | Solution | +|-------|-------|----------| +| Package installation fails | Missing lock file, network issues, or corrupted node_modules | Delete `node_modules` and lock file, then reinstall | +| TypeScript compilation fails | Type mismatches, missing declarations, or incorrect types | Fix TypeScript errors shown in `npx tsc --noEmit` output | +| Build fails | TypeScript errors, missing dependencies, or internal CLI error | Fix TypeScript errors in source; for non-obvious failures, check `.wix/debug.log` | +| Preview fails to start | Port conflict, config issue, or internal CLI error | Check `wix.config.json`; if unclear, check `.wix/debug.log` for details | +| Console errors in preview | Runtime exceptions | Check browser console output | +| UI not rendering | Component errors | Review component code and imports | +| CLI error with no clear message | Truncated terminal output | Read `.wix/debug.log` for the full error trace and stack details | +| Mysterious failures after config change | Stale CLI state | Read `.wix/debug.log` to confirm, then delete `.wix/` and rebuild | \ No newline at end of file diff --git a/CLI App - Calculator Form/.agents/skills/wix-cli-backend-api/SKILL.md b/CLI App - Calculator Form/.agents/skills/wix-cli-backend-api/SKILL.md new file mode 100644 index 0000000..5fee93a --- /dev/null +++ b/CLI App - Calculator Form/.agents/skills/wix-cli-backend-api/SKILL.md @@ -0,0 +1,246 @@ +--- +name: wix-cli-backend-api +description: Creates HTTP endpoints for Wix CLI apps. Use only when the user specifically asks for a backend endpoint. Use when building REST API endpoints, backend HTTP handlers, or server-side logic. Triggers include backend API, HTTP endpoint, HTTP methods, form handling, file uploads. +compatibility: Requires Wix CLI development environment. +--- + +# Wix Backend API Builder + +Creates HTTP endpoints for Wix CLI applications — server-side routes that handle HTTP requests, process data, and return responses. HTTP endpoints are powered by Astro endpoints and are automatically discovered from the file system. + +**Key facts:** + +- Files live in `src/pages/api/` with `.ts` extension +- Cannot be added via `npm run generate` — create files directly +- Don't appear on the Extensions page in the app dashboard +- No extension registration needed (auto-discovered) +- Replace the legacy "HTTP functions" from the previous Wix CLI for Apps + +## Use Cases + +Use HTTP endpoints when you need to: + +- Build REST APIs with multiple HTTP methods +- Integrate with external APIs or services +- Handle complex form submissions or file uploads +- Serve dynamic content (images, RSS feeds, personalized data) +- Access runtime data or server-side databases + +## File Structure and Naming + +### Basic Endpoint + +File path determines the endpoint URL: + +``` +src/pages/api/.ts +``` + +### Dynamic Routes + +Use square brackets for dynamic parameters: + +``` +src/pages/api/users/[id].ts → /api/users/:id +src/pages/api/posts/[slug].ts → /api/posts/:slug +src/pages/api/users/[userId]/posts/[postId].ts → /api/users/:userId/posts/:postId +``` + +## HTTP Methods + +Export named functions for each HTTP method. Type with `APIRoute` from `astro`. Each handler receives a `request` object and returns a `Response`: + +```typescript +import type { APIRoute } from "astro"; + +export const GET: APIRoute = async ({ request }) => { + console.log("Log from GET."); // This message logs to your CLI. + return new Response("Response from GET."); // This response is visible in the browser console +}; + +export const POST: APIRoute = async ({ request }) => { + const data = await request.json(); + console.log("Log POST with body: ", data); // This message logs to your CLI. + return new Response(JSON.stringify(data)); // This response is visible in the browser console. +}; +``` + +## Request Handling + +### Path Parameters + +```typescript +export const GET: APIRoute = async ({ params }) => { + const { id } = params; // From /api/users/[id] + + if (!id) { + return new Response(JSON.stringify({ error: "ID required" }), { + status: 400, + statusText: "Bad Request", + headers: { "Content-Type": "application/json" }, + }); + } + + // Use id to fetch data +}; +``` + +### Query Parameters + +Use `new URL(request.url).searchParams`: + +```typescript +export const GET: APIRoute = async ({ request }) => { + const url = new URL(request.url); + const search = url.searchParams.get("search"); + const limit = parseInt(url.searchParams.get("limit") || "10", 10); + const offset = parseInt(url.searchParams.get("offset") || "0", 10); + + // Use query parameters +}; +``` + +### Request Body + +Parse JSON body from POST/PUT/PATCH requests: + +```typescript +export const POST: APIRoute = async ({ request }) => { + try { + const body = await request.json(); + const { title, content } = body; + + if (!title || !content) { + return new Response( + JSON.stringify({ error: "Title and content required" }), + { + status: 400, + statusText: "Bad Request", + headers: { "Content-Type": "application/json" }, + } + ); + } + + // Process data + } catch { + return new Response(JSON.stringify({ error: "Invalid JSON" }), { + status: 400, + statusText: "Bad Request", + headers: { "Content-Type": "application/json" }, + }); + } +}; +``` + +### Headers + +```typescript +const authHeader = request.headers.get("Authorization"); +const contentType = request.headers.get("Content-Type"); +``` + +## Response Patterns + +Always return a `Response` object with proper status codes and headers: + +```typescript +// 200 OK +return new Response(JSON.stringify({ data: result }), { + status: 200, + headers: { "Content-Type": "application/json" }, +}); + +// 201 Created +return new Response(JSON.stringify({ id: newId, ...data }), { + status: 201, + headers: { "Content-Type": "application/json" }, +}); + +// 204 No Content (for DELETE) +return new Response(null, { status: 204 }); + +// 400 Bad Request +return new Response(JSON.stringify({ error: "Invalid input" }), { + status: 400, + statusText: "Bad Request", + headers: { "Content-Type": "application/json" }, +}); + +// 404 Not Found +return new Response(JSON.stringify({ error: "Not found" }), { + status: 404, + statusText: "Not Found", + headers: { "Content-Type": "application/json" }, +}); + +// 500 Internal Server Error +return new Response(JSON.stringify({ error: "Internal server error" }), { + status: 500, + statusText: "Internal Server Error", + headers: { "Content-Type": "application/json" }, +}); +``` + +## Frontend Integration + +Call HTTP endpoints from frontend components using Wix's built-in HTTP client (`httpClient.fetchWithAuth()`): + +```typescript +import { httpClient } from "@wix/essentials"; + +// GET request +const baseApiUrl = new URL(import.meta.url).origin; +const res = await httpClient.fetchWithAuth( + `${baseApiUrl}/api/`, +); +const data = await res.text(); + +// POST request +const res = await httpClient.fetchWithAuth( + `${baseApiUrl}/api/`, + { + method: "POST", + body: JSON.stringify({ message: "Hello from frontend" }), + }, +); +const data = await res.json(); +``` + +## Build, Deploy, and Delete + +To take HTTP endpoints to production, build and release your project: + +1. Build the project assets using the [`build`](https://dev.wix.com/docs/wix-cli/command-reference/project-commands/build) command. +2. Optionally create preview URLs using the [`preview`](https://dev.wix.com/docs/wix-cli/command-reference/project-commands/preview) command to share with team members for testing. +3. Release your project using the [`release`](https://dev.wix.com/docs/wix-cli/command-reference/project-commands/release) command. + +Once released, endpoints are accessible at production URLs and handle live traffic. + +To delete an HTTP endpoint, remove the file under `src/pages/api/` and release again. + +## Output Structure + +``` +src/pages/api/ +├── users.ts # /api/users endpoint +├── users/ +│ └── [id].ts # /api/users/:id endpoint +└── posts.ts # /api/posts endpoint +``` + +## Code Quality Requirements + +- Strict TypeScript (no `any`, explicit return types) +- Type all handlers with `APIRoute` from `astro` +- Always return `Response` objects with `JSON.stringify()` for JSON +- Proper HTTP status codes (200, 201, 204, 400, 404, 500) +- Include `Content-Type: application/json` header on JSON responses +- Include `statusText` in error responses +- Handle errors with try/catch blocks +- Validate input parameters and request bodies +- Use async/await for asynchronous operations +- No `@ts-ignore` comments + +## Verification + +After implementation, use [wix-cli-app-validation](../wix-cli-app-validation/SKILL.md) to validate TypeScript compilation, build, preview, and runtime behavior. diff --git a/CLI App - Calculator Form/.agents/skills/wix-cli-backend-event/SKILL.md b/CLI App - Calculator Form/.agents/skills/wix-cli-backend-event/SKILL.md new file mode 100644 index 0000000..483e52f --- /dev/null +++ b/CLI App - Calculator Form/.agents/skills/wix-cli-backend-event/SKILL.md @@ -0,0 +1,124 @@ +--- +name: wix-cli-backend-event +description: Create backend event extensions that respond to Wix events. Use when implementing handlers that run when specific conditions occur on a site. Triggers include event extension, backend event, webhook handler. +compatibility: Requires Wix CLI development environment. +--- + +# Wix CLI Backend Event Extension + +Creates event extensions for Wix CLI applications. Events are triggered when specific conditions occur—on a Wix user's site for app projects, or on your project's site for headless projects. Your project responds using event extensions built on JavaScript SDK webhooks; the CLI subscribes your project to these webhooks. + +Common use cases: run logic when a contact is created, an order is placed, a booking is confirmed, or a blog post is published. + +## Quick Start Checklist + +Follow these steps in order when creating an event extension. + +1. [ ] Create event folder: `src/backend/events//` +2. [ ] Create `.ts` with the SDK event import and handler function +3. [ ] Create `.extension.ts` with `extensions.event()` and a unique UUID +4. [ ] Update `src/extensions.ts` to import and use the new extension + +**User (manual):** Configure app permissions for the event in the app dashboard if required; release a version and trigger the event to test. + +## References + +| Topic | Reference | +| --- | --- | +| Common events (CRM, eCommerce, Bookings, Blog) | [COMMON-EVENTS.md](references/COMMON-EVENTS.md) | + +## Output Structure + +Two files per event ([docs](https://dev.wix.com/docs/wix-cli/guides/extensions/backend-extensions/events/event-extension-files-and-code)). Only **one** handler per event allowed in the app (including dashboard handlers). + +``` +src/backend/events// +├── .extension.ts # Builder: extensions.event({ id, source }) – id is unique GUID +└── .ts # Handler: imports SDK event (e.g. onContactCreated), runs on trigger +``` + +## Implementation Pattern + +### Event builder (`.extension.ts`) + +Use `extensions.event()` from `@wix/astro/builders`. Required fields: `id` (unique GUID), `source` (path to the handler file). + +```typescript +import { extensions } from "@wix/astro/builders"; + +export const eventContactCreated = extensions.event({ + id: "{{GENERATE_UUID}}", + source: "./backend/events/contact-created/contact-created.ts", +}); +``` + +**CRITICAL: UUID Generation** + +The `id` must be a unique, static UUID v4 string. Generate a fresh UUID for each extension—do NOT use `randomUUID()` or copy UUIDs from examples. Replace `{{GENERATE_UUID}}` with a freshly generated UUID like `"a1b2c3d4-e5f6-7890-abcd-ef1234567890"`. + +### Event handler (`.ts`) + +Import the event from the correct SDK module and pass a handler. Wix invokes the handler with the event payload and metadata when the event occurs. Handler signatures are documented in the [JavaScript SDK reference](https://dev.wix.com/docs/sdk). + +```typescript +import { onContactCreated } from "@wix/crm/events"; + +onContactCreated((event) => { + console.log("Contact created:", event.entity); + // Custom logic: sync to CRM, send welcome email, etc. +}); +``` + +Handler can be `async`; ensure errors are caught and logged so one failing handler does not break others. + +## Extension Registration + +**Two steps required.** + +### Step 1: Event builder file + +Create `.extension.ts` inside the event folder (and `.ts` for the handler) as shown in [Implementation Pattern](#implementation-pattern) above. + +### Step 2: Register in main extensions.ts + +**CRITICAL:** Read [wix-cli-extension-registration](../wix-cli-extension-registration/SKILL.md) and add the event extension to `src/extensions.ts` (import and `.use(eventContactCreated)` or equivalent). Without this, the event extension is not active. + +Naming: export names follow `event{CamelCaseName}` (e.g. `eventContactCreated`, `eventOrderPaid`). + +## Elevating Permissions for API Calls + +When calling Wix APIs from inside an event handler, use `auth.elevate` from `@wix/essentials` so the call runs with the right permissions. + +```typescript +import { auth } from "@wix/essentials"; +import { items } from "@wix/data"; + +onContactCreated(async (event) => { + const elevatedQuery = auth.elevate(items.query); + const result = await elevatedQuery("MyCollection").find(); + // Use result +}); +``` + +## Key Constraints + +- **One handler per event** – You cannot have two event extensions for the same event in the app (local or dashboard). +- **Permissions** – Each event may require specific permission scopes; configure them in the app dashboard (Permissions page). +- **Testing** – Release a version with your changes, then perform the action that triggers the event. Some events are not fully testable in local dev. +- **Backend limits** – Event handlers run under backend extension limits (e.g. 1000 CPU ms per request, 20 sub-requests). See [About Backend Extensions](https://dev.wix.com/docs/wix-cli/guides/extensions/backend-extensions/about-backend-extensions). + +## Best Practices + +- **Error handling:** Wrap handler logic in try/catch; log and optionally rethrow or report. +- **Idempotency:** Events may be delivered more than once; design handlers to be idempotent where possible. +- **Logging:** Use `console.log` for debugging; keep production logs minimal and non-sensitive. +- **Performance:** Finish within backend limits; offload heavy work to queues or background jobs if needed. + +## Testing Event Extensions + +1. **Release** a version with your changes. +2. **Trigger** the event by taking an action. + +## Verification + +After implementation, use [wix-cli-app-validation](../wix-cli-app-validation/SKILL.md) to validate TypeScript, build, and preview. diff --git a/CLI App - Calculator Form/.agents/skills/wix-cli-backend-event/references/COMMON-EVENTS.md b/CLI App - Calculator Form/.agents/skills/wix-cli-backend-event/references/COMMON-EVENTS.md new file mode 100644 index 0000000..1ff41ac --- /dev/null +++ b/CLI App - Calculator Form/.agents/skills/wix-cli-backend-event/references/COMMON-EVENTS.md @@ -0,0 +1,84 @@ +# Common Wix Events for CLI Event Extensions + +This reference lists common event types, SDK imports, permissions, and links. For full payload shapes and additional events, see the [JavaScript SDK reference](https://dev.wix.com/docs/sdk). + +## CRM Events + +| Event | Import | Handler Call | Permission | API Reference | +| --- | --- | --- | --- | --- | +| Contact created | `import { contacts } from "@wix/crm"` | `contacts.onContactCreated(handler)` | Read Contacts | [onContactCreated](https://dev.wix.com/docs/api-reference/crm/members-contacts/contacts/contacts/contact-v4/contact-created?apiView=SDK) | +| Contact updated | `import { contacts } from "@wix/crm"` | `contacts.onContactUpdated(handler)` | Read Contacts | [onContactUpdated](https://dev.wix.com/docs/api-reference/crm/members-contacts/contacts/contacts/contact-v4/contact-updated?apiView=SDK) | +| Contact deleted | `import { contacts } from "@wix/crm"` | `contacts.onContactDeleted(handler)` | Read Contacts | [onContactDeleted](https://dev.wix.com/docs/api-reference/crm/members-contacts/contacts/contacts/contact-v4/contact-deleted?apiView=SDK) | + +**Example – contact created:** + +```typescript +import { contacts } from "@wix/crm"; + +contacts.onContactCreated((event) => { + const contact = event.entity; + console.log("New contact:", contact._id, contact.primaryInfo?.email); +}); +``` + +## eCommerce Events + +| Event | Import | Handler Call | Permission | API Reference | +| --- | --- | --- | --- | --- | +| Order created | `import { orders } from "@wix/ecom"` | `orders.onOrderCreated(handler)` | Read Orders | [onOrderCreated](https://dev.wix.com/docs/api-reference/business-solutions/e-commerce/orders/orders/order-created?apiView=SDK) | +| Order approved | `import { orders } from "@wix/ecom"` | `orders.onOrderApproved(handler)` | Read Orders | [onOrderApproved](https://dev.wix.com/docs/api-reference/business-solutions/e-commerce/orders/orders/order-approved?apiView=SDK) | +| Cart created | `import { cart } from "@wix/ecom"` | `cart.onCartCreated(handler)` | Read Orders | [onCartCreated](https://dev.wix.com/docs/api-reference/business-solutions/e-commerce/purchase-flow/cart/cart/cart-created?apiView=SDK) | +| Cart updated | `import { cart } from "@wix/ecom"` | `cart.onCartUpdated(handler)` | Read Orders | [onCartUpdated](https://dev.wix.com/docs/api-reference/business-solutions/e-commerce/purchase-flow/cart/cart/cart-updated?apiView=SDK) | + +**Example – order approved:** + +```typescript +import { orders } from "@wix/ecom"; + +orders.onOrderApproved(async (event) => { + const order = event.data.order; + console.log("Order approved:", order._id); +}); +``` + +## Bookings Events + +| Event | Import | Handler Call | Permission | API Reference | +| --- | --- | --- | --- | --- | +| Booking confirmed | `import { bookings } from "@wix/bookings"` | `bookings.onBookingConfirmed(handler)` | Read bookings calendar - including participants | [onBookingConfirmed](https://dev.wix.com/docs/api-reference/business-solutions/bookings/bookings/bookings-writer-v2/booking-confirmed?apiView=SDK) | +| Booking canceled | `import { bookings } from "@wix/bookings"` | `bookings.onBookingCanceled(handler)` | Read bookings calendar - including participants | [onBookingCanceled](https://dev.wix.com/docs/api-reference/business-solutions/bookings/bookings/bookings-writer-v2/booking-canceled?apiView=SDK) | + +**Example – booking confirmed:** + +```typescript +import { bookings } from "@wix/bookings"; + +bookings.onBookingConfirmed((event) => { + const booking = event.data.booking; + console.log("Booking confirmed:", booking._id); +}); +``` + +## Blog Events + +| Event | Import | Handler Call | Permission | API Reference | +| --- | --- | --- | --- | --- | +| Post created | `import { posts } from "@wix/blog"` | `posts.onPostCreated(handler)` | Read Blog | [onPostCreated](https://dev.wix.com/docs/api-reference/business-solutions/blog/posts-stats/post-created?apiView=SDK) | +| Post updated | `import { posts } from "@wix/blog"` | `posts.onPostUpdated(handler)` | Read Blog | [onPostUpdated](https://dev.wix.com/docs/api-reference/business-solutions/blog/posts-stats/post-updated?apiView=SDK) | + +**Example – post created:** + +```typescript +import { posts } from "@wix/blog"; + +posts.onPostCreated((event) => { + const post = event.entity; + console.log("Post created:", post._id, post.title); +}); +``` + +## Payload Shape + +The event envelope structure varies by API — the path to the main entity differs (e.g., `event.entity`, `event.data.order`). Use TypeScript and your IDE for autocomplete and type safety. See each event's API reference link above for the exact payload shape. + +All envelopes include a **metadata** object with context such as event ID, entity ID, timestamp, and instance ID. diff --git a/CLI App - Calculator Form/.agents/skills/wix-cli-dashboard-modal/SKILL.md b/CLI App - Calculator Form/.agents/skills/wix-cli-dashboard-modal/SKILL.md new file mode 100644 index 0000000..92e10ea --- /dev/null +++ b/CLI App - Calculator Form/.agents/skills/wix-cli-dashboard-modal/SKILL.md @@ -0,0 +1,292 @@ +--- +name: wix-cli-dashboard-modal +description: Use when adding popup forms, confirmations, or detail views to Wix dashboards; creating reusable dialog components across dashboard pages; showing context-specific information in overlays; opening modals from dashboard pages; or passing data between dashboard pages and modals. Do NOT use for static content (use dashboard pages instead) or site-facing UI (use site widgets/embedded scripts). +compatibility: Requires Wix CLI development environment. +--- + +## Overview + +Dashboard modals are popup dialogs triggered from dashboard pages or plugins. They consist of three files and use the Dashboard SDK for lifecycle control via `openModal()` and `closeModal()`. + +## Quick Reference + +| Task | Method | Example | +|------|--------|---------| +| Create modal | Create 3 files in `src/dashboard/modals//` | See File Structure below | +| Open modal | `dashboard.openModal()` | `openModal({ modalId: "modal-id" })` | +| Pass data to modal | `params` in `openModal()` | `params: { userId: "123" }` | +| Read data in modal | `observeState()` | `dashboard.observeState((state) => { ... })` | +| Close modal | `dashboard.closeModal()` | `closeModal()` | +| Return data to parent | Pass data to `closeModal()` | `closeModal({ ... })` | +| Wait for modal close | `modalClosed` Promise | `const { modalClosed } = openModal(...);` | + +## File Structure + +Create **three files** in `src/dashboard/modals//`: + +1. **`extensions.ts`** - Builder configuration with modal ID, title, dimensions, component path +2. **`.tsx`** - React component rendering modal content +3. **`.config.ts`** - Configurable modal properties (title, width, height) + +## Implementation + +### Creating a Modal + +Create the three required files: + +**1. `extensions.ts`** - Modal builder configuration: + +```typescript +import { extensions } from '@wix/astro/builders'; +import config from './.config.ts'; + +export default extensions.dashboardModal({ + id: "{{GENERATE_UUID}}", + title: config.title, + width: config.width, + height: config.height, + component: './extensions/dashboard/modals//.tsx', +}); + +``` + +**CRITICAL: UUID Generation** + +The `id` must be a unique, static UUID v4 string. Generate a fresh UUID for each extension - do NOT use `randomUUID()` or copy UUIDs from examples. Replace `{{GENERATE_UUID}}` with a freshly generated UUID like `"a1b2c3d4-e5f6-7890-abcd-ef1234567890"`. + +Builder fields: +| Field | Type | Description | +|-------|------|-------------| +| id | string | Unique modal ID (GUID). Used with `openModal()` | +| title | string | Modal title shown in project dashboard | +| width | number | Initial width while loading | +| height | number | Initial height while loading | +| component | string | Path to the modal content `.tsx` file | + +**2. `.tsx`** - Modal content component: + +```typescript +import type { FC } from 'react'; +import { dashboard } from '@wix/dashboard'; +import { + WixDesignSystemProvider, + Text, + Box, + CustomModalLayout, +} from '@wix/design-system'; +import '@wix/design-system/styles.global.css'; +import config from './.config.ts'; + +const { width, height, title } = config; + +// To open your modal, call `openModal` with your modal id. +// e.g. +// import { dashboard } from '@wix/dashboard'; +// function MyComponent() { +// return ; +// } +const Modal: FC = () => { + return ( + + dashboard.closeModal()} + secondaryButtonOnClick={() => dashboard.closeModal()} + title={title} + subtitle="Edit this file to customize your modal" + content={ + + Wix CLI Modal + + } + /> + + ); +}; + +export default Modal; +``` + +**3. `.config.ts`** - Configurable properties: + +```typescript +export default { + title: "My Modal", + width: 600, + height: 400, +}; +``` + +Then register in `src/extensions.ts`: + +```typescript +import { dashboardmodalYourModal } from './dashboard/modals//extensions.ts'; + +export default app() + .use(dashboardmodalYourModal) + // ... other extensions +``` + +### Opening a Modal + +```typescript +import { dashboard } from "@wix/dashboard"; + +// Simple open +const result = await dashboard.openModal({ + modalId: "your-modal-id", // From .extension.ts id field +}); + +// Pass data to modal via params +const result = await dashboard.openModal({ + modalId: "your-modal-id", + params: { + userId: user.id, + itemData: complexObject, // Objects are passed directly, no encoding needed + }, +}); + +// Get notified when the modal is closed +const { modalClosed } = dashboard.openModal({ + modalId: "your-modal-id", +}); +const result = await modalClosed; // Resolves with data from closeModal() +``` + +### Receiving Data in Modal + +Use `observeState()` to access data passed via `params` in `openModal()`: + +```typescript +import { dashboard } from "@wix/dashboard"; +import { useEffect, useState } from "react"; + +function MyModal() { + const [modalData, setModalData] = useState<{ userId?: string; itemData?: any }>({}); + + useEffect(() => { + dashboard.observeState((state) => { + // Access custom data passed through openModal params + if (state.userId) { + setModalData({ + userId: state.userId, + itemData: state.itemData, + }); + } + }); + }, []); + + return
User ID: {modalData.userId}
; +} +``` + +### Closing Modal + +Call `closeModal()` from within the modal extension to close it. Optionally pass data back to the opener. + +```typescript +import { dashboard } from "@wix/dashboard"; + +// Close without returning data +dashboard.closeModal(); + +// Close with custom return data +dashboard.closeModal({ saved: true, itemId: "123" }); +``` + +| Parameter | Type | Description | +|-----------|------|-------------| +| closeData | Serializable (optional) | Data to pass back to the modal opener. Must be cloneable via [structured clone algorithm](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Structured_clone_algorithm). | + +**Supported types:** strings, numbers, booleans, plain objects, arrays, Dates, Maps, Sets, ArrayBuffers. +**Not supported:** functions, DOM nodes, class instances with methods, Symbols, Promises. + +**Returns:** `void` + +### Customizing Modal + +Edit `.config.ts` for organized settings: + +```typescript +export default { + title: 'User Settings', + width: 600, + height: 500, +} +``` + +Import in `.tsx`: + +```typescript +import config from './modal.config.ts'; + +export default function MyModal() { + return ( + + ); +} +``` + +## Common Mistakes + +| Mistake | Fix | +|---------|-----| +| Can't find modal ID | Check `.extension.ts` file's `id` field | +| Forgetting to register in `extensions.ts` | Import and `.use()` the modal | +| Using `extensionId` instead of `modalId` | Use `modalId` in `openModal()` | +| Can't access params in modal | Use `dashboard.observeState()` to read passed data | +| Modal won't close | Use `dashboard.closeModal()` from `@wix/dashboard` | + +## Real-World Example + +```typescript +// Dashboard Page: Opening edit modal +const handleEdit = async (item: Item) => { + dashboard.openModal({ + modalId: "edit-item-modal-guid", + params: { + itemId: item._id, + item: item, // Objects passed directly via params + }, + }); +}; + +// Modal: Receiving and saving data +export default function ItemEditModal() { + const [formData, setFormData] = useState(null); + + useEffect(() => { + dashboard.observeState((state) => { + if (state.item) { + setFormData(state.item); + } + }); + }, []); + + const handleSave = async () => { + // Save logic + dashboard.showToast({ message: "Saved!", type: "success" }); + dashboard.closeModal(); + }; + + return ( + dashboard.closeModal()} + primaryButtonOnClick={handleSave} + content={/* form fields */} + /> + ); +} +``` + +## Verification + +After implementation, use [wix-cli-app-validation](../wix-cli-app-validation/SKILL.md) to validate TypeScript compilation, build, preview, and runtime behavior. diff --git a/CLI App - Calculator Form/.agents/skills/wix-cli-dashboard-page/SKILL.md b/CLI App - Calculator Form/.agents/skills/wix-cli-dashboard-page/SKILL.md new file mode 100644 index 0000000..b005bfe --- /dev/null +++ b/CLI App - Calculator Form/.agents/skills/wix-cli-dashboard-page/SKILL.md @@ -0,0 +1,486 @@ +--- +name: wix-cli-dashboard-page +description: Use when building admin interfaces, management pages, CRUD operations, or dashboard configuration UIs. Triggers include dashboard, admin panel, data management, settings pages. +compatibility: Requires Wix CLI development environment. +--- + +# Wix Dashboard Page Builder + +Creates full-featured dashboard page extensions for Wix CLI applications. Dashboard pages appear in the Wix site owner's dashboard and enable site administrators to manage data, configure settings, and perform administrative tasks. + +--- + +## Quick Start Checklist + +Follow these steps in order when creating a dashboard page: + +1. [ ] Create page folder: `src/dashboard/pages//` +2. [ ] Create `page.tsx` with WDS components wrapped in `WixDesignSystemProvider` +3. [ ] Create `extensions.ts` with `extensions.dashboardPage()` and unique UUID +4. [ ] Update `src/extensions.ts` to import and use the new extension + +## Capabilities + +### Data Operations (Wix Data SDK) + +See [Wix Data Reference](references/WIX_DATA.md) for complete documentation. + +**Summary:** + +- Read: `items.query('Collection').filter/sort.limit.find()` → `{ items, totalCount, hasNext }` +- Write: `items.insert | update | remove`. Ensure collection permissions allow the action + +**Query methods:** `eq`, `ne`, `gt`, `ge`, `lt`, `le`, `between`, `contains`, `startsWith`, `endsWith`, `hasSome`, `hasAll`, `isEmpty`, `isNotEmpty`, `and`, `or`, `not`, `ascending`, `descending`, `limit`, `skip`, `include` + +### Dashboard APIs + +See [Dashboard API Reference](references/DASHBOARD_API.md) for complete documentation including all methods, page IDs, and examples. + +**Key methods:** + +- `dashboard.navigate()` - Navigate between dashboard pages +- `dashboard.observeState()` - Receive contextual state and environmental information +- `dashboard.showToast()` - Display toast notifications +- `dashboard.openModal()` - Open dashboard modal extensions (see [wix-cli-dashboard-modal](../wix-cli-dashboard-modal/SKILL.md)) +- `dashboard.navigateBack()` - Navigate back to previous page +- `dashboard.getPageUrl()` - Get full URL for a dashboard page +- `dashboard.openMediaManager()` - Open Wix Media Manager +- `dashboard.onBeforeUnload()` - Register beforeunload handler +- `dashboard.addSitePlugin()` - Add site plugin to slots +- `dashboard.setPageTitle()` - Set page title in browser tab +- `dashboard.onLayerStateChange()` - Handle foreground/background state changes + +**CRITICAL: Using Modals in Dashboard Pages** + +When you need to display popup forms, confirmations, detail views, or any dialog overlays from a dashboard page, you **MUST** use dashboard modals, not regular React modals or WDS Modal components. + +- **Use dashboard modals** for: edit forms, delete confirmations, detail views, settings dialogs, any popup content +- **Do NOT use** WDS `Modal` component or custom React modal implementations +- **See [wix-cli-dashboard-modal](../wix-cli-dashboard-modal/SKILL.md)** for complete implementation guide + +Dashboard modals are opened using `dashboard.openModal()` and provide proper integration with the dashboard lifecycle, state management, and navigation. + +**Ecom Navigation:** See [Ecom Navigation Reference](references/ECOM_NAVIGATION.md) for ecom-specific navigation helpers. + +### Embedded Script Configuration API + +When building a dashboard page to configure an embedded script, see [Dynamic Parameters Reference](references/DYNAMIC_PARAMETERS.md) for complete implementation guide. + +**Key points:** + +- Use `embeddedScripts` from `@wix/app-management` +- Parameters are returned as strings - handle type conversions when loading +- All parameters must be saved as strings (convert booleans/numbers to strings) +- Use `withProviders` wrapper when dynamic parameters are present + +## Files and Code Structure + +Dashboard pages live under `src/dashboard/pages`. Each page has its own folder. + +**File structure:** + +- `src/dashboard/pages//page.tsx` — page component + +**Key metadata fields:** + +- `id` (string, GUID): Unique page ID used to register the page +- `title` (string): Used for browser tab and optional sidebar label +- `additionalRoutes` (string[], optional): Extra routes leading to this page +- `sidebar.disabled` (boolean, optional): Hide page from sidebar (default false) +- `sidebar.priority` (number, optional): Sidebar ordering; lower is higher priority +- `sidebar.whenActive.selectedPageId` (string, optional): Which page appears selected when this page is active +- `sidebar.whenActive.hideSidebar` (boolean, optional): Hide sidebar when this page is active + +## WDS Provider Usage + +Wrap your dashboard page component with `WixDesignSystemProvider` to enable WDS components and theming. You must also import the global CSS styles for WDS components to render correctly. + +```typescript +import { WixDesignSystemProvider } from "@wix/design-system"; +import '@wix/design-system/styles.global.css'; + +export default function () { + return ( + + + + + + + + + ); +} +``` + +**Note:** When using dynamic parameters, use the `withProviders` wrapper instead. See [Dynamic Parameters](references/DYNAMIC_PARAMETERS.md) for details. + +## Hard Constraints + +- Do NOT invent or assume new types, modules, functions, props, events, or imports. +- Use only entities explicitly present in the provided references or standard libraries already used in this project. +- If something is missing, call it out explicitly and provide a minimal TODO or clearly marked placeholder rather than creating it. +- Always verify component availability before using it in your generated code +- If you need a component not in the list, use a basic HTML element or create a simple custom component instead +- **Do NOT use WDS `Modal` component or custom React modal implementations** - Always use dashboard modals (see [wix-cli-dashboard-modal](../wix-cli-dashboard-modal/SKILL.md)) for any popup dialogs, forms, or overlays + +## Examples + +### Data Management Table + +**Request:** "Create a dashboard page to manage blog posts" + +**Output:** Page with table displaying posts, search toolbar, add/edit/delete actions, empty state. + +### Settings Form + +**Request:** "Build a settings page for notification preferences" + +**Output:** Page with form fields, save button with toast confirmation, unsaved changes warning. + +### Order Management + +**Request:** "Create an admin panel for customer orders" + +**Output:** Page with orders table, status badges, filters, detail dashboard modal (using [wix-cli-dashboard-modal](../wix-cli-dashboard-modal/SKILL.md)), status update actions. + +### Embedded Script Configuration + +**Request:** "Create a settings page for the coupon popup embedded script" + +**Output:** Page with form fields for popup headline, coupon code, minimum cart value, and enable toggle. Uses `embeddedScripts` API to load/save parameters. + +```typescript +// Key pattern for embedded script configuration pages +import { embeddedScripts } from "@wix/app-management"; + +// Load on mount +useEffect(() => { + const load = async () => { + const script = await embeddedScripts.getEmbeddedScript(); + const data = script.parameters || {}; + setOptions({ + headline: data.headline || "Default", + enabled: data.enabled === "true", + threshold: Number(data.threshold) || 0, + }); + }; + load(); +}, []); + +// Save handler +const handleSave = async () => { + await embeddedScripts.embedScript({ + parameters: { + headline: options.headline, + enabled: String(options.enabled), + threshold: String(options.threshold), + }, + }); + dashboard.showToast({ message: "Saved!", type: "success" }); +}; +``` + +## Extension Registration + +**Extension registration is MANDATORY and has TWO required steps.** + +### Step 1: Create Page-Specific Extension File + +Each dashboard page requires an `extensions.ts` file in its folder: + +**File:** `src/dashboard/pages//extensions.ts` + +```typescript +import { extensions } from "@wix/astro/builders"; + +export const dashboardpageMyPage = extensions.dashboardPage({ + id: "{{GENERATE_UUID}}", + title: "My Page", + routePath: "my-page", + component: "./dashboard/pages/my-page/page.tsx", +}); +``` + +**CRITICAL: UUID Generation** + +The `id` must be a unique, static UUID v4 string. Generate a fresh UUID for each extension - do NOT use `randomUUID()` or copy UUIDs from examples. Replace `{{GENERATE_UUID}}` with a freshly generated UUID like `"a1b2c3d4-e5f6-7890-abcd-ef1234567890"`. + +| Property | Type | Description | +| ----------- | ------ | ---------------------------------------------------------------------------------------------------- | +| `id` | string | Unique static UUID v4 (generate fresh - see note above) | +| `title` | string | Display title in dashboard sidebar | +| `routePath` | string | URL path segment. Lowercase letters, numbers, dashes, and slashes only. Must NOT start with a slash. | +| `component` | string | Relative path to the page component (.tsx) | + +### Step 2: Register in Main Extensions File + +**CRITICAL:** After creating the page-specific extension file, you MUST read [wix-cli-extension-registration](../wix-cli-extension-registration/SKILL.md) and follow the "App Registration" section to update `src/extensions.ts`. + +**Without completing Step 2, the dashboard page will not appear in the Wix dashboard.** + +## Common Mistakes - Do NOT + +**API confusion with other extension types:** + +| WRONG (Embedded Script API) | CORRECT (Dashboard Page API) | +| --------------------------- | ---------------------------- | +| `name: "..."` | `title: "..."` | +| `source: "..."` | `component: "..."` | +| `route: "..."` | `routePath: "..."` | + +Do NOT copy field names from embedded script or other extension registrations. Dashboard pages use `title`, `routePath`, and `component`. + +## Code Quality Requirements + +### TypeScript Quality Guidelines + +- Generated code MUST compile with zero TypeScript errors under strict settings: strict, noImplicitAny, strictNullChecks, exactOptionalPropertyTypes, noUncheckedIndexedAccess +- Prefer type-narrowing and exhaustive logic over assertions; avoid non-null assertions (!) and unsafe casts (as any) +- Treat optional values, refs, and array indexing results as possibly undefined and handle them explicitly +- Use exhaustive checks for unions (e.g., switch with a never check) and return total values (no implicit undefined) +- Do NOT use // @ts-ignore or // @ts-expect-error; fix the types or add guards instead + +### Core Principles + +- Do NOT invent or assume new types, modules, functions, props, events, or imports +- NEVER use mocks, placeholders, or TODOs in any code +- ALWAYS implement complete, production-ready functionality +- Follow Wix dashboard page patterns and best practices precisely +- Handle all edge cases and error scenarios appropriately + +### Code Quality Standards + +- Prefer TypeScript with appropriate typing +- Use consistent naming conventions +- Include error handling where appropriate +- Add documentation for complex or non-obvious logic +- Prefer async/await for asynchronous operations +- Consider destructuring for cleaner code when beneficial +- Return well-structured response objects + +### Error Handling + +- Always implement proper error handling in dashboard pages +- Return appropriate error responses when data is invalid +- Log errors appropriately for debugging using console.error +- Handle network timeouts and external service failures + +### Output Constraints + +**Token limits:** Your max output is ~10,000 tokens. You MUST plan your response to stay well under this limit. + +- If making a large file (>300 lines), split it into multiple smaller files with imports. +- If editing a large section (>100 lines), break it into multiple smaller edit operations. +- Count your output before responding - if it seems too long, reduce scope and prioritize. + +**Brevity rules:** Minimize output tokens while maintaining quality and correctness. + +- Do NOT add README.md, documentation files, or markdown files unless explicitly requested. +- Do NOT add excessive comments in code - only add comments where truly necessary for clarity. +- Do NOT re-output unchanged files or duplicate existing code. +- Do NOT generate placeholder code like "// TODO: implement" - provide working implementations. +- Only output files that are directly required for the task. + +**Modular code strategy:** When generating substantial code, split into multiple smaller files with imports: + +- Extract utilities/helpers into separate files +- Separate types/interfaces into dedicated type files +- Keep each component/function focused (~50-100 lines max) + +## Verification + +After implementation completes, the **wix-cli-orchestrator** will run validation using [wix-cli-app-validation](../wix-cli-app-validation/SKILL.md). + +## API Spec Support + +When an API specification is provided, you can make API calls to those endpoints. See [API Spec Reference](references/API_SPEC.md) for details on how to use API specs in dashboard pages. + +--- + +## Layout Guidelines + +Layout determines how users interact with your dashboard content. It establishes the structure, hierarchy, and rhythm of your dashboard page, contributing to the overall coherence and user experience. By making mindful and calculated choices in how you organize your content, users can move around more smoothly, saving time and frustration when completing tasks. + +### Design Principles + +To create dashboard pages optimized for user experience, follow these design principles: + +1. **Consistent:** Maintain repetitive layouts and content patterns for intuitive and easy-to-read pages. +2. **Inclusive:** Create layouts and content that adapt well to various screen sizes. +3. **Balanced:** Emphasize the priority of regions and content elements through deliberate management of size and white space. +4. **Connected:** Minimize the distance between related regions or content elements to enhance cohesion and navigation. + +--- + +### Screen Size + +Dashboard pages are designed to accommodate various screen sizes rather than being tailored to one specific resolution. The primary content should be at the top of the page to ensure users immediately understand the purpose of the page. + +> **Note:** Content displayed in the top 600 pixels of the page will be visible for the majority of users. + +--- + +### Base Unit + +The base unit establishes the increment by which all elements and measurements are multiplied. This practice ensures consistency in the spacing and sizing of design elements. + +> **Note:** The design system is based on a 6px unit. + +The layout grid, spacing tokens, and nearly all visual elements and sizes adhere to multiples of six (6, 12, 18, 24, etc.), with only occasional exceptions. + +| TOKEN | SIZE | USE FOR | +|-------|------|---------| +| SP1 | 6px | Spacing between components | +| SP2 | 12px | Spacing between components | +| SP3 | 18px | Spacing between components | +| SP4 | 24px | Spacing between components, layout spacing | +| SP5 | 30px | Layout spacing | +| SP6 | 36px | Layout spacing | +| SP7 | 42px | Layout spacing | +| SP8 | 48px | Layout spacing | +| SP10 | 54px | Layout spacing | +| SP11 | 60px | Layout spacing | + +--- + +### Layout Structure + +To best design the layout for your app, understand: + +1. The core frame of the app (Application frame) +2. The placement and alignment of each segment within the grid layout (Grid layout) +3. The content to appear in the grid (Common layouts) + +#### Application Frame + +The dashboard app frame is used by the majority of Wix applications settings. Dashboard pages consist of 4 areas: + +| AREA | USAGE | +|------|-------| +| 1. Global navigation (top bar) | General navigation at the top of a page which allows users to navigate between different environments. Full width container with a fixed height of 48px. | +| 2. Sidebar navigation | Local navigation of an environment. Container with a fixed width of 228px. | +| 3. Content area | Page content area with a width that's adaptive to screen size. | +| 4. Side panel (optional) | An optional panel that shows additional actions or content associated with the content of a page. Fixed width of 420px. Can either overlay the main content area or push it from the right side. | + +**Side Panel Guidelines:** +- Let the side panel overlay main content when it contains supplementary actions or settings, such as data filters +- Push main content with the side panel when users must see the full context to continue + +--- + +#### Grid Layout + +The system uses a fluid grid layout with a fixed maximum width. It uses columns that scale and resize the content accordingly. + +The grid is constructed from 3 elements: +- **Columns** - The design system uses a 12-column grid. Column width is fluid and changes according to the page width. +- **Gutters** - The gaps between the columns. Gutter width has a fixed value of 24px. +- **Margins** - By default, a page's content area has 48px side margins and a 48px bottom margin. + +**Grid Specifications:** +- Minimum content area width: 864 pixels (each grid column is 50px wide) +- Maximum content area width: 1248px (each column is 82px wide) +- Wider screens maintain 1248px content width with side margins stretching to center content +- Use 24px gap between cards both vertically and horizontally + +--- + +### Common Layouts + +Page layouts can be divided by intention into the following types: + +#### 1. Form Layouts + +Forms are pages that allow users to fill in data or edit existing data. Two variations: + +- **2/3 layout with optional sidebar (8/4 column split)** - Provides flexibility to expose primary and secondary content at the same time +- **Full width (12 columns)** - Supports advanced product needs with complex structures + +Both form page layouts include mandatory **Save** and **Cancel** actions in the header and footer areas. + +**2/3 Layout Best Practices:** +- Use to expose primary and secondary content at the same time +- Keep the form easy to scan and comprehend +- Display a live content preview on the side (widget can be sticky) +- Use 8 columns for forms to keep text lines and input fields narrow for quicker reading +- Bring actions closer to related titles (e.g., toggle switches near settings) + +**Full Width Layout Best Practices:** +- Use when a form includes complex structures such as tables +- Use for list items that contain many data columns + +**Combining Layouts:** +- Avoid coast-to-coast inputs; keep inputs to 2/3 width of a card, or lay them out in two columns +- Use white space on the right side for content preview +- Use full width for tables with many columns and dividers that separate sections + +> **Note:** A column is easy to read if it is wide enough to accommodate an average of 10 words per line. + +#### 2. Display Layouts + +Display pages showcase data or content without accepting input from users. They can contain minor actions such as data filtering. + +**List (Table):** +- Tables display large data sets and provide users with a quick overview +- Use a 12-column layout for tables +- Enables users to manipulate and act on a data set + +**List (Grid) Options:** +- 2 columns (6/6 split) - For items with lengthy descriptions +- 3 columns (4/4/4 split) - For visual items with multiple data types +- 4 columns (3/3/3/3 split) - For user-generated galleries and collections, reveals up to 50% more content above the fold than 4/4/4 +- Custom - For mixed content needs + +**Grid Selection Considerations:** +- Total amount of items to show +- Content to display in each list item +- What objects the list items reflect (match physical shapes when applicable) + +**Dashboards:** +Display different types of data on a specific topic using a combination grid. + +Column span recommendations: +- **3 or 4 columns** - For list items, previews, marketing, statistics, and charts +- **12 columns (full width)** - For tables and marketing content +- **8 columns** - For lists, tables with few data columns, setup wizards, and charts +- **6 columns** - For lists, tables with few data columns, and statistics + +**Empty States:** +- Use full width layout for empty state of a page +- Indicates feature/product has no data yet, all data cleared, or not set up yet +- Include clear CTA indicating what to do to fill the page +- Can combine with other layout elements such as tabs, statistics widgets, or marketing cards + +#### 3. Marketing Layouts + +Marketing pages promote new products that site owners are not aware of yet. Built using the `` component split into 2 columns: + +1. Promo messaging +2. Visual representation of product and features + +Optional footer area can display features or testimonials list. + +#### 4. Wizard Layouts + +Wizard pages guide users through setting up a product or feature. They split complex forms into steps for easier completion. + +**Entry Points:** +- A marketing page +- A marketing card +- The primary action of a page +- An empty state + +> **Note:** Wizards must have a final destination. After completing all steps, users should end up on a relevant page: a dashboard, a details page, or any other relevant location. + +--- + +### Related WDS Components + +- `` - Main page wrapper +- `` - Grid layout container +- `` - Marketing page wrapper +- `` - Content container with 24px gaps between cards diff --git a/CLI App - Calculator Form/.agents/skills/wix-cli-dashboard-page/references/API_SPEC.md b/CLI App - Calculator Form/.agents/skills/wix-cli-dashboard-page/references/API_SPEC.md new file mode 100644 index 0000000..60c34ca --- /dev/null +++ b/CLI App - Calculator Form/.agents/skills/wix-cli-dashboard-page/references/API_SPEC.md @@ -0,0 +1,138 @@ +# API Spec Reference + +Guide for using API specifications in dashboard pages. + +## Overview + +You will be given an API specification under the "API SPEC" spec. The dashboard page code you generate can make API calls to these endpoints to read and write data. You cannot write the API calls yourself, you must use the API calls provided in the API SPEC. + +## Example API Spec + +```json +{ + "name": "Todo Management API", + "description": "A simple API for managing todo items with CRUD operations", + "endpoints": [ + { + "id": "get-todos", + "path": "/api/todos", + "method": "GET", + "name": "Get All Todos", + "description": "Retrieve all todo items", + "parameters": [], + "response": { + "statusCode": 200, + "type": "array" + } + }, + { + "id": "create-todo", + "path": "/api/todos", + "method": "POST", + "name": "Create Todo", + "description": "Create a new todo item", + "parameters": [ + { + "name": "todo", + "type": "object", + "required": true, + "location": "body" + } + ], + "response": { + "statusCode": 201, + "type": "object" + } + }, + { + "id": "update-todo", + "path": "/api/todos/[id]", + "method": "PUT", + "name": "Update Todo", + "description": "Update an existing todo item", + "parameters": [ + { + "name": "id", + "type": "string", + "required": true, + "location": "path" + }, + { + "name": "todo", + "type": "object", + "required": true, + "location": "body" + } + ], + "response": { + "statusCode": 200, + "type": "object" + } + } + ], + "dataModels": [ + { + "name": "Todo", + "properties": { + "id": { + "type": "string", + "required": true + }, + "title": { + "type": "string", + "required": true + }, + "description": { + "type": "string", + "required": false + }, + "completed": { + "type": "boolean", + "required": true + }, + "createdAt": { + "type": "string", + "required": true + } + } + } + ] +} +``` + +## Example Output Code + +```typescript +// Reading data - GET request +async function getTodos(): Promise { + const response = await fetch('/api/todos'); + const data = await response.json(); + return data; +} + +// Writing data - POST request with data model entity +async function createTodo(todo: Omit): Promise { + const response = await fetch('/api/todos', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify(todo), + }); + const data = await response.json(); + return data; +} + +// Writing data - PUT request with data model entity +async function updateTodo(id: string, todo: Partial): Promise { + const response = await fetch(`/api/todos/${id}`, { + method: 'PUT', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify(todo), + }); + const data = await response.json(); + return data; +} +``` diff --git a/CLI App - Calculator Form/.agents/skills/wix-cli-dashboard-page/references/DASHBOARD_API.md b/CLI App - Calculator Form/.agents/skills/wix-cli-dashboard-page/references/DASHBOARD_API.md new file mode 100644 index 0000000..c43d5c4 --- /dev/null +++ b/CLI App - Calculator Form/.agents/skills/wix-cli-dashboard-page/references/DASHBOARD_API.md @@ -0,0 +1,573 @@ +# Dashboard API Reference + +Complete reference for the `@wix/dashboard` host module. + +## navigate() + +Host Module '@wix/dashboard' 'navigate()' method for navigating between dashboard pages. + +**Method parameters:** +- `destination`: Destination +- `options?`: NavigationOptions + +**Destination object:** +- `pageId` (string): ID of the page to navigate to +- `relativeUrl` (string): Optional. URL segment appended to the base page URL. Can include path segments, query string, and fragment. + +**Navigation options:** +- `displayMode` ("main" | "overlay" | "auto"): How to display the destination page. "auto" (default) loads in current context. +- `history` ("push" | "replace"): Optional. Whether to push a new history entry or replace the current one. + +**Example:** +```typescript +import { dashboard } from '@wix/dashboard'; +// Navigate to your own app's page with some internal state +dashboard.navigate({pageId: , relativeUrl: "/an/internal/state?param=value"}) +// Navigate to a relative route of the current page +dashboard.navigate({ relativeUrl: "/some/internal/route" }); +// Navigate to the Products List page +dashboard.navigate({ pageId: "0845ada2-467f-4cab-ba40-2f07c812343d" }); +// Add a button that navigates to the Products List page (React/TSX) +const GoToProductsButton = () => ( + +); +// Open bookings settings page in an overlay page +dashboard.navigate( + { pageId: "bcdb42a8-2423-4101-add6-cbebc1951bc2" }, + { displayMode: "overlay" }, +); +// Navigate to the home page as a main page from inside an overlay page +dashboard.navigate( + { pageId: "2e96bad1-df32-47b6-942f-e3ecabd74e57" }, + { displayMode: "main" }, +); +``` + +## Page IDs + +Common Wix dashboard page IDs useful for navigation. Use with `dashboard.navigate({ pageId })`. + +**Selection policy:** +- When asked to navigate by page name, choose the closest match from the list below. +- Prefer exact match; otherwise use common aliases/synonyms. +- Do not default to "Home" unless the user asks for home or no reasonable match exists. +- If multiple names share the same ID, treat them as aliases. + +**ID formats:** +- Most IDs are GUIDs. Some are slugs (e.g., "wix-restaurants-orders-new", "restaurants_orders"). Use them as-is. + +**Aliases/synonyms (non-exhaustive):** +- Products List: product list, products page, catalog, product catalog, inventory products +- Automatic Discounts ↔ Coupons + +**Page IDs:** +- Abandoned Carts: bb407b4d-6df5-4607-81df-6cd9ecf5d229 +- Activity: dfad075a-1ab3-458c-a77b-8fc9f509eaca +- Accept Payments Page: abe22932-49cb-43e0-b22d-8e342482113e +- Automatic Discounts: ed0163bf-ddeb-4dbe-8042-648b44bcbaac +- Automations: 67028126-3a56-43dd-9ed2-0c9c875e739c +- Back in Stock Requests: 74ff0096-6e7f-4d40-9f72-e85a2a7d5726 +- Behavior Overview: d53c7001-5056-48d3-81e8-5320f9ef08e4 +- Bookings Settings: bcdb42a8-2423-4101-add6-cbebc1951bc2 +- Blog Overview: a7f877e0-69ac-459f-8b5b-eb7c5e25bad2 +- Blog Writers: b8c96d90-95d6-57de-9a97-0d44c4dfaa96 +- Business Cards: 44a21d57-98a3-486f-9def-5e5f356363b5 +- Business Email Settings: bfd22a01-fc5b-4b53-940d-beaeac065230 +- Contacts List: bdd09dca-7cc9-4524-81d7-c9336071b33e +- Contacts Segments: 0f410434-052f-4edb-8a89-ef564e4465e5 +- Contacts Workflows: 511fe7f0-d0fe-4acb-84bc-b9887e4c92b7 +- Content Manager: 6513755b-2a3b-45b9-8172-99c16e00dfde +- Coupons: ed0163bf-ddeb-4dbe-8042-648b44bcbaac +- Domain Connection: 3aeabb6d-0bc6-4b88-a6ba-3b40096a9c3a +- Email Marketing: 2abbf001-de3d-4b60-a186-28afd3f4c7ac +- Facebook and Instagram Ads: 4ada9d29-ff4d-40b6-802e-97dbd661fd7c +- Find Products to Sell: 958a5f12-e276-4dee-9c05-4aa880f31932 +- Forms & Submissions: 8b307095-20c5-48a8-a36e-6c7ad6f11552 +- Forum Categories: d6d2f9e8-43a7-4781-8e3c-4da93f91ea45 +- Forum Posts: 6ce59b51-95ce-485e-a158-42686d647793 +- Forum Settings: b1b1df78-6340-4ef0-b576-5dab0b2602e3 +- Gift Card Overview: 99bc7dcb-312d-4462-9ff6-ca764606cfbb +- Gift Card Sales: 8bae1213-e243-4cd5-910b-9c3d4b6c0750 +- Google Business Profile: 98b6ed3b-9ac6-486f-a347-0de6f9929965 +- Home: 2e96bad1-df32-47b6-942f-e3ecabd74e57 +- Import Contacts Page: 135f0c27-4fb9-453d-8479-7f8762227234 +- Inbox: 1ae6068f-0fe6-4986-975a-3565f4147fbe +- Integrations: 02bba945-0d2c-4173-838e-cf186d57d9c8 +- Inventory: 59a8855e-515a-49c1-894a-035731d2fd44 +- Invoices: 237552b5-9d8e-4bdc-a39b-6e70a83caea0 +- Language and Region Settings: f1f1abd6-3949-4633-a6dc-74337c70957a +- Logs: 4576d2f4-7da6-4ad1-ad51-418e09847e34 +- Loyalty Program: c3ad65e1-0b0f-4da9-a8a3-6025c321da50 +- Manage Loyalty Program: 978a178c-a739-46ed-93c3-60afaabd6ca4 +- Marketing Home: 6617e07c-c3f3-45eb-9280-b41f23f259dd +- Manage Installed Apps: ad471122-7305-4007-9210-2a764d2e5e57 +- Monitoring: e1a20a83-1908-4bae-9214-b9e26e6fda2a +- Music Library: 5da7cc0e-93e2-49cf-b8fa-de46be1af7b7 +- My Albums: ef237a91-20b1-4e62-bbd7-31e28bda04a0 +- Notification You Get - settings: e96a4137-cf9d-42ba-96c2-b583fce6f00b +- Notifications You Send - settings: e6576ec0-802c-4816-a84e-a206a10e7b3d +- New Order Form: a0278851-325c-4115-9bf1-08848468ad45 +- Orders List: 8107f05f-d646-4c81-be90-adf28d321398 +- Payments Dashboard: efe44d1d-506c-46c7-a770-e212b697acf0 +- Price Quotes: 9f45b934-56a1-4036-96eb-4f6e2ff15c73 +- Pricing Plans: e7b7afbb-6d4e-46b2-8bd6-0af78dc9d21e +- Products List: 0845ada2-467f-4cab-ba40-2f07c812343d +- Programs: ccf2fe64-86c2-44a3-8e97-eed943c49b58 +- Recurring Invoices: 5bfd82d5-51e0-4dc0-aab9-9b384bf15f5d +- Restaurants Menus (New): 37c3de13-6224-42ee-bd80-308d452a2c7d +- Restaurants Menus: b278a256-2757-4f19-9313-c05c783bec92 +- Restaurant Orders (New): wix-restaurants-orders-new +- Orders: 2c7daf4b-dbe7-4e00-9ffd-9b44b1884507 +- Restaurant Orders: restaurants_orders +- Pricing Plans Settings: ce9562b2-f279-4c45-bee8-af3870d27069 +- Roles And Permissions: ca4fc2e2-e8fc-4b4c-bfa0-32479931a00a +- Sales Overview: 98052ea0-bfe4-4095-88ba-d5c65c03254b +- Secrets Manager: f94ac43e-52c4-4564-b1da-68df51b9e614 +- Settings Page: 50103805-f706-428a-ab43-04579324d067 +- SEO - Get Found on Google: baf8b254-72c1-417b-a546-ecc9d869aa71 +- SEO Overview: 721868b6-1d4d-4a40-a876-786f6cbfffcc +- Shipping and Delivery Settings: 26128445-061b-4dfc-bc44-fd53b13dd687 +- Site Alerts: cabc24b1-fb28-445f-b38f-4db49aa26a58 +- Site History: 122ec73e-4e5d-4c3a-ad62-3f62bdb31e0f +- Site Groups: 04c7e480-f1ad-4742-81f6-ac0edfd8a350 +- Site Insights: 7f57c576-7911-46cf-abee-cd8905e59a21 +- Site Reports: 66aeefcd-3e60-4b41-8991-934c5ee331ec +- Site Members: c696eca6-7489-40ae-8c41-815cea571b53 +- Social Media Marketing: 36f17da6-ba4a-4657-af44-a45196771850 +- Staff Management: a4f36fac-ea18-483b-8236-095e29fcb726 +- New Staff Member Page: 3e6d608b-bbc2-4e72-a1ef-4d441bb113ad +- Subscriptions: 79dbb935-d823-4feb-9272-ef2cbcf2aafd +- Table Reservations: e4d65aa4-30ba-4700-ad47-28765d4cf3bc +- Tasks & Reminders: e1d6190c-bb9b-41b8-aa67-6024d19442e1 +- Tax Settings: 7f43cf15-e14a-48f7-a7fa-9d0d1b1a6f02 +- Triggered Emails: 9b111e6f-76c4-48e9-89cb-99e804ce6d31 +- New Triggered Email form: bf982c96-9bb7-49e1-8116-be03aa1fc0d5 +- Video Library: a9e63e77-29c6-4822-8687-51fa4bdd2279 +- Website Settings: 29570214-f230-4228-9209-f09efb53f768 +- Wix App Market: e839f784-0e31-45e6-8de8-426824a6dc2d + +## observeState() + +Host Module '@wix/dashboard' 'observeState()' method to receive contextual state and environmental information for dashboard pages, widgets, and modals. The observer runs on initialization and whenever the state is updated. + +**Method parameters:** +- `observer`: Observer — callback receiving (componentParams, environmentState) + +**Observer:** +- `componentParams`: P | PageParams — Data sent to your component by its host. For dashboard pages rendered by the platform, this is PageParams +- `environmentState`: EnvironmentState — Information about the user's environment + +**Page params:** +- `location`: PageLocation — Information about the location of the rendered page + +**Environment state:** +- `locale` (string): User's locale (ISO 639-1) +- `pageLocation` (PageLocation): Deprecated. Information about the currently rendered page location + +**Page location:** +- `pageId` (string): ID of the current page +- `pathname` (string): Any parts of the current URL path appended to the page's base URL path +- `search` (string, optional): Current URL query string +- `hash` (string, optional): Current URL fragment identifier + +**Example:** +```typescript +import { dashboard } from '@wix/dashboard'; + +// Receive state passed by your host +dashboard.observeState((componentParams, environmentState) => { + console.log(componentParams, environmentState); +}); + +// Receive user's locale +dashboard.observeState((_, { locale }) => { + console.log('locale:', locale); +}); + +// Handle internal page routes +dashboard.observeState((pageParams, environmentState) => { + // This value is logged on initialization and whenever either of the componentParams or environmentState objects change. + const { pathname, search } = pageParams.location; + if (pathname.startsWith("/list")) { + const queryParams = new URLSearchParams(search); + const sortBy = queryParams.get("sortBy"); + console.log("Show items list sorted by", sortBy); + } else if (pathname.startsWith("/item")) { + const { itemId } = pathname.match("/item/(?.*)").groups; + console.log("Show item with id", itemId); + } + console.log("Unknown route"); +}); +``` + +## showToast() + +Host Module '@wix/dashboard' 'showToast()' displays a toast notification from a dashboard page or widget. Up to 3 toasts show at once; additional toasts may be queued. + +**Method parameters:** +- `config`: ToastConfig — Toast configuration options + +**Toast config:** +- `message` (string): Text to display +- `type` ("standard" | "success" | "warning" | "error"): Icon and message type. Default: standard +- `priority` ("low" | "normal" | "high"): Display priority. Default: normal +- `timeout` ("none" | "normal"): Auto-dismiss after ~6s if 'normal' +- `onToastSeen` (() => void, optional): Called when the toast is seen +- `onCloseClick` (() => void, optional): Called when the toast close button is clicked +- `action` (ToastAction, optional): call-to-action displayed in the toast + +**Toast action:** +- `text` (string): Text that appears in the call-to-action. +- `uiType` ("button" | "link"): The type of call-to-action +- `onClick` (() => void): Callback function to run after the call-to-action is clicked. +- `removeToastOnClick` (boolean): Whether to remove the toast after click + +**Returns:** +An object with a method to remove the toast programmatically +`{ remove: () => void }` + +**Example:** +```typescript +import { dashboard } from '@wix/dashboard'; + +// Display a success toast when a product is updated +dashboard.showToast({ + message: "Product updated successfully!", + type: "success", +}); + +// Display an error toast with a 'Learn more' link +dashboard.showToast({ + message: "Product update failed.", + timeout: "none", + type: "error", + priority: "low", + action: { + uiType: "link", + text: "Learn more", + removeToastOnClick: true, + onClick: () => { + // Logic to run when the user clicks the 'Learn more' link. + console.log("Learn more clicked!"); + }, + }, +}); + +// Remove a displayed toast +const { remove } = dashboard.showToast({ + message: "Product updated successfully!", + type: "success", + timeout: "none", +}); + +// Remove the toast. +remove(); +``` + +## openModal() + +Host Module '@wix/dashboard' 'openModal()' opens a dashboard modal extension on your app's dashboard page. + +**Notes:** +- Does not work when developing sites or building apps with Blocks. +- Requires a dashboard modal extension to be implemented first. +- Avoid using relative CSS height units (e.g., 'vh') in extensions opened by this method. + +**Method parameters:** +- `modalInfo`: ModalInfo — Information about the dashboard modal to open + +**Modal info:** +- `modalId` (string): ID of the dashboard modal extension to open +- `params` (Record, optional): Custom data to pass into the modal (accessible via observeState in the modal) + +**Returns:** +Promise that resolves when the modal is closed. +`{ modalClosed: Promise }` + +**Example:** +```typescript +import { dashboard } from '@wix/dashboard'; + +// Open a modal +await dashboard.openModal({ + modalId: 'your-modal-id', +}); + +// Pass extra data when opening a modal +await dashboard.openModal({ + modalId: 'your-modal-id', + params: { firstName: "Name" }, +}); + +// Get notified when the modal is closed (continue after it closes) +const { modalClosed } = dashboard.openModal({ + modalId: "1d52d058-0392-44fa-bd64-ed09275a6fcc", +}); +modalClosed.then((result) => { + if (result) { + console.log("The modal was closed and returned the value:", result); + } else { + console.log("The modal was closed without any data."); + } +}); +``` + +## navigateBack() + +Host Module '@wix/dashboard' 'navigateBack()' navigates the user back to the previous dashboard page (equivalent to the browser back button). + +**Signature:** +No parameters. + +**Example:** +```typescript +import { dashboard } from '@wix/dashboard'; + +// Navigate back to the previous page +dashboard.navigateBack(); +``` + +## getPageUrl() + +Host Module '@wix/dashboard' 'getPageUrl()' returns the full URL for a dashboard page. + +**Method parameters:** +- `destination`: Destination — URL destination details + +**Destination object:** +- `pageId` (string): ID of the page to link to +- `relativeUrl` (string, optional): URL segment appended to the base page URL. Can include path segments, query string, and fragment + +**Returns:** +The full URL (string) of the dashboard page with the provided relativeUrl appended. +`Promise` + +**Example:** +```typescript +import { dashboard } from '@wix/dashboard'; + +// Get the URL of the dashboard's home page with a query string +const pageUrl = await dashboard.getPageUrl({ + pageId: "0845ada2-467f-4cab-ba40-2f07c812343d", + relativeUrl: "?referral=widget", +}); +``` + +## openMediaManager() + +Host Module '@wix/dashboard' 'openMediaManager()' opens the Wix Media Manager in a modal to let users pick media files. Developer Preview. + +**Method parameters:** +- `options?`: Options — Optional Media Manager options + +**Options:** +- `category` (string, optional): Media type to display. Supported: "IMAGE", "VIDEO", "MUSIC", "DOCUMENT", "VECTOR_ART", "3D_IMAGE". Default: all except "3D_IMAGE" +- `multiSelect` (boolean, optional): Whether multiple files can be selected. Default: false + +**Returns:** +A promise that resolves to an object with a single key called items. The value of that key is an array of file descriptor objects for the selected media files. +`Promise<{ items: Array }>` + +**File descriptor:** +FileDescriptor is the full schema describing a Media Manager file, including IDs, timestamps, media-type, URLs, status, labels, and a media-specific payload. + +**Typical fields:** +- `_id` (string): File GUID +- `_createdDate` (Date): Creation time +- `_updatedDate` (Date): Last update time +- `displayName` (string): File name as shown in Media Manager +- `mediaType` (ARCHIVE | AUDIO | DOCUMENT | IMAGE | MODEL3D | OTHER | UNKNOWN | VECTOR | VIDEO): Media file type +- `url` (string): Static URL of the file +- `thumbnailUrl` (string): Thumbnail URL +- `sizeInBytes` (string): File size in bytes +- `parentFolderId` (string): ID of the file's parent folder. +- `siteId` (string): Site GUID where the media is stored +- `private` (boolean): Whether file is private +- `operationStatus` (FAILED | READY | PENDING): Upload/processing status +- `state` (DELETED | OK): File state +- `hash` (string): File hash +- `labels` (string[]): User/AI labels +- `sourceUrl` (string): URL where the file was uploaded from. +- `media` (object): One of the following variants with specific fields + - archive: { _id: string; filename: string; sizeInBytes: string; url: string; urlExpirationDate: Date } + - audio: { _id: string; assets: string[]; bitrate: number; duration: number; format: string; sizeInBytes: string } + - document: string + - image: { caption: string; colors: { palette: Array<{ hex: string; rgb: { r: number; g: number; b: number } }>; prominent: { hex: string; rgb: { r: number; g: number; b: number } }; }; faces: Array<{ confidence: number; height: number; width: number; x: number; y: number }>; image: string; previewImage: string; } + - model3d: { _id: string; altText: string; filename: string; sizeInBytes: string; thumbnail: string; url: string; urlExpirationDate: Date } + - vector: { caption: string; colors: { palette: Array<{ hex: string; rgb: { r: number; g: number; b: number } }>; prominent: { hex: string; rgb: { r: number; g: number; b: number } }; }; faces: Array<{ confidence: number; height: number; width: number; x: number; y: number }>; image: string; previewImage: string; } + - video: string + +**Example:** +```typescript +import { dashboard } from '@wix/dashboard'; + +// Open a media manager modal allowing multiple image selection +const chosenMediaItems = await dashboard.openMediaManager({ + multiSelect: true, +}); +console.log("You have chosen: ", chosenMediaItems.items); +``` + +## onBeforeUnload() + +Host Module '@wix/dashboard' 'onBeforeUnload()' registers a beforeunload handler for a dashboard page, modal, or plugin extension. The callback runs when the user is about to navigate away or the browsing context is unloading. Calling event.preventDefault() pauses navigation and shows a warning dialog about unsaved data. + +**Signature:** +`onBeforeUnload(callback: (event: { preventDefault: () => void }) => void): { remove: () => void }` + +**Method parameters:** +- `callback`: (event: { preventDefault: () => void }) => void — Called when the beforeunload event fires + +**Notes:** +- Do not assume the beforeunload event will always fire or that a confirmation dialog will always appear; behavior varies by browser. + +**Returns:** +An object with a remove() method to unregister the handler +`{ remove: () => void }` + +**Example:** +```typescript +import { dashboard } from '@wix/dashboard'; + +// Prompt for confirmation before unloading unsaved data +const { remove } = dashboard.onBeforeUnload((event) => { + // Check if there's unsaved data on the page + if (unsavedPageData) { + event.preventDefault(); + } +}); +``` + +## addSitePlugin() + +Host Module '@wix/dashboard' 'addSitePlugin()' adds a site plugin to one of the slots supported in an app created by Wix. You can target a specific slot or rely on prioritized slots configured in your app's dashboard. + +**Notes:** +- Developer Preview. API is subject to change. +- Requires a site plugin extension to be configured first. + +**Method parameters:** +- `pluginId`: string — ID of your site plugin (from the extension's settings in your app's dashboard) +- `options`: addSitePluginOptions — Options for adding the site plugin + +**Add site plugin options:** +- `placement?`: PluginPlacement — Details of the slot to add the plugin to. If omitted, the plugin is added to the first available slot based on your installation settings. If all prioritized slots are occupied, it won't be added + +**Plugin placement:** +- `appDefinitionId`: string — ID of the Wix app hosting the widget and slot (see list of apps created by Wix) +- `widgetId`: string — ID of the host widget in which the slot exists +- `slotId`: string — ID of the slot in the host widget + +**Returns:** +Resolves on success. See Errors for possible rejection reasons +`Promise` + +**Errors:** +- 3001: Slot occupied +- 3002: Slot not found +- 3003: Error adding plugin +- 3004: Error replacing existing plugin +- 3005: Error loading modal data +- 3006: Aborted by user +- 3007: Site not published yet + +**Example:** +```typescript +import { dashboard } from '@wix/dashboard'; + +// Add a site plugin to a specific slot +const pluginId = "975bffb7-3c04-42cc-9840-3d48c24e73d5"; +const pluginPlacement = { + appDefinitionId: "13d21c63-b5ec-5912-8397-c3a5ddb27a97", + widgetId: "a91a0543-d4bd-4e6b-b315-9410aa27bcde", + slotId: "slot1", +}; + +dashboard + .addSitePlugin(pluginId, { placement: pluginPlacement }) + .then(() => { + console.log("Plugin added successfully"); + }) + .catch((error) => { + console.error("Error adding plugin:", error); + }); + +// Add a site plugin without specifying a slot (uses prioritized slots) +const pluginId = "975bffb7-3c04-42cc-9840-3d48c24e73d5"; + +dashboard + .addSitePlugin(pluginId, {}) + .then(() => { + console.log("Plugin added successfully"); + }) + .catch((error) => { + console.error("Error adding plugin:", error); + }); +``` + +## setPageTitle() + +Host Module '@wix/dashboard' 'setPageTitle()' sets the title of the current dashboard page in the browser tab. This can only be called from dashboard pages (not plugin extensions). Pass null to reset the title to the default dashboard page title. + +**Method parameters:** +- `pageTitle`: string | null — Title to set (or null to reset) + +**Returns:** +void + +**Example:** +```typescript +import { dashboard } from '@wix/dashboard'; + +// Set a static page title +dashboard.setPageTitle('Orders Overview'); + +// Reset to default dashboard page title +dashboard.observeState((_, environmentState) => { + // Use a regular expression to capture the productId value. + const queryParams = environmentState.pageLocation.search; + const productIdMatch = queryParams.match(/[?&]productId=([^&]+)/); + let productId; + if (productIdMatch) { + productId = productIdMatch[1]; + } + + // If a product ID was found, set the page title to the ID. + if (productId) { + dashboard.setPageTitle("Product: " + productId); + // If no product ID was found, reset the page title to default. + } else { + dashboard.setPageTitle(null); + } +}); +``` + +## onLayerStateChange() + +Host Module '@wix/dashboard' 'onLayerStateChange()' registers a handler fired when a page, modal, or plugin extension moves between foreground and background. Use it to refresh data when coming to foreground and pause resource-intensive work when backgrounded. + +**Method parameters:** +- `callback`: (state: "foreground" | "background") => void — Called whenever the layer state changes + +**Returns:** +An object with remove() to unregister the handler +`{ remove: () => void }` + +**Example:** +```typescript +import { dashboard } from '@wix/dashboard'; + +// Refresh/pause depending on visibility +const { remove } = dashboard.onLayerStateChange((state) => { + if (state === "foreground") { + refreshData(); + } +}); + +// Remove the onLayerStateChange handler when the beforeUnload event is triggered. +dashboard.onBeforeUnload(() => { + remove(); +}); +``` diff --git a/CLI App - Calculator Form/.agents/skills/wix-cli-dashboard-page/references/DYNAMIC_PARAMETERS.md b/CLI App - Calculator Form/.agents/skills/wix-cli-dashboard-page/references/DYNAMIC_PARAMETERS.md new file mode 100644 index 0000000..9da5fde --- /dev/null +++ b/CLI App - Calculator Form/.agents/skills/wix-cli-dashboard-page/references/DYNAMIC_PARAMETERS.md @@ -0,0 +1,269 @@ +# Dynamic Parameters Management + +Complete guide for managing dynamic parameters for embedded scripts in dashboard pages. + +## Description + +This dashboard page manages dynamic parameters for an embedded script. The parameters are configurable values that site owners can set through this dashboard interface, and they will be passed to the embedded script as template variables. + +**IMPORTANT:** Only implement UI for parameters that are relevant to your current use case. Ignore parameters that don't apply to the functionality you're building. It's perfectly fine to not use all parameters if they're not applicable. + +## Implementation Requirements + +### 1. Import embeddedScripts + +- Import embeddedScripts directly from '@wix/app-management' +- Use embeddedScripts.getEmbeddedScript() to load parameters +- Use embeddedScripts.embedScript({ parameters }) to save parameters +- Example: + ```typescript + import { embeddedScripts } from '@wix/app-management'; + ``` + +### 2. Type Definition + +- Create a TypeScript type/interface that includes all the dynamic parameters +- Example: + ```typescript + export type MyScriptOptions = { + headline: string; + text: string; + imageUrl: string; + activationMode: 'active' | 'timed' | 'disabled'; + startDate?: string; + endDate?: string; + }; + ``` + +### 3. State Management + +- Use React useState to manage the parameter values locally +- Initialize with default values for all parameters +- Add separate state for isLoading and isSaving +- Use useEffect to load parameters on mount +- **IMPORTANT:** Parameters are returned as strings from the API, so you must handle type conversions: + * BOOLEAN parameters: Convert from string 'true'/'false' to boolean + * NUMBER parameters: Convert from string to number using Number() + * Other types: Use as-is +- Example: + ```typescript + const [options, setOptions] = useState(defaultOptions); + const [isLoading, setIsLoading] = useState(true); + const [isSaving, setIsSaving] = useState(false); + + useEffect(() => { + const loadSettings = async () => { + try { + const embeddedScript = await embeddedScripts.getEmbeddedScript(); + const data = embeddedScript.parameters as Partial> || {}; + + setOptions((prev) => ({ + ...prev, + textField: data?.textField || prev.textField, + booleanField: data?.booleanField === 'true' ? true : data?.booleanField === 'false' ? false : prev.booleanField, + numberField: Number(data?.numberField) || prev.numberField, + })); + } catch (error) { + console.error('Failed to load settings:', error); + } finally { + setIsLoading(false); + } + }; + + loadSettings(); + }, []); + ``` + +### 4. Loading State + +- Show a Loader component while isLoading is true +- Example: + ```typescript + {isLoading ? ( + + + + ) : ( + // ... form content + )} + ``` + +### 5. Form Components + +- **IMPORTANT:** Only create form fields for parameters relevant to your use case +- Skip parameters that don't apply to the functionality being built +- Create appropriate WDS form fields based on parameter types: + * TEXT → Input component with FormField + * NUMBER → Input component with type="number" + * BOOLEAN → Checkbox or ToggleSwitch + * IMAGE → Custom ImagePicker component (see components/image-picker.tsx) + * DATE → DatePicker component + * SELECT → Dropdown component with options + * URL → Input with URL validation +- Use FormField wrapper for labels and validation messages +- Set required validation based on parameter.required flag +- Show validation errors using FormField status and statusMessage props + +### 6. Save Functionality + +- Add a Save button in the Page.Header actionsBar +- Make handleSave an async function +- **CRITICAL:** All parameters must be passed as STRING values because they are used as template variables in the embedded script +- Convert all values to strings before saving: + * BOOLEAN: Use String(value) or value.toString() + * NUMBER: Use String(value) or value.toString() + * Other types: Already strings, use as-is +- Disable the Save button if required fields are missing or while saving +- Add proper error handling + +### 7. Form Validation + +- Implement validation for required fields +- Show error states on FormField components +- Display clear error messages + +### 8. Layout and Organization + +- Use Card components to group related fields +- Use Box with direction="vertical" for form layout +- Add appropriate spacing with gap props +- Include helpful descriptions using Card subtitle or FormField infoContent +- Consider creating a separate settings component for complex forms + +### 9. Preview Component (Optional but Recommended) + +- If applicable, create a preview component that shows how the configuration will look +- Display the preview alongside the settings form using Layout and Cell components +- The preview should react to parameter changes in real-time + +## Example Implementation + +See the generated site-popup example for a complete reference implementation: +- src/dashboard/withProviders.tsx - Provider wrapper with WDS +- src/dashboard/pages/page.tsx - Dashboard page with parameter management (wrapped with withProviders) +- src/components/site-popup-settings.tsx - Settings form component +- src/types.ts - Type definitions + +Key implementation patterns from the example: +1. withProviders.tsx wraps the component with WixDesignSystemProvider +2. page.tsx exports the component wrapped: export default withProviders(MyComponent) +3. Parameters are saved as individual string fields, not as JSON +4. Parameters are loaded with proper type conversion (string to boolean, string to number, etc.) +5. Use embeddedScripts directly from '@wix/app-management' + +## File Generation Requirements + +When dynamic parameters are present, you MUST generate these files: +1. src/dashboard/withProviders.tsx - Provider wrapper (REQUIRED for WDS) +2. src/dashboard/pages/page.tsx - The main dashboard page component +3. src/types.ts - Type definitions for the parameters (if needed) +4. Any additional component files (settings forms, previews, etc.) + +The withProviders.tsx is NOT optional - it must always be generated when there are dynamic parameters. + +## Provider Wrapper Implementation + +You MUST generate the following file: src/dashboard/withProviders.tsx + +This file is REQUIRED to wrap dashboard components with the Wix Design System provider. + +```typescript +import React from 'react'; +import { WixDesignSystemProvider } from '@wix/design-system'; +import { i18n } from '@wix/essentials'; + +export default function withProviders

(Component: React.FC

) { + return function DashboardProviders(props: P) { + const locale = i18n.getLocale(); + return ( + + + + ); + }; +} + +// Also export as named export for backwards compatibility +export { withProviders }; +``` + +This file must be included in your generated files output. + +## Using Provider Wrapper + +In your dashboard page component (page.tsx): +1. Import the withProviders wrapper: `import withProviders from '../../withProviders';` +2. Import embeddedScripts from '@wix/app-management' +3. DO NOT wrap your component with WixDesignSystemProvider - the provider wrapper does this +4. Export the component wrapped with withProviders: `export default withProviders(MyComponent);` +5. Your component should only contain the Page component and its content, not providers + +Example structure: +```typescript +import { useEffect, useState, type FC } from 'react'; +import { dashboard } from '@wix/dashboard'; +import { embeddedScripts } from '@wix/app-management'; +import { Page, Card, Button, ... } from '@wix/design-system'; +import '@wix/design-system/styles.global.css'; +import withProviders from '../../withProviders'; + +const MyDashboardPage: FC = () => { + const [options, setOptions] = useState(defaultOptions); + const [isLoading, setIsLoading] = useState(true); + const [isSaving, setIsSaving] = useState(false); + + useEffect(() => { + const loadSettings = async () => { + try { + const embeddedScript = await embeddedScripts.getEmbeddedScript(); + const data = embeddedScript.parameters || {}; + // ... update options with data + } catch (error) { + console.error('Failed to load settings:', error); + } finally { + setIsLoading(false); + } + }; + loadSettings(); + }, []); + + const handleSave = async () => { + setIsSaving(true); + try { + await embeddedScripts.embedScript({ parameters: { /* ... */ } }); + dashboard.showToast({ message: 'Saved!', type: 'success' }); + } catch (error) { + console.error('Failed to save:', error); + dashboard.showToast({ message: 'Failed to save', type: 'error' }); + } finally { + setIsSaving(false); + } + }; + + return ( + + {/* Page content - NO WixDesignSystemProvider here */} + + ); +}; + +export default withProviders(MyDashboardPage); +``` + +## Critical Notes + +- Only implement UI for parameters that are relevant to your specific use case - ignore parameters that don't apply +- ALWAYS generate withProviders.tsx when there are dynamic parameters +- ALWAYS wrap the dashboard page export with withProviders() +- DO NOT use WixDesignSystemProvider directly in the dashboard page component - use withProviders instead +- ALWAYS use embeddedScripts directly from '@wix/app-management' +- ALWAYS convert parameter values to strings when saving (embeddedScripts.embedScript must receive all string values in the parameters object) +- ALWAYS convert string parameters back to proper types when loading (e.g., 'true' -> true for booleans, string to number for numbers) +- ALWAYS handle the loading state with isLoading state variable +- ALWAYS handle the saving state with isSaving state variable +- ALWAYS add try/catch blocks for async operations (loading and saving) +- ALWAYS use async/await for embeddedScripts operations +- ALWAYS merge parameter values correctly in useEffect with proper type conversions +- ALWAYS validate required fields and show appropriate error states +- The parameter keys MUST match exactly what is expected in the embedded script template variables +- Each parameter is saved as a separate field, NOT as a JSON string diff --git a/CLI App - Calculator Form/.agents/skills/wix-cli-dashboard-page/references/ECOM_NAVIGATION.md b/CLI App - Calculator Form/.agents/skills/wix-cli-dashboard-page/references/ECOM_NAVIGATION.md new file mode 100644 index 0000000..4897651 --- /dev/null +++ b/CLI App - Calculator Form/.agents/skills/wix-cli-dashboard-page/references/ECOM_NAVIGATION.md @@ -0,0 +1,164 @@ +# Ecom Navigation Reference + +Ecom Extensions Dashboard Pages destination builders for navigating to ecom-related dashboard pages (use with @wix/dashboard navigate). + +## deliveryProfile() + +Ecom Extensions Dashboard Pages 'deliveryProfile()' destination builder for navigating to the Delivery Profile dashboard page. + +**Method parameters:** +- `options`: deliveryProfileOptions + +**Delivery profile options:** +- `deliveryProfileId` (string): The ID of the delivery profile to open in the dashboard. + +**Example:** +```typescript +import { dashboard } from "@wix/dashboard"; +import { pages } from "@wix/ecom/dashboard"; + +dashboard.navigate( + pages.deliveryProfile({ + deliveryProfileId: "delivery-profile-id", + }), +); +``` + +## deliveryProfiles() + +Ecom Extensions Dashboard Pages 'deliveryProfiles()' destination builder for navigating to the Delivery Profiles dashboard page. + +**Request:** +This method does not take any parameters. + +**Example:** +```typescript +import { dashboard } from "@wix/dashboard"; +import { pages } from "@wix/ecom/dashboard"; + +dashboard.navigate( + pages.deliveryProfiles(), +); +``` + +## editDraftOrder() + +Ecom Extensions Dashboard Pages 'editDraftOrder()' destination builder for navigating to the Edit Draft Order dashboard page. + +**Method parameters:** +- `options`: editDraftOrderOptions + +**Edit draft order options:** +- `draftOrderId` (string): The ID of the draft order to open for editing in the dashboard. + +**Example:** +```typescript +import { dashboard } from "@wix/dashboard"; +import { pages } from "@wix/ecom/dashboard"; + +dashboard.navigate( + pages.editDraftOrder({ + draftOrderId: "draft-order-id", + }), +); +``` + +## editOrder() + +Ecom Extensions Dashboard Pages 'editOrder()' destination builder for navigating to the Edit Order dashboard page. + +**Method parameters:** +- `options`: editOrderOptions + +**Edit order options:** +- `orderId` (string): The ID of the order to open for editing in the dashboard. + +**Example:** +```typescript +import { dashboard } from "@wix/dashboard"; +import { pages } from "@wix/ecom/dashboard"; + +dashboard.navigate( + pages.editOrder({ + orderId: "order-id", + }), +); +``` + +## newOrder() + +Ecom Extensions Dashboard Pages 'newOrder()' destination builder for navigating to the New Order dashboard page. + +**Request:** +This method does not take any parameters. + +**Example:** +```typescript +import { dashboard } from "@wix/dashboard"; +import { pages } from "@wix/ecom/dashboard"; + +dashboard.navigate( + pages.newOrder(), +); +``` + +## orderDetails() + +Ecom Extensions Dashboard Pages 'orderDetails()' destination builder for navigating to the Order Details dashboard page. + +**Method parameters:** +- `options`: orderDetailsOptions + +**Order details options:** +- `id` (string): The ID of the order whose details page to open in the dashboard. + +**Example:** +```typescript +import { dashboard } from "@wix/dashboard"; +import { pages } from "@wix/ecom/dashboard"; + +dashboard.navigate( + pages.orderDetails({ + id: "order-id", + }), +); +``` + +## orderList() + +Ecom Extensions Dashboard Pages 'orderList()' destination builder for navigating to the Order List dashboard page. + +**Request:** +This method does not take any parameters. + +**Example:** +```typescript +import { dashboard } from "@wix/dashboard"; +import { pages } from "@wix/ecom/dashboard"; + +dashboard.navigate( + pages.orderList(), +); +``` + +## orderRefund() + +Ecom Extensions Dashboard Pages 'orderRefund()' destination builder for navigating to the Order Refund dashboard page. + +**Method parameters:** +- `options`: orderRefundOptions + +**Order refund options:** +- `orderId` (string): The ID of the order to open the refund page for in the dashboard. + +**Example:** +```typescript +import { dashboard } from "@wix/dashboard"; +import { pages } from "@wix/ecom/dashboard"; + +dashboard.navigate( + pages.orderRefund({ + orderId: "order-id", + }), +); +``` diff --git a/CLI App - Calculator Form/.agents/skills/wix-cli-dashboard-page/references/WIX_DATA.md b/CLI App - Calculator Form/.agents/skills/wix-cli-dashboard-page/references/WIX_DATA.md new file mode 100644 index 0000000..a31f9c1 --- /dev/null +++ b/CLI App - Calculator Form/.agents/skills/wix-cli-dashboard-page/references/WIX_DATA.md @@ -0,0 +1,270 @@ +# Wix Data SDK Reference + +Complete reference for working with Wix Data collections. + +## Installation + +**IMPORTANT**: The `@wix/data` package must be installed as a dependency before use. + +```bash +npm install @wix/data +``` + +### Troubleshooting + +**If you encounter: `Cannot find module '@wix/data'`** + +❌ **WRONG**: Do not create mock implementations or workarounds +✅ **CORRECT**: Install the package using `npm install @wix/data` + +The `@wix/data` package is a real npm package that provides access to Wix Data collections. +It must be installed before TypeScript compilation will succeed. + +## SDK Methods & Interfaces + +| Method Call | Import | TypeScript Signature | Description | +| --- | --- | --- | --- | +| `items.get()` | `import { items } from '@wix/data'` | `(collectionId: string, itemId: string, options?: WixDataGetOptions) => Promise` | Get a single item by ID | +| `items.query()` | `import { items } from '@wix/data'` | `(collectionId: string) => WixDataQuery` | Build a chainable query (call `.find()` to execute) | +| `items.insert()` | `import { items } from '@wix/data'` | `(collectionId: string, item: Partial, options?: WixDataInsertOptions) => Promise` | Add a new item to a collection | +| `items.update()` | `import { items } from '@wix/data'` | `(collectionId: string, item: WixDataItem, options?: WixDataUpdateOptions) => Promise` | Replace an existing item (item MUST include `_id`) | +| `items.save()` | `import { items } from '@wix/data'` | `(collectionId: string, item: Partial, options?: WixDataSaveOptions) => Promise` | Insert or update (upsert) based on `_id` | +| `items.remove()` | `import { items } from '@wix/data'` | `(collectionId: string, itemId: string, options?: WixDataRemoveOptions) => Promise` | Remove an item by ID | +| `items.bulkInsert()` | `import { items } from '@wix/data'` | `(collectionId: string, items: Partial[], options?: WixDataOptions) => Promise` | Insert multiple items (max 1000) | +| `items.bulkUpdate()` | `import { items } from '@wix/data'` | `(collectionId: string, items: WixDataItem[], options?: WixDataBulkUpdateOptions) => Promise` | Update multiple items (max 1000) | +| `items.bulkRemove()` | `import { items } from '@wix/data'` | `(collectionId: string, itemIds: string[], options?: WixDataBulkRemoveOptions) => Promise` | Remove multiple items (max 1000) | +| `items.filter()` | `import { items } from '@wix/data'` | `() => WixDataFilter` | Create a standalone filter (for use with `.or()`, `.and()`, `.not()`) | + +## ⚠️ Common Wrong Method Names (DO NOT USE) + +| ❌ WRONG (does not exist) | ✅ CORRECT | +| --- | --- | +| `items.queryDataItems()` | `items.query("Collection").find()` | +| `items.insertDataItem()` | `items.insert("Collection", data)` | +| `items.updateDataItem()` | `items.update("Collection", data)` | +| `items.removeDataItem()` | `items.remove("Collection", id)` | +| `items.getDataItem()` | `items.get("Collection", itemId)` | +| `items.bulkInsertDataItems()` | `items.bulkInsert("Collection", items)` | + +If you see any method with `DataItem` in the name, it is **wrong**. + +## Full Type Definitions + +### WixDataItem + +```ts +interface WixDataItem { + _id: string; + _createdDate?: Date; // read-only, set by Wix on insert + _updatedDate?: Date; // read-only, set by Wix on insert/update + _owner?: string; // ID of the user who created the item + [key: string]: any; // custom fields from your collection schema +} +``` + +### WixDataResult (returned by `query().find()`) + +```ts +interface WixDataResult { + readonly items: WixDataItem[]; + readonly totalCount: number | undefined; // only when returnTotalCount: true + readonly totalPages: number | undefined; // only when returnTotalCount: true + readonly pageSize: number | undefined; + readonly currentPage: number | undefined; + readonly length: number; + hasNext(): boolean; + hasPrev(): boolean; + next(): Promise; + prev(): Promise; +} +``` + +### WixDataQuery (returned by `items.query()`) + +Chainable query builder. Build filters, then call `.find()`, `.count()`, or `.distinct()`. + +```ts +interface WixDataQuery { + // --- Filters --- + eq(field: string, value: any): WixDataQuery; + ne(field: string, value: any): WixDataQuery; + gt(field: string, value: string | number | Date): WixDataQuery; + ge(field: string, value: string | number | Date): WixDataQuery; + lt(field: string, value: string | number | Date): WixDataQuery; + le(field: string, value: string | number | Date): WixDataQuery; + between(field: string, rangeStart: string | number | Date, rangeEnd: string | number | Date): WixDataQuery; + contains(field: string, value: string): WixDataQuery; + startsWith(field: string, value: string): WixDataQuery; + endsWith(field: string, value: string): WixDataQuery; + hasSome(field: string, values: string[] | number[] | Date[]): WixDataQuery; + hasAll(field: string, values: string[] | number[] | Date[]): WixDataQuery; + isEmpty(field: string): WixDataQuery; + isNotEmpty(field: string): WixDataQuery; + + // --- Logical operators --- + or(filter: WixDataFilter): WixDataQuery; + and(filter: WixDataFilter): WixDataQuery; + not(filter: WixDataFilter): WixDataQuery; + + // --- Sorting --- + ascending(...fields: string[]): WixDataQuery; + descending(...fields: string[]): WixDataQuery; + + // --- Pagination --- + limit(limitNumber: number): WixDataQuery; // default 50, max 1000 + skip(skipCount: number): WixDataQuery; + + // --- Projection --- + fields(...fields: string[]): WixDataQuery; + include(...fields: string[]): WixDataQuery; // include referenced items + + // --- Execute --- + find(options?: WixDataQueryOptions): Promise; + count(options?: WixDataReadOptions): Promise; + distinct(field: string, options?: WixDataQueryOptions): Promise>; +} +``` + +### Options Types + +```ts +interface WixDataOptions { + suppressHooks?: boolean; // skip beforeX/afterX hooks + showDrafts?: boolean; // include draft items + appOptions?: Record; +} + +interface WixDataReadOptions extends WixDataOptions { + language?: string; // IETF BCP 47 language tag + consistentRead?: boolean; // read from primary DB (slower but up-to-date) +} + +interface WixDataQueryOptions extends WixDataReadOptions { + returnTotalCount?: boolean; // populate totalCount/totalPages in results +} + +interface WixDataGetOptions extends WixDataReadOptions { + fields?: string[]; // fields to return + includeReferences?: { field: string; limit?: number }[]; + includeFieldGroups?: string[]; +} + +interface WixDataInsertOptions extends WixDataOptions {} + +interface WixDataUpdateOptions extends WixDataOptions { + condition?: WixDataFilter; // only update if condition is met +} + +interface WixDataSaveOptions extends WixDataOptions {} + +interface WixDataRemoveOptions extends WixDataOptions { + condition?: WixDataFilter; // only remove if condition is met +} + +interface WixDataBulkUpdateOptions extends WixDataOptions { + condition?: WixDataFilter; +} + +interface WixDataBulkRemoveOptions extends WixDataOptions { + condition?: WixDataFilter; +} +``` + +### WixDataBulkResult (returned by bulk operations) + +```ts +interface WixDataBulkResult { + inserted: number; + updated: number; + removed: number; + skipped: number; + errors: WixDataBulkError[]; + insertedItemIds: string[]; + updatedItemIds: string[]; + removedItemIds: string[]; +} + +interface WixDataBulkError extends Error { + message: string; + code: string; + originalIndex: number; // index in the request array + item: WixDataItem | string; // the failed item or ID +} +``` + +## Usage Examples + +```typescript +import { items } from "@wix/data"; + +// --- Get by ID --- +const item = await items.get("MyCollection", "item-id-123"); +// Returns WixDataItem | null + +// --- Query with filters --- +const result = await items.query("MyCollection") + .eq("status", "active") + .gt("price", 10) + .ascending("name") + .limit(20) + .find(); +// result.items: WixDataItem[] + +// --- Compound query with or/and --- +const filter1 = items.filter().eq("status", "pending"); +const filter2 = items.filter().eq("status", "active"); +const result = await items.query("MyCollection") + .or(filter1) + .or(filter2) + .find(); + +// --- Insert --- +const created = await items.insert("MyCollection", { + title: "New Item", + price: 29.99, +}); + +// --- Update (MUST include _id) --- +await items.update("MyCollection", { + _id: "item-id-123", + title: "Updated Title", + price: 39.99, +}); + +// ❌ WRONG — three args +await items.update("MyCollection", "item-id", { title: "x" }); +// ✅ CORRECT — _id inside data object +await items.update("MyCollection", { _id: "item-id", title: "x" }); + +// --- Remove --- +await items.remove("MyCollection", "item-id-123"); + +// --- Bulk Insert --- +const bulkResult = await items.bulkInsert("MyCollection", [ + { title: "Item 1" }, + { title: "Item 2" }, +]); +// bulkResult.inserted: 2, bulkResult.insertedItemIds: [...] +``` + +## Collection Schema Rules + +- Always use the exact field keys defined in your collection schema +- Use the collection ID exactly as defined in the schema +- Use the schema's exact field types for all operations +- Custom fields are stored in the `[key: string]: any` part of `WixDataItem` + +## Permissions + +| Operation | Required Scope | +| --- | --- | +| `get`, `query`, `count`, `distinct` | `SCOPE.DC-DATA.READ` | +| `insert`, `update`, `save`, `remove`, `bulkInsert`, `bulkUpdate`, `bulkRemove` | `SCOPE.DC-DATA.WRITE` | + +## Date/Time Handling + +- **Date (date-only)**: Store as a string in "YYYY-MM-DD" format (as returned by ``). +- **DateTime (date + time)**: Store as a Date object. Accept the YYYY-MM-DDTHH:mm format returned by `` and convert to a Date object using `new Date()`. +- **Time (time-only)**: Store as a string in HH:mm or HH:mm:ss 24-hour format (as returned by ``). +- Use native JavaScript Date methods for parsing, formatting, and manipulating dates/times (e.g., `new Date()`, `toISOString()`, `toLocaleString()`, `toLocaleDateString()`). +- Always validate incoming date/time values and provide graceful fallback or explicit error handling when values are invalid. diff --git a/CLI App - Calculator Form/.agents/skills/wix-cli-dashboard-plugin/SKILL.md b/CLI App - Calculator Form/.agents/skills/wix-cli-dashboard-plugin/SKILL.md new file mode 100644 index 0000000..fa3fdbb --- /dev/null +++ b/CLI App - Calculator Form/.agents/skills/wix-cli-dashboard-plugin/SKILL.md @@ -0,0 +1,226 @@ +--- +name: wix-cli-dashboard-plugin +description: Use when building widgets that extend Wix dashboard pages for first-party business apps. Triggers include dashboard plugin, dashboard slot, extend dashboard page, Wix Stores plugin, Wix Bookings plugin, Wix Blog plugin, observeState, dashboard widget. Do NOT use for standalone dashboard pages (use wix-cli-dashboard-page) or site-facing UI (use site widgets/site plugins). +compatibility: Requires Wix CLI development environment. +--- + +# Wix Dashboard Plugin Builder + +Creates dashboard plugin extensions for Wix CLI applications. Dashboard plugins are interactive widgets that embed into predefined **slots** on dashboard pages managed by Wix first-party business apps (Wix Stores, Wix Bookings, Wix Blog, Wix eCommerce, etc.). + +Dashboard plugins occupy the full width of their slot and maintain dynamic height based on content. + +--- + +## Quick Start Checklist + +Follow these steps in order when creating a dashboard plugin: + +1. [ ] Identify the target slot ID — see [Slots Reference](references/SLOTS.md) +2. [ ] Create plugin folder: `src/extensions/dashboard/plugins//` +3. [ ] Create `.extension.ts` with `extensions.dashboardPlugin()` and unique UUID +4. [ ] Create `.tsx` with React component wrapped in `WixDesignSystemProvider` +5. [ ] Update `src/extensions.ts` to import and use the new extension + +## Architecture + +Dashboard plugins operate through two mechanisms: + +1. **Visual Integration** — Embedding plugin UI inside a supported dashboard page slot +2. **Logical Integration** — Implementing communication between the plugin and the host page's data via `observeState()` + +## Files and Code Structure + +Dashboard plugins live under `src/extensions/dashboard/plugins/`. Each plugin has its own folder. + +``` +src/extensions/dashboard/plugins/ +└── / + ├── .extension.ts # Builder configuration + └── .tsx # React component +``` + +> **Note:** This is the default folder structure created by the CLI. You can move these files to any location within the `src/` folder and update the references in your `extension.ts` file. + +## Plugin Builder Configuration + +### File: `.extension.ts` + +```typescript +import { extensions } from "@wix/astro/builders"; + +export const dashboardpluginMyPlugin = extensions.dashboardPlugin({ + id: "{{GENERATE_UUID}}", + title: "My Dashboard Plugin", + extends: "", + component: "./extensions/dashboard/plugins/my-plugin/my-plugin.tsx", +}); +``` + +**CRITICAL: UUID Generation** + +The `id` must be a unique, static UUID v4 string. Generate a fresh UUID for each extension — do NOT use `randomUUID()` or copy UUIDs from examples. Replace `{{GENERATE_UUID}}` with a freshly generated UUID like `"a1b2c3d4-e5f6-7890-abcd-ef1234567890"`. + +### Builder Fields + +| Field | Type | Description | +|-------|------|-------------| +| `id` | string | Unique plugin ID (GUID). Must be unique across all extensions in the project. | +| `title` | string | Plugin title. Used to refer to the plugin in the project dashboard. | +| `extends` | string | Slot ID of the dashboard page hosting the plugin. See [Slots Reference](references/SLOTS.md). | +| `component` | string | Relative path to the plugin content component (`.tsx` file). | + +### The `extends` Field + +The `extends` field specifies which dashboard page slot hosts your plugin. Each Wix business app exposes slots on its dashboard pages. You must provide the exact slot ID. + +**Important:** Some slots with the same ID appear on different pages within the dashboard. If you create a plugin for a slot that exists on multiple pages, the plugin is displayed on all of those pages. + +For the complete list of available slot IDs, see [Slots Reference](references/SLOTS.md). + +## Plugin Component + +### File: `.tsx` + +The plugin component is a React component that renders within the dashboard page slot. + +```typescript +import type { FC } from "react"; +import { WixDesignSystemProvider, Card, Text } from "@wix/design-system"; +import "@wix/design-system/styles.global.css"; + +const Plugin: FC = () => { + return ( + + + + + + Plugin content goes here. + + + + ); +}; + +export default Plugin; +``` + +### Available Resources in Plugin Components + +- **React** — Component logic and state management +- **Wix SDK** — Access Wix business solutions and site data +- **Wix Dashboard SDK** (`@wix/dashboard`) — Interact with the dashboard page's data passed to the slot +- **Wix Design System** (`@wix/design-system`) — Native-looking React components matching Wix's own dashboard UI + +## Interacting with Dashboard Data + +Use `observeState()` from the Dashboard SDK to receive data from the host dashboard page: + +```typescript +import { dashboard } from "@wix/dashboard"; +import { useEffect, useState } from "react"; + +const Plugin: FC = () => { + const [params, setParams] = useState>({}); + + useEffect(() => { + dashboard.observeState((componentParams) => { + setParams(componentParams); + }); + }, []); + + return ( + + + + Received data: {JSON.stringify(params)} + + + + ); +}; +``` + +### Typed Props from Host Apps + +Some Wix apps expose typed interfaces for their slot parameters. Import them from the app's dashboard package: + +```typescript +import type { plugins } from "@wix/blog/dashboard"; + +type Props = plugins.BlogPosts.PostsBannerParams; + +const Plugin: FC = (props) => { + // props are typed according to the Blog Posts slot contract +}; +``` + +> **Note:** Typed props availability varies by Wix app. Consult the specific app's SDK documentation. Not all slots provide typed parameter interfaces. + +## Extension Registration + +**Extension registration is MANDATORY and has TWO required steps.** + +### Step 1: Create Plugin-Specific Extension File + +Each dashboard plugin requires an `.extension.ts` file in its folder. See [Plugin Builder Configuration](#plugin-builder-configuration) above. + +### Step 2: Register in Main Extensions File + +**CRITICAL:** After creating the plugin-specific extension file, you MUST read [wix-cli-extension-registration](../wix-cli-extension-registration/SKILL.md) and follow the "App Registration" section to update `src/extensions.ts`. + +**Without completing Step 2, the dashboard plugin will not appear on the dashboard page.** + +## Sizing Behavior + +- Dashboard plugins take the **full width** of their slot +- **Height** adjusts dynamically based on content within slot boundaries +- When using Dashboard SDK or dashboard-react SDK, dimensions change dynamically based on contents + +## Troubleshooting + +| Symptom | Cause | Fix | +|---------|-------|-----| +| Plugin not appearing on dashboard page | Missing registration | Import and `.use()` in `src/extensions.ts` | +| Plugin not appearing on dashboard page | Wrong slot ID | Verify `extends` field matches a valid slot ID from [Slots Reference](references/SLOTS.md) | + +## Hard Constraints + +- Do NOT invent or assume new types, modules, functions, props, events, or imports — use only entities explicitly present in the provided references or standard libraries already used in this project +- NEVER use mocks, placeholders, or TODOs in any code — ALWAYS implement complete, production-ready functionality +- The `extends` field MUST contain a valid slot ID from a Wix business app — do NOT invent slot IDs +- Prefer type-narrowing and exhaustive logic over assertions; avoid non-null assertions (`!`) and unsafe casts (`as any`) +- Do NOT use `// @ts-ignore` or `// @ts-expect-error`; fix the types or add guards instead + +## Examples + +### Blog Posts Banner Plugin + +**Request:** "Create a plugin for the Wix Blog posts page that shows a promotional banner" + +**Output:** Plugin targeting slot `46035d51-2ea9-4128-a216-1dba68664ffe` (Blog Posts page) with a Card component displaying promotional content, using `observeState()` to access blog post data. + +### Bookings Staff Calendar Widget + +**Request:** "Add a plugin to the Wix Bookings staff page that shows weekly availability" + +**Output:** Plugin targeting slot `261e84a2-31d0-4258-a035-10544d251108` (Bookings Staff page) with a schedule display component, using `observeState()` to receive staff data. + +### Order Details Plugin + +**Request:** "Create a plugin on the eCommerce order page showing fulfillment status" + +**Output:** Plugin targeting slot `cb16162e-42aa-41bd-a644-dc570328c6cc` (eCommerce Order page) with status badges and fulfillment details, using `observeState()` to access order data. + +### Output Constraints + +**Token limits:** Your max output is ~10,000 tokens. Plan your response to stay under this limit. + +- If making a large file (>300 lines), split it into multiple smaller files with imports +- Only output files that are directly required for the task +- Do NOT add README.md or documentation files unless explicitly requested + +## Verification + +After implementation, use [wix-cli-app-validation](../wix-cli-app-validation/SKILL.md) to validate TypeScript compilation, build, preview, and runtime behavior. diff --git a/CLI App - Calculator Form/.agents/skills/wix-cli-dashboard-plugin/references/SLOTS.md b/CLI App - Calculator Form/.agents/skills/wix-cli-dashboard-plugin/references/SLOTS.md new file mode 100644 index 0000000..f0059e6 --- /dev/null +++ b/CLI App - Calculator Form/.agents/skills/wix-cli-dashboard-plugin/references/SLOTS.md @@ -0,0 +1,294 @@ +# Dashboard Plugin Slots Reference + +Slots are UI placeholders on dashboard pages of Wix first-party business apps. Each slot has a unique ID used in the `extends` field of a dashboard plugin. + +**Key behaviors:** +- Some slots with the same ID appear on different pages. A plugin targeting such a slot is displayed on all pages containing it. +- Slots can host multiple plugins. Ordering varies by slot (see each entry). + +--- + +## Wix Blog + +### Overview Page + +**Slot ID:** `65fae040-bbeb-4c62-ba14-e0ecb5e08661` + +- **Dashboard path:** Blog > Overview +- **Location:** Top of page +- **Parameters:** None +- **Multi-plugin:** Vertical, newest at bottom +- **Use case:** Display blog analytics or quick-access management tools on the overview page. + +### Categories Page + +**Slot ID:** `0a208a9f-3b45-449c-ba8e-13a842ea5b84` + +- **Dashboard path:** Blog > Categories +- **Location:** Top of page +- **Parameters:** None +- **Multi-plugin:** Vertical, newest at bottom +- **Use case:** Display category analytics or bulk category management tools. + +### Posts Page + +**Slot ID:** `46035d51-2ea9-4128-a216-1dba68664ffe` + +- **Dashboard path:** Blog > Posts +- **Location:** Top of page +- **Parameters:** None +- **Multi-plugin:** Vertical, newest at bottom +- **Use case:** Display post analytics or quick-access post management tools. + +### Tags Page + +**Slot ID:** `0e336381-34a3-4f12-86f7-f98ab928f950` + +- **Dashboard path:** Blog > Tags +- **Location:** Top of page +- **Parameters:** None +- **Multi-plugin:** Vertical, newest at bottom +- **Use case:** Display tag analytics or bulk tag management tools. + +--- + +## Wix Bookings + +### Staff Page + +**Slot ID:** `261e84a2-31d0-4258-a035-10544d251108` + +- **Dashboard path:** Settings > Booking Settings > Staff +- **Location:** Top of page +- **Parameters:** + | Name | Type | Description | + |------|------|-------------| + | `staffResourceId` | String | Staff resource ID | + | `scheduleId` | String | Schedule ID | + | `timezone` | String | Time zone | +- **Multi-plugin:** Vertical, newest at top +- **Use case:** Display staff availability analytics or performance metrics. + +### Edit Staff Profile Page + +**Slot ID:** `049fb0fe-cc4a-4e33-b0a9-d8cda8e7a79f` + +- **Dashboard path:** Settings > Booking Settings > Staff > Edit or Add staff member +- **Location:** Top of page +- **Parameters:** + | Name | Type | Description | + |------|------|-------------| + | `staffId` | String | Staff member ID | + | `staffResourceId` | String | Staff resource ID | +- **Multi-plugin:** Vertical, newest at top +- **Use case:** Extend the staff profile editing experience with custom functionality. + +### Services Page + +**Slot ID:** `78cc4a47-8f47-489b-acc2-fd9e4208c8bd` + +- **Dashboard path:** Booking Calendar > Services +- **Location:** Between "Business setup recommendations" and "Service list" +- **Parameters:** None +- **Multi-plugin:** Horizontal, newest furthest left +- **Use case:** Display service analytics or integrate third-party booking tools. + +### Calendar Page — Pre-Collect Payment Modal + +**Slot ID:** `b92f0e25-535f-4bef-b130-8e5abc85b2fe` + +- **Dashboard path:** Booking Calendar > Calendar +- **Location:** Custom modal displayed before the default Collect Payment modal +- **Parameters:** + | Name | Type | Description | + |------|------|-------------| + | `orderId` | String | Order ID | + | `onSuccess()` | `() => Promise` | Progresses to the next modal after successful order update | + | `onCancel()` | `() => void` | Progresses to the next modal without changes | + | `menuOption` | Object | Data for the selected menu item | + | `menuOption.key` | String | `CHARGE_WITH_CREDIT_CARD`, `RECORD_ORDER_MANUAL_PAYMENT`, `CHARGE_WITH_INVOICE`, or `EXTENSION` | + | `menuOption.componentId` | String | Component ID when `EXTENSION` key is triggered | +- **Multi-plugin:** Sequential modals, each appearing before the default modal +- **Use case:** Add items to an order such as additional services, notes, or booking fees like insurance. + +> **Note:** This slot also appears on the Wix eCommerce Order Page. + +### Booking List Page + +**Slot ID:** `0f756363-1659-4929-b4ef-5ff2c458eb7d` + +- **Dashboard path:** Booking Calendar > Booking List +- **Location:** Top of page +- **Parameters:** None +- **Multi-plugin:** Horizontal, newest furthest left +- **Use case:** Add custom widgets or tools at the top of the booking list. + +--- + +## Wix eCommerce + +### Order Page + +**Slot ID:** `cb16162e-42aa-41bd-a644-dc570328c6cc` + +- **Dashboard path:** Sales > Orders > Order +- **Location:** Right side of page, under the "Order info" (customer details) card +- **Parameters:** + | Name | Type | Description | + |------|------|-------------| + | `orderId` | String | Order ID | + | `onOrderUpdate()` | `() => Promise` | Callback that notifies the host page about an order update, prompting a UI refresh | +- **Multi-plugin:** Vertical, newest at bottom +- **Use case:** Display a map with the delivery courier's location for the order. + +### Order Page — Pre-Collect Payment Modal + +**Slot ID:** `b92f0e25-535f-4bef-b130-8e5abc85b2fe` + +- **Dashboard path:** Sales > Orders > Order > Collect Payment +- **Location:** Custom modal displayed before the default Collect Payment modal +- **Parameters:** + | Name | Type | Description | + |------|------|-------------| + | `orderId` | String | Order ID | + | `onSuccess()` | `() => Promise` | Progresses to the next modal after successful order update | + | `onCancel()` | `() => void` | Progresses to the next modal without changes | + | `menuOption` | Object | Data for the selected menu item | + | `menuOption.key` | String | `CHARGE_WITH_CREDIT_CARD`, `RECORD_ORDER_MANUAL_PAYMENT`, `CHARGE_WITH_INVOICE`, or `EXTENSION` | + | `menuOption.componentId` | String | Component ID when `EXTENSION` key is triggered | +- **Multi-plugin:** Sequential modals, each appearing before the default modal +- **Use case:** Add items to an order such as additional items, notes, or extra fees. + +> **Note:** This slot also appears on the Wix Bookings Calendar Page. + +### Edit Order Page — Additional Fees + +**Slot ID:** `057f1726-f0b3-40ef-8903-1bd104e18369` + +- **Dashboard path:** Sales > Orders > Order > More Actions > Edit Order +- **Location:** Right side of page, in the "Order summary" card +- **Parameters:** + | Name | Type | Description | + |------|------|-------------| + | `draftOrderId` | String | ID of the order being edited | + | `onDraftOrderUpdate()` | `() => Promise` | Callback that notifies the host page about a draft order update, prompting a UI refresh | +- **Multi-plugin:** Vertical, newest at bottom +- **Use case:** Manage custom fees for orders — add or remove order fees according to custom business logic. + +--- + +## Wix Events + +### Event Page — Overview Tab + +**Slot ID:** `d2c6965a-7d50-47a0-881a-beb184135df3` + +- **Dashboard path:** Events > Published or Drafts > Event > Overview tab +- **Location:** Bottom of page +- **Parameters:** + | Name | Type | Description | + |------|------|-------------| + | `eventId` | String | Event ID | +- **Multi-plugin:** Vertical at bottom, newest at top +- **Use case:** Display earnings for each ticket type so the site owner can easily compare them. + +### Event Page — Features Tab + +**Slot ID:** `5566727b-e5a2-4a43-a26d-961aa4fe0898` + +- **Dashboard path:** Events > Published or Drafts > Event > Features tab +- **Location:** Features grid (displayed as cards) +- **Parameters:** + | Name | Type | Description | + |------|------|-------------| + | `eventId` | String | Event ID | +- **Multi-plugin:** Cards next to each other in the features grid, newest at top +- **Use case:** Add an FAQ section to the event details. + +### Event Page — Promotion Tab + +**Slot ID:** `bc3b9b99-7a3a-4fb5-946f-078022277b6b` + +- **Dashboard path:** Events > Published or Drafts > Event > Promotion tab +- **Location:** Bottom of page +- **Parameters:** + | Name | Type | Description | + |------|------|-------------| + | `eventId` | String | Event ID | +- **Multi-plugin:** Vertical at bottom, newest at top +- **Use case:** Send promotional emails to customers with abandoned checkouts. + +### Event Page — Settings Tab + +**Slot ID:** `c478b36b-7ce2-4564-afba-c2b0ca14bdea` + +- **Dashboard path:** Events > Published or Drafts > Event > Settings tab +- **Location:** Bottom of page +- **Parameters:** + | Name | Type | Description | + |------|------|-------------| + | `eventId` | String | Event ID | +- **Multi-plugin:** Vertical at bottom, newest at top +- **Use case:** Set up event reminder emails to customers. + +### Event Page — Tickets and Seating Tab + +**Slot ID:** `80b95e22-26db-4063-a31f-76d4bb8797ba` + +- **Dashboard path:** Events > Published or Drafts > Event > Tickets and Seating tab +- **Location:** Right side of page, below "Settings and discounts" +- **Parameters:** + | Name | Type | Description | + |------|------|-------------| + | `eventId` | String | Event ID | +- **Multi-plugin:** Vertical, newest at top +- **Use case:** Add a ticket sales scheduler to review current ticket sale status and set up start/end dates for all ticket sales. + +--- + +## Wix Stores + +### Products Page + +**Slot ID:** `3ca518a6-8ae7-45aa-8cb9-afb3da945081` + +- **Dashboard path:** Catalog > Store Products > Products +- **Location:** Top of page +- **Parameters:** None +- **Multi-plugin:** Horizontal, newest furthest right +- **Use case:** Add custom panels for external service integration or custom analytics tools. + +### Inventory Page + +**Slot ID:** `c9b19070-3e25-4f3d-9d27-4e0f74164835` + +- **Dashboard path:** Catalog > Store Products > Inventory +- **Location:** Above inventory list +- **Parameters:** None +- **Multi-plugin:** Horizontal, newest furthest left +- **Use case:** Sum the total number of available items in each product category. + +--- + +## Wix Restaurants + +### Table Reservations Page + +**Slot ID:** `7f71aacd-0cbf-4b73-9ea5-482e073ea237` + +- **Dashboard path:** Table Reservations +- **Location:** Top of page +- **Parameters:** + | Name | Type | Description | + |------|------|-------------| + | `currentReservationLocation` | Object | Object containing information about the reservation location | + | `reservations` | Array | Array of objects with information about each reservation | + | `requests` | Array | Array of objects with information about requested reservations | +- **Multi-plugin:** Horizontal, newest furthest right +- **Use case:** Display statistics for the currently selected reservation location. + +--- + +## Wix CRM + +No dashboard plugin slots available. CRM only exposes dashboard menu plugin slots. diff --git a/CLI App - Calculator Form/.agents/skills/wix-cli-data-collection/SKILL.md b/CLI App - Calculator Form/.agents/skills/wix-cli-data-collection/SKILL.md new file mode 100644 index 0000000..4202093 --- /dev/null +++ b/CLI App - Calculator Form/.agents/skills/wix-cli-data-collection/SKILL.md @@ -0,0 +1,461 @@ +--- +name: wix-cli-data-collection +description: Use when defining database schemas, creating data collections, or setting up structured data storage. Triggers include CMS, collection, database, schema, data model, fields, relationships, permissions, data structure, entity definition, data extension. +compatibility: Requires Wix CLI development environment. +--- + +# Wix Data Collection Builder + +Creates CMS data collections for Wix CLI apps. The data collections extension allows your app to automatically create CMS collections when it's installed on a site. Collections store structured data that can be accessed from dashboard pages, site pages, backend code, and external applications. + +**Important:** This extension automatically enables the site's code editor, which is required for the Wix Data APIs to work. Without this extension, apps using Data APIs would need the Wix user to manually enable the code editor on their site, which isn't guaranteed. With the data collections extension, your app can reliably use Data APIs to read and write data in the collections. + +--- + +## App Namespace Handling + +**App namespace is REQUIRED** for data collections to work. The namespace scopes your collection IDs to prevent conflicts between apps. + +### Implementation Behavior + +**If app namespace is provided in the prompt:** +- Use it in all code examples: `/collection-suffix` + +**If app namespace is NOT provided:** +- Use the placeholder `` in all code examples: `/collection-suffix` +- Add to Manual Action Items: "Replace `` with your actual app namespace from Wix Dev Center" + +### Collection ID Format + +- **In extension definition (`idSuffix`):** Use just the suffix, e.g., `"products"` +- **In API calls:** Use the full scoped ID: `"/products"` — MUST match `idSuffix` exactly (case-sensitive, no camelCase/PascalCase transformation) +- **In `referencedCollectionId`:** Use the `idSuffix` only (not the full scoped ID) — the system resolves it automatically +- Example: If `idSuffix` is `"product-recommendations"`, API calls use `"/product-recommendations"` NOT `"/productRecommendations"` + +--- + +## File Structure + +In Wix CLI apps, all CMS collections are defined in a single file: + +**File:** `src/data/extensions.ts` + +This file uses the `extensions.genericExtension()` pattern from `@wix/astro/builders` to register all collections: + +```typescript +import { extensions } from "@wix/astro/builders"; + +export const dataExtension = extensions.genericExtension({ + compId: "{{GENERATE_UUID}}", + compName: "data-extension", + compType: "DATA_COMPONENT", + compData: { + dataComponent: { + collections: [ + // All collections defined here + ], + }, + }, +}); +``` + +**CRITICAL:** The `compId` must be a unique, static UUID string. Generate a fresh UUID v4 for each app - do NOT use `randomUUID()` or copy UUIDs from examples. After creating or modifying this file, follow [wix-cli-extension-registration](../wix-cli-extension-registration/SKILL.md) for UUID generation and to register the extension in `src/extensions.ts` (required for collections to work). + +**Key points:** + +- Single file contains all collections +- Uses `extensions.genericExtension()` from `@wix/astro/builders` +- Each collection includes: `idSuffix`, `displayName`, `displayField`, `fields`, `dataPermissions`, and optionally `initialData` +- `displayField` specifies which field the CMS displays when referencing items in this collection from other collections +- Collections are generated by merging operations (INSERT, UPDATE, DELETE) with existing collections +- See [extension template](assets/extension-template.ts) for complete structure + +## Field Types + +| Type | Description | Use Case | +| ----------------- | -------------------------------- | ---------------------- | +| `TEXT` | Single-line text | Names, titles | +| `RICH_TEXT` | Formatted HTML text | Blog content | +| `RICH_CONTENT` | Rich content with embedded media | Complex blog posts | +| `NUMBER` | Decimal numbers | Prices, quantities | +| `BOOLEAN` | True/false | Toggles, flags | +| `DATE` | Date only | Birthdays | +| `DATETIME` | Date with time | Timestamps | +| `TIME` | Time only | Schedules | +| `IMAGE` | Single image | Thumbnails | +| `DOCUMENT` | File attachment | PDFs | +| `VIDEO` | Video file | Media | +| `AUDIO` | Audio file | Podcasts | +| `MEDIA_GALLERY` | Multiple media | Galleries | +| `REFERENCE` | Link to one item | Author → User | +| `MULTI_REFERENCE` | Link to many items | Post → Tags | +| `ADDRESS` | Structured address | Locations | +| `URL` | URL validation | Links | +| `PAGE_LINK` | Link to Wix page | Internal navigation | +| `LANGUAGE` | Language code | Multi-language content | +| `OBJECT` | JSON object | Flexible data | +| `ARRAY` | Array of values | Generic arrays | +| `ARRAY_STRING` | Array of strings | Tags list | +| `ARRAY_DOCUMENT` | Array of documents | File collections | +| `ANY` | Any type | Most flexible | + +**CRITICAL: OBJECT fields require `objectOptions`.** When using `type: "OBJECT"`, you MUST include the `objectOptions` property — the API will reject OBJECT fields without it. Use an empty object `{}` if you don't need schema validation: + +```json +{ + "key": "settings", + "displayName": "Settings", + "type": "OBJECT", + "objectOptions": {} +} +``` + +For structured objects, define nested fields inside `objectOptions.fields`: + +```json +{ + "key": "triggerRules", + "displayName": "Trigger Rules", + "type": "OBJECT", + "objectOptions": { + "fields": [ + { "key": "url", "displayName": "URL Condition", "type": "TEXT" }, + { + "key": "scrollDepth", + "displayName": "Scroll Depth %", + "type": "NUMBER" + }, + { "key": "dateStart", "displayName": "Start Date", "type": "DATE" } + ] + } +} +``` + +## Field Properties + +```json +{ + "key": "email", + "displayName": "Email Address", + "type": "TEXT", + "required": true, + "unique": true, + "defaultValue": null, + "description": "User's primary email" +} +``` + +| Property | Description | +| -------------- | ---------------------------- | +| `key` | Field identifier (camelCase) | +| `displayName` | Label shown in CMS | +| `type` | Field data type | +| `required` | Must have value | +| `unique` | No duplicates allowed | +| `defaultValue` | Initial value | +| `description` | Help text | + +## Naming Conventions + +- **Field keys:** `lowerCamelCase`, ASCII only (e.g., `productName`, `isActive`, `createdAt`) +- **Collection IDs (`idSuffix`):** `lower-kebab-case` or `lower_underscore` (e.g., `product-categories`, `blog_posts`) +- **Display names:** Human-readable, can contain spaces (e.g., `"Product Name"`, `"Is Active"`) + +## System Fields (Automatic) + +Every collection includes: `_id`, `_createdDate`, `_updatedDate`, `_owner` + +## Permissions + +Access levels control who can read, create, update, and delete items in collections. + +| Level | Description | +| -------------------- | -------------------------------------------------- | +| `UNDEFINED` | Not set (inherits defaults) | +| `ANYONE` | Public access (including visitors) | +| `SITE_MEMBER` | Any signed-in user (members and collaborators) | +| `SITE_MEMBER_AUTHOR` | Signed-in users, but members only access own items | +| `CMS_EDITOR` | Site collaborators with CMS Access permission | +| `PRIVILEGED` | CMS administrators and privileged users | + +**Common patterns:** + +- Public content (default, recommended): `read: ANYONE, write: PRIVILEGED` +- User-generated content: `read: SITE_MEMBER, write: SITE_MEMBER_AUTHOR` +- Editorial workflow: `read: ANYONE, write: CMS_EDITOR` +- Private/admin: `read: PRIVILEGED, write: PRIVILEGED` + +**Permission hierarchy** (most to least restrictive): `PRIVILEGED` > `CMS_EDITOR` > `SITE_MEMBER_AUTHOR` > `SITE_MEMBER` > `ANYONE` > `UNDEFINED` + +### Context-Based Permission Rules + +**CRITICAL: Permissions must match where and how the data is accessed.** The consumer of the data determines the minimum permission level — setting permissions more restrictive than the access context will cause runtime failures (empty results or permission-denied errors). + +**Determine permissions by asking: "Who interacts with this data, and from where?"** + +| Access Context | Who Sees / Uses It | Implication | +|---|---|---| +| **Site Widget** (`SITE_WIDGET`) | Any site visitor (public) | Reads must be `ANYONE`. If the widget accepts input (e.g., reviews, submissions), inserts must also be `ANYONE` or `SITE_MEMBER`. | +| **Embedded Script** | Any site visitor (public) | Same as site widget — reads must be `ANYONE`. Writes depend on whether visitors can submit data. | +| **Dashboard Page** (`DASHBOARD_PAGE`) | Site owner / collaborators only | Can use `CMS_EDITOR` or `PRIVILEGED` for all operations since only authorized users access the dashboard. | +| **Backend code (site-side)** | Runs in visitor context | If called from page code or site-side modules, the caller has visitor-level permissions — data must be readable/writable at the appropriate public level. | +| **Backend code (elevated)** | Runs with `auth.elevate()` from `@wix/essentials` | Can bypass permissions, but the collection still needs correct defaults for any non-elevated callers. | + +**How to apply this:** + +1. **Identify every place the collection is read or written** — site widgets, dashboard pages, embedded scripts, backend APIs. +2. **Use the least restrictive context as the floor.** If a site widget reads the data AND a dashboard page also reads it, `itemRead` must be `ANYONE` (because the widget is public). +3. **Apply per-operation.** A collection can have `itemRead: ANYONE` (widget displays it) but `itemInsert: CMS_EDITOR` (only dashboard users add items). Each operation is independent. + +**Examples by blueprint type:** + +- **Dashboard manages data, site widget displays it:** `itemRead: ANYONE`, `itemInsert: CMS_EDITOR`, `itemUpdate: CMS_EDITOR`, `itemRemove: CMS_EDITOR` +- **Site widget collects user submissions (e.g., reviews), dashboard moderates:** `itemRead: ANYONE`, `itemInsert: ANYONE`, `itemUpdate: CMS_EDITOR`, `itemRemove: CMS_EDITOR` +- **Members-only widget reads data, members can submit:** `itemRead: SITE_MEMBER`, `itemInsert: SITE_MEMBER`, `itemUpdate: SITE_MEMBER_AUTHOR`, `itemRemove: CMS_EDITOR` +- **Dashboard-only (no public surface):** `itemRead: CMS_EDITOR`, `itemInsert: CMS_EDITOR`, `itemUpdate: CMS_EDITOR`, `itemRemove: CMS_EDITOR` + +**Anti-pattern:** Setting `itemRead: PRIVILEGED` on a collection that a site widget queries — the widget will return empty results for all visitors because they lack privileged access. + +## Relationships + +**One-to-One / Many-to-One (REFERENCE):** + +```json +{ + "key": "category", + "displayName": "Category", + "type": "REFERENCE", + "referenceOptions": { + "referencedCollectionId": "categories" + } +} +``` + +**Many-to-Many (MULTI_REFERENCE):** + +```json +{ + "key": "tags", + "displayName": "Tags", + "type": "MULTI_REFERENCE", + "multiReferenceOptions": { + "referencedCollectionId": "tags" + } +} +``` + +**CRITICAL Constraints:** + +- REFERENCE/MULTI_REFERENCE fields can ONLY link to other custom CMS collections defined in your app +- The `referencedCollectionId` MUST be the `idSuffix` of another collection in the same plan +- **NEVER use REFERENCE fields to link to Wix business entities** (Products, Orders, Contacts, Members, etc.) +- Use Wix SDK APIs to access Wix business entities instead + +## Collection Operations + +Collections support three operation types for modifying collections: + +### INSERT + +Creates a new collection or replaces an existing one with the same `idSuffix`. + +**Use when:** Creating a new collection or completely replacing an existing collection. + +### UPDATE + +Modifies an existing collection by merging new data with existing fields. + +**Use when:** Adding fields, updating permissions, or modifying collection properties. + +**Behavior:** + +- If collection exists: Merges new data with existing collection +- If collection doesn't exist: Treats update as insert (creates new collection) + +### DELETE + +Removes a collection from the app. + +**Use when:** Removing a collection that is no longer needed. + +**Behavior:** + +- Removes the collection from `src/data/extensions.ts` +- If all collections are deleted, the entire file is deleted + +**Merge logic:** Operations are applied using a Map keyed by `idSuffix`. Existing collections are loaded into the Map first, then each operation modifies it: INSERT sets/replaces, UPDATE merges with existing (or creates if missing), DELETE removes. The final Map values become the output collections. + +## App Version Updates + +Changes to your data collections extension require releasing a new major version of your app. When a user updates to the new major version, their collections are updated as follows: + +- **Adding a new collection:** The new collection is created on the site. +- **Removing a collection:** If the old app version defined a collection and the new version doesn't, the collection is removed from the site. +- **Modifying a collection schema:** Field additions, removals, and type changes are applied to the collection. Existing data is preserved. + +**Important notes:** + +- Collection changes only affect users who update to the new major version. Users who don't update retain their current collections. +- Collection changes take up to 5 minutes to propagate after an update. +- **Initial data is only imported when a collection is first created.** If a collection already contains data, `initialData` is ignored during updates. + +## Wix CLI-Specific Constraints + +### Embedded Script Parameters vs Collections + +**CRITICAL: NEVER create CMS collections to store configuration for embedded scripts.** + +All embedded script configuration must go through embedded script parameters (`embeddedScriptParameters`), not CMS collections. + +**DO NOT create collections for:** + +- Colors, messages, headlines, text content +- Coupon codes, display settings +- UI customization (positions, sizes, styles) +- Timing settings, feature toggles +- Display frequencies, thresholds +- Minimums/maximums +- **ANY configuration that controls how an embedded script behaves or appears** + +**Examples of configuration (use parameters, NOT collections):** + +- Popup headline → embedded script parameter +- Coupon code → embedded script parameter +- Background color → embedded script parameter +- Display position → embedded script parameter +- Show/hide toggles → embedded script parameter + +**CMS collections should ONLY be created for:** + +- Business data (products, orders, inventory, etc.) +- User-generated content (reviews, comments, submissions) +- Event logs (if explicitly requested for analytics/tracking) +- Multi-record relational data that is NOT configuration + +**Decision Rule:** + +- If it controls HOW the embedded script works or looks → it's configuration → use embedded script parameters +- If it's business data or user-generated content → it's data → use CMS collections + +### Site Widget Settings vs Collections + +**CRITICAL: Site widgets have a built-in settings panel (`panel.tsx`) that handles ALL widget configuration.** + +**For SITE_WIDGET-only blueprints (no DASHBOARD_PAGE or other extensions):** + +- **ALWAYS return `collections: []` (empty array)** +- The widget panel handles everything +- **NEVER create collections to store widget configuration data** + +**Configuration handled by widget panel (NOT collections):** + +- Target date/time for countdown → widget panel +- Display colors, fonts, sizes → widget panel +- Headlines, labels, messages → widget panel +- Feature toggles, show/hide options → widget panel +- Numeric settings (delays, intervals, thresholds) → widget panel + +**Only create collections for SITE_WIDGET when ALL of these conditions are met:** + +1. The blueprint ALSO includes a DASHBOARD_PAGE extension that needs to manage data the widget displays +2. OR the widget explicitly needs to display MULTIPLE records of user-generated/business data (not configuration) +3. AND the data is NOT configuration (dates, colors, settings, display options are ALWAYS configuration) + +### Anti-Patterns + +**Don't create aggregated fields.** If you have individual `rating` fields, calculate averages dynamically — don't store computed values like `averageRating`. + +**Don't duplicate configuration.** If embedded script parameters already hold `{ headline, color }`, don't also create a CMS collection with the same data. + +**Don't create single-value collections.** A collection with one field like `{ theme: "dark" }` should be an embedded script parameter or widget setting instead. + +### Initial Data Rules + +Each item in `initialData` must match the collection schema exactly: + +- Field keys must be `lowerCamelCase` and match the schema +- `TEXT` → string, `NUMBER` → number, `BOOLEAN` → boolean +- `DATE`/`DATETIME` → use `{ "$date": "2024-01-15T10:30:00.000Z" }` format +- `REFERENCE` → provide the `idSuffix` of the referenced collection +- Required fields must always have values + +## Examples + +### Simple Collection with Initial Data + +**Request:** "Create a collection for handling fees with example data" + +**Generated file:** `src/data/extensions.ts` + +```typescript +import { extensions } from "@wix/astro/builders"; + +export const dataExtension = extensions.genericExtension({ + compId: "{{GENERATE_UUID}}", + compName: "data-extension", + compType: "DATA_COMPONENT", + compData: { + dataComponent: { + collections: [ + { + schemaUrl: "https://www.wix.com/", + idSuffix: "additional-fees", + displayName: "Additional Fees", + displayField: "title", + fields: [ + { key: "title", displayName: "Fee Title", type: "TEXT" }, + { key: "amount", displayName: "Fee Amount", type: "NUMBER" }, + ], + dataPermissions: { + itemRead: "ANYONE", + itemInsert: "PRIVILEGED", + itemUpdate: "PRIVILEGED", + itemRemove: "PRIVILEGED", + }, + initialData: [ + { title: "Handling Fee", amount: 5 }, + { title: "Gift Wrapping", amount: 3.5 }, + ], + }, + ], + }, + }, +}); +``` + +### Collection with Reference Relationship + +**Request:** "Create collections for products and categories with relationships" + +**Collections:** + +- `categories` - Category definitions +- `products` - Products that reference categories + +Both collections are defined in the same `src/data/extensions.ts` file, with the `products` collection using a REFERENCE field to link to `categories`. See the [extension template](assets/extension-template.ts) for a complete multi-collection example. + +## Common Patterns + +**Soft Delete:** Add `isDeleted` (BOOLEAN, default: false) + +**Status/Workflow:** Add `status` (TEXT) with values like draft/pending/published + +**URL Slug:** Add `slug` (TEXT, unique) for SEO-friendly URLs + +**Owner Tracking:** Add `createdBy` (REFERENCE → custom collection, not Members) + +**Note:** For owner tracking, create a custom collection for users rather than referencing Wix Members directly. + +## Verification + +After implementation, use [wix-cli-app-validation](../wix-cli-app-validation/SKILL.md) to validate TypeScript compilation, build, preview, and runtime behavior. + +## Reference Documentation + +- [extension-template.ts](assets/extension-template.ts) - Template for `src/data/extensions.ts` + +### Public Documentation + +- [About Data Collections Extensions](https://dev.wix.com/docs/build-apps/develop-your-app/extensions/backend-extensions/data-collections/about-data-collections-extensions) - When to use the extension, implementation options, and app version update behavior +- [Add a Data Collections Extension in the App Dashboard](https://dev.wix.com/docs/build-apps/develop-your-app/extensions/backend-extensions/data-collections/add-a-data-collections-extension-in-the-app-dashboard) - Step-by-step guide to configuring collections via the app dashboard JSON editor, with example configuration +- [Data Collections Extension JSON Reference](https://dev.wix.com/docs/api-reference/business-solutions/cms/collection-management/data-collections-extension/introduction) - Complete JSON schema and field definitions for the data collections extension diff --git a/CLI App - Calculator Form/.agents/skills/wix-cli-data-collection/assets/extension-template.ts b/CLI App - Calculator Form/.agents/skills/wix-cli-data-collection/assets/extension-template.ts new file mode 100644 index 0000000..4cfdc53 --- /dev/null +++ b/CLI App - Calculator Form/.agents/skills/wix-cli-data-collection/assets/extension-template.ts @@ -0,0 +1,107 @@ +/** + * Template for src/data/extensions.ts + * + * This file defines all CMS collections for your Wix CLI app. + * All collections are defined in a single file using extensions.genericExtension(). + * + * Replace the example collection with your actual collections. + */ + +import { extensions } from '@wix/astro/builders'; + +export const dataExtension = extensions.genericExtension({ + // IMPORTANT: Replace with a freshly generated UUID v4 string + // Format: xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx + // Do NOT use randomUUID() - the UUID must be a static string + compId: '{{GENERATE_UUID}}', + + // Always 'data-extension' for CMS collections + compName: 'data-extension', + + // Always 'DATA_COMPONENT' for CMS collections + compType: 'DATA_COMPONENT', + + compData: { + dataComponent: { + // Array of all collections + collections: [ + { + // Legacy field - will be removed in future + schemaUrl: 'https://www.wix.com/', + + // Collection identifier (lower-kebab-case or lower_underscore) + // This will be scoped with app namespace automatically + idSuffix: 'example-collection', + + // Human-readable name shown in CMS + displayName: 'Example Collection', + + // Field used for display (optional) + displayField: 'title', + + // Array of field definitions + fields: [ + { + // Field identifier (lowerCamelCase, ASCII only) + key: 'title', + + // Human-readable label + displayName: 'Title', + + // Field type - see SKILL.md Field Types section for all types + type: 'TEXT', + + // Optional: Help text + description: 'The title of the item' + }, + { + key: 'amount', + displayName: 'Amount', + type: 'NUMBER' + }, + { + key: 'isActive', + displayName: 'Is Active', + type: 'BOOLEAN' + } + // Add more fields as needed + ], + + // Permission configuration + // See SKILL.md Permissions section for all access levels + dataPermissions: { + // Who can read items + itemRead: 'ANYONE', + + // Who can create items + itemInsert: 'PRIVILEGED', + + // Who can update items + itemUpdate: 'PRIVILEGED', + + // Who can delete items + itemRemove: 'PRIVILEGED' + }, + + // Optional: Initial seed data + // Only include if blueprint mentions example data + initialData: [ + { + // Must match field keys exactly (lowerCamelCase) + title: 'Example Item 1', + amount: 10, + isActive: true + }, + { + title: 'Example Item 2', + amount: 20, + isActive: false + } + // Add more initial items as needed + ] + } + // Add more collections as needed + ] + } + } +}); diff --git a/CLI App - Calculator Form/.agents/skills/wix-cli-embedded-script/SKILL.md b/CLI App - Calculator Form/.agents/skills/wix-cli-embedded-script/SKILL.md new file mode 100644 index 0000000..018bef2 --- /dev/null +++ b/CLI App - Calculator Form/.agents/skills/wix-cli-embedded-script/SKILL.md @@ -0,0 +1,473 @@ +--- +name: wix-cli-embedded-script +description: Use when adding tracking code, advertising pixels, third-party integrations, popups, banners, or client-side JavaScript to sites. Triggers include embed, inject, script, third-party integration, DOM injection, Google Analytics, Facebook Pixel, tracking pixel, chat widget, popup, coupon popup, custom JavaScript, site script. +compatibility: Requires Wix CLI development environment. +--- + +# Wix Embedded Script Builder + +Creates embedded script extensions for Wix CLI applications. Embedded scripts are HTML code fragments that get injected into the DOM of Wix sites, enabling integration with third-party services, analytics tracking, advertising, and custom JavaScript functionality. + +## Quick Start Checklist + +Follow these steps in order when creating an embedded script: + +1. [ ] Create script folder: `src/site/embedded-scripts//` +2. [ ] Create `embedded.html` with config element, styles, and script logic +3. [ ] Create `extensions.ts` with `extensions.embeddedScript()` and unique UUID +4. [ ] Create dashboard config page: `src/dashboard/pages/-settings/` +5. [ ] Implement config page with `embeddedScripts` API from `@wix/app-management` +6. [ ] Update `src/extensions.ts` to import and use both extensions +7. [ ] Add the `SCOPE.DC-APPS.MANAGE-EMBEDDED-SCRIPTS` permission in the Wix Dev Center (see [Enable Embedded Script Permission](#enable-embedded-script-permission)) + +## Script Types + +Embedded scripts must declare a type for consent management: + +| Type | Description | Use Cases | +| ------------- | ------------------------------------------------ | --------------------------------------- | +| `ESSENTIAL` | Core functionality crucial to site operation | Authentication, security features | +| `FUNCTIONAL` | Remembers user choices to improve experience | Language preferences, UI customization | +| `ANALYTICS` | Provides statistics on how visitors use the site | Google Analytics, Hotjar, Mixpanel | +| `ADVERTISING` | Provides visitor data for marketing purposes | Facebook Pixel, Google Ads, retargeting | + +**Selection rule:** If a script falls into multiple types, choose the option closest to the bottom of the list (most restrictive). For example, a script with both Analytics and Advertising aspects should be typed as `ADVERTISING`. + +## Placement Options + +| Placement | Description | Best For | +| ------------ | ---------------------------------------- | --------------------------------- | +| `HEAD` | Between `` and `` tags | Analytics, early initialization | +| `BODY_START` | Immediately after opening `` tag | Critical functionality, noscript | +| `BODY_END` | Immediately before closing `` tag | Non-blocking scripts, performance | + +**Selection guidelines:** + +- Analytics/tracking → `HEAD` (initialize early) +- Advertising pixels → `BODY_END` (non-blocking) +- Critical functionality → `HEAD` or `BODY_START` +- Non-critical features → `BODY_END` (better performance) + +## Dynamic Parameters and Dashboard Configuration + +**Every embedded script requires a companion dashboard page** to configure its parameters. Site owners use the dashboard page UI to set values, which are then passed to the embedded script as template variables. + +### Architecture Flow + +``` +Dashboard Page (React UI) + │ + │ embeddedScripts.embedScript({ parameters: {...} }) + ▼ +Wix App Management API + │ + │ Stores parameters, injects as template variables + ▼ +Embedded Script (HTML) + │ + │ {{parameterKey}} → actual value + ▼ +Site DOM +``` + +**Related skill:** Use `wix-cli-dashboard-page` to create the configuration UI for your embedded script. + +### Parameter Types + +| Type | Description | Dashboard Component | +| ---------- | ------------------------ | ---------------------- | +| `TEXT` | Single-line text | Input | +| `NUMBER` | Numeric value | Input type="number" | +| `BOOLEAN` | True/false toggle | ToggleSwitch, Checkbox | +| `IMAGE` | Image from media manager | ImagePicker | +| `DATE` | Date only | DatePicker | +| `DATETIME` | Date with time | DatePicker + TimeInput | +| `URL` | URL with validation | Input | +| `SELECT` | Dropdown options | Dropdown | +| `COLOR` | Color value | ColorPicker | + +### Template Variable Syntax + +Embedded scripts support parameterization using template variable syntax `{{variableName}}`. These parameters are configured through the dashboard and passed as template variables that should be used in your HTML/JavaScript code. + +**Usage Instructions:** + +1. **Template Variable Syntax:** + - Use `{{parameterKey}}` syntax to insert parameter values into your HTML + - Template variables work in HTML attributes + - They will be replaced with actual values when the script is injected + +2. **HTML Attributes (REQUIRED):** + - Store ALL parameter values in data attributes on a configuration element + - Template variables can ONLY be used here, not directly in JavaScript + - Example: `

` + +3. **JavaScript Access:** + - JavaScript must read parameter values from the data attributes + - Use `getAttribute()` or the `dataset` property + - Examples: + ```javascript + const config = document.getElementById("config"); + const headline = config?.getAttribute("data-headline"); + // OR using dataset: + const { headline, text } = config.dataset; + ``` + +4. **Type Safety:** + - Be aware of parameter types when using them in JavaScript + - NUMBER types: convert with `Number()` or `parseInt()` + - BOOLEAN types: compare with `'true'` or `'false'` strings + - DATE/DATETIME: parse with `new Date()` + +5. **Required vs Optional:** + - Required parameters will always have values + - Optional parameters may be empty - handle gracefully + - Provide fallback values for optional parameters + +6. **Relevant Parameter Usage:** + - Only use dynamic parameters that are relevant to your current use case + - Ignore parameters that don't apply to the functionality you're implementing + - Each parameter you use should serve a clear purpose in the script's functionality + - It's perfectly fine to not use all parameters if they're not applicable + +**Example Patterns:** + +**Pattern 1 - Configuration in Data Attributes:** + +```html +
+ +``` + +**Pattern 2 - Using dataset Property:** + +```html +
+ +``` + +**Pattern 3 - Conditional Logic:** + +```html +
+ +``` + +**Validation Requirements:** + +- Only use dynamic parameters that are relevant to your specific use case +- Ignore parameters that don't apply to the functionality being implemented +- Template variables `{{parameterKey}}` must match the exact key names from the parameter definitions +- Handle both required and optional parameters appropriately +- Provide sensible default behavior when optional parameters are not set +- Ensure type-appropriate usage (don't use NUMBER parameters as strings without conversion) + +### Common Parameters + +Every embedded script should have at minimum an **enable/disable toggle** parameter: + +| Parameter | Type | Purpose | +| ------------ | --------- | ------------------------------------ | +| `enabled` | `BOOLEAN` | Allow site owner to activate/disable | +| `apiKey` | `TEXT` | Third-party service credentials | +| `trackingId` | `TEXT` | Analytics/pixel identifiers | +| `headline` | `TEXT` | Customizable display text | +| `color` | `COLOR` | UI customization | + +## Output Structure + +A complete embedded script implementation requires **two parts**: + +### 1. Embedded Script Extension + +``` +src/site/embedded-scripts/ +└── {script-name}/ + ├── embedded.html # HTML/JavaScript code to inject + └── extensions.ts # Metadata (scriptType, placement) +``` + +### 2. Dashboard Configuration Page (Required) + +``` +src/dashboard/ +├── withProviders.tsx # WDS provider wrapper (required) +└── pages/ + └── {script-name}-settings/ + ├── extensions.ts # Extension registration (REQUIRED) + └── page.tsx # Configuration UI using embeddedScripts API +``` + +**Note:** The dashboard page requires its own `extensions.ts` file. Without this file, the dashboard page will not appear in the Wix dashboard. + +**WARNING:** The dashboard page uses DIFFERENT field names than embedded scripts: + +- Dashboard pages use `title`, `routePath`, `component` +- Embedded scripts use `name`, `source`, `placement`, `scriptType` + +Do NOT apply embedded script field names to dashboard page registrations. + +**See `wix-cli-dashboard-page` skill** for dashboard page implementation details and the extension registration pattern. + +## Implementation Pattern + +```html + +
+ + +
+ + + + +``` + +## Examples + +### Analytics Tracking + +**Request:** "Add Google Analytics tracking to my site" + +**Output:** + +- Script type: `ANALYTICS` +- Placement: `HEAD` +- Template variables: `{{trackingId}}` +- Implements: gtag.js initialization, page view tracking + +### Popup/Modal + +**Request:** "Create a coupon popup that shows when cart value exceeds $50" + +**Output:** + +- Script type: `FUNCTIONAL` +- Placement: `BODY_END` +- Template variables: `{{couponCode}}`, `{{minimumCartValue}}`, `{{enablePopup}}` +- Implements: Cart value detection, popup display logic, localStorage for "don't show again" + +### Third-Party Chat Widget + +**Request:** "Integrate Intercom chat widget" + +**Output:** + +- Script type: `FUNCTIONAL` +- Placement: `BODY_END` +- Template variables: `{{appId}}`, `{{userEmail}}`, `{{userName}}` +- Implements: Intercom SDK initialization, user identification + +## Best Practices + +- **Always create a dashboard page:** Every embedded script needs a configuration UI +- **Include enable/disable toggle:** Let site owners control activation without removing the script +- **Performance:** Minimize impact - scripts should be lightweight and non-blocking +- **Security:** Avoid inline event handlers, validate data, escape user input +- **Error handling:** Fail silently when appropriate - don't break the site +- **Module scope early exits:** Use `throw new Error()` for early exits at module scope, not `return`. Rollup (used by Astro) doesn't allow `return` statements at module scope. Wrap main logic in a named async function where `return` is valid. +- **Type conversions:** Parameters are always strings - convert in JavaScript as needed +- **API calls:** Only create fetch() calls to /api/\* endpoints that exist in the API spec +- **Scoping:** Prefix CSS classes and IDs to avoid conflicts with site styles +- **Cleanup:** Remove event listeners and intervals when appropriate + +## Complete Example: Coupon Popup + +### 1. Define Parameters + +``` +Parameters for "cart-coupon-popup": +- couponCode (TEXT, required) - The coupon code to display +- popupHeadline (TEXT, required) - Headline text +- popupDescription (TEXT, required) - Description text +- minimumCartValue (NUMBER) - Minimum cart value to show popup +- enablePopup (BOOLEAN, required) - Enable/disable toggle +``` + +### 2. Embedded Script (`embedded.html`) + +```html + + + + +``` + +### 3. Dashboard Page (See `wix-cli-dashboard-page` skill) + +Uses `embeddedScripts` API from `@wix/app-management`: + +```typescript +import { embeddedScripts } from "@wix/app-management"; + +// Load parameters +const script = await embeddedScripts.getEmbeddedScript(); +const params = script.parameters; // { couponCode: "...", ... } + +// Save parameters (all values must be strings) +await embeddedScripts.embedScript({ + parameters: { + couponCode: "SAVE20", + minimumCartValue: "50", // Number as string + enablePopup: "true", // Boolean as string + }, +}); +``` + +## Extension Registration + +**Extension registration is MANDATORY and has TWO required steps.** + +### Step 1: Create Script-Specific Extension File + +Each embedded script requires an `extensions.ts` file in its folder: + +```typescript +import { extensions } from "@wix/astro/builders"; + +export const embeddedscriptMyScript = extensions.embeddedScript({ + id: "{{GENERATE_UUID}}", + name: "My Script", + source: "./site/embedded-scripts/my-script/embedded.html", + placement: "BODY_END", + scriptType: "FUNCTIONAL", +}); +``` + +**CRITICAL: UUID Generation** + +The `id` must be a unique, static UUID v4 string. Generate a fresh UUID for each extension - do NOT use `randomUUID()` or copy UUIDs from examples. Replace `{{GENERATE_UUID}}` with a freshly generated UUID like `"a1b2c3d4-e5f6-7890-abcd-ef1234567890"`. + +| Property | Type | Description | +| ------------ | ------ | ----------------------------------------------------- | +| `id` | string | Unique static UUID v4 (generate fresh) | +| `name` | string | Display name for the script | +| `source` | string | Relative path to the HTML file | +| `placement` | enum | `HEAD`, `BODY_START`, or `BODY_END` | +| `scriptType` | enum | `ESSENTIAL`, `FUNCTIONAL`, `ANALYTICS`, `ADVERTISING` | + +### Step 2: Register in Main Extensions File + +**CRITICAL:** After creating the script-specific extension file, you MUST read [wix-cli-extension-registration](../wix-cli-extension-registration/SKILL.md) and follow the "App Registration" section to update `src/extensions.ts`. + +**Without completing Step 2, the embedded script will not be deployed to the site.** + +## Enable Embedded Script Permission + +After implementation, the app developer must manually enable the embedded script permission: + +1. Go to [https://manage.wix.com/apps/{app-id}/dev-center-permissions](https://manage.wix.com/apps/{app-id}/dev-center-permissions) (replace `{app-id}` with your actual app ID) +2. Add the `SCOPE.DC-APPS.MANAGE-EMBEDDED-SCRIPTS` permission +3. Save the changes + +**Note:** This is a manual step in the Wix Dev Center. Without this permission, embedded scripts will not function on the site. \ No newline at end of file diff --git a/CLI App - Calculator Form/.agents/skills/wix-cli-extension-registration/SKILL.md b/CLI App - Calculator Form/.agents/skills/wix-cli-extension-registration/SKILL.md new file mode 100644 index 0000000..cccb3fd --- /dev/null +++ b/CLI App - Calculator Form/.agents/skills/wix-cli-extension-registration/SKILL.md @@ -0,0 +1,100 @@ +--- +name: wix-cli-extension-registration +description: Register Wix CLI extensions with the app in src/extensions.ts. Use when registering new or existing extensions with the main app builder, adding .use() calls, importing extensions, or updating the extensions chain. Triggers include register extension, extensions.ts, app().use(), import extension, extension not appearing. +compatibility: Requires Wix CLI development environment. +--- + +# Wix App Registration + +After creating any extension file, you must update the main `src/extensions.ts` file to register the extension with the app. + +## Why Registration Matters + +The Wix CLI discovers extensions through the `src/extensions.ts` file — it's the single entry point that tells the build system which extensions exist. Without registration: + +- Dashboard pages won't appear in the sidebar +- Site widgets won't show in the Wix Editor +- Service plugins won't be called during checkout flows +- Event handlers won't receive webhook deliveries +- Embedded scripts won't be injected into site pages + +The most common cause of "my extension isn't working" is a missing `.use()` call in this file. + +## Simple Pattern (Recommended for Small Apps) + +**`src/extensions.ts`** - Import and register extensions directly: + +```typescript +import { app } from "@wix/astro/builders"; +import { dataExtension } from "./data/extensions.ts"; +import { dashboardpageMyPage } from "./dashboard/pages/my-page/extensions.ts"; +import { embeddedscriptMyScript } from "./site/embedded-scripts/my-script/extensions.ts"; + +export default app() + .use(dataExtension) + .use(dashboardpageMyPage) + .use(embeddedscriptMyScript); +``` + +**Steps for each new extension:** + +1. Import the extension from its `extensions.ts` file +2. Add `.use(extensionName)` to the app chain +3. Chain multiple extensions together + +## Advanced Pattern (For Large Apps) + +**`src/index.ts`** - Re-export all extensions: + +```typescript +export { dashboardpageMyPage } from "./dashboard/pages/my-page/extensions"; +export { embeddedscriptMyScript } from "./site/embedded-scripts/my-script/extensions"; +export { dataExtension } from "./data/extensions"; +``` + +**`src/extensions.ts`** - Register all extensions programmatically: + +```typescript +import { app } from "@wix/astro/builders"; +import * as allExtensions from "./index"; + +const extensionList = Object.values(allExtensions); + +const appBuilder = app(); +extensionList.forEach((extension) => { + appBuilder.use(extension); +}); + +export default appBuilder; +``` + +## Extension Types Without Registration + +The following extension types do **not** require `extensions.ts` files: + +- **Backend API** - Astro server endpoints are auto-discovered + +## Naming Conventions + +Extension export names follow this pattern: `{extensiontype}{CamelCaseName}` + +Examples: + +- `dashboardpageCartPopupManager` +- `dashboardpluginBlogPostsBanner` +- `embeddedscriptCouponPopup` +- `sitewidgetCountdownWidget` +- `sitepluginProductBadge` +- `ecomshippingratesCustomShipping` + +The type prefix is the extension type in lowercase with no separators. + +## Troubleshooting + +| Symptom | Cause | Fix | +|---------|-------|-----| +| Extension not appearing at all | Missing `.use()` call | Add import and `.use(extensionName)` to `src/extensions.ts` | +| "Cannot find module" on build | Wrong import path | Verify the path in your import matches the actual file location (relative to `src/`) | +| Extension registered but not working | Export name mismatch | Ensure the exported name in the extension file matches the import in `extensions.ts` | +| Multiple extensions, only some work | Incomplete chain | Check that every extension has both an import and a `.use()` call | +| TypeScript error on `.use()` | Wrong export type | Ensure extension file uses the correct builder method (e.g., `extensions.dashboardPage()` not `extensions.embeddedScript()`) | diff --git a/CLI App - Calculator Form/.agents/skills/wix-cli-orchestrator/SKILL.md b/CLI App - Calculator Form/.agents/skills/wix-cli-orchestrator/SKILL.md new file mode 100644 index 0000000..1aad856 --- /dev/null +++ b/CLI App - Calculator Form/.agents/skills/wix-cli-orchestrator/SKILL.md @@ -0,0 +1,469 @@ +--- +name: wix-cli-orchestrator +description: "BLOCKING REQUIREMENT - When user requests to add/build/create/implement ANY feature or component for a Wix CLI app, you MUST invoke this skill IMMEDIATELY as your absolute FIRST action - when exploring, reading files, BEFORE launching any agents - make sure this skill is loaded. Trigger on add, build, create, I want, implement, help me where X is any feature/component. Non-negotiable - invoke immediately upon recognizing a Wix feature build request." +compatibility: Requires Wix CLI development environment. +--- + +# Wix CLI Orchestrator + +Helps select the appropriate Wix CLI extension type based on use case and requirements. + +## ⚠️ MANDATORY WORKFLOW CHECKLIST ⚠️ + +**Before reporting completion to the user, ALL boxes MUST be checked:** + +- [ ] **Step 1:** Determined extension type(s) needed + - [ ] Asked clarifying questions if requirements were unclear + - [ ] Checked for implicit Data Collection need — unless user provided a collection ID directly (see [Data Collection Inference](#data-collection-inference)) + - [ ] Obtained app namespace if Data Collection extension is being created + - [ ] Determined full scoped collection IDs if Data Collection extension is being created (see [Collection ID Coordination](#collection-id-coordination)) + - [ ] Explained recommendation with reasoning +- [ ] **Step 2:** Checked references, spawned discovery if needed + - [ ] Checked relevant reference files for required APIs + - [ ] Spawned discovery only if API not found in references + - [ ] Skip if all APIs are in reference files or no external APIs needed +- [ ] **Step 3:** Waited for discovery sub-agent to complete (if spawned) + - [ ] Received SDK methods with imports +- [ ] **Step 4:** Spawned implementation sub-agent(s) with skill context + - [ ] Included user requirements in prompt + - [ ] Included SDK context from discovery (if any) + - [ ] Instructed sub-agent to invoke `wds-docs` skill FIRST when using @wix/design-system (for correct imports, especially icons) +- [ ] **Step 5:** Waited for implementation sub-agent(s) to complete + - [ ] All files created + - [ ] Extension registered in extensions.ts +- [ ] **Step 6:** Invoked `wix-cli-app-validation` skill +- [ ] **Step 7:** Validation passed + - [ ] Dependencies installed + - [ ] TypeScript compiled + - [ ] Build succeeded + - [ ] Preview deployed +- [ ] **Step 8:** Collected and presented ALL manual action items to user + - [ ] Reviewed output from every sub-agent for manual steps + - [ ] Aggregated into a single actionable list at the end of the conversation + +**🛑 STOP:** If any box is unchecked, do NOT proceed to the next step. + +--- + +## Your Role + +You are a **decision-maker and orchestrator**, not an implementer. **Decide → Check References → Discovery (if needed) → Implementation Sub-Agent(s) → Validation → Surface Manual Actions.** Ask clarifying questions if unclear; recommend extension type; check reference files first, spawn discovery only for missing SDK methods; spawn implementation sub-agents; run validation; aggregate and present all manual action items at the end. + +--- + +## ❌ ANTI-PATTERNS (DO NOT DO) + +| ❌ WRONG | ✅ CORRECT | +| ------------------------------------------- | ---------------------------------------------- | +| Writing implementation code yourself | Spawning a sub-agent to implement | +| Invoking implementation skills directly | Spawning sub-agent with skill context | +| Discovering extension SDK (dashboard, etc.) | Extension SDK is in skill reference files | +| Spawning discovery without checking refs | Check skill refs first | +| Reporting done without validation | Always run `wix-cli-app-validation` at the end | +| Reading/writing files after invoking skills | Let sub-agents handle ALL file operations | +| Letting manual action items get buried | Aggregate all manual steps at the very end | + +**CRITICAL:** After this planner skill loads, you should ONLY: + +- Spawn sub-agents (for discovery and implementation) +- Invoke `wix-cli-app-validation` skill at the end + +You should NEVER: Read, Write, Edit files for implementation yourself + +## Quick Decision Helper + +Answer these questions to find the right extension: + +1. **What are you trying to build?** + - Admin interface → Dashboard Extensions + - Backend logic → Backend Extensions + - Data storage / CMS collections → Data Collection + - Site component → Site Extensions (app projects only) + +2. **Who will see it?** + - Admin users only → Dashboard Extensions + - Site visitors → Site Extensions + - Server-side only → Backend Extensions + +3. **Where will it appear?** + - Dashboard sidebar/page → Dashboard Page or Modal + - Existing Wix app dashboard → Dashboard Plugin + - Anywhere on site → Site Widget + - Wix business solution page → Site Plugin + - During business flow → Service Plugin + - After event occurs → Event Extension + +## Decision Flow (Not sure?) + +- **Admin:** Need full-page UI? → Dashboard Page. Need popup/form? → Dashboard Modal. Extending Wix app dashboard? → Dashboard Plugin. **Modal constraint:** Dashboard Pages cannot use ``; use a separate Dashboard Modal extension and `dashboard.openModal()`. +- **Backend:** During business flow (checkout/shipping/tax)? → Service Plugin. After event (webhooks/sync)? → Event Extension. Custom HTTP endpoints? → Backend Endpoints. Need CMS collections for app data? → Data Collection. +- **Site:** User places anywhere? → Site Widget. Fixed slot on Wix app page? → Site Plugin. Scripts/analytics only? → Embedded Script. + +### Data Collection Inference + +**CRITICAL:** Data collections are often needed implicitly — don't wait for the user to explicitly say "create a CMS collection." Infer the need automatically. + +**Skip this section if the user provides a collection ID directly** (e.g., an existing site-level collection). In that case, use the provided ID as-is — no Data Collection extension or namespace scoping needed. + +**Always include a Data Collection extension when ANY of these are true:** + +| Indicator | Example | +| --- | --- | +| User mentions saving/storing/persisting app-specific data | "save the fee amount", "store product recommendations" | +| A dashboard page will **manage** (CRUD) domain entities | "dashboard to manage fees", "admin page to edit rules" | +| A service plugin reads app-configured data at runtime | "fetch fee rules at checkout", "look up shipping rates" | +| User mentions "dedicated database/collection" | "save in a dedicated database collection" | +| Multiple extensions reference the same custom data | Dashboard manages fees + service plugin reads fees | + +**Why this matters:** Without the Data Collection extension, the collection won't be created when the app is installed, the Wix Data APIs may not work (code editor not enabled), and collection IDs won't be properly scoped to the app namespace. + +**If data collection is inferred, follow the [App Namespace Requirement](#step-1-ask-clarifying-questions-if-needed) to obtain the namespace before proceeding.** + +## Quick Reference Table + +| Extension Type | Category | Visibility | Use When | Skill | +| --------------------- | --------- | ----------- | ----------------------------- | ------------------------- | +| Dashboard Page | Dashboard | Admin only | Full admin pages | `wix-cli-dashboard-page` | +| Dashboard Modal | Dashboard | Admin only | Popup dialogs | `wix-cli-dashboard-modal` | +| Dashboard Plugin | Dashboard | Admin only | Extend Wix app dashboards | `wix-cli-dashboard-plugin` | +| Dashboard Menu Plugin | Dashboard | Admin only | Add menu items | (none yet) | +| Service Plugin | Backend | Server-side | Customize business flows | `wix-cli-service-plugin` | +| Event Extension | Backend | Server-side | React to events | `wix-cli-backend-event` | +| Backend Endpoints | Backend | API | Custom HTTP handlers | `wix-cli-backend-api` | +| Data Collection | Backend | Data | CMS collections for app data | `wix-cli-data-collection` | +| Site Widget | Site | Public | Standalone widgets | `wix-cli-site-widget` | +| Site Plugin | Site | Public | Extend Wix business solutions | `wix-cli-site-plugin` | +| Embedded Script | Site | Public | Inject scripts/analytics | `wix-cli-embedded-script` | + +**Key constraint:** Dashboard Page cannot use ``; use a separate Dashboard Modal and `dashboard.openModal()`. + +## Extension Comparison + +| Site Widget vs Site Plugin | Dashboard Page vs Modal | Service Plugin vs Event | +| -------------------------- | ----------------------- | ----------------------- | +| Widget: user places anywhere. Plugin: fixed slot in Wix app. | Page: full page. Modal: overlay; use for popups. | Service: during flow. Event: after event. | + +## Decision & Handoff Workflow + +Follow the checklist; steps below add detail. + +### Step 1: Ask Clarifying Questions (if needed) + +Only ask for configuration values when **absolutely necessary** for the implementation to proceed — i.e., the sub-agent literally cannot generate working code without it. If a value can be configured later or added as a manual step, don't block on it. + +**App Namespace Requirement:** +When creating a Data Collection, you MUST ask the user for their app namespace from Wix Dev Center. This is a required parameter that must be obtained from the user's Dev Center dashboard and cannot be recommended or guessed. + +**Instructions to give the user:** + +**If you don't have an app namespace yet:** +1. Go to [Wix Dev Center](https://manage.wix.com/studio/custom-apps/) +2. Select your app +3. In the left menu, select **Develop > Extensions** +4. Click **+ Create Extension** and find the **Data Collections** extension +5. Click **+ Create** +6. You will be prompted to create an app namespace - follow the prompts to set it up + +**If you already have an app namespace:** +1. Go to [Wix Dev Center](https://manage.wix.com/studio/custom-apps/) +2. Open your app dashboard +3. Click the three dots (...) menu button in the top-right corner (next to "Test App" button) +4. Select "View ID & keys" from the dropdown menu +5. In the modal that opens, scroll to the bottom to find the "Namespace" field +6. Copy the Namespace value + +If unclear on approach (placement, visibility, configuration, integration), ask clarifying questions. If the answer could change the extension type, wait for the response before proceeding. Otherwise, proceed with the best-fit extension type. + +### Wix Stores Versioning Requirement + +**Applies when ANY Wix Stores API is used** (products, inventory, orders, etc.): + +1. **Include the `wix-stores-versioning` skill** in implementation sub-agent prompts +2. **All Stores operations must check catalog version first** using `getCatalogVersion()` +3. **Use the correct module** based on version: `productsV3` (V3) vs `products` (V1) + +This is non-negotiable — V1 and V3 are NOT backwards compatible. + +### Collection ID Coordination + +**Applies ONLY when a Data Collection extension is being created.** If the user provides a collection ID directly, use it as-is — no namespace scoping, no Data Collection extension needed. + +When a Data Collection is created alongside other extensions that reference the same collections: + +1. **Get the app namespace** (see App Namespace Requirement above) +2. **Determine the `idSuffix`** for each collection (the `wix-cli-data-collection` skill documents the full ID format) +3. **Pass the full scoped collection ID** (`/`) to every other sub-agent (dashboard page, service plugin, etc.) so they use it in all Wix Data API calls + +### Step 2: Make Your Recommendation + +Use Quick Reference Table and decision content above. State extension type and brief reasoning (placement, functionality, integration). + +### Step 3: Check References, Then Discover (if needed) + +**Workflow: References first, search only for gaps.** + +1. **Identify required APIs** from user requirements +2. **Check relevant reference files:** + - Backend events → `wix-cli-backend-event/references/COMMON-EVENTS.md` + - Wix Data → `wix-cli-dashboard-page/references/WIX_DATA.md` + - Dashboard SDK → `wix-cli-dashboard-page/references/DASHBOARD_API.md` + - Service Plugin SPIs → `wix-cli-service-plugin/references/*.md` +3. **Verify the specific method/event exists** in references +4. **ONLY spawn discovery if NOT found** in reference files + +**Platform APIs (never discover - in references):** +- Wix Data, Dashboard SDK, Event SDK (common events), Service Plugin SPIs + +**Vertical APIs (discover if needed):** +- Wix Stores (**⚠️ MUST use `wix-stores-versioning` skill** - V1/V3 catalog check required), Wix Bookings, Wix Members, Wix Pricing Plans, third-party integrations + +**Decision table:** + +| User Requirement | Check References / Discovery Needed? | Reason / Reference File | +| ------------------------------------ | ------------------------------------ | --------------------------------------------------- | +| "Display store products" | ✅ YES (Spawn discovery) | Wix Stores API — **include `wix-stores-versioning` skill** | +| "Show booking calendar" | ✅ YES (Spawn discovery) | Wix Bookings API not in reference files | +| "Send emails to users" | ✅ YES (Spawn discovery) | Wix Triggered Emails not in reference files | +| "Get member info" | ✅ YES (Spawn discovery) | Wix Members API not in reference files | +| "Listen for cart events" | Check `COMMON-EVENTS.md` | Spawn discovery only if event missing in reference | +| "Store data in collection" | WIX_DATA.md ✅ Found | ❌ Skip discovery (covered by `WIX_DATA.md`) | +| "Create CMS collections for my app" | Reference: `wix-cli-data-collection` | ❌ Skip discovery (covered by dedicated skill) | +| "Show dashboard toast" | DASHBOARD_API.md ✅ Found | ❌ Skip discovery | +| "Show toast / navigate" | DASHBOARD_API.md ✅ Found | ❌ Skip discovery | +| "UI only (forms, inputs)" | N/A (no external API) | ❌ Skip discovery | +| "Settings page with form inputs" | N/A (UI only, no external API) | ❌ Skip discovery | +| "Dashboard page with local state" | N/A (no external API) | ❌ Skip discovery | + +**MCP Tools the sub-agent should use:** + +- `SearchWixSDKDocumentation` - SDK methods and APIs (**Always use maxResults: 5**) +- `ReadFullDocsArticle` - Full documentation when needed (only if search results need more detail) + +**Discovery sub-agent prompt template:** + +``` +Discover SDK methods for [SPECIFIC API/EVENT NOT IN REFERENCE FILES]. + +Search MCP documentation (use maxResults: 5): +- Search SDK documentation for [SPECIFIC API] with maxResults: 5 +- Only use ReadFullDocsArticle if search results need more context + +Return ONLY a concise summary in this format: + +## SDK Methods & Interfaces + +| Name | Type | TypeScript Type | Description | +| ------------------------- | ------ | -------------------------------------------- | ----------------- | +| `moduleName.methodName()` | Method | `(params: ParamType) => Promise` | Brief description | + +**Import:** `import { methodName } from '@wix/sdk-module';` + +Include any gotchas or constraints discovered. + +## Manual Action Items +List any manual steps the user must perform (e.g., configure dashboard settings, enable permissions). Write "None" if there are no manual steps. + +**Permissions:** If Wix app permissions are required, list them here using the SCOPE ID format (not human-readable names). Examples: +- `@wix/data` read operations (query, get) require "SCOPE.DC-DATA.READ" +- `@wix/data` write operations (insert, update, remove) require "SCOPE.DC-DATA.WRITE" +- Embedded scripts require "SCOPE.DC-APPS.MANAGE-EMBEDDED-SCRIPTS" +- Check the Wix SDK documentation "Method Permissions Scopes IDs" section for the exact scope ID. +- IMPORTANT: Use scope IDs like "SCOPE.DC-DATA.READ", NOT human-readable names like "Read Data Items". +``` + +**If discovery is spawned, wait for it to complete before proceeding to Step 4.** + +### Step 4: Spawn Implementation Sub-Agent(s) + +⚠️ **BLOCKING REQUIREMENT** ⚠️ + +You MUST spawn sub-agent(s) for implementation. Do NOT invoke implementation skills directly. Do NOT write code yourself. + +**Spawn an implementation sub-agent with the skill context:** + +The sub-agent prompt should include: + +1. The skill to load (e.g., `wix-cli-dashboard-page`) +2. The user's requirements +3. The SDK context from the discovery sub-agent +4. Instruction to invoke the `wds-docs` skill only when needed (e.g. when looking up WDS component props or examples) + +**Implementation sub-agent prompt MUST include:** + +1. ✅ The skill to load (full path or name) +2. ✅ The user's original requirements (copy verbatim) +3. ✅ SDK methods discovered (with imports and types) — **only if discovery was performed** +4. ✅ Instruction to invoke `wds-docs` skill FIRST when using @wix/design-system (critical for correct imports, especially icons) +5. ✅ Any constraints or gotchas discovered +6. ✅ Collection Context with full scoped collection IDs — **only if Data Collection is being created** +7. ✅ Instruction to return manual action items (see below) + +**Implementation sub-agent prompt template:** + +``` +Load and follow the skill: wix-cli-[skill-name] + +User Requirements: +[EXACT user request - copy verbatim] + +[ONLY IF DISCOVERY WAS PERFORMED:] +SDK Context: +[Methods with imports from discovery] + +Constraints: +[Any gotchas or limitations from discovery] + +⚠️ MANDATORY when using WDS: Invoke the wds-docs skill FIRST to get correct imports (icons are from @wix/wix-ui-icons-common, NOT @wix/design-system/icons). + +⚠️ MANDATORY when using Data Collections: Use EXACT collection ID from `idSuffix` (case-sensitive). Example: If `idSuffix` is "product-recommendations", use "/product-recommendations" NOT "productRecommendations". + +⚠️ MANDATORY: At the END of your response, include a section titled "## Manual Action Items" listing ANY steps the user must perform manually (e.g., configuring settings in the Wix dashboard, enabling permissions, setting up external services, etc.). If there are no manual steps, write "None". This section MUST always be present in your final response. + +Implement this extension following the skill guidelines. +``` + +**PARALLEL EXECUTION:** When multiple independent extensions are needed, spawn ALL sub-agents in parallel: + +| Extension Combination | Parallel? | Reason | +| -------------------------------- | --------- | ----------------------------------- | +| Dashboard Page + Site Widget | ✅ YES | Independent UI contexts | +| Dashboard Page + Dashboard Modal | ✅ YES | Modal code is independent from page | +| Dashboard Page + Backend API | ✅ YES | Frontend vs backend | +| Site Widget + Embedded Script | ✅ YES | Different rendering contexts | +| Service Plugin + Event Extension | ✅ YES | Independent backend handlers | +| Data Collection + Dashboard Page | ✅ YES | Data schema vs UI | +| Data Collection + Backend API | ✅ YES | Data schema vs HTTP handlers | +| Data Collection + Site Widget | ✅ YES | Data schema vs site UI | + +**Pre-spawn coordination required (then parallel is fine):** + +- When a Data Collection + other extensions reference the same collections: determine the full scoped collection IDs (`/`) BEFORE spawning sub-agents, then pass the IDs to all sub-agents and run them in parallel + +**Sequential execution required:** + +- When one extension imports types/interfaces from another +- When user explicitly says "first X, then Y" + +**Extension Type to Skill Mapping:** See [Quick Reference Table](#quick-reference-table) above. + +**Wait for sub-agents to complete before proceeding to Step 5.** + +### Step 5: Run Validation + +⚠️ **BLOCKING REQUIREMENT** ⚠️ + +After ALL implementation sub-agents complete, you MUST run validation by invoking the `wix-cli-app-validation` skill. + +**Do NOT report completion to the user until validation passes.** + +If validation fails: + +1. Review the errors +2. Spawn a new implementation sub-agent to fix the issues +3. Run validation again +4. Repeat until validation passes + +### Step 6: Report Completion + +Only after validation passes, provide a **concise summary section** at the top of your response that includes: + +**Required format:** + +```markdown +## ✅ Implementation Complete + +[1-2 sentence description of what was built] + +**Extensions Created:** +- [Extension 1 Name] - [Brief purpose] +- [Extension 2 Name] - [Brief purpose] +- [Extension 3 Name] - [Brief purpose] + +**Build Status:** +- ✅ Dependencies: [Installed / status message] +- ✅ TypeScript: [No compilation errors / status] +- ✅ Build: [Completed successfully / status] +- ✅/⚠️ Preview: [Running at URL / Failed - reason] + +**⚠️ IMPORTANT: [X] manual step(s) required to complete setup** (see "Manual Steps Required" section below) +``` + +**Critical rules:** +- The summary MUST explicitly state how many manual steps are required +- The summary MUST reference where to find the manual steps ("see Manual Steps Required section below") +- If there are NO manual steps, state: "✅ No manual steps required — you're ready to go!" +- Keep the summary concise (under 200 words) +- Present build status clearly with ✅ or ⚠️ indicators + +### Step 7: Surface Manual Action Items + +⚠️ **BLOCKING REQUIREMENT** ⚠️ + +**Sub-agents often report manual steps the user must take (e.g., configure permissions in the Wix dashboard, enable specific features, etc.). These MUST NOT get lost.** + +After ALL sub-agents complete, you MUST: + +1. **Review every sub-agent's output** for any "Manual Action Items" section or any mention of steps the user needs to perform manually +2. **Aggregate ALL manual action items** from every sub-agent into a single, deduplicated list +3. **Reference them in the summary section** (Step 6) by stating how many manual steps exist +4. **Present them prominently** at the very end of your final message to the user, under a clear heading + +**Complete workflow for manual steps:** + +1. **In the summary (Step 6):** Include the line `**⚠️ IMPORTANT: [X] manual step(s) required to complete setup** (see "Manual Steps Required" section below)` +2. **At the end of your response:** Present the full detailed manual steps section + +**Format for the manual steps section:** + +```markdown +## 🔧 Manual Steps Required + +The following actions need to be done manually by you: + +### 1. [Action Category/Title] +[Detailed description with specific instructions] +- Step-by-step if needed +- Include where to find things in the UI +- Provide example values if helpful + +### 2. [Action Category/Title] +[Detailed description] + +### 3. [Action Category/Title] +[Detailed description] + +[Continue for all manual steps...] +``` + +**If no manual steps are needed:** +```markdown +## 🔧 Manual Steps Required + +No manual steps required — you're all set! Your implementation is complete and ready to use. +``` + +**Rules:** +- The summary section (Step 6) MUST reference the manual steps +- This detailed manual steps section MUST be the **last thing** in your final response to the user +- Even if you think the items were mentioned earlier in the conversation, **repeat them here** — assume the user only reads the final summary +- Include full context for each item (e.g., "In the Wix dashboard, go to Settings > Permissions and enable X" rather than just "enable X") +- Group related steps together under category headings for clarity +- If a sub-agent didn't include a "Manual Action Items" section, review its full output for any implicit manual steps (phrases like "you'll need to", "make sure to", "don't forget to", "manually", "go to the dashboard", etc.) +- Number the main categories/sections (1, 2, 3...) for easy reference + +**Summary:** Discovery = business domain SDK only (Stores, Bookings, etc.) — skip for extension SDK and data collections. Implementation = load extension skill; invoke `wds-docs` FIRST when using WDS (for correct imports). Validation = `wix-cli-app-validation`. Manual actions = always aggregated and surfaced at the end. + +## Cost Optimization + +- **Check references first** — read relevant reference files before spawning discovery +- **Skip discovery** when all required APIs are in reference files +- **maxResults: 5** for all MCP SDK searches +- **ReadFullDocsArticle** only when search results need more context +- **Implementation prompts:** include only relevant SDK context from discovery (if performed) +- **Parallelize** independent sub-agents when possible +- **Invoke wds-docs** first when using WDS (prevents import errors) +- **Targets:** discovery output 500-1000 tokens; implementation prompt minimal; each search under 2000-3000 tokens + +## Documentation + +For detailed documentation on all extension types, see [references/DOCUMENTATION.md](references/DOCUMENTATION.md). diff --git a/CLI App - Calculator Form/.agents/skills/wix-cli-orchestrator/references/DOCUMENTATION.md b/CLI App - Calculator Form/.agents/skills/wix-cli-orchestrator/references/DOCUMENTATION.md new file mode 100644 index 0000000..9045461 --- /dev/null +++ b/CLI App - Calculator Form/.agents/skills/wix-cli-orchestrator/references/DOCUMENTATION.md @@ -0,0 +1,42 @@ +# Wix CLI Extension Documentation + +All information in the wix-cli-orchestrator skill is based on official Wix CLI documentation. This file contains links to detailed documentation for each extension type. + +## Main Documentation + +- [About Extensions](https://dev.wix.com/docs/wix-cli/guides/extensions/about-extensions) - Overview of extensions in the Wix CLI +- [About the extensions.ts File](https://dev.wix.com/docs/wix-cli/guides/extensions/about-the-extensions-ts-file) - How to register extensions + +## Dashboard Extensions + +- [About Dashboard Extensions](https://dev.wix.com/docs/wix-cli/guides/extensions/dashboard-extensions/about-dashboard-extensions) - Overview of dashboard extension types +- [Add Dashboard Page Extensions](https://dev.wix.com/docs/wix-cli/guides/extensions/dashboard-extensions/dashboard-pages/add-dashboard-page-extensions) - How to create dashboard pages +- [Dashboard Page Extension Files and Code](https://dev.wix.com/docs/wix-cli/guides/extensions/dashboard-extensions/dashboard-pages/dashboard-page-extension-files-and-code) - File structure and code examples +- [Add Dashboard Modal Extensions](https://dev.wix.com/docs/wix-cli/guides/extensions/dashboard-extensions/dashboard-modals/add-dashboard-modal-extensions) - How to create dashboard modals +- [Dashboard Modal Extension Files and Code](https://dev.wix.com/docs/wix-cli/guides/extensions/dashboard-extensions/dashboard-modals/dashboard-modal-extensions-files-and-code) - File structure and code examples +- [Add Dashboard Plugin Extensions](https://dev.wix.com/docs/wix-cli/guides/extensions/dashboard-extensions/dashboard-plugins/add-dashboard-plugin-extensions) - How to create dashboard plugins +- [Dashboard Plugin Extension Files and Code](https://dev.wix.com/docs/wix-cli/guides/extensions/dashboard-extensions/dashboard-plugins/dashboard-plugin-extension-files-and-code) - File structure and code examples +- [Add Dashboard Menu Plugin Extensions](https://dev.wix.com/docs/wix-cli/guides/extensions/dashboard-extensions/dashboard-menu-plugins/add-dashboard-menu-plugin-extensions) - How to create dashboard menu plugins +- [Dashboard Menu Plugin Extension Files and Code](https://dev.wix.com/docs/wix-cli/guides/extensions/dashboard-extensions/dashboard-menu-plugins/dashboard-menu-plugin-extension-files-and-code) - File structure and code examples + +## Backend Extensions + +- [About Backend Extensions](https://dev.wix.com/docs/wix-cli/guides/extensions/backend-extensions/about-backend-extensions) - Overview of backend extension types and limits +- [Add Service Plugin Extensions](https://dev.wix.com/docs/wix-cli/guides/extensions/backend-extensions/service-plugins/add-service-plugin-extensions) - How to create service plugins +- [Service Plugin Extension Files and Code](https://dev.wix.com/docs/wix-cli/guides/extensions/backend-extensions/service-plugins/service-plugin-extension-files-and-code) - File structure and code examples +- [Add Event Extensions](https://dev.wix.com/docs/wix-cli/guides/extensions/backend-extensions/events/add-event-extensions) - How to create event extensions +- [Event Extension Files and Code](https://dev.wix.com/docs/wix-cli/guides/extensions/backend-extensions/events/event-extension-files-and-code) - File structure and code examples +- [About HTTP Endpoints](https://dev.wix.com/docs/wix-cli/guides/development/http-endpoints/about-http-endpoints) - Overview of Astro endpoints +- [Add HTTP Endpoints to Your Project](https://dev.wix.com/docs/wix-cli/guides/development/http-endpoints/add-http-endpoints-to-your-project) - How to create backend endpoints + +## Site Extensions + +- [About Site Extensions](https://dev.wix.com/docs/wix-cli/guides/extensions/site-extensions/about-site-extensions) - Overview of site extension types +- [Add Site Widget Extensions](https://dev.wix.com/docs/wix-cli/guides/extensions/site-extensions/site-widgets/add-a-site-widget-extension) - How to create site widgets +- [Site Widget Extension Files and Code](https://dev.wix.com/docs/wix-cli/guides/extensions/site-extensions/site-widgets/site-widget-extension-files-and-code) - File structure and code examples +- [Identify the App Instance in a Site Widget](https://dev.wix.com/docs/wix-cli/guides/extensions/site-extensions/site-widgets/identify-the-app-instance-in-a-site-widget) - How to identify app instances +- [Add Site Plugin Extensions](https://dev.wix.com/docs/wix-cli/guides/extensions/site-extensions/site-plugins/add-a-site-plugin-extension) - How to create site plugins +- [Site Plugin Extension Files and Code](https://dev.wix.com/docs/wix-cli/guides/extensions/site-extensions/site-plugins/site-plugin-extension-files-and-code) - File structure and code examples +- [About Embedded Scripts](https://dev.wix.com/docs/wix-cli/guides/extensions/site-extensions/embedded-scripts/about-embedded-scripts) - Overview of embedded scripts +- [Add Embedded Script Extensions](https://dev.wix.com/docs/wix-cli/guides/extensions/site-extensions/embedded-scripts/add-an-embedded-script-extension) - How to create embedded scripts +- [Embedded Script Extension Files and Code](https://dev.wix.com/docs/wix-cli/guides/extensions/site-extensions/embedded-scripts/embedded-script-extension-files-and-code) - File structure and code examples diff --git a/CLI App - Calculator Form/.agents/skills/wix-cli-service-plugin/SKILL.md b/CLI App - Calculator Form/.agents/skills/wix-cli-service-plugin/SKILL.md new file mode 100644 index 0000000..6741c57 --- /dev/null +++ b/CLI App - Calculator Form/.agents/skills/wix-cli-service-plugin/SKILL.md @@ -0,0 +1,242 @@ +--- +name: wix-cli-service-plugin +description: Use when implementing service plugin extensions that inject custom backend logic into existing Wix business solution flows or introduce new flows to Wix sites. Triggers include SPI, service plugin, backend flow, business logic, custom shipping rates, additional fees, tax calculation, checkout validation, discount triggers, gift cards, eCommerce customization. +compatibility: Requires Wix CLI development environment. +--- + +# Wix Service Plugin (SPI) Builder + +Creates service plugin extensions for Wix CLI applications. Service plugins are a set of APIs defined by Wix that you can use to inject custom logic into the existing backend flows of Wix business solutions or to introduce entirely new flows to Wix sites. + +When you implement a service plugin, Wix calls your custom functions during specific flows. Common use cases include eCommerce customization (shipping, fees, taxes, validations), but service plugins can extend any Wix business solution that exposes SPIs. + +## Quick Start Checklist + +Follow these steps in order when creating a service plugin: + +1. [ ] **Read the reference doc** for your SPI type (REQUIRED before implementation) +2. [ ] Create plugin folder: `src/backend/service-plugins///` +3. [ ] Create `plugin.ts` with correct imports and `provideHandlers()` call +4. [ ] Implement all required handler functions with complete business logic +5. [ ] Create `extensions.ts` with appropriate builder method and unique UUID +6. [ ] Update `src/extensions.ts` to import and use the new extension +7. [ ] Run `npx tsc --noEmit` to verify TypeScript compiles +8. [ ] Run `npx wix build` to verify build succeeds +9. [ ] Test by triggering the relevant site action (e.g., add to cart for fees) + +## References + +**You MUST read the relevant reference document before implementing a relevant SPI.** Each reference contains the correct imports, handler signatures, response structures, and working examples. + +| SPI Type | Reference | +| --- | --- | +| Additional Fees | [ADDITIONAL-FEES.md](./references/ADDITIONAL-FEES.md) | +| Discount Triggers | [DISCOUNT-TRIGGERS.md](./references/DISCOUNT-TRIGGERS.md) | +| Gift Cards | [GIFT-CARDS.md](./references/GIFT-CARDS.md) | +| Shipping Rates | [SHIPPING-RATES.md](./references/SHIPPING-RATES.md) | +| Tax Calculation | [TAX-CALCULATION.md](./references/TAX-CALCULATION.md) | +| Validations | [VALIDATIONS.md](./references/VALIDATIONS.md) | + +## Output Structure + +Service plugins consist of two files that work together. Registration of plugins requires an extension builder file. + +``` +src/backend/service-plugins/ +└── {service-type}/ + └── {plugin-name}/ + ├── plugin.ts # Handler logic with provideHandlers() + └── extensions.ts # Builder configuration (id, name, source) +``` + +### File Descriptions + +| File | Purpose | +| --- | --- | +| `plugin.ts` | Contains the service plugin handler logic with `provideHandlers()` - this is where you implement your custom business logic | +| `extensions.ts` | Contains the service plugin builder configuration with id (GUID), name, source path, and builder-specific optional fields | + +## Implementation Requirements + +### Generation Requirements + +1. **Implement ALL required handler functions** with complete business logic +2. **Include proper TypeScript types and error handling** +3. **Focus on implementing the EXACT business logic** described in the user prompt + +### Implementation Patterns + +- **If capabilities are undocumented/unavailable**, explicitly state the gap and proceed only with documented minimal logic +- **Implement all required handler functions** according to Wix specifications +- **Never use placeholders** - always implement complete, working functionality + +### Data Validation + +All service plugins must include comprehensive data validation: + +- **Validate all input data** from Wix requests +- **Ensure required fields** are present and properly formatted +- **Handle missing or malformed data** gracefully +- **Validate business logic constraints** (e.g., minimum order amounts, valid addresses) + +## Implementation Pattern + +The handler file (`plugin.ts`) contains the service plugin logic. It must: + +1. Import the relevant service plugin from `@wix/ecom/service-plugins` +2. Call `provideHandlers()` with an object containing handler functions +3. Each handler function receives a payload with `request` and `metadata` +4. Return the expected response structure for that SPI type + +```typescript +import { shippingRates } from "@wix/ecom/service-plugins"; + +shippingRates.provideHandlers({ + getShippingRates: async (payload) => { + const { request, metadata } = payload; + + // Implement custom logic based on request data + // - request contains cart items, shipping address, etc. + // - metadata contains currency, locale, etc. + + return { + shippingRates: [ + { + code: "custom-shipping", + title: "Custom Shipping", + logistics: { + deliveryTime: "3-5 business days", + }, + cost: { + price: "9.99", + currency: metadata.currency || "USD", + }, + }, + ], + }; + }, +}); +``` + +Handler functions are called automatically by Wix when the relevant site action triggers them. Your custom logic should be placed inside each handler function. + +## Elevating Permissions for API Calls + +When making Wix API calls from service plugins, you must elevate permissions using `auth.elevate` from `@wix/essentials`. + +```typescript +import { auth } from "@wix/essentials"; +import { items } from "@wix/data"; + +export const myFunction = async () => { + const elevatedFunction = auth.elevate(items.query); + const elevatedResponse = await elevatedFunction("myCollection"); + return elevatedResponse; +}; +``` + +```typescript +import { auth } from "@wix/essentials"; +import { cart } from "@wix/ecom"; + +export const myFunction = async () => { + const elevatedFunction = auth.elevate(cart.getCart); + const elevatedResponse = await elevatedFunction("cart-id"); + return elevatedResponse; +}; +``` + +```typescript +import { auth } from "@wix/essentials"; +import { products } from "@wix/stores"; + +export const myFunction = async () => { + const elevatedFunction = auth.elevate(products.deleteCollection); + const elevatedResponse = await elevatedFunction("collection-id"); + return elevatedResponse; +}; +``` + +## Best Practices + +### Development Workflow + +- **Always implement complete, working functionality** - never use placeholders +- **Handle all required fields** according to Wix documentation +- **Implement proper validation** for all input data +- **Return responses in exact format** expected by Wix +- **Add comprehensive error handling** for all failure scenarios +- **Use meaningful variable names** and clear code structure +- **Test thoroughly** with different input combinations + +### Implementation Guidelines + +- **Validate all input:** Check required fields are present and properly formatted +- **Handle errors gracefully:** Return appropriate error responses, don't throw unhandled exceptions +- **Return exact format:** Responses must match Wix documented structure exactly +- **Use TypeScript types:** Leverage SDK types for better type safety +- **Test edge cases:** Empty carts, missing addresses, invalid data +- **Performance:** Keep calculations efficient - these run on every checkout +- **Logging:** Add console.log for debugging but keep production logs minimal + +## Extension Registration + +**Extension registration is MANDATORY and has TWO required steps.** + +### Step 1: Create Plugin-Specific Extension File + +Each service plugin requires an `extensions.ts` file in its folder with the appropriate builder method for the SPI type: + +```typescript +import { extensions } from "@wix/astro/builders"; + +export const ecomadditionalfeesMyFees = extensions.ecomAdditionalFees({ + id: "{{GENERATE_UUID}}", + name: "My Additional Fees", + source: "./backend/service-plugins/ecom-additional-fees/my-fees/plugin.ts", +}); +``` + +**CRITICAL: UUID Generation** + +The `id` must be a unique, static UUID v4 string. Generate a fresh UUID for each extension - do NOT use `randomUUID()` or copy UUIDs from examples. Replace `{{GENERATE_UUID}}` with a freshly generated UUID like `"a1b2c3d4-e5f6-7890-abcd-ef1234567890"`. + +### Builder Configuration Fields + +All builder methods accept these three fields: + +| Field | Type | Description | +| --- | --- | --- | +| `id` | string | Service plugin ID as a GUID. Must be unique across all extensions in the project. | +| `name` | string | The service plugin name (visible in app dashboard when developing an app). | +| `source` | string | Path to the service plugin handler file that contains the plugin logic. | + +**Builder methods by SPI type and their accepted fields:** + +| SPI Type | Builder Method | Accepted Fields | +| ----------------- | ------------------------ | --------------- | +| Shipping Rates | `ecomShippingRates()` | `id`, `name`, `source`, `description`, `learnMoreUrl`, `dashboardUrl`, `fallbackDefinitionMandatory`, `thumbnailUrl` | +| Additional Fees | `ecomAdditionalFees()` | `id`, `name`, `source` | +| Validations | `ecomValidations()` | `id`, `name`, `source`, `validateInCart` | +| Discount Triggers | `ecomDiscountTriggers()` | `id`, `name`, `source` | +| Gift Cards | `ecomGiftCards()` | `id`, `name`, `source` | +| Payment Settings | `ecomPaymentSettings()` | `id`, `name`, `source`, `fallbackValueForRequires3dSecure` | + +Only `ecomShippingRates()` accepts `description`. Passing unsupported fields to other builders causes TypeScript errors. + +### Step 2: Register in Main Extensions File + +**CRITICAL:** After creating the plugin-specific extension file, you MUST read [wix-cli-extension-registration](../wix-cli-extension-registration/SKILL.md) and follow the "App Registration" section to update `src/extensions.ts`. + +**Without completing Step 2, the service plugin will not be active in the eCommerce system.** + +## Testing Service Plugins + +To test your service plugin extension: + +1. **Release a version** with your changes - new service plugins or changes to existing ones won't take effect until you've built and released your project +2. **Trigger the call** to your service plugin by performing the relevant action (e.g., add items to cart and view cart to test Additional Fees) + +## Verification + +After implementation, use [wix-cli-app-validation](../wix-cli-app-validation/SKILL.md) to validate TypeScript compilation, build, preview, and runtime behavior. diff --git a/CLI App - Calculator Form/.agents/skills/wix-cli-service-plugin/references/ADDITIONAL-FEES.md b/CLI App - Calculator Form/.agents/skills/wix-cli-service-plugin/references/ADDITIONAL-FEES.md new file mode 100644 index 0000000..df5ff51 --- /dev/null +++ b/CLI App - Calculator Form/.agents/skills/wix-cli-service-plugin/references/ADDITIONAL-FEES.md @@ -0,0 +1,153 @@ +# Additional Fees Service Plugin Reference + +## Overview + +The Additional Fees SPI allows you to add custom fees to orders during checkout, such as handling fees, rush delivery charges, or global order fees. + +## Import + +```typescript +import { additionalFees } from '@wix/ecom/service-plugins'; +``` + +## Handler + +| Handler | Description | +| --- | --- | +| `calculateAdditionalFees` | Calculate and return additional fees to apply to the order | + +## Request Structure + +The `calculateAdditionalFees` handler receives `{ request, metadata }`. Key fields on `request`: + +```typescript +{ + lineItems: Array<{ + id: string; // Line item GUID + quantity: number; // Quantity of item + productName: string; // Item name + price: string; // Price for a single item as a STRING (e.g., "25.00"), NOT an object + catalogReference?: { + catalogItemId: string; // Item GUID within its catalog + appId: string; // Catalog app GUID + options?: Record; // Additional item details + }; + physicalProperties?: { + weight: number; // Item weight + sku: string; // Stock-keeping unit + shippable: boolean; // Whether item is shippable + }; + }>; + shippingAddress?: { // Shipping address (if provided) + country: string; // ISO-3166 alpha-2 country code + subdivision?: string; // State/province code + city?: string; + postalCode?: string; + }; + buyerDetails?: { ... }; // Buyer contact info + subtotal: string; // Pre-calculated total: sum of (price × quantity) for all line items, as a STRING +} +``` + +## Example: Global Additional Fee from Database Configuration + +This example queries a CMS collection to retrieve a configurable global fee that applies to all orders. + +```typescript +import { additionalFees } from '@wix/ecom/service-plugins'; +import { auth } from '@wix/essentials'; +import { items } from '@wix/data'; + +interface GlobalFeeConfig { + _id: string; + feeAmount: number; + isEnabled: boolean; +} + +additionalFees.provideHandlers({ + calculateAdditionalFees: async ({ request, metadata }) => { + try { + // Query the global additional fee configuration (elevated permissions required) + const elevatedQuery = auth.elevate(items.query); + const configResult = await elevatedQuery('global-additional-fee-config') + .limit(1) + .find(); + + // If no configuration found or fee is disabled, return empty fees + if (!configResult.items.length) { + return { + additionalFees: [], + currency: metadata.currency || 'USD' + }; + } + + const config = configResult.items[0] as GlobalFeeConfig; + + // Check if the fee is enabled and has a valid amount + if (!config.isEnabled || !config.feeAmount || config.feeAmount <= 0) { + return { + additionalFees: [], + currency: metadata.currency || 'USD' + }; + } + + // Ensure currency matches site currency + const responseCurrency = metadata.currency || 'USD'; + + // Convert fee amount to string as required by Wix API + const feeAmountString = config.feeAmount.toString(); + + // Create the global additional fee + const globalFee = { + code: 'global-additional-fee', + name: 'Global Additional Fee', + translatedName: 'Global Additional Fee', + price: feeAmountString, + taxDetails: { + taxable: true + } + // No lineItemIds specified - applies to entire cart + }; + + return { + additionalFees: [globalFee], + currency: responseCurrency + }; + + } catch (error) { + return { + additionalFees: [], + currency: metadata.currency || 'USD' + }; + } + }, +}); +``` + +## Response Structure + +The `calculateAdditionalFees` handler must return: + +```typescript +{ + additionalFees: Array<{ + code: string; // Unique identifier for the fee + name: string; // Display name + translatedName?: string; // Optional translated name + price: string; // Fee amount as string + taxDetails?: { + taxable: boolean; // Whether fee is taxable + }; + lineItemIds?: string[]; // Optional: specific items (omit for cart-wide) + }>; + currency: string; // Currency code (e.g., "USD") +} +``` + +## Key Implementation Notes + +1. **Elevate permissions for API calls** - Use `auth.elevate` from `@wix/essentials` when calling Wix APIs from service plugins +2. **Return empty array when no fees apply** - Always return `{ additionalFees: [], currency: "..." }` when conditions aren't met +3. **Price must be a string** - Convert numeric amounts to strings +4. **Handle errors gracefully** - Return empty fees on error rather than throwing +5. **Omit lineItemIds for cart-wide fees** - Only specify when fee applies to specific items diff --git a/CLI App - Calculator Form/.agents/skills/wix-cli-service-plugin/references/DISCOUNT-TRIGGERS.md b/CLI App - Calculator Form/.agents/skills/wix-cli-service-plugin/references/DISCOUNT-TRIGGERS.md new file mode 100644 index 0000000..35aceb1 --- /dev/null +++ b/CLI App - Calculator Form/.agents/skills/wix-cli-service-plugin/references/DISCOUNT-TRIGGERS.md @@ -0,0 +1,98 @@ +# Discount Triggers Service Plugin Reference + +## Overview + +The Custom Triggers SPI allows you to define custom conditions that can trigger discounts in the Wix eCommerce system. You can create time-based triggers, product-based triggers, or any custom logic. + +## Import + +```typescript +import { customTriggers } from "@wix/ecom/service-plugins"; +``` + +## Handlers + +| Handler | Description | +| --- | --- | +| `getEligibleTriggers` | Evaluate current conditions and return which triggers are active | +| `listTriggers` | Return the list of all available custom triggers | + +## Example: Happy Hour and Digital Products Triggers + +This example defines two custom triggers: a time-based "Happy Hour" trigger and a product-type-based "Digital Sale" trigger. + +```typescript +import { customTriggers } from "@wix/ecom/service-plugins"; + +customTriggers.provideHandlers({ + getEligibleTriggers: async (payload) => { + const { request, metadata } = payload; + // Use the `request` and `metadata` received from Wix and + // apply custom logic. + return { + // Return your response exactly as documented to integrate with Wix. + // Return value example: + eligibleTriggers: [ + { + customTriggerId: "my-happy-hour-trigger", + identifier: "123", + }, + { + customTriggerId: "my-digital-sale-trigger", + identifier: "234", + }, + ], + }; + }, + listTriggers: async (payload) => { + const { request, metadata } = payload; + // Use the `request` and `metadata` received from Wix and + // apply custom logic. + return { + // Return your response exactly as documented to integrate with Wix. + // Return value example: + customTriggers: [ + { + _id: "my-happy-hour-trigger", + name: "Happy Hour 16:00-18:00", + }, + { + _id: "my-digital-sale-trigger", + name: "Digital products discount", + }, + ], + }; + }, +}); +``` + +## Response Structure + +### getEligibleTriggers Response + +```typescript +{ + eligibleTriggers: Array<{ + customTriggerId: string; // ID matching one from listTriggers + identifier: string; // Unique identifier for this trigger instance + }>; +} +``` + +### listTriggers Response + +```typescript +{ + customTriggers: Array<{ + _id: string; // Unique trigger ID + name: string; // Display name shown in Wix dashboard + }>; +} +``` + +## Key Implementation Notes + +1. **Trigger IDs must match** - The `customTriggerId` in `getEligibleTriggers` must match an `_id` from `listTriggers` +2. **Both handlers required** - You must implement both `getEligibleTriggers` and `listTriggers` +3. **Dynamic eligibility** - `getEligibleTriggers` is called during checkout to determine which triggers are currently active +4. **Static list** - `listTriggers` provides the master list of all possible triggers for configuration in the Wix dashboard diff --git a/CLI App - Calculator Form/.agents/skills/wix-cli-service-plugin/references/GIFT-CARDS.md b/CLI App - Calculator Form/.agents/skills/wix-cli-service-plugin/references/GIFT-CARDS.md new file mode 100644 index 0000000..a5c5407 --- /dev/null +++ b/CLI App - Calculator Form/.agents/skills/wix-cli-service-plugin/references/GIFT-CARDS.md @@ -0,0 +1,102 @@ +# Gift Cards Service Plugin Reference + +## Overview + +The Gift Vouchers Provider SPI allows you to integrate external gift card or voucher systems with Wix eCommerce. This enables customers to redeem gift cards, check balances, and void transactions. + +## Import + +```typescript +import { giftVouchersProvider } from '@wix/ecom/service-plugins'; +``` + +## Handlers + +| Handler | Description | +| --- | --- | +| `redeem` | Process a gift card redemption during checkout | +| `getBalance` | Check the current balance of a gift card | +| `_void` | Cancel/void a previous redemption | + +## Example: Gift Card Provider Implementation + +This example shows a basic gift card provider with all three required handlers. + +```typescript +import { giftVouchersProvider } from '@wix/ecom/service-plugins'; + +giftVouchersProvider.provideHandlers({ + redeem: async (payload) => { + const { request, metadata } = payload; + // Use the `request` and `metadata` received from Wix and + // apply custom logic. + return { + // Return your response exactly as documented to integrate with Wix. + // Return value example: + remainingBalance: 80.00, + currencyCode: metadata.currency || "ILS", + transactionId: "00000000-0000-0000-0000-000000000001", + }; + }, + _void: async (payload) => { + const { request, metadata } = payload; + // Use the `request` and `metadata` received from Wix and + // apply custom logic. + return { + // Return your response exactly as documented to integrate with Wix. + // Return value example: + remainingBalance: 100.00, + currencyCode: metadata.currency || "ILS", + }; + }, + getBalance: async (payload) => { + const { request, metadata } = payload; + // Use the `request` and `metadata` received from Wix and + // apply custom logic. + return { + // Return your response exactly as documented to integrate with Wix. + // Return value example: + balance: 100.00, + currencyCode: metadata.currency || "ILS", + }; + }, +}); +``` + +## Response Structure + +### redeem Response + +```typescript +{ + remainingBalance: number; // Balance after redemption + currencyCode: string; // Currency code (e.g., "USD", "ILS") + transactionId: string; // Unique ID for this redemption transaction +} +``` + +### _void Response + +```typescript +{ + remainingBalance: number; // Balance after voiding (restored amount) + currencyCode: string; // Currency code +} +``` + +### getBalance Response + +```typescript +{ + balance: number; // Current gift card balance + currencyCode: string; // Currency code +} +``` + +## Key Implementation Notes + +1. **All three handlers required** - You must implement `redeem`, `getBalance`, and `_void` +2. **Transaction tracking** - The `redeem` handler must return a unique `transactionId` for tracking +3. **Balance as number** - Unlike other SPIs, balance values are numbers, not strings +4. **Void restores balance** - The `_void` handler should restore the redeemed amount back to the card +5. **Currency handling** - Use `metadata.currency` to get the site's currency setting diff --git a/CLI App - Calculator Form/.agents/skills/wix-cli-service-plugin/references/SHIPPING-RATES.md b/CLI App - Calculator Form/.agents/skills/wix-cli-service-plugin/references/SHIPPING-RATES.md new file mode 100644 index 0000000..912b07c --- /dev/null +++ b/CLI App - Calculator Form/.agents/skills/wix-cli-service-plugin/references/SHIPPING-RATES.md @@ -0,0 +1,96 @@ +# Shipping Rates Service Plugin Reference + +## Overview + +The Shipping Rates SPI allows you to provide custom shipping options and calculate shipping costs based on order details, destination, weight, or any custom logic. + +## Import + +```typescript +import { shippingRates } from "@wix/ecom/service-plugins"; +import { ChargeType } from "@wix/auto_sdk_ecom_shipping-rates"; +``` + +## Handler + +| Handler | Description | +| --- | --- | +| `getShippingRates` | Calculate and return available shipping options with costs | + +## Example: International Shipping with Handling Fee + +This example provides an international shipping option with an additional handling fee charge. + +```typescript +import { shippingRates } from "@wix/ecom/service-plugins"; +import { ChargeType } from "@wix/auto_sdk_ecom_shipping-rates"; + +shippingRates.provideHandlers({ + getShippingRates: async (payload) => { + const { request, metadata } = payload; + // Use the `request` and `metadata` received from Wix and + // apply custom logic. + return { + // Return your response exactly as documented to integrate with Wix. + // Return value example: + shippingRates: [ + { + code: "usps-international", + title: "USPS - International", + logistics: { + deliveryTime: "2-5 days", + }, + cost: { + price: "15", + currency: metadata.currency || "ILS", + additionalCharges: [ + { + price: "10", + type: ChargeType.HANDLING_FEE, + details: "Handling fee of $5 applied for fragile items.", + }, + ], + }, + }, + ], + }; + }, +}); +``` + +## Response Structure + +```typescript +{ + shippingRates: Array<{ + code: string; // Unique identifier for this shipping option + title: string; // Display name shown to customer + logistics: { + deliveryTime: string; // Estimated delivery time (e.g., "2-5 days") + }; + cost: { + price: string; // Base shipping price as string + currency: string; // Currency code (e.g., "USD") + additionalCharges?: Array<{ + price: string; // Additional charge amount + type: ChargeType; // Type of charge (HANDLING_FEE, etc.) + details?: string; // Description of the charge + }>; + }; + }>; +} +``` + +## ChargeType Values + +| Type | Description | +| --- | --- | +| `ChargeType.HANDLING_FEE` | Additional handling fee | + +## Key Implementation Notes + +1. **Price as string** - All price values must be strings, not numbers +2. **Currency from metadata** - Use `metadata.currency` to get the site's currency +3. **Multiple options** - You can return multiple shipping rate options for customer to choose +4. **Unique codes** - Each shipping option needs a unique `code` identifier +5. **Additional charges** - Use `additionalCharges` array for itemized extra costs like handling fees diff --git a/CLI App - Calculator Form/.agents/skills/wix-cli-service-plugin/references/TAX-CALCULATION.md b/CLI App - Calculator Form/.agents/skills/wix-cli-service-plugin/references/TAX-CALCULATION.md new file mode 100644 index 0000000..7b0512c --- /dev/null +++ b/CLI App - Calculator Form/.agents/skills/wix-cli-service-plugin/references/TAX-CALCULATION.md @@ -0,0 +1,87 @@ +# Tax Calculation Service Plugin Reference + +## Overview + +The Tax Calculation SPI allows you to implement custom tax calculation logic based on order details, shipping destination, product types, or any business-specific tax rules. + +## Import + +```typescript +import { taxCalculationProvider } from "@wix/ecom/service-plugins"; +``` + +## Handler + +| Handler | Description | +| --- | --- | +| `calculateTax` | Calculate and return tax amounts for line items | + +## Example: State-Based Tax Calculation + +This example calculates tax based on the shipping destination state. + +```typescript +import { taxCalculationProvider } from "@wix/ecom/service-plugins"; + +const STATE_TAX_RATES: Record = { + CA: 0.0725, + NY: 0.08, + TX: 0.0625, + // Add more states as needed +}; + +taxCalculationProvider.provideHandlers({ + calculateTax: async ({ request }) => { + const state = request.shippingAddress?.subdivision; + const taxRate = STATE_TAX_RATES[state || ""] || 0; + + const lineItemTaxes = + request.lineItems?.map((item) => { + const amount = parseFloat(item.price?.amount || "0"); + const taxAmount = (amount * taxRate).toFixed(2); + + return { + lineItemId: item._id, + taxBreakdown: [ + { + name: "State Sales Tax", + rate: String(taxRate * 100), + amount: { + amount: taxAmount, + currency: request.currency || "USD", + }, + }, + ], + }; + }) || []; + + return { lineItemTaxes }; + }, +}); +``` + +## Response Structure + +```typescript +{ + lineItemTaxes: Array<{ + lineItemId: string; // ID of the line item + taxBreakdown: Array<{ + name: string; // Tax name (e.g., "State Sales Tax") + rate: string; // Tax rate as string (e.g., "7.25") + amount: { + amount: string; // Tax amount as string + currency: string; // Currency code (e.g., "USD") + }; + }>; + }>; +} +``` + +## Key Implementation Notes + +1. **Price as string** - All amount values must be strings, not numbers +2. **Rate as percentage** - The `rate` field should be the percentage value (e.g., "7.25" for 7.25%) +3. **Line item matching** - Each `lineItemId` must match an item from the request +4. **Multiple tax breakdowns** - You can include multiple taxes per line item (state, local, etc.) +5. **Handle missing data** - Gracefully handle missing addresses or subdivision codes diff --git a/CLI App - Calculator Form/.agents/skills/wix-cli-service-plugin/references/VALIDATIONS.md b/CLI App - Calculator Form/.agents/skills/wix-cli-service-plugin/references/VALIDATIONS.md new file mode 100644 index 0000000..5efcbc4 --- /dev/null +++ b/CLI App - Calculator Form/.agents/skills/wix-cli-service-plugin/references/VALIDATIONS.md @@ -0,0 +1,90 @@ +# Validations Service Plugin Reference + +## Overview + +The Validations SPI allows you to add custom validation rules to the checkout process. You can validate cart contents, order totals, quantities, or any business logic requirement. + +## Import + +```typescript +import { validations } from "@wix/ecom/service-plugins"; +``` + +## Handler + +| Handler | Description | +| --- | --- | +| `getValidationViolations` | Evaluate order and return any validation violations | + +## Example: Minimum Quantity Validation + +This example validates that the order meets a minimum item quantity requirement. + +```typescript +import { validations } from "@wix/ecom/service-plugins"; + +validations.provideHandlers({ + getValidationViolations: async (payload) => { + const { request, metadata } = payload; + // Use the `request` and `metadata` received from Wix and + // apply custom logic. + return { + // Return your response exactly as documented to integrate with Wix. + // Return value example: + violations: [ + { + description: "You must purchase at least 100 items.", + severity: validations.Severity.WARNING, + target: { + other: { + name: validations.NameInOther.OTHER_DEFAULT, + }, + }, + }, + ], + }; + }, +}); +``` + +## Response Structure + +```typescript +{ + violations: Array<{ + description: string; // Message shown to customer + severity: validations.Severity; // ERROR or WARNING + target: { + other: { + name: validations.NameInOther; // Target type + }; + } | { + lineItem: { + _id: string; // Specific line item ID + }; + }; + }>; +} +``` + +## Severity Levels + +| Severity | Description | +| --- | --- | +| `validations.Severity.ERROR` | Blocks checkout - customer cannot proceed | +| `validations.Severity.WARNING` | Shows warning but allows checkout to continue | + +## Target Types + +| Target | Description | +| --- | --- | +| `validations.NameInOther.OTHER_DEFAULT` | General cart/order level validation | +| `lineItem._id` | Validation targeting a specific item | + +## Key Implementation Notes + +1. **Return empty array when valid** - Return `{ violations: [] }` when no validation issues +2. **Use SDK enums** - Use `validations.Severity` and `validations.NameInOther` for proper values +3. **Clear messages** - Write descriptive `description` text that helps customers fix the issue +4. **ERROR vs WARNING** - Use ERROR to block checkout, WARNING to inform but allow proceeding +5. **Target specificity** - Use `other.name` for cart-wide validations, `lineItem._id` for item-specific issues diff --git a/CLI App - Calculator Form/.agents/skills/wix-cli-site-component/SKILL.md b/CLI App - Calculator Form/.agents/skills/wix-cli-site-component/SKILL.md new file mode 100644 index 0000000..f7158c2 --- /dev/null +++ b/CLI App - Calculator Form/.agents/skills/wix-cli-site-component/SKILL.md @@ -0,0 +1,510 @@ +--- +name: wix-cli-site-component +description: "Use when building React site components with editor manifests for Wix CLI applications. Triggers include site component, editor manifest, custom component, visual customization, editor element, CSS properties, data API, site builder component, Wix Editor component. Use this skill whenever the user wants to create a component that site owners can customize through the Wix Editor's visual interface." +compatibility: Requires Wix CLI development environment. +--- + +# Wix Site Component Builder + +Creates production-quality React site components with editor manifests for Wix CLI applications. Site components are React components that integrate with the Wix Editor, allowing site owners to customize content, styling, and behavior through a visual interface. + +## Architecture + +Site components consist of **four required files**: + +### 1. Component Manifest (`manifest.json`) + +Defines the contract between the React component and Wix ecosystem: + +- **editorElement**: Root element configuration (selector, displayName, archetype, layout) +- **cssProperties**: CSS API for styling customization +- **data**: Data API for content configuration +- **elements**: Nested element definitions for granular editing +- **behaviors**: Editor interaction behaviors + +### 2. React Component (`component.tsx`) + +Production-ready React functional component: + +- Implements props interface matching manifest data structure +- Applies className and id to root element +- Handles element removal state via `wix.elementsRemovalState` +- Uses sub-component pattern for nested elements +- Includes proper TypeScript typing and error handling + +### 3. CSS Styles (`style.css`) + +Modern CSS with responsive design: + +- Synced selectors with manifest and React classNames +- CSS variables for dynamic styling +- Responsive design without media queries (flexbox, grid, clamp) +- Pointer events enabled for editor elements +- No inline styles for static values +- Each selector once only, `box-sizing: border-box` all elements +- NO `transition: all`, NO media queries (except `prefers-reduced-motion`) +- Root display: Declare `--display: [value]` CSS variable, then use `display: var(--display)` on root + +### 4. TypeScript Types (`types.ts`) + +Strict type definitions: + +- Props interfaces for all components +- Data type mappings (text → string, image → Image object) +- Element props structure with optional chaining +- Wix system types (Wix interface, REMOVED type) + +## Component Manifest Structure + +**You MUST read [MANIFEST_GUIDELINES.md](references/MANIFEST_GUIDELINES.md) before implementing a site component.** It contains the complete manifest structure, all data types, element configurations, and required patterns. + +The manifest defines the editor contract using these key sections: + +### installation (Initial Placement) + +```json +{ + "installation": { + "staticContainer": "HOMEPAGE", + "initialSize": { + "width": { "sizingType": "pixels", "pixels": 400 }, + "height": { "sizingType": "pixels", "pixels": 300 } + } + } +} +``` + +- **staticContainer**: Use `"HOMEPAGE"` for automatic installation on Harmony editor +- **initialSize**: Defines initial dimensions with `sizingType` options: + - `"content"` - Auto-size based on content + - `"stretched"` - Fill available space + - `"pixels"` - Fixed pixel dimension (requires `pixels` property) + +### editorElement (Root Configuration) + +```json +{ + "selector": ".component-name", + "displayName": "Component Name", + "archetype": "Container", + "layout": { + "resizeDirection": "horizontalAndVertical", + "contentResizeDirection": "horizontal" + }, + "cssProperties": { + "backgroundColor": { + "displayName": "Background Color", + "defaultValue": "#ffffff" + } + }, + "data": { + "columns": { + "dataType": "number", + "displayName": "Number of Columns", + "number": { "minimum": 1, "maximum": 4 } + } + }, + "elements": { + "title": { + "elementType": "inlineElement", + "inlineElement": { + "selector": ".component-name__title", + "displayName": "Title", + "data": { + "titleText": { + "dataType": "text", + "displayName": "Title Text" + } + }, + "behaviors": { + "selectable": true, + "removable": true + } + } + } + } +} +``` + +### Data Types Reference + +| Type | Runtime Value | Use Case | +|------|---------------|----------| +| `text` | string | Names, titles, descriptions | +| `textEnum` | string | Predefined options | +| `number` | number | Quantities, dimensions | +| `booleanValue` | boolean | Toggles, flags | +| `a11y` | Object | Accessibility attributes | +| `link` | `{ href, target, rel }` | Navigation links | +| `image` | `{ uri, url, alt, width, height }` | Images | +| `video` | Video object | Media content | +| `vectorArt` | Sanitized SVG object | Icons, graphics | +| `localDate` | string (YYYY-MM-DD) | Date values | +| `localTime` | string (hh:mm) | Time values | +| `webUrl` | string | External URLs | +| `richText` | string (HTML) | Formatted content | +| `arrayItems` | Array | Collections, lists | +| `direction` | string | HTML dir attribute | +| `menuItems` | Array of menu items | Navigation menus | + +### CSS Properties Reference + +Common CSS properties for styling customization: + +- **Layout**: `display`, `gap`, `padding`, `margin`, `width`, `height` +- **Typography**: `font`, `fontSize`, `fontWeight`, `textAlign`, `color` +- **Background**: `backgroundColor`, `backgroundImage` +- **Border**: `border`, `borderRadius`, `boxShadow` +- **Positioning**: `alignItems`, `justifyContent`, `flexDirection` + +**Complete CSS properties reference:** See [CSS_GUIDELINES.md](references/CSS_GUIDELINES.md) for all CSS properties, variable patterns, and styling best practices. + +## React Component Patterns + +**Complete reference:** See [REACT_PATTERNS.md](references/REACT_PATTERNS.md) for detailed component architecture, all coding patterns, and implementation examples. + +### Props Structure + +```typescript +interface ComponentProps { + // Standard props (always present) + className: string; + id: string; + wix?: Wix; + + // Component-level data (from editorElement.data) + columns?: number; + layout?: string; + + // Element props (from elements definitions) + elementProps?: { + title?: { + titleText?: string; + wix?: Wix; + }; + button?: { + buttonText?: string; + buttonLink?: Link; + wix?: Wix; + }; + }; +} +``` + +### Sub-Component Pattern + +Extract every distinct UI element into named sub-components: + +```typescript +// Title sub-component +interface TitleProps { + titleText?: string; + className: string; +} + +const Title: FC = ({ titleText = "Default Title", className }) => ( +

{titleText}

+); + +// Main component +const ProductCard: FC = ({ + className, + id, + elementProps, + wix +}) => { + const removalState = wix?.elementsRemovalState || {}; + + return ( +
+ {!removalState['title'] && ( + + )} + {!removalState['button'] && ( + <Button + className="product-card__button" + {...elementProps?.button} + /> + )} + </div> + ); +}; +``` + +### Conditional Rendering + +All elements must be conditionally rendered based on removal state: + +```typescript +const removalState = wix?.elementsRemovalState || {}; + +return ( + <div className={`component ${className}`} id={id}> + {!removalState['elementKey'] && <Element />} + </div> +); +``` + +## CSS Guidelines + +### Responsive Design Strategy + +Components live in user-resizable containers (300-1200px) within varying viewports: + +- **Root element**: `width: 100%; height: 100%` +- **Layout structure**: Use CSS Grid and Flexbox for fluid responsiveness +- **Typography**: Use `clamp()` for fluid scaling +- **Spacing**: Fixed or tight clamp spacing (≤50% variation) + +### CSS Variables for Dynamic Styling + +```css +.component { + --display: block; + --background-color: #ffffff; + --text-color: #333333; + + display: var(--display); + background-color: var(--background-color); + color: var(--text-color); + pointer-events: auto; +} +``` + +### Selector Synchronization + +**CRITICAL**: CSS selectors must match manifest selectors and React classNames exactly: + +- React: `className="product-card__title"` +- CSS: `.product-card__title { ... }` +- Manifest: `"selector": ".product-card__title"` + +## Design Guidelines + +**Complete reference:** See [DESIGN_SYSTEM.md](references/DESIGN_SYSTEM.md) for visual design principles, creative guidelines, and aesthetic best practices. + +### Spacing as Communication + +| Relationship | Value | Use Case | +|---|---|---| +| Tight (icon + label) | 0.25-0.5rem (4-8px) | Clustering related items | +| Same category | 1-1.5rem (16-24px) | Card sections, form fields | +| Different sections | 2-3rem (32-48px) | Major content blocks | +| Emphasis/Drama | 4rem+ (64px+) | Hero content, luxury feel | + +### Visual Consistency + +- **Corner Radius**: All similar elements share same radius (0-4px sharp, 6-12px rounded) +- **Shadow Levels**: Max 3 levels (rest, hover, floating) +- **Element Heights**: Consistent heights for similar elements +- **Color Strategy**: Use full palette purposefully for hierarchy and zones + +### Creative Exploration + +Push beyond obvious solutions: + +- **Cards**: Asymmetric grids, overlapping elements, thick accent borders +- **Lists**: Alternating styles, spotlight patterns, color rhythm +- **Interactive Elements**: Split buttons, colored icon circles, smooth transitions +- **Content Hierarchy**: Large numbers for stats, quote callouts, whitespace dividers + +## Component Elements Guidelines + +### One Element = One Manifest Entry + +Each distinct visual part requires a separate manifest element: + +- ✅ 3 buttons → 3 separate elements +- ✅ Image + text → 2 separate elements +- ❌ Multiple items grouped as one element + +### Data Scoping Rules + +**editorElement.data** - Component-wide configuration only: +- ✅ Layout enums, numbers (columns: 3, speed: 500) +- ❌ Text, links, images (belongs to elements) +- ❌ show/hide booleans (use removable: true instead) + +**elements[key].data** - Content for that specific element: +- ✅ Element-specific content (title text, button link, image) + +## Asset Requirements + +When components need default images, use this format: + +```typescript +// Import in component +import { heroImage } from './assets/defaultImages'; + +// Usage +<img src={heroImage} alt="Hero" /> +``` + +Asset specification format: +``` +<imageUrlName> +{ "description": "Modern cityscape at sunset", "width": 1920, "height": 1088 } +</imageUrlName> +``` + +**Rules:** +- Import as named export from `'./assets/defaultImages'` +- Width/height: multiples of 64, between 128-2048px +- NEVER use external URLs + +## Output Structure + +``` +src/site/components/ +└── {component-name}/ + ├── manifest.json # Component manifest + ├── component.tsx # React component + ├── style.css # CSS styles + ├── types.ts # TypeScript types + └── assets/ # Optional assets + └── defaultImages.ts +``` + +## Examples + +**Complete working example:** See [EXAMPLE.md](references/EXAMPLE.md) for a full production-ready site component with all patterns, including manifest, React component, CSS, and types. + +### Product Card Component + +**Request:** "Create a product card component with image, title, price, and buy button" + +**Output:** +- Manifest with 4 elements (image, title, price, button) +- React component with sub-components for each element +- CSS with responsive grid layout and hover effects +- TypeScript types for all props and data structures + +### Hero Section Component + +**Request:** "Build a hero section with background image, headline, subtitle, and CTA button" + +**Output:** +- Manifest with background image CSS property and 3 text elements +- React component with overlay design and typography hierarchy +- CSS with responsive text scaling and dramatic spacing +- Asset specifications for default hero images + +### Feature List Component + +**Request:** "Create a features component with configurable number of items" + +**Output:** +- Manifest with arrayItems data type for feature collection +- React component mapping over features array with safety checks +- CSS with flexible grid layout adapting to item count +- Sub-components for feature icons, titles, and descriptions + +## Extension Registration + +**Extension registration is MANDATORY and has TWO required steps.** + +### Step 1: Create Component-Specific Extension File + +Each site component requires an `extensions.ts` file in its folder: + +```typescript +import { extensions } from "@wix/astro/builders"; +import manifest from "./manifest.json"; + +export const sitecomponentMyComponent = extensions.siteComponent({ + ...manifest, + id: "{{GENERATE_UUID}}", + description: "My Component", + type: "platform.MyComponent", + resources: { + client: { + component: "./site/components/my-component/component.tsx", + componentUrl: "./site/components/my-component/component.tsx", + }, + }, +}); +``` + +**CRITICAL: Type Naming Convention** + +The `type` field uses the format `platform.{PascalCaseFolderName}`: +- Folder `my-component` → `type: "platform.MyComponent"` +- Folder `product-card` → `type: "platform.ProductCard"` +- Folder `hero-section` → `type: "platform.HeroSection"` + +The folder name is converted to PascalCase (hyphens removed, each word capitalized). + +**CRITICAL: UUID Generation** + +The `id` must be a unique, static UUID v4 string. Generate a fresh UUID for each extension - do NOT use `randomUUID()` or copy UUIDs from examples. + +### Step 2: Register in Main Extensions File + +**CRITICAL:** After creating the component-specific extension file, you MUST read [wix-cli-extension-registration](../wix-cli-extension-registration/SKILL.md) and follow the "App Registration" section to update `src/extensions.ts`. + +**Without completing Step 2, the site component will not be available in the Wix Editor.** + +## Code Quality Requirements + +**Complete reference:** See [TYPESCRIPT_QUALITY.md](references/TYPESCRIPT_QUALITY.md) for comprehensive type safety guidelines and code quality standards. + +### TypeScript Standards + +- Strict TypeScript with no `any` types +- Explicit return types for all functions +- Proper null/undefined handling with optional chaining +- No `@ts-ignore` or `@ts-expect-error` comments + +### React Best Practices + +- Functional components with hooks +- Proper dependency arrays in useEffect +- Component must react to prop changes +- SSR-safe code (no browser APIs at module scope) + +### ESLint Compliance + +1. No unused vars/params/imports (`@typescript-eslint/no-unused-vars`) +2. No external images: `img` `src` not `https://...` (allowed: local imports, `wixstatic.com`, variables) +3. SSR-safe: No `window`/`document` at module scope/constructor, guard browser APIs in `useEffect`/handlers +4. No `dangerouslySetInnerHTML` or inline `<style>` tags - use CSS variables or inline `style` prop for dynamic values +5. No `window.fetch` (`no-restricted-properties`) +6. Hooks `exhaustive-deps`: ALL values from component scope used inside `useEffect`/`useCallback` MUST be in dependency array +7. Use `const`/`let` (no `var`), no unknown JSX properties + +## Common Mistakes + +| Mistake | Why It Fails | Fix | +|---------|-------------|-----| +| CSS selector doesn't match manifest | Editor can't apply styles to the element | Ensure manifest `selector`, React `className`, and CSS selector are identical | +| Putting content text in `editorElement.data` | Content belongs to specific elements, not root | Move text/image/link data into `elements[key].data` | +| Using `display: flex` directly on root | Breaks editor override mechanism | Use `--display: flex` CSS variable, then `display: var(--display)` | +| Missing `removable: true` on optional elements | Site owner can't hide the element | Add `behaviors: { removable: true }` to optional elements | +| Using `window`/`document` at module scope | SSR fails during build | Guard browser APIs inside `useEffect` or event handlers | +| Importing from `@wix/design-system` | Not available in site components | Use plain HTML/CSS or custom components only | + +## Hard Constraints + +- Do NOT invent or assume new types, modules, functions, props, events, or imports +- Use only entities explicitly present in the provided references or standard libraries already used in this project +- Do NOT add dependencies; do NOT use `@wix/design-system` or `@wix/wix-ui-icons-common` +- All user-facing content must come from props (no hardcoded text) +- Links/media from manifest only, never hardcode URLs +- NEVER use mocks, placeholders, or TODOs in any code +- ALWAYS implement complete, production-ready functionality + +## Verification + +After implementation, use [wix-cli-app-validation](../wix-cli-app-validation/SKILL.md) to validate TypeScript compilation, build, preview, and runtime behavior. + +## Reference Documentation + +- [Complete Example](references/EXAMPLE.md) - Full production-ready site component example with all patterns +- [Component Manifest Guidelines](references/MANIFEST_GUIDELINES.md) - Detailed manifest structure and best practices +- [React Patterns](references/REACT_PATTERNS.md) - Component architecture and coding patterns +- [CSS Guidelines](references/CSS_GUIDELINES.md) - Styling conventions and responsive design +- [Design System](references/DESIGN_SYSTEM.md) - Visual design principles and creative guidelines +- [TypeScript Quality](references/TYPESCRIPT_QUALITY.md) - Type safety and code quality standards diff --git a/CLI App - Calculator Form/.agents/skills/wix-cli-site-component/references/CSS_GUIDELINES.md b/CLI App - Calculator Form/.agents/skills/wix-cli-site-component/references/CSS_GUIDELINES.md new file mode 100644 index 0000000..b660150 --- /dev/null +++ b/CLI App - Calculator Form/.agents/skills/wix-cli-site-component/references/CSS_GUIDELINES.md @@ -0,0 +1,583 @@ +# CSS Guidelines + +Modern CSS patterns for responsive, maintainable site components that integrate with Wix Editor styling controls. + +## Core Principles + +### No Inline Styles for Static Values + +```css +/* ✅ Correct - use CSS classes */ +.component { + padding: 20px; + border-radius: 8px; + background-color: #ffffff; +} + +/* ❌ Wrong - inline styles for static values */ +<div style={{ padding: '20px', borderRadius: '8px' }}> +``` + +**Inline styles allowed ONLY for JS-computed dynamic values:** + +```typescript +// ✅ Correct - dynamic values from props/state +<div style={{ + '--columns': columns, + '--item-width': `${100 / columns}%` +} as React.CSSProperties}> + +// ✅ Correct - computed styles +<div style={{ + transform: `translateX(${offset}px)`, + opacity: isVisible ? 1 : 0 +}}> +``` + +### CSS Variables for Dynamic Styling + +```css +.component { + --display: block; + --background-color: #ffffff; + --text-color: #333333; + --columns: 1; + + display: var(--display); + background-color: var(--background-color); + color: var(--text-color); + grid-template-columns: repeat(var(--columns), 1fr); +} +``` + +### Pointer Events (Required) + +```css +/* ✅ Required for all manifest elements */ +.component, +.component__title, +.component__button { + pointer-events: auto; +} +``` + +**Apply to:** +- Root element (editorElement selector) +- All nested elements defined in manifest +- Any selectors targeting manifest elements + +### Critical CSS Rules + +- **Each selector once only** - do not duplicate selectors +- **`box-sizing: border-box`** on all elements +- **NO `transition: all`** - be specific about transitioned properties +- **NO media queries** (except `prefers-reduced-motion`) +- **Root display**: Declare `--display: [value]` CSS variable, then use `display: var(--display)` on root element + +## Responsive Design Strategy + +### Container-Based Responsiveness + +Components live in user-resizable containers (300-1200px) within varying viewports (375-1920px). + +```css +/* ✅ Root element sizing */ +.component { + width: 100%; + height: 100%; + box-sizing: border-box; +} + +/* ✅ Flexible layout structure */ +.component__grid { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); + gap: clamp(1rem, 2.5vw, 2rem); +} + +/* ✅ Flexible content */ +.component__content { + display: flex; + flex-direction: column; + gap: 1rem; +} +``` + +### Fluid Typography + +```css +/* ✅ Responsive text scaling */ +.component__title { + font-size: clamp(1.5rem, 4vw, 3rem); + line-height: 1.2; +} + +.component__description { + font-size: clamp(1rem, 2.5vw, 1.25rem); + line-height: 1.6; +} + +/* ✅ Tight spacing variation */ +.component__section { + margin-bottom: clamp(2rem, 3vw, 3rem); + padding: clamp(1rem, 2vw, 1.5rem); +} +``` + +### Layout Patterns + +**Single-Column (Mobile-First)** +```css +.hero { + display: flex; + flex-direction: column; + align-items: center; + text-align: center; + gap: 2rem; + padding: clamp(2rem, 5vw, 4rem); +} +``` + +**Two-Column Split** +```css +.feature-section { + display: grid; + grid-template-columns: 1fr 1fr; + gap: clamp(2rem, 4vw, 4rem); + align-items: center; +} + +@container (max-width: 600px) { + .feature-section { + grid-template-columns: 1fr; + } +} +``` + +**Multi-Column Grid** +```css +.card-grid { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); + gap: clamp(1.5rem, 3vw, 2.5rem); +} +``` + +## Selector Synchronization + +**CRITICAL**: Selectors must match exactly between files: + +| File | Format | Example | +|------|--------|---------| +| React | `className="product-card__title"` | Direct class | +| CSS | `.product-card__title { ... }` | Same class | +| Manifest | `"selector": ".product-card__title"` | Same class | + +### Naming Convention + +```css +/* ✅ BEM-style naming */ +.product-card { } /* Block */ +.product-card__image { } /* Element */ +.product-card__title { } /* Element */ +.product-card__button { } /* Element */ +.product-card__button--primary { } /* Modifier */ +``` + +### Forbidden Selectors + +```css +/* ❌ Compound selectors */ +.product-card.featured { } + +/* ❌ Descendant selectors */ +.product-card .title { } + +/* ❌ Child selectors */ +.product-card > .content { } + +/* ✅ Use direct classes only */ +.product-card { } +.product-card__title { } +.product-card__content { } +``` + +## Box Model and Spacing + +### Universal Box Sizing + +```css +.component, +.component *, +.component *::before, +.component *::after { + box-sizing: border-box; +} +``` + +### Spacing Scale + +```css +:root { + /* Spacing tokens */ + --space-xs: 0.25rem; /* 4px - tight clustering */ + --space-sm: 0.5rem; /* 8px - related items */ + --space-md: 1rem; /* 16px - same category */ + --space-lg: 1.5rem; /* 24px - form fields */ + --space-xl: 2rem; /* 32px - sections */ + --space-2xl: 3rem; /* 48px - major blocks */ + --space-3xl: 4rem; /* 64px - emphasis */ +} + +.component { + padding: var(--space-xl); + gap: var(--space-lg); +} + +.component__section { + margin-bottom: var(--space-2xl); +} + +.component__title { + margin-bottom: var(--space-md); +} +``` + +## Color and Theming + +### CSS Custom Properties + +```css +.component { + /* Color tokens */ + --color-primary: #007bff; + --color-secondary: #6c757d; + --color-success: #28a745; + --color-danger: #dc3545; + --color-warning: #ffc107; + + /* Background tokens */ + --bg-primary: #ffffff; + --bg-secondary: #f8f9fa; + --bg-accent: #e9ecef; + + /* Text tokens */ + --text-primary: #212529; + --text-secondary: #6c757d; + --text-muted: #adb5bd; + + /* Apply colors */ + background-color: var(--bg-primary); + color: var(--text-primary); +} +``` + +### Color Usage Patterns + +```css +/* ✅ Semantic color usage */ +.component__header { + background-color: var(--bg-secondary); + border-bottom: 1px solid var(--bg-accent); +} + +.component__button { + background-color: var(--color-primary); + color: white; + border: none; +} + +.component__button:hover { + background-color: color-mix(in srgb, var(--color-primary) 90%, black); +} + +.component__text { + color: var(--text-primary); +} + +.component__caption { + color: var(--text-secondary); + font-size: 0.875rem; +} +``` + +## Layout Systems + +### Flexbox Patterns + +```css +/* Horizontal layout with gap */ +.component__row { + display: flex; + align-items: center; + gap: var(--space-md); +} + +/* Vertical layout with stretch */ +.component__column { + display: flex; + flex-direction: column; + gap: var(--space-lg); + height: 100%; +} + +/* Space between layout */ +.component__header { + display: flex; + justify-content: space-between; + align-items: center; +} + +/* Centered content */ +.component__center { + display: flex; + align-items: center; + justify-content: center; + min-height: 200px; +} +``` + +### Grid Patterns + +```css +/* Auto-fit grid */ +.component__grid { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); + gap: var(--space-xl); +} + +/* Fixed columns with responsive */ +.component__layout { + display: grid; + grid-template-columns: 1fr 2fr; + gap: var(--space-2xl); +} + +@container (max-width: 768px) { + .component__layout { + grid-template-columns: 1fr; + } +} + +/* Named grid areas */ +.component__page { + display: grid; + grid-template-areas: + "header header" + "sidebar content" + "footer footer"; + grid-template-columns: 250px 1fr; + gap: var(--space-lg); +} + +.component__header { grid-area: header; } +.component__sidebar { grid-area: sidebar; } +.component__content { grid-area: content; } +.component__footer { grid-area: footer; } +``` + +## Visual Effects + +### Shadows and Depth + +```css +/* Shadow scale */ +.component { + --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.05); + --shadow-md: 0 4px 6px rgba(0, 0, 0, 0.07); + --shadow-lg: 0 10px 15px rgba(0, 0, 0, 0.1); + --shadow-xl: 0 20px 25px rgba(0, 0, 0, 0.15); +} + +.component__card { + box-shadow: var(--shadow-md); + transition: box-shadow 0.2s ease; +} + +.component__card:hover { + box-shadow: var(--shadow-lg); +} +``` + +### Border Radius + +```css +.component { + --radius-sm: 4px; + --radius-md: 8px; + --radius-lg: 12px; + --radius-xl: 16px; + --radius-full: 9999px; +} + +.component__card { + border-radius: var(--radius-lg); +} + +.component__button { + border-radius: var(--radius-md); +} + +.component__avatar { + border-radius: var(--radius-full); +} +``` + +## Animations and Transitions + +### Standard Transitions + +```css +.component { + --duration-fast: 150ms; + --duration-normal: 250ms; + --duration-slow: 400ms; + + --ease-out: cubic-bezier(0.0, 0.0, 0.2, 1); + --ease-in: cubic-bezier(0.4, 0.0, 1, 1); + --ease-in-out: cubic-bezier(0.4, 0.0, 0.2, 1); +} + +/* Hover transitions */ +.component__button { + transition: all var(--duration-fast) var(--ease-out); +} + +.component__button:hover { + transform: translateY(-1px); + box-shadow: var(--shadow-lg); +} + +/* Focus states */ +.component__input:focus { + outline: 2px solid var(--color-primary); + outline-offset: 2px; + transition: outline var(--duration-fast) var(--ease-out); +} +``` + +### Content Reveal Animation + +```css +@keyframes contentAppear { + from { + opacity: 0; + transform: translateY(10px); + } + to { + opacity: 1; + transform: translateY(0); + } +} + +.component__content { + animation: contentAppear var(--duration-normal) var(--ease-out); +} + +/* Respect reduced motion */ +@media (prefers-reduced-motion: reduce) { + .component__content { + animation: none; + } + + .component__button { + transition: none; + } +} +``` + +### Loading States + +```css +@keyframes pulse { + 0%, 100% { opacity: 1; } + 50% { opacity: 0.5; } +} + +.component__skeleton { + background-color: var(--bg-accent); + border-radius: var(--radius-md); + animation: pulse 2s infinite; +} + +@keyframes spin { + to { transform: rotate(360deg); } +} + +.component__spinner { + animation: spin 1s linear infinite; +} +``` + +## Media Queries (Limited Use) + +**Only allowed media query:** + +```css +/* ✅ Accessibility - only allowed media query */ +@media (prefers-reduced-motion: reduce) { + .component * { + animation-duration: 0.01ms !important; + animation-iteration-count: 1 !important; + transition-duration: 0.01ms !important; + } +} + +/* ❌ No other media queries allowed */ +@media (max-width: 768px) { } /* Forbidden */ +@media (min-width: 1024px) { } /* Forbidden */ +``` + +## Performance Optimizations + +### GPU Acceleration + +```css +/* ✅ Animate only transform and opacity */ +.component__slide { + transform: translateX(0); + opacity: 1; + transition: transform var(--duration-normal) var(--ease-out), + opacity var(--duration-normal) var(--ease-out); +} + +.component__slide--hidden { + transform: translateX(-100%); + opacity: 0; +} + +/* ✅ Force GPU layer for complex animations */ +.component__animated { + will-change: transform; + transform: translateZ(0); /* Force GPU layer */ +} +``` + +### Efficient Selectors + +```css +/* ✅ Efficient - direct class selectors */ +.component { } +.component__title { } +.component__button { } + +/* ❌ Inefficient - complex selectors */ +.component div p span { } +.component > div:nth-child(2n+1) { } +``` + +## Validation Checklist + +- [ ] All selectors match manifest and React classNames exactly +- [ ] Root element has `width: 100%; height: 100%` +- [ ] All manifest elements have `pointer-events: auto` +- [ ] CSS variables used for dynamic values +- [ ] No inline styles for static values +- [ ] Box-sizing: border-box applied to all elements +- [ ] Responsive design uses modern CSS (no media queries except prefers-reduced-motion) +- [ ] Animations only use transform and opacity +- [ ] Transitions have appropriate durations and easing +- [ ] Color tokens defined and used consistently +- [ ] Spacing scale applied consistently +- [ ] No external dependencies or imports diff --git a/CLI App - Calculator Form/.agents/skills/wix-cli-site-component/references/DESIGN_SYSTEM.md b/CLI App - Calculator Form/.agents/skills/wix-cli-site-component/references/DESIGN_SYSTEM.md new file mode 100644 index 0000000..86f9e4c --- /dev/null +++ b/CLI App - Calculator Form/.agents/skills/wix-cli-site-component/references/DESIGN_SYSTEM.md @@ -0,0 +1,702 @@ +# Design System Guidelines + +Creative design principles for building distinctive, award-winning site components that avoid generic "AI slop" aesthetics. + +## 1. Spacing as Communication + +Spacing communicates relationships and hierarchy—not decoration. + +### Semantic Roles + +| Role | Purpose | Implementation | +|------|---------|----------------| +| **Padding** | Internal breathing room | Prevents cramped layouts | +| **Gap** | Relationship indicator | Consistent gaps = visual unity | +| **Margin** | Section separation | Clear boundaries between major blocks | +| **Whitespace** | Focus amplifier | Strategic emptiness = premium feel | + +### Spacing Scale + +| Relationship | Value | Use Case | Example | +|---|---|---|---| +| Tight (icon + label) | 0.25-0.5rem (4-8px) | Clustering related items | Button icon + text | +| Same category | 1-1.5rem (16-24px) | Card sections, form fields | Title + description | +| Different sections | 2-3rem (32-48px) | Major content blocks | Hero + features | +| Emphasis/Drama | 4rem+ (64px+) | Hero content, luxury feel | Landing page sections | + +### Generous Whitespace Examples + +Create sophistication and clarity with spacious layouts: + +```css +.hero-section { + padding: clamp(4rem, 8vw, 8rem) clamp(2rem, 4vw, 4rem); + margin-bottom: clamp(4rem, 6vw, 6rem); +} + +.feature-grid { + gap: clamp(2.5rem, 4vw, 4rem); + margin: clamp(3rem, 5vw, 5rem) 0; +} + +.card-content { + padding: clamp(1.5rem, 3vw, 2.5rem); +} +``` + +## 2. Alignment as Intent + +Every alignment choice must support comprehension and flow—never default. + +### Principles + +- **Proximity**: Group related elements +- **Consistency**: Same pattern for same type +- **Balance**: Distribute visual weight +- **Scanability**: Guide the eye naturally + +### Alignment Patterns + +| Element Type | Horizontal | Vertical | Reasoning | +|---|---|---|---| +| Body text, lists | Left | Top | Natural reading flow | +| Headlines, CTAs | Center | Center | Draw attention | +| Metadata, timestamps | Right | — | Secondary information | +| Form inputs | Stretch | — | Maximize usability | + +```css +/* Left-aligned content */ +.content-block { + text-align: left; + display: flex; + flex-direction: column; + align-items: flex-start; +} + +/* Center-aligned hero */ +.hero-content { + text-align: center; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; +} + +/* Right-aligned metadata */ +.card-meta { + text-align: right; + margin-left: auto; +} +``` + +## 3. Layout Patterns + +Choose patterns that serve the component's purpose—don't default to the first idea. + +### Single-Column (Focused Actions) + +**When to use:** Simple, focused content (hero, single CTA) +**Spacing strategy:** Generous vertical gaps (2-3rem) +**Best for:** Mobile-first, focused actions + +```css +.single-column { + display: flex; + flex-direction: column; + align-items: center; + gap: clamp(2rem, 4vw, 3rem); + max-width: 600px; + margin: 0 auto; + text-align: center; +} +``` + +### Two-Column Split (Contrasting Content) + +**When to use:** Contrasting content (image + text) +**Spacing strategy:** Balance weight with whitespace +**Best for:** Product cards, profiles + +```css +.two-column-split { + display: grid; + grid-template-columns: 1fr 1fr; + gap: clamp(2rem, 4vw, 4rem); + align-items: center; +} + +@container (max-width: 600px) { + .two-column-split { + grid-template-columns: 1fr; + gap: clamp(1.5rem, 3vw, 2rem); + } +} +``` + +### Grid/Multi-Column (Repeating Items) + +**When to use:** Repeating items (galleries, cards) +**Spacing strategy:** Consistent gaps, subtle depth +**Best for:** Collections, dashboards + +```css +.multi-column-grid { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); + gap: clamp(1.5rem, 3vw, 2.5rem); +} +``` + +### Stacked + Emphasis (Primary + Metadata) + +**When to use:** Primary + metadata (pricing) +**Spacing strategy:** Large top element, smaller secondary +**Best for:** Pricing, announcements + +```css +.stacked-emphasis { + display: flex; + flex-direction: column; + gap: var(--space-sm); +} + +.stacked-emphasis__primary { + font-size: clamp(2rem, 5vw, 4rem); + font-weight: 700; + line-height: 1.1; +} + +.stacked-emphasis__secondary { + font-size: clamp(0.875rem, 2vw, 1rem); + opacity: 0.7; +} +``` + +## 4. Visual Consistency + +All similar elements must share the same visual DNA. + +### Corner Radius Strategy + +| Style | Range | Use Case | Personality | +|-------|-------|----------|-------------| +| Sharp | 0-4px | Editorial, Luxury, Technical | Precise, modern | +| Rounded | 6-12px | Contemporary, Professional | Friendly, approachable | +| Soft | 16px+ | Playful, Consumer | Warm, casual | + +**Rule:** All buttons same radius, all cards same radius, all inputs same radius + +```css +:root { + --radius-sharp: 2px; + --radius-rounded: 8px; + --radius-soft: 16px; +} + +.button { border-radius: var(--radius-rounded); } +.card { border-radius: var(--radius-rounded); } +.input { border-radius: var(--radius-rounded); } +``` + +### Shadow Levels (Max 3) + +```css +:root { + --shadow-rest: 0 1px 2px rgba(0, 0, 0, 0.05); + --shadow-hover: 0 4px 12px rgba(0, 0, 0, 0.08); + --shadow-floating: 0 8px 24px rgba(0, 0, 0, 0.12); +} + +.card { + box-shadow: var(--shadow-rest); + transition: box-shadow 0.2s ease; +} + +.card:hover { + box-shadow: var(--shadow-hover); +} + +.modal { + box-shadow: var(--shadow-floating); +} +``` + +### Element Heights + +Consistent heights create visual rhythm: + +```css +:root { + --height-input: 44px; + --height-button: 44px; + --height-nav: 60px; +} + +.input, +.button, +.select { + height: var(--height-input); +} +``` + +## 5. Color Strategy + +Color creates hierarchy, zones, and rhythm—not just decoration. + +### Token Usage Philosophy + +- **Backgrounds**: Use accent tints for section backgrounds, base-1 for primary +- **Depth**: Mid-tone shades for layering, subtle background shifts +- **Emphasis**: Vibrant accents for CTAs, highlights, focus states +- **Text**: High contrast for readability + +### Color Palette Structure + +```css +:root { + /* Base colors */ + --color-base-1: #ffffff; + --color-base-2: #f8fafc; + --color-base-3: #e2e8f0; + --color-base-4: #cbd5e1; + + /* Accent colors */ + --color-accent-1: #3b82f6; /* Primary brand */ + --color-accent-2: #8b5cf6; /* Secondary brand */ + --color-accent-3: #06b6d4; /* Tertiary accent */ + --color-accent-4: #10b981; /* Success/positive */ + + /* Text colors */ + --color-text-primary: #0f172a; + --color-text-secondary: #475569; + --color-text-muted: #94a3b8; +} +``` + +### Color Application Patterns + +```css +/* Section backgrounds with subtle tints */ +.hero-section { + background: linear-gradient(135deg, var(--color-base-1) 0%, var(--color-base-2) 100%); +} + +.feature-section { + background-color: var(--color-base-2); +} + +/* Emphasis through color variety */ +.cta-primary { + background-color: var(--color-accent-1); + color: white; +} + +.cta-secondary { + background-color: var(--color-accent-2); + color: white; +} + +/* Zoning with background shifts */ +.sidebar { + background-color: var(--color-base-2); + border-right: 1px solid var(--color-base-3); +} +``` + +## 6. Typography as Structure + +Typography creates hierarchy without relying on color. + +### Font Selection Principles + +1. **Establish Clear Hierarchy**: Use font size and weight for visual hierarchy +2. **Maintain Consistency**: Apply font stack and sizing scale consistently +3. **Anchor & Pair**: Pair fonts that complement each other + +### Hierarchy Rules + +- **Max 3 levels** per component +- **Size contrast**: Headlines 1.5-2x body size minimum +- **Weight contrast**: 700 for emphasis, 400-500 for body + +```css +:root { + /* Type scale */ + --text-xs: clamp(0.75rem, 1.5vw, 0.875rem); + --text-sm: clamp(0.875rem, 2vw, 1rem); + --text-base: clamp(1rem, 2.5vw, 1.125rem); + --text-lg: clamp(1.125rem, 3vw, 1.25rem); + --text-xl: clamp(1.25rem, 3.5vw, 1.5rem); + --text-2xl: clamp(1.5rem, 4vw, 2rem); + --text-3xl: clamp(2rem, 5vw, 3rem); + --text-4xl: clamp(3rem, 6vw, 4rem); +} + +.heading-1 { + font-size: var(--text-4xl); + font-weight: 700; + line-height: 1.1; +} + +.heading-2 { + font-size: var(--text-2xl); + font-weight: 600; + line-height: 1.2; +} + +.body-text { + font-size: var(--text-base); + font-weight: 400; + line-height: 1.6; +} +``` + +### Legibility Guidelines + +```css +/* Optimal line heights */ +.heading { line-height: 1.1-1.3; } +.body-text { line-height: 1.5-1.7; } + +/* Optimal line lengths */ +.readable-content { + max-width: 65ch; /* 45-75 characters optimal */ +} + +/* Prevent orphans */ +.heading { + text-wrap: balance; /* CSS Text Level 4 */ +} +``` + +## 7. Motion System + +All animations: pure CSS, smooth, purposeful. + +### Timing Standards + +| Interaction | Duration | Easing | Use Case | +|---|---|---|---| +| Hover, click | 150-200ms | `ease-out` | Immediate feedback | +| Active states | 250ms | `ease-out` | State changes | +| Content reveals | 400-500ms | `ease-out` or spring | Page transitions | + +### Easing Functions + +```css +:root { + --ease-out: cubic-bezier(0.0, 0.0, 0.2, 1); + --ease-in: cubic-bezier(0.4, 0.0, 1, 1); + --ease-in-out: cubic-bezier(0.4, 0.0, 0.2, 1); + --ease-spring: cubic-bezier(0.34, 1.56, 0.64, 1); +} +``` + +### Standard Animations + +```css +/* Content reveal */ +@keyframes contentAppear { + from { + opacity: 0; + transform: translateY(10px); + } + to { + opacity: 1; + transform: translateY(0); + } +} + +/* Hover lift */ +.interactive-card { + transition: transform 200ms var(--ease-out), + box-shadow 200ms var(--ease-out); +} + +.interactive-card:hover { + transform: translateY(-2px); + box-shadow: var(--shadow-hover); +} + +/* Focus ring */ +.focusable:focus { + outline: 2px solid var(--color-accent-1); + outline-offset: 2px; + transition: outline 150ms var(--ease-out); +} +``` + +### Performance Rules + +- **Only animate** `transform` and `opacity` (GPU-accelerated) +- **Respect** `prefers-reduced-motion` +- **No looping** (except loading spinners) + +```css +@media (prefers-reduced-motion: reduce) { + *, + *::before, + *::after { + animation-duration: 0.01ms !important; + animation-iteration-count: 1 !important; + transition-duration: 0.01ms !important; + } +} +``` + +## 8. Creative Exploration + +Push beyond the obvious. Award-winning design comes from exploring multiple creative directions. + +### Trigger Questions + +1. **"What are 3 different layout approaches for this?"** → Sketch mentally before choosing +2. **"What would make a user say 'wow'?"** → Aim for delight, not just function +3. **"How can proportion create interest?"** → Vary sizes, use asymmetry intentionally +4. **"What interaction details would feel polished?"** → Hover states, micro-animations + +### Creative Pattern Ideas + +#### Cards & Containers + +```css +/* Asymmetric grid (60/40 split) */ +.asymmetric-card { + display: grid; + grid-template-columns: 3fr 2fr; + gap: 2rem; +} + +/* Overlapping elements with z-index */ +.overlapping-card { + position: relative; +} + +.overlapping-card__image { + position: relative; + z-index: 1; +} + +.overlapping-card__content { + position: relative; + z-index: 2; + margin-top: -2rem; + background: white; + border-radius: 12px; + padding: 2rem; +} + +/* Thick accent border */ +.accent-border-card { + border-left: 4px solid var(--color-accent-1); + padding-left: 1.5rem; +} + +/* Color blocking backgrounds */ +.color-block-card { + background: linear-gradient(135deg, var(--color-accent-1) 0%, var(--color-accent-2) 100%); + color: white; +} +``` + +#### Lists & Collections + +```css +/* Alternating styles */ +.alternating-list .item:nth-child(odd) { + background-color: var(--color-base-2); + border-radius: 8px; +} + +.alternating-list .item:nth-child(even) { + box-shadow: var(--shadow-rest); + border-radius: 8px; +} + +/* Spotlight pattern (every 3rd item larger) */ +.spotlight-grid .item:nth-child(3n) { + grid-column: span 2; + font-size: 1.25em; +} + +/* Horizontal scroll with varied widths */ +.varied-scroll { + display: flex; + gap: 1rem; + overflow-x: auto; +} + +.varied-scroll .item:nth-child(odd) { min-width: 200px; } +.varied-scroll .item:nth-child(even) { min-width: 300px; } +``` + +#### Interactive Elements + +```css +/* Split buttons (action + dropdown) */ +.split-button { + display: flex; + border-radius: 8px; + overflow: hidden; +} + +.split-button__action { + flex: 1; + border-radius: 0; +} + +.split-button__dropdown { + width: 40px; + border-left: 1px solid rgba(255, 255, 255, 0.2); +} + +/* Icons in colored circles */ +.icon-circle { + width: 48px; + height: 48px; + border-radius: 50%; + background-color: var(--color-accent-1); + display: flex; + align-items: center; + justify-content: center; + color: white; +} + +/* Large toggles with smooth transitions */ +.large-toggle { + width: 60px; + height: 32px; + border-radius: 16px; + background-color: var(--color-base-3); + position: relative; + transition: background-color 300ms var(--ease-out); +} + +.large-toggle::after { + content: ''; + width: 24px; + height: 24px; + border-radius: 50%; + background: white; + position: absolute; + top: 4px; + left: 4px; + transition: transform 300ms var(--ease-spring); +} + +.large-toggle:checked { + background-color: var(--color-accent-1); +} + +.large-toggle:checked::after { + transform: translateX(28px); +} +``` + +#### Content Hierarchy + +```css +/* Large numbers (3-4x size for stats) */ +.stat-number { + font-size: clamp(3rem, 8vw, 6rem); + font-weight: 900; + line-height: 0.9; + color: var(--color-accent-1); +} + +/* Quote callouts */ +.quote-callout { + border-left: 4px solid var(--color-accent-1); + background-color: var(--color-base-2); + padding: 2rem; + margin: 3rem 0; + font-style: italic; + font-size: 1.25em; +} + +/* Pill badges */ +.pill-badge { + display: inline-flex; + align-items: center; + padding: 0.25rem 0.75rem; + background-color: var(--color-accent-1); + color: white; + border-radius: 999px; + font-size: 0.875rem; + font-weight: 500; +} +``` + +#### Spacing Drama + +```css +/* Hero sections with dramatic padding */ +.dramatic-hero { + padding: clamp(6rem, 12vw, 12rem) clamp(2rem, 4vw, 4rem); +} + +/* Asymmetric margins */ +.asymmetric-section { + margin-top: clamp(1.5rem, 3vw, 2rem); + margin-bottom: clamp(2.5rem, 5vw, 4rem); +} + +/* Tight clustering + huge gaps */ +.cluster-and-gap { + display: flex; + flex-direction: column; +} + +.cluster-and-gap .cluster { + display: flex; + gap: 0.5rem; /* Tight clustering */ + margin-bottom: 3rem; /* Huge gap between groups */ +} +``` + +## 9. Forbidden Patterns (Anti-LLM-Default) + +**Never use these unless explicitly requested:** + +### Generic Shadows +```css +/* ❌ Generic AI default */ +box-shadow: 0 2px 4px rgba(0,0,0,0.1); + +/* ✅ Use defined shadow levels */ +box-shadow: var(--shadow-rest); +``` + +### Default Browser Outlines +```css +/* ❌ Default browser outline */ +button:focus { + outline: auto; +} + +/* ✅ Custom accessible focus */ +button:focus { + outline: 2px solid var(--color-accent-1); + outline-offset: 2px; +} +``` + +### Decorative Elements +- ❌ Accent lines above titles +- ❌ Emojis or decorative shapes (unless core to request) +- ❌ Looping animations (only for loading states) +- ❌ Center-aligned multi-line body text + +### Overused Aesthetics +- ❌ Purple gradients on white backgrounds +- ❌ Inter, Roboto, Arial, system fonts +- ❌ Cookie-cutter card layouts +- ❌ Predictable color schemes + +### Creative Alternatives + +Instead of defaults, explore: +- **Unique fonts**: Playfair Display, Crimson Text, Space Grotesk +- **Bold color choices**: Deep blues with warm oranges, forest greens with cream +- **Unexpected layouts**: Diagonal grids, overlapping sections, asymmetric compositions +- **Contextual design**: Match the component's purpose and brand personality diff --git a/CLI App - Calculator Form/.agents/skills/wix-cli-site-component/references/EXAMPLE.md b/CLI App - Calculator Form/.agents/skills/wix-cli-site-component/references/EXAMPLE.md new file mode 100644 index 0000000..0e820fe --- /dev/null +++ b/CLI App - Calculator Form/.agents/skills/wix-cli-site-component/references/EXAMPLE.md @@ -0,0 +1,1044 @@ +# Site Component Example: Perfect Example + +A complete production-ready site component demonstrating all key patterns: manifest configuration, React component architecture, CSS styling, and TypeScript types. + +## Component Overview + +This example showcases a versatile component with: +- Badge, title, subtitle text elements +- Tags with comma-separated parsing +- Counter with numeric value +- Button with link and disabled state +- Featured image with placeholder +- Social links (Facebook, Twitter, Instagram) + +--- + +## File Structure + +``` +src/site/components/perfect-example/ +├── manifest.json +├── component.tsx +├── style.css +├── types.ts +└── components/ + ├── index.ts + ├── Badge.tsx + ├── Button.tsx + ├── Counter.tsx + ├── FeaturedImage.tsx + ├── SocialLinks.tsx + ├── Subtitle.tsx + ├── Tags.tsx + └── Title.tsx +``` + +--- + +## manifest.json + +```json +{ + "installation": { + "staticContainer": "HOMEPAGE", + "initialSize": { + "width": { "sizingType": "pixels", "pixels": 400 }, + "height": { "sizingType": "pixels", "pixels": 400 } + } + }, + "editorElement": { + "selector": ".perfect-example", + "displayName": "Perfect Example", + "archetype": "Container", + "interactions": { + "triggers": ["viewEnter", "pageVisible", "animationEnd", "viewProgress", "pointerMove"], + "effectGroups": ["UNKNOWN_EFFECT_GROUP"] + }, + "layout": { + "resizeDirection": "horizontalAndVertical", + "contentResizeDirection": "vertical", + "disableStretching": false, + "disablePositioning": false + }, + "data": { + "direction": { + "dataType": "direction", + "displayName": "Text Direction" + } + }, + "cssProperties": { + "backgroundColor": { + "displayName": "Background", + "defaultValue": "#ff6b6b" + }, + "padding": { + "displayName": "Padding", + "defaultValue": "40px" + }, + "borderRadius": { + "displayName": "Border Radius", + "defaultValue": "0" + }, + "border": { + "displayName": "Border", + "defaultValue": "none" + }, + "gap": { + "displayName": "Gap", + "defaultValue": "20px" + }, + "boxShadow": { + "displayName": "Shadow", + "defaultValue": "none" + }, + "opacity": { + "displayName": "Opacity", + "defaultValue": "1" + }, + "display": { + "displayName": "Display", + "defaultValue": "flex", + "display": { + "displayValues": ["none", "flex", "block"] + } + }, + "flexDirection": { + "displayName": "Direction", + "defaultValue": "column" + }, + "alignItems": { + "displayName": "Align Items", + "defaultValue": "center" + }, + "justifyContent": { + "displayName": "Justify", + "defaultValue": "center" + } + }, + "elements": { + "badge": { + "elementType": "inlineElement", + "inlineElement": { + "selector": ".perfect-example__badge", + "displayName": "Badge", + "archetype": "Text", + "data": { + "badgeText": { + "dataType": "text", + "displayName": "Badge Text", + "text": { "maxLength": 30 } + } + }, + "cssProperties": { + "backgroundColor": { "displayName": "Background", "defaultValue": "#ffffff" }, + "color": { "displayName": "Color", "defaultValue": "#ff6b6b" }, + "font": { "displayName": "Font", "defaultValue": "normal normal 600 12px/1.3em wix-madefor-display-v2" }, + "padding": { "displayName": "Padding", "defaultValue": "4px 12px" }, + "borderRadius": { "displayName": "Radius", "defaultValue": "20px" }, + "textTransform": { "displayName": "Transform", "defaultValue": "uppercase" }, + "letterSpacing": { "displayName": "Spacing", "defaultValue": "0.05em" }, + "display": { + "displayName": "Display", + "defaultValue": "inline-block", + "display": { "displayValues": ["none", "inline_block"] } + } + }, + "behaviors": { "selectable": true, "removable": true } + } + }, + "title": { + "elementType": "inlineElement", + "inlineElement": { + "selector": ".perfect-example__title", + "displayName": "Title", + "archetype": "Text", + "data": { + "titleText": { + "dataType": "text", + "displayName": "Title Text", + "text": { "maxLength": 100 } + } + }, + "cssProperties": { + "color": { "displayName": "Color", "defaultValue": "#ffffff" }, + "font": { "displayName": "Font", "defaultValue": "normal normal 700 48px/1.2em wix-madefor-display-v2" }, + "textAlign": { "displayName": "Align", "defaultValue": "center" }, + "textShadow": { "displayName": "Shadow", "defaultValue": "none" }, + "width": { "displayName": "Width", "defaultValue": "100%" }, + "display": { + "displayName": "Display", + "defaultValue": "block", + "display": { "displayValues": ["none", "block"] } + } + }, + "behaviors": { "selectable": true, "removable": true } + } + }, + "subtitle": { + "elementType": "inlineElement", + "inlineElement": { + "selector": ".perfect-example__subtitle", + "displayName": "Subtitle", + "archetype": "Text", + "data": { + "subtitleText": { + "dataType": "text", + "displayName": "Subtitle Text", + "text": { "maxLength": 200 } + } + }, + "cssProperties": { + "color": { "displayName": "Color", "defaultValue": "rgba(255, 255, 255, 0.9)" }, + "font": { "displayName": "Font", "defaultValue": "normal normal 400 18px/1.5em wix-madefor-display-v2" }, + "textAlign": { "displayName": "Align", "defaultValue": "center" }, + "width": { "displayName": "Width", "defaultValue": "100%" }, + "opacity": { "displayName": "Opacity", "defaultValue": "0.9" }, + "display": { + "displayName": "Display", + "defaultValue": "block", + "display": { "displayValues": ["none", "block"] } + } + }, + "behaviors": { "selectable": true, "removable": true } + } + }, + "tags": { + "elementType": "inlineElement", + "inlineElement": { + "selector": ".perfect-example__tags", + "displayName": "Tags", + "archetype": "Container", + "data": { + "tagsText": { + "dataType": "text", + "displayName": "Tags (comma separated)", + "text": { "maxLength": 200 } + } + }, + "cssProperties": { + "gap": { "displayName": "Gap", "defaultValue": "8px" }, + "width": { "displayName": "Width", "defaultValue": "auto" }, + "display": { + "displayName": "Display", + "defaultValue": "flex", + "display": { "displayValues": ["none", "flex"] } + } + }, + "behaviors": { "selectable": true, "removable": true } + } + }, + "counter": { + "elementType": "inlineElement", + "inlineElement": { + "selector": ".perfect-example__counter", + "displayName": "Counter", + "archetype": "Text", + "data": { + "counterValue": { + "dataType": "number", + "displayName": "Count", + "number": { "minimum": 0, "maximum": 9999 } + } + }, + "cssProperties": { + "color": { "displayName": "Color", "defaultValue": "#ffffff" }, + "font": { "displayName": "Font", "defaultValue": "normal normal 700 36px/1.2em wix-madefor-display-v2" }, + "display": { + "displayName": "Display", + "defaultValue": "flex", + "display": { "displayValues": ["none", "flex"] } + } + }, + "behaviors": { "selectable": true, "removable": true } + } + }, + "button": { + "elementType": "inlineElement", + "inlineElement": { + "selector": ".perfect-example__button", + "displayName": "Button", + "archetype": "Button", + "data": { + "buttonText": { + "dataType": "text", + "displayName": "Button Text", + "text": { "maxLength": 50 } + }, + "buttonLink": { + "dataType": "link", + "displayName": "Button Link", + "link": { + "linkTypes": ["externalLink", "pageLink", "anchorLink", "emailLink", "phoneLink"] + } + }, + "buttonDisabled": { + "dataType": "booleanValue", + "displayName": "Disabled" + } + }, + "cssProperties": { + "backgroundColor": { "displayName": "Background", "defaultValue": "#ffffff" }, + "color": { "displayName": "Text Color", "defaultValue": "#ff6b6b" }, + "font": { "displayName": "Font", "defaultValue": "normal normal 600 16px/1.4em wix-madefor-display-v2" }, + "padding": { "displayName": "Padding", "defaultValue": "12px 32px" }, + "borderRadius": { "displayName": "Radius", "defaultValue": "50px" }, + "border": { "displayName": "Border", "defaultValue": "none" }, + "boxShadow": { "displayName": "Shadow", "defaultValue": "0 4px 15px rgba(0, 0, 0, 0.2)" }, + "opacity": { "displayName": "Opacity", "defaultValue": "1" }, + "display": { + "displayName": "Display", + "defaultValue": "inline-flex", + "display": { "displayValues": ["none", "inline_flex"] } + } + }, + "behaviors": { "selectable": true, "removable": true } + } + }, + "featuredImage": { + "elementType": "inlineElement", + "inlineElement": { + "selector": ".perfect-example__image", + "displayName": "Featured Image", + "archetype": "Image", + "data": { + "image": { + "dataType": "image", + "displayName": "Image" + }, + "imageAlt": { + "dataType": "text", + "displayName": "Alt Text", + "text": { "maxLength": 100 } + } + }, + "cssProperties": { + "borderRadius": { "displayName": "Radius", "defaultValue": "12px" }, + "width": { "displayName": "Width", "defaultValue": "100%" }, + "height": { "displayName": "Height", "defaultValue": "auto" }, + "boxShadow": { "displayName": "Shadow", "defaultValue": "0 10px 40px rgba(0, 0, 0, 0.3)" }, + "objectFit": { "displayName": "Fit", "defaultValue": "cover" }, + "opacity": { "displayName": "Opacity", "defaultValue": "1" }, + "display": { + "displayName": "Display", + "defaultValue": "block", + "display": { "displayValues": ["none", "block"] } + } + }, + "behaviors": { "selectable": true, "removable": true } + } + }, + "socialLinks": { + "elementType": "inlineElement", + "inlineElement": { + "selector": ".perfect-example__social", + "displayName": "Social Links", + "archetype": "Social", + "data": { + "facebookUrl": { + "dataType": "webUrl", + "displayName": "Facebook URL" + }, + "twitterUrl": { + "dataType": "webUrl", + "displayName": "Twitter URL" + }, + "instagramUrl": { + "dataType": "webUrl", + "displayName": "Instagram URL" + } + }, + "cssProperties": { + "gap": { "displayName": "Gap", "defaultValue": "16px" }, + "display": { + "displayName": "Display", + "defaultValue": "flex", + "display": { "displayValues": ["none", "flex"] } + } + }, + "behaviors": { "selectable": true, "removable": true } + } + } + }, + "actions": { + "editContent": { + "displayName": "Edit Content", + "execution": { + "actionType": "data", + "data": { "dataItemKey": "titleText" } + } + } + } + } +} +``` + +--- + +## component.tsx + +```tsx +import React from 'react'; +import './style.css'; + +import { + Badge, + Title, + Subtitle, + Tags, + Counter, + Button, + FeaturedImage, + SocialLinks, +} from './components'; + +import type { + Text, + RichText, + NumberType, + BooleanValue, + WebUrl, + Link, + Image, + Direction, + Wix, +} from './types'; + +interface PerfectExampleProps { + className: string; + id: string; + wix?: Wix; + direction?: Direction; + elementProps?: { + badge?: { + badgeText?: Text; + }; + title?: { + titleText?: Text; + }; + subtitle?: { + subtitleText?: Text; + }; + tags?: { + tagsText?: Text; + }; + counter?: { + counterValue?: NumberType; + counterLabel?: Text; + }; + button?: { + buttonText?: Text; + buttonLink?: Link; + buttonDisabled?: BooleanValue; + }; + featuredImage?: { + image?: Image; + imageAlt?: Text; + }; + socialLinks?: { + facebookUrl?: WebUrl; + twitterUrl?: WebUrl; + instagramUrl?: WebUrl; + }; + }; +} + +const PerfectExample: React.FC<PerfectExampleProps> = ({ + className, + id, + wix, + direction, + elementProps, +}) => { + const rm = wix?.elementsRemovalState || {}; + + return ( + <div className={`perfect-example ${className}`} id={id} dir={direction}> + {!rm['badge'] && ( + <Badge className="perfect-example__badge" {...elementProps?.badge} /> + )} + + {!rm['title'] && ( + <Title className="perfect-example__title" {...elementProps?.title} /> + )} + + {!rm['subtitle'] && ( + <Subtitle className="perfect-example__subtitle" {...elementProps?.subtitle} /> + )} + + {!rm['tags'] && ( + <Tags className="perfect-example__tags" {...elementProps?.tags} /> + )} + + {!rm['counter'] && ( + <Counter className="perfect-example__counter" {...elementProps?.counter} /> + )} + + <div className="perfect-example__buttons"> + {!rm['button'] && ( + <Button className="perfect-example__button" {...elementProps?.button} /> + )} + </div> + + {!rm['featuredImage'] && ( + <FeaturedImage className="perfect-example__image" {...elementProps?.featuredImage} /> + )} + + {!rm['socialLinks'] && ( + <SocialLinks className="perfect-example__social" {...elementProps?.socialLinks} /> + )} + </div> + ); +}; + +export default PerfectExample; +``` + +--- + +## style.css + +```css +.perfect-example { + box-sizing: border-box; + width: 100%; + min-height: 400px; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + gap: 20px; + padding: 40px; + background-color: #ff6b6b; + text-align: center; +} + +.perfect-example *, +.perfect-example *::before, +.perfect-example *::after { + box-sizing: border-box; +} + +.perfect-example__badge { + display: inline-block; + padding: 4px 12px; + background-color: #ffffff; + color: #ff6b6b; + font: normal normal 600 12px/1.3em wix-madefor-display-v2; + text-transform: uppercase; + letter-spacing: 0.05em; + border-radius: 20px; +} + +.perfect-example__title { + margin: 0; + color: #ffffff; + font: normal normal 700 48px/1.2em wix-madefor-display-v2; + text-align: center; +} + +.perfect-example__subtitle { + margin: 0; + color: rgba(255, 255, 255, 0.9); + font: normal normal 400 18px/1.5em wix-madefor-display-v2; + text-align: center; + max-width: 600px; +} + +.perfect-example__tags { + display: flex; + flex-wrap: wrap; + justify-content: center; + gap: 8px; +} + +.perfect-example__tag { + display: inline-block; + padding: 6px 14px; + background-color: rgba(255, 255, 255, 0.15); + color: #ffffff; + font: normal normal 500 13px/1.3em wix-madefor-display-v2; + border-radius: 16px; + border: 1px solid rgba(255, 255, 255, 0.2); +} + +.perfect-example__counter { + display: flex; + flex-direction: column; + align-items: center; + gap: 4px; + color: #ffffff; +} + +.perfect-example__counter-label { + font: normal normal 400 14px/1.4em wix-madefor-display-v2; + opacity: 0.8; +} + +.perfect-example__buttons { + display: flex; + flex-wrap: wrap; + justify-content: center; + gap: 12px; +} + +.perfect-example__button { + display: inline-flex; + align-items: center; + justify-content: center; + padding: 12px 32px; + background-color: #ffffff; + color: #ff6b6b; + font: normal normal 600 16px/1.4em wix-madefor-display-v2; + text-decoration: none; + border: none; + border-radius: 50px; + box-shadow: 0 4px 15px rgba(0, 0, 0, 0.2); + cursor: pointer; + transition: transform 0.2s ease, box-shadow 0.2s ease; +} + +.perfect-example__button:hover { + transform: translateY(-2px); + box-shadow: 0 6px 20px rgba(0, 0, 0, 0.25); +} + +.perfect-example__image-wrapper { + width: 100%; + max-width: 400px; +} + +.perfect-example__image { + width: 100%; + height: auto; + border-radius: 12px; + box-shadow: 0 10px 40px rgba(0, 0, 0, 0.3); + object-fit: cover; +} + +.perfect-example__image--placeholder { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + gap: 8px; + min-height: 200px; + background: rgba(255, 255, 255, 0.15); + color: rgba(255, 255, 255, 0.7); + font: normal normal 500 14px/1.4em wix-madefor-display-v2; + border: 2px dashed rgba(255, 255, 255, 0.3); +} + +.perfect-example__social { + display: flex; + gap: 16px; +} + +.perfect-example__social-link { + display: flex; + align-items: center; + justify-content: center; + width: 40px; + height: 40px; + background-color: rgba(255, 255, 255, 0.15); + color: #ffffff; + border-radius: 50%; + text-decoration: none; + transition: background-color 0.2s ease, transform 0.2s ease; +} + +.perfect-example__social-link:hover { + background-color: rgba(255, 255, 255, 0.25); + transform: scale(1.1); +} + +.perfect-example[dir="rtl"] { + direction: rtl; +} + +@media (prefers-reduced-motion: reduce) { + .perfect-example *, + .perfect-example *::before, + .perfect-example *::after { + animation-duration: 0.01ms !important; + animation-iteration-count: 1 !important; + transition-duration: 0.01ms !important; + } +} +``` + +--- + +## types.ts + +```typescript +export type Text = string; +export type RichText = string; +export type NumberType = number; +export type BooleanValue = boolean; +export type WebUrl = string; +export type Direction = 'rtl' | 'ltr' | 'auto'; + +export type Link = { + href: string; + target?: string; + rel?: string; +}; + +export type Image = { + uri: string; + url: string; + name?: string; + alt?: string; + width?: number; + height?: number; +}; + +export interface Wix { + elementsRemovalState?: Record<string, 'REMOVED'>; +} + +export interface BadgeProps { + badgeText?: Text; +} + +export interface TitleProps { + titleText?: Text; +} + +export interface SubtitleProps { + subtitleText?: Text; +} + +export interface DescriptionProps { + descriptionContent?: RichText; +} + +export interface TagsProps { + tagsText?: Text; +} + +export interface CounterProps { + counterValue?: NumberType; + counterLabel?: Text; +} + +export interface ButtonProps { + buttonText?: Text; + buttonLink?: Link; + buttonDisabled?: BooleanValue; +} + +export interface FeaturedImageProps { + image?: Image; + imageAlt?: Text; +} + +export interface SocialLinksProps { + facebookUrl?: WebUrl; + twitterUrl?: WebUrl; + instagramUrl?: WebUrl; +} +``` + +--- + +## Sub-Components + +### components/index.ts + +```typescript +export { Badge } from './Badge'; +export { Title } from './Title'; +export { Subtitle } from './Subtitle'; +export { Tags } from './Tags'; +export { Counter } from './Counter'; +export { Button } from './Button'; +export { FeaturedImage } from './FeaturedImage'; +export { SocialLinks } from './SocialLinks'; +``` + +### components/Badge.tsx + +```tsx +import React from 'react'; +import type { Text } from '../types'; + +interface BadgeComponentProps { + className: string; + badgeText?: Text; +} + +export const Badge: React.FC<BadgeComponentProps> = ({ className, badgeText }) => ( + <span className={className}> + {badgeText || 'New'} + </span> +); +``` + +### components/Title.tsx + +```tsx +import React from 'react'; +import type { Text } from '../types'; + +interface TitleComponentProps { + className: string; + titleText?: Text; +} + +export const Title: React.FC<TitleComponentProps> = ({ className, titleText }) => ( + <h1 className={className}>{titleText || 'Perfect Example'}</h1> +); +``` + +### components/Subtitle.tsx + +```tsx +import React from 'react'; +import type { Text } from '../types'; + +interface SubtitleComponentProps { + className: string; + subtitleText?: Text; +} + +export const Subtitle: React.FC<SubtitleComponentProps> = ({ className, subtitleText }) => ( + <p className={className}>{subtitleText || 'The ultimate React component builder showcase'}</p> +); +``` + +### components/Tags.tsx + +```tsx +import React from 'react'; +import type { Text } from '../types'; + +interface TagsComponentProps { + className: string; + tagsText?: Text; +} + +const DEFAULT_TAGS = 'React, Builder, Wix'; + +export const Tags: React.FC<TagsComponentProps> = ({ className, tagsText }) => { + const tagsString = tagsText || DEFAULT_TAGS; + const tags = tagsString.split(',').map(tag => tag.trim()).filter(tag => tag.length > 0); + + return ( + <div className={className}> + {tags.map((tag, index) => ( + <span key={index} className="perfect-example__tag"> + {tag} + </span> + ))} + </div> + ); +}; +``` + +### components/Counter.tsx + +```tsx +import React from 'react'; +import type { NumberType } from '../types'; + +interface CounterComponentProps { + className: string; + counterValue?: NumberType; +} + +export const Counter: React.FC<CounterComponentProps> = ({ className, counterValue }) => ( + <div className={className}> + <span className="perfect-example__counter-value">{counterValue ?? 100}</span> + </div> +); +``` + +### components/Button.tsx + +```tsx +import React from 'react'; +import type { Text, Link, BooleanValue } from '../types'; + +interface ButtonComponentProps { + className: string; + buttonText?: Text; + buttonLink?: Link; + buttonDisabled?: BooleanValue; +} + +export const Button: React.FC<ButtonComponentProps> = ({ className, buttonText, buttonLink, buttonDisabled }) => { + const handleClick = (e: React.MouseEvent<HTMLAnchorElement>) => { + if (buttonDisabled || !buttonLink?.href || buttonLink.href === '#') { + e.preventDefault(); + } + }; + + return ( + <a + href={buttonLink?.href || '#'} + target={buttonLink?.target} + rel={buttonLink?.rel} + onClick={handleClick} + className={className} + aria-disabled={buttonDisabled} + style={{ pointerEvents: buttonDisabled ? 'none' : 'auto', opacity: buttonDisabled ? 0.5 : 1 }} + > + {buttonText || 'Get Started'} + </a> + ); +}; +``` + +### components/FeaturedImage.tsx + +```tsx +import React from 'react'; +import type { Image, Text } from '../types'; + +interface FeaturedImageComponentProps { + className: string; + image?: Image; + imageAlt?: Text; +} + +export const FeaturedImage: React.FC<FeaturedImageComponentProps> = ({ className, image, imageAlt }) => ( + <div className="perfect-example__image-wrapper"> + {image?.url ? ( + <img + className={className} + src={image.url} + alt={imageAlt || image.alt || 'Featured image'} + loading="lazy" + /> + ) : ( + <div className={`${className} perfect-example__image--placeholder`}> + <svg width="48" height="48" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.5"> + <rect x="3" y="3" width="18" height="18" rx="2" ry="2" /> + <circle cx="8.5" cy="8.5" r="1.5" /> + <polyline points="21 15 16 10 5 21" /> + </svg> + <span>Add Image</span> + </div> + )} + </div> +); +``` + +### components/SocialLinks.tsx + +```tsx +import React from 'react'; +import type { WebUrl } from '../types'; + +interface SocialLinksComponentProps { + className: string; + facebookUrl?: WebUrl; + twitterUrl?: WebUrl; + instagramUrl?: WebUrl; +} + +const SocialIcon: React.FC<{ type: 'facebook' | 'twitter' | 'instagram' }> = ({ type }) => { + const paths: Record<string, string> = { + facebook: 'M18 2h-3a5 5 0 0 0-5 5v3H7v4h3v8h4v-8h3l1-4h-4V7a1 1 0 0 1 1-1h3z', + twitter: 'M23 3a10.9 10.9 0 0 1-3.14 1.53 4.48 4.48 0 0 0-7.86 3v1A10.66 10.66 0 0 1 3 4s-4 9 5 13a11.64 11.64 0 0 1-7 2c9 5 20 0 20-11.5a4.5 4.5 0 0 0-.08-.83A7.72 7.72 0 0 0 23 3z', + instagram: 'M16 4H8a4 4 0 0 0-4 4v8a4 4 0 0 0 4 4h8a4 4 0 0 0 4-4V8a4 4 0 0 0-4-4zm-4 11a3 3 0 1 1 0-6 3 3 0 0 1 0 6zm4.5-7.5a1 1 0 1 1 0-2 1 1 0 0 1 0 2z', + }; + + return ( + <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"> + <path d={paths[type]} /> + </svg> + ); +}; + +export const SocialLinks: React.FC<SocialLinksComponentProps> = ({ + className, + facebookUrl, + twitterUrl, + instagramUrl +}) => { + const links = [ + { type: 'facebook' as const, url: facebookUrl }, + { type: 'twitter' as const, url: twitterUrl }, + { type: 'instagram' as const, url: instagramUrl }, + ].filter(link => link.url); + + const displayLinks = links.length > 0 ? links : [ + { type: 'facebook' as const, url: '#' }, + { type: 'twitter' as const, url: '#' }, + { type: 'instagram' as const, url: '#' }, + ]; + + return ( + <div className={className}> + {displayLinks.map(({ type, url }) => ( + <a + key={type} + href={url || '#'} + target="_blank" + rel="noopener noreferrer" + className="perfect-example__social-link" + aria-label={type} + onClick={(e) => { if (!url || url === '#') e.preventDefault(); }} + > + <SocialIcon type={type} /> + </a> + ))} + </div> + ); +}; +``` + +--- + +## Key Patterns Demonstrated + +### 1. Installation Configuration + +```json +"installation": { + "staticContainer": "HOMEPAGE", + "initialSize": { + "width": { "sizingType": "pixels", "pixels": 400 }, + "height": { "sizingType": "pixels", "pixels": 400 } + } +} +``` + +- `staticContainer: "HOMEPAGE"` ensures automatic installation on Harmony editor +- `initialSize` defines the component's default dimensions when added to a page + +### 2. Manifest-to-React Alignment + +- Each manifest element key (`badge`, `title`, etc.) matches the React removal state check +- CSS selectors match manifest selectors exactly (`.perfect-example__badge`) +- Data types in manifest match TypeScript types (`text` → `Text`, `number` → `NumberType`) + +### 3. Sub-Component Architecture + +- Each visual element is a separate sub-component +- Sub-components receive `className` prop for CSS styling +- Props spread pattern: `{...elementProps?.badge}` + +### 4. Removal State Handling + +```tsx +const rm = wix?.elementsRemovalState || {}; +{!rm['badge'] && <Badge ... />} +``` + +### 5. CSS Variable Integration + +- Root element uses CSS variables for dynamic styling +- `display` property configurable via manifest +- All selectors declared once with `box-sizing: border-box` + +### 6. Accessibility + +- Proper `aria-disabled` on buttons +- `loading="lazy"` on images +- `aria-label` on icon-only links +- Reduced motion media query support + diff --git a/CLI App - Calculator Form/.agents/skills/wix-cli-site-component/references/MANIFEST_GUIDELINES.md b/CLI App - Calculator Form/.agents/skills/wix-cli-site-component/references/MANIFEST_GUIDELINES.md new file mode 100644 index 0000000..1d30a19 --- /dev/null +++ b/CLI App - Calculator Form/.agents/skills/wix-cli-site-component/references/MANIFEST_GUIDELINES.md @@ -0,0 +1,479 @@ +# Component Manifest Guidelines + +The manifest defines the contract between your React component and the Wix ecosystem, enabling users to interact with inner elements, edit component style and props through the visual editor. + +## Core Structure + +```json +{ + "installation": { + "staticContainer": "HOMEPAGE", + "initialSize": { + "width": { "sizingType": "pixels", "pixels": 400 }, + "height": { "sizingType": "pixels", "pixels": 300 } + } + }, + "editorElement": { + "selector": ".component-name", + "displayName": "Component Name", + "archetype": "Container", + "layout": { ... }, + "cssProperties": { ... }, + "data": { ... }, + "elements": { ... } + } +} +``` + +## Installation Configuration + +The `installation` property defines how the component is initially placed and sized when added to a page. + +### Installation Fields + +| Field | Type | Description | +|-------|------|-------------| +| `staticContainer` | string | Automatic installation location. Use `"HOMEPAGE"` to auto-install on homepage | +| `initialSize` | object | Initial dimensions when the component is added | + +### Initial Size Configuration + +| Property | Type | Description | +|----------|------|-------------| +| `width` | InitialSizeSetting | Width configuration | +| `height` | InitialSizeSetting | Height configuration | + +### InitialSizeSetting + +| Property | Type | Description | +|----------|------|-------------| +| `sizingType` | string | One of: `"content"`, `"stretched"`, `"pixels"` | +| `pixels` | number | Required when sizingType is `"pixels"` | + +### Sizing Type Values + +| Value | Description | +|-------|-------------| +| `content` | Component auto-sizes based on its content | +| `stretched` | Component stretches to fill available space | +| `pixels` | Component has a fixed pixel dimension (requires `pixels` property) | + +### Installation Examples + +```json +// Fixed dimensions (most common) +{ + "installation": { + "staticContainer": "HOMEPAGE", + "initialSize": { + "width": { "sizingType": "pixels", "pixels": 400 }, + "height": { "sizingType": "pixels", "pixels": 300 } + } + } +} + +// Content-based height +{ + "installation": { + "staticContainer": "HOMEPAGE", + "initialSize": { + "width": { "sizingType": "pixels", "pixels": 600 }, + "height": { "sizingType": "content" } + } + } +} + +// Stretched width +{ + "installation": { + "staticContainer": "HOMEPAGE", + "initialSize": { + "width": { "sizingType": "stretched" }, + "height": { "sizingType": "pixels", "pixels": 400 } + } + } +} +``` + +### Installation Guidelines + +- **Always include** `"staticContainer": "HOMEPAGE"` for automatic installation on Harmony editor +- **Default initial size** is 400px width, 300px height (matches Wix Harmony defaults) +- Use `"content"` for height when the component should auto-size based on its content +- Use `"stretched"` when the component should fill available space +- Use `"pixels"` for fixed dimensions + +## Data Types + +### Basic Types + +| Type | Runtime Value | Constraints | Use Case | +|------|---------------|-------------|----------| +| `text` | string | maxLength, minLength, pattern | Names, titles, descriptions | +| `textEnum` | string | required options list | Predefined choices | +| `number` | number | minimum, maximum, multipleOf | Quantities, dimensions | +| `booleanValue` | boolean | - | Toggles, feature flags | +| `localDate` | string (YYYY-MM-DD) | - | Birthdays, events | +| `localTime` | string (hh:mm[:ss][.sss]) | - | Schedules | +| `webUrl` | string | http/https validation | External links | +| `direction` | string | - | HTML dir attribute (ltr/rtl) | + +### Rich Content Types + +| Type | Runtime Value | Configuration | Use Case | +|------|---------------|---------------|----------| +| `richText` | string (HTML) | richTextAbilities array | Formatted content | +| `link` | `{ href, target, rel }` | linkTypes array | Navigation | +| `image` | `{ uri, url, alt, width, height }` | - | Media content | +| `video` | Video object | - | Media content | +| `vectorArt` | Sanitized SVG object | - | Icons, graphics | +| `a11y` | Object | selected A11Y fields | Accessibility attributes | + +### Collection Types + +| Type | Runtime Value | Configuration | Use Case | +|------|---------------|---------------|----------| +| `arrayItems` | Array | data structure, maxSize | Lists, collections | +| `menuItems` | Array of menu items | - | Navigation menus | + +### DataItem Fields + +Each data item in the manifest can have these configuration fields: + +| Field | Type | Description | +|-------|------|-------------| +| `dataType` | DataType | Type of data being configured (required) | +| `displayName` | string | Display name shown in editor, max 100 chars | +| `text` | Text | Limitations on text input (maxLength, minLength, pattern) | +| `textEnum` | TextEnum | Required list of options with value and displayName | +| `number` | Number | Restrictions (minimum, maximum, multipleOf) | +| `link` | Link | Link support definition with linkTypes array | +| `arrayItems` | ArrayItems | Array data type definition with data structure and maxSize | +| `richTextAbilities` | RichTextAbilities[] | Rich text formatting abilities array | + +### Link Types + +Available options for `link` dataType: +- `externalLink`, `anchorLink`, `emailLink`, `phoneLink` +- `dynamicPageLink`, `pageLink`, `whatsAppLink`, `documentLink` +- `popupLink`, `addressLink`, `edgeAnchorLinks`, `loginToWixLink` + +### Rich Text Abilities + +Available formatting options for `richText` dataType: +- `font`, `fontFamily`, `fontSize`, `fontStyle`, `fontWeight` +- `textDecoration`, `color`, `backgroundColor`, `letterSpacing` +- `textAlign`, `direction`, `marginStart`, `marginEnd` +- `bulletedList`, `numberedList`, `seoTag` + +## CSS Properties + +### Common Properties + +| Property | Description | Values | +|----------|-------------|--------| +| `backgroundColor` | Background color | Color values | +| `color` | Text color | Color values | +| `font` | Font shorthand | Derives fontFamily, fontSize, etc. | +| `padding` | Internal spacing | Derives all directional variants | +| `margin` | External spacing | Derives all directional variants | +| `border` | Border shorthand | Derives width, style, color variants | +| `borderRadius` | Corner rounding | Derives all corner variants | +| `display` | Display type | See display values below | +| `gap` | Flex/grid spacing | Length values | +| `width`, `height` | Dimensions | Length values | +| `textAlign` | Text alignment | left, center, right, justify | +| `flexDirection` | Flex direction | row, column, row-reverse, column-reverse | +| `alignItems` | Cross-axis alignment | flex-start, center, flex-end, stretch | +| `justifyContent` | Main-axis alignment | flex-start, center, flex-end, space-between | +| `objectFit` | Image fitting | contain, cover, fill, scale-down | + +### Display Values + +Use underscores for multi-word values: +- `none`, `block`, `inline`, `flow`, `flowRoot`, `table` +- `flex`, `grid`, `list_item`, `contents` +- `inline_block`, `inline_table`, `inline_flex`, `inline_grid` + +### CSS Property Item Fields + +- **displayName** (string): Display name, max 100 chars +- **defaultValue** (Value): Default CSS value +- **display** (Display): Options for display property with displayValues array + +### CSS Shorthand Properties + +Shorthand properties derive their constituent parts: +- **border**: Derives borderWidth, borderStyle, borderColor, and all directional variants +- **background**: Derives backgroundColor, backgroundImage, backgroundSize, etc. +- **margin**: Derives marginTop, marginRight, marginBottom, marginLeft +- **padding**: Derives paddingTop, paddingRight, paddingBottom, paddingLeft +- **font**: Derives fontFamily, fontSize, fontWeight, fontStyle, lineHeight +- **borderRadius**: Derives all corner radius variants + +### CSS Property Structure + +```json +{ + "cssProperties": { + "backgroundColor": { + "displayName": "Background Color", + "defaultValue": "#ffffff" + }, + "display": { + "displayName": "Display Type", + "display": { + "displayValues": ["none", "block", "flex", "grid"] + } + } + } +} +``` + +## Editor Element Configuration + +### Main Properties + +| Property | Type | Description | Constraints | +|----------|------|-------------|-------------| +| `selector` | string | CSS class from React | 4-50 chars, one class only | +| `displayName` | string | Editor stage name | 4-20 chars | +| `cssProperties` | object | CSS API | Container styles only | +| `data` | object | Data API | Component-wide config only | +| `elements` | object | Inner elements | Each distinct UI part | +| `layout` | object | Layout capabilities | Resize/position options | +| `archetype` | string | Component type | See archetype options | + +### Archetype Options + +Complete list of available archetypes: + +**Containers**: `Container`, `Carousel`, `Accordion`, `Tabs` + +**Content**: `Text`, `RichTextEditor`, `Image`, `Gallery`, `Video`, `Audio`, `VectorArt`, `AnimatedGraphic`, `Line`, `Logo`, `Avatar` + +**Interactive**: `Button`, `LoginButton`, `Menu`, `Pagination`, `Slider`, `SearchBox`, `Social`, `Breadcrumbs` + +**Input**: `TextInput`, `SignatureInput`, `Checkbox`, `RadioGroup`, `Switch`, `Dropdown`, `DatePicker`, `TimePicker`, `Ratings`, `RatingInput`, `Upload`, `Captcha` + +**Specialized**: `Map`, `Cart`, `ContactForm`, `ProgressBar` + +### Layout Configuration + +```json +{ + "layout": { + "resizeDirection": "horizontalAndVertical", + "contentResizeDirection": "horizontal", + "disableStretching": false, + "disablePositioning": false, + "disableRotation": false + } +} +``` + +**Resize Direction Options:** +- `horizontal`, `vertical`, `horizontalAndVertical`, `aspectRatio` + +**Content Resize Direction Options:** +- `horizontal`, `vertical`, `horizontalAndVertical`, `none` + +## Elements Structure + +### Element Definition + +```json +{ + "elements": { + "elementKey": { + "elementType": "inlineElement", + "inlineElement": { + "selector": ".component__element", + "displayName": "Element Name", + "cssProperties": { ... }, + "data": { ... }, + "elements": { ... }, + "behaviors": { + "selectable": true, + "removable": true + }, + "archetype": "Button" + } + } + } +} +``` + +### Critical Rules + +**One Element = One Manifest Entry** +- Each distinct visual part = separate element +- 3 buttons → 3 separate elements (NOT 1 "buttons" element) +- Image + text → 2 separate elements (NOT 1 "hero" element) + +**Data Scoping** +- `editorElement.data` - ONLY component-wide config (layout enums, numbers) +- `elements[key].data` - Content for THAT element (text, links, images) +- NEVER put element content in component-level data + +**Display CSS Property (Required)** +The root editorElement MUST include a display CSS property: +```json +"display": { + "displayName": "Display", + "display": { + "displayValues": ["none", "block"] + } +} +``` + +**Behaviors (Required)** +- Always set `selectable: true` and `removable: true` +- Users need to select and remove elements independently + +**Data VS CSS Properties** +- Anything that can be defined in CSS should be exposed in the manifest via CSS properties, never data +- Use `cssProperties` for: colors, sizes, spacing, fonts, borders, shadows +- Use `data` for: text content, links, images, arrays, configuration values + +**Repeated Data** +- Whenever the component has repeated data (e.g. lists, collections), ALWAYS use the `arrayItems` data type +- Never create multiple separate elements for items that should be in an array + +## Examples + +### Simple Text Element + +```json +{ + "title": { + "elementType": "inlineElement", + "inlineElement": { + "selector": ".product-card__title", + "displayName": "Title", + "data": { + "titleText": { + "dataType": "text", + "displayName": "Title Text" + } + }, + "cssProperties": { + "color": { + "displayName": "Text Color", + "defaultValue": "#333333" + }, + "fontSize": { + "displayName": "Font Size", + "defaultValue": "24px" + } + }, + "behaviors": { + "selectable": true, + "removable": true + }, + "archetype": "Text" + } + } +} +``` + +### Button with Link + +```json +{ + "ctaButton": { + "elementType": "inlineElement", + "inlineElement": { + "selector": ".hero__cta-button", + "displayName": "CTA Button", + "data": { + "buttonText": { + "dataType": "text", + "displayName": "Button Text" + }, + "buttonLink": { + "dataType": "link", + "displayName": "Button Link", + "link": { + "linkTypes": ["externalLink", "pageLink"] + } + } + }, + "cssProperties": { + "backgroundColor": { + "displayName": "Background Color", + "defaultValue": "#007bff" + }, + "borderRadius": { + "displayName": "Border Radius", + "defaultValue": "8px" + } + }, + "behaviors": { + "selectable": true, + "removable": true + }, + "archetype": "Button" + } + } +} +``` + +### Array Items Collection + +```json +{ + "featureList": { + "dataType": "arrayItems", + "displayName": "Feature List", + "arrayItems": { + "data": { + "items": { + "title": { + "dataType": "text", + "displayName": "Feature Title" + }, + "description": { + "dataType": "text", + "displayName": "Feature Description" + }, + "icon": { + "dataType": "vectorArt", + "displayName": "Feature Icon" + } + } + }, + "maxSize": 6 + } + } +} +``` + +## Synchronization Requirements + +**CRITICAL**: Manifest must match React and CSS exactly: + +| File | Convention | Example | +|------|------------|---------| +| React className | Direct class | `className="product-card__title"` | +| CSS selector | Same class | `.product-card__title { ... }` | +| Manifest selector | Same class | `"selector": ".product-card__title"` | +| React prop | camelCase | `titleText` | +| Manifest data key | camelCase | `"titleText"` | + +**Never use:** +- Compound selectors (`.a.b`) +- Descendant selectors (`.parent .child`) +- Different naming between files + +## Validation Checklist + +- [ ] All selectors match between manifest, React, and CSS +- [ ] Each distinct UI element has separate manifest entry +- [ ] Component data contains only layout/config, not content +- [ ] Element data contains only content for that element +- [ ] All elements have `selectable: true, removable: true` +- [ ] CSS properties have appropriate default values +- [ ] Data types match expected runtime values +- [ ] Display names are user-friendly (4-20 chars) +- [ ] Selectors are valid CSS classes (4-50 chars) diff --git a/CLI App - Calculator Form/.agents/skills/wix-cli-site-component/references/REACT_PATTERNS.md b/CLI App - Calculator Form/.agents/skills/wix-cli-site-component/references/REACT_PATTERNS.md new file mode 100644 index 0000000..9f67230 --- /dev/null +++ b/CLI App - Calculator Form/.agents/skills/wix-cli-site-component/references/REACT_PATTERNS.md @@ -0,0 +1,657 @@ +# React Component Patterns + +Guidelines for building production-quality React components that integrate seamlessly with Wix Editor manifests. + +## General Instructions + +### File Structure and Imports + +- Import `./style.css` at the top of the component file +- Component must be a pure function, SSR-safe (no browser APIs at module scope, guard hooks) +- Declare types at top of file, include wix prop in interface +- Use default export for the main component + +### Root Element Pattern + +- Apply `className` and `id` to root element: `<div className={\`my-component ${className}\`} id={id}>` +- Top-level className MUST match manifest `editorElement.selector` +- Pattern: `className={\`base ${className}\`}` where `base` = selector without the dot +- Example: If selector is `.product-card`, then: `className={\`product-card ${className}\`}` + +### Synchronization Requirements + +- Sync component with manifest (props ↔ data keys, classNames ↔ selectors) +- Component MUST react to prop changes - if state is initialized from props, update it when props change using useEffect with prop dependencies +- Conditionally render ALL elements per `wix.elementsRemovalState` (all removable) + +### Content and Data + +- **All user-facing content must come from props** - text, media, links, labels, arrays should be controlled by manifest data +- Hardcoded values are ONLY for fallback defaults when props are undefined +- Links/media from manifest only, never hardcode URLs +- Map a11y props to DOM attributes when applicable + +### Code Quality + +- Default export required +- No TypeScript errors, unused variables, or TODOs +- Code must compile and pass linting on first try + +## Component Hierarchy + +### Three Component Types + +**1. Leaf Components** - Render content only, no children: +```typescript +type LeafComponent<TProps> = (props: TProps & { className: string }) => React.JSX.Element; +``` + +**2. Container Components** - Render child sub-components: +```typescript +type ContainerComponent<TProps> = ( + props: TProps & { + className: string; + elementProps?: Record<string, any>; + wix?: Wix; + } +) => React.JSX.Element; +``` + +**3. Root Component** - The exported default, receives all builder props: +```typescript +type RootComponent<TProps> = ( + props: TProps & { + id?: string; + className: string; + elementProps?: Record<string, any>; + wix?: Wix; + } +) => React.JSX.Element; +``` + +## Standard Props Structure + +### Always Present Props + +```typescript +interface BaseProps { + className: string; // CSS classes - MUST apply to root element + id: string; // Unique identifier - MUST apply to root element + wix?: Wix; // Wix system props including elementsRemovalState +} +``` + +### Wix System Props + +```typescript +type REMOVED = 'REMOVED'; + +interface Wix { + elementsRemovalState?: Record<string, REMOVED>; +} +``` + +### Element Props Structure + +```typescript +interface ElementProps { + [dataKey: string]: DataType; // Data from element + elementProps?: Record<string, ElementProps>; // Nested child elements + wix?: Wix; // Element-level removal state +} +``` + +### Complete Props Example + +```typescript +interface ProductCardProps extends BaseProps { + // Component-level data (from editorElement.data) + columns?: number; + layout?: 'grid' | 'list'; + + // Element props (from elements definitions) + elementProps?: { + image?: { + productImage?: Image; + wix?: Wix; + elementProps?: { + badge?: { + badgeText?: string; + badgeColor?: string; + }; + }; + }; + content?: { + wix?: Wix; + elementProps?: { + title?: { titleText?: string }; + price?: { priceAmount?: number }; + button?: { + buttonText?: string; + buttonLink?: Link; + }; + }; + }; + }; +} +``` + +## Sub-Component Pattern + +### Extract Every Distinct UI Unit + +Create named sub-components for: +- **Manifest elements** - matching keys in manifest elements +- **Logical units** - buttons, icons, controls, sections +- **Reusable pieces** - any distinct JSX block + +### Sub-Component Rules + +1. **Unique nickname** (valid CSS classname, matches manifest element key) +2. **Pass nickname as className** +3. **Separate function component** for each element +4. **Single spread** for data props: `{...elementProps?.['childKey']}` +5. **Self-contained** - complete units, never wrap with semantic elements + +### Example Implementation + +```typescript +// Title sub-component +interface TitleProps { + titleText?: string; + className: string; +} + +const Title: FC<TitleProps> = ({ + titleText = 'Default Title', + className +}) => ( + <h2 className={className}>{titleText}</h2> +); + +// Price sub-component +interface PriceProps { + priceAmount?: number; + currency?: string; + className: string; +} + +const Price: FC<PriceProps> = ({ + priceAmount = 0, + currency = 'USD', + className +}) => ( + <span className={className}> + {new Intl.NumberFormat('en-US', { + style: 'currency', + currency + }).format(priceAmount)} + </span> +); + +// Button sub-component +interface ButtonProps { + buttonText?: string; + buttonLink?: Link; + className: string; +} + +const Button: FC<ButtonProps> = ({ + buttonText = 'Click Here', + buttonLink, + className +}) => { + const handleClick = (e: React.MouseEvent) => { + if (!buttonLink?.href || buttonLink.href === '#') { + e.preventDefault(); + } + }; + + return ( + <a + href={buttonLink?.href || '#'} + target={buttonLink?.target} + rel={buttonLink?.rel} + className={className} + onClick={handleClick} + > + {buttonText} + </a> + ); +}; + +// Main component +const ProductCard: FC<ProductCardProps> = ({ + className, + id, + columns = 1, + elementProps, + wix +}) => { + const removalState = wix?.elementsRemovalState || {}; + + return ( + <div + className={`product-card ${className}`} + id={id} + style={{ '--columns': columns } as React.CSSProperties} + > + {!removalState['image'] && ( + <div className="product-card__image"> + <img + src={elementProps?.image?.productImage?.url || '/default-image.jpg'} + alt={elementProps?.image?.productImage?.alt || 'Product'} + className="product-card__img" + /> + {!removalState['badge'] && elementProps?.image?.elementProps?.badge && ( + <span className="product-card__badge"> + {elementProps.image.elementProps.badge.badgeText} + </span> + )} + </div> + )} + + {!removalState['content'] && ( + <div className="product-card__content"> + {!removalState['title'] && ( + <Title + className="product-card__title" + {...elementProps?.content?.elementProps?.title} + /> + )} + + {!removalState['price'] && ( + <Price + className="product-card__price" + {...elementProps?.content?.elementProps?.price} + /> + )} + + {!removalState['button'] && ( + <Button + className="product-card__button" + {...elementProps?.content?.elementProps?.button} + /> + )} + </div> + )} + </div> + ); +}; + +export default ProductCard; +``` + +## Props and State Management + +### Default Handling + +**Default each field independently**, never the entire element object: + +```typescript +// ✅ Correct - individual field defaults +const titleText = elementProps?.title?.titleText || 'Default Title'; +const priceAmount = elementProps?.price?.priceAmount || 0; + +// ❌ Wrong - defaulting entire object +const titleProps = elementProps?.title || { titleText: 'Default' }; +``` + +**For arrays, check length:** +```typescript +const items = (props?.items?.length > 0) ? props.items : DEFAULT_ITEMS; + +// With safety checks in map +{items?.map((item, index) => { + if (!item?.title) return null; + return <div key={index}>{item.title}</div>; +})} +``` + +### State Synchronization + +**Component MUST react to prop changes:** + +```typescript +const [selectedTab, setSelectedTab] = useState(props.defaultTab); + +// Sync state when props change +useEffect(() => { + setSelectedTab(props.defaultTab); +}, [props.defaultTab]); +``` + +### Type Definitions + +**All data props must be optional:** +```typescript +interface ComponentProps { + // Required system props + className: string; + id: string; + wix?: Wix; + + // Optional data props (use ?) + title?: string; + description?: string; + items?: Array<Item>; + config?: ConfigObject; +} +``` + +## Conditional Rendering + +### Element Removal State + +**All elements must be conditionally rendered:** + +```typescript +const removalState = wix?.elementsRemovalState || {}; + +return ( + <div className={`component ${className}`} id={id}> + {!removalState['header'] && ( + <Header {...elementProps?.header} /> + )} + + {!removalState['content'] && ( + <Content {...elementProps?.content} /> + )} + + {!removalState['footer'] && ( + <Footer {...elementProps?.footer} /> + )} + </div> +); +``` + +### Nested Element Removal + +```typescript +// Check removal state at each level +{!removalState['content'] && ( + <div className="content"> + {!elementProps?.content?.wix?.elementsRemovalState?.['title'] && ( + <Title {...elementProps?.content?.elementProps?.title} /> + )} + </div> +)} +``` + +## Links and Media Handling + +### Link Pattern + +```typescript +interface LinkProps { + buttonText?: string; + buttonLink?: Link; + className: string; +} + +const LinkButton: FC<LinkProps> = ({ buttonText, buttonLink, className }) => { + const handleClick = (e: React.MouseEvent) => { + if (!buttonLink?.href || buttonLink.href === '#') { + e.preventDefault(); + } + }; + + return ( + <a + href={buttonLink?.href || '#'} + target={buttonLink?.target} + rel={buttonLink?.rel} + className={className} + onClick={handleClick} + > + {buttonText || 'Click Here'} + </a> + ); +}; +``` + +### Image Pattern + +```typescript +interface ImageProps { + productImage?: Image; + className: string; +} + +const ProductImage: FC<ImageProps> = ({ productImage, className }) => ( + <img + src={productImage?.url || '/default-image.jpg'} + alt={productImage?.alt || 'Product'} + width={productImage?.width} + height={productImage?.height} + className={className} + /> +); +``` + +### Rich Text Pattern + +**Note**: `dangerouslySetInnerHTML` and inline `<style>` tags are **forbidden** by ESLint rules. For rich text content, use CSS variables or the inline `style` prop for dynamic values. + +```typescript +interface RichTextProps { + content?: string; + className: string; +} + +// For simple formatted text, parse and render safely +const RichTextContent: FC<RichTextProps> = ({ content, className }) => ( + <div className={className}> + {/* Render plain text or use a sanitized rendering approach */} + {content || 'Default content'} + </div> +); +``` + +**IMPORTANT**: If rich text HTML rendering is absolutely required, consult with the Wix CLI team for approved sanitization methods. + +## Array Handling + +### Safe Array Mapping + +```typescript +interface ListProps { + items?: Array<ListItem>; + className: string; +} + +const ItemList: FC<ListProps> = ({ items, className }) => { + const safeItems = (items?.length > 0) ? items : DEFAULT_ITEMS; + + return ( + <ul className={className}> + {safeItems.map((item, index) => { + // Safety check for each item + if (!item?.title) return null; + + return ( + <li key={item.id || index} className="item"> + <h3>{item.title}</h3> + {item.description && <p>{item.description}</p>} + </li> + ); + })} + </ul> + ); +}; +``` + +### Default Arrays + +```typescript +// Define outside component to prevent re-creation +const DEFAULT_FEATURES = [ + { id: '1', title: 'Feature 1', description: 'Description 1' }, + { id: '2', title: 'Feature 2', description: 'Description 2' }, + { id: '3', title: 'Feature 3', description: 'Description 3' } +]; + +const FeatureList: FC<FeatureListProps> = ({ features }) => { + const displayFeatures = (features?.length > 0) ? features : DEFAULT_FEATURES; + + return ( + <div className="features"> + {displayFeatures.map(feature => ( + <FeatureCard key={feature.id} {...feature} /> + ))} + </div> + ); +}; +``` + +## TypeScript Best Practices + +### Strict Typing + +```typescript +// ✅ Proper type definitions +interface Image { + uri: string; + url: string; + name?: string; + alt?: string; + width?: number; + height?: number; +} + +interface Link { + href: string; + target?: string; + rel?: string; +} + +// ✅ Union types for enums +type LayoutType = 'grid' | 'list' | 'masonry'; +type ButtonVariant = 'primary' | 'secondary' | 'outline'; + +// ❌ Avoid any +const handleData = (data: any) => { ... }; // Wrong + +// ✅ Use proper typing +const handleData = (data: ComponentData) => { ... }; // Correct +``` + +### Event Handlers + +```typescript +// ✅ Proper event typing +const handleClick = (e: React.MouseEvent<HTMLButtonElement>) => { + e.preventDefault(); + // Handle click +}; + +const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => { + setValue(e.target.value); +}; + +// ✅ Custom event handlers +interface CustomHandler { + onItemSelect?: (item: Item) => void; + onItemRemove?: (id: string) => void; +} +``` + +## ESLint Compliance + +### Critical ESLint Rules + +1. **No unused vars/params/imports** (`@typescript-eslint/no-unused-vars`) +2. **No external images**: `img` `src` not `https://...` (allowed: local imports, `wixstatic.com`, variables) +3. **SSR-safe**: No `window`/`document` at module scope/constructor, guard browser APIs in `useEffect`/handlers +4. **No `dangerouslySetInnerHTML` or inline `<style>` tags** - use CSS variables or inline `style` prop for dynamic values +5. **No `window.fetch`** (`no-restricted-properties`) +6. **Hooks `exhaustive-deps`**: ALL values from component scope used inside `useEffect`/`useCallback` MUST be in dependency array + - Functions used in `useEffect`: declare inside the hook and wrap in `useCallback`, or include in dependency array + - Event handlers (e.g., `handleMouseMove`, `handleClick`) used in effects MUST be wrapped in `useCallback` or included in dependency array + - Props/state/functions from component scope must be in dependency array +7. **Use `const`/`let` (no `var`)**, no unknown JSX properties + +### Dependency Arrays + +```typescript +// ✅ Include all dependencies +useEffect(() => { + const handleResize = () => { + setDimensions({ width: window.innerWidth, height: window.innerHeight }); + }; + + window.addEventListener('resize', handleResize); + return () => window.removeEventListener('resize', handleResize); +}, []); // No dependencies needed + +// ✅ Include prop dependencies +useEffect(() => { + if (autoPlay && duration) { + const timer = setTimeout(() => { + nextSlide(); + }, duration); + return () => clearTimeout(timer); + } +}, [autoPlay, duration, nextSlide]); // All used values included +``` + +### useCallback for Event Handlers + +```typescript +// ✅ Wrap handlers used in effects +const handleMouseMove = useCallback((e: MouseEvent) => { + setPosition({ x: e.clientX, y: e.clientY }); +}, []); + +useEffect(() => { + document.addEventListener('mousemove', handleMouseMove); + return () => document.removeEventListener('mousemove', handleMouseMove); +}, [handleMouseMove]); // Include in dependencies +``` + +### No External Images + +```typescript +// ❌ External URLs not allowed +<img src="https://example.com/image.jpg" alt="Example" /> + +// ✅ Use assets or wixstatic.com +import { defaultImage } from './assets/defaultImages'; +<img src={defaultImage} alt="Default" /> + +// ✅ Or wixstatic.com URLs +<img src="https://static.wixstatic.com/media/example.jpg" alt="Example" /> +``` + +## Performance Considerations + +### Avoid Re-renders + +```typescript +// ✅ Memoize expensive calculations +const expensiveValue = useMemo(() => { + return items.reduce((acc, item) => acc + item.value, 0); +}, [items]); + +// ✅ Memoize components when needed +const MemoizedItem = React.memo<ItemProps>(({ item }) => ( + <div className="item">{item.title}</div> +)); +``` + +### Lazy Loading + +```typescript +// ✅ Lazy load heavy components +const HeavyChart = lazy(() => import('./HeavyChart')); + +const Dashboard: FC<DashboardProps> = ({ showChart }) => ( + <div> + {showChart && ( + <Suspense fallback={<div>Loading chart...</div>}> + <HeavyChart /> + </Suspense> + )} + </div> +); +``` diff --git a/CLI App - Calculator Form/.agents/skills/wix-cli-site-component/references/TYPESCRIPT_QUALITY.md b/CLI App - Calculator Form/.agents/skills/wix-cli-site-component/references/TYPESCRIPT_QUALITY.md new file mode 100644 index 0000000..a020cf7 --- /dev/null +++ b/CLI App - Calculator Form/.agents/skills/wix-cli-site-component/references/TYPESCRIPT_QUALITY.md @@ -0,0 +1,577 @@ +# TypeScript Quality Guidelines + +Strict TypeScript standards for production-quality site components with zero compilation errors. + +## Core Principles + +### Strict Configuration + +Generated code MUST compile with zero TypeScript errors under strict settings: +- `strict: true` +- `noImplicitAny: true` +- `strictNullChecks: true` +- `exactOptionalPropertyTypes: true` +- `noUncheckedIndexedAccess: true` + +### Type Safety First + +- Prefer type-narrowing and exhaustive logic over assertions +- Avoid non-null assertions (`!`) and unsafe casts (`as any`) +- Treat optional values, refs, and array indexing as possibly undefined +- Use exhaustive checks for unions with never type guards +- Return total values (no implicit undefined) + +## Type Definitions + +### Component Props Interface + +```typescript +// ✅ Correct - strict typing with optional data props +interface ProductCardProps { + // Required system props + className: string; + id: string; + wix?: Wix; + + // Optional component data (from editorElement.data) + columns?: number; + layout?: 'grid' | 'list' | 'masonry'; + showPrices?: boolean; + + // Optional element props (from elements definitions) + elementProps?: { + image?: { + productImage?: Image; + wix?: Wix; + elementProps?: { + badge?: { + badgeText?: string; + badgeColor?: string; + }; + }; + }; + content?: { + wix?: Wix; + elementProps?: { + title?: { titleText?: string }; + price?: { priceAmount?: number; currency?: string }; + button?: { buttonText?: string; buttonLink?: Link }; + }; + }; + }; +} + +// ❌ Wrong - using any or missing optionals +interface BadProps { + className: string; + id: string; + data: any; // Never use any + title: string; // Should be optional +} +``` + +### Data Type Mappings + +```typescript +// Runtime value types for manifest data types +interface DataTypeMapping { + text: string; + textEnum: string; + number: number; + booleanValue: boolean; + localDate: string; // YYYY-MM-DD format + localTime: string; // hh:mm format + webUrl: string; + richText: string; // HTML string + link: Link; + image: Image; + video: Video; + vectorArt: VectorArt; + arrayItems: Array<unknown> | Array<Record<string, unknown>>; + menuItems: Array<MenuItem>; +} + +// Wix system types +interface Link { + href: string; + target?: string; + rel?: string; +} + +interface Image { + uri: string; + url: string; + name?: string; + alt?: string; + width?: number; + height?: number; +} + +type REMOVED = 'REMOVED'; + +interface Wix { + elementsRemovalState?: Record<string, REMOVED>; +} +``` + +### Sub-Component Props + +```typescript +// ✅ Correct - explicit props with defaults +interface TitleProps { + titleText?: string; + className: string; +} + +interface ButtonProps { + buttonText?: string; + buttonLink?: Link; + variant?: 'primary' | 'secondary' | 'outline'; + className: string; +} + +interface ImageProps { + productImage?: Image; + className: string; + loading?: 'lazy' | 'eager'; +} + +// ✅ Array item props +interface FeatureItemProps { + title?: string; + description?: string; + icon?: VectorArt; + className: string; +} +``` + +## Function Signatures + +### Component Functions + +```typescript +// ✅ Correct - explicit return type +const ProductCard: React.FC<ProductCardProps> = ({ + className, + id, + columns = 1, + layout = 'grid', + elementProps, + wix +}): React.JSX.Element => { + // Implementation + return <div>...</div>; +}; + +// ✅ Sub-component with explicit return +const Title: React.FC<TitleProps> = ({ + titleText = 'Default Title', + className +}): React.JSX.Element => ( + <h2 className={className}>{titleText}</h2> +); + +// ❌ Wrong - implicit return type +const BadComponent = (props: any) => { + return <div>...</div>; +}; +``` + +### Event Handlers + +```typescript +// ✅ Correct - explicit event types +const handleClick = (e: React.MouseEvent<HTMLButtonElement>): void => { + e.preventDefault(); + // Handle click logic +}; + +const handleChange = (e: React.ChangeEvent<HTMLInputElement>): void => { + setValue(e.target.value); +}; + +const handleSubmit = (e: React.FormEvent<HTMLFormElement>): void => { + e.preventDefault(); + // Handle form submission +}; + +// ✅ Custom event handlers +interface CustomHandlers { + onItemSelect?: (item: Item) => void; + onItemRemove?: (id: string) => void; + onStateChange?: (state: ComponentState) => void; +} +``` + +### Hook Usage + +```typescript +// ✅ Correct - explicit state types +const [selectedIndex, setSelectedIndex] = useState<number>(0); +const [items, setItems] = useState<Array<Item>>([]); +const [isLoading, setIsLoading] = useState<boolean>(false); +const [error, setError] = useState<string | null>(null); + +// ✅ Ref typing +const containerRef = useRef<HTMLDivElement>(null); +const inputRef = useRef<HTMLInputElement>(null); + +// ✅ Effect with proper dependencies +useEffect((): void => { + if (autoPlay && duration && !isLoading) { + const timer = setTimeout(() => { + setSelectedIndex(prev => (prev + 1) % items.length); + }, duration); + + return (): void => { + clearTimeout(timer); + }; + } +}, [autoPlay, duration, isLoading, items.length]); +``` + +## Type Guards and Narrowing + +### Null/Undefined Checks + +```typescript +// ✅ Correct - explicit null checks +const renderTitle = (elementProps?: ElementProps): React.JSX.Element | null => { + if (!elementProps?.title?.titleText) { + return null; + } + + return <h2>{elementProps.title.titleText}</h2>; +}; + +// ✅ Optional chaining with fallbacks +const getImageUrl = (image?: Image): string => { + return image?.url ?? '/default-image.jpg'; +}; + +// ✅ Array length checks +const renderItems = (items?: Array<Item>): React.JSX.Element => { + if (!items || items.length === 0) { + return <EmptyState />; + } + + return ( + <div> + {items.map((item, index) => { + if (!item?.id || !item?.title) { + return null; + } + return <ItemCard key={item.id} item={item} />; + })} + </div> + ); +}; +``` + +### Union Type Handling + +```typescript +// ✅ Correct - exhaustive union handling +type ButtonVariant = 'primary' | 'secondary' | 'outline'; + +const getButtonClasses = (variant: ButtonVariant): string => { + switch (variant) { + case 'primary': + return 'btn btn--primary'; + case 'secondary': + return 'btn btn--secondary'; + case 'outline': + return 'btn btn--outline'; + default: + // Exhaustive check with never + const _exhaustive: never = variant; + return _exhaustive; + } +}; + +// ✅ Layout type with proper handling +type LayoutType = 'grid' | 'list' | 'masonry'; + +const getLayoutClasses = (layout: LayoutType = 'grid'): string => { + const baseClass = 'product-grid'; + + switch (layout) { + case 'grid': + return `${baseClass} ${baseClass}--grid`; + case 'list': + return `${baseClass} ${baseClass}--list`; + case 'masonry': + return `${baseClass} ${baseClass}--masonry`; + default: + const _exhaustive: never = layout; + return _exhaustive; + } +}; +``` + +### Type Predicates + +```typescript +// ✅ Type predicate functions +const isValidImage = (image: unknown): image is Image => { + return ( + typeof image === 'object' && + image !== null && + 'url' in image && + typeof (image as Image).url === 'string' + ); +}; + +const isValidLink = (link: unknown): link is Link => { + return ( + typeof link === 'object' && + link !== null && + 'href' in link && + typeof (link as Link).href === 'string' + ); +}; + +// Usage with type narrowing +const renderImage = (image: unknown): React.JSX.Element | null => { + if (!isValidImage(image)) { + return null; + } + + // image is now typed as Image + return <img src={image.url} alt={image.alt || 'Image'} />; +}; +``` + +## Error Handling + +### Safe Property Access + +```typescript +// ✅ Correct - safe property access +const getNestedValue = ( + elementProps?: ElementProps +): string | undefined => { + return elementProps?.content?.elementProps?.title?.titleText; +}; + +// ✅ Safe array access +const getFirstItem = <T>(items?: Array<T>): T | undefined => { + return items?.[0]; +}; + +// ✅ Safe object access with defaults +const getConfigValue = ( + config?: Record<string, unknown>, + key: string, + defaultValue: string = '' +): string => { + const value = config?.[key]; + return typeof value === 'string' ? value : defaultValue; +}; +``` + +### Runtime Validation + +```typescript +// ✅ Runtime validation with type guards +const validateComponentProps = ( + props: unknown +): props is ProductCardProps => { + if (typeof props !== 'object' || props === null) { + return false; + } + + const p = props as Record<string, unknown>; + + return ( + typeof p.className === 'string' && + typeof p.id === 'string' + ); +}; + +// ✅ Safe parsing with error handling +const parseJsonSafely = <T>( + json: string, + fallback: T +): T => { + try { + const parsed = JSON.parse(json); + return parsed as T; + } catch { + return fallback; + } +}; +``` + +## Generic Types + +### Reusable Component Types + +```typescript +// ✅ Generic list component +interface ListProps<T> { + items?: Array<T>; + renderItem: (item: T, index: number) => React.JSX.Element; + keyExtractor: (item: T) => string; + className: string; + emptyMessage?: string; +} + +const List = <T,>({ + items = [], + renderItem, + keyExtractor, + className, + emptyMessage = 'No items found' +}: ListProps<T>): React.JSX.Element => { + if (items.length === 0) { + return <div className={`${className}__empty`}>{emptyMessage}</div>; + } + + return ( + <div className={className}> + {items.map((item, index) => ( + <div key={keyExtractor(item)} className={`${className}__item`}> + {renderItem(item, index)} + </div> + ))} + </div> + ); +}; + +// ✅ Generic data fetching hook +interface UseDataResult<T> { + data: T | null; + loading: boolean; + error: string | null; +} + +const useData = <T>( + fetcher: () => Promise<T>, + dependencies: Array<unknown> = [] +): UseDataResult<T> => { + const [data, setData] = useState<T | null>(null); + const [loading, setLoading] = useState<boolean>(true); + const [error, setError] = useState<string | null>(null); + + useEffect(() => { + let cancelled = false; + + const fetchData = async (): Promise<void> => { + try { + setLoading(true); + setError(null); + const result = await fetcher(); + + if (!cancelled) { + setData(result); + } + } catch (err) { + if (!cancelled) { + setError(err instanceof Error ? err.message : 'Unknown error'); + } + } finally { + if (!cancelled) { + setLoading(false); + } + } + }; + + fetchData(); + + return (): void => { + cancelled = true; + }; + }, dependencies); + + return { data, loading, error }; +}; +``` + +## Utility Types + +### Component-Specific Utilities + +```typescript +// ✅ Extract element props type +type ElementProps<T> = T extends { elementProps?: infer E } ? E : never; + +// ✅ Make properties required +type RequiredProps<T, K extends keyof T> = T & Required<Pick<T, K>>; + +// ✅ Component with required className +type ComponentWithClassName<T> = RequiredProps<T, 'className'>; + +// ✅ Extract data properties +type DataProps<T> = Omit<T, 'className' | 'id' | 'wix' | 'elementProps'>; + +// ✅ Element removal state helper +type RemovalState = Record<string, 'REMOVED'>; + +const isElementRemoved = ( + removalState: RemovalState | undefined, + elementKey: string +): boolean => { + return removalState?.[elementKey] === 'REMOVED'; +}; +``` + +## Common Patterns + +### Conditional Rendering with Types + +```typescript +// ✅ Type-safe conditional rendering +interface ConditionalProps { + condition?: boolean; + children: React.ReactNode; + fallback?: React.ReactNode; +} + +const Conditional: React.FC<ConditionalProps> = ({ + condition = false, + children, + fallback = null +}): React.JSX.Element | null => { + return condition ? <>{children}</> : <>{fallback}</>; +}; + +// Usage +<Conditional condition={!isElementRemoved(removalState, 'title')}> + <Title {...elementProps?.title} /> +</Conditional> +``` + +### Array Mapping with Safety + +```typescript +// ✅ Type-safe array mapping +const renderItems = <T extends { id: string }>( + items: Array<T> | undefined, + renderFn: (item: T) => React.JSX.Element +): Array<React.JSX.Element> => { + if (!items || items.length === 0) { + return []; + } + + return items + .filter((item): item is T => Boolean(item?.id)) + .map(renderFn); +}; +``` + +## Validation Checklist + +- [ ] All props interfaces use optional (`?`) for data properties +- [ ] Component functions have explicit return types +- [ ] Event handlers have proper event types +- [ ] useState calls have explicit type parameters +- [ ] useRef calls specify element types +- [ ] useEffect dependencies include all used values +- [ ] Union types handled exhaustively with never checks +- [ ] Optional chaining used for nested property access +- [ ] Array access checked for length before mapping +- [ ] No `any` types used anywhere +- [ ] No `@ts-ignore` or `@ts-expect-error` comments +- [ ] All imports have correct types +- [ ] Generic types used appropriately for reusable components diff --git a/CLI App - Calculator Form/.agents/skills/wix-cli-site-plugin/SKILL.md b/CLI App - Calculator Form/.agents/skills/wix-cli-site-plugin/SKILL.md new file mode 100644 index 0000000..c2da644 --- /dev/null +++ b/CLI App - Calculator Form/.agents/skills/wix-cli-site-plugin/SKILL.md @@ -0,0 +1,441 @@ +--- +name: wix-cli-site-plugin +description: Use when building interactive components for predefined slots in Wix business solutions. Triggers include site plugin, slot, Wix app integration, plugin explorer, business solution extension. +compatibility: Requires Wix CLI development environment. +--- + +# Wix Site Plugin Builder + +Creates site plugin extensions for Wix CLI applications. Site plugins are custom elements that integrate into predefined **slots** within Wix business solutions (like Wix Stores, Wix Bookings, Wix eCommerce), extending their functionality and user experience. + +Site owners can place site plugins into UI slots using the plugin explorer in Wix editors. + +## Quick Start Checklist + +Follow these steps in order when creating a site plugin: + +1. [ ] Create plugin folder: `src/extensions/site/plugins/<plugin-name>/` +2. [ ] Create `<plugin-name>.tsx` extending `HTMLElement` with `observedAttributes` +3. [ ] Create `<plugin-name>.panel.tsx` with WDS components and `widget.getProp/setProp` +4. [ ] Create `<plugin-name>.extension.ts` with `extensions.sitePlugin()` and unique UUID +5. [ ] Update `src/extensions.ts` to import and use the new extension + +## Architecture + +Site plugins consist of **three required files**: + +### 1. Plugin Component (`<plugin-name>.tsx`) + +Custom element component that renders in the slot using native HTMLElement: + +- Extend `HTMLElement` class +- Define `observedAttributes` for reactive properties +- Implement `connectedCallback()` and `attributeChangedCallback()` for rendering +- Use inline styles via template strings +- Attributes use **kebab-case** (e.g., `display-name`) + +### 2. Settings Panel (`<plugin-name>.panel.tsx`) + +Settings panel shown in the Wix Editor sidebar: + +- Uses Wix Design System (`@wix/design-system`) components — see [wds-docs](../wds-docs/SKILL.md) for component reference +- Manages plugin properties via `@wix/editor` widget API +- Loads initial values with `widget.getProp('kebab-case-name')` +- Updates properties with `widget.setProp('kebab-case-name', value)` +- Widget properties are bound to custom element attributes — any property change automatically updates the corresponding attribute +- Wrapped in `WixDesignSystemProvider > SidePanel > SidePanel.Content` + +### 3. Extension Configuration (`<plugin-name>.extension.ts`) + +Defines the plugin's placement configuration: + +- Specifies which slots the plugin can be added to +- Configures auto-add behavior on app installation +- Sets the tag name and file paths + +## Plugin Component Pattern + +Site plugins use native `HTMLElement` custom elements: + +```typescript +// my-site-plugin.tsx +class MyElement extends HTMLElement { + static get observedAttributes() { + return ['display-name']; + } + + constructor() { + super(); + } + + connectedCallback() { + this.render(); + } + + attributeChangedCallback() { + this.render(); + } + + render() { + const displayName = this.getAttribute('display-name') || "Your Plugin's Title"; + + this.innerHTML = ` + <div style="font-size: 16px; padding: 16px; border: 1px solid #ccc; border-radius: 8px; margin: 16px;"> + <h2>${displayName}</h2> + <hr /> + <p> + This is a Site Plugin generated by Wix CLI.<br /> + Edit your element's code to change this text. + </p> + </div> + `; + } +} + +export default MyElement; +``` + +**Key Points:** + +- Extend `HTMLElement` class directly +- Define `observedAttributes` static getter to list reactive attributes +- Attributes use **kebab-case** (e.g., `display-name`, `bg-color`) +- Implement `connectedCallback()` for initial render +- Implement `attributeChangedCallback()` to re-render when attributes change +- Use inline styles via template strings +- Use `this.getAttribute('attribute-name')` to read attribute values +- Wix handles `define()` for you — do NOT call `customElements.define()` in your code + +## Settings Panel Pattern + +```typescript +// my-site-plugin.panel.tsx +import React, { type FC, useState, useEffect, useCallback } from 'react'; +import { widget } from '@wix/editor'; +import { + SidePanel, + WixDesignSystemProvider, + Input, + FormField, +} from '@wix/design-system'; +import '@wix/design-system/styles.global.css'; + +const Panel: FC = () => { + const [displayName, setDisplayName] = useState<string>(''); + + useEffect(() => { + widget.getProp('display-name') + .then(displayName => setDisplayName(displayName || "Your Plugin's Title")) + .catch(error => console.error('Failed to fetch display-name:', error)); + }, [setDisplayName]); + + const handleDisplayNameChange = useCallback((event: React.ChangeEvent<HTMLInputElement>) => { + const newDisplayName = event.target.value; + setDisplayName(newDisplayName); + widget.setProp('display-name', newDisplayName); + }, [setDisplayName]); + + return ( + <WixDesignSystemProvider> + <SidePanel width="300" height="100vh"> + <SidePanel.Content noPadding stretchVertically> + <SidePanel.Field> + <FormField label="Display Name"> + <Input + type="text" + value={displayName} + onChange={handleDisplayNameChange} + aria-label="Display Name" + /> + </FormField> + </SidePanel.Field> + </SidePanel.Content> + </SidePanel> + </WixDesignSystemProvider> + ); +}; + +export default Panel; +``` + +**Key Points:** + +- Prop names in `widget.getProp()` and `widget.setProp()` use **kebab-case** (e.g., `"display-name"`) +- Always update both local state AND widget prop in onChange handlers +- Widget properties are bound to custom element attributes — changes automatically update the corresponding attribute +- Wrap content in `WixDesignSystemProvider > SidePanel > SidePanel.Content` +- Use WDS components from `@wix/design-system` +- Import `@wix/design-system/styles.global.css` for styles +- Include `aria-label` for accessibility + +## Color & Font Picker Fields + +Site plugin settings panels can use `inputs.selectColor()` and `inputs.selectFont()` from `@wix/editor` to open the native Wix Editor color and font picker dialogs. + +### ColorPickerField + +Opens the Wix color picker with theme colors, gradients, and more — **NOT** a basic HTML `<input type="color">`. + +```typescript +import React, { type FC } from 'react'; +import { inputs } from '@wix/editor'; +import { FormField, Box, FillPreview, SidePanel } from '@wix/design-system'; + +interface ColorPickerFieldProps { + label: string; + value: string; + onChange: (value: string) => void; +} + +export const ColorPickerField: FC<ColorPickerFieldProps> = ({ + label, + value, + onChange, +}) => ( + <SidePanel.Field> + <FormField label={label}> + <Box width="30px" height="30px"> + <FillPreview + fill={value} + onClick={() => inputs.selectColor(value, { onChange: (val) => { if (val) onChange(val); } })} + /> + </Box> + </FormField> + </SidePanel.Field> +); +``` + +### FontPickerField + +Opens the Wix font picker with font family, size, bold, italic, and other typography features. + +```typescript +import React, { type FC } from 'react'; +import { inputs } from '@wix/editor'; +import { FormField, Button, Text, SidePanel } from '@wix/design-system'; + +interface FontValue { + font: string; + textDecoration: string; +} + +interface FontPickerFieldProps { + label: string; + value: FontValue; + onChange: (value: FontValue) => void; +} + +export const FontPickerField: FC<FontPickerFieldProps> = ({ + label, + value, + onChange, +}) => ( + <SidePanel.Field> + <FormField label={label}> + <Button + size="small" + priority="secondary" + onClick={() => inputs.selectFont(value, { onChange: (val) => onChange({ font: val.font, textDecoration: val.textDecoration || "" }) })} + fullWidth + > + <Text size="small" ellipsis>Change Font</Text> + </Button> + </FormField> + </SidePanel.Field> +); +``` + +**Important:** +- Always use `inputs.selectColor()` from `@wix/editor` with `FillPreview` — do NOT use `<Input type="color">` +- Always use `inputs.selectFont()` from `@wix/editor` with the callback pattern `inputs.selectFont(value, { onChange })` +- Import `inputs` from `@wix/editor` (not from `@wix/sdk`) + +## Attribute Naming Convention + +Site plugins use **kebab-case** consistently for HTML attributes: + +| File | Convention | Example | +| --------------------------------- | ---------- | ---------------------------------- | +| `<plugin>.tsx` (getAttribute) | kebab-case | `this.getAttribute('display-name')` | +| `<plugin>.tsx` (observedAttributes) | kebab-case | `['display-name', 'bg-color']` | +| `<plugin>.panel.tsx` (widget API) | kebab-case | `widget.getProp('display-name')` | + +## Output Structure + +Site plugins live under `src/extensions/site/plugins`. Each plugin has its own folder with files named after the plugin. + +``` +src/extensions/site/plugins/ +└── {plugin-name}/ + ├── {plugin-name}.tsx # Main plugin component (HTMLElement) + ├── {plugin-name}.panel.tsx # Settings panel component + └── {plugin-name}.extension.ts # Extension registration +public/ +└── {plugin-name}-logo.svg # Plugin logo (optional) +``` + +## References + +| Topic | Reference | +| --- | --- | +| Complete Examples | [EXAMPLES.md](references/EXAMPLES.md) | +| Slots (App IDs, multiple placements, finding slots) | [SLOTS.md](references/SLOTS.md) | +| WDS Components | [wds-docs](../wds-docs/SKILL.md) | + +## Available Slots + +Site plugins integrate into predefined slots in Wix business solutions. Each slot is identified by: + +- **appDefinitionId**: The ID of the Wix app (e.g., Stores, Bookings) +- **widgetId**: The ID of the page containing the slot +- **slotId**: The specific slot identifier + +Common placement areas include product pages (Wix Stores), checkout and side cart (Wix eCommerce), booking pages (Wix Bookings), service pages, event pages, and blog post pages. + +For supported pages, common Wix App IDs, and how to find slot IDs, see [SLOTS.md](./references/SLOTS.md). + +## Extension Registration + +**Extension registration is MANDATORY and has TWO required steps.** + +### Step 1: Create Plugin-Specific Extension File + +Each site plugin requires an extension file in its folder: + +```typescript +// my-site-plugin.extension.ts +import { extensions } from '@wix/astro/builders'; + +export default extensions.sitePlugin({ + id: '{{GENERATE_UUID}}', + name: 'My Site Plugin', + marketData: { + name: 'My Site Plugin', + description: 'Marketing Description', + logoUrl: '{{BASE_URL}}/my-site-plugin-logo.svg', + }, + placements: [{ + appDefinitionId: 'a0c68605-c2e7-4c8d-9ea1-767f9770e087', + widgetId: '6a25b678-53ec-4b37-a190-65fcd1ca1a63', + slotId: 'product-page-details-6', + }], + installation: { autoAdd: true }, + tagName: 'my-site-plugin', + element: './extensions/site/plugins/my-site-plugin/my-site-plugin.tsx', + settings: './extensions/site/plugins/my-site-plugin/my-site-plugin.panel.tsx', +}); +``` + +**CRITICAL: UUID Generation** + +The `id` must be a unique, static UUID v4 string. Generate a fresh UUID for each extension - do NOT use `randomUUID()` or copy UUIDs from examples. Replace `{{GENERATE_UUID}}` with a freshly generated UUID like `"95a28afd-7df1-4e09-9ec1-ce710b0389a0"`. + +| Property | Type | Description | +| -------------------------- | ------- | --------------------------------------------------------------- | +| `id` | string | Unique static UUID v4 (generate fresh) | +| `name` | string | Internal name for the plugin | +| `marketData.name` | string | Display name in plugin explorer and app dashboard | +| `marketData.description` | string | Description shown in plugin explorer and app dashboard | +| `marketData.logoUrl` | string | Path to logo file (`{{BASE_URL}}` resolves to public folder) | +| `placements` | array | Array of slot placements where plugin can be added | +| `placements.appDefinitionId` | string | ID of the Wix app containing the slot | +| `placements.widgetId` | string | ID of the page containing the slot | +| `placements.slotId` | string | ID of the specific slot | +| `installation.autoAdd` | boolean | Whether to auto-add plugin to slots on app installation | +| `tagName` | string | HTML custom element tag (kebab-case, must contain a hyphen) | +| `element` | string | Relative path to plugin component | +| `settings` | string | Relative path to settings panel component | + +### Step 2: Register in Main Extensions File + +**CRITICAL:** After creating the plugin-specific extension file, you MUST read [wix-cli-extension-registration](../wix-cli-extension-registration/SKILL.md) and follow the "App Registration" section to update `src/extensions.ts`. + +**Without completing Step 2, the site plugin will not be available in the plugin explorer.** + +## Checkout Plugins + +If you are building a plugin for the **checkout page**, it may not support automatic addition upon installation. You must create a dashboard page to provide users with a way to add the plugin to their site. See [EXAMPLES.md](references/EXAMPLES.md) for the dashboard page pattern. + +## Examples + +For complete examples with all three required files (plugin component, settings panel, extension configuration), see [EXAMPLES.md](references/EXAMPLES.md). + +**Example use cases:** + +- **Best Seller Badge** - Customizable badge on product pages with text and color settings +- **Booking Confirmation** - Custom confirmation message for booking pages +- **Product Reviews Summary** - Star rating and review count display +- **Data-Driven Plugin** - Plugin with Wix Data API integration and editor environment handling + +## Best Practices + +### Implementation Guidelines + +- **Use inline styles** - CSS imports are not supported in custom elements +- **Handle editor environment** - Show placeholders when in editor mode for data-dependent plugins +- **Do not call `define()`** - Wix handles `customElements.define()` for you automatically +- **Validate all input** - Check required props are present +- **Follow naming conventions** - kebab-case for all attributes and widget API +- **Keep plugins focused** - Each plugin should do one thing well +- **Test in multiple slots** - If supporting multiple placements, test each one +- **Support both Stores versions** - Include placements for both old and new Wix Stores product pages for maximum compatibility + +### Editor Sandboxing + +Site plugins are sandboxed when rendered in the editor. This means they're treated as if they come from a different domain, which impacts access to browser storage APIs. + +**Restricted APIs in the editor:** +- `localStorage` and `sessionStorage` (Web Storage API) +- `document.cookie` (Cookie Store API) +- IndexedDB API +- Cache API + +**How to handle sandboxing:** + +Use the `viewMode()` function from `@wix/site-window` to check the current mode before accessing restricted APIs: + +```typescript +import { window as wixWindow } from '@wix/site-window'; + +const viewMode = await wixWindow.viewMode(); + +if (viewMode === 'Site') { + const item = localStorage.getItem('myKey'); +} else { + // Mock storage or modify API usage for editor mode +} +``` + +### Using Wix SDK Modules in Site Plugins + +Site plugins can import and use Wix SDK modules directly — you do NOT need `createClient()`. The Wix runtime provides the client context automatically. + +```typescript +// ✅ CORRECT — Import SDK modules directly +import { items } from "@wix/data"; +import { currentCart } from "@wix/ecom"; +import { products } from "@wix/stores"; + +class MyPlugin extends HTMLElement { + async loadData() { + // Call SDK methods directly — no createClient needed + const result = await items.query("MyCollection").find(); + const cart = await currentCart.getCurrentCart(); + const productList = await products.queryProducts().limit(10).find(); + } +} +``` + +```typescript +// ❌ WRONG — Do NOT use createClient in site plugins +import { createClient } from "@wix/sdk"; +const wixClient = createClient({ modules: { items, products } }); +await wixClient.items.query(...); // Wrong — API surface differs through client +``` + +### Performance Considerations + +- Keep bundle size small - plugins load on user-facing pages +- Avoid heavy computations on initial render +- Lazy load data when possible +- Use efficient re-rendering patterns diff --git a/CLI App - Calculator Form/.agents/skills/wix-cli-site-plugin/references/EXAMPLES.md b/CLI App - Calculator Form/.agents/skills/wix-cli-site-plugin/references/EXAMPLES.md new file mode 100644 index 0000000..74bfcca --- /dev/null +++ b/CLI App - Calculator Form/.agents/skills/wix-cli-site-plugin/references/EXAMPLES.md @@ -0,0 +1,311 @@ +# Site Plugin Examples + +Complete examples showing all required files for site plugins. + +## Best Seller Badge Plugin + +A customizable badge that displays on product pages with configurable text and colors. + +### Plugin Component (`best-seller-badge.tsx`) + +```typescript +class BestSellerBadge extends HTMLElement { + static get observedAttributes() { + return ['badge-text', 'bg-color', 'text-color']; + } + + constructor() { + super(); + } + + connectedCallback() { + this.render(); + } + + attributeChangedCallback() { + this.render(); + } + + render() { + const badgeText = this.getAttribute('badge-text') || 'Best Seller'; + const bgColor = this.getAttribute('bg-color') || '#ff6b35'; + const textColor = this.getAttribute('text-color') || '#ffffff'; + + this.innerHTML = ` + <span style=" + display: inline-block; + padding: 8px 16px; + background-color: ${bgColor}; + color: ${textColor}; + font-weight: bold; + border-radius: 4px; + font-size: 14px; + text-transform: uppercase; + letter-spacing: 1px; + ">${badgeText}</span> + `; + } +} + +export default BestSellerBadge; +``` + +### Settings Panel (`best-seller-badge.panel.tsx`) + +```typescript +import React, { type FC, useState, useEffect, useCallback } from 'react'; +import { widget, inputs } from '@wix/editor'; +import { + SidePanel, + WixDesignSystemProvider, + Input, + FormField, + Box, + FillPreview, +} from '@wix/design-system'; +import '@wix/design-system/styles.global.css'; + +const Panel: FC = () => { + const [badgeText, setBadgeText] = useState<string>(''); + const [bgColor, setBgColor] = useState<string>('#ff6b35'); + const [textColor, setTextColor] = useState<string>('#ffffff'); + + useEffect(() => { + Promise.all([ + widget.getProp('badge-text'), + widget.getProp('bg-color'), + widget.getProp('text-color'), + ]) + .then(([text, bg, color]) => { + setBadgeText(text || 'Best Seller'); + setBgColor(bg || '#ff6b35'); + setTextColor(color || '#ffffff'); + }) + .catch(error => console.error('Failed to fetch props:', error)); + }, []); + + const handleTextChange = useCallback((event: React.ChangeEvent<HTMLInputElement>) => { + const newText = event.target.value; + setBadgeText(newText); + widget.setProp('badge-text', newText); + }, []); + + const handleBgColorChange = useCallback((value: string) => { + setBgColor(value); + widget.setProp('bg-color', value); + }, []); + + const handleTextColorChange = useCallback((value: string) => { + setTextColor(value); + widget.setProp('text-color', value); + }, []); + + return ( + <WixDesignSystemProvider> + <SidePanel width="300" height="100vh"> + <SidePanel.Content noPadding stretchVertically> + <SidePanel.Field> + <FormField label="Badge Text"> + <Input + type="text" + value={badgeText} + onChange={handleTextChange} + aria-label="Badge Text" + /> + </FormField> + </SidePanel.Field> + <SidePanel.Field> + <FormField label="Background Color"> + <Box width="30px" height="30px"> + <FillPreview + fill={bgColor} + onClick={() => inputs.selectColor(bgColor, { onChange: (val) => { if (val) handleBgColorChange(val); } })} + /> + </Box> + </FormField> + </SidePanel.Field> + <SidePanel.Field> + <FormField label="Text Color"> + <Box width="30px" height="30px"> + <FillPreview + fill={textColor} + onClick={() => inputs.selectColor(textColor, { onChange: (val) => { if (val) handleTextColorChange(val); } })} + /> + </Box> + </FormField> + </SidePanel.Field> + </SidePanel.Content> + </SidePanel> + </WixDesignSystemProvider> + ); +}; + +export default Panel; +``` + +### Extension Configuration (`best-seller-badge.extension.ts`) + +```typescript +import { extensions } from '@wix/astro/builders'; + +export default extensions.sitePlugin({ + id: 'f8e2a1b3-c4d5-6789-abcd-ef0123456789', + name: 'Best Seller Badge', + marketData: { + name: 'Best Seller Badge', + description: 'Display a customizable badge on product pages', + logoUrl: '{{BASE_URL}}/best-seller-badge-logo.svg', + }, + placements: [ + { + appDefinitionId: '1380b703-ce81-ff05-f115-39571d94dfcd', + widgetId: '13a94f09-2766-3c40-4a32-8edb5acdd8bc', + slotId: 'product-page-details-2', + }, + { + appDefinitionId: 'a0c68605-c2e7-4c8d-9ea1-767f9770e087', + widgetId: '6a25b678-53ec-4b37-a190-65fcd1ca1a63', + slotId: 'product-page-details-2', + }, + ], + installation: { autoAdd: true }, + tagName: 'best-seller-badge', + element: './extensions/site/plugins/best-seller-badge/best-seller-badge.tsx', + settings: './extensions/site/plugins/best-seller-badge/best-seller-badge.panel.tsx', +}); +``` + +## Dashboard Page for Plugin Management + +For plugins that require back-office management (especially checkout and side cart plugins that may not support auto-add), create a dashboard page. + +> **Note:** The `placement` option in `addSitePlugin()` is optional. If omitted, the plugin is placed in the first available slot based on the priority order configured in the plugin's installation settings in your app's dashboard. + +```typescript +// src/dashboard/pages/plugin-settings/page.tsx +import { dashboard } from "@wix/dashboard"; +import { Page, WixDesignSystemProvider, Card, FormField, Input, Button } from "@wix/design-system"; + +export default function PluginSettingsPage() { + const handleAddToSlot = async () => { + const pluginId = "your-plugin-id"; + const pluginPlacement = { + appDefinitionId: "host-app-definition-id", + widgetId: "host-widget-id", + slotId: "target-slot-id", + }; + + await dashboard.addSitePlugin(pluginId, { + placement: pluginPlacement, + }); + dashboard.showToast({ message: "Plugin added!", type: "success" }); + }; + + return ( + <WixDesignSystemProvider> + <Page> + <Page.Header title="Plugin Settings" /> + <Page.Content> + <Card> + <Card.Header title="Manage Your Plugin" /> + <Card.Content> + <Button onClick={handleAddToSlot}>Add Plugin to Slot</Button> + </Card.Content> + </Card> + </Page.Content> + </Page> + </WixDesignSystemProvider> + ); +} +``` + +## Wix Data API Integration + +When using Wix Data API in plugins, handle the Wix Editor environment: + +```typescript +import { items } from "@wix/data"; +import { window as wixWindow } from "@wix/site-window"; + +class DataPlugin extends HTMLElement { + static get observedAttributes() { + return ['collection-id']; + } + + constructor() { + super(); + } + + connectedCallback() { + this.render(); + this.loadData(); + } + + attributeChangedCallback() { + this.loadData(); + } + + render() { + this.innerHTML = ` + <div style="padding: 16px; border: 1px solid #ccc; border-radius: 8px;"> + <p>Loading...</p> + </div> + `; + } + + async loadData() { + const collectionId = this.getAttribute('collection-id'); + if (!collectionId) return; + + try { + const viewMode = await wixWindow.viewMode(); + + if (viewMode === 'Editor') { + this.innerHTML = ` + <div style="padding: 20px; border: 2px dashed #ccc;"> + <p>Plugin will display data on the live site</p> + <p>Collection: ${collectionId}</p> + </div> + `; + return; + } + + const results = await items.query(collectionId).limit(10).find(); + this.innerHTML = ` + <div style="padding: 16px;"> + ${results.items.map(item => `<div>${item.title}</div>`).join('')} + </div> + `; + } catch (error) { + console.error('Failed to load data:', error); + this.innerHTML = `<div style="color: red;">Error loading data</div>`; + } + } +} + +export default DataPlugin; +``` + +## Example Use Cases + +### Booking Confirmation Message Plugin + +**Request:** "Create a plugin for booking pages that shows a custom confirmation message" + +**Output:** + +- Plugin with configurable title, message, and styling +- Settings panel with text inputs and color pickers +- Responsive layout that fits the booking page slot + +### Product Reviews Summary Plugin + +**Request:** "Create a plugin that displays a reviews summary on product pages" + +**Output:** + +- Plugin showing star rating and review count +- Configurable display options (show count, show average) +- Settings panel for styling customization +- Integration with slot on product page +- Include placements for both old and new Wix Stores product page versions diff --git a/CLI App - Calculator Form/.agents/skills/wix-cli-site-plugin/references/SLOTS.md b/CLI App - Calculator Form/.agents/skills/wix-cli-site-plugin/references/SLOTS.md new file mode 100644 index 0000000..5212dcf --- /dev/null +++ b/CLI App - Calculator Form/.agents/skills/wix-cli-site-plugin/references/SLOTS.md @@ -0,0 +1,263 @@ +# Site Plugin Slots Reference + +This reference provides detailed information about all available slots for site plugins across Wix business solutions. + +## Supported Pages and Slots + +| Wix App | Supported Pages/Widgets | +| -------------- | ------------------------------------------------------------ | +| Wix Stores | Product Page (new and old versions), Category Page, Shop Page, Gallery Widget | +| Wix eCommerce | Checkout Page, Side Cart | +| Wix Bookings | Service Page | +| Wix Events | Event Details Page | +| Wix Blog | Post Page | + +## Common Wix App IDs + +| Wix App | App Definition ID | +| ---------------------- | -------------------------------------- | +| Wix Stores (Old) | `1380b703-ce81-ff05-f115-39571d94dfcd` | +| Wix Stores (New) | `a0c68605-c2e7-4c8d-9ea1-767f9770e087` | +| Wix Bookings | `13d21c63-b5ec-5912-8397-c3a5ddb27a97` | +| Wix Events | `140603ad-af8d-84a5-2c80-a0f60cb47351` | +| Wix Blog | `14bcded7-0066-7c35-14d7-466cb3f09103` | +| Wix Restaurants | `13e8d036-5516-6104-b456-c8466db39542` | + +--- + +## Wix Stores Slots + +### Product Page (New Version) + +| Property | Value | +| ----------------- | ---------------------------------------- | +| `appDefinitionId` | `a0c68605-c2e7-4c8d-9ea1-767f9770e087` | +| `widgetId` | `6a25b678-53ec-4b37-a190-65fcd1ca1a63` | + +**Available Slot IDs:** +- `product-page-media-1` +- `product-page-details-2` + +**Note:** If using the `product-page-media-1` slot, it may overlap with the thumbnail images on the left side in desktop view. Consider offering settings in your app to control the left padding. ([Wix docs reference](https://dev.wix.com/docs/build-apps/develop-your-app/extensions/site-extensions/site-plugins/supported-wix-app-pages/wix-stores/wix-stores-product-page)) + +**Plugin API Properties:** +- `productId` (string) - The ID of the product on the product page +- `selectedVariantId` (string) - The ID of the selected product variant. Only available after the site visitor picks all required product choices. Until all required choices are selected, this is `undefined` +- `selectedChoices` (object) - An object containing all choices the site visitor picks. Each key is an option name and each value is the selected option (e.g., `{ color: "green", size: "large" }`) +- `quantity` (number) - The number of product items the site visitor wants to buy +- `customText` (string[]) - An array of text values entered by the site visitor in custom text fields (e.g., personalization). Each entry corresponds to a different custom text field on the product page + +### Product Page (Old Version) + +| Property | Value | +| ----------------- | ---------------------------------------- | +| `appDefinitionId` | `1380b703-ce81-ff05-f115-39571d94dfcd` | +| `widgetId` | `13a94f09-2766-3c40-4a32-8edb5acdd8bc` | + +**Available Slot IDs:** +- `product-page-details-2` +- Additional slots vary by layout (Classic, Simple, Sleek, Spotlight, Stunning) + +**Note:** Check which Wix Stores version is installed before building +plugins, as slots differ between versions. Your app should include +placements for both versions for maximum compatibility. + +**Plugin API Properties:** Same as New Version above. + +### Category Page + +| Property | Value | +| ----------------- | ---------------------------------------- | +| `appDefinitionId` | `1380b703-ce81-ff05-f115-39571d94dfcd` | +| `widgetId` | `bda15dc1-816d-4ff3-8dcb-1172d5343cce` | + +**Plugin API Properties:** +- `categoryId` (string) - The ID of the category + +### Shop Page + +| Property | Value | +| ----------------- | ---------------------------------------- | +| `appDefinitionId` | `1380b703-ce81-ff05-f115-39571d94dfcd` | +| `widgetId` | `1380bba0-253e-a800-a235-88821cf3f8a4` | + +**Plugin API Properties:** +- `categoryId` (string) - The category ID + +### Gallery Widget + +| Property | Value | +| ----------------- | ---------------------------------------- | +| `appDefinitionId` | `1380b703-ce81-ff05-f115-39571d94dfcd` | +| `widgetId` | `13afb094-84f9-739f-44fd-78d036adb028` | + +**Plugin API Properties:** +- `categoryId` (string) - The category ID + +**Note:** When selecting slots, use the same slot across Shop page, Gallery widget, and Category page to ensure compatibility across different Wix site setups. + +--- + +## Wix eCommerce Slots + +### Checkout Page + +| Property | Value | +| ----------------- | ---------------------------------------- | +| `appDefinitionId` | `1380b703-ce81-ff05-f115-39571d94dfcd` | +| `widgetId` | `14fd5970-8072-c276-1246-058b79e70c1a` | + +**Available Slot IDs:** +- `checkout:header` +- `checkout:top` +- `checkout:steps:before` +- `checkout:delivery-step:options:after` +- `checkout:policies:after-1` +- `checkout:summary:before` +- `checkout:summary:lineItems:after` +- `checkout:summary:lineItems:after2` +- `checkout:summary:totalsBreakdown:before` +- `checkout:summary:after` + +**Note:** Some checkout plugins may not support automatic addition upon installation. Create a dashboard page to manage your site plugin. + +**Checkout Plugin API Properties:** +- `checkoutId` (string) - ID of the current checkout process +- `stepId` (string) - Current step: `contact-details`, `delivery-method`, `payment-and-billing`, or `place-order` +- `checkoutUpdatedDate` (string) - When checkout was last updated + +**Checkout Plugin API Functions:** +- `onRefreshCheckout(callback: () => void)` - An event handler that accepts a callback function invoked whenever the checkout needs to be refreshed + +**Note:** The `checkout:delivery-step:options:after` slot uses a **different API** — see Delivery Step Options Slot API below. + +#### Delivery Step Options Slot API + +The `checkout:delivery-step:options:after` slot has its own API that is different from the other checkout slots. + +**Properties:** +- `checkoutId` (string) - ID of the current checkout process +- `checkoutUpdatedDate` (string) - When checkout was last updated +- `selectedDeliveryOptionCarrierId` (string) - The ID of the carrier for the selected delivery option +- `selectedDeliveryOptionId` (string) - The ID of the selected delivery option +- `deliveryStepState` (string) - The current state of the delivery step. Possible values: `open` or `summary` + +**Functions:** +- `onRefreshCheckout(callback: () => Promise)` - Event handler invoked whenever the checkout needs to be refreshed +- `disableContinueButton(callback: (isDisabled: boolean) => void)` - Event handler to control the checkout's continue button. Call with `true` to disable or `false` to enable + +### Side Cart + +| Property | Value | +| ----------------- | ---------------------------------------- | +| `appDefinitionId` | `1380b703-ce81-ff05-f115-39571d94dfcd` | +| `widgetId` | `49dbb2d9-d9e5-4605-a147-e926605bf164` | + +**Available Slot IDs:** +- `side-cart:header:after-1` +- `side-cart:lineItems:after-1` +- `side-cart:customer-input:after-1` +- `side-cart:footer:actions:before-1` +- `side-cart:footer:actions:after-1` + +**Note:** Some side cart plugins may not support automatic addition upon installation. Create a dashboard page to manage your site plugin. + +**Design Guidelines:** + +The Side Cart uses a `4px` baseline grid. Don't add extra spacing around your plugin — the slot handles spacing automatically. + +| Slot | Recommended Height | Max Height | +| ------------------------------------- | ------------------ | ---------- | +| `side-cart:header:after-1` | `30px` | `70px` | +| `side-cart:lineItems:after-1` | `50px` | `150px` | +| `side-cart:customer-input:after-1` | `24px` | `150px` | +| `side-cart:footer:actions:before-1` | `50px` | `70px` | +| `side-cart:footer:actions:after-1` | `50px` | `70px` | + +--- + +## Wix Blog Slots + +### Post Page + +| Property | Value | +| ----------------- | ---------------------------------------- | +| `appDefinitionId` | `14bcded7-0066-7c35-14d7-466cb3f09103` | +| `widgetId` | `211b5287-14e2-4690-bb71-525908938c81` | + +**Available Slot IDs:** +- `above-header` +- `above-content-1` +- `above-content-2` +- `below-content-1` +- `below-content-2` +- `page-bottom-1` +- `page-bottom-2` +- `page-bottom-3` + +**Plugin API Properties:** +- `postId` (string) - The ID of the current post + +--- + +## Wix Bookings Slots + +### Service Page + +| Property | Value | +| ----------------- | ---------------------------------------- | +| `appDefinitionId` | `13d21c63-b5ec-5912-8397-c3a5ddb27a97` | +| `widgetId` | `a91a0543-d4bd-4e6b-b315-9410aa27bcde` | +| `slotId` | `slot1` | + +The Service Page can host a single plugin that users are free to reposition within the page by reordering the Service Page sections. + +**Plugin API Properties:** +- `bookingsServiceId` (string) - The ID of the Wix Bookings service currently applied on the plugin's host + +--- + +## Wix Events Slots + +### Event Details Page + +| Property | Value | +| ----------------- | ---------------------------------------- | +| `appDefinitionId` | `140603ad-af8d-84a5-2c80-a0f60cb47351` | +| `widgetId` | `14d2abc2-5350-6322-487d-8c16ff833c8a` | + +**Available Slot IDs:** +- `header` +- `details` + +**Plugin API Properties:** +- `eventId` (string) - The ID of the event currently applied on the plugin's host + +--- + +## Multiple Placements + +You can configure a single plugin to appear in multiple slots: + +```typescript +placements: [ + { + appDefinitionId: '1380b703-ce81-ff05-f115-39571d94dfcd', + widgetId: '13a94f09-2766-3c40-4a32-8edb5acdd8bc', + slotId: 'product-page-details-2', + }, + { + appDefinitionId: 'a0c68605-c2e7-4c8d-9ea1-767f9770e087', + widgetId: '6a25b678-53ec-4b37-a190-65fcd1ca1a63', + slotId: 'product-page-details-2', + }, +] +``` + +**Note:** If you have multiple placements for slots on a single page, the plugin will be added to the first available slot according to the order you defined. If that slot is occupied, it will be placed in the next available slot. If there are no available slots, it will not be placed. Users may manually move the plugin to their desired location in the editor. + +## Slot Limitations + +- Each slot has specific size constraints defined by the host app +- Some slots may only be available in certain editor types (Wix Editor, Editor X, Wix Studio) +- Multiple plugins can occupy the same slot, displayed next to each other and ordered by creation date diff --git a/CLI App - Calculator Form/.agents/skills/wix-cli-site-widget/SKILL.md b/CLI App - Calculator Form/.agents/skills/wix-cli-site-widget/SKILL.md new file mode 100644 index 0000000..cbc6671 --- /dev/null +++ b/CLI App - Calculator Form/.agents/skills/wix-cli-site-widget/SKILL.md @@ -0,0 +1,599 @@ +--- +name: wix-cli-site-widget +description: Use when building interactive widgets, custom data displays, or configurable site components with settings panels. Triggers include widget, custom element, interactive component, editor component, configurable widget, web component. +compatibility: Requires Wix CLI development environment. +--- + +# Wix Site Widget Builder + +Creates custom element widget extensions for Wix CLI applications. Site widgets are React components converted to web components that appear in the Wix Editor, allowing site owners to add interactive, configurable widgets to their pages with a built-in settings panel. + +## Quick Start Checklist + +Follow these steps in order when creating a site widget: + +1. [ ] Create widget folder: `src/site/widgets/custom-elements/<widget-name>/` +2. [ ] Create `widget.tsx` with React component and `reactToWebComponent` conversion +3. [ ] Create `panel.tsx` with WDS components and `widget.getProp/setProp` +4. [ ] Create `extensions.ts` with `extensions.customElement()` and unique UUID +5. [ ] Update `src/extensions.ts` to import and use the new extension + +## Architecture + +Site widgets consist of **two required files**: + +### 1. Widget Component (`widget.tsx`) + +React component converted to a web component using `react-to-webcomponent`: + +- Define Props interface with configurable properties (camelCase) +- Create a React functional component that renders the widget UI +- Convert to web component with props mapping +- Use inline styles (no CSS imports) +- Handle Wix Editor environment when using Wix Data API + +### 2. Settings Panel (`panel.tsx`) + +Settings panel shown in the Wix Editor sidebar: + +- Uses Wix Design System components (see [references/SETTINGS_PANEL.md](references/SETTINGS_PANEL.md)) +- Manages widget properties via `@wix/editor` widget API +- Loads initial values with `widget.getProp('kebab-case-name')` +- Updates properties with `widget.setProp('kebab-case-name', value)` +- Wrapped in `WixDesignSystemProvider > SidePanel > SidePanel.Content` +- For color pickers, use `inputs.selectColor()` from `@wix/editor` with `FillPreview` — NOT `<Input type="color">` +- For font pickers, use `inputs.selectFont()` from `@wix/editor` with a `Button` — NOT a text Input + +## Widget Component Pattern + +```typescript +import React, { type FC, useState, useEffect } from 'react'; +import ReactDOM from 'react-dom'; +import reactToWebComponent from 'react-to-webcomponent'; + +interface WidgetProps { + title?: string; + targetDate?: string; + targetTime?: string; + bgColor?: string; + textColor?: string; + font?: string; +} + +const CustomElement: FC<WidgetProps> = ({ + title = 'Countdown', + targetDate = '', + targetTime = '00:00', + bgColor = '#ffffff', + textColor = '#333333', + font = "{}", +}) => { + const { font: textFont, textDecoration } = JSON.parse(font); + const [time, setTime] = useState({ days: 0, hours: 0, minutes: 0, seconds: 0, isExpired: false }); + + useEffect(() => { + if (!targetDate) return; + + const update = () => { + const target = new Date(`${targetDate}T${targetTime}`); + const diff = target.getTime() - Date.now(); + if (diff <= 0) { + setTime({ days: 0, hours: 0, minutes: 0, seconds: 0, isExpired: true }); + return; + } + setTime({ + days: Math.floor(diff / (1000 * 60 * 60 * 24)), + hours: Math.floor((diff % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60)), + minutes: Math.floor((diff % (1000 * 60 * 60)) / (1000 * 60)), + seconds: Math.floor((diff % (1000 * 60)) / 1000), + isExpired: false, + }); + }; + + update(); + const interval = setInterval(update, 1000); + return () => clearInterval(interval); + }, [targetDate, targetTime]); + + const styles = { + wrapper: { + backgroundColor: bgColor, + padding: '24px 32px', + textAlign: 'center' as const, + display: 'inline-block', + }, + title: { + font: textFont || '600 24px sans-serif', + color: textColor, + textDecoration, + marginBottom: '16px', + }, + }; + + return ( + <div style={styles.wrapper}> + {title && <div style={styles.title}>{title}</div>} + {/* Widget content */} + </div> + ); +}; + +const customElement = reactToWebComponent(CustomElement, React, ReactDOM, { + props: { + title: 'string', + targetDate: 'string', + targetTime: 'string', + bgColor: 'string', + textColor: 'string', + font: 'string', + }, +}); + +export default customElement; +``` + +**Key Points:** + +- Props interface uses **camelCase** (e.g., `targetDate`, `bgColor`) +- `reactToWebComponent` config uses camelCase keys with `'string'` type +- All props are passed as strings from the web component +- Use inline styles, not CSS imports +- Parse complex props (like `font`) from JSON strings: `const { font: textFont, textDecoration } = JSON.parse(font)` +- Apply font via `font` CSS shorthand and `textDecoration` property +- Extract helper components, utility functions, and styles into separate files for clean code organization + +## Settings Panel Pattern + +```typescript +import React, { type FC, useState, useEffect, useCallback } from "react"; +import { widget } from "@wix/editor"; +import { + SidePanel, + WixDesignSystemProvider, + Input, + FormField, + TimeInput, + Box, +} from "@wix/design-system"; +import "@wix/design-system/styles.global.css"; +import { ColorPickerField } from "./components/ColorPickerField"; +import { FontPickerField } from "./components/FontPickerField"; +import { parseTimeValue } from "./utils"; + +const DEFAULT_BG_COLOR = "#0a0e27"; +const DEFAULT_TEXT_COLOR = "#00ff88"; +const DEFAULT_TEXT_FONT = ""; +const DEFAULT_TEXT_DECORATION = ""; + +const Panel: FC = () => { + const [title, setTitle] = useState<string>("Countdown"); + const [targetDate, setTargetDate] = useState<string>(""); + const [targetTime, setTargetTime] = useState<string>("00:00"); + const [bgColor, setBgColor] = useState<string>(DEFAULT_BG_COLOR); + const [textColor, setTextColor] = useState<string>(DEFAULT_TEXT_COLOR); + const [font, setFont] = useState({ font: DEFAULT_TEXT_FONT, textDecoration: DEFAULT_TEXT_DECORATION }); + + useEffect(() => { + Promise.all([ + widget.getProp("title"), + widget.getProp("target-date"), + widget.getProp("target-time"), + widget.getProp("bg-color"), + widget.getProp("text-color"), + widget.getProp("font"), + ]) + .then(([titleVal, dateVal, timeVal, bgColorVal, textColorVal, fontString]) => { + setTitle(titleVal || "Countdown"); + setTargetDate(dateVal || ""); + setTargetTime(timeVal || "00:00"); + setBgColor(bgColorVal || DEFAULT_BG_COLOR); + setTextColor(textColorVal || DEFAULT_TEXT_COLOR); + setFont(JSON.parse(fontString || "{}")); + }) + .catch((error) => console.error("Failed to fetch widget properties:", error)); + }, []); + + const handleTitleChange = useCallback((event: React.ChangeEvent<HTMLInputElement>) => { + const newTitle = event.target.value; + setTitle(newTitle); + widget.setProp("title", newTitle); + }, []); + + const handleDateChange = useCallback((event: React.ChangeEvent<HTMLInputElement>) => { + const newDate = event.target.value; + setTargetDate(newDate); + widget.setProp("target-date", newDate); + }, []); + + const handleTimeChange = useCallback(({ date }: { date: Date }) => { + if (date) { + const hours = String(date.getHours()).padStart(2, '0'); + const minutes = String(date.getMinutes()).padStart(2, '0'); + const newTime = `${hours}:${minutes}`; + setTargetTime(newTime); + widget.setProp("target-time", newTime); + } + }, []); + + const handleBgColorChange = (value: string) => { + setBgColor(value); + widget.setProp("bg-color", value); + }; + + const handleTextColorChange = (value: string) => { + setTextColor(value); + widget.setProp("text-color", value); + }; + + const handleFontChange = (value: { font: string; textDecoration: string }) => { + setFont(value); + widget.setProp("font", JSON.stringify(value)); + }; + + return ( + <WixDesignSystemProvider> + <SidePanel width="300" height="100vh"> + <SidePanel.Header title="Countdown Settings" /> + <SidePanel.Content noPadding stretchVertically> + <Box direction="vertical" gap="24px"> + <SidePanel.Field> + <FormField label="Title" required> + <Input + type="text" + value={title} + onChange={handleTitleChange} + placeholder="Enter countdown title" + /> + </FormField> + </SidePanel.Field> + + <SidePanel.Field> + <FormField label="Target Date" required> + <Input + type="date" + value={targetDate} + onChange={handleDateChange} + /> + </FormField> + </SidePanel.Field> + + <SidePanel.Field> + <FormField label="Target Time" required> + <TimeInput + value={parseTimeValue(targetTime)} + onChange={handleTimeChange} + /> + </FormField> + </SidePanel.Field> + + <ColorPickerField + label="Background Color" + value={bgColor} + onChange={handleBgColorChange} + /> + + <ColorPickerField + label="Text Color" + value={textColor} + onChange={handleTextColorChange} + /> + + <FontPickerField + label="Text Font" + value={font} + onChange={handleFontChange} + /> + </Box> + </SidePanel.Content> + </SidePanel> + </WixDesignSystemProvider> + ); +}; + +export default Panel; +``` + +**Key Points:** + +- Prop names in `widget.getProp()` and `widget.setProp()` use **kebab-case** (e.g., `"target-date"`, `"bg-color"`) +- Always update both local state AND widget prop in onChange handlers +- Wrap content in `WixDesignSystemProvider > SidePanel > SidePanel.Content` +- Use WDS components from `@wix/design-system` (see [references/SETTINGS_PANEL.md](references/SETTINGS_PANEL.md)) +- Import `@wix/design-system/styles.global.css` for styles +- For colors, use `ColorPickerField` with `inputs.selectColor()` from `@wix/editor` — NOT `<Input type="color">` +- For fonts, use `FontPickerField` with `inputs.selectFont()` from `@wix/editor` — NOT a text Input +- Font values are stored as JSON strings via `JSON.stringify()` / `JSON.parse()` + +## Props Naming Convention + +**Critical:** Props use different naming conventions in each file: + +| File | Convention | Example | +| ------------------------------ | ---------- | --------------------------------------------- | +| `widget.tsx` (Props interface) | camelCase | `targetDate`, `bgColor`, `textColor` | +| `panel.tsx` (widget API) | kebab-case | `"target-date"`, `"bg-color"`, `"text-color"` | +| `reactToWebComponent` config | camelCase | `targetDate: 'string'` | + +The web component automatically converts between camelCase (React props) and kebab-case (HTML attributes). + +## Wix Data API Integration + +When using Wix Data API in widgets, you **must** handle the Wix Editor environment gracefully: + +```typescript +import { items } from "@wix/data"; +import { window as wixWindow } from "@wix/site-window"; + +const CustomElement: FC<WidgetProps> = ({ collectionId }) => { + const [data, setData] = useState(null); + const [isEditor, setIsEditor] = useState(false); + + useEffect(() => { + const loadData = async () => { + const currentViewMode = await wixWindow.viewMode(); + + if (currentViewMode === "Editor") { + // Don't fetch data in editor - show placeholder + setIsEditor(true); + return; + } + + // Fetch real data only on live site + try { + const results = await items.query(collectionId).limit(10).find(); + setData(results.items); + } catch (error) { + console.error("Failed to load data:", error); + } + }; + + loadData(); + }, [collectionId]); + + if (isEditor) { + return ( + <div style={{ padding: "20px", border: "2px dashed #ccc" }}> + <p>Widget will display data on the live site</p> + <p>Collection: {collectionId}</p> + </div> + ); + } + + // Render widget with real data + return ( + <div> + {data?.map((item) => ( + <div key={item._id}>{item.title}</div> + ))} + </div> + ); +}; +``` + +**Requirements:** + +- Import `{ window as wixWindow }` from `"@wix/site-window"` +- Check `await wixWindow.viewMode()` before fetching data +- If `viewMode === 'Editor'`, show a placeholder UI instead +- Only fetch and render real data when NOT in editor mode + +## Color Selection + +For color selection in settings panels, use `ColorPickerField` component with `inputs.selectColor()` from `@wix/editor`. Do NOT use `<Input type="color">`. + +```typescript +// components/ColorPickerField.tsx +import React, { type FC } from 'react'; +import { inputs } from '@wix/editor'; +import { FormField, Box, FillPreview, SidePanel } from '@wix/design-system'; + +interface ColorPickerFieldProps { + label: string; + value: string; + onChange: (value: string) => void; +} + +export const ColorPickerField: FC<ColorPickerFieldProps> = ({ + label, + value, + onChange, +}) => ( + <SidePanel.Field> + <FormField label={label}> + <Box width="30px" height="30px"> + <FillPreview + fill={value} + onClick={() => inputs.selectColor(value, { onChange: (val) => { if (val) onChange(val); } })} + /> + </Box> + </FormField> + </SidePanel.Field> +); +``` + +Usage in panel: + +```typescript +const handleBgColorChange = (value: string) => { + setBgColor(value); + widget.setProp("bg-color", value); +}; + +<ColorPickerField label="Background Color" value={bgColor} onChange={handleBgColorChange} /> +``` + +**Important:** Use `inputs.selectColor(value, { onChange })` from `@wix/editor` with `FillPreview` from WDS. This opens the native Wix color picker with theme colors, gradients, and more. Never use `<Input type="color">`. + +## Font Selection + +For font selection in settings panels, use `FontPickerField` component with `inputs.selectFont()` from `@wix/editor`. Do NOT use a text Input. + +```typescript +// components/FontPickerField.tsx +import React, { type FC } from 'react'; +import { inputs } from '@wix/editor'; +import { FormField, Button, Text, SidePanel } from '@wix/design-system'; + +interface FontValue { + font: string; + textDecoration: string; +} + +interface FontPickerFieldProps { + label: string; + value: FontValue; + onChange: (value: FontValue) => void; +} + +export const FontPickerField: FC<FontPickerFieldProps> = ({ + label, + value, + onChange, +}) => ( + <SidePanel.Field> + <FormField label={label}> + <Button + size="small" + priority="secondary" + onClick={() => inputs.selectFont(value, { onChange: (val) => onChange({ font: val.font, textDecoration: val.textDecoration || "" }) })} + fullWidth + > + <Text size="small" ellipsis>Change Font</Text> + </Button> + </FormField> + </SidePanel.Field> +); +``` + +Usage in panel: + +```typescript +const [font, setFont] = useState<FontValue>({ font: "", textDecoration: "" }); + +const handleFontChange = (value: FontValue) => { + setFont(value); + widget.setProp("font", JSON.stringify(value)); +}; + +<FontPickerField label="Text Font" value={font} onChange={handleFontChange} /> +``` + +**Important:** Use `inputs.selectFont(value, { onChange })` from `@wix/editor` with the callback pattern. This provides a rich font picker dialog with bold, italic, size, and typography features. Font values are stored as JSON strings. + +## Output Structure + +``` +src/site/widgets/custom-elements/ +└── {widget-name}/ + ├── widget.tsx # Main widget component + ├── panel.tsx # Settings panel component + ├── extensions.ts # Extension registration + ├── components/ # Optional sub-components + │ ├── ColorPickerField.tsx + │ └── FontPickerField.tsx + └── utils/ # Optional helper functions + └── formatters.ts +``` + +## Examples + +### Countdown Timer Widget + +**Request:** "Create a countdown timer widget" + +**Output:** + +- Widget with configurable title, target date/time, colors, and font +- Settings panel with date picker, time input, color pickers, font picker +- Real-time countdown display with days, hours, minutes, seconds + +### Product Showcase Widget + +**Request:** "Create a widget that displays products from a collection" + +**Output:** + +- Widget that queries Wix Data collection +- Editor environment handling (shows placeholder in editor) +- Settings panel for collection selection, display options, styling +- Responsive grid layout with product cards + +### Interactive Calculator Widget + +**Request:** "Create a calculator widget with customizable colors" + +**Output:** + +- Functional calculator component +- Settings panel for color customization (background, buttons, text) +- Inline styles for all styling +- No external dependencies + +## Frontend Aesthetics + +Avoid generic aesthetics. Create distinctive designs with unique fonts (avoid Inter, Roboto, Arial), cohesive color palettes, CSS animations for micro-interactions, and context-specific choices. Don't use clichéd color schemes or predictable layouts. + +## Extension Registration + +**Extension registration is MANDATORY and has TWO required steps.** + +### Step 1: Create Widget-Specific Extension File + +Each site widget requires an `extensions.ts` file in its folder: + +```typescript +import { extensions } from "@wix/astro/builders"; + +export const sitewidgetMyWidget = extensions.customElement({ + id: "{{GENERATE_UUID}}", + name: "My Widget", + tagName: "my-widget", + element: "./site/widgets/custom-elements/my-widget/widget.tsx", + settings: "./site/widgets/custom-elements/my-widget/panel.tsx", + installation: { + autoAdd: true, + }, + width: { + defaultWidth: 500, + allowStretch: true, + }, + height: { + defaultHeight: 500, + }, +}); +``` + +**CRITICAL: UUID Generation** + +The `id` must be a unique, static UUID v4 string. Generate a fresh UUID for each extension - do NOT use `randomUUID()` or copy UUIDs from examples. Replace `{{GENERATE_UUID}}` with a freshly generated UUID like `"a1b2c3d4-e5f6-7890-abcd-ef1234567890"`. + +| Property | Type | Description | +| -------------- | ------ | -------------------------------------- | +| `id` | string | Unique static UUID v4 (generate fresh) | +| `name` | string | Display name in editor | +| `tagName` | string | HTML custom element tag (kebab-case) | +| `element` | string | Path to widget React component | +| `settings` | string | Path to settings panel component | +| `installation` | object | Auto-add behavior | +| `width` | object | Default width and stretch settings | +| `height` | object | Default height settings | + +### Step 2: Register in Main Extensions File + +**CRITICAL:** After creating the widget-specific extension file, you MUST read [wix-cli-extension-registration](../wix-cli-extension-registration/SKILL.md) and follow the "App Registration" section to update `src/extensions.ts`. + +**Without completing Step 2, the site widget will not be available in the Wix Editor.** + +## Code Quality Requirements + +- Strict TypeScript (no `any`, explicit return types) +- Functional React components with hooks +- Proper error handling and loading states +- No `@ts-ignore` comments +- Inline styles only (no CSS imports) +- Handle Wix Editor environment when using Wix Data API +- Consistent prop naming (camelCase in widget, kebab-case in panel) + +## Verification + +After implementation completes, the **wix-cli-orchestrator** will run validation using [wix-cli-app-validation](../wix-cli-app-validation/SKILL.md). diff --git a/CLI App - Calculator Form/.agents/skills/wix-cli-site-widget/references/SETTINGS_PANEL.md b/CLI App - Calculator Form/.agents/skills/wix-cli-site-widget/references/SETTINGS_PANEL.md new file mode 100644 index 0000000..d3763dd --- /dev/null +++ b/CLI App - Calculator Form/.agents/skills/wix-cli-site-widget/references/SETTINGS_PANEL.md @@ -0,0 +1,345 @@ +# Settings Panel Components Reference + +This reference documents components and patterns specific to widget settings panels. For general WDS component documentation (FormField, Input, Dropdown, Checkbox, ToggleSwitch, DatePicker, Box, etc.), use the [wds-docs](../../wds-docs/SKILL.md) skill. + +## Import + +```typescript +import { + SidePanel, + FormField, + Input, + Dropdown, + Checkbox, + ToggleSwitch, + DatePicker, + TimeInput, + Box, + WixDesignSystemProvider, +} from "@wix/design-system"; +import "@wix/design-system/styles.global.css"; +``` + +## SidePanel Components + +### SidePanel + +Main container for the settings panel. Always wrap panel content in this component. + +```typescript +<SidePanel width="300" height="100vh"> + <SidePanel.Header title="Widget Settings" /> + <SidePanel.Content noPadding stretchVertically> + {/* Form fields */} + </SidePanel.Content> +</SidePanel> +``` + +**Props:** + +- `width`: Panel width (default: "300") +- `height`: Panel height (default: "100vh") + +### SidePanel.Header + +Header section with title. + +```typescript +<SidePanel.Header title="Widget Settings" /> +``` + +**Props:** + +- `title`: Header title text + +### SidePanel.Content + +Content area for form fields. + +```typescript +<SidePanel.Content noPadding stretchVertically> + {/* Form content */} +</SidePanel.Content> +``` + +**Props:** + +- `noPadding`: Remove default padding +- `stretchVertically`: Stretch to fill available height + +### SidePanel.Field + +Wrapper for individual form fields. Use this to wrap each `FormField`. + +```typescript +<SidePanel.Field> + <FormField label="Title"> + <Input value={title} onChange={handleChange} /> + </FormField> +</SidePanel.Field> +``` + +## Widget API Integration Patterns + +### TimeInput with widget.setProp + +```typescript +const parseTimeValue = (timeString: string): Date => { + const [hours, minutes] = timeString.split(':'); + const date = new Date(); + date.setHours(parseInt(hours, 10), parseInt(minutes, 10), 0, 0); + return date; +}; + +<TimeInput + value={parseTimeValue(targetTime)} + onChange={({ date }) => { + const hours = String(date.getHours()).padStart(2, '0'); + const minutes = String(date.getMinutes()).padStart(2, '0'); + const newTime = `${hours}:${minutes}`; + setTargetTime(newTime); + widget.setProp("target-time", newTime); + }} +/> +``` + +## Custom Components + +### ColorPickerField + +Custom component for color selection using `inputs.selectColor()` from `@wix/editor`. This opens the Wix color picker dialog with theme colors, gradients, and more — **NOT** a basic HTML `<input type="color">`. + +```typescript +import React, { type FC } from 'react'; +import { inputs } from '@wix/editor'; +import { FormField, Box, FillPreview, SidePanel } from '@wix/design-system'; + +interface ColorPickerFieldProps { + label: string; + value: string; + onChange: (value: string) => void; +} + +export const ColorPickerField: FC<ColorPickerFieldProps> = ({ + label, + value, + onChange, +}) => ( + <SidePanel.Field> + <FormField label={label}> + <Box width="30px" height="30px"> + <FillPreview + fill={value} + onClick={() => inputs.selectColor(value, { onChange: (val) => { if (val) onChange(val); } })} + /> + </Box> + </FormField> + </SidePanel.Field> +); +``` + +**Important:** Always use `inputs.selectColor()` from `@wix/editor` with the `FillPreview` WDS component. Do NOT use `<Input type="color">` — it produces a basic browser color picker that doesn't match the Wix Editor UX. + +### FontPickerField + +Custom component for font selection using `inputs.selectFont()` from `@wix/editor`. This opens the Wix font picker dialog with font family, size, bold, italic, and other typography features. + +```typescript +import React, { type FC } from 'react'; +import { inputs } from '@wix/editor'; +import { FormField, Button, Text, SidePanel } from '@wix/design-system'; + +interface FontValue { + font: string; + textDecoration: string; +} + +interface FontPickerFieldProps { + label: string; + value: FontValue; + onChange: (value: FontValue) => void; +} + +export const FontPickerField: FC<FontPickerFieldProps> = ({ + label, + value, + onChange, +}) => ( + <SidePanel.Field> + <FormField label={label}> + <Button + size="small" + priority="secondary" + onClick={() => inputs.selectFont(value, { onChange: (val) => onChange({ font: val.font, textDecoration: val.textDecoration || "" }) })} + fullWidth + > + <Text size="small" ellipsis>Change Font</Text> + </Button> + </FormField> + </SidePanel.Field> +); +``` + +**Important:** Always use `inputs.selectFont()` from `@wix/editor` with the callback pattern `inputs.selectFont(value, { onChange })`. Do NOT use an async/await pattern or a readOnly text Input — the callback pattern integrates directly with the Wix Editor font picker dialog. + +## Complete Example + +```typescript +import React, { type FC, useState, useEffect, useCallback } from "react"; +import { widget } from "@wix/editor"; +import { + SidePanel, + WixDesignSystemProvider, + Input, + FormField, + TimeInput, + Box, +} from "@wix/design-system"; +import "@wix/design-system/styles.global.css"; +import { ColorPickerField } from "./components/ColorPickerField"; +import { FontPickerField } from "./components/FontPickerField"; +import { parseTimeValue } from "./utils"; + +const DEFAULT_BG_COLOR = "#0a0e27"; +const DEFAULT_TEXT_COLOR = "#00ff88"; +const DEFAULT_TEXT_FONT = ""; +const DEFAULT_TEXT_DECORATION = ""; + +const Panel: FC = () => { + const [title, setTitle] = useState<string>("Countdown"); + const [targetDate, setTargetDate] = useState<string>(""); + const [targetTime, setTargetTime] = useState<string>("00:00"); + const [bgColor, setBgColor] = useState<string>(DEFAULT_BG_COLOR); + const [textColor, setTextColor] = useState<string>(DEFAULT_TEXT_COLOR); + const [font, setFont] = useState({ font: DEFAULT_TEXT_FONT, textDecoration: DEFAULT_TEXT_DECORATION }); + + useEffect(() => { + Promise.all([ + widget.getProp("title"), + widget.getProp("target-date"), + widget.getProp("target-time"), + widget.getProp("bg-color"), + widget.getProp("text-color"), + widget.getProp("font"), + ]) + .then(([titleVal, dateVal, timeVal, bgColorVal, textColorVal, fontString]) => { + setTitle(titleVal || "Countdown"); + setTargetDate(dateVal || ""); + setTargetTime(timeVal || "00:00"); + setBgColor(bgColorVal || DEFAULT_BG_COLOR); + setTextColor(textColorVal || DEFAULT_TEXT_COLOR); + setFont(JSON.parse(fontString || "{}")); + }) + .catch((error) => console.error("Failed to fetch widget properties:", error)); + }, []); + + const handleTitleChange = useCallback((event: React.ChangeEvent<HTMLInputElement>) => { + const newTitle = event.target.value; + setTitle(newTitle); + widget.setProp("title", newTitle); + }, []); + + const handleDateChange = useCallback((event: React.ChangeEvent<HTMLInputElement>) => { + const newDate = event.target.value; + setTargetDate(newDate); + widget.setProp("target-date", newDate); + }, []); + + const handleTimeChange = useCallback(({ date }: { date: Date }) => { + if (date) { + const hours = String(date.getHours()).padStart(2, '0'); + const minutes = String(date.getMinutes()).padStart(2, '0'); + const newTime = `${hours}:${minutes}`; + setTargetTime(newTime); + widget.setProp("target-time", newTime); + } + }, []); + + const handleBgColorChange = (value: string) => { + setBgColor(value); + widget.setProp("bg-color", value); + }; + + const handleTextColorChange = (value: string) => { + setTextColor(value); + widget.setProp("text-color", value); + }; + + const handleFontChange = (value: { font: string; textDecoration: string }) => { + setFont(value); + widget.setProp("font", JSON.stringify(value)); + }; + + return ( + <WixDesignSystemProvider> + <SidePanel width="300" height="100vh"> + <SidePanel.Header title="Countdown Settings" /> + <SidePanel.Content noPadding stretchVertically> + <Box direction="vertical" gap="24px"> + <SidePanel.Field> + <FormField label="Title" required> + <Input + type="text" + value={title} + onChange={handleTitleChange} + placeholder="Enter countdown title" + /> + </FormField> + </SidePanel.Field> + + <SidePanel.Field> + <FormField label="Target Date" required> + <Input + type="date" + value={targetDate} + onChange={handleDateChange} + /> + </FormField> + </SidePanel.Field> + + <SidePanel.Field> + <FormField label="Target Time" required> + <TimeInput + value={parseTimeValue(targetTime)} + onChange={handleTimeChange} + /> + </FormField> + </SidePanel.Field> + + <ColorPickerField + label="Background Color" + value={bgColor} + onChange={handleBgColorChange} + /> + + <ColorPickerField + label="Text Color" + value={textColor} + onChange={handleTextColorChange} + /> + + <FontPickerField + label="Text Font" + value={font} + onChange={handleFontChange} + /> + </Box> + </SidePanel.Content> + </SidePanel> + </WixDesignSystemProvider> + ); +}; + +export default Panel; +``` + +## Notes + +- Always import `@wix/design-system/styles.global.css` for proper styling +- Use `SidePanel.Field` to wrap each `FormField` +- Update both local state AND `widget.setProp()` in onChange handlers +- Prop names in `widget.getProp()` and `widget.setProp()` use kebab-case +- For color selection, use `inputs.selectColor()` from `@wix/editor` with `FillPreview` — do NOT use `<Input type="color">` +- For font selection, use `inputs.selectFont()` from `@wix/editor` with a `Button` — do NOT use a text Input +- Both `inputs.selectColor()` and `inputs.selectFont()` use the callback pattern: `inputs.selectColor(value, { onChange })` and `inputs.selectFont(value, { onChange })` +- Font values are stored as JSON strings via `widget.setProp("font", JSON.stringify(value))` and parsed back with `JSON.parse()` diff --git a/CLI App - Calculator Form/.agents/skills/wix-stores-versioning/SKILL.md b/CLI App - Calculator Form/.agents/skills/wix-stores-versioning/SKILL.md new file mode 100644 index 0000000..d15f344 --- /dev/null +++ b/CLI App - Calculator Form/.agents/skills/wix-stores-versioning/SKILL.md @@ -0,0 +1,78 @@ +--- +name: wix-stores-versioning +description: "Handle Wix Stores Catalog V1 and V3 SDK compatibility. Use when building any integration that interacts with Wix Stores products, inventory, orders, or collections. Triggers include Wix Stores, products API, inventory API, catalog version, productsV3, V1 vs V3, store products, queryProducts, getProduct." +compatibility: Requires Wix CLI development environment. +--- + +# Wix Stores Catalog Versioning + +Wix Stores has two catalog versions that are **NOT backwards compatible**: + +| Version | Status | +|---------|--------| +| **V1_CATALOG** | Legacy (e.g., `products`, `inventory`) | +| **V3_CATALOG** | Current (e.g., `productsV3`, `inventoryItemsV3`) | + +V3 modules typically have a `V3` suffix. Use Wix MCP to search for the specific module you need. + +## Core Pattern + +Always check catalog version before any Stores operation: + +```typescript +import { catalogVersioning, products, productsV3 } from '@wix/stores'; + +async function getProducts() { + const { catalogVersion } = await catalogVersioning.getCatalogVersion(); + + if (catalogVersion === 'STORES_NOT_INSTALLED') { + return []; + } + + if (catalogVersion === 'V3_CATALOG') { + // Use V3 module + const result = await productsV3.queryProducts().limit(10).find(); + return result.items; + } + + // Use V1 module + const result = await products.queryProducts().limit(10).find(); + return result.items; +} +``` + +## Required Permissions + +**Always look up permissions for each API method you use:** + +1. Search for the method using `SearchWixRESTDocumentation` +2. Read the full docs with `ReadFullDocsArticle` to get the required permissions +3. Return the required permissions to the user + +## Key Rules + +- Call `getCatalogVersion()` at the start of each flow +- Catalog version is permanent per site (won't downgrade from V3 to V1) +- V1 and V3 have different payload structures — field names, nesting, and types differ +- Subscribe to both V1 and V3 webhooks to handle all sites + +## Finding SDK Details + +**Use MCP tools to search for version-specific documentation:** + +- `SearchWixRESTDocumentation` - Search for methods and permissions +- `ReadFullDocsArticle` - Read full documentation when needed + +**Search queries** (results show both V1 and V3 namespaces): +- `"getCatalogVersion"` → permissions and usage +- `"createProduct"` → `productsV3` (V3) and `products` (V1) +- `"queryProducts"` → `productsV3` (V3) and `products` (V1) +- `"getInventoryItem"` → `inventoryItemsV3` (V3) and `inventory` (V1) + +**Important:** After finding the method, use `ReadFullDocsArticle` to get the full documentation including required permissions. Return them to the user. + +## API Differences Reference + +V1 and V3 have different field structures. For field mapping, see: +[Catalog V1 to V3 Migration Guide](https://dev.wix.com/docs/api-reference/business-solutions/stores/catalog-v3/catalog-v1-to-v3-migration-guide?apiView=SDK) + diff --git a/CLI App - Calculator Form/.cursor/mcp.json b/CLI App - Calculator Form/.cursor/mcp.json new file mode 100644 index 0000000..63b4e5e --- /dev/null +++ b/CLI App - Calculator Form/.cursor/mcp.json @@ -0,0 +1,12 @@ +{ + "mcpServers": { + "wix-mcp-remote": { + "command": "npx", + "args": [ + "-y", + "@wix/mcp-remote", + "https://mcp.wix.com/sse" + ] + } + } +} diff --git a/CLI App - Calculator Form/.gemini/settings.json b/CLI App - Calculator Form/.gemini/settings.json new file mode 100644 index 0000000..ebf257e --- /dev/null +++ b/CLI App - Calculator Form/.gemini/settings.json @@ -0,0 +1,3 @@ +{ + "contextFileName": "AGENTS.md" +} diff --git a/CLI App - Calculator Form/.gitignore b/CLI App - Calculator Form/.gitignore new file mode 100644 index 0000000..5208a33 --- /dev/null +++ b/CLI App - Calculator Form/.gitignore @@ -0,0 +1,26 @@ +# wix integration +.wix/ + +# build output +dist/ + +# generated types +.astro/ + +# dependencies +node_modules/ + +# logs +*.log +npm-debug.log* + + +# environment variables +.env +.env.local +.env.production + +# misc +.DS_Store +.idea/ +out diff --git a/CLI App - Calculator Form/.npmrc b/CLI App - Calculator Form/.npmrc new file mode 100644 index 0000000..521a9f7 --- /dev/null +++ b/CLI App - Calculator Form/.npmrc @@ -0,0 +1 @@ +legacy-peer-deps=true diff --git a/CLI App - Calculator Form/.nvmrc b/CLI App - Calculator Form/.nvmrc new file mode 100644 index 0000000..ec7ba0e --- /dev/null +++ b/CLI App - Calculator Form/.nvmrc @@ -0,0 +1 @@ +22.10.0 diff --git a/CLI App - Calculator Form/.vscode/extensions.json b/CLI App - Calculator Form/.vscode/extensions.json new file mode 100644 index 0000000..22a1505 --- /dev/null +++ b/CLI App - Calculator Form/.vscode/extensions.json @@ -0,0 +1,4 @@ +{ + "recommendations": ["astro-build.astro-vscode"], + "unwantedRecommendations": [] +} diff --git a/CLI App - Calculator Form/.vscode/launch.json b/CLI App - Calculator Form/.vscode/launch.json new file mode 100644 index 0000000..d642209 --- /dev/null +++ b/CLI App - Calculator Form/.vscode/launch.json @@ -0,0 +1,11 @@ +{ + "version": "0.2.0", + "configurations": [ + { + "command": "./node_modules/.bin/astro dev", + "name": "Development server", + "request": "launch", + "type": "node-terminal" + } + ] +} diff --git a/CLI App - Calculator Form/.vscode/settings.json b/CLI App - Calculator Form/.vscode/settings.json new file mode 100644 index 0000000..54ecf2a --- /dev/null +++ b/CLI App - Calculator Form/.vscode/settings.json @@ -0,0 +1,5 @@ +{ + "editor.quickSuggestions": { + "strings": "on" + } +} diff --git a/CLI App - Calculator Form/AGENTS.md b/CLI App - Calculator Form/AGENTS.md new file mode 100644 index 0000000..ace10bc --- /dev/null +++ b/CLI App - Calculator Form/AGENTS.md @@ -0,0 +1,14 @@ +## CLI Commands + +All CLI instructions can be found at: +node_modules/@wix/cli/agents/instructions.md + +## Skills + +This project comes with a set of skills that can be used when the user asks for help with specific tasks. +If you're using the instructions provided by a skill and fail, or if you do not find a relevant skill for the task, +you can try updating the skills by running the following command: + +`wix skills update` + +This will update the skills to the latest version. \ No newline at end of file diff --git a/CLI App - Calculator Form/CLAUDE.md b/CLI App - Calculator Form/CLAUDE.md new file mode 100644 index 0000000..eef4bd2 --- /dev/null +++ b/CLI App - Calculator Form/CLAUDE.md @@ -0,0 +1 @@ +@AGENTS.md \ No newline at end of file diff --git a/CLI App - Calculator Form/README.md b/CLI App - Calculator Form/README.md new file mode 100644 index 0000000..fcc7918 --- /dev/null +++ b/CLI App - Calculator Form/README.md @@ -0,0 +1,501 @@ +# Calculator Form + +A [Wix CLI](https://dev.wix.com/docs/wix-cli/guides/about-the-wix-cli) app that demonstrates an **Editor React Component** extension — a React-based site widget with auto-generated editor panels for [Wix Harmony](https://dev.wix.com/docs/build-apps/get-started/overview/about-wix-harmony-and-apps). + +Site owners add the **Calculator Form** component to a Harmony page, enter numeric values, tap **Calculate total**, and see the sum. All labels, field configuration, and styling are editable in the editor through **auto panels** — no custom settings panel code required. + +Use this guide to explore the app, run it locally, connect AI tools (Wix Skills + Wix MCP), and rebuild the same pattern in your own Wix CLI project. + +> **Video walkthrough:** [Create Editor React Component Extension](https://youtu.be/6wBiPGc0U3o) — a step-by-step tutorial that covers creating the app, generating the extension, building the widget with an AI agent, and testing on a Harmony site. + +--- + +## Table of Contents + +1. [What This App Does](#what-this-app-does) +2. [Features](#features) +3. [What Is an Editor React Component Extension?](#what-is-an-editor-react-component-extension) +4. [Architecture](#architecture) +5. [Project Structure](#project-structure) +6. [Prerequisites](#prerequisites) +7. [Quick Start](#quick-start) +8. [Connect Wix Skills](#connect-wix-skills) +9. [Connect Wix MCP](#connect-wix-mcp) +10. [Build This App Yourself](#build-this-app-yourself) +11. [Editor React Component Files](#editor-react-component-files) +12. [Manifest and Auto Panels](#manifest-and-auto-panels) +13. [Extensions in This App](#extensions-in-this-app) +14. [Manual Steps After Install](#manual-steps-after-install) +15. [CLI Commands Reference](#cli-commands-reference) +16. [Resources](#resources) + +--- + +## What This App Does + +This example app ships a single **Editor React Component** — a calculator form that: + +- Shows a title and short description +- Renders a configurable list of numeric input fields +- Sums the values when the user submits the form +- Displays the total in a results view with a **Start over** button + +Unlike a [custom element site widget](https://dev.wix.com/docs/build-apps/develop-your-app/extensions/site-extensions/site-widgets/about-site-widget-extensions) (which requires you to build and maintain a settings panel), an Editor React Component declares what's editable in a **manifest**. Wix Harmony reads that manifest and builds matching [auto panels](https://dev.wix.com/docs/build-apps/develop-your-app/extensions/site-extensions/editor-react-components/auto-panels/about-auto-panels) for text, design, layout, and more. + +The app also includes a minimal **dashboard page** scaffold (empty state) — the calculator itself lives entirely on the site as an Editor React Component. + +--- + +## Features + +- **Editor React Component** — React widget with Harmony-native editing experience +- **Auto panels** — Text, design, and layout controls generated from the manifest (no custom panel code) +- **Configurable fields** — `arrayItems` data type lets site owners add, remove, and label input fields +- **Two-step UX** — Form view and results view managed with React state +- **Editor styling** — CSS module classes paired with manifest `cssProperties` and `elements` for per-part design controls +- **Accessibility** — Supports `direction` and `a11y` props from `@wix/editor-react-types` +- **AI-ready** — Includes Wix Skills and Wix MCP configuration for building with coding agents + +--- + +## What Is an Editor React Component Extension? + +An [Editor React Component extension](https://dev.wix.com/docs/build-apps/develop-your-app/extensions/site-extensions/editor-react-components/about-editor-react-components) has two main parts: + +| Part | Purpose | +|------|---------| +| **React component** | Your UI code — renders in Harmony and on the live site | +| **Manifest** | Declares what's customizable (text, images, CSS, layout, elements) so the editor builds auto panels | + +### How it works + +1. You build the React component and add CSS class selectors to elements you want the editor to target. +2. The CLI **auto-generates** most of the manifest from your component (`my-calculator-form.generated.ts`). +3. You override installation, layout, and display settings in the hand-edited extension file (`my-calculator-form.extension.ts`). +4. When a site owner adds your component, Harmony reads the manifest, builds auto panels, and passes data changes as **props** and style changes as **CSS** on matching selectors. + +```mermaid +graph TD + subgraph Dev ["Your code"] + A[React component] --- B[Manifest] + end + Dev --> C[Site owner installs app] + C --> D[Harmony editor] + subgraph Editor ["Harmony editor"] + D --> E[Reads manifest → builds auto panels] + E --> F{User edits} + F -->|Data| G[Delivered as React props] + F -->|Style| H[Applied via CSS selectors] + G --> I[Component rerenders] + H --> I + end +``` + +### Important constraints + +- **Harmony only** — Editor React Components work on [Wix Harmony](https://dev.wix.com/docs/build-apps/get-started/overview/about-wix-harmony-and-apps) sites. They are **not** supported on classic Wix Editor or Wix Studio sites. +- **Alpha feature** — Editor React Components are currently in alpha and may change. +- **No custom panels** — You configure everything through the manifest; you cannot ship your own React settings panel. +- **Manifest regeneration** — After manual changes to component structure or selectors, run `npm run build` and `npx wix generate manifest` so the auto-generated manifest stays in sync. + +--- + +## Architecture + +This project has two layers: + +1. **Site layer (Editor React Component)** — `src/extensions/site/components/my-calculator-form/` contains the React component, CSS module, auto-generated manifest, and extension registration. This is the core of the example. +2. **Dashboard layer (optional scaffold)** — `src/extensions/dashboard/pages/my-page/` is a placeholder dashboard page generated with the Basic App template. The calculator does not require dashboard logic. + +Both extensions are registered in `src/extensions.ts`: + +```ts +export default app() + .use(myPage) + .use(myCalculatorForm); +``` + +--- + +## Project Structure + +``` +calculator-form/ +├── .agents/skills/ # Wix Skills — AI instructions for building Wix CLI extensions +├── .cursor/mcp.json # Wix MCP config for Cursor (commit this for your team) +├── skills-lock.json # Locked versions of installed Wix Skills +├── wix.config.json # App ID, namespace, code identifier (you must configure this) +├── AGENTS.md # Entry point for AI agents working in this repo +├── src/ +│ ├── extensions.ts # Registers all extensions with the Wix app builder +│ └── extensions/ +│ ├── dashboard/pages/my-page/ # Placeholder dashboard page +│ └── site/components/my-calculator-form/ # Editor React Component +│ ├── my-calculator-form.tsx # Main React component +│ ├── my-calculator-form.module.css # Component styles +│ ├── my-calculator-form.generated.ts # Auto-generated manifest (do not edit) +│ ├── my-calculator-form.extension.ts # Extension config + manifest overrides +│ └── component.tsx # Wires component with default props +``` + +--- + +## Prerequisites + +| Requirement | Details | +|-------------|---------| +| **Node.js** | v20+ (this project uses v22 — see `.nvmrc`) | +| **npm** | Comes with Node | +| **Wix account** | [Sign up](https://www.wix.com/) if needed | +| **Wix Dev Center app** | Create a custom app (see Quick Start) | +| **Harmony test site** | Editor React Components require a Harmony site for testing | +| **AI editor (optional)** | [Cursor](https://cursor.com/), Claude Code, or Gemini with MCP support | + +--- + +## Quick Start + +### Step 1 — Create a Wix app in Dev Center + +1. Go to [Wix Dev Center](https://dev.wix.com/). +2. Click **Create New App** (or open an existing app). +3. Note your **App ID**. +4. During CLI setup (or in Dev Center), choose a **namespace** and **code identifier** — unique strings for your app. Once set, they cannot be changed. + +### Step 2 — Clone and install + +```bash +git clone https://github.com/wix/cli-examples.git +cd "cli-examples/CLI App - Calculator Form" +npm install +``` + +### Step 3 — Configure `wix.config.json` + +Replace the placeholders with your Dev Center values: + +```json +{ + "appId": "<YOUR_APP_ID>", + "namespace": "<YOUR_APP_NAMESPACE>", + "projectId": "calculator-form", + "codeIdentifier": "<YOUR_CODE_IDENTIFIER>", + "projectType": "App" +} +``` + +Also update the `type` field in `src/extensions/site/components/my-calculator-form/my-calculator-form.extension.ts` to match your code identifier: + +```ts +type: '<YOUR_CODE_IDENTIFIER>.CalculatorForm', +``` + +### Step 4 — Log in to the Wix CLI + +```bash +npx wix login +npx wix whoami +``` + +### Step 5 — Build and start local development + +```bash +npm run build +npm run dev +``` + +`wix dev` starts the Astro dev server and connects to your Wix app for live testing. + +> When prompted to choose a site, select a **Harmony** site. Editor React Components are not supported on other site types. + +### Step 6 — Build and preview on a real site + +```bash +npm run build +npm run preview +``` + +`wix preview` deploys a preview version you can install and test on a Harmony site. + +### Step 7 — Release (when ready) + +```bash +npm run release +``` + +--- + +## Connect Wix Skills + +[Wix Skills](https://dev.wix.com/docs/api-reference/articles/ai-tools/about-wix-skills) are instruction files that teach AI coding assistants how to build Wix CLI extensions correctly — including Editor React Components, manifests, dashboard pages, and more. + +This repo already includes skills under `.agents/skills/`, tracked in `skills-lock.json`. + +**If you cloned this repo**, skills are already installed. Update them with: + +```bash +wix skills update +``` + +**If you are starting a new Wix CLI project**, add skills with: + +```bash +npx skills add wix/skills +``` + +> Keep the Wix CLI and Wix Skills in sync. When you upgrade `@wix/cli`, run `wix skills update` too. + +When building the calculator widget with an AI agent, mention in your prompt that the agent should use **Wix MCP** and **Wix Skills** — especially the `wix-cli-site-component` skill and Editor React Component references in `wix-app`. + +--- + +## Connect Wix MCP + +The [Wix MCP](https://dev.wix.com/docs/api-reference/articles/ai-tools/about-the-wix-mcp) (Model Context Protocol) server gives AI assistants access to Wix documentation search, SDK references, and (with auth) live site APIs. + +This repo includes a Cursor config at `.cursor/mcp.json`. To connect: + +1. Open **Cursor Settings → Tools & MCP** and add the Wix MCP from the MCP library, or use the config in `.cursor/mcp.json`. +2. Restart Cursor after saving changes. + +Useful MCP tools for this example: + +| Tool | Use for | +|------|---------| +| `SearchBuildAppsDocumentation` | Editor React Component docs, manifest reference, auto panels | +| `SearchWixCLIDocumentation` | CLI commands (`generate`, `generate manifest`, `dev`, `build`) | +| `ReadFullDocsArticle` | Full documentation articles when search results need more detail | + +See [About the Wix MCP](https://dev.wix.com/docs/api-reference/articles/ai-tools/about-the-wix-mcp) for other editors and auth options. + +--- + +## Build This App Yourself + +Follow this order to recreate the Calculator Form example from scratch. The [video tutorial](https://youtu.be/6wBiPGc0U3o) walks through the same workflow. + +### Phase 1 — Project bootstrap + +1. Create a new Wix CLI app: + ```bash + npm create @wix/app@latest + ``` +2. Choose **Basic App** template and name your app and project. +3. **Enable Wix MCP** when prompted (recommended for AI-assisted development). +4. Enter your **namespace** and **code identifier** (cannot be changed later). +5. Set `appId`, `namespace`, and `codeIdentifier` in `wix.config.json`. +6. Run `npx wix login`. +7. Connect Wix Skills and Wix MCP in your AI editor. + +### Phase 2 — Generate the Editor React Component extension + +```bash +npm run generate +``` + +1. Select **Editor React Component**. +2. Enter a component name (e.g. `Calculator Form`). +3. Choose a folder name (e.g. `my-calculator-form`). +4. Add a short description. +5. Approve dependency installation. + +The CLI scaffolds files under `src/extensions/site/components/my-calculator-form/` and registers the extension in `src/extensions.ts`. + +### Phase 3 — Build the React component + +Describe the widget you want in a prompt to your AI agent. For this example: + +- A title and short "what it does" description +- Several numeric input fields (configurable via manifest `arrayItems`) +- A submit button that calculates the sum +- A results view showing the total +- A **Start over** button to reset + +**Prompt tip:** Ask the agent to use **Wix MCP** and **Wix Skills** for accurate Editor React Component patterns. + +The agent should: + +1. Implement `my-calculator-form.tsx` with React state for form values, view switching (`form` / `results`), and sum calculation. +2. Add CSS module classes that match manifest selectors (e.g. `.calculator-form`, `.title`, `.number-input`, `.submit-button`). +3. Export `defaultProps` for editor defaults. +4. Run `npm run build` and regenerate the manifest so editor capabilities stay in sync. + +If you edit the component manually after generation: + +```bash +npm run build +npx wix generate manifest +``` + +### Phase 4 — Configure the extension file + +Edit `my-calculator-form.extension.ts` to set installation and layout behavior: + +```ts +installation: { + staticContainer: 'HOMEPAGE', + initialSize: { + width: { sizingType: LAYOUT.SIZING_TYPE.pixels, pixels: 360 }, + height: { sizingType: LAYOUT.SIZING_TYPE.content }, + }, +}, +editorElement: withEditorElementDefaults({ + ...editorElement, + layout: { + resizeDirection: LAYOUT.RESIZE_DIRECTION.horizontalAndVertical, + contentResizeDirection: LAYOUT.CONTENT_RESIZE_DIRECTION.vertical, + }, +}, defaultProps), +``` + +- **`height: content`** — the component grows with its content (good for forms). +- **`resizeDirection: horizontalAndVertical`** — site owners can resize the widget in both axes. + +### Phase 5 — Validate and test on Harmony + +```bash +npm run build +npm run dev +``` + +1. Select a **Harmony** site when prompted. +2. Open the Harmony editor — the widget should appear on the page. +3. Test the calculator: enter numbers, calculate, start over. +4. Use auto panels to edit text labels, colors, and field configuration. + +```bash +npm run preview # deploy preview build to a test site +npm run release # release when ready +``` + +--- + +## Editor React Component Files + +| File | Editable? | Purpose | +|------|-----------|---------| +| `my-calculator-form.tsx` | Yes | Main React component — UI logic, state, props interface | +| `my-calculator-form.module.css` | Yes | Styles; class names must match manifest selectors | +| `component.tsx` | Rarely | Wires `withDefaults()` — scaffold file, avoid changing structure | +| `my-calculator-form.generated.ts` | **No** | Auto-generated manifest (`editorElement`). Overwritten on build/sync | +| `my-calculator-form.extension.ts` | Yes | Extension registration, installation config, manifest overrides | + +### Component requirements + +For Harmony to style and configure your component: + +- Export a default function component. +- Accept `className` and `id` props; apply `className` to the root element. +- Add CSS class selectors to inner elements you want in the manifest (e.g. `.title`, `.submit-button`). +- Name data props to match manifest `data` keys (`title`, `fields`, `submitLabel`, etc.). +- Use `useStableId` from `@wix/react-component-utils` for accessible form field IDs. + +### Key implementation details in this example + +- **`fields` stability** — Harmony may pass a new `fields` array reference on every render. The component uses a serialized `fieldsKey` in `useEffect` dependencies so typing in inputs does not reset form state. +- **View switching** — `view` state toggles between the form and results sections using CSS visibility classes. +- **Internationalization** — `Intl.NumberFormat` formats the total for the visitor's locale. + +--- + +## Manifest and Auto Panels + +The manifest (in `my-calculator-form.generated.ts`) declares what site owners can customize. Key sections for this calculator: + +### Root `data` properties + +| Property | Data type | Auto panel | +|----------|-----------|------------| +| `title` | `text` | Edit Text | +| `whatItDoes` | `text` | Edit Text | +| `fields` | `arrayItems` | Settings (add/remove/reorder fields) | +| `submitLabel` | `text` | Edit Text | +| `resultsHeading` | `text` | Edit Text | +| `totalLabel` | `text` | Edit Text | +| `startOverLabel` | `text` | Edit Text | +| `direction` | `direction` | Settings | +| `a11y` | `a11y` | Accessibility | + +### `elements` (nested editor targets) + +Each inner element with a CSS selector gets its own design controls: + +- `.intro`, `.title`, `.what-it-does` +- `.field-label`, `.number-input` (with hover/focus/disabled states) +- `.submit-button`, `.results-heading`, `.total-label`, `.total-value`, `.start-over-button` + +### `cssProperties` (root design) + +Background, borders, padding, border radius, box shadow, and display — surfaced in the **Design** auto panel. + +Learn more: + +- [About Auto Panels](https://dev.wix.com/docs/build-apps/develop-your-app/extensions/site-extensions/editor-react-components/auto-panels/about-auto-panels) +- [About the Manifest](https://dev.wix.com/docs/build-apps/develop-your-app/extensions/site-extensions/editor-react-components/manifest-reference/about-the-manifest) +- [Runtime Props](https://dev.wix.com/docs/build-apps/develop-your-app/extensions/site-extensions/editor-react-components/manifest-reference/runtime-props) + +--- + +## Extensions in This App + +| Extension | File | Purpose | +|-----------|------|---------| +| Editor React Component | `site/components/my-calculator-form/` | Calculator form widget with auto panels | +| Dashboard Page | `dashboard/pages/my-page/` | Placeholder dashboard (not required for the calculator) | + +The calculator feature only requires the **Editor React Component** extension. The dashboard page is optional scaffolding from the Basic App template. + +--- + +## Manual Steps After Install + +After deploying or previewing the app on a Harmony site: + +1. **Install the app** on a Harmony site (via preview link or App Market). +2. **Open the Harmony editor** — the Calculator Form component is added to the homepage by default (`installation.staticContainer: 'HOMEPAGE'`). +3. **Customize** text, fields, and design using auto panels in the editor. +4. **Preview or publish** the site to test the live calculator experience. + +--- + +## CLI Commands Reference + +| Command | Description | +|---------|-------------| +| `npm run dev` | Start local dev server (`wix dev`) | +| `npm run build` | Build the app (`wix build`) | +| `npm run preview` | Deploy preview version for testing on a site | +| `npm run release` | Release a new app version | +| `npx wix login` | Authenticate CLI with your Wix account | +| `npx wix whoami` | Show logged-in account | +| `npx wix generate` | Scaffold a new extension | +| `npx wix generate manifest` | Regenerate auto-generated manifest after manual component changes | +| `wix skills update` | Update Wix Skills to latest version | +| `npx skills add wix/skills` | Add Wix Skills to a project | + +--- + +## Resources + +### Documentation + +- [About Editor React Components](https://dev.wix.com/docs/build-apps/develop-your-app/extensions/site-extensions/editor-react-components/about-editor-react-components) +- [Add an Editor React Component with the CLI](https://dev.wix.com/docs/build-apps/develop-your-app/develop-an-app-with-the-cli/supported-extensions/site/editor-react-components/add-an-editor-react-component-extension-with-the-wix-cli) +- [About Auto Panels](https://dev.wix.com/docs/build-apps/develop-your-app/extensions/site-extensions/editor-react-components/auto-panels/about-auto-panels) +- [About the Manifest](https://dev.wix.com/docs/build-apps/develop-your-app/extensions/site-extensions/editor-react-components/manifest-reference/about-the-manifest) +- [About Wix Harmony and Apps](https://dev.wix.com/docs/build-apps/get-started/overview/about-wix-harmony-and-apps) +- [Wix CLI documentation](https://dev.wix.com/docs/wix-cli/guides/about-the-wix-cli) + +### Video + +- [Create Editor React Component Extension](https://youtu.be/6wBiPGc0U3o) — full workflow from app creation to release (Wix for Developers) + +### AI tools + +- [About Wix Skills](https://dev.wix.com/docs/api-reference/articles/ai-tools/about-wix-skills) +- [About the Wix MCP](https://dev.wix.com/docs/api-reference/articles/ai-tools/about-the-wix-mcp) +- [Wix Skills repository](https://github.com/wix/skills) + +### Related example + +- [CLI App - FAQ manager](../CLI%20App%20-%20FAQ%20manager/) — demonstrates data collections, API routes, dashboard UI, and a custom element site widget diff --git a/CLI App - Calculator Form/astro.config.mjs b/CLI App - Calculator Form/astro.config.mjs new file mode 100644 index 0000000..5c2e60c --- /dev/null +++ b/CLI App - Calculator Form/astro.config.mjs @@ -0,0 +1,14 @@ +// @ts-check +import { defineConfig } from 'astro/config'; +import wix from '@wix/astro'; +import react from "@astrojs/react"; +import cloudflare from "@astrojs/cloudflare"; + +export default defineConfig({ + output: "server", + adapter: cloudflare(), + integrations: [wix(), react()], + image: { domains: ["static.wixstatic.com"] }, + security: { checkOrigin: false }, + devToolbar: { enabled: false } +}); diff --git a/CLI App - Calculator Form/package-lock.json b/CLI App - Calculator Form/package-lock.json new file mode 100644 index 0000000..9dcabe9 --- /dev/null +++ b/CLI App - Calculator Form/package-lock.json @@ -0,0 +1,14050 @@ +{ + "name": "calculator-form", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "calculator-form", + "version": "1.0.0", + "dependencies": { + "@wix/astro": "^2.38.0", + "@wix/dashboard": "^1.3.43", + "@wix/design-system": "^1.154.0", + "@wix/editor-react-types": "^1.0.8", + "@wix/essentials": "^0.1.23", + "@wix/react-component-schema": "^1.0.0", + "@wix/react-component-utils": "^1.7.0", + "astro": "^5.8.0", + "classnames": "^2.3.2", + "typescript": "^5.8.3" + }, + "devDependencies": { + "@astrojs/check": "^0.9.9", + "@astrojs/cloudflare": "^12.5.3", + "@astrojs/react": "^4.3.0", + "@types/react": "^18.3.1", + "@types/react-dom": "^18.3.1", + "@wix/cli": "^1.1.135", + "@wix/sdk-types": "^1.0.0", + "react": "^18.3.1", + "react-dom": "^18.3.1" + } + }, + "node_modules/@astrojs/check": { + "version": "0.9.9", + "resolved": "https://registry.npmjs.org/@astrojs/check/-/check-0.9.9.tgz", + "integrity": "sha512-A5UW8uIuErLWEoRQvzgXpO1gTjUFtK8r7nU2Z7GewAMxUb7bPvpk11qaKKgxqXlHJWlAvaaxy+Xg28A6bmQ1Tg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@astrojs/language-server": "^2.16.7", + "chokidar": "^4.0.3", + "kleur": "^4.1.5", + "yargs": "^17.7.2" + }, + "bin": { + "astro-check": "bin/astro-check.js" + }, + "peerDependencies": { + "typescript": "^5.0.0 || ^6.0.0" + } + }, + "node_modules/@astrojs/cloudflare": { + "version": "12.6.13", + "resolved": "https://registry.npmjs.org/@astrojs/cloudflare/-/cloudflare-12.6.13.tgz", + "integrity": "sha512-oKaCyiovyQr183r9U93787Ju1zwk+rRMgPnLTwCLckHmOUK7sltA1Gp4LSGt8oNMgqQS6jR7uRdfQ/NPul37QA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@astrojs/internal-helpers": "0.7.6", + "@astrojs/underscore-redirects": "1.0.0", + "@cloudflare/workers-types": "^4.20260116.0", + "tinyglobby": "^0.2.15", + "vite": "^6.4.1", + "wrangler": "4.59.2" + }, + "peerDependencies": { + "astro": "^5.7.0" + } + }, + "node_modules/@astrojs/compiler": { + "version": "2.13.1", + "resolved": "https://registry.npmjs.org/@astrojs/compiler/-/compiler-2.13.1.tgz", + "integrity": "sha512-f3FN83d2G/v32ipNClRKgYv30onQlMZX1vCeZMjPsMMPl1mDpmbl0+N5BYo4S/ofzqJyS5hvwacEo0CCVDn/Qg==", + "license": "MIT" + }, + "node_modules/@astrojs/internal-helpers": { + "version": "0.7.6", + "resolved": "https://registry.npmjs.org/@astrojs/internal-helpers/-/internal-helpers-0.7.6.tgz", + "integrity": "sha512-GOle7smBWKfMSP8osUIGOlB5kaHdQLV3foCsf+5Q9Wsuu+C6Fs3Ez/ttXmhjZ1HkSgsogcM1RXSjjOVieHq16Q==", + "license": "MIT" + }, + "node_modules/@astrojs/language-server": { + "version": "2.16.10", + "resolved": "https://registry.npmjs.org/@astrojs/language-server/-/language-server-2.16.10.tgz", + "integrity": "sha512-87VQ/5GSdHlRnUA+hGuerYyIGAj+9RbZmATyuKLEUePinUXhQ5YkRnRrHhOD9sSi5JOErLjrLkHnfZFEvGrV8w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@astrojs/compiler": "^2.13.1", + "@astrojs/yaml2ts": "^0.2.4", + "@jridgewell/sourcemap-codec": "^1.5.5", + "@volar/kit": "~2.4.28", + "@volar/language-core": "~2.4.28", + "@volar/language-server": "~2.4.28", + "@volar/language-service": "~2.4.28", + "muggle-string": "^0.4.1", + "tinyglobby": "^0.2.16", + "volar-service-css": "0.0.70", + "volar-service-emmet": "0.0.70", + "volar-service-html": "0.0.70", + "volar-service-prettier": "0.0.70", + "volar-service-typescript": "0.0.70", + "volar-service-typescript-twoslash-queries": "0.0.70", + "volar-service-yaml": "0.0.70", + "vscode-html-languageservice": "^5.6.2", + "vscode-uri": "^3.1.0" + }, + "bin": { + "astro-ls": "bin/nodeServer.js" + }, + "peerDependencies": { + "prettier": "^3.0.0", + "prettier-plugin-astro": ">=0.11.0" + }, + "peerDependenciesMeta": { + "prettier": { + "optional": true + }, + "prettier-plugin-astro": { + "optional": true + } + } + }, + "node_modules/@astrojs/markdown-remark": { + "version": "6.3.11", + "resolved": "https://registry.npmjs.org/@astrojs/markdown-remark/-/markdown-remark-6.3.11.tgz", + "integrity": "sha512-hcaxX/5aC6lQgHeGh1i+aauvSwIT6cfyFjKWvExYSxUhZZBBdvCliOtu06gbQyhbe0pGJNoNmqNlQZ5zYUuIyQ==", + "license": "MIT", + "dependencies": { + "@astrojs/internal-helpers": "0.7.6", + "@astrojs/prism": "3.3.0", + "github-slugger": "^2.0.0", + "hast-util-from-html": "^2.0.3", + "hast-util-to-text": "^4.0.2", + "import-meta-resolve": "^4.2.0", + "js-yaml": "^4.1.1", + "mdast-util-definitions": "^6.0.0", + "rehype-raw": "^7.0.0", + "rehype-stringify": "^10.0.1", + "remark-gfm": "^4.0.1", + "remark-parse": "^11.0.0", + "remark-rehype": "^11.1.2", + "remark-smartypants": "^3.0.2", + "shiki": "^3.21.0", + "smol-toml": "^1.6.0", + "unified": "^11.0.5", + "unist-util-remove-position": "^5.0.0", + "unist-util-visit": "^5.0.0", + "unist-util-visit-parents": "^6.0.2", + "vfile": "^6.0.3" + } + }, + "node_modules/@astrojs/prism": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/@astrojs/prism/-/prism-3.3.0.tgz", + "integrity": "sha512-q8VwfU/fDZNoDOf+r7jUnMC2//H2l0TuQ6FkGJL8vD8nw/q5KiL3DS1KKBI3QhI9UQhpJ5dc7AtqfbXWuOgLCQ==", + "license": "MIT", + "dependencies": { + "prismjs": "^1.30.0" + }, + "engines": { + "node": "18.20.8 || ^20.3.0 || >=22.0.0" + } + }, + "node_modules/@astrojs/react": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/@astrojs/react/-/react-4.4.2.tgz", + "integrity": "sha512-1tl95bpGfuaDMDn8O3x/5Dxii1HPvzjvpL2YTuqOOrQehs60I2DKiDgh1jrKc7G8lv+LQT5H15V6QONQ+9waeQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitejs/plugin-react": "^4.7.0", + "ultrahtml": "^1.6.0", + "vite": "^6.4.1" + }, + "engines": { + "node": "18.20.8 || ^20.3.0 || >=22.0.0" + }, + "peerDependencies": { + "@types/react": "^17.0.50 || ^18.0.21 || ^19.0.0", + "@types/react-dom": "^17.0.17 || ^18.0.6 || ^19.0.0", + "react": "^17.0.2 || ^18.0.0 || ^19.0.0", + "react-dom": "^17.0.2 || ^18.0.0 || ^19.0.0" + } + }, + "node_modules/@astrojs/telemetry": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/@astrojs/telemetry/-/telemetry-3.3.0.tgz", + "integrity": "sha512-UFBgfeldP06qu6khs/yY+q1cDAaArM2/7AEIqQ9Cuvf7B1hNLq0xDrZkct+QoIGyjq56y8IaE2I3CTvG99mlhQ==", + "license": "MIT", + "dependencies": { + "ci-info": "^4.2.0", + "debug": "^4.4.0", + "dlv": "^1.1.3", + "dset": "^3.1.4", + "is-docker": "^3.0.0", + "is-wsl": "^3.1.0", + "which-pm-runs": "^1.1.0" + }, + "engines": { + "node": "18.20.8 || ^20.3.0 || >=22.0.0" + } + }, + "node_modules/@astrojs/underscore-redirects": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@astrojs/underscore-redirects/-/underscore-redirects-1.0.0.tgz", + "integrity": "sha512-qZxHwVnmb5FXuvRsaIGaqWgnftjCuMY+GSbaVZdBmE4j8AfgPqKPxYp8SUERyJcjpKCEmO4wD6ybuGH8A2kVRQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@astrojs/yaml2ts": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/@astrojs/yaml2ts/-/yaml2ts-0.2.4.tgz", + "integrity": "sha512-8oddpOae35pJsXPQXhTkM0ypfKPskVsh2bCxRtbf7e+/Epw2nReakFYpLKjZMEr75CsoF203PMnCocpfz0s69A==", + "dev": true, + "license": "MIT", + "dependencies": { + "yaml": "^2.8.3" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.7.tgz", + "integrity": "sha512-Aup7aUOfpbAUg2ROOJN6Iw5f9DMBlzu0mIkm/malLQFN/YQgO48wCj0Kxa3sEHJvPVFg7siR+qRInwXd2qhQKw==", + "license": "MIT", + "dependencies": { + "@babel/helper-validator-identifier": "^7.29.7", + "js-tokens": "^4.0.0", + "picocolors": "^1.1.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.29.7.tgz", + "integrity": "sha512-locTkQyKvwIEgBzVrn8693ebc97F2U8ZHjbXwDXJ5Fn2TCpNwTlKcaKLkdHop5c/icOFE7qt7Q9JC5hnKNa6Gg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.29.7.tgz", + "integrity": "sha512-RgHBCvtjbOK2gXSNBNIkNoEc9qoVEtau3hj8gEqKQuL3HZAibKarWFEI3Lfm6EYKkLalOh8eSrj9b+ch9H/VBA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.29.7", + "@babel/generator": "^7.29.7", + "@babel/helper-compilation-targets": "^7.29.7", + "@babel/helper-module-transforms": "^7.29.7", + "@babel/helpers": "^7.29.7", + "@babel/parser": "^7.29.7", + "@babel/template": "^7.29.7", + "@babel/traverse": "^7.29.7", + "@babel/types": "^7.29.7", + "@jridgewell/remapping": "^2.3.5", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@babel/generator": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.29.7.tgz", + "integrity": "sha512-DkXD5OJQaAQIdZ1bt3UZdEnHAn9Imd3IVBdX03UFe+ony9Ojw5pzr9YVKGDY1jt+Gcn/FnGkNf8r+Vj5NOJWtQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.29.7", + "@babel/types": "^7.29.7", + "@jridgewell/gen-mapping": "^0.3.12", + "@jridgewell/trace-mapping": "^0.3.28", + "jsesc": "^3.0.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.29.7.tgz", + "integrity": "sha512-wem6WaBj4NaVYVdNhLPPVacES6ZJ+KBBfSkTMD3YZxbP3rm3Di85tJU5ljaUNhaOynt+Aj0xruhYuzQBt8n71g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/compat-data": "^7.29.7", + "@babel/helper-validator-option": "^7.29.7", + "browserslist": "^4.24.0", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-globals": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.29.7.tgz", + "integrity": "sha512-3nQVUAtvkKH9zahfWgw96Jc/uFOmjACE1kQz82E2lqWmHBgjzbNlsC22nuQTfahmWeQtTq5nQ/4Nnd2A1wj4zA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.29.7.tgz", + "integrity": "sha512-ejHwrQQYcm9xnTivShn2IDOlIzInN34AXskvq9QicvCtEzq1Vzclu/tKF8Jq1Cg8JG2GL6/EmjgsCT7lXepE3g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.29.7", + "@babel/types": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.29.7.tgz", + "integrity": "sha512-UPUVSyXbOh627KiCIGQSgwWzGeBKLkaJ9PJEdrngIwMSzxLR4jS4+f1f1jb7VzBbg8nFLaYotvVPFCTqdrmTAg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-module-imports": "^7.29.7", + "@babel/helper-validator-identifier": "^7.29.7", + "@babel/traverse": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-plugin-utils": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.29.7.tgz", + "integrity": "sha512-G7sHYigPY17oO5SYWnfD/0MTBwVR781S/JI643e/JhUYgVgWE/61SoW3NH9KWUKyKq5LVh3npif99Wkt6j86Jw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.29.7.tgz", + "integrity": "sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.29.7.tgz", + "integrity": "sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.29.7.tgz", + "integrity": "sha512-N9ZErrD+yW5geCDtBqnOoxmR8+tNKiGuxKlDpuJxfsqpa2dFcexaziGAE/qoHLiDDreVNMupxGmSoNlyvsA3gw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.29.7.tgz", + "integrity": "sha512-1k2lAGRMfHTcwuNYcCNUmaUffmQv8KWMfh2iJUUeRlwlwH4FdNG7mfPI10NPfLHJFThE4Tyr4mv7kTNZOiPuBg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/template": "^7.29.7", + "@babel/types": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.7.tgz", + "integrity": "sha512-hnORnjP/1P/zFEndoeX+n+t1RwWRJiJpM/jO7FW32Kn9r5+sJB2JWOdYo4L6k78j15eCwY3Gm/7364B1EMwtNg==", + "license": "MIT", + "dependencies": { + "@babel/types": "^7.29.7" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx-self": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.29.7.tgz", + "integrity": "sha512-TL0hMc9xzy86VD31nUiwzd5otRAcyEPcsegCxolO0PvcXuH1v0kECe/UIznYFihpkvU5wg/jk4v0TTEFfm53fw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx-source": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.29.7.tgz", + "integrity": "sha512-06IyK09H3wi4cGbhDBwp5gUGo0IKtnYa8tyTiephirPCK6fbobVGiXMMI5zLQ4aKEYP3wZ3ArU44o+8KMrSG/Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/runtime": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.29.7.tgz", + "integrity": "sha512-Nq8OhGWiZIZGV6hLHoyAKLLcJihP/xFeBMGJoUrxTX2psI8dCifzLhZISFb+VWS3wFMRDmCGw5R+dOySCqPLhw==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/template": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.29.7.tgz", + "integrity": "sha512-puq+Gf35oI24FeN11LkoUQFqv9uwNeWpxXZi/Ji3rRIoKAzKnxRaZ+Gkj0vKS9ZCiTESfng1N9LyOyXvo+m+Gg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.29.7", + "@babel/parser": "^7.29.7", + "@babel/types": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.29.7.tgz", + "integrity": "sha512-EhlfNQtZ+NK22w5BM61ciuiq1m58ed33Wr1Xan//ZRTy6hgjnwyCffRYwzsGXdASJSUJ1guZILsErh1eQcl+zw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.29.7", + "@babel/generator": "^7.29.7", + "@babel/helper-globals": "^7.29.7", + "@babel/parser": "^7.29.7", + "@babel/template": "^7.29.7", + "@babel/types": "^7.29.7", + "debug": "^4.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/types": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.7.tgz", + "integrity": "sha512-4zBIxpPzowiZpusoFkyGVwakdRJUyuH5PxQ/PrqghfdFWWasvnCdPfQXHrenDai+gyLARulZjZowCOj6fjT4pA==", + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.29.7", + "@babel/helper-validator-identifier": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@capsizecss/unpack": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@capsizecss/unpack/-/unpack-4.0.0.tgz", + "integrity": "sha512-VERIM64vtTP1C4mxQ5thVT9fK0apjPFobqybMtA1UdUujWka24ERHbRHFGmpbbhp73MhV+KSsHQH9C6uOTdEQA==", + "license": "MIT", + "dependencies": { + "fontkitten": "^1.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@cloudflare/kv-asset-handler": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/@cloudflare/kv-asset-handler/-/kv-asset-handler-0.4.2.tgz", + "integrity": "sha512-SIOD2DxrRRwQ+jgzlXCqoEFiKOFqaPjhnNTGKXSRLvp1HiOvapLaFG2kEr9dYQTYe8rKrd9uvDUzmAITeNyaHQ==", + "dev": true, + "license": "MIT OR Apache-2.0", + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@cloudflare/unenv-preset": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/@cloudflare/unenv-preset/-/unenv-preset-2.10.0.tgz", + "integrity": "sha512-/uII4vLQXhzCAZzEVeYAjFLBNg2nqTJ1JGzd2lRF6ItYe6U2zVoYGfeKpGx/EkBF6euiU+cyBXgMdtJih+nQ6g==", + "dev": true, + "license": "MIT OR Apache-2.0", + "peerDependencies": { + "unenv": "2.0.0-rc.24", + "workerd": "^1.20251221.0" + }, + "peerDependenciesMeta": { + "workerd": { + "optional": true + } + } + }, + "node_modules/@cloudflare/workerd-darwin-64": { + "version": "1.20260114.0", + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-darwin-64/-/workerd-darwin-64-1.20260114.0.tgz", + "integrity": "sha512-HNlsRkfNgardCig2P/5bp/dqDECsZ4+NU5XewqArWxMseqt3C5daSuptI620s4pn7Wr0ZKg7jVLH0PDEBkA+aA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=16" + } + }, + "node_modules/@cloudflare/workerd-darwin-arm64": { + "version": "1.20260114.0", + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-darwin-arm64/-/workerd-darwin-arm64-1.20260114.0.tgz", + "integrity": "sha512-qyE1UdFnAlxzb+uCfN/d9c8icch7XRiH49/DjoqEa+bCDihTuRS7GL1RmhVIqHJhb3pX3DzxmKgQZBDBL83Inw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=16" + } + }, + "node_modules/@cloudflare/workerd-linux-64": { + "version": "1.20260114.0", + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-linux-64/-/workerd-linux-64-1.20260114.0.tgz", + "integrity": "sha512-Z0BLvAj/JPOabzads2ddDEfgExWTlD22pnwsuNbPwZAGTSZeQa3Y47eGUWyHk+rSGngknk++S7zHTGbKuG7RRg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=16" + } + }, + "node_modules/@cloudflare/workerd-linux-arm64": { + "version": "1.20260114.0", + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-linux-arm64/-/workerd-linux-arm64-1.20260114.0.tgz", + "integrity": "sha512-kPUmEtUxUWlr9PQ64kuhdK0qyo8idPe5IIXUgi7xCD7mDd6EOe5J7ugDpbfvfbYKEjx4DpLvN2t45izyI/Sodw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=16" + } + }, + "node_modules/@cloudflare/workerd-windows-64": { + "version": "1.20260114.0", + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-windows-64/-/workerd-windows-64-1.20260114.0.tgz", + "integrity": "sha512-MJnKgm6i1jZGyt2ZHQYCnRlpFTEZcK2rv9y7asS3KdVEXaDgGF8kOns5u6YL6/+eMogfZuHRjfDS+UqRTUYIFA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=16" + } + }, + "node_modules/@cloudflare/workers-types": { + "version": "4.20260602.1", + "resolved": "https://registry.npmjs.org/@cloudflare/workers-types/-/workers-types-4.20260602.1.tgz", + "integrity": "sha512-0VssYYXHUn4VR1BaV+GXfhFpI53P2f6AIi17qyA9lQFyTs/u5ZF6IDPda2enDTIPFz/02872RM8CYVlXvRKtUA==", + "dev": true, + "license": "MIT OR Apache-2.0" + }, + "node_modules/@cspotcode/source-map-support": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", + "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/trace-mapping": "0.3.9" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@cspotcode/source-map-support/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", + "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, + "node_modules/@emmetio/abbreviation": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/@emmetio/abbreviation/-/abbreviation-2.3.3.tgz", + "integrity": "sha512-mgv58UrU3rh4YgbE/TzgLQwJ3pFsHHhCLqY20aJq+9comytTXUDNGG/SMtSeMJdkpxgXSXunBGLD8Boka3JyVA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@emmetio/scanner": "^1.0.4" + } + }, + "node_modules/@emmetio/css-abbreviation": { + "version": "2.1.8", + "resolved": "https://registry.npmjs.org/@emmetio/css-abbreviation/-/css-abbreviation-2.1.8.tgz", + "integrity": "sha512-s9yjhJ6saOO/uk1V74eifykk2CBYi01STTK3WlXWGOepyKa23ymJ053+DNQjpFcy1ingpaO7AxCcwLvHFY9tuw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@emmetio/scanner": "^1.0.4" + } + }, + "node_modules/@emmetio/css-parser": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@emmetio/css-parser/-/css-parser-0.4.1.tgz", + "integrity": "sha512-2bC6m0MV/voF4CTZiAbG5MWKbq5EBmDPKu9Sb7s7nVcEzNQlrZP6mFFFlIaISM8X6514H9shWMme1fCm8cWAfQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@emmetio/stream-reader": "^2.2.0", + "@emmetio/stream-reader-utils": "^0.1.0" + } + }, + "node_modules/@emmetio/html-matcher": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@emmetio/html-matcher/-/html-matcher-1.3.0.tgz", + "integrity": "sha512-NTbsvppE5eVyBMuyGfVu2CRrLvo7J4YHb6t9sBFLyY03WYhXET37qA4zOYUjBWFCRHO7pS1B9khERtY0f5JXPQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "@emmetio/scanner": "^1.0.0" + } + }, + "node_modules/@emmetio/scanner": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@emmetio/scanner/-/scanner-1.0.4.tgz", + "integrity": "sha512-IqRuJtQff7YHHBk4G8YZ45uB9BaAGcwQeVzgj/zj8/UdOhtQpEIupUhSk8dys6spFIWVZVeK20CzGEnqR5SbqA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@emmetio/stream-reader": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@emmetio/stream-reader/-/stream-reader-2.2.0.tgz", + "integrity": "sha512-fXVXEyFA5Yv3M3n8sUGT7+fvecGrZP4k6FnWWMSZVQf69kAq0LLpaBQLGcPR30m3zMmKYhECP4k/ZkzvhEW5kw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@emmetio/stream-reader-utils": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/@emmetio/stream-reader-utils/-/stream-reader-utils-0.1.0.tgz", + "integrity": "sha512-ZsZ2I9Vzso3Ho/pjZFsmmZ++FWeEd/txqybHTm4OgaZzdS8V9V/YYWQwg5TC38Z7uLWUV1vavpLLbjJtKubR1A==", + "dev": true, + "license": "MIT" + }, + "node_modules/@emnapi/runtime": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.10.0.tgz", + "integrity": "sha512-ewvYlk86xUoGI0zQRNq/mC+16R1QeDlKQy21Ki3oSYXNgLb45GV1P6A0M+/s6nyCuNDqe5VpaY84BzXGwVbwFA==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@emotion/is-prop-valid": { + "version": "0.8.8", + "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-0.8.8.tgz", + "integrity": "sha512-u5WtneEAr5IDG2Wv65yhunPSMLIpuKsbuOktRojfrEiEvRyC85LgPMZI63cr7NUqT8ZIGdSVg8ZKGxIug4lXcA==", + "license": "MIT", + "optional": true, + "dependencies": { + "@emotion/memoize": "0.7.4" + } + }, + "node_modules/@emotion/memoize": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.7.4.tgz", + "integrity": "sha512-Ja/Vfqe3HpuzRsG1oBtWTHk2PGZ7GR+2Vz5iYGelAw8dx32K0y7PjVuxK6z1nMpZOqAFsRUPCkK1YjJ56qJlgw==", + "license": "MIT", + "optional": true + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.7.tgz", + "integrity": "sha512-EKX3Qwmhz1eMdEJokhALr0YiD0lhQNwDqkPYyPhiSwKrh7/4KRjQc04sZ8db+5DVVnZ1LmbNDI1uAMPEUBnQPg==", + "cpu": [ + "ppc64" + ], + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.27.7.tgz", + "integrity": "sha512-jbPXvB4Yj2yBV7HUfE2KHe4GJX51QplCN1pGbYjvsyCZbQmies29EoJbkEc+vYuU5o45AfQn37vZlyXy4YJ8RQ==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.27.7.tgz", + "integrity": "sha512-62dPZHpIXzvChfvfLJow3q5dDtiNMkwiRzPylSCfriLvZeq0a1bWChrGx/BbUbPwOrsWKMn8idSllklzBy+dgQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.27.7.tgz", + "integrity": "sha512-x5VpMODneVDb70PYV2VQOmIUUiBtY3D3mPBG8NxVk5CogneYhkR7MmM3yR/uMdITLrC1ml/NV1rj4bMJuy9MCg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.27.7.tgz", + "integrity": "sha512-5lckdqeuBPlKUwvoCXIgI2D9/ABmPq3Rdp7IfL70393YgaASt7tbju3Ac+ePVi3KDH6N2RqePfHnXkaDtY9fkw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.27.7.tgz", + "integrity": "sha512-rYnXrKcXuT7Z+WL5K980jVFdvVKhCHhUwid+dDYQpH+qu+TefcomiMAJpIiC2EM3Rjtq0sO3StMV/+3w3MyyqQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.7.tgz", + "integrity": "sha512-B48PqeCsEgOtzME2GbNM2roU29AMTuOIN91dsMO30t+Ydis3z/3Ngoj5hhnsOSSwNzS+6JppqWsuhTp6E82l2w==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.27.7.tgz", + "integrity": "sha512-jOBDK5XEjA4m5IJK3bpAQF9/Lelu/Z9ZcdhTRLf4cajlB+8VEhFFRjWgfy3M1O4rO2GQ/b2dLwCUGpiF/eATNQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.27.7.tgz", + "integrity": "sha512-RkT/YXYBTSULo3+af8Ib0ykH8u2MBh57o7q/DAs3lTJlyVQkgQvlrPTnjIzzRPQyavxtPtfg0EopvDyIt0j1rA==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.27.7.tgz", + "integrity": "sha512-RZPHBoxXuNnPQO9rvjh5jdkRmVizktkT7TCDkDmQ0W2SwHInKCAV95GRuvdSvA7w4VMwfCjUiPwDi0ZO6Nfe9A==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.27.7.tgz", + "integrity": "sha512-GA48aKNkyQDbd3KtkplYWT102C5sn/EZTY4XROkxONgruHPU72l+gW+FfF8tf2cFjeHaRbWpOYa/uRBz/Xq1Pg==", + "cpu": [ + "ia32" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.27.7.tgz", + "integrity": "sha512-a4POruNM2oWsD4WKvBSEKGIiWQF8fZOAsycHOt6JBpZ+JN2n2JH9WAv56SOyu9X5IqAjqSIPTaJkqN8F7XOQ5Q==", + "cpu": [ + "loong64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.27.7.tgz", + "integrity": "sha512-KabT5I6StirGfIz0FMgl1I+R1H73Gp0ofL9A3nG3i/cYFJzKHhouBV5VWK1CSgKvVaG4q1RNpCTR2LuTVB3fIw==", + "cpu": [ + "mips64el" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.27.7.tgz", + "integrity": "sha512-gRsL4x6wsGHGRqhtI+ifpN/vpOFTQtnbsupUF5R5YTAg+y/lKelYR1hXbnBdzDjGbMYjVJLJTd2OFmMewAgwlQ==", + "cpu": [ + "ppc64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.27.7.tgz", + "integrity": "sha512-hL25LbxO1QOngGzu2U5xeXtxXcW+/GvMN3ejANqXkxZ/opySAZMrc+9LY/WyjAan41unrR3YrmtTsUpwT66InQ==", + "cpu": [ + "riscv64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.27.7.tgz", + "integrity": "sha512-2k8go8Ycu1Kb46vEelhu1vqEP+UeRVj2zY1pSuPdgvbd5ykAw82Lrro28vXUrRmzEsUV0NzCf54yARIK8r0fdw==", + "cpu": [ + "s390x" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.27.7.tgz", + "integrity": "sha512-hzznmADPt+OmsYzw1EE33ccA+HPdIqiCRq7cQeL1Jlq2gb1+OyWBkMCrYGBJ+sxVzve2ZJEVeePbLM2iEIZSxA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.7.tgz", + "integrity": "sha512-b6pqtrQdigZBwZxAn1UpazEisvwaIDvdbMbmrly7cDTMFnw/+3lVxxCTGOrkPVnsYIosJJXAsILG9XcQS+Yu6w==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.27.7.tgz", + "integrity": "sha512-OfatkLojr6U+WN5EDYuoQhtM+1xco+/6FSzJJnuWiUw5eVcicbyK3dq5EeV/QHT1uy6GoDhGbFpprUiHUYggrw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.7.tgz", + "integrity": "sha512-AFuojMQTxAz75Fo8idVcqoQWEHIXFRbOc1TrVcFSgCZtQfSdc1RXgB3tjOn/krRHENUB4j00bfGjyl2mJrU37A==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.27.7.tgz", + "integrity": "sha512-+A1NJmfM8WNDv5CLVQYJ5PshuRm/4cI6WMZRg1by1GwPIQPCTs1GLEUHwiiQGT5zDdyLiRM/l1G0Pv54gvtKIg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openharmony-arm64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.7.tgz", + "integrity": "sha512-+KrvYb/C8zA9CU/g0sR6w2RBw7IGc5J2BPnc3dYc5VJxHCSF1yNMxTV5LQ7GuKteQXZtspjFbiuW5/dOj7H4Yw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.27.7.tgz", + "integrity": "sha512-ikktIhFBzQNt/QDyOL580ti9+5mL/YZeUPKU2ivGtGjdTYoqz6jObj6nOMfhASpS4GU4Q/Clh1QtxWAvcYKamA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.27.7.tgz", + "integrity": "sha512-7yRhbHvPqSpRUV7Q20VuDwbjW5kIMwTHpptuUzV+AA46kiPze5Z7qgt6CLCK3pWFrHeNfDd1VKgyP4O+ng17CA==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.27.7.tgz", + "integrity": "sha512-SmwKXe6VHIyZYbBLJrhOoCJRB/Z1tckzmgTLfFYOfpMAx63BJEaL9ExI8x7v0oAO3Zh6D/Oi1gVxEYr5oUCFhw==", + "cpu": [ + "ia32" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.27.7.tgz", + "integrity": "sha512-56hiAJPhwQ1R4i+21FVF7V8kSD5zZTdHcVuRFMW0hn753vVfQN8xlx4uOPT4xoGH0Z/oVATuR82AiqSTDIpaHg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@floating-ui/core": { + "version": "1.7.5", + "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.7.5.tgz", + "integrity": "sha512-1Ih4WTWyw0+lKyFMcBHGbb5U5FtuHJuujoyyr5zTaWS5EYMeT6Jb2AuDeftsCsEuchO+mM2ij5+q9crhydzLhQ==", + "license": "MIT", + "dependencies": { + "@floating-ui/utils": "^0.2.11" + } + }, + "node_modules/@floating-ui/dom": { + "version": "1.7.6", + "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.7.6.tgz", + "integrity": "sha512-9gZSAI5XM36880PPMm//9dfiEngYoC6Am2izES1FF406YFsjvyBMmeJ2g4SAju3xWwtuynNRFL2s9hgxpLI5SQ==", + "license": "MIT", + "dependencies": { + "@floating-ui/core": "^1.7.5", + "@floating-ui/utils": "^0.2.11" + } + }, + "node_modules/@floating-ui/react": { + "version": "0.26.28", + "resolved": "https://registry.npmjs.org/@floating-ui/react/-/react-0.26.28.tgz", + "integrity": "sha512-yORQuuAtVpiRjpMhdc0wJj06b9JFjrYF4qp96j++v2NBpbi6SEGF7donUJ3TMieerQ6qVkAv1tgr7L4r5roTqw==", + "license": "MIT", + "dependencies": { + "@floating-ui/react-dom": "^2.1.2", + "@floating-ui/utils": "^0.2.8", + "tabbable": "^6.0.0" + }, + "peerDependencies": { + "react": ">=16.8.0", + "react-dom": ">=16.8.0" + } + }, + "node_modules/@floating-ui/react-dom": { + "version": "2.1.8", + "resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.1.8.tgz", + "integrity": "sha512-cC52bHwM/n/CxS87FH0yWdngEZrjdtLW/qVruo68qg+prK7ZQ4YGdut2GyDVpoGeAYe/h899rVeOVm6Oi40k2A==", + "license": "MIT", + "dependencies": { + "@floating-ui/dom": "^1.7.6" + }, + "peerDependencies": { + "react": ">=16.8.0", + "react-dom": ">=16.8.0" + } + }, + "node_modules/@floating-ui/utils": { + "version": "0.2.11", + "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.11.tgz", + "integrity": "sha512-RiB/yIh78pcIxl6lLMG0CgBXAZ2Y0eVHqMPYugu+9U0AeT6YBeiJpf7lbdJNIugFP5SIjwNRgo4DhR1Qxi26Gg==", + "license": "MIT" + }, + "node_modules/@formatjs/ecma402-abstract": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/@formatjs/ecma402-abstract/-/ecma402-abstract-2.3.6.tgz", + "integrity": "sha512-HJnTFeRM2kVFVr5gr5kH1XP6K0JcJtE7Lzvtr3FS/so5f1kpsqqqxy5JF+FRaO6H2qmcMfAUIox7AJteieRtVw==", + "license": "MIT", + "dependencies": { + "@formatjs/fast-memoize": "2.2.7", + "@formatjs/intl-localematcher": "0.6.2", + "decimal.js": "^10.4.3", + "tslib": "^2.8.0" + } + }, + "node_modules/@formatjs/fast-memoize": { + "version": "2.2.7", + "resolved": "https://registry.npmjs.org/@formatjs/fast-memoize/-/fast-memoize-2.2.7.tgz", + "integrity": "sha512-Yabmi9nSvyOMrlSeGGWDiH7rf3a7sIwplbvo/dlz9WCIjzIQAfy1RMf4S0X3yG724n5Ghu2GmEl5NJIV6O9sZQ==", + "license": "MIT", + "dependencies": { + "tslib": "^2.8.0" + } + }, + "node_modules/@formatjs/icu-messageformat-parser": { + "version": "2.11.4", + "resolved": "https://registry.npmjs.org/@formatjs/icu-messageformat-parser/-/icu-messageformat-parser-2.11.4.tgz", + "integrity": "sha512-7kR78cRrPNB4fjGFZg3Rmj5aah8rQj9KPzuLsmcSn4ipLXQvC04keycTI1F7kJYDwIXtT2+7IDEto842CfZBtw==", + "license": "MIT", + "dependencies": { + "@formatjs/ecma402-abstract": "2.3.6", + "@formatjs/icu-skeleton-parser": "1.8.16", + "tslib": "^2.8.0" + } + }, + "node_modules/@formatjs/icu-skeleton-parser": { + "version": "1.8.16", + "resolved": "https://registry.npmjs.org/@formatjs/icu-skeleton-parser/-/icu-skeleton-parser-1.8.16.tgz", + "integrity": "sha512-H13E9Xl+PxBd8D5/6TVUluSpxGNvFSlN/b3coUp0e0JpuWXXnQDiavIpY3NnvSp4xhEMoXyyBvVfdFX8jglOHQ==", + "license": "MIT", + "dependencies": { + "@formatjs/ecma402-abstract": "2.3.6", + "tslib": "^2.8.0" + } + }, + "node_modules/@formatjs/intl-localematcher": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/@formatjs/intl-localematcher/-/intl-localematcher-0.6.2.tgz", + "integrity": "sha512-XOMO2Hupl0wdd172Y06h6kLpBz6Dv+J4okPLl4LPtzbr8f66WbIoy4ev98EBuZ6ZK4h5ydTN6XneT4QVpD7cdA==", + "license": "MIT", + "dependencies": { + "tslib": "^2.8.0" + } + }, + "node_modules/@gar/promisify": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@gar/promisify/-/promisify-1.1.3.tgz", + "integrity": "sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@hypnosphi/create-react-context": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@hypnosphi/create-react-context/-/create-react-context-0.3.1.tgz", + "integrity": "sha512-V1klUed202XahrWJLLOT3EXNeCpFHCcJntdFGI15ntCwau+jfT386w7OFTMaCqOgXUH1fa0w/I1oZs+i/Rfr0A==", + "license": "MIT", + "dependencies": { + "gud": "^1.0.0", + "warning": "^4.0.3" + }, + "peerDependencies": { + "prop-types": "^15.0.0", + "react": ">=0.14.0" + } + }, + "node_modules/@img/colour": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@img/colour/-/colour-1.1.0.tgz", + "integrity": "sha512-Td76q7j57o/tLVdgS746cYARfSyxk8iEfRxewL9h4OMzYhbW4TAcppl0mT4eyqXddh6L/jwoM75mo7ixa/pCeQ==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/@img/sharp-darwin-arm64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.34.5.tgz", + "integrity": "sha512-imtQ3WMJXbMY4fxb/Ndp6HBTNVtWCUI0WdobyheGf5+ad6xX8VIDO8u2xE4qc/fr08CKG/7dDseFtn6M6g/r3w==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-darwin-arm64": "1.2.4" + } + }, + "node_modules/@img/sharp-darwin-x64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.34.5.tgz", + "integrity": "sha512-YNEFAF/4KQ/PeW0N+r+aVVsoIY0/qxxikF2SWdp+NRkmMB7y9LBZAVqQ4yhGCm/H3H270OSykqmQMKLBhBJDEw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-darwin-x64": "1.2.4" + } + }, + "node_modules/@img/sharp-libvips-darwin-arm64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.2.4.tgz", + "integrity": "sha512-zqjjo7RatFfFoP0MkQ51jfuFZBnVE2pRiaydKJ1G/rHZvnsrHAOcQALIi9sA5co5xenQdTugCvtb1cuf78Vf4g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "darwin" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-darwin-x64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.2.4.tgz", + "integrity": "sha512-1IOd5xfVhlGwX+zXv2N93k0yMONvUlANylbJw1eTah8K/Jtpi15KC+WSiaX/nBmbm2HxRM1gZ0nSdjSsrZbGKg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "darwin" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-arm": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.2.4.tgz", + "integrity": "sha512-bFI7xcKFELdiNCVov8e44Ia4u2byA+l3XtsAj+Q8tfCwO6BQ8iDojYdvoPMqsKDkuoOo+X6HZA0s0q11ANMQ8A==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-arm64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.2.4.tgz", + "integrity": "sha512-excjX8DfsIcJ10x1Kzr4RcWe1edC9PquDRRPx3YVCvQv+U5p7Yin2s32ftzikXojb1PIFc/9Mt28/y+iRklkrw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-ppc64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-ppc64/-/sharp-libvips-linux-ppc64-1.2.4.tgz", + "integrity": "sha512-FMuvGijLDYG6lW+b/UvyilUWu5Ayu+3r2d1S8notiGCIyYU/76eig1UfMmkZ7vwgOrzKzlQbFSuQfgm7GYUPpA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-riscv64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-riscv64/-/sharp-libvips-linux-riscv64-1.2.4.tgz", + "integrity": "sha512-oVDbcR4zUC0ce82teubSm+x6ETixtKZBh/qbREIOcI3cULzDyb18Sr/Wcyx7NRQeQzOiHTNbZFF1UwPS2scyGA==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-s390x": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.2.4.tgz", + "integrity": "sha512-qmp9VrzgPgMoGZyPvrQHqk02uyjA0/QrTO26Tqk6l4ZV0MPWIW6LTkqOIov+J1yEu7MbFQaDpwdwJKhbJvuRxQ==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-x64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.2.4.tgz", + "integrity": "sha512-tJxiiLsmHc9Ax1bz3oaOYBURTXGIRDODBqhveVHonrHJ9/+k89qbLl0bcJns+e4t4rvaNBxaEZsFtSfAdquPrw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linuxmusl-arm64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.2.4.tgz", + "integrity": "sha512-FVQHuwx1IIuNow9QAbYUzJ+En8KcVm9Lk5+uGUQJHaZmMECZmOlix9HnH7n1TRkXMS0pGxIJokIVB9SuqZGGXw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linuxmusl-x64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.2.4.tgz", + "integrity": "sha512-+LpyBk7L44ZIXwz/VYfglaX/okxezESc6UxDSoyo2Ks6Jxc4Y7sGjpgU9s4PMgqgjj1gZCylTieNamqA1MF7Dg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-linux-arm": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.34.5.tgz", + "integrity": "sha512-9dLqsvwtg1uuXBGZKsxem9595+ujv0sJ6Vi8wcTANSFpwV/GONat5eCkzQo/1O6zRIkh0m/8+5BjrRr7jDUSZw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-arm": "1.2.4" + } + }, + "node_modules/@img/sharp-linux-arm64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.34.5.tgz", + "integrity": "sha512-bKQzaJRY/bkPOXyKx5EVup7qkaojECG6NLYswgktOZjaXecSAeCWiZwwiFf3/Y+O1HrauiE3FVsGxFg8c24rZg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-arm64": "1.2.4" + } + }, + "node_modules/@img/sharp-linux-ppc64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-ppc64/-/sharp-linux-ppc64-0.34.5.tgz", + "integrity": "sha512-7zznwNaqW6YtsfrGGDA6BRkISKAAE1Jo0QdpNYXNMHu2+0dTrPflTLNkpc8l7MUP5M16ZJcUvysVWWrMefZquA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-ppc64": "1.2.4" + } + }, + "node_modules/@img/sharp-linux-riscv64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-riscv64/-/sharp-linux-riscv64-0.34.5.tgz", + "integrity": "sha512-51gJuLPTKa7piYPaVs8GmByo7/U7/7TZOq+cnXJIHZKavIRHAP77e3N2HEl3dgiqdD/w0yUfiJnII77PuDDFdw==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-riscv64": "1.2.4" + } + }, + "node_modules/@img/sharp-linux-s390x": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.34.5.tgz", + "integrity": "sha512-nQtCk0PdKfho3eC5MrbQoigJ2gd1CgddUMkabUj+rBevs8tZ2cULOx46E7oyX+04WGfABgIwmMC0VqieTiR4jg==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-s390x": "1.2.4" + } + }, + "node_modules/@img/sharp-linux-x64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.34.5.tgz", + "integrity": "sha512-MEzd8HPKxVxVenwAa+JRPwEC7QFjoPWuS5NZnBt6B3pu7EG2Ge0id1oLHZpPJdn3OQK+BQDiw9zStiHBTJQQQQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-x64": "1.2.4" + } + }, + "node_modules/@img/sharp-linuxmusl-arm64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.34.5.tgz", + "integrity": "sha512-fprJR6GtRsMt6Kyfq44IsChVZeGN97gTD331weR1ex1c1rypDEABN6Tm2xa1wE6lYb5DdEnk03NZPqA7Id21yg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linuxmusl-arm64": "1.2.4" + } + }, + "node_modules/@img/sharp-linuxmusl-x64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.34.5.tgz", + "integrity": "sha512-Jg8wNT1MUzIvhBFxViqrEhWDGzqymo3sV7z7ZsaWbZNDLXRJZoRGrjulp60YYtV4wfY8VIKcWidjojlLcWrd8Q==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linuxmusl-x64": "1.2.4" + } + }, + "node_modules/@img/sharp-wasm32": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.34.5.tgz", + "integrity": "sha512-OdWTEiVkY2PHwqkbBI8frFxQQFekHaSSkUIJkwzclWZe64O1X4UlUjqqqLaPbUpMOQk6FBu/HtlGXNblIs0huw==", + "cpu": [ + "wasm32" + ], + "dev": true, + "license": "Apache-2.0 AND LGPL-3.0-or-later AND MIT", + "optional": true, + "dependencies": { + "@emnapi/runtime": "^1.7.0" + }, + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-win32-arm64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-arm64/-/sharp-win32-arm64-0.34.5.tgz", + "integrity": "sha512-WQ3AgWCWYSb2yt+IG8mnC6Jdk9Whs7O0gxphblsLvdhSpSTtmu69ZG1Gkb6NuvxsNACwiPV6cNSZNzt0KPsw7g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "Apache-2.0 AND LGPL-3.0-or-later", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-win32-ia32": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.34.5.tgz", + "integrity": "sha512-FV9m/7NmeCmSHDD5j4+4pNI8Cp3aW+JvLoXcTUo0IqyjSfAZJ8dIUmijx1qaJsIiU+Hosw6xM5KijAWRJCSgNg==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "Apache-2.0 AND LGPL-3.0-or-later", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-win32-x64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.34.5.tgz", + "integrity": "sha512-+29YMsqY2/9eFEiW93eqWnuLcWcufowXewwSNIT6UwZdUUCrM3oFjMWH/Z6/TMmb4hlFenmfAVbpWeup2jryCw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0 AND LGPL-3.0-or-later", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@internationalized/date": { + "version": "3.12.2", + "resolved": "https://registry.npmjs.org/@internationalized/date/-/date-3.12.2.tgz", + "integrity": "sha512-FY1Y+H64NDs+HAF6omlnWxm3mEpfgaCSWtL5l551ZZfImA+kGjPFgrnJrGjH6lfmLL0g8Z/mBu1R3kufeCp6Jw==", + "license": "Apache-2.0", + "dependencies": { + "@swc/helpers": "^0.5.0" + } + }, + "node_modules/@internationalized/number": { + "version": "3.6.7", + "resolved": "https://registry.npmjs.org/@internationalized/number/-/number-3.6.7.tgz", + "integrity": "sha512-3ji1fcrT+FPAK86UqEhB/psHixYo6niWPJtt7+qRaYFynt/BaJG8GhAPimtWUpEiVSTq8ZM8L5psMxGquiB/Vg==", + "license": "Apache-2.0", + "dependencies": { + "@swc/helpers": "^0.5.0" + } + }, + "node_modules/@internationalized/string": { + "version": "3.2.9", + "resolved": "https://registry.npmjs.org/@internationalized/string/-/string-3.2.9.tgz", + "integrity": "sha512-kzP/M/mbQxODlmOt4bIQZ2SBVUWUSqMLXooXixnX7noche8WHaQcA+nwFN1K2KCF/cp+LDUhcJsCicwkvhD1pg==", + "license": "Apache-2.0", + "dependencies": { + "@swc/helpers": "^0.5.0" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.13", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", + "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/remapping": { + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz", + "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@npmcli/fs": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-1.1.1.tgz", + "integrity": "sha512-8KG5RD0GVP4ydEzRn/I4BNDuxDtqVbOdm8675T49OIG/NGhaK0pjPX7ZcDlvKYbA+ulvVK3ztfcF4uBdOxuJbQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "@gar/promisify": "^1.0.1", + "semver": "^7.3.5" + } + }, + "node_modules/@npmcli/fs/node_modules/semver": { + "version": "7.8.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.1.tgz", + "integrity": "sha512-rkVq3IXh+4FDGch+KwzX3aV9W3kO54GyEgpvBzSyctDA6Xtd7RJQV1xmXbeQp5v7+VzLOfVqiutSE6GICgPFvg==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@npmcli/move-file": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@npmcli/move-file/-/move-file-1.1.2.tgz", + "integrity": "sha512-1SUf/Cg2GzGDyaf15aR9St9TWlb+XvbZXWpDx8YKs7MLzMH/BCeopv+y9vzrzgkfykCGuWOlSu3mZhj2+FQcrg==", + "deprecated": "This functionality has been moved to @npmcli/fs", + "dev": true, + "license": "MIT", + "dependencies": { + "mkdirp": "^1.0.4", + "rimraf": "^3.0.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@oslojs/encoding": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@oslojs/encoding/-/encoding-1.1.0.tgz", + "integrity": "sha512-70wQhgYmndg4GCPxPPxPGevRKqTIJ2Nh4OkiMWmDAVYsTQ+Ta7Sq+rPevXyXGdzr30/qZBnyOalCszoMxlyldQ==", + "license": "MIT" + }, + "node_modules/@poppinss/colors": { + "version": "4.1.6", + "resolved": "https://registry.npmjs.org/@poppinss/colors/-/colors-4.1.6.tgz", + "integrity": "sha512-H9xkIdFswbS8n1d6vmRd8+c10t2Qe+rZITbbDHHkQixH5+2x1FDGmi/0K+WgWiqQFKPSlIYB7jlH6Kpfn6Fleg==", + "dev": true, + "license": "MIT", + "dependencies": { + "kleur": "^4.1.5" + } + }, + "node_modules/@poppinss/dumper": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/@poppinss/dumper/-/dumper-0.6.5.tgz", + "integrity": "sha512-NBdYIb90J7LfOI32dOewKI1r7wnkiH6m920puQ3qHUeZkxNkQiFnXVWoE6YtFSv6QOiPPf7ys6i+HWWecDz7sw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@poppinss/colors": "^4.1.5", + "@sindresorhus/is": "^7.0.2", + "supports-color": "^10.0.0" + } + }, + "node_modules/@poppinss/dumper/node_modules/supports-color": { + "version": "10.2.2", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-10.2.2.tgz", + "integrity": "sha512-SS+jx45GF1QjgEXQx4NJZV9ImqmO2NPz5FNsIHrsDjh2YsHnawpan7SNQ1o8NuhrbHZy9AZhIoCUiCeaW/C80g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/@poppinss/exception": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@poppinss/exception/-/exception-1.2.3.tgz", + "integrity": "sha512-dCED+QRChTVatE9ibtoaxc+WkdzOSjYTKi/+uacHWIsfodVfpsueo3+DKpgU5Px8qXjgmXkSvhXvSCz3fnP9lw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@preact/signals-core": { + "version": "1.14.2", + "resolved": "https://registry.npmjs.org/@preact/signals-core/-/signals-core-1.14.2.tgz", + "integrity": "sha512-RZHdBj9ZF4n40Rp4jS052EHHjBWf96P9oNdXPfhQTovCuWY9iQn3Gq+gOTJSgBO9A/JBuPfMOWsSX/lIU9Pc/A==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/preact" + } + }, + "node_modules/@preact/signals-react": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@preact/signals-react/-/signals-react-3.10.1.tgz", + "integrity": "sha512-42/ESNbLT2dpK/IElwo9YG0kFmFKz+pUQoAKLf59BVjSXdWMeUIm4WaVYTnC01ROuF2UDU+H3uX5fq8WreamSg==", + "license": "MIT", + "dependencies": { + "@preact/signals-core": "^1.14.2", + "use-sync-external-store": "^1.2.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/preact" + }, + "peerDependencies": { + "react": "^16.14.0 || 17.x || 18.x || 19.x" + } + }, + "node_modules/@radix-ui/primitive": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.1.3.tgz", + "integrity": "sha512-JTF99U/6XIjCBo0wqkU5sK10glYe27MRRsfwoiq5zzOEZLHU3A3KCMa5X/azekYRCJ0HlwI0crAXS/5dEHTzDg==", + "license": "MIT" + }, + "node_modules/@radix-ui/react-compose-refs": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.2.tgz", + "integrity": "sha512-z4eqJvfiNnFMHIIvXP3CY57y2WJs5g2v3X0zm9mEJkrkNv4rDxu+sg9Jh8EkXyeqBkB7SOcboo9dMVqhyrACIg==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-context": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.2.tgz", + "integrity": "sha512-jCi/QKUM2r1Ju5a3J64TH2A5SpKAgh0LpknyqdQ4m6DCV0xJ2HG1xARRwNGPQfi1SLdLWZ1OJz6F4OMBBNiGJA==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-dialog": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/@radix-ui/react-dialog/-/react-dialog-1.1.15.tgz", + "integrity": "sha512-TCglVRtzlffRNxRMEyR36DGBLJpeusFcgMVD9PZEzAKnUs1lKCgX5u9BmC2Yg+LL9MgZDugFFs1Vl+Jp4t/PGw==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-dismissable-layer": "1.1.11", + "@radix-ui/react-focus-guards": "1.1.3", + "@radix-ui/react-focus-scope": "1.1.7", + "@radix-ui/react-id": "1.1.1", + "@radix-ui/react-portal": "1.1.9", + "@radix-ui/react-presence": "1.1.5", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-slot": "1.2.3", + "@radix-ui/react-use-controllable-state": "1.2.2", + "aria-hidden": "^1.2.4", + "react-remove-scroll": "^2.6.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-dismissable-layer": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.1.11.tgz", + "integrity": "sha512-Nqcp+t5cTB8BinFkZgXiMJniQH0PsUt2k51FUhbdfeKvc4ACcG2uQniY/8+h1Yv6Kza4Q7lD7PQV0z0oicE0Mg==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-callback-ref": "1.1.1", + "@radix-ui/react-use-escape-keydown": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-focus-guards": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-guards/-/react-focus-guards-1.1.3.tgz", + "integrity": "sha512-0rFg/Rj2Q62NCm62jZw0QX7a3sz6QCQU0LpZdNrJX8byRGaGVTqbrW9jAoIAHyMQqsNpeZ81YgSizOt5WXq0Pw==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-focus-scope": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-scope/-/react-focus-scope-1.1.7.tgz", + "integrity": "sha512-t2ODlkXBQyn7jkl6TNaw/MtVEVvIGelJDCG41Okq/KwUsJBwQ4XVZsHAVUkK4mBv3ewiAS3PGuUWuY2BoK4ZUw==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-callback-ref": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-id": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-id/-/react-id-1.1.1.tgz", + "integrity": "sha512-kGkGegYIdQsOb4XjsfM97rXsiHaBwco+hFI66oO4s9LU+PLAC5oJ7khdOVFxkhsmlbpUqDAvXw11CluXP+jkHg==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-use-layout-effect": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-portal": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/@radix-ui/react-portal/-/react-portal-1.1.9.tgz", + "integrity": "sha512-bpIxvq03if6UNwXZ+HTK71JLh4APvnXntDc6XOX8UVq4XQOVl7lwok0AvIl+b8zgCw3fSaVTZMpAPPagXbKmHQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-layout-effect": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-presence": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@radix-ui/react-presence/-/react-presence-1.1.5.tgz", + "integrity": "sha512-/jfEwNDdQVBCNvjkGit4h6pMOzq8bHkopq458dPt2lMjx+eBQUohZNG9A7DtO/O5ukSbxuaNGXMjHicgwy6rQQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-use-layout-effect": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-primitive": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz", + "integrity": "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-slot": "1.2.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-slot": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz", + "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.2" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-callback-ref": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.1.1.tgz", + "integrity": "sha512-FkBMwD+qbGQeMu1cOHnuGB6x4yzPjho8ap5WtbEJ26umhgqVXbhekKUQO+hZEL1vU92a3wHwdp0HAcqAUF5iDg==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-controllable-state": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.2.2.tgz", + "integrity": "sha512-BjasUjixPFdS+NKkypcyyN5Pmg83Olst0+c6vGov0diwTEo6mgdqVR6hxcEgFuh4QrAs7Rc+9KuGJ9TVCj0Zzg==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-use-effect-event": "0.0.2", + "@radix-ui/react-use-layout-effect": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-effect-event": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-effect-event/-/react-use-effect-event-0.0.2.tgz", + "integrity": "sha512-Qp8WbZOBe+blgpuUT+lw2xheLP8q0oatc9UpmiemEICxGvFLYmHm9QowVZGHtJlGbS6A6yJ3iViad/2cVjnOiA==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-use-layout-effect": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-escape-keydown": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-escape-keydown/-/react-use-escape-keydown-1.1.1.tgz", + "integrity": "sha512-Il0+boE7w/XebUHyBjroE+DbByORGR9KKmITzbR7MyQ4akpORYP/ZmbhAr0DG7RmmBqoOnZdy2QlvajJ2QA59g==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-use-callback-ref": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-layout-effect": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.1.1.tgz", + "integrity": "sha512-RbJRS4UWQFkzHTTwVymMTUv8EqYhOp8dOOviLj2ugtTiXRaRQS7GLGxZTLL1jWhMeoSCf5zmcZkqTl9IiYfXcQ==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@react-aria/focus": { + "version": "3.22.1", + "resolved": "https://registry.npmjs.org/@react-aria/focus/-/focus-3.22.1.tgz", + "integrity": "sha512-CPxtkyrBi/HYY5P3lE/57sQ6qfa0lN8E55TOm89H0kNGv0lKt+/0zP7lWERzBjRr5IxBVrQX4gFEowBN52LPaA==", + "license": "Apache-2.0", + "dependencies": { + "@swc/helpers": "^0.5.0", + "react-aria": "^3.48.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1", + "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@react-dnd/asap": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@react-dnd/asap/-/asap-4.0.1.tgz", + "integrity": "sha512-kLy0PJDDwvwwTXxqTFNAAllPHD73AycE9ypWeln/IguoGBEbvFcPDbCV03G52bEcC5E+YgupBE0VzHGdC8SIXg==", + "license": "MIT" + }, + "node_modules/@react-dnd/invariant": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@react-dnd/invariant/-/invariant-2.0.0.tgz", + "integrity": "sha512-xL4RCQBCBDJ+GRwKTFhGUW8GXa4yoDfJrPbLblc3U09ciS+9ZJXJ3Qrcs/x2IODOdIE5kQxvMmE2UKyqUictUw==", + "license": "MIT" + }, + "node_modules/@react-dnd/shallowequal": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@react-dnd/shallowequal/-/shallowequal-2.0.0.tgz", + "integrity": "sha512-Pc/AFTdwZwEKJxFJvlxrSmGe/di+aAOBn60sremrpLo6VI/6cmiUYNNwlI5KNYttg7uypzA3ILPMPgxB2GYZEg==", + "license": "MIT" + }, + "node_modules/@react-types/shared": { + "version": "3.35.0", + "resolved": "https://registry.npmjs.org/@react-types/shared/-/shared-3.35.0.tgz", + "integrity": "sha512-iNWvuzEwANttpQpdlu8nPBtdHb0mcCMj1ZTH//iRB5E/14IAnyRlR25rxH7pNLyzHINsPGEKnWvpwDMCT6vziQ==", + "license": "Apache-2.0", + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@rolldown/pluginutils": { + "version": "1.0.0-beta.27", + "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.27.tgz", + "integrity": "sha512-+d0F4MKMCbeVUJwG96uQ4SgAznZNSq93I3V+9NHA4OpvqG8mRCpGdKmK8l/dl02h2CCDHwW2FqilnTyDcAnqjA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@rollup/pluginutils": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.4.0.tgz", + "integrity": "sha512-MfPp06CjRLfXQ3wY0R8vJDYBy/MvVcc9OulEfR0B8Iv9ko+GCNaRZ+EpJYFl27LhKsZK0o420sYCRHCjfCgeUg==", + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "estree-walker": "^2.0.2", + "picomatch": "^4.0.2" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" + }, + "peerDependenciesMeta": { + "rollup": { + "optional": true + } + } + }, + "node_modules/@rollup/pluginutils/node_modules/estree-walker": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", + "license": "MIT" + }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.61.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.61.0.tgz", + "integrity": "sha512-dnxczajOqt0gesZlN5pGQ1s1imQVrsmCw5G2Ci4oM+0WvNz3pyRnlWrT7McoZIb8VlFwCawdmbWRmxRn7HI+VQ==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.61.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.61.0.tgz", + "integrity": "sha512-Bp3JpGP00Vu3f238ivRrjf7z3xSzVPXqCmaJYA9t2c+c8vKYvOzmXF7LkkeUalTEGd6cZcSWe+PFIP3Vy48fRg==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.61.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.61.0.tgz", + "integrity": "sha512-zaYIpr670mUmmZ1tVzUFplbQbG7h3Gugx3L5FoqhsC2m/YnLlR1a7zVLmXNPy+iY1tFPEbNG+HHBXZGyId0G5w==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.61.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.61.0.tgz", + "integrity": "sha512-+P49fvkv2dSoeevUW+lgZ/I2JHSsJCK1Lyjj7Cu6E4UHG4tS9XIefzIjo5qhgELjAclnen1rLzK2PMKJdo+Dyg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-freebsd-arm64": { + "version": "4.61.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.61.0.tgz", + "integrity": "sha512-l3FAAOyKJXH2ea6KNFN+MMgC/rnE94YGLXs2ehYqDcCoHt1DpvgWX75BhUJxN38XojP7Ul+4H8PRn7EdyqSDrw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-freebsd-x64": { + "version": "4.61.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.61.0.tgz", + "integrity": "sha512-VokPN3TSctKj65cyCNPaUh4vMFA8awxOot/0sp+4J7ZlNRKQEhXhawqPwajoi8H5ZFt61i0ugZJuTKXBjGJ17Q==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.61.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.61.0.tgz", + "integrity": "sha512-DxH0P3wxm+Yzs/p3zrk9dw1rURu8p0Nv5+MRK/L7OtnLNg5rLZraSBFZ8iUXOd9f2BlhJyEpIZUH/emjq4UJ4g==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.61.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.61.0.tgz", + "integrity": "sha512-T6ZvMNe84kAz6TBWHC7hGAoEtzP1LWYw/AqayGWEF6uISt3Abk/st06LqRD9THd7Xz3NxzurUpzAuEAUbZf+nw==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.61.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.61.0.tgz", + "integrity": "sha512-q/4hzvQkDs8b4jIBab1pnLiiM0ayTZsN2amBFPDzuyZxjEd4wDwx0UJFYM3cOZzSf5Kw8fnWSprJzIBMkcR44Q==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.61.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.61.0.tgz", + "integrity": "sha512-vvYWX3akdEAY6km+9wAqFDnk6pQsbJKVnj7xawcvs/+fdlYBGp+U+Qq/lLfpIxYIZvZLHMAKD9HLdacSx/r3dw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-gnu": { + "version": "4.61.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.61.0.tgz", + "integrity": "sha512-DePa5cqOxDP/Zp0VOXpeWaGew5iIv5DXp9NYbzkX5PFQyWVX9184WCTh3hvr/7lhXo8ZVlbFLkz8+o/q1dU6gA==", + "cpu": [ + "loong64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-musl": { + "version": "4.61.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.61.0.tgz", + "integrity": "sha512-LV8aWMB8UChglMCEzs7RkN0GsH29RJaLLqwm9fCIjlqwxQTiWAqNcc7wjBkH31hV0PU/yVxGYvrYsgfea2qw6g==", + "cpu": [ + "loong64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-gnu": { + "version": "4.61.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.61.0.tgz", + "integrity": "sha512-QoNSnwQtaeNu5grdBbsL0tt1uyl5EnS8DA8Mr3nluMXbhdQNyhN+G4tBax7VCdxLKj8YJ0/4OO9Ho84jMnJtKA==", + "cpu": [ + "ppc64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-musl": { + "version": "4.61.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.61.0.tgz", + "integrity": "sha512-/zZp5MKapIIApE8trN8qLGNSiRN9TUoaUZ1cmVu4XnVdd5LQLOXTtyi+vtfUbNnT3iyjzpPqYeKXmvJ+gJGYWw==", + "cpu": [ + "ppc64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.61.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.61.0.tgz", + "integrity": "sha512-RbrzcD3aJ1k3UbtMRRBNwojdVVyXjuVAFTfn/xPa6EEl6GE9Sm/akPgFTb9aAC9pMKGJ6CtWxaGrqWcabH+ySg==", + "cpu": [ + "riscv64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-musl": { + "version": "4.61.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.61.0.tgz", + "integrity": "sha512-ZF+onDsBso8PJf1XaG9lB+O9RnBpKGnY6OrzC4CSHrtC1jb6jWLTKK4bRqdoCXHd22gyr2hiYmEAm8Wns/BOCw==", + "cpu": [ + "riscv64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.61.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.61.0.tgz", + "integrity": "sha512-Atk0aSIk5Zx2Wuh9dgRQgLP0Koc8hOeYpbWryMXyk8G8/HmPkwPPkMqIIDhrXHHYqfUzSJA/I7IWSBv8xSmRBA==", + "cpu": [ + "s390x" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.61.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.61.0.tgz", + "integrity": "sha512-0uMOcf3eZ5K+K4cYHkdxShFMPlPXCOdfDFEFn9dNYAEEd2cVvmOfH7zFgRVoDgmtQ1m9k5q7qfrHzyMAubKYUA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.61.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.61.0.tgz", + "integrity": "sha512-mvFtE4A/t/7hRJ7X8Ozmu8FsIkAUat2nzl12pgU337BRmq87AQUJztwHz2Zv5/tjo9/C95E66CK03SI/ToEDJw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-openbsd-x64": { + "version": "4.61.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.61.0.tgz", + "integrity": "sha512-z9b9+aTxvt8n2rNltMPvyaUfB8NJ+CVyOrGK/MdIKHx7B+lXmZpm/XbRsU7Rpf3fRqJ2uS6mBJiJveCtq8LHDg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ] + }, + "node_modules/@rollup/rollup-openharmony-arm64": { + "version": "4.61.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.61.0.tgz", + "integrity": "sha512-jXaXFqKMehsOc+g8R6oo33RRC6w07G9jDBxAE5eAKX7mOcCbZloYIPNhfG9Wl+P9O9IWHFO4OJgPi1Ml2qkt7w==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.61.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.61.0.tgz", + "integrity": "sha512-OXNWVFocS2IA4+QplhTZZ2a+8hPZR7T8KuozsNmJKK8y7cp83StHvGksfHzPG3wczWTczyWHVQuqeiTUbjiyBg==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.61.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.61.0.tgz", + "integrity": "sha512-AlAbNtBO637LxSldqV43z0FfXoGfl2TW1DgAg/bs7aQswFbDewz2SJm3BUhiGfbOVtW571xbc9p+REdxhyN/Eg==", + "cpu": [ + "ia32" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-gnu": { + "version": "4.61.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.61.0.tgz", + "integrity": "sha512-QRSrQXyJ1M4tjNXdR0/G/IgV6lzfQQJYBjlWIEYkY2Xs86DRl/iEpQ4blMDjJxSl7n19eDKKXMg0AmuBVYy8pQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.61.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.61.0.tgz", + "integrity": "sha512-tkuFxhvKO/HlGd0VsINF6vHSYH8AF8W0TcNxKDK6JZmrehngFj78pToc8iemtnvwilDjs2G/qSzYFhe9U8q+fw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@shikijs/core": { + "version": "3.23.0", + "resolved": "https://registry.npmjs.org/@shikijs/core/-/core-3.23.0.tgz", + "integrity": "sha512-NSWQz0riNb67xthdm5br6lAkvpDJRTgB36fxlo37ZzM2yq0PQFFzbd8psqC2XMPgCzo1fW6cVi18+ArJ44wqgA==", + "license": "MIT", + "dependencies": { + "@shikijs/types": "3.23.0", + "@shikijs/vscode-textmate": "^10.0.2", + "@types/hast": "^3.0.4", + "hast-util-to-html": "^9.0.5" + } + }, + "node_modules/@shikijs/engine-javascript": { + "version": "3.23.0", + "resolved": "https://registry.npmjs.org/@shikijs/engine-javascript/-/engine-javascript-3.23.0.tgz", + "integrity": "sha512-aHt9eiGFobmWR5uqJUViySI1bHMqrAgamWE1TYSUoftkAeCCAiGawPMwM+VCadylQtF4V3VNOZ5LmfItH5f3yA==", + "license": "MIT", + "dependencies": { + "@shikijs/types": "3.23.0", + "@shikijs/vscode-textmate": "^10.0.2", + "oniguruma-to-es": "^4.3.4" + } + }, + "node_modules/@shikijs/engine-oniguruma": { + "version": "3.23.0", + "resolved": "https://registry.npmjs.org/@shikijs/engine-oniguruma/-/engine-oniguruma-3.23.0.tgz", + "integrity": "sha512-1nWINwKXxKKLqPibT5f4pAFLej9oZzQTsby8942OTlsJzOBZ0MWKiwzMsd+jhzu8YPCHAswGnnN1YtQfirL35g==", + "license": "MIT", + "dependencies": { + "@shikijs/types": "3.23.0", + "@shikijs/vscode-textmate": "^10.0.2" + } + }, + "node_modules/@shikijs/langs": { + "version": "3.23.0", + "resolved": "https://registry.npmjs.org/@shikijs/langs/-/langs-3.23.0.tgz", + "integrity": "sha512-2Ep4W3Re5aB1/62RSYQInK9mM3HsLeB91cHqznAJMuylqjzNVAVCMnNWRHFtcNHXsoNRayP9z1qj4Sq3nMqYXg==", + "license": "MIT", + "dependencies": { + "@shikijs/types": "3.23.0" + } + }, + "node_modules/@shikijs/themes": { + "version": "3.23.0", + "resolved": "https://registry.npmjs.org/@shikijs/themes/-/themes-3.23.0.tgz", + "integrity": "sha512-5qySYa1ZgAT18HR/ypENL9cUSGOeI2x+4IvYJu4JgVJdizn6kG4ia5Q1jDEOi7gTbN4RbuYtmHh0W3eccOrjMA==", + "license": "MIT", + "dependencies": { + "@shikijs/types": "3.23.0" + } + }, + "node_modules/@shikijs/types": { + "version": "3.23.0", + "resolved": "https://registry.npmjs.org/@shikijs/types/-/types-3.23.0.tgz", + "integrity": "sha512-3JZ5HXOZfYjsYSk0yPwBrkupyYSLpAE26Qc0HLghhZNGTZg/SKxXIIgoxOpmmeQP0RRSDJTk1/vPfw9tbw+jSQ==", + "license": "MIT", + "dependencies": { + "@shikijs/vscode-textmate": "^10.0.2", + "@types/hast": "^3.0.4" + } + }, + "node_modules/@shikijs/vscode-textmate": { + "version": "10.0.2", + "resolved": "https://registry.npmjs.org/@shikijs/vscode-textmate/-/vscode-textmate-10.0.2.tgz", + "integrity": "sha512-83yeghZ2xxin3Nj8z1NMd/NCuca+gsYXswywDy5bHvwlWL8tpTQmzGeUuHd9FC3E/SBEMvzJRwWEOz5gGes9Qg==", + "license": "MIT" + }, + "node_modules/@sindresorhus/is": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-7.2.0.tgz", + "integrity": "sha512-P1Cz1dWaFfR4IR+U13mqqiGsLFf1KbayybWwdd2vfctdV6hDpUkgCY0nKOLLTMSoRd/jJNjtbqzf13K8DCCXQw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sindresorhus/is?sponsor=1" + } + }, + "node_modules/@sinonjs/commons": { + "version": "1.8.6", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.6.tgz", + "integrity": "sha512-Ky+XkAkqPZSm3NLBeUng77EBQl3cmeJhITaGHdYH8kjVB+aun3S4XBRti2zt17mtt0mIUDiNxYeoJm6drVvBJQ==", + "license": "BSD-3-Clause", + "dependencies": { + "type-detect": "4.0.8" + } + }, + "node_modules/@sinonjs/commons/node_modules/type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/@sinonjs/formatio": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@sinonjs/formatio/-/formatio-2.0.0.tgz", + "integrity": "sha512-ls6CAMA6/5gG+O/IdsBcblvnd8qcO/l1TYoNeAzp3wcISOxlPXQEus0mLcdwazEkWjaBdaJ3TaxmNgCLWwvWzg==", + "license": "BSD-3-Clause", + "dependencies": { + "samsam": "1.3.0" + } + }, + "node_modules/@sinonjs/samsam": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-3.3.3.tgz", + "integrity": "sha512-bKCMKZvWIjYD0BLGnNrxVuw4dkWCYsLqFOUWw8VgKF/+5Y+mE7LfHWPIYoDXowH+3a9LsWDMo0uAP8YDosPvHQ==", + "license": "BSD-3-Clause", + "dependencies": { + "@sinonjs/commons": "^1.3.0", + "array-from": "^2.1.1", + "lodash": "^4.17.15" + } + }, + "node_modules/@sinonjs/text-encoding": { + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/@sinonjs/text-encoding/-/text-encoding-0.7.3.tgz", + "integrity": "sha512-DE427ROAphMQzU4ENbliGYrBSYPXF+TtLg9S8vzeA+OF4ZKzoDdzfL8sxuMUGS/lgRhM6j1URSk9ghf7Xo1tyA==", + "deprecated": "Deprecated: no longer maintained and no longer used by Sinon packages. See\n https://github.com/sinonjs/nise/issues/243 for replacement details.", + "license": "(Unlicense OR Apache-2.0)" + }, + "node_modules/@speed-highlight/core": { + "version": "1.2.15", + "resolved": "https://registry.npmjs.org/@speed-highlight/core/-/core-1.2.15.tgz", + "integrity": "sha512-BMq1K3DsElxDWawkX6eLg9+CKJrTVGCBAWVuHXVUV2u0s2711qiChLSId6ikYPfxhdYocLNt3wWwSvDiTvFabw==", + "dev": true, + "license": "CC0-1.0" + }, + "node_modules/@stylable/uni-driver": { + "version": "2.5.3", + "resolved": "https://registry.npmjs.org/@stylable/uni-driver/-/uni-driver-2.5.3.tgz", + "integrity": "sha512-thE0QYRDmJ3tF3p4LE3Av5dSPGMwmBkK0H257MxtfPEE0JMN3Hez9i4xDNq5L591kuStCq1oEx+r/H5i6BQ5HA==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=8" + } + }, + "node_modules/@swc/helpers": { + "version": "0.5.23", + "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.23.tgz", + "integrity": "sha512-5lSsMOTXURePglDfvuAQUqkGek9Hg2kksOYay2m0+XR++b2NWYL/4sWyuvVBIs8oKnJaxkdi9whaL/sqN13afw==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.8.0" + } + }, + "node_modules/@testing-library/dom": { + "version": "10.4.1", + "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-10.4.1.tgz", + "integrity": "sha512-o4PXJQidqJl82ckFaXUeoAW+XysPLauYI43Abki5hABd853iMhitooc6znOnczgbTYmEP6U6/y1ZyKAIsvMKGg==", + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.10.4", + "@babel/runtime": "^7.12.5", + "@types/aria-query": "^5.0.1", + "aria-query": "5.3.0", + "dom-accessibility-api": "^0.5.9", + "lz-string": "^1.5.0", + "picocolors": "1.1.1", + "pretty-format": "^27.0.2" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@tootallnate/once": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", + "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/@types/aria-query": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-5.0.4.tgz", + "integrity": "sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==", + "license": "MIT" + }, + "node_modules/@types/babel__core": { + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", + "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" + } + }, + "node_modules/@types/babel__generator": { + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.27.0.tgz", + "integrity": "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__template": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", + "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__traverse": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.28.0.tgz", + "integrity": "sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.28.2" + } + }, + "node_modules/@types/debug": { + "version": "4.1.13", + "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.13.tgz", + "integrity": "sha512-KSVgmQmzMwPlmtljOomayoR89W4FynCAi3E8PPs7vmDVPe84hT+vGPKkJfThkmXs0x0jAaa9U8uW8bbfyS2fWw==", + "license": "MIT", + "dependencies": { + "@types/ms": "*" + } + }, + "node_modules/@types/estree": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.9.tgz", + "integrity": "sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==", + "license": "MIT" + }, + "node_modules/@types/hast": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.4.tgz", + "integrity": "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==", + "license": "MIT", + "dependencies": { + "@types/unist": "*" + } + }, + "node_modules/@types/hoist-non-react-statics": { + "version": "3.3.7", + "resolved": "https://registry.npmjs.org/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.7.tgz", + "integrity": "sha512-PQTyIulDkIDro8P+IHbKCsw7U2xxBYflVzW/FgWdCAePD9xGSidgA76/GeJ6lBKoblyhf9pBY763gbrN+1dI8g==", + "license": "MIT", + "dependencies": { + "hoist-non-react-statics": "^3.3.0" + }, + "peerDependencies": { + "@types/react": "*" + } + }, + "node_modules/@types/mdast": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-4.0.4.tgz", + "integrity": "sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==", + "license": "MIT", + "dependencies": { + "@types/unist": "*" + } + }, + "node_modules/@types/ms": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@types/ms/-/ms-2.1.0.tgz", + "integrity": "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==", + "license": "MIT" + }, + "node_modules/@types/nlcst": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@types/nlcst/-/nlcst-2.0.3.tgz", + "integrity": "sha512-vSYNSDe6Ix3q+6Z7ri9lyWqgGhJTmzRjZRqyq15N0Z/1/UnVsno9G/N40NBijoYx2seFDIl0+B2mgAb9mezUCA==", + "license": "MIT", + "dependencies": { + "@types/unist": "*" + } + }, + "node_modules/@types/prop-types": { + "version": "15.7.15", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.15.tgz", + "integrity": "sha512-F6bEyamV9jKGAFBEmlQnesRPGOQqS2+Uwi0Em15xenOxHaf2hv6L8YCVn3rPdPJOiJfPiCnLIRyvwVaqMY3MIw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/react": { + "version": "18.3.30", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.30.tgz", + "integrity": "sha512-3ek6mwJL5/VBewBcY4S66cqlCtK3qi4WIq37Z0m/NHw1hjhI7274Mx1qz/+ggSzyBCOEf7eHjBN6INjPAWYfYw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/prop-types": "*", + "csstype": "^3.2.2" + } + }, + "node_modules/@types/react-dom": { + "version": "18.3.7", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.7.tgz", + "integrity": "sha512-MEe3UeoENYVFXzoXEWsvcpg6ZvlrFNlOQ7EOsvhI3CfAXwzPfO8Qwuxd40nepsYKqyyVQnTdEfv68q91yLcKrQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "@types/react": "^18.0.0" + } + }, + "node_modules/@types/unist": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz", + "integrity": "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==", + "license": "MIT" + }, + "node_modules/@ungap/structured-clone": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.1.tgz", + "integrity": "sha512-mUFwbeTqrVgDQxFveS+df2yfap6iuP20NAKAsBt5jDEoOTDew+zwLAOilHCeQJOVSvmgCX4ogqIrA0mnyr08yQ==", + "license": "ISC" + }, + "node_modules/@vitejs/plugin-react": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-4.7.0.tgz", + "integrity": "sha512-gUu9hwfWvvEDBBmgtAowQCojwZmJ5mcLn3aufeCsitijs3+f2NsrPtlAWIR6OPiqljl96GVCUbLe0HyqIpVaoA==", + "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" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "peerDependencies": { + "vite": "^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0" + } + }, + "node_modules/@volar/kit": { + "version": "2.4.28", + "resolved": "https://registry.npmjs.org/@volar/kit/-/kit-2.4.28.tgz", + "integrity": "sha512-cKX4vK9dtZvDRaAzeoUdaAJEew6IdxHNCRrdp5Kvcl6zZOqb6jTOfk3kXkIkG3T7oTFXguEMt5+9ptyqYR84Pg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@volar/language-service": "2.4.28", + "@volar/typescript": "2.4.28", + "typesafe-path": "^0.2.2", + "vscode-languageserver-textdocument": "^1.0.11", + "vscode-uri": "^3.0.8" + }, + "peerDependencies": { + "typescript": "*" + } + }, + "node_modules/@volar/language-core": { + "version": "2.4.28", + "resolved": "https://registry.npmjs.org/@volar/language-core/-/language-core-2.4.28.tgz", + "integrity": "sha512-w4qhIJ8ZSitgLAkVay6AbcnC7gP3glYM3fYwKV3srj8m494E3xtrCv6E+bWviiK/8hs6e6t1ij1s2Endql7vzQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@volar/source-map": "2.4.28" + } + }, + "node_modules/@volar/language-server": { + "version": "2.4.28", + "resolved": "https://registry.npmjs.org/@volar/language-server/-/language-server-2.4.28.tgz", + "integrity": "sha512-NqcLnE5gERKuS4PUFwlhMxf6vqYo7hXtbMFbViXcbVkbZ905AIVWhnSo0ZNBC2V127H1/2zP7RvVOVnyITFfBw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@volar/language-core": "2.4.28", + "@volar/language-service": "2.4.28", + "@volar/typescript": "2.4.28", + "path-browserify": "^1.0.1", + "request-light": "^0.7.0", + "vscode-languageserver": "^9.0.1", + "vscode-languageserver-protocol": "^3.17.5", + "vscode-languageserver-textdocument": "^1.0.11", + "vscode-uri": "^3.0.8" + } + }, + "node_modules/@volar/language-service": { + "version": "2.4.28", + "resolved": "https://registry.npmjs.org/@volar/language-service/-/language-service-2.4.28.tgz", + "integrity": "sha512-Rh/wYCZJrI5vCwMk9xyw/Z+MsWxlJY1rmMZPsxUoJKfzIRjS/NF1NmnuEcrMbEVGja00aVpCsInJfixQTMdvLw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@volar/language-core": "2.4.28", + "vscode-languageserver-protocol": "^3.17.5", + "vscode-languageserver-textdocument": "^1.0.11", + "vscode-uri": "^3.0.8" + } + }, + "node_modules/@volar/source-map": { + "version": "2.4.28", + "resolved": "https://registry.npmjs.org/@volar/source-map/-/source-map-2.4.28.tgz", + "integrity": "sha512-yX2BDBqJkRXfKw8my8VarTyjv48QwxdJtvRgUpNE5erCsgEUdI2DsLbpa+rOQVAJYshY99szEcRDmyHbF10ggQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@volar/typescript": { + "version": "2.4.28", + "resolved": "https://registry.npmjs.org/@volar/typescript/-/typescript-2.4.28.tgz", + "integrity": "sha512-Ja6yvWrbis2QtN4ClAKreeUZPVYMARDYZl9LMEv1iQ1QdepB6wn0jTRxA9MftYmYa4DQ4k/DaSZpFPUfxl8giw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@volar/language-core": "2.4.28", + "path-browserify": "^1.0.1", + "vscode-uri": "^3.0.8" + } + }, + "node_modules/@vscode/emmet-helper": { + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/@vscode/emmet-helper/-/emmet-helper-2.11.0.tgz", + "integrity": "sha512-QLxjQR3imPZPQltfbWRnHU6JecWTF1QSWhx3GAKQpslx7y3Dp6sIIXhKjiUJ/BR9FX8PVthjr9PD6pNwOJfAzw==", + "dev": true, + "license": "MIT", + "dependencies": { + "emmet": "^2.4.3", + "jsonc-parser": "^2.3.0", + "vscode-languageserver-textdocument": "^1.0.1", + "vscode-languageserver-types": "^3.15.1", + "vscode-uri": "^3.0.8" + } + }, + "node_modules/@vscode/l10n": { + "version": "0.0.18", + "resolved": "https://registry.npmjs.org/@vscode/l10n/-/l10n-0.0.18.tgz", + "integrity": "sha512-KYSIHVmslkaCDyw013pphY+d7x1qV8IZupYfeIfzNA+nsaWHbn5uPuQRvdRFsa9zFzGeudPuoGoZ1Op4jrJXIQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@wix/agent-skills": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@wix/agent-skills/-/agent-skills-1.7.0.tgz", + "integrity": "sha512-N4MRHXI+b4tuIYRirOufvnJWa0XQvEsPRoQaMl0Hq6+94gDlywGkMHGKB4tEsRzjwoUKJ/PqAGt6dQly3S3Nqg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@wix/analytics": { + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/@wix/analytics/-/analytics-1.19.0.tgz", + "integrity": "sha512-WlF1fNoXMOcHzu2ORLosmTytnOEQGvwVvF0TjmUiscxnLOin0HQVZOvonggj+J2sS1/uyhyNaKxzhsROoIF1AQ==", + "license": "MIT" + }, + "node_modules/@wix/app-extensions": { + "version": "1.0.49", + "resolved": "https://registry.npmjs.org/@wix/app-extensions/-/app-extensions-1.0.49.tgz", + "integrity": "sha512-9YZUUxFtIm+TCvoYXEav7kfN2LvkN+nvfv3IUOk3T2upJ6VkvT4UV5J870aUSAxE9cWwL/LS7CXN9onhkB6BLw==" + }, + "node_modules/@wix/astro": { + "version": "2.50.0", + "resolved": "https://registry.npmjs.org/@wix/astro/-/astro-2.50.0.tgz", + "integrity": "sha512-oKmhKvAgYzfpJYmCSN8AuSYXXF7FuJHunBu89X/NjOs33rPDPe4pUYTQMuZfIxUSD1oVWI4gf0TlrzHq0yafHA==", + "dependencies": { + "@wix/auth-management": "^1.0.71", + "@wix/dashboard": "^1.3.43", + "@wix/editor": "^1.403.0", + "@wix/essentials": "^1.0.7", + "@wix/headless-localization-utils": "^1.0.13", + "@wix/headless-node": "^1.43.0", + "@wix/headless-site": "^1.31.0", + "@wix/headless-site-assets": "^1.0.13", + "@wix/multilingual-manager": "^1.5.0", + "@wix/react-component-schema": "^1.4.0", + "@wix/sdk": "^1.21.3", + "@wix/sdk-runtime": "^1.0.0", + "@wix/sdk-types": "^1.17.1", + "@wix/site": "^1.40.0" + }, + "peerDependencies": { + "astro": "^5.0.0", + "react": "^18.3.1", + "react-dom": "^18.3.1" + } + }, + "node_modules/@wix/astro/node_modules/@wix/essentials": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@wix/essentials/-/essentials-1.0.8.tgz", + "integrity": "sha512-yBTL7SzwK7YWRVq/jScWqIUNHjGn61c56dleOjrAlutdDu3Nrpme95FNUL0nyZAx80JlbjX9ZInyPPib9QjhLQ==", + "license": "MIT", + "dependencies": { + "@wix/error-handler": "^1.67.0", + "@wix/monitoring": "^0.21.0", + "@wix/multilingual-manager": "^1.2.0", + "@wix/sdk-runtime": "1.0.14", + "@wix/sdk-types": "1.17.8", + "i18next": "^25.6.3", + "i18next-icu": "^2.4.1", + "intl-messageformat": "^10.7.18", + "react-i18next": "^16.1.2" + }, + "optionalDependencies": { + "graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" + } + }, + "node_modules/@wix/auth-management": { + "version": "1.0.84", + "resolved": "https://registry.npmjs.org/@wix/auth-management/-/auth-management-1.0.84.tgz", + "integrity": "sha512-dtlRUpkTN8BNPXBzrCResgpzhICwZpu8rHNYdlD38RueduTCryzc0W2ist0kIeTNbPEscLenzmYmDP9JfbOUrQ==", + "license": "MIT", + "dependencies": { + "@wix/auto_sdk_auth-management_o-auth-apps": "1.0.46" + } + }, + "node_modules/@wix/authentication": { + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/@wix/authentication/-/authentication-1.14.0.tgz", + "integrity": "sha512-X718lWlTpaP4ls2skTveFka9insTkxc0d90xYDQ2Kad/aRl6XqXHDmsIJddRpnXDHexpkYJLQlEdBmWkNFG1QQ==", + "license": "MIT", + "dependencies": { + "@wix/sdk-runtime": "^1.0.13", + "@wix/sdk-types": "^1.17.8" + } + }, + "node_modules/@wix/auto_sdk_auth-management_o-auth-apps": { + "version": "1.0.46", + "resolved": "https://registry.npmjs.org/@wix/auto_sdk_auth-management_o-auth-apps/-/auto_sdk_auth-management_o-auth-apps-1.0.46.tgz", + "integrity": "sha512-IGYAfXSHPIylh/qPBVNQRHjwgMuuHF34elALgv/z9A6+vo+AylLeZC65udsYno9QDhoxPn2JnTWn/bHJXDNsxA==", + "license": "MIT", + "dependencies": { + "@wix/sdk-runtime": "^1.0.12", + "@wix/sdk-types": "^1.17.7", + "zod": "^4.3.6" + } + }, + "node_modules/@wix/auto_sdk_headless-site-assets_scripts": { + "version": "1.0.13", + "resolved": "https://registry.npmjs.org/@wix/auto_sdk_headless-site-assets_scripts/-/auto_sdk_headless-site-assets_scripts-1.0.13.tgz", + "integrity": "sha512-4ISEZzeYsi0TAX9Te6zZWcsKM+if0LjcTG8dHXO766t3yE1Elo+8jHP+IrUU/tl5I2hNsG1ri8E5uRdojpXH/g==", + "license": "MIT", + "dependencies": { + "@wix/sdk-runtime": "^1.0.12", + "@wix/sdk-types": "^1.17.7", + "zod": "^4.3.6" + } + }, + "node_modules/@wix/auto_sdk_identity_authentication": { + "version": "1.0.47", + "resolved": "https://registry.npmjs.org/@wix/auto_sdk_identity_authentication/-/auto_sdk_identity_authentication-1.0.47.tgz", + "integrity": "sha512-F4a3LCi656OgXD1GXX5fYrbyeAo/I3b8WzptjZ7kVjkxdDGT4sAtBtcLhMEMjmZCOIcoNp9CadIOfjlPen2yxQ==", + "license": "MIT", + "dependencies": { + "@wix/sdk-runtime": "^1.0.12", + "@wix/sdk-types": "^1.17.7", + "zod": "^4.3.6" + } + }, + "node_modules/@wix/auto_sdk_identity_oauth": { + "version": "1.0.37", + "resolved": "https://registry.npmjs.org/@wix/auto_sdk_identity_oauth/-/auto_sdk_identity_oauth-1.0.37.tgz", + "integrity": "sha512-iGFnvKooVkzoXxiaxNusZWUSNswwWESwGdGj0WjSdNhoFMayEJ1QEYjb+qXimIhfuSmBwVHrJPXFMQTFQqbjwA==", + "license": "MIT", + "dependencies": { + "@wix/sdk-runtime": "^1.0.12", + "@wix/sdk-types": "^1.17.7", + "zod": "^4.3.6" + } + }, + "node_modules/@wix/auto_sdk_identity_recovery": { + "version": "1.0.43", + "resolved": "https://registry.npmjs.org/@wix/auto_sdk_identity_recovery/-/auto_sdk_identity_recovery-1.0.43.tgz", + "integrity": "sha512-O6r0v92FQLgCGffwDclUy83IsBRkz0+3T+m67tCxf3/7JYkMv5k2ml0zSfVfRjWqkY00Pue7/ABLYuQuMdwB+Q==", + "license": "MIT", + "dependencies": { + "@wix/sdk-runtime": "^1.0.12", + "@wix/sdk-types": "^1.17.7", + "zod": "^4.3.6" + } + }, + "node_modules/@wix/auto_sdk_identity_verification": { + "version": "1.0.43", + "resolved": "https://registry.npmjs.org/@wix/auto_sdk_identity_verification/-/auto_sdk_identity_verification-1.0.43.tgz", + "integrity": "sha512-lqhh+tnZCeEubcnabmP+WaK/38/qHkliNW4EAv7qW6obxLxgP78vqrSs+Sdk7SGUItznRyakldqiVZyJnB7lLw==", + "license": "MIT", + "dependencies": { + "@wix/sdk-runtime": "^1.0.12", + "@wix/sdk-types": "^1.17.7", + "zod": "^4.3.6" + } + }, + "node_modules/@wix/auto_sdk_media_enterprise-media-categories": { + "version": "1.0.35", + "resolved": "https://registry.npmjs.org/@wix/auto_sdk_media_enterprise-media-categories/-/auto_sdk_media_enterprise-media-categories-1.0.35.tgz", + "integrity": "sha512-gqWns248MoY9qlYq6SrvfB05sS0qTYf3+PhuZW3wNubeqQSWXdU27G1rtpXDM8qUtLdreLm89k8Agk5wiizMhQ==", + "license": "MIT", + "dependencies": { + "@wix/sdk-runtime": "^1.0.12", + "@wix/sdk-types": "^1.17.7", + "zod": "^4.3.6" + } + }, + "node_modules/@wix/auto_sdk_media_enterprise-media-items": { + "version": "1.0.37", + "resolved": "https://registry.npmjs.org/@wix/auto_sdk_media_enterprise-media-items/-/auto_sdk_media_enterprise-media-items-1.0.37.tgz", + "integrity": "sha512-OkoCViJOu/nu1WXxoDxle9gN4TN/AXHIS1ihA8SvzidyY0SsbZf6VeGdyYvOwu4bZIKFXNcfFRb9GQbAznlC5w==", + "license": "MIT", + "dependencies": { + "@wix/sdk-runtime": "^1.0.12", + "@wix/sdk-types": "^1.17.7", + "zod": "^4.3.6" + } + }, + "node_modules/@wix/auto_sdk_media_files": { + "version": "1.0.81", + "resolved": "https://registry.npmjs.org/@wix/auto_sdk_media_files/-/auto_sdk_media_files-1.0.81.tgz", + "integrity": "sha512-+uPUFQ5C/upiA/+CVdGg3aaAow5NL5AcJk+Zp+U65SfIhl+HhXfS7hZcf7nUDeQ8w7J9xmSLxER3VTzL3ZsUqQ==", + "license": "MIT", + "dependencies": { + "@wix/sdk-runtime": "^1.0.12", + "@wix/sdk-types": "^1.17.7", + "zod": "^4.3.6" + } + }, + "node_modules/@wix/auto_sdk_media_folders": { + "version": "1.0.53", + "resolved": "https://registry.npmjs.org/@wix/auto_sdk_media_folders/-/auto_sdk_media_folders-1.0.53.tgz", + "integrity": "sha512-lfqsF80fz1BnldfZTPowVInP+V+HrggvoXPw16IBef9caOWDvRbwXD4jmo3jYZ1x7i27jNEn1nANL82nieHJuA==", + "license": "MIT", + "dependencies": { + "@wix/sdk-runtime": "^1.0.12", + "@wix/sdk-types": "^1.17.7", + "zod": "^4.3.6" + } + }, + "node_modules/@wix/auto_sdk_redirects_redirects": { + "version": "1.0.43", + "resolved": "https://registry.npmjs.org/@wix/auto_sdk_redirects_redirects/-/auto_sdk_redirects_redirects-1.0.43.tgz", + "integrity": "sha512-AU3OfsSi2s7o2bQ1luwmNVBWtXsiau7nbwNo6Dce3HndguGCndgLi+DhGd/H0vCt3K8iBykzzCs2pyfLNM04Ng==", + "license": "MIT", + "dependencies": { + "@wix/sdk-runtime": "^1.0.12", + "@wix/sdk-types": "^1.17.7", + "zod": "^4.3.6" + } + }, + "node_modules/@wix/awaiter-utils": { + "version": "1.0.141", + "resolved": "https://registry.npmjs.org/@wix/awaiter-utils/-/awaiter-utils-1.0.141.tgz", + "integrity": "sha512-ScV5PZNZR/KwX/pmANHWdn2Il0mDqVZL8/0qQRF38zKmiXiUqSipp4uiuRft2ocA2Jz+aP9qvAW1+CJgvW9VNQ==", + "license": "MIT", + "engines": { + "node": ">=20" + } + }, + "node_modules/@wix/cli": { + "version": "1.1.207", + "resolved": "https://registry.npmjs.org/@wix/cli/-/cli-1.1.207.tgz", + "integrity": "sha512-pzA0Sf94DaDiQnvGO19zS6nM/8MwtAYJJmj22DiuKek1DI6fAC64F/rdEhl8nY8sYtqrdpoZcyDPf5m36Fv8Cw==", + "dev": true, + "dependencies": { + "@wix/agent-skills": "^1.1.0", + "node-gyp": "^8.4.1" + }, + "bin": { + "wix": "bin/wix.cjs" + }, + "engines": { + "node": ">= 20.11.0" + }, + "optionalDependencies": { + "fsevents": "^2.3.2" + } + }, + "node_modules/@wix/communication-channel": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@wix/communication-channel/-/communication-channel-1.0.9.tgz", + "integrity": "sha512-l26YzWhDyJ3bS2i9OlMEJzjZsg5GrDaHDGHjyq/p2gczx0uNwl+f+ioxoGn1eg7Oiy5KYiT/vM8AlL/fJn0GvA==", + "license": "UNLICENSED", + "dependencies": { + "@babel/runtime": "^7.0.0", + "comlink": "4.3.0" + } + }, + "node_modules/@wix/consent-policy-manager": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/@wix/consent-policy-manager/-/consent-policy-manager-1.15.0.tgz", + "integrity": "sha512-XIQeVkNYEdCmAA/jLVTFxzZ7E6lwHbd17HecHZaeCcWjZwVoGuFPlH4mAs4sdrUisMGxe3MJhIHWsoGZ3nBwmA==", + "license": "MIT" + }, + "node_modules/@wix/credits-types": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@wix/credits-types/-/credits-types-1.0.2.tgz", + "integrity": "sha512-IP4gsoZgvcPt4/KFxdRTjlzMRWH9Iu8sEcQtGpL1gaLRUg6WWpxDcEUDya0LMdrNtm/FAiRdiVXlBYuI4yU66Q==", + "license": "UNLICENSED", + "dependencies": { + "@babel/runtime": "^7.28.4" + } + }, + "node_modules/@wix/dashboard": { + "version": "1.3.44", + "resolved": "https://registry.npmjs.org/@wix/dashboard/-/dashboard-1.3.44.tgz", + "integrity": "sha512-CdeFlQ+z1urhw51f6f8+vB78aS4g0GOEQgn3uObzMz1VRlz+U6XaIVNF4nqRjHBGdq6PzyGU2SMHpSHlt/ydlA==", + "license": "UNLICENSED", + "dependencies": { + "@babel/runtime": "^7.0.0", + "@wix/communication-channel": "1.0.9", + "@wix/feedback-loop-structure": "^1.32.0", + "@wix/media": "^1.0.123", + "@wix/monitoring-browser-sdk-host": "^0.1.16", + "@wix/sdk-runtime": "^0.3.59", + "@wix/sdk-types": "^1.13.39", + "@wix/workspace": "^1.3.11", + "ua-parser-js": "^2.0.6", + "zustand": "^4.5.0" + }, + "peerDependencies": { + "@wix/sdk": ">=1.12.4", + "react": "^16.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "@wix/sdk": { + "optional": true + }, + "react": { + "optional": true + } + } + }, + "node_modules/@wix/dashboard/node_modules/@wix/sdk-runtime": { + "version": "0.3.62", + "resolved": "https://registry.npmjs.org/@wix/sdk-runtime/-/sdk-runtime-0.3.62.tgz", + "integrity": "sha512-5imt9mSEaceX365iLGzMJ7jS4qr4lJj+2DZox86Ge8P7V9IeuPYLsQ+0PN9wN6XgMfjNLHt4G6hJUIi3bdglGA==", + "license": "MIT", + "dependencies": { + "@wix/sdk-context": "0.0.1", + "@wix/sdk-types": "^1.13.41" + } + }, + "node_modules/@wix/design-system": { + "version": "1.283.0", + "resolved": "https://registry.npmjs.org/@wix/design-system/-/design-system-1.283.0.tgz", + "integrity": "sha512-+1L1T1dNKB89liymifI6TWEvyY31goMJYOHZxDKbcDVcfGUTZOIlFhnf/5egXK+snxefePdX9/2C8EuoutS3LQ==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.29.2", + "@floating-ui/core": "^1.7.5", + "@floating-ui/react": "0.26.28", + "@radix-ui/react-dialog": "^1.1.15", + "@react-aria/focus": "^3.21.5", + "@wix/awaiter-utils": "^1.0.141", + "@wix/design-system-illustrations": "^2.1.0", + "@wix/design-system-tokens": "^1.197.0", + "@wix/design-systems-locale-utils": "1.192.0", + "@wix/unidriver-core": "^1.5.5", + "@wix/wix-ui-icons-common": "^3.165.0", + "@wix/wix-ui-test-utils": "^1.3.4", + "chart.js": "^2.9.4", + "classnames": "^2.5.1", + "color": "^2.0.1", + "css-element-queries": "^1.2.3", + "d3-array": "^2.12.1", + "d3-axis": "^2.1.0", + "d3-ease": "^2.0.0", + "d3-format": "^2.0.0", + "d3-scale": "^3.3.0", + "d3-selection": "^2.0.0", + "d3-shape": "^2.1.0", + "d3-transition": "^2.0.0", + "date-fns": "^2.30.0", + "difference": "^1.0.2", + "embla-carousel-autoplay": "^8.6.0", + "embla-carousel-react": "^8.6.0", + "fbjs": "^2.0.0", + "framer-motion": "6.2.4", + "globals": "^16.0.0", + "gradient-parser": "^1.0.2", + "hoist-non-react-methods": "^1.1.0", + "howler": "^2.2.4", + "immutable": "^3.8.2", + "invariant": "^2.2.1", + "lodash": "^4.18.1", + "object-assign": "^4.1.1", + "omit": "^1.0.1", + "overlayscrollbars": "2.6.1", + "popper.js": "^1.16.1", + "rc-slider": "9.7.2", + "react-chartjs-2": "^2.11.2", + "react-day-picker": "^7.4.10", + "react-dnd": "^11.1.3", + "react-dnd-test-backend": "^11.1.3", + "react-dnd-touch-backend": "^11.1.3", + "react-dom-instance": "^2.0.0", + "react-modal": "^3.16.3", + "react-popper": "^1.3.11", + "react-remove-scroll": "2.7.1", + "react-scroll-sync": "0.11.0", + "react-transition-group": "^4.4.5", + "react-window": "^1.8.10", + "shallowequal": "^1.1.0", + "tslib": "^2.8.1" + }, + "peerDependencies": { + "@playwright/test": "1.58.2", + "@types/react": "^16.14.0 || ^17.0.0 || ^18.0.0", + "@types/react-dom": "^16.0.0 || ^17.0.0 || ^18.0.0", + "@wix/ambassador": "^4.0.485", + "@wix/ambassador-wix-atlas-service-web": "^1.0.150", + "playwright": "1.58.2", + "puppeteer": "^5.5.0 || ^14.0.0", + "puppeteer-core": "^10.1.0 || ^14.0.0", + "react": "^16.14.0 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.0.0 || ^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "@playwright/test": { + "optional": true + }, + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + }, + "@wix/ambassador": { + "optional": true + }, + "@wix/ambassador-wix-atlas-service-web": { + "optional": true + }, + "playwright": { + "optional": true + }, + "puppeteer": { + "optional": true + }, + "puppeteer-core": { + "optional": true + } + } + }, + "node_modules/@wix/design-system-illustrations": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@wix/design-system-illustrations/-/design-system-illustrations-2.1.0.tgz", + "integrity": "sha512-Sz5kcH2e7aotisi0zPYkAg7hLTlfx6lIB2b/o9p2/KhesKcUxAsMFasUp1Tczn8obKL6kVEk0qdhkOZbdGrg9w==", + "license": "MIT", + "peerDependencies": { + "react": "^16.14.0 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.14.0 || ^17.0.0 || ^18.0.0" + } + }, + "node_modules/@wix/design-system-tokens": { + "version": "1.197.0", + "resolved": "https://registry.npmjs.org/@wix/design-system-tokens/-/design-system-tokens-1.197.0.tgz", + "integrity": "sha512-dWspobTJS0HKoBb0qTP5zfB+hZX9q9/DR6nSRowWbeCTmQMpb/vlLX2fbZPqb6iWnOBu+4Ir5clgq/TkEc4f7A==", + "license": "MIT" + }, + "node_modules/@wix/design-systems-locale-utils": { + "version": "1.192.0", + "resolved": "https://registry.npmjs.org/@wix/design-systems-locale-utils/-/design-systems-locale-utils-1.192.0.tgz", + "integrity": "sha512-a9p+H00XT0SHYykTEC45J4y9FnxT0XJbJI9tPmKnAdfzSnxLgqfkxz8COT+UKldNcVTgwTMDUXQYA5KIhp/dSQ==", + "dependencies": { + "@babel/runtime": "^7.29.2" + } + }, + "node_modules/@wix/editor": { + "version": "1.537.0", + "resolved": "https://registry.npmjs.org/@wix/editor/-/editor-1.537.0.tgz", + "integrity": "sha512-8YtDiTJeZom5K1GfT2HBvWB2J0znD76oDQNE8y8BNlXvOU5wT43z0IKU/VrGjCGUBVk+jhyNKJGuI/8E8QsNuA==", + "license": "UNLICENSED", + "dependencies": { + "@wix/editor-platform-contexts": "1.110.0", + "@wix/editor-platform-environment-api": "1.111.0", + "@wix/monitoring-browser-sdk-host": "^0.1.25", + "@wix/public-editor-platform-errors": "1.9.0", + "@wix/public-editor-platform-interfaces": "1.53.0", + "@wix/sdk-runtime": "^0.7.0", + "@wix/sdk-types": "^1.17.8", + "@wix/workspace": "^1.3.1" + } + }, + "node_modules/@wix/editor-application": { + "version": "1.423.0", + "resolved": "https://registry.npmjs.org/@wix/editor-application/-/editor-application-1.423.0.tgz", + "integrity": "sha512-/ekaPRo3QINptHTsjvMYaPBzzOv8vOGipIZyYAORXs+e/x8OO013rCw6mh/HOzyzXjIaHh/ZBP21kkCZmFKu6Q==", + "license": "UNLICENSED", + "dependencies": { + "@wix/editor-platform-contexts": "1.110.0", + "@wix/public-editor-platform-errors": "1.9.0", + "@wix/public-editor-platform-events": "1.344.0", + "@wix/public-editor-platform-interfaces": "1.53.0" + } + }, + "node_modules/@wix/editor-platform-contexts": { + "version": "1.110.0", + "resolved": "https://registry.npmjs.org/@wix/editor-platform-contexts/-/editor-platform-contexts-1.110.0.tgz", + "integrity": "sha512-maNgQ36XvT5ERLQYJ7YTtVS4mkD/jraJzns4E97vQzEN+yQb7yYJXyrsSs0W6gBDVxZvEw0hNNmGENturaSN3g==", + "license": "UNLICENSED", + "dependencies": { + "@wix/editor-platform-transport": "1.15.0", + "@wix/public-editor-platform-errors": "1.9.0", + "@wix/public-editor-platform-events": "1.344.0", + "@wix/public-editor-platform-interfaces": "1.53.0" + } + }, + "node_modules/@wix/editor-platform-environment-api": { + "version": "1.111.0", + "resolved": "https://registry.npmjs.org/@wix/editor-platform-environment-api/-/editor-platform-environment-api-1.111.0.tgz", + "integrity": "sha512-EVJ06vmHIQOTDvU5/Pjz93m+SpzcHdmdrRFI8MVkd7zW6fZ9uY0oysMaNMszd6fB4lfcZhG1Lq2hMRTS0tC2TQ==", + "license": "UNLICENSED", + "dependencies": { + "@wix/editor-application": "1.423.0", + "@wix/editor-platform-contexts": "1.110.0", + "@wix/editor-platform-transport": "1.15.0", + "@wix/public-editor-platform-errors": "1.9.0", + "@wix/public-editor-platform-events": "1.344.0", + "@wix/public-editor-platform-interfaces": "1.53.0" + } + }, + "node_modules/@wix/editor-platform-transport": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/@wix/editor-platform-transport/-/editor-platform-transport-1.15.0.tgz", + "integrity": "sha512-dQVqbJv1TiD7XtxGSu1vy+G7fOF5/33XqjwWR1sM4GagDa7FTlt5H+P490ih8ROeZM0g21yPPfA7Sar/2IKHtQ==", + "license": "UNLICENSED" + }, + "node_modules/@wix/editor-react-types": { + "version": "1.0.26", + "resolved": "https://registry.npmjs.org/@wix/editor-react-types/-/editor-react-types-1.0.26.tgz", + "integrity": "sha512-H/aIgzIsDgEY90t+JZn+Isx7b5+Es4kWy4tTBiwaUufV5/QwGKAfyRMygYFJ1Lk8s/W4O/qBavirr+sTyjzHeA==", + "license": "MIT", + "dependencies": { + "react": "^18.3.1" + } + }, + "node_modules/@wix/editor/node_modules/@wix/sdk-runtime": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/@wix/sdk-runtime/-/sdk-runtime-0.7.0.tgz", + "integrity": "sha512-wqLo26ZkMDoyMqVMC7H0lG5qYmGbCk7m3443XJB/cw0MrYl4o4Eermc+LPDf6vsaGKgiVSQ+6OY6G2SZ6RPnSg==", + "license": "MIT", + "dependencies": { + "@wix/sdk-context": "0.0.1", + "@wix/sdk-types": "1.14.0" + } + }, + "node_modules/@wix/editor/node_modules/@wix/sdk-runtime/node_modules/@wix/sdk-types": { + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/@wix/sdk-types/-/sdk-types-1.14.0.tgz", + "integrity": "sha512-1ae6emTMiiYr+cpupnmHS05WMU04vP12DlW5cII3pjau3iLhmfo6KjA++ZRSnmOJc0sNYI5iL7sMVrJFy46hPA==", + "license": "MIT", + "dependencies": { + "@wix/error-handler-types": "^1.19.0", + "@wix/monitoring-types": "^0.12.0", + "type-fest": "^4.41.0" + } + }, + "node_modules/@wix/error-handler": { + "version": "1.68.0", + "resolved": "https://registry.npmjs.org/@wix/error-handler/-/error-handler-1.68.0.tgz", + "integrity": "sha512-DGP/C3Uv5cpGQX4OxDgXmSvDPJxQPjOkD3vpe+50kVm6CDd2UAvnvkMnvA/6SpvVJwowHeqBLC8DKqzBe5YuHA==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.28.4", + "@wix/error-handler-core": "1.20.0", + "events": "^3.3.0", + "http-status-codes": "^2.3.0", + "uuid": "^11.0.3" + }, + "peerDependencies": { + "@wix/fe-essentials": "^1.233.0", + "i18next": ">=19.9.2", + "i18next-icu": ">=2.3.0", + "intl-messageformat": ">=7.8.4" + }, + "peerDependenciesMeta": { + "@wix/fe-essentials": { + "optional": true + }, + "i18next": { + "optional": true + }, + "i18next-icu": { + "optional": true + }, + "intl-messageformat": { + "optional": true + } + } + }, + "node_modules/@wix/error-handler-core": { + "version": "1.20.0", + "resolved": "https://registry.npmjs.org/@wix/error-handler-core/-/error-handler-core-1.20.0.tgz", + "integrity": "sha512-ubswKgfxN/KwUZKoO0dcz27gER6uVtSbiaV7L91F9hwYUthvrb79zLZiP64NZCGVlgBFIsjHm2JrdPnCDL3TbA==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.28.4", + "@wix/error-handler-types": "1.20.0" + } + }, + "node_modules/@wix/error-handler-types": { + "version": "1.20.0", + "resolved": "https://registry.npmjs.org/@wix/error-handler-types/-/error-handler-types-1.20.0.tgz", + "integrity": "sha512-tMi5BucbWs6CnwIoMaPteWu4J6TeI6O2TsYx5hznKERz509We3ZKi+liJLp+oe2Kd/IUxZr3BAh1Zr+bcbKMVA==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.28.4" + } + }, + "node_modules/@wix/essentials": { + "version": "0.1.28", + "resolved": "https://registry.npmjs.org/@wix/essentials/-/essentials-0.1.28.tgz", + "integrity": "sha512-uAB9xpwqebaIrdgPD9YsdZA8XSqWEJvtLT4HKSpuWmSmtLZBRYb+8U0D6NfY5grVw1qYzw0Z4XaGdeM2LLyuuw==", + "license": "MIT", + "dependencies": { + "@wix/error-handler": "^1.67.0", + "@wix/monitoring": "^0.21.0", + "@wix/sdk-runtime": "^0.3.62", + "@wix/sdk-types": "^1.13.41", + "i18next": "^25.3.2", + "i18next-icu": "^2.3.0", + "intl-messageformat": "^10.7.16" + }, + "optionalDependencies": { + "graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" + } + }, + "node_modules/@wix/essentials/node_modules/@wix/sdk-runtime": { + "version": "0.3.62", + "resolved": "https://registry.npmjs.org/@wix/sdk-runtime/-/sdk-runtime-0.3.62.tgz", + "integrity": "sha512-5imt9mSEaceX365iLGzMJ7jS4qr4lJj+2DZox86Ge8P7V9IeuPYLsQ+0PN9wN6XgMfjNLHt4G6hJUIi3bdglGA==", + "license": "MIT", + "dependencies": { + "@wix/sdk-context": "0.0.1", + "@wix/sdk-types": "^1.13.41" + } + }, + "node_modules/@wix/feedback-loop-structure": { + "version": "1.34.0", + "resolved": "https://registry.npmjs.org/@wix/feedback-loop-structure/-/feedback-loop-structure-1.34.0.tgz", + "integrity": "sha512-7oRFhiVTdfalMqJwS76yTDZP9SQOgRf1KacXsiLfAjD3IbBxk/PvuvLqmS/XEK9gFUvd971kUaAVKyaA/dT+QQ==", + "license": "MIT", + "dependencies": { + "zod": "^3.23.8" + } + }, + "node_modules/@wix/feedback-loop-structure/node_modules/zod": { + "version": "3.25.76", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz", + "integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + }, + "node_modules/@wix/headless-localization-utils": { + "version": "1.0.15", + "resolved": "https://registry.npmjs.org/@wix/headless-localization-utils/-/headless-localization-utils-1.0.15.tgz", + "integrity": "sha512-ZM1aw52LH4nTcWRIYuFcONQbrl6zdevtXCry3PwaA9J4ty7m+G7o/L4Xv3RzKsYq7djsTeVLggFgdW6/6q2jbQ==", + "license": "MIT", + "dependencies": { + "@wix/headless-node": "^1.42.0", + "@wix/headless-site-assets": "^1.0.9" + } + }, + "node_modules/@wix/headless-media": { + "version": "0.0.25", + "resolved": "https://registry.npmjs.org/@wix/headless-media/-/headless-media-0.0.25.tgz", + "integrity": "sha512-qxS7892M8cr2y6Pata1laHmQDCXeF5SAepB2csxTvCk/bYzFsp7gJOTYwjVqKnZP2O28RW/JO8F00nkKwP1/NA==", + "license": "MIT", + "dependencies": { + "@wix/sdk": "^1.17.1", + "@wix/services-definitions": "^1.0.1", + "@wix/services-manager-react": "^1.0.3" + } + }, + "node_modules/@wix/headless-node": { + "version": "1.44.0", + "resolved": "https://registry.npmjs.org/@wix/headless-node/-/headless-node-1.44.0.tgz", + "integrity": "sha512-CE/3/bL3Vxg54aEwMMCcPe6xihImQu21+p21rwQ79W7uQsYyI0GZ8+sVR3WQHuP3DOR/Nc9NcfRPQ48BDXGjdw==", + "license": "UNLICENSED", + "dependencies": { + "@babel/runtime": "^7.0.0", + "@wix/monitoring-velo": "^1.31.0", + "@wix/sdk-runtime": "^1.0.0" + } + }, + "node_modules/@wix/headless-site": { + "version": "1.37.0", + "resolved": "https://registry.npmjs.org/@wix/headless-site/-/headless-site-1.37.0.tgz", + "integrity": "sha512-C1teSScB62BAwSFvB8a4PwbzLyb4NfjRfF2g+krlePmOapZ4YDGM/JwttL8sl9kWV9DGICO3kNCC0+9G9xdUGg==", + "license": "UNLICENSED", + "dependencies": { + "@babel/runtime": "^7.0.0", + "@wix/monitoring-velo": "^1.31.0", + "@wix/sdk-runtime": "^1.0.0" + } + }, + "node_modules/@wix/headless-site-assets": { + "version": "1.0.13", + "resolved": "https://registry.npmjs.org/@wix/headless-site-assets/-/headless-site-assets-1.0.13.tgz", + "integrity": "sha512-t8wo7ux7fWmzmz2UAUtsVuKnXnLW1SF4duEyTDWPlIw0vpsQjzcsY4fGpFIVvxXSAGpAIz+qecAZHPmUrP50Rw==", + "license": "MIT", + "dependencies": { + "@wix/auto_sdk_headless-site-assets_scripts": "1.0.13" + } + }, + "node_modules/@wix/identity": { + "version": "1.0.196", + "resolved": "https://registry.npmjs.org/@wix/identity/-/identity-1.0.196.tgz", + "integrity": "sha512-8QHYzJkJFAUk/zE0ANlWlYmYWCwMJ4mqOyT1s6XGTsySL/rUJFXlI97BjVFNYEU3PAQZ7waBjdNdTMNQF+iE+g==", + "license": "MIT", + "dependencies": { + "@wix/auto_sdk_identity_authentication": "1.0.47", + "@wix/auto_sdk_identity_oauth": "1.0.37", + "@wix/auto_sdk_identity_recovery": "1.0.43", + "@wix/auto_sdk_identity_verification": "1.0.43" + } + }, + "node_modules/@wix/image-kit": { + "version": "1.123.0", + "resolved": "https://registry.npmjs.org/@wix/image-kit/-/image-kit-1.123.0.tgz", + "integrity": "sha512-3Nhf6LT4Iaktr6Lj2XqQXll8kdTb/NywiO5hB9VChg2a5y1Nw437lG9/1VZUbmAluik3HP03L9HMl7t4Ow2VsQ==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.26.0", + "tslib": "^2.8.1" + } + }, + "node_modules/@wix/media": { + "version": "1.0.249", + "resolved": "https://registry.npmjs.org/@wix/media/-/media-1.0.249.tgz", + "integrity": "sha512-wDAgP1fSaSYJpiNM0jZ6i+48/57cfJrnhnTx7tG95QhwemdN31a1QpNIByKxEkhOauyf1MEDof5ps70lfNV2aQ==", + "license": "MIT", + "dependencies": { + "@wix/auto_sdk_media_enterprise-media-categories": "1.0.35", + "@wix/auto_sdk_media_enterprise-media-items": "1.0.37", + "@wix/auto_sdk_media_files": "1.0.81", + "@wix/auto_sdk_media_folders": "1.0.53", + "@wix/headless-media": "^0.0.25" + } + }, + "node_modules/@wix/monitoring": { + "version": "0.21.0", + "resolved": "https://registry.npmjs.org/@wix/monitoring/-/monitoring-0.21.0.tgz", + "integrity": "sha512-2KC4ZuJE4abToc2QelY7Bv99BOfbvZiAK8PY5090iP4YVGM9t+VgUdg8H6l94Q0bF/vF44dcA9rjFiEcUz4K7g==", + "license": "UNLICENSED", + "dependencies": { + "@wix/monitoring-types": "0.12.0" + } + }, + "node_modules/@wix/monitoring-browser-panorama": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/@wix/monitoring-browser-panorama/-/monitoring-browser-panorama-0.10.0.tgz", + "integrity": "sha512-xZCyaVKIR/XRhIovPwDgIiySygb100jL2ZFRiYvk+KECAjX6HlVme6GvxV90dbDGREAZLm+qm0jyjptNHoVVjw==", + "license": "UNLICENSED", + "dependencies": { + "@wix/monitoring": "1.0.0", + "@wix/monitoring-common-sentry": "0.2.0" + } + }, + "node_modules/@wix/monitoring-browser-panorama/node_modules/@wix/monitoring": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@wix/monitoring/-/monitoring-1.0.0.tgz", + "integrity": "sha512-l/0UaT0n4AFVU/7cbe5PLu09WX8s3Zs+dkHf0duacTYwjgnCA+oXuXJ+S2zIKo/85EBZvDEEUx2eD3FUFEztsA==", + "license": "UNLICENSED", + "dependencies": { + "@wix/monitoring-types": "0.17.0" + } + }, + "node_modules/@wix/monitoring-browser-panorama/node_modules/@wix/monitoring-types": { + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/@wix/monitoring-types/-/monitoring-types-0.17.0.tgz", + "integrity": "sha512-1R3kOhnd/gGy3B88NFvIog4JRXpQy3Hs1zRtWXZybAFgP+nZiApClwbFwR6xBDIgxV9MaImaEfMN0Y5Sitvttw==", + "license": "UNLICENSED" + }, + "node_modules/@wix/monitoring-browser-sdk-host": { + "version": "0.1.27", + "resolved": "https://registry.npmjs.org/@wix/monitoring-browser-sdk-host/-/monitoring-browser-sdk-host-0.1.27.tgz", + "integrity": "sha512-sCJqMCvPX5hxpMblQx0rlJz/b0d/VcPzT1eA9Te97eop3yaRzJoaWI99XqwxvxyOqZZ8wNgF711UEHHFLTmVfQ==", + "dependencies": { + "@wix/monitoring": "1.0.0", + "@wix/monitoring-browser-panorama": "0.10.0", + "@wix/monitoring-browser-sentry": "0.26.0", + "@wix/monitoring-types": "0.17.0", + "@wix/monitoring-velo": "1.29.0" + } + }, + "node_modules/@wix/monitoring-browser-sdk-host/node_modules/@wix/monitoring": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@wix/monitoring/-/monitoring-1.0.0.tgz", + "integrity": "sha512-l/0UaT0n4AFVU/7cbe5PLu09WX8s3Zs+dkHf0duacTYwjgnCA+oXuXJ+S2zIKo/85EBZvDEEUx2eD3FUFEztsA==", + "license": "UNLICENSED", + "dependencies": { + "@wix/monitoring-types": "0.17.0" + } + }, + "node_modules/@wix/monitoring-browser-sdk-host/node_modules/@wix/monitoring-types": { + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/@wix/monitoring-types/-/monitoring-types-0.17.0.tgz", + "integrity": "sha512-1R3kOhnd/gGy3B88NFvIog4JRXpQy3Hs1zRtWXZybAFgP+nZiApClwbFwR6xBDIgxV9MaImaEfMN0Y5Sitvttw==", + "license": "UNLICENSED" + }, + "node_modules/@wix/monitoring-browser-sdk-host/node_modules/@wix/monitoring-velo": { + "version": "1.29.0", + "resolved": "https://registry.npmjs.org/@wix/monitoring-velo/-/monitoring-velo-1.29.0.tgz", + "integrity": "sha512-cJZI6yCMdnHuE0lTla04h74IxulsafLwoAx3aQzheda+jBhQtWHHNAB1Dr8OuNFF4jPbLPpHsbGAQNTC8DZ1vg==", + "license": "UNLICENSED", + "dependencies": { + "@wix/monitoring": "1.0.0", + "@wix/monitoring-common": "1.13.0", + "@wix/monitoring-types": "0.17.0" + } + }, + "node_modules/@wix/monitoring-browser-sentry": { + "version": "0.26.0", + "resolved": "https://registry.npmjs.org/@wix/monitoring-browser-sentry/-/monitoring-browser-sentry-0.26.0.tgz", + "integrity": "sha512-ghloi6CN7AvnHAXOxQgwKNcfPl0IZfzHXqLOfoAyVKQ9wqDepkK1HH0Yp5fOz5xvkvlnt0TXc8sTRCScFHTNjg==", + "license": "UNLICENSED", + "dependencies": { + "@wix/monitoring": "1.0.0", + "@wix/monitoring-common-sentry": "0.2.0", + "@wix/monitoring-types": "0.17.0" + } + }, + "node_modules/@wix/monitoring-browser-sentry/node_modules/@wix/monitoring": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@wix/monitoring/-/monitoring-1.0.0.tgz", + "integrity": "sha512-l/0UaT0n4AFVU/7cbe5PLu09WX8s3Zs+dkHf0duacTYwjgnCA+oXuXJ+S2zIKo/85EBZvDEEUx2eD3FUFEztsA==", + "license": "UNLICENSED", + "dependencies": { + "@wix/monitoring-types": "0.17.0" + } + }, + "node_modules/@wix/monitoring-browser-sentry/node_modules/@wix/monitoring-types": { + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/@wix/monitoring-types/-/monitoring-types-0.17.0.tgz", + "integrity": "sha512-1R3kOhnd/gGy3B88NFvIog4JRXpQy3Hs1zRtWXZybAFgP+nZiApClwbFwR6xBDIgxV9MaImaEfMN0Y5Sitvttw==", + "license": "UNLICENSED" + }, + "node_modules/@wix/monitoring-common": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/@wix/monitoring-common/-/monitoring-common-1.13.0.tgz", + "integrity": "sha512-gT7sMyoJ50O+jGFKxxlsvg6vZm2K7Bvmwzf5KI1reu2Owz6eC7Rf2pDKnlMrHLTn2uJA7Zxynrj2nS8j0OURdQ==", + "license": "UNLICENSED" + }, + "node_modules/@wix/monitoring-common-sentry": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@wix/monitoring-common-sentry/-/monitoring-common-sentry-0.2.0.tgz", + "integrity": "sha512-AE87Zt9MsJSbU5RczEqYijataEUyhChaKL06mJodrbt7we/rb09Ji8E4aZX4Pddfsf0tXG+XN0hI5kdeGXxM7g==", + "license": "UNLICENSED" + }, + "node_modules/@wix/monitoring-types": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/@wix/monitoring-types/-/monitoring-types-0.12.0.tgz", + "integrity": "sha512-nlv4jwQMewjzPIWFF9rnKf9WhVojj67oLtvilYXfi+lnhXyVlYOfqCnL3qLJuKtJ6wT5XIJdt0Fj0su2NM5taQ==", + "license": "UNLICENSED" + }, + "node_modules/@wix/monitoring-velo": { + "version": "1.31.0", + "resolved": "https://registry.npmjs.org/@wix/monitoring-velo/-/monitoring-velo-1.31.0.tgz", + "integrity": "sha512-cgSOZO68e2f4DRzI8yyRiwYftn/7GJcxJ5hcpVPL8yfb7g1quPtFtsT5ChEZdvPjhbx1j0MSQ70dqYkVyWsacg==", + "license": "UNLICENSED", + "dependencies": { + "@wix/monitoring": "1.1.0", + "@wix/monitoring-common": "1.13.0", + "@wix/monitoring-types": "1.0.0" + } + }, + "node_modules/@wix/monitoring-velo/node_modules/@wix/monitoring": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@wix/monitoring/-/monitoring-1.1.0.tgz", + "integrity": "sha512-sX8QKAuRZl6gaR5pOJ+8BpxtgOddYzyQAvv706A5F/wsO+YDcSU/ViE1U+i2rL2Jlr2B9J4+vnCCZgQH0CMPmQ==", + "license": "UNLICENSED", + "dependencies": { + "@wix/monitoring-types": "1.0.0" + } + }, + "node_modules/@wix/monitoring-velo/node_modules/@wix/monitoring-types": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@wix/monitoring-types/-/monitoring-types-1.0.0.tgz", + "integrity": "sha512-Cc9t8HCt4QUXZQ6T2+MmtARsEKx/UL78mQpouc1IZhblUsM1QF+N5J+o4D5qxZSjt7GzuIXN5cUdLFuUSAfvyA==", + "license": "UNLICENSED" + }, + "node_modules/@wix/multilingual-manager": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@wix/multilingual-manager/-/multilingual-manager-1.11.0.tgz", + "integrity": "sha512-hyvEM9KqmYgHD00KB4yx4dIotMxM4wajAZlAyQkqjDFJaZtfa/aCidhQgmqJ3gyKbvK3I5MAWS0FyqR3vHNFkw==", + "license": "MIT", + "dependencies": { + "@wix/headless-localization-utils": "^1.0.11", + "lodash": "^4.17.21" + } + }, + "node_modules/@wix/public-editor-platform-errors": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@wix/public-editor-platform-errors/-/public-editor-platform-errors-1.9.0.tgz", + "integrity": "sha512-nHiypFes1kQ0eUlwulwM6fmi5HTTJ0wFISPb6FUgcq3HpvDHbAO3DP8cLOIVYppyTfNv7Ew7yv/oubnuLcX/YA==", + "license": "UNLICENSED" + }, + "node_modules/@wix/public-editor-platform-events": { + "version": "1.344.0", + "resolved": "https://registry.npmjs.org/@wix/public-editor-platform-events/-/public-editor-platform-events-1.344.0.tgz", + "integrity": "sha512-843g44rdXLkvGINjI0gr3ovzgxqWpv/7ueew/wKpf2E4hO15SGTZsXTyFQetUu6v6RlD3/RRzggV2ja+Wq0FxA==", + "license": "UNLICENSED", + "dependencies": { + "@wix/public-editor-platform-interfaces": "1.53.0" + } + }, + "node_modules/@wix/public-editor-platform-interfaces": { + "version": "1.53.0", + "resolved": "https://registry.npmjs.org/@wix/public-editor-platform-interfaces/-/public-editor-platform-interfaces-1.53.0.tgz", + "integrity": "sha512-B5NXmSeehhPLK6n9/pbyBR41o4DivBXwzSRcUJjlUNfXJ3HzlQmMF7YB6NlaLnFTtESIBNDfVEo67snB3QDsiQ==", + "license": "UNLICENSED", + "dependencies": { + "@wix/app-extensions": "^1.0.49", + "@wix/sdk-types": "^1.17.8" + } + }, + "node_modules/@wix/react-component-schema": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@wix/react-component-schema/-/react-component-schema-1.7.0.tgz", + "integrity": "sha512-CpbzOlXkZBdisckBd0i/cE9IxTG2zQmtcbrFvAVtLZJwFct9vVmxnDgj4zZ9uY8IwpeKXcn+4Cqttasp/p/5vQ==", + "license": "ISC" + }, + "node_modules/@wix/react-component-utils": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@wix/react-component-utils/-/react-component-utils-1.7.0.tgz", + "integrity": "sha512-37uRguvTWEGa63ZBndt4o1iydhdmdSaAcOBRWl6KvlJPVLVHj3hdRDn0D7/MsEa1fDBnnKskoI/ik43RT55Xug==", + "license": "ISC", + "peerDependencies": { + "@types/react": "^18.0.0 || ^19.0.0", + "react": "^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@wix/redirects": { + "version": "1.0.115", + "resolved": "https://registry.npmjs.org/@wix/redirects/-/redirects-1.0.115.tgz", + "integrity": "sha512-nPJRPRR7+FDpAaBgCTAhnmQLJ6L2pBgTdEz0Wo5qBV2LYEe5E1dUrkKmg/6JJKKf7Ef+ISbGZzhWo4mRGVocQw==", + "license": "MIT", + "dependencies": { + "@wix/auto_sdk_redirects_redirects": "1.0.43" + } + }, + "node_modules/@wix/sdk": { + "version": "1.21.12", + "resolved": "https://registry.npmjs.org/@wix/sdk/-/sdk-1.21.12.tgz", + "integrity": "sha512-fjRFQJyqsy/ZbTfShBWnA12b61u2LGmyeL1UxAB8/AdsnsknEB2dUTSIdfKfLw852rtX2uqChSOUwADDRqe0Ug==", + "license": "MIT", + "dependencies": { + "@wix/identity": "^1.0.104", + "@wix/image-kit": "^1.114.0", + "@wix/redirects": "^1.0.70", + "@wix/sdk-context": "0.0.1", + "@wix/sdk-runtime": "1.0.14", + "@wix/sdk-types": "1.17.8", + "jose": "^5.10.0", + "type-fest": "^4.41.0" + }, + "optionalDependencies": { + "graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" + } + }, + "node_modules/@wix/sdk-context": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/@wix/sdk-context/-/sdk-context-0.0.1.tgz", + "integrity": "sha512-ziSzrceUC0KFn4IJIVBn1cXXKrZ49ZKG5tQ6fl+TpontyUw5p/Z4VofFUUsnqNl9JYCpYNTzIXpzwok93Vrl8A==", + "license": "UNLICENSED" + }, + "node_modules/@wix/sdk-react-context": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@wix/sdk-react-context/-/sdk-react-context-1.0.2.tgz", + "integrity": "sha512-dX1A+IlLVzsW0pE7ZyhtJHNEeeCYnu/suELnHm4FrxX5alJl1JaEpHbvjuaCt6kD/kDP1iIu9Pu6AvyJUCtYrg==", + "license": "UNLICENSED", + "peerDependencies": { + "react": "*" + } + }, + "node_modules/@wix/sdk-runtime": { + "version": "1.0.14", + "resolved": "https://registry.npmjs.org/@wix/sdk-runtime/-/sdk-runtime-1.0.14.tgz", + "integrity": "sha512-x8XXtrWtRqmHOu5AIrAeM4vSY2HPuRF3k1ESnwrZ7046pESutUe5TZenI3CM/GTbSOpKO25Iuahgbk2xgzye4w==", + "license": "MIT", + "dependencies": { + "@wix/sdk-context": "0.0.1", + "@wix/sdk-types": "1.17.8" + } + }, + "node_modules/@wix/sdk-types": { + "version": "1.17.8", + "resolved": "https://registry.npmjs.org/@wix/sdk-types/-/sdk-types-1.17.8.tgz", + "integrity": "sha512-lG9nBTSzMJzuwoUyL0AozxqlIX+iGj8Ji2axhFFRGKAGSSa4ycbdFDdwrMv61+edTnDghJbqu3NY7e5TH7dTQg==", + "license": "MIT", + "dependencies": { + "@wix/error-handler-types": "^1.19.0", + "@wix/monitoring-types": "^0.12.0", + "type-fest": "^4.41.0" + } + }, + "node_modules/@wix/services-definitions": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@wix/services-definitions/-/services-definitions-1.0.3.tgz", + "integrity": "sha512-nhkN+ccXnV+MW/CtVOVu2ibXrxOLVv9oDza0wc4FWRzGDubwnIpRxh/x1pPLH5nI+vOF9mQxHCmoSET5Jn1J/Q==", + "dependencies": { + "type-fest": "^4.41.0" + } + }, + "node_modules/@wix/services-manager-react": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/@wix/services-manager-react/-/services-manager-react-1.0.6.tgz", + "integrity": "sha512-c0Zx+DCn993NbIYtWeNsU2HPTJ/+DhGMP3zMBbyJTQHUCBfCEKb74dbDILUadAcg+3ZNIJdIg96m6awj8NfsbQ==", + "license": "MIT", + "dependencies": { + "@preact/signals-react": "^3.6.1", + "@wix/sdk-react-context": "1.0.2", + "@wix/services-definitions": "^1.0.3" + }, + "peerDependencies": { + "@wix/services-manager": "^1.0.0", + "react": "^16.14.0 || 17.x || 18.x || 19.x", + "react-dom": "^18.3.1", + "use-sync-external-store": "^1.0.0" + } + }, + "node_modules/@wix/site": { + "version": "1.62.0", + "resolved": "https://registry.npmjs.org/@wix/site/-/site-1.62.0.tgz", + "integrity": "sha512-v3cQfrjEVZ2bfd80cp3frtmwYfv8YWxFX1BGUeSm/j3ea8EV8DPC9NrRJIvE1DlymAdAql9hFMgSD8oG21nT4g==", + "license": "UNLICENSED", + "dependencies": { + "@babel/runtime": "^7.0.0", + "@wix/analytics": "1.19.0", + "@wix/authentication": "1.14.0", + "@wix/consent-policy-manager": "1.15.0", + "@wix/multilingual-manager": "1.11.0", + "@wix/sdk-types": "^1.13.2" + } + }, + "node_modules/@wix/unidriver-common": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@wix/unidriver-common/-/unidriver-common-1.5.5.tgz", + "integrity": "sha512-Jcn8I1OZSiMEj2bjFMAJ73T7C92jKTcqmWA6cSnEo2xBkhZ3X2Y6IBBC69jAU2vs5ahCa91c0Mmv2GH8t9MVQQ==", + "license": "UNLICENSED", + "dependencies": { + "@wix/unidriver-core": "^1.5.5" + } + }, + "node_modules/@wix/unidriver-core": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@wix/unidriver-core/-/unidriver-core-1.5.5.tgz", + "integrity": "sha512-y1503p7d8FQoZczAXnmRQvm6ocbDusUiVJA7qR5dheAxAYVteOuNGFuwQZEmWFGSB96GpGKSRI3K/LknhF2XGQ==", + "license": "UNLICENSED" + }, + "node_modules/@wix/unidriver-jsdom-react": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@wix/unidriver-jsdom-react/-/unidriver-jsdom-react-1.5.5.tgz", + "integrity": "sha512-02lOjdh7vgzFmblbA8ahF7sJ6BixvGxFRs0DAlOa9nv/s4uT7KlsnSJ/7bAWw4dQGANz4zXp5h0PDLwgxSxmMQ==", + "license": "UNLICENSED", + "dependencies": { + "@testing-library/dom": "^10.4.1", + "@wix/unidriver-common": "^1.5.5", + "@wix/unidriver-core": "^1.5.5" + }, + "peerDependencies": { + "@testing-library/react": ">=14 <17", + "react": ">=16 <=19", + "react-dom": ">=16 <=19" + } + }, + "node_modules/@wix/unidriver-jsdom-react-legacy": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@wix/unidriver-jsdom-react-legacy/-/unidriver-jsdom-react-legacy-1.5.5.tgz", + "integrity": "sha512-IK0oyI4yD8GWqC7L7OMG4Ab0K8b+zieufnWtoTBWu0jvVV+35pmD/70KWDKXb5v9snxS7NqgAoO/pHvwueDVCQ==", + "license": "UNLICENSED", + "dependencies": { + "@wix/unidriver-common": "^1.5.5", + "@wix/unidriver-core": "^1.5.5" + }, + "peerDependencies": { + "react": ">=16.14.0 <=18", + "react-dom": ">=16.14.0 <=18" + } + }, + "node_modules/@wix/unidriver-playwright": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@wix/unidriver-playwright/-/unidriver-playwright-1.5.5.tgz", + "integrity": "sha512-9djmN4r5om4OuZo7Cmhp514lQyoURFajW35QcbicGef/rDrpCwPdyYJjg6LSZn2UKbXxxWlNYJVnSvwUz+j63A==", + "license": "UNLICENSED", + "dependencies": { + "@wix/unidriver-common": "^1.5.5", + "@wix/unidriver-core": "^1.5.5" + } + }, + "node_modules/@wix/unidriver-puppeteer": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@wix/unidriver-puppeteer/-/unidriver-puppeteer-1.5.5.tgz", + "integrity": "sha512-jZUxBJowQ2QfZKfnoioTDWe17S5CBp3FINmnQQRh9s1SO4Uzo3J8D29PsAgA9wwirqgSWPDFe4OLsDFyBCPqbA==", + "license": "UNLICENSED", + "dependencies": { + "@wix/unidriver-common": "^1.5.5", + "@wix/unidriver-core": "^1.5.5", + "array.prototype.at": "^1.1.3" + } + }, + "node_modules/@wix/wix-ui-icons-common": { + "version": "3.165.0", + "resolved": "https://registry.npmjs.org/@wix/wix-ui-icons-common/-/wix-ui-icons-common-3.165.0.tgz", + "integrity": "sha512-FqSjzkY6WqQoFzDTLtvzkzAp17g6zuogrFhijsk/IQF3/fTJF9e8rlTIPbmu0a/YyQM84XrvxXBnA0RTmi0D7w==", + "license": "UNLICENSED", + "dependencies": { + "@babel/runtime": "^7.29.2", + "react-error-boundary": "^5.0.0", + "tslib": "^2.8.1" + } + }, + "node_modules/@wix/wix-ui-test-utils": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/@wix/wix-ui-test-utils/-/wix-ui-test-utils-1.3.4.tgz", + "integrity": "sha512-oc1N21VYKmaVuQmIBiPuEJu9YSMCmf1J/pp1achCwYrgvIPZ4b0l//FnMfpWnrNCjgwVSOzmbTVRbMbpQ4rmSQ==", + "license": "UNLICENSED", + "dependencies": { + "@babel/runtime": "^7.28.4", + "@stylable/uni-driver": "^2.5.3", + "@wix/unidriver-core": "^1.4.7", + "@wix/unidriver-jsdom-react": "^1.4.7", + "@wix/unidriver-jsdom-react-legacy": "^1.4.7", + "@wix/unidriver-playwright": "^1.4.7", + "@wix/unidriver-puppeteer": "^1.4.7", + "tslib": "^2.8.1" + }, + "peerDependencies": { + "@testing-library/react": ">=12", + "playwright": "^1.54.2", + "puppeteer": "^14.0.0", + "puppeteer-core": "^14.0.0" + }, + "peerDependenciesMeta": { + "@testing-library/react": { + "optional": true + }, + "playwright": { + "optional": true + }, + "puppeteer": { + "optional": true + }, + "puppeteer-core": { + "optional": true + } + } + }, + "node_modules/@wix/workspace": { + "version": "1.3.11", + "resolved": "https://registry.npmjs.org/@wix/workspace/-/workspace-1.3.11.tgz", + "integrity": "sha512-I2G03FqJhd2vvjXBrShKWpBr4HIH6yZfsvWFQGdnp0I7W8CiTZKBTOVfziv4SqhrxPOPswgTm0M3XqO4eDmGKQ==", + "license": "UNLICENSED", + "dependencies": { + "@babel/runtime": "^7.0.0", + "@wix/credits-types": "^1.0.0", + "@wix/sdk-runtime": "^1.0.7", + "@wix/sdk-types": "^1.17.3" + }, + "peerDependencies": { + "@wix/sdk": "^1.21.3" + } + }, + "node_modules/abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", + "dev": true, + "license": "ISC" + }, + "node_modules/acorn": { + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.16.0.tgz", + "integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==", + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/agentkeepalive": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.6.0.tgz", + "integrity": "sha512-kja8j7PjmncONqaTsB8fQ+wE2mSU2DJ9D4XKoJ5PFWIdRMa6SLSN1ff4mOr4jCbfRSsxR4keIiySJU0N9T5hIQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "humanize-ms": "^1.2.1" + }, + "engines": { + "node": ">= 8.0.0" + } + }, + "node_modules/aggregate-error": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", + "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", + "dev": true, + "license": "MIT", + "dependencies": { + "clean-stack": "^2.0.0", + "indent-string": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/ajv": { + "version": "8.20.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.20.0.tgz", + "integrity": "sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ajv-draft-04": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/ajv-draft-04/-/ajv-draft-04-1.0.0.tgz", + "integrity": "sha512-mv00Te6nmYbRp5DCwclxtt7yV/joXJPGS7nM+97GdxvuttCOfgI3K4U25zboyeX0O+myI8ERluxQe5wljMmVIw==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "ajv": "^8.5.0" + }, + "peerDependenciesMeta": { + "ajv": { + "optional": true + } + } + }, + "node_modules/ansi-align": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.1.tgz", + "integrity": "sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==", + "license": "ISC", + "dependencies": { + "string-width": "^4.1.0" + } + }, + "node_modules/ansi-align/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "license": "MIT" + }, + "node_modules/ansi-align/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "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/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "license": "ISC", + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/anymatch/node_modules/picomatch": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", + "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/aproba": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.1.0.tgz", + "integrity": "sha512-tLIEcj5GuR2RSTnxNKdkK0dJ/GrC7P38sUkiDmDuHfsHmbagTFAxDVIBltoklXEVIQ/f14IL8IMJ5pn9Hez1Ew==", + "dev": true, + "license": "ISC" + }, + "node_modules/are-we-there-yet": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-3.0.1.tgz", + "integrity": "sha512-QZW4EDmGwlYur0Yyf/b2uGucHQMa8aFUP7eu9ddR73vvhFyt4V0Vl3QHPcTNJ8l6qYOBdxgXdnBXQrHilfRQBg==", + "deprecated": "This package is no longer supported.", + "dev": true, + "license": "ISC", + "dependencies": { + "delegates": "^1.0.0", + "readable-stream": "^3.6.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "license": "Python-2.0" + }, + "node_modules/aria-hidden": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/aria-hidden/-/aria-hidden-1.2.6.tgz", + "integrity": "sha512-ik3ZgC9dY/lYVVM++OISsaYDeg1tb0VtP5uL3ouh1koGOaUMDPpbFIei4JkFimWUFPn90sbMNMXQAIVOlnYKJA==", + "license": "MIT", + "dependencies": { + "tslib": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/aria-query": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.0.tgz", + "integrity": "sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==", + "license": "Apache-2.0", + "dependencies": { + "dequal": "^2.0.3" + } + }, + "node_modules/array-buffer-byte-length": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.2.tgz", + "integrity": "sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "is-array-buffer": "^3.0.5" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array-from": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/array-from/-/array-from-2.1.1.tgz", + "integrity": "sha512-GQTc6Uupx1FCavi5mPzBvVT7nEOeWMmUA9P95wpfpW1XwMSKs+KaymD5C2Up7KAUKg/mYwbsUYzdZWcoajlNZg==", + "license": "MIT" + }, + "node_modules/array-iterate": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/array-iterate/-/array-iterate-2.0.1.tgz", + "integrity": "sha512-I1jXZMjAgCMmxT4qxXfPXa6SthSoE8h6gkSI9BGGNv8mP8G/v0blc+qFnZu6K42vTOiuME596QaLO0TP3Lk0xg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/array.prototype.at": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/array.prototype.at/-/array.prototype.at-1.1.3.tgz", + "integrity": "sha512-TX4J1Uig4skvpOakrvP8q/uyhUj+ZDNmQoZpHf3MsKTrXcMHDPrgJlpv2nRJMfANrsmhg1JoOGrg3yOp209SWg==", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-object-atoms": "^1.0.0", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/arraybuffer.prototype.slice": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.4.tgz", + "integrity": "sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ==", + "license": "MIT", + "dependencies": { + "array-buffer-byte-length": "^1.0.1", + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "is-array-buffer": "^3.0.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/asap": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", + "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==", + "license": "MIT" + }, + "node_modules/astro": { + "version": "5.18.2", + "resolved": "https://registry.npmjs.org/astro/-/astro-5.18.2.tgz", + "integrity": "sha512-TnFwLnAXty5MXKPDGuKXqK4AMBXG+FH6RUdK7Oyc3gyfNoFIthT+4eRbzOK43bdRlLaZuxgciDSjgtggZ3OtGQ==", + "license": "MIT", + "dependencies": { + "@astrojs/compiler": "^2.13.0", + "@astrojs/internal-helpers": "0.7.6", + "@astrojs/markdown-remark": "6.3.11", + "@astrojs/telemetry": "3.3.0", + "@capsizecss/unpack": "^4.0.0", + "@oslojs/encoding": "^1.1.0", + "@rollup/pluginutils": "^5.3.0", + "acorn": "^8.15.0", + "aria-query": "^5.3.2", + "axobject-query": "^4.1.0", + "boxen": "8.0.1", + "ci-info": "^4.3.1", + "clsx": "^2.1.1", + "common-ancestor-path": "^1.0.1", + "cookie": "^1.1.1", + "cssesc": "^3.0.0", + "debug": "^4.4.3", + "deterministic-object-hash": "^2.0.2", + "devalue": "^5.6.2", + "diff": "^8.0.3", + "dlv": "^1.1.3", + "dset": "^3.1.4", + "es-module-lexer": "^1.7.0", + "esbuild": "^0.27.3", + "estree-walker": "^3.0.3", + "flattie": "^1.1.1", + "fontace": "~0.4.0", + "github-slugger": "^2.0.0", + "html-escaper": "3.0.3", + "http-cache-semantics": "^4.2.0", + "import-meta-resolve": "^4.2.0", + "js-yaml": "^4.1.1", + "magic-string": "^0.30.21", + "magicast": "^0.5.1", + "mrmime": "^2.0.1", + "neotraverse": "^0.6.18", + "p-limit": "^6.2.0", + "p-queue": "^8.1.1", + "package-manager-detector": "^1.6.0", + "piccolore": "^0.1.3", + "picomatch": "^4.0.3", + "prompts": "^2.4.2", + "rehype": "^13.0.2", + "semver": "^7.7.3", + "shiki": "^3.21.0", + "smol-toml": "^1.6.0", + "svgo": "^4.0.0", + "tinyexec": "^1.0.2", + "tinyglobby": "^0.2.15", + "tsconfck": "^3.1.6", + "ultrahtml": "^1.6.0", + "unifont": "~0.7.3", + "unist-util-visit": "^5.0.0", + "unstorage": "^1.17.4", + "vfile": "^6.0.3", + "vite": "^6.4.1", + "vitefu": "^1.1.1", + "xxhash-wasm": "^1.1.0", + "yargs-parser": "^21.1.1", + "yocto-spinner": "^0.2.3", + "zod": "^3.25.76", + "zod-to-json-schema": "^3.25.1", + "zod-to-ts": "^1.2.0" + }, + "bin": { + "astro": "astro.js" + }, + "engines": { + "node": "18.20.8 || ^20.3.0 || >=22.0.0", + "npm": ">=9.6.5", + "pnpm": ">=7.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/astrodotbuild" + }, + "optionalDependencies": { + "sharp": "^0.34.0" + } + }, + "node_modules/astro/node_modules/aria-query": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.2.tgz", + "integrity": "sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==", + "license": "Apache-2.0", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/astro/node_modules/semver": { + "version": "7.8.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.1.tgz", + "integrity": "sha512-rkVq3IXh+4FDGch+KwzX3aV9W3kO54GyEgpvBzSyctDA6Xtd7RJQV1xmXbeQp5v7+VzLOfVqiutSE6GICgPFvg==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/astro/node_modules/zod": { + "version": "3.25.76", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz", + "integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + }, + "node_modules/async-function": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/async-function/-/async-function-1.0.0.tgz", + "integrity": "sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/available-typed-arrays": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", + "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", + "license": "MIT", + "dependencies": { + "possible-typed-array-names": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/axobject-query": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-4.1.0.tgz", + "integrity": "sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==", + "license": "Apache-2.0", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/bail": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/bail/-/bail-2.0.2.tgz", + "integrity": "sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/base-64": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/base-64/-/base-64-1.0.0.tgz", + "integrity": "sha512-kwDPIFCGx0NZHog36dj+tHiwP4QMzsZ3AgMViUBKI0+V5n4U0ufTCUMhnQ04diaRI8EX/QcPfql7zlhZ7j4zgg==", + "license": "MIT" + }, + "node_modules/baseline-browser-mapping": { + "version": "2.10.33", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.33.tgz", + "integrity": "sha512-bA6+tcSLpz2tIEdDXZPpPTIuxBcC4+w6SieaYyfigIa4h8GlFxbA17v22Vx3JUtuZQj9SgOsnbK+aTBzyDyEuw==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "baseline-browser-mapping": "dist/cli.cjs" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/blake3-wasm": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/blake3-wasm/-/blake3-wasm-2.1.5.tgz", + "integrity": "sha512-F1+K8EbfOZE49dtoPtmxUQrpXaBIl3ICvasLh+nJta0xkz+9kF/7uet9fLnwKqhDrmj6g+6K3Tw9yQPUg2ka5g==", + "dev": true, + "license": "MIT" + }, + "node_modules/boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==", + "license": "ISC" + }, + "node_modules/boxen": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/boxen/-/boxen-8.0.1.tgz", + "integrity": "sha512-F3PH5k5juxom4xktynS7MoFY+NUWH5LC4CnH11YB8NPew+HLpmBLCybSAEyb2F+4pRXhuhWqFesoQd6DAyc2hw==", + "license": "MIT", + "dependencies": { + "ansi-align": "^3.0.1", + "camelcase": "^8.0.0", + "chalk": "^5.3.0", + "cli-boxes": "^3.0.0", + "string-width": "^7.2.0", + "type-fest": "^4.21.0", + "widest-line": "^5.0.0", + "wrap-ansi": "^9.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/brace-expansion": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.15.tgz", + "integrity": "sha512-EwOCDEex4quD37XhqM3omwtMoJjr//isUZz1JopUNWms+4Z2ViyM/k1YIRePpoVNnQhENnxtFjLaxNHrT7xIUg==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/browserslist": { + "version": "4.28.2", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.2.tgz", + "integrity": "sha512-48xSriZYYg+8qXna9kwqjIVzuQxi+KYWp2+5nCYnYKPTr0LvD89Jqk2Or5ogxz0NUMfIjhh2lIUX/LyX9B4oIg==", + "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": { + "baseline-browser-mapping": "^2.10.12", + "caniuse-lite": "^1.0.30001782", + "electron-to-chromium": "^1.5.328", + "node-releases": "^2.0.36", + "update-browserslist-db": "^1.2.3" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/cacache": { + "version": "15.3.0", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-15.3.0.tgz", + "integrity": "sha512-VVdYzXEn+cnbXpFgWs5hTT7OScegHVmLhJIR8Ufqk3iFD6A6j5iSX1KuBTfNEv4tdJWE2PzA6IVFtcLC7fN9wQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "@npmcli/fs": "^1.0.0", + "@npmcli/move-file": "^1.0.1", + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "glob": "^7.1.4", + "infer-owner": "^1.0.4", + "lru-cache": "^6.0.0", + "minipass": "^3.1.1", + "minipass-collect": "^1.0.2", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.2", + "mkdirp": "^1.0.3", + "p-map": "^4.0.0", + "promise-inflight": "^1.0.1", + "rimraf": "^3.0.2", + "ssri": "^8.0.1", + "tar": "^6.0.2", + "unique-filename": "^1.1.1" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/cacache/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/cacache/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true, + "license": "ISC" + }, + "node_modules/call-bind": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.9.tgz", + "integrity": "sha512-a/hy+pNsFUTR+Iz8TCJvXudKVLAnz/DyeSUo10I5yvFDQJBFU2s9uqQpoSrJlroHUKoKqzg+epxyP9lqFdzfBQ==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "get-intrinsic": "^1.3.0", + "set-function-length": "^1.2.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/call-bound": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/camelcase": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-8.0.0.tgz", + "integrity": "sha512-8WB3Jcas3swSvjIeA2yvCJ+Miyz5l1ZmB6HFb9R1317dt9LCQoswg/BGrmAmkWVEszSrrg4RwmO46qIm2OEnSA==", + "license": "MIT", + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001793", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001793.tgz", + "integrity": "sha512-iwSsYWaCOoh26cV8NwNRViHlrfUvYsHDfRVcbtmw0Kg6PJIZZXwMkj1442FYLBGkeUf1juAsU3DTfxW579mrPA==", + "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/ccount": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/ccount/-/ccount-2.0.1.tgz", + "integrity": "sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/chalk": { + "version": "5.6.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.6.2.tgz", + "integrity": "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==", + "license": "MIT", + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/character-entities": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-2.0.2.tgz", + "integrity": "sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/character-entities-html4": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/character-entities-html4/-/character-entities-html4-2.1.0.tgz", + "integrity": "sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/character-entities-legacy": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-3.0.0.tgz", + "integrity": "sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/chart.js": { + "version": "2.9.4", + "resolved": "https://registry.npmjs.org/chart.js/-/chart.js-2.9.4.tgz", + "integrity": "sha512-B07aAzxcrikjAPyV+01j7BmOpxtQETxTSlQ26BEYJ+3iUkbNKaOJ/nDbT6JjyqYxseM0ON12COHYdU2cTIjC7A==", + "license": "MIT", + "dependencies": { + "chartjs-color": "^2.1.0", + "moment": "^2.10.2" + } + }, + "node_modules/chartjs-color": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/chartjs-color/-/chartjs-color-2.4.1.tgz", + "integrity": "sha512-haqOg1+Yebys/Ts/9bLo/BqUcONQOdr/hoEr2LLTRl6C5LXctUdHxsCYfvQVg5JIxITrfCNUDr4ntqmQk9+/0w==", + "license": "MIT", + "dependencies": { + "chartjs-color-string": "^0.6.0", + "color-convert": "^1.9.3" + } + }, + "node_modules/chartjs-color-string": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/chartjs-color-string/-/chartjs-color-string-0.6.0.tgz", + "integrity": "sha512-TIB5OKn1hPJvO7JcteW4WY/63v6KwEdt6udfnDE9iCAZgy+V4SrbSxoIbTw/xkUIapjEI4ExGtD0+6D3KyFd7A==", + "license": "MIT", + "dependencies": { + "color-name": "^1.0.0" + } + }, + "node_modules/chokidar": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", + "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", + "dev": true, + "license": "MIT", + "dependencies": { + "readdirp": "^4.0.1" + }, + "engines": { + "node": ">= 14.16.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/chownr": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "node_modules/ci-info": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-4.4.0.tgz", + "integrity": "sha512-77PSwercCZU2Fc4sX94eF8k8Pxte6JAwL4/ICZLFjJLqegs7kCuAsqqj/70NQF6TvDpgFjkubQB2FW2ZZddvQg==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/classnames": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.5.1.tgz", + "integrity": "sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow==", + "license": "MIT" + }, + "node_modules/clean-stack": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", + "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/cli-boxes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-3.0.0.tgz", + "integrity": "sha512-/lzGpEWL/8PfI0BmBOPRwp0c/wFNX1RdUML3jK/RcSBA9T8mZDdQpqYBKtCFTOfQbwPqWEOpjqW+Fnayc0969g==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/cliui/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/cliui/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/cliui/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT" + }, + "node_modules/cliui/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "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/cliui/node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/clsx": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", + "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/color": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color/-/color-2.0.1.tgz", + "integrity": "sha512-ubUCVVKfT7r2w2D3qtHakj8mbmKms+tThR8gI8zEYCbUBl8/voqFGt3kgBqGwXAopgXybnkuOq+qMYCRrp4cXw==", + "license": "MIT", + "dependencies": { + "color-convert": "^1.9.1", + "color-string": "^1.5.2" + } + }, + "node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "license": "MIT", + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/color-convert/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "license": "MIT" + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "license": "MIT" + }, + "node_modules/color-string": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz", + "integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==", + "license": "MIT", + "dependencies": { + "color-name": "^1.0.0", + "simple-swizzle": "^0.2.2" + } + }, + "node_modules/color-support": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", + "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", + "dev": true, + "license": "ISC", + "bin": { + "color-support": "bin.js" + } + }, + "node_modules/comlink": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/comlink/-/comlink-4.3.0.tgz", + "integrity": "sha512-mu4KKKNuW8TvkfpW/H88HBPeILubBS6T94BdD1VWBXNXfiyqVtwUCVNO1GeNOBTsIswzsMjWlycYr+77F5b84g==", + "license": "Apache-2.0" + }, + "node_modules/comma-separated-tokens": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-2.0.3.tgz", + "integrity": "sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/commander": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-11.1.0.tgz", + "integrity": "sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==", + "license": "MIT", + "engines": { + "node": ">=16" + } + }, + "node_modules/common-ancestor-path": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/common-ancestor-path/-/common-ancestor-path-1.0.1.tgz", + "integrity": "sha512-L3sHRo1pXXEqX8VU28kfgUY+YGsk09hPqZiZmLacNib6XNTCM8ubYeT7ryXQw8asB1sKgcU5lkB7ONug08aB8w==", + "license": "ISC" + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true, + "license": "MIT" + }, + "node_modules/console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true, + "license": "MIT" + }, + "node_modules/cookie": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-1.1.1.tgz", + "integrity": "sha512-ei8Aos7ja0weRpFzJnEA9UHJ/7XQmqglbRwnf2ATjcB9Wq874VKH9kfjjirM6UhU2/E5fFYadylyhFldcqSidQ==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/cookie-es": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/cookie-es/-/cookie-es-1.2.3.tgz", + "integrity": "sha512-lXVyvUvrNXblMqzIRrxHb57UUVmqsSWlxqt3XIjCkUP0wDAf6uicO6KMbEgYrMNtEvWgWHwe42CKxPu9MYAnWw==", + "license": "MIT" + }, + "node_modules/core-js": { + "version": "3.49.0", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.49.0.tgz", + "integrity": "sha512-es1U2+YTtzpwkxVLwAFdSpaIMyQaq0PBgm3YD1W3Qpsn1NAmO3KSgZfu+oGSWVu6NvLHoHCV/aYcsE5wiB7ALg==", + "hasInstallScript": true, + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" + } + }, + "node_modules/cross-fetch": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.2.0.tgz", + "integrity": "sha512-Q+xVJLoGOeIMXZmbUK4HYk+69cQH6LudR0Vu/pRm2YlU/hDV9CiS0gKUMaWY5f2NeUH9C1nV3bsTlCo0FsTV1Q==", + "license": "MIT", + "dependencies": { + "node-fetch": "^2.7.0" + } + }, + "node_modules/crossws": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/crossws/-/crossws-0.3.5.tgz", + "integrity": "sha512-ojKiDvcmByhwa8YYqbQI/hg7MEU0NC03+pSdEq4ZUnZR9xXpwk7E43SMNGkn+JxJGPFtNvQ48+vV2p+P1ml5PA==", + "license": "MIT", + "dependencies": { + "uncrypto": "^0.1.3" + } + }, + "node_modules/css-element-queries": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/css-element-queries/-/css-element-queries-1.2.3.tgz", + "integrity": "sha512-QK9uovYmKTsV2GXWQiMOByVNrLn2qz6m3P7vWpOR4IdD6I3iXoDw5qtgJEN3Xq7gIbdHVKvzHjdAtcl+4Arc4Q==", + "license": "MIT" + }, + "node_modules/css-select": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.2.2.tgz", + "integrity": "sha512-TizTzUddG/xYLA3NXodFM0fSbNizXjOKhqiQQwvhlspadZokn1KDy0NZFS0wuEubIYAV5/c1/lAr0TaaFXEXzw==", + "license": "BSD-2-Clause", + "dependencies": { + "boolbase": "^1.0.0", + "css-what": "^6.1.0", + "domhandler": "^5.0.2", + "domutils": "^3.0.1", + "nth-check": "^2.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/css-tree": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-3.2.1.tgz", + "integrity": "sha512-X7sjQzceUhu1u7Y/ylrRZFU2FS6LRiFVp6rKLPg23y3x3c3DOKAwuXGDp+PAGjh6CSnCjYeAul8pcT8bAl+lSA==", + "license": "MIT", + "dependencies": { + "mdn-data": "2.27.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0" + } + }, + "node_modules/css-what": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.2.2.tgz", + "integrity": "sha512-u/O3vwbptzhMs3L1fQE82ZSLHQQfto5gyZzwteVIEyeaY5Fc7R4dapF/BvRoSYFeqfBk4m0V1Vafq5Pjv25wvA==", + "license": "BSD-2-Clause", + "engines": { + "node": ">= 6" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", + "license": "MIT", + "bin": { + "cssesc": "bin/cssesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/csso": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/csso/-/csso-5.0.5.tgz", + "integrity": "sha512-0LrrStPOdJj+SPCCrGhzryycLjwcgUSHBtxNA8aIDxf0GLsRh1cKYhB00Gd1lDOS4yGH69+SNn13+TWbVHETFQ==", + "license": "MIT", + "dependencies": { + "css-tree": "~2.2.0" + }, + "engines": { + "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0", + "npm": ">=7.0.0" + } + }, + "node_modules/csso/node_modules/css-tree": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.2.1.tgz", + "integrity": "sha512-OA0mILzGc1kCOCSJerOeqDxDQ4HOh+G8NbOJFOTgOCzpw7fCBubk0fEyxp8AgOL/jvLgYA/uV0cMbe43ElF1JA==", + "license": "MIT", + "dependencies": { + "mdn-data": "2.0.28", + "source-map-js": "^1.0.1" + }, + "engines": { + "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0", + "npm": ">=7.0.0" + } + }, + "node_modules/csso/node_modules/mdn-data": { + "version": "2.0.28", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.28.tgz", + "integrity": "sha512-aylIc7Z9y4yzHYAJNuESG3hfhC+0Ibp/MAMiaOZgNv4pmEdFyfZhhhny4MNiAfWdBQ1RQ2mfDWmM1x8SvGyp8g==", + "license": "CC0-1.0" + }, + "node_modules/csstype": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", + "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", + "license": "MIT" + }, + "node_modules/d3-array": { + "version": "2.12.1", + "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-2.12.1.tgz", + "integrity": "sha512-B0ErZK/66mHtEsR1TkPEEkwdy+WDesimkM5gpZr5Dsg54BiTA5RXtYW5qTLIAcekaS9xfZrzBLF/OAkB3Qn1YQ==", + "license": "BSD-3-Clause", + "dependencies": { + "internmap": "^1.0.0" + } + }, + "node_modules/d3-axis": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/d3-axis/-/d3-axis-2.1.0.tgz", + "integrity": "sha512-z/G2TQMyuf0X3qP+Mh+2PimoJD41VOCjViJzT0BHeL/+JQAofkiWZbWxlwFGb1N8EN+Cl/CW+MUKbVzr1689Cw==", + "license": "BSD-3-Clause" + }, + "node_modules/d3-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/d3-color/-/d3-color-2.0.0.tgz", + "integrity": "sha512-SPXi0TSKPD4g9tw0NMZFnR95XVgUZiBH+uUTqQuDu1OsE2zomHU7ho0FISciaPvosimixwHFl3WHLGabv6dDgQ==", + "license": "BSD-3-Clause" + }, + "node_modules/d3-dispatch": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/d3-dispatch/-/d3-dispatch-2.0.0.tgz", + "integrity": "sha512-S/m2VsXI7gAti2pBoLClFFTMOO1HTtT0j99AuXLoGFKO6deHDdnv6ZGTxSTTUTgO1zVcv82fCOtDjYK4EECmWA==", + "license": "BSD-3-Clause" + }, + "node_modules/d3-ease": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-2.0.0.tgz", + "integrity": "sha512-68/n9JWarxXkOWMshcT5IcjbB+agblQUaIsbnXmrzejn2O82n3p2A9R2zEB9HIEFWKFwPAEDDN8gR0VdSAyyAQ==", + "license": "BSD-3-Clause" + }, + "node_modules/d3-format": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/d3-format/-/d3-format-2.0.0.tgz", + "integrity": "sha512-Ab3S6XuE/Q+flY96HXT0jOXcM4EAClYFnRGY5zsjRGNy6qCYrQsMffs7cV5Q9xejb35zxW5hf/guKw34kvIKsA==", + "license": "BSD-3-Clause" + }, + "node_modules/d3-interpolate": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-2.0.1.tgz", + "integrity": "sha512-c5UhwwTs/yybcmTpAVqwSFl6vrQ8JZJoT5F7xNFK9pymv5C0Ymcc9/LIJHtYIggg/yS9YHw8i8O8tgb9pupjeQ==", + "license": "BSD-3-Clause", + "dependencies": { + "d3-color": "1 - 2" + } + }, + "node_modules/d3-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-2.0.0.tgz", + "integrity": "sha512-ZwZQxKhBnv9yHaiWd6ZU4x5BtCQ7pXszEV9CU6kRgwIQVQGLMv1oiL4M+MK/n79sYzsj+gcgpPQSctJUsLN7fA==", + "license": "BSD-3-Clause" + }, + "node_modules/d3-scale": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/d3-scale/-/d3-scale-3.3.0.tgz", + "integrity": "sha512-1JGp44NQCt5d1g+Yy+GeOnZP7xHo0ii8zsQp6PGzd+C1/dl0KGsp9A7Mxwp+1D1o4unbTTxVdU/ZOIEBoeZPbQ==", + "license": "BSD-3-Clause", + "dependencies": { + "d3-array": "^2.3.0", + "d3-format": "1 - 2", + "d3-interpolate": "1.2.0 - 2", + "d3-time": "^2.1.1", + "d3-time-format": "2 - 3" + } + }, + "node_modules/d3-selection": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-2.0.0.tgz", + "integrity": "sha512-XoGGqhLUN/W14NmaqcO/bb1nqjDAw5WtSYb2X8wiuQWvSZUsUVYsOSkOybUrNvcBjaywBdYPy03eXHMXjk9nZA==", + "license": "BSD-3-Clause" + }, + "node_modules/d3-shape": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-2.1.0.tgz", + "integrity": "sha512-PnjUqfM2PpskbSLTJvAzp2Wv4CZsnAgTfcVRTwW03QR3MkXF8Uo7B1y/lWkAsmbKwuecto++4NlsYcvYpXpTHA==", + "license": "BSD-3-Clause", + "dependencies": { + "d3-path": "1 - 2" + } + }, + "node_modules/d3-time": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/d3-time/-/d3-time-2.1.1.tgz", + "integrity": "sha512-/eIQe/eR4kCQwq7yxi7z4c6qEXf2IYGcjoWB5OOQy4Tq9Uv39/947qlDcN2TLkiTzQWzvnsuYPB9TrWaNfipKQ==", + "license": "BSD-3-Clause", + "dependencies": { + "d3-array": "2" + } + }, + "node_modules/d3-time-format": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-time-format/-/d3-time-format-3.0.0.tgz", + "integrity": "sha512-UXJh6EKsHBTjopVqZBhFysQcoXSv/5yLONZvkQ5Kk3qbwiUYkdX17Xa1PT6U1ZWXGGfB1ey5L8dKMlFq2DO0Ag==", + "license": "BSD-3-Clause", + "dependencies": { + "d3-time": "1 - 2" + } + }, + "node_modules/d3-timer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-2.0.0.tgz", + "integrity": "sha512-TO4VLh0/420Y/9dO3+f9abDEFYeCUr2WZRlxJvbp4HPTQcSylXNiL6yZa9FIUvV1yRiFufl1bszTCLDqv9PWNA==", + "license": "BSD-3-Clause" + }, + "node_modules/d3-transition": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/d3-transition/-/d3-transition-2.0.0.tgz", + "integrity": "sha512-42ltAGgJesfQE3u9LuuBHNbGrI/AJjNL2OAUdclE70UE6Vy239GCBEYD38uBPoLeNsOhFStGpPI0BAOV+HMxog==", + "license": "BSD-3-Clause", + "dependencies": { + "d3-color": "1 - 2", + "d3-dispatch": "1 - 2", + "d3-ease": "1 - 2", + "d3-interpolate": "1 - 2", + "d3-timer": "1 - 2" + }, + "peerDependencies": { + "d3-selection": "2" + } + }, + "node_modules/data-view-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.2.tgz", + "integrity": "sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/data-view-byte-length": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.2.tgz", + "integrity": "sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/inspect-js" + } + }, + "node_modules/data-view-byte-offset": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.1.tgz", + "integrity": "sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/date-fns": { + "version": "2.30.0", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.30.0.tgz", + "integrity": "sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.21.0" + }, + "engines": { + "node": ">=0.11" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/date-fns" + } + }, + "node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decimal.js": { + "version": "10.6.0", + "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.6.0.tgz", + "integrity": "sha512-YpgQiITW3JXGntzdUmyUR1V812Hn8T1YVXhCu+wO3OpS4eU9l4YdD3qjyiKdV6mvV29zapkMeD390UVEf2lkUg==", + "license": "MIT" + }, + "node_modules/decode-named-character-reference": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/decode-named-character-reference/-/decode-named-character-reference-1.3.0.tgz", + "integrity": "sha512-GtpQYB283KrPp6nRw50q3U9/VfOutZOe103qlN7BPP6Ad27xYnOIWv4lPzo8HCAL+mMZofJ9KEy30fq6MfaK6Q==", + "license": "MIT", + "dependencies": { + "character-entities": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/deep-equal": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.1.2.tgz", + "integrity": "sha512-5tdhKF6DbU7iIzrIOa1AOUt39ZRm13cmL1cGEh//aqR8x9+tNfbywRf0n5FD/18OKMdo7DNEtrX2t22ZAkI+eg==", + "license": "MIT", + "dependencies": { + "is-arguments": "^1.1.1", + "is-date-object": "^1.0.5", + "is-regex": "^1.1.4", + "object-is": "^1.1.5", + "object-keys": "^1.1.1", + "regexp.prototype.flags": "^1.5.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/define-properties": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", + "license": "MIT", + "dependencies": { + "define-data-property": "^1.0.1", + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/defu": { + "version": "6.1.7", + "resolved": "https://registry.npmjs.org/defu/-/defu-6.1.7.tgz", + "integrity": "sha512-7z22QmUWiQ/2d0KkdYmANbRUVABpZ9SNYyH5vx6PZ+nE5bcC0l7uFvEfHlyld/HcGBFTL536ClDt3DEcSlEJAQ==", + "license": "MIT" + }, + "node_modules/delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/dequal": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", + "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/destr": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/destr/-/destr-2.0.5.tgz", + "integrity": "sha512-ugFTXCtDZunbzasqBxrK93Ik/DRYsO6S/fedkWEMKqt04xZ4csmnmwGDBAb07QWNaGMAmnTIemsYZCksjATwsA==", + "license": "MIT" + }, + "node_modules/detect-europe-js": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/detect-europe-js/-/detect-europe-js-0.1.2.tgz", + "integrity": "sha512-lgdERlL3u0aUdHocoouzT10d9I89VVhk0qNRmll7mXdGfJT1/wqZ2ZLA4oJAjeACPY5fT1wsbq2AT+GkuInsow==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/faisalman" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/ua-parser-js" + }, + { + "type": "paypal", + "url": "https://paypal.me/faisalman" + } + ], + "license": "MIT" + }, + "node_modules/detect-libc": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", + "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", + "devOptional": true, + "license": "Apache-2.0", + "engines": { + "node": ">=8" + } + }, + "node_modules/detect-node-es": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/detect-node-es/-/detect-node-es-1.1.0.tgz", + "integrity": "sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ==", + "license": "MIT" + }, + "node_modules/deterministic-object-hash": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/deterministic-object-hash/-/deterministic-object-hash-2.0.2.tgz", + "integrity": "sha512-KxektNH63SrbfUyDiwXqRb1rLwKt33AmMv+5Nhsw1kqZ13SJBRTgZHtGbE+hH3a1mVW1cz+4pqSWVPAtLVXTzQ==", + "license": "MIT", + "dependencies": { + "base-64": "^1.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/devalue": { + "version": "5.8.1", + "resolved": "https://registry.npmjs.org/devalue/-/devalue-5.8.1.tgz", + "integrity": "sha512-4CXDYRBGqN+57wVJkuXBYmpAVUSg3L6JAQa/DFqm238G73E1wuyc/JhGQJzN7vUf/CMphYau2zXbfWzDR5aTEw==", + "license": "MIT" + }, + "node_modules/devlop": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/devlop/-/devlop-1.1.0.tgz", + "integrity": "sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==", + "license": "MIT", + "dependencies": { + "dequal": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/diff": { + "version": "8.0.4", + "resolved": "https://registry.npmjs.org/diff/-/diff-8.0.4.tgz", + "integrity": "sha512-DPi0FmjiSU5EvQV0++GFDOJ9ASQUVFh5kD+OzOnYdi7n3Wpm9hWWGfB/O2blfHcMVTL5WkQXSnRiK9makhrcnw==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/difference": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/difference/-/difference-1.0.2.tgz", + "integrity": "sha512-bNfxVectrfp4CcZx/qdVhnyPnMWMetwMDrJB6jyEKUTqA4y6WQpeeGSWD8ZCUVzc4TKaeHHASlJwlhDYy3SSeg==", + "license": "MIT" + }, + "node_modules/dlv": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", + "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==", + "license": "MIT" + }, + "node_modules/dnd-core": { + "version": "11.1.3", + "resolved": "https://registry.npmjs.org/dnd-core/-/dnd-core-11.1.3.tgz", + "integrity": "sha512-QugF55dNW+h+vzxVJ/LSJeTeUw9MCJ2cllhmVThVPEtF16ooBkxj0WBE5RB+AceFxMFo1rO6bJKXtqKl+JNnyA==", + "license": "MIT", + "dependencies": { + "@react-dnd/asap": "^4.0.0", + "@react-dnd/invariant": "^2.0.0", + "redux": "^4.0.4" + } + }, + "node_modules/dom-accessibility-api": { + "version": "0.5.16", + "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.5.16.tgz", + "integrity": "sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==", + "license": "MIT" + }, + "node_modules/dom-align": { + "version": "1.12.4", + "resolved": "https://registry.npmjs.org/dom-align/-/dom-align-1.12.4.tgz", + "integrity": "sha512-R8LUSEay/68zE5c8/3BDxiTEvgb4xZTF0RKmAHfiEVN3klfIpXfi2/QCoiWPccVQ0J/ZGdz9OjzL4uJEP/MRAw==", + "license": "MIT" + }, + "node_modules/dom-helpers": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-5.2.1.tgz", + "integrity": "sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.8.7", + "csstype": "^3.0.2" + } + }, + "node_modules/dom-serializer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", + "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", + "license": "MIT", + "dependencies": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.2", + "entities": "^4.2.0" + }, + "funding": { + "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" + } + }, + "node_modules/dom-serializer/node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/domelementtype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "license": "BSD-2-Clause" + }, + "node_modules/domhandler": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", + "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", + "license": "BSD-2-Clause", + "dependencies": { + "domelementtype": "^2.3.0" + }, + "engines": { + "node": ">= 4" + }, + "funding": { + "url": "https://github.com/fb55/domhandler?sponsor=1" + } + }, + "node_modules/domutils": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.2.2.tgz", + "integrity": "sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==", + "license": "BSD-2-Clause", + "dependencies": { + "dom-serializer": "^2.0.0", + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3" + }, + "funding": { + "url": "https://github.com/fb55/domutils?sponsor=1" + } + }, + "node_modules/dset": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/dset/-/dset-3.1.4.tgz", + "integrity": "sha512-2QF/g9/zTaPDc3BjNcVTGoBbXBgYfMTTceLaYcFJ/W9kggFUkhxD/hMEeuLKbugyef9SqAx8cpgwlIP/jinUTA==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/electron-to-chromium": { + "version": "1.5.365", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.365.tgz", + "integrity": "sha512-xfip4u1QF1s+URFqpA6N+OeFpDGpN7VJz1f3MO3bVL0QYBjpGiZ5/Of7kugvM+o8TTqmanUlviHN3c8M9vYWCw==", + "dev": true, + "license": "ISC" + }, + "node_modules/embla-carousel": { + "version": "8.6.0", + "resolved": "https://registry.npmjs.org/embla-carousel/-/embla-carousel-8.6.0.tgz", + "integrity": "sha512-SjWyZBHJPbqxHOzckOfo8lHisEaJWmwd23XppYFYVh10bU66/Pn5tkVkbkCMZVdbUE5eTCI2nD8OyIP4Z+uwkA==", + "license": "MIT" + }, + "node_modules/embla-carousel-autoplay": { + "version": "8.6.0", + "resolved": "https://registry.npmjs.org/embla-carousel-autoplay/-/embla-carousel-autoplay-8.6.0.tgz", + "integrity": "sha512-OBu5G3nwaSXkZCo1A6LTaFMZ8EpkYbwIaH+bPqdBnDGQ2fh4+NbzjXjs2SktoPNKCtflfVMc75njaDHOYXcrsA==", + "license": "MIT", + "peerDependencies": { + "embla-carousel": "8.6.0" + } + }, + "node_modules/embla-carousel-react": { + "version": "8.6.0", + "resolved": "https://registry.npmjs.org/embla-carousel-react/-/embla-carousel-react-8.6.0.tgz", + "integrity": "sha512-0/PjqU7geVmo6F734pmPqpyHqiM99olvyecY7zdweCw+6tKEXnrE90pBiBbMMU8s5tICemzpQ3hi5EpxzGW+JA==", + "license": "MIT", + "dependencies": { + "embla-carousel": "8.6.0", + "embla-carousel-reactive-utils": "8.6.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.1 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" + } + }, + "node_modules/embla-carousel-reactive-utils": { + "version": "8.6.0", + "resolved": "https://registry.npmjs.org/embla-carousel-reactive-utils/-/embla-carousel-reactive-utils-8.6.0.tgz", + "integrity": "sha512-fMVUDUEx0/uIEDM0Mz3dHznDhfX+znCCDCeIophYb1QGVM7YThSWX+wz11zlYwWFOr74b4QLGg0hrGPJeG2s4A==", + "license": "MIT", + "peerDependencies": { + "embla-carousel": "8.6.0" + } + }, + "node_modules/emmet": { + "version": "2.4.11", + "resolved": "https://registry.npmjs.org/emmet/-/emmet-2.4.11.tgz", + "integrity": "sha512-23QPJB3moh/U9sT4rQzGgeyyGIrcM+GH5uVYg2C6wZIxAIJq7Ng3QLT79tl8FUwDXhyq9SusfknOrofAKqvgyQ==", + "dev": true, + "license": "MIT", + "workspaces": [ + "./packages/scanner", + "./packages/abbreviation", + "./packages/css-abbreviation", + "./" + ], + "dependencies": { + "@emmetio/abbreviation": "^2.3.3", + "@emmetio/css-abbreviation": "^2.1.8" + } + }, + "node_modules/emoji-regex": { + "version": "10.6.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.6.0.tgz", + "integrity": "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==", + "license": "MIT" + }, + "node_modules/encoding": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz", + "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "iconv-lite": "^0.6.2" + } + }, + "node_modules/entities": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-6.0.1.tgz", + "integrity": "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/env-paths": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", + "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/err-code": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/err-code/-/err-code-2.0.3.tgz", + "integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==", + "dev": true, + "license": "MIT" + }, + "node_modules/error-stack-parser-es": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/error-stack-parser-es/-/error-stack-parser-es-1.0.5.tgz", + "integrity": "sha512-5qucVt2XcuGMcEGgWI7i+yZpmpByQ8J1lHhcL7PwqCwu9FPP3VUXzT4ltHe5i2z9dePwEHcDVOAfSnHsOlCXRA==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/es-abstract": { + "version": "1.24.2", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.24.2.tgz", + "integrity": "sha512-2FpH9Q5i2RRwyEP1AylXe6nYLR5OhaJTZwmlcP0dL/+JCbgg7yyEo/sEK6HeGZRf3dFpWwThaRHVApXSkW3xeg==", + "license": "MIT", + "dependencies": { + "array-buffer-byte-length": "^1.0.2", + "arraybuffer.prototype.slice": "^1.0.4", + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "data-view-buffer": "^1.0.2", + "data-view-byte-length": "^1.0.2", + "data-view-byte-offset": "^1.0.1", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "es-set-tostringtag": "^2.1.0", + "es-to-primitive": "^1.3.0", + "function.prototype.name": "^1.1.8", + "get-intrinsic": "^1.3.0", + "get-proto": "^1.0.1", + "get-symbol-description": "^1.1.0", + "globalthis": "^1.0.4", + "gopd": "^1.2.0", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "internal-slot": "^1.1.0", + "is-array-buffer": "^3.0.5", + "is-callable": "^1.2.7", + "is-data-view": "^1.0.2", + "is-negative-zero": "^2.0.3", + "is-regex": "^1.2.1", + "is-set": "^2.0.3", + "is-shared-array-buffer": "^1.0.4", + "is-string": "^1.1.1", + "is-typed-array": "^1.1.15", + "is-weakref": "^1.1.1", + "math-intrinsics": "^1.1.0", + "object-inspect": "^1.13.4", + "object-keys": "^1.1.1", + "object.assign": "^4.1.7", + "own-keys": "^1.0.1", + "regexp.prototype.flags": "^1.5.4", + "safe-array-concat": "^1.1.3", + "safe-push-apply": "^1.0.0", + "safe-regex-test": "^1.1.0", + "set-proto": "^1.0.0", + "stop-iteration-iterator": "^1.1.0", + "string.prototype.trim": "^1.2.10", + "string.prototype.trimend": "^1.0.9", + "string.prototype.trimstart": "^1.0.8", + "typed-array-buffer": "^1.0.3", + "typed-array-byte-length": "^1.0.3", + "typed-array-byte-offset": "^1.0.4", + "typed-array-length": "^1.0.7", + "unbox-primitive": "^1.1.0", + "which-typed-array": "^1.1.19" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-module-lexer": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.7.0.tgz", + "integrity": "sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==", + "license": "MIT" + }, + "node_modules/es-object-atoms": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.2.tgz", + "integrity": "sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-shim-unscopables": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.1.0.tgz", + "integrity": "sha512-d9T8ucsEhh8Bi1woXCf+TIKDIROLG5WCkxg8geBCbvk22kzwC5G2OnXVMO6FUsvQlgUUXQ2itephWDLqDzbeCw==", + "license": "MIT", + "dependencies": { + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-to-primitive": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.3.0.tgz", + "integrity": "sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==", + "license": "MIT", + "dependencies": { + "is-callable": "^1.2.7", + "is-date-object": "^1.0.5", + "is-symbol": "^1.0.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/esbuild": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.7.tgz", + "integrity": "sha512-IxpibTjyVnmrIQo5aqNpCgoACA/dTKLTlhMHihVHhdkxKyPO1uBBthumT0rdHmcsk9uMonIWS0m4FljWzILh3w==", + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.27.7", + "@esbuild/android-arm": "0.27.7", + "@esbuild/android-arm64": "0.27.7", + "@esbuild/android-x64": "0.27.7", + "@esbuild/darwin-arm64": "0.27.7", + "@esbuild/darwin-x64": "0.27.7", + "@esbuild/freebsd-arm64": "0.27.7", + "@esbuild/freebsd-x64": "0.27.7", + "@esbuild/linux-arm": "0.27.7", + "@esbuild/linux-arm64": "0.27.7", + "@esbuild/linux-ia32": "0.27.7", + "@esbuild/linux-loong64": "0.27.7", + "@esbuild/linux-mips64el": "0.27.7", + "@esbuild/linux-ppc64": "0.27.7", + "@esbuild/linux-riscv64": "0.27.7", + "@esbuild/linux-s390x": "0.27.7", + "@esbuild/linux-x64": "0.27.7", + "@esbuild/netbsd-arm64": "0.27.7", + "@esbuild/netbsd-x64": "0.27.7", + "@esbuild/openbsd-arm64": "0.27.7", + "@esbuild/openbsd-x64": "0.27.7", + "@esbuild/openharmony-arm64": "0.27.7", + "@esbuild/sunos-x64": "0.27.7", + "@esbuild/win32-arm64": "0.27.7", + "@esbuild/win32-ia32": "0.27.7", + "@esbuild/win32-x64": "0.27.7" + } + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-string-regexp": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz", + "integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/estree-walker": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", + "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0" + } + }, + "node_modules/eventemitter3": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.4.tgz", + "integrity": "sha512-mlsTRyGaPBjPedk6Bvw+aqbsXDtoAyAzm5MO7JgU+yVRyMQ5O8bD4Kcci7BS85f93veegeCPkL8R4GLClnjLFw==", + "license": "MIT" + }, + "node_modules/events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "license": "MIT", + "engines": { + "node": ">=0.8.x" + } + }, + "node_modules/exenv": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/exenv/-/exenv-1.2.2.tgz", + "integrity": "sha512-Z+ktTxTwv9ILfgKCk32OX3n/doe+OcLTRtqK9pcL+JsP3J1/VW8Uvl4ZjLlKqeW4rzK4oesDOGMEMRIZqtP4Iw==", + "license": "BSD-3-Clause" + }, + "node_modules/extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "license": "MIT" + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.2.tgz", + "integrity": "sha512-rVjf7ArG3LTk+FS6Yw81V1DLuZl1bRbNrev6Tmd/9RaroeeRRJhAt7jg/6YFxbvAQXUCavSoZhPPj6oOx+5KjQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "BSD-3-Clause" + }, + "node_modules/fbjs": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fbjs/-/fbjs-2.0.0.tgz", + "integrity": "sha512-8XA8ny9ifxrAWlyhAbexXcs3rRMtxWcs3M0lctLfB49jRDHiaxj+Mo0XxbwE7nKZYzgCFoq64FS+WFd4IycPPQ==", + "license": "MIT", + "dependencies": { + "core-js": "^3.6.4", + "cross-fetch": "^3.0.4", + "fbjs-css-vars": "^1.0.0", + "loose-envify": "^1.0.0", + "object-assign": "^4.1.0", + "promise": "^7.1.1", + "setimmediate": "^1.0.5", + "ua-parser-js": "^0.7.18" + } + }, + "node_modules/fbjs-css-vars": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/fbjs-css-vars/-/fbjs-css-vars-1.0.2.tgz", + "integrity": "sha512-b2XGFAFdWZWg0phtAWLHCk836A1Xann+I+Dgd3Gk64MHKZO44FfoD1KxyvbSh0qZsIoXQGGlVztIY+oitJPpRQ==", + "license": "MIT" + }, + "node_modules/fbjs/node_modules/ua-parser-js": { + "version": "0.7.41", + "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.41.tgz", + "integrity": "sha512-O3oYyCMPYgNNHuO7Jjk3uacJWZF8loBgwrfd/5LE/HyZ3lUIOdniQ7DNXJcIgZbwioZxk0fLfI4EVnetdiX5jg==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/ua-parser-js" + }, + { + "type": "paypal", + "url": "https://paypal.me/faisalman" + }, + { + "type": "github", + "url": "https://github.com/sponsors/faisalman" + } + ], + "license": "MIT", + "bin": { + "ua-parser-js": "script/cli.js" + }, + "engines": { + "node": "*" + } + }, + "node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/flattie": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/flattie/-/flattie-1.1.1.tgz", + "integrity": "sha512-9UbaD6XdAL97+k/n+N7JwX46K/M6Zc6KcFYskrYL8wbBV/Uyk0CTAMY0VT+qiK5PM7AIc9aTWYtq65U7T+aCNQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/fontace": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/fontace/-/fontace-0.4.1.tgz", + "integrity": "sha512-lDMvbAzSnHmbYMTEld5qdtvNH2/pWpICOqpean9IgC7vUbUJc3k+k5Dokp85CegamqQpFbXf0rAVkbzpyTA8aw==", + "license": "MIT", + "dependencies": { + "fontkitten": "^1.0.2" + } + }, + "node_modules/fontkitten": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/fontkitten/-/fontkitten-1.0.3.tgz", + "integrity": "sha512-Wp1zXWPVUPBmfoa3Cqc9ctaKuzKAV6uLstRqlR56kSjplf5uAce+qeyYym7F+PHbGTk+tCEdkCW6RD7DX/gBZw==", + "license": "MIT", + "dependencies": { + "tiny-inflate": "^1.0.3" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/for-each": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz", + "integrity": "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==", + "license": "MIT", + "dependencies": { + "is-callable": "^1.2.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/framer-motion": { + "version": "6.2.4", + "resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-6.2.4.tgz", + "integrity": "sha512-1UfnSG4c4CefKft6QMYGx8AWt3TtaFoR/Ax4dkuDDD5BDDeIuUm7gesmJrF8GzxeX/i6fMm8+MEdPngUyPVdLA==", + "license": "MIT", + "dependencies": { + "framesync": "6.0.1", + "hey-listen": "^1.0.8", + "popmotion": "11.0.3", + "style-value-types": "5.0.0", + "tslib": "^2.1.0" + }, + "optionalDependencies": { + "@emotion/is-prop-valid": "^0.8.2" + }, + "peerDependencies": { + "react": ">=16.8 || ^17.0.0", + "react-dom": ">=16.8 || ^17.0.0" + } + }, + "node_modules/framesync": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/framesync/-/framesync-6.0.1.tgz", + "integrity": "sha512-fUY88kXvGiIItgNC7wcTOl0SNRCVXMKSWW2Yzfmn7EKNc+MpCzcz9DhdHcdjbrtN3c6R4H5dTY2jiCpPdysEjA==", + "license": "MIT", + "dependencies": { + "tslib": "^2.1.0" + } + }, + "node_modules/fs-minipass": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "dev": true, + "license": "ISC", + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true, + "license": "ISC" + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/function.prototype.name": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.8.tgz", + "integrity": "sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q==", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "functions-have-names": "^1.2.3", + "hasown": "^2.0.2", + "is-callable": "^1.2.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/functions-have-names": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", + "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gauge": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-4.0.4.tgz", + "integrity": "sha512-f9m+BEN5jkg6a0fZjleidjN51VE1X+mPFQ2DJ0uv1V39oCLCbsGe6yjbBnp7eK7z/+GAon99a3nHuqbuuthyPg==", + "deprecated": "This package is no longer supported.", + "dev": true, + "license": "ISC", + "dependencies": { + "aproba": "^1.0.3 || ^2.0.0", + "color-support": "^1.1.3", + "console-control-strings": "^1.1.0", + "has-unicode": "^2.0.1", + "signal-exit": "^3.0.7", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1", + "wide-align": "^1.1.5" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/gauge/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT" + }, + "node_modules/gauge/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "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/generator-function": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/generator-function/-/generator-function-2.0.1.tgz", + "integrity": "sha512-SFdFmIJi+ybC0vjlHN0ZGVGHc3lgE0DxPAT0djjVg+kjOnSqclqmj0KQ7ykTOLP6YxoqOvuAODGdcHJn+43q3g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true, + "license": "ISC", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-east-asian-width": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.6.0.tgz", + "integrity": "sha512-QRbvDIbx6YklUe6RxeTeleMR0yv3cYH6PsPZHcnVn7xv7zO1BHN8r0XETu8n6Ye3Q+ahtSarc3WgtNWmehIBfA==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-nonce": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-nonce/-/get-nonce-1.0.1.tgz", + "integrity": "sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/get-symbol-description": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.1.0.tgz", + "integrity": "sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/github-slugger": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/github-slugger/-/github-slugger-2.0.0.tgz", + "integrity": "sha512-IaOQ9puYtjrkq7Y0Ygl9KDZnrf/aiUJYUpVf89y8kyaxbRG7Y1SrX/jaumrv81vc61+kiMempujsM3Yw7w5qcw==", + "license": "ISC" + }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", + "dev": true, + "license": "ISC", + "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" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/globals": { + "version": "16.5.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-16.5.0.tgz", + "integrity": "sha512-c/c15i26VrJ4IRt5Z89DnIzCGDn9EcebibhAOjw5ibqEHsE1wLUgkPn9RDmNcUKyU87GeaL633nyJ+pplFR2ZQ==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/globalthis": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz", + "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==", + "license": "MIT", + "dependencies": { + "define-properties": "^1.2.1", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/gradient-parser": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gradient-parser/-/gradient-parser-1.2.0.tgz", + "integrity": "sha512-6ABGa9CR7WR/0pAJicBy5SJkiikbFM6kf/JjykwX7x+t+s8ORWVnlbi6FkHeFFb36yWsjUpHqSYrygd7ofEUqA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/graphql": { + "version": "16.14.1", + "resolved": "https://registry.npmjs.org/graphql/-/graphql-16.14.1.tgz", + "integrity": "sha512-cQOsSMS/IrDz82PVyRDvf/Q1F/bRbBVjJlh+xYOkI1qw2bWRvWGiWc+m2O0d6l4Bt1fyY+8kzJ8JFWGJqNeDBg==", + "license": "MIT", + "optional": true, + "engines": { + "node": "^12.22.0 || ^14.16.0 || ^16.0.0 || >=17.0.0" + } + }, + "node_modules/gud": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/gud/-/gud-1.0.0.tgz", + "integrity": "sha512-zGEOVKFM5sVPPrYs7J5/hYEw2Pof8KCyOwyhG8sAF26mCAeUFAcYPu1mwB7hhpIP29zOIBaDqwuHdLp0jvZXjw==", + "license": "MIT" + }, + "node_modules/h3": { + "version": "1.15.11", + "resolved": "https://registry.npmjs.org/h3/-/h3-1.15.11.tgz", + "integrity": "sha512-L3THSe2MPeBwgIZVSH5zLdBBU90TOxarvhK9d04IDY2AmVS8j2Jz2LIWtwsGOU3lu2I5jCN7FNvVfY2+XyF+mg==", + "license": "MIT", + "dependencies": { + "cookie-es": "^1.2.3", + "crossws": "^0.3.5", + "defu": "^6.1.6", + "destr": "^2.0.5", + "iron-webcrypto": "^1.2.1", + "node-mock-http": "^1.0.4", + "radix3": "^1.1.2", + "ufo": "^1.6.3", + "uncrypto": "^0.1.3" + } + }, + "node_modules/has-bigints": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.1.0.tgz", + "integrity": "sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-proto": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.2.0.tgz", + "integrity": "sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ==", + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "license": "MIT", + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/hasown": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.4.tgz", + "integrity": "sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==", + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/hast-util-from-html": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/hast-util-from-html/-/hast-util-from-html-2.0.3.tgz", + "integrity": "sha512-CUSRHXyKjzHov8yKsQjGOElXy/3EKpyX56ELnkHH34vDVw1N1XSQ1ZcAvTyAPtGqLTuKP/uxM+aLkSPqF/EtMw==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "devlop": "^1.1.0", + "hast-util-from-parse5": "^8.0.0", + "parse5": "^7.0.0", + "vfile": "^6.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-from-parse5": { + "version": "8.0.3", + "resolved": "https://registry.npmjs.org/hast-util-from-parse5/-/hast-util-from-parse5-8.0.3.tgz", + "integrity": "sha512-3kxEVkEKt0zvcZ3hCRYI8rqrgwtlIOFMWkbclACvjlDw8Li9S2hk/d51OI0nr/gIpdMHNepwgOKqZ/sy0Clpyg==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/unist": "^3.0.0", + "devlop": "^1.0.0", + "hastscript": "^9.0.0", + "property-information": "^7.0.0", + "vfile": "^6.0.0", + "vfile-location": "^5.0.0", + "web-namespaces": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-is-element": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/hast-util-is-element/-/hast-util-is-element-3.0.0.tgz", + "integrity": "sha512-Val9mnv2IWpLbNPqc/pUem+a7Ipj2aHacCwgNfTiK0vJKl0LF+4Ba4+v1oPHFpf3bLYmreq0/l3Gud9S5OH42g==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-parse-selector": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/hast-util-parse-selector/-/hast-util-parse-selector-4.0.0.tgz", + "integrity": "sha512-wkQCkSYoOGCRKERFWcxMVMOcYE2K1AaNLU8DXS9arxnLOUEWbOXKXiJUNzEpqZ3JOKpnha3jkFrumEjVliDe7A==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-raw": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/hast-util-raw/-/hast-util-raw-9.1.0.tgz", + "integrity": "sha512-Y8/SBAHkZGoNkpzqqfCldijcuUKh7/su31kEBp67cFY09Wy0mTRgtsLYsiIxMJxlu0f6AA5SUTbDR8K0rxnbUw==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/unist": "^3.0.0", + "@ungap/structured-clone": "^1.0.0", + "hast-util-from-parse5": "^8.0.0", + "hast-util-to-parse5": "^8.0.0", + "html-void-elements": "^3.0.0", + "mdast-util-to-hast": "^13.0.0", + "parse5": "^7.0.0", + "unist-util-position": "^5.0.0", + "unist-util-visit": "^5.0.0", + "vfile": "^6.0.0", + "web-namespaces": "^2.0.0", + "zwitch": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-to-html": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/hast-util-to-html/-/hast-util-to-html-9.0.5.tgz", + "integrity": "sha512-OguPdidb+fbHQSU4Q4ZiLKnzWo8Wwsf5bZfbvu7//a9oTYoqD/fWpe96NuHkoS9h0ccGOTe0C4NGXdtS0iObOw==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/unist": "^3.0.0", + "ccount": "^2.0.0", + "comma-separated-tokens": "^2.0.0", + "hast-util-whitespace": "^3.0.0", + "html-void-elements": "^3.0.0", + "mdast-util-to-hast": "^13.0.0", + "property-information": "^7.0.0", + "space-separated-tokens": "^2.0.0", + "stringify-entities": "^4.0.0", + "zwitch": "^2.0.4" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-to-parse5": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/hast-util-to-parse5/-/hast-util-to-parse5-8.0.1.tgz", + "integrity": "sha512-MlWT6Pjt4CG9lFCjiz4BH7l9wmrMkfkJYCxFwKQic8+RTZgWPuWxwAfjJElsXkex7DJjfSJsQIt931ilUgmwdA==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "comma-separated-tokens": "^2.0.0", + "devlop": "^1.0.0", + "property-information": "^7.0.0", + "space-separated-tokens": "^2.0.0", + "web-namespaces": "^2.0.0", + "zwitch": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-to-text": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/hast-util-to-text/-/hast-util-to-text-4.0.2.tgz", + "integrity": "sha512-KK6y/BN8lbaq654j7JgBydev7wuNMcID54lkRav1P0CaE1e47P72AWWPiGKXTJU271ooYzcvTAn/Zt0REnvc7A==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/unist": "^3.0.0", + "hast-util-is-element": "^3.0.0", + "unist-util-find-after": "^5.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-whitespace": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/hast-util-whitespace/-/hast-util-whitespace-3.0.0.tgz", + "integrity": "sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hastscript": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/hastscript/-/hastscript-9.0.1.tgz", + "integrity": "sha512-g7df9rMFX/SPi34tyGCyUBREQoKkapwdY/T04Qn9TDWfHhAYt4/I0gMVirzK5wEzeUqIjEB+LXC/ypb7Aqno5w==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "comma-separated-tokens": "^2.0.0", + "hast-util-parse-selector": "^4.0.0", + "property-information": "^7.0.0", + "space-separated-tokens": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hey-listen": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/hey-listen/-/hey-listen-1.0.8.tgz", + "integrity": "sha512-COpmrF2NOg4TBWUJ5UVyaCU2A88wEMkUPK4hNqyCkqHbxT92BbvfjoSozkAIIm6XhicGlJHhFdullInrdhwU8Q==", + "license": "MIT" + }, + "node_modules/hoist-non-react-methods": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/hoist-non-react-methods/-/hoist-non-react-methods-1.1.0.tgz", + "integrity": "sha512-0y58VIZRsvwl8m4e/NrGSiZSPQUmlaxK5UnnR0aJ8++2xN6MLb2j73TknC0aK7mlQaA97bwK/mgadTtvFP7zLA==", + "license": "MIT", + "dependencies": { + "sinon": "^4.2.0" + } + }, + "node_modules/hoist-non-react-statics": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", + "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==", + "license": "BSD-3-Clause", + "dependencies": { + "react-is": "^16.7.0" + } + }, + "node_modules/hoist-non-react-statics/node_modules/react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", + "license": "MIT" + }, + "node_modules/howler": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/howler/-/howler-2.2.4.tgz", + "integrity": "sha512-iARIBPgcQrwtEr+tALF+rapJ8qSc+Set2GJQl7xT1MQzWaVkFebdJhR3alVlSiUf5U7nAANKuj3aWpwerocD5w==", + "license": "MIT" + }, + "node_modules/html-escaper": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-3.0.3.tgz", + "integrity": "sha512-RuMffC89BOWQoY0WKGpIhn5gX3iI54O6nRA0yC124NYVtzjmFWBIiFd8M0x+ZdX0P9R4lADg1mgP8C7PxGOWuQ==", + "license": "MIT" + }, + "node_modules/html-parse-stringify": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/html-parse-stringify/-/html-parse-stringify-3.0.1.tgz", + "integrity": "sha512-KknJ50kTInJ7qIScF3jeaFRpMpE8/lfiTdzf/twXyPBLAGrLRTmkz3AdTnKeh40X8k9L2fdYwEp/42WGXIRGcg==", + "license": "MIT", + "dependencies": { + "void-elements": "3.1.0" + } + }, + "node_modules/html-void-elements": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/html-void-elements/-/html-void-elements-3.0.0.tgz", + "integrity": "sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/http-cache-semantics": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.2.0.tgz", + "integrity": "sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ==", + "license": "BSD-2-Clause" + }, + "node_modules/http-proxy-agent": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", + "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@tootallnate/once": "1", + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/http-status-codes": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/http-status-codes/-/http-status-codes-2.3.0.tgz", + "integrity": "sha512-RJ8XvFvpPM/Dmc5SV+dC4y5PCeOhT3x1Hq0NU3rjGeg5a/CqlhZ7uudknPwZFz4aeAXDcbAyaeP7GAo9lvngtA==", + "license": "MIT" + }, + "node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "dev": true, + "license": "MIT", + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/humanize-ms": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz", + "integrity": "sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.0.0" + } + }, + "node_modules/i18next": { + "version": "25.10.10", + "resolved": "https://registry.npmjs.org/i18next/-/i18next-25.10.10.tgz", + "integrity": "sha512-cqUW2Z3EkRx7NqSyywjkgCLK7KLCL6IFVFcONG7nVYIJ3ekZ1/N5jUsihHV6Bq37NfhgtczxJcxduELtjTwkuQ==", + "funding": [ + { + "type": "individual", + "url": "https://www.locize.com/i18next" + }, + { + "type": "individual", + "url": "https://www.i18next.com/how-to/faq#i18next-is-awesome.-how-can-i-support-the-project" + }, + { + "type": "individual", + "url": "https://www.locize.com" + } + ], + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.29.2" + }, + "peerDependencies": { + "typescript": "^5 || ^6" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/i18next-icu": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/i18next-icu/-/i18next-icu-2.4.3.tgz", + "integrity": "sha512-Clb5XCp416Z+BkJUTATCjmDcw2AFzSUDVLxLVK/KhtXP6TJQHrht+6MqoJU1hCpyoCBKe59wMO9pvCvYroNcKg==", + "license": "MIT", + "peerDependencies": { + "intl-messageformat": ">=10.3.3 <12.0.0" + } + }, + "node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/immutable": { + "version": "3.8.3", + "resolved": "https://registry.npmjs.org/immutable/-/immutable-3.8.3.tgz", + "integrity": "sha512-AUY/VyX0E5XlibOmWt10uabJzam1zlYjwiEgQSDc5+UIkFNaF9WM0JxXKaNMGf+F/ffUF+7kRKXM9A7C0xXqMg==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/import-meta-resolve": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/import-meta-resolve/-/import-meta-resolve-4.2.0.tgz", + "integrity": "sha512-Iqv2fzaTQN28s/FwZAoFq0ZSs/7hMAHJVX+w8PZl3cY19Pxk6jFFalxQoIfW2826i/fDLXv8IiEZRIT0lDuWcg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/infer-owner": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz", + "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==", + "dev": true, + "license": "ISC" + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", + "dev": true, + "license": "ISC", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/internal-slot": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.1.0.tgz", + "integrity": "sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "hasown": "^2.0.2", + "side-channel": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/internmap": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/internmap/-/internmap-1.0.1.tgz", + "integrity": "sha512-lDB5YccMydFBtasVtxnZ3MRBHuaoE8GKsppq+EchKL2U4nK/DmEpPHNH8MZe5HkMtpSiTSOZwfN0tzYjO/lJEw==", + "license": "ISC" + }, + "node_modules/intl-messageformat": { + "version": "10.7.18", + "resolved": "https://registry.npmjs.org/intl-messageformat/-/intl-messageformat-10.7.18.tgz", + "integrity": "sha512-m3Ofv/X/tV8Y3tHXLohcuVuhWKo7BBq62cqY15etqmLxg2DZ34AGGgQDeR+SCta2+zICb1NX83af0GJmbQ1++g==", + "license": "BSD-3-Clause", + "dependencies": { + "@formatjs/ecma402-abstract": "2.3.6", + "@formatjs/fast-memoize": "2.2.7", + "@formatjs/icu-messageformat-parser": "2.11.4", + "tslib": "^2.8.0" + } + }, + "node_modules/invariant": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", + "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.0.0" + } + }, + "node_modules/ip-address": { + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.2.0.tgz", + "integrity": "sha512-/+S6j4E9AHvW9SWMSEY9Xfy66O5PWvVEJ08O0y5JGyEKQpojb0K0GKpz/v5HJ/G0vi3D2sjGK78119oXZeE0qA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 12" + } + }, + "node_modules/iron-webcrypto": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/iron-webcrypto/-/iron-webcrypto-1.2.1.tgz", + "integrity": "sha512-feOM6FaSr6rEABp/eDfVseKyTMDt+KGpeB35SkVn9Tyn0CqvVsY3EwI0v5i8nMHyJnzCIQf7nsy3p41TPkJZhg==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/brc-dd" + } + }, + "node_modules/is-arguments": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.2.0.tgz", + "integrity": "sha512-7bVbi0huj/wrIAOzb8U1aszg9kdi3KN/CyU19CTI7tAoZYEZoL9yCDXpbXN+uPsuWnP02cyug1gleqq+TU+YCA==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-array-buffer": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.5.tgz", + "integrity": "sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "get-intrinsic": "^1.2.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-arrayish": { + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.4.tgz", + "integrity": "sha512-m6UrgzFVUYawGBh1dUsWR5M2Clqic9RVXC/9f8ceNlv2IcO9j9J/z8UoCLPqtsPBFNzEpfR3xftohbfqDx8EQA==", + "license": "MIT" + }, + "node_modules/is-async-function": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.1.1.tgz", + "integrity": "sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ==", + "license": "MIT", + "dependencies": { + "async-function": "^1.0.0", + "call-bound": "^1.0.3", + "get-proto": "^1.0.1", + "has-tostringtag": "^1.0.2", + "safe-regex-test": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-bigint": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.1.0.tgz", + "integrity": "sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==", + "license": "MIT", + "dependencies": { + "has-bigints": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-boolean-object": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.2.2.tgz", + "integrity": "sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-callable": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-data-view": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.2.tgz", + "integrity": "sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "get-intrinsic": "^1.2.6", + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-date-object": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.1.0.tgz", + "integrity": "sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-docker": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-3.0.0.tgz", + "integrity": "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==", + "license": "MIT", + "bin": { + "is-docker": "cli.js" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-finalizationregistry": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.1.1.tgz", + "integrity": "sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-generator-function": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.1.2.tgz", + "integrity": "sha512-upqt1SkGkODW9tsGNG5mtXTXtECizwtS2kA161M+gJPc1xdb/Ax629af6YrTwcOeQHbewrPNlE5Dx7kzvXTizA==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.4", + "generator-function": "^2.0.0", + "get-proto": "^1.0.1", + "has-tostringtag": "^1.0.2", + "safe-regex-test": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-inside-container": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-inside-container/-/is-inside-container-1.0.0.tgz", + "integrity": "sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==", + "license": "MIT", + "dependencies": { + "is-docker": "^3.0.0" + }, + "bin": { + "is-inside-container": "cli.js" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-lambda": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-lambda/-/is-lambda-1.0.1.tgz", + "integrity": "sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/is-map": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz", + "integrity": "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-negative-zero": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", + "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-number-object": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.1.1.tgz", + "integrity": "sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-plain-obj": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-4.1.0.tgz", + "integrity": "sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-regex": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz", + "integrity": "sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "gopd": "^1.2.0", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-set": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.3.tgz", + "integrity": "sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-shared-array-buffer": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.4.tgz", + "integrity": "sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-standalone-pwa": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-standalone-pwa/-/is-standalone-pwa-0.1.1.tgz", + "integrity": "sha512-9Cbovsa52vNQCjdXOzeQq5CnCbAcRk05aU62K20WO372NrTv0NxibLFCK6lQ4/iZEFdEA3p3t2VNOn8AJ53F5g==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/faisalman" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/ua-parser-js" + }, + { + "type": "paypal", + "url": "https://paypal.me/faisalman" + } + ], + "license": "MIT" + }, + "node_modules/is-string": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.1.1.tgz", + "integrity": "sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-symbol": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.1.1.tgz", + "integrity": "sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "has-symbols": "^1.1.0", + "safe-regex-test": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-typed-array": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.15.tgz", + "integrity": "sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==", + "license": "MIT", + "dependencies": { + "which-typed-array": "^1.1.16" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakmap": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz", + "integrity": "sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakref": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.1.1.tgz", + "integrity": "sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakset": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.4.tgz", + "integrity": "sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "get-intrinsic": "^1.2.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-wsl": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-3.1.1.tgz", + "integrity": "sha512-e6rvdUCiQCAuumZslxRJWR/Doq4VpPR82kqclvcS0efgt430SlGIk05vdCN58+VrzgtIcfNODjozVielycD4Sw==", + "license": "MIT", + "dependencies": { + "is-inside-container": "^1.0.0" + }, + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "license": "MIT" + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true, + "license": "ISC" + }, + "node_modules/jose": { + "version": "5.10.0", + "resolved": "https://registry.npmjs.org/jose/-/jose-5.10.0.tgz", + "integrity": "sha512-s+3Al/p9g32Iq+oqXxkW//7jk2Vig6FF1CFqzVXoTUXt2qz89YWbL+OwS17NFYEvxC35n0FKeGO2LGYSxeM2Gg==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/panva" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "license": "MIT" + }, + "node_modules/js-yaml": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.2.0.tgz", + "integrity": "sha512-ePWsvanv0DWuDRsW8dnt+R4jQ31SCRCQ7hhNcPXZPsoBZiemuZNYGf7adZdqX2D86j6rvKp3RpCxVTSb8WQlOw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/puzrin" + }, + { + "type": "github", + "url": "https://github.com/sponsors/nodeca" + } + ], + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsesc": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", + "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", + "dev": true, + "license": "MIT", + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true, + "license": "MIT" + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true, + "license": "MIT", + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/jsonc-parser": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-2.3.1.tgz", + "integrity": "sha512-H8jvkz1O50L3dMZCsLqiuB2tA7muqbSg1AtGEkN0leAqGjsUzDJir3Zwr02BhqdcITPg3ei3mZ+HjMocAknhhg==", + "dev": true, + "license": "MIT" + }, + "node_modules/just-extend": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-4.2.1.tgz", + "integrity": "sha512-g3UB796vUFIY90VIv/WX3L2c8CS2MdWUww3CNrYmqza1Fg0DURc2K/O4YrnklBdQarSJ/y8JnJYDGc+1iumQjg==", + "license": "MIT" + }, + "node_modules/kleur": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.5.tgz", + "integrity": "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/lodash": { + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.18.1.tgz", + "integrity": "sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q==", + "license": "MIT" + }, + "node_modules/lodash.get": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", + "integrity": "sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==", + "deprecated": "This package is deprecated. Use the optional chaining (?.) operator instead.", + "license": "MIT" + }, + "node_modules/lolex": { + "version": "2.7.5", + "resolved": "https://registry.npmjs.org/lolex/-/lolex-2.7.5.tgz", + "integrity": "sha512-l9x0+1offnKKIzYVjyXU2SiwhXDLekRzKyhnbyldPHvC7BvLPVpdNUNR2KeMAiCN2D/kLNttZgQD5WjSxuBx3Q==", + "license": "BSD-3-Clause" + }, + "node_modules/longest-streak": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/longest-streak/-/longest-streak-3.1.0.tgz", + "integrity": "sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "license": "MIT", + "dependencies": { + "js-tokens": "^3.0.0 || ^4.0.0" + }, + "bin": { + "loose-envify": "cli.js" + } + }, + "node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/lz-string": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/lz-string/-/lz-string-1.5.0.tgz", + "integrity": "sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==", + "license": "MIT", + "bin": { + "lz-string": "bin/bin.js" + } + }, + "node_modules/magic-string": { + "version": "0.30.21", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", + "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.5" + } + }, + "node_modules/magicast": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/magicast/-/magicast-0.5.3.tgz", + "integrity": "sha512-pVKE4UdSQ7DvHzivsCIFx2BJn1mHG6KsyrFcaxFx6tONdneEuThrDx0Cj3AMg58KyN4pzYT+LHOotxDQDjNvkw==", + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.29.3", + "@babel/types": "^7.29.0", + "source-map-js": "^1.2.1" + } + }, + "node_modules/make-fetch-happen": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-9.1.0.tgz", + "integrity": "sha512-+zopwDy7DNknmwPQplem5lAZX/eCOzSvSNNcSKm5eVwTkOBzoktEfXsa9L23J/GIRhxRsaxzkPEhrJEpE2F4Gg==", + "dev": true, + "license": "ISC", + "dependencies": { + "agentkeepalive": "^4.1.3", + "cacache": "^15.2.0", + "http-cache-semantics": "^4.1.0", + "http-proxy-agent": "^4.0.1", + "https-proxy-agent": "^5.0.0", + "is-lambda": "^1.0.1", + "lru-cache": "^6.0.0", + "minipass": "^3.1.3", + "minipass-collect": "^1.0.2", + "minipass-fetch": "^1.3.2", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "negotiator": "^0.6.2", + "promise-retry": "^2.0.1", + "socks-proxy-agent": "^6.0.0", + "ssri": "^8.0.0" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/make-fetch-happen/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/make-fetch-happen/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true, + "license": "ISC" + }, + "node_modules/markdown-table": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-3.0.4.tgz", + "integrity": "sha512-wiYz4+JrLyb/DqW2hkFJxP7Vd7JuTDm77fvbM8VfEQdmSMqcImWeeRbHwZjBjIFki/VaMK2BhFi7oUUZeM5bqw==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/mdast-util-definitions": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-definitions/-/mdast-util-definitions-6.0.0.tgz", + "integrity": "sha512-scTllyX6pnYNZH/AIp/0ePz6s4cZtARxImwoPJ7kS42n+MnVsI4XbnG6d4ibehRIldYMWM2LD7ImQblVhUejVQ==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "@types/unist": "^3.0.0", + "unist-util-visit": "^5.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-find-and-replace": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/mdast-util-find-and-replace/-/mdast-util-find-and-replace-3.0.2.tgz", + "integrity": "sha512-Tmd1Vg/m3Xz43afeNxDIhWRtFZgM2VLyaf4vSTYwudTyeuTneoL3qtWMA5jeLyz/O1vDJmmV4QuScFCA2tBPwg==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "escape-string-regexp": "^5.0.0", + "unist-util-is": "^6.0.0", + "unist-util-visit-parents": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-from-markdown": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-2.0.3.tgz", + "integrity": "sha512-W4mAWTvSlKvf8L6J+VN9yLSqQ9AOAAvHuoDAmPkz4dHf553m5gVj2ejadHJhoJmcmxEnOv6Pa8XJhpxE93kb8Q==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "@types/unist": "^3.0.0", + "decode-named-character-reference": "^1.0.0", + "devlop": "^1.0.0", + "mdast-util-to-string": "^4.0.0", + "micromark": "^4.0.0", + "micromark-util-decode-numeric-character-reference": "^2.0.0", + "micromark-util-decode-string": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0", + "unist-util-stringify-position": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mdast-util-gfm/-/mdast-util-gfm-3.1.0.tgz", + "integrity": "sha512-0ulfdQOM3ysHhCJ1p06l0b0VKlhU0wuQs3thxZQagjcjPrlFRqY215uZGHHJan9GEAXd9MbfPjFJz+qMkVR6zQ==", + "license": "MIT", + "dependencies": { + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-gfm-autolink-literal": "^2.0.0", + "mdast-util-gfm-footnote": "^2.0.0", + "mdast-util-gfm-strikethrough": "^2.0.0", + "mdast-util-gfm-table": "^2.0.0", + "mdast-util-gfm-task-list-item": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm-autolink-literal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/mdast-util-gfm-autolink-literal/-/mdast-util-gfm-autolink-literal-2.0.1.tgz", + "integrity": "sha512-5HVP2MKaP6L+G6YaxPNjuL0BPrq9orG3TsrZ9YXbA3vDw/ACI4MEsnoDpn6ZNm7GnZgtAcONJyPhOP8tNJQavQ==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "ccount": "^2.0.0", + "devlop": "^1.0.0", + "mdast-util-find-and-replace": "^3.0.0", + "micromark-util-character": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm-footnote": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mdast-util-gfm-footnote/-/mdast-util-gfm-footnote-2.1.0.tgz", + "integrity": "sha512-sqpDWlsHn7Ac9GNZQMeUzPQSMzR6Wv0WKRNvQRg0KqHh02fpTz69Qc1QSseNX29bhz1ROIyNyxExfawVKTm1GQ==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "devlop": "^1.1.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm-strikethrough": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-gfm-strikethrough/-/mdast-util-gfm-strikethrough-2.0.0.tgz", + "integrity": "sha512-mKKb915TF+OC5ptj5bJ7WFRPdYtuHv0yTRxK2tJvi+BDqbkiG7h7u/9SI89nRAYcmap2xHQL9D+QG/6wSrTtXg==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm-table": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-gfm-table/-/mdast-util-gfm-table-2.0.0.tgz", + "integrity": "sha512-78UEvebzz/rJIxLvE7ZtDd/vIQ0RHv+3Mh5DR96p7cS7HsBhYIICDBCu8csTNWNO6tBWfqXPWekRuj2FNOGOZg==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "devlop": "^1.0.0", + "markdown-table": "^3.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm-task-list-item": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-gfm-task-list-item/-/mdast-util-gfm-task-list-item-2.0.0.tgz", + "integrity": "sha512-IrtvNvjxC1o06taBAVJznEnkiHxLFTzgonUdy8hzFVeDun0uTjxxrRGVaNFqkU1wJR3RBPEfsxmU6jDWPofrTQ==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "devlop": "^1.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-phrasing": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/mdast-util-phrasing/-/mdast-util-phrasing-4.1.0.tgz", + "integrity": "sha512-TqICwyvJJpBwvGAMZjj4J2n0X8QWp21b9l0o7eXyVJ25YNWYbJDVIyD1bZXE6WtV6RmKJVYmQAKWa0zWOABz2w==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "unist-util-is": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-to-hast": { + "version": "13.2.1", + "resolved": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-13.2.1.tgz", + "integrity": "sha512-cctsq2wp5vTsLIcaymblUriiTcZd0CwWtCbLvrOzYCDZoWyMNV8sZ7krj09FSnsiJi3WVsHLM4k6Dq/yaPyCXA==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "@ungap/structured-clone": "^1.0.0", + "devlop": "^1.0.0", + "micromark-util-sanitize-uri": "^2.0.0", + "trim-lines": "^3.0.0", + "unist-util-position": "^5.0.0", + "unist-util-visit": "^5.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-to-markdown": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/mdast-util-to-markdown/-/mdast-util-to-markdown-2.1.2.tgz", + "integrity": "sha512-xj68wMTvGXVOKonmog6LwyJKrYXZPvlwabaryTjLh9LuvovB/KAH+kvi8Gjj+7rJjsFi23nkUxRQv1KqSroMqA==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "@types/unist": "^3.0.0", + "longest-streak": "^3.0.0", + "mdast-util-phrasing": "^4.0.0", + "mdast-util-to-string": "^4.0.0", + "micromark-util-classify-character": "^2.0.0", + "micromark-util-decode-string": "^2.0.0", + "unist-util-visit": "^5.0.0", + "zwitch": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-to-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-4.0.0.tgz", + "integrity": "sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdn-data": { + "version": "2.27.1", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.27.1.tgz", + "integrity": "sha512-9Yubnt3e8A0OKwxYSXyhLymGW4sCufcLG6VdiDdUGVkPhpqLxlvP5vl1983gQjJl3tqbrM731mjaZaP68AgosQ==", + "license": "CC0-1.0" + }, + "node_modules/memoize-one": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-5.2.1.tgz", + "integrity": "sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q==", + "license": "MIT" + }, + "node_modules/micromark": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/micromark/-/micromark-4.0.2.tgz", + "integrity": "sha512-zpe98Q6kvavpCr1NPVSCMebCKfD7CA2NqZ+rykeNhONIJBpc1tFKt9hucLGwha3jNTNI8lHpctWJWoimVF4PfA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "@types/debug": "^4.0.0", + "debug": "^4.0.0", + "decode-named-character-reference": "^1.0.0", + "devlop": "^1.0.0", + "micromark-core-commonmark": "^2.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-chunked": "^2.0.0", + "micromark-util-combine-extensions": "^2.0.0", + "micromark-util-decode-numeric-character-reference": "^2.0.0", + "micromark-util-encode": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0", + "micromark-util-resolve-all": "^2.0.0", + "micromark-util-sanitize-uri": "^2.0.0", + "micromark-util-subtokenize": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-core-commonmark": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/micromark-core-commonmark/-/micromark-core-commonmark-2.0.3.tgz", + "integrity": "sha512-RDBrHEMSxVFLg6xvnXmb1Ayr2WzLAWjeSATAoxwKYJV94TeNavgoIdA0a9ytzDSVzBy2YKFK+emCPOEibLeCrg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "decode-named-character-reference": "^1.0.0", + "devlop": "^1.0.0", + "micromark-factory-destination": "^2.0.0", + "micromark-factory-label": "^2.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-factory-title": "^2.0.0", + "micromark-factory-whitespace": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-chunked": "^2.0.0", + "micromark-util-classify-character": "^2.0.0", + "micromark-util-html-tag-name": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0", + "micromark-util-resolve-all": "^2.0.0", + "micromark-util-subtokenize": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-extension-gfm": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm/-/micromark-extension-gfm-3.0.0.tgz", + "integrity": "sha512-vsKArQsicm7t0z2GugkCKtZehqUm31oeGBV/KVSorWSy8ZlNAv7ytjFhvaryUiCUJYqs+NoE6AFhpQvBTM6Q4w==", + "license": "MIT", + "dependencies": { + "micromark-extension-gfm-autolink-literal": "^2.0.0", + "micromark-extension-gfm-footnote": "^2.0.0", + "micromark-extension-gfm-strikethrough": "^2.0.0", + "micromark-extension-gfm-table": "^2.0.0", + "micromark-extension-gfm-tagfilter": "^2.0.0", + "micromark-extension-gfm-task-list-item": "^2.0.0", + "micromark-util-combine-extensions": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-autolink-literal": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-autolink-literal/-/micromark-extension-gfm-autolink-literal-2.1.0.tgz", + "integrity": "sha512-oOg7knzhicgQ3t4QCjCWgTmfNhvQbDDnJeVu9v81r7NltNCVmhPy1fJRX27pISafdjL+SVc4d3l48Gb6pbRypw==", + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-sanitize-uri": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-footnote": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-footnote/-/micromark-extension-gfm-footnote-2.1.0.tgz", + "integrity": "sha512-/yPhxI1ntnDNsiHtzLKYnE3vf9JZ6cAisqVDauhp4CEHxlb4uoOTxOCJ+9s51bIB8U1N1FJ1RXOKTIlD5B/gqw==", + "license": "MIT", + "dependencies": { + "devlop": "^1.0.0", + "micromark-core-commonmark": "^2.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0", + "micromark-util-sanitize-uri": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-strikethrough": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-strikethrough/-/micromark-extension-gfm-strikethrough-2.1.0.tgz", + "integrity": "sha512-ADVjpOOkjz1hhkZLlBiYA9cR2Anf8F4HqZUO6e5eDcPQd0Txw5fxLzzxnEkSkfnD0wziSGiv7sYhk/ktvbf1uw==", + "license": "MIT", + "dependencies": { + "devlop": "^1.0.0", + "micromark-util-chunked": "^2.0.0", + "micromark-util-classify-character": "^2.0.0", + "micromark-util-resolve-all": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-table": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-table/-/micromark-extension-gfm-table-2.1.1.tgz", + "integrity": "sha512-t2OU/dXXioARrC6yWfJ4hqB7rct14e8f7m0cbI5hUmDyyIlwv5vEtooptH8INkbLzOatzKuVbQmAYcbWoyz6Dg==", + "license": "MIT", + "dependencies": { + "devlop": "^1.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-tagfilter": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-tagfilter/-/micromark-extension-gfm-tagfilter-2.0.0.tgz", + "integrity": "sha512-xHlTOmuCSotIA8TW1mDIM6X2O1SiX5P9IuDtqGonFhEK0qgRI4yeC6vMxEV2dgyr2TiD+2PQ10o+cOhdVAcwfg==", + "license": "MIT", + "dependencies": { + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-task-list-item": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-task-list-item/-/micromark-extension-gfm-task-list-item-2.1.0.tgz", + "integrity": "sha512-qIBZhqxqI6fjLDYFTBIa4eivDMnP+OZqsNwmQ3xNLE4Cxwc+zfQEfbs6tzAo2Hjq+bh6q5F+Z8/cksrLFYWQQw==", + "license": "MIT", + "dependencies": { + "devlop": "^1.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-factory-destination": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-destination/-/micromark-factory-destination-2.0.1.tgz", + "integrity": "sha512-Xe6rDdJlkmbFRExpTOmRj9N3MaWmbAgdpSrBQvCFqhezUn4AHqJHbaEnfbVYYiexVSs//tqOdY/DxhjdCiJnIA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-label": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-label/-/micromark-factory-label-2.0.1.tgz", + "integrity": "sha512-VFMekyQExqIW7xIChcXn4ok29YE3rnuyveW3wZQWWqF4Nv9Wk5rgJ99KzPvHjkmPXF93FXIbBp6YdW3t71/7Vg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "devlop": "^1.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-space": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-2.0.1.tgz", + "integrity": "sha512-zRkxjtBxxLd2Sc0d+fbnEunsTj46SWXgXciZmHq0kDYGnck/ZSGj9/wULTV95uoeYiK5hRXP2mJ98Uo4cq/LQg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-title": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-title/-/micromark-factory-title-2.0.1.tgz", + "integrity": "sha512-5bZ+3CjhAd9eChYTHsjy6TGxpOFSKgKKJPJxr293jTbfry2KDoWkhBb6TcPVB4NmzaPhMs1Frm9AZH7OD4Cjzw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-whitespace": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-whitespace/-/micromark-factory-whitespace-2.0.1.tgz", + "integrity": "sha512-Ob0nuZ3PKt/n0hORHyvoD9uZhr+Za8sFoP+OnMcnWK5lngSzALgQYKMr9RJVOWLqQYuyn6ulqGWSXdwf6F80lQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-character": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.1.tgz", + "integrity": "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-chunked": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-chunked/-/micromark-util-chunked-2.0.1.tgz", + "integrity": "sha512-QUNFEOPELfmvv+4xiNg2sRYeS/P84pTW0TCgP5zc9FpXetHY0ab7SxKyAQCNCc1eK0459uoLI1y5oO5Vc1dbhA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-classify-character": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-classify-character/-/micromark-util-classify-character-2.0.1.tgz", + "integrity": "sha512-K0kHzM6afW/MbeWYWLjoHQv1sgg2Q9EccHEDzSkxiP/EaagNzCm7T/WMKZ3rjMbvIpvBiZgwR3dKMygtA4mG1Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-combine-extensions": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-combine-extensions/-/micromark-util-combine-extensions-2.0.1.tgz", + "integrity": "sha512-OnAnH8Ujmy59JcyZw8JSbK9cGpdVY44NKgSM7E9Eh7DiLS2E9RNQf0dONaGDzEG9yjEl5hcqeIsj4hfRkLH/Bg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-chunked": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-decode-numeric-character-reference": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/micromark-util-decode-numeric-character-reference/-/micromark-util-decode-numeric-character-reference-2.0.2.tgz", + "integrity": "sha512-ccUbYk6CwVdkmCQMyr64dXz42EfHGkPQlBj5p7YVGzq8I7CtjXZJrubAYezf7Rp+bjPseiROqe7G6foFd+lEuw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-decode-string": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-decode-string/-/micromark-util-decode-string-2.0.1.tgz", + "integrity": "sha512-nDV/77Fj6eH1ynwscYTOsbK7rR//Uj0bZXBwJZRfaLEJ1iGBR6kIfNmlNqaqJf649EP0F3NWNdeJi03elllNUQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "decode-named-character-reference": "^1.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-decode-numeric-character-reference": "^2.0.0", + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-encode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-encode/-/micromark-util-encode-2.0.1.tgz", + "integrity": "sha512-c3cVx2y4KqUnwopcO9b/SCdo2O67LwJJ/UyqGfbigahfegL9myoEFoDYZgkT7f36T0bLrM9hZTAaAyH+PCAXjw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-util-html-tag-name": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-html-tag-name/-/micromark-util-html-tag-name-2.0.1.tgz", + "integrity": "sha512-2cNEiYDhCWKI+Gs9T0Tiysk136SnR13hhO8yW6BGNyhOC4qYFnwF1nKfD3HFAIXA5c45RrIG1ub11GiXeYd1xA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-util-normalize-identifier": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-normalize-identifier/-/micromark-util-normalize-identifier-2.0.1.tgz", + "integrity": "sha512-sxPqmo70LyARJs0w2UclACPUUEqltCkJ6PhKdMIDuJ3gSf/Q+/GIe3WKl0Ijb/GyH9lOpUkRAO2wp0GVkLvS9Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-resolve-all": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-resolve-all/-/micromark-util-resolve-all-2.0.1.tgz", + "integrity": "sha512-VdQyxFWFT2/FGJgwQnJYbe1jjQoNTS4RjglmSjTUlpUMa95Htx9NHeYW4rGDJzbjvCsl9eLjMQwGeElsqmzcHg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-sanitize-uri": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-2.0.1.tgz", + "integrity": "sha512-9N9IomZ/YuGGZZmQec1MbgxtlgougxTodVwDzzEouPKo3qFWvymFHWcnDi2vzV1ff6kas9ucW+o3yzJK9YB1AQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-encode": "^2.0.0", + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-subtokenize": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-subtokenize/-/micromark-util-subtokenize-2.1.0.tgz", + "integrity": "sha512-XQLu552iSctvnEcgXw6+Sx75GflAPNED1qx7eBJ+wydBb2KCbRZe+NwvIEEMM83uml1+2WSXpBAcp9IUCgCYWA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "devlop": "^1.0.0", + "micromark-util-chunked": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-symbol": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz", + "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-util-types": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/micromark-util-types/-/micromark-util-types-2.0.2.tgz", + "integrity": "sha512-Yw0ECSpJoViF1qTU4DC6NwtC4aWGt1EkzaQB8KPPyCRR8z9TWeV0HbEFGTO+ZY1wB22zmxnJqhPyTpOVCpeHTA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/miniflare": { + "version": "4.20260114.0", + "resolved": "https://registry.npmjs.org/miniflare/-/miniflare-4.20260114.0.tgz", + "integrity": "sha512-QwHT7S6XqGdQxIvql1uirH/7/i3zDEt0B/YBXTYzMfJtVCR4+ue3KPkU+Bl0zMxvpgkvjh9+eCHhJbKEqya70A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@cspotcode/source-map-support": "0.8.1", + "sharp": "^0.34.5", + "undici": "7.14.0", + "workerd": "1.20260114.0", + "ws": "8.18.0", + "youch": "4.1.0-beta.10", + "zod": "^3.25.76" + }, + "bin": { + "miniflare": "bootstrap.js" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/miniflare/node_modules/zod": { + "version": "3.25.76", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz", + "integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + }, + "node_modules/minimatch": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-collect": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-1.0.2.tgz", + "integrity": "sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==", + "dev": true, + "license": "ISC", + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/minipass-fetch": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-1.4.1.tgz", + "integrity": "sha512-CGH1eblLq26Y15+Azk7ey4xh0J/XfJfrCox5LDJiKqI2Q2iwOLOKrlmIaODiSQS8d18jalF6y2K2ePUm0CmShw==", + "dev": true, + "license": "MIT", + "dependencies": { + "minipass": "^3.1.0", + "minipass-sized": "^1.0.3", + "minizlib": "^2.0.0" + }, + "engines": { + "node": ">=8" + }, + "optionalDependencies": { + "encoding": "^0.1.12" + } + }, + "node_modules/minipass-flush": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.7.tgz", + "integrity": "sha512-TbqTz9cUwWyHS2Dy89P3ocAGUGxKjjLuR9z8w4WUTGAVgEj17/4nhgo2Du56i0Fm3Pm30g4iA8Lcqctc76jCzA==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/minipass-pipeline": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz", + "integrity": "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==", + "dev": true, + "license": "ISC", + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-sized": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/minipass-sized/-/minipass-sized-1.0.3.tgz", + "integrity": "sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==", + "dev": true, + "license": "ISC", + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true, + "license": "ISC" + }, + "node_modules/minizlib": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "dev": true, + "license": "MIT", + "dependencies": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/minizlib/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true, + "license": "ISC" + }, + "node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true, + "license": "MIT", + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/moment": { + "version": "2.30.1", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz", + "integrity": "sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==", + "license": "MIT", + "engines": { + "node": "*" + } + }, + "node_modules/mrmime": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/mrmime/-/mrmime-2.0.1.tgz", + "integrity": "sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ==", + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, + "node_modules/muggle-string": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/muggle-string/-/muggle-string-0.4.1.tgz", + "integrity": "sha512-VNTrAak/KhO2i8dqqnqnAHOa3cYBwXEZe9h+D5h/1ZqFSTEFHdM65lR7RoIqq3tBBYavsOXV84NoHXZ0AkPyqQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/nanoid": { + "version": "3.3.12", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.12.tgz", + "integrity": "sha512-ZB9RH/39qpq5Vu6Y+NmUaFhQR6pp+M2Xt76XBnEwDaGcVAqhlvxrl3B2bKS5D3NH3QR76v3aSrKaF/Kiy7lEtQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/negotiator": { + "version": "0.6.4", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.4.tgz", + "integrity": "sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/neotraverse": { + "version": "0.6.18", + "resolved": "https://registry.npmjs.org/neotraverse/-/neotraverse-0.6.18.tgz", + "integrity": "sha512-Z4SmBUweYa09+o6pG+eASabEpP6QkQ70yHj351pQoEXIs8uHbaU2DWVmzBANKgflPa47A50PtB2+NgRpQvr7vA==", + "license": "MIT", + "engines": { + "node": ">= 10" + } + }, + "node_modules/nise": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/nise/-/nise-1.5.3.tgz", + "integrity": "sha512-Ymbac/94xeIrMf59REBPOv0thr+CJVFMhrlAkW/gjCIE58BGQdCj0x7KRCb3yz+Ga2Rz3E9XXSvUyyxqqhjQAQ==", + "license": "BSD-3-Clause", + "dependencies": { + "@sinonjs/formatio": "^3.2.1", + "@sinonjs/text-encoding": "^0.7.1", + "just-extend": "^4.0.2", + "lolex": "^5.0.1", + "path-to-regexp": "^1.7.0" + } + }, + "node_modules/nise/node_modules/@sinonjs/formatio": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/@sinonjs/formatio/-/formatio-3.2.2.tgz", + "integrity": "sha512-B8SEsgd8gArBLMD6zpRw3juQ2FVSsmdd7qlevyDqzS9WTCtvF55/gAL+h6gue8ZvPYcdiPdvueM/qm//9XzyTQ==", + "license": "BSD-3-Clause", + "dependencies": { + "@sinonjs/commons": "^1", + "@sinonjs/samsam": "^3.1.0" + } + }, + "node_modules/nise/node_modules/lolex": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/lolex/-/lolex-5.1.2.tgz", + "integrity": "sha512-h4hmjAvHTmd+25JSwrtTIuwbKdwg5NzZVRMLn9saij4SZaepCrTCxPr35H/3bjwfMJtN+t3CX8672UIkglz28A==", + "license": "BSD-3-Clause", + "dependencies": { + "@sinonjs/commons": "^1.7.0" + } + }, + "node_modules/nlcst-to-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/nlcst-to-string/-/nlcst-to-string-4.0.0.tgz", + "integrity": "sha512-YKLBCcUYKAg0FNlOBT6aI91qFmSiFKiluk655WzPF+DDMA02qIyy8uiRqI8QXtcFpEvll12LpL5MXqEmAZ+dcA==", + "license": "MIT", + "dependencies": { + "@types/nlcst": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/node-fetch": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "license": "MIT", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/node-fetch-native": { + "version": "1.6.7", + "resolved": "https://registry.npmjs.org/node-fetch-native/-/node-fetch-native-1.6.7.tgz", + "integrity": "sha512-g9yhqoedzIUm0nTnTqAQvueMPVOuIY16bqgAJJC8XOOubYFNwz6IER9qs0Gq2Xd0+CecCKFjtdDTMA4u4xG06Q==", + "license": "MIT" + }, + "node_modules/node-gyp": { + "version": "8.4.1", + "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-8.4.1.tgz", + "integrity": "sha512-olTJRgUtAb/hOXG0E93wZDs5YiJlgbXxTwQAFHyNlRsXQnYzUaF2aGgujZbw+hR8aF4ZG/rST57bWMWD16jr9w==", + "dev": true, + "license": "MIT", + "dependencies": { + "env-paths": "^2.2.0", + "glob": "^7.1.4", + "graceful-fs": "^4.2.6", + "make-fetch-happen": "^9.1.0", + "nopt": "^5.0.0", + "npmlog": "^6.0.0", + "rimraf": "^3.0.2", + "semver": "^7.3.5", + "tar": "^6.1.2", + "which": "^2.0.2" + }, + "bin": { + "node-gyp": "bin/node-gyp.js" + }, + "engines": { + "node": ">= 10.12.0" + } + }, + "node_modules/node-gyp/node_modules/semver": { + "version": "7.8.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.1.tgz", + "integrity": "sha512-rkVq3IXh+4FDGch+KwzX3aV9W3kO54GyEgpvBzSyctDA6Xtd7RJQV1xmXbeQp5v7+VzLOfVqiutSE6GICgPFvg==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/node-mock-http": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/node-mock-http/-/node-mock-http-1.0.4.tgz", + "integrity": "sha512-8DY+kFsDkNXy1sJglUfuODx1/opAGJGyrTuFqEoN90oRc2Vk0ZbD4K2qmKXBBEhZQzdKHIVfEJpDU8Ak2NJEvQ==", + "license": "MIT" + }, + "node_modules/node-releases": { + "version": "2.0.47", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.47.tgz", + "integrity": "sha512-Uzmd6LXpouKo8EUK68IjH4+E01w/hXyV3R3g/geCJo+rXLNfh1xucB+LOzYEOQPSiUK3h/xZf0cQGcSsmyL2Og==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/nopt": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", + "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "abbrev": "1" + }, + "bin": { + "nopt": "bin/nopt.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/npmlog": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-6.0.2.tgz", + "integrity": "sha512-/vBvz5Jfr9dT/aFWd0FIRf+T/Q2WBsLENygUaFUqstqsycmZAP/t5BvFJTK0viFmSUxiUKTUplWy5vt+rvKIxg==", + "deprecated": "This package is no longer supported.", + "dev": true, + "license": "ISC", + "dependencies": { + "are-we-there-yet": "^3.0.0", + "console-control-strings": "^1.1.0", + "gauge": "^4.0.3", + "set-blocking": "^2.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/nth-check": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", + "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", + "license": "BSD-2-Clause", + "dependencies": { + "boolbase": "^1.0.0" + }, + "funding": { + "url": "https://github.com/fb55/nth-check?sponsor=1" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-inspect": { + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-is": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.6.tgz", + "integrity": "sha512-F8cZ+KfGlSGi09lJT7/Nd6KJZ9ygtvYC0/UYYLI9nmQKLMnydpB9yvbv9K1uSkEu7FU9vYPmVwLg328tX+ot3Q==", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.assign": { + "version": "4.1.7", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.7.tgz", + "integrity": "sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0", + "has-symbols": "^1.1.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/ofetch": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/ofetch/-/ofetch-1.5.1.tgz", + "integrity": "sha512-2W4oUZlVaqAPAil6FUg/difl6YhqhUR7x2eZY4bQCko22UXg3hptq9KLQdqFClV+Wu85UX7hNtdGTngi/1BxcA==", + "license": "MIT", + "dependencies": { + "destr": "^2.0.5", + "node-fetch-native": "^1.6.7", + "ufo": "^1.6.1" + } + }, + "node_modules/ohash": { + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/ohash/-/ohash-2.0.11.tgz", + "integrity": "sha512-RdR9FQrFwNBNXAr4GixM8YaRZRJ5PUWbKYbE5eOsrwAjJW0q2REGcf79oYPsLyskQCZG1PLN+S/K1V00joZAoQ==", + "license": "MIT" + }, + "node_modules/omit": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/omit/-/omit-1.0.1.tgz", + "integrity": "sha512-WHNzQdTq2gO0iJgbPySheMN79fL3FtriIOGam8Ei4kRpdtTSdq9LX3BxSZlvKKz4vtiSUqASCFD3adel0zP/iA==", + "license": "MIT" + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, + "license": "ISC", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/oniguruma-parser": { + "version": "0.12.2", + "resolved": "https://registry.npmjs.org/oniguruma-parser/-/oniguruma-parser-0.12.2.tgz", + "integrity": "sha512-6HVa5oIrgMC6aA6WF6XyyqbhRPJrKR02L20+2+zpDtO5QAzGHAUGw5TKQvwi5vctNnRHkJYmjAhRVQF2EKdTQw==", + "license": "MIT" + }, + "node_modules/oniguruma-to-es": { + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/oniguruma-to-es/-/oniguruma-to-es-4.3.6.tgz", + "integrity": "sha512-csuQ9x3Yr0cEIs/Zgx/OEt9iBw9vqIunAPQkx19R/fiMq2oGVTgcMqO/V3Ybqefr1TBvosI6jU539ksaBULJyA==", + "license": "MIT", + "dependencies": { + "oniguruma-parser": "^0.12.2", + "regex": "^6.1.0", + "regex-recursion": "^6.0.2" + } + }, + "node_modules/overlayscrollbars": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/overlayscrollbars/-/overlayscrollbars-2.6.1.tgz", + "integrity": "sha512-V+ZAqWMYMyGBJNRDEcdRC7Ch+WT9RBx9hY8bfJSMyFObQeJoecs1Vqg7ZAzBVcpN6sCUXFAZldCbeySwmmD0RA==", + "license": "MIT" + }, + "node_modules/own-keys": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/own-keys/-/own-keys-1.0.1.tgz", + "integrity": "sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==", + "license": "MIT", + "dependencies": { + "get-intrinsic": "^1.2.6", + "object-keys": "^1.1.1", + "safe-push-apply": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/p-limit": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-6.2.0.tgz", + "integrity": "sha512-kuUqqHNUqoIWp/c467RI4X6mmyuojY5jGutNU0wVTmEOOfcuwLqyMVoAi9MKi2Ak+5i9+nhmrK4ufZE8069kHA==", + "license": "MIT", + "dependencies": { + "yocto-queue": "^1.1.1" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-map": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", + "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "aggregate-error": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-queue": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/p-queue/-/p-queue-8.1.1.tgz", + "integrity": "sha512-aNZ+VfjobsWryoiPnEApGGmf5WmNsCo9xu8dfaYamG5qaLP7ClhLN6NgsFe6SwJ2UbLEBK5dv9x8Mn5+RVhMWQ==", + "license": "MIT", + "dependencies": { + "eventemitter3": "^5.0.1", + "p-timeout": "^6.1.2" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-timeout": { + "version": "6.1.4", + "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-6.1.4.tgz", + "integrity": "sha512-MyIV3ZA/PmyBN/ud8vV9XzwTrNtR4jFrObymZYnZqMmW0zA8Z17vnT0rBgFE/TlohB+YCHqXMgZzb3Csp49vqg==", + "license": "MIT", + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/package-manager-detector": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/package-manager-detector/-/package-manager-detector-1.6.0.tgz", + "integrity": "sha512-61A5ThoTiDG/C8s8UMZwSorAGwMJ0ERVGj2OjoW5pAalsNOg15+iQiPzrLJ4jhZ1HJzmC2PIHT2oEiH3R5fzNA==", + "license": "MIT" + }, + "node_modules/parse-latin": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/parse-latin/-/parse-latin-7.0.0.tgz", + "integrity": "sha512-mhHgobPPua5kZ98EF4HWiH167JWBfl4pvAIXXdbaVohtK7a6YBOy56kvhCqduqyo/f3yrHFWmqmiMg/BkBkYYQ==", + "license": "MIT", + "dependencies": { + "@types/nlcst": "^2.0.0", + "@types/unist": "^3.0.0", + "nlcst-to-string": "^4.0.0", + "unist-util-modify-children": "^4.0.0", + "unist-util-visit-children": "^3.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/parse5": { + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.3.0.tgz", + "integrity": "sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==", + "license": "MIT", + "dependencies": { + "entities": "^6.0.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, + "node_modules/path-browserify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz", + "integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==", + "dev": true, + "license": "MIT" + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-to-regexp": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.9.0.tgz", + "integrity": "sha512-xIp7/apCFJuUHdDLWe8O1HIkb0kQrOMb/0u6FXQjemHn/ii5LrIzU6bdECnsiTF/GjZkMEKg1xdiZwNqDYlZ6g==", + "license": "MIT", + "dependencies": { + "isarray": "0.0.1" + } + }, + "node_modules/path-to-regexp/node_modules/isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==", + "license": "MIT" + }, + "node_modules/pathe": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", + "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", + "dev": true, + "license": "MIT" + }, + "node_modules/piccolore": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/piccolore/-/piccolore-0.1.3.tgz", + "integrity": "sha512-o8bTeDWjE086iwKrROaDf31K0qC/BENdm15/uH9usSC/uZjJOKb2YGiVHfLY4GhwsERiPI1jmwI2XrA7ACOxVw==", + "license": "ISC" + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", + "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/popmotion": { + "version": "11.0.3", + "resolved": "https://registry.npmjs.org/popmotion/-/popmotion-11.0.3.tgz", + "integrity": "sha512-Y55FLdj3UxkR7Vl3s7Qr4e9m0onSnP8W7d/xQLsoJM40vs6UKHFdygs6SWryasTZYqugMjm3BepCF4CWXDiHgA==", + "license": "MIT", + "dependencies": { + "framesync": "6.0.1", + "hey-listen": "^1.0.8", + "style-value-types": "5.0.0", + "tslib": "^2.1.0" + } + }, + "node_modules/popper.js": { + "version": "1.16.1", + "resolved": "https://registry.npmjs.org/popper.js/-/popper.js-1.16.1.tgz", + "integrity": "sha512-Wb4p1J4zyFTbM+u6WuO4XstYx4Ky9Cewe4DWrel7B0w6VVICvPwdOpotjzcf6eD8TsckVnIMNONQyPIUFOUbCQ==", + "deprecated": "You can find the new Popper v2 at @popperjs/core, this package is dedicated to the legacy v1", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/popperjs" + } + }, + "node_modules/possible-typed-array-names": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz", + "integrity": "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/postcss": { + "version": "8.5.15", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.15.tgz", + "integrity": "sha512-FfR8sjd4em2T6fb3I2MwAJU7HWVMr9zba+enmQeeWFfCbm+UOC/0X4DS8XtpUTMwWMGbjKYP7xjfNekzyGmB3A==", + "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.12", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/prettier": { + "version": "3.8.3", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.8.3.tgz", + "integrity": "sha512-7igPTM53cGHMW8xWuVTydi2KO233VFiTNyF5hLJqpilHfmn8C8gPf+PS7dUT64YcXFbiMGZxS9pCSxL/Dxm/Jw==", + "dev": true, + "license": "MIT", + "bin": { + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, + "node_modules/pretty-format": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", + "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^17.0.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/prismjs": { + "version": "1.30.0", + "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.30.0.tgz", + "integrity": "sha512-DEvV2ZF2r2/63V+tK8hQvrR2ZGn10srHbXviTlcv7Kpzw8jWiNTqbVgjO3IY8RxrrOUF8VPMQQFysYYYv0YZxw==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/promise": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz", + "integrity": "sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==", + "license": "MIT", + "dependencies": { + "asap": "~2.0.3" + } + }, + "node_modules/promise-inflight": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", + "integrity": "sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==", + "dev": true, + "license": "ISC" + }, + "node_modules/promise-retry": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-2.0.1.tgz", + "integrity": "sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==", + "dev": true, + "license": "MIT", + "dependencies": { + "err-code": "^2.0.2", + "retry": "^0.12.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/prompts": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", + "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", + "license": "MIT", + "dependencies": { + "kleur": "^3.0.3", + "sisteransi": "^1.0.5" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/prompts/node_modules/kleur": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", + "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/prop-types": { + "version": "15.8.1", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", + "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.13.1" + } + }, + "node_modules/prop-types/node_modules/react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", + "license": "MIT" + }, + "node_modules/property-information": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/property-information/-/property-information-7.2.0.tgz", + "integrity": "sha512-IAtzIB6sUiWaJYrX9smp3V46pBGbBeLFRGdh25kg1334VcBlD8HzhPeNIWQH9zhGmo2itIe25EHt9dQP7G5hmg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/radix3": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/radix3/-/radix3-1.1.2.tgz", + "integrity": "sha512-b484I/7b8rDEdSDKckSSBA8knMpcdsXudlE/LNL639wFoHKwLbEkQFZHWEYwDC0wa0FKUcCY+GAF73Z7wxNVFA==", + "license": "MIT" + }, + "node_modules/rc-align": { + "version": "4.0.15", + "resolved": "https://registry.npmjs.org/rc-align/-/rc-align-4.0.15.tgz", + "integrity": "sha512-wqJtVH60pka/nOX7/IspElA8gjPNQKIx/ZqJ6heATCkXpe1Zg4cPVrMD2vC96wjsFFL8WsmhPbx9tdMo1qqlIA==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.10.1", + "classnames": "2.x", + "dom-align": "^1.7.0", + "rc-util": "^5.26.0", + "resize-observer-polyfill": "^1.5.1" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-motion": { + "version": "2.9.5", + "resolved": "https://registry.npmjs.org/rc-motion/-/rc-motion-2.9.5.tgz", + "integrity": "sha512-w+XTUrfh7ArbYEd2582uDrEhmBHwK1ZENJiSJVb7uRxdE7qJSYjbO2eksRXmndqyKqKoYPc9ClpPh5242mV1vA==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.11.1", + "classnames": "^2.2.1", + "rc-util": "^5.44.0" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-slider": { + "version": "9.7.2", + "resolved": "https://registry.npmjs.org/rc-slider/-/rc-slider-9.7.2.tgz", + "integrity": "sha512-mVaLRpDo6otasBs6yVnG02ykI3K6hIrLTNfT5eyaqduFv95UODI9PDS6fWuVVehVpdS4ENgOSwsTjrPVun+k9g==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.10.1", + "classnames": "^2.2.5", + "rc-tooltip": "^5.0.1", + "rc-util": "^5.0.0", + "shallowequal": "^1.1.0" + }, + "engines": { + "node": ">=8.x" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-tooltip": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/rc-tooltip/-/rc-tooltip-5.3.1.tgz", + "integrity": "sha512-e6H0dMD38EPaSPD2XC8dRfct27VvT2TkPdoBSuNl3RRZ5tspiY/c5xYEmGC0IrABvMBgque4Mr2SMZuliCvoiQ==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.11.2", + "classnames": "^2.3.1", + "rc-trigger": "^5.3.1" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-trigger": { + "version": "5.3.4", + "resolved": "https://registry.npmjs.org/rc-trigger/-/rc-trigger-5.3.4.tgz", + "integrity": "sha512-mQv+vas0TwKcjAO2izNPkqR4j86OemLRmvL2nOzdP9OWNWA1ivoTt5hzFqYNW9zACwmTezRiN8bttrC7cZzYSw==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.18.3", + "classnames": "^2.2.6", + "rc-align": "^4.0.0", + "rc-motion": "^2.0.0", + "rc-util": "^5.19.2" + }, + "engines": { + "node": ">=8.x" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-util": { + "version": "5.44.4", + "resolved": "https://registry.npmjs.org/rc-util/-/rc-util-5.44.4.tgz", + "integrity": "sha512-resueRJzmHG9Q6rI/DfK6Kdv9/Lfls05vzMs1Sk3M2P+3cJa+MakaZyWY8IPfehVuhPJFKrIY1IK4GqbiaiY5w==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.18.3", + "react-is": "^18.2.0" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-util/node_modules/react-is": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", + "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", + "license": "MIT" + }, + "node_modules/react": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", + "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-aria": { + "version": "3.49.0", + "resolved": "https://registry.npmjs.org/react-aria/-/react-aria-3.49.0.tgz", + "integrity": "sha512-4+oK9FwJQWYhyA5zLfj/feOGY0zZbkE1muoF4gyxMroHVypjcYaRSTlJwvxph2zIlxt757KX6xIK2wJ5Aw1Kog==", + "license": "Apache-2.0", + "dependencies": { + "@internationalized/date": "^3.12.2", + "@internationalized/number": "^3.6.7", + "@internationalized/string": "^3.2.9", + "@react-types/shared": "^3.35.0", + "@swc/helpers": "^0.5.0", + "aria-hidden": "^1.2.3", + "clsx": "^2.0.0", + "react-stately": "3.47.0", + "use-sync-external-store": "^1.6.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1", + "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/react-chartjs-2": { + "version": "2.11.2", + "resolved": "https://registry.npmjs.org/react-chartjs-2/-/react-chartjs-2-2.11.2.tgz", + "integrity": "sha512-hcPS9vmRJeAALPPf0uo02BiD8BDm0HNmneJYTZVR74UKprXOpql+Jy1rVuj93rKw0Jfx77mkcRfXPxTe5K83uw==", + "license": "MIT", + "dependencies": { + "lodash": "^4.17.19", + "prop-types": "^15.7.2" + }, + "peerDependencies": { + "chart.js": "^2.3", + "react": "^0.14.0 || ^15.0.0 || ^16.0.0 || ^17.0.0", + "react-dom": "^0.14.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" + } + }, + "node_modules/react-day-picker": { + "version": "7.4.10", + "resolved": "https://registry.npmjs.org/react-day-picker/-/react-day-picker-7.4.10.tgz", + "integrity": "sha512-/QkK75qLKdyLmv0kcVzhL7HoJPazoZXS8a6HixbVoK6vWey1Od1WRLcxfyEiUsRfccAlIlf6oKHShqY2SM82rA==", + "license": "MIT", + "dependencies": { + "prop-types": "^15.6.2" + }, + "peerDependencies": { + "react": "~0.13.x || ~0.14.x || ^15.0.0 || ^16.0.0 || ^17.0.0" + } + }, + "node_modules/react-dnd": { + "version": "11.1.3", + "resolved": "https://registry.npmjs.org/react-dnd/-/react-dnd-11.1.3.tgz", + "integrity": "sha512-8rtzzT8iwHgdSC89VktwhqdKKtfXaAyC4wiqp0SywpHG12TTLvfOoL6xNEIUWXwIEWu+CFfDn4GZJyynCEuHIQ==", + "license": "MIT", + "dependencies": { + "@react-dnd/shallowequal": "^2.0.0", + "@types/hoist-non-react-statics": "^3.3.1", + "dnd-core": "^11.1.3", + "hoist-non-react-statics": "^3.3.0" + }, + "peerDependencies": { + "react": ">= 16.9.0", + "react-dom": ">= 16.9.0" + } + }, + "node_modules/react-dnd-test-backend": { + "version": "11.1.3", + "resolved": "https://registry.npmjs.org/react-dnd-test-backend/-/react-dnd-test-backend-11.1.3.tgz", + "integrity": "sha512-5qFm+NI2GdWIUfiYun0A8Gv0xjbq0NGOPS+f6z3x/3nTuliApjmqcM1lfTgePoz1FDG47ZofF58N8y96If62+Q==", + "license": "MIT", + "dependencies": { + "dnd-core": "^11.1.3" + } + }, + "node_modules/react-dnd-touch-backend": { + "version": "11.1.3", + "resolved": "https://registry.npmjs.org/react-dnd-touch-backend/-/react-dnd-touch-backend-11.1.3.tgz", + "integrity": "sha512-8lz4fxfYwUuJ6Y2seQYwh8+OfwKcbBX0CIbz7AwXfBYz54Wg2nIDU6CP8Dyybt/Wyx4D3oXmTPEaOMB62uqJvQ==", + "license": "MIT", + "dependencies": { + "@react-dnd/invariant": "^2.0.0", + "dnd-core": "^11.1.3" + } + }, + "node_modules/react-dom": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", + "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==", + "dev": true, + "license": "MIT", + "dependencies": { + "loose-envify": "^1.1.0", + "scheduler": "^0.23.2" + }, + "peerDependencies": { + "react": "^18.3.1" + } + }, + "node_modules/react-dom-instance": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/react-dom-instance/-/react-dom-instance-2.0.0.tgz", + "integrity": "sha512-DH5IQOCm2pkRwAuWcNyILQBkmt5JS019LqH7KeakTAK2jMl2v1crLO5oXqqGPXsxP0arjRG7OPO8h/mZVuHADQ==", + "license": "MIT" + }, + "node_modules/react-error-boundary": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/react-error-boundary/-/react-error-boundary-5.0.0.tgz", + "integrity": "sha512-tnjAxG+IkpLephNcePNA7v6F/QpWLH8He65+DmedchDwg162JZqx4NmbXj0mlAYVVEd81OW7aFhmbsScYfiAFQ==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.12.5" + }, + "peerDependencies": { + "react": ">=16.13.1" + } + }, + "node_modules/react-i18next": { + "version": "16.6.6", + "resolved": "https://registry.npmjs.org/react-i18next/-/react-i18next-16.6.6.tgz", + "integrity": "sha512-ZgL2HUoW34UKUkOV7uSQFE1CDnRPD+tCR3ywSuWH7u2iapnz86U8Bi3Vrs620qNDzCf1F47NxglCEkchCTDOHw==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.29.2", + "html-parse-stringify": "^3.0.1", + "use-sync-external-store": "^1.6.0" + }, + "peerDependencies": { + "i18next": ">= 25.10.9", + "react": ">= 16.8.0", + "typescript": "^5 || ^6" + }, + "peerDependenciesMeta": { + "react-dom": { + "optional": true + }, + "react-native": { + "optional": true + }, + "typescript": { + "optional": true + } + } + }, + "node_modules/react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", + "license": "MIT" + }, + "node_modules/react-lifecycles-compat": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz", + "integrity": "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==", + "license": "MIT" + }, + "node_modules/react-modal": { + "version": "3.16.3", + "resolved": "https://registry.npmjs.org/react-modal/-/react-modal-3.16.3.tgz", + "integrity": "sha512-yCYRJB5YkeQDQlTt17WGAgFJ7jr2QYcWa1SHqZ3PluDmnKJ/7+tVU+E6uKyZ0nODaeEj+xCpK4LcSnKXLMC0Nw==", + "license": "MIT", + "dependencies": { + "exenv": "^1.2.0", + "prop-types": "^15.7.2", + "react-lifecycles-compat": "^3.0.0", + "warning": "^4.0.3" + }, + "peerDependencies": { + "react": "^0.14.0 || ^15.0.0 || ^16 || ^17 || ^18 || ^19", + "react-dom": "^0.14.0 || ^15.0.0 || ^16 || ^17 || ^18 || ^19" + } + }, + "node_modules/react-popper": { + "version": "1.3.11", + "resolved": "https://registry.npmjs.org/react-popper/-/react-popper-1.3.11.tgz", + "integrity": "sha512-VSA/bS+pSndSF2fiasHK/PTEEAyOpX60+H5EPAjoArr8JGm+oihu4UbrqcEBpQibJxBVCpYyjAX7abJ+7DoYVg==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.1.2", + "@hypnosphi/create-react-context": "^0.3.1", + "deep-equal": "^1.1.1", + "popper.js": "^1.14.4", + "prop-types": "^15.6.1", + "typed-styles": "^0.0.7", + "warning": "^4.0.2" + }, + "peerDependencies": { + "react": "0.14.x || ^15.0.0 || ^16.0.0 || ^17.0.0" + } + }, + "node_modules/react-refresh": { + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.17.0.tgz", + "integrity": "sha512-z6F7K9bV85EfseRCp2bzrpyQ0Gkw1uLoCel9XBVWPg/TjRj94SkJzUTGfOa4bs7iJvBWtQG0Wq7wnI0syw3EBQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-remove-scroll": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/react-remove-scroll/-/react-remove-scroll-2.7.1.tgz", + "integrity": "sha512-HpMh8+oahmIdOuS5aFKKY6Pyog+FNaZV/XyJOq7b4YFwsFHe5yYfdbIalI4k3vU2nSDql7YskmUseHsRrJqIPA==", + "license": "MIT", + "dependencies": { + "react-remove-scroll-bar": "^2.3.7", + "react-style-singleton": "^2.2.3", + "tslib": "^2.1.0", + "use-callback-ref": "^1.3.3", + "use-sidecar": "^1.1.3" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/react-remove-scroll-bar": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/react-remove-scroll-bar/-/react-remove-scroll-bar-2.3.8.tgz", + "integrity": "sha512-9r+yi9+mgU33AKcj6IbT9oRCO78WriSj6t/cF8DWBZJ9aOGPOTEDvdUDz1FwKim7QXWwmHqtdHnRJfhAxEG46Q==", + "license": "MIT", + "dependencies": { + "react-style-singleton": "^2.2.2", + "tslib": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/react-scroll-sync": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/react-scroll-sync/-/react-scroll-sync-0.11.0.tgz", + "integrity": "sha512-COfA885/2NAQPxusIU6sukKiSFXgAd9+OWD7iBWA4NF5Y1Np8poBKLwgZ3y4iywo5/+ch0PLGz887myIbm+fPw==", + "license": "MIT", + "dependencies": { + "prop-types": "^15.5.7" + }, + "peerDependencies": { + "react": "16.x || 17.x || 18.x", + "react-dom": "16.x || 17.x || 18.x" + } + }, + "node_modules/react-stately": { + "version": "3.47.0", + "resolved": "https://registry.npmjs.org/react-stately/-/react-stately-3.47.0.tgz", + "integrity": "sha512-H3ar+SOWP920EbVg7qWfP3fZjZiwhlEJAEJQqjt+w8oKijCwFgr0+R4941PIHscOXRNRvEOjvWilitImC0DdBg==", + "license": "Apache-2.0", + "dependencies": { + "@internationalized/date": "^3.12.2", + "@internationalized/number": "^3.6.7", + "@internationalized/string": "^3.2.9", + "@react-types/shared": "^3.35.0", + "@swc/helpers": "^0.5.0", + "use-sync-external-store": "^1.6.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/react-style-singleton": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/react-style-singleton/-/react-style-singleton-2.2.3.tgz", + "integrity": "sha512-b6jSvxvVnyptAiLjbkWLE/lOnR4lfTtDAl+eUC7RZy+QQWc6wRzIV2CE6xBuMmDxc2qIihtDCZD5NPOFl7fRBQ==", + "license": "MIT", + "dependencies": { + "get-nonce": "^1.0.0", + "tslib": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/react-transition-group": { + "version": "4.4.5", + "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz", + "integrity": "sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g==", + "license": "BSD-3-Clause", + "dependencies": { + "@babel/runtime": "^7.5.5", + "dom-helpers": "^5.0.1", + "loose-envify": "^1.4.0", + "prop-types": "^15.6.2" + }, + "peerDependencies": { + "react": ">=16.6.0", + "react-dom": ">=16.6.0" + } + }, + "node_modules/react-window": { + "version": "1.8.11", + "resolved": "https://registry.npmjs.org/react-window/-/react-window-1.8.11.tgz", + "integrity": "sha512-+SRbUVT2scadgFSWx+R1P754xHPEqvcfSfVX10QYg6POOz+WNgkN48pS+BtZNIMGiL1HYrSEiCkwsMS15QogEQ==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.0.0", + "memoize-one": ">=3.1.1 <6" + }, + "engines": { + "node": ">8.0.0" + }, + "peerDependencies": { + "react": "^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", + "react-dom": "^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, + "node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dev": true, + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/readdirp": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz", + "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 14.18.0" + }, + "funding": { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/redux": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/redux/-/redux-4.2.1.tgz", + "integrity": "sha512-LAUYz4lc+Do8/g7aeRa8JkyDErK6ekstQaqWQrNRW//MY1TvCEpMtpTWvlQ+FPbWCx+Xixu/6SHt5N0HR+SB4w==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.9.2" + } + }, + "node_modules/reflect.getprototypeof": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz", + "integrity": "sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.9", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.7", + "get-proto": "^1.0.1", + "which-builtin-type": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/regex": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/regex/-/regex-6.1.0.tgz", + "integrity": "sha512-6VwtthbV4o/7+OaAF9I5L5V3llLEsoPyq9P1JVXkedTP33c7MfCG0/5NOPcSJn0TzXcG9YUrR0gQSWioew3LDg==", + "license": "MIT", + "dependencies": { + "regex-utilities": "^2.3.0" + } + }, + "node_modules/regex-recursion": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/regex-recursion/-/regex-recursion-6.0.2.tgz", + "integrity": "sha512-0YCaSCq2VRIebiaUviZNs0cBz1kg5kVS2UKUfNIx8YVs1cN3AV7NTctO5FOKBA+UT2BPJIWZauYHPqJODG50cg==", + "license": "MIT", + "dependencies": { + "regex-utilities": "^2.3.0" + } + }, + "node_modules/regex-utilities": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/regex-utilities/-/regex-utilities-2.3.0.tgz", + "integrity": "sha512-8VhliFJAWRaUiVvREIiW2NXXTmHs4vMNnSzuJVhscgmGav3g9VDxLrQndI3dZZVVdp0ZO/5v0xmX516/7M9cng==", + "license": "MIT" + }, + "node_modules/regexp.prototype.flags": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.4.tgz", + "integrity": "sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-errors": "^1.3.0", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "set-function-name": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/rehype": { + "version": "13.0.2", + "resolved": "https://registry.npmjs.org/rehype/-/rehype-13.0.2.tgz", + "integrity": "sha512-j31mdaRFrwFRUIlxGeuPXXKWQxet52RBQRvCmzl5eCefn/KGbomK5GMHNMsOJf55fgo3qw5tST5neDuarDYR2A==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "rehype-parse": "^9.0.0", + "rehype-stringify": "^10.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/rehype-parse": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/rehype-parse/-/rehype-parse-9.0.1.tgz", + "integrity": "sha512-ksCzCD0Fgfh7trPDxr2rSylbwq9iYDkSn8TCDmEJ49ljEUBxDVCzCHv7QNzZOfODanX4+bWQ4WZqLCRWYLfhag==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "hast-util-from-html": "^2.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/rehype-raw": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/rehype-raw/-/rehype-raw-7.0.0.tgz", + "integrity": "sha512-/aE8hCfKlQeA8LmyeyQvQF3eBiLRGNlfBJEvWH7ivp9sBqs7TNqBL5X3v157rM4IFETqDnIOO+z5M/biZbo9Ww==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "hast-util-raw": "^9.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/rehype-stringify": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/rehype-stringify/-/rehype-stringify-10.0.1.tgz", + "integrity": "sha512-k9ecfXHmIPuFVI61B9DeLPN0qFHfawM6RsuX48hoqlaKSF61RskNjSm1lI8PhBEM0MRdLxVVm4WmTqJQccH9mA==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "hast-util-to-html": "^9.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-gfm": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/remark-gfm/-/remark-gfm-4.0.1.tgz", + "integrity": "sha512-1quofZ2RQ9EWdeN34S79+KExV1764+wCUGop5CPL1WGdD0ocPpu91lzPGbwWMECpEpd42kJGQwzRfyov9j4yNg==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "mdast-util-gfm": "^3.0.0", + "micromark-extension-gfm": "^3.0.0", + "remark-parse": "^11.0.0", + "remark-stringify": "^11.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-parse": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-11.0.0.tgz", + "integrity": "sha512-FCxlKLNGknS5ba/1lmpYijMUzX2esxW5xQqjWxw2eHFfS2MSdaHVINFmhjo+qN1WhZhNimq0dZATN9pH0IDrpA==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "mdast-util-from-markdown": "^2.0.0", + "micromark-util-types": "^2.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-rehype": { + "version": "11.1.2", + "resolved": "https://registry.npmjs.org/remark-rehype/-/remark-rehype-11.1.2.tgz", + "integrity": "sha512-Dh7l57ianaEoIpzbp0PC9UKAdCSVklD8E5Rpw7ETfbTl3FqcOOgq5q2LVDhgGCkaBv7p24JXikPdvhhmHvKMsw==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "mdast-util-to-hast": "^13.0.0", + "unified": "^11.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-smartypants": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/remark-smartypants/-/remark-smartypants-3.0.2.tgz", + "integrity": "sha512-ILTWeOriIluwEvPjv67v7Blgrcx+LZOkAUVtKI3putuhlZm84FnqDORNXPPm+HY3NdZOMhyDwZ1E+eZB/Df5dA==", + "license": "MIT", + "dependencies": { + "retext": "^9.0.0", + "retext-smartypants": "^6.0.0", + "unified": "^11.0.4", + "unist-util-visit": "^5.0.0" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/remark-stringify": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/remark-stringify/-/remark-stringify-11.0.0.tgz", + "integrity": "sha512-1OSmLd3awB/t8qdoEOMazZkNsfVTeY4fTsgzcQFdXNq8ToTN4ZGwrMnlda4K6smTFKD+GRV6O48i6Z4iKgPPpw==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "mdast-util-to-markdown": "^2.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/request-light": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/request-light/-/request-light-0.7.0.tgz", + "integrity": "sha512-lMbBMrDoxgsyO+yB3sDcrDuX85yYt7sS8BfQd11jtbW/z5ZWgLZRcEGLsLoYw7I0WSUGQBs8CC8ScIxkTX1+6Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/resize-observer-polyfill": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/resize-observer-polyfill/-/resize-observer-polyfill-1.5.1.tgz", + "integrity": "sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg==", + "license": "MIT" + }, + "node_modules/retext": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/retext/-/retext-9.0.0.tgz", + "integrity": "sha512-sbMDcpHCNjvlheSgMfEcVrZko3cDzdbe1x/e7G66dFp0Ff7Mldvi2uv6JkJQzdRcvLYE8CA8Oe8siQx8ZOgTcA==", + "license": "MIT", + "dependencies": { + "@types/nlcst": "^2.0.0", + "retext-latin": "^4.0.0", + "retext-stringify": "^4.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/retext-latin": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/retext-latin/-/retext-latin-4.0.0.tgz", + "integrity": "sha512-hv9woG7Fy0M9IlRQloq/N6atV82NxLGveq+3H2WOi79dtIYWN8OaxogDm77f8YnVXJL2VD3bbqowu5E3EMhBYA==", + "license": "MIT", + "dependencies": { + "@types/nlcst": "^2.0.0", + "parse-latin": "^7.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/retext-smartypants": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/retext-smartypants/-/retext-smartypants-6.2.0.tgz", + "integrity": "sha512-kk0jOU7+zGv//kfjXEBjdIryL1Acl4i9XNkHxtM7Tm5lFiCog576fjNC9hjoR7LTKQ0DsPWy09JummSsH1uqfQ==", + "license": "MIT", + "dependencies": { + "@types/nlcst": "^2.0.0", + "nlcst-to-string": "^4.0.0", + "unist-util-visit": "^5.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/retext-stringify": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/retext-stringify/-/retext-stringify-4.0.0.tgz", + "integrity": "sha512-rtfN/0o8kL1e+78+uxPTqu1Klt0yPzKuQ2BfWwwfgIUSayyzxpM1PJzkKt4V8803uB9qSy32MvI7Xep9khTpiA==", + "license": "MIT", + "dependencies": { + "@types/nlcst": "^2.0.0", + "nlcst-to-string": "^4.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/retry": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", + "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", + "dev": true, + "license": "ISC", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/rollup": { + "version": "4.61.0", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.61.0.tgz", + "integrity": "sha512-T9mWdbWfQtp0B5lv/HX+wrhYsmXRlcWnXXmJbXqKJhlRaoS6KMhq0gpyzW4UJfclcxrEdLnTgjT2NjruLONu0g==", + "license": "MIT", + "dependencies": { + "@types/estree": "1.0.9" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.61.0", + "@rollup/rollup-android-arm64": "4.61.0", + "@rollup/rollup-darwin-arm64": "4.61.0", + "@rollup/rollup-darwin-x64": "4.61.0", + "@rollup/rollup-freebsd-arm64": "4.61.0", + "@rollup/rollup-freebsd-x64": "4.61.0", + "@rollup/rollup-linux-arm-gnueabihf": "4.61.0", + "@rollup/rollup-linux-arm-musleabihf": "4.61.0", + "@rollup/rollup-linux-arm64-gnu": "4.61.0", + "@rollup/rollup-linux-arm64-musl": "4.61.0", + "@rollup/rollup-linux-loong64-gnu": "4.61.0", + "@rollup/rollup-linux-loong64-musl": "4.61.0", + "@rollup/rollup-linux-ppc64-gnu": "4.61.0", + "@rollup/rollup-linux-ppc64-musl": "4.61.0", + "@rollup/rollup-linux-riscv64-gnu": "4.61.0", + "@rollup/rollup-linux-riscv64-musl": "4.61.0", + "@rollup/rollup-linux-s390x-gnu": "4.61.0", + "@rollup/rollup-linux-x64-gnu": "4.61.0", + "@rollup/rollup-linux-x64-musl": "4.61.0", + "@rollup/rollup-openbsd-x64": "4.61.0", + "@rollup/rollup-openharmony-arm64": "4.61.0", + "@rollup/rollup-win32-arm64-msvc": "4.61.0", + "@rollup/rollup-win32-ia32-msvc": "4.61.0", + "@rollup/rollup-win32-x64-gnu": "4.61.0", + "@rollup/rollup-win32-x64-msvc": "4.61.0", + "fsevents": "~2.3.2" + } + }, + "node_modules/safe-array-concat": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.4.tgz", + "integrity": "sha512-wtZlHyOje6OZTGqAoaDKxFkgRtkF9CnHAVnCHKfuj200wAgL+bSJhdsCD2l0Qx/2ekEXjPWcyKkfGb5CPboslg==", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.9", + "call-bound": "^1.0.4", + "get-intrinsic": "^1.3.0", + "has-symbols": "^1.1.0", + "isarray": "^2.0.5" + }, + "engines": { + "node": ">=0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/safe-push-apply": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/safe-push-apply/-/safe-push-apply-1.0.0.tgz", + "integrity": "sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "isarray": "^2.0.5" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safe-regex-test": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.1.0.tgz", + "integrity": "sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "is-regex": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true, + "license": "MIT", + "optional": true + }, + "node_modules/samsam": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/samsam/-/samsam-1.3.0.tgz", + "integrity": "sha512-1HwIYD/8UlOtFS3QO3w7ey+SdSDFE4HRNLZoZRYVQefrOY3l17epswImeB1ijgJFQJodIaHcwkp3r/myBjFVbg==", + "deprecated": "This package has been deprecated in favour of @sinonjs/samsam", + "license": "BSD-3-Clause" + }, + "node_modules/sax": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.6.0.tgz", + "integrity": "sha512-6R3J5M4AcbtLUdZmRv2SygeVaM7IhrLXu9BmnOGmmACak8fiUtOsYNWUS4uK7upbmHIBbLBeFeI//477BKLBzA==", + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=11.0.0" + } + }, + "node_modules/scheduler": { + "version": "0.23.2", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz", + "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "loose-envify": "^1.1.0" + } + }, + "node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", + "dev": true, + "license": "ISC" + }, + "node_modules/set-function-length": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "license": "MIT", + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/set-function-name": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz", + "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==", + "license": "MIT", + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "functions-have-names": "^1.2.3", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/set-proto": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/set-proto/-/set-proto-1.0.0.tgz", + "integrity": "sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw==", + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/setimmediate": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", + "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==", + "license": "MIT" + }, + "node_modules/shallowequal": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/shallowequal/-/shallowequal-1.1.0.tgz", + "integrity": "sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ==", + "license": "MIT" + }, + "node_modules/sharp": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.34.5.tgz", + "integrity": "sha512-Ou9I5Ft9WNcCbXrU9cMgPBcCK8LiwLqcbywW3t4oDV37n1pzpuNLsYiAV8eODnjbtQlSDwZ2cUEeQz4E54Hltg==", + "devOptional": true, + "hasInstallScript": true, + "license": "Apache-2.0", + "dependencies": { + "@img/colour": "^1.0.0", + "detect-libc": "^2.1.2", + "semver": "^7.7.3" + }, + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-darwin-arm64": "0.34.5", + "@img/sharp-darwin-x64": "0.34.5", + "@img/sharp-libvips-darwin-arm64": "1.2.4", + "@img/sharp-libvips-darwin-x64": "1.2.4", + "@img/sharp-libvips-linux-arm": "1.2.4", + "@img/sharp-libvips-linux-arm64": "1.2.4", + "@img/sharp-libvips-linux-ppc64": "1.2.4", + "@img/sharp-libvips-linux-riscv64": "1.2.4", + "@img/sharp-libvips-linux-s390x": "1.2.4", + "@img/sharp-libvips-linux-x64": "1.2.4", + "@img/sharp-libvips-linuxmusl-arm64": "1.2.4", + "@img/sharp-libvips-linuxmusl-x64": "1.2.4", + "@img/sharp-linux-arm": "0.34.5", + "@img/sharp-linux-arm64": "0.34.5", + "@img/sharp-linux-ppc64": "0.34.5", + "@img/sharp-linux-riscv64": "0.34.5", + "@img/sharp-linux-s390x": "0.34.5", + "@img/sharp-linux-x64": "0.34.5", + "@img/sharp-linuxmusl-arm64": "0.34.5", + "@img/sharp-linuxmusl-x64": "0.34.5", + "@img/sharp-wasm32": "0.34.5", + "@img/sharp-win32-arm64": "0.34.5", + "@img/sharp-win32-ia32": "0.34.5", + "@img/sharp-win32-x64": "0.34.5" + } + }, + "node_modules/sharp/node_modules/semver": { + "version": "7.8.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.1.tgz", + "integrity": "sha512-rkVq3IXh+4FDGch+KwzX3aV9W3kO54GyEgpvBzSyctDA6Xtd7RJQV1xmXbeQp5v7+VzLOfVqiutSE6GICgPFvg==", + "devOptional": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/shiki": { + "version": "3.23.0", + "resolved": "https://registry.npmjs.org/shiki/-/shiki-3.23.0.tgz", + "integrity": "sha512-55Dj73uq9ZXL5zyeRPzHQsK7Nbyt6Y10k5s7OjuFZGMhpp4r/rsLBH0o/0fstIzX1Lep9VxefWljK/SKCzygIA==", + "license": "MIT", + "dependencies": { + "@shikijs/core": "3.23.0", + "@shikijs/engine-javascript": "3.23.0", + "@shikijs/engine-oniguruma": "3.23.0", + "@shikijs/langs": "3.23.0", + "@shikijs/themes": "3.23.0", + "@shikijs/types": "3.23.0", + "@shikijs/vscode-textmate": "^10.0.2", + "@types/hast": "^3.0.4" + } + }, + "node_modules/side-channel": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", + "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3", + "side-channel-list": "^1.0.0", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-list": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.1.tgz", + "integrity": "sha512-mjn/0bi/oUURjc5Xl7IaWi/OJJJumuoJFQJfDDyO46+hBWsfaVM65TBHq2eoZBhzl9EchxOijpkbRC8SVBQU0w==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-weakmap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/simple-swizzle": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.4.tgz", + "integrity": "sha512-nAu1WFPQSMNr2Zn9PGSZK9AGn4t/y97lEm+MXTtUDwfP0ksAIX4nO+6ruD9Jwut4C49SB1Ws+fbXsm/yScWOHw==", + "license": "MIT", + "dependencies": { + "is-arrayish": "^0.3.1" + } + }, + "node_modules/sinon": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/sinon/-/sinon-4.5.0.tgz", + "integrity": "sha512-trdx+mB0VBBgoYucy6a9L7/jfQOmvGeaKZT4OOJ+lPAtI8623xyGr8wLiE4eojzBS8G9yXbhx42GHUOVLr4X2w==", + "deprecated": "16.1.1", + "hasInstallScript": true, + "license": "BSD-3-Clause", + "dependencies": { + "@sinonjs/formatio": "^2.0.0", + "diff": "^3.1.0", + "lodash.get": "^4.4.2", + "lolex": "^2.2.0", + "nise": "^1.2.0", + "supports-color": "^5.1.0", + "type-detect": "^4.0.5" + } + }, + "node_modules/sinon/node_modules/diff": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.1.tgz", + "integrity": "sha512-Z3u54A8qGyqFOSr2pk0ijYs8mOE9Qz8kTvtKeBI+upoG9j04Sq+oI7W8zAJiQybDcESET8/uIdHzs0p3k4fZlw==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/sisteransi": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", + "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", + "license": "MIT" + }, + "node_modules/smart-buffer": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", + "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 6.0.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/smol-toml": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/smol-toml/-/smol-toml-1.6.1.tgz", + "integrity": "sha512-dWUG8F5sIIARXih1DTaQAX4SsiTXhInKf1buxdY9DIg4ZYPZK5nGM1VRIYmEbDbsHt7USo99xSLFu5Q1IqTmsg==", + "license": "BSD-3-Clause", + "engines": { + "node": ">= 18" + }, + "funding": { + "url": "https://github.com/sponsors/cyyynthia" + } + }, + "node_modules/socks": { + "version": "2.8.9", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.9.tgz", + "integrity": "sha512-LJhUYUvItdQ0LkJTmPeaEObWXAqFyfmP85x0tch/ez9cahmhlBBLbIqDFnvBnUJGagb0JbIQrkBs1wJ+yRYpEw==", + "dev": true, + "license": "MIT", + "dependencies": { + "ip-address": "^10.1.1", + "smart-buffer": "^4.2.0" + }, + "engines": { + "node": ">= 10.0.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/socks-proxy-agent": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-6.2.1.tgz", + "integrity": "sha512-a6KW9G+6B3nWZ1yB8G7pJwL3ggLy1uTzKAgCb7ttblwqdz9fMGJUuTy3uFzEP48FAs9FLILlmzDlE2JJhVQaXQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "agent-base": "^6.0.2", + "debug": "^4.3.3", + "socks": "^2.6.2" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/space-separated-tokens": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-2.0.2.tgz", + "integrity": "sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/ssri": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-8.0.1.tgz", + "integrity": "sha512-97qShzy1AiyxvPNIkLWoGua7xoQzzPjQ0HAH4B0rWKo7SZ6USuPcrUiAFrws0UH8RrbWmgq3LMTObhPIHbbBeQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "minipass": "^3.1.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/stop-iteration-iterator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.1.0.tgz", + "integrity": "sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "internal-slot": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dev": true, + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/string-width": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", + "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", + "license": "MIT", + "dependencies": { + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/string-width/node_modules/ansi-regex": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", + "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/string-width/node_modules/strip-ansi": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.2.0.tgz", + "integrity": "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.2.2" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/string.prototype.trim": { + "version": "1.2.10", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.10.tgz", + "integrity": "sha512-Rs66F0P/1kedk5lyYyH9uBzuiI/kNRmwJAR9quK6VOtIpZ2G+hMZd+HQbbv25MgCA6gEffoMZYxlTod4WcdrKA==", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.2", + "define-data-property": "^1.1.4", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-object-atoms": "^1.0.0", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimend": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.9.tgz", + "integrity": "sha512-G7Ok5C6E/j4SGfyLCloXTrngQIQU3PWtXGst3yM7Bea9FRURf1S42ZHlZZtsNque2FN2PoUhfZXYLNWwEr4dLQ==", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.2", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimstart": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz", + "integrity": "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/stringify-entities": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/stringify-entities/-/stringify-entities-4.0.4.tgz", + "integrity": "sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg==", + "license": "MIT", + "dependencies": { + "character-entities-html4": "^2.0.0", + "character-entities-legacy": "^3.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/style-value-types": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/style-value-types/-/style-value-types-5.0.0.tgz", + "integrity": "sha512-08yq36Ikn4kx4YU6RD7jWEv27v4V+PUsOGa4n/as8Et3CuODMJQ00ENeAVXAeydX4Z2j1XHZF1K2sX4mGl18fA==", + "license": "MIT", + "dependencies": { + "hey-listen": "^1.0.8", + "tslib": "^2.1.0" + } + }, + "node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "license": "MIT", + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/svgo": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/svgo/-/svgo-4.0.1.tgz", + "integrity": "sha512-XDpWUOPC6FEibaLzjfe0ucaV0YrOjYotGJO1WpF0Zd+n6ZGEQUsSugaoLq9QkEZtAfQIxT42UChcssDVPP3+/w==", + "license": "MIT", + "dependencies": { + "commander": "^11.1.0", + "css-select": "^5.1.0", + "css-tree": "^3.0.1", + "css-what": "^6.1.0", + "csso": "^5.0.5", + "picocolors": "^1.1.1", + "sax": "^1.5.0" + }, + "bin": { + "svgo": "bin/svgo.js" + }, + "engines": { + "node": ">=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/svgo" + } + }, + "node_modules/tabbable": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/tabbable/-/tabbable-6.4.0.tgz", + "integrity": "sha512-05PUHKSNE8ou2dwIxTngl4EzcnsCDZGJ/iCLtDflR/SHB/ny14rXc+qU5P4mG9JkusiV7EivzY9Mhm55AzAvCg==", + "license": "MIT" + }, + "node_modules/tar": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz", + "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==", + "deprecated": "Old versions of tar are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", + "dev": true, + "license": "ISC", + "dependencies": { + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^5.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/tar/node_modules/minipass": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=8" + } + }, + "node_modules/tar/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true, + "license": "ISC" + }, + "node_modules/tiny-inflate": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/tiny-inflate/-/tiny-inflate-1.0.3.tgz", + "integrity": "sha512-pkY1fj1cKHb2seWDy0B16HeWyczlJA9/WW3u3c4z/NiWDsO3DOU5D7nhTLE9CF0yXv/QZFY7sEJmj24dK+Rrqw==", + "license": "MIT" + }, + "node_modules/tinyexec": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.2.4.tgz", + "integrity": "sha512-SHf/r48b7vOrjve9PxJo3MN5v5yuyjHvdUcrQffT3WXMUfnGmHDVbC4k3sHJaJTgZCwpUplIaAo5ANtMyp3YHg==", + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/tinyglobby": { + "version": "0.2.17", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.17.tgz", + "integrity": "sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==", + "license": "MIT", + "dependencies": { + "fdir": "^6.5.0", + "picomatch": "^4.0.4" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" + } + }, + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", + "license": "MIT" + }, + "node_modules/trim-lines": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/trim-lines/-/trim-lines-3.0.1.tgz", + "integrity": "sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/trough": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/trough/-/trough-2.2.0.tgz", + "integrity": "sha512-tmMpK00BjZiUyVyvrBK7knerNgmgvcV/KLVyuma/SC+TQN167GrMRciANTz09+k3zW8L8t60jWO1GpfkZdjTaw==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/tsconfck": { + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/tsconfck/-/tsconfck-3.1.6.tgz", + "integrity": "sha512-ks6Vjr/jEw0P1gmOVwutM3B7fWxoWBL2KRDb1JfqGVawBmO5UsvmWOQFGHBPl5yxYz4eERr19E6L7NMv+Fej4w==", + "license": "MIT", + "bin": { + "tsconfck": "bin/tsconfck.js" + }, + "engines": { + "node": "^18 || >=20" + }, + "peerDependencies": { + "typescript": "^5.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD" + }, + "node_modules/type-detect": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.1.0.tgz", + "integrity": "sha512-Acylog8/luQ8L7il+geoSxhEkazvkslg7PSNKOX59mbB9cOveP5aq9h74Y7YU8yDpJwetzQQrfIwtf4Wp4LKcw==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/type-fest": { + "version": "4.41.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.41.0.tgz", + "integrity": "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==", + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/typed-array-buffer": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz", + "integrity": "sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "is-typed-array": "^1.1.14" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/typed-array-byte-length": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.3.tgz", + "integrity": "sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg==", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "for-each": "^0.3.3", + "gopd": "^1.2.0", + "has-proto": "^1.2.0", + "is-typed-array": "^1.1.14" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-byte-offset": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.4.tgz", + "integrity": "sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ==", + "license": "MIT", + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.8", + "for-each": "^0.3.3", + "gopd": "^1.2.0", + "has-proto": "^1.2.0", + "is-typed-array": "^1.1.15", + "reflect.getprototypeof": "^1.0.9" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-length": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.8.tgz", + "integrity": "sha512-phPGCwqr2+Qo0fwniCE8e4pKnGu/yFb5nD5Y8bf0EEeiI5GklnACYA9GFy/DrAeRrKHXvHn+1SUsOWgJp6RO+g==", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.9", + "for-each": "^0.3.5", + "gopd": "^1.2.0", + "is-typed-array": "^1.1.15", + "possible-typed-array-names": "^1.1.0", + "reflect.getprototypeof": "^1.0.10" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-styles": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/typed-styles/-/typed-styles-0.0.7.tgz", + "integrity": "sha512-pzP0PWoZUhsECYjABgCGQlRGL1n7tOHsgwYv3oIiEpJwGhFTuty/YNeduxQYzXXa3Ge5BdT6sHYIQYpl4uJ+5Q==", + "license": "MIT" + }, + "node_modules/typesafe-path": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/typesafe-path/-/typesafe-path-0.2.2.tgz", + "integrity": "sha512-OJabfkAg1WLZSqJAJ0Z6Sdt3utnbzr/jh+NAHoyWHJe8CMSy79Gm085094M9nvTPy22KzTVn5Zq5mbapCI/hPA==", + "dev": true, + "license": "MIT" + }, + "node_modules/typescript": { + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/typescript-auto-import-cache": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/typescript-auto-import-cache/-/typescript-auto-import-cache-0.3.6.tgz", + "integrity": "sha512-RpuHXrknHdVdK7wv/8ug3Fr0WNsNi5l5aB8MYYuXhq2UH5lnEB1htJ1smhtD5VeCsGr2p8mUDtd83LCQDFVgjQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "semver": "^7.3.8" + } + }, + "node_modules/typescript-auto-import-cache/node_modules/semver": { + "version": "7.8.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.1.tgz", + "integrity": "sha512-rkVq3IXh+4FDGch+KwzX3aV9W3kO54GyEgpvBzSyctDA6Xtd7RJQV1xmXbeQp5v7+VzLOfVqiutSE6GICgPFvg==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/ua-is-frozen": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/ua-is-frozen/-/ua-is-frozen-0.1.2.tgz", + "integrity": "sha512-RwKDW2p3iyWn4UbaxpP2+VxwqXh0jpvdxsYpZ5j/MLLiQOfbsV5shpgQiw93+KMYQPcteeMQ289MaAFzs3G9pw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/faisalman" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/ua-parser-js" + }, + { + "type": "paypal", + "url": "https://paypal.me/faisalman" + } + ], + "license": "MIT" + }, + "node_modules/ua-parser-js": { + "version": "2.0.10", + "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-2.0.10.tgz", + "integrity": "sha512-t+3Ktbq0Ies2vaSezfOaWiolH4OigQIO1dk+1xDpOydB1COVPocVYOrEV5rqZ0kFY9XYG1v9LutCyMgYBpABcw==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/ua-parser-js" + }, + { + "type": "paypal", + "url": "https://paypal.me/faisalman" + }, + { + "type": "github", + "url": "https://github.com/sponsors/faisalman" + } + ], + "license": "AGPL-3.0-or-later", + "dependencies": { + "detect-europe-js": "^0.1.2", + "is-standalone-pwa": "^0.1.1", + "ua-is-frozen": "^0.1.2" + }, + "bin": { + "ua-parser-js": "script/cli.js" + }, + "engines": { + "node": "*" + } + }, + "node_modules/ufo": { + "version": "1.6.4", + "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.6.4.tgz", + "integrity": "sha512-JFNbkD1Svwe0KvGi8GOeLcP4kAWQ609twvCdcHxq1oSL8svv39ZuSvajcD8B+5D0eL4+s1Is2D/O6KN3qcTeRA==", + "license": "MIT" + }, + "node_modules/ultrahtml": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/ultrahtml/-/ultrahtml-1.6.0.tgz", + "integrity": "sha512-R9fBn90VTJrqqLDwyMph+HGne8eqY1iPfYhPzZrvKpIfwkWZbcYlfpsb8B9dTvBfpy1/hqAD7Wi8EKfP9e8zdw==", + "license": "MIT" + }, + "node_modules/unbox-primitive": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.1.0.tgz", + "integrity": "sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "has-bigints": "^1.0.2", + "has-symbols": "^1.1.0", + "which-boxed-primitive": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/uncrypto": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/uncrypto/-/uncrypto-0.1.3.tgz", + "integrity": "sha512-Ql87qFHB3s/De2ClA9e0gsnS6zXG27SkTiSJwjCc9MebbfapQfuPzumMIUMi38ezPZVNFcHI9sUIepeQfw8J8Q==", + "license": "MIT" + }, + "node_modules/undici": { + "version": "7.14.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-7.14.0.tgz", + "integrity": "sha512-Vqs8HTzjpQXZeXdpsfChQTlafcMQaaIwnGwLam1wudSSjlJeQ3bw1j+TLPePgrCnCpUXx7Ba5Pdpf5OBih62NQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=20.18.1" + } + }, + "node_modules/unenv": { + "version": "2.0.0-rc.24", + "resolved": "https://registry.npmjs.org/unenv/-/unenv-2.0.0-rc.24.tgz", + "integrity": "sha512-i7qRCmY42zmCwnYlh9H2SvLEypEFGye5iRmEMKjcGi7zk9UquigRjFtTLz0TYqr0ZGLZhaMHl/foy1bZR+Cwlw==", + "dev": true, + "license": "MIT", + "dependencies": { + "pathe": "^2.0.3" + } + }, + "node_modules/unified": { + "version": "11.0.5", + "resolved": "https://registry.npmjs.org/unified/-/unified-11.0.5.tgz", + "integrity": "sha512-xKvGhPWw3k84Qjh8bI3ZeJjqnyadK+GEFtazSfZv/rKeTkTjOJho6mFqh2SM96iIcZokxiOpg78GazTSg8+KHA==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "bail": "^2.0.0", + "devlop": "^1.0.0", + "extend": "^3.0.0", + "is-plain-obj": "^4.0.0", + "trough": "^2.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unifont": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/unifont/-/unifont-0.7.4.tgz", + "integrity": "sha512-oHeis4/xl42HUIeHuNZRGEvxj5AaIKR+bHPNegRq5LV1gdc3jundpONbjglKpihmJf+dswygdMJn3eftGIMemg==", + "license": "MIT", + "dependencies": { + "css-tree": "^3.1.0", + "ofetch": "^1.5.1", + "ohash": "^2.0.11" + } + }, + "node_modules/unique-filename": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz", + "integrity": "sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "unique-slug": "^2.0.0" + } + }, + "node_modules/unique-slug": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.2.tgz", + "integrity": "sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w==", + "dev": true, + "license": "ISC", + "dependencies": { + "imurmurhash": "^0.1.4" + } + }, + "node_modules/unist-util-find-after": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/unist-util-find-after/-/unist-util-find-after-5.0.0.tgz", + "integrity": "sha512-amQa0Ep2m6hE2g72AugUItjbuM8X8cGQnFoHk0pGfrFeT9GZhzN5SW8nRsiGKK7Aif4CrACPENkA6P/Lw6fHGQ==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-is": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.1.tgz", + "integrity": "sha512-LsiILbtBETkDz8I9p1dQ0uyRUWuaQzd/cuEeS1hoRSyW5E5XGmTzlwY1OrNzzakGowI9Dr/I8HVaw4hTtnxy8g==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-modify-children": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/unist-util-modify-children/-/unist-util-modify-children-4.0.0.tgz", + "integrity": "sha512-+tdN5fGNddvsQdIzUF3Xx82CU9sMM+fA0dLgR9vOmT0oPT2jH+P1nd5lSqfCfXAw+93NhcXNY2qqvTUtE4cQkw==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "array-iterate": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-position": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/unist-util-position/-/unist-util-position-5.0.0.tgz", + "integrity": "sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-remove-position": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/unist-util-remove-position/-/unist-util-remove-position-5.0.0.tgz", + "integrity": "sha512-Hp5Kh3wLxv0PHj9m2yZhhLt58KzPtEYKQQ4yxfYFEO7EvHwzyDYnduhHnY1mDxoqr7VUwVuHXk9RXKIiYS1N8Q==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-visit": "^5.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-stringify-position": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-4.0.0.tgz", + "integrity": "sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-visit": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-5.1.0.tgz", + "integrity": "sha512-m+vIdyeCOpdr/QeQCu2EzxX/ohgS8KbnPDgFni4dQsfSCtpz8UqDyY5GjRru8PDKuYn7Fq19j1CQ+nJSsGKOzg==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0", + "unist-util-visit-parents": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-visit-children": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/unist-util-visit-children/-/unist-util-visit-children-3.0.0.tgz", + "integrity": "sha512-RgmdTfSBOg04sdPcpTSD1jzoNBjt9a80/ZCzp5cI9n1qPzLZWF9YdvWGN2zmTumP1HWhXKdUWexjy/Wy/lJ7tA==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-visit-parents": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.0.2.tgz", + "integrity": "sha512-goh1s1TBrqSqukSc8wrjwWhL0hiJxgA8m4kFxGlQ+8FYQ3C/m11FcTs4YYem7V664AhHVvgoQLk890Ssdsr2IQ==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unstorage": { + "version": "1.17.5", + "resolved": "https://registry.npmjs.org/unstorage/-/unstorage-1.17.5.tgz", + "integrity": "sha512-0i3iqvRfx29hkNntHyQvJTpf5W9dQ9ZadSoRU8+xVlhVtT7jAX57fazYO9EHvcRCfBCyi5YRya7XCDOsbTgkPg==", + "license": "MIT", + "dependencies": { + "anymatch": "^3.1.3", + "chokidar": "^5.0.0", + "destr": "^2.0.5", + "h3": "^1.15.10", + "lru-cache": "^11.2.7", + "node-fetch-native": "^1.6.7", + "ofetch": "^1.5.1", + "ufo": "^1.6.3" + }, + "peerDependencies": { + "@azure/app-configuration": "^1.8.0", + "@azure/cosmos": "^4.2.0", + "@azure/data-tables": "^13.3.0", + "@azure/identity": "^4.6.0", + "@azure/keyvault-secrets": "^4.9.0", + "@azure/storage-blob": "^12.26.0", + "@capacitor/preferences": "^6 || ^7 || ^8", + "@deno/kv": ">=0.9.0", + "@netlify/blobs": "^6.5.0 || ^7.0.0 || ^8.1.0 || ^9.0.0 || ^10.0.0", + "@planetscale/database": "^1.19.0", + "@upstash/redis": "^1.34.3", + "@vercel/blob": ">=0.27.1", + "@vercel/functions": "^2.2.12 || ^3.0.0", + "@vercel/kv": "^1 || ^2 || ^3", + "aws4fetch": "^1.0.20", + "db0": ">=0.2.1", + "idb-keyval": "^6.2.1", + "ioredis": "^5.4.2", + "uploadthing": "^7.4.4" + }, + "peerDependenciesMeta": { + "@azure/app-configuration": { + "optional": true + }, + "@azure/cosmos": { + "optional": true + }, + "@azure/data-tables": { + "optional": true + }, + "@azure/identity": { + "optional": true + }, + "@azure/keyvault-secrets": { + "optional": true + }, + "@azure/storage-blob": { + "optional": true + }, + "@capacitor/preferences": { + "optional": true + }, + "@deno/kv": { + "optional": true + }, + "@netlify/blobs": { + "optional": true + }, + "@planetscale/database": { + "optional": true + }, + "@upstash/redis": { + "optional": true + }, + "@vercel/blob": { + "optional": true + }, + "@vercel/functions": { + "optional": true + }, + "@vercel/kv": { + "optional": true + }, + "aws4fetch": { + "optional": true + }, + "db0": { + "optional": true + }, + "idb-keyval": { + "optional": true + }, + "ioredis": { + "optional": true + }, + "uploadthing": { + "optional": true + } + } + }, + "node_modules/unstorage/node_modules/chokidar": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-5.0.0.tgz", + "integrity": "sha512-TQMmc3w+5AxjpL8iIiwebF73dRDF4fBIieAqGn9RGCWaEVwQ6Fb2cGe31Yns0RRIzii5goJ1Y7xbMwo1TxMplw==", + "license": "MIT", + "dependencies": { + "readdirp": "^5.0.0" + }, + "engines": { + "node": ">= 20.19.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/unstorage/node_modules/lru-cache": { + "version": "11.5.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.5.1.tgz", + "integrity": "sha512-RPimw/7aMdv2oqRrxKwvZXcPfwBrn/JZ2xYcY9Hus/6LaS3VOAKVWKWgNLCFSiOm1ESXinjsDlidVU7JlnCN2A==", + "license": "BlueOak-1.0.0", + "engines": { + "node": "20 || >=22" + } + }, + "node_modules/unstorage/node_modules/readdirp": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-5.0.0.tgz", + "integrity": "sha512-9u/XQ1pvrQtYyMpZe7DXKv2p5CNvyVwzUB6uhLAnQwHMSgKMBR62lc7AHljaeteeHXn11XTAaLLUVZYVZyuRBQ==", + "license": "MIT", + "engines": { + "node": ">= 20.19.0" + }, + "funding": { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz", + "integrity": "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==", + "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/use-callback-ref": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/use-callback-ref/-/use-callback-ref-1.3.3.tgz", + "integrity": "sha512-jQL3lRnocaFtu3V00JToYz/4QkNWswxijDaCVNZRiRTO3HQDLsdu1ZtmIUvV4yPp+rvWm5j0y0TG/S61cuijTg==", + "license": "MIT", + "dependencies": { + "tslib": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/use-sidecar": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/use-sidecar/-/use-sidecar-1.1.3.tgz", + "integrity": "sha512-Fedw0aZvkhynoPYlA5WXrMCAMm+nSWdZt6lzJQ7Ok8S6Q+VsHmHpRWndVRJ8Be0ZbkfPc5LRYH+5XrzXcEeLRQ==", + "license": "MIT", + "dependencies": { + "detect-node-es": "^1.1.0", + "tslib": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/use-sync-external-store": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.6.0.tgz", + "integrity": "sha512-Pp6GSwGP/NrPIrxVFAIkOQeyw8lFenOHijQWkUTrDvrF4ALqylP2C/KCkeS9dpUM3KvYRQhna5vt7IL95+ZQ9w==", + "license": "MIT", + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "dev": true, + "license": "MIT" + }, + "node_modules/uuid": { + "version": "11.1.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-11.1.1.tgz", + "integrity": "sha512-vIYxrBCC/N/K+Js3qSN88go7kIfNPssr/hHCesKCQNAjmgvYS2oqr69kIufEG+O4+PfezOH4EbIeHCfFov8ZgQ==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "license": "MIT", + "bin": { + "uuid": "dist/esm/bin/uuid" + } + }, + "node_modules/vfile": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/vfile/-/vfile-6.0.3.tgz", + "integrity": "sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/vfile-location": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/vfile-location/-/vfile-location-5.0.3.tgz", + "integrity": "sha512-5yXvWDEgqeiYiBe1lbxYF7UMAIm/IcopxMHrMQDq3nvKcjPKIhZklUKL+AE7J7uApI4kwe2snsK+eI6UTj9EHg==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/vfile-message": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-4.0.3.tgz", + "integrity": "sha512-QTHzsGd1EhbZs4AsQ20JX1rC3cOlt/IWJruk893DfLRr57lcnOeMaWG4K0JrRta4mIJZKth2Au3mM3u03/JWKw==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-stringify-position": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/vite": { + "version": "6.4.3", + "resolved": "https://registry.npmjs.org/vite/-/vite-6.4.3.tgz", + "integrity": "sha512-NTKlcQjlAK7MlQoyb6LgaqHc8sso/pVyUJYWMws3jg21uTJw/LddqIFPcPqP6PzpgbIcZyKI85sFE4HBrQDA8A==", + "license": "MIT", + "dependencies": { + "esbuild": "^0.25.0", + "fdir": "^6.4.4", + "picomatch": "^4.0.2", + "postcss": "^8.5.3", + "rollup": "^4.34.9", + "tinyglobby": "^0.2.13" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^18.0.0 || ^20.0.0 || >=22.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 || >=22.0.0", + "jiti": ">=1.21.0", + "less": "*", + "lightningcss": "^1.21.0", + "sass": "*", + "sass-embedded": "*", + "stylus": "*", + "sugarss": "*", + "terser": "^5.16.0", + "tsx": "^4.8.1", + "yaml": "^2.4.2" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "jiti": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + }, + "tsx": { + "optional": true + }, + "yaml": { + "optional": true + } + } + }, + "node_modules/vite/node_modules/@esbuild/aix-ppc64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.12.tgz", + "integrity": "sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA==", + "cpu": [ + "ppc64" + ], + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/android-arm": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.12.tgz", + "integrity": "sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/android-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.12.tgz", + "integrity": "sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/android-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.12.tgz", + "integrity": "sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/darwin-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.12.tgz", + "integrity": "sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/darwin-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.12.tgz", + "integrity": "sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/freebsd-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.12.tgz", + "integrity": "sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/freebsd-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.12.tgz", + "integrity": "sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-arm": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.12.tgz", + "integrity": "sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.12.tgz", + "integrity": "sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-ia32": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.12.tgz", + "integrity": "sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA==", + "cpu": [ + "ia32" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-loong64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.12.tgz", + "integrity": "sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng==", + "cpu": [ + "loong64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-mips64el": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.12.tgz", + "integrity": "sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw==", + "cpu": [ + "mips64el" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-ppc64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.12.tgz", + "integrity": "sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA==", + "cpu": [ + "ppc64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-riscv64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.12.tgz", + "integrity": "sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w==", + "cpu": [ + "riscv64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-s390x": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.12.tgz", + "integrity": "sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg==", + "cpu": [ + "s390x" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.12.tgz", + "integrity": "sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/netbsd-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.12.tgz", + "integrity": "sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/netbsd-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.12.tgz", + "integrity": "sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/openbsd-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.12.tgz", + "integrity": "sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/openbsd-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.12.tgz", + "integrity": "sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/openharmony-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.12.tgz", + "integrity": "sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/sunos-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.12.tgz", + "integrity": "sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/win32-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.12.tgz", + "integrity": "sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/win32-ia32": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.12.tgz", + "integrity": "sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ==", + "cpu": [ + "ia32" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/win32-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.12.tgz", + "integrity": "sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/esbuild": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.12.tgz", + "integrity": "sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg==", + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.25.12", + "@esbuild/android-arm": "0.25.12", + "@esbuild/android-arm64": "0.25.12", + "@esbuild/android-x64": "0.25.12", + "@esbuild/darwin-arm64": "0.25.12", + "@esbuild/darwin-x64": "0.25.12", + "@esbuild/freebsd-arm64": "0.25.12", + "@esbuild/freebsd-x64": "0.25.12", + "@esbuild/linux-arm": "0.25.12", + "@esbuild/linux-arm64": "0.25.12", + "@esbuild/linux-ia32": "0.25.12", + "@esbuild/linux-loong64": "0.25.12", + "@esbuild/linux-mips64el": "0.25.12", + "@esbuild/linux-ppc64": "0.25.12", + "@esbuild/linux-riscv64": "0.25.12", + "@esbuild/linux-s390x": "0.25.12", + "@esbuild/linux-x64": "0.25.12", + "@esbuild/netbsd-arm64": "0.25.12", + "@esbuild/netbsd-x64": "0.25.12", + "@esbuild/openbsd-arm64": "0.25.12", + "@esbuild/openbsd-x64": "0.25.12", + "@esbuild/openharmony-arm64": "0.25.12", + "@esbuild/sunos-x64": "0.25.12", + "@esbuild/win32-arm64": "0.25.12", + "@esbuild/win32-ia32": "0.25.12", + "@esbuild/win32-x64": "0.25.12" + } + }, + "node_modules/vitefu": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/vitefu/-/vitefu-1.1.3.tgz", + "integrity": "sha512-ub4okH7Z5KLjb6hDyjqrGXqWtWvoYdU3IGm/NorpgHncKoLTCfRIbvlhBm7r0YstIaQRYlp4yEbFqDcKSzXSSg==", + "license": "MIT", + "workspaces": [ + "tests/deps/*", + "tests/projects/*", + "tests/projects/workspace/packages/*" + ], + "peerDependencies": { + "vite": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "vite": { + "optional": true + } + } + }, + "node_modules/void-elements": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/void-elements/-/void-elements-3.1.0.tgz", + "integrity": "sha512-Dhxzh5HZuiHQhbvTW9AMetFfBHDMYpo23Uo9btPXgdYP+3T5S+p+jgNy7spra+veYhBP2dCSgxR/i2Y02h5/6w==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/volar-service-css": { + "version": "0.0.70", + "resolved": "https://registry.npmjs.org/volar-service-css/-/volar-service-css-0.0.70.tgz", + "integrity": "sha512-K1qyOvBpE3rzdAv3e4/6Rv5yizrYPy5R/ne3IWCAzLBuMO4qBMV3kSqWzj6KUVe6S0AnN6wxF7cRkiaKfYMYJw==", + "dev": true, + "license": "MIT", + "dependencies": { + "vscode-css-languageservice": "^6.3.0", + "vscode-languageserver-textdocument": "^1.0.11", + "vscode-uri": "^3.0.8" + }, + "peerDependencies": { + "@volar/language-service": "~2.4.0" + }, + "peerDependenciesMeta": { + "@volar/language-service": { + "optional": true + } + } + }, + "node_modules/volar-service-emmet": { + "version": "0.0.70", + "resolved": "https://registry.npmjs.org/volar-service-emmet/-/volar-service-emmet-0.0.70.tgz", + "integrity": "sha512-xi5bC4m/VyE3zy/n2CXspKeDZs3qA41tHLTw275/7dNWM/RqE2z3BnDICQybHIVp/6G1iOQj5c1qXMgQC08TNg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@emmetio/css-parser": "^0.4.1", + "@emmetio/html-matcher": "^1.3.0", + "@vscode/emmet-helper": "^2.9.3", + "vscode-uri": "^3.0.8" + }, + "peerDependencies": { + "@volar/language-service": "~2.4.0" + }, + "peerDependenciesMeta": { + "@volar/language-service": { + "optional": true + } + } + }, + "node_modules/volar-service-html": { + "version": "0.0.70", + "resolved": "https://registry.npmjs.org/volar-service-html/-/volar-service-html-0.0.70.tgz", + "integrity": "sha512-eR6vCgMdmYAo4n+gcT7DSyBQbwB8S3HZZvSagTf0sxNaD4WppMCFfpqWnkrlGStPKMZvMiejRRVmqsX9dYcTvQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "vscode-html-languageservice": "^5.3.0", + "vscode-languageserver-textdocument": "^1.0.11", + "vscode-uri": "^3.0.8" + }, + "peerDependencies": { + "@volar/language-service": "~2.4.0" + }, + "peerDependenciesMeta": { + "@volar/language-service": { + "optional": true + } + } + }, + "node_modules/volar-service-prettier": { + "version": "0.0.70", + "resolved": "https://registry.npmjs.org/volar-service-prettier/-/volar-service-prettier-0.0.70.tgz", + "integrity": "sha512-Z6BCFSpGVCd8BPAsZ785Kce1BGlWd5ODqmqZGVuB14MJvrR4+CYz6cDy4F+igmE1gMifqfvMhdgT8Aud4M5ngg==", + "dev": true, + "license": "MIT", + "dependencies": { + "vscode-uri": "^3.0.8" + }, + "peerDependencies": { + "@volar/language-service": "~2.4.0", + "prettier": "^2.2 || ^3.0" + }, + "peerDependenciesMeta": { + "@volar/language-service": { + "optional": true + }, + "prettier": { + "optional": true + } + } + }, + "node_modules/volar-service-typescript": { + "version": "0.0.70", + "resolved": "https://registry.npmjs.org/volar-service-typescript/-/volar-service-typescript-0.0.70.tgz", + "integrity": "sha512-l46Bx4cokkUedTd74ojO5H/zqHZJ8SUuyZ0IB8JN4jfRqUM3bQFBHoOwlZCyZmOeO0A3RQNkMnFclxO4c++gsg==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-browserify": "^1.0.1", + "semver": "^7.6.2", + "typescript-auto-import-cache": "^0.3.5", + "vscode-languageserver-textdocument": "^1.0.11", + "vscode-nls": "^5.2.0", + "vscode-uri": "^3.0.8" + }, + "peerDependencies": { + "@volar/language-service": "~2.4.0" + }, + "peerDependenciesMeta": { + "@volar/language-service": { + "optional": true + } + } + }, + "node_modules/volar-service-typescript-twoslash-queries": { + "version": "0.0.70", + "resolved": "https://registry.npmjs.org/volar-service-typescript-twoslash-queries/-/volar-service-typescript-twoslash-queries-0.0.70.tgz", + "integrity": "sha512-IdD13Z9N2Bu8EM6CM0fDV1E69olEYGHDU25X51YXmq8Y0CmJ2LNj6gOiBJgpS5JGUqFzECVhMNBW7R0sPdRTMQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "vscode-uri": "^3.0.8" + }, + "peerDependencies": { + "@volar/language-service": "~2.4.0" + }, + "peerDependenciesMeta": { + "@volar/language-service": { + "optional": true + } + } + }, + "node_modules/volar-service-typescript/node_modules/semver": { + "version": "7.8.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.1.tgz", + "integrity": "sha512-rkVq3IXh+4FDGch+KwzX3aV9W3kO54GyEgpvBzSyctDA6Xtd7RJQV1xmXbeQp5v7+VzLOfVqiutSE6GICgPFvg==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/volar-service-yaml": { + "version": "0.0.70", + "resolved": "https://registry.npmjs.org/volar-service-yaml/-/volar-service-yaml-0.0.70.tgz", + "integrity": "sha512-0c8bXDBeoATF9F6iPIlOuYTuZAC4c+yi0siQo920u7eiBJk8oQmUmg9cDUbR4+Gl++bvGP4plj3fErbJuPqdcQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "vscode-uri": "^3.0.8", + "yaml-language-server": "~1.20.0" + }, + "peerDependencies": { + "@volar/language-service": "~2.4.0" + }, + "peerDependenciesMeta": { + "@volar/language-service": { + "optional": true + } + } + }, + "node_modules/vscode-css-languageservice": { + "version": "6.3.10", + "resolved": "https://registry.npmjs.org/vscode-css-languageservice/-/vscode-css-languageservice-6.3.10.tgz", + "integrity": "sha512-eq5N9Er3fC4vA9zd9EFhyBG90wtCCuXgRSpAndaOgXMh1Wgep5lBgRIeDgjZBW9pa+332yC9+49cZMW8jcL3MA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vscode/l10n": "^0.0.18", + "vscode-languageserver-textdocument": "^1.0.12", + "vscode-languageserver-types": "3.17.5", + "vscode-uri": "^3.1.0" + } + }, + "node_modules/vscode-html-languageservice": { + "version": "5.6.2", + "resolved": "https://registry.npmjs.org/vscode-html-languageservice/-/vscode-html-languageservice-5.6.2.tgz", + "integrity": "sha512-ulCrSnFnfQ16YzvwnYUgEbUEl/ZG7u2eV27YhvLObSHKkb8fw1Z9cgsnUwjTEeDIdJDoTDTDpxuhQwoenoLNMg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vscode/l10n": "^0.0.18", + "vscode-languageserver-textdocument": "^1.0.12", + "vscode-languageserver-types": "^3.17.5", + "vscode-uri": "^3.1.0" + } + }, + "node_modules/vscode-json-languageservice": { + "version": "4.1.8", + "resolved": "https://registry.npmjs.org/vscode-json-languageservice/-/vscode-json-languageservice-4.1.8.tgz", + "integrity": "sha512-0vSpg6Xd9hfV+eZAaYN63xVVMOTmJ4GgHxXnkLCh+9RsQBkWKIghzLhW2B9ebfG+LQQg8uLtsQ2aUKjTgE+QOg==", + "dev": true, + "license": "MIT", + "dependencies": { + "jsonc-parser": "^3.0.0", + "vscode-languageserver-textdocument": "^1.0.1", + "vscode-languageserver-types": "^3.16.0", + "vscode-nls": "^5.0.0", + "vscode-uri": "^3.0.2" + }, + "engines": { + "npm": ">=7.0.0" + } + }, + "node_modules/vscode-json-languageservice/node_modules/jsonc-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.3.1.tgz", + "integrity": "sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/vscode-jsonrpc": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-8.2.0.tgz", + "integrity": "sha512-C+r0eKJUIfiDIfwJhria30+TYWPtuHJXHtI7J0YlOmKAo7ogxP20T0zxB7HZQIFhIyvoBPwWskjxrvAtfjyZfA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/vscode-languageserver": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/vscode-languageserver/-/vscode-languageserver-9.0.1.tgz", + "integrity": "sha512-woByF3PDpkHFUreUa7Hos7+pUWdeWMXRd26+ZX2A8cFx6v/JPTtd4/uN0/jB6XQHYaOlHbio03NTHCqrgG5n7g==", + "dev": true, + "license": "MIT", + "dependencies": { + "vscode-languageserver-protocol": "3.17.5" + }, + "bin": { + "installServerIntoExtension": "bin/installServerIntoExtension" + } + }, + "node_modules/vscode-languageserver-protocol": { + "version": "3.17.5", + "resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.17.5.tgz", + "integrity": "sha512-mb1bvRJN8SVznADSGWM9u/b07H7Ecg0I3OgXDuLdn307rl/J3A9YD6/eYOssqhecL27hK1IPZAsaqh00i/Jljg==", + "dev": true, + "license": "MIT", + "dependencies": { + "vscode-jsonrpc": "8.2.0", + "vscode-languageserver-types": "3.17.5" + } + }, + "node_modules/vscode-languageserver-textdocument": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/vscode-languageserver-textdocument/-/vscode-languageserver-textdocument-1.0.12.tgz", + "integrity": "sha512-cxWNPesCnQCcMPeenjKKsOCKQZ/L6Tv19DTRIGuLWe32lyzWhihGVJ/rcckZXJxfdKCFvRLS3fpBIsV/ZGX4zA==", + "dev": true, + "license": "MIT" + }, + "node_modules/vscode-languageserver-types": { + "version": "3.17.5", + "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.17.5.tgz", + "integrity": "sha512-Ld1VelNuX9pdF39h2Hgaeb5hEZM2Z3jUrrMgWQAu82jMtZp7p3vJT3BzToKtZI7NgQssZje5o0zryOrhQvzQAg==", + "dev": true, + "license": "MIT" + }, + "node_modules/vscode-nls": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/vscode-nls/-/vscode-nls-5.2.0.tgz", + "integrity": "sha512-RAaHx7B14ZU04EU31pT+rKz2/zSl7xMsfIZuo8pd+KZO6PXtQmpevpq3vxvWNcrGbdmhM/rr5Uw5Mz+NBfhVng==", + "dev": true, + "license": "MIT" + }, + "node_modules/vscode-uri": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-3.1.0.tgz", + "integrity": "sha512-/BpdSx+yCQGnCvecbyXdxHDkuk55/G3xwnC0GqY4gmQ3j+A+g8kzzgB4Nk/SINjqn6+waqw3EgbVF2QKExkRxQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/warning": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/warning/-/warning-4.0.3.tgz", + "integrity": "sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w==", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.0.0" + } + }, + "node_modules/web-namespaces": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/web-namespaces/-/web-namespaces-2.0.1.tgz", + "integrity": "sha512-bKr1DkiNa2krS7qxNtdrtHAmzuYGFQLiQ13TsorsdT6ULTkPLKuu5+GsFpDlg6JFjUTwX2DyhMPG2be8uPrqsQ==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", + "license": "BSD-2-Clause" + }, + "node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "license": "MIT", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/which-boxed-primitive": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.1.1.tgz", + "integrity": "sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==", + "license": "MIT", + "dependencies": { + "is-bigint": "^1.1.0", + "is-boolean-object": "^1.2.1", + "is-number-object": "^1.1.1", + "is-string": "^1.1.1", + "is-symbol": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-builtin-type": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.2.1.tgz", + "integrity": "sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "function.prototype.name": "^1.1.6", + "has-tostringtag": "^1.0.2", + "is-async-function": "^2.0.0", + "is-date-object": "^1.1.0", + "is-finalizationregistry": "^1.1.0", + "is-generator-function": "^1.0.10", + "is-regex": "^1.2.1", + "is-weakref": "^1.0.2", + "isarray": "^2.0.5", + "which-boxed-primitive": "^1.1.0", + "which-collection": "^1.0.2", + "which-typed-array": "^1.1.16" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-collection": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.2.tgz", + "integrity": "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==", + "license": "MIT", + "dependencies": { + "is-map": "^2.0.3", + "is-set": "^2.0.3", + "is-weakmap": "^2.0.2", + "is-weakset": "^2.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-pm-runs": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/which-pm-runs/-/which-pm-runs-1.1.0.tgz", + "integrity": "sha512-n1brCuqClxfFfq/Rb0ICg9giSZqCS+pLtccdag6C2HyufBrh3fBOiy9nb6ggRMvWOVH5GrdJskj5iGTZNxd7SA==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/which-typed-array": { + "version": "1.1.21", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.21.tgz", + "integrity": "sha512-zbRA8cVm6io/d5W8uIe2hblzN76/Wm3v/yiythQvr+dpBWeqhPSWIDNj4zOyHi4zKbMK6DN34Xsr9jPHJERAEw==", + "license": "MIT", + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.9", + "call-bound": "^1.0.4", + "for-each": "^0.3.5", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/wide-align": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", + "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^1.0.2 || 2 || 3 || 4" + } + }, + "node_modules/wide-align/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT" + }, + "node_modules/wide-align/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "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/widest-line": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-5.0.0.tgz", + "integrity": "sha512-c9bZp7b5YtRj2wOe6dlj32MK+Bx/M/d+9VB2SHM1OtsUHR0aV0tdP6DWh/iMt0kWi1t5g1Iudu6hQRNd1A4PVA==", + "license": "MIT", + "dependencies": { + "string-width": "^7.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/workerd": { + "version": "1.20260114.0", + "resolved": "https://registry.npmjs.org/workerd/-/workerd-1.20260114.0.tgz", + "integrity": "sha512-kTJ+jNdIllOzWuVA3NRQRvywP0T135zdCjAE2dAUY1BFbxM6fmMZV8BbskEoQ4hAODVQUfZQmyGctcwvVCKxFA==", + "dev": true, + "hasInstallScript": true, + "license": "Apache-2.0", + "bin": { + "workerd": "bin/workerd" + }, + "engines": { + "node": ">=16" + }, + "optionalDependencies": { + "@cloudflare/workerd-darwin-64": "1.20260114.0", + "@cloudflare/workerd-darwin-arm64": "1.20260114.0", + "@cloudflare/workerd-linux-64": "1.20260114.0", + "@cloudflare/workerd-linux-arm64": "1.20260114.0", + "@cloudflare/workerd-windows-64": "1.20260114.0" + } + }, + "node_modules/wrangler": { + "version": "4.59.2", + "resolved": "https://registry.npmjs.org/wrangler/-/wrangler-4.59.2.tgz", + "integrity": "sha512-Z4xn6jFZTaugcOKz42xvRAYKgkVUERHVbuCJ5+f+gK+R6k12L02unakPGOA0L0ejhUl16dqDjKe4tmL9sedHcw==", + "dev": true, + "license": "MIT OR Apache-2.0", + "dependencies": { + "@cloudflare/kv-asset-handler": "0.4.2", + "@cloudflare/unenv-preset": "2.10.0", + "blake3-wasm": "2.1.5", + "esbuild": "0.27.0", + "miniflare": "4.20260114.0", + "path-to-regexp": "6.3.0", + "unenv": "2.0.0-rc.24", + "workerd": "1.20260114.0" + }, + "bin": { + "wrangler": "bin/wrangler.js", + "wrangler2": "bin/wrangler.js" + }, + "engines": { + "node": ">=20.0.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + }, + "peerDependencies": { + "@cloudflare/workers-types": "^4.20260114.0" + }, + "peerDependenciesMeta": { + "@cloudflare/workers-types": { + "optional": true + } + } + }, + "node_modules/wrangler/node_modules/@esbuild/aix-ppc64": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.0.tgz", + "integrity": "sha512-KuZrd2hRjz01y5JK9mEBSD3Vj3mbCvemhT466rSuJYeE/hjuBrHfjjcjMdTm/sz7au+++sdbJZJmuBwQLuw68A==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/wrangler/node_modules/@esbuild/android-arm": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.27.0.tgz", + "integrity": "sha512-j67aezrPNYWJEOHUNLPj9maeJte7uSMM6gMoxfPC9hOg8N02JuQi/T7ewumf4tNvJadFkvLZMlAq73b9uwdMyQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/wrangler/node_modules/@esbuild/android-arm64": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.27.0.tgz", + "integrity": "sha512-CC3vt4+1xZrs97/PKDkl0yN7w8edvU2vZvAFGD16n9F0Cvniy5qvzRXjfO1l94efczkkQE6g1x0i73Qf5uthOQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/wrangler/node_modules/@esbuild/android-x64": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.27.0.tgz", + "integrity": "sha512-wurMkF1nmQajBO1+0CJmcN17U4BP6GqNSROP8t0X/Jiw2ltYGLHpEksp9MpoBqkrFR3kv2/te6Sha26k3+yZ9Q==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/wrangler/node_modules/@esbuild/darwin-arm64": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.27.0.tgz", + "integrity": "sha512-uJOQKYCcHhg07DL7i8MzjvS2LaP7W7Pn/7uA0B5S1EnqAirJtbyw4yC5jQ5qcFjHK9l6o/MX9QisBg12kNkdHg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/wrangler/node_modules/@esbuild/darwin-x64": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.27.0.tgz", + "integrity": "sha512-8mG6arH3yB/4ZXiEnXof5MK72dE6zM9cDvUcPtxhUZsDjESl9JipZYW60C3JGreKCEP+p8P/72r69m4AZGJd5g==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/wrangler/node_modules/@esbuild/freebsd-arm64": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.0.tgz", + "integrity": "sha512-9FHtyO988CwNMMOE3YIeci+UV+x5Zy8fI2qHNpsEtSF83YPBmE8UWmfYAQg6Ux7Gsmd4FejZqnEUZCMGaNQHQw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/wrangler/node_modules/@esbuild/freebsd-x64": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.27.0.tgz", + "integrity": "sha512-zCMeMXI4HS/tXvJz8vWGexpZj2YVtRAihHLk1imZj4efx1BQzN76YFeKqlDr3bUWI26wHwLWPd3rwh6pe4EV7g==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/wrangler/node_modules/@esbuild/linux-arm": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.27.0.tgz", + "integrity": "sha512-t76XLQDpxgmq2cNXKTVEB7O7YMb42atj2Re2Haf45HkaUpjM2J0UuJZDuaGbPbamzZ7bawyGFUkodL+zcE+jvQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/wrangler/node_modules/@esbuild/linux-arm64": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.27.0.tgz", + "integrity": "sha512-AS18v0V+vZiLJyi/4LphvBE+OIX682Pu7ZYNsdUHyUKSoRwdnOsMf6FDekwoAFKej14WAkOef3zAORJgAtXnlQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/wrangler/node_modules/@esbuild/linux-ia32": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.27.0.tgz", + "integrity": "sha512-Mz1jxqm/kfgKkc/KLHC5qIujMvnnarD9ra1cEcrs7qshTUSksPihGrWHVG5+osAIQ68577Zpww7SGapmzSt4Nw==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/wrangler/node_modules/@esbuild/linux-loong64": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.27.0.tgz", + "integrity": "sha512-QbEREjdJeIreIAbdG2hLU1yXm1uu+LTdzoq1KCo4G4pFOLlvIspBm36QrQOar9LFduavoWX2msNFAAAY9j4BDg==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/wrangler/node_modules/@esbuild/linux-mips64el": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.27.0.tgz", + "integrity": "sha512-sJz3zRNe4tO2wxvDpH/HYJilb6+2YJxo/ZNbVdtFiKDufzWq4JmKAiHy9iGoLjAV7r/W32VgaHGkk35cUXlNOg==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/wrangler/node_modules/@esbuild/linux-ppc64": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.27.0.tgz", + "integrity": "sha512-z9N10FBD0DCS2dmSABDBb5TLAyF1/ydVb+N4pi88T45efQ/w4ohr/F/QYCkxDPnkhkp6AIpIcQKQ8F0ANoA2JA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/wrangler/node_modules/@esbuild/linux-riscv64": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.27.0.tgz", + "integrity": "sha512-pQdyAIZ0BWIC5GyvVFn5awDiO14TkT/19FTmFcPdDec94KJ1uZcmFs21Fo8auMXzD4Tt+diXu1LW1gHus9fhFQ==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/wrangler/node_modules/@esbuild/linux-s390x": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.27.0.tgz", + "integrity": "sha512-hPlRWR4eIDDEci953RI1BLZitgi5uqcsjKMxwYfmi4LcwyWo2IcRP+lThVnKjNtk90pLS8nKdroXYOqW+QQH+w==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/wrangler/node_modules/@esbuild/linux-x64": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.27.0.tgz", + "integrity": "sha512-1hBWx4OUJE2cab++aVZ7pObD6s+DK4mPGpemtnAORBvb5l/g5xFGk0vc0PjSkrDs0XaXj9yyob3d14XqvnQ4gw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/wrangler/node_modules/@esbuild/netbsd-arm64": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.0.tgz", + "integrity": "sha512-6m0sfQfxfQfy1qRuecMkJlf1cIzTOgyaeXaiVaaki8/v+WB+U4hc6ik15ZW6TAllRlg/WuQXxWj1jx6C+dfy3w==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/wrangler/node_modules/@esbuild/netbsd-x64": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.27.0.tgz", + "integrity": "sha512-xbbOdfn06FtcJ9d0ShxxvSn2iUsGd/lgPIO2V3VZIPDbEaIj1/3nBBe1AwuEZKXVXkMmpr6LUAgMkLD/4D2PPA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/wrangler/node_modules/@esbuild/openbsd-arm64": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.0.tgz", + "integrity": "sha512-fWgqR8uNbCQ/GGv0yhzttj6sU/9Z5/Sv/VGU3F5OuXK6J6SlriONKrQ7tNlwBrJZXRYk5jUhuWvF7GYzGguBZQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/wrangler/node_modules/@esbuild/openbsd-x64": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.27.0.tgz", + "integrity": "sha512-aCwlRdSNMNxkGGqQajMUza6uXzR/U0dIl1QmLjPtRbLOx3Gy3otfFu/VjATy4yQzo9yFDGTxYDo1FfAD9oRD2A==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/wrangler/node_modules/@esbuild/openharmony-arm64": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.0.tgz", + "integrity": "sha512-nyvsBccxNAsNYz2jVFYwEGuRRomqZ149A39SHWk4hV0jWxKM0hjBPm3AmdxcbHiFLbBSwG6SbpIcUbXjgyECfA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/wrangler/node_modules/@esbuild/sunos-x64": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.27.0.tgz", + "integrity": "sha512-Q1KY1iJafM+UX6CFEL+F4HRTgygmEW568YMqDA5UV97AuZSm21b7SXIrRJDwXWPzr8MGr75fUZPV67FdtMHlHA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/wrangler/node_modules/@esbuild/win32-arm64": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.27.0.tgz", + "integrity": "sha512-W1eyGNi6d+8kOmZIwi/EDjrL9nxQIQ0MiGqe/AWc6+IaHloxHSGoeRgDRKHFISThLmsewZ5nHFvGFWdBYlgKPg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/wrangler/node_modules/@esbuild/win32-ia32": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.27.0.tgz", + "integrity": "sha512-30z1aKL9h22kQhilnYkORFYt+3wp7yZsHWus+wSKAJR8JtdfI76LJ4SBdMsCopTR3z/ORqVu5L1vtnHZWVj4cQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/wrangler/node_modules/@esbuild/win32-x64": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.27.0.tgz", + "integrity": "sha512-aIitBcjQeyOhMTImhLZmtxfdOcuNRpwlPNmlFKPcHQYPhEssw75Cl1TSXJXpMkzaua9FUetx/4OQKq7eJul5Cg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/wrangler/node_modules/esbuild": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.0.tgz", + "integrity": "sha512-jd0f4NHbD6cALCyGElNpGAOtWxSq46l9X/sWB0Nzd5er4Kz2YTm+Vl0qKFT9KUJvD8+fiO8AvoHhFvEatfVixA==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.27.0", + "@esbuild/android-arm": "0.27.0", + "@esbuild/android-arm64": "0.27.0", + "@esbuild/android-x64": "0.27.0", + "@esbuild/darwin-arm64": "0.27.0", + "@esbuild/darwin-x64": "0.27.0", + "@esbuild/freebsd-arm64": "0.27.0", + "@esbuild/freebsd-x64": "0.27.0", + "@esbuild/linux-arm": "0.27.0", + "@esbuild/linux-arm64": "0.27.0", + "@esbuild/linux-ia32": "0.27.0", + "@esbuild/linux-loong64": "0.27.0", + "@esbuild/linux-mips64el": "0.27.0", + "@esbuild/linux-ppc64": "0.27.0", + "@esbuild/linux-riscv64": "0.27.0", + "@esbuild/linux-s390x": "0.27.0", + "@esbuild/linux-x64": "0.27.0", + "@esbuild/netbsd-arm64": "0.27.0", + "@esbuild/netbsd-x64": "0.27.0", + "@esbuild/openbsd-arm64": "0.27.0", + "@esbuild/openbsd-x64": "0.27.0", + "@esbuild/openharmony-arm64": "0.27.0", + "@esbuild/sunos-x64": "0.27.0", + "@esbuild/win32-arm64": "0.27.0", + "@esbuild/win32-ia32": "0.27.0", + "@esbuild/win32-x64": "0.27.0" + } + }, + "node_modules/wrangler/node_modules/path-to-regexp": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.3.0.tgz", + "integrity": "sha512-Yhpw4T9C6hPpgPeA28us07OJeqZ5EzQTkbfwuhsUg0c237RomFoETJgmp2sa3F/41gfLE6G5cqcYwznmeEeOlQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/wrap-ansi": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.2.tgz", + "integrity": "sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.2.1", + "string-width": "^7.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-regex": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", + "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-styles": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", + "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/strip-ansi": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.2.0.tgz", + "integrity": "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.2.2" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/ws": { + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", + "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/xxhash-wasm": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/xxhash-wasm/-/xxhash-wasm-1.1.0.tgz", + "integrity": "sha512-147y/6YNh+tlp6nd/2pWq38i9h6mz/EuQ6njIrmW8D1BS5nCqs0P6DG+m6zTGnNz5I+uhZ0SHxBs9BsPrwcKDA==", + "license": "MIT" + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true, + "license": "ISC" + }, + "node_modules/yaml": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.9.0.tgz", + "integrity": "sha512-2AvhNX3mb8zd6Zy7INTtSpl1F15HW6Wnqj0srWlkKLcpYl/gMIMJiyuGq2KeI2YFxUPjdlB+3Lc10seMLtL4cA==", + "dev": true, + "license": "ISC", + "bin": { + "yaml": "bin.mjs" + }, + "engines": { + "node": ">= 14.6" + }, + "funding": { + "url": "https://github.com/sponsors/eemeli" + } + }, + "node_modules/yaml-language-server": { + "version": "1.20.0", + "resolved": "https://registry.npmjs.org/yaml-language-server/-/yaml-language-server-1.20.0.tgz", + "integrity": "sha512-qhjK/bzSRZ6HtTvgeFvjNPJGWdZ0+x5NREV/9XZWFjIGezew2b4r5JPy66IfOhd5OA7KeFwk1JfmEbnTvev0cA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vscode/l10n": "^0.0.18", + "ajv": "^8.17.1", + "ajv-draft-04": "^1.0.0", + "prettier": "^3.5.0", + "request-light": "^0.5.7", + "vscode-json-languageservice": "4.1.8", + "vscode-languageserver": "^9.0.0", + "vscode-languageserver-textdocument": "^1.0.1", + "vscode-languageserver-types": "^3.16.0", + "vscode-uri": "^3.0.2", + "yaml": "2.7.1" + }, + "bin": { + "yaml-language-server": "bin/yaml-language-server" + } + }, + "node_modules/yaml-language-server/node_modules/request-light": { + "version": "0.5.8", + "resolved": "https://registry.npmjs.org/request-light/-/request-light-0.5.8.tgz", + "integrity": "sha512-3Zjgh+8b5fhRJBQZoy+zbVKpAQGLyka0MPgW3zruTF4dFFJ8Fqcfu9YsAvi/rvdcaTeWG3MkbZv4WKxAn/84Lg==", + "dev": true, + "license": "MIT" + }, + "node_modules/yaml-language-server/node_modules/yaml": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.7.1.tgz", + "integrity": "sha512-10ULxpnOCQXxJvBgxsn9ptjq6uviG/htZKk9veJGhlqn3w/DxQ631zFF+nlQXLwmImeS5amR2dl2U8sg6U9jsQ==", + "dev": true, + "license": "ISC", + "bin": { + "yaml": "bin.mjs" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT" + }, + "node_modules/yargs/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "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/yocto-queue": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.2.2.tgz", + "integrity": "sha512-4LCcse/U2MHZ63HAJVE+v71o7yOdIe4cZ70Wpf8D/IyjDKYQLV5GD46B+hSTjJsvV5PztjvHoU580EftxjDZFQ==", + "license": "MIT", + "engines": { + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/yocto-spinner": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/yocto-spinner/-/yocto-spinner-0.2.3.tgz", + "integrity": "sha512-sqBChb33loEnkoXte1bLg45bEBsOP9N1kzQh5JZNKj/0rik4zAPTNSAVPj3uQAdc6slYJ0Ksc403G2XgxsJQFQ==", + "license": "MIT", + "dependencies": { + "yoctocolors": "^2.1.1" + }, + "engines": { + "node": ">=18.19" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/yoctocolors": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yoctocolors/-/yoctocolors-2.1.2.tgz", + "integrity": "sha512-CzhO+pFNo8ajLM2d2IW/R93ipy99LWjtwblvC1RsoSUMZgyLbYFr221TnSNT7GjGdYui6P459mw9JH/g/zW2ug==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/youch": { + "version": "4.1.0-beta.10", + "resolved": "https://registry.npmjs.org/youch/-/youch-4.1.0-beta.10.tgz", + "integrity": "sha512-rLfVLB4FgQneDr0dv1oddCVZmKjcJ6yX6mS4pU82Mq/Dt9a3cLZQ62pDBL4AUO+uVrCvtWz3ZFUL2HFAFJ/BXQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@poppinss/colors": "^4.1.5", + "@poppinss/dumper": "^0.6.4", + "@speed-highlight/core": "^1.2.7", + "cookie": "^1.0.2", + "youch-core": "^0.3.3" + } + }, + "node_modules/youch-core": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/youch-core/-/youch-core-0.3.3.tgz", + "integrity": "sha512-ho7XuGjLaJ2hWHoK8yFnsUGy2Y5uDpqSTq1FkHLK4/oqKtyUU1AFbOOxY4IpC9f0fTLjwYbslUz0Po5BpD1wrA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@poppinss/exception": "^1.2.2", + "error-stack-parser-es": "^1.0.5" + } + }, + "node_modules/zod": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/zod/-/zod-4.4.3.tgz", + "integrity": "sha512-ytENFjIJFl2UwYglde2jchW2Hwm4GJFLDiSXWdTrJQBIN9Fcyp7n4DhxJEiWNAJMV1/BqWfW/kkg71UDcHJyTQ==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + }, + "node_modules/zod-to-json-schema": { + "version": "3.25.2", + "resolved": "https://registry.npmjs.org/zod-to-json-schema/-/zod-to-json-schema-3.25.2.tgz", + "integrity": "sha512-O/PgfnpT1xKSDeQYSCfRI5Gy3hPf91mKVDuYLUHZJMiDFptvP41MSnWofm8dnCm0256ZNfZIM7DSzuSMAFnjHA==", + "license": "ISC", + "peerDependencies": { + "zod": "^3.25.28 || ^4" + } + }, + "node_modules/zod-to-ts": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/zod-to-ts/-/zod-to-ts-1.2.0.tgz", + "integrity": "sha512-x30XE43V+InwGpvTySRNz9kB7qFU8DlyEy7BsSTCHPH1R0QasMmHWZDCzYm6bVXtj/9NNJAZF3jW8rzFvH5OFA==", + "peerDependencies": { + "typescript": "^4.9.4 || ^5.0.2", + "zod": "^3" + } + }, + "node_modules/zustand": { + "version": "4.5.7", + "resolved": "https://registry.npmjs.org/zustand/-/zustand-4.5.7.tgz", + "integrity": "sha512-CHOUy7mu3lbD6o6LJLfllpjkzhHXSBlX8B9+qPddUsIfeF5S/UZ5q0kmCsnRqT1UHFQZchNFDDzMbQsuesHWlw==", + "license": "MIT", + "dependencies": { + "use-sync-external-store": "^1.2.2" + }, + "engines": { + "node": ">=12.7.0" + }, + "peerDependencies": { + "@types/react": ">=16.8", + "immer": ">=9.0.6", + "react": ">=16.8" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "immer": { + "optional": true + }, + "react": { + "optional": true + } + } + }, + "node_modules/zwitch": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/zwitch/-/zwitch-2.0.4.tgz", + "integrity": "sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + } + } +} diff --git a/CLI App - Calculator Form/package.json b/CLI App - Calculator Form/package.json new file mode 100644 index 0000000..a8c8f9e --- /dev/null +++ b/CLI App - Calculator Form/package.json @@ -0,0 +1,40 @@ +{ + "name": "calculator-form", + "type": "module", + "version": "1.0.0", + "scripts": { + "astro": "astro", + "wix": "wix", + "env": "wix env", + "dev": "wix dev --allowed-hosts all", + "build": "wix build", + "preview": "wix preview", + "release": "wix release", + "generate": "wix generate", + "skills": "wix skills", + "typecheck": "astro check" + }, + "dependencies": { + "@wix/astro": "^2.38.0", + "@wix/dashboard": "^1.3.43", + "@wix/design-system": "^1.154.0", + "@wix/editor-react-types": "^1.0.8", + "@wix/essentials": "^0.1.23", + "@wix/react-component-schema": "^1.0.0", + "@wix/react-component-utils": "^1.7.0", + "astro": "^5.8.0", + "classnames": "^2.3.2", + "typescript": "^5.8.3" + }, + "devDependencies": { + "@astrojs/check": "^0.9.9", + "@astrojs/cloudflare": "^12.5.3", + "@astrojs/react": "^4.3.0", + "@types/react": "^18.3.1", + "@types/react-dom": "^18.3.1", + "@wix/cli": "^1.1.135", + "@wix/sdk-types": "^1.0.0", + "react": "^18.3.1", + "react-dom": "^18.3.1" + } +} diff --git a/CLI App - Calculator Form/skills-lock.json b/CLI App - Calculator Form/skills-lock.json new file mode 100644 index 0000000..6d306ac --- /dev/null +++ b/CLI App - Calculator Form/skills-lock.json @@ -0,0 +1,85 @@ +{ + "version": 1, + "skills": { + "wds-docs": { + "source": "wix/skills", + "sourceType": "github", + "computedHash": "38b417a2053f1470cc59c7f2cbb84094ea25cf7fc4a043b5d17ae209597c6a6e" + }, + "wix-cli-app-validation": { + "source": "wix/skills", + "sourceType": "github", + "computedHash": "11293ccded09677de341632e3e0e90af12800743d9561d014d312cb457d06002" + }, + "wix-cli-backend-api": { + "source": "wix/skills", + "sourceType": "github", + "computedHash": "ce86e0ae16592adbec3244040407be7656c5922f23cb41ec58866389b28c3d09" + }, + "wix-cli-backend-event": { + "source": "wix/skills", + "sourceType": "github", + "computedHash": "eb79e531a08a1863d76196f8b7ad74aa6c8efec55cceed296dbe0e8b4c44fc10" + }, + "wix-cli-dashboard-modal": { + "source": "wix/skills", + "sourceType": "github", + "computedHash": "b72d39b9ffa8ad754e96895b5845d04e89d4d809264f909f82414b7fb30a7e39" + }, + "wix-cli-dashboard-page": { + "source": "wix/skills", + "sourceType": "github", + "computedHash": "0c79609b13baa66b1a1a616357cef4cf408eeba392d2875b278417a7aa74cd77" + }, + "wix-cli-dashboard-plugin": { + "source": "wix/skills", + "sourceType": "github", + "computedHash": "517afa10d5f6c1a84156ae095c5700aa30dfca91c227e882935b71798fd1e673" + }, + "wix-cli-data-collection": { + "source": "wix/skills", + "sourceType": "github", + "computedHash": "78d90e79bcbc2905dbe33f105315e66997651824b2813458c1bd724d6abee840" + }, + "wix-cli-embedded-script": { + "source": "wix/skills", + "sourceType": "github", + "computedHash": "0ba80a015ba8ecd20455f66d55a1c3fe0fae57ebda7fe3d9e3ed241685dc96f1" + }, + "wix-cli-extension-registration": { + "source": "wix/skills", + "sourceType": "github", + "computedHash": "43c968c7f2d18d1c895a4a8bad0f2bfabfd6dc683897eeba667e827175e92b91" + }, + "wix-cli-orchestrator": { + "source": "wix/skills", + "sourceType": "github", + "computedHash": "5b11f3efddeba3e31c69253218cd752ee18270262e9c5c76aaeb23718c4a100b" + }, + "wix-cli-service-plugin": { + "source": "wix/skills", + "sourceType": "github", + "computedHash": "04314647a1f4222bb124eb47e081225cb576648a4a5d738e62fcf016ae3e3dc9" + }, + "wix-cli-site-component": { + "source": "wix/skills", + "sourceType": "github", + "computedHash": "45f4c3f7f32db1e6c8111a124fb66e84c80dd85368680ffa15f32de22111640b" + }, + "wix-cli-site-plugin": { + "source": "wix/skills", + "sourceType": "github", + "computedHash": "1ce973912c78ba4acdf3bbe79f712a832f325faabd00d9ff4ee8cfce520ae538" + }, + "wix-cli-site-widget": { + "source": "wix/skills", + "sourceType": "github", + "computedHash": "bdd9de7a265f73d2b8f369b002298510c3b42645b4438d627b6880e0c839d5c2" + }, + "wix-stores-versioning": { + "source": "wix/skills", + "sourceType": "github", + "computedHash": "7ba09e79185a39881a34a7debfb08cce0c92c14eff671f3104670078845fafb1" + } + } +} diff --git a/CLI App - Calculator Form/src/env.d.ts b/CLI App - Calculator Form/src/env.d.ts new file mode 100644 index 0000000..e4d1c87 --- /dev/null +++ b/CLI App - Calculator Form/src/env.d.ts @@ -0,0 +1,4 @@ +/// <reference types="@wix/sdk-types/client" /> +/// <reference path="../.astro/types.d.ts" /> + +// NOTE: This file should not be edited. This is an auto-generated file. diff --git a/CLI App - Calculator Form/src/extensions.ts b/CLI App - Calculator Form/src/extensions.ts new file mode 100644 index 0000000..7dd2371 --- /dev/null +++ b/CLI App - Calculator Form/src/extensions.ts @@ -0,0 +1,7 @@ +import { app } from '@wix/astro/builders'; +import myPage from './extensions/dashboard/pages/my-page/my-page.extension.ts'; + +import myCalculatorForm from './extensions/site/components/my-calculator-form/my-calculator-form.extension.ts'; + +export default app() + .use(myPage).use(myCalculatorForm); diff --git a/CLI App - Calculator Form/src/extensions/dashboard/pages/my-page/my-page.extension.ts b/CLI App - Calculator Form/src/extensions/dashboard/pages/my-page/my-page.extension.ts new file mode 100644 index 0000000..669639c --- /dev/null +++ b/CLI App - Calculator Form/src/extensions/dashboard/pages/my-page/my-page.extension.ts @@ -0,0 +1,8 @@ +import { extensions } from '@wix/astro/builders'; + +export default extensions.dashboardPage({ + id: 'b42192c6-d73f-42e4-a42b-ea5d4436362e', + title: 'My Page', + routePath: '', + component: './extensions/dashboard/pages/my-page/my-page.tsx', +}); diff --git a/CLI App - Calculator Form/src/extensions/dashboard/pages/my-page/my-page.tsx b/CLI App - Calculator Form/src/extensions/dashboard/pages/my-page/my-page.tsx new file mode 100644 index 0000000..1b38489 --- /dev/null +++ b/CLI App - Calculator Form/src/extensions/dashboard/pages/my-page/my-page.tsx @@ -0,0 +1,25 @@ +import type { FC } from 'react'; +import { EmptyState, Page, WixDesignSystemProvider } from '@wix/design-system'; +import '@wix/design-system/styles.global.css'; + +const DashboardPage: FC = () => { + return ( + <WixDesignSystemProvider> + <Page> + <Page.Header + title="My Page" + subtitle="This is a subtitle for your page" + /> + <Page.Content> + <EmptyState + title="My Page" + subtitle="Edit src/extensions/dashboard/pages/my-page/my-page.tsx to change this text." + skin="page" + /> + </Page.Content> + </Page> + </WixDesignSystemProvider> + ); +}; + +export default DashboardPage; diff --git a/CLI App - Calculator Form/src/extensions/site/components/my-calculator-form/component.tsx b/CLI App - Calculator Form/src/extensions/site/components/my-calculator-form/component.tsx new file mode 100644 index 0000000..1738429 --- /dev/null +++ b/CLI App - Calculator Form/src/extensions/site/components/my-calculator-form/component.tsx @@ -0,0 +1,9 @@ +// This file wires your component with its default props and exports it for use by the extension. +// Please do not modify the structure or logic of this file + +import { withDefaults } from '@wix/react-component-utils'; +import Component, { defaultProps } from './my-calculator-form'; + +const MyCalculatorForm = withDefaults(Component, defaultProps); + +export default MyCalculatorForm; diff --git a/CLI App - Calculator Form/src/extensions/site/components/my-calculator-form/my-calculator-form.extension.ts b/CLI App - Calculator Form/src/extensions/site/components/my-calculator-form/my-calculator-form.extension.ts new file mode 100644 index 0000000..7f8ee10 --- /dev/null +++ b/CLI App - Calculator Form/src/extensions/site/components/my-calculator-form/my-calculator-form.extension.ts @@ -0,0 +1,37 @@ +import { extensions } from '@wix/astro/builders'; +import { LAYOUT } from '@wix/react-component-schema'; +import { withEditorElementDefaults } from '@wix/react-component-utils'; +import { editorElement } from './my-calculator-form.generated'; +import { defaultProps } from './my-calculator-form'; +import componentUrl from './component.tsx?url'; + +export default extensions.editorReactComponent({ + id: '29162caa-787b-4458-8b59-08711209cc8f', + type: '<CODE_IDENTIFIER>.CalculatorForm', + displayName: 'Calculator Form', + description: 'A calculator form that sums numeric inputs and displays the total.', + editorElement: withEditorElementDefaults({ + ...editorElement, + layout: { + resizeDirection: LAYOUT.RESIZE_DIRECTION.horizontalAndVertical, + contentResizeDirection: LAYOUT.CONTENT_RESIZE_DIRECTION.vertical, + }, + }, defaultProps), + installation: { + staticContainer: 'HOMEPAGE', + initialSize: { + width: { + sizingType: LAYOUT.SIZING_TYPE.pixels, + pixels: 360, + }, + height: { + sizingType: LAYOUT.SIZING_TYPE.content, + }, + }, + }, + resources: { + client: { + componentUrl, + }, + }, +}); diff --git a/CLI App - Calculator Form/src/extensions/site/components/my-calculator-form/my-calculator-form.generated.ts b/CLI App - Calculator Form/src/extensions/site/components/my-calculator-form/my-calculator-form.generated.ts new file mode 100644 index 0000000..188aae5 --- /dev/null +++ b/CLI App - Calculator Form/src/extensions/site/components/my-calculator-form/my-calculator-form.generated.ts @@ -0,0 +1,681 @@ +/** + * THIS FILE IS AUTO-GENERATED + * Changes to this file will be overwritten during the next build/sync. + * To make changes, update the source code or use the my-calculator-form.extension.ts file + */ + +import type { EditorElement } from '@wix/react-component-schema'; + +export const editorElement = { + "selector": ".calculator-form", + "displayName": "My Calculator Form", + "data": { + "title": { + "displayName": "Title", + "dataType": "text", + "text": {} + }, + "whatItDoes": { + "displayName": "What It Does", + "dataType": "text", + "text": {} + }, + "fields": { + "displayName": "Fields", + "dataType": "arrayItems", + "arrayItems": { + "data": { + "items": { + "id": { + "displayName": "Id", + "dataType": "text", + "text": {} + }, + "label": { + "displayName": "Label", + "dataType": "text", + "text": {} + }, + "placeholder": { + "displayName": "Placeholder", + "dataType": "text", + "text": {} + } + } + } + } + }, + "submitLabel": { + "displayName": "Submit Label", + "dataType": "text", + "text": {} + }, + "resultsHeading": { + "displayName": "Results Heading", + "dataType": "text", + "text": {} + }, + "totalLabel": { + "displayName": "Total Label", + "dataType": "text", + "text": {} + }, + "startOverLabel": { + "displayName": "Start Over Label", + "dataType": "text", + "text": {} + }, + "direction": { + "displayName": "Direction", + "dataType": "direction" + }, + "a11y": { + "displayName": "Accessibility", + "dataType": "a11y", + "a11y": { + "attributes": [ + "tabIndex", + "ariaLevel", + "ariaExpanded", + "ariaDisabled", + "ariaAtomic", + "ariaHidden", + "ariaBusy", + "ariaAutocomplete", + "ariaPressed", + "ariaHaspopup", + "ariaRelevant", + "role", + "ariaLive", + "ariaCurrent", + "ariaLabel", + "ariaRoledescription", + "ariaDescribedby", + "ariaLabelledby", + "ariaErrormessage", + "ariaOwns", + "ariaControls", + "tag", + "ariaMultiline", + "ariaInvalid" + ] + } + } + }, + "elements": { + "intro": { + "elementType": "inlineElement", + "inlineElement": { + "selector": ".intro", + "displayName": "Intro", + "behaviors": { + "removable": true, + "selectable": false + }, + "cssProperties": { + "background": {}, + "borderTop": {}, + "borderBottom": {}, + "borderInlineStart": {}, + "borderInlineEnd": {}, + "paddingTop": {}, + "paddingBottom": {}, + "paddingInlineStart": {}, + "paddingInlineEnd": {}, + "borderStartStartRadius": {}, + "borderStartEndRadius": {}, + "borderEndStartRadius": {}, + "borderEndEndRadius": {}, + "boxShadow": {}, + "display": { + "display": { + "displayValues": [ + "none", + "flex" + ] + } + }, + "gap": { + "defaultValue": "0.5rem" + } + }, + "elements": { + "title": { + "elementType": "inlineElement", + "inlineElement": { + "selector": ".title", + "displayName": "Title", + "behaviors": { + "removable": true, + "selectable": false + }, + "cssProperties": { + "font": { + "defaultValue": "600 1.375rem/1.3 system-ui,sans-serif" + }, + "lineHeight": {}, + "letterSpacing": {}, + "textDecorationLine": {}, + "textTransform": {}, + "textAlign": { + "defaultValue": "start" + }, + "textShadow": {}, + "color": { + "defaultValue": "#0f172a" + }, + "display": { + "display": { + "displayValues": [ + "none", + "block" + ] + } + } + } + } + }, + "whatItDoes": { + "elementType": "inlineElement", + "inlineElement": { + "selector": ".what-it-does", + "displayName": "What It Does", + "behaviors": { + "removable": true, + "selectable": false + }, + "cssProperties": { + "font": { + "defaultValue": "400 0.875rem/1.5 system-ui,sans-serif" + }, + "lineHeight": {}, + "letterSpacing": {}, + "textDecorationLine": {}, + "textTransform": {}, + "textAlign": { + "defaultValue": "start" + }, + "textShadow": {}, + "color": { + "defaultValue": "#64748b" + }, + "display": { + "display": { + "displayValues": [ + "none", + "block" + ] + } + } + } + } + } + } + } + }, + "fieldLabel": { + "elementType": "inlineElement", + "inlineElement": { + "selector": ".field-label", + "displayName": "Field Label", + "behaviors": { + "removable": true, + "selectable": false + }, + "cssProperties": { + "font": { + "defaultValue": "500 0.875rem/1.4 system-ui,sans-serif" + }, + "lineHeight": {}, + "letterSpacing": {}, + "textDecorationLine": {}, + "textTransform": {}, + "textAlign": {}, + "textShadow": {}, + "color": { + "defaultValue": "#334155" + }, + "display": { + "display": { + "displayValues": [ + "none", + "inline" + ] + } + } + } + } + }, + "numberInput": { + "elementType": "inlineElement", + "inlineElement": { + "selector": ".number-input", + "displayName": "Number Input", + "behaviors": { + "removable": true, + "selectable": false + }, + "cssProperties": { + "background": { + "defaultValue": "#f8fafc" + }, + "borderTop": { + "defaultValue": "1px solid #e2e8f0" + }, + "borderBottom": { + "defaultValue": "1px solid #e2e8f0" + }, + "borderInlineStart": { + "defaultValue": "1px solid #e2e8f0" + }, + "borderInlineEnd": { + "defaultValue": "1px solid #e2e8f0" + }, + "paddingTop": { + "defaultValue": "0.625rem" + }, + "paddingBottom": { + "defaultValue": "0.625rem" + }, + "paddingInlineStart": { + "defaultValue": "0.875rem" + }, + "paddingInlineEnd": { + "defaultValue": "0.875rem" + }, + "borderStartStartRadius": { + "defaultValue": "8px" + }, + "borderStartEndRadius": { + "defaultValue": "8px" + }, + "borderEndStartRadius": { + "defaultValue": "8px" + }, + "borderEndEndRadius": { + "defaultValue": "8px" + }, + "boxShadow": {}, + "display": { + "display": { + "displayValues": [ + "none", + "inline" + ] + } + } + }, + "states": { + "hover": { + "displayName": "Hover", + "className": "number-input--hover", + "pseudoClass": "hover" + }, + "focus": { + "displayName": "Focus", + "className": "number-input--focus", + "pseudoClass": "focus" + }, + "disabled": { + "displayName": "Disabled", + "className": "number-input--disabled", + "pseudoClass": "disabled" + }, + "invalid": { + "displayName": "Invalid", + "className": "number-input--invalid", + "pseudoClass": "invalid" + } + } + } + }, + "submitButton": { + "elementType": "inlineElement", + "inlineElement": { + "selector": ".submit-button", + "displayName": "Submit Button", + "behaviors": { + "removable": true, + "selectable": false + }, + "cssProperties": { + "background": { + "defaultValue": "#6366f1" + }, + "borderTop": { + "defaultValue": "none" + }, + "borderBottom": { + "defaultValue": "none" + }, + "borderInlineStart": { + "defaultValue": "none" + }, + "borderInlineEnd": { + "defaultValue": "none" + }, + "paddingTop": { + "defaultValue": "0.625rem" + }, + "paddingBottom": { + "defaultValue": "0.625rem" + }, + "paddingInlineStart": { + "defaultValue": "1.25rem" + }, + "paddingInlineEnd": { + "defaultValue": "1.25rem" + }, + "borderStartStartRadius": { + "defaultValue": "8px" + }, + "borderStartEndRadius": { + "defaultValue": "8px" + }, + "borderEndStartRadius": { + "defaultValue": "8px" + }, + "borderEndEndRadius": { + "defaultValue": "8px" + }, + "boxShadow": {}, + "display": { + "display": { + "displayValues": [ + "none", + "inlineBlock" + ] + } + }, + "font": { + "defaultValue": "600 1rem/1.5 system-ui,sans-serif" + }, + "lineHeight": {}, + "letterSpacing": {}, + "textDecorationLine": {}, + "textTransform": {}, + "textAlign": {}, + "textShadow": {}, + "color": { + "defaultValue": "#ffffff" + } + }, + "states": { + "hover": { + "displayName": "Hover", + "className": "submit-button--hover", + "pseudoClass": "hover" + }, + "focus": { + "displayName": "Focus", + "className": "submit-button--focus", + "pseudoClass": "focus" + }, + "disabled": { + "displayName": "Disabled", + "className": "submit-button--disabled", + "pseudoClass": "disabled" + } + } + } + }, + "resultsHeading": { + "elementType": "inlineElement", + "inlineElement": { + "selector": ".results-heading", + "displayName": "Results Heading", + "behaviors": { + "removable": true, + "selectable": false + }, + "cssProperties": { + "font": { + "defaultValue": "600 1.125rem/1.3 system-ui,sans-serif" + }, + "lineHeight": {}, + "letterSpacing": {}, + "textDecorationLine": {}, + "textTransform": {}, + "textAlign": { + "defaultValue": "start" + }, + "textShadow": {}, + "color": { + "defaultValue": "#0f172a" + }, + "display": { + "display": { + "displayValues": [ + "none", + "block" + ] + } + } + } + } + }, + "totalLabel": { + "elementType": "inlineElement", + "inlineElement": { + "selector": ".total-label", + "displayName": "Total Label", + "behaviors": { + "removable": true, + "selectable": false + }, + "cssProperties": { + "font": { + "defaultValue": "500 0.875rem/1.4 system-ui,sans-serif" + }, + "lineHeight": {}, + "letterSpacing": {}, + "textDecorationLine": {}, + "textTransform": {}, + "textAlign": {}, + "textShadow": {}, + "color": { + "defaultValue": "#64748b" + }, + "display": { + "display": { + "displayValues": [ + "none", + "inline" + ] + } + } + } + } + }, + "totalValue": { + "elementType": "inlineElement", + "inlineElement": { + "selector": ".total-value", + "displayName": "Total Value", + "behaviors": { + "removable": true, + "selectable": false + }, + "cssProperties": { + "background": {}, + "borderTop": {}, + "borderBottom": {}, + "borderInlineStart": {}, + "borderInlineEnd": {}, + "paddingTop": {}, + "paddingBottom": {}, + "paddingInlineStart": {}, + "paddingInlineEnd": {}, + "borderStartStartRadius": {}, + "borderStartEndRadius": {}, + "borderEndStartRadius": {}, + "borderEndEndRadius": {}, + "boxShadow": {}, + "display": { + "display": { + "displayValues": [ + "none", + "block" + ] + } + }, + "font": { + "defaultValue": "600 2rem/1.2 system-ui,sans-serif" + }, + "lineHeight": {}, + "letterSpacing": {}, + "textDecorationLine": {}, + "textTransform": {}, + "textAlign": {}, + "textShadow": {}, + "color": { + "defaultValue": "#0f172a" + } + } + } + }, + "startOverButton": { + "elementType": "inlineElement", + "inlineElement": { + "selector": ".start-over-button", + "displayName": "Start Over Button", + "behaviors": { + "removable": true, + "selectable": false + }, + "cssProperties": { + "background": { + "defaultValue": "#ffffff" + }, + "borderTop": { + "defaultValue": "1px solid #e2e8f0" + }, + "borderBottom": { + "defaultValue": "1px solid #e2e8f0" + }, + "borderInlineStart": { + "defaultValue": "1px solid #e2e8f0" + }, + "borderInlineEnd": { + "defaultValue": "1px solid #e2e8f0" + }, + "paddingTop": { + "defaultValue": "0.625rem" + }, + "paddingBottom": { + "defaultValue": "0.625rem" + }, + "paddingInlineStart": { + "defaultValue": "1.25rem" + }, + "paddingInlineEnd": { + "defaultValue": "1.25rem" + }, + "borderStartStartRadius": { + "defaultValue": "8px" + }, + "borderStartEndRadius": { + "defaultValue": "8px" + }, + "borderEndStartRadius": { + "defaultValue": "8px" + }, + "borderEndEndRadius": { + "defaultValue": "8px" + }, + "boxShadow": {}, + "display": { + "display": { + "displayValues": [ + "none", + "inlineBlock" + ] + } + }, + "font": { + "defaultValue": "600 1rem/1.5 system-ui,sans-serif" + }, + "lineHeight": {}, + "letterSpacing": {}, + "textDecorationLine": {}, + "textTransform": {}, + "textAlign": {}, + "textShadow": {}, + "color": { + "defaultValue": "#334155" + } + }, + "states": { + "hover": { + "displayName": "Hover", + "className": "start-over-button--hover", + "pseudoClass": "hover" + }, + "focus": { + "displayName": "Focus", + "className": "start-over-button--focus", + "pseudoClass": "focus" + }, + "disabled": { + "displayName": "Disabled", + "className": "start-over-button--disabled", + "pseudoClass": "disabled" + } + } + } + } + }, + "cssProperties": { + "background": { + "defaultValue": "#ffffff" + }, + "borderTop": { + "defaultValue": "1px solid #e2e8f0" + }, + "borderBottom": { + "defaultValue": "1px solid #e2e8f0" + }, + "borderInlineStart": { + "defaultValue": "1px solid #e2e8f0" + }, + "borderInlineEnd": { + "defaultValue": "1px solid #e2e8f0" + }, + "paddingTop": { + "defaultValue": "1.5rem" + }, + "paddingBottom": { + "defaultValue": "1.5rem" + }, + "paddingInlineStart": { + "defaultValue": "1.5rem" + }, + "paddingInlineEnd": { + "defaultValue": "1.5rem" + }, + "borderStartStartRadius": { + "defaultValue": "12px" + }, + "borderStartEndRadius": { + "defaultValue": "12px" + }, + "borderEndStartRadius": { + "defaultValue": "12px" + }, + "borderEndEndRadius": { + "defaultValue": "12px" + }, + "boxShadow": { + "defaultValue": "0 2px 8px rgba(15,23,42,0.06),0 0 1px rgba(15,23,42,0.08)" + }, + "display": { + "display": { + "displayValues": [ + "none", + "block" + ] + } + } + }, + "cssCustomProperties": {} +} as EditorElement; diff --git a/CLI App - Calculator Form/src/extensions/site/components/my-calculator-form/my-calculator-form.module.css b/CLI App - Calculator Form/src/extensions/site/components/my-calculator-form/my-calculator-form.module.css new file mode 100644 index 0000000..08b3eac --- /dev/null +++ b/CLI App - Calculator Form/src/extensions/site/components/my-calculator-form/my-calculator-form.module.css @@ -0,0 +1,172 @@ +.calculatorForm { + --display: flex; + flex-direction: column; + align-items: stretch; + gap: 1.25rem; + width: 100%; + height: 100%; + box-sizing: border-box; + background: #ffffff; + border: 1px solid #e2e8f0; + border-radius: 12px; + box-shadow: 0 2px 8px rgba(15, 23, 42, 0.06), 0 0 1px rgba(15, 23, 42, 0.08); + padding-block: 1.5rem; + padding-inline: 1.5rem; + pointer-events: auto; +} + +.title { + margin: 0; + color: #0f172a; + font: 600 1.375rem/1.3 system-ui, sans-serif; + text-align: start; + box-sizing: border-box; + pointer-events: auto; +} + +.intro { + display: flex; + flex-direction: column; + gap: 0.5rem; + box-sizing: border-box; +} + +.whatItDoes { + margin: 0; + color: #64748b; + font: 400 0.875rem/1.5 system-ui, sans-serif; + text-align: start; + box-sizing: border-box; +} + +.form { + display: flex; + flex-direction: column; + gap: 1.25rem; + flex: 1; + min-width: 0; + box-sizing: border-box; + pointer-events: auto; +} + +.formHidden { + display: none; +} + +.fields { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(9rem, 1fr)); + gap: 1rem; + box-sizing: border-box; +} + +.field { + display: flex; + flex-direction: column; + gap: 0.375rem; + min-width: 0; + box-sizing: border-box; +} + +.fieldLabel { + color: #334155; + font: 500 0.875rem/1.4 system-ui, sans-serif; + box-sizing: border-box; + pointer-events: auto; +} + +.numberInput { + width: 100%; + min-height: 2.75rem; + padding-block: 0.625rem; + padding-inline: 0.875rem; + border: 1px solid #e2e8f0; + border-radius: 8px; + background: #f8fafc; + color: #0f172a; + font: 400 1rem/1.5 system-ui, sans-serif; + box-sizing: border-box; + pointer-events: auto; +} + +.submitButton { + align-self: stretch; + min-height: 2.75rem; + padding-block: 0.625rem; + padding-inline: 1.25rem; + border: none; + border-radius: 8px; + background: #6366f1; + color: #ffffff; + font: 600 1rem/1.5 system-ui, sans-serif; + cursor: pointer; + box-sizing: border-box; + pointer-events: auto; +} + +.results { + display: flex; + flex-direction: column; + gap: 1.25rem; + flex: 1; + min-width: 0; + box-sizing: border-box; + pointer-events: auto; +} + +.resultsHidden { + display: none; +} + +.resultsHeading { + margin: 0; + color: #0f172a; + font: 600 1.125rem/1.3 system-ui, sans-serif; + text-align: start; + box-sizing: border-box; + pointer-events: auto; +} + +.totalRow { + display: flex; + flex-direction: column; + gap: 0.375rem; + padding-block: 1rem; + padding-inline: 1rem; + border-radius: 8px; + background: #f1f5f9; + box-sizing: border-box; +} + +.totalLabel { + color: #64748b; + font: 500 0.875rem/1.4 system-ui, sans-serif; + box-sizing: border-box; + pointer-events: auto; +} + +.totalValue { + color: #0f172a; + font: 600 2rem/1.2 system-ui, sans-serif; + box-sizing: border-box; + pointer-events: auto; +} + +.startOverButton { + align-self: stretch; + min-height: 2.75rem; + padding-block: 0.625rem; + padding-inline: 1.25rem; + border: 1px solid #e2e8f0; + border-radius: 8px; + background: #ffffff; + color: #334155; + font: 600 1rem/1.5 system-ui, sans-serif; + cursor: pointer; + box-sizing: border-box; + pointer-events: auto; +} + +.fallbackDirection:not([dir]) { + direction: var(--wix-opt-in-direction); +} diff --git a/CLI App - Calculator Form/src/extensions/site/components/my-calculator-form/my-calculator-form.tsx b/CLI App - Calculator Form/src/extensions/site/components/my-calculator-form/my-calculator-form.tsx new file mode 100644 index 0000000..51179aa --- /dev/null +++ b/CLI App - Calculator Form/src/extensions/site/components/my-calculator-form/my-calculator-form.tsx @@ -0,0 +1,193 @@ +import { useState, useCallback, useEffect, useMemo, type FC, type FormEvent, type ChangeEvent } from 'react'; +import classNames from 'classnames'; +import type { A11y, Direction } from '@wix/editor-react-types'; +import { convertA11yKeysToHtmlFormat, useStableId } from '@wix/react-component-utils'; +import styles from './my-calculator-form.module.css'; + +export type CalculatorField = { + id: string; + label: string; + placeholder?: string; +}; + +export type MyCalculatorFormProps = { + id?: string; + className?: string; + title?: string; + /** Short line under the title explaining what the calculator does. */ + whatItDoes?: string; + fields?: Array<CalculatorField>; + submitLabel?: string; + resultsHeading?: string; + totalLabel?: string; + startOverLabel?: string; + direction?: Direction; + a11y?: A11y; +}; + +export const defaultProps = { + title: 'Calculator', + whatItDoes: + 'Fill in each value, then tap Calculate total to see their sum. Tap Start over to enter new numbers.', + fields: [ + { id: 'field-1', label: 'Value 1', placeholder: '0' }, + { id: 'field-2', label: 'Value 2', placeholder: '0' }, + { id: 'field-3', label: 'Value 3', placeholder: '0' }, + { id: 'field-4', label: 'Value 4', placeholder: '0' }, + ], + submitLabel: 'Calculate total', + resultsHeading: 'Your total', + totalLabel: 'Sum', + startOverLabel: 'Start over', +} as const satisfies Omit<MyCalculatorFormProps, 'id' | 'className' | 'direction' | 'a11y'>; + +type View = 'form' | 'results'; + +const createEmptyValues = (fields: Array<CalculatorField>): Record<string, string> => + Object.fromEntries(fields.map((field) => [field.id, ''])); + +const MyCalculatorForm: FC<MyCalculatorFormProps> = (props) => { + const { + id, + className, + title, + whatItDoes = defaultProps.whatItDoes, + fields = defaultProps.fields as Array<CalculatorField>, + submitLabel = defaultProps.submitLabel, + resultsHeading = defaultProps.resultsHeading, + totalLabel = defaultProps.totalLabel, + startOverLabel = defaultProps.startOverLabel, + direction, + a11y, + } = props; + + const formFieldIdPrefix = useStableId(id); + const [view, setView] = useState<View>('form'); + const [values, setValues] = useState<Record<string, string>>(() => createEmptyValues(fields)); + const [total, setTotal] = useState(0); + + const fieldsKey = useMemo( + () => + fields + .map((field) => [field.id, field.label, field.placeholder ?? ''].join('\u0000')) + .join('\u0001'), + [fields], + ); + + // Reset local state only when field definitions change (id/label/placeholder). + // Harmony often passes a new `fields` array reference on every render; `[fields]` would reset on every keystroke. + useEffect(() => { + setValues(createEmptyValues(fields)); + setView('form'); + setTotal(0); + // eslint-disable-next-line react-hooks/exhaustive-deps -- `fieldsKey` is the stability boundary; `fields` is current from this render + }, [fieldsKey]); + + const handleChange = useCallback( + (fieldId: string) => (event: ChangeEvent<HTMLInputElement>) => { + const input = event.currentTarget; + if (input == null) return; + setValues((previous) => ({ ...previous, [fieldId]: input.value })); + }, + [], + ); + + const handleSubmit = useCallback( + (event: FormEvent<HTMLFormElement>) => { + event.preventDefault(); + const sum = fields.reduce((accumulator, field) => { + const parsed = Number.parseFloat(values[field.id] ?? ''); + return accumulator + (Number.isFinite(parsed) ? parsed : 0); + }, 0); + setTotal(sum); + setView('results'); + }, + [fields, values], + ); + + const handleStartOver = useCallback(() => { + setValues(createEmptyValues(fields)); + setTotal(0); + setView('form'); + }, [fields]); + + const formattedTotal = new Intl.NumberFormat(undefined, { + maximumFractionDigits: 10, + }).format(total); + + const introText = whatItDoes?.trim() ?? ''; + + return ( + <div + id={id} + dir={direction} + className={classNames( + 'calculator-form', + styles.calculatorForm, + styles.fallbackDirection, + className, + )} + {...(a11y ? convertA11yKeysToHtmlFormat(a11y) : undefined)} + > + <div className={classNames('intro', styles.intro)}> + <h2 className={classNames('title', styles.title)}>{title}</h2> + {introText ? ( + <p className={classNames('what-it-does', styles.whatItDoes)}>{introText}</p> + ) : null} + </div> + + <form + className={classNames(styles.form, view === 'results' && styles.formHidden)} + onSubmit={handleSubmit} + noValidate + > + <div className={styles.fields}> + {fields.map((field) => { + const inputId = `${formFieldIdPrefix}-${field.id}`; + return ( + <div key={field.id} className={styles.field}> + <label htmlFor={inputId} className={classNames('field-label', styles.fieldLabel)}> + {field.label} + </label> + <input + id={inputId} + className={classNames('number-input', styles.numberInput)} + type="number" + inputMode="decimal" + step="any" + placeholder={field.placeholder} + value={values[field.id] ?? ''} + onChange={handleChange(field.id)} + /> + </div> + ); + })} + </div> + <button type="submit" className={classNames('submit-button', styles.submitButton)}> + {submitLabel} + </button> + </form> + + <section + className={classNames(styles.results, view === 'form' && styles.resultsHidden)} + aria-live="polite" + aria-atomic="true" + > + <h3 className={classNames('results-heading', styles.resultsHeading)}>{resultsHeading}</h3> + <div className={styles.totalRow}> + <span className={classNames('total-label', styles.totalLabel)}>{totalLabel}</span> + <output className={classNames('total-value', styles.totalValue)}>{formattedTotal}</output> + </div> + <button + type="button" + className={classNames('start-over-button', styles.startOverButton)} + onClick={handleStartOver} + > + {startOverLabel} + </button> + </section> + </div> + ); +}; + +export default MyCalculatorForm; diff --git a/CLI App - Calculator Form/tsconfig.json b/CLI App - Calculator Form/tsconfig.json new file mode 100644 index 0000000..8bf91d3 --- /dev/null +++ b/CLI App - Calculator Form/tsconfig.json @@ -0,0 +1,5 @@ +{ + "extends": "astro/tsconfigs/strict", + "include": [".astro/types.d.ts", "**/*"], + "exclude": ["dist"] +} diff --git a/CLI App - Calculator Form/wix.config.json b/CLI App - Calculator Form/wix.config.json new file mode 100644 index 0000000..9288300 --- /dev/null +++ b/CLI App - Calculator Form/wix.config.json @@ -0,0 +1,7 @@ +{ + "appId": "<APP_ID>", + "namespace": "<APP_NAMESPACE>", + "projectId": "calculator-form", + "codeIdentifier": "<CODE_IDENTIFIER>", + "projectType": "App" +}