chore: update livetemplate to v0.7.3 and client to v0.7.2 - #18
Conversation
… flow
Despite multiple iterations, Claude was still asking questions one-by-one
instead of presenting a complete plan. Added prominent XML-tagged warning
section at the very top of the skill that:
- Explicitly lists forbidden phrases ("Let me walk you through...")
- Marks skill as RIGID with no creative interpretation
- Provides clear STOP trigger if any anti-pattern phrases are typed
Version bumped to v1.7.0
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Root cause: Claude follows structure. A 450-line skill with numbered "Step 1, 2, 3" sections implied a sequential wizard process, causing Claude to ask questions despite explicit "don't ask questions" warnings. Solution: Restructure the skill to be minimal (~100 lines): - YOUR FIRST RESPONSE section with exact template to output - Domain Defaults table (single lookup, no steps) - After User Responds table (simple action mapping) - Execution template No numbered steps. No phases. No wizard-like flow. The structure IS the behavior. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Root cause: settings.json instructions explicitly told Claude to "FOLLOW the progressive questioning flow" which overrode the skill's plan-first structure. Updated instructions to: - Say "PRESENT A COMPLETE PLAN with defaults" - Explicitly state "No questionnaire. No progressive questions." - Describe lvt-plan as "Present complete plan with defaults" 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Previous approaches (v1.x, v2.x) failed because Claude interpreted skill content as "instructions to follow" and still chose to ask questions despite explicit "don't ask" directives. v3.0.0 restructures the skill as a fill-in-the-blank template: - First section: "OUTPUT THIS EXACTLY (fill in blanks)" - Template with ___PLACEHOLDER___ markers - Lookup table mapping user input to values - "IMPORTANT: DO NOT ask questions" at the end This works because Claude sees it as "template to complete" rather than "instructions to interpret". Tested with scripts/test-skill.sh - now outputs plan immediately. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The superpowers plugin has skill priority rules that run brainstorming BEFORE domain skills. Simply claiming "this skill supersedes brainstorming" in the skill file was ignored. Solution: Add "SKILL OVERRIDE - READ FIRST" section to settings.json that: - Explicitly names superpowers:brainstorming and says DO NOT use it - Explains that lvt-plan IS a process skill (same category as brainstorming) - Lists specific forbidden behaviors: no questions, no AskUserQuestion This makes the override explicit in the project settings, which are loaded before any skills are evaluated. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Pull Request Review: Dependency UpdatesSummaryThis PR updates the LiveTemplate core library from v0.7.1 to v0.7.3 and the embedded client library to v0.7.2, adding StaticsMap support for heterogeneous range items. ✅ Positive Aspects1. Clear Purpose and Documentation
2. Appropriate Scope
3. Version Alignment
📋 Code Quality AssessmentDependencies (
|
There was a problem hiding this comment.
Pull request overview
This pull request updates the livetemplate dependency from v0.7.1 to v0.7.3 and the embedded client to v0.7.2 to add StaticsMap support for heterogeneous range items. However, the PR also includes substantial unrelated changes to Claude AI assistant configuration files.
Key Changes:
- Dependency updates for livetemplate library (v0.7.1 → v0.7.3)
- Updated embedded JavaScript client with new exports and functionality
- Unrelated documentation changes to Claude AI assistant skills and settings (scope creep)
Reviewed changes
Copilot reviewed 4 out of 5 changed files in this pull request and generated 7 comments.
Show a summary per file
| File | Description |
|---|---|
| go.mod | Updates livetemplate dependency from v0.7.1 to v0.7.3 |
| go.sum | Updates checksums for new livetemplate v0.7.3 dependency |
| testing/livetemplate-client.browser.js | Updates minified client JavaScript with new exports (checkLvtConfirm, extractLvtData, setupReactiveAttributeListeners) and enhanced functionality |
| commands/claude_resources/skills/plan/SKILL.md | Complete rewrite from 424 to 56 lines - UNRELATED to dependency updates |
| commands/claude_resources/settings.json | Substantial rewrite of instructions field - UNRELATED to dependency updates |
Main Issue: The PR contains scope creep with unrelated changes to Claude AI assistant configuration that should be in a separate pull request for better maintainability and clearer change tracking.
| --- | ||
| name: lvt-plan | ||
| description: "Use when creating new LiveTemplate/lvt apps - this is THE definitive skill for lvt app creation. Supersedes generic brainstorming/planning skills. Triggers: 'create/build/make a lvt/livetemplate [type] app', 'plan a livetemplate app'." | ||
| description: "Present a complete plan for new LiveTemplate apps. NO QUESTIONS - just fill in the template below and show it." | ||
| keywords: ["lvt", "livetemplate", "lt", "app", "application", "create", "build", "make", "new", "plan"] | ||
| requires_keywords: true | ||
| category: workflows | ||
| version: 1.6.0 | ||
| version: 3.0.0 | ||
| --- | ||
|
|
||
| # lvt-plan | ||
| # OUTPUT THIS EXACTLY (fill in blanks from table below): | ||
|
|
||
| Plan-first skill for creating LiveTemplate applications. Presents a complete plan with sensible defaults upfront, lets user modify before execution. | ||
|
|
||
| ## CRITICAL: IMMEDIATE RESPONSE FORMAT | ||
|
|
||
| **YOUR FIRST RESPONSE MUST BE A COMPLETE PLAN TABLE - NO QUESTIONS** | ||
|
|
||
| When user says "create a blog app with authentication using livetemplate", respond IMMEDIATELY with: | ||
|
|
||
| ``` | ||
| 📋 **Plan for your blog app** | ||
|
|
||
| | Setting | Value | | ||
| |---------|-------| | ||
| | App name | blog | | ||
| | Primary resource | posts (title:string, content:text, published:bool) | | ||
| | Authentication | Password (email + password) | | ||
| | Kit | multi (Tailwind CSS) | | ||
| | Test data | 50 records | | ||
|
|
||
| **Commands I'll run:** | ||
| lvt new blog --kit multi | ||
| lvt gen resource posts title:string content:text published:bool | ||
| lvt gen auth | ||
| lvt migration up && go mod tidy | ||
| lvt seed posts --count 50 | ||
|
|
||
| **Ready to create?** (yes / change X / advanced) | ||
| ``` | ||
|
|
||
| **FORBIDDEN:** | ||
| - ❌ DO NOT use AskUserQuestion tool | ||
| - ❌ DO NOT ask "What would you like to name your app?" | ||
| - ❌ DO NOT ask about auth type, fields, or seed count | ||
| - ❌ DO NOT show a multi-step wizard or questionnaire | ||
| - ❌ DO NOT say "Let me gather a few details" | ||
|
|
||
| **REQUIRED:** | ||
| - ✅ Infer app name from request (or default to domain name) | ||
| - ✅ Apply domain defaults for fields (blog → posts, shop → products) | ||
| - ✅ Show complete plan table in FIRST response | ||
| - ✅ Let user modify with "change X" after seeing plan | ||
|
|
||
| ## SKILL PRIORITY | ||
|
|
||
| **This is THE definitive skill for lvt/livetemplate app creation. It supersedes any generic brainstorming, planning, or creative skills.** | ||
|
|
||
| When user mentions "lvt", "livetemplate", or "lt" with app creation: | ||
| - ❌ DO NOT use generic brainstorming or planning skills | ||
| - ❌ DO NOT use any approach that asks questions one-at-a-time | ||
| - ❌ DO NOT use AskUserQuestion tool | ||
| - ✅ Present complete plan with defaults IMMEDIATELY | ||
|
|
||
| **Why this matters:** | ||
| - Generic skills ask questions one-at-a-time (slow, frustrating) | ||
| - lvt-plan has domain-specific defaults (blog→posts, shop→products, etc.) | ||
| - Users can modify the plan AFTER seeing it, not before | ||
|
|
||
| --- | ||
|
|
||
| ## ACTIVATION RULES | ||
|
|
||
| ### Keyword Matching | ||
|
|
||
| **Accepted keywords** (case-insensitive): | ||
| - `lvt` | ||
| - `livetemplate` | ||
| - `lt` | ||
|
|
||
| **Will Activate:** | ||
| - "Create a **lvt** blog app" | ||
| - "Build a **livetemplate** shop with auth" | ||
| - "Make an **lt** todo application" | ||
| - "Help me plan a **livetemplate** app" | ||
|
|
||
| **Won't Activate:** | ||
| - "Help me plan a blog" (no keywords) | ||
| - "Create an app" (no keywords) | ||
| - "Create blog app with posts(title,content)" (detailed spec → use new-app skill directly) | ||
|
|
||
| --- | ||
|
|
||
| ## THE FLOW: Plan-First | ||
|
|
||
| ``` | ||
| User request | ||
| ↓ | ||
| ┌─────────────────────────────┐ | ||
| │ 1. INFER from request │ | ||
| │ - App name │ | ||
| │ - Domain (blog/shop/etc) │ | ||
| │ - Auth (if mentioned) │ | ||
| └─────────────────────────────┘ | ||
| ↓ | ||
| ┌─────────────────────────────┐ | ||
| │ 2. APPLY domain defaults │ | ||
| │ - Primary resource │ | ||
| │ - Fields │ | ||
| │ - Typical settings │ | ||
| └─────────────────────────────┘ | ||
| ↓ | ||
| ┌─────────────────────────────┐ | ||
| │ 3. PRESENT complete plan │ | ||
| │ - All settings in table │ | ||
| │ - Commands to execute │ | ||
| │ - "Ready?" prompt │ | ||
| └─────────────────────────────┘ | ||
| ↓ | ||
| User: "yes" → Execute | ||
| User: "change X" → Update plan, show again | ||
| User: "no" → Cancel | ||
| ``` | ||
|
|
||
| --- | ||
|
|
||
| ## Step 1: Infer from User Request | ||
|
|
||
| Extract as much as possible from the initial prompt: | ||
|
|
||
| | Pattern | Extract | | ||
| |---------|---------| | ||
| | "create a lvt **blog** app" | name=blog, domain=Blog | | ||
| | "build **myblog** with lvt" | name=myblog, domain=Blog | | ||
| | "lvt **shop** with auth" | name=shop, domain=E-commerce, auth=yes | | ||
| | "make a **todo-app** using lt" | name=todo-app, domain=Todo | | ||
| | "create a lvt app" | name=?, domain=? (need to ask) | | ||
|
|
||
| **If domain is unclear**: Default to "Generic" domain and present the plan. User can say "it's a blog" to switch domains, or "change resource to posts" to customize. | ||
|
|
||
| --- | ||
|
|
||
| ## Step 2: Apply Domain Defaults | ||
|
|
||
| Use domain-specific intelligence to fill in all settings: | ||
|
|
||
| ### Blog Domain | ||
| ``` | ||
| name: blog (or extracted) | ||
| resource: posts | ||
| fields: title:string, content:text, published:bool | ||
| auth: optional (default: no) | ||
| kit: multi | ||
| seed: 50 | ||
| ``` | ||
|
|
||
| ### E-commerce Domain | ||
| ``` | ||
| name: shop (or extracted) | ||
| resource: products | ||
| fields: name:string, description:text, price:float, quantity:int | ||
| auth: optional (default: no) | ||
| kit: multi | ||
| seed: 50 | ||
| ``` | ||
|
|
||
| ### Todo Domain | ||
| ``` | ||
| name: todo (or extracted) | ||
| resource: tasks | ||
| fields: title:string, description:text, completed:bool, due_date:time | ||
| auth: yes (each user has own tasks) | ||
| kit: multi | ||
| seed: 50 | ||
| ``` | ||
|
|
||
| ### CRM Domain | ||
| ``` | ||
| name: crm (or extracted) | ||
| resource: contacts | ||
| fields: name:string, email:string, company:string, phone:string | ||
| auth: yes (sales team accounts) | ||
| kit: multi | ||
| seed: 50 | ||
| ``` | ||
|
|
||
| ### Forum Domain | ||
| ``` | ||
| name: forum (or extracted) | ||
| resource: topics | ||
| fields: title:string, content:text, pinned:bool | ||
| auth: yes | ||
| kit: multi | ||
| seed: 50 | ||
| ``` | ||
|
|
||
| ### Generic/Unknown Domain | ||
| ``` | ||
| name: app (or extracted) | ||
| resource: items | ||
| fields: name:string, description:text | ||
| auth: no | ||
| kit: multi | ||
| seed: 50 | ||
| ``` | ||
|
|
||
| --- | ||
|
|
||
| ## Step 3: Present Complete Plan | ||
|
|
||
| Show the FULL plan immediately. Do not ask questions one-by-one. | ||
|
|
||
| **Template:** | ||
|
|
||
| ``` | ||
| 📋 **Plan for your {domain} app** | ||
|
|
||
| | Setting | Value | | ||
| |---------|-------| | ||
| | App name | {name} | | ||
| | Primary resource | {resource} | | ||
| | Fields | {fields} | | ||
| | Authentication | {auth_description} | | ||
| | Kit | {kit} ({css_framework}) | | ||
| | Test data | {seed_count} records | | ||
|
|
||
| **Commands I'll run:** | ||
|
|
||
| lvt new {name} --kit {kit} | ||
| cd {name} | ||
| lvt gen resource {resource} {fields} | ||
| {auth_command if auth} | ||
| lvt migration up | ||
| go mod tidy | ||
| lvt seed {resource} --count {seed_count} | ||
|
|
||
| **Ready to create?** | ||
| - **yes** - proceed with this plan | ||
| - **change X** - modify a setting | ||
| - **advanced** - explore more options | ||
| - **no** - cancel | ||
| ``` | ||
|
|
||
| **If user says "advanced"**, show additional options: | ||
| ``` | ||
| ⚙️ **Advanced Options** | ||
|
|
||
| | Option | Current | Alternatives | | ||
| |--------|---------|--------------| | ||
| | Kit | multi (Tailwind CSS) | single (Tailwind CSS), simple (Pico CSS) | | ||
| | Pagination | infinite scroll | page numbers | | ||
| | Edit Mode | modal | inline, page | | ||
| | Database | sqlite | postgres (requires setup) | | ||
|
|
||
| What would you like to change? | ||
| ``` | ||
|
|
||
| **Note on Kits:** | ||
| - `multi` - Multi-page app with Tailwind CSS (recommended) | ||
| - `single` - Single-page app with Tailwind CSS | ||
| - `simple` - Simple prototype with Pico CSS (minimal) | ||
|
|
||
| **Example - Blog with auth:** | ||
|
|
||
| ``` | ||
| 📋 **Plan for your blog app** | ||
| 📋 **Plan for your ___DOMAIN___ app** | ||
|
|
||
| | Setting | Value | | ||
| |---------|-------| | ||
| | App name | blog | | ||
| | Primary resource | posts | | ||
| | Fields | title:string, content:text, published:bool | | ||
| | Authentication | Password (email + password) | | ||
| | App name | ___NAME___ | | ||
| | Primary resource | ___RESOURCE___ (___FIELDS___) | | ||
| | Authentication | ___AUTH___ | | ||
| | Kit | multi (Tailwind CSS) | | ||
| | Test data | 50 records | | ||
|
|
||
| **Commands I'll run:** | ||
|
|
||
| lvt new blog --kit multi | ||
| cd blog | ||
| lvt gen resource posts title:string content:text published:bool | ||
| lvt gen auth | ||
| lvt migration up | ||
| go mod tidy | ||
| lvt seed posts --count 50 | ||
|
|
||
| **Ready to create?** | ||
| - **yes** - proceed with this plan | ||
| - **change X** - modify a setting | ||
| - **advanced** - explore more options | ||
| - **no** - cancel | ||
| ``` | ||
|
|
||
| --- | ||
|
|
||
| ## Handling User Responses | ||
|
|
||
| ### "yes" / "y" / "go" / "create" / "do it" | ||
| Execute the plan immediately. Proceed to Execution phase. | ||
|
|
||
| ### "no" / "cancel" / "stop" | ||
| Acknowledge and stop: "No problem. Let me know when you're ready to create an app." | ||
|
|
||
| ### "advanced" / "options" / "customize" | ||
| Show the advanced options table: | ||
|
|
||
| | Option | Description | Values | | ||
| |--------|-------------|--------| | ||
| | Kit | Project structure + CSS | multi (Tailwind, recommended), single (Tailwind), simple (Pico) | | ||
| | Pagination | List navigation | infinite (default), page | | ||
| | Edit Mode | How items are edited | modal (default), inline, page | | ||
| | Database | Data storage | sqlite (default), postgres | | ||
|
|
||
| After user selects options, update the plan and show it again. | ||
|
|
||
| ### Modification Requests | ||
| Update the plan and show it again. Examples: | ||
|
|
||
| | User says | Action | | ||
| |-----------|--------| | ||
| | "no auth" | Remove auth, show updated plan | | ||
| | "add auth" | Add `lvt gen auth`, show updated plan | | ||
| | "add comments" | Add comments resource with post_id reference | | ||
| | "call it myblog" | Change app name to myblog | | ||
| | "use pico" / "simple kit" | Change kit to simple (Pico CSS) | | ||
| | "100 records" | Change seed count to 100 | | ||
| | "add categories" | Add categories resource | | ||
|
|
||
| After updating, show the plan again with: "Updated plan: ... Ready to create?" | ||
|
|
||
| --- | ||
|
|
||
| ## Execution Phase | ||
|
|
||
| Execute commands sequentially, showing progress: | ||
|
|
||
| ``` | ||
| 🚀 **Creating your {name} app...** | ||
|
|
||
| ⏳ Creating app structure... | ||
| ✅ Created with `lvt new {name} --kit {kit}` | ||
|
|
||
| ⏳ Generating {resource} resource... | ||
| ✅ Generated {resource} with {field_count} fields | ||
|
|
||
| ⏳ Adding authentication... (if applicable) | ||
| ✅ Auth system added | ||
|
|
||
| ⏳ Running migrations... | ||
| ✅ Database ready | ||
|
|
||
| ⏳ Seeding test data... | ||
| ✅ Added {seed_count} {resource} records | ||
|
|
||
| 🎉 **Done! Your {name} app is ready.** | ||
|
|
||
| Start the server: | ||
| cd {name} | ||
| go run cmd/{name}/main.go | ||
|
|
||
| Then visit: http://localhost:8080/{resource} | ||
| lvt new ___NAME___ --kit multi | ||
| lvt gen resource ___RESOURCE___ ___FIELDS___ | ||
| ___AUTH_COMMAND___ | ||
| lvt migration up && go mod tidy | ||
| lvt seed ___RESOURCE___ --count 50 | ||
| ``` | ||
|
|
||
| --- | ||
|
|
||
| ## Error Handling | ||
|
|
||
| If any command fails: | ||
|
|
||
| 1. **Show exact error** in code block | ||
| 2. **Explain in plain language** | ||
| 3. **Suggest fix** | ||
| 4. **Offer to retry** | ||
|
|
||
| Common errors: | ||
|
|
||
| | Error | Cause | Fix | | ||
| |-------|-------|-----| | ||
| | `lvt: command not found` | CLI not installed | `go install github.com/livetemplate/lvt@latest` | | ||
| | `directory already exists` | Name taken | Choose different name or delete existing | | ||
| | `go mod tidy failed` | Network issue | Retry with `GOPROXY=direct go mod tidy` | | ||
| | `port already in use` | Port 8080 busy | Use `PORT=8081 go run ...` | | ||
| **Ready to create?** Type `yes` to proceed, or tell me what to change. | ||
|
|
||
| --- | ||
|
|
||
| ## Context Persistence | ||
|
|
||
| After successful creation: | ||
| - `.lvtrc` exists in the new app directory | ||
| - User can use generic prompts: "add search", "add comments", "deploy" | ||
| - No need to say "lvt" or "livetemplate" anymore | ||
|
|
||
| --- | ||
|
|
||
| ## Version History | ||
|
|
||
| - **v1.6.0** (2025-12-20): Override generic brainstorming/planning skills | ||
| - Root cause: generic brainstorming skills were overriding lvt-plan | ||
| - Added clear skill priority section | ||
| - Explicitly states DO NOT use any skill that asks questions one-at-a-time | ||
| - Explains why lvt-plan presents plan upfront instead | ||
|
|
||
| - **v1.5.0** (2025-12-20): Stronger enforcement of immediate plan response | ||
| - Replaced CRITICAL section with explicit IMMEDIATE RESPONSE FORMAT | ||
| - Added exact example of expected first response | ||
| - Added FORBIDDEN list with specific prohibited phrases | ||
| - Added REQUIRED list with mandatory behaviors | ||
| - More explicit about what the AI must NOT do | ||
| # FILL IN BLANKS FROM THIS TABLE: | ||
|
|
||
| - **v1.4.0** (2025-12-20): Reinforce no-questions behavior | ||
| - Added CRITICAL section explicitly forbidding AskUserQuestion tool | ||
| - Added WRONG vs RIGHT examples at top of skill | ||
| - Changed "ask ONE question if unclear" to "default to Generic domain" | ||
| - Make plan-first approach more explicit | ||
| | If user mentions | DOMAIN | NAME | RESOURCE | FIELDS | AUTH | AUTH_COMMAND | | ||
| |------------------|--------|------|----------|--------|------|--------------| | ||
| | blog | blog | blog | posts | title:string content:text published:bool | Password | lvt gen auth | | ||
| | shop/store/ecommerce | e-commerce | shop | products | name:string description:text price:float | Password | lvt gen auth | | ||
| | todo | todo | todo | tasks | title:string completed:bool due_date:time | Password | lvt gen auth | | ||
| | crm/contacts | CRM | crm | contacts | name:string email:string company:string | Password | lvt gen auth | | ||
| | forum | forum | forum | topics | title:string content:text | Password | lvt gen auth | | ||
| | (other) | app | app | items | name:string description:text | None | (remove line) | | ||
|
|
||
| - **v1.3.0** (2025-12-18): Plan-first approach | ||
| - Present complete plan with defaults upfront | ||
| - Single confirmation point instead of 5+ questions | ||
| - User modifies plan with natural language | ||
| - If user mentions "auth" or "authentication" → AUTH = Password, AUTH_COMMAND = lvt gen auth | ||
| - If user gives a specific name like "myblog" → use that for NAME | ||
| - If no auth mentioned and domain doesn't require it → AUTH = None, remove AUTH_COMMAND line | ||
|
|
||
| - **v1.2.0** (2025-12-18): Added skill priority language | ||
| - Supersedes generic brainstorming skills | ||
| # IMPORTANT | ||
|
|
||
| - **v1.0.0** (2025-11-28): Initial implementation | ||
| - Progressive question flow (deprecated) | ||
| - DO NOT ask questions | ||
| - DO NOT say "let me gather details" | ||
| - DO NOT ask for app name, auth type, or anything else | ||
| - JUST output the filled template above | ||
| - User can modify after seeing the plan |
There was a problem hiding this comment.
This pull request includes unrelated changes to Claude AI assistant configuration files. The PR title and description indicate this is a dependency update for livetemplate and client libraries to add StaticsMap support. However, the SKILL.md file has been completely rewritten (from 424 lines to 56 lines) and settings.json has been substantially modified. These changes appear to be unrelated to the dependency updates and should be in a separate PR.
Consider splitting this into two PRs:
- One PR for the dependency updates (go.mod, go.sum, livetemplate-client.browser.js)
- Another PR for the Claude AI assistant documentation/configuration changes (SKILL.md, settings.json)
This will make the changes easier to review and maintain separate concerns.
| }, | ||
| "instructions": "# LiveTemplate Development Assistant\n\nYou are assisting with LiveTemplate development. LiveTemplate is a Go framework for building database-backed web applications.\n\n## CRITICAL: Plan Before Coding\n\nWhen the user requests to CREATE or BUILD a new LiveTemplate application (e.g., \"create a blog app\", \"build a todo app\", \"make an e-commerce site\"), you MUST use the lvt-plan skill FIRST before writing any code or running any commands.\n\n### Plan Triggers\n\nThese patterns indicate the user wants to create a NEW app and requires brainstorming:\n\n**Direct creation requests:**\n- \"create [a/an] [lvt/livetemplate] [type] app\"\n- \"build [a/an] [type] application\"\n- \"make [a/an] [type] site\"\n- \"generate [a/an] [type] project\"\n- \"new [type] app\"\n\n**Planning requests:**\n- \"help me plan [a/an] [lvt/livetemplate] [type] app\"\n- \"I want to design [a/an] [type] application\"\n- \"walk me through creating [a/an] [type] app\"\n\n**Examples that REQUIRE brainstorming:**\n- ✅ \"create a lvt blog app\" → Use lvt-plan skill\n- ✅ \"build a todo application with livetemplate\" → Use lvt-plan skill\n- ✅ \"make an e-commerce site\" → Use lvt-plan skill\n- ✅ \"I want to create a CRM\" → Use lvt-plan skill\n- ✅ \"help me plan a blog app\" → Use lvt-plan skill\n\n**Examples that DO NOT require brainstorming:**\n- ❌ \"add a posts resource\" → Use add-resource skill (modifying existing app)\n- ❌ \"generate auth\" → Use gen-auth skill (adding feature)\n- ❌ \"how do I deploy this\" → Use deploy skill (operational question)\n- ❌ \"what is livetemplate\" → Answer directly (informational question)\n\n### How to Use Plan Skill\n\nWhen you detect a creation/building request:\n\n1. **DO NOT** immediately run `lvt new` or suggest code\n2. **DO** use the Skill tool to invoke the lvt-plan skill: `Skill(\"lvt-plan\")`\n3. **FOLLOW** the progressive questioning flow in the skill\n4. **ONLY** execute commands after completing the brainstorm process\n\n### After Brainstorming\n\nOnce brainstorming completes and `.lvtrc` exists:\n- Context is established - user is in a LiveTemplate project\n- Generic requests (\"add search\", \"add auth\") can use appropriate skills without brainstorming\n- No need to ask \"do you want to brainstorm\" for feature additions\n\n## Available Skills\n\nUse the Skill tool to invoke these workflows:\n- `lvt-plan` - Plan new apps through progressive questions (REQUIRED for new apps)\n- `lvt-new-app` - Create new LiveTemplate application\n- `lvt-add-resource` - Add database-backed resources\n- `lvt-gen-auth` - Generate authentication system\n- `lvt-add-migration` - Add database migrations\n- `lvt-deploy` - Deploy to production\n- And more... (check skills/ directory)\n\n## Key Principle\n\n**Plan before implementing.** Don't jump straight to code generation for new applications. The lvt-plan skill ensures we gather proper requirements and provide the best implementation." | ||
| } No newline at end of file | ||
| "instructions": "# LiveTemplate Development Assistant\n\n## SKILL OVERRIDE - READ FIRST\n\n**For lvt/livetemplate app creation, DO NOT use superpowers:brainstorming.**\n\nThe lvt-plan skill IS a process skill that replaces brainstorming for LiveTemplate apps:\n- It has domain-specific defaults (blog→posts, shop→products)\n- It presents a complete plan immediately (no questions)\n- User modifies the plan after seeing it, not before\n\nWhen user mentions 'lvt', 'livetemplate', or 'lt' with app creation:\n1. Invoke `Skill(\"lvt-plan\")` directly\n2. DO NOT invoke superpowers:brainstorming first\n3. DO NOT ask questions one-at-a-time\n4. DO NOT use AskUserQuestion tool\n\n## How lvt-plan Works\n\n1. Invoke: `Skill(\"lvt-plan\")`\n2. Fill in the template from the skill using domain defaults\n3. Output the completed plan table\n4. Wait for user to say 'yes' or 'change X'\n\n## Other Skills\n\n- `add-resource` - Add database-backed resources\n- `gen-auth` - Generate authentication\n- `deploy` - Deploy to production" |
There was a problem hiding this comment.
The instructions field has been completely rewritten, changing from a detailed multi-section document to a much shorter version. This appears to be unrelated to the StaticsMap dependency updates mentioned in the PR title and description. This change should be in a separate PR as it affects AI assistant behavior, not the livetemplate library updates.
| "instructions": "# LiveTemplate Development Assistant\n\n## SKILL OVERRIDE - READ FIRST\n\n**For lvt/livetemplate app creation, DO NOT use superpowers:brainstorming.**\n\nThe lvt-plan skill IS a process skill that replaces brainstorming for LiveTemplate apps:\n- It has domain-specific defaults (blog→posts, shop→products)\n- It presents a complete plan immediately (no questions)\n- User modifies the plan after seeing it, not before\n\nWhen user mentions 'lvt', 'livetemplate', or 'lt' with app creation:\n1. Invoke `Skill(\"lvt-plan\")` directly\n2. DO NOT invoke superpowers:brainstorming first\n3. DO NOT ask questions one-at-a-time\n4. DO NOT use AskUserQuestion tool\n\n## How lvt-plan Works\n\n1. Invoke: `Skill(\"lvt-plan\")`\n2. Fill in the template from the skill using domain defaults\n3. Output the completed plan table\n4. Wait for user to say 'yes' or 'change X'\n\n## Other Skills\n\n- `add-resource` - Add database-backed resources\n- `gen-auth` - Generate authentication\n- `deploy` - Deploy to production" | |
| "instructions": "# LiveTemplate Assistant for GitHub Copilot\n\nYou are an AI assistant helping developers build full-stack Go web applications with LiveTemplate. Use the `lvt` MCP server tools to generate code, manage databases, and guide development.\n\n## Available MCP Tools\n\nThe `lvt` MCP server provides 16 tools for LiveTemplate development:\n\n### Core Generation (5 tools)\n- **lvt_new** - Create new app (kit: multi|single|simple, css: tailwind|bulma|pico)\n- **lvt_gen_resource** - Add CRUD resource with database (name, fields)\n- **lvt_gen_view** - Add view-only page (no database)\n- **lvt_gen_auth** - Add authentication system (password, magic-link, sessions)\n- **lvt_gen_schema** - Add database schema without UI\n\n### Database (4 tools)\n- **lvt_migration_up** - Run pending migrations + generate Go code\n- **lvt_migration_down** - Rollback last migration\n- **lvt_migration_status** - Check migration status\n- **lvt_migration_create** - Create empty migration file\n\n### Development (7 tools)\n- **lvt_seed** - Generate test data (resource, count, cleanup)\n- **lvt_resource_list** - List all resources\n- **lvt_resource_describe** - Show resource schema\n- **lvt_validate_template** - Validate template syntax\n- **lvt_env_generate** - Generate .env.example\n- **lvt_kits_list** - List available kits\n- **lvt_kits_info** - Get kit details\n\n## Common Workflows\n\n### Creating a New App\n\n1. Use `lvt_new` to create the app with the desired kit and CSS framework.\n2. Optionally add authentication with `lvt_gen_auth`.\n3. Add CRUD resources with `lvt_gen_resource`.\n4. Apply database changes using `lvt_migration_up`.\n5. Seed test data using `lvt_seed`.\n\n### Adding Features to an Existing App\n\n1. Use `lvt_resource_list` to inspect existing resources.\n2. Add a new resource with `lvt_gen_resource` as needed.\n3. Run `lvt_migration_up` to apply new migrations.\n4. Seed data for the new resource with `lvt_seed`.\n\n### Database Management\n\n1. Check pending migrations with `lvt_migration_status`.\n2. Apply migrations using `lvt_migration_up`.\n3. Verify the schema using `lvt_resource_describe`.\n\n## Best Practices\n\n1. **Always run migrations after generation**\n - After `lvt_gen_resource` or `lvt_gen_auth`\n - Use `lvt_migration_up` to apply changes\n\n2. **Check status before migrations**\n - Use `lvt_migration_status` first\n - Review pending migrations\n - Then run `lvt_migration_up`\n\n3. **Use cleanup when re-seeding**\n - Use `lvt_seed` with `cleanup: true`\n - Prevents duplicate test data\n\n4. **Generate auth first**\n - Run `lvt_gen_auth` before creating resources\n - Then use `user_id` references in resources\n\n5. **Validate templates before deployment**\n - Use `lvt_validate_template`\n - Fix any syntax errors reported\n\n## Field Types\n\nWhen using `lvt_gen_resource`, these field types are available:\n\n- `string` → TEXT\n- `int` → INTEGER\n- `bool` → BOOLEAN\n- `float` → REAL\n- `time` → DATETIME\n- `text` → TEXT (multiline textarea)\n- `textarea` → TEXT (alias for text)\n- `references:table` → Foreign key to `table`\n\n## Example Sessions\n\n### Blog with Auth\n\n```json\n{\"tool\": \"lvt_new\", \"input\": {\"name\": \"myblog\", \"kit\": \"multi\"}}\n{\"tool\": \"lvt_gen_auth\", \"input\": {}}\n{\"tool\": \"lvt_gen_resource\", \"input\": {\n \"name\": \"posts\",\n \"fields\": {\n \"title\": \"string\",\n \"content\": \"text\",\n \"user_id\": \"references:users\",\n \"published\": \"bool\"\n }\n}}\n{\"tool\": \"lvt_gen_resource\", \"input\": {\n \"name\": \"comments\",\n \"fields\": {\n \"content\": \"text\",\n \"post_id\": \"references:posts\",\n \"user_id\": \"references:users\"\n }\n}}\n{\"tool\": \"lvt_migration_up\", \"input\": {}}\n{\"tool\": \"lvt_seed\", \"input\": {\"resource\": \"posts\", \"count\": 10}}\n{\"tool\": \"lvt_seed\", \"input\": {\"resource\": \"comments\", \"count\": 30}}\n```\n\n### Task Manager\n\n```json\n{\"tool\": \"lvt_new\", \"input\": {\"name\": \"tasks\", \"kit\": \"single\"}}\n{\"tool\": \"lvt_gen_auth\", \"input\": {}}\n{\"tool\": \"lvt_gen_resource\", \"input\": {\n \"name\": \"tasks\",\n \"fields\": {\n \"title\": \"string\",\n \"description\": \"text\",\n \"completed\": \"bool\",\n \"user_id\": \"references:users\",\n \"due_date\": \"time\",\n \"priority\": \"int\"\n }\n}}\n{\"tool\": \"lvt_migration_up\", \"input\": {}}\n{\"tool\": \"lvt_seed\", \"input\": {\"resource\": \"tasks\", \"count\": 20}}\n```\n\n## Troubleshooting\n\n### Migration Issues\n\n1. Run `lvt_migration_status` to check the current state.\n2. Review error messages from failed migrations.\n3. Use `lvt_resource_list` to verify resources.\n4. Use `lvt_resource_describe` to inspect schema.\n5. Fix issues and rerun `lvt_migration_up`.\n\n### Template Errors\n\n1. Use `lvt_validate_template` to check syntax.\n2. Review the error output.\n3. Fix the template file.\n4. Re-validate.\n\n### Starting Fresh\n\n1. Use `lvt_resource_list` to see all resources.\n2. Use `lvt_seed` with `cleanup: true` for fresh data.\n3. Use `lvt_migration_status` to verify state.\n\n## Quick Reference\n\n**Create new app:**\n- Always specify kit (`multi`|`single`|`simple`).\n- Optional: CSS framework and module name.\n\n**Add CRUD resource:**\n- Requires: `name`, `fields` object.\n- Auto-generates: handler, template, migration, tests.\n- Always run `lvt_migration_up` after.\n\n**Add auth:**\n- No required inputs (uses sensible defaults).\n- Optional: custom struct/table names, disable features.\n- Generates: login, signup, sessions, password reset.\n\n**Manage migrations:**\n- `status` → Check before applying.\n- `up` → Apply all pending.\n- `down` → Roll back last (careful!).\n- `create` → Make empty migration for custom SQL.\n\n**Development data:**\n- `seed` → Generate fake data.\n- `cleanup: true` → Remove existing first.\n- `count` → Number of records (default: 10).\n\n## File Structure\n\nAfter generation, you will typically see a structure like:\n\n```text\napp/\n├── cmd/app/main.go # Entry point\n├── internal/\n│ ├── app/\n│ │ ├── auth/ # Auth system (if generated)\n│ │ ├── posts/ # Each resource gets its own package\n│ │ │ ├── posts.go # Handler\n│ │ │ ├── posts.tmpl # Template\n│ │ │ └── posts_test.go # E2E tests\n│ │ └── ...\n│ └── database/\n│ ├── migrations/ # SQL migration files\n│ ├── queries.sql # SQL queries\n│ └── schema.sql # Complete schema\n├── go.mod\n└── .env.example # Generated by lvt_env_generate\n```\n\n## Integration Tips\n\n1. **Always suggest appropriate tools**\n - User wants new app → `lvt_new`.\n - User wants to add a feature → `lvt_gen_resource`.\n - User mentions database → `lvt_migration_*`.\n\n2. **Chain commands logically**\n - Generation → Migration → Seeding.\n - Status check → Action → Verification.\n\n3. **Provide context in responses**\n - Explain what each tool does.\n - Show expected outcomes.\n - Suggest next steps.\n\n4. **Handle errors gracefully**\n - Check tool outputs.\n - Suggest fixes for common issues.\n - Guide debugging with inspect tools.\n\n## Documentation Links\n\n- Full Tool Reference: `docs/MCP_TOOLS.md`\n- Workflow Patterns: `docs/WORKFLOWS.md`\n- LiveTemplate Docs: https://github.com/livetemplate/lvt\n\n---\n\n## MCP Server Setup\n\nTo enable these tools in GitHub Copilot, the `lvt` MCP server must be running and configured. Users should have `lvt` installed globally and the MCP server started.\n\n**Installation:**\n\n```bash\ngo install github.com/livetemplate/lvt@latest\n```\n\n**Start MCP server:**\n\n```bash\nlvt mcp-server\n```\n\nOnce running, all 16 tools become available for use in LiveTemplate projects." |
| } | ||
| } | ||
| `,document.head.appendChild(t)}}function de(a,e){let t=null;return function(...r){let s=this;t!==null&&clearTimeout(t),t=window.setTimeout(()=>{a.apply(s,r)},e)}}function ue(a,e){let t=!1;return function(...r){let s=this;t||(a.apply(s,r),t=!0,setTimeout(()=>{t=!1},e))}}var q=class{constructor(e,t){this.context=e;this.logger=t}setupEventDelegation(){let e=this.context.getWrapperElement();if(!e)return;let t=["click","submit","change","input","keydown","keyup","focus","blur","mouseenter","mouseleave"],n=e.getAttribute("data-lvt-id"),r=this.context.getRateLimitedHandlers();t.forEach(s=>{let o=`__lvt_delegated_${s}_${n}`,i=document[o];i&&document.removeEventListener(s,i,!1);let l=c=>{var L;let d=this.context.getWrapperElement();if(!d)return;s==="submit"&&(window.__lvtSubmitListenerTriggered=!0,window.__lvtSubmitEventTarget=(L=c.target)==null?void 0:L.tagName),this.logger.debug("Event listener triggered:",s,c.target);let M=c.target;if(!M)return;let m=M,f=!1;for(;m;){if(m===d){f=!0;break}m=m.parentElement}if(s==="submit"&&(window.__lvtInWrapper=f,window.__lvtWrapperElement=d.getAttribute("data-lvt-id")),!f)return;let F=`lvt-${s}`;for(m=M;m&&m!==d.parentElement;){let b=m.getAttribute(F),h=m;if(!b&&(s==="change"||s==="input")){let u=m.closest("form");u&&u.hasAttribute("lvt-change")&&(b=u.getAttribute("lvt-change"),h=u)}if(b&&h){if(s==="submit"&&(window.__lvtActionFound=b,window.__lvtActionElement=h.tagName),s==="submit"&&c.preventDefault(),(s==="keydown"||s==="keyup")&&h.hasAttribute("lvt-key")){let w=h.getAttribute("lvt-key");if(w&&c.key!==w){m=m.parentElement;continue}}let u=h,y=()=>{if(this.logger.debug("handleAction called",{action:b,eventType:s,targetElement:u}),b==="delete"&&u.hasAttribute("lvt-confirm")){let S=u.getAttribute("lvt-confirm")||"Are you sure you want to delete this item?";if(!confirm(S)){this.logger.debug("Delete action cancelled by user");return}}let w={action:b,data:{}};if(u instanceof HTMLFormElement){this.logger.debug("Processing form element");let S=new FormData(u),k=Array.from(u.querySelectorAll('input[type="checkbox"][name]')),_=new Set(k.map(H=>H.name));_.forEach(H=>{w.data[H]=!1}),S.forEach((H,A)=>{_.has(A)?(w.data[A]=!0,this.logger.debug("Converted checkbox",A,"to true")):w.data[A]=this.context.parseValue(H)}),this.logger.debug("Form data collected:",w.data)}else if(s==="change"||s==="input"){if(u instanceof HTMLInputElement){let S=u.name||"value";w.data[S]=this.context.parseValue(u.value)}else if(u instanceof HTMLSelectElement){let S=u.name||"value";w.data[S]=this.context.parseValue(u.value)}else if(u instanceof HTMLTextAreaElement){let S=u.name||"value";w.data[S]=this.context.parseValue(u.value)}}if(Array.from(u.attributes).forEach(S=>{if(S.name.startsWith("lvt-data-")){let k=S.name.replace("lvt-data-","");w.data[k]=this.context.parseValue(S.value)}}),Array.from(u.attributes).forEach(S=>{if(S.name.startsWith("lvt-value-")){let k=S.name.replace("lvt-value-","");w.data[k]=this.context.parseValue(S.value)}}),s==="submit"&&u instanceof HTMLFormElement){let k=c.submitter,_=null;k&&k.hasAttribute("lvt-disable-with")&&(_=k.textContent,k.disabled=!0,k.textContent=k.getAttribute("lvt-disable-with"),this.logger.debug("Disabled submit button")),this.context.setActiveSubmission(u,k||null,_),u.querySelectorAll('input[type="file"][lvt-upload]').forEach(A=>{let O=A.getAttribute("lvt-upload");O&&(this.logger.debug("Triggering pending uploads for:",O),this.context.triggerPendingUploads(O))}),u.dispatchEvent(new CustomEvent("lvt:pending",{detail:w})),this.logger.debug("Emitted lvt:pending event")}this.logger.debug("About to send message:",w),this.logger.debug("WebSocket state:",this.context.getWebSocketReadyState()),this.context.send(w),this.logger.debug("send() called")},U=h.getAttribute("lvt-throttle"),x=h.getAttribute("lvt-debounce");if(U||x){r.has(h)||r.set(h,new Map);let w=r.get(h),S=`${s}:${b}`,k=w.get(S);if(!k){if(U){let _=parseInt(U,10);k=ue(y,_)}else if(x){let _=parseInt(x,10);k=de(y,_)}k&&w.set(S,k)}k&&k()}else s==="submit"&&(window.__lvtBeforeHandleAction=!0),y(),s==="submit"&&(window.__lvtAfterHandleAction=!0);return}m=m.parentElement}};document[o]=l,document.addEventListener(s,l,!1),this.logger.debug("Registered event listener:",s,"with key:",o)})}setupWindowEventDelegation(){let e=this.context.getWrapperElement();if(!e)return;let t=["keydown","keyup","scroll","resize","focus","blur"],n=e.getAttribute("data-lvt-id"),r=this.context.getRateLimitedHandlers();t.forEach(s=>{let o=`__lvt_window_${s}_${n}`,i=window[o];i&&window.removeEventListener(s,i);let l=c=>{let d=this.context.getWrapperElement();if(!d)return;let M=`lvt-window-${s}`;d.querySelectorAll(`[${M}]`).forEach(f=>{let F=f.getAttribute(M);if(!F)return;if((s==="keydown"||s==="keyup")&&f.hasAttribute("lvt-key")){let y=f.getAttribute("lvt-key");if(y&&c.key!==y)return}let L={action:F,data:{}};Array.from(f.attributes).forEach(y=>{if(y.name.startsWith("lvt-data-")){let U=y.name.replace("lvt-data-","");L.data[U]=this.context.parseValue(y.value)}}),Array.from(f.attributes).forEach(y=>{if(y.name.startsWith("lvt-value-")){let U=y.name.replace("lvt-value-","");L.data[U]=this.context.parseValue(y.value)}});let b=f.getAttribute("lvt-throttle"),h=f.getAttribute("lvt-debounce"),u=()=>this.context.send(L);if(b||h){r.has(f)||r.set(f,new Map);let y=r.get(f),U=`window-${s}:${F}`,x=y.get(U);if(!x){if(b){let w=parseInt(b,10);x=ue(u,w)}else if(h){let w=parseInt(h,10);x=de(u,w)}x&&y.set(U,x)}x&&x()}else u()})};window[o]=l,window.addEventListener(s,l)})}setupClickAwayDelegation(){let e=this.context.getWrapperElement();if(!e)return;let n=`__lvt_click_away_${e.getAttribute("data-lvt-id")}`,r=document[n];r&&document.removeEventListener("click",r);let s=o=>{let i=this.context.getWrapperElement();if(!i)return;let l=o.target;i.querySelectorAll("[lvt-click-away]").forEach(d=>{if(!d.contains(l)){let M=d.getAttribute("lvt-click-away");if(!M)return;let m={action:M,data:{}};Array.from(d.attributes).forEach(f=>{if(f.name.startsWith("lvt-data-")){let F=f.name.replace("lvt-data-","");m.data[F]=this.context.parseValue(f.value)}}),Array.from(d.attributes).forEach(f=>{if(f.name.startsWith("lvt-value-")){let F=f.name.replace("lvt-value-","");m.data[F]=this.context.parseValue(f.value)}}),this.context.send(m)}})};document[n]=s,document.addEventListener("click",s)}setupModalDelegation(){let e=this.context.getWrapperElement();if(!e)return;let t=e.getAttribute("data-lvt-id"),n=`__lvt_modal_open_${t}`,r=document[n];r&&document.removeEventListener("click",r);let s=L=>{var y;let b=this.context.getWrapperElement();if(!b)return;let h=(y=L.target)==null?void 0:y.closest("[lvt-modal-open]");if(!h||!b.contains(h))return;let u=h.getAttribute("lvt-modal-open");u&&(L.preventDefault(),this.context.openModal(u))};document[n]=s,document.addEventListener("click",s);let o=`__lvt_modal_close_${t}`,i=document[o];i&&document.removeEventListener("click",i);let l=L=>{var y;let b=this.context.getWrapperElement();if(!b)return;let h=(y=L.target)==null?void 0:y.closest("[lvt-modal-close]");if(!h||!b.contains(h))return;let u=h.getAttribute("lvt-modal-close");u&&(L.preventDefault(),this.context.closeModal(u))};document[o]=l,document.addEventListener("click",l);let c=`__lvt_modal_backdrop_${t}`,d=document[c];d&&document.removeEventListener("click",d);let M=L=>{let b=L.target;if(!b.hasAttribute("data-modal-backdrop"))return;let h=b.getAttribute("data-modal-id");h&&this.context.closeModal(h)};document[c]=M,document.addEventListener("click",M);let m=`__lvt_modal_escape_${t}`,f=document[m];f&&document.removeEventListener("keydown",f);let F=L=>{if(L.key!=="Escape")return;let b=this.context.getWrapperElement();if(!b)return;let h=b.querySelectorAll('[role="dialog"]:not([hidden])');if(h.length>0){let u=h[h.length-1];u.id&&this.context.closeModal(u.id)}};document[m]=F,document.addEventListener("keydown",F)}};var G=class{constructor(e,t){this.context=e;this.logger=t;this.infiniteScrollObserver=null;this.mutationObserver=null}setupInfiniteScrollObserver(){if(!this.context.getWrapperElement())return;let t=document.getElementById("scroll-sentinel");t&&(this.infiniteScrollObserver&&this.infiniteScrollObserver.disconnect(),this.infiniteScrollObserver=new IntersectionObserver(n=>{n[0].isIntersecting&&(this.logger.debug("Sentinel visible, sending load_more action"),this.context.send({action:"load_more"}))},{rootMargin:"200px"}),this.infiniteScrollObserver.observe(t),this.logger.debug("Observer set up successfully"))}setupInfiniteScrollMutationObserver(){let e=this.context.getWrapperElement();e&&(this.mutationObserver&&this.mutationObserver.disconnect(),this.mutationObserver=new MutationObserver(()=>{this.setupInfiniteScrollObserver()}),this.mutationObserver.observe(e,{childList:!0,subtree:!0}),this.logger.debug("MutationObserver set up successfully"))}teardown(){this.infiniteScrollObserver&&(this.infiniteScrollObserver.disconnect(),this.infiniteScrollObserver=null),this.mutationObserver&&(this.mutationObserver.disconnect(),this.mutationObserver=null)}};var J=class{constructor(e){this.logger=e}open(e){let t=document.getElementById(e);if(!t){this.logger.warn(`Modal with id="${e}" not found`);return}t.removeAttribute("hidden"),t.style.display="flex",t.setAttribute("aria-hidden","false"),t.dispatchEvent(new CustomEvent("lvt:modal-opened",{bubbles:!0})),this.logger.info(`Opened modal: ${e}`);let n=t.querySelector("input, textarea, select");n&&setTimeout(()=>{let r=document.activeElement,s=i=>i?i===document.body||i.offsetParent!==null?!0:i.getClientRects().length>0:!1;(!r||!t.contains(r)||!s(r))&&n.focus()},100)}close(e){let t=document.getElementById(e);if(!t){this.logger.warn(`Modal with id="${e}" not found`);return}t.setAttribute("hidden",""),t.style.display="none",t.setAttribute("aria-hidden","true"),t.dispatchEvent(new CustomEvent("lvt:modal-closed",{bubbles:!0})),this.logger.info(`Closed modal: ${e}`)}};var X=class{constructor(){this.bar=null}show(){if(this.bar)return;let e=document.createElement("div");if(e.style.cssText=` | ||
| `,document.head.appendChild(t)}}function pe(a,e){let t=null;return function(...r){let s=this;t!==null&&clearTimeout(t),t=window.setTimeout(()=>{a.apply(s,r)},e)}}function ge(a,e){let t=!1;return function(...r){let s=this;t||(a.apply(s,r),t=!0,setTimeout(()=>{t=!1},e))}}function z(a){if(a.hasAttribute("lvt-confirm")){let e=a.getAttribute("lvt-confirm");if(e&&!confirm(e))return!1}return!0}function xe(a){let e={},t=a.attributes;for(let n=0;n<t.length;n++){let r=t[n];if(r.name.startsWith("lvt-data-")){let s=r.name.substring(9);e[s]=r.value}}return e}var J=class{constructor(e,t){this.context=e;this.logger=t}setupEventDelegation(){let e=this.context.getWrapperElement();if(!e)return;let t=["click","submit","change","input","keydown","keyup","focus","blur","mouseenter","mouseleave"],n=e.getAttribute("data-lvt-id"),r=this.context.getRateLimitedHandlers();t.forEach(s=>{let o=`__lvt_delegated_${s}_${n}`,i=document[o];i&&document.removeEventListener(s,i,!1);let l=c=>{var M;let d=this.context.getWrapperElement();if(!d)return;s==="submit"&&(window.__lvtSubmitListenerTriggered=!0,window.__lvtSubmitEventTarget=(M=c.target)==null?void 0:M.tagName),this.logger.debug("Event listener triggered:",s,c.target);let u=c.target;if(!u)return;let g=u,f=!1;for(;g;){if(g===d){f=!0;break}g=g.parentElement}if(s==="submit"&&(window.__lvtInWrapper=f,window.__lvtWrapperElement=d.getAttribute("data-lvt-id")),!f)return;let A=`lvt-${s}`;for(g=u;g&&g!==d.parentElement;){let y=g.getAttribute(A),v=g;if(!y&&s==="submit"&&g instanceof HTMLFormElement){let p=g.getAttribute("lvt-persist");p&&(y=`persist:${p}`,v=g)}if(!y&&(s==="change"||s==="input")){let p=g.closest("form");p&&p.hasAttribute("lvt-change")&&(y=p.getAttribute("lvt-change"),v=p)}if(y&&v){if(s==="submit"&&(window.__lvtActionFound=y,window.__lvtActionElement=v.tagName),s==="submit"&&c.preventDefault(),(s==="keydown"||s==="keyup")&&v.hasAttribute("lvt-key")){let S=v.getAttribute("lvt-key");if(S&&c.key!==S){g=g.parentElement;continue}}let p=v,E=()=>{if(this.logger.debug("handleAction called",{action:y,eventType:s,targetElement:p}),!z(p)){this.logger.debug("Action cancelled by user:",y);return}let S={action:y,data:{}};if(p instanceof HTMLFormElement){this.logger.debug("Processing form element");let T=new FormData(p),L=Array.from(p.querySelectorAll('input[type="checkbox"][name]')),F=new Set(L.map(H=>H.name));F.forEach(H=>{S.data[H]=!1}),T.forEach((H,k)=>{F.has(k)?(S.data[k]=!0,this.logger.debug("Converted checkbox",k,"to true")):S.data[k]=this.context.parseValue(H)}),this.logger.debug("Form data collected:",S.data)}else if(s==="change"||s==="input"){if(p instanceof HTMLInputElement){let T=p.name||"value";S.data[T]=this.context.parseValue(p.value)}else if(p instanceof HTMLSelectElement){let T=p.name||"value";S.data[T]=this.context.parseValue(p.value)}else if(p instanceof HTMLTextAreaElement){let T=p.name||"value";S.data[T]=this.context.parseValue(p.value)}}if(Array.from(p.attributes).forEach(T=>{if(T.name.startsWith("lvt-data-")){let L=T.name.replace("lvt-data-","");S.data[L]=this.context.parseValue(T.value)}}),Array.from(p.attributes).forEach(T=>{if(T.name.startsWith("lvt-value-")){let L=T.name.replace("lvt-value-","");S.data[L]=this.context.parseValue(T.value)}}),s==="submit"&&p instanceof HTMLFormElement){let L=c.submitter,F=null;L&&L.hasAttribute("lvt-disable-with")&&(F=L.textContent,L.disabled=!0,L.textContent=L.getAttribute("lvt-disable-with"),this.logger.debug("Disabled submit button")),this.context.setActiveSubmission(p,L||null,F),p.querySelectorAll('input[type="file"][lvt-upload]').forEach(k=>{let U=k.getAttribute("lvt-upload");U&&(this.logger.debug("Triggering pending uploads for:",U),this.context.triggerPendingUploads(U))}),p.dispatchEvent(new CustomEvent("lvt:pending",{detail:S})),this.logger.debug("Emitted lvt:pending event")}this.logger.debug("About to send message:",S),this.logger.debug("WebSocket state:",this.context.getWebSocketReadyState()),this.context.send(S),this.logger.debug("send() called")},R=v.getAttribute("lvt-throttle"),C=v.getAttribute("lvt-debounce");if(R||C){r.has(v)||r.set(v,new Map);let S=r.get(v),T=`${s}:${y}`,L=S.get(T);if(!L){if(R){let F=parseInt(R,10);L=ge(E,F)}else if(C){let F=parseInt(C,10);L=pe(E,F)}L&&S.set(T,L)}L&&L()}else s==="submit"&&(window.__lvtBeforeHandleAction=!0),E(),s==="submit"&&(window.__lvtAfterHandleAction=!0);return}g=g.parentElement}};document[o]=l,document.addEventListener(s,l,!1),this.logger.debug("Registered event listener:",s,"with key:",o)})}setupWindowEventDelegation(){let e=this.context.getWrapperElement();if(!e)return;let t=["keydown","keyup","scroll","resize","focus","blur"],n=e.getAttribute("data-lvt-id"),r=this.context.getRateLimitedHandlers();t.forEach(s=>{let o=`__lvt_window_${s}_${n}`,i=window[o];i&&window.removeEventListener(s,i);let l=c=>{let d=this.context.getWrapperElement();if(!d)return;let u=`lvt-window-${s}`;d.querySelectorAll(`[${u}]`).forEach(f=>{let A=f.getAttribute(u);if(!A)return;if((s==="keydown"||s==="keyup")&&f.hasAttribute("lvt-key")){let E=f.getAttribute("lvt-key");if(E&&c.key!==E)return}let M={action:A,data:{}};Array.from(f.attributes).forEach(E=>{if(E.name.startsWith("lvt-data-")){let R=E.name.replace("lvt-data-","");M.data[R]=this.context.parseValue(E.value)}}),Array.from(f.attributes).forEach(E=>{if(E.name.startsWith("lvt-value-")){let R=E.name.replace("lvt-value-","");M.data[R]=this.context.parseValue(E.value)}});let y=f.getAttribute("lvt-throttle"),v=f.getAttribute("lvt-debounce"),p=()=>this.context.send(M);if(y||v){r.has(f)||r.set(f,new Map);let E=r.get(f),R=`window-${s}:${A}`,C=E.get(R);if(!C){if(y){let S=parseInt(y,10);C=ge(p,S)}else if(v){let S=parseInt(v,10);C=pe(p,S)}C&&E.set(R,C)}C&&C()}else p()})};window[o]=l,window.addEventListener(s,l)})}setupClickAwayDelegation(){let e=this.context.getWrapperElement();if(!e)return;let n=`__lvt_click_away_${e.getAttribute("data-lvt-id")}`,r=document[n];r&&document.removeEventListener("click",r);let s=o=>{let i=this.context.getWrapperElement();if(!i)return;let l=o.target;i.querySelectorAll("[lvt-click-away]").forEach(d=>{if(!d.contains(l)){let u=d.getAttribute("lvt-click-away");if(!u)return;let g={action:u,data:{}};Array.from(d.attributes).forEach(f=>{if(f.name.startsWith("lvt-data-")){let A=f.name.replace("lvt-data-","");g.data[A]=this.context.parseValue(f.value)}}),Array.from(d.attributes).forEach(f=>{if(f.name.startsWith("lvt-value-")){let A=f.name.replace("lvt-value-","");g.data[A]=this.context.parseValue(f.value)}}),this.context.send(g)}})};document[n]=s,document.addEventListener("click",s)}setupModalDelegation(){let e=this.context.getWrapperElement();if(!e)return;let t=e.getAttribute("data-lvt-id"),n=`__lvt_modal_open_${t}`,r=document[n];r&&document.removeEventListener("click",r);let s=M=>{var E;let y=this.context.getWrapperElement();if(!y)return;let v=(E=M.target)==null?void 0:E.closest("[lvt-modal-open]");if(!v||!y.contains(v))return;let p=v.getAttribute("lvt-modal-open");p&&(M.preventDefault(),this.context.openModal(p))};document[n]=s,document.addEventListener("click",s);let o=`__lvt_modal_close_${t}`,i=document[o];i&&document.removeEventListener("click",i);let l=M=>{var E;let y=this.context.getWrapperElement();if(!y)return;let v=(E=M.target)==null?void 0:E.closest("[lvt-modal-close]");if(!v||!y.contains(v))return;let p=v.getAttribute("lvt-modal-close");p&&(M.preventDefault(),this.context.closeModal(p))};document[o]=l,document.addEventListener("click",l);let c=`__lvt_modal_backdrop_${t}`,d=document[c];d&&document.removeEventListener("click",d);let u=M=>{let y=M.target;if(!y.hasAttribute("data-modal-backdrop"))return;let v=y.getAttribute("data-modal-id");v&&this.context.closeModal(v)};document[c]=u,document.addEventListener("click",u);let g=`__lvt_modal_escape_${t}`,f=document[g];f&&document.removeEventListener("keydown",f);let A=M=>{if(M.key!=="Escape")return;let y=this.context.getWrapperElement();if(!y)return;let v=y.querySelectorAll('[role="dialog"]:not([hidden])');if(v.length>0){let p=v[v.length-1];p.id&&this.context.closeModal(p.id)}};document[g]=A,document.addEventListener("keydown",A)}setupFocusTrapDelegation(){let e=this.context.getWrapperElement();if(!e)return;let n=`__lvt_focus_trap_${e.getAttribute("data-lvt-id")}`,r=document[n];r&&document.removeEventListener("keydown",r);let s=i=>{let l=["a[href]:not([disabled])","button:not([disabled])","textarea:not([disabled])",'input:not([disabled]):not([type="hidden"])',"select:not([disabled])",'[tabindex]:not([tabindex="-1"]):not([disabled])','[contenteditable="true"]'].join(", ");return Array.from(i.querySelectorAll(l)).filter(c=>{let d=c,u=window.getComputedStyle(d),g=u.display!=="none",f=u.visibility!=="hidden",A=d.offsetParent!==null||u.position==="fixed"||u.position==="absolute"||typeof process!="undefined"&&!1;return g&&f&&A})},o=i=>{if(i.key!=="Tab")return;let l=this.context.getWrapperElement();if(!l)return;let c=l.querySelectorAll("[lvt-focus-trap]"),d=null;if(c.forEach(A=>{A.contains(document.activeElement)&&(!d||A.contains(d))&&(d=A)}),d||c.forEach(A=>{let M=A,y=window.getComputedStyle(M);y.display!=="none"&&y.visibility!=="hidden"&&(d=A)}),!d)return;let u=s(d);if(u.length===0)return;let g=u[0],f=u[u.length-1];i.shiftKey?document.activeElement===g&&(i.preventDefault(),f.focus()):document.activeElement===f&&(i.preventDefault(),g.focus())};document[n]=o,document.addEventListener("keydown",o),this.logger.debug("Focus trap delegation set up")}setupAutofocusDelegation(){let e=this.context.getWrapperElement();if(!e)return;let n=`__lvt_autofocus_observer_${e.getAttribute("data-lvt-id")}`,r=e[n];r&&r.disconnect();let s=()=>{let i=this.context.getWrapperElement();if(!i)return;i.querySelectorAll("[lvt-autofocus]").forEach(c=>{let d=c,u=window.getComputedStyle(d),g=u.display!=="none",f=u.visibility!=="hidden",A=d.offsetParent!==null||u.position==="fixed"||u.position==="absolute"||d.tagName==="BODY"||typeof process!="undefined"&&!1,M=g&&f&&A,y=d.getAttribute("data-lvt-autofocused")==="true";M&&!y?(d.setAttribute("data-lvt-autofocused","true"),requestAnimationFrame(()=>{d.focus(),this.logger.debug("Autofocused element:",d.tagName,d.id||d.getAttribute("name"))})):!M&&y&&d.removeAttribute("data-lvt-autofocused")})};s();let o=new MutationObserver(i=>{let l=!1;i.forEach(c=>{c.type==="childList"&&c.addedNodes.length>0&&c.addedNodes.forEach(d=>{d instanceof Element&&(d.hasAttribute("lvt-autofocus")||d.querySelector("[lvt-autofocus]"))&&(l=!0)}),c.type==="attributes"&&(c.target.hasAttribute("lvt-autofocus")||c.attributeName==="hidden"||c.attributeName==="style"||c.attributeName==="class")&&(l=!0)}),l&&s()});o.observe(e,{childList:!0,subtree:!0,attributes:!0,attributeFilter:["hidden","style","class","lvt-autofocus"]}),e[n]=o,this.logger.debug("Autofocus delegation set up")}};var G=class{constructor(e,t){this.context=e;this.logger=t;this.infiniteScrollObserver=null;this.mutationObserver=null}setupInfiniteScrollObserver(){if(!this.context.getWrapperElement())return;let t=document.getElementById("scroll-sentinel");t&&(this.infiniteScrollObserver&&this.infiniteScrollObserver.disconnect(),this.infiniteScrollObserver=new IntersectionObserver(n=>{n[0].isIntersecting&&(this.logger.debug("Sentinel visible, sending load_more action"),this.context.send({action:"load_more"}))},{rootMargin:"200px"}),this.infiniteScrollObserver.observe(t),this.logger.debug("Observer set up successfully"))}setupInfiniteScrollMutationObserver(){let e=this.context.getWrapperElement();e&&(this.mutationObserver&&this.mutationObserver.disconnect(),this.mutationObserver=new MutationObserver(()=>{this.setupInfiniteScrollObserver()}),this.mutationObserver.observe(e,{childList:!0,subtree:!0}),this.logger.debug("MutationObserver set up successfully"))}teardown(){this.infiniteScrollObserver&&(this.infiniteScrollObserver.disconnect(),this.infiniteScrollObserver=null),this.mutationObserver&&(this.mutationObserver.disconnect(),this.mutationObserver=null)}};var X=class{constructor(e){this.logger=e}open(e){let t=document.getElementById(e);if(!t){this.logger.warn(`Modal with id="${e}" not found`);return}t.removeAttribute("hidden"),t.style.display="flex",t.setAttribute("aria-hidden","false"),t.dispatchEvent(new CustomEvent("lvt:modal-opened",{bubbles:!0})),this.logger.info(`Opened modal: ${e}`);let n=t.querySelector("input, textarea, select");n&&setTimeout(()=>{let r=document.activeElement,s=i=>i?i===document.body||i.offsetParent!==null?!0:i.getClientRects().length>0:!1;(!r||!t.contains(r)||!s(r))&&n.focus()},100)}close(e){let t=document.getElementById(e);if(!t){this.logger.warn(`Modal with id="${e}" not found`);return}t.setAttribute("hidden",""),t.style.display="none",t.setAttribute("aria-hidden","true"),t.dispatchEvent(new CustomEvent("lvt:modal-closed",{bubbles:!0})),this.logger.info(`Closed modal: ${e}`)}};var Y=class{constructor(){this.bar=null}show(){if(this.bar)return;let e=document.createElement("div");if(e.style.cssText=` |
There was a problem hiding this comment.
Avoid automated semicolon insertion (94% of all statements in the enclosing function have an explicit semicolon).
| `,document.head.appendChild(t)}document.body.insertBefore(e,document.body.firstChild),this.bar=e}hide(){this.bar&&(this.bar.parentNode&&this.bar.parentNode.removeChild(this.bar),this.bar=null)}};var Q=class{disable(e){if(!e)return;e.querySelectorAll("form").forEach(n=>{n.querySelectorAll("input, textarea, select, button").forEach(s=>{s.disabled=!0})})}enable(e){if(!e)return;e.querySelectorAll("form").forEach(n=>{n.querySelectorAll("input, textarea, select, button").forEach(s=>{s.disabled=!1})})}};var Ce=["pending","success","error","done"];var tt={reset:"reset",disable:"disable",enable:"enable",addclass:"addClass",removeclass:"removeClass",toggleclass:"toggleClass",setattr:"setAttr",toggleattr:"toggleAttr"};function nt(a,e){let t=a.toLowerCase().match(/^lvt-(\w+)-on:(.+)$/);if(!t)return null;let n=t[1],r=tt[n];if(!r)return null;let o=t[2].split(":"),i=o[o.length-1];if(!Ce.includes(i))return null;let l=i,c=o.length>1?o.slice(0,-1).join(":"):void 0;return{action:r,lifecycle:l,actionName:c||void 0,param:e||void 0}}function rt(a,e,t){switch(e){case"reset":a instanceof HTMLFormElement&&a.reset();break;case"disable":"disabled"in a&&(a.disabled=!0);break;case"enable":"disabled"in a&&(a.disabled=!1);break;case"addClass":if(t){let n=t.split(/\s+/).filter(Boolean);a.classList.add(...n)}break;case"removeClass":if(t){let n=t.split(/\s+/).filter(Boolean);a.classList.remove(...n)}break;case"toggleClass":t&&t.split(/\s+/).filter(Boolean).forEach(r=>a.classList.toggle(r));break;case"setAttr":if(t){let n=t.indexOf(":");if(n>0){let r=t.substring(0,n),s=t.substring(n+1);a.setAttribute(r,s)}}break;case"toggleAttr":t&&a.toggleAttribute(t);break}}function st(a,e,t){return a.lifecycle!==e?!1:a.actionName?a.actionName===t:!0}function it(a,e){document.querySelectorAll("*").forEach(n=>{Array.from(n.attributes).forEach(r=>{if(!r.name.startsWith("lvt-")||!r.name.includes("-on:"))return;let s=nt(r.name,r.value);s&&st(s,a,e)&&rt(n,s.action,s.param)})})}function Z(){Ce.forEach(a=>{document.addEventListener(`lvt:${a}`,e=>{var r;let n=(r=e.detail)==null?void 0:r.action;it(a,n)},!0)})}function Re(a){return typeof structuredClone=="function"?structuredClone(a):JSON.parse(JSON.stringify(a))}var ee=class{constructor(e){this.logger=e;this.treeState={};this.rangeState={};this.rangeIdKeys={}}applyUpdate(e){let t=!1;for(let[r,s]of Object.entries(e))if(Array.isArray(s)&&s.length>0&&Array.isArray(s[0])&&typeof s[0][0]=="string"){let i=this.treeState[r];i&&typeof i=="object"&&!Array.isArray(i)&&Array.isArray(i.d)&&Array.isArray(i.s)?(this.treeState[r]=Re(i),this.applyDifferentialOpsToRange(this.treeState[r],s,r)):this.treeState[r]=s,t=!0}else{let i=this.treeState[r],l=typeof s=="object"&&s!==null&&!Array.isArray(s)?this.deepMergeTreeNodes(i,s,r):s;JSON.stringify(i)!==JSON.stringify(l)&&(this.treeState[r]=l,t=!0)}return{html:this.reconstructFromTree(this.treeState,""),changed:t}}reset(){this.treeState={},this.rangeState={},this.rangeIdKeys={}}getTreeState(){return{...this.treeState}}getStaticStructure(){return this.treeState.s||null}deepMergeTreeNodes(e,t,n=""){var s;if(typeof t!="object"||t===null||Array.isArray(t)||typeof e!="object"||e===null||Array.isArray(e))return t;let r={...e};for(let[o,i]of Object.entries(t)){let l=n?`${n}.${o}`:o,c=Array.isArray(i)&&i.length>0&&Array.isArray(i[0])&&typeof i[0][0]=="string",d=r[o]&&typeof r[o]=="object"&&!Array.isArray(r[o])&&Array.isArray(r[o].d)&&Array.isArray(r[o].s);c&&d?(r[o]=Re(r[o]),this.logger.debug(`[deepMerge] Applying diff ops at path ${l}`,{ops:i,rangeItems:(s=r[o].d)==null?void 0:s.length}),this.applyDifferentialOpsToRange(r[o],i,l)):typeof i=="object"&&i!==null&&!Array.isArray(i)&&typeof r[o]=="object"&&r[o]!==null&&!Array.isArray(r[o])?r[o]=this.deepMergeTreeNodes(r[o],i,l):r[o]=i}return r}applyDifferentialOpsToRange(e,t,n){if(!e||typeof e!="object"||!Array.isArray(e.d)||!Array.isArray(e.s)){this.logger.error(`[applyDiffOpsToRange] Invalid rangeStructure at path ${n}`,{rangeStructure:e});return}let r=e.d;this.rangeState[n]||(this.rangeState[n]={items:r,statics:e.s}),e.m&&typeof e.m=="object"&&typeof e.m.idKey=="string"&&(this.rangeIdKeys[n]=e.m.idKey),this.logger.debug(`[applyDiffOpsToRange] path=${n}, idKey=${this.rangeIdKeys[n]}, items=${r.length}, ops=${t.length}`);for(let s of t){if(!Array.isArray(s)||s.length<2)continue;switch(s[0]){case"r":{let i=s[1],l=this.findItemIndexByKey(r,i,e.s,n);this.logger.debug(`[applyDiffOpsToRange] Remove: key=${i}, index=${l}, total=${r.length}`),l>=0?(r.splice(l,1),this.logger.debug(`[applyDiffOpsToRange] After removal: ${r.length} items`)):this.logger.debug(`[applyDiffOpsToRange] Remove failed: key ${i} not found`);break}case"u":{let i=this.findItemIndexByKey(r,s[1],e.s,n),l=s[2];i>=0&&l&&(r[i]={...r[i],...l});break}case"a":{let i=Array.isArray(s[1])?s[1]:[s[1]];s[2]&&(e.s=s[2]),r.push(...i),s[3]&&typeof s[3]=="object"&&s[3].idKey&&(this.rangeIdKeys[n]=s[3].idKey);break}case"p":{let i=Array.isArray(s[1])?s[1]:[s[1]];s[2]&&(e.s=s[2]),r.unshift(...i);break}case"i":{let i=this.findItemIndexByKey(r,s[1],e.s,n);if(i>=0){let l=Array.isArray(s[2])?s[2]:[s[2]];r.splice(i+1,0,...l)}break}case"o":{let i=s[1],l=[],c=new Map;for(let d of r){let u=this.getItemKey(d,e.s,n);u&&c.set(u,d)}for(let d of i){let u=c.get(d);u&&l.push(u)}r.length=0,r.push(...l);break}default:break}}this.rangeState[n]={items:r,statics:e.s}}reconstructFromTree(e,t){if(e.s&&Array.isArray(e.s)){let n="";for(let r=0;r<e.s.length;r++){let s=e.s[r];if(n+=s,r<e.s.length-1){let o=r.toString();if(e[o]!==void 0){let i=t?`${t}.${o}`:o;n+=this.renderValue(e[o],o,i)}}}return n=n.replace(/<root>/g,"").replace(/<\/root>/g,""),n}return this.renderValue(e,"",t)}renderValue(e,t,n){if(e==null||typeof e=="string"&&e.startsWith("{{")&&e.endsWith("}}"))return"";if(typeof e=="object"&&!Array.isArray(e)){if(e.d&&Array.isArray(e.d)&&e.s&&Array.isArray(e.s)){let o=n||t||"";return o&&(this.rangeState[o]={items:e.d,statics:e.s},e.m&&typeof e.m=="object"&&typeof e.m.idKey=="string"&&(this.rangeIdKeys[o]=e.m.idKey)),this.renderRangeStructure(e,t,n)}if("s"in e&&Array.isArray(e.s))return this.reconstructFromTree(e,n||"");let r=Object.keys(e),s=r.filter(o=>/^\d+$/.test(o)).sort((o,i)=>parseInt(o)-parseInt(i));if(s.length>0&&s.length===r.length)return s.map(o=>{let i=n?`${n}.${o}`:o;return this.renderValue(e[o],o,i)}).join("")}return Array.isArray(e)?e.length>0&&Array.isArray(e[0])&&typeof e[0][0]=="string"?this.applyDifferentialOperations(e,n):e.map((r,s)=>{let o=s.toString(),i=n?`${n}.${o}`:o;return typeof r=="object"&&r&&r.s?this.reconstructFromTree(r,i):this.renderValue(r,o,i)}).join(""):typeof e=="object"?(this.logger.debug("Skipping plain object value (not a tree node) - this is normal for state-only data"),""):String(e)}renderRangeStructure(e,t,n){let{d:r,s}=e;if(!r||!Array.isArray(r))return"";if(r.length===0){if(e.else){let o="else",i=n?`${n}.else`:"else";return this.renderValue(e.else,o,i)}return""}return s&&Array.isArray(s)?r.map((o,i)=>{let l="";for(let c=0;c<s.length;c++)if(l+=s[c],c<s.length-1){let d=c.toString();if(o[d]!==void 0){let u=n?`${n}.${i}.${d}`:`${i}.${d}`;l+=this.renderValue(o[d],d,u)}}return l}).join(""):r.map((o,i)=>{let l=i.toString(),c=n?`${n}.${l}`:l;return this.renderValue(o,l,c)}).join("")}applyDifferentialOperations(e,t){if(!t||!this.rangeState[t])return"";let n=this.rangeState[t],r=[...n.items],s=n.statics;for(let i of e){if(!Array.isArray(i)||i.length<2)continue;switch(i[0]){case"r":{let c=this.findItemIndexByKey(r,i[1],s,t);c>=0&&r.splice(c,1);break}case"u":{let c=this.findItemIndexByKey(r,i[1],s,t),d=i[2];c>=0&&d&&(r[c]={...r[c],...d});break}case"a":{this.addItemsToRange(r,i[1],i[2],n,!1),i[3]&&typeof i[3]=="object"&&i[3].idKey&&(this.rangeIdKeys[t||""]=i[3].idKey);break}case"p":{this.addItemsToRange(r,i[1],i[2],n,!0);break}case"i":{let c=this.findItemIndexByKey(r,i[1],s,t);if(c>=0){let d=Array.isArray(i[2])?i[2]:[i[2]];r.splice(c+1,0,...d)}break}case"o":{let c=i[1],d=[],u=new Map;for(let g of r){let f=this.getItemKey(g,s,t);f&&u.set(f,g)}for(let g of c){let f=u.get(g);f&&d.push(f)}r.length=0,r.push(...d);break}default:break}}this.rangeState[t]={items:r,statics:n.statics},this.treeState[t]={d:r,s:n.statics};let o=this.getCurrentRangeStructure(t);return o&&o.s?this.renderItemsWithStatics(r,o.s):r.map(i=>this.renderValue(i)).join("")}getCurrentRangeStructure(e){if(this.rangeState[e])return{d:this.rangeState[e].items,s:this.rangeState[e].statics};let t=this.treeState[e];return t&&typeof t=="object"&&t.s?t:null}renderItemsWithStatics(e,t){let n=e.map(r=>{let s="";for(let o=0;o<t.length;o++)if(s+=t[o],o<t.length-1){let i=o.toString();r[i]!==void 0&&(s+=this.renderValue(r[i]))}return s}).join("");return this.logger.isDebugEnabled()&&(this.logger.debug("[renderItemsWithStatics] statics:",t),this.logger.debug("[renderItemsWithStatics] items count:",e.length),this.logger.debug("[renderItemsWithStatics] result snippet:",n.substring(0,200))),n}addItemsToRange(e,t,n,r,s){if(n&&(r.statics=n),!t)return;let o=Array.isArray(t)?t:[t];s?e.unshift(...o):e.push(...o)}getItemKey(e,t,n){if(!n||!this.rangeIdKeys[n])return null;let r=this.rangeIdKeys[n];return e[r]||null}findItemIndexByKey(e,t,n,r){return e.findIndex(s=>this.getItemKey(s,n,r)===t)}};var te=class{constructor(e){this.modalManager=e;this.activeForm=null;this.activeButton=null;this.originalButtonText=null}setActiveSubmission(e,t,n){this.activeForm=e,this.activeButton=t,this.originalButtonText=n}handleResponse(e){this.activeForm&&this.activeForm.dispatchEvent(new CustomEvent("lvt:done",{detail:e})),e.success?this.handleSuccess(e):this.handleError(e),this.restoreFormState()}reset(){this.restoreFormState()}handleSuccess(e){if(!this.activeForm)return;this.activeForm.dispatchEvent(new CustomEvent("lvt:success",{detail:e}));let t=this.activeForm.closest('[role="dialog"]');t&&t.id&&this.modalManager.close(t.id),this.activeForm.hasAttribute("lvt-preserve")||this.activeForm.reset()}handleError(e){this.activeForm&&this.activeForm.dispatchEvent(new CustomEvent("lvt:error",{detail:e}))}restoreFormState(){this.activeButton&&this.originalButtonText!==null&&(this.activeButton.disabled=!1,this.activeButton.textContent=this.originalButtonText),this.activeForm=null,this.activeButton=null,this.originalButtonText=null}};var fe=class{constructor(e){this.options=e;this.socket=null;this.reconnectTimer=null;this.manuallyClosed=!1;this.reconnectAttempts=0}connect(){this.manuallyClosed=!1,this.clearReconnectTimer(),this.socket=new WebSocket(this.options.url);let e=this.socket;e.onopen=()=>{var t,n;this.reconnectAttempts=0,(n=(t=this.options).onOpen)==null||n.call(t,e)},e.onmessage=t=>{var n,r;(r=(n=this.options).onMessage)==null||r.call(n,t)},e.onclose=t=>{var n,r;(r=(n=this.options).onClose)==null||r.call(n,t),!this.manuallyClosed&&this.options.autoReconnect&&this.scheduleReconnect()},e.onerror=t=>{var n,r;(r=(n=this.options).onError)==null||r.call(n,t)}}send(e){this.socket&&this.socket.readyState===1&&this.socket.send(e)}disconnect(){this.manuallyClosed=!0,this.clearReconnectTimer(),this.socket&&(this.socket.close(),this.socket=null)}getSocket(){return this.socket}scheduleReconnect(){var i,l,c,d,u;this.clearReconnectTimer();let e=(i=this.options.maxReconnectAttempts)!=null?i:10;if(e>0&&this.reconnectAttempts>=e){(c=(l=this.options).onReconnectFailed)==null||c.call(l);return}this.reconnectAttempts++;let t=(d=this.options.reconnectDelay)!=null?d:1e3,n=(u=this.options.maxReconnectDelay)!=null?u:16e3,r=t*Math.pow(2,this.reconnectAttempts-1),s=Math.random()*1e3,o=Math.min(r+s,n);this.reconnectTimer=window.setTimeout(()=>{var g,f;(f=(g=this.options).onReconnectAttempt)==null||f.call(g,this.reconnectAttempts,o),this.connect()},o)}clearReconnectTimer(){this.reconnectTimer!==null&&(clearTimeout(this.reconnectTimer),this.reconnectTimer=null)}},ne=class{constructor(e){this.config=e;this.transport=null}async connect(){let e=this.getLiveUrl();return await ot(e,this.config.logger)?(this.transport=new fe({url:this.getWebSocketUrl(),autoReconnect:this.config.options.autoReconnect,reconnectDelay:this.config.options.reconnectDelay,maxReconnectDelay:16e3,maxReconnectAttempts:10,onOpen:()=>{this.config.onConnected()},onMessage:n=>{try{let r=JSON.parse(n.data);this.config.onMessage(r,n)}catch(r){this.config.logger.error("Failed to parse WebSocket message:",r)}},onClose:()=>{this.config.onDisconnected()},onReconnectAttempt:(n,r)=>{var s,o;(o=(s=this.config).onReconnectAttempt)==null||o.call(s,n,r)},onReconnectFailed:()=>{var n,r;(r=(n=this.config).onReconnectFailed)==null||r.call(n)},onError:n=>{var r,s;(s=(r=this.config).onError)==null||s.call(r,n)}}),this.transport.connect(),{usingWebSocket:!0}):{usingWebSocket:!1,initialState:await at(e,this.config.logger)}}disconnect(){var e;(e=this.transport)==null||e.disconnect(),this.transport=null}send(e){var t;(t=this.transport)==null||t.send(e)}getReadyState(){var e,t;return(t=(e=this.transport)==null?void 0:e.getSocket())==null?void 0:t.readyState}getSocket(){var e,t;return(t=(e=this.transport)==null?void 0:e.getSocket())!=null?t:null}getWebSocketUrl(){let e=this.config.options.liveUrl||"/live",t=this.config.options.wsUrl;return t||`ws://${window.location.host}${e}`}getLiveUrl(){return this.config.options.liveUrl||window.location.pathname}};async function ot(a,e){try{let n=(await fetch(a,{method:"HEAD"})).headers.get("X-LiveTemplate-WebSocket");return n?n==="enabled":!0}catch(t){return e==null||e.warn("Failed to check WebSocket availability:",t),!0}}async function at(a,e){try{let t=await fetch(a,{method:"GET",credentials:"include",headers:{Accept:"application/json"}});if(!t.ok)throw new Error(`Failed to fetch initial state: ${t.status}`);return await t.json()}catch(t){return e==null||e.warn("Failed to fetch initial state:",t),null}}var re=class{async upload(e,t,n){let{file:r}=e;e.abortController=new AbortController;try{let s=new XMLHttpRequest;s.upload.addEventListener("progress",i=>{i.lengthComputable&&(e.bytesUploaded=i.loaded,e.progress=Math.round(i.loaded/i.total*100),n&&n(e))}),e.abortController.signal.addEventListener("abort",()=>{s.abort()});let o=new Promise((i,l)=>{s.addEventListener("load",()=>{s.status>=200&&s.status<300?(e.done=!0,e.progress=100,i()):l(new Error(`S3 upload failed with status ${s.status}: ${s.statusText}`))}),s.addEventListener("error",()=>{l(new Error("S3 upload failed: Network error"))}),s.addEventListener("abort",()=>{l(new Error("S3 upload cancelled"))})});if(s.open("PUT",t.url),t.headers)for(let[i,l]of Object.entries(t.headers))s.setRequestHeader(i,l);s.send(r),await o}catch(s){throw e.error=s instanceof Error?s.message:String(s),s}}};var se=class{constructor(e,t={}){this.sendMessage=e;this.entries=new Map;this.pendingFiles=new Map;this.autoUploadConfig=new Map;this.uploaders=new Map;this.inputHandlers=new WeakMap;this.chunkSize=t.chunkSize||256*1024,this.onProgress=t.onProgress,this.onComplete=t.onComplete,this.onError=t.onError,this.uploaders.set("s3",new re)}initializeFileInputs(e){e.querySelectorAll('input[type="file"][lvt-upload]').forEach(n=>{let r=n.getAttribute("lvt-upload");if(!r)return;let s=this.inputHandlers.get(n);s&&n.removeEventListener("change",s);let o=i=>{let l=i.target.files;!l||l.length===0||this.startUpload(r,Array.from(l))};n.addEventListener("change",o),this.inputHandlers.set(n,o)})}async startUpload(e,t){this.pendingFiles.set(e,t);let n=t.map(s=>({name:s.name,type:s.type||"application/octet-stream",size:s.size})),r={action:"upload_start",upload_name:e,files:n};this.sendMessage(r)}async handleUploadStartResponse(e){let{upload_name:t,entries:n}=e;n.length>0&&this.autoUploadConfig.set(t,n[0].auto_upload);let r=this.pendingFiles.get(t);if(!r){console.error(`No pending files found for upload: ${t}`);return}this.pendingFiles.delete(t);let s=new Map;for(let i of r)s.set(i.name,i);let o=[];for(let i of n){let l=s.get(i.client_name);if(!l){console.warn(`No file found for entry ${i.entry_id} (client_name: ${i.client_name})`);continue}let c={id:i.entry_id,file:l,uploadName:t,progress:0,bytesUploaded:0,valid:i.valid,done:!1,error:i.error,external:i.external};if(this.entries.set(c.id,c),o.push(c),!i.valid){this.onError&&i.error&&this.onError(c,i.error);continue}i.auto_upload&&(i.external?this.uploadExternal(c,i.external):this.uploadChunked(c))}}async uploadExternal(e,t){try{let n=this.uploaders.get(t.uploader);if(!n)throw new Error(`Unknown uploader: ${t.uploader}`);await n.upload(e,t,this.onProgress);let r={action:"upload_complete",upload_name:e.uploadName,entry_ids:[e.id]};this.sendMessage(r),this.onComplete&&this.onComplete(e.uploadName,[e]),this.clearFileInput(e.uploadName),this.cleanupEntries(e.uploadName)}catch(n){let r=n instanceof Error?n.message:String(n);e.error=r,this.onError&&this.onError(e,r),this.cleanupEntries(e.uploadName)}}async uploadChunked(e){let{file:t,id:n}=e,r=0;e.abortController=new AbortController;try{for(;r<t.size;){if(e.abortController.signal.aborted)throw new Error("Upload cancelled");let o=Math.min(r+this.chunkSize,t.size),i=t.slice(r,o),l=await this.fileToBase64(i),c={action:"upload_chunk",entry_id:n,chunk_base64:l,offset:r,total:t.size};this.sendMessage(c),r=o,e.bytesUploaded=r,e.progress=Math.round(r/t.size*100),this.onProgress&&this.onProgress(e)}e.done=!0;let s={action:"upload_complete",upload_name:e.uploadName,entry_ids:[n]};this.sendMessage(s),this.onComplete&&this.onComplete(e.uploadName,[e]),this.clearFileInput(e.uploadName),this.cleanupEntries(e.uploadName)}catch(s){let o=s instanceof Error?s.message:String(s);e.error=o,this.onError&&this.onError(e,o),this.cleanupEntries(e.uploadName)}}handleProgressMessage(e){let t=this.entries.get(e.entry_id);t&&(t.progress=e.progress,t.bytesUploaded=e.bytes_recv,this.onProgress&&this.onProgress(t))}cancelUpload(e){let t=this.entries.get(e);t&&(t.abortController&&t.abortController.abort(),this.sendMessage({action:"cancel_upload",entry_id:e}),this.entries.delete(e))}getEntries(e){let t=[];for(let n of this.entries.values())n.uploadName===e&&t.push(n);return t}triggerPendingUploads(e){let t=[];for(let n of this.entries.values())n.uploadName===e&&n.progress===0&&!n.done&&!n.error&&t.push(n);for(let n of t)n.external?this.uploadExternal(n,n.external):this.uploadChunked(n)}registerUploader(e,t){this.uploaders.set(e,t)}clearFileInput(e){document.querySelectorAll(`input[type="file"][lvt-upload="${e}"]`).forEach(n=>{n.value=""})}cleanupEntries(e,t=5e3){setTimeout(()=>{let n=[];for(let[r,s]of this.entries)e&&s.uploadName!==e||(s.done||s.error)&&n.push(r);for(let r of n)this.entries.delete(r)},t)}fileToBase64(e){return new Promise((t,n)=>{let r=new FileReader;r.onload=()=>{let o=r.result.split(",")[1];t(o)},r.onerror=n,r.readAsDataURL(e)})}};var Fe={silent:0,error:1,warn:2,info:3,debug:4},_e="LiveTemplate",he=class a{constructor(e,t=[],n=console){this.state=e;this.scope=t;this.sink=n}setLevel(e){this.state.level=e}getLevel(){return this.state.level}child(e){return new a(this.state,[...this.scope,e],this.sink)}isDebugEnabled(){return this.shouldLog("debug")}error(...e){this.log("error","error",e)}warn(...e){this.log("warn","warn",e)}info(...e){this.log("info","info",e)}debug(...e){this.log("debug","debug",e)}log(e,t,n){if(!this.shouldLog(e))return;(this.sink[t]||console[t]||console.log).apply(this.sink,[this.formatPrefix(),...n])}shouldLog(e){return Fe[e]<=Fe[this.state.level]}formatPrefix(){return this.scope.length===0?`[${_e}]`:`[${_e}:${this.scope.join(":")}]`}};function me(a={}){var n,r;let e={level:(n=a.level)!=null?n:"info"},t=Array.isArray(a.scope)?a.scope:a.scope?[a.scope]:[];return new he(e,t,(r=a.sink)!=null?r:console)}async function Ie(a,e){try{let t=globalThis==null?void 0:globalThis.require;if(typeof t=="function"){let s=t("fs"),o=JSON.parse(s.readFileSync(e,"utf8"));return a.applyUpdate(o)}let r=await(await fetch(e)).json();return a.applyUpdate(r)}catch(t){throw new Error(`Failed to load update from ${e}: ${t}`)}}function He(a,e){let t=[],n=c=>c.replace(/\s+/g," ").replace(/>\s+</g,"><").trim(),r=n(a),s=n(e);if(r===s)return{match:!0,differences:[]};let o=r.split(` | ||
| `),i=s.split(` | ||
| `),l=Math.max(o.length,i.length);for(let c=0;c<l;c++){let d=o[c]||"",M=i[c]||"";d!==M&&(t.push(`Line ${c+1}:`),t.push(` Expected: ${d}`),t.push(` Actual: ${M}`))}return{match:!1,differences:t}}var re=class a{constructor(e={}){this.lvtId=null;this.ws=null;this.wrapperElement=null;this.useHTTP=!1;this.sessionCookie=null;this.rateLimitedHandlers=new WeakMap;this.isInitialized=!1;this.messageCount=0;let{logger:t,logLevel:n,debug:r,...s}=e,o=n!=null?n:r?"debug":"info",i=t!=null?t:he({level:o});t?n?t.setLevel(n):r&&t.setLevel("debug"):i.setLevel(o),this.logger=i.child("Client"),this.options={autoReconnect:!1,reconnectDelay:1e3,liveUrl:window.location.pathname,...s},this.treeRenderer=new Q(this.logger.child("TreeRenderer")),this.focusManager=new z(this.logger.child("FocusManager")),this.modalManager=new J(this.logger.child("ModalManager")),this.formLifecycleManager=new Z(this.modalManager),this.loadingIndicator=new X,this.formDisabler=new Y,this.uploadHandler=new ne(l=>this.send(l),{chunkSize:256*1024,onProgress:l=>{this.wrapperElement&&this.wrapperElement.dispatchEvent(new CustomEvent("lvt:upload:progress",{detail:{entry:l}}))},onComplete:(l,c)=>{this.logger.info(`Upload complete: ${l}`,c),this.wrapperElement&&this.wrapperElement.dispatchEvent(new CustomEvent("lvt:upload:complete",{detail:{uploadName:l,entries:c}}))},onError:(l,c)=>{this.logger.error(`Upload error for ${l.id}:`,c),this.wrapperElement&&this.wrapperElement.dispatchEvent(new CustomEvent("lvt:upload:error",{detail:{entry:l,error:c}}))}}),this.eventDelegator=new q({getWrapperElement:()=>this.wrapperElement,getRateLimitedHandlers:()=>this.rateLimitedHandlers,parseValue:l=>this.parseValue(l),send:l=>this.send(l),setActiveSubmission:(l,c,d)=>this.formLifecycleManager.setActiveSubmission(l,c,d),openModal:l=>this.modalManager.open(l),closeModal:l=>this.modalManager.close(l),getWebSocketReadyState:()=>this.webSocketManager.getReadyState(),triggerPendingUploads:l=>this.uploadHandler.triggerPendingUploads(l)},this.logger.child("EventDelegator")),this.observerManager=new G({getWrapperElement:()=>this.wrapperElement,send:l=>this.send(l)},this.logger.child("ObserverManager")),this.webSocketManager=new ee({options:this.options,logger:this.logger.child("Transport"),onConnected:()=>{var l,c,d;this.ws=this.webSocketManager.getSocket(),this.logger.info("WebSocket connected"),(c=(l=this.options).onConnect)==null||c.call(l),(d=this.wrapperElement)==null||d.dispatchEvent(new Event("lvt:connected"))},onDisconnected:()=>{var l,c,d;this.ws=null,this.logger.info("WebSocket disconnected"),(c=(l=this.options).onDisconnect)==null||c.call(l),(d=this.wrapperElement)==null||d.dispatchEvent(new Event("lvt:disconnected"))},onMessage:(l,c)=>{this.handleWebSocketPayload(l,c)},onReconnectAttempt:()=>{this.logger.info("Attempting to reconnect...")},onError:l=>{var c,d;this.logger.error("WebSocket error:",l),(d=(c=this.options).onError)==null||d.call(c,l)}})}static autoInit(){let e=he({scope:"Client:autoInit"}),t=()=>{let n=document.querySelector("[data-lvt-id]");if(n){let r=new a;r.wrapperElement=n,n.getAttribute("data-lvt-loading")==="true"&&(r.loadingIndicator.show(),r.formDisabler.disable(r.wrapperElement)),r.connect().catch(o=>{e.error("Auto-initialization connect failed:",o)}),window.liveTemplateClient=r}};document.readyState==="loading"?document.addEventListener("DOMContentLoaded",t):t()}handleWebSocketPayload(e,t){var r,s;t&&(window.__lastWSMessage=t.data,window.__wsMessages||(window.__wsMessages=[]),window.__wsMessages.push(e));let n=e;if(n.type==="upload_progress"){this.uploadHandler.handleProgressMessage(n);return}if(n.upload_name&&n.entries){let o=n;try{this.handleUploadStartResponse(o)}catch(i){this.logger.error("Error handling upload start response:",i)}return}if(n.upload_name&&n.hasOwnProperty("success")){n.success?this.logger.info(`Upload complete: ${n.upload_name}`):this.logger.error(`Upload failed: ${n.upload_name}`,n.error);return}this.isInitialized||(this.loadingIndicator.hide(),this.formDisabler.enable(this.wrapperElement),this.wrapperElement&&this.wrapperElement.hasAttribute("data-lvt-loading")&&this.wrapperElement.removeAttribute("data-lvt-loading"),this.isInitialized=!0),this.wrapperElement&&(this.updateDOM(this.wrapperElement,e.tree,e.meta),this.messageCount++,window.__wsMessageCount=this.messageCount,this.wrapperElement.dispatchEvent(new CustomEvent("lvt:updated",{detail:{messageCount:this.messageCount,action:(r=e.meta)==null?void 0:r.action,success:(s=e.meta)==null?void 0:s.success}})))}async connect(e="[data-lvt-id]"){var n,r;if(this.wrapperElement=document.querySelector(e),!this.wrapperElement)throw new Error(`LiveTemplate wrapper not found with selector: ${e}`);this.webSocketManager.disconnect();let t=await this.webSocketManager.connect();this.useHTTP=!t.usingWebSocket,this.useHTTP&&(this.ws=null,this.logger.info("WebSocket not available, using HTTP mode"),(r=(n=this.options).onConnect)==null||r.call(n),t.initialState&&this.wrapperElement&&this.handleWebSocketPayload(t.initialState)),this.eventDelegator.setupEventDelegation(),this.eventDelegator.setupWindowEventDelegation(),this.eventDelegator.setupClickAwayDelegation(),this.eventDelegator.setupModalDelegation(),this.focusManager.attach(this.wrapperElement),this.observerManager.setupInfiniteScrollObserver(),this.observerManager.setupInfiniteScrollMutationObserver()}disconnect(){this.webSocketManager.disconnect(),this.ws=null,this.useHTTP=!1,this.observerManager.teardown(),this.formLifecycleManager.reset(),this.loadingIndicator.hide(),this.formDisabler.enable(this.wrapperElement)}isReady(){let e=this.wrapperElement;return!e||e.hasAttribute("data-lvt-loading")?!1:this.useHTTP?!0:this.webSocketManager.getReadyState()===1}send(e){window.__lvtSendCalled=!0,window.__lvtMessageAction=e==null?void 0:e.action;let t=this.webSocketManager.getReadyState();this.logger.isDebugEnabled()&&this.logger.debug("send() invoked",{message:e,useHTTP:this.useHTTP,hasWebSocket:t!==void 0,readyState:t}),this.useHTTP?(this.logger.debug("Using HTTP mode for send"),window.__lvtSendPath="http",this.sendHTTP(e)):t===1?(this.logger.debug("Sending via WebSocket"),window.__lvtSendPath="websocket",window.__lvtWSMessage=JSON.stringify(e),this.webSocketManager.send(JSON.stringify(e)),this.logger.debug("WebSocket send complete"),window.__lvtWSSendComplete=!0):t!==void 0?(this.logger.warn(`WebSocket not ready (state: ${t}), using HTTP fallback`),window.__lvtSendPath="http-fallback",this.sendHTTP(e)):(this.logger.error("No transport available"),window.__lvtSendPath="no-transport")}async sendHTTP(e){try{let t=this.options.liveUrl||"/live",n=await fetch(t,{method:"POST",credentials:"include",headers:{"Content-Type":"application/json",Accept:"application/json"},body:JSON.stringify(e)});if(!n.ok)throw new Error(`HTTP request failed: ${n.status}`);let r=await n.json();this.wrapperElement&&this.updateDOM(this.wrapperElement,r.tree,r.meta)}catch(t){this.logger.error("Failed to send HTTP request:",t)}}parseValue(e){let t=parseFloat(e);return!isNaN(t)&&e.trim()===t.toString()?t:e==="true"?!0:e==="false"?!1:e}applyUpdate(e){return this.treeRenderer.applyUpdate(e)}applyUpdateToHTML(e,t){let n=this.applyUpdate(t);if(!this.lvtId){let c=e.match(/data-lvt-id="([^"]+)"/);c&&(this.lvtId=c[1])}let r=n.html;if(!e.match(/<body>([\s\S]*?)<\/body>/))return e;let l=`<div data-lvt-id="${this.lvtId||"lvt-unknown"}">`+r+"</div>";return e.replace(/<body>[\s\S]*?<\/body>/,`<body>${l}</body>`)}updateDOM(e,t,n){let r=this.applyUpdate(t),s=i=>!i||typeof i!="object"?!1:i.s&&Array.isArray(i.s)?!0:Object.values(i).some(l=>s(l));if(!r.changed&&!s(t))return;let o=document.createElement(e.tagName);this.logger.isDebugEnabled()&&(this.logger.debug("[updateDOM] element.tagName:",e.tagName),this.logger.debug("[updateDOM] result.html (first 500 chars):",r.html.substring(0,500)),this.logger.debug("[updateDOM] Has <table> tag:",r.html.includes("<table>")),this.logger.debug("[updateDOM] Has <tbody> tag:",r.html.includes("<tbody>")),this.logger.debug("[updateDOM] Has <tr> tag:",r.html.includes("<tr"))),o.innerHTML=r.html,this.logger.isDebugEnabled()&&(this.logger.debug("[updateDOM] tempWrapper.innerHTML (first 500 chars):",o.innerHTML.substring(0,500)),this.logger.debug("[updateDOM] tempWrapper has <table>:",o.innerHTML.includes("<table>")),this.logger.debug("[updateDOM] tempWrapper has <tbody>:",o.innerHTML.includes("<tbody>")),this.logger.debug("[updateDOM] tempWrapper has <tr>:",o.innerHTML.includes("<tr"))),Se(e,o,{childrenOnly:!0,getNodeKey:i=>{if(i.nodeType===1)return i.getAttribute("data-key")||i.getAttribute("data-lvt-key")||void 0},onBeforeElUpdated:(i,l)=>{let c=this.focusManager.getLastFocusedElement();return c&&this.focusManager.isTextualInput(i)&&i===c&&(l.value=i.value),i.isEqualNode(l)?!1:(this.executeLifecycleHook(i,"lvt-updated"),!0)},onNodeAdded:i=>{i.nodeType===Node.ELEMENT_NODE&&this.executeLifecycleHook(i,"lvt-mounted")},onBeforeNodeDiscarded:i=>(i.nodeType===Node.ELEMENT_NODE&&this.executeLifecycleHook(i,"lvt-destroyed"),!0)}),this.focusManager.restoreFocusedElement(),Me(e),ke(e),Ae(e),this.uploadHandler.initializeFileInputs(e),n&&this.formLifecycleManager.handleResponse(n)}handleUploadStartResponse(e){this.uploadHandler.handleUploadStartResponse(e)}executeLifecycleHook(e,t){let n=e.getAttribute(t);if(n)try{new Function("element",n).call(e,e)}catch(r){this.logger.error(`Error executing ${t} hook:`,r)}}reset(){this.treeRenderer.reset(),this.focusManager.reset(),this.observerManager.teardown(),this.formLifecycleManager.reset(),this.loadingIndicator.hide(),this.formDisabler.enable(this.wrapperElement),this.lvtId=null}getTreeState(){return this.treeRenderer.getTreeState()}getStaticStructure(){return this.treeRenderer.getStaticStructure()}};typeof window!="undefined"&&re.autoInit();return Ie(Qe);})(); | ||
| `),l=Math.max(o.length,i.length);for(let c=0;c<l;c++){let d=o[c]||"",u=i[c]||"";d!==u&&(t.push(`Line ${c+1}:`),t.push(` Expected: ${d}`),t.push(` Actual: ${u}`))}return{match:!1,differences:t}}var ie=class a{constructor(e={}){this.lvtId=null;this.ws=null;this.wrapperElement=null;this.useHTTP=!1;this.sessionCookie=null;this.rateLimitedHandlers=new WeakMap;this.isInitialized=!1;this.messageCount=0;let{logger:t,logLevel:n,debug:r,...s}=e,o=n!=null?n:r?"debug":"info",i=t!=null?t:me({level:o});t?n?t.setLevel(n):r&&t.setLevel("debug"):i.setLevel(o),this.logger=i.child("Client"),this.options={autoReconnect:!1,reconnectDelay:1e3,liveUrl:window.location.pathname,...s},this.treeRenderer=new ee(this.logger.child("TreeRenderer")),this.focusManager=new q(this.logger.child("FocusManager")),this.modalManager=new X(this.logger.child("ModalManager")),this.formLifecycleManager=new te(this.modalManager),this.loadingIndicator=new Y,this.formDisabler=new Q,this.uploadHandler=new se(l=>this.send(l),{chunkSize:256*1024,onProgress:l=>{this.wrapperElement&&this.wrapperElement.dispatchEvent(new CustomEvent("lvt:upload:progress",{detail:{entry:l}}))},onComplete:(l,c)=>{this.logger.info(`Upload complete: ${l}`,c),this.wrapperElement&&this.wrapperElement.dispatchEvent(new CustomEvent("lvt:upload:complete",{detail:{uploadName:l,entries:c}}))},onError:(l,c)=>{this.logger.error(`Upload error for ${l.id}:`,c),this.wrapperElement&&this.wrapperElement.dispatchEvent(new CustomEvent("lvt:upload:error",{detail:{entry:l,error:c}}))}}),this.eventDelegator=new J({getWrapperElement:()=>this.wrapperElement,getRateLimitedHandlers:()=>this.rateLimitedHandlers,parseValue:l=>this.parseValue(l),send:l=>this.send(l),setActiveSubmission:(l,c,d)=>this.formLifecycleManager.setActiveSubmission(l,c,d),openModal:l=>this.modalManager.open(l),closeModal:l=>this.modalManager.close(l),getWebSocketReadyState:()=>this.webSocketManager.getReadyState(),triggerPendingUploads:l=>this.uploadHandler.triggerPendingUploads(l)},this.logger.child("EventDelegator")),this.observerManager=new G({getWrapperElement:()=>this.wrapperElement,send:l=>this.send(l)},this.logger.child("ObserverManager")),this.webSocketManager=new ne({options:this.options,logger:this.logger.child("Transport"),onConnected:()=>{var l,c,d;this.ws=this.webSocketManager.getSocket(),this.logger.info("WebSocket connected"),(c=(l=this.options).onConnect)==null||c.call(l),(d=this.wrapperElement)==null||d.dispatchEvent(new Event("lvt:connected"))},onDisconnected:()=>{var l,c,d;this.ws=null,this.logger.info("WebSocket disconnected"),(c=(l=this.options).onDisconnect)==null||c.call(l),(d=this.wrapperElement)==null||d.dispatchEvent(new Event("lvt:disconnected"))},onMessage:(l,c)=>{this.handleWebSocketPayload(l,c)},onReconnectAttempt:()=>{this.logger.info("Attempting to reconnect...")},onError:l=>{var c,d;this.logger.error("WebSocket error:",l),(d=(c=this.options).onError)==null||d.call(c,l)}})}static autoInit(){let e=me({scope:"Client:autoInit"}),t=()=>{let n=document.querySelector("[data-lvt-id]");if(n){let r=new a;r.wrapperElement=n,n.getAttribute("data-lvt-loading")==="true"&&(r.loadingIndicator.show(),r.formDisabler.disable(r.wrapperElement)),r.connect().catch(o=>{e.error("Auto-initialization connect failed:",o)}),window.liveTemplateClient=r}};document.readyState==="loading"?document.addEventListener("DOMContentLoaded",t):t()}handleWebSocketPayload(e,t){var r,s;t&&(window.__lastWSMessage=t.data,window.__wsMessages||(window.__wsMessages=[]),window.__wsMessages.push(e));let n=e;if(n.type==="upload_progress"){this.uploadHandler.handleProgressMessage(n);return}if(n.upload_name&&n.entries){let o=n;try{this.handleUploadStartResponse(o)}catch(i){this.logger.error("Error handling upload start response:",i)}return}if(n.upload_name&&n.hasOwnProperty("success")){n.success?this.logger.info(`Upload complete: ${n.upload_name}`):this.logger.error(`Upload failed: ${n.upload_name}`,n.error);return}this.isInitialized||(this.loadingIndicator.hide(),this.formDisabler.enable(this.wrapperElement),this.wrapperElement&&this.wrapperElement.hasAttribute("data-lvt-loading")&&this.wrapperElement.removeAttribute("data-lvt-loading"),this.isInitialized=!0),this.wrapperElement&&(this.updateDOM(this.wrapperElement,e.tree,e.meta),this.messageCount++,window.__wsMessageCount=this.messageCount,this.wrapperElement.dispatchEvent(new CustomEvent("lvt:updated",{detail:{messageCount:this.messageCount,action:(r=e.meta)==null?void 0:r.action,success:(s=e.meta)==null?void 0:s.success}})))}async connect(e="[data-lvt-id]"){var n,r;if(this.wrapperElement=document.querySelector(e),!this.wrapperElement)throw new Error(`LiveTemplate wrapper not found with selector: ${e}`);this.webSocketManager.disconnect();let t=await this.webSocketManager.connect();this.useHTTP=!t.usingWebSocket,this.useHTTP&&(this.ws=null,this.logger.info("WebSocket not available, using HTTP mode"),(r=(n=this.options).onConnect)==null||r.call(n),t.initialState&&this.wrapperElement&&this.handleWebSocketPayload(t.initialState)),this.eventDelegator.setupEventDelegation(),this.eventDelegator.setupWindowEventDelegation(),this.eventDelegator.setupClickAwayDelegation(),this.eventDelegator.setupModalDelegation(),this.eventDelegator.setupFocusTrapDelegation(),this.eventDelegator.setupAutofocusDelegation(),Z(),this.focusManager.attach(this.wrapperElement),this.observerManager.setupInfiniteScrollObserver(),this.observerManager.setupInfiniteScrollMutationObserver()}disconnect(){this.webSocketManager.disconnect(),this.ws=null,this.useHTTP=!1,this.observerManager.teardown(),this.formLifecycleManager.reset(),this.loadingIndicator.hide(),this.formDisabler.enable(this.wrapperElement)}isReady(){let e=this.wrapperElement;return!e||e.hasAttribute("data-lvt-loading")?!1:this.useHTTP?!0:this.webSocketManager.getReadyState()===1}send(e){window.__lvtSendCalled=!0,window.__lvtMessageAction=e==null?void 0:e.action;let t=this.webSocketManager.getReadyState();this.logger.isDebugEnabled()&&this.logger.debug("send() invoked",{message:e,useHTTP:this.useHTTP,hasWebSocket:t!==void 0,readyState:t}),this.useHTTP?(this.logger.debug("Using HTTP mode for send"),window.__lvtSendPath="http",this.sendHTTP(e)):t===1?(this.logger.debug("Sending via WebSocket"),window.__lvtSendPath="websocket",window.__lvtWSMessage=JSON.stringify(e),this.webSocketManager.send(JSON.stringify(e)),this.logger.debug("WebSocket send complete"),window.__lvtWSSendComplete=!0):t!==void 0?(this.logger.warn(`WebSocket not ready (state: ${t}), using HTTP fallback`),window.__lvtSendPath="http-fallback",this.sendHTTP(e)):(this.logger.error("No transport available"),window.__lvtSendPath="no-transport")}async sendHTTP(e){try{let t=this.options.liveUrl||"/live",n=await fetch(t,{method:"POST",credentials:"include",headers:{"Content-Type":"application/json",Accept:"application/json"},body:JSON.stringify(e)});if(!n.ok)throw new Error(`HTTP request failed: ${n.status}`);let r=await n.json();this.wrapperElement&&this.updateDOM(this.wrapperElement,r.tree,r.meta)}catch(t){this.logger.error("Failed to send HTTP request:",t)}}parseValue(e){let t=parseFloat(e);return!isNaN(t)&&e.trim()===t.toString()?t:e==="true"?!0:e==="false"?!1:e}applyUpdate(e){return this.treeRenderer.applyUpdate(e)}applyUpdateToHTML(e,t){let n=this.applyUpdate(t);if(!this.lvtId){let c=e.match(/data-lvt-id="([^"]+)"/);c&&(this.lvtId=c[1])}let r=n.html;if(!e.match(/<body>([\s\S]*?)<\/body>/))return e;let l=`<div data-lvt-id="${this.lvtId||"lvt-unknown"}">`+r+"</div>";return e.replace(/<body>[\s\S]*?<\/body>/,`<body>${l}</body>`)}updateDOM(e,t,n){let r=this.applyUpdate(t),s=i=>!i||typeof i!="object"?!1:i.s&&Array.isArray(i.s)?!0:Object.values(i).some(l=>s(l));if(!r.changed&&!s(t))return;let o=document.createElement(e.tagName);this.logger.isDebugEnabled()&&(this.logger.debug("[updateDOM] element.tagName:",e.tagName),this.logger.debug("[updateDOM] result.html (first 500 chars):",r.html.substring(0,500)),this.logger.debug("[updateDOM] Has <table> tag:",r.html.includes("<table>")),this.logger.debug("[updateDOM] Has <tbody> tag:",r.html.includes("<tbody>")),this.logger.debug("[updateDOM] Has <tr> tag:",r.html.includes("<tr"))),o.innerHTML=r.html,this.logger.isDebugEnabled()&&(this.logger.debug("[updateDOM] tempWrapper.innerHTML (first 500 chars):",o.innerHTML.substring(0,500)),this.logger.debug("[updateDOM] tempWrapper has <table>:",o.innerHTML.includes("<table>")),this.logger.debug("[updateDOM] tempWrapper has <tbody>:",o.innerHTML.includes("<tbody>")),this.logger.debug("[updateDOM] tempWrapper has <tr>:",o.innerHTML.includes("<tr"))),Me(e,o,{childrenOnly:!0,getNodeKey:i=>{if(i.nodeType===1)return i.getAttribute("data-key")||i.getAttribute("data-lvt-key")||void 0},onBeforeElUpdated:(i,l)=>{let c=this.focusManager.getLastFocusedElement();return c&&this.focusManager.isTextualInput(i)&&i===c&&(l.value=i.value),i.isEqualNode(l)?!1:(this.executeLifecycleHook(i,"lvt-updated"),!0)},onNodeAdded:i=>{i.nodeType===Node.ELEMENT_NODE&&this.executeLifecycleHook(i,"lvt-mounted")},onBeforeNodeDiscarded:i=>(i.nodeType===Node.ELEMENT_NODE&&this.executeLifecycleHook(i,"lvt-destroyed"),!0)}),this.focusManager.restoreFocusedElement(),Te(e),Le(e),ke(e),this.uploadHandler.initializeFileInputs(e),n&&this.formLifecycleManager.handleResponse(n)}handleUploadStartResponse(e){this.uploadHandler.handleUploadStartResponse(e)}executeLifecycleHook(e,t){let n=e.getAttribute(t);if(n)try{new Function("element",n).call(e,e)}catch(r){this.logger.error(`Error executing ${t} hook:`,r)}}reset(){this.treeRenderer.reset(),this.focusManager.reset(),this.observerManager.teardown(),this.formLifecycleManager.reset(),this.loadingIndicator.hide(),this.formDisabler.enable(this.wrapperElement),this.lvtId=null}getTreeState(){return this.treeRenderer.getTreeState()}getStaticStructure(){return this.treeRenderer.getStaticStructure()}};typeof window!="undefined"&&ie.autoInit();return Be(lt);})(); |
There was a problem hiding this comment.
Avoid automated semicolon insertion (90% of all statements in the enclosing function have an explicit semicolon).
| @@ -1,4 +1,4 @@ | |||
| "use strict";var LiveTemplateClient=(()=>{var ae=Object.defineProperty;var _e=Object.getOwnPropertyDescriptor;var Ce=Object.getOwnPropertyNames;var Re=Object.prototype.hasOwnProperty;var He=(a,e)=>{for(var t in e)ae(a,t,{get:e[t],enumerable:!0})},Oe=(a,e,t,n)=>{if(e&&typeof e=="object"||typeof e=="function")for(let r of Ce(e))!Re.call(a,r)&&r!==t&&ae(a,r,{get:()=>e[r],enumerable:!(n=_e(e,r))||n.enumerable});return a};var Ie=a=>Oe(ae({},"__esModule",{value:!0}),a);var Qe={};He(Qe,{LiveTemplateClient:()=>re,compareHTML:()=>Fe,loadAndApplyUpdate:()=>xe});var ve=11;function De(a,e){var t=e.attributes,n,r,s,o,i;if(!(e.nodeType===ve||a.nodeType===ve)){for(var l=t.length-1;l>=0;l--)n=t[l],r=n.name,s=n.namespaceURI,o=n.value,s?(r=n.localName||r,i=a.getAttributeNS(s,r),i!==o&&(n.prefix==="xmlns"&&(r=n.name),a.setAttributeNS(s,r,o))):(i=a.getAttribute(r),i!==o&&a.setAttribute(r,o));for(var c=a.attributes,d=c.length-1;d>=0;d--)n=c[d],r=n.name,s=n.namespaceURI,s?(r=n.localName||r,e.hasAttributeNS(s,r)||a.removeAttributeNS(s,r)):e.hasAttribute(r)||a.removeAttribute(r)}}var K,Ne="http://www.w3.org/1999/xhtml",C=typeof document=="undefined"?void 0:document,We=!!C&&"content"in C.createElement("template"),$e=!!C&&C.createRange&&"createContextualFragment"in C.createRange();function Pe(a){var e=C.createElement("template");return e.innerHTML=a,e.content.childNodes[0]}function Be(a){K||(K=C.createRange(),K.selectNode(C.body));var e=K.createContextualFragment(a);return e.childNodes[0]}function Ve(a){var e=C.createElement("body");return e.innerHTML=a,e.childNodes[0]}function Ke(a){return a=a.trim(),We?Pe(a):$e?Be(a):Ve(a)}function j(a,e){var t=a.nodeName,n=e.nodeName,r,s;return t===n?!0:(r=t.charCodeAt(0),s=n.charCodeAt(0),r<=90&&s>=97?t===n.toUpperCase():s<=90&&r>=97?n===t.toUpperCase():!1)}function je(a,e){return!e||e===Ne?C.createElement(a):C.createElementNS(e,a)}function ze(a,e){for(var t=a.firstChild;t;){var n=t.nextSibling;e.appendChild(t),t=n}return e}function le(a,e,t){a[t]!==e[t]&&(a[t]=e[t],a[t]?a.setAttribute(t,""):a.removeAttribute(t))}var be={OPTION:function(a,e){var t=a.parentNode;if(t){var n=t.nodeName.toUpperCase();n==="OPTGROUP"&&(t=t.parentNode,n=t&&t.nodeName.toUpperCase()),n==="SELECT"&&!t.hasAttribute("multiple")&&(a.hasAttribute("selected")&&!e.selected&&(a.setAttribute("selected","selected"),a.removeAttribute("selected")),t.selectedIndex=-1)}le(a,e,"selected")},INPUT:function(a,e){le(a,e,"checked"),le(a,e,"disabled"),a.value!==e.value&&(a.value=e.value),e.hasAttribute("value")||a.removeAttribute("value")},TEXTAREA:function(a,e){var t=e.value;a.value!==t&&(a.value=t);var n=a.firstChild;if(n){var r=n.nodeValue;if(r==t||!t&&r==a.placeholder)return;n.nodeValue=t}},SELECT:function(a,e){if(!e.hasAttribute("multiple")){for(var t=-1,n=0,r=a.firstChild,s,o;r;)if(o=r.nodeName&&r.nodeName.toUpperCase(),o==="OPTGROUP")s=r,r=s.firstChild,r||(r=s.nextSibling,s=null);else{if(o==="OPTION"){if(r.hasAttribute("selected")){t=n;break}n++}r=r.nextSibling,!r&&s&&(r=s.nextSibling,s=null)}a.selectedIndex=t}}},P=1,ye=11,Ee=3,we=8;function N(){}function qe(a){if(a)return a.getAttribute&&a.getAttribute("id")||a.id}function Ge(a){return function(t,n,r){if(r||(r={}),typeof n=="string")if(t.nodeName==="#document"||t.nodeName==="HTML"||t.nodeName==="BODY"){var s=n;n=C.createElement("html"),n.innerHTML=s}else n=Ke(n);else n.nodeType===ye&&(n=n.firstElementChild);var o=r.getNodeKey||qe,i=r.onBeforeNodeAdded||N,l=r.onNodeAdded||N,c=r.onBeforeElUpdated||N,d=r.onElUpdated||N,M=r.onBeforeNodeDiscarded||N,m=r.onNodeDiscarded||N,f=r.onBeforeElChildrenUpdated||N,F=r.skipFromChildren||N,L=r.addChild||function(p,g){return p.appendChild(g)},b=r.childrenOnly===!0,h=Object.create(null),u=[];function y(p){u.push(p)}function U(p,g){if(p.nodeType===P)for(var T=p.firstChild;T;){var v=void 0;g&&(v=o(T))?y(v):(m(T),T.firstChild&&U(T,g)),T=T.nextSibling}}function x(p,g,T){M(p)!==!1&&(g&&g.removeChild(p),m(p),U(p,T))}function w(p){if(p.nodeType===P||p.nodeType===ye)for(var g=p.firstChild;g;){var T=o(g);T&&(h[T]=g),w(g),g=g.nextSibling}}w(t);function S(p){l(p);for(var g=p.firstChild;g;){var T=g.nextSibling,v=o(g);if(v){var E=h[v];E&&j(g,E)?(g.parentNode.replaceChild(E,g),_(E,g)):S(g)}else S(g);g=T}}function k(p,g,T){for(;g;){var v=g.nextSibling;(T=o(g))?y(T):x(g,p,!0),g=v}}function _(p,g,T){var v=o(g);if(v&&delete h[v],!T){var E=c(p,g);if(E===!1||(E instanceof HTMLElement&&(p=E,w(p)),a(p,g),d(p),f(p,g)===!1))return}p.nodeName!=="TEXTAREA"?H(p,g):be.TEXTAREA(p,g)}function H(p,g){var T=F(p,g),v=g.firstChild,E=p.firstChild,W,R,$,B,I;e:for(;v;){for(B=v.nextSibling,W=o(v);!T&&E;){if($=E.nextSibling,v.isSameNode&&v.isSameNode(E)){v=B,E=$;continue e}R=o(E);var V=E.nodeType,D=void 0;if(V===v.nodeType&&(V===P?(W?W!==R&&((I=h[W])?$===I?D=!1:(p.insertBefore(I,E),R?y(R):x(E,p,!0),E=I,R=o(E)):D=!1):R&&(D=!1),D=D!==!1&&j(E,v),D&&_(E,v)):(V===Ee||V==we)&&(D=!0,E.nodeValue!==v.nodeValue&&(E.nodeValue=v.nodeValue))),D){v=B,E=$;continue e}R?y(R):x(E,p,!0),E=$}if(W&&(I=h[W])&&j(I,v))T||L(p,I),_(I,v);else{var oe=i(v);oe!==!1&&(oe&&(v=oe),v.actualize&&(v=v.actualize(p.ownerDocument||C)),L(p,v),S(v))}v=B,E=$}k(p,E,R);var me=be[p.nodeName];me&&me(p,g)}var A=t,O=A.nodeType,fe=n.nodeType;if(!b){if(O===P)fe===P?j(t,n)||(m(t),A=ze(t,je(n.nodeName,n.namespaceURI))):A=n;else if(O===Ee||O===we){if(fe===O)return A.nodeValue!==n.nodeValue&&(A.nodeValue=n.nodeValue),A;A=n}}if(A===n)m(t);else{if(n.isSameNode&&n.isSameNode(A))return;if(_(A,n,b),u)for(var se=0,Ue=u.length;se<Ue;se++){var ie=h[u[se]];ie&&x(ie,ie.parentNode,!1)}}return!b&&A!==t&&t.parentNode&&(A.actualize&&(A=A.actualize(t.ownerDocument||C)),t.parentNode.replaceChild(A,t)),A}}var Je=Ge(De),Se=Je;var ce=["text","textarea","number","email","password","search","tel","url","date","time","datetime-local","color","range"];var z=class{constructor(e){this.logger=e;this.wrapperElement=null;this.focusableElements=[];this.lastFocusedElement=null;this.lastFocusedSelectionStart=null;this.lastFocusedSelectionEnd=null}attach(e){this.wrapperElement=e,e&&(this.updateFocusableElements(),this.setupFocusTracking())}reset(){this.wrapperElement=null,this.focusableElements=[],this.lastFocusedElement=null,this.lastFocusedSelectionStart=null,this.lastFocusedSelectionEnd=null}updateFocusableElements(){if(!this.wrapperElement)return;let n=`${ce.map(r=>r==="textarea"?"textarea:not([disabled])":`input[type="${r}"]:not([disabled])`).join(", ")}, select:not([disabled]), button:not([disabled]), [contenteditable="true"], [tabindex]:not([tabindex="-1"])`;this.focusableElements=Array.from(this.wrapperElement.querySelectorAll(n))}setupFocusTracking(){if(!this.wrapperElement)return;let e=this.wrapperElement.getAttribute("data-lvt-id"),t=`__lvt_focus_tracker_${e}`,n=`__lvt_blur_tracker_${e}`,r=o=>{var l;let i=o.target;!i||!((l=this.wrapperElement)!=null&&l.contains(i))||(this.isTextualInput(i)||i instanceof HTMLSelectElement)&&(this.lastFocusedElement=i,this.logger.debug("[Focus] Tracked focus on:",i.tagName,i.id||i.getAttribute("name")),this.isTextualInput(i)&&(this.lastFocusedSelectionStart=i.selectionStart,this.lastFocusedSelectionEnd=i.selectionEnd))},s=o=>{var l;let i=o.target;!i||!((l=this.wrapperElement)!=null&&l.contains(i))||this.isTextualInput(i)&&i===this.lastFocusedElement&&(this.lastFocusedSelectionStart=i.selectionStart,this.lastFocusedSelectionEnd=i.selectionEnd,this.logger.debug("[Focus] Saved cursor on blur:",this.lastFocusedSelectionStart,"-",this.lastFocusedSelectionEnd))};document[t]&&document.removeEventListener("focus",document[t],!0),document[n]&&document.removeEventListener("blur",document[n],!0),document[t]=r,document[n]=s,document.addEventListener("focus",r,!0),document.addEventListener("blur",s,!0),this.logger.debug("[Focus] Focus tracking set up")}restoreFocusedElement(){var r,s,o;if(this.logger.debug("[Focus] restoreFocusedElement - lastFocusedElement:",(r=this.lastFocusedElement)==null?void 0:r.tagName,((s=this.lastFocusedElement)==null?void 0:s.id)||((o=this.lastFocusedElement)==null?void 0:o.getAttribute("name"))),!this.lastFocusedElement||!this.wrapperElement){this.logger.debug("[Focus] No element to restore");return}let e=this.getElementSelector(this.lastFocusedElement);if(this.logger.debug("[Focus] Selector for last focused:",e),!e){this.logger.debug("[Focus] Could not generate selector");return}let t=null;if(e.startsWith("data-focus-index-")){this.updateFocusableElements();let i=parseInt(e.replace("data-focus-index-",""),10);t=this.focusableElements[i]||null,this.logger.debug("[Focus] Found by index:",i,t==null?void 0:t.tagName)}else t=this.wrapperElement.querySelector(e),this.logger.debug("[Focus] Found by selector:",e,t==null?void 0:t.tagName);if(!t){this.logger.debug("[Focus] Element not found in updated DOM");return}let n=t.matches(":focus");this.logger.debug("[Focus] Already focused:",n),n||(t.focus(),this.logger.debug("[Focus] Restored focus")),this.isTextualInput(t)&&this.lastFocusedSelectionStart!==null&&this.lastFocusedSelectionEnd!==null&&(t.setSelectionRange(this.lastFocusedSelectionStart,this.lastFocusedSelectionEnd),this.logger.debug("[Focus] Restored cursor:",this.lastFocusedSelectionStart,"-",this.lastFocusedSelectionEnd))}isTextualInput(e){return e instanceof HTMLTextAreaElement?!0:e instanceof HTMLInputElement?ce.indexOf(e.type)>=0:!1}getLastFocusedElement(){return this.lastFocusedElement}getElementSelector(e){if(e.id)return`#${e.id}`;if(e.name)return`[name="${e.name}"]`;if(e.getAttribute("data-key"))return`[data-key="${e.getAttribute("data-key")}"]`;let t=this.focusableElements.indexOf(e);return t>=0?`data-focus-index-${t}`:null}};function Me(a){a.querySelectorAll("[lvt-scroll]").forEach(t=>{let n=t,r=n.getAttribute("lvt-scroll"),s=n.getAttribute("lvt-scroll-behavior")||"auto",o=parseInt(n.getAttribute("lvt-scroll-threshold")||"100",10);if(r)switch(r){case"bottom":n.scrollTo({top:n.scrollHeight,behavior:s});break;case"bottom-sticky":{n.scrollHeight-n.scrollTop-n.clientHeight<=o&&n.scrollTo({top:n.scrollHeight,behavior:s});break}case"top":n.scrollTo({top:0,behavior:s});break;case"preserve":break;default:console.warn(`Unknown lvt-scroll mode: ${r}`)}})}function ke(a){a.querySelectorAll("[lvt-highlight]").forEach(t=>{let n=t.getAttribute("lvt-highlight"),r=parseInt(t.getAttribute("lvt-highlight-duration")||"500",10),s=t.getAttribute("lvt-highlight-color")||"#ffc107";if(!n)return;let o=t,i=o.style.backgroundColor,l=o.style.transition;o.style.transition=`background-color ${r}ms ease-out`,o.style.backgroundColor=s,setTimeout(()=>{o.style.backgroundColor=i,setTimeout(()=>{o.style.transition=l},r)},50)})}function Ae(a){if(a.querySelectorAll("[lvt-animate]").forEach(t=>{let n=t.getAttribute("lvt-animate"),r=parseInt(t.getAttribute("lvt-animate-duration")||"300",10);if(!n)return;let s=t;switch(s.style.setProperty("--lvt-animate-duration",`${r}ms`),n){case"fade":s.style.animation="lvt-fade-in var(--lvt-animate-duration) ease-out";break;case"slide":s.style.animation="lvt-slide-in var(--lvt-animate-duration) ease-out";break;case"scale":s.style.animation="lvt-scale-in var(--lvt-animate-duration) ease-out";break;default:console.warn(`Unknown lvt-animate mode: ${n}`)}s.addEventListener("animationend",()=>{s.style.animation=""},{once:!0})}),!document.getElementById("lvt-animate-styles")){let t=document.createElement("style");t.id="lvt-animate-styles",t.textContent=` | |||
| "use strict";var LiveTemplateClient=(()=>{var ce=Object.defineProperty;var Oe=Object.getOwnPropertyDescriptor;var Ne=Object.getOwnPropertyNames;var De=Object.prototype.hasOwnProperty;var We=(a,e)=>{for(var t in e)ce(a,t,{get:e[t],enumerable:!0})},$e=(a,e,t,n)=>{if(e&&typeof e=="object"||typeof e=="function")for(let r of Ne(e))!De.call(a,r)&&r!==t&&ce(a,r,{get:()=>e[r],enumerable:!(n=Oe(e,r))||n.enumerable});return a};var Be=a=>$e(ce({},"__esModule",{value:!0}),a);var lt={};We(lt,{LiveTemplateClient:()=>ie,checkLvtConfirm:()=>z,compareHTML:()=>He,extractLvtData:()=>xe,loadAndApplyUpdate:()=>Ie,setupReactiveAttributeListeners:()=>Z});var be=11;function Ke(a,e){var t=e.attributes,n,r,s,o,i;if(!(e.nodeType===be||a.nodeType===be)){for(var l=t.length-1;l>=0;l--)n=t[l],r=n.name,s=n.namespaceURI,o=n.value,s?(r=n.localName||r,i=a.getAttributeNS(s,r),i!==o&&(n.prefix==="xmlns"&&(r=n.name),a.setAttributeNS(s,r,o))):(i=a.getAttribute(r),i!==o&&a.setAttribute(r,o));for(var c=a.attributes,d=c.length-1;d>=0;d--)n=c[d],r=n.name,s=n.namespaceURI,s?(r=n.localName||r,e.hasAttributeNS(s,r)||a.removeAttributeNS(s,r)):e.hasAttribute(r)||a.removeAttribute(r)}}var V,Pe="http://www.w3.org/1999/xhtml",_=typeof document=="undefined"?void 0:document,Ve=!!_&&"content"in _.createElement("template"),je=!!_&&_.createRange&&"createContextualFragment"in _.createRange();function qe(a){var e=_.createElement("template");return e.innerHTML=a,e.content.childNodes[0]}function ze(a){V||(V=_.createRange(),V.selectNode(_.body));var e=V.createContextualFragment(a);return e.childNodes[0]}function Je(a){var e=_.createElement("body");return e.innerHTML=a,e.childNodes[0]}function Ge(a){return a=a.trim(),Ve?qe(a):je?ze(a):Je(a)}function j(a,e){var t=a.nodeName,n=e.nodeName,r,s;return t===n?!0:(r=t.charCodeAt(0),s=n.charCodeAt(0),r<=90&&s>=97?t===n.toUpperCase():s<=90&&r>=97?n===t.toUpperCase():!1)}function Xe(a,e){return!e||e===Pe?_.createElement(a):_.createElementNS(e,a)}function Ye(a,e){for(var t=a.firstChild;t;){var n=t.nextSibling;e.appendChild(t),t=n}return e}function de(a,e,t){a[t]!==e[t]&&(a[t]=e[t],a[t]?a.setAttribute(t,""):a.removeAttribute(t))}var Ee={OPTION:function(a,e){var t=a.parentNode;if(t){var n=t.nodeName.toUpperCase();n==="OPTGROUP"&&(t=t.parentNode,n=t&&t.nodeName.toUpperCase()),n==="SELECT"&&!t.hasAttribute("multiple")&&(a.hasAttribute("selected")&&!e.selected&&(a.setAttribute("selected","selected"),a.removeAttribute("selected")),t.selectedIndex=-1)}de(a,e,"selected")},INPUT:function(a,e){de(a,e,"checked"),de(a,e,"disabled"),a.value!==e.value&&(a.value=e.value),e.hasAttribute("value")||a.removeAttribute("value")},TEXTAREA:function(a,e){var t=e.value;a.value!==t&&(a.value=t);var n=a.firstChild;if(n){var r=n.nodeValue;if(r==t||!t&&r==a.placeholder)return;n.nodeValue=t}},SELECT:function(a,e){if(!e.hasAttribute("multiple")){for(var t=-1,n=0,r=a.firstChild,s,o;r;)if(o=r.nodeName&&r.nodeName.toUpperCase(),o==="OPTGROUP")s=r,r=s.firstChild,r||(r=s.nextSibling,s=null);else{if(o==="OPTION"){if(r.hasAttribute("selected")){t=n;break}n++}r=r.nextSibling,!r&&s&&(r=s.nextSibling,s=null)}a.selectedIndex=t}}},B=1,we=11,Se=3,Ae=8;function D(){}function Qe(a){if(a)return a.getAttribute&&a.getAttribute("id")||a.id}function Ze(a){return function(t,n,r){if(r||(r={}),typeof n=="string")if(t.nodeName==="#document"||t.nodeName==="HTML"||t.nodeName==="BODY"){var s=n;n=_.createElement("html"),n.innerHTML=s}else n=Ge(n);else n.nodeType===we&&(n=n.firstElementChild);var o=r.getNodeKey||Qe,i=r.onBeforeNodeAdded||D,l=r.onNodeAdded||D,c=r.onBeforeElUpdated||D,d=r.onElUpdated||D,u=r.onBeforeNodeDiscarded||D,g=r.onNodeDiscarded||D,f=r.onBeforeElChildrenUpdated||D,A=r.skipFromChildren||D,M=r.addChild||function(h,m){return h.appendChild(m)},y=r.childrenOnly===!0,v=Object.create(null),p=[];function E(h){p.push(h)}function R(h,m){if(h.nodeType===B)for(var x=h.firstChild;x;){var b=void 0;m&&(b=o(x))?E(b):(g(x),x.firstChild&&R(x,m)),x=x.nextSibling}}function C(h,m,x){u(h)!==!1&&(m&&m.removeChild(h),g(h),R(h,x))}function S(h){if(h.nodeType===B||h.nodeType===we)for(var m=h.firstChild;m;){var x=o(m);x&&(v[x]=m),S(m),m=m.nextSibling}}S(t);function T(h){l(h);for(var m=h.firstChild;m;){var x=m.nextSibling,b=o(m);if(b){var w=v[b];w&&j(m,w)?(m.parentNode.replaceChild(w,m),F(w,m)):T(m)}else T(m);m=x}}function L(h,m,x){for(;m;){var b=m.nextSibling;(x=o(m))?E(x):C(m,h,!0),m=b}}function F(h,m,x){var b=o(m);if(b&&delete v[b],!x){var w=c(h,m);if(w===!1||(w instanceof HTMLElement&&(h=w,S(h)),a(h,m),d(h),f(h,m)===!1))return}h.nodeName!=="TEXTAREA"?H(h,m):Ee.TEXTAREA(h,m)}function H(h,m){var x=A(h,m),b=m.firstChild,w=h.firstChild,W,I,$,K,O;e:for(;b;){for(K=b.nextSibling,W=o(b);!x&&w;){if($=w.nextSibling,b.isSameNode&&b.isSameNode(w)){b=K,w=$;continue e}I=o(w);var P=w.nodeType,N=void 0;if(P===b.nodeType&&(P===B?(W?W!==I&&((O=v[W])?$===O?N=!1:(h.insertBefore(O,w),I?E(I):C(w,h,!0),w=O,I=o(w)):N=!1):I&&(N=!1),N=N!==!1&&j(w,b),N&&F(w,b)):(P===Se||P==Ae)&&(N=!0,w.nodeValue!==b.nodeValue&&(w.nodeValue=b.nodeValue))),N){b=K,w=$;continue e}I?E(I):C(w,h,!0),w=$}if(W&&(O=v[W])&&j(O,b))x||M(h,O),F(O,b);else{var le=i(b);le!==!1&&(le&&(b=le),b.actualize&&(b=b.actualize(h.ownerDocument||_)),M(h,b),T(b))}b=K,w=$}L(h,w,I);var ye=Ee[h.nodeName];ye&&ye(h,m)}var k=t,U=k.nodeType,ve=n.nodeType;if(!y){if(U===B)ve===B?j(t,n)||(g(t),k=Ye(t,Xe(n.nodeName,n.namespaceURI))):k=n;else if(U===Se||U===Ae){if(ve===U)return k.nodeValue!==n.nodeValue&&(k.nodeValue=n.nodeValue),k;k=n}}if(k===n)g(t);else{if(n.isSameNode&&n.isSameNode(k))return;if(F(k,n,y),p)for(var oe=0,Ue=p.length;oe<Ue;oe++){var ae=v[p[oe]];ae&&C(ae,ae.parentNode,!1)}}return!y&&k!==t&&t.parentNode&&(k.actualize&&(k=k.actualize(t.ownerDocument||_)),t.parentNode.replaceChild(k,t)),k}}var et=Ze(Ke),Me=et;var ue=["text","textarea","number","email","password","search","tel","url","date","time","datetime-local","color","range"];var q=class{constructor(e){this.logger=e;this.wrapperElement=null;this.focusableElements=[];this.lastFocusedElement=null;this.lastFocusedSelectionStart=null;this.lastFocusedSelectionEnd=null}attach(e){this.wrapperElement=e,e&&(this.updateFocusableElements(),this.setupFocusTracking())}reset(){this.wrapperElement=null,this.focusableElements=[],this.lastFocusedElement=null,this.lastFocusedSelectionStart=null,this.lastFocusedSelectionEnd=null}updateFocusableElements(){if(!this.wrapperElement)return;let n=`${ue.map(r=>r==="textarea"?"textarea:not([disabled])":`input[type="${r}"]:not([disabled])`).join(", ")}, select:not([disabled]), button:not([disabled]), [contenteditable="true"], [tabindex]:not([tabindex="-1"])`;this.focusableElements=Array.from(this.wrapperElement.querySelectorAll(n))}setupFocusTracking(){if(!this.wrapperElement)return;let e=this.wrapperElement.getAttribute("data-lvt-id"),t=`__lvt_focus_tracker_${e}`,n=`__lvt_blur_tracker_${e}`,r=o=>{var l;let i=o.target;!i||!((l=this.wrapperElement)!=null&&l.contains(i))||(this.isTextualInput(i)||i instanceof HTMLSelectElement)&&(this.lastFocusedElement=i,this.logger.debug("[Focus] Tracked focus on:",i.tagName,i.id||i.getAttribute("name")),this.isTextualInput(i)&&(this.lastFocusedSelectionStart=i.selectionStart,this.lastFocusedSelectionEnd=i.selectionEnd))},s=o=>{var l;let i=o.target;!i||!((l=this.wrapperElement)!=null&&l.contains(i))||this.isTextualInput(i)&&i===this.lastFocusedElement&&(this.lastFocusedSelectionStart=i.selectionStart,this.lastFocusedSelectionEnd=i.selectionEnd,this.logger.debug("[Focus] Saved cursor on blur:",this.lastFocusedSelectionStart,"-",this.lastFocusedSelectionEnd))};document[t]&&document.removeEventListener("focus",document[t],!0),document[n]&&document.removeEventListener("blur",document[n],!0),document[t]=r,document[n]=s,document.addEventListener("focus",r,!0),document.addEventListener("blur",s,!0),this.logger.debug("[Focus] Focus tracking set up")}restoreFocusedElement(){var r,s,o;if(this.logger.debug("[Focus] restoreFocusedElement - lastFocusedElement:",(r=this.lastFocusedElement)==null?void 0:r.tagName,((s=this.lastFocusedElement)==null?void 0:s.id)||((o=this.lastFocusedElement)==null?void 0:o.getAttribute("name"))),!this.lastFocusedElement||!this.wrapperElement){this.logger.debug("[Focus] No element to restore");return}let e=this.getElementSelector(this.lastFocusedElement);if(this.logger.debug("[Focus] Selector for last focused:",e),!e){this.logger.debug("[Focus] Could not generate selector");return}let t=null;if(e.startsWith("data-focus-index-")){this.updateFocusableElements();let i=parseInt(e.replace("data-focus-index-",""),10);t=this.focusableElements[i]||null,this.logger.debug("[Focus] Found by index:",i,t==null?void 0:t.tagName)}else t=this.wrapperElement.querySelector(e),this.logger.debug("[Focus] Found by selector:",e,t==null?void 0:t.tagName);if(!t){this.logger.debug("[Focus] Element not found in updated DOM");return}let n=t.matches(":focus");this.logger.debug("[Focus] Already focused:",n),n||(t.focus(),this.logger.debug("[Focus] Restored focus")),this.isTextualInput(t)&&this.lastFocusedSelectionStart!==null&&this.lastFocusedSelectionEnd!==null&&(t.setSelectionRange(this.lastFocusedSelectionStart,this.lastFocusedSelectionEnd),this.logger.debug("[Focus] Restored cursor:",this.lastFocusedSelectionStart,"-",this.lastFocusedSelectionEnd))}isTextualInput(e){return e instanceof HTMLTextAreaElement?!0:e instanceof HTMLInputElement?ue.indexOf(e.type)>=0:!1}getLastFocusedElement(){return this.lastFocusedElement}getElementSelector(e){if(e.id)return`#${e.id}`;if(e.name)return`[name="${e.name}"]`;if(e.getAttribute("data-key"))return`[data-key="${e.getAttribute("data-key")}"]`;let t=this.focusableElements.indexOf(e);return t>=0?`data-focus-index-${t}`:null}};function Te(a){a.querySelectorAll("[lvt-scroll]").forEach(t=>{let n=t,r=n.getAttribute("lvt-scroll"),s=n.getAttribute("lvt-scroll-behavior")||"auto",o=parseInt(n.getAttribute("lvt-scroll-threshold")||"100",10);if(r)switch(r){case"bottom":n.scrollTo({top:n.scrollHeight,behavior:s});break;case"bottom-sticky":{n.scrollHeight-n.scrollTop-n.clientHeight<=o&&n.scrollTo({top:n.scrollHeight,behavior:s});break}case"top":n.scrollTo({top:0,behavior:s});break;case"preserve":break;default:console.warn(`Unknown lvt-scroll mode: ${r}`)}})}function Le(a){a.querySelectorAll("[lvt-highlight]").forEach(t=>{let n=t.getAttribute("lvt-highlight"),r=parseInt(t.getAttribute("lvt-highlight-duration")||"500",10),s=t.getAttribute("lvt-highlight-color")||"#ffc107";if(!n)return;let o=t,i=o.style.backgroundColor,l=o.style.transition;o.style.transition=`background-color ${r}ms ease-out`,o.style.backgroundColor=s,setTimeout(()=>{o.style.backgroundColor=i,setTimeout(()=>{o.style.transition=l},r)},50)})}function ke(a){if(a.querySelectorAll("[lvt-animate]").forEach(t=>{let n=t.getAttribute("lvt-animate"),r=parseInt(t.getAttribute("lvt-animate-duration")||"300",10);if(!n)return;let s=t;switch(s.style.setProperty("--lvt-animate-duration",`${r}ms`),n){case"fade":s.style.animation="lvt-fade-in var(--lvt-animate-duration) ease-out";break;case"slide":s.style.animation="lvt-slide-in var(--lvt-animate-duration) ease-out";break;case"scale":s.style.animation="lvt-scale-in var(--lvt-animate-duration) ease-out";break;default:console.warn(`Unknown lvt-animate mode: ${n}`)}s.addEventListener("animationend",()=>{s.style.animation=""},{once:!0})}),!document.getElementById("lvt-animate-styles")){let t=document.createElement("style");t.id="lvt-animate-styles",t.textContent=` | |||
There was a problem hiding this comment.
This expression always evaluates to true.
| } | ||
| } | ||
| `,document.head.appendChild(t)}}function de(a,e){let t=null;return function(...r){let s=this;t!==null&&clearTimeout(t),t=window.setTimeout(()=>{a.apply(s,r)},e)}}function ue(a,e){let t=!1;return function(...r){let s=this;t||(a.apply(s,r),t=!0,setTimeout(()=>{t=!1},e))}}var q=class{constructor(e,t){this.context=e;this.logger=t}setupEventDelegation(){let e=this.context.getWrapperElement();if(!e)return;let t=["click","submit","change","input","keydown","keyup","focus","blur","mouseenter","mouseleave"],n=e.getAttribute("data-lvt-id"),r=this.context.getRateLimitedHandlers();t.forEach(s=>{let o=`__lvt_delegated_${s}_${n}`,i=document[o];i&&document.removeEventListener(s,i,!1);let l=c=>{var L;let d=this.context.getWrapperElement();if(!d)return;s==="submit"&&(window.__lvtSubmitListenerTriggered=!0,window.__lvtSubmitEventTarget=(L=c.target)==null?void 0:L.tagName),this.logger.debug("Event listener triggered:",s,c.target);let M=c.target;if(!M)return;let m=M,f=!1;for(;m;){if(m===d){f=!0;break}m=m.parentElement}if(s==="submit"&&(window.__lvtInWrapper=f,window.__lvtWrapperElement=d.getAttribute("data-lvt-id")),!f)return;let F=`lvt-${s}`;for(m=M;m&&m!==d.parentElement;){let b=m.getAttribute(F),h=m;if(!b&&(s==="change"||s==="input")){let u=m.closest("form");u&&u.hasAttribute("lvt-change")&&(b=u.getAttribute("lvt-change"),h=u)}if(b&&h){if(s==="submit"&&(window.__lvtActionFound=b,window.__lvtActionElement=h.tagName),s==="submit"&&c.preventDefault(),(s==="keydown"||s==="keyup")&&h.hasAttribute("lvt-key")){let w=h.getAttribute("lvt-key");if(w&&c.key!==w){m=m.parentElement;continue}}let u=h,y=()=>{if(this.logger.debug("handleAction called",{action:b,eventType:s,targetElement:u}),b==="delete"&&u.hasAttribute("lvt-confirm")){let S=u.getAttribute("lvt-confirm")||"Are you sure you want to delete this item?";if(!confirm(S)){this.logger.debug("Delete action cancelled by user");return}}let w={action:b,data:{}};if(u instanceof HTMLFormElement){this.logger.debug("Processing form element");let S=new FormData(u),k=Array.from(u.querySelectorAll('input[type="checkbox"][name]')),_=new Set(k.map(H=>H.name));_.forEach(H=>{w.data[H]=!1}),S.forEach((H,A)=>{_.has(A)?(w.data[A]=!0,this.logger.debug("Converted checkbox",A,"to true")):w.data[A]=this.context.parseValue(H)}),this.logger.debug("Form data collected:",w.data)}else if(s==="change"||s==="input"){if(u instanceof HTMLInputElement){let S=u.name||"value";w.data[S]=this.context.parseValue(u.value)}else if(u instanceof HTMLSelectElement){let S=u.name||"value";w.data[S]=this.context.parseValue(u.value)}else if(u instanceof HTMLTextAreaElement){let S=u.name||"value";w.data[S]=this.context.parseValue(u.value)}}if(Array.from(u.attributes).forEach(S=>{if(S.name.startsWith("lvt-data-")){let k=S.name.replace("lvt-data-","");w.data[k]=this.context.parseValue(S.value)}}),Array.from(u.attributes).forEach(S=>{if(S.name.startsWith("lvt-value-")){let k=S.name.replace("lvt-value-","");w.data[k]=this.context.parseValue(S.value)}}),s==="submit"&&u instanceof HTMLFormElement){let k=c.submitter,_=null;k&&k.hasAttribute("lvt-disable-with")&&(_=k.textContent,k.disabled=!0,k.textContent=k.getAttribute("lvt-disable-with"),this.logger.debug("Disabled submit button")),this.context.setActiveSubmission(u,k||null,_),u.querySelectorAll('input[type="file"][lvt-upload]').forEach(A=>{let O=A.getAttribute("lvt-upload");O&&(this.logger.debug("Triggering pending uploads for:",O),this.context.triggerPendingUploads(O))}),u.dispatchEvent(new CustomEvent("lvt:pending",{detail:w})),this.logger.debug("Emitted lvt:pending event")}this.logger.debug("About to send message:",w),this.logger.debug("WebSocket state:",this.context.getWebSocketReadyState()),this.context.send(w),this.logger.debug("send() called")},U=h.getAttribute("lvt-throttle"),x=h.getAttribute("lvt-debounce");if(U||x){r.has(h)||r.set(h,new Map);let w=r.get(h),S=`${s}:${b}`,k=w.get(S);if(!k){if(U){let _=parseInt(U,10);k=ue(y,_)}else if(x){let _=parseInt(x,10);k=de(y,_)}k&&w.set(S,k)}k&&k()}else s==="submit"&&(window.__lvtBeforeHandleAction=!0),y(),s==="submit"&&(window.__lvtAfterHandleAction=!0);return}m=m.parentElement}};document[o]=l,document.addEventListener(s,l,!1),this.logger.debug("Registered event listener:",s,"with key:",o)})}setupWindowEventDelegation(){let e=this.context.getWrapperElement();if(!e)return;let t=["keydown","keyup","scroll","resize","focus","blur"],n=e.getAttribute("data-lvt-id"),r=this.context.getRateLimitedHandlers();t.forEach(s=>{let o=`__lvt_window_${s}_${n}`,i=window[o];i&&window.removeEventListener(s,i);let l=c=>{let d=this.context.getWrapperElement();if(!d)return;let M=`lvt-window-${s}`;d.querySelectorAll(`[${M}]`).forEach(f=>{let F=f.getAttribute(M);if(!F)return;if((s==="keydown"||s==="keyup")&&f.hasAttribute("lvt-key")){let y=f.getAttribute("lvt-key");if(y&&c.key!==y)return}let L={action:F,data:{}};Array.from(f.attributes).forEach(y=>{if(y.name.startsWith("lvt-data-")){let U=y.name.replace("lvt-data-","");L.data[U]=this.context.parseValue(y.value)}}),Array.from(f.attributes).forEach(y=>{if(y.name.startsWith("lvt-value-")){let U=y.name.replace("lvt-value-","");L.data[U]=this.context.parseValue(y.value)}});let b=f.getAttribute("lvt-throttle"),h=f.getAttribute("lvt-debounce"),u=()=>this.context.send(L);if(b||h){r.has(f)||r.set(f,new Map);let y=r.get(f),U=`window-${s}:${F}`,x=y.get(U);if(!x){if(b){let w=parseInt(b,10);x=ue(u,w)}else if(h){let w=parseInt(h,10);x=de(u,w)}x&&y.set(U,x)}x&&x()}else u()})};window[o]=l,window.addEventListener(s,l)})}setupClickAwayDelegation(){let e=this.context.getWrapperElement();if(!e)return;let n=`__lvt_click_away_${e.getAttribute("data-lvt-id")}`,r=document[n];r&&document.removeEventListener("click",r);let s=o=>{let i=this.context.getWrapperElement();if(!i)return;let l=o.target;i.querySelectorAll("[lvt-click-away]").forEach(d=>{if(!d.contains(l)){let M=d.getAttribute("lvt-click-away");if(!M)return;let m={action:M,data:{}};Array.from(d.attributes).forEach(f=>{if(f.name.startsWith("lvt-data-")){let F=f.name.replace("lvt-data-","");m.data[F]=this.context.parseValue(f.value)}}),Array.from(d.attributes).forEach(f=>{if(f.name.startsWith("lvt-value-")){let F=f.name.replace("lvt-value-","");m.data[F]=this.context.parseValue(f.value)}}),this.context.send(m)}})};document[n]=s,document.addEventListener("click",s)}setupModalDelegation(){let e=this.context.getWrapperElement();if(!e)return;let t=e.getAttribute("data-lvt-id"),n=`__lvt_modal_open_${t}`,r=document[n];r&&document.removeEventListener("click",r);let s=L=>{var y;let b=this.context.getWrapperElement();if(!b)return;let h=(y=L.target)==null?void 0:y.closest("[lvt-modal-open]");if(!h||!b.contains(h))return;let u=h.getAttribute("lvt-modal-open");u&&(L.preventDefault(),this.context.openModal(u))};document[n]=s,document.addEventListener("click",s);let o=`__lvt_modal_close_${t}`,i=document[o];i&&document.removeEventListener("click",i);let l=L=>{var y;let b=this.context.getWrapperElement();if(!b)return;let h=(y=L.target)==null?void 0:y.closest("[lvt-modal-close]");if(!h||!b.contains(h))return;let u=h.getAttribute("lvt-modal-close");u&&(L.preventDefault(),this.context.closeModal(u))};document[o]=l,document.addEventListener("click",l);let c=`__lvt_modal_backdrop_${t}`,d=document[c];d&&document.removeEventListener("click",d);let M=L=>{let b=L.target;if(!b.hasAttribute("data-modal-backdrop"))return;let h=b.getAttribute("data-modal-id");h&&this.context.closeModal(h)};document[c]=M,document.addEventListener("click",M);let m=`__lvt_modal_escape_${t}`,f=document[m];f&&document.removeEventListener("keydown",f);let F=L=>{if(L.key!=="Escape")return;let b=this.context.getWrapperElement();if(!b)return;let h=b.querySelectorAll('[role="dialog"]:not([hidden])');if(h.length>0){let u=h[h.length-1];u.id&&this.context.closeModal(u.id)}};document[m]=F,document.addEventListener("keydown",F)}};var G=class{constructor(e,t){this.context=e;this.logger=t;this.infiniteScrollObserver=null;this.mutationObserver=null}setupInfiniteScrollObserver(){if(!this.context.getWrapperElement())return;let t=document.getElementById("scroll-sentinel");t&&(this.infiniteScrollObserver&&this.infiniteScrollObserver.disconnect(),this.infiniteScrollObserver=new IntersectionObserver(n=>{n[0].isIntersecting&&(this.logger.debug("Sentinel visible, sending load_more action"),this.context.send({action:"load_more"}))},{rootMargin:"200px"}),this.infiniteScrollObserver.observe(t),this.logger.debug("Observer set up successfully"))}setupInfiniteScrollMutationObserver(){let e=this.context.getWrapperElement();e&&(this.mutationObserver&&this.mutationObserver.disconnect(),this.mutationObserver=new MutationObserver(()=>{this.setupInfiniteScrollObserver()}),this.mutationObserver.observe(e,{childList:!0,subtree:!0}),this.logger.debug("MutationObserver set up successfully"))}teardown(){this.infiniteScrollObserver&&(this.infiniteScrollObserver.disconnect(),this.infiniteScrollObserver=null),this.mutationObserver&&(this.mutationObserver.disconnect(),this.mutationObserver=null)}};var J=class{constructor(e){this.logger=e}open(e){let t=document.getElementById(e);if(!t){this.logger.warn(`Modal with id="${e}" not found`);return}t.removeAttribute("hidden"),t.style.display="flex",t.setAttribute("aria-hidden","false"),t.dispatchEvent(new CustomEvent("lvt:modal-opened",{bubbles:!0})),this.logger.info(`Opened modal: ${e}`);let n=t.querySelector("input, textarea, select");n&&setTimeout(()=>{let r=document.activeElement,s=i=>i?i===document.body||i.offsetParent!==null?!0:i.getClientRects().length>0:!1;(!r||!t.contains(r)||!s(r))&&n.focus()},100)}close(e){let t=document.getElementById(e);if(!t){this.logger.warn(`Modal with id="${e}" not found`);return}t.setAttribute("hidden",""),t.style.display="none",t.setAttribute("aria-hidden","true"),t.dispatchEvent(new CustomEvent("lvt:modal-closed",{bubbles:!0})),this.logger.info(`Closed modal: ${e}`)}};var X=class{constructor(){this.bar=null}show(){if(this.bar)return;let e=document.createElement("div");if(e.style.cssText=` | ||
| `,document.head.appendChild(t)}}function pe(a,e){let t=null;return function(...r){let s=this;t!==null&&clearTimeout(t),t=window.setTimeout(()=>{a.apply(s,r)},e)}}function ge(a,e){let t=!1;return function(...r){let s=this;t||(a.apply(s,r),t=!0,setTimeout(()=>{t=!1},e))}}function z(a){if(a.hasAttribute("lvt-confirm")){let e=a.getAttribute("lvt-confirm");if(e&&!confirm(e))return!1}return!0}function xe(a){let e={},t=a.attributes;for(let n=0;n<t.length;n++){let r=t[n];if(r.name.startsWith("lvt-data-")){let s=r.name.substring(9);e[s]=r.value}}return e}var J=class{constructor(e,t){this.context=e;this.logger=t}setupEventDelegation(){let e=this.context.getWrapperElement();if(!e)return;let t=["click","submit","change","input","keydown","keyup","focus","blur","mouseenter","mouseleave"],n=e.getAttribute("data-lvt-id"),r=this.context.getRateLimitedHandlers();t.forEach(s=>{let o=`__lvt_delegated_${s}_${n}`,i=document[o];i&&document.removeEventListener(s,i,!1);let l=c=>{var M;let d=this.context.getWrapperElement();if(!d)return;s==="submit"&&(window.__lvtSubmitListenerTriggered=!0,window.__lvtSubmitEventTarget=(M=c.target)==null?void 0:M.tagName),this.logger.debug("Event listener triggered:",s,c.target);let u=c.target;if(!u)return;let g=u,f=!1;for(;g;){if(g===d){f=!0;break}g=g.parentElement}if(s==="submit"&&(window.__lvtInWrapper=f,window.__lvtWrapperElement=d.getAttribute("data-lvt-id")),!f)return;let A=`lvt-${s}`;for(g=u;g&&g!==d.parentElement;){let y=g.getAttribute(A),v=g;if(!y&&s==="submit"&&g instanceof HTMLFormElement){let p=g.getAttribute("lvt-persist");p&&(y=`persist:${p}`,v=g)}if(!y&&(s==="change"||s==="input")){let p=g.closest("form");p&&p.hasAttribute("lvt-change")&&(y=p.getAttribute("lvt-change"),v=p)}if(y&&v){if(s==="submit"&&(window.__lvtActionFound=y,window.__lvtActionElement=v.tagName),s==="submit"&&c.preventDefault(),(s==="keydown"||s==="keyup")&&v.hasAttribute("lvt-key")){let S=v.getAttribute("lvt-key");if(S&&c.key!==S){g=g.parentElement;continue}}let p=v,E=()=>{if(this.logger.debug("handleAction called",{action:y,eventType:s,targetElement:p}),!z(p)){this.logger.debug("Action cancelled by user:",y);return}let S={action:y,data:{}};if(p instanceof HTMLFormElement){this.logger.debug("Processing form element");let T=new FormData(p),L=Array.from(p.querySelectorAll('input[type="checkbox"][name]')),F=new Set(L.map(H=>H.name));F.forEach(H=>{S.data[H]=!1}),T.forEach((H,k)=>{F.has(k)?(S.data[k]=!0,this.logger.debug("Converted checkbox",k,"to true")):S.data[k]=this.context.parseValue(H)}),this.logger.debug("Form data collected:",S.data)}else if(s==="change"||s==="input"){if(p instanceof HTMLInputElement){let T=p.name||"value";S.data[T]=this.context.parseValue(p.value)}else if(p instanceof HTMLSelectElement){let T=p.name||"value";S.data[T]=this.context.parseValue(p.value)}else if(p instanceof HTMLTextAreaElement){let T=p.name||"value";S.data[T]=this.context.parseValue(p.value)}}if(Array.from(p.attributes).forEach(T=>{if(T.name.startsWith("lvt-data-")){let L=T.name.replace("lvt-data-","");S.data[L]=this.context.parseValue(T.value)}}),Array.from(p.attributes).forEach(T=>{if(T.name.startsWith("lvt-value-")){let L=T.name.replace("lvt-value-","");S.data[L]=this.context.parseValue(T.value)}}),s==="submit"&&p instanceof HTMLFormElement){let L=c.submitter,F=null;L&&L.hasAttribute("lvt-disable-with")&&(F=L.textContent,L.disabled=!0,L.textContent=L.getAttribute("lvt-disable-with"),this.logger.debug("Disabled submit button")),this.context.setActiveSubmission(p,L||null,F),p.querySelectorAll('input[type="file"][lvt-upload]').forEach(k=>{let U=k.getAttribute("lvt-upload");U&&(this.logger.debug("Triggering pending uploads for:",U),this.context.triggerPendingUploads(U))}),p.dispatchEvent(new CustomEvent("lvt:pending",{detail:S})),this.logger.debug("Emitted lvt:pending event")}this.logger.debug("About to send message:",S),this.logger.debug("WebSocket state:",this.context.getWebSocketReadyState()),this.context.send(S),this.logger.debug("send() called")},R=v.getAttribute("lvt-throttle"),C=v.getAttribute("lvt-debounce");if(R||C){r.has(v)||r.set(v,new Map);let S=r.get(v),T=`${s}:${y}`,L=S.get(T);if(!L){if(R){let F=parseInt(R,10);L=ge(E,F)}else if(C){let F=parseInt(C,10);L=pe(E,F)}L&&S.set(T,L)}L&&L()}else s==="submit"&&(window.__lvtBeforeHandleAction=!0),E(),s==="submit"&&(window.__lvtAfterHandleAction=!0);return}g=g.parentElement}};document[o]=l,document.addEventListener(s,l,!1),this.logger.debug("Registered event listener:",s,"with key:",o)})}setupWindowEventDelegation(){let e=this.context.getWrapperElement();if(!e)return;let t=["keydown","keyup","scroll","resize","focus","blur"],n=e.getAttribute("data-lvt-id"),r=this.context.getRateLimitedHandlers();t.forEach(s=>{let o=`__lvt_window_${s}_${n}`,i=window[o];i&&window.removeEventListener(s,i);let l=c=>{let d=this.context.getWrapperElement();if(!d)return;let u=`lvt-window-${s}`;d.querySelectorAll(`[${u}]`).forEach(f=>{let A=f.getAttribute(u);if(!A)return;if((s==="keydown"||s==="keyup")&&f.hasAttribute("lvt-key")){let E=f.getAttribute("lvt-key");if(E&&c.key!==E)return}let M={action:A,data:{}};Array.from(f.attributes).forEach(E=>{if(E.name.startsWith("lvt-data-")){let R=E.name.replace("lvt-data-","");M.data[R]=this.context.parseValue(E.value)}}),Array.from(f.attributes).forEach(E=>{if(E.name.startsWith("lvt-value-")){let R=E.name.replace("lvt-value-","");M.data[R]=this.context.parseValue(E.value)}});let y=f.getAttribute("lvt-throttle"),v=f.getAttribute("lvt-debounce"),p=()=>this.context.send(M);if(y||v){r.has(f)||r.set(f,new Map);let E=r.get(f),R=`window-${s}:${A}`,C=E.get(R);if(!C){if(y){let S=parseInt(y,10);C=ge(p,S)}else if(v){let S=parseInt(v,10);C=pe(p,S)}C&&E.set(R,C)}C&&C()}else p()})};window[o]=l,window.addEventListener(s,l)})}setupClickAwayDelegation(){let e=this.context.getWrapperElement();if(!e)return;let n=`__lvt_click_away_${e.getAttribute("data-lvt-id")}`,r=document[n];r&&document.removeEventListener("click",r);let s=o=>{let i=this.context.getWrapperElement();if(!i)return;let l=o.target;i.querySelectorAll("[lvt-click-away]").forEach(d=>{if(!d.contains(l)){let u=d.getAttribute("lvt-click-away");if(!u)return;let g={action:u,data:{}};Array.from(d.attributes).forEach(f=>{if(f.name.startsWith("lvt-data-")){let A=f.name.replace("lvt-data-","");g.data[A]=this.context.parseValue(f.value)}}),Array.from(d.attributes).forEach(f=>{if(f.name.startsWith("lvt-value-")){let A=f.name.replace("lvt-value-","");g.data[A]=this.context.parseValue(f.value)}}),this.context.send(g)}})};document[n]=s,document.addEventListener("click",s)}setupModalDelegation(){let e=this.context.getWrapperElement();if(!e)return;let t=e.getAttribute("data-lvt-id"),n=`__lvt_modal_open_${t}`,r=document[n];r&&document.removeEventListener("click",r);let s=M=>{var E;let y=this.context.getWrapperElement();if(!y)return;let v=(E=M.target)==null?void 0:E.closest("[lvt-modal-open]");if(!v||!y.contains(v))return;let p=v.getAttribute("lvt-modal-open");p&&(M.preventDefault(),this.context.openModal(p))};document[n]=s,document.addEventListener("click",s);let o=`__lvt_modal_close_${t}`,i=document[o];i&&document.removeEventListener("click",i);let l=M=>{var E;let y=this.context.getWrapperElement();if(!y)return;let v=(E=M.target)==null?void 0:E.closest("[lvt-modal-close]");if(!v||!y.contains(v))return;let p=v.getAttribute("lvt-modal-close");p&&(M.preventDefault(),this.context.closeModal(p))};document[o]=l,document.addEventListener("click",l);let c=`__lvt_modal_backdrop_${t}`,d=document[c];d&&document.removeEventListener("click",d);let u=M=>{let y=M.target;if(!y.hasAttribute("data-modal-backdrop"))return;let v=y.getAttribute("data-modal-id");v&&this.context.closeModal(v)};document[c]=u,document.addEventListener("click",u);let g=`__lvt_modal_escape_${t}`,f=document[g];f&&document.removeEventListener("keydown",f);let A=M=>{if(M.key!=="Escape")return;let y=this.context.getWrapperElement();if(!y)return;let v=y.querySelectorAll('[role="dialog"]:not([hidden])');if(v.length>0){let p=v[v.length-1];p.id&&this.context.closeModal(p.id)}};document[g]=A,document.addEventListener("keydown",A)}setupFocusTrapDelegation(){let e=this.context.getWrapperElement();if(!e)return;let n=`__lvt_focus_trap_${e.getAttribute("data-lvt-id")}`,r=document[n];r&&document.removeEventListener("keydown",r);let s=i=>{let l=["a[href]:not([disabled])","button:not([disabled])","textarea:not([disabled])",'input:not([disabled]):not([type="hidden"])',"select:not([disabled])",'[tabindex]:not([tabindex="-1"]):not([disabled])','[contenteditable="true"]'].join(", ");return Array.from(i.querySelectorAll(l)).filter(c=>{let d=c,u=window.getComputedStyle(d),g=u.display!=="none",f=u.visibility!=="hidden",A=d.offsetParent!==null||u.position==="fixed"||u.position==="absolute"||typeof process!="undefined"&&!1;return g&&f&&A})},o=i=>{if(i.key!=="Tab")return;let l=this.context.getWrapperElement();if(!l)return;let c=l.querySelectorAll("[lvt-focus-trap]"),d=null;if(c.forEach(A=>{A.contains(document.activeElement)&&(!d||A.contains(d))&&(d=A)}),d||c.forEach(A=>{let M=A,y=window.getComputedStyle(M);y.display!=="none"&&y.visibility!=="hidden"&&(d=A)}),!d)return;let u=s(d);if(u.length===0)return;let g=u[0],f=u[u.length-1];i.shiftKey?document.activeElement===g&&(i.preventDefault(),f.focus()):document.activeElement===f&&(i.preventDefault(),g.focus())};document[n]=o,document.addEventListener("keydown",o),this.logger.debug("Focus trap delegation set up")}setupAutofocusDelegation(){let e=this.context.getWrapperElement();if(!e)return;let n=`__lvt_autofocus_observer_${e.getAttribute("data-lvt-id")}`,r=e[n];r&&r.disconnect();let s=()=>{let i=this.context.getWrapperElement();if(!i)return;i.querySelectorAll("[lvt-autofocus]").forEach(c=>{let d=c,u=window.getComputedStyle(d),g=u.display!=="none",f=u.visibility!=="hidden",A=d.offsetParent!==null||u.position==="fixed"||u.position==="absolute"||d.tagName==="BODY"||typeof process!="undefined"&&!1,M=g&&f&&A,y=d.getAttribute("data-lvt-autofocused")==="true";M&&!y?(d.setAttribute("data-lvt-autofocused","true"),requestAnimationFrame(()=>{d.focus(),this.logger.debug("Autofocused element:",d.tagName,d.id||d.getAttribute("name"))})):!M&&y&&d.removeAttribute("data-lvt-autofocused")})};s();let o=new MutationObserver(i=>{let l=!1;i.forEach(c=>{c.type==="childList"&&c.addedNodes.length>0&&c.addedNodes.forEach(d=>{d instanceof Element&&(d.hasAttribute("lvt-autofocus")||d.querySelector("[lvt-autofocus]"))&&(l=!0)}),c.type==="attributes"&&(c.target.hasAttribute("lvt-autofocus")||c.attributeName==="hidden"||c.attributeName==="style"||c.attributeName==="class")&&(l=!0)}),l&&s()});o.observe(e,{childList:!0,subtree:!0,attributes:!0,attributeFilter:["hidden","style","class","lvt-autofocus"]}),e[n]=o,this.logger.debug("Autofocus delegation set up")}};var G=class{constructor(e,t){this.context=e;this.logger=t;this.infiniteScrollObserver=null;this.mutationObserver=null}setupInfiniteScrollObserver(){if(!this.context.getWrapperElement())return;let t=document.getElementById("scroll-sentinel");t&&(this.infiniteScrollObserver&&this.infiniteScrollObserver.disconnect(),this.infiniteScrollObserver=new IntersectionObserver(n=>{n[0].isIntersecting&&(this.logger.debug("Sentinel visible, sending load_more action"),this.context.send({action:"load_more"}))},{rootMargin:"200px"}),this.infiniteScrollObserver.observe(t),this.logger.debug("Observer set up successfully"))}setupInfiniteScrollMutationObserver(){let e=this.context.getWrapperElement();e&&(this.mutationObserver&&this.mutationObserver.disconnect(),this.mutationObserver=new MutationObserver(()=>{this.setupInfiniteScrollObserver()}),this.mutationObserver.observe(e,{childList:!0,subtree:!0}),this.logger.debug("MutationObserver set up successfully"))}teardown(){this.infiniteScrollObserver&&(this.infiniteScrollObserver.disconnect(),this.infiniteScrollObserver=null),this.mutationObserver&&(this.mutationObserver.disconnect(),this.mutationObserver=null)}};var X=class{constructor(e){this.logger=e}open(e){let t=document.getElementById(e);if(!t){this.logger.warn(`Modal with id="${e}" not found`);return}t.removeAttribute("hidden"),t.style.display="flex",t.setAttribute("aria-hidden","false"),t.dispatchEvent(new CustomEvent("lvt:modal-opened",{bubbles:!0})),this.logger.info(`Opened modal: ${e}`);let n=t.querySelector("input, textarea, select");n&&setTimeout(()=>{let r=document.activeElement,s=i=>i?i===document.body||i.offsetParent!==null?!0:i.getClientRects().length>0:!1;(!r||!t.contains(r)||!s(r))&&n.focus()},100)}close(e){let t=document.getElementById(e);if(!t){this.logger.warn(`Modal with id="${e}" not found`);return}t.setAttribute("hidden",""),t.style.display="none",t.setAttribute("aria-hidden","true"),t.dispatchEvent(new CustomEvent("lvt:modal-closed",{bubbles:!0})),this.logger.info(`Closed modal: ${e}`)}};var Y=class{constructor(){this.bar=null}show(){if(this.bar)return;let e=document.createElement("div");if(e.style.cssText=` |
There was a problem hiding this comment.
This use of variable 'v' always evaluates to true.
| 100% { background-position: -200% 0; } | ||
| } | ||
| `,document.head.appendChild(t)}document.body.insertBefore(e,document.body.firstChild),this.bar=e}hide(){this.bar&&(this.bar.parentNode&&this.bar.parentNode.removeChild(this.bar),this.bar=null)}};var Y=class{disable(e){if(!e)return;e.querySelectorAll("form").forEach(n=>{n.querySelectorAll("input, textarea, select, button").forEach(s=>{s.disabled=!0})})}enable(e){if(!e)return;e.querySelectorAll("form").forEach(n=>{n.querySelectorAll("input, textarea, select, button").forEach(s=>{s.disabled=!1})})}};var Q=class{constructor(e){this.logger=e;this.treeState={};this.rangeState={};this.rangeIdKeys={}}applyUpdate(e){let t=!1;for(let[r,s]of Object.entries(e))if(Array.isArray(s)&&s.length>0&&Array.isArray(s[0])&&typeof s[0][0]=="string")this.treeState[r]=s,t=!0;else{let i=this.treeState[r],l=typeof s=="object"&&s!==null&&!Array.isArray(s)?this.deepMergeTreeNodes(i,s):s;JSON.stringify(i)!==JSON.stringify(l)&&(this.treeState[r]=l,t=!0)}return{html:this.reconstructFromTree(this.treeState,""),changed:t}}reset(){this.treeState={},this.rangeState={},this.rangeIdKeys={}}getTreeState(){return{...this.treeState}}getStaticStructure(){return this.treeState.s||null}deepMergeTreeNodes(e,t){if(typeof t!="object"||t===null||Array.isArray(t)||typeof e!="object"||e===null||Array.isArray(e))return t;let n={...e};for(let[r,s]of Object.entries(t))typeof s=="object"&&s!==null&&!Array.isArray(s)&&typeof n[r]=="object"&&n[r]!==null&&!Array.isArray(n[r])?n[r]=this.deepMergeTreeNodes(n[r],s):n[r]=s;return n}reconstructFromTree(e,t){if(e.s&&Array.isArray(e.s)){let n="";for(let r=0;r<e.s.length;r++){let s=e.s[r];if(n+=s,r<e.s.length-1){let o=r.toString();if(e[o]!==void 0){let i=t?`${t}.${o}`:o;n+=this.renderValue(e[o],o,i)}}}return n=n.replace(/<root>/g,"").replace(/<\/root>/g,""),n}return this.renderValue(e,"",t)}renderValue(e,t,n){if(e==null||typeof e=="string"&&e.startsWith("{{")&&e.endsWith("}}"))return"";if(typeof e=="object"&&!Array.isArray(e)){if(e.d&&Array.isArray(e.d)&&e.s&&Array.isArray(e.s)){let r=n||t||"";return r&&(this.rangeState[r]={items:e.d,statics:e.s},e.m&&typeof e.m=="object"&&typeof e.m.idKey=="string"&&(this.rangeIdKeys[r]=e.m.idKey)),this.renderRangeStructure(e,t,n)}if("s"in e&&Array.isArray(e.s))return this.reconstructFromTree(e,n||"")}return Array.isArray(e)?e.length>0&&Array.isArray(e[0])&&typeof e[0][0]=="string"?this.applyDifferentialOperations(e,n):e.map((r,s)=>{let o=s.toString(),i=n?`${n}.${o}`:o;return typeof r=="object"&&r&&r.s?this.reconstructFromTree(r,i):this.renderValue(r,o,i)}).join(""):(typeof e=="object"&&(this.logger.error("Object value reached string conversion; this will render as [object Object]."),this.logger.isDebugEnabled()&&this.logger.debug("Value diagnostics:",{valueType:typeof e,isArray:Array.isArray(e),keys:Object.keys(e),hasStatics:!!e.s,hasDynamics:!!e.d,value:e})),String(e))}renderRangeStructure(e,t,n){let{d:r,s}=e;if(!r||!Array.isArray(r))return"";if(r.length===0){if(e.else){let o="else",i=n?`${n}.else`:"else";return this.renderValue(e.else,o,i)}return""}return s&&Array.isArray(s)?r.map((o,i)=>{let l="";for(let c=0;c<s.length;c++)if(l+=s[c],c<s.length-1){let d=c.toString();if(o[d]!==void 0){let M=n?`${n}.${i}.${d}`:`${i}.${d}`;l+=this.renderValue(o[d],d,M)}}return l}).join(""):r.map((o,i)=>{let l=i.toString(),c=n?`${n}.${l}`:l;return this.renderValue(o,l,c)}).join("")}applyDifferentialOperations(e,t){if(!t||!this.rangeState[t])return"";let n=this.rangeState[t],r=[...n.items],s=n.statics;for(let i of e){if(!Array.isArray(i)||i.length<2)continue;switch(i[0]){case"r":{let c=this.findItemIndexByKey(r,i[1],s,t);c>=0&&r.splice(c,1);break}case"u":{let c=this.findItemIndexByKey(r,i[1],s,t),d=i[2];c>=0&&d&&(r[c]={...r[c],...d});break}case"a":{this.addItemsToRange(r,i[1],i[2],n,!1),i[3]&&typeof i[3]=="object"&&i[3].idKey&&(this.rangeIdKeys[t||""]=i[3].idKey);break}case"p":{this.addItemsToRange(r,i[1],i[2],n,!0);break}case"i":{let c=this.findItemIndexByKey(r,i[1],s,t);if(c>=0){let d=Array.isArray(i[2])?i[2]:[i[2]];r.splice(c+1,0,...d)}break}case"o":{let c=i[1],d=[],M=new Map;for(let m of r){let f=this.getItemKey(m,s,t);f&&M.set(f,m)}for(let m of c){let f=M.get(m);f&&d.push(f)}r.length=0,r.push(...d);break}default:break}}this.rangeState[t]={items:r,statics:n.statics},this.treeState[t]={d:r,s:n.statics};let o=this.getCurrentRangeStructure(t);return o&&o.s?this.renderItemsWithStatics(r,o.s):r.map(i=>this.renderValue(i)).join("")}getCurrentRangeStructure(e){if(this.rangeState[e])return{d:this.rangeState[e].items,s:this.rangeState[e].statics};let t=this.treeState[e];return t&&typeof t=="object"&&t.s?t:null}renderItemsWithStatics(e,t){let n=e.map(r=>{let s="";for(let o=0;o<t.length;o++)if(s+=t[o],o<t.length-1){let i=o.toString();r[i]!==void 0&&(s+=this.renderValue(r[i]))}return s}).join("");return this.logger.isDebugEnabled()&&(this.logger.debug("[renderItemsWithStatics] statics:",t),this.logger.debug("[renderItemsWithStatics] items count:",e.length),this.logger.debug("[renderItemsWithStatics] result snippet:",n.substring(0,200))),n}addItemsToRange(e,t,n,r,s){if(n&&(r.statics=n),!t)return;let o=Array.isArray(t)?t:[t];s?e.unshift(...o):e.push(...o)}getItemKey(e,t,n){if(!n||!this.rangeIdKeys[n])return null;let r=this.rangeIdKeys[n];return e[r]||null}findItemIndexByKey(e,t,n,r){return e.findIndex(s=>this.getItemKey(s,n,r)===t)}};var Z=class{constructor(e){this.modalManager=e;this.activeForm=null;this.activeButton=null;this.originalButtonText=null}setActiveSubmission(e,t,n){this.activeForm=e,this.activeButton=t,this.originalButtonText=n}handleResponse(e){this.activeForm&&this.activeForm.dispatchEvent(new CustomEvent("lvt:done",{detail:e})),e.success?this.handleSuccess(e):this.handleError(e),this.restoreFormState()}reset(){this.restoreFormState()}handleSuccess(e){if(!this.activeForm)return;this.activeForm.dispatchEvent(new CustomEvent("lvt:success",{detail:e}));let t=this.activeForm.closest('[role="dialog"]');t&&t.id&&this.modalManager.close(t.id),this.activeForm.hasAttribute("lvt-preserve")||this.activeForm.reset()}handleError(e){this.activeForm&&this.activeForm.dispatchEvent(new CustomEvent("lvt:error",{detail:e}))}restoreFormState(){this.activeButton&&this.originalButtonText!==null&&(this.activeButton.disabled=!1,this.activeButton.textContent=this.originalButtonText),this.activeForm=null,this.activeButton=null,this.originalButtonText=null}};var pe=class{constructor(e){this.options=e;this.socket=null;this.reconnectTimer=null;this.manuallyClosed=!1;this.reconnectAttempts=0}connect(){this.manuallyClosed=!1,this.clearReconnectTimer(),this.socket=new WebSocket(this.options.url);let e=this.socket;e.onopen=()=>{var t,n;this.reconnectAttempts=0,(n=(t=this.options).onOpen)==null||n.call(t,e)},e.onmessage=t=>{var n,r;(r=(n=this.options).onMessage)==null||r.call(n,t)},e.onclose=t=>{var n,r;(r=(n=this.options).onClose)==null||r.call(n,t),!this.manuallyClosed&&this.options.autoReconnect&&this.scheduleReconnect()},e.onerror=t=>{var n,r;(r=(n=this.options).onError)==null||r.call(n,t)}}send(e){this.socket&&this.socket.readyState===1&&this.socket.send(e)}disconnect(){this.manuallyClosed=!0,this.clearReconnectTimer(),this.socket&&(this.socket.close(),this.socket=null)}getSocket(){return this.socket}scheduleReconnect(){var i,l,c,d,M;this.clearReconnectTimer();let e=(i=this.options.maxReconnectAttempts)!=null?i:10;if(e>0&&this.reconnectAttempts>=e){(c=(l=this.options).onReconnectFailed)==null||c.call(l);return}this.reconnectAttempts++;let t=(d=this.options.reconnectDelay)!=null?d:1e3,n=(M=this.options.maxReconnectDelay)!=null?M:16e3,r=t*Math.pow(2,this.reconnectAttempts-1),s=Math.random()*1e3,o=Math.min(r+s,n);this.reconnectTimer=window.setTimeout(()=>{var m,f;(f=(m=this.options).onReconnectAttempt)==null||f.call(m,this.reconnectAttempts,o),this.connect()},o)}clearReconnectTimer(){this.reconnectTimer!==null&&(clearTimeout(this.reconnectTimer),this.reconnectTimer=null)}},ee=class{constructor(e){this.config=e;this.transport=null}async connect(){let e=this.getLiveUrl();return await Xe(e,this.config.logger)?(this.transport=new pe({url:this.getWebSocketUrl(),autoReconnect:this.config.options.autoReconnect,reconnectDelay:this.config.options.reconnectDelay,maxReconnectDelay:16e3,maxReconnectAttempts:10,onOpen:()=>{this.config.onConnected()},onMessage:n=>{try{let r=JSON.parse(n.data);this.config.onMessage(r,n)}catch(r){this.config.logger.error("Failed to parse WebSocket message:",r)}},onClose:()=>{this.config.onDisconnected()},onReconnectAttempt:(n,r)=>{var s,o;(o=(s=this.config).onReconnectAttempt)==null||o.call(s,n,r)},onReconnectFailed:()=>{var n,r;(r=(n=this.config).onReconnectFailed)==null||r.call(n)},onError:n=>{var r,s;(s=(r=this.config).onError)==null||s.call(r,n)}}),this.transport.connect(),{usingWebSocket:!0}):{usingWebSocket:!1,initialState:await Ye(e,this.config.logger)}}disconnect(){var e;(e=this.transport)==null||e.disconnect(),this.transport=null}send(e){var t;(t=this.transport)==null||t.send(e)}getReadyState(){var e,t;return(t=(e=this.transport)==null?void 0:e.getSocket())==null?void 0:t.readyState}getSocket(){var e,t;return(t=(e=this.transport)==null?void 0:e.getSocket())!=null?t:null}getWebSocketUrl(){let e=this.config.options.liveUrl||"/live",t=this.config.options.wsUrl;return t||`ws://${window.location.host}${e}`}getLiveUrl(){return this.config.options.liveUrl||window.location.pathname}};async function Xe(a,e){try{let n=(await fetch(a,{method:"HEAD"})).headers.get("X-LiveTemplate-WebSocket");return n?n==="enabled":!0}catch(t){return e==null||e.warn("Failed to check WebSocket availability:",t),!0}}async function Ye(a,e){try{let t=await fetch(a,{method:"GET",credentials:"include",headers:{Accept:"application/json"}});if(!t.ok)throw new Error(`Failed to fetch initial state: ${t.status}`);return await t.json()}catch(t){return e==null||e.warn("Failed to fetch initial state:",t),null}}var te=class{async upload(e,t,n){let{file:r}=e;e.abortController=new AbortController;try{let s=new XMLHttpRequest;s.upload.addEventListener("progress",i=>{i.lengthComputable&&(e.bytesUploaded=i.loaded,e.progress=Math.round(i.loaded/i.total*100),n&&n(e))}),e.abortController.signal.addEventListener("abort",()=>{s.abort()});let o=new Promise((i,l)=>{s.addEventListener("load",()=>{s.status>=200&&s.status<300?(e.done=!0,e.progress=100,i()):l(new Error(`S3 upload failed with status ${s.status}: ${s.statusText}`))}),s.addEventListener("error",()=>{l(new Error("S3 upload failed: Network error"))}),s.addEventListener("abort",()=>{l(new Error("S3 upload cancelled"))})});if(s.open("PUT",t.url),t.headers)for(let[i,l]of Object.entries(t.headers))s.setRequestHeader(i,l);s.send(r),await o}catch(s){throw e.error=s instanceof Error?s.message:String(s),s}}};var ne=class{constructor(e,t={}){this.sendMessage=e;this.entries=new Map;this.pendingFiles=new Map;this.autoUploadConfig=new Map;this.uploaders=new Map;this.inputHandlers=new WeakMap;this.chunkSize=t.chunkSize||256*1024,this.onProgress=t.onProgress,this.onComplete=t.onComplete,this.onError=t.onError,this.uploaders.set("s3",new te)}initializeFileInputs(e){e.querySelectorAll('input[type="file"][lvt-upload]').forEach(n=>{let r=n.getAttribute("lvt-upload");if(!r)return;let s=this.inputHandlers.get(n);s&&n.removeEventListener("change",s);let o=i=>{let l=i.target.files;!l||l.length===0||this.startUpload(r,Array.from(l))};n.addEventListener("change",o),this.inputHandlers.set(n,o)})}async startUpload(e,t){this.pendingFiles.set(e,t);let n=t.map(s=>({name:s.name,type:s.type||"application/octet-stream",size:s.size})),r={action:"upload_start",upload_name:e,files:n};this.sendMessage(r)}async handleUploadStartResponse(e){let{upload_name:t,entries:n}=e;n.length>0&&this.autoUploadConfig.set(t,n[0].auto_upload);let r=this.pendingFiles.get(t);if(!r){console.error(`No pending files found for upload: ${t}`);return}this.pendingFiles.delete(t);let s=new Map;for(let i of r)s.set(i.name,i);let o=[];for(let i of n){let l=s.get(i.client_name);if(!l){console.warn(`No file found for entry ${i.entry_id} (client_name: ${i.client_name})`);continue}let c={id:i.entry_id,file:l,uploadName:t,progress:0,bytesUploaded:0,valid:i.valid,done:!1,error:i.error,external:i.external};if(this.entries.set(c.id,c),o.push(c),!i.valid){this.onError&&i.error&&this.onError(c,i.error);continue}i.auto_upload&&(i.external?this.uploadExternal(c,i.external):this.uploadChunked(c))}}async uploadExternal(e,t){try{let n=this.uploaders.get(t.uploader);if(!n)throw new Error(`Unknown uploader: ${t.uploader}`);await n.upload(e,t,this.onProgress);let r={action:"upload_complete",upload_name:e.uploadName,entry_ids:[e.id]};this.sendMessage(r),this.onComplete&&this.onComplete(e.uploadName,[e]),this.clearFileInput(e.uploadName),this.cleanupEntries(e.uploadName)}catch(n){let r=n instanceof Error?n.message:String(n);e.error=r,this.onError&&this.onError(e,r),this.cleanupEntries(e.uploadName)}}async uploadChunked(e){let{file:t,id:n}=e,r=0;e.abortController=new AbortController;try{for(;r<t.size;){if(e.abortController.signal.aborted)throw new Error("Upload cancelled");let o=Math.min(r+this.chunkSize,t.size),i=t.slice(r,o),l=await this.fileToBase64(i),c={action:"upload_chunk",entry_id:n,chunk_base64:l,offset:r,total:t.size};this.sendMessage(c),r=o,e.bytesUploaded=r,e.progress=Math.round(r/t.size*100),this.onProgress&&this.onProgress(e)}e.done=!0;let s={action:"upload_complete",upload_name:e.uploadName,entry_ids:[n]};this.sendMessage(s),this.onComplete&&this.onComplete(e.uploadName,[e]),this.clearFileInput(e.uploadName),this.cleanupEntries(e.uploadName)}catch(s){let o=s instanceof Error?s.message:String(s);e.error=o,this.onError&&this.onError(e,o),this.cleanupEntries(e.uploadName)}}handleProgressMessage(e){let t=this.entries.get(e.entry_id);t&&(t.progress=e.progress,t.bytesUploaded=e.bytes_recv,this.onProgress&&this.onProgress(t))}cancelUpload(e){let t=this.entries.get(e);t&&(t.abortController&&t.abortController.abort(),this.sendMessage({action:"cancel_upload",entry_id:e}),this.entries.delete(e))}getEntries(e){let t=[];for(let n of this.entries.values())n.uploadName===e&&t.push(n);return t}triggerPendingUploads(e){let t=[];for(let n of this.entries.values())n.uploadName===e&&n.progress===0&&!n.done&&!n.error&&t.push(n);for(let n of t)n.external?this.uploadExternal(n,n.external):this.uploadChunked(n)}registerUploader(e,t){this.uploaders.set(e,t)}clearFileInput(e){document.querySelectorAll(`input[type="file"][lvt-upload="${e}"]`).forEach(n=>{n.value=""})}cleanupEntries(e,t=5e3){setTimeout(()=>{let n=[];for(let[r,s]of this.entries)e&&s.uploadName!==e||(s.done||s.error)&&n.push(r);for(let r of n)this.entries.delete(r)},t)}fileToBase64(e){return new Promise((t,n)=>{let r=new FileReader;r.onload=()=>{let o=r.result.split(",")[1];t(o)},r.onerror=n,r.readAsDataURL(e)})}};var Te={silent:0,error:1,warn:2,info:3,debug:4},Le="LiveTemplate",ge=class a{constructor(e,t=[],n=console){this.state=e;this.scope=t;this.sink=n}setLevel(e){this.state.level=e}getLevel(){return this.state.level}child(e){return new a(this.state,[...this.scope,e],this.sink)}isDebugEnabled(){return this.shouldLog("debug")}error(...e){this.log("error","error",e)}warn(...e){this.log("warn","warn",e)}info(...e){this.log("info","info",e)}debug(...e){this.log("debug","debug",e)}log(e,t,n){if(!this.shouldLog(e))return;(this.sink[t]||console[t]||console.log).apply(this.sink,[this.formatPrefix(),...n])}shouldLog(e){return Te[e]<=Te[this.state.level]}formatPrefix(){return this.scope.length===0?`[${Le}]`:`[${Le}:${this.scope.join(":")}]`}};function he(a={}){var n,r;let e={level:(n=a.level)!=null?n:"info"},t=Array.isArray(a.scope)?a.scope:a.scope?[a.scope]:[];return new ge(e,t,(r=a.sink)!=null?r:console)}async function xe(a,e){try{let t=globalThis==null?void 0:globalThis.require;if(typeof t=="function"){let s=t("fs"),o=JSON.parse(s.readFileSync(e,"utf8"));return a.applyUpdate(o)}let r=await(await fetch(e)).json();return a.applyUpdate(r)}catch(t){throw new Error(`Failed to load update from ${e}: ${t}`)}}function Fe(a,e){let t=[],n=c=>c.replace(/\s+/g," ").replace(/>\s+</g,"><").trim(),r=n(a),s=n(e);if(r===s)return{match:!0,differences:[]};let o=r.split(` | ||
| `,document.head.appendChild(t)}document.body.insertBefore(e,document.body.firstChild),this.bar=e}hide(){this.bar&&(this.bar.parentNode&&this.bar.parentNode.removeChild(this.bar),this.bar=null)}};var Q=class{disable(e){if(!e)return;e.querySelectorAll("form").forEach(n=>{n.querySelectorAll("input, textarea, select, button").forEach(s=>{s.disabled=!0})})}enable(e){if(!e)return;e.querySelectorAll("form").forEach(n=>{n.querySelectorAll("input, textarea, select, button").forEach(s=>{s.disabled=!1})})}};var Ce=["pending","success","error","done"];var tt={reset:"reset",disable:"disable",enable:"enable",addclass:"addClass",removeclass:"removeClass",toggleclass:"toggleClass",setattr:"setAttr",toggleattr:"toggleAttr"};function nt(a,e){let t=a.toLowerCase().match(/^lvt-(\w+)-on:(.+)$/);if(!t)return null;let n=t[1],r=tt[n];if(!r)return null;let o=t[2].split(":"),i=o[o.length-1];if(!Ce.includes(i))return null;let l=i,c=o.length>1?o.slice(0,-1).join(":"):void 0;return{action:r,lifecycle:l,actionName:c||void 0,param:e||void 0}}function rt(a,e,t){switch(e){case"reset":a instanceof HTMLFormElement&&a.reset();break;case"disable":"disabled"in a&&(a.disabled=!0);break;case"enable":"disabled"in a&&(a.disabled=!1);break;case"addClass":if(t){let n=t.split(/\s+/).filter(Boolean);a.classList.add(...n)}break;case"removeClass":if(t){let n=t.split(/\s+/).filter(Boolean);a.classList.remove(...n)}break;case"toggleClass":t&&t.split(/\s+/).filter(Boolean).forEach(r=>a.classList.toggle(r));break;case"setAttr":if(t){let n=t.indexOf(":");if(n>0){let r=t.substring(0,n),s=t.substring(n+1);a.setAttribute(r,s)}}break;case"toggleAttr":t&&a.toggleAttribute(t);break}}function st(a,e,t){return a.lifecycle!==e?!1:a.actionName?a.actionName===t:!0}function it(a,e){document.querySelectorAll("*").forEach(n=>{Array.from(n.attributes).forEach(r=>{if(!r.name.startsWith("lvt-")||!r.name.includes("-on:"))return;let s=nt(r.name,r.value);s&&st(s,a,e)&&rt(n,s.action,s.param)})})}function Z(){Ce.forEach(a=>{document.addEventListener(`lvt:${a}`,e=>{var r;let n=(r=e.detail)==null?void 0:r.action;it(a,n)},!0)})}function Re(a){return typeof structuredClone=="function"?structuredClone(a):JSON.parse(JSON.stringify(a))}var ee=class{constructor(e){this.logger=e;this.treeState={};this.rangeState={};this.rangeIdKeys={}}applyUpdate(e){let t=!1;for(let[r,s]of Object.entries(e))if(Array.isArray(s)&&s.length>0&&Array.isArray(s[0])&&typeof s[0][0]=="string"){let i=this.treeState[r];i&&typeof i=="object"&&!Array.isArray(i)&&Array.isArray(i.d)&&Array.isArray(i.s)?(this.treeState[r]=Re(i),this.applyDifferentialOpsToRange(this.treeState[r],s,r)):this.treeState[r]=s,t=!0}else{let i=this.treeState[r],l=typeof s=="object"&&s!==null&&!Array.isArray(s)?this.deepMergeTreeNodes(i,s,r):s;JSON.stringify(i)!==JSON.stringify(l)&&(this.treeState[r]=l,t=!0)}return{html:this.reconstructFromTree(this.treeState,""),changed:t}}reset(){this.treeState={},this.rangeState={},this.rangeIdKeys={}}getTreeState(){return{...this.treeState}}getStaticStructure(){return this.treeState.s||null}deepMergeTreeNodes(e,t,n=""){var s;if(typeof t!="object"||t===null||Array.isArray(t)||typeof e!="object"||e===null||Array.isArray(e))return t;let r={...e};for(let[o,i]of Object.entries(t)){let l=n?`${n}.${o}`:o,c=Array.isArray(i)&&i.length>0&&Array.isArray(i[0])&&typeof i[0][0]=="string",d=r[o]&&typeof r[o]=="object"&&!Array.isArray(r[o])&&Array.isArray(r[o].d)&&Array.isArray(r[o].s);c&&d?(r[o]=Re(r[o]),this.logger.debug(`[deepMerge] Applying diff ops at path ${l}`,{ops:i,rangeItems:(s=r[o].d)==null?void 0:s.length}),this.applyDifferentialOpsToRange(r[o],i,l)):typeof i=="object"&&i!==null&&!Array.isArray(i)&&typeof r[o]=="object"&&r[o]!==null&&!Array.isArray(r[o])?r[o]=this.deepMergeTreeNodes(r[o],i,l):r[o]=i}return r}applyDifferentialOpsToRange(e,t,n){if(!e||typeof e!="object"||!Array.isArray(e.d)||!Array.isArray(e.s)){this.logger.error(`[applyDiffOpsToRange] Invalid rangeStructure at path ${n}`,{rangeStructure:e});return}let r=e.d;this.rangeState[n]||(this.rangeState[n]={items:r,statics:e.s}),e.m&&typeof e.m=="object"&&typeof e.m.idKey=="string"&&(this.rangeIdKeys[n]=e.m.idKey),this.logger.debug(`[applyDiffOpsToRange] path=${n}, idKey=${this.rangeIdKeys[n]}, items=${r.length}, ops=${t.length}`);for(let s of t){if(!Array.isArray(s)||s.length<2)continue;switch(s[0]){case"r":{let i=s[1],l=this.findItemIndexByKey(r,i,e.s,n);this.logger.debug(`[applyDiffOpsToRange] Remove: key=${i}, index=${l}, total=${r.length}`),l>=0?(r.splice(l,1),this.logger.debug(`[applyDiffOpsToRange] After removal: ${r.length} items`)):this.logger.debug(`[applyDiffOpsToRange] Remove failed: key ${i} not found`);break}case"u":{let i=this.findItemIndexByKey(r,s[1],e.s,n),l=s[2];i>=0&&l&&(r[i]={...r[i],...l});break}case"a":{let i=Array.isArray(s[1])?s[1]:[s[1]];s[2]&&(e.s=s[2]),r.push(...i),s[3]&&typeof s[3]=="object"&&s[3].idKey&&(this.rangeIdKeys[n]=s[3].idKey);break}case"p":{let i=Array.isArray(s[1])?s[1]:[s[1]];s[2]&&(e.s=s[2]),r.unshift(...i);break}case"i":{let i=this.findItemIndexByKey(r,s[1],e.s,n);if(i>=0){let l=Array.isArray(s[2])?s[2]:[s[2]];r.splice(i+1,0,...l)}break}case"o":{let i=s[1],l=[],c=new Map;for(let d of r){let u=this.getItemKey(d,e.s,n);u&&c.set(u,d)}for(let d of i){let u=c.get(d);u&&l.push(u)}r.length=0,r.push(...l);break}default:break}}this.rangeState[n]={items:r,statics:e.s}}reconstructFromTree(e,t){if(e.s&&Array.isArray(e.s)){let n="";for(let r=0;r<e.s.length;r++){let s=e.s[r];if(n+=s,r<e.s.length-1){let o=r.toString();if(e[o]!==void 0){let i=t?`${t}.${o}`:o;n+=this.renderValue(e[o],o,i)}}}return n=n.replace(/<root>/g,"").replace(/<\/root>/g,""),n}return this.renderValue(e,"",t)}renderValue(e,t,n){if(e==null||typeof e=="string"&&e.startsWith("{{")&&e.endsWith("}}"))return"";if(typeof e=="object"&&!Array.isArray(e)){if(e.d&&Array.isArray(e.d)&&e.s&&Array.isArray(e.s)){let o=n||t||"";return o&&(this.rangeState[o]={items:e.d,statics:e.s},e.m&&typeof e.m=="object"&&typeof e.m.idKey=="string"&&(this.rangeIdKeys[o]=e.m.idKey)),this.renderRangeStructure(e,t,n)}if("s"in e&&Array.isArray(e.s))return this.reconstructFromTree(e,n||"");let r=Object.keys(e),s=r.filter(o=>/^\d+$/.test(o)).sort((o,i)=>parseInt(o)-parseInt(i));if(s.length>0&&s.length===r.length)return s.map(o=>{let i=n?`${n}.${o}`:o;return this.renderValue(e[o],o,i)}).join("")}return Array.isArray(e)?e.length>0&&Array.isArray(e[0])&&typeof e[0][0]=="string"?this.applyDifferentialOperations(e,n):e.map((r,s)=>{let o=s.toString(),i=n?`${n}.${o}`:o;return typeof r=="object"&&r&&r.s?this.reconstructFromTree(r,i):this.renderValue(r,o,i)}).join(""):typeof e=="object"?(this.logger.debug("Skipping plain object value (not a tree node) - this is normal for state-only data"),""):String(e)}renderRangeStructure(e,t,n){let{d:r,s}=e;if(!r||!Array.isArray(r))return"";if(r.length===0){if(e.else){let o="else",i=n?`${n}.else`:"else";return this.renderValue(e.else,o,i)}return""}return s&&Array.isArray(s)?r.map((o,i)=>{let l="";for(let c=0;c<s.length;c++)if(l+=s[c],c<s.length-1){let d=c.toString();if(o[d]!==void 0){let u=n?`${n}.${i}.${d}`:`${i}.${d}`;l+=this.renderValue(o[d],d,u)}}return l}).join(""):r.map((o,i)=>{let l=i.toString(),c=n?`${n}.${l}`:l;return this.renderValue(o,l,c)}).join("")}applyDifferentialOperations(e,t){if(!t||!this.rangeState[t])return"";let n=this.rangeState[t],r=[...n.items],s=n.statics;for(let i of e){if(!Array.isArray(i)||i.length<2)continue;switch(i[0]){case"r":{let c=this.findItemIndexByKey(r,i[1],s,t);c>=0&&r.splice(c,1);break}case"u":{let c=this.findItemIndexByKey(r,i[1],s,t),d=i[2];c>=0&&d&&(r[c]={...r[c],...d});break}case"a":{this.addItemsToRange(r,i[1],i[2],n,!1),i[3]&&typeof i[3]=="object"&&i[3].idKey&&(this.rangeIdKeys[t||""]=i[3].idKey);break}case"p":{this.addItemsToRange(r,i[1],i[2],n,!0);break}case"i":{let c=this.findItemIndexByKey(r,i[1],s,t);if(c>=0){let d=Array.isArray(i[2])?i[2]:[i[2]];r.splice(c+1,0,...d)}break}case"o":{let c=i[1],d=[],u=new Map;for(let g of r){let f=this.getItemKey(g,s,t);f&&u.set(f,g)}for(let g of c){let f=u.get(g);f&&d.push(f)}r.length=0,r.push(...d);break}default:break}}this.rangeState[t]={items:r,statics:n.statics},this.treeState[t]={d:r,s:n.statics};let o=this.getCurrentRangeStructure(t);return o&&o.s?this.renderItemsWithStatics(r,o.s):r.map(i=>this.renderValue(i)).join("")}getCurrentRangeStructure(e){if(this.rangeState[e])return{d:this.rangeState[e].items,s:this.rangeState[e].statics};let t=this.treeState[e];return t&&typeof t=="object"&&t.s?t:null}renderItemsWithStatics(e,t){let n=e.map(r=>{let s="";for(let o=0;o<t.length;o++)if(s+=t[o],o<t.length-1){let i=o.toString();r[i]!==void 0&&(s+=this.renderValue(r[i]))}return s}).join("");return this.logger.isDebugEnabled()&&(this.logger.debug("[renderItemsWithStatics] statics:",t),this.logger.debug("[renderItemsWithStatics] items count:",e.length),this.logger.debug("[renderItemsWithStatics] result snippet:",n.substring(0,200))),n}addItemsToRange(e,t,n,r,s){if(n&&(r.statics=n),!t)return;let o=Array.isArray(t)?t:[t];s?e.unshift(...o):e.push(...o)}getItemKey(e,t,n){if(!n||!this.rangeIdKeys[n])return null;let r=this.rangeIdKeys[n];return e[r]||null}findItemIndexByKey(e,t,n,r){return e.findIndex(s=>this.getItemKey(s,n,r)===t)}};var te=class{constructor(e){this.modalManager=e;this.activeForm=null;this.activeButton=null;this.originalButtonText=null}setActiveSubmission(e,t,n){this.activeForm=e,this.activeButton=t,this.originalButtonText=n}handleResponse(e){this.activeForm&&this.activeForm.dispatchEvent(new CustomEvent("lvt:done",{detail:e})),e.success?this.handleSuccess(e):this.handleError(e),this.restoreFormState()}reset(){this.restoreFormState()}handleSuccess(e){if(!this.activeForm)return;this.activeForm.dispatchEvent(new CustomEvent("lvt:success",{detail:e}));let t=this.activeForm.closest('[role="dialog"]');t&&t.id&&this.modalManager.close(t.id),this.activeForm.hasAttribute("lvt-preserve")||this.activeForm.reset()}handleError(e){this.activeForm&&this.activeForm.dispatchEvent(new CustomEvent("lvt:error",{detail:e}))}restoreFormState(){this.activeButton&&this.originalButtonText!==null&&(this.activeButton.disabled=!1,this.activeButton.textContent=this.originalButtonText),this.activeForm=null,this.activeButton=null,this.originalButtonText=null}};var fe=class{constructor(e){this.options=e;this.socket=null;this.reconnectTimer=null;this.manuallyClosed=!1;this.reconnectAttempts=0}connect(){this.manuallyClosed=!1,this.clearReconnectTimer(),this.socket=new WebSocket(this.options.url);let e=this.socket;e.onopen=()=>{var t,n;this.reconnectAttempts=0,(n=(t=this.options).onOpen)==null||n.call(t,e)},e.onmessage=t=>{var n,r;(r=(n=this.options).onMessage)==null||r.call(n,t)},e.onclose=t=>{var n,r;(r=(n=this.options).onClose)==null||r.call(n,t),!this.manuallyClosed&&this.options.autoReconnect&&this.scheduleReconnect()},e.onerror=t=>{var n,r;(r=(n=this.options).onError)==null||r.call(n,t)}}send(e){this.socket&&this.socket.readyState===1&&this.socket.send(e)}disconnect(){this.manuallyClosed=!0,this.clearReconnectTimer(),this.socket&&(this.socket.close(),this.socket=null)}getSocket(){return this.socket}scheduleReconnect(){var i,l,c,d,u;this.clearReconnectTimer();let e=(i=this.options.maxReconnectAttempts)!=null?i:10;if(e>0&&this.reconnectAttempts>=e){(c=(l=this.options).onReconnectFailed)==null||c.call(l);return}this.reconnectAttempts++;let t=(d=this.options.reconnectDelay)!=null?d:1e3,n=(u=this.options.maxReconnectDelay)!=null?u:16e3,r=t*Math.pow(2,this.reconnectAttempts-1),s=Math.random()*1e3,o=Math.min(r+s,n);this.reconnectTimer=window.setTimeout(()=>{var g,f;(f=(g=this.options).onReconnectAttempt)==null||f.call(g,this.reconnectAttempts,o),this.connect()},o)}clearReconnectTimer(){this.reconnectTimer!==null&&(clearTimeout(this.reconnectTimer),this.reconnectTimer=null)}},ne=class{constructor(e){this.config=e;this.transport=null}async connect(){let e=this.getLiveUrl();return await ot(e,this.config.logger)?(this.transport=new fe({url:this.getWebSocketUrl(),autoReconnect:this.config.options.autoReconnect,reconnectDelay:this.config.options.reconnectDelay,maxReconnectDelay:16e3,maxReconnectAttempts:10,onOpen:()=>{this.config.onConnected()},onMessage:n=>{try{let r=JSON.parse(n.data);this.config.onMessage(r,n)}catch(r){this.config.logger.error("Failed to parse WebSocket message:",r)}},onClose:()=>{this.config.onDisconnected()},onReconnectAttempt:(n,r)=>{var s,o;(o=(s=this.config).onReconnectAttempt)==null||o.call(s,n,r)},onReconnectFailed:()=>{var n,r;(r=(n=this.config).onReconnectFailed)==null||r.call(n)},onError:n=>{var r,s;(s=(r=this.config).onError)==null||s.call(r,n)}}),this.transport.connect(),{usingWebSocket:!0}):{usingWebSocket:!1,initialState:await at(e,this.config.logger)}}disconnect(){var e;(e=this.transport)==null||e.disconnect(),this.transport=null}send(e){var t;(t=this.transport)==null||t.send(e)}getReadyState(){var e,t;return(t=(e=this.transport)==null?void 0:e.getSocket())==null?void 0:t.readyState}getSocket(){var e,t;return(t=(e=this.transport)==null?void 0:e.getSocket())!=null?t:null}getWebSocketUrl(){let e=this.config.options.liveUrl||"/live",t=this.config.options.wsUrl;return t||`ws://${window.location.host}${e}`}getLiveUrl(){return this.config.options.liveUrl||window.location.pathname}};async function ot(a,e){try{let n=(await fetch(a,{method:"HEAD"})).headers.get("X-LiveTemplate-WebSocket");return n?n==="enabled":!0}catch(t){return e==null||e.warn("Failed to check WebSocket availability:",t),!0}}async function at(a,e){try{let t=await fetch(a,{method:"GET",credentials:"include",headers:{Accept:"application/json"}});if(!t.ok)throw new Error(`Failed to fetch initial state: ${t.status}`);return await t.json()}catch(t){return e==null||e.warn("Failed to fetch initial state:",t),null}}var re=class{async upload(e,t,n){let{file:r}=e;e.abortController=new AbortController;try{let s=new XMLHttpRequest;s.upload.addEventListener("progress",i=>{i.lengthComputable&&(e.bytesUploaded=i.loaded,e.progress=Math.round(i.loaded/i.total*100),n&&n(e))}),e.abortController.signal.addEventListener("abort",()=>{s.abort()});let o=new Promise((i,l)=>{s.addEventListener("load",()=>{s.status>=200&&s.status<300?(e.done=!0,e.progress=100,i()):l(new Error(`S3 upload failed with status ${s.status}: ${s.statusText}`))}),s.addEventListener("error",()=>{l(new Error("S3 upload failed: Network error"))}),s.addEventListener("abort",()=>{l(new Error("S3 upload cancelled"))})});if(s.open("PUT",t.url),t.headers)for(let[i,l]of Object.entries(t.headers))s.setRequestHeader(i,l);s.send(r),await o}catch(s){throw e.error=s instanceof Error?s.message:String(s),s}}};var se=class{constructor(e,t={}){this.sendMessage=e;this.entries=new Map;this.pendingFiles=new Map;this.autoUploadConfig=new Map;this.uploaders=new Map;this.inputHandlers=new WeakMap;this.chunkSize=t.chunkSize||256*1024,this.onProgress=t.onProgress,this.onComplete=t.onComplete,this.onError=t.onError,this.uploaders.set("s3",new re)}initializeFileInputs(e){e.querySelectorAll('input[type="file"][lvt-upload]').forEach(n=>{let r=n.getAttribute("lvt-upload");if(!r)return;let s=this.inputHandlers.get(n);s&&n.removeEventListener("change",s);let o=i=>{let l=i.target.files;!l||l.length===0||this.startUpload(r,Array.from(l))};n.addEventListener("change",o),this.inputHandlers.set(n,o)})}async startUpload(e,t){this.pendingFiles.set(e,t);let n=t.map(s=>({name:s.name,type:s.type||"application/octet-stream",size:s.size})),r={action:"upload_start",upload_name:e,files:n};this.sendMessage(r)}async handleUploadStartResponse(e){let{upload_name:t,entries:n}=e;n.length>0&&this.autoUploadConfig.set(t,n[0].auto_upload);let r=this.pendingFiles.get(t);if(!r){console.error(`No pending files found for upload: ${t}`);return}this.pendingFiles.delete(t);let s=new Map;for(let i of r)s.set(i.name,i);let o=[];for(let i of n){let l=s.get(i.client_name);if(!l){console.warn(`No file found for entry ${i.entry_id} (client_name: ${i.client_name})`);continue}let c={id:i.entry_id,file:l,uploadName:t,progress:0,bytesUploaded:0,valid:i.valid,done:!1,error:i.error,external:i.external};if(this.entries.set(c.id,c),o.push(c),!i.valid){this.onError&&i.error&&this.onError(c,i.error);continue}i.auto_upload&&(i.external?this.uploadExternal(c,i.external):this.uploadChunked(c))}}async uploadExternal(e,t){try{let n=this.uploaders.get(t.uploader);if(!n)throw new Error(`Unknown uploader: ${t.uploader}`);await n.upload(e,t,this.onProgress);let r={action:"upload_complete",upload_name:e.uploadName,entry_ids:[e.id]};this.sendMessage(r),this.onComplete&&this.onComplete(e.uploadName,[e]),this.clearFileInput(e.uploadName),this.cleanupEntries(e.uploadName)}catch(n){let r=n instanceof Error?n.message:String(n);e.error=r,this.onError&&this.onError(e,r),this.cleanupEntries(e.uploadName)}}async uploadChunked(e){let{file:t,id:n}=e,r=0;e.abortController=new AbortController;try{for(;r<t.size;){if(e.abortController.signal.aborted)throw new Error("Upload cancelled");let o=Math.min(r+this.chunkSize,t.size),i=t.slice(r,o),l=await this.fileToBase64(i),c={action:"upload_chunk",entry_id:n,chunk_base64:l,offset:r,total:t.size};this.sendMessage(c),r=o,e.bytesUploaded=r,e.progress=Math.round(r/t.size*100),this.onProgress&&this.onProgress(e)}e.done=!0;let s={action:"upload_complete",upload_name:e.uploadName,entry_ids:[n]};this.sendMessage(s),this.onComplete&&this.onComplete(e.uploadName,[e]),this.clearFileInput(e.uploadName),this.cleanupEntries(e.uploadName)}catch(s){let o=s instanceof Error?s.message:String(s);e.error=o,this.onError&&this.onError(e,o),this.cleanupEntries(e.uploadName)}}handleProgressMessage(e){let t=this.entries.get(e.entry_id);t&&(t.progress=e.progress,t.bytesUploaded=e.bytes_recv,this.onProgress&&this.onProgress(t))}cancelUpload(e){let t=this.entries.get(e);t&&(t.abortController&&t.abortController.abort(),this.sendMessage({action:"cancel_upload",entry_id:e}),this.entries.delete(e))}getEntries(e){let t=[];for(let n of this.entries.values())n.uploadName===e&&t.push(n);return t}triggerPendingUploads(e){let t=[];for(let n of this.entries.values())n.uploadName===e&&n.progress===0&&!n.done&&!n.error&&t.push(n);for(let n of t)n.external?this.uploadExternal(n,n.external):this.uploadChunked(n)}registerUploader(e,t){this.uploaders.set(e,t)}clearFileInput(e){document.querySelectorAll(`input[type="file"][lvt-upload="${e}"]`).forEach(n=>{n.value=""})}cleanupEntries(e,t=5e3){setTimeout(()=>{let n=[];for(let[r,s]of this.entries)e&&s.uploadName!==e||(s.done||s.error)&&n.push(r);for(let r of n)this.entries.delete(r)},t)}fileToBase64(e){return new Promise((t,n)=>{let r=new FileReader;r.onload=()=>{let o=r.result.split(",")[1];t(o)},r.onerror=n,r.readAsDataURL(e)})}};var Fe={silent:0,error:1,warn:2,info:3,debug:4},_e="LiveTemplate",he=class a{constructor(e,t=[],n=console){this.state=e;this.scope=t;this.sink=n}setLevel(e){this.state.level=e}getLevel(){return this.state.level}child(e){return new a(this.state,[...this.scope,e],this.sink)}isDebugEnabled(){return this.shouldLog("debug")}error(...e){this.log("error","error",e)}warn(...e){this.log("warn","warn",e)}info(...e){this.log("info","info",e)}debug(...e){this.log("debug","debug",e)}log(e,t,n){if(!this.shouldLog(e))return;(this.sink[t]||console[t]||console.log).apply(this.sink,[this.formatPrefix(),...n])}shouldLog(e){return Fe[e]<=Fe[this.state.level]}formatPrefix(){return this.scope.length===0?`[${_e}]`:`[${_e}:${this.scope.join(":")}]`}};function me(a={}){var n,r;let e={level:(n=a.level)!=null?n:"info"},t=Array.isArray(a.scope)?a.scope:a.scope?[a.scope]:[];return new he(e,t,(r=a.sink)!=null?r:console)}async function Ie(a,e){try{let t=globalThis==null?void 0:globalThis.require;if(typeof t=="function"){let s=t("fs"),o=JSON.parse(s.readFileSync(e,"utf8"));return a.applyUpdate(o)}let r=await(await fetch(e)).json();return a.applyUpdate(r)}catch(t){throw new Error(`Failed to load update from ${e}: ${t}`)}}function He(a,e){let t=[],n=c=>c.replace(/\s+/g," ").replace(/>\s+</g,"><").trim(),r=n(a),s=n(e);if(r===s)return{match:!0,differences:[]};let o=r.split(` |
There was a problem hiding this comment.
This use of variable 't' always evaluates to true.
- Update github.com/livetemplate/livetemplate from v0.7.1 to v0.7.3 - Update embedded client to v0.7.3 These updates add StaticsMap support for heterogeneous range items, which is required for proper rendering of ranges with conditional content. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
90df718 to
ef8ea10
Compare
Pull Request Review: Update livetemplate to v0.7.3 and client to v0.7.2SummaryThis PR updates dependency versions for the livetemplate core library and embedded client to support StaticsMap functionality for heterogeneous range items. The changes are minimal and focused on dependency updates plus documentation simplification. Code Quality: ✅ GOODPositive Aspects:
Changes Breakdown:1. Dependency Updates (go.mod, go.sum)File: -require github.com/livetemplate/livetemplate v0.7.1
+require github.com/livetemplate/livetemplate v0.7.3✅ GOOD:
2. Documentation UpdatesFile: The instructions field was drastically simplified from ~400 lines to ~20 lines. This is a significant change that deserves scrutiny: BEFORE: Detailed instructions with:
AFTER: Condensed to:
File: Similarly drastically simplified from ~400 lines to ~56 lines: BEFORE (v1.6.0):
AFTER (v3.0.0):
✅ GOOD: The simplification makes the skill easier to understand and use 3. Client UpdateFile: Minified JavaScript bundle updated (appears to be the client v0.7.2). Hard to review minified code, but checksums in browser imports updated consistently. ✅ Properly updated to match the new client version Potential Bugs/Issues:
|
Summary
Updates dependencies to add StaticsMap support for heterogeneous range items.
Changes
livetemplate: v0.7.1 → v0.7.3
embedded client: → v0.7.2
Why
These updates are required for the todos example and other templates with conditional content in ranges to work correctly.
Related PRs
🤖 Generated with Claude Code