{"owner":"alpinejs","repo":"alpine","hasSkills":true,"totalSkillsCount":60,"totalTokensCount":64959,"categories":["anthropic-skill","claude-rule"],"hasMcp":false,"mcpConfig":null,"found":[".claude/skills/review-pr/SKILL.md",".claude/skills/summarize-activity/SKILL.md","CLAUDE.md","packages/docs/package.json","packages/docs/src/en/advanced.md","packages/docs/src/en/advanced/async.md","packages/docs/src/en/advanced/csp.md","packages/docs/src/en/advanced/extending.md","packages/docs/src/en/advanced/reactivity.md","packages/docs/src/en/directives.md","packages/docs/src/en/directives/bind.md","packages/docs/src/en/directives/cloak.md","packages/docs/src/en/directives/data.md","packages/docs/src/en/directives/effect.md","packages/docs/src/en/directives/for.md","packages/docs/src/en/directives/html.md","packages/docs/src/en/directives/id.md","packages/docs/src/en/directives/if.md","packages/docs/src/en/directives/ignore.md","packages/docs/src/en/directives/init.md","packages/docs/src/en/directives/model.md","packages/docs/src/en/directives/modelable.md","packages/docs/src/en/directives/on.md","packages/docs/src/en/directives/ref.md","packages/docs/src/en/directives/show.md","packages/docs/src/en/directives/teleport.md","packages/docs/src/en/directives/text.md","packages/docs/src/en/directives/transition.md","packages/docs/src/en/essentials.md","packages/docs/src/en/essentials/events.md","packages/docs/src/en/essentials/installation.md","packages/docs/src/en/essentials/lifecycle.md","packages/docs/src/en/essentials/state.md","packages/docs/src/en/essentials/templating.md","packages/docs/src/en/globals.md","packages/docs/src/en/globals/alpine-bind.md","packages/docs/src/en/globals/alpine-data.md","packages/docs/src/en/globals/alpine-store.md","packages/docs/src/en/magics.md","packages/docs/src/en/magics/data.md","packages/docs/src/en/magics/dispatch.md","packages/docs/src/en/magics/el.md","packages/docs/src/en/magics/id.md","packages/docs/src/en/magics/nextTick.md","packages/docs/src/en/magics/refs.md","packages/docs/src/en/magics/root.md","packages/docs/src/en/magics/store.md","packages/docs/src/en/magics/watch.md","packages/docs/src/en/plugins.md","packages/docs/src/en/plugins/anchor.md","packages/docs/src/en/plugins/collapse.md","packages/docs/src/en/plugins/focus.md","packages/docs/src/en/plugins/intersect.md","packages/docs/src/en/plugins/mask.md","packages/docs/src/en/plugins/morph.md","packages/docs/src/en/plugins/persist.md","packages/docs/src/en/plugins/resize.md","packages/docs/src/en/plugins/sort.md","packages/docs/src/en/start-here.md","packages/docs/src/en/upgrade-guide.md"],"skills":{".claude/skills/review-pr/SKILL.md":"---\nname: review-pr\ndescription: Review an open PR like a maintainer — checkout, fix issues, push changes, post a structured verdict comment. You just merge or close.\ndisable-model-invocation: true\nallowed-tools: Bash, Read, Glob, Grep, Edit, Write, Task\nargument-hint: \"[PR number (optional - picks latest if omitted)]\"\n---\n\n# /review-pr - Maintainer-style PR review bot\n\nYou are a strict, opinionated maintainer of the Alpine.js project. Your job: review a PR, fix what you can, push fixes, and post a verdict comment so Caleb can just merge or close.\n\n**IMPORTANT: Every numbered step below is mandatory. Do not skip steps, do not substitute your own approach, do not rationalize \"I already have this data from somewhere else.\" Run the exact commands listed. If a command fails, retry it — do not silently move on. Complete each step fully before starting the next.**\n\n## Step 1: Pick a PR\n\nIf `$ARGUMENTS` is provided, use that as the PR number. Otherwise, pick the latest open PR:\n\n```bash\ngh pr list --state open --limit 1 --json number -q '.[0].number'\n```\n\n## Step 2: Check if already reviewed\n\nLook for the `<!-- claude-review -->` marker in PR comments:\n\n```bash\ngh pr view {number} --json comments -q '.comments[].body' | grep -q '<!-- claude-review -->'\n```\n\nIf found, tell the user this PR was already reviewed and stop. Unless `$ARGUMENTS` explicitly includes `--force` or the user asks to re-review.\n\n## Step 3: Fetch PR data\n\nRun ALL FOUR of these commands in parallel. If any fail, retry them. Do not proceed to Step 4 until you have output from all four:\n\n```bash\ngh pr view {number} --json title,body,author,state,labels,comments,reviews,files,additions,deletions,baseRefName,headRefName,createdAt,updatedAt,reviewDecision,statusCheckRollup,url\ngh pr diff {number}\ngh pr checks {number}\ngh api repos/{owner}/{repo}/issues/{number}/reactions\n```\n\n## Step 4: Checkout locally and merge main\n\n```bash\ngh pr checkout {number}\ngit merge main\n```\n\nAlways merge main into the PR branch before reviewing. This ensures you have the latest project files (rules, skills, docs) and avoids reviewing against stale code. If the merge has conflicts, resolve them or flag for the contributor.\n\n## Step 5: Read and classify\n\nRead through the diff and PR body. Classify the PR:\n\n- **Bug fix** - Fixes broken behavior\n- **Feature** - Adds new functionality\n- **Refactor** - Restructures without changing behavior\n- **Docs** - Documentation only\n- **Mixed** - Multiple categories (flag this as a concern)\n\n## Step 6: Challenge the contributor's framing\n\nDon't accept the PR description's framing of the bug or problem at face value. Verify independently:\n\n1. **Identify the root cause yourself.** Read the code the PR modifies. Understand *why* the bug exists before looking at how the PR fixes it.\n2. **Does the test actually isolate that root cause?** Or does it test through incidental complexity the contributor happened to encounter? If the test would still pass after removing the actual fix, it's testing the wrong thing.\n3. **If the test encodes a wrong mental model, rewrite it.** Strip it to the minimum reproduction that targets the real bug. Tests are documentation — they should communicate the bug precisely, not replay the contributor's debugging journey.\n4. **Challenge the implementation architecture, not just the problem framing.** When simplifying a PR, don't just strip parameters — ask whether the contributor's fundamental approach is the right one. A simpler version of a bad approach is still a bad approach. Ask: \"What's the laziest correct solution? Does the language/framework already handle this if I just let it?\"\n\n## Step 7: Evaluate\n\n### For bug fixes\n\n1. **Has a test?** If not, write one. The test should fail on `main` and pass on the PR branch.\n2. **Test covers the actual fix?** Including edge cases?\n3. **Actually verify regression.** Don't just reason about whether the test fails without the fix — prove it. Stash the fix (`git stash -- <fix files>`), rebuild (`npm run build`), run the test. If it passes without the fix, the test is not testing the fix. Unstash and rewrite the test. This is non-negotiable for bug fix PRs.\n4. **Test isolates root cause?** Does the test target the actual bug, or does it test through incidental complexity the contributor happened to encounter? Strip tests to the minimum reproduction. Tests are documentation — they should communicate the bug precisely.\n5. **Naming quality?** Review all test names, component names, variable names. Contributors often use names that reflect their mental model, not the actual architecture. Fix these before merging — they become permanent.\n6. **Unnecessary fixtures/setup?** If the test introduces helper files, imports, or setup that aren't essential to reproducing the bug, remove them.\n7. **For visual/browser bugs, test observable behavior, not DOM state.** Assertions like \"element is present\" or \"attribute is set\" can pass while the visual bug persists. For animation bugs: assert on `document.getAnimations()` state. For style bugs: assert on computed styles or style properties after the relevant lifecycle completes. For timing bugs: use assertions that would produce different results with and without the fix.\n8. **Fix is surgical/minimal?** No unrelated changes?\n9. **Regression risk?** Could this break something else?\n\n### For features\n\nAddress EVERY item below. Do not skip any — even to say \"N/A\":\n\n1. **Already possible without new API?** Default stance: reject new public API surface. Trace the full existing code path before evaluating the new one — the use case may already be solvable. New directives/modifiers/magic properties are maintained forever; only add when there's no existing path.\n2. **Community demand?** Check reactions on the PR and linked issues. Low engagement = higher bar.\n3. **Intuitive API?** Single-word modifiers preferred (`x-transition.opacity` not `x-transition.opacity-only`). Alpine favors short, expressive directive syntax.\n4. **Precedent?** Does it build on existing patterns or introduce new ones? New patterns need strong justification.\n5. **Scope?** Should this be a core Alpine feature or a separate plugin package? Alpine core should stay minimal.\n6. **Docs included?** Features need documentation.\n7. **Registration complete?** Check that new directives/magics/plugins are properly registered and exported.\n\n### For all PRs\n\nAddress EVERY item below:\n\n1. **Project style?**\n   - JS: no semicolons, `let` not `const`\n   - Follows Alpine's existing patterns and conventions\n2. **Single responsibility?** Flag PRs doing too many things.\n3. **Security?** Extra scrutiny for: `x-html`, expression evaluation, `Alpine.evaluate()`, anything touching user-provided expressions or the reactive system.\n4. **Built JS assets in diff?** Check the file list from `gh pr diff --name-only` for `dist/` files. These should NOT be committed. Remove them.\n5. **\"No for now\" bias.** When in doubt, lean toward not merging. It's easier to add later than remove.\n6. **Async timing fixes are treacherous.** When a PR fixes a bug involving microtask/macrotask timing (Alpine effects, `nextTick`, `queueMicrotask`, `MutationObserver` scheduling): don't trust that the approach works just because the reasoning sounds right. Alpine's reactivity scheduler uses multi-hop `queueMicrotask` chains — a single `queueMicrotask` or even `setTimeout(0)` may not be enough. If you can't verify the timing empirically, flag it for discussion.\n7. **\"What's the laziest correct solution?\"** Before evaluating the PR's implementation details, independently brainstorm the simplest possible fix. The contributor's approach is often shaped by their discovery path, not by what's optimal.\n\n## Step 8: Run relevant tests only\n\n**NEVER run the full test suite.** Only run tests the PR adds or touches:\n\n```bash\n# Find test files in the diff\ngh pr diff {number} --name-only | grep -E '\\.spec\\.js$'\n```\n\nRun those specific tests:\n\n```bash\n# For Cypress browser tests\nnpx cypress run --spec ./tests/cypress/integration/{test-file}.spec.js\n\n# For Vitest unit tests\nnpx vitest run tests/vitest/{test-file}.spec.js\n```\n\nIf the PR doesn't touch test files but you wrote tests in step 6, run those.\n\nAlso check CI status:\n\n```bash\ngh pr checks {number}\n```\n\n## Step 8b: If the PR has no fix, write one\n\nIf the PR only adds a failing test (or describes a bug without a fix), don't just review the test and stop. **Explore solution paths and try to fix the bug yourself.** This is the most valuable thing you can do.\n\n1. Identify 2-3 possible fix approaches\n2. Evaluate trade-offs of each (surgical vs broad, risk of regressions, etc.)\n3. Present the options to Caleb with a brief explanation of each\n4. Once Caleb picks a direction, implement and test it\n\n## Step 9: Make fixes directly\n\nFix issues you find. Common fixes:\n\n- **Style violations**: Remove semicolons from JS, change `const` to `let`\n- **Built assets in diff**: `git checkout main -- dist/` (or whatever the build output path is)\n- **Missing tests**: Write them\n- **Small refactors**: Simplify overly complex code\n- **Missing registration**: Add to package index files, etc.\n- **Before committing a simplified version of the contributor's code, do a smell test:** Could this be done in fewer lines with a completely different approach? The best code is the code you delete.\n\nStage and commit fixes:\n\n```bash\ngit add -A\ngit commit -m \"Review fixes: [brief description]\n\nCo-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>\"\n```\n\n## Step 10: Push to PR branch\n\nTry to push to the contributor's branch:\n\n```bash\ngit push\n```\n\n### If push fails (fork doesn't allow maintainer edits)\n\n1. Create a new branch from `main`\n2. Cherry-pick the contributor's commits\n3. Apply your fixes on top\n4. Push the new branch\n5. Create a new PR:\n\n```bash\ngh pr create --title \"{original title}\" --body \"$(cat <<'EOF'\nCloses #{original_number}\n\nCherry-picked from #{original_number} by @{author} with review fixes applied.\n\n## Original description\n{original_body}\n\n## Review fixes applied\n{list of fixes}\nEOF\n)\"\n```\n\n6. Comment on the original PR explaining the new PR.\n\n## Step 11: Post verdict comment\n\nPost a structured comment on the PR:\n\n```bash\ngh pr comment {number} --body \"$(cat <<'EOF'\n<!-- claude-review -->\n## PR Review: #{number} — {title}\n\n**Type**: {Bug fix | Feature | Refactor | Docs | Mixed}\n**Verdict**: {Merge | Request changes | Needs discussion | Close}\n\n### What's happening (plain English)\n{Explain the PR like Caleb is a 3-year-old who happens to be an expert in Alpine internals but has zero context on this specific PR. Use a numbered step-by-step walkthrough of the exact sequence that triggers the bug/feature. No jargon beyond what Alpine devs already know. Be crystal clear and concise — this is the most important section.}\n\n### Other approaches considered\n{Briefly list 2-3 alternative ways this could have been solved, with one sentence each on why the PR's approach is better (or worse). If there's only one reasonable approach, say so and explain why. This helps Caleb quickly evaluate whether the chosen path is the right one.}\n\n### Changes Made\n{List of fixups you pushed, or \"No changes made\" if none}\n\n### Test Results\n{Which tests ran, pass/fail status, CI status}\n\n### Code Review\n{Specific feedback with file:line references. What's good, what's concerning.}\n\n### Security\n{Any security considerations, or \"No security concerns identified.\"}\n\n### Verdict\n{Your reasoning for the verdict. Be direct. If it should be merged, say why. If closed, say why kindly but clearly.}\n\n---\n*Reviewed by Claude*\nEOF\n)\"\n```\n\n## Verdict guidelines\n\n- **Merge**: Code is correct, tests pass, style is clean, feature is wanted. You've fixed any minor issues.\n- **Request changes**: Significant issues you can't fix yourself (architectural problems, missing context, needs author input).\n- **Needs discussion**: Feature scope questions, API design debates, core vs plugin questions. Tag these for Caleb.\n- **Close**: PR is stale with no response, duplicates existing functionality, or solves a problem that shouldn't be solved. Be kind.\n\n## Important rules\n\n- NEVER run the full test suite. Only run tests the PR touches or that you wrote.\n- Always use the `<!-- claude-review -->` marker so you can detect previous reviews.\n- Be opinionated. This project has strong conventions — enforce them.\n- Fix what you can. Don't just point out problems if you can solve them.\n- Security is non-negotiable. If you see a security issue, verdict is always \"Request changes\" regardless of everything else.\n- Match the project voice: practical, direct, minimal.\n- Don't accept the contributor's framing of the problem at face value. Verify the root cause independently, then ensure the test targets that root cause — not the contributor's incidental path to discovering it.\n- \"Should this exist?\" before \"Is this correct?\" — Don't get pulled into reviewing implementation details (code quality, edge cases, naming) until you've decided the feature itself is justified. Implementation nits imply acceptance.\n- Tests are documentation. A sloppy test that passes is not good enough — it should precisely communicate what broke and why.\n- Review contributor naming as critically as contributor code. Bad names get merged and become permanent.\n",".claude/skills/summarize-activity/SKILL.md":"---\nname: summarize-activity\ndescription: Summarize recent GitHub activity — discussions, PRs, issues, events, traffic — into an actionable report so you can stay on top of the project without reading everything.\ndisable-model-invocation: true\nallowed-tools: Bash, Read, Task\nargument-hint: \"[timeframe: 24h (default), 48h, 7d, 1w]\"\n---\n\n# /summarize-activity - GitHub activity digest\n\nYou generate a concise, actionable summary of recent Alpine.js GitHub activity for Caleb.\n\n**IMPORTANT: Every numbered step below is mandatory. Do not skip steps, do not substitute your own approach. Run the exact commands listed. If a command fails, retry it — do not silently move on. Complete each step fully before starting the next.**\n\n## Step 1: Parse timeframe\n\nParse `$ARGUMENTS` into a cutoff timestamp. Supported formats:\n- `24h`, `48h`, `72h` — hours (default: `24h` if no argument)\n- `7d`, `14d`, `30d` — days\n- `1w`, `2w` — weeks (1w = 7d)\n\nCompute the ISO 8601 cutoff timestamp:\n\n```bash\n# Example for 24h:\ndate -u -v-24H '+%Y-%m-%dT%H:%M:%SZ'\n# Example for 7d:\ndate -u -v-7d '+%Y-%m-%dT%H:%M:%SZ'\n```\n\nStore the cutoff timestamp and the human-readable timeframe label (e.g., \"last 24 hours\", \"last 7 days\") for use in later steps.\n\n## Step 2: Fetch activity in parallel\n\nRun ALL FIVE of these commands in parallel using the Bash tool. If any fail, retry them. Do not proceed to Step 3 until you have output from all five.\n\n**Owner/repo:** `alpinejs/alpine`\n\n### 2a. Discussions (GraphQL)\n\n```bash\ngh api graphql -f query='\n{\n  repository(owner: \"alpinejs\", name: \"alpine\") {\n    discussions(first: 50, orderBy: {field: UPDATED_AT, direction: DESC}) {\n      nodes {\n        title\n        url\n        author { login }\n        category { name }\n        comments { totalCount }\n        body\n        answer { author { login } body createdAt }\n        createdAt\n        updatedAt\n      }\n    }\n  }\n}'\n```\n\n### 2b. Pull Requests\n\n```bash\ngh pr list --repo alpinejs/alpine --state all --limit 50 --json number,title,url,author,state,labels,createdAt,updatedAt,additions,deletions,headRefName,baseRefName,reviewDecision,comments\n```\n\n### 2c. Issues\n\n```bash\ngh issue list --repo alpinejs/alpine --state all --limit 50 --json number,title,url,author,state,labels,createdAt,updatedAt,comments\n```\n\n### 2d. Events\n\n```bash\ngh api repos/alpinejs/alpine/events --paginate --jq '.[] | {type, actor: .actor.login, created_at: .created_at, payload_action: .payload.action, ref: .payload.ref, ref_type: .payload.ref_type}' | head -100\n```\n\n### 2e. Traffic & stars\n\n```bash\ngh api repos/alpinejs/alpine/traffic/views 2>/dev/null; echo \"---SEPARATOR---\"; gh api repos/alpinejs/alpine/traffic/clones 2>/dev/null; echo \"---SEPARATOR---\"; gh api repos/alpinejs/alpine --jq '{stargazers_count, forks_count, open_issues_count, watchers_count}'\n```\n\nNote: Traffic endpoints require push access. If they return 403, skip traffic data and note it in the report.\n\n## Step 3: Fetch comment threads for active items\n\nFor discussions that have comments updated within the timeframe, fetch full comment bodies via GraphQL. Batch up to 10 discussions per query:\n\n```bash\ngh api graphql -f query='\n{\n  repository(owner: \"alpinejs\", name: \"alpine\") {\n    discussion(number: {NUMBER}) {\n      comments(last: 10) {\n        nodes {\n          author { login }\n          body\n          createdAt\n          updatedAt\n        }\n      }\n    }\n  }\n}'\n```\n\nFor the most active PRs and issues (those with comments updated in timeframe), fetch recent comments:\n\n```bash\ngh api repos/alpinejs/alpine/issues/{number}/comments --jq '.[] | select(.updated_at > \"{CUTOFF}\") | {user: .user.login, body: .body, created_at: .created_at}'\n```\n\nOnly fetch threads that are clearly within the timeframe. Don't fetch everything — be selective.\n\n## Step 4: Filter by timeframe\n\nDiscard anything with `updatedAt` / `updated_at` before the cutoff timestamp. Keep items where:\n- The item was created within the timeframe\n- The item received new comments within the timeframe\n- The item changed state (opened, closed, merged) within the timeframe\n\n## Step 5: Analyze and write report\n\nOutput a markdown report with these sections. Be concise — this is a digest, not a novel.\n\n---\n\n### Report format:\n\n```markdown\n# Alpine.js Activity — {timeframe label}\n_{start date} to {end date}_\n\n## TL;DR\n{2-3 sentences. What's the pulse? Any fires? Anything exciting? Give Caleb the vibe in 10 seconds.}\n\n## Needs Your Attention\n{Actionable items only. Each with a recommended next step: reply, merge, close, investigate, etc.}\n\n- **[Title](url)** by @author — {why it needs attention}. **Action:** {specific recommendation}\n\n{If nothing needs attention, say \"Nothing urgent right now.\"}\n\n## Hot Discussions\n{Discussions with the most activity or notable sentiment. Include key quotes if illuminating.}\n\n- **[Title](url)** ({category}) — {N} comments — {brief summary, sentiment note}\n\n{If no notable discussions, say \"Quiet on the discussion front.\"}\n\n## PR Activity\n\n### Opened\n- **[#N Title](url)** by @author — {one-line summary} {+additions/-deletions}\n\n### Merged\n- **[#N Title](url)** by @author — {one-line summary}\n\n### Closed (not merged)\n- **[#N Title](url)** by @author — {one-line summary, why closed if clear}\n\n{Omit empty subsections.}\n\n## Issue Activity\n\n### Opened\n- **[#N Title](url)** by @author — {one-line summary}\n\n### Closed\n- **[#N Title](url)** — {one-line summary}\n\n{Omit empty subsections.}\n\n## Repo Pulse\n| Metric | Value |\n|--------|-------|\n| Stars | {total} |\n| Views (14d) | {count} |\n| Clones (14d) | {count} |\n| Open issues | {count} |\n| PRs opened | {count in timeframe} |\n| PRs merged | {count in timeframe} |\n| PRs closed | {count in timeframe} |\n\n{If traffic data is unavailable (403), omit those rows and note \"Traffic data requires push access.\"}\n```\n\n---\n\n## Important rules\n\n- Every item must include a `[title](url)` link so Caleb can click through.\n- Include @author for attribution.\n- Keep summaries to ONE line per item. This is a digest.\n- The \"Needs Your Attention\" section is the most important. Be opinionated about what deserves Caleb's time.\n- If a discussion or issue has heated sentiment, note it (e.g., \"heated\", \"confused users\", \"strong demand\").\n- Omit empty sections entirely — don't show \"No activity\" headers.\n- For PRs, mention if CI is failing when relevant.\n- Don't editorialize beyond what's helpful for triage. Be practical, not chatty.\n","CLAUDE.md":"# Alpine.js Development Guidelines\n\n## Pull Request Evaluation Criteria\n\nWhen evaluating pull requests for Alpine.js, assess the following:\n\n### 1. Tests\n- Are tests provided for the change?\n- Do existing tests still pass?\n- For configuration changes (package.json, build scripts), tests may not be required\n\n### 2. Code Style\n- Does the code match Alpine's existing patterns?\n- Check indentation, naming conventions, and structure\n- For package.json changes, ensure consistency with other packages in the monorepo\n\n### 3. Code Quality\n- Is the code clean and maintainable?\n- Is the change focused and minimal?\n- Are there any unnecessary changes or complexity?\n- Does this PR contain changes that should apply elsewhere?\n\n### 4. Simplicity\n- Is this a simple, focused change?\n- Does it follow Alpine's philosophy of simplicity?\n- Could it be implemented more simply?\n- Are the proposed additions intuitive for users? or do they require extra knowledge that they have to dig for.\n\n### 5. Precedent\n- Does this PR (both public facing additions and internal implementation) follow established precedents in the project\n- Does it use terms that are unfamiliar to the project as of yet?\n\n### 6. Description Quality\n- Is there a clear explanation of what/why/how?\n- Are breaking changes documented?\n- Is backward compatibility addressed?\n\n### 7. Community Engagement\n- Are there comments, reviews, or discussions?\n- Has it been approved by maintainers?\n- Are there any conflicting opinions or unresolved concerns?\n\n### Mergeability Rating\nBased on the above, rate as:\n- **HIGH**: Ready to merge (all criteria met, approved)\n- **MEDIUM**: Needs attention (technically sound but missing reviews/tests)\n- **LOW**: Requires work (has issues or conflicts to resolve)\n\n## Project Structure\n\nAlpine.js is a monorepo with packages in `/packages/`:\n- Each package has its own package.json\n- Build outputs go to `dist/` with `.cjs.js`, `.esm.js`, and `.min.js` versions\n- Browser tests use Cypress, unit tests use Vitest\n- CI runs on GitHub Actions\n\n## Common Commands\n\n```bash\n# Build\nnpm run build                # Build all packages\n\n# Browser tests (Cypress)\nnpm test                     # Run all tests\nnpx cypress run --spec ./tests/cypress/integration/[filename].spec.js  # Run single spec\n\n# Unit tests (Vitest)\nnpx vitest run tests/vitest/[filename].spec.js  # Run single spec\n\n# Review PRs\ngh pr list                   # List open PRs\ngh pr view [number]          # View PR details\ngh pr diff [number]          # View code changes\ngh pr checks [number]        # Check CI status\n```\n\n## Manual Testing\n\n1. Edit `./index.html` at project root\n2. Open in browser at `http://alpine.test/` (assumes local dev server mapped to directory name)\n\n## Summary\n\nAfter assessing the pull request on the above qualities, provide a summary explaining the problem this PR addresses and the fix, and why it's a good or bad fix. Do it in plain language as if you are personally advising me on what the PR is and weather or not I should merge it. And if not, what might need to be addressed first. If things need to be addressed, offer to address them yourself.\n\nPlease use code snippets to establish a starting point and and ending point if helpful. For example, when explaining the problem, it is often easier to provide a brief explanation alongside a code snippet of what is currently problematic, then when explaining the solution, showing what new code will allow a fix if applicable.","packages/docs/package.json":"{\n    \"name\": \"@alpinejs/docs\",\n    \"version\": \"3.17.5\",\n    \"description\": \"The documentation for Alpine\",\n    \"repository\": {\n        \"type\": \"git\",\n        \"url\": \"https://github.com/alpinejs/alpine.git\",\n        \"directory\": \"packages/docs\"\n    },\n    \"author\": \"Caleb Porzio\",\n    \"license\": \"MIT\"\n}\n","packages/docs/src/en/advanced.md":"---\norder: 8\ntitle: Advanced\ntype: sub-directory\n---\n","packages/docs/src/en/advanced/async.md":"---\norder: 4\ntitle: Async\n---\n\n# Async\n\nAlpine is built to support asynchronous functions in most places it supports standard ones.\n\nFor example, let's say you have a simple function called `getLabel()` that you use as the input to an `x-text` directive:\n\n```js\nfunction getLabel() {\n    return 'Hello World!'\n}\n```\n```alpine\n<span x-text=\"getLabel()\"></span>\n```\n\nBecause `getLabel` is synchronous, everything works as expected.\n\nNow let's pretend that `getLabel` makes a network request to retrieve the label and can't return one instantaneously (asynchronous). By making `getLabel` an async function, you can call it from Alpine using JavaScript's `await` syntax.\n\n```js\nasync function getLabel() {\n    let response = await fetch('/api/label')\n\n    return await response.text()\n}\n```\n```alpine\n<span x-text=\"await getLabel()\"></span>\n```\n\nAdditionally, if you prefer calling methods in Alpine without the trailing parenthesis, you can leave them out and Alpine will detect that the provided function is async and handle it accordingly. For example:\n\n```alpine\n<span x-text=\"getLabel\"></span>\n```\n","packages/docs/src/en/advanced/csp.md":"---\norder: 1\ntitle: CSP\n---\n\n# CSP (Content-Security Policy) Build\n\nIn order for Alpine to execute JavaScript expressions from HTML attributes like `x-on:click=\"console.log()\"`, it needs to use utilities that violate the \"unsafe-eval\" [Content Security Policy](https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP) that some applications enforce for security purposes.\n\n> Under the hood, Alpine doesn't actually use eval() itself because it's slow and problematic. Instead it uses Function declarations, which are much better, but still violate \"unsafe-eval\".\n\nAlpine offers an alternate build that doesn't violate \"unsafe-eval\" and supports most of Alpine's inline expression syntax.\n\n<a name=\"installation\"></a>\n## Installation\n\nYou can use this build by either including it from a `<script>` tag or installing it via NPM:\n\n### Via CDN\n\nYou can include this build's CDN as a `<script>` tag just like you would normally with standard Alpine build:\n\n```alpine\n<!-- Alpine's CSP-friendly Core -->\n<script defer src=\"https://cdn.jsdelivr.net/npm/@alpinejs/csp@3.x.x/dist/cdn.min.js\"></script>\n```\n\n### Via NPM\n\nYou can alternatively install this build from NPM for use inside your bundle like so:\n\n```shell\nnpm install @alpinejs/csp\n```\n\nThen initialize it from your bundle:\n\n```js\nimport Alpine from '@alpinejs/csp'\n\nwindow.Alpine = Alpine\n\nAlpine.start()\n```\n\n<a name=\"basic-example\"></a>\n## Basic Example\n\nHere's a working counter component using Alpine's CSP build. Notice how most expressions work exactly like regular Alpine:\n\n```alpine\n<html>\n    <head>\n        <meta http-equiv=\"Content-Security-Policy\" content=\"default-src 'self'; script-src 'nonce-a23gbfz9e'\">\n        <script defer nonce=\"a23gbfz9e\" src=\"https://cdn.jsdelivr.net/npm/@alpinejs/csp@3.x.x/dist/cdn.min.js\"></script>\n    </head>\n    <body>\n        <div x-data=\"{ count: 0, message: 'Hello' }\">\n            <button x-on:click=\"count++\">Increment</button>\n            <button x-on:click=\"count = 0\">Reset</button>\n\n            <span x-text=\"count\"></span>\n            <span x-text=\"message + ' World'\"></span>\n            <span x-show=\"count > 5\">Count is greater than 5!</span>\n        </div>\n    </body>\n</html>\n```\n\n<a name=\"whats-supported\"></a>\n## What's Supported\n\nThe CSP build supports most JavaScript expressions you'd want to use in Alpine:\n\n### Object and Array Literals\n```alpine\n<!-- ✅ These work -->\n<div x-data=\"{ user: { name: 'John', age: 30 }, items: [1, 2, 3] }\">\n    <span x-text=\"user.name\"></span>\n    <span x-text=\"items[0]\"></span>\n</div>\n```\n\n### Basic Operations\n```alpine\n<!-- ✅ These work -->\n<div x-data=\"{ count: 5, name: 'Alpine' }\">\n    <span x-text=\"count + 10\"></span>\n    <span x-text=\"count > 3\"></span>\n    <span x-text=\"count === 5 ? 'Yes' : 'No'\"></span>\n    <span x-text=\"'Hello ' + name\"></span>\n    <div x-show=\"!loading && count > 0\"></div>\n</div>\n```\n\n### Assignments and Updates\n```alpine\n<!-- ✅ These work -->\n<div x-data=\"{ count: 0, user: { name: '' } }\">\n    <button x-on:click=\"count++\">Increment</button>\n    <button x-on:click=\"count = 0\">Reset</button>\n    <input x-model=\"user.name\">\n</div>\n```\n\n### Method Calls\n```alpine\n<!-- ✅ These work -->\n<div x-data=\"{ items: ['a', 'b'] }\">\n    <button x-on:click=\"items.push('c')\">Add Item</button>\n</div>\n```\n\n<a name=\"whats-not-supported\"></a>\n## What's Not Supported\n\nSome advanced and potentially dangerous JavaScript features aren't supported:\n\n### Complex Expressions\n```alpine\n<!-- ❌ These don't work -->\n<div x-data=\"{ user: { name: '' } }\">\n    <!-- Property assignments -->\n    <button x-on:click=\"user.name = 'John'\">Bad</button>\n\n    <!-- Arrow functions -->\n    <button x-on:click=\"() => console.log('hi')\">Bad</button>\n\n    <!-- Destructuring -->\n    <div x-text=\"{ name } = user\">Bad</div>\n\n    <!-- Template literals -->\n    <div x-text=\"`Hello ${name}`\">Bad</div>\n\n    <!-- Spread operator -->\n    <div x-data=\"{ ...defaults }\">Bad</div>\n</div>\n```\n\n### Global Variables and Functions\n```alpine\n<!-- ❌ These don't work -->\n<div x-data>\n    <button x-on:click=\"console.log('hi')\"></button>\n    <span x-text=\"document.title\"></span>\n    <span x-text=\"window.innerWidth\"></span>\n    <span x-text=\"Math.max(count, 100)\"></span>\n    <span x-text=\"parseInt('123') + count\"></span>\n    <span x-text=\"JSON.stringify({ value: count })\"></span>\n</div>\n```\n\n### HTML Injection\n```alpine\n<!-- ❌ These don't work -->\n<div x-data=\"{ message: 'Hello <span>World</span>' }\">\n    <span x-html=\"message\"></span>\n    <span x-init=\"$el.insertAdjacentHTML('beforeend', message)\"></span>\n</div>\n```\n\n<a name=\"when-to-extract-logic\"></a>\n## When to Extract Logic\n\nWhile the CSP build supports simple inline expressions, you'll want to extract complex logic into dedicated functions or Alpine.data() components for better organization:\n\n```alpine\n<!-- Instead of this -->\n<div x-data=\"{ users: [] }\" x-show=\"users.filter(u => u.active && u.role === 'admin').length > 0\">\n```\n\n```alpine\n<!-- Do this -->\n<div x-data=\"userManager\" x-show=\"hasActiveAdmins\">\n\n<script nonce=\"...\">\n    Alpine.data('userManager', () => ({\n        users: [],\n\n        get hasActiveAdmins() {\n            return this.users.filter(u => u.active && u.role === 'admin').length > 0\n        }\n    }))\n</script>\n```\n\nThis approach makes your code more readable, testable, and maintainable, especially for complex applications.\n\n<a name=\"csp-headers\"></a>\n## CSP Headers\n\nHere's an example CSP header that works with Alpine's CSP build:\n\n```\nContent-Security-Policy: default-src 'self'; script-src 'nonce-[random]' 'strict-dynamic';\n```\n\nThe key is removing `'unsafe-eval'` from your `script-src` directive while still allowing your nonce-based scripts to run.","packages/docs/src/en/advanced/extending.md":"---\norder: 3\ntitle: Extending\n---\n\n# Extending\n\nAlpine has a very open codebase that allows for extension in a number of ways. In fact, every available directive and magic in Alpine itself uses these exact APIs. In theory you could rebuild all of Alpine's functionality using them yourself.\n\n<a name=\"lifecycle-concerns\"></a>\n## Lifecycle concerns\nBefore we dive into each individual API, let's first talk about where in your codebase you should consume these APIs.\n\nBecause these APIs have an impact on how Alpine initializes the page, they must be registered AFTER Alpine is downloaded and available on the page, but BEFORE it has initialized the page itself.\n\nThere are two different techniques depending on if you are importing Alpine into a bundle, or including it directly via a `<script>` tag. Let's look at them both:\n\n<a name=\"via-script-tag\"></a>\n### Via a script tag\n\nIf you are including Alpine via a script tag, you will need to register any custom extension code inside an `alpine:init` event listener.\n\nHere's an example:\n\n```alpine\n<html>\n    <script src=\"/js/alpine.js\" defer></script>\n\n    <div x-data x-foo></div>\n\n    <script>\n        document.addEventListener('alpine:init', () => {\n            Alpine.directive('foo', ...)\n        })\n    </script>\n</html>\n```\n\nIf you want to extract your extension code into an external file, you will need to make sure that file's `<script>` tag is located BEFORE Alpine's like so:\n\n```alpine\n<html>\n    <script src=\"/js/foo.js\" defer></script>\n    <script src=\"/js/alpine.js\" defer></script>\n\n    <div x-data x-foo></div>\n</html>\n```\n\n<a name=\"via-npm\"></a>\n### Via an NPM module\n\nIf you imported Alpine into a bundle, you have to make sure you are registering any extension code IN BETWEEN when you import the `Alpine` global object, and when you initialize Alpine by calling `Alpine.start()`. For example:\n\n```js\nimport Alpine from 'alpinejs'\n\nAlpine.directive('foo', ...)\n\nwindow.Alpine = Alpine\nwindow.Alpine.start()\n```\n\nNow that we know where to use these extension APIs, let's look more closely at how to use each one:\n\n<a name=\"custom-directives\"></a>\n## Custom directives\n\nAlpine allows you to register your own custom directives using the `Alpine.directive()` API.\n\n<a name=\"method-signature\"></a>\n### Method Signature\n\n```js\nAlpine.directive('[name]', (el, { value, modifiers, expression }, { Alpine, effect, cleanup }) => {})\n```\n\n&nbsp; | &nbsp;\n---|---\nname | The name of the directive. The name \"foo\" for example would be consumed as `x-foo`\nel | The DOM element the directive is added to\nvalue | If provided, the part of the directive after a colon. Ex: `'bar'` in `x-foo:bar`\nmodifiers | An array of dot-separated trailing additions to the directive. Ex: `['baz', 'lob']` from `x-foo.baz.lob`\nexpression | The attribute value portion of the directive. Ex: `law` from `x-foo=\"law\"`\nAlpine | The Alpine global object\neffect | A function to create reactive effects that will auto-cleanup after this directive is removed from the DOM\ncleanup | A function you can pass bespoke callbacks to that will run when this directive is removed from the DOM\n\n<a name=\"simple-example\"></a>\n### Simple Example\n\nHere's an example of a simple directive we're going to create called: `x-uppercase`:\n\n```js\nAlpine.directive('uppercase', el => {\n    el.textContent = el.textContent.toUpperCase()\n})\n```\n```alpine\n<div x-data>\n    <span x-uppercase>Hello World!</span>\n</div>\n```\n\n<a name=\"evaluating-expressions\"></a>\n### Evaluating expressions\n\nWhen registering a custom directive, you may want to evaluate a user-supplied JavaScript expression:\n\nFor example, let's say you wanted to create a custom directive as a shortcut to `console.log()`. Something like:\n\n```alpine\n<div x-data=\"{ message: 'Hello World!' }\">\n    <div x-log=\"message\"></div>\n</div>\n```\n\nYou need to retrieve the actual value of `message` by evaluating it as a JavaScript expression with the `x-data` scope.\n\nFortunately, Alpine exposes its system for evaluating JavaScript expressions with an `evaluate()` API. Here's an example:\n\n```js\nAlpine.directive('log', (el, { expression }, { evaluate }) => {\n    // expression === 'message'\n\n    console.log(\n        evaluate(expression)\n    )\n})\n```\n\nNow, when Alpine initializes the `<div x-log...>`, it will retrieve the expression passed into the directive (\"message\" in this case), and evaluate it in the context of the current element's Alpine component scope.\n\n<a name=\"introducing-reactivity\"></a>\n### Introducing reactivity\n\nBuilding on the `x-log` example from before, let's say we wanted `x-log` to log the value of `message` and also log it if the value changes.\n\nGiven the following template:\n\n```alpine\n<div x-data=\"{ message: 'Hello World!' }\">\n    <div x-log=\"message\"></div>\n\n    <button @click=\"message = 'yolo'\">Change</button>\n</div>\n```\n\nWe want \"Hello World!\" to be logged initially, then we want \"yolo\" to be logged after pressing the `<button>`.\n\nWe can adjust the implementation of `x-log` and introduce two new APIs to achieve this: `evaluateLater()` and `effect()`:\n\n```js\nAlpine.directive('log', (el, { expression }, { evaluateLater, effect }) => {\n    let getThingToLog = evaluateLater(expression)\n\n    effect(() => {\n        getThingToLog(thingToLog => {\n            console.log(thingToLog)\n        })\n    })\n})\n```\n\nLet's walk through the above code, line by line.\n\n```js\nlet getThingToLog = evaluateLater(expression)\n```\n\nHere, instead of immediately evaluating `message` and retrieving the result, we will convert the string expression (\"message\") into an actual JavaScript function that we can run at any time. If you're going to evaluate a JavaScript expression more than once, it is highly recommended to first generate a JavaScript function and use that rather than calling `evaluate()` directly. The reason being that the process to interpret a plain string as a JavaScript function is expensive and should be avoided when unnecessary.\n\n```js\neffect(() => {\n    ...\n})\n```\n\nBy passing in a callback to `effect()`, we are telling Alpine to run the callback immediately, then track any dependencies it uses (`x-data` properties like `message` in our case). Now as soon as one of the dependencies changes, this callback will be re-run. This gives us our \"reactivity\".\n\nYou may recognize this functionality from `x-effect`. It is the same mechanism under the hood.\n\nYou may also notice that `Alpine.effect()` exists and wonder why we're not using it here. The reason is that the `effect` function provided via the method parameter has special functionality that cleans itself up when the directive is removed from the page for any reason.\n\nFor example, if for some reason the element with `x-log` on it got removed from the page, by using `effect()` instead of `Alpine.effect()` when the `message` property is changed, the value will no longer be logged to the console.\n\n[→ Read more about reactivity in Alpine](/advanced/reactivity)\n\n```js\ngetThingToLog(thingToLog => {\n    console.log(thingToLog)\n})\n```\n\nNow we will call `getThingToLog`, which if you recall is the actual JavaScript function version of the string expression: \"message\".\n\nYou might expect `getThingToCall()` to return the result right away, but instead Alpine requires you to pass in a callback to receive the result.\n\nThe reason for this is to support async expressions like `await getMessage()`. By passing in a \"receiver\" callback instead of getting the result immediately, you are allowing your directive to work with async expressions as well.\n\n[→ Read more about async in Alpine](/advanced/async)\n\n<a name=\"cleaning-up\"></a>\n### Cleaning Up\n\nLet's say you needed to register an event listener from a custom directive. After that directive is removed from the page for any reason, you would want to remove the event listener as well.\n\nAlpine makes this simple by providing you with a `cleanup` function when registering custom directives.\n\nHere's an example:\n\n```js\nAlpine.directive('...', (el, {}, { cleanup }) => {\n    let handler = () => {}\n\n    window.addEventListener('click', handler)\n\n    cleanup(() => {\n        window.removeEventListener('click', handler)\n    })\n\n})\n```\n\nNow if the directive is removed from this element or the element is removed itself, the event listener will be removed as well.\n\n<a name=\"custom-order\"></a>\n### Custom order\n\nBy default, any new directive will run after the majority of the standard ones (with the exception of `x-teleport`). This is usually acceptable but some times you might need to run your custom directive before another specific one.\nThis can be achieved by chaining the `.before() function to `Alpine.directive()` and specifying which directive needs to run after your custom one.\n\n```js\nAlpine.directive('foo', (el, { value, modifiers, expression }) => {\n    Alpine.addScopeToNode(el, {foo: 'bar'})\n}).before('bind')\n```\n```alpine\n<div x-data>\n    <span x-foo x-bind:foo=\"foo\"></span>\n</div>\n```\n> Note, the directive name must be written without the `x-` prefix (or any other custom prefix you may use).\n\n<a name=\"custom-magics\"></a>\n## Custom magics\n\nAlpine allows you to register custom \"magics\" (properties or methods) using `Alpine.magic()`. Any magic you register will be available to all your application's Alpine code with the `$` prefix.\n\n<a name=\"method-signature\"></a>\n### Method Signature\n\n```js\nAlpine.magic('[name]', (el, { Alpine }) => {})\n```\n\n&nbsp; | &nbsp;\n---|---\nname | The name of the magic. The name \"foo\" for example would be consumed as `$foo`\nel | The DOM element the magic was triggered from\nAlpine | The Alpine global object\n\n<a name=\"magic-properties\"></a>\n### Magic Properties\n\nHere's a basic example of a \"$now\" magic helper to easily get the current time from anywhere in Alpine:\n\n```js\nAlpine.magic('now', () => {\n    return (new Date).toLocaleTimeString()\n})\n```\n```alpine\n<span x-text=\"$now\"></span>\n```\n\nNow the `<span>` tag will contain the current time, resembling something like \"12:00:00 PM\".\n\nAs you can see `$now` behaves like a static property, but under the hood is actually a getter that evaluates every time the property is accessed.\n\nBecause of this, you can implement magic \"functions\" by returning a function from the getter.\n\n<a name=\"magic-functions\"></a>\n### Magic Functions\n\nFor example, if we wanted to create a `$clipboard()` magic function that accepts a string to copy to clipboard, we could implement it like so:\n\n```js\nAlpine.magic('clipboard', () => {\n    return subject => navigator.clipboard.writeText(subject)\n})\n```\n```alpine\n<button @click=\"$clipboard('hello world')\">Copy \"Hello World\"</button>\n```\n\nNow that accessing `$clipboard` returns a function itself, we can immediately call it and pass it an argument like we see in the template with `$clipboard('hello world')`.\n\nYou can use the more brief syntax (a double arrow function) for returning a function from a function if you'd prefer:\n\n```js\nAlpine.magic('clipboard', () => subject => {\n    navigator.clipboard.writeText(subject)\n})\n```\n\n<a name=\"writing-and-sharing-plugins\"></a>\n## Writing and sharing plugins\n\nBy now you should see how friendly and simple it is to register your own custom directives and magics in your application, but what about sharing that functionality with others via an NPM package or something?\n\nYou can get started quickly with Alpine's official \"plugin-blueprint\" package. It's as simple as cloning the repository and running `npm install && npm run build` to get a plugin authored.\n\nFor demonstration purposes, let's create a pretend Alpine plugin from scratch called `Foo` that includes both a directive (`x-foo`) and a magic (`$foo`).\n\nWe'll start producing this plugin for consumption as a simple `<script>` tag alongside Alpine, then we'll level it up to a module for importing into a bundle:\n\n<a name=\"script-include\"></a>\n### Script include\n\nLet's start in reverse by looking at how our plugin will be included into a project:\n\n```alpine\n<html>\n    <script src=\"/js/foo.js\" defer></script>\n    <script src=\"/js/alpine.js\" defer></script>\n\n    <div x-data x-init=\"$foo()\">\n        <span x-foo=\"'hello world'\">\n    </div>\n</html>\n```\n\nNotice how our script is included BEFORE Alpine itself. This is important, otherwise, Alpine would have already been initialized by the time our plugin got loaded.\n\nNow let's look inside of `/js/foo.js`'s contents:\n\n```js\ndocument.addEventListener('alpine:init', () => {\n    window.Alpine.directive('foo', ...)\n\n    window.Alpine.magic('foo', ...)\n})\n```\n\nThat's it! Authoring a plugin for inclusion via a script tag is extremely simple with Alpine.\n\n<a name=\"bundle-module\"></a>\n### Bundle module\n\nNow let's say you wanted to author a plugin that someone could install via NPM and include into their bundle.\n\nLike the last example, we'll walk through this in reverse, starting with what it will look like to consume this plugin:\n\n```js\nimport Alpine from 'alpinejs'\n\nimport foo from 'foo'\nAlpine.plugin(foo)\n\nwindow.Alpine = Alpine\nwindow.Alpine.start()\n```\n\nYou'll notice a new API here: `Alpine.plugin()`. This is a convenience method Alpine exposes to prevent consumers of your plugin from having to register multiple different directives and magics themselves.\n\nNow let's look at the source of the plugin and what gets exported from `foo`:\n\n```js\nexport default function (Alpine) {\n    Alpine.directive('foo', ...)\n    Alpine.magic('foo', ...)\n}\n```\n\nYou'll see that `Alpine.plugin` is incredibly simple. It accepts a callback and immediately invokes it while providing the `Alpine` global as a parameter for use inside of it.\n\nThen you can go about extending Alpine as you please.\n\n<a name=\"deferring-initialization\"></a>\n## Deferring initialization\n\nAlpine initializes a tree of elements synchronously. Integrations that load JavaScript for a component asynchronously — a script module that registers an `Alpine.data()` provider, for example — can lose that race: Alpine evaluates `x-data=\"someComponent\"` before the registration exists.\n\n`Alpine.deferInit(el, promise)` suspends initialization of one element's tree until a promise settles. Nothing inside the tree initializes while it's suspended: directives don't evaluate, nodes added inside it wait, and attribute changes are held and replayed when the tree resumes. The rest of the page initializes normally.\n\n```js\nAlpine.interceptInit(el => {\n    if (el.hasAttribute('data-widget') && ! widgetIsLoaded(el)) {\n        Alpine.deferInit(el, loadWidget(el))\n    }\n})\n```\n\n(`Alpine.interceptInit()` is Alpine's low-level integration hook — its callback runs for every element just before that element initializes.)\n\nA few things to know about the contract:\n\n- Registering must happen synchronously — from an `Alpine.interceptInit()` callback before the element initializes, or on an already-initialized element to suspend future activity in its tree (a morph that's about to bring in new markup, for example).\n- Calling `deferInit()` on the same element again before it resumes adds another prerequisite: the tree initializes after every registered promise settles.\n- A rejected promise is reported through Alpine's error handler, then the tree initializes anyway — a failed prerequisite never leaves a tree permanently suspended.\n- If the element has left the DOM by the time the promise settles, nothing happens. If it re-enters later, it initializes like any other added node.\n- When a suspended tree resumes, init interceptors run again for elements that hadn't initialized yet. Only defer while your prerequisite is still outstanding — like the `widgetIsLoaded()` check above — so the resume pass initializes normally instead of suspending again.\n- `[x-cloak]` attributes inside a suspended tree stay in place until it resumes, so the existing cloaking pattern hides not-yet-ready content.\n- `alpine:initialized` does not wait for suspended trees — it fires when the synchronous pass over the page completes.\n- The promise is expected to settle. A prerequisite that never settles leaves its tree suspended indefinitely — put timeouts on operations that need them before handing the promise to Alpine.\n","packages/docs/src/en/advanced/reactivity.md":"---\norder: 2\ntitle: Reactivity\n---\n\n# Reactivity\n\nAlpine is \"reactive\" in the sense that when you change a piece of data, everything that depends on that data \"reacts\" automatically to that change.\n\nEvery bit of reactivity that takes place in Alpine, happens because of two very important reactive functions in Alpine's core: `Alpine.reactive()`, and `Alpine.effect()`.\n\n> Alpine uses VueJS's reactivity engine under the hood to provide these functions.\n> [→ Browse the @vue/reactivity source](https://github.com/vuejs/core/tree/main/packages/reactivity)\n\nUnderstanding these two functions will give you super powers as an Alpine developer, but also just as a web developer in general.\n\n<a name=\"alpine-reactive\"></a>\n## Alpine.reactive()\n\nLet's first look at `Alpine.reactive()`. This function accepts a JavaScript object as its parameter and returns a \"reactive\" version of that object. For example:\n\n```js\nlet data = { count: 1 }\n\nlet reactiveData = Alpine.reactive(data)\n```\n\nUnder the hood, when `Alpine.reactive` receives `data`, it wraps it inside a custom JavaScript proxy.\n\nA proxy is a special kind of object in JavaScript that can intercept \"get\" and \"set\" calls to a JavaScript object.\n\n[→ Read more about JavaScript proxies](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy)\n\nAt face value, `reactiveData` should behave exactly like `data`. For example:\n\n```js\nconsole.log(data.count) // 1\nconsole.log(reactiveData.count) // 1\n\nreactiveData.count = 2\n\nconsole.log(data.count) // 2\nconsole.log(reactiveData.count) // 2\n```\n\nWhat you see here is that because `reactiveData` is a thin wrapper around `data`, any attempts to get or set a property will behave exactly as if you had interacted with `data` directly.\n\nThe main difference here is that any time you modify or retrieve (get or set) a value from `reactiveData`, Alpine is aware of it and can execute any other logic that depends on this data.\n\n`Alpine.reactive` is only the first half of the story. `Alpine.effect` is the other half, let's dig in.\n\n<a name=\"alpine-effect\"></a>\n## Alpine.effect()\n\n`Alpine.effect` accepts a single callback function. As soon as `Alpine.effect` is called, it runs the provided function and watches for reads from reactive data. Each reactive property read during that execution becomes a dependency. When one of those properties changes later, Alpine runs the callback again. For example:\n\n```js\nlet data = Alpine.reactive({ count: 1 })\n\nAlpine.effect(() => {\n    console.log(data.count)\n})\n```\n\nWhen this code is first run, \"1\" will be logged to the console. Any time `data.count` changes, its value will be logged to the console again.\n\nThis is the mechanism that unlocks all of the reactivity at the core of Alpine.\n\n### How dependency tracking works\n\nDependency collection happens while the effect callback is running. Reading `data.count` inside the callback registers that property with the effect. Changing `data.count` later notifies the effect, which runs again and collects the dependencies used by that execution.\n\nReads made after the callback has returned, such as inside a `setTimeout` callback, are not automatically tracked by the original effect.\n\nAlpine delegates this behavior to Vue's reactivity package. For a deeper explanation of the proxy, dependency-map, and `track`/`trigger` model, see [Vue's reactivity internals](https://frontendatlas.com/vue/trivia/vue-reactivity-system).\n\nTo connect the dots further, let's look at a simple \"counter\" component example without using Alpine syntax at all, only using `Alpine.reactive` and `Alpine.effect`:\n\n```alpine\n<button>Increment</button>\n\nCount: <span></span>\n```\n```js\nlet button = document.querySelector('button')\nlet span = document.querySelector('span')\n\nlet data = Alpine.reactive({ count: 1 })\n\nAlpine.effect(() => {\n    span.textContent = data.count\n})\n\nbutton.addEventListener('click', () => {\n    data.count = data.count + 1\n})\n```\n\n<!-- START_VERBATIM -->\n<div x-data=\"{ count: 1 }\" class=\"demo\">\n    <button @click=\"count++\">Increment</button>\n\n    <div>Count: <span x-text=\"count\"></span></div>\n</div>\n<!-- END_VERBATIM -->\n\nAs you can see, you can make any data reactive, and you can also wrap any functionality in `Alpine.effect`.\n\nThis combination unlocks an incredibly powerful programming paradigm for web development. Run wild and free.\n","packages/docs/src/en/directives.md":"---\norder: 4\ntitle: Directives\nprefix: x-\nfont-type: mono\ntype: sub-directory\n---\n","packages/docs/src/en/directives/bind.md":"---\norder: 4\ntitle: bind\n---\n\n# x-bind\n\n`x-bind` allows you to set HTML attributes on elements based on the result of JavaScript expressions.\n\nFor example, here's a component where we will use `x-bind` to set the placeholder value of an input.\n\n```alpine\n<div x-data=\"{ placeholderText: 'Type here...' }\">\n    <input type=\"text\" x-bind:placeholder=\"placeholderText\">\n</div>\n```\n\n<a name=\"shorthand-syntax\"></a>\n## Shorthand syntax\n\nIf `x-bind:` is too verbose for your liking, you can use the shorthand: `:`. For example, here is the same input element as above, but refactored to use the shorthand syntax.\n\n```alpine\n<input type=\"text\" :placeholder=\"placeholderText\">\n```\n\n> Despite not being included in the above snippet, `x-bind` cannot be used if no parent element has `x-data` defined. [→ Read more about `x-data`](/directives/data)\n\n<a name=\"binding-classes\"></a>\n## Binding classes\n\n`x-bind` is most often useful for setting specific classes on an element based on your Alpine state.\n\nHere's a simple example of a simple dropdown toggle, but instead of using `x-show`, we'll use a \"hidden\" class to toggle an element.\n\n```alpine\n<div x-data=\"{ open: false }\">\n    <button x-on:click=\"open = ! open\">Toggle Dropdown</button>\n\n    <div :class=\"open ? '' : 'hidden'\">\n        Dropdown Contents...\n    </div>\n</div>\n```\n\nNow, when `open` is `false`, the \"hidden\" class will be added to the dropdown.\n\n<a name=\"shorthand-conditionals\"></a>\n### Shorthand conditionals\n\nIn cases like these, if you prefer a less verbose syntax you can use JavaScript's short-circuit evaluation instead of standard conditionals:\n\n```alpine\n<div :class=\"show ? '' : 'hidden'\">\n<!-- Is equivalent to: -->\n<div :class=\"show || 'hidden'\">\n```\n\nThe inverse is also available to you. Suppose instead of `open`, we use a variable with the opposite value: `closed`.\n\n```alpine\n<div :class=\"closed ? 'hidden' : ''\">\n<!-- Is equivalent to: -->\n<div :class=\"closed && 'hidden'\">\n```\n\n<a name=\"class-object-syntax\"></a>\n### Class object syntax\n\nAlpine offers an additional syntax for toggling classes if you prefer. By passing a JavaScript object where the classes are the keys and booleans are the values, Alpine will know which classes to apply and which to remove. For example:\n\n```alpine\n<div :class=\"{ 'hidden': ! show }\">\n```\n\nThis technique offers a unique advantage to other methods. When using object-syntax, Alpine will NOT preserve original classes applied to an element's `class` attribute.\n\nFor example, if you wanted to apply the \"hidden\" class to an element before Alpine loads, AND use Alpine to toggle its existence you can only achieve that behavior using object-syntax:\n\n```alpine\n<div class=\"hidden\" :class=\"{ 'hidden': ! show }\">\n```\n\nIn case that confused you, let's dig deeper into how Alpine handles `x-bind:class` differently than other attributes.\n\n<a name=\"special-behavior\"></a>\n### Special behavior\n\n`x-bind:class` behaves differently than other attributes under the hood.\n\nConsider the following case.\n\n```alpine\n<div class=\"opacity-50\" :class=\"hide && 'hidden'\">\n```\n\nIf \"class\" were any other attribute, the `:class` binding would overwrite any existing class attribute, causing `opacity-50` to be overwritten by either `hidden` or `''`.\n\nHowever, Alpine treats `class` bindings differently. It's smart enough to preserve existing classes on an element.\n\nFor example, if `hide` is true, the above example will result in the following DOM element:\n\n```alpine\n<div class=\"opacity-50 hidden\">\n```\n\nIf `hide` is false, the DOM element will look like:\n\n```alpine\n<div class=\"opacity-50\">\n```\n\nThis behavior should be invisible and intuitive to most users, but it is worth mentioning explicitly for the inquiring developer or any special cases that might crop up.\n\n<a name=\"binding-styles\"></a>\n## Binding styles\n\nSimilar to the special syntax for binding classes with JavaScript objects, Alpine also offers an object-based syntax for binding `style` attributes.\n\nJust like the class objects, this syntax is entirely optional. Only use it if it affords you some advantage.\n\n```alpine\n<div :style=\"{ color: 'red', display: 'flex' }\">\n\n<!-- Will render: -->\n<div style=\"color: red; display: flex;\" ...>\n```\n\nConditional inline styling is possible using expressions just like with x-bind:class. Short circuit operators can be used here as well by using a styles object as the second operand.\n```alpine\n<div x-bind:style=\"true && { color: 'red' }\">\n\n<!-- Will render: -->\n<div style=\"color: red;\">\n```\n\nOne advantage of this approach is being able to mix it in with existing styles on an element:\n\n```alpine\n<div style=\"padding: 1rem;\" :style=\"{ color: 'red', display: 'flex' }\">\n\n<!-- Will render: -->\n<div style=\"padding: 1rem; color: red; display: flex;\" ...>\n```\n\nAnd like most expressions in Alpine, you can always use the result of a JavaScript expression as the reference:\n\n```alpine\n<div x-data=\"{ styles: { color: 'red', display: 'flex' }}\">\n    <div :style=\"styles\">\n</div>\n\n<!-- Will render: -->\n<div ...>\n    <div style=\"color: red; display: flex;\" ...>\n</div>\n```\n\n<a name=\"bind-directives\"></a>\n## Binding Alpine Directives Directly\n\n`x-bind` allows you to bind an object of different directives and attributes to an element.\n\nThe object keys can be anything you would normally write as an attribute name in Alpine. This includes Alpine directives and modifiers, but also plain HTML attributes. The object values are either plain strings, or in the case of dynamic Alpine directives, callbacks to be evaluated by Alpine.\n\n```alpine\n<div x-data=\"dropdown\">\n    <button x-bind=\"trigger\">Open Dropdown</button>\n\n    <span x-bind=\"dialogue\">Dropdown Contents</span>\n</div>\n\n<script>\n    document.addEventListener('alpine:init', () => {\n        Alpine.data('dropdown', () => ({\n            open: false,\n\n            trigger: {\n                ['x-ref']: 'trigger',\n                ['@click']() {\n                    this.open = true\n                },\n            },\n\n            dialogue: {\n                ['x-show']() {\n                    return this.open\n                },\n                ['@click.outside']() {\n                    this.open = false\n                },\n            },\n        }))\n    })\n</script>\n```\n\nThere are a couple of caveats to this usage of `x-bind`:\n\n> When the directive being \"bound\" or \"applied\" is `x-for`, you should return a normal expression string from the callback. For example: `['x-for']() { return 'item in items' }`\n","packages/docs/src/en/directives/cloak.md":"---\norder: 12\ntitle: cloak\n---\n\n# x-cloak\n\nSometimes, when you're using AlpineJS for a part of your template, there is a \"blip\" where you might see your uninitialized template after the page loads, but before Alpine loads.\n\n`x-cloak` addresses this scenario by hiding the element it's attached to until Alpine is fully loaded on the page.\n\nFor `x-cloak` to work however, you must add the following CSS to the page.\n\n```css\n[x-cloak] { display: none !important; }\n```\n\nThe following example will hide the `<span>` tag until its `x-show` is specifically set to true, preventing any \"blip\" of the hidden element onto screen as Alpine loads.\n\n```alpine\n<span x-cloak x-show=\"false\">This will not 'blip' onto screen at any point</span>\n```\n\n`x-cloak` doesn't just work on elements hidden by `x-show` or `x-if`: it also ensures that elements containing data are hidden until the data is correctly set. The following example will hide the `<span>` tag until Alpine has set its text content to the `message` property.\n\n```alpine\n<span x-cloak x-text=\"message\"></span>\n```\n\nWhen Alpine loads on the page, it removes all `x-cloak` property from the element, which also removes the `display: none;` applied by CSS, therefore showing the element.\n\n## Alternative to global syntax\n\nIf you'd like to achieve this same behavior, but avoid having to include a global style, you can use the following cool, but admittedly odd trick:\n\n```alpine\n<template x-if=\"true\">\n    <span x-text=\"message\"></span>\n</template>\n```\n\nThis will achieve the same goal as `x-cloak` by just leveraging the way `x-if` works.\n\nBecause `<template>` elements are \"hidden\" in browsers by default, you won't see the `<span>` until Alpine has had a chance to render the `x-if=\"true\"` and show it.\n\nAgain, this solution is not for everyone, but it's worth mentioning for special cases.\n","packages/docs/src/en/directives/data.md":"---\norder: 1\ntitle: data\n---\n\n# x-data\n\nEverything in Alpine starts with the `x-data` directive.\n\n`x-data` defines a chunk of HTML as an Alpine component and provides the reactive data for that component to reference.\n\nHere's an example of a contrived dropdown component:\n\n```alpine\n<div x-data=\"{ open: false }\">\n    <button @click=\"open = ! open\">Toggle Content</button>\n\n    <div x-show=\"open\">\n        Content...\n    </div>\n</div>\n```\n\nDon't worry about the other directives in this example (`@click` and `x-show`), we'll get to those in a bit. For now, let's focus on `x-data`.\n\n<a name=\"scope\"></a>\n## Scope\n\nProperties defined in an `x-data` directive are available to all element children. Even ones inside other, nested `x-data` components.\n\nFor example:\n\n```alpine\n<div x-data=\"{ foo: 'bar' }\">\n    <span x-text=\"foo\"><!-- Will output: \"bar\" --></span>\n\n    <div x-data=\"{ bar: 'baz' }\">\n        <span x-text=\"foo\"><!-- Will output: \"bar\" --></span>\n\n        <div x-data=\"{ foo: 'bob' }\">\n            <span x-text=\"foo\"><!-- Will output: \"bob\" --></span>\n        </div>\n    </div>\n</div>\n```\n\n<a name=\"methods\"></a>\n## Methods\n\nBecause `x-data` is evaluated as a normal JavaScript object, in addition to state, you can store methods and even getters.\n\nFor example, let's extract the \"Toggle Content\" behavior into a method on  `x-data`.\n\n```alpine\n<div x-data=\"{ open: false, toggle() { this.open = ! this.open } }\">\n    <button @click=\"toggle()\">Toggle Content</button>\n\n    <div x-show=\"open\">\n        Content...\n    </div>\n</div>\n```\n\nNotice the added `toggle() { this.open = ! this.open }` method on `x-data`. This method can now be called from anywhere inside the component.\n\nYou'll also notice the usage of `this.` to access state on the object itself. This is because Alpine evaluates this data object like any standard JavaScript object with a `this` context.\n\nIf you prefer, you can leave the calling parenthesis off of the `toggle` method completely. For example:\n\n```alpine\n<!-- Before -->\n<button @click=\"toggle()\">...</button>\n\n<!-- After -->\n<button @click=\"toggle\">...</button>\n```\n\n<a name=\"getters\"></a>\n## Getters\n\nJavaScript [getters](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/get) are handy when the sole purpose of a method is to return data based on other state.\n\nThink of them like \"computed properties\" (although, they are not cached like Vue's computed properties).\n\nLet's refactor our component to use a getter called `isOpen` instead of accessing `open` directly.\n\n```alpine\n<div x-data=\"{\n    open: false,\n    get isOpen() { return this.open },\n    toggle() { this.open = ! this.open },\n}\">\n    <button @click=\"toggle()\">Toggle Content</button>\n\n    <div x-show=\"isOpen\">\n        Content...\n    </div>\n</div>\n```\n\nNotice the \"Content\" now depends on the `isOpen` getter instead of the `open` property directly.\n\nIn this case there is no tangible benefit. But in some cases, getters are helpful for providing a more expressive syntax in your components.\n\n<a name=\"data-less-components\"></a>\n## Data-less components\n\nOccasionally, you want to create an Alpine component, but you don't need any data.\n\nIn these cases, you can always pass in an empty object.\n\n```alpine\n<div x-data=\"{}\">\n```\n\nHowever, if you wish, you can also eliminate the attribute value entirely if it looks better to you.\n\n```alpine\n<div x-data>\n```\n\n<a name=\"single-element-components\"></a>\n## Single-element components\n\nSometimes you may only have a single element inside your Alpine component, like the following:\n\n```alpine\n<div x-data=\"{ open: true }\">\n    <button @click=\"open = false\" x-show=\"open\">Hide Me</button>\n</div>\n```\n\nIn these cases, you can declare `x-data` directly on that single element:\n\n```alpine\n<button x-data=\"{ open: true }\" @click=\"open = false\" x-show=\"open\">\n    Hide Me\n</button>\n```\n\n<a name=\"re-usable-data\"></a>\n## Re-usable Data\n\nIf you find yourself duplicating the contents of `x-data`, or you find the inline syntax verbose, you can extract the `x-data` object out to a dedicated component using `Alpine.data`.\n\nHere's a quick example:\n\n```alpine\n<div x-data=\"dropdown\">\n    <button @click=\"toggle\">Toggle Content</button>\n\n    <div x-show=\"open\">\n        Content...\n    </div>\n</div>\n\n<script>\n    document.addEventListener('alpine:init', () => {\n        Alpine.data('dropdown', () => ({\n            open: false,\n\n            toggle() {\n                this.open = ! this.open\n            },\n        }))\n    })\n</script>\n```\n\n[→ Read more about `Alpine.data(...)`](/globals/alpine-data)\n","packages/docs/src/en/directives/effect.md":"---\norder: 11\ntitle: effect\n---\n\n# x-effect\n\n`x-effect` is a useful directive for re-evaluating an expression when one of its dependencies change. You can think of it as a watcher where you don't have to specify what property to watch, it will watch all properties used within it.\n\nIf this definition is confusing for you, that's ok. It's better explained through an example:\n\n```alpine\n<div x-data=\"{ label: 'Hello' }\" x-effect=\"console.log(label)\">\n    <button @click=\"label += ' World!'\">Change Message</button>\n</div>\n```\n\nWhen this component is loaded, the `x-effect` expression will be run and \"Hello\" will be logged into the console.\n\nBecause Alpine knows about any property references contained within `x-effect`, when the button is clicked and `label` is changed, the effect will be re-triggered and \"Hello World!\" will be logged to the console.\n","packages/docs/src/en/directives/for.md":"---\norder: 8\ntitle: for\n---\n\n# x-for\n\nAlpine's `x-for` directive allows you to create DOM elements by iterating through a list. Here's a simple example of using it to create a list of colors based on an array.\n\n```alpine\n<ul x-data=\"{ colors: ['Red', 'Orange', 'Yellow'] }\">\n    <template x-for=\"color in colors\">\n        <li x-text=\"color\"></li>\n    </template>\n</ul>\n```\n\n<!-- START_VERBATIM -->\n<div class=\"demo\">\n    <ul x-data=\"{ colors: ['Red', 'Orange', 'Yellow'] }\">\n        <template x-for=\"color in colors\">\n            <li x-text=\"color\"></li>\n        </template>\n    </ul>\n</div>\n<!-- END_VERBATIM -->\n\nYou may also pass objects to `x-for`.\n\n```alpine\n<ul x-data=\"{ car: { make: 'Jeep', model: 'Grand Cherokee', color: 'Black' } }\">\n    <template x-for=\"(value, index) in car\">\n        <li>\n            <span x-text=\"index\"></span>: <span x-text=\"value\"></span>\n        </li>\n    </template>\n</ul>\n```\n\n<!-- START_VERBATIM -->\n<div class=\"demo\">\n    <ul x-data=\"{ car: { make: 'Jeep', model: 'Grand Cherokee', color: 'Black' } }\">\n        <template x-for=\"(value, index) in car\">\n            <li>\n                <span x-text=\"index\"></span>: <span x-text=\"value\"></span>\n            </li>\n        </template>\n    </ul>\n</div>\n<!-- END_VERBATIM -->\n\nThere are two rules worth noting about `x-for`:\n\n> `x-for` MUST be declared on a `<template>` element.\n> That `<template>` element MUST contain only one root element\n\n<a name=\"keys\"></a>\n## Keys\n\nIt is important to specify unique keys for each `x-for` iteration if you are going to be re-ordering items. Without dynamic keys, Alpine may have a hard time keeping track of what re-orders and will cause odd side-effects.\n\n```alpine\n<ul x-data=\"{ colors: [\n    { id: 1, label: 'Red' },\n    { id: 2, label: 'Orange' },\n    { id: 3, label: 'Yellow' },\n]}\">\n    <template x-for=\"color in colors\" :key=\"color.id\">\n        <li x-text=\"color.label\"></li>\n    </template>\n</ul>\n```\n\nNow if the colors are added, removed, re-ordered, or their \"id\"s change, Alpine will preserve or destroy the iterated `<li>`elements accordingly.\n\n<a name=\"accessing-indexes\"></a>\n## Accessing indexes\n\nIf you need to access the index of each item in the iteration, you can do so using the `([item], [index]) in [items]` syntax like so:\n\n```alpine\n<ul x-data=\"{ colors: ['Red', 'Orange', 'Yellow'] }\">\n    <template x-for=\"(color, index) in colors\">\n        <li>\n            <span x-text=\"index + ': '\"></span>\n            <span x-text=\"color\"></span>\n        </li>\n    </template>\n</ul>\n```\n\nYou can also access the index inside a dynamic `:key` expression.\n\n```alpine\n<template x-for=\"(color, index) in colors\" :key=\"index\">\n```\n\n<a name=\"iterating-over-a-range\"></a>\n## Iterating over a range\n\nIf you need to simply loop `n` number of times, rather than iterate through an array, Alpine offers a short syntax.\n\n```alpine\n<ul>\n    <template x-for=\"i in 10\">\n        <li x-text=\"i\"></li>\n    </template>\n</ul>\n```\n\n`i` in this case can be named anything you like.\n\n> Despite not being included in the above snippet, `x-for` cannot be used if no parent element has `x-data` defined. [→ Read more about `x-data`](/directives/data)\n\n<a name=\"contents-of-a-template\"></a>\n## Contents of a `<template>`\n\nAs mentioned above, an `<template>` tag must contain only one root element.\n\nFor example, the following code will not work:\n\n```alpine\n<template x-for=\"color in colors\">\n    <span>The next color is </span><span x-text=\"color\">\n</template>\n```\n\nbut this code will work:\n```alpine\n<template x-for=\"color in colors\">\n    <p>\n        <span>The next color is </span><span x-text=\"color\">\n    </p>\n</template>\n```\n","packages/docs/src/en/directives/html.md":"---\norder: 7\ntitle: html\n---\n\n# x-html\n\n`x-html` sets the \"innerHTML\" property of an element to the result of a given expression.\n\n> ⚠️ Only use on trusted content and never on user-provided content. ⚠️\n> Dynamically rendering HTML from third parties can easily lead to XSS vulnerabilities.\n\nHere's a basic example of using `x-html` to display a user's username.\n\n```alpine\n<div x-data=\"{ username: '<strong>calebporzio</strong>' }\">\n    Username: <span x-html=\"username\"></span>\n</div>\n```\n\n<!-- START_VERBATIM -->\n<div class=\"demo\">\n    <div x-data=\"{ username: '<strong>calebporzio</strong>' }\">\n        Username: <span x-html=\"username\"></span>\n    </div>\n</div>\n<!-- END_VERBATIM -->\n\nNow the `<span>` tag's inner HTML will be set to \"<strong>calebporzio</strong>\".\n","packages/docs/src/en/directives/id.md":"---\norder: 17\ntitle: id\n---\n\n# x-id\n\n`x-id` allows you to declare a new \"scope\" for any new IDs generated using `$id()`. It accepts an array of strings (ID names) and adds a suffix to each `$id('...')` generated within it that is unique to other IDs on the page.\n\n`x-id` is meant to be used in conjunction with the `$id(...)` magic.\n\n[Visit the $id documentation](/magics/id) for a better understanding of this feature.\n\nHere's a brief example of this directive in use:\n\n```alpine\n<div x-id=\"['text-input']\">\n    <label :for=\"$id('text-input')\">Username</label>\n    <!-- for=\"text-input-1\" -->\n\n    <input type=\"text\" :id=\"$id('text-input')\">\n    <!-- id=\"text-input-1\" -->\n</div>\n\n<div x-id=\"['text-input']\">\n    <label :for=\"$id('text-input')\">Username</label>\n    <!-- for=\"text-input-2\" -->\n\n    <input type=\"text\" :id=\"$id('text-input')\">\n    <!-- id=\"text-input-2\" -->\n</div>\n```\n\n> Despite not being included in the above snippet, `x-id` cannot be used if no parent element has `x-data` defined. [→ Read more about `x-data`](/directives/data)\n","packages/docs/src/en/directives/if.md":"---\norder: 16\ntitle: if\n---\n\n# x-if\n\n`x-if` is used for toggling elements on the page, similarly to `x-show`, however it completely adds and removes the element it's applied to rather than just changing its CSS display property to \"none\".\n\nBecause of this difference in behavior, `x-if` should not be applied directly to the element, but instead to a `<template>` tag that encloses the element. This way, Alpine can keep a record of the element once it's removed from the page.\n\n```alpine\n<template x-if=\"open\">\n    <div>Contents...</div>\n</template>\n```\n\n> Despite not being included in the above snippet, `x-if` cannot be used if no parent element has `x-data` defined. [→ Read more about `x-data`](/directives/data)\n\n## Caveats\n\nUnlike `x-show`, `x-if`, does NOT support transitioning toggles with `x-transition`.\n\n`<template>` tags can only contain one root element.\n","packages/docs/src/en/directives/ignore.md":"---\norder: 11\ntitle: ignore\n---\n\n# x-ignore\n\nBy default, Alpine will crawl and initialize the entire DOM tree of an element containing `x-init` or `x-data`.\n\nIf for some reason, you don't want Alpine to touch a specific section of your HTML, you can prevent it from doing so using `x-ignore`.\n\n```alpine\n<div x-data=\"{ label: 'From Alpine' }\">\n    <div x-ignore>\n        <span x-text=\"label\"></span>\n    </div>\n</div>\n```\n\nIn the above example, the `<span>` tag will not contain \"From Alpine\" because we told Alpine to ignore the contents of the `div` completely.\n","packages/docs/src/en/directives/init.md":"---\norder: 2\ntitle: init\n---\n\n# x-init\n\nThe `x-init` directive allows you to hook into the initialization phase of any element in Alpine.\n\n```alpine\n<div x-init=\"console.log('I\\'m being initialized!')\"></div>\n```\n\nIn the above example, \"I\\'m being initialized!\" will be output in the console before it makes further DOM updates.\n\nConsider another example where `x-init` is used to fetch some JSON and store it in `x-data` before the component is processed.\n\n```alpine\n<div\n    x-data=\"{ posts: [] }\"\n    x-init=\"posts = await (await fetch('/posts')).json()\"\n>...</div>\n```\n\n<a name=\"next-tick\"></a>\n## $nextTick\n\nSometimes, you want to wait until after Alpine has completely finished rendering to execute some code.\n\nThis would be something like `useEffect(..., [])` in react, or `mount` in Vue.\n\nBy using Alpine's internal `$nextTick` magic, you can make this happen.\n\n```alpine\n<div x-init=\"$nextTick(() => { ... })\"></div>\n```\n\n<a name=\"standalone-x-init\"></a>\n## Standalone `x-init`\n\nYou can add `x-init` to any elements inside or outside an `x-data` HTML block. For example:\n\n```alpine\n<div x-data>\n    <span x-init=\"console.log('I can initialize')\"></span>\n</div>\n\n<span x-init=\"console.log('I can initialize too')\"></span>\n```\n\n<a name=\"auto-evaluate-init-method\"></a>\n## Auto-evaluate init() method\n\nIf the `x-data` object of a component contains an `init()` method, it will be called automatically. For example:\n\n```alpine\n<div x-data=\"{\n    init() {\n        console.log('I am called automatically')\n    }\n}\">\n    ...\n</div>\n```\n\nThis is also the case for components that were registered using the `Alpine.data()` syntax.\n\n```js\nAlpine.data('dropdown', () => ({\n    init() {\n        console.log('I will get evaluated when initializing each \"dropdown\" component.')\n    },\n}))\n```\n\nIf you have both an `x-data` object containing an `init()` method and an `x-init` directive, the `x-data` method will be called before the directive.\n\n```alpine\n<div\n    x-data=\"{\n        init() {\n            console.log('I am called first')\n        }\n    }\"\n    x-init=\"console.log('I am called second')\"\n    >\n    ...\n</div>\n```\n","packages/docs/src/en/directives/model.md":"---\norder: 7\ntitle: model\n---\n\n# x-model\n\n`x-model` allows you to bind the value of an input element to Alpine data.\n\nHere's a simple example of using `x-model` to bind the value of a text field to a piece of data in Alpine.\n\n```alpine\n<div x-data=\"{ message: '' }\">\n    <input type=\"text\" x-model=\"message\">\n\n    <span x-text=\"message\"></span>\n</div>\n```\n\n<!-- START_VERBATIM -->\n<div class=\"demo\">\n    <div x-data=\"{ message: '' }\">\n        <input type=\"text\" x-model=\"message\" placeholder=\"Type message...\">\n\n        <div class=\"pt-4\" x-text=\"message\"></div>\n    </div>\n</div>\n<!-- END_VERBATIM -->\n\n\nNow as the user types into the text field, the `message` will be reflected in the `<span>` tag.\n\n`x-model` is two-way bound, meaning it both \"sets\" and \"gets\". In addition to changing data, if the data itself changes, the element will reflect the change.\n\n\nWe can use the same example as above but this time, we'll add a button to change the value of the `message` property.\n\n```alpine\n<div x-data=\"{ message: '' }\">\n    <input type=\"text\" x-model=\"message\">\n\n    <button x-on:click=\"message = 'changed'\">Change Message</button>\n</div>\n```\n\n<!-- START_VERBATIM -->\n<div class=\"demo\">\n    <div x-data=\"{ message: '' }\">\n        <input type=\"text\" x-model=\"message\" placeholder=\"Type message...\">\n\n        <button x-on:click=\"message = 'changed'\">Change Message</button>\n    </div>\n</div>\n<!-- END_VERBATIM -->\n\nNow when the `<button>` is clicked, the input element's value will instantly be updated to \"changed\".\n\n`x-model` works with the following input elements:\n\n* `<input type=\"text\">`\n* `<textarea>`\n* `<input type=\"checkbox\">`\n* `<input type=\"radio\">`\n* `<select>`\n* `<input type=\"range\">`\n\n<a name=\"text-inputs\"></a>\n## Text inputs\n\n```alpine\n<input type=\"text\" x-model=\"message\">\n\n<span x-text=\"message\"></span>\n```\n\n<!-- START_VERBATIM -->\n<div class=\"demo\">\n    <div x-data=\"{ message: '' }\">\n        <input type=\"text\" x-model=\"message\" placeholder=\"Type message\">\n\n        <div class=\"pt-4\" x-text=\"message\"></div>\n    </div>\n</div>\n<!-- END_VERBATIM -->\n\n> Despite not being included in the above snippet, `x-model` cannot be used if no parent element has `x-data` defined. [→ Read more about `x-data`](/directives/data)\n\n<a name=\"textarea-inputs\"></a>\n## Textarea inputs\n\n```alpine\n<textarea x-model=\"message\"></textarea>\n\n<span x-text=\"message\"></span>\n```\n\n<!-- START_VERBATIM -->\n<div class=\"demo\">\n    <div x-data=\"{ message: '' }\">\n        <textarea x-model=\"message\" placeholder=\"Type message\"></textarea>\n\n        <div class=\"pt-4\" x-text=\"message\"></div>\n    </div>\n</div>\n<!-- END_VERBATIM -->\n\n<a name=\"checkbox-inputs\"></a>\n## Checkbox inputs\n\n<a name=\"single-checkbox-with-boolean\"></a>\n### Single checkbox with boolean\n\n```alpine\n<input type=\"checkbox\" id=\"checkbox\" x-model=\"show\">\n\n<label for=\"checkbox\" x-text=\"show\"></label>\n```\n\n<!-- START_VERBATIM -->\n<div class=\"demo\">\n    <div x-data=\"{ open: '' }\">\n        <input type=\"checkbox\" id=\"checkbox\" x-model=\"open\">\n\n        <label for=\"checkbox\" x-text=\"open\"></label>\n    </div>\n</div>\n<!-- END_VERBATIM -->\n\n<a name=\"multiple-checkboxes-bound-to-array\"></a>\n### Multiple checkboxes bound to array\n\n```alpine\n<input type=\"checkbox\" value=\"red\" x-model=\"colors\">\n<input type=\"checkbox\" value=\"orange\" x-model=\"colors\">\n<input type=\"checkbox\" value=\"yellow\" x-model=\"colors\">\n\nColors: <span x-text=\"colors\"></span>\n```\n\n<!-- START_VERBATIM -->\n<div class=\"demo\">\n    <div x-data=\"{ colors: [] }\">\n        <input type=\"checkbox\" value=\"red\" x-model=\"colors\">\n        <input type=\"checkbox\" value=\"orange\" x-model=\"colors\">\n        <input type=\"checkbox\" value=\"yellow\" x-model=\"colors\">\n\n        <div class=\"pt-4\">Colors: <span x-text=\"colors\"></span></div>\n    </div>\n</div>\n<!-- END_VERBATIM -->\n\n<a name=\"radio-inputs\"></a>\n## Radio inputs\n\n```alpine\n<input type=\"radio\" value=\"yes\" x-model=\"answer\">\n<input type=\"radio\" value=\"no\" x-model=\"answer\">\n\nAnswer: <span x-text=\"answer\"></span>\n```\n\n<!-- START_VERBATIM -->\n<div class=\"demo\">\n    <div x-data=\"{ answer: '' }\">\n        <input type=\"radio\" value=\"yes\" x-model=\"answer\">\n        <input type=\"radio\" value=\"no\" x-model=\"answer\">\n\n        <div class=\"pt-4\">Answer: <span x-text=\"answer\"></span></div>\n    </div>\n</div>\n<!-- END_VERBATIM -->\n\n<a name=\"select-inputs\"></a>\n## Select inputs\n\n\n<a name=\"single-select\"></a>\n### Single select\n\n```alpine\n<select x-model=\"color\">\n    <option>Red</option>\n    <option>Orange</option>\n    <option>Yellow</option>\n</select>\n\nColor: <span x-text=\"color\"></span>\n```\n\n<!-- START_VERBATIM -->\n<div class=\"demo\">\n    <div x-data=\"{ color: '' }\">\n        <select x-model=\"color\">\n            <option>Red</option>\n            <option>Orange</option>\n            <option>Yellow</option>\n        </select>\n\n        <div class=\"pt-4\">Color: <span x-text=\"color\"></span></div>\n    </div>\n</div>\n<!-- END_VERBATIM -->\n\n<a name=\"single-select-with-placeholder\"></a>\n### Single select with placeholder\n\n```alpine\n<select x-model=\"color\">\n    <option value=\"\" disabled>Select A Color</option>\n    <option>Red</option>\n    <option>Orange</option>\n    <option>Yellow</option>\n</select>\n\nColor: <span x-text=\"color\"></span>\n```\n\n\n<!-- START_VERBATIM -->\n<div class=\"demo\">\n    <div x-data=\"{ color: '' }\">\n        <select x-model=\"color\">\n            <option value=\"\" disabled>Select A Color</option>\n            <option>Red</option>\n            <option>Orange</option>\n            <option>Yellow</option>\n        </select>\n\n        <div class=\"pt-4\">Color: <span x-text=\"color\"></span></div>\n    </div>\n</div>\n<!-- END_VERBATIM -->\n\n<a name=\"multiple-select\"></a>\n### Multiple select\n\n```alpine\n<select x-model=\"color\" multiple>\n    <option>Red</option>\n    <option>Orange</option>\n    <option>Yellow</option>\n</select>\n\nColors: <span x-text=\"color\"></span>\n```\n\n<!-- START_VERBATIM -->\n<div class=\"demo\">\n    <div x-data=\"{ color: '' }\">\n        <select x-model=\"color\" multiple>\n            <option>Red</option>\n            <option>Orange</option>\n            <option>Yellow</option>\n        </select>\n\n        <div class=\"pt-4\">Color: <span x-text=\"color\"></span></div>\n    </div>\n</div>\n<!-- END_VERBATIM -->\n\n<a name=\"dynamically-populated-select-options\"></a>\n### Dynamically populated Select Options\n\n```alpine\n<select x-model=\"color\">\n    <template x-for=\"color in ['Red', 'Orange', 'Yellow']\">\n        <option x-text=\"color\"></option>\n    </template>\n</select>\n\nColor: <span x-text=\"color\"></span>\n```\n\n<!-- START_VERBATIM -->\n<div class=\"demo\">\n    <div x-data=\"{ color: '' }\">\n        <select x-model=\"color\">\n            <template x-for=\"color in ['Red', 'Orange', 'Yellow']\">\n                <option x-text=\"color\"></option>\n            </template>\n        </select>\n\n        <div class=\"pt-4\">Color: <span x-text=\"color\"></span></div>\n    </div>\n</div>\n<!-- END_VERBATIM -->\n\n<a name=\"range-inputs\"></a>\n## Range inputs\n\n```alpine\n<input type=\"range\" x-model=\"range\" min=\"0\" max=\"1\" step=\"0.1\">\n\n<span x-text=\"range\"></span>\n```\n\n<!-- START_VERBATIM -->\n<div class=\"demo\">\n    <div x-data=\"{ range: 0.5 }\">\n        <input type=\"range\" x-model=\"range\" min=\"0\" max=\"1\" step=\"0.1\">\n\n        <div class=\"pt-4\" x-text=\"range\"></div>\n    </div>\n</div>\n<!-- END_VERBATIM -->\n\n\n<a name=\"modifiers\"></a>\n## Modifiers\n\n<a name=\"lazy\"></a>\n### `.lazy`\n\nOn text inputs, by default, `x-model` updates the property on every keystroke. By adding the `.lazy` modifier, you can force an `x-model` input to only update the property when user focuses away from the input element.\n\nThis is handy for things like real-time form-validation where you might not want to show an input validation error until the user \"tabs\" away from a field.\n\n```alpine\n<input type=\"text\" x-model.lazy=\"username\">\n<span x-show=\"username.length > 20\">The username is too long.</span>\n```\n\n<a name=\"change\"></a>\n### `.change`\n\n`.change` syncs the data only when the input loses focus and its value has changed (the native `change` event). This is functionally equivalent to `.lazy`.\n\n```alpine\n<input type=\"text\" x-model.change=\"username\">\n```\n\n<a name=\"blur\"></a>\n### `.blur`\n\n`.blur` syncs the data when the input loses focus, regardless of whether the value has changed.\n\n```alpine\n<input type=\"text\" x-model.blur=\"email\">\n```\n\n<a name=\"enter\"></a>\n### `.enter`\n\n`.enter` syncs the data when the user presses the Enter key. This is useful for search fields where you want to trigger an action only when the user explicitly submits.\n\n```alpine\n<input type=\"text\" x-model.enter=\"search\">\n```\n\n> Note: `.enter` does not prevent the default behavior. If the input is inside a form, the form will still submit.\n\n<a name=\"combining-event-modifiers\"></a>\n### Combining Event Modifiers\n\nThe `.change`, `.blur`, and `.enter` modifiers can be combined to sync on multiple events. This is useful when you want to give users flexibility in how they submit data.\n\n```alpine\n<!-- Sync on blur OR enter -->\n<input type=\"text\" x-model.blur.enter=\"search\" placeholder=\"Press Enter or click away\">\n\n<!-- Sync on change, blur, OR enter -->\n<input type=\"text\" x-model.change.blur.enter=\"message\">\n```\n\n<!-- START_VERBATIM -->\n<div class=\"demo\">\n    <div x-data=\"{ search: '' }\">\n        <input type=\"text\" x-model.blur.enter=\"search\" placeholder=\"Press Enter or click away\">\n\n        <div class=\"pt-4\">Search: <span x-text=\"search\"></span></div>\n    </div>\n</div>\n<!-- END_VERBATIM -->\n\n<a name=\"number\"></a>\n### `.number`\n\nBy default, any data stored in a property via `x-model` is stored as a string. To force Alpine to store the value as a JavaScript number, add the `.number` modifier.\n\n```alpine\n<input type=\"text\" x-model.number=\"age\">\n<span x-text=\"typeof age\"></span>\n```\n\n<a name=\"boolean\"></a>\n### `.boolean`\n\nBy default, any data stored in a property via `x-model` is stored as a string. To force Alpine to store the value as a JavaScript boolean, add the `.boolean` modifier. Both integers (1/0) and strings (true/false) are valid boolean values.\n\n```alpine\n<select x-model.boolean=\"isActive\">\n    <option value=\"true\">Yes</option>\n    <option value=\"false\">No</option>\n</select>\n<span x-text=\"typeof isActive\"></span>\n```\n\n<a name=\"debounce\"></a>\n### `.debounce`\n\nBy adding `.debounce` to `x-model`, you can easily debounce the updating of bound input.\n\nThis is useful for things like real-time search inputs that fetch new data from the server every time the search property changes.\n\n```alpine\n<input type=\"text\" x-model.debounce=\"search\">\n```\n\nThe default debounce time is 250 milliseconds, you can easily customize this by adding a time modifier like so.\n\n```alpine\n<input type=\"text\" x-model.debounce.500ms=\"search\">\n```\n\n<a name=\"throttle\"></a>\n### `.throttle`\n\nSimilar to `.debounce` you can limit the property update triggered by `x-model` to only updating on a specified interval.\n\n<input type=\"text\" x-model.throttle=\"search\">\n\nThe default throttle interval is 250 milliseconds, you can easily customize this by adding a time modifier like so.\n\n```alpine\n<input type=\"text\" x-model.throttle.500ms=\"search\">\n```\n\n<a name=\"fill\"></a>\n### `.fill`\n\nBy default, if an input has a value attribute, it is ignored by Alpine and instead, the value of the input is set to the value of the property bound using `x-model`.\n\nBut if a bound property is empty, then you can use an input's value attribute to populate the property by adding the `.fill` modifier.\n\n<div x-data=\"{ message: null }\">\n  <input type=\"text\" x-model.fill=\"message\" value=\"This is the default message.\">\n</div>\n\n<a name=\"programmatic access\"></a>\n## Programmatic access\n\nAlpine exposes under-the-hood utilities for getting and setting properties bound with `x-model`. This is useful for complex Alpine utilities that may want to override the default x-model behavior, or instances where you want to allow `x-model` on a non-input element.\n\nYou can access these utilities through a property called `_x_model` on the `x-model`ed element. `_x_model` has two methods to get and set the bound property:\n\n* `el._x_model.get()` (returns the value of the bound property)\n* `el._x_model.set()` (sets the value of the bound property)\n\n```alpine\n<div x-data=\"{ username: 'calebporzio' }\">\n    <div x-ref=\"div\" x-model=\"username\"></div>\n\n    <button @click=\"$refs.div._x_model.set('phantomatrix')\">\n        Change username to: 'phantomatrix'\n    </button>\n\n    <span x-text=\"$refs.div._x_model.get()\"></span>\n</div>\n```\n\n<!-- START_VERBATIM -->\n<div class=\"demo\">\n    <div x-data=\"{ username: 'calebporzio' }\">\n        <div x-ref=\"div\" x-model=\"username\"></div>\n\n        <button @click=\"$refs.div._x_model.set('phantomatrix')\">\n            Change username to: 'phantomatrix'\n        </button>\n\n        <span x-text=\"$refs.div._x_model.get()\"></span>\n    </div>\n</div>\n<!-- END_VERBATIM -->\n","packages/docs/src/en/directives/modelable.md":"---\norder: 7\ntitle: modelable\n---\n\n# x-modelable\n\n`x-modelable` allows you to expose Alpine state as the target of the `x-model` directive.\n\nHere's a simple example of using `x-modelable` to expose a variable for binding with `x-model`.\n\n```alpine\n<div x-data=\"{ number: 5 }\">\n    <div x-data=\"{ count: 0 }\" x-modelable=\"count\" x-model=\"number\">\n        <button @click=\"count++\">Increment</button>\n    </div>\n\n    Number: <span x-text=\"number\"></span>\n</div>\n```\n\n<!-- START_VERBATIM -->\n<div class=\"demo\">\n    <div x-data=\"{ number: 5 }\">\n        <div x-data=\"{ count: 0 }\" x-modelable=\"count\" x-model=\"number\">\n            <button @click=\"count++\">Increment</button>\n        </div>\n\n        Number: <span x-text=\"number\"></span>\n    </div>\n</div>\n<!-- END_VERBATIM -->\n\nAs you can see the outer scope property \"number\" is now bound to the inner scope property \"count\".\n\nTypically this feature would be used in conjunction with a backend templating framework like Laravel Blade. It's useful for abstracting away Alpine components into backend templates and exposing state to the outside through `x-model` as if it were a native input.\n\n## Supported values\n\n`x-modelable` keeps its inner and outer state independent by cloning values as JSON. It is therefore intended for JSON-compatible state such as strings, numbers, booleans, `null`, arrays, and plain objects containing those values.\n\nBrowser objects and other state that cannot be represented as JSON won't cross this boundary intact. For example, a `File` loses properties such as its name, size, and type. The same limitation applies to values such as `FileList`, `Map`, `Set`, `Date`, class instances, and DOM nodes.\n\nFor a custom input that produces one of these values, omit `x-modelable` and [dispatch an `input` event](/magics/dispatch#dispatching-to-x-model) instead. `x-model` reads the value directly from the event without cloning it:\n\n```alpine\n<div x-data=\"{ files: [] }\">\n    <div x-model=\"files\">\n        <input\n            type=\"file\"\n            multiple\n            @change=\"$dispatch('input', Array.from($event.target.files))\"\n        >\n    </div>\n\n    <template x-for=\"file in files\" :key=\"file.name\">\n        <p x-text=\"file.name\"></p>\n    </template>\n</div>\n```\n","packages/docs/src/en/directives/on.md":"---\norder: 5\ntitle: on\n---\n\n# x-on\n\n`x-on` allows you to easily run code on dispatched DOM events.\n\nHere's an example of simple button that shows an alert when clicked.\n\n```alpine\n<button x-on:click=\"alert('Hello World!')\">Say Hi</button>\n```\n\n> `x-on` can only listen for events with lower case names, as HTML attributes are case-insensitive. Writing `x-on:CLICK` will listen for an event named `click`. If you need to listen for a custom event with a camelCase name, you can use the [`.camel` helper](#camel) to work around this limitation. Alternatively, you can use [`x-bind`](/directives/bind#bind-directives) to attach an `x-on` directive to an element in javascript code (where case will be preserved).\n\n<a name=\"shorthand-syntax\"></a>\n## Shorthand syntax\n\nIf `x-on:` is too verbose for your tastes, you can use the shorthand syntax: `@`.\n\nHere's the same component as above, but using the shorthand syntax instead:\n\n```alpine\n<button @click=\"alert('Hello World!')\">Say Hi</button>\n```\n\n> Despite not being included in the above snippet, `x-on` cannot be used if no parent element has `x-data` defined. [→ Read more about `x-data`](/directives/data)\n\n<a name=\"the-event-object\"></a>\n## The event object\n\nIf you wish to access the native JavaScript event object from your expression, you can use Alpine's magic `$event` property.\n\n```alpine\n<button @click=\"alert($event.target.getAttribute('message'))\" message=\"Hello World\">Say Hi</button>\n```\n\nIn addition, Alpine also passes the event object to any methods referenced without trailing parenthesis. For example:\n\n```alpine\n<button @click=\"handleClick\">...</button>\n\n<script>\n    function handleClick(e) {\n        // Now you can access the event object (e) directly\n    }\n</script>\n```\n\n<a name=\"keyboard-events\"></a>\n## Keyboard events\n\nAlpine makes it easy to listen for `keydown` and `keyup` events on specific keys.\n\nHere's an example of listening for the `Enter` key inside an input element.\n\n```alpine\n<input type=\"text\" @keyup.enter=\"alert('Submitted!')\">\n```\n\nYou can also chain these key modifiers to achieve more complex listeners.\n\nHere's a listener that runs when the `Shift` key is held and `Enter` is pressed, but not when `Enter` is pressed alone.\n\n```alpine\n<input type=\"text\" @keyup.shift.enter=\"alert('Submitted!')\">\n```\n\nYou can directly use any valid key names exposed via [`KeyboardEvent.key`](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key/Key_Values) as modifiers by converting them to kebab-case.\n\n```alpine\n<input type=\"text\" @keyup.page-down=\"alert('Submitted!')\">\n```\n\nFor easy reference, here is a list of common keys you may want to listen for.\n\n| Modifier                       | Keyboard Key                       |\n| ------------------------------ | ---------------------------------- |\n| `.shift`                       | Shift                              |\n| `.enter`                       | Enter                              |\n| `.space`                       | Space                              |\n| `.ctrl`                        | Ctrl                               |\n| `.cmd`                         | Cmd                                |\n| `.meta`                        | Cmd on Mac, Windows key on Windows |\n| `.alt`                         | Alt                                |\n| `.up` `.down` `.left` `.right` | Up/Down/Left/Right arrows          |\n| `.escape`                      | Escape                             |\n| `.tab`                         | Tab                                |\n| `.caps-lock`                   | Caps Lock                          |\n| `.equal`                       | Equal, `=`                         |\n| `.period`                      | Period, `.`                        |\n| `.comma`                       | Comma, `,`                         |\n| `.slash`                       | Forward Slash, `/`                 |\n\n<a name=\"mouse-events\"></a>\n## Mouse events\n\nLike the above Keyboard Events, Alpine allows the use of some key modifiers for handling `click` events.\n\n| Modifier | Event Key |\n| -------- | --------- |\n| `.shift` | shiftKey  |\n| `.ctrl`  | ctrlKey   |\n| `.cmd`   | metaKey   |\n| `.meta`  | metaKey   |\n| `.alt`   | altKey    |\n\nThese work on `click`, `auxclick`, `context` and `dblclick` events, and even `mouseover`, `mousemove`, `mouseenter`, `mouseleave`, `mouseout`, `mouseup` and `mousedown`.\n\nHere's an example of a button that changes behaviour when the `Shift` key is held down.\n\n```alpine\n<button type=\"button\"\n    x-data=\"{ message: 'select' }\"\n    @click=\"message = 'selected'\"\n    @click.shift=\"message = 'added to selection'\"\n    @mousemove.shift=\"message = 'add to selection'\"\n    @mouseout=\"message = 'select'\"\n    x-text=\"message\"></button>\n```\n\n<!-- START_VERBATIM -->\n<div class=\"demo\">\n    <div x-data=\"{ message: '' }\">\n        <button type=\"button\"\n            x-data=\"{ message: 'select' }\"\n            @click=\"message = 'selected'\"\n            @click.shift=\"message = 'added to selection'\"\n            @mousemove.shift=\"message = 'add to selection'\"\n            @mouseout=\"message = 'select'\"\n            x-text=\"message\"></button>\n    </div>\n</div>\n<!-- END_VERBATIM -->\n\n> Note: Normal click events with some modifiers (like `ctrl`) will automatically become `contextmenu` events in most browsers. Similarly, `right-click` events will trigger a `contextmenu` event, but will also trigger an `auxclick` event if the `contextmenu` event is prevented.\n\n<a name=\"custom-events\"></a>\n## Custom events\n\nAlpine event listeners are a wrapper for native DOM event listeners. Therefore, they can listen for ANY DOM event, including custom events.\n\nHere's an example of a component that dispatches a custom DOM event and listens for it as well.\n\n```alpine\n<div x-data @foo=\"alert('Button Was Clicked!')\">\n    <button @click=\"$event.target.dispatchEvent(new CustomEvent('foo', { bubbles: true }))\">...</button>\n</div>\n```\n\nWhen the button is clicked, the `@foo` listener will be called.\n\nBecause the `.dispatchEvent` API is verbose, Alpine offers a `$dispatch` helper to simplify things.\n\nHere's the same component re-written with the `$dispatch` magic property.\n\n```alpine\n<div x-data @foo=\"alert('Button Was Clicked!')\">\n    <button @click=\"$dispatch('foo')\">...</button>\n</div>\n```\n\n[→ Read more about `$dispatch`](/magics/dispatch)\n\n<a name=\"modifiers\"></a>\n## Modifiers\n\nAlpine offers a number of directive modifiers to customize the behavior of your event listeners.\n\n<a name=\"prevent\"></a>\n### .prevent\n\n`.prevent` is the equivalent of calling `.preventDefault()` inside a listener on the browser event object.\n\n```alpine\n<form @submit.prevent=\"console.log('submitted')\" action=\"/foo\">\n    <button>Submit</button>\n</form>\n```\n\nIn the above example, with the `.prevent`, clicking the button will NOT submit the form to the `/foo` endpoint. Instead, Alpine's listener will handle it and \"prevent\" the event from being handled any further.\n\n<a name=\"stop\"></a>\n### .stop\n\nSimilar to `.prevent`, `.stop` is the equivalent of calling `.stopPropagation()` inside a listener on the browser event object.\n\n```alpine\n<div @click=\"console.log('I will not get logged')\">\n    <button @click.stop>Click Me</button>\n</div>\n```\n\nIn the above example, clicking the button WON'T log the message. This is because we are stopping the propagation of the event immediately and not allowing it to \"bubble\" up to the `<div>` with the `@click` listener on it.\n\n<a name=\"outside\"></a>\n### .outside\n\n`.outside` is a convenience helper for listening for a click outside of the element it is attached to. Here's a simple dropdown component example to demonstrate:\n\n```alpine\n<div x-data=\"{ open: false }\">\n    <button @click=\"open = ! open\">Toggle</button>\n\n    <div x-show=\"open\" @click.outside=\"open = false\">\n        Contents...\n    </div>\n</div>\n```\n\nIn the above example, after showing the dropdown contents by clicking the \"Toggle\" button, you can close the dropdown by clicking anywhere on the page outside the content.\n\nThis is because `.outside` is listening for clicks that DON'T originate from the element it's registered on.\n\n> It's worth noting that the `.outside` expression will only be evaluated when the element it's registered on is visible on the page. Otherwise, there would be nasty race conditions where clicking the \"Toggle\" button would also fire the `@click.outside` handler when it is not visible.\n\n<a name=\"window\"></a>\n### .window\n\nWhen the `.window` modifier is present, Alpine will register the event listener on the root `window` object on the page instead of the element itself.\n\n```alpine\n<div @keyup.escape.window=\"...\">...</div>\n```\n\nThe above snippet will listen for the \"escape\" key to be pressed ANYWHERE on the page.\n\nAdding `.window` to listeners is extremely useful for these sorts of cases where a small part of your markup is concerned with events that take place on the entire page.\n\n<a name=\"document\"></a>\n### .document\n\n`.document` works similarly to `.window` only it registers listeners on the `document` global, instead of the `window` global.\n\n<a name=\"once\"></a>\n### .once\n\nBy adding `.once` to a listener, you are ensuring that the handler is only called ONCE.\n\n```alpine\n<button @click.once=\"console.log('I will only log once')\">...</button>\n```\n\n<a name=\"debounce\"></a>\n### .debounce\n\nSometimes it is useful to \"debounce\" an event handler so that it only is called after a certain period of inactivity (250 milliseconds by default).\n\nFor example if you have a search field that fires network requests as the user types into it, adding a debounce will prevent the network requests from firing on every single keystroke.\n\n```alpine\n<input @input.debounce=\"fetchResults\">\n```\n\nNow, instead of calling `fetchResults` after every keystroke, `fetchResults` will only be called after 250 milliseconds of no keystrokes.\n\nIf you wish to lengthen or shorten the debounce time, you can do so by trailing a duration after the `.debounce` modifier like so:\n\n```alpine\n<input @input.debounce.500ms=\"fetchResults\">\n```\n\nNow, `fetchResults` will only be called after 500 milliseconds of inactivity.\n\n<a name=\"throttle\"></a>\n### .throttle\n\n`.throttle` is similar to `.debounce` except it will release a handler call every 250 milliseconds instead of deferring it indefinitely.\n\nThis is useful for cases where there may be repeated and prolonged event firing and using `.debounce` won't work because you want to still handle the event every so often.\n\nFor example:\n\n```alpine\n<div @scroll.window.throttle=\"handleScroll\">...</div>\n```\n\nThe above example is a great use case of throttling. Without `.throttle`, the `handleScroll` method would be fired hundreds of times as the user scrolls down a page. This can really slow down a site. By adding `.throttle`, we are ensuring that `handleScroll` only gets called every 250 milliseconds.\n\n> Fun Fact: This exact strategy is used on this very documentation site to update the currently highlighted section in the right sidebar.\n\nJust like with `.debounce`, you can add a custom duration to your throttled event:\n\n```alpine\n<div @scroll.window.throttle.750ms=\"handleScroll\">...</div>\n```\n\nNow, `handleScroll` will only be called every 750 milliseconds.\n\n<a name=\"self\"></a>\n### .self\n\nBy adding `.self` to an event listener, you are ensuring that the event originated on the element it is declared on, and not from a child element.\n\n```alpine\n<button @click.self=\"handleClick\">\n    Click Me\n\n    <img src=\"...\">\n</button>\n```\n\nIn the above example, we have an `<img>` tag inside the `<button>` tag. Normally, any click originating within the `<button>` element (like on `<img>` for example), would be picked up by a `@click` listener on the button.\n\nHowever, in this case, because we've added a `.self`, only clicking the button itself will call `handleClick`. Only clicks originating on the `<img>` element will not be handled.\n\n<a name=\"camel\"></a>\n### .camel\n\n```alpine\n<div @custom-event.camel=\"handleCustomEvent\">\n    ...\n</div>\n```\n\nSometimes you may want to listen for camelCased events such as `customEvent` in our example. Because camelCasing inside HTML attributes is not supported, adding the `.camel` modifier is necessary for Alpine to camelCase the event name internally.\n\nBy adding `.camel` in the above example, Alpine is now listening for `customEvent` instead of `custom-event`.\n\n<a name=\"dot\"></a>\n### .dot\n\n```alpine\n<div @custom-event.dot=\"handleCustomEvent\">\n    ...\n</div>\n```\n\nSimilar to the `.camelCase` modifier there may be situations where you want to listen for events that have dots in their name (like `custom.event`). Since dots within the event name are reserved by Alpine you need to write them with dashes and add the `.dot` modifier.\n\nIn the code example above `custom-event.dot` will correspond to the event name `custom.event`.\n\n<a name=\"passive\"></a>\n### .passive\n\nBrowsers optimize scrolling on pages to be fast and smooth even when JavaScript is being executed on the page. However, improperly implemented touch and wheel listeners can block this optimization and cause poor site performance.\n\nIf you are listening for touch events, it's important to add `.passive` to your listeners to not block scroll performance.\n\n```alpine\n<div @touchstart.passive=\"...\">...</div>\n```\n\n[→ Read more about passive listeners](https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener#improving_scrolling_performance_with_passive_listeners)\n\n<a name=\"passive-false\"></a>\n### .passive.false\n\nIn modern browsers, touch and wheel event listeners are passive by default. Pass `.passive.false` to make these events cancelable, so that you can call `preventDefault` on them.\n\n```alpine\n<div @touchmove.passive.false=\"$event.preventDefault()\">...</div>\n```\n\n### .capture\n\nAdd this modifier if you want to execute this listener in the event's capturing phase, e.g. before the event bubbles from the target element up the DOM.\n\n```alpine\n<div @click.capture=\"console.log('I will log first')\">\n    <button @click=\"console.log('I will log second')\"></button>\n</div>\n```\n\n[→ Read more about the capturing and bubbling phase of events](https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener#usecapture)\n","packages/docs/src/en/directives/ref.md":"---\norder: 11\ntitle: ref\n---\n\n# x-ref\n\n`x-ref` in combination with `$refs` is a useful utility for easily accessing DOM elements directly. It's most useful as a replacement for APIs like `getElementById` and `querySelector`.\n\n```alpine\n<button @click=\"$refs.text.remove()\">Remove Text</button>\n\n<span x-ref=\"text\">Hello 👋</span>\n```\n\n<!-- START_VERBATIM -->\n<div class=\"demo\">\n    <div x-data>\n        <button @click=\"$refs.text.remove()\">Remove Text</button>\n\n        <div class=\"pt-4\" x-ref=\"text\">Hello 👋</div>\n    </div>\n</div>\n<!-- END_VERBATIM -->\n\n> Despite not being included in the above snippet, `x-ref` cannot be used if no parent element has `x-data` defined. [→ Read more about `x-data`](/directives/data)\n","packages/docs/src/en/directives/show.md":"---\norder: 3\ntitle: show\n---\n\n# x-show\n\n`x-show` is one of the most useful and powerful directives in Alpine. It provides an expressive way to show and hide DOM elements.\n\nHere's an example of a simple dropdown component using `x-show`.\n\n```alpine\n<div x-data=\"{ open: false }\">\n    <button x-on:click=\"open = ! open\">Toggle Dropdown</button>\n\n    <div x-show=\"open\">\n        Dropdown Contents...\n    </div>\n</div>\n```\n\nWhen the \"Toggle Dropdown\" button is clicked, the dropdown will show and hide accordingly.\n\n> If the \"default\" state of an `x-show` on page load is \"false\", you may want to use `x-cloak` on the page to avoid \"page flicker\" (The effect that happens when the browser renders your content before Alpine is finished initializing and hiding it.) You can learn more about `x-cloak` in its documentation.\n\n<a name=\"with-transitions\"></a>\n## With transitions\n\nIf you want to apply smooth transitions to the `x-show` behavior, you can use it in conjunction with `x-transition`. You can learn more about that directive [here](/directives/transition), but here's a quick example of the same component as above, just with transitions applied.\n\n```alpine\n<div x-data=\"{ open: false }\">\n    <button x-on:click=\"open = ! open\">Toggle Dropdown</button>\n\n    <div x-show=\"open\" x-transition>\n        Dropdown Contents...\n    </div>\n</div>\n```\n\n<a name=\"using-the-important-modifier\"></a>\n## Using the important modifier\n\nSometimes you need to apply a little more force to actually hide an element. In cases where a CSS selector applies the `display` property with the `!important` flag, it will take precedence over the inline style set by Alpine.\n\nIn these cases you may use the `.important` modifier to set the inline style to `display: none !important`.\n\n```alpine\n<div x-data=\"{ open: false }\">\n    <button x-on:click=\"open = ! open\">Toggle Dropdown</button>\n\n    <div x-show.important=\"open\">\n        Dropdown Contents...\n    </div>\n</div>\n```\n","packages/docs/src/en/directives/teleport.md":"---\norder: 12\ntitle: teleport\ndescription: Send Alpine templates to other parts of the DOM\ngraph_image: https://alpinejs.dev/social_teleport.jpg\n---\n\n# x-teleport\n\nThe `x-teleport` directive allows you to transport part of your Alpine template to another part of the DOM on the page entirely.\n\nThis is useful for things like modals (especially nesting them), where it's helpful to break out of the z-index of the current Alpine component.\n\n<a name=\"x-teleport\"></a>\n## x-teleport\n\nBy attaching `x-teleport` to a `<template>` element, you are telling Alpine to \"append\" that element to the provided selector.\n\n> The `x-teleport` selector can be any string you would normally pass into something like `document.querySelector`. It will find the first element that matches, be it a tag name (`body`), class name (`.my-class`), ID (`#my-id`), or any other valid CSS selector.\n\n[→ Read more about `document.querySelector`](https://developer.mozilla.org/en-US/docs/Web/API/Document/querySelector)\n\nHere's a contrived modal example:\n\n```alpine\n<body>\n    <div x-data=\"{ open: false }\">\n        <button @click=\"open = ! open\">Toggle Modal</button>\n\n        <template x-teleport=\"body\">\n            <div x-show=\"open\">\n                Modal contents...\n            </div>\n        </template>\n    </div>\n\n    <div>Some other content placed AFTER the modal markup.</div>\n\n    ...\n\n</body>\n```\n\n<!-- START_VERBATIM -->\n<div class=\"demo\" x-ref=\"root\" id=\"modal2\">\n    <div x-data=\"{ open: false }\">\n        <button @click=\"open = ! open\">Toggle Modal</button>\n\n        <template x-teleport=\"#modal2\">\n            <div x-show=\"open\">\n                Modal contents...\n            </div>\n        </template>\n\n    </div>\n\n    <div class=\"py-4\">Some other content placed AFTER the modal markup.</div>\n</div>\n<!-- END_VERBATIM -->\n\nNotice how when toggling the modal, the actual modal contents show up AFTER the \"Some other content...\" element? This is because when Alpine is initializing, it sees `x-teleport=\"body\"` and appends and initializes that element to the provided element selector.\n\n<a name=\"forwarding-events\"></a>\n## Forwarding events\n\nAlpine tries its best to make the experience of teleporting seamless. Anything you would normally do in a template, you should be able to do inside an `x-teleport` template. Teleported content can access the normal Alpine scope of the component as well as other features like `$refs`, `$root`, etc...\n\nHowever, native DOM events have no concept of teleportation, so if, for example, you trigger a \"click\" event from inside a teleported element, that event will bubble up the DOM tree as it normally would.\n\nTo make this experience more seamless, you can \"forward\" events by simply registering event listeners on the `<template x-teleport...>` element itself like so:\n\n```alpine\n<div x-data=\"{ open: false }\">\n    <button @click=\"open = ! open\">Toggle Modal</button>\n\n    <template x-teleport=\"body\" @click=\"open = false\">\n        <div x-show=\"open\">\n            Modal contents...\n            (click to close)\n        </div>\n    </template>\n</div>\n```\n\n<!-- START_VERBATIM -->\n<div class=\"demo\" x-ref=\"root\" id=\"modal3\">\n    <div x-data=\"{ open: false }\">\n        <button @click=\"open = ! open\">Toggle Modal</button>\n\n        <template x-teleport=\"#modal3\" @click=\"open = false\">\n            <div x-show=\"open\">\n                Modal contents...\n                <div>(click to close)</div>\n            </div>\n        </template>\n    </div>\n</div>\n<!-- END_VERBATIM -->\n\nNotice how we are now able to listen for events dispatched from within the teleported element from outside the `<template>` element itself?\n\nAlpine does this by looking for event listeners registered on `<template x-teleport...>` and stops those events from propagating past the live, teleported, DOM element. Then, it creates a copy of that event and re-dispatches it from `<template x-teleport...>`.\n\n<a name=\"nesting\"></a>\n## Nesting\n\nTeleporting is especially helpful if you are trying to nest one modal within another. Alpine makes it simple to do so:\n\n```alpine\n<div x-data=\"{ open: false }\">\n    <button @click=\"open = ! open\">Toggle Modal</button>\n\n    <template x-teleport=\"body\">\n        <div x-show=\"open\">\n            Modal contents...\n\n            <div x-data=\"{ open: false }\">\n                <button @click=\"open = ! open\">Toggle Nested Modal</button>\n\n                <template x-teleport=\"body\">\n                    <div x-show=\"open\">\n                        Nested modal contents...\n                    </div>\n                </template>\n            </div>\n        </div>\n    </template>\n</div>\n```\n\n<!-- START_VERBATIM -->\n<div class=\"demo\" x-ref=\"root\" id=\"modal4\">\n    <div x-data=\"{ open: false }\">\n        <button @click=\"open = ! open\">Toggle Modal</button>\n\n        <template x-teleport=\"#modal4\">\n            <div x-show=\"open\">\n                <div class=\"py-4\">Modal contents...</div>\n\n                <div x-data=\"{ open: false }\">\n                    <button @click=\"open = ! open\">Toggle Nested Modal</button>\n\n                    <template x-teleport=\"#modal4\">\n                        <div class=\"pt-4\" x-show=\"open\">\n                            Nested modal contents...\n                        </div>\n                    </template>\n                </div>\n            </div>\n        </template>\n    </div>\n\n    <template x-teleport-target=\"modals3\"></template>\n</div>\n<!-- END_VERBATIM -->\n\nAfter toggling \"on\" both modals, they are authored as children, but will be rendered as sibling elements on the page, not within one another.\n","packages/docs/src/en/directives/text.md":"---\norder: 6\ntitle: text\n---\n\n# x-text\n\n`x-text` sets the text content of an element to the result of a given expression.\n\nHere's a basic example of using `x-text` to display a user's username.\n\n```alpine\n<div x-data=\"{ username: 'calebporzio' }\">\n    Username: <strong x-text=\"username\"></strong>\n</div>\n```\n\n<!-- START_VERBATIM -->\n<div class=\"demo\">\n    <div x-data=\"{ username: 'calebporzio' }\">\n        Username: <strong x-text=\"username\"></strong>\n    </div>\n</div>\n<!-- END_VERBATIM -->\n\nNow the `<strong>` tag's inner text content will be set to \"calebporzio\".\n","packages/docs/src/en/directives/transition.md":"---\norder: 10\ntitle: transition\n---\n\n# x-transition\n\nAlpine provides a robust transitions utility out of the box. With a few `x-transition` directives, you can create smooth transitions between when an element is shown or hidden.\n\nThere are two primary ways to handle transitions in Alpine:\n\n* [The Transition Helper](#the-transition-helper)\n* [Applying CSS Classes](#applying-css-classes)\n\n<a name=\"the-transition-helper\"></a>\n## The transition helper\n\nThe simplest way to achieve a transition using Alpine is by adding `x-transition` to an element with `x-show` on it. For example:\n\n```alpine\n<div x-data=\"{ open: false }\">\n    <button @click=\"open = ! open\">Toggle</button>\n\n    <div x-show=\"open\" x-transition>\n        Hello 👋\n    </div>\n</div>\n```\n\n<!-- START_VERBATIM -->\n<div class=\"demo\">\n    <div x-data=\"{ open: false }\">\n        <button @click=\"open = ! open\">Toggle</button>\n\n        <div x-show=\"open\" x-transition>\n            Hello 👋\n        </div>\n    </div>\n</div>\n<!-- END_VERBATIM -->\n\nAs you can see, by default, `x-transition` applies pleasant transition defaults to fade and scale the revealing element.\n\nYou can override these defaults with modifiers attached to `x-transition`. Let's take a look at those.\n\n<a name=\"customizing-duration\"></a>\n### Customizing duration\n\nInitially, the duration is set to be 150 milliseconds when entering, and 75 milliseconds when leaving.\n\nYou can configure the duration you want for a transition with the `.duration` modifier:\n\n```alpine\n<div ... x-transition.duration.500ms>\n```\n\nThe above `<div>` will transition for 500 milliseconds when entering, and 500 milliseconds when leaving.\n\nIf you wish to customize the durations specifically for entering and leaving, you can do that like so:\n\n```alpine\n<div ...\n    x-transition:enter.duration.500ms\n    x-transition:leave.duration.400ms\n>\n```\n\n> Despite not being included in the above snippet, `x-transition` cannot be used if no parent element has `x-data` defined. [→ Read more about `x-data`](/directives/data)\n\n<a name=\"customizing-delay\"></a>\n### Customizing delay\n\nYou can delay a transition using the `.delay` modifier like so:\n\n```alpine\n<div ... x-transition.delay.50ms>\n```\n\nThe above example will delay the transition and in and out of the element by 50 milliseconds.\n\n<a name=\"customizing-opacity\"></a>\n### Customizing opacity\n\nBy default, Alpine's `x-transition` applies both a scale and opacity transition to achieve a \"fade\" effect.\n\nIf you wish to only apply the opacity transition (no scale), you can accomplish that like so:\n\n```alpine\n<div ... x-transition.opacity>\n```\n\n<a name=\"customizing-scale\"></a>\n### Customizing scale\n\nSimilar to the `.opacity` modifier, you can configure `x-transition` to ONLY scale (and not transition opacity as well) like so:\n\n```alpine\n<div ... x-transition.scale>\n```\n\nThe `.scale` modifier also offers the ability to configure its scale values AND its origin values:\n\n```alpine\n<div ... x-transition.scale.80>\n```\n\nThe above snippet will scale the element up and down by 80%.\n\nAgain, you may customize these values separately for enter and leaving transitions like so:\n\n```alpine\n<div ...\n    x-transition:enter.scale.80\n    x-transition:leave.scale.90\n>\n```\n\nTo customize the origin of the scale transition, you can use the `.origin` modifier:\n\n```alpine\n<div ... x-transition.scale.origin.top>\n```\n\nNow the scale will be applied using the top of the element as the origin, instead of the center by default.\n\nLike you may have guessed, the possible values for this customization are: `top`, `bottom`, `left`, and `right`.\n\nIf you wish, you can also combine two origin values. For example, if you want the origin of the scale to be \"top right\", you can use: `.origin.top.right` as the modifier.\n\n\n<a name=\"applying-css-classes\"></a>\n## Applying CSS classes\n\nFor direct control over exactly what goes into your transitions, you can apply CSS classes at different stages of the transition.\n\n> The following examples use [TailwindCSS](https://tailwindcss.com/docs/transition-property) utility classes.\n\n```alpine\n<div x-data=\"{ open: false }\">\n    <button @click=\"open = ! open\">Toggle</button>\n\n    <div\n        x-show=\"open\"\n        x-transition:enter=\"transition ease-out duration-300\"\n        x-transition:enter-start=\"opacity-0 scale-90\"\n        x-transition:enter-end=\"opacity-100 scale-100\"\n        x-transition:leave=\"transition ease-in duration-300\"\n        x-transition:leave-start=\"opacity-100 scale-100\"\n        x-transition:leave-end=\"opacity-0 scale-90\"\n    >Hello 👋</div>\n</div>\n```\n\n<!-- START_VERBATIM -->\n<div class=\"demo\">\n    <div x-data=\"{ open: false }\">\n    <button @click=\"open = ! open\">Toggle</button>\n\n    <div\n        x-show=\"open\"\n        x-transition:enter=\"transition ease-out duration-300\"\n        x-transition:enter-start=\"opacity-0 transform scale-90\"\n        x-transition:enter-end=\"opacity-100 transform scale-100\"\n        x-transition:leave=\"transition ease-in duration-300\"\n        x-transition:leave-start=\"opacity-100 transform scale-100\"\n        x-transition:leave-end=\"opacity-0 transform scale-90\"\n    >Hello 👋</div>\n</div>\n</div>\n<!-- END_VERBATIM -->\n\n| Directive      | Description |\n| ---            | --- |\n| `:enter`       | Applied during the entire entering phase. |\n| `:enter-start` | Added before element is inserted, removed one frame after element is inserted. |\n| `:enter-end`   | Added one frame after element is inserted (at the same time `enter-start` is removed), removed when transition/animation finishes.\n| `:leave`       | Applied during the entire leaving phase. |\n| `:leave-start` | Added immediately when a leaving transition is triggered, removed after one frame. |\n| `:leave-end`   | Added one frame after a leaving transition is triggered (at the same time `leave-start` is removed), removed when the transition/animation finishes.\n","packages/docs/src/en/essentials.md":"---\norder: 3\ntitle: Essentials\ntype: sub-directory\n---\n","packages/docs/src/en/essentials/events.md":"---\norder: 4\ntitle: Events\n---\n\n# Events\n\nAlpine makes it simple to listen for browser events and react to them.\n\n<a name=\"listening-for-simple-events\"></a>\n## Listening for simple events\n\nBy using `x-on`, you can listen for browser events that are dispatched on or within an element.\n\nHere's a basic example of listening for a click on a button:\n\n```alpine\n<button x-on:click=\"console.log('clicked')\">...</button>\n```\n\nAs an alternative, you can use the event shorthand syntax if you prefer: `@`. Here's the same example as before, but using the shorthand syntax (which we'll be using from now on):\n\n```alpine\n<button @click=\"...\">...</button>\n```\n\nIn addition to `click`, you can listen for any browser event by name. For example: `@mouseenter`, `@keyup`, etc... are all valid syntax.\n\n<a name=\"listening-for-specific-keys\"></a>\n## Listening for specific keys\n\nLet's say you wanted to listen for the `enter` key to be pressed inside an `<input>` element. Alpine makes this easy by adding the `.enter` like so:\n\n```alpine\n<input @keyup.enter=\"...\">\n```\n\nYou can even combine key modifiers to listen for key combinations like pressing `enter` while holding `shift`:\n\n```alpine\n<input @keyup.shift.enter=\"...\">\n```\n\n<a name=\"preventing-default\"></a>\n## Preventing default\n\nWhen reacting to browser events, it is often necessary to \"prevent default\" (prevent the default behavior of the browser event).\n\nFor example, if you want to listen for a form submission but prevent the browser from submitting a form request, you can use `.prevent`:\n\n```alpine\n<form @submit.prevent=\"...\">...</form>\n```\n\nYou can also apply `.stop` to achieve the equivalent of `event.stopPropagation()`.\n\n<a name=\"accessing-the-event-object\"></a>\n## Accessing the event object\n\nSometimes you may want to access the native browser event object inside your own code. To make this easy, Alpine automatically injects an `$event` magic variable:\n\n```alpine\n<button @click=\"$event.target.remove()\">Remove Me</button>\n```\n\n<a name=\"dispatching-custom-events\"></a>\n## Dispatching custom events\n\nIn addition to listening for browser events, you can dispatch them as well. This is extremely useful for communicating with other Alpine components or triggering events in tools outside of Alpine itself.\n\nAlpine exposes a magic helper called `$dispatch` for this:\n\n```alpine\n<div @foo=\"console.log('foo was dispatched')\">\n    <button @click=\"$dispatch('foo')\"></button>\n</div>\n```\n\nAs you can see, when the button is clicked, Alpine will dispatch a browser event called \"foo\", and our `@foo` listener on the `<div>` will pick it up and react to it.\n\n<a name=\"listening-for-events-on-window\"></a>\n## Listening for events on window\n\nBecause of the nature of events in the browser, it is sometimes useful to listen to events on the top-level window object.\n\nThis allows you to communicate across components completely like the following example:\n\n\n```alpine\n<div x-data>\n    <button @click=\"$dispatch('foo')\"></button>\n</div>\n\n<div x-data @foo.window=\"console.log('foo was dispatched')\">...</div>\n```\n\nIn the above example, if we click the button in the first component, Alpine will dispatch the \"foo\" event. Because of the way events work in the browser, they \"bubble\" up through parent elements all the way to the top-level \"window\".\n\nNow, because in our second component we are listening for \"foo\" on the window (with `.window`), when the button is clicked, this listener will pick it up and log the \"foo was dispatched\" message.\n\n[→ Read more about x-on](/directives/on)\n","packages/docs/src/en/essentials/installation.md":"---\norder: 1\ntitle: Installation\n---\n\n# Installation\n\nThere are 2 ways to include Alpine into your project:\n\n* Including it from a `<script>` tag\n* Importing it as a module\n\nEither is perfectly valid. It all depends on the project's needs and the developer's taste.\n\n<a name=\"from-a-script-tag\"></a>\n## From a script tag\n\nThis is by far the simplest way to get started with Alpine. Include the following `<script>` tag in the head of your HTML page.\n\n```alpine\n<html>\n    <head>\n        ...\n\n        <script defer src=\"https://cdn.jsdelivr.net/npm/alpinejs@3.x.x/dist/cdn.min.js\"></script>\n    </head>\n    ...\n</html>\n```\n\n> Don't forget the \"defer\" attribute in the `<script>` tag.\n\nNotice the `@3.x.x` in the provided CDN link. This will pull the latest version of Alpine version 3. For stability in production, it's recommended that you hardcode the latest version in the CDN link.\n\n```alpine\n<script defer src=\"https://cdn.jsdelivr.net/npm/alpinejs@3.17.5/dist/cdn.min.js\"></script>\n```\n\nThat's it! Alpine is now available for use inside your page.\n\nNote that you will still need to define a component with `x-data` in order for any Alpine.js attributes to work. See <https://github.com/alpinejs/alpine/discussions/3805> for more information.\n\n<a name=\"as-a-module\"></a>\n## As a module\n\nIf you prefer the more robust approach, you can install Alpine via NPM and import it into a bundle.\n\nRun the following command to install it.\n\n```shell\nnpm install alpinejs\n```\n\nNow import Alpine into your bundle and initialize it like so:\n\n```js\nimport Alpine from 'alpinejs'\n\nwindow.Alpine = Alpine\n\nAlpine.start()\n```\n\n> The `window.Alpine = Alpine` bit is optional, but is nice to have for freedom and flexibility. Like when tinkering with Alpine from the devtools for example.\n\n> If you imported Alpine into a bundle, you have to make sure you are registering any extension code IN BETWEEN when you import the `Alpine` global object, and when you initialize Alpine by calling `Alpine.start()`.\n\n> Ensure that `Alpine.start()` is only called once per page. Calling it more than once will result in multiple \"instances\" of Alpine running at the same time.\n\n\n[→ Read more about extending Alpine](/advanced/extending)\n","packages/docs/src/en/essentials/lifecycle.md":"---\norder: 5\ntitle: Lifecycle\n---\n\n# Lifecycle\n\nAlpine has a handful of different techniques for hooking into different parts of its lifecycle. Let's go through the most useful ones to familiarize yourself with:\n\n<a name=\"element-initialization\"></a>\n## Element initialization\n\nAnother extremely useful lifecycle hook in Alpine is the `x-init` directive.\n\n`x-init` can be added to any element on a page and will execute any JavaScript you call inside it when Alpine begins initializing that element.\n\n```alpine\n<button x-init=\"console.log('Im initing')\">\n```\n\nIn addition to the directive, Alpine will automatically call any `init()` methods stored on a data object. For example:\n\n```js\nAlpine.data('dropdown', () => ({\n    init() {\n        // I get called before the element using this data initializes.\n    }\n}))\n```\n\n<a name=\"after-a-state-change\"></a>\n## After a state change\n\nAlpine allows you to execute code when a piece of data (state) changes. It offers two different APIs for such a task: `$watch` and `x-effect`.\n\n<a name=\"watch\"></a>\n### `$watch`\n\n```alpine\n<div x-data=\"{ open: false }\" x-init=\"$watch('open', value => console.log(value))\">\n```\n\nAs you can see above, `$watch` allows you to hook into data changes using a dot-notation key. When that piece of data changes, Alpine will call the passed callback and pass it the new value. along with the old value before the change.\n\n[→ Read more about $watch](/magics/watch)\n\n<a name=\"x-effect\"></a>\n### `x-effect`\n\n`x-effect` uses the same mechanism under the hood as `$watch` but has very different usage.\n\nInstead of specifying which data key you wish to watch, `x-effect` will call the provided code and intelligently look for any Alpine data used within it. Now when one of those pieces of data changes, the `x-effect` expression will be re-run.\n\nHere's the same bit of code from the `$watch` example rewritten using `x-effect`:\n\n```alpine\n<div x-data=\"{ open: false }\" x-effect=\"console.log(open)\">\n```\n\nNow, this expression will be called right away, and re-called every time `open` is updated.\n\nThe two main behavioral differences with this approach are:\n\n1. The provided code will be run right away AND when data changes (`$watch` is \"lazy\" -- won't run until the first data change)\n2. No knowledge of the previous value. (The callback provided to `$watch` receives both the new value AND the old one)\n\n[→ Read more about x-effect](/directives/effect)\n\n<a name=\"alpine-initialization\"></a>\n## Alpine initialization\n\n<a name=\"alpine-initializing\"></a>\n### `alpine:init`\n\nEnsuring a bit of code executes after Alpine is loaded, but BEFORE it initializes itself on the page is a necessary task.\n\nThis hook allows you to register custom data, directives, magics, etc. before Alpine does its thing on a page.\n\nYou can hook into this point in the lifecycle by listening for an event that Alpine dispatches called: `alpine:init`\n\n```js\ndocument.addEventListener('alpine:init', () => {\n    Alpine.data(...)\n})\n```\n\n<a name=\"alpine-initialized\"></a>\n### `alpine:initialized`\n\nAlpine also offers a hook that you can use to execute code AFTER it's done initializing called `alpine:initialized`:\n\n```js\ndocument.addEventListener('alpine:initialized', () => {\n    //\n})\n```\n","packages/docs/src/en/essentials/state.md":"---\norder: 2\ntitle: State\n---\n\n# State\n\nState (JavaScript data that Alpine watches for changes) is at the core of everything you do in Alpine. You can provide local data to a chunk of HTML, or make it globally available for use anywhere on a page using `x-data` or `Alpine.store()` respectively.\n\n<a name=\"local-state-x-data\"></a>\n## Local state\n\nAlpine allows you to declare an HTML block's state in a single `x-data` attribute without ever leaving your markup.\n\nHere's a basic example:\n\n```alpine\n<div x-data=\"{ open: false }\">\n    ...\n</div>\n```\n\nNow any other Alpine syntax on or within this element will be able to access `open`. And like you'd guess, when `open` changes for any reason, everything that depends on it will react automatically.\n\n[→ Read more about `x-data`](/directives/data)\n\n<a name=\"nesting-data\"></a>\n### Nesting data\n\nData is nestable in Alpine. For example, if you have two elements with Alpine data attached (one inside the other), you can access the parent's data from inside the child element.\n\n```alpine\n<div x-data=\"{ open: false }\">\n    <div x-data=\"{ label: 'Content:' }\">\n        <span x-text=\"label\"></span>\n        <span x-show=\"open\"></span>\n    </div>\n</div>\n```\n\nThis is similar to scoping in JavaScript itself (code within a function can access variables declared outside that function.)\n\nLike you may have guessed, if the child has a data property matching the name of a parent's property, the child property will take precedence.\n\n<a name=\"single-element-data\"></a>\n### Single-element data\n\nAlthough this may seem obvious to some, it's worth mentioning that Alpine data can be used within the same element. For example:\n\n```alpine\n<button x-data=\"{ label: 'Click Here' }\" x-text=\"label\"></button>\n```\n\n<a name=\"data-less-alpine\"></a>\n### Data-less Alpine\n\nSometimes you may want to use Alpine functionality, but don't need any reactive data. In these cases, you can opt out of passing an expression to `x-data` entirely. For example:\n\n```alpine\n<button x-data @click=\"alert('I\\'ve been clicked!')\">Click Me</button>\n```\n\n<a name=\"re-usable-data\"></a>\n### Re-usable data\n\nWhen using Alpine, you may find the need to re-use a chunk of data and/or its corresponding template.\n\nIf you are using a backend framework like Rails or Laravel, Alpine first recommends that you extract the entire block of HTML into a template partial or include.\n\nIf for some reason that isn't ideal for you or you're not in a back-end templating environment, Alpine allows you to globally register and re-use the data portion of a component using `Alpine.data(...)`.\n\n```js\nAlpine.data('dropdown', () => ({\n    open: false,\n\n    toggle() {\n        this.open = ! this.open\n    }\n}))\n```\n\nNow that you've registered the \"dropdown\" data, you can use it inside your markup in as many places as you like:\n\n```alpine\n<div x-data=\"dropdown\">\n    <button @click=\"toggle\">Expand</button>\n\n    <span x-show=\"open\">Content...</span>\n</div>\n\n<div x-data=\"dropdown\">\n    <button @click=\"toggle\">Expand</button>\n\n    <span x-show=\"open\">Some Other Content...</span>\n</div>\n```\n\n[→ Read more about using `Alpine.data()`](/globals/alpine-data)\n\n<a name=\"global-state\"></a>\n## Global state\n\nIf you wish to make some data available to every component on the page, you can do so using Alpine's \"global store\" feature.\n\nYou can register a store using `Alpine.store(...)`, and reference one with the magic `$store()` method.\n\nLet's look at a simple example. First we'll register the store globally:\n\n```js\nAlpine.store('tabs', {\n    current: 'first',\n\n    items: ['first', 'second', 'third'],\n})\n```\n\nNow we can access or modify its data from anywhere on our page:\n\n```alpine\n<div x-data>\n    <template x-for=\"tab in $store.tabs.items\">\n        ...\n    </template>\n</div>\n\n<div x-data>\n    <button @click=\"$store.tabs.current = 'first'\">First Tab</button>\n    <button @click=\"$store.tabs.current = 'second'\">Second Tab</button>\n    <button @click=\"$store.tabs.current = 'third'\">Third Tab</button>\n</div>\n```\n\n[→ Read more about `Alpine.store()`](/globals/alpine-store)\n","packages/docs/src/en/essentials/templating.md":"---\norder: 3\ntitle: Templating\n---\n\n# Templating\n\nAlpine offers a handful of useful directives for manipulating the DOM on a web page.\n\nLet's cover a few of the basic templating directives here, but be sure to look through the available directives in the sidebar for an exhaustive list.\n\n<a name=\"text-content\"></a>\n## Text content\n\nAlpine makes it easy to control the text content of an element with the `x-text` directive.\n\n```alpine\n<div x-data=\"{ title: 'Start Here' }\">\n    <h1 x-text=\"title\"></h1>\n</div>\n```\n\n<!-- START_VERBATIM -->\n<div x-data=\"{ title: 'Start Here' }\" class=\"demo\">\n    <strong x-text=\"title\"></strong>\n</div>\n<!-- END_VERBATIM -->\n\nNow, Alpine will set the text content of the `<h1>` with the value of `title` (\"Start Here\"). When `title` changes, so will the contents of `<h1>`.\n\nLike all directives in Alpine, you can use any JavaScript expression you like. For example:\n\n```alpine\n<span x-text=\"1 + 2\"></span>\n```\n\n<!-- START_VERBATIM -->\n<div class=\"demo\" x-data>\n    <span x-text=\"1 + 2\"></span>\n</div>\n<!-- END_VERBATIM -->\n\nThe `<span>` will now contain the sum of \"1\" and \"2\".\n\n[→ Read more about `x-text`](/directives/text)\n\n<a name=\"toggling-elements\"></a>\n## Toggling elements\n\nToggling elements is a common need in web pages and applications. Dropdowns, modals, dialogues, \"show-more\"s, etc... are all good examples.\n\nAlpine offers the `x-show` and `x-if` directives for toggling elements on a page.\n\n<a name=\"x-show\"></a>\n### `x-show`\n\nHere's a simple toggle component using `x-show`.\n\n```alpine\n<div x-data=\"{ open: false }\">\n    <button @click=\"open = ! open\">Expand</button>\n\n    <div x-show=\"open\">\n        Content...\n    </div>\n</div>\n```\n\n<!-- START_VERBATIM -->\n<div x-data=\"{ open: false }\" class=\"demo\">\n    <button @click=\"open = ! open\" :aria-pressed=\"open\">Expand</button>\n\n    <div x-show=\"open\">\n        Content...\n    </div>\n</div>\n<!-- END_VERBATIM -->\n\nNow the entire `<div>` containing the contents will be shown and hidden based on the value of `open`.\n\nUnder the hood, Alpine adds the CSS property `display: none;` to the element when it should be hidden.\n\n[→ Read more about `x-show`](/directives/show)\n\nThis works well for most cases, but sometimes you may want to completely add and remove the element from the DOM entirely. This is what `x-if` is for.\n\n<a name=\"x-if\"></a>\n### `x-if`\n\nHere is the same toggle from before, but this time using `x-if` instead of `x-show`.\n\n```alpine\n<div x-data=\"{ open: false }\">\n    <button @click=\"open = ! open\">Expand</button>\n\n    <template x-if=\"open\">\n        <div>\n            Content...\n        </div>\n    </template>\n</div>\n```\n\n<!-- START_VERBATIM -->\n<div x-data=\"{ open: false }\" class=\"demo\">\n    <button @click=\"open = ! open\" :aria-pressed=\"open\">Expand</button>\n\n    <template x-if=\"open\">\n        <div>\n            Content...\n        </div>\n    </template>\n</div>\n<!-- END_VERBATIM -->\n\nNotice that `x-if` must be declared on a `<template>` tag. This is so that Alpine can leverage the existing browser behavior of the `<template>` element and use it as the source of the target `<div>` to be added and removed from the page.\n\nWhen `open` is true, Alpine will append the `<div>` to the `<template>` tag, and remove it when `open` is false.\n\n[→ Read more about `x-if`](/directives/if)\n\n<a name=\"toggling-with-transitions\"></a>\n## Toggling with transitions\n\nAlpine makes it simple to smoothly transition between \"shown\" and \"hidden\" states using the `x-transition` directive.\n\n> `x-transition` only works with `x-show`, not with `x-if`.\n\nHere is, again, the simple toggle example, but this time with transitions applied:\n\n```alpine\n<div x-data=\"{ open: false }\">\n    <button @click=\"open = ! open\">Expands</button>\n\n    <div x-show=\"open\" x-transition>\n        Content...\n    </div>\n</div>\n```\n\n<!-- START_VERBATIM -->\n<div x-data=\"{ open: false }\" class=\"demo\">\n    <button @click=\"open = ! open\">Expands</button>\n\n    <div class=\"flex\">\n        <div x-show=\"open\" x-transition style=\"will-change: transform;\">\n            Content...\n        </div>\n    </div>\n</div>\n<!-- END_VERBATIM -->\n\nLet's zoom in on the portion of the template dealing with transitions:\n\n```alpine\n<div x-show=\"open\" x-transition>\n```\n\n`x-transition` by itself will apply sensible default transitions (fade and scale) to the toggle.\n\nThere are two ways to customize these transitions:\n\n* Transition helpers\n* Transition CSS classes.\n\nLet's take a look at each of these approaches:\n\n<a name=\"transition-helpers\"></a>\n### Transition helpers\n\nLet's say you wanted to make the duration of the transition longer, you can manually specify that using the `.duration` modifier like so:\n\n```alpine\n<div x-show=\"open\" x-transition.duration.500ms>\n```\n\n<!-- START_VERBATIM -->\n<div x-data=\"{ open: false }\" class=\"demo\">\n    <button @click=\"open = ! open\">Expands</button>\n\n    <div class=\"flex\">\n        <div x-show=\"open\" x-transition.duration.500ms style=\"will-change: transform;\">\n            Content...\n        </div>\n    </div>\n</div>\n<!-- END_VERBATIM -->\n\nNow the transition will last 500 milliseconds.\n\nIf you want to specify different values for in and out transitions, you can use `x-transition:enter` and `x-transition:leave`:\n\n```alpine\n<div\n    x-show=\"open\"\n    x-transition:enter.duration.500ms\n    x-transition:leave.duration.1000ms\n>\n```\n\n<!-- START_VERBATIM -->\n<div x-data=\"{ open: false }\" class=\"demo\">\n    <button @click=\"open = ! open\">Expands</button>\n\n    <div class=\"flex\">\n        <div x-show=\"open\" x-transition:enter.duration.500ms x-transition:leave.duration.1000ms style=\"will-change: transform;\">\n            Content...\n        </div>\n    </div>\n</div>\n<!-- END_VERBATIM -->\n\nAdditionally, you can add either `.opacity` or `.scale` to only transition that property. For example:\n\n```alpine\n<div x-show=\"open\" x-transition.opacity>\n```\n\n<!-- START_VERBATIM -->\n<div x-data=\"{ open: false }\" class=\"demo\">\n    <button @click=\"open = ! open\">Expands</button>\n\n    <div class=\"flex\">\n        <div x-show=\"open\" x-transition:enter.opacity.duration.500 x-transition:leave.opacity.duration.250>\n            Content...\n        </div>\n    </div>\n</div>\n<!-- END_VERBATIM -->\n\n[→ Read more about transition helpers](/directives/transition#the-transition-helper)\n\n<a name=\"transition-classes\"></a>\n### Transition classes\n\nIf you need more fine-grained control over the transitions in your application, you can apply specific CSS classes at specific phases of the transition using the following syntax (this example uses [Tailwind CSS](https://tailwindcss.com/)):\n\n```alpine\n<div\n    x-show=\"open\"\n    x-transition:enter=\"transition ease-out duration-300\"\n    x-transition:enter-start=\"opacity-0 transform scale-90\"\n    x-transition:enter-end=\"opacity-100 transform scale-100\"\n    x-transition:leave=\"transition ease-in duration-300\"\n    x-transition:leave-start=\"opacity-100 transform scale-100\"\n    x-transition:leave-end=\"opacity-0 transform scale-90\"\n>...</div>\n```\n\n<!-- START_VERBATIM -->\n<div x-data=\"{ open: false }\" class=\"demo\">\n    <button @click=\"open = ! open\">Expands</button>\n\n    <div class=\"flex\">\n        <div\n            x-show=\"open\"\n            x-transition:enter=\"transition ease-out duration-300\"\n            x-transition:enter-start=\"opacity-0 transform scale-90\"\n            x-transition:enter-end=\"opacity-100 transform scale-100\"\n            x-transition:leave=\"transition ease-in duration-300\"\n            x-transition:leave-start=\"opacity-100 transform scale-100\"\n            x-transition:leave-end=\"opacity-0 transform scale-90\"\n            style=\"will-change: transform\"\n        >\n            Content...\n        </div>\n    </div>\n</div>\n<!-- END_VERBATIM -->\n\n[→ Read more about transition classes](/directives/transition#applying-css-classes)\n\n<a name=\"binding-attributes\"></a>\n## Binding attributes\n\nYou can add HTML attributes like `class`, `style`, `disabled`, etc... to elements in Alpine using the `x-bind` directive.\n\nHere is an example of a dynamically bound `class` attribute:\n\n```alpine\n<button\n    x-data=\"{ red: false }\"\n    x-bind:class=\"red ? 'bg-red' : ''\"\n    @click=\"red = ! red\"\n>\n    Toggle Red\n</button>\n```\n\n<!-- START_VERBATIM -->\n<div class=\"demo\">\n    <button\n        x-data=\"{ red: false }\"\n        x-bind:style=\"red && 'background: red'\"\n        @click=\"red = ! red\"\n    >\n        Toggle Red\n    </button>\n</div>\n<!-- END_VERBATIM -->\n\n\nAs a shortcut, you can leave out the `x-bind` and use the shorthand `:` syntax directly:\n\n```alpine\n<button ... :class=\"red ? 'bg-red' : ''\">\n```\n\nToggling classes on and off based on data inside Alpine is a common need. Here's an example of toggling a class using Alpine's `class` binding object syntax: (Note: this syntax is only available for `class` attributes)\n\n```alpine\n<div x-data=\"{ open: true }\">\n    <span :class=\"{ 'hidden': ! open }\">...</span>\n</div>\n```\n\nNow the `hidden` class will be added to the element if `open` is false, and removed if `open` is true.\n\n<a name=\"looping-elements\"></a>\n## Looping elements\n\nAlpine allows for iterating parts of your template based on JavaScript data using the `x-for` directive. Here is a simple example:\n\n```alpine\n<div x-data=\"{ statuses: ['open', 'closed', 'archived'] }\">\n    <template x-for=\"status in statuses\">\n        <div x-text=\"status\"></div>\n    </template>\n</div>\n```\n\n<!-- START_VERBATIM -->\n<div x-data=\"{ statuses: ['open', 'closed', 'archived'] }\" class=\"demo\">\n    <template x-for=\"status in statuses\">\n        <div x-text=\"status\"></div>\n    </template>\n</div>\n<!-- END_VERBATIM -->\n\nSimilar to `x-if`, `x-for` must be applied to a `<template>` tag. Internally, Alpine will append the contents of `<template>` tag for every iteration in the loop.\n\nAs you can see the new `status` variable is available in the scope of the iterated templates.\n\n[→ Read more about `x-for`](/directives/for)\n\n<a name=\"inner-html\"></a>\n## Inner HTML\n\nAlpine makes it easy to control the HTML content of an element with the `x-html` directive.\n\n```alpine\n<div x-data=\"{ title: '<h1>Start Here</h1>' }\">\n    <div x-html=\"title\"></div>\n</div>\n```\n\n<!-- START_VERBATIM -->\n<div x-data=\"{ title: '<h1>Start Here</h1>' }\" class=\"demo\">\n    <div x-html=\"title\"></div>\n</div>\n<!-- END_VERBATIM -->\n\nNow, Alpine will set the text content of the `<div>` with the element `<h1>Start Here</h1>`. When `title` changes, so will the contents of `<h1>`.\n\n> ⚠️ Only use on trusted content and never on user-provided content. ⚠️\n> Dynamically rendering HTML from third parties can easily lead to XSS vulnerabilities.\n\n[→ Read more about `x-html`](/directives/html)\n","packages/docs/src/en/globals.md":"---\norder: 6\ntitle: Globals\nfont-type: mono\nprefix: Alpine.\ntype: sub-directory\n---\n","packages/docs/src/en/globals/alpine-bind.md":"---\norder: 3\ntitle: bind()\n---\n\n# Alpine.bind\n\n`Alpine.bind(...)` provides a way to re-use [`x-bind`](/directives/bind#bind-directives) objects within your application.\n\nHere's a simple example. Rather than binding attributes manually with Alpine:\n\n```alpine\n<button type=\"button\" @click=\"doSomething()\" :disabled=\"shouldDisable\"></button>\n```\n\nYou can bundle these attributes up into a reusable object and use `x-bind` to bind to that:\n\n```alpine\n<button x-bind=\"SomeButton\"></button>\n\n<script>\n    document.addEventListener('alpine:init', () => {\n        Alpine.bind('SomeButton', () => ({\n            type: 'button',\n\n            '@click'() {\n                this.doSomething()\n            },\n\n            ':disabled'() {\n                return this.shouldDisable\n            },\n        }))\n    })\n</script>\n```\n","packages/docs/src/en/globals/alpine-data.md":"---\norder: 1\ntitle: data()\n---\n\n# Alpine.data\n\n`Alpine.data(...)` provides a way to re-use `x-data` contexts within your application.\n\nHere's a contrived `dropdown` component for example:\n\n```alpine\n<div x-data=\"dropdown\">\n    <button @click=\"toggle\">...</button>\n\n    <div x-show=\"open\">...</div>\n</div>\n\n<script>\n    document.addEventListener('alpine:init', () => {\n        Alpine.data('dropdown', () => ({\n            open: false,\n\n            toggle() {\n                this.open = ! this.open\n            }\n        }))\n    })\n</script>\n```\n\nAs you can see we've extracted the properties and methods we would usually define directly inside `x-data` into a separate Alpine component object.\n\n<a name=\"registering-from-a-bundle\"></a>\n## Registering from a bundle\n\nIf you've chosen to use a build step for your Alpine code, you should register your components in the following way:\n\n```js\nimport Alpine from 'alpinejs'\nimport dropdown from './dropdown.js'\n\nAlpine.data('dropdown', dropdown)\n\nAlpine.start()\n```\n\nThis assumes you have a file called `dropdown.js` with the following contents:\n\n```js\nexport default () => ({\n    open: false,\n\n    toggle() {\n        this.open = ! this.open\n    }\n})\n```\n\n<a name=\"initial-parameters\"></a>\n## Initial parameters\n\nIn addition to referencing `Alpine.data` providers by their name plainly (like `x-data=\"dropdown\"`), you can also reference them as functions (`x-data=\"dropdown()\"`). By calling them as functions directly, you can pass in additional parameters to be used when creating the initial data object like so:\n\n```alpine\n<div x-data=\"dropdown(true)\">\n```\n```js\nAlpine.data('dropdown', (initialOpenState = false) => ({\n    open: initialOpenState\n}))\n```\n\nNow, you can re-use the `dropdown` object, but provide it with different parameters as you need to.\n\n<a name=\"init-functions\"></a>\n## Init functions\n\nIf your component contains an `init()` method, Alpine will automatically execute it before it renders the component. For example:\n\n```js\nAlpine.data('dropdown', () => ({\n    init() {\n        // This code will be executed before Alpine\n        // initializes the rest of the component.\n    }\n}))\n```\n\n<a name=\"destroy-functions\"></a>\n## Destroy functions\n\nIf your component contains a `destroy()` method, Alpine will automatically execute it before cleaning up the component.\n\nA primary example for this is when registering an event handler with another library or a browser API that isn't available through Alpine.\nSee the following example code on how to use the `destroy()` method to clean up such a handler.\n\n```js\nAlpine.data('timer', () => ({\n    timer: null,\n    counter: 0,\n    init() {\n      // Register an event handler that references the component instance\n      this.timer = setInterval(() => {\n        console.log('Increased counter to', ++this.counter);\n      }, 1000);\n    },\n    destroy() {\n        // Detach the handler, avoiding memory and side-effect leakage\n        clearInterval(this.timer);\n    },\n}))\n```\n\nAn example where a component is destroyed is when using one inside an `x-if`:\n\n```html\n<span x-data=\"{ enabled: false }\">\n    <button @click.prevent=\"enabled = !enabled\">Toggle</button>\n\n    <template x-if=\"enabled\">\n        <span x-data=\"timer\" x-text=\"counter\"></span>\n    </template>\n</span>\n```\n\n<a name=\"using-magic-properties\"></a>\n## Using magic properties\n\nIf you want to access magic methods or properties from a component object, you can do so using the `this` context:\n\n```js\nAlpine.data('dropdown', () => ({\n    open: false,\n\n    init() {\n        this.$watch('open', () => {...})\n    }\n}))\n```\n\n<a name=\"encapsulating-directives-with-x-bind\"></a>\n## Encapsulating directives with `x-bind`\n\nIf you wish to re-use more than just the data object of a component, you can encapsulate entire Alpine template directives using `x-bind`.\n\nThe following is an example of extracting the templating details of our previous dropdown component using `x-bind`:\n\n```alpine\n<div x-data=\"dropdown\">\n    <button x-bind=\"trigger\"></button>\n\n    <div x-bind=\"dialogue\"></div>\n</div>\n```\n\n```js\nAlpine.data('dropdown', () => ({\n    open: false,\n\n    trigger: {\n        ['@click']() {\n            this.open = ! this.open\n        },\n    },\n\n    dialogue: {\n        ['x-show']() {\n            return this.open\n        },\n    },\n}))\n```\n","packages/docs/src/en/globals/alpine-store.md":"---\norder: 2\ntitle: store()\n---\n\n# Alpine.store\n\nAlpine offers global state management through the `Alpine.store()` API.\n\n<a name=\"registering-a-store\"></a>\n## Registering A Store\n\nYou can either define an Alpine store inside of an `alpine:init` listener (in the case of including Alpine via a `<script>` tag), OR you can define it before manually calling `Alpine.start()` (in the case of importing Alpine into a build):\n\n**From a script tag:**\n```alpine\n<script>\n    document.addEventListener('alpine:init', () => {\n        Alpine.store('darkMode', {\n            on: false,\n\n            toggle() {\n                this.on = ! this.on\n            }\n        })\n    })\n</script>\n```\n\n**From a bundle:**\n```js\nimport Alpine from 'alpinejs'\n\nAlpine.store('darkMode', {\n    on: false,\n\n    toggle() {\n        this.on = ! this.on\n    }\n})\n\nAlpine.start()\n```\n\n<a name=\"accessing stores\"></a>\n## Accessing stores\n\nYou can access data from any store within Alpine expressions using the `$store` magic property:\n\n```alpine\n<div x-data :class=\"$store.darkMode.on && 'bg-black'\">...</div>\n```\n\nYou can also modify properties within the store and everything that depends on those properties will automatically react. For example:\n\n```alpine\n<button x-data @click=\"$store.darkMode.toggle()\">Toggle Dark Mode</button>\n```\n\nAdditionally, you can access a store externally using `Alpine.store()` by omitting the second parameter like so:\n\n```alpine\n<script>\n    Alpine.store('darkMode').toggle()\n</script>\n```\n\n<a name=\"initializing-stores\"></a>\n## Initializing stores\n\nIf you provide `init()` method in an Alpine store, it will be executed right after the store is registered. This is useful for initializing any state inside the store with sensible starting values.\n\n```alpine\n<script>\n    document.addEventListener('alpine:init', () => {\n        Alpine.store('darkMode', {\n            init() {\n                this.on = window.matchMedia('(prefers-color-scheme: dark)').matches\n            },\n\n            on: false,\n\n            toggle() {\n                this.on = ! this.on\n            }\n        })\n    })\n</script>\n```\n\nNotice the newly added `init()` method in the example above. With this addition, the `on` store variable will be set to the browser's color scheme preference before Alpine renders anything on the page.\n\n<a name=\"single-value-stores\"></a>\n## Single-value stores\n\nIf you don't need an entire object for a store, you can set and use any kind of data as a store.\n\nHere's the example from above but using it more simply as a boolean value:\n\n```alpine\n<button x-data @click=\"$store.darkMode = ! $store.darkMode\">Toggle Dark Mode</button>\n\n...\n\n<div x-data :class=\"$store.darkMode && 'bg-black'\">\n    ...\n</div>\n\n\n<script>\n    document.addEventListener('alpine:init', () => {\n        Alpine.store('darkMode', false)\n    })\n</script>\n```\n","packages/docs/src/en/magics.md":"---\norder: 5\ntitle: Magics\nprefix: $\nfont-type: mono\ntype: sub-directory\n---\n","packages/docs/src/en/magics/data.md":"---\norder: 8\nprefix: $\ntitle: data\n---\n\n# $data\n\n`$data` is a magic property that gives you access to the current Alpine data scope (generally provided by `x-data`).\n\nMost of the time, you can just access Alpine data within expressions directly. for example `x-data=\"{ message: 'Hello Caleb!' }\"` will allow you to do things like `x-text=\"message\"`.\n\nHowever, sometimes it is helpful to have an actual object that encapsulates all scope that you can pass around to other functions:\n\n```alpine\n<div x-data=\"{ greeting: 'Hello' }\">\n    <div x-data=\"{ name: 'Caleb' }\">\n        <button @click=\"sayHello($data)\">Say Hello</button>\n    </div>\n</div>\n\n<script>\n    function sayHello({ greeting, name }) {\n        alert(greeting + ' ' + name + '!')\n    }\n</script>\n```\n\n<!-- START_VERBATIM -->\n<div x-data=\"{ greeting: 'Hello' }\" class=\"demo\">\n    <div x-data=\"{ name: 'Caleb' }\">\n        <button @click=\"sayHello($data)\">Say Hello</button>\n    </div>\n</div>\n\n<script>\n    function sayHello({ greeting, name }) {\n        alert(greeting + ' ' + name + '!')\n    }\n</script>\n<!-- END_VERBATIM -->\n\nNow when the button is pressed, the browser will alert `Hello Caleb!` because it was passed a data object that contained all the Alpine scope of the expression that called it (`@click=\"...\"`).\n\nMost applications won't need this magic property, but it can be very helpful for deeper, more complicated Alpine utilities.\n","packages/docs/src/en/magics/dispatch.md":"---\norder: 5\ntitle: dispatch\n---\n\n# $dispatch\n\n`$dispatch` is a helpful shortcut for dispatching browser events.\n\n```alpine\n<div @notify=\"alert('Hello World!')\">\n    <button @click=\"$dispatch('notify')\">\n        Notify\n    </button>\n</div>\n```\n\n<!-- START_VERBATIM -->\n<div class=\"demo\">\n    <div x-data @notify=\"alert('Hello World!')\">\n        <button @click=\"$dispatch('notify')\">\n            Notify\n        </button>\n    </div>\n</div>\n<!-- END_VERBATIM -->\n\nYou can also pass data along with the dispatched event if you wish. This data will be accessible as the `.detail` property of the event:\n\n```alpine\n<div @notify=\"alert($event.detail.message)\">\n    <button @click=\"$dispatch('notify', { message: 'Hello World!' })\">\n        Notify\n    </button>\n</div>\n```\n\n<!-- START_VERBATIM -->\n<div class=\"demo\">\n    <div x-data @notify=\"alert($event.detail.message)\">\n        <button @click=\"$dispatch('notify', { message: 'Hello World!' })\">Notify</button>\n    </div>\n</div>\n<!-- END_VERBATIM -->\n\n\nUnder the hood, `$dispatch` is a wrapper for the more verbose API: `element.dispatchEvent(new CustomEvent(...))`\n\n**Note on event propagation**\n\nNotice that, because of [event bubbling](https://en.wikipedia.org/wiki/Event_bubbling), when you need to capture events dispatched from nodes that are under the same nesting hierarchy, you'll need to use the [`.window`](https://github.com/alpinejs/alpine#x-on) modifier:\n\n**Example:**\n\n```alpine\n<!-- 🚫 Won't work -->\n<div x-data>\n    <span @notify=\"...\"></span>\n    <button @click=\"$dispatch('notify')\">Notify</button>\n</div>\n\n<!-- ✅ Will work (because of .window) -->\n<div x-data>\n    <span @notify.window=\"...\"></span>\n    <button @click=\"$dispatch('notify')\">Notify</button>\n</div>\n```\n\n> The first example won't work because when `notify` is dispatched, it'll propagate to its common ancestor, the `div`, not its sibling, the `<span>`. The second example will work because the sibling is listening for `notify` at the `window` level, which the custom event will eventually bubble up to.\n\n<a name=\"dispatching-to-components\"></a>\n## Dispatching to other components\n\nYou can also take advantage of the previous technique to make your components talk to each other:\n\n**Example:**\n\n```alpine\n<div\n    x-data=\"{ title: 'Hello' }\"\n    @set-title.window=\"title = $event.detail\"\n>\n    <h1 x-text=\"title\"></h1>\n</div>\n\n<div x-data>\n    <button @click=\"$dispatch('set-title', 'Hello World!')\">Click me</button>\n</div>\n<!-- When clicked, the content of the h1 will set to \"Hello World!\". -->\n```\n\n<a name=\"dispatching-to-x-model\"></a>\n## Dispatching to x-model\n\nYou can also use `$dispatch()` to trigger data updates for `x-model` data bindings. For example:\n\n```alpine\n<div x-data=\"{ title: 'Hello' }\">\n    <span x-model=\"title\">\n        <button @click=\"$dispatch('input', 'Hello World!')\">Click me</button>\n        <!-- After the button is pressed, `x-model` will catch the bubbling \"input\" event, and update title. -->\n    </span>\n</div>\n```\n\nThis opens up the door for making custom input components whose value can be set via `x-model`.\n\n<a name=\"cancelable-events\"></a>\n## Cancelable events\n\nYou can use the returned value of `$dispatch` to check if the event was canceled or not. This is useful when you want to prevent the default behavior of an action.\n\n```alpine\n<div x-data x-on:open=\"$event.preventDefault()\">\n    <div x-data=\"{ open: false }\">\n        <button @click=\"if($dispatch('open')){ open = true; }\">Click me</button>\n        <!-- When the button is pressed an event is dispatched and only if the result is truthy (not prevented by any handler) the content will be shown. -->\n        \n        <div x-show=\"open\">\n            <h1>Hello</h1>\n        </div>\n    </div>\n</div>\n```\n\nThis could be useful when you want to prevent opening/closing a modal or something like that by using event handlers.\n\n<a name=\"overwriting-options\"></a>\n## Overwriting options\n\nYou can use the third parameter of `$dispatch` to overwrite the default options of the event. For example, you can set `bubbles` to `false`:\n\n```alpine\n<!-- 🚫 Won't work because the event is being listened on the parent element -->\n<div x-data=\"{ title: 'Hello' }\" x-on:update-title=\"title = $event.detail\">\n    <button @click=\"$dispatch('update-title', 'Hello World!', {bubbles: false})\">Click me</button>\n</div>\n\n<!-- ✅ Will work because the event is being listened on the same element -->\n<div x-data=\"{ title: 'Hello' }\">\n    <button x-on:update-title=\"title = $event.detail\" @click=\"$dispatch('update-title', 'Hello World!', {bubbles: false})\">Click me</button>\n</div>\n```\n\nThis is useful when you want to prevent the event from bubbling up to the parent elements.\n","packages/docs/src/en/magics/el.md":"---\norder: 1\nprefix: $\ntitle: el\n---\n\n# $el\n\n`$el` is a magic property that can be used to retrieve the current DOM node.\n\n```alpine\n<button @click=\"$el.innerHTML = 'Hello World!'\">Replace me with \"Hello World!\"</button>\n```\n\n<!-- START_VERBATIM -->\n<div class=\"demo\">\n    <div x-data>\n        <button @click=\"$el.textContent = 'Hello World!'\">Replace me with \"Hello World!\"</button>\n    </div>\n</div>\n<!-- END_VERBATIM -->\n","packages/docs/src/en/magics/id.md":"---\norder: 9\nprefix: $\ntitle: id\n---\n\n# $id\n\n`$id` is a magic property that can be used to generate an element's ID and ensure that it won't conflict with other IDs of the same name on the same page.\n\nThis utility is extremely helpful when building re-usable components (presumably in a back-end template) that might occur multiple times on a page, and make use of ID attributes.\n\nThings like input components, modals, listboxes, etc. will all benefit from this utility.\n\n<a name=\"basic-usage\"></a>\n## Basic usage\n\nSuppose you have two input elements on a page, and you want them to have a unique ID from each other, you can do the following:\n\n```alpine\n<input type=\"text\" :id=\"$id('text-input')\">\n<!-- id=\"text-input-1\" -->\n\n<input type=\"text\" :id=\"$id('text-input')\">\n<!-- id=\"text-input-2\" -->\n```\n\nAs you can see, `$id` takes in a string and spits out an appended suffix that is unique on the page.\n\n<a name=\"groups-with-x-id\"></a>\n## Grouping with x-id\n\nNow let's say you want to have those same two input elements, but this time you want `<label>` elements for each of them.\n\nThis presents a problem, you now need to be able to reference the same ID twice. One for the `<label>`'s `for` attribute, and the other for the `id` on the input.\n\nHere is a way that you might think to accomplish this and is totally valid:\n\n```alpine\n<div x-data=\"{ id: $id('text-input') }\">\n    <label :for=\"id\"> <!-- \"text-input-1\" -->\n    <input type=\"text\" :id=\"id\"> <!-- \"text-input-1\" -->\n</div>\n\n<div x-data=\"{ id: $id('text-input') }\">\n    <label :for=\"id\"> <!-- \"text-input-2\" -->\n    <input type=\"text\" :id=\"id\"> <!-- \"text-input-2\" -->\n</div>\n```\n\nThis approach is fine, however, having to name and store the ID in your component scope feels cumbersome.\n\nTo accomplish this same task in a more flexible way, you can use Alpine's `x-id` directive to declare an \"id scope\" for a set of IDs:\n\n```alpine\n<div x-id=\"['text-input']\">\n    <label :for=\"$id('text-input')\"> <!-- \"text-input-1\" -->\n    <input type=\"text\" :id=\"$id('text-input')\"> <!-- \"text-input-1\" -->\n</div>\n\n<div x-id=\"['text-input']\">\n    <label :for=\"$id('text-input')\"> <!-- \"text-input-2\" -->\n    <input type=\"text\" :id=\"$id('text-input')\"> <!-- \"text-input-2\" -->\n</div>\n```\n\nAs you can see, `x-id` accepts an array of ID names. Now any usages of `$id()` within that scope, will all use the same ID. Think of them as \"id groups\".\n\n<a name=\"nesting\"></a>\n## Nesting\n\nAs you might have intuited, you can freely nest these `x-id` groups, like so:\n\n```alpine\n<div x-id=\"['text-input']\">\n    <label :for=\"$id('text-input')\"> <!-- \"text-input-1\" -->\n    <input type=\"text\" :id=\"$id('text-input')\"> <!-- \"text-input-1\" -->\n\n    <div x-id=\"['text-input']\">\n        <label :for=\"$id('text-input')\"> <!-- \"text-input-2\" -->\n        <input type=\"text\" :id=\"$id('text-input')\"> <!-- \"text-input-2\" -->\n    </div>\n</div>\n```\n\n<a name=\"keyed-ids\"></a>\n## Keyed IDs (For Looping)\n\nSometimes, it is helpful to specify an additional suffix on the end of an ID for the purpose of identifying it within a loop.\n\nFor this, `$id()` accepts an optional second parameter that will be added as a suffix on the end of the generated ID.\n\nA common example of this need is something like a listbox component that uses the `aria-activedescendant` attribute to tell assistive technologies which element is \"active\" in the list:\n\n```alpine\n<ul\n    x-id=\"['list-item']\"\n    :aria-activedescendant=\"$id('list-item', activeItem.id)\"\n>\n    <template x-for=\"item in items\" :key=\"item.id\">\n        <li :id=\"$id('list-item', item.id)\">...</li>\n    </template>\n</ul>\n```\n\nThis is an incomplete example of a listbox, but it should still be helpful to demonstrate a scenario where you might need each ID in a group to still be unique to the page, but also be keyed within a loop so that you can reference individual IDs within that group.\n","packages/docs/src/en/magics/nextTick.md":"---\norder: 6\nprefix: $\ntitle: nextTick\n---\n\n# $nextTick\n\n`$nextTick` is a magic property that allows you to only execute a given expression AFTER Alpine has made its reactive DOM updates. This is useful for times you want to interact with the DOM state AFTER it's reflected any data updates you've made.\n\n```alpine\n<div x-data=\"{ title: 'Hello' }\">\n    <button\n        @click=\"\n            title = 'Hello World!';\n            $nextTick(() => { console.log($el.innerText) });\n        \"\n        x-text=\"title\"\n    ></button>\n</div>\n```\n\nIn the above example, rather than logging \"Hello\" to the console, \"Hello World!\" will be logged because `$nextTick` was used to wait until Alpine was finished updating the DOM.\n\n<a name=\"promises\"></a>\n\n## Promises\n\n`$nextTick` returns a promise, allowing the use of `$nextTick` to pause an async function until after pending dom updates. When used like this, `$nextTick` also does not require an argument to be passed.\n\n```alpine\n<div x-data=\"{ title: 'Hello' }\">\n    <button\n        @click=\"\n            title = 'Hello World!';\n            await $nextTick();\n            console.log($el.innerText);\n        \"\n        x-text=\"title\"\n    ></button>\n</div>\n```\n","packages/docs/src/en/magics/refs.md":"---\norder: 2\nprefix: $\ntitle: refs\n---\n\n# $refs\n\n`$refs` is a magic property that can be used to retrieve DOM elements marked with `x-ref` inside the component. This is useful when you need to manually manipulate DOM elements. It's often used as a more succinct, scoped, alternative to `document.querySelector`.\n\n```alpine\n<button @click=\"$refs.text.remove()\">Remove Text</button>\n\n<span x-ref=\"text\">Hello 👋</span>\n```\n\n<!-- START_VERBATIM -->\n<div class=\"demo\">\n    <div x-data>\n        <button @click=\"$refs.text.remove()\">Remove Text</button>\n\n        <div class=\"pt-4\" x-ref=\"text\">Hello 👋</div>\n    </div>\n</div>\n<!-- END_VERBATIM -->\n\nNow, when the `<button>` is pressed, the `<span>` will be removed.\n\n<a name=\"limitations\"></a>\n### Limitations\n\nIn V2 it was possible to bind `$refs` to elements dynamically, like seen below:\n\n```alpine\n<template x-for=\"item in items\" :key=\"item.id\" >\n    <div :x-ref=\"item.name\">\n    some content ...\n    </div>\n</template>\n```\n\nHowever, in V3, `$refs` can only be accessed for elements that are created statically. So for the example above: if you were expecting the value of `item.name` inside of `$refs` to be something like *Batteries*, you should be aware that `$refs` will actually contain the literal string `'item.name'` and not *Batteries*.\n","packages/docs/src/en/magics/root.md":"---\norder: 7\nprefix: $\ntitle: root\n---\n\n# $root\n\n`$root` is a magic property that can be used to retrieve the root element of any Alpine component. In other words the closest element up the DOM tree that contains `x-data`.\n\n```alpine\n<div x-data data-message=\"Hello World!\">\n    <button @click=\"alert($root.dataset.message)\">Say Hi</button>\n</div>\n```\n\n<!-- START_VERBATIM -->\n<div x-data data-message=\"Hello World!\" class=\"demo\">\n    <button @click=\"alert($root.dataset.message)\">Say Hi</button>\n</div>\n<!-- END_VERBATIM -->\n","packages/docs/src/en/magics/store.md":"---\norder: 3\nprefix: $\ntitle: store\n---\n\n# $store\n\nYou can use `$store` to conveniently access global Alpine stores registered using [`Alpine.store(...)`](/globals/alpine-store). For example:\n\n```alpine\n<button x-data @click=\"$store.darkMode.toggle()\">Toggle Dark Mode</button>\n\n...\n\n<div x-data :class=\"$store.darkMode.on && 'bg-black'\">\n    ...\n</div>\n\n\n<script>\n    document.addEventListener('alpine:init', () => {\n        Alpine.store('darkMode', {\n            on: false,\n\n            toggle() {\n                this.on = ! this.on\n            }\n        })\n    })\n</script>\n```\n\nGiven that we've registered the `darkMode` store and set `on` to \"false\", when the `<button>` is pressed, `on` will be \"true\" and the background color of the page will change to black.\n\n<a name=\"single-value-stores\"></a>\n## Single-value stores\n\nIf you don't need an entire object for a store, you can set and use any kind of data as a store.\n\nHere's the example from above but using it more simply as a boolean value:\n\n```alpine\n<button x-data @click=\"$store.darkMode = ! $store.darkMode\">Toggle Dark Mode</button>\n\n...\n\n<div x-data :class=\"$store.darkMode && 'bg-black'\">\n    ...\n</div>\n\n\n<script>\n    document.addEventListener('alpine:init', () => {\n        Alpine.store('darkMode', false)\n    })\n</script>\n```\n\n[→ Read more about Alpine stores](/globals/alpine-store)\n","packages/docs/src/en/magics/watch.md":"---\norder: 4\ntitle: watch\n---\n\n# $watch\n\nYou can \"watch\" a component property using the `$watch` magic method. For example:\n\n```alpine\n<div x-data=\"{ open: false }\" x-init=\"$watch('open', value => console.log(value))\">\n    <button @click=\"open = ! open\">Toggle Open</button>\n</div>\n```\n\nIn the above example, when the button is pressed and `open` is changed, the provided callback will fire and `console.log` the new value:\n\nYou can watch deeply nested properties using \"dot\" notation\n\n```alpine\n<div x-data=\"{ foo: { bar: 'baz' }}\" x-init=\"$watch('foo.bar', value => console.log(value))\">\n    <button @click=\"foo.bar = 'bob'\">Toggle Open</button>\n</div>\n```\n\nWhen the `<button>` is pressed, `foo.bar` will be set to \"bob\", and \"bob\" will be logged to the console.\n\n<a name=\"getting-the-old-value\"></a>\n### Getting the \"old\" value\n\n`$watch` keeps track of the previous value of the property being watched, You can access it using the optional second argument to the callback like so:\n\n```alpine\n<div x-data=\"{ open: false }\" x-init=\"$watch('open', (value, oldValue) => console.log(value, oldValue))\">\n    <button @click=\"open = ! open\">Toggle Open</button>\n</div>\n```\n\n<a name=\"deep-watching\"></a>\n### Deep watching\n\n`$watch` automatically watches from changes at any level but you should keep in mind that, when a change is detected, the watcher will return the value of the observed property, not the value of the subproperty that has changed.\n\n```alpine\n<div x-data=\"{ foo: { bar: 'baz' }}\" x-init=\"$watch('foo', (value, oldValue) => console.log(value, oldValue))\">\n    <button @click=\"foo.bar = 'bob'\">Update</button>\n</div>\n```\n\nWhen the `<button>` is pressed, `foo.bar` will be set to \"bob\", and \"{bar: 'bob'} {bar: 'baz'}\" will be logged to the console (new and old value).\n\n> ⚠️ Changing a property of a \"watched\" object as a side effect of the `$watch` callback will generate an infinite loop and eventually error. \n\n```alpine\n<!-- 🚫 Infinite loop -->\n<div x-data=\"{ foo: { bar: 'baz', bob: 'lob' }}\" x-init=\"$watch('foo', value => foo.bob = foo.bar)\">\n    <button @click=\"foo.bar = 'bob'\">Update</button>\n</div>\n```\n","packages/docs/src/en/plugins.md":"---\norder: 7\ntitle: Plugins\nfont-type: mono\ntype: sub-directory\n---\n","packages/docs/src/en/plugins/anchor.md":"---\norder: 7\ntitle: Anchor\ndescription: Anchor an element's positioning to another element on the page\ngraph_image: https://alpinejs.dev/social_anchor.jpg\n---\n\n# Anchor Plugin\n\nAlpine's Anchor plugin allows you to easily anchor an element's positioning to another element on the page.\n\nThis functionality is useful when creating dropdown menus, popovers, dialogs, and tooltips with Alpine.\n\nThe \"anchoring\" functionality used in this plugin is provided by the [Floating UI](https://floating-ui.com/) project.\n\n<a name=\"installation\"></a>\n## Installation\n\nYou can use this plugin by either including it from a `<script>` tag or installing it via NPM:\n\n### Via CDN\n\nYou can include the CDN build of this plugin as a `<script>` tag, just make sure to include it BEFORE Alpine's core JS file.\n\n```alpine\n<!-- Alpine Plugins -->\n<script defer src=\"https://cdn.jsdelivr.net/npm/@alpinejs/anchor@3.x.x/dist/cdn.min.js\"></script>\n\n<!-- Alpine Core -->\n<script defer src=\"https://cdn.jsdelivr.net/npm/alpinejs@3.x.x/dist/cdn.min.js\"></script>\n```\n\n### Via NPM\n\nYou can install Anchor from NPM for use inside your bundle like so:\n\n```shell\nnpm install @alpinejs/anchor\n```\n\nThen initialize it from your bundle:\n\n```js\nimport Alpine from 'alpinejs'\nimport anchor from '@alpinejs/anchor'\n\nAlpine.plugin(anchor)\n\n...\n```\n\n<a name=\"x-anchor\"></a>\n## x-anchor\n\nThe primary API for using this plugin is the `x-anchor` directive.\n\nTo use this plugin, add the `x-anchor` directive to any element and pass it a reference to the element you want to anchor it's position to (often a button on the page).\n\nBy default, `x-anchor` will set the element's CSS to `position: absolute` and the appropriate `top` and `left` values. If the anchored element is normally displayed below the reference element but doesn't have room on the page, it's styling will be adjusted to render above the element.\n\nFor example, here's a simple dropdown anchored to the button that toggles it:\n\n```alpine\n<div x-data=\"{ open: false }\">\n    <button x-ref=\"button\" @click=\"open = ! open\">Toggle</button>\n\n    <div x-show=\"open\" x-anchor=\"$refs.button\">\n        Dropdown content\n    </div>\n</div>\n```\n\n<!-- START_VERBATIM -->\n<div x-data=\"{ open: false }\" class=\"demo overflow-hidden\">\n    <div class=\"flex justify-center\">\n        <button x-ref=\"button\" @click=\"open = ! open\">Toggle</button>\n    </div>\n\n    <div x-show=\"open\" x-anchor=\"$refs.button\" class=\"bg-white rounded p-4 border shadow z-10\">\n        Dropdown content\n    </div>\n</div>\n<!-- END_VERBATIM -->\n\n<a name=\"positioning\"></a>\n## Positioning\n\n`x-anchor` allows you to customize the positioning of the anchored element using the following modifiers:\n\n* Bottom: `.bottom`, `.bottom-start`, `.bottom-end`\n* Top: `.top`, `.top-start`, `.top-end`\n* Left: `.left`, `.left-start`, `.left-end`\n* Right: `.right`, `.right-start`, `.right-end`\n\nHere is an example of using `.bottom-start` to position a dropdown below and to the right of the reference element:\n\n```alpine\n<div x-data=\"{ open: false }\">\n    <button x-ref=\"button\" @click=\"open = ! open\">Toggle</button>\n\n    <div x-show=\"open\" x-anchor.bottom-start=\"$refs.button\">\n        Dropdown content\n    </div>\n</div>\n```\n\n<!-- START_VERBATIM -->\n<div x-data=\"{ open: false }\" class=\"demo overflow-hidden\">\n    <div class=\"flex justify-center\">\n        <button x-ref=\"button\" @click=\"open = ! open\">Toggle</button>\n    </div>\n\n    <div x-show=\"open\" x-anchor.bottom-start=\"$refs.button\" class=\"bg-white rounded p-4 border shadow z-10\">\n        Dropdown content\n    </div>\n</div>\n<!-- END_VERBATIM -->\n\n<a name=\"fixed-positioning\"></a>\n### Fixed positioning\n\nBy default, `x-anchor` applies `position: absolute` to the anchored element. This is fine for most cases, but it falls apart when the reference element lives inside a container with `overflow: hidden`, `overflow: clip`, or `overflow: auto`—the anchored element is clipped along with it.\n\nYou can instruct Floating UI to use a fixed positioning strategy instead by adding the `.fixed` modifier:\n\n```html\n<div x-data=\"{ open: false }\">\n    <button x-ref=\"button\" @click=\"open = ! open\">Toggle</button>\n\n    <div x-show=\"open\" x-anchor.fixed=\"$refs.button\">\n        Dropdown content\n    </div>\n</div>\n```\n\n<!-- START_VERBATIM -->\n<div x-data=\"{ open: false }\" class=\"demo overflow-hidden\">\n    <div class=\"flex justify-center\">\n        <button x-ref=\"button\" @click=\"open = ! open\">Toggle</button>\n    </div>\n\n    <div x-show=\"open\" x-anchor.fixed=\"$refs.button\" class=\"bg-white rounded p-4 border shadow z-10\">\n        Dropdown content\n    </div>\n</div>\n<!-- END_VERBATIM -->\n\n> **Heads up:** a `transform`, `filter`, `perspective`, `backdrop-filter`, `will-change`, or `contain` on any ancestor element creates a new containing block for `position: fixed` descendants ([per the CSS spec](https://developer.mozilla.org/en-US/docs/Web/CSS/position#fixed_positioning)). When that happens, `.fixed` will behave like `position: absolute` relative to that ancestor—and won't escape its `overflow: hidden`. If `.fixed` seems to be doing nothing, check for a transformed ancestor.\n\n<a name=\"offset\"></a>\n## Offset\n\nYou can add an offset to your anchored element using the `.offset.[px value]` modifier like so:\n\n```alpine\n<div x-data=\"{ open: false }\">\n    <button x-ref=\"button\" @click=\"open = ! open\">Toggle</button>\n\n    <div x-show=\"open\" x-anchor.offset.10=\"$refs.button\">\n        Dropdown content\n    </div>\n</div>\n```\n\n<!-- START_VERBATIM -->\n<div x-data=\"{ open: false }\" class=\"demo overflow-hidden\">\n    <div class=\"flex justify-center\">\n        <button x-ref=\"button\" @click=\"open = ! open\">Toggle</button>\n    </div>\n\n    <div x-show=\"open\" x-anchor.offset.10=\"$refs.button\" class=\"bg-white rounded p-4 border shadow z-10\">\n        Dropdown content\n    </div>\n</div>\n<!-- END_VERBATIM -->\n\n<a name=\"prevent-flipping\"></a>\n## Prevent flipping position\n\nBy default, `x-anchor` will flip the position of the anchored element if it doesn't have enough room to render below the reference element.\n\nYou can prevent this behavior by adding the `.noflip` modifier:\n\n```alpine\n<div x-data=\"{ open: false }\">\n    <button x-ref=\"button\" @click=\"open = ! open\">Toggle</button>\n\n    <div x-show=\"open\" x-anchor.noflip=\"$refs.button\">\n        Dropdown content\n    </div>\n</div>\n```\n\n<!-- START_VERBATIM -->\n<div x-data=\"{ open: false }\" class=\"demo overflow-hidden\">\n    <div class=\"flex justify-center\">\n        <button x-ref=\"button\" @click=\"open = ! open\">Toggle</button>\n    </div>\n\n    <div x-show=\"open\" x-anchor.noflip=\"$refs.button\" class=\"bg-white rounded p-4 border shadow z-10\">\n        Dropdown content\n    </div>\n</div>\n<!-- END_VERBATIM -->\n\n<a name=\"manual-styling\"></a>\n## Manual styling\n\nBy default, `x-anchor` applies the positioning styles to your element under the hood. If you'd prefer full control over styling, you can pass the `.no-style` modifer and use the `$anchor` magic to access the values inside another Alpine expression.\n\nBelow is an example of bypassing `x-anchor`'s internal styling and instead applying the styles yourself using `x-bind:style`:\n\n```alpine\n<div x-data=\"{ open: false }\">\n    <button x-ref=\"button\" @click=\"open = ! open\">Toggle</button>\n\n    <div\n        x-show=\"open\"\n        x-anchor.no-style=\"$refs.button\"\n        x-bind:style=\"{ position: 'absolute', top: $anchor.y+'px', left: $anchor.x+'px' }\"\n    >\n        Dropdown content\n    </div>\n</div>\n```\n\n<!-- START_VERBATIM -->\n<div x-data=\"{ open: false }\" class=\"demo overflow-hidden\">\n    <div class=\"flex justify-center\">\n        <button x-ref=\"button\" @click=\"open = ! open\">Toggle</button>\n    </div>\n\n    <div\n        x-show=\"open\"\n        x-anchor.no-style=\"$refs.button\"\n        x-bind:style=\"{ position: 'absolute', top: $anchor.y+'px', left: $anchor.x+'px' }\"\n        class=\"bg-white rounded p-4 border shadow z-10\"\n    >\n        Dropdown content\n    </div>\n</div>\n<!-- END_VERBATIM -->\n\n> **Combining `.no-style` with `.fixed`:** when you opt out of Alpine's internal styling and also want fixed positioning, remember to set `position: 'fixed'` yourself. `$anchor.x` and `$anchor.y` are returned in the coordinate space of whichever strategy is active—absolute coordinates are relative to the offset parent, fixed coordinates are relative to the viewport—so applying the wrong `position` will put your element in the wrong place.\n>\n> ```alpine\n> <div\n>     x-show=\"open\"\n>     x-anchor.no-style.fixed=\"$refs.button\"\n>     x-bind:style=\"{ position: 'fixed', top: $anchor.y+'px', left: $anchor.x+'px' }\"\n> >\n>     Dropdown content\n> </div>\n> ```\n\n<a name=\"from-id\"></a>\n## Anchor to an ID\n\nThe examples thus far have all been anchoring to other elements using Alpine refs.\n\nBecause `x-anchor` accepts a reference to any DOM element, you can use utilities like `document.getElementById()` to anchor to an element by its `id` attribute:\n\n```alpine\n<div x-data=\"{ open: false }\">\n    <button id=\"trigger\" @click=\"open = ! open\">Toggle</button>\n\n    <div x-show=\"open\" x-anchor=\"document.getElementById('trigger')\">\n        Dropdown content\n    </div>\n</div>\n```\n\n<!-- START_VERBATIM -->\n<div x-data=\"{ open: false }\" class=\"demo overflow-hidden\">\n    <div class=\"flex justify-center\">\n        <button class=\"trigger\" @click=\"open = ! open\">Toggle</button>\n    </div>\n\n\n    <div x-show=\"open\" x-anchor=\"document.querySelector('.trigger')\">\n        Dropdown content\n    </div>\n</div>\n<!-- END_VERBATIM -->\n","packages/docs/src/en/plugins/collapse.md":"<!-- Skill available on-demand via /api/skills/alpinejs/alpine?path=packages%2Fdocs%2Fsrc%2Fen%2Fplugins%2Fcollapse.md -->","packages/docs/src/en/plugins/focus.md":"<!-- Skill available on-demand via /api/skills/alpinejs/alpine?path=packages%2Fdocs%2Fsrc%2Fen%2Fplugins%2Ffocus.md -->","packages/docs/src/en/plugins/intersect.md":"<!-- Skill available on-demand via /api/skills/alpinejs/alpine?path=packages%2Fdocs%2Fsrc%2Fen%2Fplugins%2Fintersect.md -->","packages/docs/src/en/plugins/mask.md":"<!-- Skill available on-demand via /api/skills/alpinejs/alpine?path=packages%2Fdocs%2Fsrc%2Fen%2Fplugins%2Fmask.md -->","packages/docs/src/en/plugins/morph.md":"<!-- Skill available on-demand via /api/skills/alpinejs/alpine?path=packages%2Fdocs%2Fsrc%2Fen%2Fplugins%2Fmorph.md -->","packages/docs/src/en/plugins/persist.md":"<!-- Skill available on-demand via /api/skills/alpinejs/alpine?path=packages%2Fdocs%2Fsrc%2Fen%2Fplugins%2Fpersist.md -->","packages/docs/src/en/plugins/resize.md":"<!-- Skill available on-demand via /api/skills/alpinejs/alpine?path=packages%2Fdocs%2Fsrc%2Fen%2Fplugins%2Fresize.md -->","packages/docs/src/en/plugins/sort.md":"<!-- Skill available on-demand via /api/skills/alpinejs/alpine?path=packages%2Fdocs%2Fsrc%2Fen%2Fplugins%2Fsort.md -->","packages/docs/src/en/start-here.md":"<!-- Skill available on-demand via /api/skills/alpinejs/alpine?path=packages%2Fdocs%2Fsrc%2Fen%2Fstart-here.md -->","packages/docs/src/en/upgrade-guide.md":"<!-- Skill available on-demand via /api/skills/alpinejs/alpine?path=packages%2Fdocs%2Fsrc%2Fen%2Fupgrade-guide.md -->"},"files":{".claude/skills/review-pr/SKILL.md":"---\nname: review-pr\ndescription: Review an open PR like a maintainer — checkout, fix issues, push changes, post a structured verdict comment. You just merge or close.\ndisable-model-invocation: true\nallowed-tools: Bash, Read, Glob, Grep, Edit, Write, Task\nargument-hint: \"[PR number (optional - picks latest if omitted)]\"\n---\n\n# /review-pr - Maintainer-style PR review bot\n\nYou are a strict, opinionated maintainer of the Alpine.js project. Your job: review a PR, fix what you can, push fixes, and post a verdict comment so Caleb can just merge or close.\n\n**IMPORTANT: Every numbered step below is mandatory. Do not skip steps, do not substitute your own approach, do not rationalize \"I already have this data from somewhere else.\" Run the exact commands listed. If a command fails, retry it — do not silently move on. Complete each step fully before starting the next.**\n\n## Step 1: Pick a PR\n\nIf `$ARGUMENTS` is provided, use that as the PR number. Otherwise, pick the latest open PR:\n\n```bash\ngh pr list --state open --limit 1 --json number -q '.[0].number'\n```\n\n## Step 2: Check if already reviewed\n\nLook for the `<!-- claude-review -->` marker in PR comments:\n\n```bash\ngh pr view {number} --json comments -q '.comments[].body' | grep -q '<!-- claude-review -->'\n```\n\nIf found, tell the user this PR was already reviewed and stop. Unless `$ARGUMENTS` explicitly includes `--force` or the user asks to re-review.\n\n## Step 3: Fetch PR data\n\nRun ALL FOUR of these commands in parallel. If any fail, retry them. Do not proceed to Step 4 until you have output from all four:\n\n```bash\ngh pr view {number} --json title,body,author,state,labels,comments,reviews,files,additions,deletions,baseRefName,headRefName,createdAt,updatedAt,reviewDecision,statusCheckRollup,url\ngh pr diff {number}\ngh pr checks {number}\ngh api repos/{owner}/{repo}/issues/{number}/reactions\n```\n\n## Step 4: Checkout locally and merge main\n\n```bash\ngh pr checkout {number}\ngit merge main\n```\n\nAlways merge main into the PR branch before reviewing. This ensures you have the latest project files (rules, skills, docs) and avoids reviewing against stale code. If the merge has conflicts, resolve them or flag for the contributor.\n\n## Step 5: Read and classify\n\nRead through the diff and PR body. Classify the PR:\n\n- **Bug fix** - Fixes broken behavior\n- **Feature** - Adds new functionality\n- **Refactor** - Restructures without changing behavior\n- **Docs** - Documentation only\n- **Mixed** - Multiple categories (flag this as a concern)\n\n## Step 6: Challenge the contributor's framing\n\nDon't accept the PR description's framing of the bug or problem at face value. Verify independently:\n\n1. **Identify the root cause yourself.** Read the code the PR modifies. Understand *why* the bug exists before looking at how the PR fixes it.\n2. **Does the test actually isolate that root cause?** Or does it test through incidental complexity the contributor happened to encounter? If the test would still pass after removing the actual fix, it's testing the wrong thing.\n3. **If the test encodes a wrong mental model, rewrite it.** Strip it to the minimum reproduction that targets the real bug. Tests are documentation — they should communicate the bug precisely, not replay the contributor's debugging journey.\n4. **Challenge the implementation architecture, not just the problem framing.** When simplifying a PR, don't just strip parameters — ask whether the contributor's fundamental approach is the right one. A simpler version of a bad approach is still a bad approach. Ask: \"What's the laziest correct solution? Does the language/framework already handle this if I just let it?\"\n\n## Step 7: Evaluate\n\n### For bug fixes\n\n1. **Has a test?** If not, write one. The test should fail on `main` and pass on the PR branch.\n2. **Test covers the actual fix?** Including edge cases?\n3. **Actually verify regression.** Don't just reason about whether the test fails without the fix — prove it. Stash the fix (`git stash -- <fix files>`), rebuild (`npm run build`), run the test. If it passes without the fix, the test is not testing the fix. Unstash and rewrite the test. This is non-negotiable for bug fix PRs.\n4. **Test isolates root cause?** Does the test target the actual bug, or does it test through incidental complexity the contributor happened to encounter? Strip tests to the minimum reproduction. Tests are documentation — they should communicate the bug precisely.\n5. **Naming quality?** Review all test names, component names, variable names. Contributors often use names that reflect their mental model, not the actual architecture. Fix these before merging — they become permanent.\n6. **Unnecessary fixtures/setup?** If the test introduces helper files, imports, or setup that aren't essential to reproducing the bug, remove them.\n7. **For visual/browser bugs, test observable behavior, not DOM state.** Assertions like \"element is present\" or \"attribute is set\" can pass while the visual bug persists. For animation bugs: assert on `document.getAnimations()` state. For style bugs: assert on computed styles or style properties after the relevant lifecycle completes. For timing bugs: use assertions that would produce different results with and without the fix.\n8. **Fix is surgical/minimal?** No unrelated changes?\n9. **Regression risk?** Could this break something else?\n\n### For features\n\nAddress EVERY item below. Do not skip any — even to say \"N/A\":\n\n1. **Already possible without new API?** Default stance: reject new public API surface. Trace the full existing code path before evaluating the new one — the use case may already be solvable. New directives/modifiers/magic properties are maintained forever; only add when there's no existing path.\n2. **Community demand?** Check reactions on the PR and linked issues. Low engagement = higher bar.\n3. **Intuitive API?** Single-word modifiers preferred (`x-transition.opacity` not `x-transition.opacity-only`). Alpine favors short, expressive directive syntax.\n4. **Precedent?** Does it build on existing patterns or introduce new ones? New patterns need strong justification.\n5. **Scope?** Should this be a core Alpine feature or a separate plugin package? Alpine core should stay minimal.\n6. **Docs included?** Features need documentation.\n7. **Registration complete?** Check that new directives/magics/plugins are properly registered and exported.\n\n### For all PRs\n\nAddress EVERY item below:\n\n1. **Project style?**\n   - JS: no semicolons, `let` not `const`\n   - Follows Alpine's existing patterns and conventions\n2. **Single responsibility?** Flag PRs doing too many things.\n3. **Security?** Extra scrutiny for: `x-html`, expression evaluation, `Alpine.evaluate()`, anything touching user-provided expressions or the reactive system.\n4. **Built JS assets in diff?** Check the file list from `gh pr diff --name-only` for `dist/` files. These should NOT be committed. Remove them.\n5. **\"No for now\" bias.** When in doubt, lean toward not merging. It's easier to add later than remove.\n6. **Async timing fixes are treacherous.** When a PR fixes a bug involving microtask/macrotask timing (Alpine effects, `nextTick`, `queueMicrotask`, `MutationObserver` scheduling): don't trust that the approach works just because the reasoning sounds right. Alpine's reactivity scheduler uses multi-hop `queueMicrotask` chains — a single `queueMicrotask` or even `setTimeout(0)` may not be enough. If you can't verify the timing empirically, flag it for discussion.\n7. **\"What's the laziest correct solution?\"** Before evaluating the PR's implementation details, independently brainstorm the simplest possible fix. The contributor's approach is often shaped by their discovery path, not by what's optimal.\n\n## Step 8: Run relevant tests only\n\n**NEVER run the full test suite.** Only run tests the PR adds or touches:\n\n```bash\n# Find test files in the diff\ngh pr diff {number} --name-only | grep -E '\\.spec\\.js$'\n```\n\nRun those specific tests:\n\n```bash\n# For Cypress browser tests\nnpx cypress run --spec ./tests/cypress/integration/{test-file}.spec.js\n\n# For Vitest unit tests\nnpx vitest run tests/vitest/{test-file}.spec.js\n```\n\nIf the PR doesn't touch test files but you wrote tests in step 6, run those.\n\nAlso check CI status:\n\n```bash\ngh pr checks {number}\n```\n\n## Step 8b: If the PR has no fix, write one\n\nIf the PR only adds a failing test (or describes a bug without a fix), don't just review the test and stop. **Explore solution paths and try to fix the bug yourself.** This is the most valuable thing you can do.\n\n1. Identify 2-3 possible fix approaches\n2. Evaluate trade-offs of each (surgical vs broad, risk of regressions, etc.)\n3. Present the options to Caleb with a brief explanation of each\n4. Once Caleb picks a direction, implement and test it\n\n## Step 9: Make fixes directly\n\nFix issues you find. Common fixes:\n\n- **Style violations**: Remove semicolons from JS, change `const` to `let`\n- **Built assets in diff**: `git checkout main -- dist/` (or whatever the build output path is)\n- **Missing tests**: Write them\n- **Small refactors**: Simplify overly complex code\n- **Missing registration**: Add to package index files, etc.\n- **Before committing a simplified version of the contributor's code, do a smell test:** Could this be done in fewer lines with a completely different approach? The best code is the code you delete.\n\nStage and commit fixes:\n\n```bash\ngit add -A\ngit commit -m \"Review fixes: [brief description]\n\nCo-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>\"\n```\n\n## Step 10: Push to PR branch\n\nTry to push to the contributor's branch:\n\n```bash\ngit push\n```\n\n### If push fails (fork doesn't allow maintainer edits)\n\n1. Create a new branch from `main`\n2. Cherry-pick the contributor's commits\n3. Apply your fixes on top\n4. Push the new branch\n5. Create a new PR:\n\n```bash\ngh pr create --title \"{original title}\" --body \"$(cat <<'EOF'\nCloses #{original_number}\n\nCherry-picked from #{original_number} by @{author} with review fixes applied.\n\n## Original description\n{original_body}\n\n## Review fixes applied\n{list of fixes}\nEOF\n)\"\n```\n\n6. Comment on the original PR explaining the new PR.\n\n## Step 11: Post verdict comment\n\nPost a structured comment on the PR:\n\n```bash\ngh pr comment {number} --body \"$(cat <<'EOF'\n<!-- claude-review -->\n## PR Review: #{number} — {title}\n\n**Type**: {Bug fix | Feature | Refactor | Docs | Mixed}\n**Verdict**: {Merge | Request changes | Needs discussion | Close}\n\n### What's happening (plain English)\n{Explain the PR like Caleb is a 3-year-old who happens to be an expert in Alpine internals but has zero context on this specific PR. Use a numbered step-by-step walkthrough of the exact sequence that triggers the bug/feature. No jargon beyond what Alpine devs already know. Be crystal clear and concise — this is the most important section.}\n\n### Other approaches considered\n{Briefly list 2-3 alternative ways this could have been solved, with one sentence each on why the PR's approach is better (or worse). If there's only one reasonable approach, say so and explain why. This helps Caleb quickly evaluate whether the chosen path is the right one.}\n\n### Changes Made\n{List of fixups you pushed, or \"No changes made\" if none}\n\n### Test Results\n{Which tests ran, pass/fail status, CI status}\n\n### Code Review\n{Specific feedback with file:line references. What's good, what's concerning.}\n\n### Security\n{Any security considerations, or \"No security concerns identified.\"}\n\n### Verdict\n{Your reasoning for the verdict. Be direct. If it should be merged, say why. If closed, say why kindly but clearly.}\n\n---\n*Reviewed by Claude*\nEOF\n)\"\n```\n\n## Verdict guidelines\n\n- **Merge**: Code is correct, tests pass, style is clean, feature is wanted. You've fixed any minor issues.\n- **Request changes**: Significant issues you can't fix yourself (architectural problems, missing context, needs author input).\n- **Needs discussion**: Feature scope questions, API design debates, core vs plugin questions. Tag these for Caleb.\n- **Close**: PR is stale with no response, duplicates existing functionality, or solves a problem that shouldn't be solved. Be kind.\n\n## Important rules\n\n- NEVER run the full test suite. Only run tests the PR touches or that you wrote.\n- Always use the `<!-- claude-review -->` marker so you can detect previous reviews.\n- Be opinionated. This project has strong conventions — enforce them.\n- Fix what you can. Don't just point out problems if you can solve them.\n- Security is non-negotiable. If you see a security issue, verdict is always \"Request changes\" regardless of everything else.\n- Match the project voice: practical, direct, minimal.\n- Don't accept the contributor's framing of the problem at face value. Verify the root cause independently, then ensure the test targets that root cause — not the contributor's incidental path to discovering it.\n- \"Should this exist?\" before \"Is this correct?\" — Don't get pulled into reviewing implementation details (code quality, edge cases, naming) until you've decided the feature itself is justified. Implementation nits imply acceptance.\n- Tests are documentation. A sloppy test that passes is not good enough — it should precisely communicate what broke and why.\n- Review contributor naming as critically as contributor code. Bad names get merged and become permanent.\n",".claude/skills/summarize-activity/SKILL.md":"---\nname: summarize-activity\ndescription: Summarize recent GitHub activity — discussions, PRs, issues, events, traffic — into an actionable report so you can stay on top of the project without reading everything.\ndisable-model-invocation: true\nallowed-tools: Bash, Read, Task\nargument-hint: \"[timeframe: 24h (default), 48h, 7d, 1w]\"\n---\n\n# /summarize-activity - GitHub activity digest\n\nYou generate a concise, actionable summary of recent Alpine.js GitHub activity for Caleb.\n\n**IMPORTANT: Every numbered step below is mandatory. Do not skip steps, do not substitute your own approach. Run the exact commands listed. If a command fails, retry it — do not silently move on. Complete each step fully before starting the next.**\n\n## Step 1: Parse timeframe\n\nParse `$ARGUMENTS` into a cutoff timestamp. Supported formats:\n- `24h`, `48h`, `72h` — hours (default: `24h` if no argument)\n- `7d`, `14d`, `30d` — days\n- `1w`, `2w` — weeks (1w = 7d)\n\nCompute the ISO 8601 cutoff timestamp:\n\n```bash\n# Example for 24h:\ndate -u -v-24H '+%Y-%m-%dT%H:%M:%SZ'\n# Example for 7d:\ndate -u -v-7d '+%Y-%m-%dT%H:%M:%SZ'\n```\n\nStore the cutoff timestamp and the human-readable timeframe label (e.g., \"last 24 hours\", \"last 7 days\") for use in later steps.\n\n## Step 2: Fetch activity in parallel\n\nRun ALL FIVE of these commands in parallel using the Bash tool. If any fail, retry them. Do not proceed to Step 3 until you have output from all five.\n\n**Owner/repo:** `alpinejs/alpine`\n\n### 2a. Discussions (GraphQL)\n\n```bash\ngh api graphql -f query='\n{\n  repository(owner: \"alpinejs\", name: \"alpine\") {\n    discussions(first: 50, orderBy: {field: UPDATED_AT, direction: DESC}) {\n      nodes {\n        title\n        url\n        author { login }\n        category { name }\n        comments { totalCount }\n        body\n        answer { author { login } body createdAt }\n        createdAt\n        updatedAt\n      }\n    }\n  }\n}'\n```\n\n### 2b. Pull Requests\n\n```bash\ngh pr list --repo alpinejs/alpine --state all --limit 50 --json number,title,url,author,state,labels,createdAt,updatedAt,additions,deletions,headRefName,baseRefName,reviewDecision,comments\n```\n\n### 2c. Issues\n\n```bash\ngh issue list --repo alpinejs/alpine --state all --limit 50 --json number,title,url,author,state,labels,createdAt,updatedAt,comments\n```\n\n### 2d. Events\n\n```bash\ngh api repos/alpinejs/alpine/events --paginate --jq '.[] | {type, actor: .actor.login, created_at: .created_at, payload_action: .payload.action, ref: .payload.ref, ref_type: .payload.ref_type}' | head -100\n```\n\n### 2e. Traffic & stars\n\n```bash\ngh api repos/alpinejs/alpine/traffic/views 2>/dev/null; echo \"---SEPARATOR---\"; gh api repos/alpinejs/alpine/traffic/clones 2>/dev/null; echo \"---SEPARATOR---\"; gh api repos/alpinejs/alpine --jq '{stargazers_count, forks_count, open_issues_count, watchers_count}'\n```\n\nNote: Traffic endpoints require push access. If they return 403, skip traffic data and note it in the report.\n\n## Step 3: Fetch comment threads for active items\n\nFor discussions that have comments updated within the timeframe, fetch full comment bodies via GraphQL. Batch up to 10 discussions per query:\n\n```bash\ngh api graphql -f query='\n{\n  repository(owner: \"alpinejs\", name: \"alpine\") {\n    discussion(number: {NUMBER}) {\n      comments(last: 10) {\n        nodes {\n          author { login }\n          body\n          createdAt\n          updatedAt\n        }\n      }\n    }\n  }\n}'\n```\n\nFor the most active PRs and issues (those with comments updated in timeframe), fetch recent comments:\n\n```bash\ngh api repos/alpinejs/alpine/issues/{number}/comments --jq '.[] | select(.updated_at > \"{CUTOFF}\") | {user: .user.login, body: .body, created_at: .created_at}'\n```\n\nOnly fetch threads that are clearly within the timeframe. Don't fetch everything — be selective.\n\n## Step 4: Filter by timeframe\n\nDiscard anything with `updatedAt` / `updated_at` before the cutoff timestamp. Keep items where:\n- The item was created within the timeframe\n- The item received new comments within the timeframe\n- The item changed state (opened, closed, merged) within the timeframe\n\n## Step 5: Analyze and write report\n\nOutput a markdown report with these sections. Be concise — this is a digest, not a novel.\n\n---\n\n### Report format:\n\n```markdown\n# Alpine.js Activity — {timeframe label}\n_{start date} to {end date}_\n\n## TL;DR\n{2-3 sentences. What's the pulse? Any fires? Anything exciting? Give Caleb the vibe in 10 seconds.}\n\n## Needs Your Attention\n{Actionable items only. Each with a recommended next step: reply, merge, close, investigate, etc.}\n\n- **[Title](url)** by @author — {why it needs attention}. **Action:** {specific recommendation}\n\n{If nothing needs attention, say \"Nothing urgent right now.\"}\n\n## Hot Discussions\n{Discussions with the most activity or notable sentiment. Include key quotes if illuminating.}\n\n- **[Title](url)** ({category}) — {N} comments — {brief summary, sentiment note}\n\n{If no notable discussions, say \"Quiet on the discussion front.\"}\n\n## PR Activity\n\n### Opened\n- **[#N Title](url)** by @author — {one-line summary} {+additions/-deletions}\n\n### Merged\n- **[#N Title](url)** by @author — {one-line summary}\n\n### Closed (not merged)\n- **[#N Title](url)** by @author — {one-line summary, why closed if clear}\n\n{Omit empty subsections.}\n\n## Issue Activity\n\n### Opened\n- **[#N Title](url)** by @author — {one-line summary}\n\n### Closed\n- **[#N Title](url)** — {one-line summary}\n\n{Omit empty subsections.}\n\n## Repo Pulse\n| Metric | Value |\n|--------|-------|\n| Stars | {total} |\n| Views (14d) | {count} |\n| Clones (14d) | {count} |\n| Open issues | {count} |\n| PRs opened | {count in timeframe} |\n| PRs merged | {count in timeframe} |\n| PRs closed | {count in timeframe} |\n\n{If traffic data is unavailable (403), omit those rows and note \"Traffic data requires push access.\"}\n```\n\n---\n\n## Important rules\n\n- Every item must include a `[title](url)` link so Caleb can click through.\n- Include @author for attribution.\n- Keep summaries to ONE line per item. This is a digest.\n- The \"Needs Your Attention\" section is the most important. Be opinionated about what deserves Caleb's time.\n- If a discussion or issue has heated sentiment, note it (e.g., \"heated\", \"confused users\", \"strong demand\").\n- Omit empty sections entirely — don't show \"No activity\" headers.\n- For PRs, mention if CI is failing when relevant.\n- Don't editorialize beyond what's helpful for triage. Be practical, not chatty.\n","CLAUDE.md":"# Alpine.js Development Guidelines\n\n## Pull Request Evaluation Criteria\n\nWhen evaluating pull requests for Alpine.js, assess the following:\n\n### 1. Tests\n- Are tests provided for the change?\n- Do existing tests still pass?\n- For configuration changes (package.json, build scripts), tests may not be required\n\n### 2. Code Style\n- Does the code match Alpine's existing patterns?\n- Check indentation, naming conventions, and structure\n- For package.json changes, ensure consistency with other packages in the monorepo\n\n### 3. Code Quality\n- Is the code clean and maintainable?\n- Is the change focused and minimal?\n- Are there any unnecessary changes or complexity?\n- Does this PR contain changes that should apply elsewhere?\n\n### 4. Simplicity\n- Is this a simple, focused change?\n- Does it follow Alpine's philosophy of simplicity?\n- Could it be implemented more simply?\n- Are the proposed additions intuitive for users? or do they require extra knowledge that they have to dig for.\n\n### 5. Precedent\n- Does this PR (both public facing additions and internal implementation) follow established precedents in the project\n- Does it use terms that are unfamiliar to the project as of yet?\n\n### 6. Description Quality\n- Is there a clear explanation of what/why/how?\n- Are breaking changes documented?\n- Is backward compatibility addressed?\n\n### 7. Community Engagement\n- Are there comments, reviews, or discussions?\n- Has it been approved by maintainers?\n- Are there any conflicting opinions or unresolved concerns?\n\n### Mergeability Rating\nBased on the above, rate as:\n- **HIGH**: Ready to merge (all criteria met, approved)\n- **MEDIUM**: Needs attention (technically sound but missing reviews/tests)\n- **LOW**: Requires work (has issues or conflicts to resolve)\n\n## Project Structure\n\nAlpine.js is a monorepo with packages in `/packages/`:\n- Each package has its own package.json\n- Build outputs go to `dist/` with `.cjs.js`, `.esm.js`, and `.min.js` versions\n- Browser tests use Cypress, unit tests use Vitest\n- CI runs on GitHub Actions\n\n## Common Commands\n\n```bash\n# Build\nnpm run build                # Build all packages\n\n# Browser tests (Cypress)\nnpm test                     # Run all tests\nnpx cypress run --spec ./tests/cypress/integration/[filename].spec.js  # Run single spec\n\n# Unit tests (Vitest)\nnpx vitest run tests/vitest/[filename].spec.js  # Run single spec\n\n# Review PRs\ngh pr list                   # List open PRs\ngh pr view [number]          # View PR details\ngh pr diff [number]          # View code changes\ngh pr checks [number]        # Check CI status\n```\n\n## Manual Testing\n\n1. Edit `./index.html` at project root\n2. Open in browser at `http://alpine.test/` (assumes local dev server mapped to directory name)\n\n## Summary\n\nAfter assessing the pull request on the above qualities, provide a summary explaining the problem this PR addresses and the fix, and why it's a good or bad fix. Do it in plain language as if you are personally advising me on what the PR is and weather or not I should merge it. And if not, what might need to be addressed first. If things need to be addressed, offer to address them yourself.\n\nPlease use code snippets to establish a starting point and and ending point if helpful. For example, when explaining the problem, it is often easier to provide a brief explanation alongside a code snippet of what is currently problematic, then when explaining the solution, showing what new code will allow a fix if applicable.","packages/docs/package.json":"{\n    \"name\": \"@alpinejs/docs\",\n    \"version\": \"3.17.5\",\n    \"description\": \"The documentation for Alpine\",\n    \"repository\": {\n        \"type\": \"git\",\n        \"url\": \"https://github.com/alpinejs/alpine.git\",\n        \"directory\": \"packages/docs\"\n    },\n    \"author\": \"Caleb Porzio\",\n    \"license\": \"MIT\"\n}\n","packages/docs/src/en/advanced.md":"---\norder: 8\ntitle: Advanced\ntype: sub-directory\n---\n","packages/docs/src/en/advanced/async.md":"---\norder: 4\ntitle: Async\n---\n\n# Async\n\nAlpine is built to support asynchronous functions in most places it supports standard ones.\n\nFor example, let's say you have a simple function called `getLabel()` that you use as the input to an `x-text` directive:\n\n```js\nfunction getLabel() {\n    return 'Hello World!'\n}\n```\n```alpine\n<span x-text=\"getLabel()\"></span>\n```\n\nBecause `getLabel` is synchronous, everything works as expected.\n\nNow let's pretend that `getLabel` makes a network request to retrieve the label and can't return one instantaneously (asynchronous). By making `getLabel` an async function, you can call it from Alpine using JavaScript's `await` syntax.\n\n```js\nasync function getLabel() {\n    let response = await fetch('/api/label')\n\n    return await response.text()\n}\n```\n```alpine\n<span x-text=\"await getLabel()\"></span>\n```\n\nAdditionally, if you prefer calling methods in Alpine without the trailing parenthesis, you can leave them out and Alpine will detect that the provided function is async and handle it accordingly. For example:\n\n```alpine\n<span x-text=\"getLabel\"></span>\n```\n","packages/docs/src/en/advanced/csp.md":"---\norder: 1\ntitle: CSP\n---\n\n# CSP (Content-Security Policy) Build\n\nIn order for Alpine to execute JavaScript expressions from HTML attributes like `x-on:click=\"console.log()\"`, it needs to use utilities that violate the \"unsafe-eval\" [Content Security Policy](https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP) that some applications enforce for security purposes.\n\n> Under the hood, Alpine doesn't actually use eval() itself because it's slow and problematic. Instead it uses Function declarations, which are much better, but still violate \"unsafe-eval\".\n\nAlpine offers an alternate build that doesn't violate \"unsafe-eval\" and supports most of Alpine's inline expression syntax.\n\n<a name=\"installation\"></a>\n## Installation\n\nYou can use this build by either including it from a `<script>` tag or installing it via NPM:\n\n### Via CDN\n\nYou can include this build's CDN as a `<script>` tag just like you would normally with standard Alpine build:\n\n```alpine\n<!-- Alpine's CSP-friendly Core -->\n<script defer src=\"https://cdn.jsdelivr.net/npm/@alpinejs/csp@3.x.x/dist/cdn.min.js\"></script>\n```\n\n### Via NPM\n\nYou can alternatively install this build from NPM for use inside your bundle like so:\n\n```shell\nnpm install @alpinejs/csp\n```\n\nThen initialize it from your bundle:\n\n```js\nimport Alpine from '@alpinejs/csp'\n\nwindow.Alpine = Alpine\n\nAlpine.start()\n```\n\n<a name=\"basic-example\"></a>\n## Basic Example\n\nHere's a working counter component using Alpine's CSP build. Notice how most expressions work exactly like regular Alpine:\n\n```alpine\n<html>\n    <head>\n        <meta http-equiv=\"Content-Security-Policy\" content=\"default-src 'self'; script-src 'nonce-a23gbfz9e'\">\n        <script defer nonce=\"a23gbfz9e\" src=\"https://cdn.jsdelivr.net/npm/@alpinejs/csp@3.x.x/dist/cdn.min.js\"></script>\n    </head>\n    <body>\n        <div x-data=\"{ count: 0, message: 'Hello' }\">\n            <button x-on:click=\"count++\">Increment</button>\n            <button x-on:click=\"count = 0\">Reset</button>\n\n            <span x-text=\"count\"></span>\n            <span x-text=\"message + ' World'\"></span>\n            <span x-show=\"count > 5\">Count is greater than 5!</span>\n        </div>\n    </body>\n</html>\n```\n\n<a name=\"whats-supported\"></a>\n## What's Supported\n\nThe CSP build supports most JavaScript expressions you'd want to use in Alpine:\n\n### Object and Array Literals\n```alpine\n<!-- ✅ These work -->\n<div x-data=\"{ user: { name: 'John', age: 30 }, items: [1, 2, 3] }\">\n    <span x-text=\"user.name\"></span>\n    <span x-text=\"items[0]\"></span>\n</div>\n```\n\n### Basic Operations\n```alpine\n<!-- ✅ These work -->\n<div x-data=\"{ count: 5, name: 'Alpine' }\">\n    <span x-text=\"count + 10\"></span>\n    <span x-text=\"count > 3\"></span>\n    <span x-text=\"count === 5 ? 'Yes' : 'No'\"></span>\n    <span x-text=\"'Hello ' + name\"></span>\n    <div x-show=\"!loading && count > 0\"></div>\n</div>\n```\n\n### Assignments and Updates\n```alpine\n<!-- ✅ These work -->\n<div x-data=\"{ count: 0, user: { name: '' } }\">\n    <button x-on:click=\"count++\">Increment</button>\n    <button x-on:click=\"count = 0\">Reset</button>\n    <input x-model=\"user.name\">\n</div>\n```\n\n### Method Calls\n```alpine\n<!-- ✅ These work -->\n<div x-data=\"{ items: ['a', 'b'] }\">\n    <button x-on:click=\"items.push('c')\">Add Item</button>\n</div>\n```\n\n<a name=\"whats-not-supported\"></a>\n## What's Not Supported\n\nSome advanced and potentially dangerous JavaScript features aren't supported:\n\n### Complex Expressions\n```alpine\n<!-- ❌ These don't work -->\n<div x-data=\"{ user: { name: '' } }\">\n    <!-- Property assignments -->\n    <button x-on:click=\"user.name = 'John'\">Bad</button>\n\n    <!-- Arrow functions -->\n    <button x-on:click=\"() => console.log('hi')\">Bad</button>\n\n    <!-- Destructuring -->\n    <div x-text=\"{ name } = user\">Bad</div>\n\n    <!-- Template literals -->\n    <div x-text=\"`Hello ${name}`\">Bad</div>\n\n    <!-- Spread operator -->\n    <div x-data=\"{ ...defaults }\">Bad</div>\n</div>\n```\n\n### Global Variables and Functions\n```alpine\n<!-- ❌ These don't work -->\n<div x-data>\n    <button x-on:click=\"console.log('hi')\"></button>\n    <span x-text=\"document.title\"></span>\n    <span x-text=\"window.innerWidth\"></span>\n    <span x-text=\"Math.max(count, 100)\"></span>\n    <span x-text=\"parseInt('123') + count\"></span>\n    <span x-text=\"JSON.stringify({ value: count })\"></span>\n</div>\n```\n\n### HTML Injection\n```alpine\n<!-- ❌ These don't work -->\n<div x-data=\"{ message: 'Hello <span>World</span>' }\">\n    <span x-html=\"message\"></span>\n    <span x-init=\"$el.insertAdjacentHTML('beforeend', message)\"></span>\n</div>\n```\n\n<a name=\"when-to-extract-logic\"></a>\n## When to Extract Logic\n\nWhile the CSP build supports simple inline expressions, you'll want to extract complex logic into dedicated functions or Alpine.data() components for better organization:\n\n```alpine\n<!-- Instead of this -->\n<div x-data=\"{ users: [] }\" x-show=\"users.filter(u => u.active && u.role === 'admin').length > 0\">\n```\n\n```alpine\n<!-- Do this -->\n<div x-data=\"userManager\" x-show=\"hasActiveAdmins\">\n\n<script nonce=\"...\">\n    Alpine.data('userManager', () => ({\n        users: [],\n\n        get hasActiveAdmins() {\n            return this.users.filter(u => u.active && u.role === 'admin').length > 0\n        }\n    }))\n</script>\n```\n\nThis approach makes your code more readable, testable, and maintainable, especially for complex applications.\n\n<a name=\"csp-headers\"></a>\n## CSP Headers\n\nHere's an example CSP header that works with Alpine's CSP build:\n\n```\nContent-Security-Policy: default-src 'self'; script-src 'nonce-[random]' 'strict-dynamic';\n```\n\nThe key is removing `'unsafe-eval'` from your `script-src` directive while still allowing your nonce-based scripts to run.","packages/docs/src/en/advanced/extending.md":"---\norder: 3\ntitle: Extending\n---\n\n# Extending\n\nAlpine has a very open codebase that allows for extension in a number of ways. In fact, every available directive and magic in Alpine itself uses these exact APIs. In theory you could rebuild all of Alpine's functionality using them yourself.\n\n<a name=\"lifecycle-concerns\"></a>\n## Lifecycle concerns\nBefore we dive into each individual API, let's first talk about where in your codebase you should consume these APIs.\n\nBecause these APIs have an impact on how Alpine initializes the page, they must be registered AFTER Alpine is downloaded and available on the page, but BEFORE it has initialized the page itself.\n\nThere are two different techniques depending on if you are importing Alpine into a bundle, or including it directly via a `<script>` tag. Let's look at them both:\n\n<a name=\"via-script-tag\"></a>\n### Via a script tag\n\nIf you are including Alpine via a script tag, you will need to register any custom extension code inside an `alpine:init` event listener.\n\nHere's an example:\n\n```alpine\n<html>\n    <script src=\"/js/alpine.js\" defer></script>\n\n    <div x-data x-foo></div>\n\n    <script>\n        document.addEventListener('alpine:init', () => {\n            Alpine.directive('foo', ...)\n        })\n    </script>\n</html>\n```\n\nIf you want to extract your extension code into an external file, you will need to make sure that file's `<script>` tag is located BEFORE Alpine's like so:\n\n```alpine\n<html>\n    <script src=\"/js/foo.js\" defer></script>\n    <script src=\"/js/alpine.js\" defer></script>\n\n    <div x-data x-foo></div>\n</html>\n```\n\n<a name=\"via-npm\"></a>\n### Via an NPM module\n\nIf you imported Alpine into a bundle, you have to make sure you are registering any extension code IN BETWEEN when you import the `Alpine` global object, and when you initialize Alpine by calling `Alpine.start()`. For example:\n\n```js\nimport Alpine from 'alpinejs'\n\nAlpine.directive('foo', ...)\n\nwindow.Alpine = Alpine\nwindow.Alpine.start()\n```\n\nNow that we know where to use these extension APIs, let's look more closely at how to use each one:\n\n<a name=\"custom-directives\"></a>\n## Custom directives\n\nAlpine allows you to register your own custom directives using the `Alpine.directive()` API.\n\n<a name=\"method-signature\"></a>\n### Method Signature\n\n```js\nAlpine.directive('[name]', (el, { value, modifiers, expression }, { Alpine, effect, cleanup }) => {})\n```\n\n&nbsp; | &nbsp;\n---|---\nname | The name of the directive. The name \"foo\" for example would be consumed as `x-foo`\nel | The DOM element the directive is added to\nvalue | If provided, the part of the directive after a colon. Ex: `'bar'` in `x-foo:bar`\nmodifiers | An array of dot-separated trailing additions to the directive. Ex: `['baz', 'lob']` from `x-foo.baz.lob`\nexpression | The attribute value portion of the directive. Ex: `law` from `x-foo=\"law\"`\nAlpine | The Alpine global object\neffect | A function to create reactive effects that will auto-cleanup after this directive is removed from the DOM\ncleanup | A function you can pass bespoke callbacks to that will run when this directive is removed from the DOM\n\n<a name=\"simple-example\"></a>\n### Simple Example\n\nHere's an example of a simple directive we're going to create called: `x-uppercase`:\n\n```js\nAlpine.directive('uppercase', el => {\n    el.textContent = el.textContent.toUpperCase()\n})\n```\n```alpine\n<div x-data>\n    <span x-uppercase>Hello World!</span>\n</div>\n```\n\n<a name=\"evaluating-expressions\"></a>\n### Evaluating expressions\n\nWhen registering a custom directive, you may want to evaluate a user-supplied JavaScript expression:\n\nFor example, let's say you wanted to create a custom directive as a shortcut to `console.log()`. Something like:\n\n```alpine\n<div x-data=\"{ message: 'Hello World!' }\">\n    <div x-log=\"message\"></div>\n</div>\n```\n\nYou need to retrieve the actual value of `message` by evaluating it as a JavaScript expression with the `x-data` scope.\n\nFortunately, Alpine exposes its system for evaluating JavaScript expressions with an `evaluate()` API. Here's an example:\n\n```js\nAlpine.directive('log', (el, { expression }, { evaluate }) => {\n    // expression === 'message'\n\n    console.log(\n        evaluate(expression)\n    )\n})\n```\n\nNow, when Alpine initializes the `<div x-log...>`, it will retrieve the expression passed into the directive (\"message\" in this case), and evaluate it in the context of the current element's Alpine component scope.\n\n<a name=\"introducing-reactivity\"></a>\n### Introducing reactivity\n\nBuilding on the `x-log` example from before, let's say we wanted `x-log` to log the value of `message` and also log it if the value changes.\n\nGiven the following template:\n\n```alpine\n<div x-data=\"{ message: 'Hello World!' }\">\n    <div x-log=\"message\"></div>\n\n    <button @click=\"message = 'yolo'\">Change</button>\n</div>\n```\n\nWe want \"Hello World!\" to be logged initially, then we want \"yolo\" to be logged after pressing the `<button>`.\n\nWe can adjust the implementation of `x-log` and introduce two new APIs to achieve this: `evaluateLater()` and `effect()`:\n\n```js\nAlpine.directive('log', (el, { expression }, { evaluateLater, effect }) => {\n    let getThingToLog = evaluateLater(expression)\n\n    effect(() => {\n        getThingToLog(thingToLog => {\n            console.log(thingToLog)\n        })\n    })\n})\n```\n\nLet's walk through the above code, line by line.\n\n```js\nlet getThingToLog = evaluateLater(expression)\n```\n\nHere, instead of immediately evaluating `message` and retrieving the result, we will convert the string expression (\"message\") into an actual JavaScript function that we can run at any time. If you're going to evaluate a JavaScript expression more than once, it is highly recommended to first generate a JavaScript function and use that rather than calling `evaluate()` directly. The reason being that the process to interpret a plain string as a JavaScript function is expensive and should be avoided when unnecessary.\n\n```js\neffect(() => {\n    ...\n})\n```\n\nBy passing in a callback to `effect()`, we are telling Alpine to run the callback immediately, then track any dependencies it uses (`x-data` properties like `message` in our case). Now as soon as one of the dependencies changes, this callback will be re-run. This gives us our \"reactivity\".\n\nYou may recognize this functionality from `x-effect`. It is the same mechanism under the hood.\n\nYou may also notice that `Alpine.effect()` exists and wonder why we're not using it here. The reason is that the `effect` function provided via the method parameter has special functionality that cleans itself up when the directive is removed from the page for any reason.\n\nFor example, if for some reason the element with `x-log` on it got removed from the page, by using `effect()` instead of `Alpine.effect()` when the `message` property is changed, the value will no longer be logged to the console.\n\n[→ Read more about reactivity in Alpine](/advanced/reactivity)\n\n```js\ngetThingToLog(thingToLog => {\n    console.log(thingToLog)\n})\n```\n\nNow we will call `getThingToLog`, which if you recall is the actual JavaScript function version of the string expression: \"message\".\n\nYou might expect `getThingToCall()` to return the result right away, but instead Alpine requires you to pass in a callback to receive the result.\n\nThe reason for this is to support async expressions like `await getMessage()`. By passing in a \"receiver\" callback instead of getting the result immediately, you are allowing your directive to work with async expressions as well.\n\n[→ Read more about async in Alpine](/advanced/async)\n\n<a name=\"cleaning-up\"></a>\n### Cleaning Up\n\nLet's say you needed to register an event listener from a custom directive. After that directive is removed from the page for any reason, you would want to remove the event listener as well.\n\nAlpine makes this simple by providing you with a `cleanup` function when registering custom directives.\n\nHere's an example:\n\n```js\nAlpine.directive('...', (el, {}, { cleanup }) => {\n    let handler = () => {}\n\n    window.addEventListener('click', handler)\n\n    cleanup(() => {\n        window.removeEventListener('click', handler)\n    })\n\n})\n```\n\nNow if the directive is removed from this element or the element is removed itself, the event listener will be removed as well.\n\n<a name=\"custom-order\"></a>\n### Custom order\n\nBy default, any new directive will run after the majority of the standard ones (with the exception of `x-teleport`). This is usually acceptable but some times you might need to run your custom directive before another specific one.\nThis can be achieved by chaining the `.before() function to `Alpine.directive()` and specifying which directive needs to run after your custom one.\n\n```js\nAlpine.directive('foo', (el, { value, modifiers, expression }) => {\n    Alpine.addScopeToNode(el, {foo: 'bar'})\n}).before('bind')\n```\n```alpine\n<div x-data>\n    <span x-foo x-bind:foo=\"foo\"></span>\n</div>\n```\n> Note, the directive name must be written without the `x-` prefix (or any other custom prefix you may use).\n\n<a name=\"custom-magics\"></a>\n## Custom magics\n\nAlpine allows you to register custom \"magics\" (properties or methods) using `Alpine.magic()`. Any magic you register will be available to all your application's Alpine code with the `$` prefix.\n\n<a name=\"method-signature\"></a>\n### Method Signature\n\n```js\nAlpine.magic('[name]', (el, { Alpine }) => {})\n```\n\n&nbsp; | &nbsp;\n---|---\nname | The name of the magic. The name \"foo\" for example would be consumed as `$foo`\nel | The DOM element the magic was triggered from\nAlpine | The Alpine global object\n\n<a name=\"magic-properties\"></a>\n### Magic Properties\n\nHere's a basic example of a \"$now\" magic helper to easily get the current time from anywhere in Alpine:\n\n```js\nAlpine.magic('now', () => {\n    return (new Date).toLocaleTimeString()\n})\n```\n```alpine\n<span x-text=\"$now\"></span>\n```\n\nNow the `<span>` tag will contain the current time, resembling something like \"12:00:00 PM\".\n\nAs you can see `$now` behaves like a static property, but under the hood is actually a getter that evaluates every time the property is accessed.\n\nBecause of this, you can implement magic \"functions\" by returning a function from the getter.\n\n<a name=\"magic-functions\"></a>\n### Magic Functions\n\nFor example, if we wanted to create a `$clipboard()` magic function that accepts a string to copy to clipboard, we could implement it like so:\n\n```js\nAlpine.magic('clipboard', () => {\n    return subject => navigator.clipboard.writeText(subject)\n})\n```\n```alpine\n<button @click=\"$clipboard('hello world')\">Copy \"Hello World\"</button>\n```\n\nNow that accessing `$clipboard` returns a function itself, we can immediately call it and pass it an argument like we see in the template with `$clipboard('hello world')`.\n\nYou can use the more brief syntax (a double arrow function) for returning a function from a function if you'd prefer:\n\n```js\nAlpine.magic('clipboard', () => subject => {\n    navigator.clipboard.writeText(subject)\n})\n```\n\n<a name=\"writing-and-sharing-plugins\"></a>\n## Writing and sharing plugins\n\nBy now you should see how friendly and simple it is to register your own custom directives and magics in your application, but what about sharing that functionality with others via an NPM package or something?\n\nYou can get started quickly with Alpine's official \"plugin-blueprint\" package. It's as simple as cloning the repository and running `npm install && npm run build` to get a plugin authored.\n\nFor demonstration purposes, let's create a pretend Alpine plugin from scratch called `Foo` that includes both a directive (`x-foo`) and a magic (`$foo`).\n\nWe'll start producing this plugin for consumption as a simple `<script>` tag alongside Alpine, then we'll level it up to a module for importing into a bundle:\n\n<a name=\"script-include\"></a>\n### Script include\n\nLet's start in reverse by looking at how our plugin will be included into a project:\n\n```alpine\n<html>\n    <script src=\"/js/foo.js\" defer></script>\n    <script src=\"/js/alpine.js\" defer></script>\n\n    <div x-data x-init=\"$foo()\">\n        <span x-foo=\"'hello world'\">\n    </div>\n</html>\n```\n\nNotice how our script is included BEFORE Alpine itself. This is important, otherwise, Alpine would have already been initialized by the time our plugin got loaded.\n\nNow let's look inside of `/js/foo.js`'s contents:\n\n```js\ndocument.addEventListener('alpine:init', () => {\n    window.Alpine.directive('foo', ...)\n\n    window.Alpine.magic('foo', ...)\n})\n```\n\nThat's it! Authoring a plugin for inclusion via a script tag is extremely simple with Alpine.\n\n<a name=\"bundle-module\"></a>\n### Bundle module\n\nNow let's say you wanted to author a plugin that someone could install via NPM and include into their bundle.\n\nLike the last example, we'll walk through this in reverse, starting with what it will look like to consume this plugin:\n\n```js\nimport Alpine from 'alpinejs'\n\nimport foo from 'foo'\nAlpine.plugin(foo)\n\nwindow.Alpine = Alpine\nwindow.Alpine.start()\n```\n\nYou'll notice a new API here: `Alpine.plugin()`. This is a convenience method Alpine exposes to prevent consumers of your plugin from having to register multiple different directives and magics themselves.\n\nNow let's look at the source of the plugin and what gets exported from `foo`:\n\n```js\nexport default function (Alpine) {\n    Alpine.directive('foo', ...)\n    Alpine.magic('foo', ...)\n}\n```\n\nYou'll see that `Alpine.plugin` is incredibly simple. It accepts a callback and immediately invokes it while providing the `Alpine` global as a parameter for use inside of it.\n\nThen you can go about extending Alpine as you please.\n\n<a name=\"deferring-initialization\"></a>\n## Deferring initialization\n\nAlpine initializes a tree of elements synchronously. Integrations that load JavaScript for a component asynchronously — a script module that registers an `Alpine.data()` provider, for example — can lose that race: Alpine evaluates `x-data=\"someComponent\"` before the registration exists.\n\n`Alpine.deferInit(el, promise)` suspends initialization of one element's tree until a promise settles. Nothing inside the tree initializes while it's suspended: directives don't evaluate, nodes added inside it wait, and attribute changes are held and replayed when the tree resumes. The rest of the page initializes normally.\n\n```js\nAlpine.interceptInit(el => {\n    if (el.hasAttribute('data-widget') && ! widgetIsLoaded(el)) {\n        Alpine.deferInit(el, loadWidget(el))\n    }\n})\n```\n\n(`Alpine.interceptInit()` is Alpine's low-level integration hook — its callback runs for every element just before that element initializes.)\n\nA few things to know about the contract:\n\n- Registering must happen synchronously — from an `Alpine.interceptInit()` callback before the element initializes, or on an already-initialized element to suspend future activity in its tree (a morph that's about to bring in new markup, for example).\n- Calling `deferInit()` on the same element again before it resumes adds another prerequisite: the tree initializes after every registered promise settles.\n- A rejected promise is reported through Alpine's error handler, then the tree initializes anyway — a failed prerequisite never leaves a tree permanently suspended.\n- If the element has left the DOM by the time the promise settles, nothing happens. If it re-enters later, it initializes like any other added node.\n- When a suspended tree resumes, init interceptors run again for elements that hadn't initialized yet. Only defer while your prerequisite is still outstanding — like the `widgetIsLoaded()` check above — so the resume pass initializes normally instead of suspending again.\n- `[x-cloak]` attributes inside a suspended tree stay in place until it resumes, so the existing cloaking pattern hides not-yet-ready content.\n- `alpine:initialized` does not wait for suspended trees — it fires when the synchronous pass over the page completes.\n- The promise is expected to settle. A prerequisite that never settles leaves its tree suspended indefinitely — put timeouts on operations that need them before handing the promise to Alpine.\n","packages/docs/src/en/advanced/reactivity.md":"---\norder: 2\ntitle: Reactivity\n---\n\n# Reactivity\n\nAlpine is \"reactive\" in the sense that when you change a piece of data, everything that depends on that data \"reacts\" automatically to that change.\n\nEvery bit of reactivity that takes place in Alpine, happens because of two very important reactive functions in Alpine's core: `Alpine.reactive()`, and `Alpine.effect()`.\n\n> Alpine uses VueJS's reactivity engine under the hood to provide these functions.\n> [→ Browse the @vue/reactivity source](https://github.com/vuejs/core/tree/main/packages/reactivity)\n\nUnderstanding these two functions will give you super powers as an Alpine developer, but also just as a web developer in general.\n\n<a name=\"alpine-reactive\"></a>\n## Alpine.reactive()\n\nLet's first look at `Alpine.reactive()`. This function accepts a JavaScript object as its parameter and returns a \"reactive\" version of that object. For example:\n\n```js\nlet data = { count: 1 }\n\nlet reactiveData = Alpine.reactive(data)\n```\n\nUnder the hood, when `Alpine.reactive` receives `data`, it wraps it inside a custom JavaScript proxy.\n\nA proxy is a special kind of object in JavaScript that can intercept \"get\" and \"set\" calls to a JavaScript object.\n\n[→ Read more about JavaScript proxies](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy)\n\nAt face value, `reactiveData` should behave exactly like `data`. For example:\n\n```js\nconsole.log(data.count) // 1\nconsole.log(reactiveData.count) // 1\n\nreactiveData.count = 2\n\nconsole.log(data.count) // 2\nconsole.log(reactiveData.count) // 2\n```\n\nWhat you see here is that because `reactiveData` is a thin wrapper around `data`, any attempts to get or set a property will behave exactly as if you had interacted with `data` directly.\n\nThe main difference here is that any time you modify or retrieve (get or set) a value from `reactiveData`, Alpine is aware of it and can execute any other logic that depends on this data.\n\n`Alpine.reactive` is only the first half of the story. `Alpine.effect` is the other half, let's dig in.\n\n<a name=\"alpine-effect\"></a>\n## Alpine.effect()\n\n`Alpine.effect` accepts a single callback function. As soon as `Alpine.effect` is called, it runs the provided function and watches for reads from reactive data. Each reactive property read during that execution becomes a dependency. When one of those properties changes later, Alpine runs the callback again. For example:\n\n```js\nlet data = Alpine.reactive({ count: 1 })\n\nAlpine.effect(() => {\n    console.log(data.count)\n})\n```\n\nWhen this code is first run, \"1\" will be logged to the console. Any time `data.count` changes, its value will be logged to the console again.\n\nThis is the mechanism that unlocks all of the reactivity at the core of Alpine.\n\n### How dependency tracking works\n\nDependency collection happens while the effect callback is running. Reading `data.count` inside the callback registers that property with the effect. Changing `data.count` later notifies the effect, which runs again and collects the dependencies used by that execution.\n\nReads made after the callback has returned, such as inside a `setTimeout` callback, are not automatically tracked by the original effect.\n\nAlpine delegates this behavior to Vue's reactivity package. For a deeper explanation of the proxy, dependency-map, and `track`/`trigger` model, see [Vue's reactivity internals](https://frontendatlas.com/vue/trivia/vue-reactivity-system).\n\nTo connect the dots further, let's look at a simple \"counter\" component example without using Alpine syntax at all, only using `Alpine.reactive` and `Alpine.effect`:\n\n```alpine\n<button>Increment</button>\n\nCount: <span></span>\n```\n```js\nlet button = document.querySelector('button')\nlet span = document.querySelector('span')\n\nlet data = Alpine.reactive({ count: 1 })\n\nAlpine.effect(() => {\n    span.textContent = data.count\n})\n\nbutton.addEventListener('click', () => {\n    data.count = data.count + 1\n})\n```\n\n<!-- START_VERBATIM -->\n<div x-data=\"{ count: 1 }\" class=\"demo\">\n    <button @click=\"count++\">Increment</button>\n\n    <div>Count: <span x-text=\"count\"></span></div>\n</div>\n<!-- END_VERBATIM -->\n\nAs you can see, you can make any data reactive, and you can also wrap any functionality in `Alpine.effect`.\n\nThis combination unlocks an incredibly powerful programming paradigm for web development. Run wild and free.\n","packages/docs/src/en/directives.md":"---\norder: 4\ntitle: Directives\nprefix: x-\nfont-type: mono\ntype: sub-directory\n---\n","packages/docs/src/en/directives/bind.md":"---\norder: 4\ntitle: bind\n---\n\n# x-bind\n\n`x-bind` allows you to set HTML attributes on elements based on the result of JavaScript expressions.\n\nFor example, here's a component where we will use `x-bind` to set the placeholder value of an input.\n\n```alpine\n<div x-data=\"{ placeholderText: 'Type here...' }\">\n    <input type=\"text\" x-bind:placeholder=\"placeholderText\">\n</div>\n```\n\n<a name=\"shorthand-syntax\"></a>\n## Shorthand syntax\n\nIf `x-bind:` is too verbose for your liking, you can use the shorthand: `:`. For example, here is the same input element as above, but refactored to use the shorthand syntax.\n\n```alpine\n<input type=\"text\" :placeholder=\"placeholderText\">\n```\n\n> Despite not being included in the above snippet, `x-bind` cannot be used if no parent element has `x-data` defined. [→ Read more about `x-data`](/directives/data)\n\n<a name=\"binding-classes\"></a>\n## Binding classes\n\n`x-bind` is most often useful for setting specific classes on an element based on your Alpine state.\n\nHere's a simple example of a simple dropdown toggle, but instead of using `x-show`, we'll use a \"hidden\" class to toggle an element.\n\n```alpine\n<div x-data=\"{ open: false }\">\n    <button x-on:click=\"open = ! open\">Toggle Dropdown</button>\n\n    <div :class=\"open ? '' : 'hidden'\">\n        Dropdown Contents...\n    </div>\n</div>\n```\n\nNow, when `open` is `false`, the \"hidden\" class will be added to the dropdown.\n\n<a name=\"shorthand-conditionals\"></a>\n### Shorthand conditionals\n\nIn cases like these, if you prefer a less verbose syntax you can use JavaScript's short-circuit evaluation instead of standard conditionals:\n\n```alpine\n<div :class=\"show ? '' : 'hidden'\">\n<!-- Is equivalent to: -->\n<div :class=\"show || 'hidden'\">\n```\n\nThe inverse is also available to you. Suppose instead of `open`, we use a variable with the opposite value: `closed`.\n\n```alpine\n<div :class=\"closed ? 'hidden' : ''\">\n<!-- Is equivalent to: -->\n<div :class=\"closed && 'hidden'\">\n```\n\n<a name=\"class-object-syntax\"></a>\n### Class object syntax\n\nAlpine offers an additional syntax for toggling classes if you prefer. By passing a JavaScript object where the classes are the keys and booleans are the values, Alpine will know which classes to apply and which to remove. For example:\n\n```alpine\n<div :class=\"{ 'hidden': ! show }\">\n```\n\nThis technique offers a unique advantage to other methods. When using object-syntax, Alpine will NOT preserve original classes applied to an element's `class` attribute.\n\nFor example, if you wanted to apply the \"hidden\" class to an element before Alpine loads, AND use Alpine to toggle its existence you can only achieve that behavior using object-syntax:\n\n```alpine\n<div class=\"hidden\" :class=\"{ 'hidden': ! show }\">\n```\n\nIn case that confused you, let's dig deeper into how Alpine handles `x-bind:class` differently than other attributes.\n\n<a name=\"special-behavior\"></a>\n### Special behavior\n\n`x-bind:class` behaves differently than other attributes under the hood.\n\nConsider the following case.\n\n```alpine\n<div class=\"opacity-50\" :class=\"hide && 'hidden'\">\n```\n\nIf \"class\" were any other attribute, the `:class` binding would overwrite any existing class attribute, causing `opacity-50` to be overwritten by either `hidden` or `''`.\n\nHowever, Alpine treats `class` bindings differently. It's smart enough to preserve existing classes on an element.\n\nFor example, if `hide` is true, the above example will result in the following DOM element:\n\n```alpine\n<div class=\"opacity-50 hidden\">\n```\n\nIf `hide` is false, the DOM element will look like:\n\n```alpine\n<div class=\"opacity-50\">\n```\n\nThis behavior should be invisible and intuitive to most users, but it is worth mentioning explicitly for the inquiring developer or any special cases that might crop up.\n\n<a name=\"binding-styles\"></a>\n## Binding styles\n\nSimilar to the special syntax for binding classes with JavaScript objects, Alpine also offers an object-based syntax for binding `style` attributes.\n\nJust like the class objects, this syntax is entirely optional. Only use it if it affords you some advantage.\n\n```alpine\n<div :style=\"{ color: 'red', display: 'flex' }\">\n\n<!-- Will render: -->\n<div style=\"color: red; display: flex;\" ...>\n```\n\nConditional inline styling is possible using expressions just like with x-bind:class. Short circuit operators can be used here as well by using a styles object as the second operand.\n```alpine\n<div x-bind:style=\"true && { color: 'red' }\">\n\n<!-- Will render: -->\n<div style=\"color: red;\">\n```\n\nOne advantage of this approach is being able to mix it in with existing styles on an element:\n\n```alpine\n<div style=\"padding: 1rem;\" :style=\"{ color: 'red', display: 'flex' }\">\n\n<!-- Will render: -->\n<div style=\"padding: 1rem; color: red; display: flex;\" ...>\n```\n\nAnd like most expressions in Alpine, you can always use the result of a JavaScript expression as the reference:\n\n```alpine\n<div x-data=\"{ styles: { color: 'red', display: 'flex' }}\">\n    <div :style=\"styles\">\n</div>\n\n<!-- Will render: -->\n<div ...>\n    <div style=\"color: red; display: flex;\" ...>\n</div>\n```\n\n<a name=\"bind-directives\"></a>\n## Binding Alpine Directives Directly\n\n`x-bind` allows you to bind an object of different directives and attributes to an element.\n\nThe object keys can be anything you would normally write as an attribute name in Alpine. This includes Alpine directives and modifiers, but also plain HTML attributes. The object values are either plain strings, or in the case of dynamic Alpine directives, callbacks to be evaluated by Alpine.\n\n```alpine\n<div x-data=\"dropdown\">\n    <button x-bind=\"trigger\">Open Dropdown</button>\n\n    <span x-bind=\"dialogue\">Dropdown Contents</span>\n</div>\n\n<script>\n    document.addEventListener('alpine:init', () => {\n        Alpine.data('dropdown', () => ({\n            open: false,\n\n            trigger: {\n                ['x-ref']: 'trigger',\n                ['@click']() {\n                    this.open = true\n                },\n            },\n\n            dialogue: {\n                ['x-show']() {\n                    return this.open\n                },\n                ['@click.outside']() {\n                    this.open = false\n                },\n            },\n        }))\n    })\n</script>\n```\n\nThere are a couple of caveats to this usage of `x-bind`:\n\n> When the directive being \"bound\" or \"applied\" is `x-for`, you should return a normal expression string from the callback. For example: `['x-for']() { return 'item in items' }`\n","packages/docs/src/en/directives/cloak.md":"---\norder: 12\ntitle: cloak\n---\n\n# x-cloak\n\nSometimes, when you're using AlpineJS for a part of your template, there is a \"blip\" where you might see your uninitialized template after the page loads, but before Alpine loads.\n\n`x-cloak` addresses this scenario by hiding the element it's attached to until Alpine is fully loaded on the page.\n\nFor `x-cloak` to work however, you must add the following CSS to the page.\n\n```css\n[x-cloak] { display: none !important; }\n```\n\nThe following example will hide the `<span>` tag until its `x-show` is specifically set to true, preventing any \"blip\" of the hidden element onto screen as Alpine loads.\n\n```alpine\n<span x-cloak x-show=\"false\">This will not 'blip' onto screen at any point</span>\n```\n\n`x-cloak` doesn't just work on elements hidden by `x-show` or `x-if`: it also ensures that elements containing data are hidden until the data is correctly set. The following example will hide the `<span>` tag until Alpine has set its text content to the `message` property.\n\n```alpine\n<span x-cloak x-text=\"message\"></span>\n```\n\nWhen Alpine loads on the page, it removes all `x-cloak` property from the element, which also removes the `display: none;` applied by CSS, therefore showing the element.\n\n## Alternative to global syntax\n\nIf you'd like to achieve this same behavior, but avoid having to include a global style, you can use the following cool, but admittedly odd trick:\n\n```alpine\n<template x-if=\"true\">\n    <span x-text=\"message\"></span>\n</template>\n```\n\nThis will achieve the same goal as `x-cloak` by just leveraging the way `x-if` works.\n\nBecause `<template>` elements are \"hidden\" in browsers by default, you won't see the `<span>` until Alpine has had a chance to render the `x-if=\"true\"` and show it.\n\nAgain, this solution is not for everyone, but it's worth mentioning for special cases.\n","packages/docs/src/en/directives/data.md":"---\norder: 1\ntitle: data\n---\n\n# x-data\n\nEverything in Alpine starts with the `x-data` directive.\n\n`x-data` defines a chunk of HTML as an Alpine component and provides the reactive data for that component to reference.\n\nHere's an example of a contrived dropdown component:\n\n```alpine\n<div x-data=\"{ open: false }\">\n    <button @click=\"open = ! open\">Toggle Content</button>\n\n    <div x-show=\"open\">\n        Content...\n    </div>\n</div>\n```\n\nDon't worry about the other directives in this example (`@click` and `x-show`), we'll get to those in a bit. For now, let's focus on `x-data`.\n\n<a name=\"scope\"></a>\n## Scope\n\nProperties defined in an `x-data` directive are available to all element children. Even ones inside other, nested `x-data` components.\n\nFor example:\n\n```alpine\n<div x-data=\"{ foo: 'bar' }\">\n    <span x-text=\"foo\"><!-- Will output: \"bar\" --></span>\n\n    <div x-data=\"{ bar: 'baz' }\">\n        <span x-text=\"foo\"><!-- Will output: \"bar\" --></span>\n\n        <div x-data=\"{ foo: 'bob' }\">\n            <span x-text=\"foo\"><!-- Will output: \"bob\" --></span>\n        </div>\n    </div>\n</div>\n```\n\n<a name=\"methods\"></a>\n## Methods\n\nBecause `x-data` is evaluated as a normal JavaScript object, in addition to state, you can store methods and even getters.\n\nFor example, let's extract the \"Toggle Content\" behavior into a method on  `x-data`.\n\n```alpine\n<div x-data=\"{ open: false, toggle() { this.open = ! this.open } }\">\n    <button @click=\"toggle()\">Toggle Content</button>\n\n    <div x-show=\"open\">\n        Content...\n    </div>\n</div>\n```\n\nNotice the added `toggle() { this.open = ! this.open }` method on `x-data`. This method can now be called from anywhere inside the component.\n\nYou'll also notice the usage of `this.` to access state on the object itself. This is because Alpine evaluates this data object like any standard JavaScript object with a `this` context.\n\nIf you prefer, you can leave the calling parenthesis off of the `toggle` method completely. For example:\n\n```alpine\n<!-- Before -->\n<button @click=\"toggle()\">...</button>\n\n<!-- After -->\n<button @click=\"toggle\">...</button>\n```\n\n<a name=\"getters\"></a>\n## Getters\n\nJavaScript [getters](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/get) are handy when the sole purpose of a method is to return data based on other state.\n\nThink of them like \"computed properties\" (although, they are not cached like Vue's computed properties).\n\nLet's refactor our component to use a getter called `isOpen` instead of accessing `open` directly.\n\n```alpine\n<div x-data=\"{\n    open: false,\n    get isOpen() { return this.open },\n    toggle() { this.open = ! this.open },\n}\">\n    <button @click=\"toggle()\">Toggle Content</button>\n\n    <div x-show=\"isOpen\">\n        Content...\n    </div>\n</div>\n```\n\nNotice the \"Content\" now depends on the `isOpen` getter instead of the `open` property directly.\n\nIn this case there is no tangible benefit. But in some cases, getters are helpful for providing a more expressive syntax in your components.\n\n<a name=\"data-less-components\"></a>\n## Data-less components\n\nOccasionally, you want to create an Alpine component, but you don't need any data.\n\nIn these cases, you can always pass in an empty object.\n\n```alpine\n<div x-data=\"{}\">\n```\n\nHowever, if you wish, you can also eliminate the attribute value entirely if it looks better to you.\n\n```alpine\n<div x-data>\n```\n\n<a name=\"single-element-components\"></a>\n## Single-element components\n\nSometimes you may only have a single element inside your Alpine component, like the following:\n\n```alpine\n<div x-data=\"{ open: true }\">\n    <button @click=\"open = false\" x-show=\"open\">Hide Me</button>\n</div>\n```\n\nIn these cases, you can declare `x-data` directly on that single element:\n\n```alpine\n<button x-data=\"{ open: true }\" @click=\"open = false\" x-show=\"open\">\n    Hide Me\n</button>\n```\n\n<a name=\"re-usable-data\"></a>\n## Re-usable Data\n\nIf you find yourself duplicating the contents of `x-data`, or you find the inline syntax verbose, you can extract the `x-data` object out to a dedicated component using `Alpine.data`.\n\nHere's a quick example:\n\n```alpine\n<div x-data=\"dropdown\">\n    <button @click=\"toggle\">Toggle Content</button>\n\n    <div x-show=\"open\">\n        Content...\n    </div>\n</div>\n\n<script>\n    document.addEventListener('alpine:init', () => {\n        Alpine.data('dropdown', () => ({\n            open: false,\n\n            toggle() {\n                this.open = ! this.open\n            },\n        }))\n    })\n</script>\n```\n\n[→ Read more about `Alpine.data(...)`](/globals/alpine-data)\n","packages/docs/src/en/directives/effect.md":"---\norder: 11\ntitle: effect\n---\n\n# x-effect\n\n`x-effect` is a useful directive for re-evaluating an expression when one of its dependencies change. You can think of it as a watcher where you don't have to specify what property to watch, it will watch all properties used within it.\n\nIf this definition is confusing for you, that's ok. It's better explained through an example:\n\n```alpine\n<div x-data=\"{ label: 'Hello' }\" x-effect=\"console.log(label)\">\n    <button @click=\"label += ' World!'\">Change Message</button>\n</div>\n```\n\nWhen this component is loaded, the `x-effect` expression will be run and \"Hello\" will be logged into the console.\n\nBecause Alpine knows about any property references contained within `x-effect`, when the button is clicked and `label` is changed, the effect will be re-triggered and \"Hello World!\" will be logged to the console.\n","packages/docs/src/en/directives/for.md":"---\norder: 8\ntitle: for\n---\n\n# x-for\n\nAlpine's `x-for` directive allows you to create DOM elements by iterating through a list. Here's a simple example of using it to create a list of colors based on an array.\n\n```alpine\n<ul x-data=\"{ colors: ['Red', 'Orange', 'Yellow'] }\">\n    <template x-for=\"color in colors\">\n        <li x-text=\"color\"></li>\n    </template>\n</ul>\n```\n\n<!-- START_VERBATIM -->\n<div class=\"demo\">\n    <ul x-data=\"{ colors: ['Red', 'Orange', 'Yellow'] }\">\n        <template x-for=\"color in colors\">\n            <li x-text=\"color\"></li>\n        </template>\n    </ul>\n</div>\n<!-- END_VERBATIM -->\n\nYou may also pass objects to `x-for`.\n\n```alpine\n<ul x-data=\"{ car: { make: 'Jeep', model: 'Grand Cherokee', color: 'Black' } }\">\n    <template x-for=\"(value, index) in car\">\n        <li>\n            <span x-text=\"index\"></span>: <span x-text=\"value\"></span>\n        </li>\n    </template>\n</ul>\n```\n\n<!-- START_VERBATIM -->\n<div class=\"demo\">\n    <ul x-data=\"{ car: { make: 'Jeep', model: 'Grand Cherokee', color: 'Black' } }\">\n        <template x-for=\"(value, index) in car\">\n            <li>\n                <span x-text=\"index\"></span>: <span x-text=\"value\"></span>\n            </li>\n        </template>\n    </ul>\n</div>\n<!-- END_VERBATIM -->\n\nThere are two rules worth noting about `x-for`:\n\n> `x-for` MUST be declared on a `<template>` element.\n> That `<template>` element MUST contain only one root element\n\n<a name=\"keys\"></a>\n## Keys\n\nIt is important to specify unique keys for each `x-for` iteration if you are going to be re-ordering items. Without dynamic keys, Alpine may have a hard time keeping track of what re-orders and will cause odd side-effects.\n\n```alpine\n<ul x-data=\"{ colors: [\n    { id: 1, label: 'Red' },\n    { id: 2, label: 'Orange' },\n    { id: 3, label: 'Yellow' },\n]}\">\n    <template x-for=\"color in colors\" :key=\"color.id\">\n        <li x-text=\"color.label\"></li>\n    </template>\n</ul>\n```\n\nNow if the colors are added, removed, re-ordered, or their \"id\"s change, Alpine will preserve or destroy the iterated `<li>`elements accordingly.\n\n<a name=\"accessing-indexes\"></a>\n## Accessing indexes\n\nIf you need to access the index of each item in the iteration, you can do so using the `([item], [index]) in [items]` syntax like so:\n\n```alpine\n<ul x-data=\"{ colors: ['Red', 'Orange', 'Yellow'] }\">\n    <template x-for=\"(color, index) in colors\">\n        <li>\n            <span x-text=\"index + ': '\"></span>\n            <span x-text=\"color\"></span>\n        </li>\n    </template>\n</ul>\n```\n\nYou can also access the index inside a dynamic `:key` expression.\n\n```alpine\n<template x-for=\"(color, index) in colors\" :key=\"index\">\n```\n\n<a name=\"iterating-over-a-range\"></a>\n## Iterating over a range\n\nIf you need to simply loop `n` number of times, rather than iterate through an array, Alpine offers a short syntax.\n\n```alpine\n<ul>\n    <template x-for=\"i in 10\">\n        <li x-text=\"i\"></li>\n    </template>\n</ul>\n```\n\n`i` in this case can be named anything you like.\n\n> Despite not being included in the above snippet, `x-for` cannot be used if no parent element has `x-data` defined. [→ Read more about `x-data`](/directives/data)\n\n<a name=\"contents-of-a-template\"></a>\n## Contents of a `<template>`\n\nAs mentioned above, an `<template>` tag must contain only one root element.\n\nFor example, the following code will not work:\n\n```alpine\n<template x-for=\"color in colors\">\n    <span>The next color is </span><span x-text=\"color\">\n</template>\n```\n\nbut this code will work:\n```alpine\n<template x-for=\"color in colors\">\n    <p>\n        <span>The next color is </span><span x-text=\"color\">\n    </p>\n</template>\n```\n","packages/docs/src/en/directives/html.md":"---\norder: 7\ntitle: html\n---\n\n# x-html\n\n`x-html` sets the \"innerHTML\" property of an element to the result of a given expression.\n\n> ⚠️ Only use on trusted content and never on user-provided content. ⚠️\n> Dynamically rendering HTML from third parties can easily lead to XSS vulnerabilities.\n\nHere's a basic example of using `x-html` to display a user's username.\n\n```alpine\n<div x-data=\"{ username: '<strong>calebporzio</strong>' }\">\n    Username: <span x-html=\"username\"></span>\n</div>\n```\n\n<!-- START_VERBATIM -->\n<div class=\"demo\">\n    <div x-data=\"{ username: '<strong>calebporzio</strong>' }\">\n        Username: <span x-html=\"username\"></span>\n    </div>\n</div>\n<!-- END_VERBATIM -->\n\nNow the `<span>` tag's inner HTML will be set to \"<strong>calebporzio</strong>\".\n","packages/docs/src/en/directives/id.md":"---\norder: 17\ntitle: id\n---\n\n# x-id\n\n`x-id` allows you to declare a new \"scope\" for any new IDs generated using `$id()`. It accepts an array of strings (ID names) and adds a suffix to each `$id('...')` generated within it that is unique to other IDs on the page.\n\n`x-id` is meant to be used in conjunction with the `$id(...)` magic.\n\n[Visit the $id documentation](/magics/id) for a better understanding of this feature.\n\nHere's a brief example of this directive in use:\n\n```alpine\n<div x-id=\"['text-input']\">\n    <label :for=\"$id('text-input')\">Username</label>\n    <!-- for=\"text-input-1\" -->\n\n    <input type=\"text\" :id=\"$id('text-input')\">\n    <!-- id=\"text-input-1\" -->\n</div>\n\n<div x-id=\"['text-input']\">\n    <label :for=\"$id('text-input')\">Username</label>\n    <!-- for=\"text-input-2\" -->\n\n    <input type=\"text\" :id=\"$id('text-input')\">\n    <!-- id=\"text-input-2\" -->\n</div>\n```\n\n> Despite not being included in the above snippet, `x-id` cannot be used if no parent element has `x-data` defined. [→ Read more about `x-data`](/directives/data)\n","packages/docs/src/en/directives/if.md":"---\norder: 16\ntitle: if\n---\n\n# x-if\n\n`x-if` is used for toggling elements on the page, similarly to `x-show`, however it completely adds and removes the element it's applied to rather than just changing its CSS display property to \"none\".\n\nBecause of this difference in behavior, `x-if` should not be applied directly to the element, but instead to a `<template>` tag that encloses the element. This way, Alpine can keep a record of the element once it's removed from the page.\n\n```alpine\n<template x-if=\"open\">\n    <div>Contents...</div>\n</template>\n```\n\n> Despite not being included in the above snippet, `x-if` cannot be used if no parent element has `x-data` defined. [→ Read more about `x-data`](/directives/data)\n\n## Caveats\n\nUnlike `x-show`, `x-if`, does NOT support transitioning toggles with `x-transition`.\n\n`<template>` tags can only contain one root element.\n","packages/docs/src/en/directives/ignore.md":"---\norder: 11\ntitle: ignore\n---\n\n# x-ignore\n\nBy default, Alpine will crawl and initialize the entire DOM tree of an element containing `x-init` or `x-data`.\n\nIf for some reason, you don't want Alpine to touch a specific section of your HTML, you can prevent it from doing so using `x-ignore`.\n\n```alpine\n<div x-data=\"{ label: 'From Alpine' }\">\n    <div x-ignore>\n        <span x-text=\"label\"></span>\n    </div>\n</div>\n```\n\nIn the above example, the `<span>` tag will not contain \"From Alpine\" because we told Alpine to ignore the contents of the `div` completely.\n","packages/docs/src/en/directives/init.md":"---\norder: 2\ntitle: init\n---\n\n# x-init\n\nThe `x-init` directive allows you to hook into the initialization phase of any element in Alpine.\n\n```alpine\n<div x-init=\"console.log('I\\'m being initialized!')\"></div>\n```\n\nIn the above example, \"I\\'m being initialized!\" will be output in the console before it makes further DOM updates.\n\nConsider another example where `x-init` is used to fetch some JSON and store it in `x-data` before the component is processed.\n\n```alpine\n<div\n    x-data=\"{ posts: [] }\"\n    x-init=\"posts = await (await fetch('/posts')).json()\"\n>...</div>\n```\n\n<a name=\"next-tick\"></a>\n## $nextTick\n\nSometimes, you want to wait until after Alpine has completely finished rendering to execute some code.\n\nThis would be something like `useEffect(..., [])` in react, or `mount` in Vue.\n\nBy using Alpine's internal `$nextTick` magic, you can make this happen.\n\n```alpine\n<div x-init=\"$nextTick(() => { ... })\"></div>\n```\n\n<a name=\"standalone-x-init\"></a>\n## Standalone `x-init`\n\nYou can add `x-init` to any elements inside or outside an `x-data` HTML block. For example:\n\n```alpine\n<div x-data>\n    <span x-init=\"console.log('I can initialize')\"></span>\n</div>\n\n<span x-init=\"console.log('I can initialize too')\"></span>\n```\n\n<a name=\"auto-evaluate-init-method\"></a>\n## Auto-evaluate init() method\n\nIf the `x-data` object of a component contains an `init()` method, it will be called automatically. For example:\n\n```alpine\n<div x-data=\"{\n    init() {\n        console.log('I am called automatically')\n    }\n}\">\n    ...\n</div>\n```\n\nThis is also the case for components that were registered using the `Alpine.data()` syntax.\n\n```js\nAlpine.data('dropdown', () => ({\n    init() {\n        console.log('I will get evaluated when initializing each \"dropdown\" component.')\n    },\n}))\n```\n\nIf you have both an `x-data` object containing an `init()` method and an `x-init` directive, the `x-data` method will be called before the directive.\n\n```alpine\n<div\n    x-data=\"{\n        init() {\n            console.log('I am called first')\n        }\n    }\"\n    x-init=\"console.log('I am called second')\"\n    >\n    ...\n</div>\n```\n","packages/docs/src/en/directives/model.md":"---\norder: 7\ntitle: model\n---\n\n# x-model\n\n`x-model` allows you to bind the value of an input element to Alpine data.\n\nHere's a simple example of using `x-model` to bind the value of a text field to a piece of data in Alpine.\n\n```alpine\n<div x-data=\"{ message: '' }\">\n    <input type=\"text\" x-model=\"message\">\n\n    <span x-text=\"message\"></span>\n</div>\n```\n\n<!-- START_VERBATIM -->\n<div class=\"demo\">\n    <div x-data=\"{ message: '' }\">\n        <input type=\"text\" x-model=\"message\" placeholder=\"Type message...\">\n\n        <div class=\"pt-4\" x-text=\"message\"></div>\n    </div>\n</div>\n<!-- END_VERBATIM -->\n\n\nNow as the user types into the text field, the `message` will be reflected in the `<span>` tag.\n\n`x-model` is two-way bound, meaning it both \"sets\" and \"gets\". In addition to changing data, if the data itself changes, the element will reflect the change.\n\n\nWe can use the same example as above but this time, we'll add a button to change the value of the `message` property.\n\n```alpine\n<div x-data=\"{ message: '' }\">\n    <input type=\"text\" x-model=\"message\">\n\n    <button x-on:click=\"message = 'changed'\">Change Message</button>\n</div>\n```\n\n<!-- START_VERBATIM -->\n<div class=\"demo\">\n    <div x-data=\"{ message: '' }\">\n        <input type=\"text\" x-model=\"message\" placeholder=\"Type message...\">\n\n        <button x-on:click=\"message = 'changed'\">Change Message</button>\n    </div>\n</div>\n<!-- END_VERBATIM -->\n\nNow when the `<button>` is clicked, the input element's value will instantly be updated to \"changed\".\n\n`x-model` works with the following input elements:\n\n* `<input type=\"text\">`\n* `<textarea>`\n* `<input type=\"checkbox\">`\n* `<input type=\"radio\">`\n* `<select>`\n* `<input type=\"range\">`\n\n<a name=\"text-inputs\"></a>\n## Text inputs\n\n```alpine\n<input type=\"text\" x-model=\"message\">\n\n<span x-text=\"message\"></span>\n```\n\n<!-- START_VERBATIM -->\n<div class=\"demo\">\n    <div x-data=\"{ message: '' }\">\n        <input type=\"text\" x-model=\"message\" placeholder=\"Type message\">\n\n        <div class=\"pt-4\" x-text=\"message\"></div>\n    </div>\n</div>\n<!-- END_VERBATIM -->\n\n> Despite not being included in the above snippet, `x-model` cannot be used if no parent element has `x-data` defined. [→ Read more about `x-data`](/directives/data)\n\n<a name=\"textarea-inputs\"></a>\n## Textarea inputs\n\n```alpine\n<textarea x-model=\"message\"></textarea>\n\n<span x-text=\"message\"></span>\n```\n\n<!-- START_VERBATIM -->\n<div class=\"demo\">\n    <div x-data=\"{ message: '' }\">\n        <textarea x-model=\"message\" placeholder=\"Type message\"></textarea>\n\n        <div class=\"pt-4\" x-text=\"message\"></div>\n    </div>\n</div>\n<!-- END_VERBATIM -->\n\n<a name=\"checkbox-inputs\"></a>\n## Checkbox inputs\n\n<a name=\"single-checkbox-with-boolean\"></a>\n### Single checkbox with boolean\n\n```alpine\n<input type=\"checkbox\" id=\"checkbox\" x-model=\"show\">\n\n<label for=\"checkbox\" x-text=\"show\"></label>\n```\n\n<!-- START_VERBATIM -->\n<div class=\"demo\">\n    <div x-data=\"{ open: '' }\">\n        <input type=\"checkbox\" id=\"checkbox\" x-model=\"open\">\n\n        <label for=\"checkbox\" x-text=\"open\"></label>\n    </div>\n</div>\n<!-- END_VERBATIM -->\n\n<a name=\"multiple-checkboxes-bound-to-array\"></a>\n### Multiple checkboxes bound to array\n\n```alpine\n<input type=\"checkbox\" value=\"red\" x-model=\"colors\">\n<input type=\"checkbox\" value=\"orange\" x-model=\"colors\">\n<input type=\"checkbox\" value=\"yellow\" x-model=\"colors\">\n\nColors: <span x-text=\"colors\"></span>\n```\n\n<!-- START_VERBATIM -->\n<div class=\"demo\">\n    <div x-data=\"{ colors: [] }\">\n        <input type=\"checkbox\" value=\"red\" x-model=\"colors\">\n        <input type=\"checkbox\" value=\"orange\" x-model=\"colors\">\n        <input type=\"checkbox\" value=\"yellow\" x-model=\"colors\">\n\n        <div class=\"pt-4\">Colors: <span x-text=\"colors\"></span></div>\n    </div>\n</div>\n<!-- END_VERBATIM -->\n\n<a name=\"radio-inputs\"></a>\n## Radio inputs\n\n```alpine\n<input type=\"radio\" value=\"yes\" x-model=\"answer\">\n<input type=\"radio\" value=\"no\" x-model=\"answer\">\n\nAnswer: <span x-text=\"answer\"></span>\n```\n\n<!-- START_VERBATIM -->\n<div class=\"demo\">\n    <div x-data=\"{ answer: '' }\">\n        <input type=\"radio\" value=\"yes\" x-model=\"answer\">\n        <input type=\"radio\" value=\"no\" x-model=\"answer\">\n\n        <div class=\"pt-4\">Answer: <span x-text=\"answer\"></span></div>\n    </div>\n</div>\n<!-- END_VERBATIM -->\n\n<a name=\"select-inputs\"></a>\n## Select inputs\n\n\n<a name=\"single-select\"></a>\n### Single select\n\n```alpine\n<select x-model=\"color\">\n    <option>Red</option>\n    <option>Orange</option>\n    <option>Yellow</option>\n</select>\n\nColor: <span x-text=\"color\"></span>\n```\n\n<!-- START_VERBATIM -->\n<div class=\"demo\">\n    <div x-data=\"{ color: '' }\">\n        <select x-model=\"color\">\n            <option>Red</option>\n            <option>Orange</option>\n            <option>Yellow</option>\n        </select>\n\n        <div class=\"pt-4\">Color: <span x-text=\"color\"></span></div>\n    </div>\n</div>\n<!-- END_VERBATIM -->\n\n<a name=\"single-select-with-placeholder\"></a>\n### Single select with placeholder\n\n```alpine\n<select x-model=\"color\">\n    <option value=\"\" disabled>Select A Color</option>\n    <option>Red</option>\n    <option>Orange</option>\n    <option>Yellow</option>\n</select>\n\nColor: <span x-text=\"color\"></span>\n```\n\n\n<!-- START_VERBATIM -->\n<div class=\"demo\">\n    <div x-data=\"{ color: '' }\">\n        <select x-model=\"color\">\n            <option value=\"\" disabled>Select A Color</option>\n            <option>Red</option>\n            <option>Orange</option>\n            <option>Yellow</option>\n        </select>\n\n        <div class=\"pt-4\">Color: <span x-text=\"color\"></span></div>\n    </div>\n</div>\n<!-- END_VERBATIM -->\n\n<a name=\"multiple-select\"></a>\n### Multiple select\n\n```alpine\n<select x-model=\"color\" multiple>\n    <option>Red</option>\n    <option>Orange</option>\n    <option>Yellow</option>\n</select>\n\nColors: <span x-text=\"color\"></span>\n```\n\n<!-- START_VERBATIM -->\n<div class=\"demo\">\n    <div x-data=\"{ color: '' }\">\n        <select x-model=\"color\" multiple>\n            <option>Red</option>\n            <option>Orange</option>\n            <option>Yellow</option>\n        </select>\n\n        <div class=\"pt-4\">Color: <span x-text=\"color\"></span></div>\n    </div>\n</div>\n<!-- END_VERBATIM -->\n\n<a name=\"dynamically-populated-select-options\"></a>\n### Dynamically populated Select Options\n\n```alpine\n<select x-model=\"color\">\n    <template x-for=\"color in ['Red', 'Orange', 'Yellow']\">\n        <option x-text=\"color\"></option>\n    </template>\n</select>\n\nColor: <span x-text=\"color\"></span>\n```\n\n<!-- START_VERBATIM -->\n<div class=\"demo\">\n    <div x-data=\"{ color: '' }\">\n        <select x-model=\"color\">\n            <template x-for=\"color in ['Red', 'Orange', 'Yellow']\">\n                <option x-text=\"color\"></option>\n            </template>\n        </select>\n\n        <div class=\"pt-4\">Color: <span x-text=\"color\"></span></div>\n    </div>\n</div>\n<!-- END_VERBATIM -->\n\n<a name=\"range-inputs\"></a>\n## Range inputs\n\n```alpine\n<input type=\"range\" x-model=\"range\" min=\"0\" max=\"1\" step=\"0.1\">\n\n<span x-text=\"range\"></span>\n```\n\n<!-- START_VERBATIM -->\n<div class=\"demo\">\n    <div x-data=\"{ range: 0.5 }\">\n        <input type=\"range\" x-model=\"range\" min=\"0\" max=\"1\" step=\"0.1\">\n\n        <div class=\"pt-4\" x-text=\"range\"></div>\n    </div>\n</div>\n<!-- END_VERBATIM -->\n\n\n<a name=\"modifiers\"></a>\n## Modifiers\n\n<a name=\"lazy\"></a>\n### `.lazy`\n\nOn text inputs, by default, `x-model` updates the property on every keystroke. By adding the `.lazy` modifier, you can force an `x-model` input to only update the property when user focuses away from the input element.\n\nThis is handy for things like real-time form-validation where you might not want to show an input validation error until the user \"tabs\" away from a field.\n\n```alpine\n<input type=\"text\" x-model.lazy=\"username\">\n<span x-show=\"username.length > 20\">The username is too long.</span>\n```\n\n<a name=\"change\"></a>\n### `.change`\n\n`.change` syncs the data only when the input loses focus and its value has changed (the native `change` event). This is functionally equivalent to `.lazy`.\n\n```alpine\n<input type=\"text\" x-model.change=\"username\">\n```\n\n<a name=\"blur\"></a>\n### `.blur`\n\n`.blur` syncs the data when the input loses focus, regardless of whether the value has changed.\n\n```alpine\n<input type=\"text\" x-model.blur=\"email\">\n```\n\n<a name=\"enter\"></a>\n### `.enter`\n\n`.enter` syncs the data when the user presses the Enter key. This is useful for search fields where you want to trigger an action only when the user explicitly submits.\n\n```alpine\n<input type=\"text\" x-model.enter=\"search\">\n```\n\n> Note: `.enter` does not prevent the default behavior. If the input is inside a form, the form will still submit.\n\n<a name=\"combining-event-modifiers\"></a>\n### Combining Event Modifiers\n\nThe `.change`, `.blur`, and `.enter` modifiers can be combined to sync on multiple events. This is useful when you want to give users flexibility in how they submit data.\n\n```alpine\n<!-- Sync on blur OR enter -->\n<input type=\"text\" x-model.blur.enter=\"search\" placeholder=\"Press Enter or click away\">\n\n<!-- Sync on change, blur, OR enter -->\n<input type=\"text\" x-model.change.blur.enter=\"message\">\n```\n\n<!-- START_VERBATIM -->\n<div class=\"demo\">\n    <div x-data=\"{ search: '' }\">\n        <input type=\"text\" x-model.blur.enter=\"search\" placeholder=\"Press Enter or click away\">\n\n        <div class=\"pt-4\">Search: <span x-text=\"search\"></span></div>\n    </div>\n</div>\n<!-- END_VERBATIM -->\n\n<a name=\"number\"></a>\n### `.number`\n\nBy default, any data stored in a property via `x-model` is stored as a string. To force Alpine to store the value as a JavaScript number, add the `.number` modifier.\n\n```alpine\n<input type=\"text\" x-model.number=\"age\">\n<span x-text=\"typeof age\"></span>\n```\n\n<a name=\"boolean\"></a>\n### `.boolean`\n\nBy default, any data stored in a property via `x-model` is stored as a string. To force Alpine to store the value as a JavaScript boolean, add the `.boolean` modifier. Both integers (1/0) and strings (true/false) are valid boolean values.\n\n```alpine\n<select x-model.boolean=\"isActive\">\n    <option value=\"true\">Yes</option>\n    <option value=\"false\">No</option>\n</select>\n<span x-text=\"typeof isActive\"></span>\n```\n\n<a name=\"debounce\"></a>\n### `.debounce`\n\nBy adding `.debounce` to `x-model`, you can easily debounce the updating of bound input.\n\nThis is useful for things like real-time search inputs that fetch new data from the server every time the search property changes.\n\n```alpine\n<input type=\"text\" x-model.debounce=\"search\">\n```\n\nThe default debounce time is 250 milliseconds, you can easily customize this by adding a time modifier like so.\n\n```alpine\n<input type=\"text\" x-model.debounce.500ms=\"search\">\n```\n\n<a name=\"throttle\"></a>\n### `.throttle`\n\nSimilar to `.debounce` you can limit the property update triggered by `x-model` to only updating on a specified interval.\n\n<input type=\"text\" x-model.throttle=\"search\">\n\nThe default throttle interval is 250 milliseconds, you can easily customize this by adding a time modifier like so.\n\n```alpine\n<input type=\"text\" x-model.throttle.500ms=\"search\">\n```\n\n<a name=\"fill\"></a>\n### `.fill`\n\nBy default, if an input has a value attribute, it is ignored by Alpine and instead, the value of the input is set to the value of the property bound using `x-model`.\n\nBut if a bound property is empty, then you can use an input's value attribute to populate the property by adding the `.fill` modifier.\n\n<div x-data=\"{ message: null }\">\n  <input type=\"text\" x-model.fill=\"message\" value=\"This is the default message.\">\n</div>\n\n<a name=\"programmatic access\"></a>\n## Programmatic access\n\nAlpine exposes under-the-hood utilities for getting and setting properties bound with `x-model`. This is useful for complex Alpine utilities that may want to override the default x-model behavior, or instances where you want to allow `x-model` on a non-input element.\n\nYou can access these utilities through a property called `_x_model` on the `x-model`ed element. `_x_model` has two methods to get and set the bound property:\n\n* `el._x_model.get()` (returns the value of the bound property)\n* `el._x_model.set()` (sets the value of the bound property)\n\n```alpine\n<div x-data=\"{ username: 'calebporzio' }\">\n    <div x-ref=\"div\" x-model=\"username\"></div>\n\n    <button @click=\"$refs.div._x_model.set('phantomatrix')\">\n        Change username to: 'phantomatrix'\n    </button>\n\n    <span x-text=\"$refs.div._x_model.get()\"></span>\n</div>\n```\n\n<!-- START_VERBATIM -->\n<div class=\"demo\">\n    <div x-data=\"{ username: 'calebporzio' }\">\n        <div x-ref=\"div\" x-model=\"username\"></div>\n\n        <button @click=\"$refs.div._x_model.set('phantomatrix')\">\n            Change username to: 'phantomatrix'\n        </button>\n\n        <span x-text=\"$refs.div._x_model.get()\"></span>\n    </div>\n</div>\n<!-- END_VERBATIM -->\n","packages/docs/src/en/directives/modelable.md":"---\norder: 7\ntitle: modelable\n---\n\n# x-modelable\n\n`x-modelable` allows you to expose Alpine state as the target of the `x-model` directive.\n\nHere's a simple example of using `x-modelable` to expose a variable for binding with `x-model`.\n\n```alpine\n<div x-data=\"{ number: 5 }\">\n    <div x-data=\"{ count: 0 }\" x-modelable=\"count\" x-model=\"number\">\n        <button @click=\"count++\">Increment</button>\n    </div>\n\n    Number: <span x-text=\"number\"></span>\n</div>\n```\n\n<!-- START_VERBATIM -->\n<div class=\"demo\">\n    <div x-data=\"{ number: 5 }\">\n        <div x-data=\"{ count: 0 }\" x-modelable=\"count\" x-model=\"number\">\n            <button @click=\"count++\">Increment</button>\n        </div>\n\n        Number: <span x-text=\"number\"></span>\n    </div>\n</div>\n<!-- END_VERBATIM -->\n\nAs you can see the outer scope property \"number\" is now bound to the inner scope property \"count\".\n\nTypically this feature would be used in conjunction with a backend templating framework like Laravel Blade. It's useful for abstracting away Alpine components into backend templates and exposing state to the outside through `x-model` as if it were a native input.\n\n## Supported values\n\n`x-modelable` keeps its inner and outer state independent by cloning values as JSON. It is therefore intended for JSON-compatible state such as strings, numbers, booleans, `null`, arrays, and plain objects containing those values.\n\nBrowser objects and other state that cannot be represented as JSON won't cross this boundary intact. For example, a `File` loses properties such as its name, size, and type. The same limitation applies to values such as `FileList`, `Map`, `Set`, `Date`, class instances, and DOM nodes.\n\nFor a custom input that produces one of these values, omit `x-modelable` and [dispatch an `input` event](/magics/dispatch#dispatching-to-x-model) instead. `x-model` reads the value directly from the event without cloning it:\n\n```alpine\n<div x-data=\"{ files: [] }\">\n    <div x-model=\"files\">\n        <input\n            type=\"file\"\n            multiple\n            @change=\"$dispatch('input', Array.from($event.target.files))\"\n        >\n    </div>\n\n    <template x-for=\"file in files\" :key=\"file.name\">\n        <p x-text=\"file.name\"></p>\n    </template>\n</div>\n```\n","packages/docs/src/en/directives/on.md":"---\norder: 5\ntitle: on\n---\n\n# x-on\n\n`x-on` allows you to easily run code on dispatched DOM events.\n\nHere's an example of simple button that shows an alert when clicked.\n\n```alpine\n<button x-on:click=\"alert('Hello World!')\">Say Hi</button>\n```\n\n> `x-on` can only listen for events with lower case names, as HTML attributes are case-insensitive. Writing `x-on:CLICK` will listen for an event named `click`. If you need to listen for a custom event with a camelCase name, you can use the [`.camel` helper](#camel) to work around this limitation. Alternatively, you can use [`x-bind`](/directives/bind#bind-directives) to attach an `x-on` directive to an element in javascript code (where case will be preserved).\n\n<a name=\"shorthand-syntax\"></a>\n## Shorthand syntax\n\nIf `x-on:` is too verbose for your tastes, you can use the shorthand syntax: `@`.\n\nHere's the same component as above, but using the shorthand syntax instead:\n\n```alpine\n<button @click=\"alert('Hello World!')\">Say Hi</button>\n```\n\n> Despite not being included in the above snippet, `x-on` cannot be used if no parent element has `x-data` defined. [→ Read more about `x-data`](/directives/data)\n\n<a name=\"the-event-object\"></a>\n## The event object\n\nIf you wish to access the native JavaScript event object from your expression, you can use Alpine's magic `$event` property.\n\n```alpine\n<button @click=\"alert($event.target.getAttribute('message'))\" message=\"Hello World\">Say Hi</button>\n```\n\nIn addition, Alpine also passes the event object to any methods referenced without trailing parenthesis. For example:\n\n```alpine\n<button @click=\"handleClick\">...</button>\n\n<script>\n    function handleClick(e) {\n        // Now you can access the event object (e) directly\n    }\n</script>\n```\n\n<a name=\"keyboard-events\"></a>\n## Keyboard events\n\nAlpine makes it easy to listen for `keydown` and `keyup` events on specific keys.\n\nHere's an example of listening for the `Enter` key inside an input element.\n\n```alpine\n<input type=\"text\" @keyup.enter=\"alert('Submitted!')\">\n```\n\nYou can also chain these key modifiers to achieve more complex listeners.\n\nHere's a listener that runs when the `Shift` key is held and `Enter` is pressed, but not when `Enter` is pressed alone.\n\n```alpine\n<input type=\"text\" @keyup.shift.enter=\"alert('Submitted!')\">\n```\n\nYou can directly use any valid key names exposed via [`KeyboardEvent.key`](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key/Key_Values) as modifiers by converting them to kebab-case.\n\n```alpine\n<input type=\"text\" @keyup.page-down=\"alert('Submitted!')\">\n```\n\nFor easy reference, here is a list of common keys you may want to listen for.\n\n| Modifier                       | Keyboard Key                       |\n| ------------------------------ | ---------------------------------- |\n| `.shift`                       | Shift                              |\n| `.enter`                       | Enter                              |\n| `.space`                       | Space                              |\n| `.ctrl`                        | Ctrl                               |\n| `.cmd`                         | Cmd                                |\n| `.meta`                        | Cmd on Mac, Windows key on Windows |\n| `.alt`                         | Alt                                |\n| `.up` `.down` `.left` `.right` | Up/Down/Left/Right arrows          |\n| `.escape`                      | Escape                             |\n| `.tab`                         | Tab                                |\n| `.caps-lock`                   | Caps Lock                          |\n| `.equal`                       | Equal, `=`                         |\n| `.period`                      | Period, `.`                        |\n| `.comma`                       | Comma, `,`                         |\n| `.slash`                       | Forward Slash, `/`                 |\n\n<a name=\"mouse-events\"></a>\n## Mouse events\n\nLike the above Keyboard Events, Alpine allows the use of some key modifiers for handling `click` events.\n\n| Modifier | Event Key |\n| -------- | --------- |\n| `.shift` | shiftKey  |\n| `.ctrl`  | ctrlKey   |\n| `.cmd`   | metaKey   |\n| `.meta`  | metaKey   |\n| `.alt`   | altKey    |\n\nThese work on `click`, `auxclick`, `context` and `dblclick` events, and even `mouseover`, `mousemove`, `mouseenter`, `mouseleave`, `mouseout`, `mouseup` and `mousedown`.\n\nHere's an example of a button that changes behaviour when the `Shift` key is held down.\n\n```alpine\n<button type=\"button\"\n    x-data=\"{ message: 'select' }\"\n    @click=\"message = 'selected'\"\n    @click.shift=\"message = 'added to selection'\"\n    @mousemove.shift=\"message = 'add to selection'\"\n    @mouseout=\"message = 'select'\"\n    x-text=\"message\"></button>\n```\n\n<!-- START_VERBATIM -->\n<div class=\"demo\">\n    <div x-data=\"{ message: '' }\">\n        <button type=\"button\"\n            x-data=\"{ message: 'select' }\"\n            @click=\"message = 'selected'\"\n            @click.shift=\"message = 'added to selection'\"\n            @mousemove.shift=\"message = 'add to selection'\"\n            @mouseout=\"message = 'select'\"\n            x-text=\"message\"></button>\n    </div>\n</div>\n<!-- END_VERBATIM -->\n\n> Note: Normal click events with some modifiers (like `ctrl`) will automatically become `contextmenu` events in most browsers. Similarly, `right-click` events will trigger a `contextmenu` event, but will also trigger an `auxclick` event if the `contextmenu` event is prevented.\n\n<a name=\"custom-events\"></a>\n## Custom events\n\nAlpine event listeners are a wrapper for native DOM event listeners. Therefore, they can listen for ANY DOM event, including custom events.\n\nHere's an example of a component that dispatches a custom DOM event and listens for it as well.\n\n```alpine\n<div x-data @foo=\"alert('Button Was Clicked!')\">\n    <button @click=\"$event.target.dispatchEvent(new CustomEvent('foo', { bubbles: true }))\">...</button>\n</div>\n```\n\nWhen the button is clicked, the `@foo` listener will be called.\n\nBecause the `.dispatchEvent` API is verbose, Alpine offers a `$dispatch` helper to simplify things.\n\nHere's the same component re-written with the `$dispatch` magic property.\n\n```alpine\n<div x-data @foo=\"alert('Button Was Clicked!')\">\n    <button @click=\"$dispatch('foo')\">...</button>\n</div>\n```\n\n[→ Read more about `$dispatch`](/magics/dispatch)\n\n<a name=\"modifiers\"></a>\n## Modifiers\n\nAlpine offers a number of directive modifiers to customize the behavior of your event listeners.\n\n<a name=\"prevent\"></a>\n### .prevent\n\n`.prevent` is the equivalent of calling `.preventDefault()` inside a listener on the browser event object.\n\n```alpine\n<form @submit.prevent=\"console.log('submitted')\" action=\"/foo\">\n    <button>Submit</button>\n</form>\n```\n\nIn the above example, with the `.prevent`, clicking the button will NOT submit the form to the `/foo` endpoint. Instead, Alpine's listener will handle it and \"prevent\" the event from being handled any further.\n\n<a name=\"stop\"></a>\n### .stop\n\nSimilar to `.prevent`, `.stop` is the equivalent of calling `.stopPropagation()` inside a listener on the browser event object.\n\n```alpine\n<div @click=\"console.log('I will not get logged')\">\n    <button @click.stop>Click Me</button>\n</div>\n```\n\nIn the above example, clicking the button WON'T log the message. This is because we are stopping the propagation of the event immediately and not allowing it to \"bubble\" up to the `<div>` with the `@click` listener on it.\n\n<a name=\"outside\"></a>\n### .outside\n\n`.outside` is a convenience helper for listening for a click outside of the element it is attached to. Here's a simple dropdown component example to demonstrate:\n\n```alpine\n<div x-data=\"{ open: false }\">\n    <button @click=\"open = ! open\">Toggle</button>\n\n    <div x-show=\"open\" @click.outside=\"open = false\">\n        Contents...\n    </div>\n</div>\n```\n\nIn the above example, after showing the dropdown contents by clicking the \"Toggle\" button, you can close the dropdown by clicking anywhere on the page outside the content.\n\nThis is because `.outside` is listening for clicks that DON'T originate from the element it's registered on.\n\n> It's worth noting that the `.outside` expression will only be evaluated when the element it's registered on is visible on the page. Otherwise, there would be nasty race conditions where clicking the \"Toggle\" button would also fire the `@click.outside` handler when it is not visible.\n\n<a name=\"window\"></a>\n### .window\n\nWhen the `.window` modifier is present, Alpine will register the event listener on the root `window` object on the page instead of the element itself.\n\n```alpine\n<div @keyup.escape.window=\"...\">...</div>\n```\n\nThe above snippet will listen for the \"escape\" key to be pressed ANYWHERE on the page.\n\nAdding `.window` to listeners is extremely useful for these sorts of cases where a small part of your markup is concerned with events that take place on the entire page.\n\n<a name=\"document\"></a>\n### .document\n\n`.document` works similarly to `.window` only it registers listeners on the `document` global, instead of the `window` global.\n\n<a name=\"once\"></a>\n### .once\n\nBy adding `.once` to a listener, you are ensuring that the handler is only called ONCE.\n\n```alpine\n<button @click.once=\"console.log('I will only log once')\">...</button>\n```\n\n<a name=\"debounce\"></a>\n### .debounce\n\nSometimes it is useful to \"debounce\" an event handler so that it only is called after a certain period of inactivity (250 milliseconds by default).\n\nFor example if you have a search field that fires network requests as the user types into it, adding a debounce will prevent the network requests from firing on every single keystroke.\n\n```alpine\n<input @input.debounce=\"fetchResults\">\n```\n\nNow, instead of calling `fetchResults` after every keystroke, `fetchResults` will only be called after 250 milliseconds of no keystrokes.\n\nIf you wish to lengthen or shorten the debounce time, you can do so by trailing a duration after the `.debounce` modifier like so:\n\n```alpine\n<input @input.debounce.500ms=\"fetchResults\">\n```\n\nNow, `fetchResults` will only be called after 500 milliseconds of inactivity.\n\n<a name=\"throttle\"></a>\n### .throttle\n\n`.throttle` is similar to `.debounce` except it will release a handler call every 250 milliseconds instead of deferring it indefinitely.\n\nThis is useful for cases where there may be repeated and prolonged event firing and using `.debounce` won't work because you want to still handle the event every so often.\n\nFor example:\n\n```alpine\n<div @scroll.window.throttle=\"handleScroll\">...</div>\n```\n\nThe above example is a great use case of throttling. Without `.throttle`, the `handleScroll` method would be fired hundreds of times as the user scrolls down a page. This can really slow down a site. By adding `.throttle`, we are ensuring that `handleScroll` only gets called every 250 milliseconds.\n\n> Fun Fact: This exact strategy is used on this very documentation site to update the currently highlighted section in the right sidebar.\n\nJust like with `.debounce`, you can add a custom duration to your throttled event:\n\n```alpine\n<div @scroll.window.throttle.750ms=\"handleScroll\">...</div>\n```\n\nNow, `handleScroll` will only be called every 750 milliseconds.\n\n<a name=\"self\"></a>\n### .self\n\nBy adding `.self` to an event listener, you are ensuring that the event originated on the element it is declared on, and not from a child element.\n\n```alpine\n<button @click.self=\"handleClick\">\n    Click Me\n\n    <img src=\"...\">\n</button>\n```\n\nIn the above example, we have an `<img>` tag inside the `<button>` tag. Normally, any click originating within the `<button>` element (like on `<img>` for example), would be picked up by a `@click` listener on the button.\n\nHowever, in this case, because we've added a `.self`, only clicking the button itself will call `handleClick`. Only clicks originating on the `<img>` element will not be handled.\n\n<a name=\"camel\"></a>\n### .camel\n\n```alpine\n<div @custom-event.camel=\"handleCustomEvent\">\n    ...\n</div>\n```\n\nSometimes you may want to listen for camelCased events such as `customEvent` in our example. Because camelCasing inside HTML attributes is not supported, adding the `.camel` modifier is necessary for Alpine to camelCase the event name internally.\n\nBy adding `.camel` in the above example, Alpine is now listening for `customEvent` instead of `custom-event`.\n\n<a name=\"dot\"></a>\n### .dot\n\n```alpine\n<div @custom-event.dot=\"handleCustomEvent\">\n    ...\n</div>\n```\n\nSimilar to the `.camelCase` modifier there may be situations where you want to listen for events that have dots in their name (like `custom.event`). Since dots within the event name are reserved by Alpine you need to write them with dashes and add the `.dot` modifier.\n\nIn the code example above `custom-event.dot` will correspond to the event name `custom.event`.\n\n<a name=\"passive\"></a>\n### .passive\n\nBrowsers optimize scrolling on pages to be fast and smooth even when JavaScript is being executed on the page. However, improperly implemented touch and wheel listeners can block this optimization and cause poor site performance.\n\nIf you are listening for touch events, it's important to add `.passive` to your listeners to not block scroll performance.\n\n```alpine\n<div @touchstart.passive=\"...\">...</div>\n```\n\n[→ Read more about passive listeners](https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener#improving_scrolling_performance_with_passive_listeners)\n\n<a name=\"passive-false\"></a>\n### .passive.false\n\nIn modern browsers, touch and wheel event listeners are passive by default. Pass `.passive.false` to make these events cancelable, so that you can call `preventDefault` on them.\n\n```alpine\n<div @touchmove.passive.false=\"$event.preventDefault()\">...</div>\n```\n\n### .capture\n\nAdd this modifier if you want to execute this listener in the event's capturing phase, e.g. before the event bubbles from the target element up the DOM.\n\n```alpine\n<div @click.capture=\"console.log('I will log first')\">\n    <button @click=\"console.log('I will log second')\"></button>\n</div>\n```\n\n[→ Read more about the capturing and bubbling phase of events](https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener#usecapture)\n","packages/docs/src/en/directives/ref.md":"---\norder: 11\ntitle: ref\n---\n\n# x-ref\n\n`x-ref` in combination with `$refs` is a useful utility for easily accessing DOM elements directly. It's most useful as a replacement for APIs like `getElementById` and `querySelector`.\n\n```alpine\n<button @click=\"$refs.text.remove()\">Remove Text</button>\n\n<span x-ref=\"text\">Hello 👋</span>\n```\n\n<!-- START_VERBATIM -->\n<div class=\"demo\">\n    <div x-data>\n        <button @click=\"$refs.text.remove()\">Remove Text</button>\n\n        <div class=\"pt-4\" x-ref=\"text\">Hello 👋</div>\n    </div>\n</div>\n<!-- END_VERBATIM -->\n\n> Despite not being included in the above snippet, `x-ref` cannot be used if no parent element has `x-data` defined. [→ Read more about `x-data`](/directives/data)\n","packages/docs/src/en/directives/show.md":"---\norder: 3\ntitle: show\n---\n\n# x-show\n\n`x-show` is one of the most useful and powerful directives in Alpine. It provides an expressive way to show and hide DOM elements.\n\nHere's an example of a simple dropdown component using `x-show`.\n\n```alpine\n<div x-data=\"{ open: false }\">\n    <button x-on:click=\"open = ! open\">Toggle Dropdown</button>\n\n    <div x-show=\"open\">\n        Dropdown Contents...\n    </div>\n</div>\n```\n\nWhen the \"Toggle Dropdown\" button is clicked, the dropdown will show and hide accordingly.\n\n> If the \"default\" state of an `x-show` on page load is \"false\", you may want to use `x-cloak` on the page to avoid \"page flicker\" (The effect that happens when the browser renders your content before Alpine is finished initializing and hiding it.) You can learn more about `x-cloak` in its documentation.\n\n<a name=\"with-transitions\"></a>\n## With transitions\n\nIf you want to apply smooth transitions to the `x-show` behavior, you can use it in conjunction with `x-transition`. You can learn more about that directive [here](/directives/transition), but here's a quick example of the same component as above, just with transitions applied.\n\n```alpine\n<div x-data=\"{ open: false }\">\n    <button x-on:click=\"open = ! open\">Toggle Dropdown</button>\n\n    <div x-show=\"open\" x-transition>\n        Dropdown Contents...\n    </div>\n</div>\n```\n\n<a name=\"using-the-important-modifier\"></a>\n## Using the important modifier\n\nSometimes you need to apply a little more force to actually hide an element. In cases where a CSS selector applies the `display` property with the `!important` flag, it will take precedence over the inline style set by Alpine.\n\nIn these cases you may use the `.important` modifier to set the inline style to `display: none !important`.\n\n```alpine\n<div x-data=\"{ open: false }\">\n    <button x-on:click=\"open = ! open\">Toggle Dropdown</button>\n\n    <div x-show.important=\"open\">\n        Dropdown Contents...\n    </div>\n</div>\n```\n","packages/docs/src/en/directives/teleport.md":"---\norder: 12\ntitle: teleport\ndescription: Send Alpine templates to other parts of the DOM\ngraph_image: https://alpinejs.dev/social_teleport.jpg\n---\n\n# x-teleport\n\nThe `x-teleport` directive allows you to transport part of your Alpine template to another part of the DOM on the page entirely.\n\nThis is useful for things like modals (especially nesting them), where it's helpful to break out of the z-index of the current Alpine component.\n\n<a name=\"x-teleport\"></a>\n## x-teleport\n\nBy attaching `x-teleport` to a `<template>` element, you are telling Alpine to \"append\" that element to the provided selector.\n\n> The `x-teleport` selector can be any string you would normally pass into something like `document.querySelector`. It will find the first element that matches, be it a tag name (`body`), class name (`.my-class`), ID (`#my-id`), or any other valid CSS selector.\n\n[→ Read more about `document.querySelector`](https://developer.mozilla.org/en-US/docs/Web/API/Document/querySelector)\n\nHere's a contrived modal example:\n\n```alpine\n<body>\n    <div x-data=\"{ open: false }\">\n        <button @click=\"open = ! open\">Toggle Modal</button>\n\n        <template x-teleport=\"body\">\n            <div x-show=\"open\">\n                Modal contents...\n            </div>\n        </template>\n    </div>\n\n    <div>Some other content placed AFTER the modal markup.</div>\n\n    ...\n\n</body>\n```\n\n<!-- START_VERBATIM -->\n<div class=\"demo\" x-ref=\"root\" id=\"modal2\">\n    <div x-data=\"{ open: false }\">\n        <button @click=\"open = ! open\">Toggle Modal</button>\n\n        <template x-teleport=\"#modal2\">\n            <div x-show=\"open\">\n                Modal contents...\n            </div>\n        </template>\n\n    </div>\n\n    <div class=\"py-4\">Some other content placed AFTER the modal markup.</div>\n</div>\n<!-- END_VERBATIM -->\n\nNotice how when toggling the modal, the actual modal contents show up AFTER the \"Some other content...\" element? This is because when Alpine is initializing, it sees `x-teleport=\"body\"` and appends and initializes that element to the provided element selector.\n\n<a name=\"forwarding-events\"></a>\n## Forwarding events\n\nAlpine tries its best to make the experience of teleporting seamless. Anything you would normally do in a template, you should be able to do inside an `x-teleport` template. Teleported content can access the normal Alpine scope of the component as well as other features like `$refs`, `$root`, etc...\n\nHowever, native DOM events have no concept of teleportation, so if, for example, you trigger a \"click\" event from inside a teleported element, that event will bubble up the DOM tree as it normally would.\n\nTo make this experience more seamless, you can \"forward\" events by simply registering event listeners on the `<template x-teleport...>` element itself like so:\n\n```alpine\n<div x-data=\"{ open: false }\">\n    <button @click=\"open = ! open\">Toggle Modal</button>\n\n    <template x-teleport=\"body\" @click=\"open = false\">\n        <div x-show=\"open\">\n            Modal contents...\n            (click to close)\n        </div>\n    </template>\n</div>\n```\n\n<!-- START_VERBATIM -->\n<div class=\"demo\" x-ref=\"root\" id=\"modal3\">\n    <div x-data=\"{ open: false }\">\n        <button @click=\"open = ! open\">Toggle Modal</button>\n\n        <template x-teleport=\"#modal3\" @click=\"open = false\">\n            <div x-show=\"open\">\n                Modal contents...\n                <div>(click to close)</div>\n            </div>\n        </template>\n    </div>\n</div>\n<!-- END_VERBATIM -->\n\nNotice how we are now able to listen for events dispatched from within the teleported element from outside the `<template>` element itself?\n\nAlpine does this by looking for event listeners registered on `<template x-teleport...>` and stops those events from propagating past the live, teleported, DOM element. Then, it creates a copy of that event and re-dispatches it from `<template x-teleport...>`.\n\n<a name=\"nesting\"></a>\n## Nesting\n\nTeleporting is especially helpful if you are trying to nest one modal within another. Alpine makes it simple to do so:\n\n```alpine\n<div x-data=\"{ open: false }\">\n    <button @click=\"open = ! open\">Toggle Modal</button>\n\n    <template x-teleport=\"body\">\n        <div x-show=\"open\">\n            Modal contents...\n\n            <div x-data=\"{ open: false }\">\n                <button @click=\"open = ! open\">Toggle Nested Modal</button>\n\n                <template x-teleport=\"body\">\n                    <div x-show=\"open\">\n                        Nested modal contents...\n                    </div>\n                </template>\n            </div>\n        </div>\n    </template>\n</div>\n```\n\n<!-- START_VERBATIM -->\n<div class=\"demo\" x-ref=\"root\" id=\"modal4\">\n    <div x-data=\"{ open: false }\">\n        <button @click=\"open = ! open\">Toggle Modal</button>\n\n        <template x-teleport=\"#modal4\">\n            <div x-show=\"open\">\n                <div class=\"py-4\">Modal contents...</div>\n\n                <div x-data=\"{ open: false }\">\n                    <button @click=\"open = ! open\">Toggle Nested Modal</button>\n\n                    <template x-teleport=\"#modal4\">\n                        <div class=\"pt-4\" x-show=\"open\">\n                            Nested modal contents...\n                        </div>\n                    </template>\n                </div>\n            </div>\n        </template>\n    </div>\n\n    <template x-teleport-target=\"modals3\"></template>\n</div>\n<!-- END_VERBATIM -->\n\nAfter toggling \"on\" both modals, they are authored as children, but will be rendered as sibling elements on the page, not within one another.\n","packages/docs/src/en/directives/text.md":"---\norder: 6\ntitle: text\n---\n\n# x-text\n\n`x-text` sets the text content of an element to the result of a given expression.\n\nHere's a basic example of using `x-text` to display a user's username.\n\n```alpine\n<div x-data=\"{ username: 'calebporzio' }\">\n    Username: <strong x-text=\"username\"></strong>\n</div>\n```\n\n<!-- START_VERBATIM -->\n<div class=\"demo\">\n    <div x-data=\"{ username: 'calebporzio' }\">\n        Username: <strong x-text=\"username\"></strong>\n    </div>\n</div>\n<!-- END_VERBATIM -->\n\nNow the `<strong>` tag's inner text content will be set to \"calebporzio\".\n","packages/docs/src/en/directives/transition.md":"---\norder: 10\ntitle: transition\n---\n\n# x-transition\n\nAlpine provides a robust transitions utility out of the box. With a few `x-transition` directives, you can create smooth transitions between when an element is shown or hidden.\n\nThere are two primary ways to handle transitions in Alpine:\n\n* [The Transition Helper](#the-transition-helper)\n* [Applying CSS Classes](#applying-css-classes)\n\n<a name=\"the-transition-helper\"></a>\n## The transition helper\n\nThe simplest way to achieve a transition using Alpine is by adding `x-transition` to an element with `x-show` on it. For example:\n\n```alpine\n<div x-data=\"{ open: false }\">\n    <button @click=\"open = ! open\">Toggle</button>\n\n    <div x-show=\"open\" x-transition>\n        Hello 👋\n    </div>\n</div>\n```\n\n<!-- START_VERBATIM -->\n<div class=\"demo\">\n    <div x-data=\"{ open: false }\">\n        <button @click=\"open = ! open\">Toggle</button>\n\n        <div x-show=\"open\" x-transition>\n            Hello 👋\n        </div>\n    </div>\n</div>\n<!-- END_VERBATIM -->\n\nAs you can see, by default, `x-transition` applies pleasant transition defaults to fade and scale the revealing element.\n\nYou can override these defaults with modifiers attached to `x-transition`. Let's take a look at those.\n\n<a name=\"customizing-duration\"></a>\n### Customizing duration\n\nInitially, the duration is set to be 150 milliseconds when entering, and 75 milliseconds when leaving.\n\nYou can configure the duration you want for a transition with the `.duration` modifier:\n\n```alpine\n<div ... x-transition.duration.500ms>\n```\n\nThe above `<div>` will transition for 500 milliseconds when entering, and 500 milliseconds when leaving.\n\nIf you wish to customize the durations specifically for entering and leaving, you can do that like so:\n\n```alpine\n<div ...\n    x-transition:enter.duration.500ms\n    x-transition:leave.duration.400ms\n>\n```\n\n> Despite not being included in the above snippet, `x-transition` cannot be used if no parent element has `x-data` defined. [→ Read more about `x-data`](/directives/data)\n\n<a name=\"customizing-delay\"></a>\n### Customizing delay\n\nYou can delay a transition using the `.delay` modifier like so:\n\n```alpine\n<div ... x-transition.delay.50ms>\n```\n\nThe above example will delay the transition and in and out of the element by 50 milliseconds.\n\n<a name=\"customizing-opacity\"></a>\n### Customizing opacity\n\nBy default, Alpine's `x-transition` applies both a scale and opacity transition to achieve a \"fade\" effect.\n\nIf you wish to only apply the opacity transition (no scale), you can accomplish that like so:\n\n```alpine\n<div ... x-transition.opacity>\n```\n\n<a name=\"customizing-scale\"></a>\n### Customizing scale\n\nSimilar to the `.opacity` modifier, you can configure `x-transition` to ONLY scale (and not transition opacity as well) like so:\n\n```alpine\n<div ... x-transition.scale>\n```\n\nThe `.scale` modifier also offers the ability to configure its scale values AND its origin values:\n\n```alpine\n<div ... x-transition.scale.80>\n```\n\nThe above snippet will scale the element up and down by 80%.\n\nAgain, you may customize these values separately for enter and leaving transitions like so:\n\n```alpine\n<div ...\n    x-transition:enter.scale.80\n    x-transition:leave.scale.90\n>\n```\n\nTo customize the origin of the scale transition, you can use the `.origin` modifier:\n\n```alpine\n<div ... x-transition.scale.origin.top>\n```\n\nNow the scale will be applied using the top of the element as the origin, instead of the center by default.\n\nLike you may have guessed, the possible values for this customization are: `top`, `bottom`, `left`, and `right`.\n\nIf you wish, you can also combine two origin values. For example, if you want the origin of the scale to be \"top right\", you can use: `.origin.top.right` as the modifier.\n\n\n<a name=\"applying-css-classes\"></a>\n## Applying CSS classes\n\nFor direct control over exactly what goes into your transitions, you can apply CSS classes at different stages of the transition.\n\n> The following examples use [TailwindCSS](https://tailwindcss.com/docs/transition-property) utility classes.\n\n```alpine\n<div x-data=\"{ open: false }\">\n    <button @click=\"open = ! open\">Toggle</button>\n\n    <div\n        x-show=\"open\"\n        x-transition:enter=\"transition ease-out duration-300\"\n        x-transition:enter-start=\"opacity-0 scale-90\"\n        x-transition:enter-end=\"opacity-100 scale-100\"\n        x-transition:leave=\"transition ease-in duration-300\"\n        x-transition:leave-start=\"opacity-100 scale-100\"\n        x-transition:leave-end=\"opacity-0 scale-90\"\n    >Hello 👋</div>\n</div>\n```\n\n<!-- START_VERBATIM -->\n<div class=\"demo\">\n    <div x-data=\"{ open: false }\">\n    <button @click=\"open = ! open\">Toggle</button>\n\n    <div\n        x-show=\"open\"\n        x-transition:enter=\"transition ease-out duration-300\"\n        x-transition:enter-start=\"opacity-0 transform scale-90\"\n        x-transition:enter-end=\"opacity-100 transform scale-100\"\n        x-transition:leave=\"transition ease-in duration-300\"\n        x-transition:leave-start=\"opacity-100 transform scale-100\"\n        x-transition:leave-end=\"opacity-0 transform scale-90\"\n    >Hello 👋</div>\n</div>\n</div>\n<!-- END_VERBATIM -->\n\n| Directive      | Description |\n| ---            | --- |\n| `:enter`       | Applied during the entire entering phase. |\n| `:enter-start` | Added before element is inserted, removed one frame after element is inserted. |\n| `:enter-end`   | Added one frame after element is inserted (at the same time `enter-start` is removed), removed when transition/animation finishes.\n| `:leave`       | Applied during the entire leaving phase. |\n| `:leave-start` | Added immediately when a leaving transition is triggered, removed after one frame. |\n| `:leave-end`   | Added one frame after a leaving transition is triggered (at the same time `leave-start` is removed), removed when the transition/animation finishes.\n","packages/docs/src/en/essentials.md":"---\norder: 3\ntitle: Essentials\ntype: sub-directory\n---\n","packages/docs/src/en/essentials/events.md":"---\norder: 4\ntitle: Events\n---\n\n# Events\n\nAlpine makes it simple to listen for browser events and react to them.\n\n<a name=\"listening-for-simple-events\"></a>\n## Listening for simple events\n\nBy using `x-on`, you can listen for browser events that are dispatched on or within an element.\n\nHere's a basic example of listening for a click on a button:\n\n```alpine\n<button x-on:click=\"console.log('clicked')\">...</button>\n```\n\nAs an alternative, you can use the event shorthand syntax if you prefer: `@`. Here's the same example as before, but using the shorthand syntax (which we'll be using from now on):\n\n```alpine\n<button @click=\"...\">...</button>\n```\n\nIn addition to `click`, you can listen for any browser event by name. For example: `@mouseenter`, `@keyup`, etc... are all valid syntax.\n\n<a name=\"listening-for-specific-keys\"></a>\n## Listening for specific keys\n\nLet's say you wanted to listen for the `enter` key to be pressed inside an `<input>` element. Alpine makes this easy by adding the `.enter` like so:\n\n```alpine\n<input @keyup.enter=\"...\">\n```\n\nYou can even combine key modifiers to listen for key combinations like pressing `enter` while holding `shift`:\n\n```alpine\n<input @keyup.shift.enter=\"...\">\n```\n\n<a name=\"preventing-default\"></a>\n## Preventing default\n\nWhen reacting to browser events, it is often necessary to \"prevent default\" (prevent the default behavior of the browser event).\n\nFor example, if you want to listen for a form submission but prevent the browser from submitting a form request, you can use `.prevent`:\n\n```alpine\n<form @submit.prevent=\"...\">...</form>\n```\n\nYou can also apply `.stop` to achieve the equivalent of `event.stopPropagation()`.\n\n<a name=\"accessing-the-event-object\"></a>\n## Accessing the event object\n\nSometimes you may want to access the native browser event object inside your own code. To make this easy, Alpine automatically injects an `$event` magic variable:\n\n```alpine\n<button @click=\"$event.target.remove()\">Remove Me</button>\n```\n\n<a name=\"dispatching-custom-events\"></a>\n## Dispatching custom events\n\nIn addition to listening for browser events, you can dispatch them as well. This is extremely useful for communicating with other Alpine components or triggering events in tools outside of Alpine itself.\n\nAlpine exposes a magic helper called `$dispatch` for this:\n\n```alpine\n<div @foo=\"console.log('foo was dispatched')\">\n    <button @click=\"$dispatch('foo')\"></button>\n</div>\n```\n\nAs you can see, when the button is clicked, Alpine will dispatch a browser event called \"foo\", and our `@foo` listener on the `<div>` will pick it up and react to it.\n\n<a name=\"listening-for-events-on-window\"></a>\n## Listening for events on window\n\nBecause of the nature of events in the browser, it is sometimes useful to listen to events on the top-level window object.\n\nThis allows you to communicate across components completely like the following example:\n\n\n```alpine\n<div x-data>\n    <button @click=\"$dispatch('foo')\"></button>\n</div>\n\n<div x-data @foo.window=\"console.log('foo was dispatched')\">...</div>\n```\n\nIn the above example, if we click the button in the first component, Alpine will dispatch the \"foo\" event. Because of the way events work in the browser, they \"bubble\" up through parent elements all the way to the top-level \"window\".\n\nNow, because in our second component we are listening for \"foo\" on the window (with `.window`), when the button is clicked, this listener will pick it up and log the \"foo was dispatched\" message.\n\n[→ Read more about x-on](/directives/on)\n","packages/docs/src/en/essentials/installation.md":"---\norder: 1\ntitle: Installation\n---\n\n# Installation\n\nThere are 2 ways to include Alpine into your project:\n\n* Including it from a `<script>` tag\n* Importing it as a module\n\nEither is perfectly valid. It all depends on the project's needs and the developer's taste.\n\n<a name=\"from-a-script-tag\"></a>\n## From a script tag\n\nThis is by far the simplest way to get started with Alpine. Include the following `<script>` tag in the head of your HTML page.\n\n```alpine\n<html>\n    <head>\n        ...\n\n        <script defer src=\"https://cdn.jsdelivr.net/npm/alpinejs@3.x.x/dist/cdn.min.js\"></script>\n    </head>\n    ...\n</html>\n```\n\n> Don't forget the \"defer\" attribute in the `<script>` tag.\n\nNotice the `@3.x.x` in the provided CDN link. This will pull the latest version of Alpine version 3. For stability in production, it's recommended that you hardcode the latest version in the CDN link.\n\n```alpine\n<script defer src=\"https://cdn.jsdelivr.net/npm/alpinejs@3.17.5/dist/cdn.min.js\"></script>\n```\n\nThat's it! Alpine is now available for use inside your page.\n\nNote that you will still need to define a component with `x-data` in order for any Alpine.js attributes to work. See <https://github.com/alpinejs/alpine/discussions/3805> for more information.\n\n<a name=\"as-a-module\"></a>\n## As a module\n\nIf you prefer the more robust approach, you can install Alpine via NPM and import it into a bundle.\n\nRun the following command to install it.\n\n```shell\nnpm install alpinejs\n```\n\nNow import Alpine into your bundle and initialize it like so:\n\n```js\nimport Alpine from 'alpinejs'\n\nwindow.Alpine = Alpine\n\nAlpine.start()\n```\n\n> The `window.Alpine = Alpine` bit is optional, but is nice to have for freedom and flexibility. Like when tinkering with Alpine from the devtools for example.\n\n> If you imported Alpine into a bundle, you have to make sure you are registering any extension code IN BETWEEN when you import the `Alpine` global object, and when you initialize Alpine by calling `Alpine.start()`.\n\n> Ensure that `Alpine.start()` is only called once per page. Calling it more than once will result in multiple \"instances\" of Alpine running at the same time.\n\n\n[→ Read more about extending Alpine](/advanced/extending)\n","packages/docs/src/en/essentials/lifecycle.md":"---\norder: 5\ntitle: Lifecycle\n---\n\n# Lifecycle\n\nAlpine has a handful of different techniques for hooking into different parts of its lifecycle. Let's go through the most useful ones to familiarize yourself with:\n\n<a name=\"element-initialization\"></a>\n## Element initialization\n\nAnother extremely useful lifecycle hook in Alpine is the `x-init` directive.\n\n`x-init` can be added to any element on a page and will execute any JavaScript you call inside it when Alpine begins initializing that element.\n\n```alpine\n<button x-init=\"console.log('Im initing')\">\n```\n\nIn addition to the directive, Alpine will automatically call any `init()` methods stored on a data object. For example:\n\n```js\nAlpine.data('dropdown', () => ({\n    init() {\n        // I get called before the element using this data initializes.\n    }\n}))\n```\n\n<a name=\"after-a-state-change\"></a>\n## After a state change\n\nAlpine allows you to execute code when a piece of data (state) changes. It offers two different APIs for such a task: `$watch` and `x-effect`.\n\n<a name=\"watch\"></a>\n### `$watch`\n\n```alpine\n<div x-data=\"{ open: false }\" x-init=\"$watch('open', value => console.log(value))\">\n```\n\nAs you can see above, `$watch` allows you to hook into data changes using a dot-notation key. When that piece of data changes, Alpine will call the passed callback and pass it the new value. along with the old value before the change.\n\n[→ Read more about $watch](/magics/watch)\n\n<a name=\"x-effect\"></a>\n### `x-effect`\n\n`x-effect` uses the same mechanism under the hood as `$watch` but has very different usage.\n\nInstead of specifying which data key you wish to watch, `x-effect` will call the provided code and intelligently look for any Alpine data used within it. Now when one of those pieces of data changes, the `x-effect` expression will be re-run.\n\nHere's the same bit of code from the `$watch` example rewritten using `x-effect`:\n\n```alpine\n<div x-data=\"{ open: false }\" x-effect=\"console.log(open)\">\n```\n\nNow, this expression will be called right away, and re-called every time `open` is updated.\n\nThe two main behavioral differences with this approach are:\n\n1. The provided code will be run right away AND when data changes (`$watch` is \"lazy\" -- won't run until the first data change)\n2. No knowledge of the previous value. (The callback provided to `$watch` receives both the new value AND the old one)\n\n[→ Read more about x-effect](/directives/effect)\n\n<a name=\"alpine-initialization\"></a>\n## Alpine initialization\n\n<a name=\"alpine-initializing\"></a>\n### `alpine:init`\n\nEnsuring a bit of code executes after Alpine is loaded, but BEFORE it initializes itself on the page is a necessary task.\n\nThis hook allows you to register custom data, directives, magics, etc. before Alpine does its thing on a page.\n\nYou can hook into this point in the lifecycle by listening for an event that Alpine dispatches called: `alpine:init`\n\n```js\ndocument.addEventListener('alpine:init', () => {\n    Alpine.data(...)\n})\n```\n\n<a name=\"alpine-initialized\"></a>\n### `alpine:initialized`\n\nAlpine also offers a hook that you can use to execute code AFTER it's done initializing called `alpine:initialized`:\n\n```js\ndocument.addEventListener('alpine:initialized', () => {\n    //\n})\n```\n","packages/docs/src/en/essentials/state.md":"---\norder: 2\ntitle: State\n---\n\n# State\n\nState (JavaScript data that Alpine watches for changes) is at the core of everything you do in Alpine. You can provide local data to a chunk of HTML, or make it globally available for use anywhere on a page using `x-data` or `Alpine.store()` respectively.\n\n<a name=\"local-state-x-data\"></a>\n## Local state\n\nAlpine allows you to declare an HTML block's state in a single `x-data` attribute without ever leaving your markup.\n\nHere's a basic example:\n\n```alpine\n<div x-data=\"{ open: false }\">\n    ...\n</div>\n```\n\nNow any other Alpine syntax on or within this element will be able to access `open`. And like you'd guess, when `open` changes for any reason, everything that depends on it will react automatically.\n\n[→ Read more about `x-data`](/directives/data)\n\n<a name=\"nesting-data\"></a>\n### Nesting data\n\nData is nestable in Alpine. For example, if you have two elements with Alpine data attached (one inside the other), you can access the parent's data from inside the child element.\n\n```alpine\n<div x-data=\"{ open: false }\">\n    <div x-data=\"{ label: 'Content:' }\">\n        <span x-text=\"label\"></span>\n        <span x-show=\"open\"></span>\n    </div>\n</div>\n```\n\nThis is similar to scoping in JavaScript itself (code within a function can access variables declared outside that function.)\n\nLike you may have guessed, if the child has a data property matching the name of a parent's property, the child property will take precedence.\n\n<a name=\"single-element-data\"></a>\n### Single-element data\n\nAlthough this may seem obvious to some, it's worth mentioning that Alpine data can be used within the same element. For example:\n\n```alpine\n<button x-data=\"{ label: 'Click Here' }\" x-text=\"label\"></button>\n```\n\n<a name=\"data-less-alpine\"></a>\n### Data-less Alpine\n\nSometimes you may want to use Alpine functionality, but don't need any reactive data. In these cases, you can opt out of passing an expression to `x-data` entirely. For example:\n\n```alpine\n<button x-data @click=\"alert('I\\'ve been clicked!')\">Click Me</button>\n```\n\n<a name=\"re-usable-data\"></a>\n### Re-usable data\n\nWhen using Alpine, you may find the need to re-use a chunk of data and/or its corresponding template.\n\nIf you are using a backend framework like Rails or Laravel, Alpine first recommends that you extract the entire block of HTML into a template partial or include.\n\nIf for some reason that isn't ideal for you or you're not in a back-end templating environment, Alpine allows you to globally register and re-use the data portion of a component using `Alpine.data(...)`.\n\n```js\nAlpine.data('dropdown', () => ({\n    open: false,\n\n    toggle() {\n        this.open = ! this.open\n    }\n}))\n```\n\nNow that you've registered the \"dropdown\" data, you can use it inside your markup in as many places as you like:\n\n```alpine\n<div x-data=\"dropdown\">\n    <button @click=\"toggle\">Expand</button>\n\n    <span x-show=\"open\">Content...</span>\n</div>\n\n<div x-data=\"dropdown\">\n    <button @click=\"toggle\">Expand</button>\n\n    <span x-show=\"open\">Some Other Content...</span>\n</div>\n```\n\n[→ Read more about using `Alpine.data()`](/globals/alpine-data)\n\n<a name=\"global-state\"></a>\n## Global state\n\nIf you wish to make some data available to every component on the page, you can do so using Alpine's \"global store\" feature.\n\nYou can register a store using `Alpine.store(...)`, and reference one with the magic `$store()` method.\n\nLet's look at a simple example. First we'll register the store globally:\n\n```js\nAlpine.store('tabs', {\n    current: 'first',\n\n    items: ['first', 'second', 'third'],\n})\n```\n\nNow we can access or modify its data from anywhere on our page:\n\n```alpine\n<div x-data>\n    <template x-for=\"tab in $store.tabs.items\">\n        ...\n    </template>\n</div>\n\n<div x-data>\n    <button @click=\"$store.tabs.current = 'first'\">First Tab</button>\n    <button @click=\"$store.tabs.current = 'second'\">Second Tab</button>\n    <button @click=\"$store.tabs.current = 'third'\">Third Tab</button>\n</div>\n```\n\n[→ Read more about `Alpine.store()`](/globals/alpine-store)\n","packages/docs/src/en/essentials/templating.md":"---\norder: 3\ntitle: Templating\n---\n\n# Templating\n\nAlpine offers a handful of useful directives for manipulating the DOM on a web page.\n\nLet's cover a few of the basic templating directives here, but be sure to look through the available directives in the sidebar for an exhaustive list.\n\n<a name=\"text-content\"></a>\n## Text content\n\nAlpine makes it easy to control the text content of an element with the `x-text` directive.\n\n```alpine\n<div x-data=\"{ title: 'Start Here' }\">\n    <h1 x-text=\"title\"></h1>\n</div>\n```\n\n<!-- START_VERBATIM -->\n<div x-data=\"{ title: 'Start Here' }\" class=\"demo\">\n    <strong x-text=\"title\"></strong>\n</div>\n<!-- END_VERBATIM -->\n\nNow, Alpine will set the text content of the `<h1>` with the value of `title` (\"Start Here\"). When `title` changes, so will the contents of `<h1>`.\n\nLike all directives in Alpine, you can use any JavaScript expression you like. For example:\n\n```alpine\n<span x-text=\"1 + 2\"></span>\n```\n\n<!-- START_VERBATIM -->\n<div class=\"demo\" x-data>\n    <span x-text=\"1 + 2\"></span>\n</div>\n<!-- END_VERBATIM -->\n\nThe `<span>` will now contain the sum of \"1\" and \"2\".\n\n[→ Read more about `x-text`](/directives/text)\n\n<a name=\"toggling-elements\"></a>\n## Toggling elements\n\nToggling elements is a common need in web pages and applications. Dropdowns, modals, dialogues, \"show-more\"s, etc... are all good examples.\n\nAlpine offers the `x-show` and `x-if` directives for toggling elements on a page.\n\n<a name=\"x-show\"></a>\n### `x-show`\n\nHere's a simple toggle component using `x-show`.\n\n```alpine\n<div x-data=\"{ open: false }\">\n    <button @click=\"open = ! open\">Expand</button>\n\n    <div x-show=\"open\">\n        Content...\n    </div>\n</div>\n```\n\n<!-- START_VERBATIM -->\n<div x-data=\"{ open: false }\" class=\"demo\">\n    <button @click=\"open = ! open\" :aria-pressed=\"open\">Expand</button>\n\n    <div x-show=\"open\">\n        Content...\n    </div>\n</div>\n<!-- END_VERBATIM -->\n\nNow the entire `<div>` containing the contents will be shown and hidden based on the value of `open`.\n\nUnder the hood, Alpine adds the CSS property `display: none;` to the element when it should be hidden.\n\n[→ Read more about `x-show`](/directives/show)\n\nThis works well for most cases, but sometimes you may want to completely add and remove the element from the DOM entirely. This is what `x-if` is for.\n\n<a name=\"x-if\"></a>\n### `x-if`\n\nHere is the same toggle from before, but this time using `x-if` instead of `x-show`.\n\n```alpine\n<div x-data=\"{ open: false }\">\n    <button @click=\"open = ! open\">Expand</button>\n\n    <template x-if=\"open\">\n        <div>\n            Content...\n        </div>\n    </template>\n</div>\n```\n\n<!-- START_VERBATIM -->\n<div x-data=\"{ open: false }\" class=\"demo\">\n    <button @click=\"open = ! open\" :aria-pressed=\"open\">Expand</button>\n\n    <template x-if=\"open\">\n        <div>\n            Content...\n        </div>\n    </template>\n</div>\n<!-- END_VERBATIM -->\n\nNotice that `x-if` must be declared on a `<template>` tag. This is so that Alpine can leverage the existing browser behavior of the `<template>` element and use it as the source of the target `<div>` to be added and removed from the page.\n\nWhen `open` is true, Alpine will append the `<div>` to the `<template>` tag, and remove it when `open` is false.\n\n[→ Read more about `x-if`](/directives/if)\n\n<a name=\"toggling-with-transitions\"></a>\n## Toggling with transitions\n\nAlpine makes it simple to smoothly transition between \"shown\" and \"hidden\" states using the `x-transition` directive.\n\n> `x-transition` only works with `x-show`, not with `x-if`.\n\nHere is, again, the simple toggle example, but this time with transitions applied:\n\n```alpine\n<div x-data=\"{ open: false }\">\n    <button @click=\"open = ! open\">Expands</button>\n\n    <div x-show=\"open\" x-transition>\n        Content...\n    </div>\n</div>\n```\n\n<!-- START_VERBATIM -->\n<div x-data=\"{ open: false }\" class=\"demo\">\n    <button @click=\"open = ! open\">Expands</button>\n\n    <div class=\"flex\">\n        <div x-show=\"open\" x-transition style=\"will-change: transform;\">\n            Content...\n        </div>\n    </div>\n</div>\n<!-- END_VERBATIM -->\n\nLet's zoom in on the portion of the template dealing with transitions:\n\n```alpine\n<div x-show=\"open\" x-transition>\n```\n\n`x-transition` by itself will apply sensible default transitions (fade and scale) to the toggle.\n\nThere are two ways to customize these transitions:\n\n* Transition helpers\n* Transition CSS classes.\n\nLet's take a look at each of these approaches:\n\n<a name=\"transition-helpers\"></a>\n### Transition helpers\n\nLet's say you wanted to make the duration of the transition longer, you can manually specify that using the `.duration` modifier like so:\n\n```alpine\n<div x-show=\"open\" x-transition.duration.500ms>\n```\n\n<!-- START_VERBATIM -->\n<div x-data=\"{ open: false }\" class=\"demo\">\n    <button @click=\"open = ! open\">Expands</button>\n\n    <div class=\"flex\">\n        <div x-show=\"open\" x-transition.duration.500ms style=\"will-change: transform;\">\n            Content...\n        </div>\n    </div>\n</div>\n<!-- END_VERBATIM -->\n\nNow the transition will last 500 milliseconds.\n\nIf you want to specify different values for in and out transitions, you can use `x-transition:enter` and `x-transition:leave`:\n\n```alpine\n<div\n    x-show=\"open\"\n    x-transition:enter.duration.500ms\n    x-transition:leave.duration.1000ms\n>\n```\n\n<!-- START_VERBATIM -->\n<div x-data=\"{ open: false }\" class=\"demo\">\n    <button @click=\"open = ! open\">Expands</button>\n\n    <div class=\"flex\">\n        <div x-show=\"open\" x-transition:enter.duration.500ms x-transition:leave.duration.1000ms style=\"will-change: transform;\">\n            Content...\n        </div>\n    </div>\n</div>\n<!-- END_VERBATIM -->\n\nAdditionally, you can add either `.opacity` or `.scale` to only transition that property. For example:\n\n```alpine\n<div x-show=\"open\" x-transition.opacity>\n```\n\n<!-- START_VERBATIM -->\n<div x-data=\"{ open: false }\" class=\"demo\">\n    <button @click=\"open = ! open\">Expands</button>\n\n    <div class=\"flex\">\n        <div x-show=\"open\" x-transition:enter.opacity.duration.500 x-transition:leave.opacity.duration.250>\n            Content...\n        </div>\n    </div>\n</div>\n<!-- END_VERBATIM -->\n\n[→ Read more about transition helpers](/directives/transition#the-transition-helper)\n\n<a name=\"transition-classes\"></a>\n### Transition classes\n\nIf you need more fine-grained control over the transitions in your application, you can apply specific CSS classes at specific phases of the transition using the following syntax (this example uses [Tailwind CSS](https://tailwindcss.com/)):\n\n```alpine\n<div\n    x-show=\"open\"\n    x-transition:enter=\"transition ease-out duration-300\"\n    x-transition:enter-start=\"opacity-0 transform scale-90\"\n    x-transition:enter-end=\"opacity-100 transform scale-100\"\n    x-transition:leave=\"transition ease-in duration-300\"\n    x-transition:leave-start=\"opacity-100 transform scale-100\"\n    x-transition:leave-end=\"opacity-0 transform scale-90\"\n>...</div>\n```\n\n<!-- START_VERBATIM -->\n<div x-data=\"{ open: false }\" class=\"demo\">\n    <button @click=\"open = ! open\">Expands</button>\n\n    <div class=\"flex\">\n        <div\n            x-show=\"open\"\n            x-transition:enter=\"transition ease-out duration-300\"\n            x-transition:enter-start=\"opacity-0 transform scale-90\"\n            x-transition:enter-end=\"opacity-100 transform scale-100\"\n            x-transition:leave=\"transition ease-in duration-300\"\n            x-transition:leave-start=\"opacity-100 transform scale-100\"\n            x-transition:leave-end=\"opacity-0 transform scale-90\"\n            style=\"will-change: transform\"\n        >\n            Content...\n        </div>\n    </div>\n</div>\n<!-- END_VERBATIM -->\n\n[→ Read more about transition classes](/directives/transition#applying-css-classes)\n\n<a name=\"binding-attributes\"></a>\n## Binding attributes\n\nYou can add HTML attributes like `class`, `style`, `disabled`, etc... to elements in Alpine using the `x-bind` directive.\n\nHere is an example of a dynamically bound `class` attribute:\n\n```alpine\n<button\n    x-data=\"{ red: false }\"\n    x-bind:class=\"red ? 'bg-red' : ''\"\n    @click=\"red = ! red\"\n>\n    Toggle Red\n</button>\n```\n\n<!-- START_VERBATIM -->\n<div class=\"demo\">\n    <button\n        x-data=\"{ red: false }\"\n        x-bind:style=\"red && 'background: red'\"\n        @click=\"red = ! red\"\n    >\n        Toggle Red\n    </button>\n</div>\n<!-- END_VERBATIM -->\n\n\nAs a shortcut, you can leave out the `x-bind` and use the shorthand `:` syntax directly:\n\n```alpine\n<button ... :class=\"red ? 'bg-red' : ''\">\n```\n\nToggling classes on and off based on data inside Alpine is a common need. Here's an example of toggling a class using Alpine's `class` binding object syntax: (Note: this syntax is only available for `class` attributes)\n\n```alpine\n<div x-data=\"{ open: true }\">\n    <span :class=\"{ 'hidden': ! open }\">...</span>\n</div>\n```\n\nNow the `hidden` class will be added to the element if `open` is false, and removed if `open` is true.\n\n<a name=\"looping-elements\"></a>\n## Looping elements\n\nAlpine allows for iterating parts of your template based on JavaScript data using the `x-for` directive. Here is a simple example:\n\n```alpine\n<div x-data=\"{ statuses: ['open', 'closed', 'archived'] }\">\n    <template x-for=\"status in statuses\">\n        <div x-text=\"status\"></div>\n    </template>\n</div>\n```\n\n<!-- START_VERBATIM -->\n<div x-data=\"{ statuses: ['open', 'closed', 'archived'] }\" class=\"demo\">\n    <template x-for=\"status in statuses\">\n        <div x-text=\"status\"></div>\n    </template>\n</div>\n<!-- END_VERBATIM -->\n\nSimilar to `x-if`, `x-for` must be applied to a `<template>` tag. Internally, Alpine will append the contents of `<template>` tag for every iteration in the loop.\n\nAs you can see the new `status` variable is available in the scope of the iterated templates.\n\n[→ Read more about `x-for`](/directives/for)\n\n<a name=\"inner-html\"></a>\n## Inner HTML\n\nAlpine makes it easy to control the HTML content of an element with the `x-html` directive.\n\n```alpine\n<div x-data=\"{ title: '<h1>Start Here</h1>' }\">\n    <div x-html=\"title\"></div>\n</div>\n```\n\n<!-- START_VERBATIM -->\n<div x-data=\"{ title: '<h1>Start Here</h1>' }\" class=\"demo\">\n    <div x-html=\"title\"></div>\n</div>\n<!-- END_VERBATIM -->\n\nNow, Alpine will set the text content of the `<div>` with the element `<h1>Start Here</h1>`. When `title` changes, so will the contents of `<h1>`.\n\n> ⚠️ Only use on trusted content and never on user-provided content. ⚠️\n> Dynamically rendering HTML from third parties can easily lead to XSS vulnerabilities.\n\n[→ Read more about `x-html`](/directives/html)\n","packages/docs/src/en/globals.md":"---\norder: 6\ntitle: Globals\nfont-type: mono\nprefix: Alpine.\ntype: sub-directory\n---\n","packages/docs/src/en/globals/alpine-bind.md":"---\norder: 3\ntitle: bind()\n---\n\n# Alpine.bind\n\n`Alpine.bind(...)` provides a way to re-use [`x-bind`](/directives/bind#bind-directives) objects within your application.\n\nHere's a simple example. Rather than binding attributes manually with Alpine:\n\n```alpine\n<button type=\"button\" @click=\"doSomething()\" :disabled=\"shouldDisable\"></button>\n```\n\nYou can bundle these attributes up into a reusable object and use `x-bind` to bind to that:\n\n```alpine\n<button x-bind=\"SomeButton\"></button>\n\n<script>\n    document.addEventListener('alpine:init', () => {\n        Alpine.bind('SomeButton', () => ({\n            type: 'button',\n\n            '@click'() {\n                this.doSomething()\n            },\n\n            ':disabled'() {\n                return this.shouldDisable\n            },\n        }))\n    })\n</script>\n```\n","packages/docs/src/en/globals/alpine-data.md":"---\norder: 1\ntitle: data()\n---\n\n# Alpine.data\n\n`Alpine.data(...)` provides a way to re-use `x-data` contexts within your application.\n\nHere's a contrived `dropdown` component for example:\n\n```alpine\n<div x-data=\"dropdown\">\n    <button @click=\"toggle\">...</button>\n\n    <div x-show=\"open\">...</div>\n</div>\n\n<script>\n    document.addEventListener('alpine:init', () => {\n        Alpine.data('dropdown', () => ({\n            open: false,\n\n            toggle() {\n                this.open = ! this.open\n            }\n        }))\n    })\n</script>\n```\n\nAs you can see we've extracted the properties and methods we would usually define directly inside `x-data` into a separate Alpine component object.\n\n<a name=\"registering-from-a-bundle\"></a>\n## Registering from a bundle\n\nIf you've chosen to use a build step for your Alpine code, you should register your components in the following way:\n\n```js\nimport Alpine from 'alpinejs'\nimport dropdown from './dropdown.js'\n\nAlpine.data('dropdown', dropdown)\n\nAlpine.start()\n```\n\nThis assumes you have a file called `dropdown.js` with the following contents:\n\n```js\nexport default () => ({\n    open: false,\n\n    toggle() {\n        this.open = ! this.open\n    }\n})\n```\n\n<a name=\"initial-parameters\"></a>\n## Initial parameters\n\nIn addition to referencing `Alpine.data` providers by their name plainly (like `x-data=\"dropdown\"`), you can also reference them as functions (`x-data=\"dropdown()\"`). By calling them as functions directly, you can pass in additional parameters to be used when creating the initial data object like so:\n\n```alpine\n<div x-data=\"dropdown(true)\">\n```\n```js\nAlpine.data('dropdown', (initialOpenState = false) => ({\n    open: initialOpenState\n}))\n```\n\nNow, you can re-use the `dropdown` object, but provide it with different parameters as you need to.\n\n<a name=\"init-functions\"></a>\n## Init functions\n\nIf your component contains an `init()` method, Alpine will automatically execute it before it renders the component. For example:\n\n```js\nAlpine.data('dropdown', () => ({\n    init() {\n        // This code will be executed before Alpine\n        // initializes the rest of the component.\n    }\n}))\n```\n\n<a name=\"destroy-functions\"></a>\n## Destroy functions\n\nIf your component contains a `destroy()` method, Alpine will automatically execute it before cleaning up the component.\n\nA primary example for this is when registering an event handler with another library or a browser API that isn't available through Alpine.\nSee the following example code on how to use the `destroy()` method to clean up such a handler.\n\n```js\nAlpine.data('timer', () => ({\n    timer: null,\n    counter: 0,\n    init() {\n      // Register an event handler that references the component instance\n      this.timer = setInterval(() => {\n        console.log('Increased counter to', ++this.counter);\n      }, 1000);\n    },\n    destroy() {\n        // Detach the handler, avoiding memory and side-effect leakage\n        clearInterval(this.timer);\n    },\n}))\n```\n\nAn example where a component is destroyed is when using one inside an `x-if`:\n\n```html\n<span x-data=\"{ enabled: false }\">\n    <button @click.prevent=\"enabled = !enabled\">Toggle</button>\n\n    <template x-if=\"enabled\">\n        <span x-data=\"timer\" x-text=\"counter\"></span>\n    </template>\n</span>\n```\n\n<a name=\"using-magic-properties\"></a>\n## Using magic properties\n\nIf you want to access magic methods or properties from a component object, you can do so using the `this` context:\n\n```js\nAlpine.data('dropdown', () => ({\n    open: false,\n\n    init() {\n        this.$watch('open', () => {...})\n    }\n}))\n```\n\n<a name=\"encapsulating-directives-with-x-bind\"></a>\n## Encapsulating directives with `x-bind`\n\nIf you wish to re-use more than just the data object of a component, you can encapsulate entire Alpine template directives using `x-bind`.\n\nThe following is an example of extracting the templating details of our previous dropdown component using `x-bind`:\n\n```alpine\n<div x-data=\"dropdown\">\n    <button x-bind=\"trigger\"></button>\n\n    <div x-bind=\"dialogue\"></div>\n</div>\n```\n\n```js\nAlpine.data('dropdown', () => ({\n    open: false,\n\n    trigger: {\n        ['@click']() {\n            this.open = ! this.open\n        },\n    },\n\n    dialogue: {\n        ['x-show']() {\n            return this.open\n        },\n    },\n}))\n```\n","packages/docs/src/en/globals/alpine-store.md":"---\norder: 2\ntitle: store()\n---\n\n# Alpine.store\n\nAlpine offers global state management through the `Alpine.store()` API.\n\n<a name=\"registering-a-store\"></a>\n## Registering A Store\n\nYou can either define an Alpine store inside of an `alpine:init` listener (in the case of including Alpine via a `<script>` tag), OR you can define it before manually calling `Alpine.start()` (in the case of importing Alpine into a build):\n\n**From a script tag:**\n```alpine\n<script>\n    document.addEventListener('alpine:init', () => {\n        Alpine.store('darkMode', {\n            on: false,\n\n            toggle() {\n                this.on = ! this.on\n            }\n        })\n    })\n</script>\n```\n\n**From a bundle:**\n```js\nimport Alpine from 'alpinejs'\n\nAlpine.store('darkMode', {\n    on: false,\n\n    toggle() {\n        this.on = ! this.on\n    }\n})\n\nAlpine.start()\n```\n\n<a name=\"accessing stores\"></a>\n## Accessing stores\n\nYou can access data from any store within Alpine expressions using the `$store` magic property:\n\n```alpine\n<div x-data :class=\"$store.darkMode.on && 'bg-black'\">...</div>\n```\n\nYou can also modify properties within the store and everything that depends on those properties will automatically react. For example:\n\n```alpine\n<button x-data @click=\"$store.darkMode.toggle()\">Toggle Dark Mode</button>\n```\n\nAdditionally, you can access a store externally using `Alpine.store()` by omitting the second parameter like so:\n\n```alpine\n<script>\n    Alpine.store('darkMode').toggle()\n</script>\n```\n\n<a name=\"initializing-stores\"></a>\n## Initializing stores\n\nIf you provide `init()` method in an Alpine store, it will be executed right after the store is registered. This is useful for initializing any state inside the store with sensible starting values.\n\n```alpine\n<script>\n    document.addEventListener('alpine:init', () => {\n        Alpine.store('darkMode', {\n            init() {\n                this.on = window.matchMedia('(prefers-color-scheme: dark)').matches\n            },\n\n            on: false,\n\n            toggle() {\n                this.on = ! this.on\n            }\n        })\n    })\n</script>\n```\n\nNotice the newly added `init()` method in the example above. With this addition, the `on` store variable will be set to the browser's color scheme preference before Alpine renders anything on the page.\n\n<a name=\"single-value-stores\"></a>\n## Single-value stores\n\nIf you don't need an entire object for a store, you can set and use any kind of data as a store.\n\nHere's the example from above but using it more simply as a boolean value:\n\n```alpine\n<button x-data @click=\"$store.darkMode = ! $store.darkMode\">Toggle Dark Mode</button>\n\n...\n\n<div x-data :class=\"$store.darkMode && 'bg-black'\">\n    ...\n</div>\n\n\n<script>\n    document.addEventListener('alpine:init', () => {\n        Alpine.store('darkMode', false)\n    })\n</script>\n```\n","packages/docs/src/en/magics.md":"---\norder: 5\ntitle: Magics\nprefix: $\nfont-type: mono\ntype: sub-directory\n---\n","packages/docs/src/en/magics/data.md":"---\norder: 8\nprefix: $\ntitle: data\n---\n\n# $data\n\n`$data` is a magic property that gives you access to the current Alpine data scope (generally provided by `x-data`).\n\nMost of the time, you can just access Alpine data within expressions directly. for example `x-data=\"{ message: 'Hello Caleb!' }\"` will allow you to do things like `x-text=\"message\"`.\n\nHowever, sometimes it is helpful to have an actual object that encapsulates all scope that you can pass around to other functions:\n\n```alpine\n<div x-data=\"{ greeting: 'Hello' }\">\n    <div x-data=\"{ name: 'Caleb' }\">\n        <button @click=\"sayHello($data)\">Say Hello</button>\n    </div>\n</div>\n\n<script>\n    function sayHello({ greeting, name }) {\n        alert(greeting + ' ' + name + '!')\n    }\n</script>\n```\n\n<!-- START_VERBATIM -->\n<div x-data=\"{ greeting: 'Hello' }\" class=\"demo\">\n    <div x-data=\"{ name: 'Caleb' }\">\n        <button @click=\"sayHello($data)\">Say Hello</button>\n    </div>\n</div>\n\n<script>\n    function sayHello({ greeting, name }) {\n        alert(greeting + ' ' + name + '!')\n    }\n</script>\n<!-- END_VERBATIM -->\n\nNow when the button is pressed, the browser will alert `Hello Caleb!` because it was passed a data object that contained all the Alpine scope of the expression that called it (`@click=\"...\"`).\n\nMost applications won't need this magic property, but it can be very helpful for deeper, more complicated Alpine utilities.\n","packages/docs/src/en/magics/dispatch.md":"---\norder: 5\ntitle: dispatch\n---\n\n# $dispatch\n\n`$dispatch` is a helpful shortcut for dispatching browser events.\n\n```alpine\n<div @notify=\"alert('Hello World!')\">\n    <button @click=\"$dispatch('notify')\">\n        Notify\n    </button>\n</div>\n```\n\n<!-- START_VERBATIM -->\n<div class=\"demo\">\n    <div x-data @notify=\"alert('Hello World!')\">\n        <button @click=\"$dispatch('notify')\">\n            Notify\n        </button>\n    </div>\n</div>\n<!-- END_VERBATIM -->\n\nYou can also pass data along with the dispatched event if you wish. This data will be accessible as the `.detail` property of the event:\n\n```alpine\n<div @notify=\"alert($event.detail.message)\">\n    <button @click=\"$dispatch('notify', { message: 'Hello World!' })\">\n        Notify\n    </button>\n</div>\n```\n\n<!-- START_VERBATIM -->\n<div class=\"demo\">\n    <div x-data @notify=\"alert($event.detail.message)\">\n        <button @click=\"$dispatch('notify', { message: 'Hello World!' })\">Notify</button>\n    </div>\n</div>\n<!-- END_VERBATIM -->\n\n\nUnder the hood, `$dispatch` is a wrapper for the more verbose API: `element.dispatchEvent(new CustomEvent(...))`\n\n**Note on event propagation**\n\nNotice that, because of [event bubbling](https://en.wikipedia.org/wiki/Event_bubbling), when you need to capture events dispatched from nodes that are under the same nesting hierarchy, you'll need to use the [`.window`](https://github.com/alpinejs/alpine#x-on) modifier:\n\n**Example:**\n\n```alpine\n<!-- 🚫 Won't work -->\n<div x-data>\n    <span @notify=\"...\"></span>\n    <button @click=\"$dispatch('notify')\">Notify</button>\n</div>\n\n<!-- ✅ Will work (because of .window) -->\n<div x-data>\n    <span @notify.window=\"...\"></span>\n    <button @click=\"$dispatch('notify')\">Notify</button>\n</div>\n```\n\n> The first example won't work because when `notify` is dispatched, it'll propagate to its common ancestor, the `div`, not its sibling, the `<span>`. The second example will work because the sibling is listening for `notify` at the `window` level, which the custom event will eventually bubble up to.\n\n<a name=\"dispatching-to-components\"></a>\n## Dispatching to other components\n\nYou can also take advantage of the previous technique to make your components talk to each other:\n\n**Example:**\n\n```alpine\n<div\n    x-data=\"{ title: 'Hello' }\"\n    @set-title.window=\"title = $event.detail\"\n>\n    <h1 x-text=\"title\"></h1>\n</div>\n\n<div x-data>\n    <button @click=\"$dispatch('set-title', 'Hello World!')\">Click me</button>\n</div>\n<!-- When clicked, the content of the h1 will set to \"Hello World!\". -->\n```\n\n<a name=\"dispatching-to-x-model\"></a>\n## Dispatching to x-model\n\nYou can also use `$dispatch()` to trigger data updates for `x-model` data bindings. For example:\n\n```alpine\n<div x-data=\"{ title: 'Hello' }\">\n    <span x-model=\"title\">\n        <button @click=\"$dispatch('input', 'Hello World!')\">Click me</button>\n        <!-- After the button is pressed, `x-model` will catch the bubbling \"input\" event, and update title. -->\n    </span>\n</div>\n```\n\nThis opens up the door for making custom input components whose value can be set via `x-model`.\n\n<a name=\"cancelable-events\"></a>\n## Cancelable events\n\nYou can use the returned value of `$dispatch` to check if the event was canceled or not. This is useful when you want to prevent the default behavior of an action.\n\n```alpine\n<div x-data x-on:open=\"$event.preventDefault()\">\n    <div x-data=\"{ open: false }\">\n        <button @click=\"if($dispatch('open')){ open = true; }\">Click me</button>\n        <!-- When the button is pressed an event is dispatched and only if the result is truthy (not prevented by any handler) the content will be shown. -->\n        \n        <div x-show=\"open\">\n            <h1>Hello</h1>\n        </div>\n    </div>\n</div>\n```\n\nThis could be useful when you want to prevent opening/closing a modal or something like that by using event handlers.\n\n<a name=\"overwriting-options\"></a>\n## Overwriting options\n\nYou can use the third parameter of `$dispatch` to overwrite the default options of the event. For example, you can set `bubbles` to `false`:\n\n```alpine\n<!-- 🚫 Won't work because the event is being listened on the parent element -->\n<div x-data=\"{ title: 'Hello' }\" x-on:update-title=\"title = $event.detail\">\n    <button @click=\"$dispatch('update-title', 'Hello World!', {bubbles: false})\">Click me</button>\n</div>\n\n<!-- ✅ Will work because the event is being listened on the same element -->\n<div x-data=\"{ title: 'Hello' }\">\n    <button x-on:update-title=\"title = $event.detail\" @click=\"$dispatch('update-title', 'Hello World!', {bubbles: false})\">Click me</button>\n</div>\n```\n\nThis is useful when you want to prevent the event from bubbling up to the parent elements.\n","packages/docs/src/en/magics/el.md":"---\norder: 1\nprefix: $\ntitle: el\n---\n\n# $el\n\n`$el` is a magic property that can be used to retrieve the current DOM node.\n\n```alpine\n<button @click=\"$el.innerHTML = 'Hello World!'\">Replace me with \"Hello World!\"</button>\n```\n\n<!-- START_VERBATIM -->\n<div class=\"demo\">\n    <div x-data>\n        <button @click=\"$el.textContent = 'Hello World!'\">Replace me with \"Hello World!\"</button>\n    </div>\n</div>\n<!-- END_VERBATIM -->\n","packages/docs/src/en/magics/id.md":"---\norder: 9\nprefix: $\ntitle: id\n---\n\n# $id\n\n`$id` is a magic property that can be used to generate an element's ID and ensure that it won't conflict with other IDs of the same name on the same page.\n\nThis utility is extremely helpful when building re-usable components (presumably in a back-end template) that might occur multiple times on a page, and make use of ID attributes.\n\nThings like input components, modals, listboxes, etc. will all benefit from this utility.\n\n<a name=\"basic-usage\"></a>\n## Basic usage\n\nSuppose you have two input elements on a page, and you want them to have a unique ID from each other, you can do the following:\n\n```alpine\n<input type=\"text\" :id=\"$id('text-input')\">\n<!-- id=\"text-input-1\" -->\n\n<input type=\"text\" :id=\"$id('text-input')\">\n<!-- id=\"text-input-2\" -->\n```\n\nAs you can see, `$id` takes in a string and spits out an appended suffix that is unique on the page.\n\n<a name=\"groups-with-x-id\"></a>\n## Grouping with x-id\n\nNow let's say you want to have those same two input elements, but this time you want `<label>` elements for each of them.\n\nThis presents a problem, you now need to be able to reference the same ID twice. One for the `<label>`'s `for` attribute, and the other for the `id` on the input.\n\nHere is a way that you might think to accomplish this and is totally valid:\n\n```alpine\n<div x-data=\"{ id: $id('text-input') }\">\n    <label :for=\"id\"> <!-- \"text-input-1\" -->\n    <input type=\"text\" :id=\"id\"> <!-- \"text-input-1\" -->\n</div>\n\n<div x-data=\"{ id: $id('text-input') }\">\n    <label :for=\"id\"> <!-- \"text-input-2\" -->\n    <input type=\"text\" :id=\"id\"> <!-- \"text-input-2\" -->\n</div>\n```\n\nThis approach is fine, however, having to name and store the ID in your component scope feels cumbersome.\n\nTo accomplish this same task in a more flexible way, you can use Alpine's `x-id` directive to declare an \"id scope\" for a set of IDs:\n\n```alpine\n<div x-id=\"['text-input']\">\n    <label :for=\"$id('text-input')\"> <!-- \"text-input-1\" -->\n    <input type=\"text\" :id=\"$id('text-input')\"> <!-- \"text-input-1\" -->\n</div>\n\n<div x-id=\"['text-input']\">\n    <label :for=\"$id('text-input')\"> <!-- \"text-input-2\" -->\n    <input type=\"text\" :id=\"$id('text-input')\"> <!-- \"text-input-2\" -->\n</div>\n```\n\nAs you can see, `x-id` accepts an array of ID names. Now any usages of `$id()` within that scope, will all use the same ID. Think of them as \"id groups\".\n\n<a name=\"nesting\"></a>\n## Nesting\n\nAs you might have intuited, you can freely nest these `x-id` groups, like so:\n\n```alpine\n<div x-id=\"['text-input']\">\n    <label :for=\"$id('text-input')\"> <!-- \"text-input-1\" -->\n    <input type=\"text\" :id=\"$id('text-input')\"> <!-- \"text-input-1\" -->\n\n    <div x-id=\"['text-input']\">\n        <label :for=\"$id('text-input')\"> <!-- \"text-input-2\" -->\n        <input type=\"text\" :id=\"$id('text-input')\"> <!-- \"text-input-2\" -->\n    </div>\n</div>\n```\n\n<a name=\"keyed-ids\"></a>\n## Keyed IDs (For Looping)\n\nSometimes, it is helpful to specify an additional suffix on the end of an ID for the purpose of identifying it within a loop.\n\nFor this, `$id()` accepts an optional second parameter that will be added as a suffix on the end of the generated ID.\n\nA common example of this need is something like a listbox component that uses the `aria-activedescendant` attribute to tell assistive technologies which element is \"active\" in the list:\n\n```alpine\n<ul\n    x-id=\"['list-item']\"\n    :aria-activedescendant=\"$id('list-item', activeItem.id)\"\n>\n    <template x-for=\"item in items\" :key=\"item.id\">\n        <li :id=\"$id('list-item', item.id)\">...</li>\n    </template>\n</ul>\n```\n\nThis is an incomplete example of a listbox, but it should still be helpful to demonstrate a scenario where you might need each ID in a group to still be unique to the page, but also be keyed within a loop so that you can reference individual IDs within that group.\n","packages/docs/src/en/magics/nextTick.md":"---\norder: 6\nprefix: $\ntitle: nextTick\n---\n\n# $nextTick\n\n`$nextTick` is a magic property that allows you to only execute a given expression AFTER Alpine has made its reactive DOM updates. This is useful for times you want to interact with the DOM state AFTER it's reflected any data updates you've made.\n\n```alpine\n<div x-data=\"{ title: 'Hello' }\">\n    <button\n        @click=\"\n            title = 'Hello World!';\n            $nextTick(() => { console.log($el.innerText) });\n        \"\n        x-text=\"title\"\n    ></button>\n</div>\n```\n\nIn the above example, rather than logging \"Hello\" to the console, \"Hello World!\" will be logged because `$nextTick` was used to wait until Alpine was finished updating the DOM.\n\n<a name=\"promises\"></a>\n\n## Promises\n\n`$nextTick` returns a promise, allowing the use of `$nextTick` to pause an async function until after pending dom updates. When used like this, `$nextTick` also does not require an argument to be passed.\n\n```alpine\n<div x-data=\"{ title: 'Hello' }\">\n    <button\n        @click=\"\n            title = 'Hello World!';\n            await $nextTick();\n            console.log($el.innerText);\n        \"\n        x-text=\"title\"\n    ></button>\n</div>\n```\n","packages/docs/src/en/magics/refs.md":"---\norder: 2\nprefix: $\ntitle: refs\n---\n\n# $refs\n\n`$refs` is a magic property that can be used to retrieve DOM elements marked with `x-ref` inside the component. This is useful when you need to manually manipulate DOM elements. It's often used as a more succinct, scoped, alternative to `document.querySelector`.\n\n```alpine\n<button @click=\"$refs.text.remove()\">Remove Text</button>\n\n<span x-ref=\"text\">Hello 👋</span>\n```\n\n<!-- START_VERBATIM -->\n<div class=\"demo\">\n    <div x-data>\n        <button @click=\"$refs.text.remove()\">Remove Text</button>\n\n        <div class=\"pt-4\" x-ref=\"text\">Hello 👋</div>\n    </div>\n</div>\n<!-- END_VERBATIM -->\n\nNow, when the `<button>` is pressed, the `<span>` will be removed.\n\n<a name=\"limitations\"></a>\n### Limitations\n\nIn V2 it was possible to bind `$refs` to elements dynamically, like seen below:\n\n```alpine\n<template x-for=\"item in items\" :key=\"item.id\" >\n    <div :x-ref=\"item.name\">\n    some content ...\n    </div>\n</template>\n```\n\nHowever, in V3, `$refs` can only be accessed for elements that are created statically. So for the example above: if you were expecting the value of `item.name` inside of `$refs` to be something like *Batteries*, you should be aware that `$refs` will actually contain the literal string `'item.name'` and not *Batteries*.\n","packages/docs/src/en/magics/root.md":"---\norder: 7\nprefix: $\ntitle: root\n---\n\n# $root\n\n`$root` is a magic property that can be used to retrieve the root element of any Alpine component. In other words the closest element up the DOM tree that contains `x-data`.\n\n```alpine\n<div x-data data-message=\"Hello World!\">\n    <button @click=\"alert($root.dataset.message)\">Say Hi</button>\n</div>\n```\n\n<!-- START_VERBATIM -->\n<div x-data data-message=\"Hello World!\" class=\"demo\">\n    <button @click=\"alert($root.dataset.message)\">Say Hi</button>\n</div>\n<!-- END_VERBATIM -->\n","packages/docs/src/en/magics/store.md":"---\norder: 3\nprefix: $\ntitle: store\n---\n\n# $store\n\nYou can use `$store` to conveniently access global Alpine stores registered using [`Alpine.store(...)`](/globals/alpine-store). For example:\n\n```alpine\n<button x-data @click=\"$store.darkMode.toggle()\">Toggle Dark Mode</button>\n\n...\n\n<div x-data :class=\"$store.darkMode.on && 'bg-black'\">\n    ...\n</div>\n\n\n<script>\n    document.addEventListener('alpine:init', () => {\n        Alpine.store('darkMode', {\n            on: false,\n\n            toggle() {\n                this.on = ! this.on\n            }\n        })\n    })\n</script>\n```\n\nGiven that we've registered the `darkMode` store and set `on` to \"false\", when the `<button>` is pressed, `on` will be \"true\" and the background color of the page will change to black.\n\n<a name=\"single-value-stores\"></a>\n## Single-value stores\n\nIf you don't need an entire object for a store, you can set and use any kind of data as a store.\n\nHere's the example from above but using it more simply as a boolean value:\n\n```alpine\n<button x-data @click=\"$store.darkMode = ! $store.darkMode\">Toggle Dark Mode</button>\n\n...\n\n<div x-data :class=\"$store.darkMode && 'bg-black'\">\n    ...\n</div>\n\n\n<script>\n    document.addEventListener('alpine:init', () => {\n        Alpine.store('darkMode', false)\n    })\n</script>\n```\n\n[→ Read more about Alpine stores](/globals/alpine-store)\n","packages/docs/src/en/magics/watch.md":"---\norder: 4\ntitle: watch\n---\n\n# $watch\n\nYou can \"watch\" a component property using the `$watch` magic method. For example:\n\n```alpine\n<div x-data=\"{ open: false }\" x-init=\"$watch('open', value => console.log(value))\">\n    <button @click=\"open = ! open\">Toggle Open</button>\n</div>\n```\n\nIn the above example, when the button is pressed and `open` is changed, the provided callback will fire and `console.log` the new value:\n\nYou can watch deeply nested properties using \"dot\" notation\n\n```alpine\n<div x-data=\"{ foo: { bar: 'baz' }}\" x-init=\"$watch('foo.bar', value => console.log(value))\">\n    <button @click=\"foo.bar = 'bob'\">Toggle Open</button>\n</div>\n```\n\nWhen the `<button>` is pressed, `foo.bar` will be set to \"bob\", and \"bob\" will be logged to the console.\n\n<a name=\"getting-the-old-value\"></a>\n### Getting the \"old\" value\n\n`$watch` keeps track of the previous value of the property being watched, You can access it using the optional second argument to the callback like so:\n\n```alpine\n<div x-data=\"{ open: false }\" x-init=\"$watch('open', (value, oldValue) => console.log(value, oldValue))\">\n    <button @click=\"open = ! open\">Toggle Open</button>\n</div>\n```\n\n<a name=\"deep-watching\"></a>\n### Deep watching\n\n`$watch` automatically watches from changes at any level but you should keep in mind that, when a change is detected, the watcher will return the value of the observed property, not the value of the subproperty that has changed.\n\n```alpine\n<div x-data=\"{ foo: { bar: 'baz' }}\" x-init=\"$watch('foo', (value, oldValue) => console.log(value, oldValue))\">\n    <button @click=\"foo.bar = 'bob'\">Update</button>\n</div>\n```\n\nWhen the `<button>` is pressed, `foo.bar` will be set to \"bob\", and \"{bar: 'bob'} {bar: 'baz'}\" will be logged to the console (new and old value).\n\n> ⚠️ Changing a property of a \"watched\" object as a side effect of the `$watch` callback will generate an infinite loop and eventually error. \n\n```alpine\n<!-- 🚫 Infinite loop -->\n<div x-data=\"{ foo: { bar: 'baz', bob: 'lob' }}\" x-init=\"$watch('foo', value => foo.bob = foo.bar)\">\n    <button @click=\"foo.bar = 'bob'\">Update</button>\n</div>\n```\n","packages/docs/src/en/plugins.md":"---\norder: 7\ntitle: Plugins\nfont-type: mono\ntype: sub-directory\n---\n","packages/docs/src/en/plugins/anchor.md":"---\norder: 7\ntitle: Anchor\ndescription: Anchor an element's positioning to another element on the page\ngraph_image: https://alpinejs.dev/social_anchor.jpg\n---\n\n# Anchor Plugin\n\nAlpine's Anchor plugin allows you to easily anchor an element's positioning to another element on the page.\n\nThis functionality is useful when creating dropdown menus, popovers, dialogs, and tooltips with Alpine.\n\nThe \"anchoring\" functionality used in this plugin is provided by the [Floating UI](https://floating-ui.com/) project.\n\n<a name=\"installation\"></a>\n## Installation\n\nYou can use this plugin by either including it from a `<script>` tag or installing it via NPM:\n\n### Via CDN\n\nYou can include the CDN build of this plugin as a `<script>` tag, just make sure to include it BEFORE Alpine's core JS file.\n\n```alpine\n<!-- Alpine Plugins -->\n<script defer src=\"https://cdn.jsdelivr.net/npm/@alpinejs/anchor@3.x.x/dist/cdn.min.js\"></script>\n\n<!-- Alpine Core -->\n<script defer src=\"https://cdn.jsdelivr.net/npm/alpinejs@3.x.x/dist/cdn.min.js\"></script>\n```\n\n### Via NPM\n\nYou can install Anchor from NPM for use inside your bundle like so:\n\n```shell\nnpm install @alpinejs/anchor\n```\n\nThen initialize it from your bundle:\n\n```js\nimport Alpine from 'alpinejs'\nimport anchor from '@alpinejs/anchor'\n\nAlpine.plugin(anchor)\n\n...\n```\n\n<a name=\"x-anchor\"></a>\n## x-anchor\n\nThe primary API for using this plugin is the `x-anchor` directive.\n\nTo use this plugin, add the `x-anchor` directive to any element and pass it a reference to the element you want to anchor it's position to (often a button on the page).\n\nBy default, `x-anchor` will set the element's CSS to `position: absolute` and the appropriate `top` and `left` values. If the anchored element is normally displayed below the reference element but doesn't have room on the page, it's styling will be adjusted to render above the element.\n\nFor example, here's a simple dropdown anchored to the button that toggles it:\n\n```alpine\n<div x-data=\"{ open: false }\">\n    <button x-ref=\"button\" @click=\"open = ! open\">Toggle</button>\n\n    <div x-show=\"open\" x-anchor=\"$refs.button\">\n        Dropdown content\n    </div>\n</div>\n```\n\n<!-- START_VERBATIM -->\n<div x-data=\"{ open: false }\" class=\"demo overflow-hidden\">\n    <div class=\"flex justify-center\">\n        <button x-ref=\"button\" @click=\"open = ! open\">Toggle</button>\n    </div>\n\n    <div x-show=\"open\" x-anchor=\"$refs.button\" class=\"bg-white rounded p-4 border shadow z-10\">\n        Dropdown content\n    </div>\n</div>\n<!-- END_VERBATIM -->\n\n<a name=\"positioning\"></a>\n## Positioning\n\n`x-anchor` allows you to customize the positioning of the anchored element using the following modifiers:\n\n* Bottom: `.bottom`, `.bottom-start`, `.bottom-end`\n* Top: `.top`, `.top-start`, `.top-end`\n* Left: `.left`, `.left-start`, `.left-end`\n* Right: `.right`, `.right-start`, `.right-end`\n\nHere is an example of using `.bottom-start` to position a dropdown below and to the right of the reference element:\n\n```alpine\n<div x-data=\"{ open: false }\">\n    <button x-ref=\"button\" @click=\"open = ! open\">Toggle</button>\n\n    <div x-show=\"open\" x-anchor.bottom-start=\"$refs.button\">\n        Dropdown content\n    </div>\n</div>\n```\n\n<!-- START_VERBATIM -->\n<div x-data=\"{ open: false }\" class=\"demo overflow-hidden\">\n    <div class=\"flex justify-center\">\n        <button x-ref=\"button\" @click=\"open = ! open\">Toggle</button>\n    </div>\n\n    <div x-show=\"open\" x-anchor.bottom-start=\"$refs.button\" class=\"bg-white rounded p-4 border shadow z-10\">\n        Dropdown content\n    </div>\n</div>\n<!-- END_VERBATIM -->\n\n<a name=\"fixed-positioning\"></a>\n### Fixed positioning\n\nBy default, `x-anchor` applies `position: absolute` to the anchored element. This is fine for most cases, but it falls apart when the reference element lives inside a container with `overflow: hidden`, `overflow: clip`, or `overflow: auto`—the anchored element is clipped along with it.\n\nYou can instruct Floating UI to use a fixed positioning strategy instead by adding the `.fixed` modifier:\n\n```html\n<div x-data=\"{ open: false }\">\n    <button x-ref=\"button\" @click=\"open = ! open\">Toggle</button>\n\n    <div x-show=\"open\" x-anchor.fixed=\"$refs.button\">\n        Dropdown content\n    </div>\n</div>\n```\n\n<!-- START_VERBATIM -->\n<div x-data=\"{ open: false }\" class=\"demo overflow-hidden\">\n    <div class=\"flex justify-center\">\n        <button x-ref=\"button\" @click=\"open = ! open\">Toggle</button>\n    </div>\n\n    <div x-show=\"open\" x-anchor.fixed=\"$refs.button\" class=\"bg-white rounded p-4 border shadow z-10\">\n        Dropdown content\n    </div>\n</div>\n<!-- END_VERBATIM -->\n\n> **Heads up:** a `transform`, `filter`, `perspective`, `backdrop-filter`, `will-change`, or `contain` on any ancestor element creates a new containing block for `position: fixed` descendants ([per the CSS spec](https://developer.mozilla.org/en-US/docs/Web/CSS/position#fixed_positioning)). When that happens, `.fixed` will behave like `position: absolute` relative to that ancestor—and won't escape its `overflow: hidden`. If `.fixed` seems to be doing nothing, check for a transformed ancestor.\n\n<a name=\"offset\"></a>\n## Offset\n\nYou can add an offset to your anchored element using the `.offset.[px value]` modifier like so:\n\n```alpine\n<div x-data=\"{ open: false }\">\n    <button x-ref=\"button\" @click=\"open = ! open\">Toggle</button>\n\n    <div x-show=\"open\" x-anchor.offset.10=\"$refs.button\">\n        Dropdown content\n    </div>\n</div>\n```\n\n<!-- START_VERBATIM -->\n<div x-data=\"{ open: false }\" class=\"demo overflow-hidden\">\n    <div class=\"flex justify-center\">\n        <button x-ref=\"button\" @click=\"open = ! open\">Toggle</button>\n    </div>\n\n    <div x-show=\"open\" x-anchor.offset.10=\"$refs.button\" class=\"bg-white rounded p-4 border shadow z-10\">\n        Dropdown content\n    </div>\n</div>\n<!-- END_VERBATIM -->\n\n<a name=\"prevent-flipping\"></a>\n## Prevent flipping position\n\nBy default, `x-anchor` will flip the position of the anchored element if it doesn't have enough room to render below the reference element.\n\nYou can prevent this behavior by adding the `.noflip` modifier:\n\n```alpine\n<div x-data=\"{ open: false }\">\n    <button x-ref=\"button\" @click=\"open = ! open\">Toggle</button>\n\n    <div x-show=\"open\" x-anchor.noflip=\"$refs.button\">\n        Dropdown content\n    </div>\n</div>\n```\n\n<!-- START_VERBATIM -->\n<div x-data=\"{ open: false }\" class=\"demo overflow-hidden\">\n    <div class=\"flex justify-center\">\n        <button x-ref=\"button\" @click=\"open = ! open\">Toggle</button>\n    </div>\n\n    <div x-show=\"open\" x-anchor.noflip=\"$refs.button\" class=\"bg-white rounded p-4 border shadow z-10\">\n        Dropdown content\n    </div>\n</div>\n<!-- END_VERBATIM -->\n\n<a name=\"manual-styling\"></a>\n## Manual styling\n\nBy default, `x-anchor` applies the positioning styles to your element under the hood. If you'd prefer full control over styling, you can pass the `.no-style` modifer and use the `$anchor` magic to access the values inside another Alpine expression.\n\nBelow is an example of bypassing `x-anchor`'s internal styling and instead applying the styles yourself using `x-bind:style`:\n\n```alpine\n<div x-data=\"{ open: false }\">\n    <button x-ref=\"button\" @click=\"open = ! open\">Toggle</button>\n\n    <div\n        x-show=\"open\"\n        x-anchor.no-style=\"$refs.button\"\n        x-bind:style=\"{ position: 'absolute', top: $anchor.y+'px', left: $anchor.x+'px' }\"\n    >\n        Dropdown content\n    </div>\n</div>\n```\n\n<!-- START_VERBATIM -->\n<div x-data=\"{ open: false }\" class=\"demo overflow-hidden\">\n    <div class=\"flex justify-center\">\n        <button x-ref=\"button\" @click=\"open = ! open\">Toggle</button>\n    </div>\n\n    <div\n        x-show=\"open\"\n        x-anchor.no-style=\"$refs.button\"\n        x-bind:style=\"{ position: 'absolute', top: $anchor.y+'px', left: $anchor.x+'px' }\"\n        class=\"bg-white rounded p-4 border shadow z-10\"\n    >\n        Dropdown content\n    </div>\n</div>\n<!-- END_VERBATIM -->\n\n> **Combining `.no-style` with `.fixed`:** when you opt out of Alpine's internal styling and also want fixed positioning, remember to set `position: 'fixed'` yourself. `$anchor.x` and `$anchor.y` are returned in the coordinate space of whichever strategy is active—absolute coordinates are relative to the offset parent, fixed coordinates are relative to the viewport—so applying the wrong `position` will put your element in the wrong place.\n>\n> ```alpine\n> <div\n>     x-show=\"open\"\n>     x-anchor.no-style.fixed=\"$refs.button\"\n>     x-bind:style=\"{ position: 'fixed', top: $anchor.y+'px', left: $anchor.x+'px' }\"\n> >\n>     Dropdown content\n> </div>\n> ```\n\n<a name=\"from-id\"></a>\n## Anchor to an ID\n\nThe examples thus far have all been anchoring to other elements using Alpine refs.\n\nBecause `x-anchor` accepts a reference to any DOM element, you can use utilities like `document.getElementById()` to anchor to an element by its `id` attribute:\n\n```alpine\n<div x-data=\"{ open: false }\">\n    <button id=\"trigger\" @click=\"open = ! open\">Toggle</button>\n\n    <div x-show=\"open\" x-anchor=\"document.getElementById('trigger')\">\n        Dropdown content\n    </div>\n</div>\n```\n\n<!-- START_VERBATIM -->\n<div x-data=\"{ open: false }\" class=\"demo overflow-hidden\">\n    <div class=\"flex justify-center\">\n        <button class=\"trigger\" @click=\"open = ! open\">Toggle</button>\n    </div>\n\n\n    <div x-show=\"open\" x-anchor=\"document.querySelector('.trigger')\">\n        Dropdown content\n    </div>\n</div>\n<!-- END_VERBATIM -->\n","packages/docs/src/en/plugins/collapse.md":"<!-- Skill available on-demand via /api/skills/alpinejs/alpine?path=packages%2Fdocs%2Fsrc%2Fen%2Fplugins%2Fcollapse.md -->","packages/docs/src/en/plugins/focus.md":"<!-- Skill available on-demand via /api/skills/alpinejs/alpine?path=packages%2Fdocs%2Fsrc%2Fen%2Fplugins%2Ffocus.md -->","packages/docs/src/en/plugins/intersect.md":"<!-- Skill available on-demand via /api/skills/alpinejs/alpine?path=packages%2Fdocs%2Fsrc%2Fen%2Fplugins%2Fintersect.md -->","packages/docs/src/en/plugins/mask.md":"<!-- Skill available on-demand via /api/skills/alpinejs/alpine?path=packages%2Fdocs%2Fsrc%2Fen%2Fplugins%2Fmask.md -->","packages/docs/src/en/plugins/morph.md":"<!-- Skill available on-demand via /api/skills/alpinejs/alpine?path=packages%2Fdocs%2Fsrc%2Fen%2Fplugins%2Fmorph.md -->","packages/docs/src/en/plugins/persist.md":"<!-- Skill available on-demand via /api/skills/alpinejs/alpine?path=packages%2Fdocs%2Fsrc%2Fen%2Fplugins%2Fpersist.md -->","packages/docs/src/en/plugins/resize.md":"<!-- Skill available on-demand via /api/skills/alpinejs/alpine?path=packages%2Fdocs%2Fsrc%2Fen%2Fplugins%2Fresize.md -->","packages/docs/src/en/plugins/sort.md":"<!-- Skill available on-demand via /api/skills/alpinejs/alpine?path=packages%2Fdocs%2Fsrc%2Fen%2Fplugins%2Fsort.md -->","packages/docs/src/en/start-here.md":"<!-- Skill available on-demand via /api/skills/alpinejs/alpine?path=packages%2Fdocs%2Fsrc%2Fen%2Fstart-here.md -->","packages/docs/src/en/upgrade-guide.md":"<!-- Skill available on-demand via /api/skills/alpinejs/alpine?path=packages%2Fdocs%2Fsrc%2Fen%2Fupgrade-guide.md -->"},"items":[{"name":"CLAUDE.md","path":"CLAUDE.md","rawUrl":"https://raw.githubusercontent.com/alpinejs/alpine/HEAD/CLAUDE.md","title":"Claude Agent Guidelines & System Prompt","category":"claude-rule","format":"markdown","content":"# Alpine.js Development Guidelines\n\n## Pull Request Evaluation Criteria\n\nWhen evaluating pull requests for Alpine.js, assess the following:\n\n### 1. Tests\n- Are tests provided for the change?\n- Do existing tests still pass?\n- For configuration changes (package.json, build scripts), tests may not be required\n\n### 2. Code Style\n- Does the code match Alpine's existing patterns?\n- Check indentation, naming conventions, and structure\n- For package.json changes, ensure consistency with other packages in the monorepo\n\n### 3. Code Quality\n- Is the code clean and maintainable?\n- Is the change focused and minimal?\n- Are there any unnecessary changes or complexity?\n- Does this PR contain changes that should apply elsewhere?\n\n### 4. Simplicity\n- Is this a simple, focused change?\n- Does it follow Alpine's philosophy of simplicity?\n- Could it be implemented more simply?\n- Are the proposed additions intuitive for users? or do they require extra knowledge that they have to dig for.\n\n### 5. Precedent\n- Does this PR (both public facing additions and internal implementation) follow established precedents in the project\n- Does it use terms that are unfamiliar to the project as of yet?\n\n### 6. Description Quality\n- Is there a clear explanation of what/why/how?\n- Are breaking changes documented?\n- Is backward compatibility addressed?\n\n### 7. Community Engagement\n- Are there comments, reviews, or discussions?\n- Has it been approved by maintainers?\n- Are there any conflicting opinions or unresolved concerns?\n\n### Mergeability Rating\nBased on the above, rate as:\n- **HIGH**: Ready to merge (all criteria met, approved)\n- **MEDIUM**: Needs attention (technically sound but missing reviews/tests)\n- **LOW**: Requires work (has issues or conflicts to resolve)\n\n## Project Structure\n\nAlpine.js is a monorepo with packages in `/packages/`:\n- Each package has its own package.json\n- Build outputs go to `dist/` with `.cjs.js`, `.esm.js`, and `.min.js` versions\n- Browser tests use Cypress, unit tests use Vitest\n- CI runs on GitHub Actions\n\n## Common Commands\n\n```bash\n# Build\nnpm run build                # Build all packages\n\n# Browser tests (Cypress)\nnpm test                     # Run all tests\nnpx cypress run --spec ./tests/cypress/integration/[filename].spec.js  # Run single spec\n\n# Unit tests (Vitest)\nnpx vitest run tests/vitest/[filename].spec.js  # Run single spec\n\n# Review PRs\ngh pr list                   # List open PRs\ngh pr view [number]          # View PR details\ngh pr diff [number]          # View code changes\ngh pr checks [number]        # Check CI status\n```\n\n## Manual Testing\n\n1. Edit `./index.html` at project root\n2. Open in browser at `http://alpine.test/` (assumes local dev server mapped to directory name)\n\n## Summary\n\nAfter assessing the pull request on the above qualities, provide a summary explaining the problem this PR addresses and the fix, and why it's a good or bad fix. Do it in plain language as if you are personally advising me on what the PR is and weather or not I should merge it. And if not, what might need to be addressed first. If things need to be addressed, offer to address them yourself.\n\nPlease use code snippets to establish a starting point and and ending point if helpful. For example, when explaining the problem, it is often easier to provide a brief explanation alongside a code snippet of what is currently problematic, then when explaining the solution, showing what new code will allow a fix if applicable.","isInternal":false,"tokens":775,"sizeBytes":3466},{"name":"SKILL.md","path":".claude/skills/review-pr/SKILL.md","rawUrl":"https://raw.githubusercontent.com/alpinejs/alpine/HEAD/.claude/skills/review-pr/SKILL.md","title":"review-pr","category":"anthropic-skill","format":"markdown","content":"---\nname: review-pr\ndescription: Review an open PR like a maintainer — checkout, fix issues, push changes, post a structured verdict comment. You just merge or close.\ndisable-model-invocation: true\nallowed-tools: Bash, Read, Glob, Grep, Edit, Write, Task\nargument-hint: \"[PR number (optional - picks latest if omitted)]\"\n---\n\n# /review-pr - Maintainer-style PR review bot\n\nYou are a strict, opinionated maintainer of the Alpine.js project. Your job: review a PR, fix what you can, push fixes, and post a verdict comment so Caleb can just merge or close.\n\n**IMPORTANT: Every numbered step below is mandatory. Do not skip steps, do not substitute your own approach, do not rationalize \"I already have this data from somewhere else.\" Run the exact commands listed. If a command fails, retry it — do not silently move on. Complete each step fully before starting the next.**\n\n## Step 1: Pick a PR\n\nIf `$ARGUMENTS` is provided, use that as the PR number. Otherwise, pick the latest open PR:\n\n```bash\ngh pr list --state open --limit 1 --json number -q '.[0].number'\n```\n\n## Step 2: Check if already reviewed\n\nLook for the `<!-- claude-review -->` marker in PR comments:\n\n```bash\ngh pr view {number} --json comments -q '.comments[].body' | grep -q '<!-- claude-review -->'\n```\n\nIf found, tell the user this PR was already reviewed and stop. Unless `$ARGUMENTS` explicitly includes `--force` or the user asks to re-review.\n\n## Step 3: Fetch PR data\n\nRun ALL FOUR of these commands in parallel. If any fail, retry them. Do not proceed to Step 4 until you have output from all four:\n\n```bash\ngh pr view {number} --json title,body,author,state,labels,comments,reviews,files,additions,deletions,baseRefName,headRefName,createdAt,updatedAt,reviewDecision,statusCheckRollup,url\ngh pr diff {number}\ngh pr checks {number}\ngh api repos/{owner}/{repo}/issues/{number}/reactions\n```\n\n## Step 4: Checkout locally and merge main\n\n```bash\ngh pr checkout {number}\ngit merge main\n```\n\nAlways merge main into the PR branch before reviewing. This ensures you have the latest project files (rules, skills, docs) and avoids reviewing against stale code. If the merge has conflicts, resolve them or flag for the contributor.\n\n## Step 5: Read and classify\n\nRead through the diff and PR body. Classify the PR:\n\n- **Bug fix** - Fixes broken behavior\n- **Feature** - Adds new functionality\n- **Refactor** - Restructures without changing behavior\n- **Docs** - Documentation only\n- **Mixed** - Multiple categories (flag this as a concern)\n\n## Step 6: Challenge the contributor's framing\n\nDon't accept the PR description's framing of the bug or problem at face value. Verify independently:\n\n1. **Identify the root cause yourself.** Read the code the PR modifies. Understand *why* the bug exists before looking at how the PR fixes it.\n2. **Does the test actually isolate that root cause?** Or does it test through incidental complexity the contributor happened to encounter? If the test would still pass after removing the actual fix, it's testing the wrong thing.\n3. **If the test encodes a wrong mental model, rewrite it.** Strip it to the minimum reproduction that targets the real bug. Tests are documentation — they should communicate the bug precisely, not replay the contributor's debugging journey.\n4. **Challenge the implementation architecture, not just the problem framing.** When simplifying a PR, don't just strip parameters — ask whether the contributor's fundamental approach is the right one. A simpler version of a bad approach is still a bad approach. Ask: \"What's the laziest correct solution? Does the language/framework already handle this if I just let it?\"\n\n## Step 7: Evaluate\n\n### For bug fixes\n\n1. **Has a test?** If not, write one. The test should fail on `main` and pass on the PR branch.\n2. **Test covers the actual fix?** Including edge cases?\n3. **Actually verify regression.** Don't just reason about whether the test fails without the fix — prove it. Stash the fix (`git stash -- <fix files>`), rebuild (`npm run build`), run the test. If it passes without the fix, the test is not testing the fix. Unstash and rewrite the test. This is non-negotiable for bug fix PRs.\n4. **Test isolates root cause?** Does the test target the actual bug, or does it test through incidental complexity the contributor happened to encounter? Strip tests to the minimum reproduction. Tests are documentation — they should communicate the bug precisely.\n5. **Naming quality?** Review all test names, component names, variable names. Contributors often use names that reflect their mental model, not the actual architecture. Fix these before merging — they become permanent.\n6. **Unnecessary fixtures/setup?** If the test introduces helper files, imports, or setup that aren't essential to reproducing the bug, remove them.\n7. **For visual/browser bugs, test observable behavior, not DOM state.** Assertions like \"element is present\" or \"attribute is set\" can pass while the visual bug persists. For animation bugs: assert on `document.getAnimations()` state. For style bugs: assert on computed styles or style properties after the relevant lifecycle completes. For timing bugs: use assertions that would produce different results with and without the fix.\n8. **Fix is surgical/minimal?** No unrelated changes?\n9. **Regression risk?** Could this break something else?\n\n### For features\n\nAddress EVERY item below. Do not skip any — even to say \"N/A\":\n\n1. **Already possible without new API?** Default stance: reject new public API surface. Trace the full existing code path before evaluating the new one — the use case may already be solvable. New directives/modifiers/magic properties are maintained forever; only add when there's no existing path.\n2. **Community demand?** Check reactions on the PR and linked issues. Low engagement = higher bar.\n3. **Intuitive API?** Single-word modifiers preferred (`x-transition.opacity` not `x-transition.opacity-only`). Alpine favors short, expressive directive syntax.\n4. **Precedent?** Does it build on existing patterns or introduce new ones? New patterns need strong justification.\n5. **Scope?** Should this be a core Alpine feature or a separate plugin package? Alpine core should stay minimal.\n6. **Docs included?** Features need documentation.\n7. **Registration complete?** Check that new directives/magics/plugins are properly registered and exported.\n\n### For all PRs\n\nAddress EVERY item below:\n\n1. **Project style?**\n   - JS: no semicolons, `let` not `const`\n   - Follows Alpine's existing patterns and conventions\n2. **Single responsibility?** Flag PRs doing too many things.\n3. **Security?** Extra scrutiny for: `x-html`, expression evaluation, `Alpine.evaluate()`, anything touching user-provided expressions or the reactive system.\n4. **Built JS assets in diff?** Check the file list from `gh pr diff --name-only` for `dist/` files. These should NOT be committed. Remove them.\n5. **\"No for now\" bias.** When in doubt, lean toward not merging. It's easier to add later than remove.\n6. **Async timing fixes are treacherous.** When a PR fixes a bug involving microtask/macrotask timing (Alpine effects, `nextTick`, `queueMicrotask`, `MutationObserver` scheduling): don't trust that the approach works just because the reasoning sounds right. Alpine's reactivity scheduler uses multi-hop `queueMicrotask` chains — a single `queueMicrotask` or even `setTimeout(0)` may not be enough. If you can't verify the timing empirically, flag it for discussion.\n7. **\"What's the laziest correct solution?\"** Before evaluating the PR's implementation details, independently brainstorm the simplest possible fix. The contributor's approach is often shaped by their discovery path, not by what's optimal.\n\n## Step 8: Run relevant tests only\n\n**NEVER run the full test suite.** Only run tests the PR adds or touches:\n\n```bash\n# Find test files in the diff\ngh pr diff {number} --name-only | grep -E '\\.spec\\.js$'\n```\n\nRun those specific tests:\n\n```bash\n# For Cypress browser tests\nnpx cypress run --spec ./tests/cypress/integration/{test-file}.spec.js\n\n# For Vitest unit tests\nnpx vitest run tests/vitest/{test-file}.spec.js\n```\n\nIf the PR doesn't touch test files but you wrote tests in step 6, run those.\n\nAlso check CI status:\n\n```bash\ngh pr checks {number}\n```\n\n## Step 8b: If the PR has no fix, write one\n\nIf the PR only adds a failing test (or describes a bug without a fix), don't just review the test and stop. **Explore solution paths and try to fix the bug yourself.** This is the most valuable thing you can do.\n\n1. Identify 2-3 possible fix approaches\n2. Evaluate trade-offs of each (surgical vs broad, risk of regressions, etc.)\n3. Present the options to Caleb with a brief explanation of each\n4. Once Caleb picks a direction, implement and test it\n\n## Step 9: Make fixes directly\n\nFix issues you find. Common fixes:\n\n- **Style violations**: Remove semicolons from JS, change `const` to `let`\n- **Built assets in diff**: `git checkout main -- dist/` (or whatever the build output path is)\n- **Missing tests**: Write them\n- **Small refactors**: Simplify overly complex code\n- **Missing registration**: Add to package index files, etc.\n- **Before committing a simplified version of the contributor's code, do a smell test:** Could this be done in fewer lines with a completely different approach? The best code is the code you delete.\n\nStage and commit fixes:\n\n```bash\ngit add -A\ngit commit -m \"Review fixes: [brief description]\n\nCo-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>\"\n```\n\n## Step 10: Push to PR branch\n\nTry to push to the contributor's branch:\n\n```bash\ngit push\n```\n\n### If push fails (fork doesn't allow maintainer edits)\n\n1. Create a new branch from `main`\n2. Cherry-pick the contributor's commits\n3. Apply your fixes on top\n4. Push the new branch\n5. Create a new PR:\n\n```bash\ngh pr create --title \"{original title}\" --body \"$(cat <<'EOF'\nCloses #{original_number}\n\nCherry-picked from #{original_number} by @{author} with review fixes applied.\n\n## Original description\n{original_body}\n\n## Review fixes applied\n{list of fixes}\nEOF\n)\"\n```\n\n6. Comment on the original PR explaining the new PR.\n\n## Step 11: Post verdict comment\n\nPost a structured comment on the PR:\n\n```bash\ngh pr comment {number} --body \"$(cat <<'EOF'\n<!-- claude-review -->\n## PR Review: #{number} — {title}\n\n**Type**: {Bug fix | Feature | Refactor | Docs | Mixed}\n**Verdict**: {Merge | Request changes | Needs discussion | Close}\n\n### What's happening (plain English)\n{Explain the PR like Caleb is a 3-year-old who happens to be an expert in Alpine internals but has zero context on this specific PR. Use a numbered step-by-step walkthrough of the exact sequence that triggers the bug/feature. No jargon beyond what Alpine devs already know. Be crystal clear and concise — this is the most important section.}\n\n### Other approaches considered\n{Briefly list 2-3 alternative ways this could have been solved, with one sentence each on why the PR's approach is better (or worse). If there's only one reasonable approach, say so and explain why. This helps Caleb quickly evaluate whether the chosen path is the right one.}\n\n### Changes Made\n{List of fixups you pushed, or \"No changes made\" if none}\n\n### Test Results\n{Which tests ran, pass/fail status, CI status}\n\n### Code Review\n{Specific feedback with file:line references. What's good, what's concerning.}\n\n### Security\n{Any security considerations, or \"No security concerns identified.\"}\n\n### Verdict\n{Your reasoning for the verdict. Be direct. If it should be merged, say why. If closed, say why kindly but clearly.}\n\n---\n*Reviewed by Claude*\nEOF\n)\"\n```\n\n## Verdict guidelines\n\n- **Merge**: Code is correct, tests pass, style is clean, feature is wanted. You've fixed any minor issues.\n- **Request changes**: Significant issues you can't fix yourself (architectural problems, missing context, needs author input).\n- **Needs discussion**: Feature scope questions, API design debates, core vs plugin questions. Tag these for Caleb.\n- **Close**: PR is stale with no response, duplicates existing functionality, or solves a problem that shouldn't be solved. Be kind.\n\n## Important rules\n\n- NEVER run the full test suite. Only run tests the PR touches or that you wrote.\n- Always use the `<!-- claude-review -->` marker so you can detect previous reviews.\n- Be opinionated. This project has strong conventions — enforce them.\n- Fix what you can. Don't just point out problems if you can solve them.\n- Security is non-negotiable. If you see a security issue, verdict is always \"Request changes\" regardless of everything else.\n- Match the project voice: practical, direct, minimal.\n- Don't accept the contributor's framing of the problem at face value. Verify the root cause independently, then ensure the test targets that root cause — not the contributor's incidental path to discovering it.\n- \"Should this exist?\" before \"Is this correct?\" — Don't get pulled into reviewing implementation details (code quality, edge cases, naming) until you've decided the feature itself is justified. Implementation nits imply acceptance.\n- Tests are documentation. A sloppy test that passes is not good enough — it should precisely communicate what broke and why.\n- Review contributor naming as critically as contributor code. Bad names get merged and become permanent.\n","frontmatter":{"name":"review-pr","description":"Review an open PR like a maintainer — checkout, fix issues, push changes, post a structured verdict comment. You just merge or close.","disable-model-invocation":true,"allowed-tools":"Bash, Read, Glob, Grep, Edit, Write, Task","argument-hint":"[PR number (optional - picks latest if omitted)]","allowedTools":["Bash,","Read,","Glob,","Grep,","Edit,","Write,","Task"],"disableModelInvocation":true},"allowedTools":["Bash,","Read,","Glob,","Grep,","Edit,","Write,","Task"],"isInternal":false,"tokens":3080,"sizeBytes":13345},{"name":"SKILL.md","path":".claude/skills/summarize-activity/SKILL.md","rawUrl":"https://raw.githubusercontent.com/alpinejs/alpine/HEAD/.claude/skills/summarize-activity/SKILL.md","title":"summarize-activity","category":"anthropic-skill","format":"markdown","content":"---\nname: summarize-activity\ndescription: Summarize recent GitHub activity — discussions, PRs, issues, events, traffic — into an actionable report so you can stay on top of the project without reading everything.\ndisable-model-invocation: true\nallowed-tools: Bash, Read, Task\nargument-hint: \"[timeframe: 24h (default), 48h, 7d, 1w]\"\n---\n\n# /summarize-activity - GitHub activity digest\n\nYou generate a concise, actionable summary of recent Alpine.js GitHub activity for Caleb.\n\n**IMPORTANT: Every numbered step below is mandatory. Do not skip steps, do not substitute your own approach. Run the exact commands listed. If a command fails, retry it — do not silently move on. Complete each step fully before starting the next.**\n\n## Step 1: Parse timeframe\n\nParse `$ARGUMENTS` into a cutoff timestamp. Supported formats:\n- `24h`, `48h`, `72h` — hours (default: `24h` if no argument)\n- `7d`, `14d`, `30d` — days\n- `1w`, `2w` — weeks (1w = 7d)\n\nCompute the ISO 8601 cutoff timestamp:\n\n```bash\n# Example for 24h:\ndate -u -v-24H '+%Y-%m-%dT%H:%M:%SZ'\n# Example for 7d:\ndate -u -v-7d '+%Y-%m-%dT%H:%M:%SZ'\n```\n\nStore the cutoff timestamp and the human-readable timeframe label (e.g., \"last 24 hours\", \"last 7 days\") for use in later steps.\n\n## Step 2: Fetch activity in parallel\n\nRun ALL FIVE of these commands in parallel using the Bash tool. If any fail, retry them. Do not proceed to Step 3 until you have output from all five.\n\n**Owner/repo:** `alpinejs/alpine`\n\n### 2a. Discussions (GraphQL)\n\n```bash\ngh api graphql -f query='\n{\n  repository(owner: \"alpinejs\", name: \"alpine\") {\n    discussions(first: 50, orderBy: {field: UPDATED_AT, direction: DESC}) {\n      nodes {\n        title\n        url\n        author { login }\n        category { name }\n        comments { totalCount }\n        body\n        answer { author { login } body createdAt }\n        createdAt\n        updatedAt\n      }\n    }\n  }\n}'\n```\n\n### 2b. Pull Requests\n\n```bash\ngh pr list --repo alpinejs/alpine --state all --limit 50 --json number,title,url,author,state,labels,createdAt,updatedAt,additions,deletions,headRefName,baseRefName,reviewDecision,comments\n```\n\n### 2c. Issues\n\n```bash\ngh issue list --repo alpinejs/alpine --state all --limit 50 --json number,title,url,author,state,labels,createdAt,updatedAt,comments\n```\n\n### 2d. Events\n\n```bash\ngh api repos/alpinejs/alpine/events --paginate --jq '.[] | {type, actor: .actor.login, created_at: .created_at, payload_action: .payload.action, ref: .payload.ref, ref_type: .payload.ref_type}' | head -100\n```\n\n### 2e. Traffic & stars\n\n```bash\ngh api repos/alpinejs/alpine/traffic/views 2>/dev/null; echo \"---SEPARATOR---\"; gh api repos/alpinejs/alpine/traffic/clones 2>/dev/null; echo \"---SEPARATOR---\"; gh api repos/alpinejs/alpine --jq '{stargazers_count, forks_count, open_issues_count, watchers_count}'\n```\n\nNote: Traffic endpoints require push access. If they return 403, skip traffic data and note it in the report.\n\n## Step 3: Fetch comment threads for active items\n\nFor discussions that have comments updated within the timeframe, fetch full comment bodies via GraphQL. Batch up to 10 discussions per query:\n\n```bash\ngh api graphql -f query='\n{\n  repository(owner: \"alpinejs\", name: \"alpine\") {\n    discussion(number: {NUMBER}) {\n      comments(last: 10) {\n        nodes {\n          author { login }\n          body\n          createdAt\n          updatedAt\n        }\n      }\n    }\n  }\n}'\n```\n\nFor the most active PRs and issues (those with comments updated in timeframe), fetch recent comments:\n\n```bash\ngh api repos/alpinejs/alpine/issues/{number}/comments --jq '.[] | select(.updated_at > \"{CUTOFF}\") | {user: .user.login, body: .body, created_at: .created_at}'\n```\n\nOnly fetch threads that are clearly within the timeframe. Don't fetch everything — be selective.\n\n## Step 4: Filter by timeframe\n\nDiscard anything with `updatedAt` / `updated_at` before the cutoff timestamp. Keep items where:\n- The item was created within the timeframe\n- The item received new comments within the timeframe\n- The item changed state (opened, closed, merged) within the timeframe\n\n## Step 5: Analyze and write report\n\nOutput a markdown report with these sections. Be concise — this is a digest, not a novel.\n\n---\n\n### Report format:\n\n```markdown\n# Alpine.js Activity — {timeframe label}\n_{start date} to {end date}_\n\n## TL;DR\n{2-3 sentences. What's the pulse? Any fires? Anything exciting? Give Caleb the vibe in 10 seconds.}\n\n## Needs Your Attention\n{Actionable items only. Each with a recommended next step: reply, merge, close, investigate, etc.}\n\n- **[Title](url)** by @author — {why it needs attention}. **Action:** {specific recommendation}\n\n{If nothing needs attention, say \"Nothing urgent right now.\"}\n\n## Hot Discussions\n{Discussions with the most activity or notable sentiment. Include key quotes if illuminating.}\n\n- **[Title](url)** ({category}) — {N} comments — {brief summary, sentiment note}\n\n{If no notable discussions, say \"Quiet on the discussion front.\"}\n\n## PR Activity\n\n### Opened\n- **[#N Title](url)** by @author — {one-line summary} {+additions/-deletions}\n\n### Merged\n- **[#N Title](url)** by @author — {one-line summary}\n\n### Closed (not merged)\n- **[#N Title](url)** by @author — {one-line summary, why closed if clear}\n\n{Omit empty subsections.}\n\n## Issue Activity\n\n### Opened\n- **[#N Title](url)** by @author — {one-line summary}\n\n### Closed\n- **[#N Title](url)** — {one-line summary}\n\n{Omit empty subsections.}\n\n## Repo Pulse\n| Metric | Value |\n|--------|-------|\n| Stars | {total} |\n| Views (14d) | {count} |\n| Clones (14d) | {count} |\n| Open issues | {count} |\n| PRs opened | {count in timeframe} |\n| PRs merged | {count in timeframe} |\n| PRs closed | {count in timeframe} |\n\n{If traffic data is unavailable (403), omit those rows and note \"Traffic data requires push access.\"}\n```\n\n---\n\n## Important rules\n\n- Every item must include a `[title](url)` link so Caleb can click through.\n- Include @author for attribution.\n- Keep summaries to ONE line per item. This is a digest.\n- The \"Needs Your Attention\" section is the most important. Be opinionated about what deserves Caleb's time.\n- If a discussion or issue has heated sentiment, note it (e.g., \"heated\", \"confused users\", \"strong demand\").\n- Omit empty sections entirely — don't show \"No activity\" headers.\n- For PRs, mention if CI is failing when relevant.\n- Don't editorialize beyond what's helpful for triage. Be practical, not chatty.\n","frontmatter":{"name":"summarize-activity","description":"Summarize recent GitHub activity — discussions, PRs, issues, events, traffic — into an actionable report so you can stay on top of the project without reading everything.","disable-model-invocation":true,"allowed-tools":"Bash, Read, Task","argument-hint":"[timeframe: 24h (default), 48h, 7d, 1w]","allowedTools":["Bash,","Read,","Task"],"disableModelInvocation":true},"allowedTools":["Bash,","Read,","Task"],"isInternal":false,"tokens":1691,"sizeBytes":6464},{"name":"package.json","path":"packages/docs/package.json","rawUrl":"https://raw.githubusercontent.com/alpinejs/alpine/HEAD/packages/docs/package.json","title":"@alpinejs/docs","category":"anthropic-skill","format":"json","content":"{\n    \"name\": \"@alpinejs/docs\",\n    \"version\": \"3.17.5\",\n    \"description\": \"The documentation for Alpine\",\n    \"repository\": {\n        \"type\": \"git\",\n        \"url\": \"https://github.com/alpinejs/alpine.git\",\n        \"directory\": \"packages/docs\"\n    },\n    \"author\": \"Caleb Porzio\",\n    \"license\": \"MIT\"\n}\n","frontmatter":{"name":"@alpinejs/docs","version":"3.17.5","description":"The documentation for Alpine","repository":{"type":"git","url":"https://github.com/alpinejs/alpine.git","directory":"packages/docs"},"author":"Caleb Porzio","license":"MIT"},"isInternal":false,"tokens":89,"sizeBytes":305},{"name":"advanced.md","path":"packages/docs/src/en/advanced.md","rawUrl":"https://raw.githubusercontent.com/alpinejs/alpine/HEAD/packages/docs/src/en/advanced.md","title":"En Skill","category":"anthropic-skill","format":"markdown","content":"---\norder: 8\ntitle: Advanced\ntype: sub-directory\n---\n","frontmatter":{"order":8,"title":"Advanced","type":"sub-directory"},"isInternal":false,"tokens":16,"sizeBytes":53},{"name":"async.md","path":"packages/docs/src/en/advanced/async.md","rawUrl":"https://raw.githubusercontent.com/alpinejs/alpine/HEAD/packages/docs/src/en/advanced/async.md","title":"Advanced Skill","category":"anthropic-skill","format":"markdown","content":"---\norder: 4\ntitle: Async\n---\n\n# Async\n\nAlpine is built to support asynchronous functions in most places it supports standard ones.\n\nFor example, let's say you have a simple function called `getLabel()` that you use as the input to an `x-text` directive:\n\n```js\nfunction getLabel() {\n    return 'Hello World!'\n}\n```\n```alpine\n<span x-text=\"getLabel()\"></span>\n```\n\nBecause `getLabel` is synchronous, everything works as expected.\n\nNow let's pretend that `getLabel` makes a network request to retrieve the label and can't return one instantaneously (asynchronous). By making `getLabel` an async function, you can call it from Alpine using JavaScript's `await` syntax.\n\n```js\nasync function getLabel() {\n    let response = await fetch('/api/label')\n\n    return await response.text()\n}\n```\n```alpine\n<span x-text=\"await getLabel()\"></span>\n```\n\nAdditionally, if you prefer calling methods in Alpine without the trailing parenthesis, you can leave them out and Alpine will detect that the provided function is async and handle it accordingly. For example:\n\n```alpine\n<span x-text=\"getLabel\"></span>\n```\n","frontmatter":{"order":4,"title":"Async"},"isInternal":false,"tokens":256,"sizeBytes":1099},{"name":"csp.md","path":"packages/docs/src/en/advanced/csp.md","rawUrl":"https://raw.githubusercontent.com/alpinejs/alpine/HEAD/packages/docs/src/en/advanced/csp.md","title":"Advanced Skill","category":"anthropic-skill","format":"markdown","content":"---\norder: 1\ntitle: CSP\n---\n\n# CSP (Content-Security Policy) Build\n\nIn order for Alpine to execute JavaScript expressions from HTML attributes like `x-on:click=\"console.log()\"`, it needs to use utilities that violate the \"unsafe-eval\" [Content Security Policy](https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP) that some applications enforce for security purposes.\n\n> Under the hood, Alpine doesn't actually use eval() itself because it's slow and problematic. Instead it uses Function declarations, which are much better, but still violate \"unsafe-eval\".\n\nAlpine offers an alternate build that doesn't violate \"unsafe-eval\" and supports most of Alpine's inline expression syntax.\n\n<a name=\"installation\"></a>\n## Installation\n\nYou can use this build by either including it from a `<script>` tag or installing it via NPM:\n\n### Via CDN\n\nYou can include this build's CDN as a `<script>` tag just like you would normally with standard Alpine build:\n\n```alpine\n<!-- Alpine's CSP-friendly Core -->\n<script defer src=\"https://cdn.jsdelivr.net/npm/@alpinejs/csp@3.x.x/dist/cdn.min.js\"></script>\n```\n\n### Via NPM\n\nYou can alternatively install this build from NPM for use inside your bundle like so:\n\n```shell\nnpm install @alpinejs/csp\n```\n\nThen initialize it from your bundle:\n\n```js\nimport Alpine from '@alpinejs/csp'\n\nwindow.Alpine = Alpine\n\nAlpine.start()\n```\n\n<a name=\"basic-example\"></a>\n## Basic Example\n\nHere's a working counter component using Alpine's CSP build. Notice how most expressions work exactly like regular Alpine:\n\n```alpine\n<html>\n    <head>\n        <meta http-equiv=\"Content-Security-Policy\" content=\"default-src 'self'; script-src 'nonce-a23gbfz9e'\">\n        <script defer nonce=\"a23gbfz9e\" src=\"https://cdn.jsdelivr.net/npm/@alpinejs/csp@3.x.x/dist/cdn.min.js\"></script>\n    </head>\n    <body>\n        <div x-data=\"{ count: 0, message: 'Hello' }\">\n            <button x-on:click=\"count++\">Increment</button>\n            <button x-on:click=\"count = 0\">Reset</button>\n\n            <span x-text=\"count\"></span>\n            <span x-text=\"message + ' World'\"></span>\n            <span x-show=\"count > 5\">Count is greater than 5!</span>\n        </div>\n    </body>\n</html>\n```\n\n<a name=\"whats-supported\"></a>\n## What's Supported\n\nThe CSP build supports most JavaScript expressions you'd want to use in Alpine:\n\n### Object and Array Literals\n```alpine\n<!-- ✅ These work -->\n<div x-data=\"{ user: { name: 'John', age: 30 }, items: [1, 2, 3] }\">\n    <span x-text=\"user.name\"></span>\n    <span x-text=\"items[0]\"></span>\n</div>\n```\n\n### Basic Operations\n```alpine\n<!-- ✅ These work -->\n<div x-data=\"{ count: 5, name: 'Alpine' }\">\n    <span x-text=\"count + 10\"></span>\n    <span x-text=\"count > 3\"></span>\n    <span x-text=\"count === 5 ? 'Yes' : 'No'\"></span>\n    <span x-text=\"'Hello ' + name\"></span>\n    <div x-show=\"!loading && count > 0\"></div>\n</div>\n```\n\n### Assignments and Updates\n```alpine\n<!-- ✅ These work -->\n<div x-data=\"{ count: 0, user: { name: '' } }\">\n    <button x-on:click=\"count++\">Increment</button>\n    <button x-on:click=\"count = 0\">Reset</button>\n    <input x-model=\"user.name\">\n</div>\n```\n\n### Method Calls\n```alpine\n<!-- ✅ These work -->\n<div x-data=\"{ items: ['a', 'b'] }\">\n    <button x-on:click=\"items.push('c')\">Add Item</button>\n</div>\n```\n\n<a name=\"whats-not-supported\"></a>\n## What's Not Supported\n\nSome advanced and potentially dangerous JavaScript features aren't supported:\n\n### Complex Expressions\n```alpine\n<!-- ❌ These don't work -->\n<div x-data=\"{ user: { name: '' } }\">\n    <!-- Property assignments -->\n    <button x-on:click=\"user.name = 'John'\">Bad</button>\n\n    <!-- Arrow functions -->\n    <button x-on:click=\"() => console.log('hi')\">Bad</button>\n\n    <!-- Destructuring -->\n    <div x-text=\"{ name } = user\">Bad</div>\n\n    <!-- Template literals -->\n    <div x-text=\"`Hello ${name}`\">Bad</div>\n\n    <!-- Spread operator -->\n    <div x-data=\"{ ...defaults }\">Bad</div>\n</div>\n```\n\n### Global Variables and Functions\n```alpine\n<!-- ❌ These don't work -->\n<div x-data>\n    <button x-on:click=\"console.log('hi')\"></button>\n    <span x-text=\"document.title\"></span>\n    <span x-text=\"window.innerWidth\"></span>\n    <span x-text=\"Math.max(count, 100)\"></span>\n    <span x-text=\"parseInt('123') + count\"></span>\n    <span x-text=\"JSON.stringify({ value: count })\"></span>\n</div>\n```\n\n### HTML Injection\n```alpine\n<!-- ❌ These don't work -->\n<div x-data=\"{ message: 'Hello <span>World</span>' }\">\n    <span x-html=\"message\"></span>\n    <span x-init=\"$el.insertAdjacentHTML('beforeend', message)\"></span>\n</div>\n```\n\n<a name=\"when-to-extract-logic\"></a>\n## When to Extract Logic\n\nWhile the CSP build supports simple inline expressions, you'll want to extract complex logic into dedicated functions or Alpine.data() components for better organization:\n\n```alpine\n<!-- Instead of this -->\n<div x-data=\"{ users: [] }\" x-show=\"users.filter(u => u.active && u.role === 'admin').length > 0\">\n```\n\n```alpine\n<!-- Do this -->\n<div x-data=\"userManager\" x-show=\"hasActiveAdmins\">\n\n<script nonce=\"...\">\n    Alpine.data('userManager', () => ({\n        users: [],\n\n        get hasActiveAdmins() {\n            return this.users.filter(u => u.active && u.role === 'admin').length > 0\n        }\n    }))\n</script>\n```\n\nThis approach makes your code more readable, testable, and maintainable, especially for complex applications.\n\n<a name=\"csp-headers\"></a>\n## CSP Headers\n\nHere's an example CSP header that works with Alpine's CSP build:\n\n```\nContent-Security-Policy: default-src 'self'; script-src 'nonce-[random]' 'strict-dynamic';\n```\n\nThe key is removing `'unsafe-eval'` from your `script-src` directive while still allowing your nonce-based scripts to run.","frontmatter":{"order":1,"title":"CSP"},"isInternal":false,"tokens":1511,"sizeBytes":5705},{"name":"extending.md","path":"packages/docs/src/en/advanced/extending.md","rawUrl":"https://raw.githubusercontent.com/alpinejs/alpine/HEAD/packages/docs/src/en/advanced/extending.md","title":"Advanced Skill","category":"anthropic-skill","format":"markdown","content":"---\norder: 3\ntitle: Extending\n---\n\n# Extending\n\nAlpine has a very open codebase that allows for extension in a number of ways. In fact, every available directive and magic in Alpine itself uses these exact APIs. In theory you could rebuild all of Alpine's functionality using them yourself.\n\n<a name=\"lifecycle-concerns\"></a>\n## Lifecycle concerns\nBefore we dive into each individual API, let's first talk about where in your codebase you should consume these APIs.\n\nBecause these APIs have an impact on how Alpine initializes the page, they must be registered AFTER Alpine is downloaded and available on the page, but BEFORE it has initialized the page itself.\n\nThere are two different techniques depending on if you are importing Alpine into a bundle, or including it directly via a `<script>` tag. Let's look at them both:\n\n<a name=\"via-script-tag\"></a>\n### Via a script tag\n\nIf you are including Alpine via a script tag, you will need to register any custom extension code inside an `alpine:init` event listener.\n\nHere's an example:\n\n```alpine\n<html>\n    <script src=\"/js/alpine.js\" defer></script>\n\n    <div x-data x-foo></div>\n\n    <script>\n        document.addEventListener('alpine:init', () => {\n            Alpine.directive('foo', ...)\n        })\n    </script>\n</html>\n```\n\nIf you want to extract your extension code into an external file, you will need to make sure that file's `<script>` tag is located BEFORE Alpine's like so:\n\n```alpine\n<html>\n    <script src=\"/js/foo.js\" defer></script>\n    <script src=\"/js/alpine.js\" defer></script>\n\n    <div x-data x-foo></div>\n</html>\n```\n\n<a name=\"via-npm\"></a>\n### Via an NPM module\n\nIf you imported Alpine into a bundle, you have to make sure you are registering any extension code IN BETWEEN when you import the `Alpine` global object, and when you initialize Alpine by calling `Alpine.start()`. For example:\n\n```js\nimport Alpine from 'alpinejs'\n\nAlpine.directive('foo', ...)\n\nwindow.Alpine = Alpine\nwindow.Alpine.start()\n```\n\nNow that we know where to use these extension APIs, let's look more closely at how to use each one:\n\n<a name=\"custom-directives\"></a>\n## Custom directives\n\nAlpine allows you to register your own custom directives using the `Alpine.directive()` API.\n\n<a name=\"method-signature\"></a>\n### Method Signature\n\n```js\nAlpine.directive('[name]', (el, { value, modifiers, expression }, { Alpine, effect, cleanup }) => {})\n```\n\n&nbsp; | &nbsp;\n---|---\nname | The name of the directive. The name \"foo\" for example would be consumed as `x-foo`\nel | The DOM element the directive is added to\nvalue | If provided, the part of the directive after a colon. Ex: `'bar'` in `x-foo:bar`\nmodifiers | An array of dot-separated trailing additions to the directive. Ex: `['baz', 'lob']` from `x-foo.baz.lob`\nexpression | The attribute value portion of the directive. Ex: `law` from `x-foo=\"law\"`\nAlpine | The Alpine global object\neffect | A function to create reactive effects that will auto-cleanup after this directive is removed from the DOM\ncleanup | A function you can pass bespoke callbacks to that will run when this directive is removed from the DOM\n\n<a name=\"simple-example\"></a>\n### Simple Example\n\nHere's an example of a simple directive we're going to create called: `x-uppercase`:\n\n```js\nAlpine.directive('uppercase', el => {\n    el.textContent = el.textContent.toUpperCase()\n})\n```\n```alpine\n<div x-data>\n    <span x-uppercase>Hello World!</span>\n</div>\n```\n\n<a name=\"evaluating-expressions\"></a>\n### Evaluating expressions\n\nWhen registering a custom directive, you may want to evaluate a user-supplied JavaScript expression:\n\nFor example, let's say you wanted to create a custom directive as a shortcut to `console.log()`. Something like:\n\n```alpine\n<div x-data=\"{ message: 'Hello World!' }\">\n    <div x-log=\"message\"></div>\n</div>\n```\n\nYou need to retrieve the actual value of `message` by evaluating it as a JavaScript expression with the `x-data` scope.\n\nFortunately, Alpine exposes its system for evaluating JavaScript expressions with an `evaluate()` API. Here's an example:\n\n```js\nAlpine.directive('log', (el, { expression }, { evaluate }) => {\n    // expression === 'message'\n\n    console.log(\n        evaluate(expression)\n    )\n})\n```\n\nNow, when Alpine initializes the `<div x-log...>`, it will retrieve the expression passed into the directive (\"message\" in this case), and evaluate it in the context of the current element's Alpine component scope.\n\n<a name=\"introducing-reactivity\"></a>\n### Introducing reactivity\n\nBuilding on the `x-log` example from before, let's say we wanted `x-log` to log the value of `message` and also log it if the value changes.\n\nGiven the following template:\n\n```alpine\n<div x-data=\"{ message: 'Hello World!' }\">\n    <div x-log=\"message\"></div>\n\n    <button @click=\"message = 'yolo'\">Change</button>\n</div>\n```\n\nWe want \"Hello World!\" to be logged initially, then we want \"yolo\" to be logged after pressing the `<button>`.\n\nWe can adjust the implementation of `x-log` and introduce two new APIs to achieve this: `evaluateLater()` and `effect()`:\n\n```js\nAlpine.directive('log', (el, { expression }, { evaluateLater, effect }) => {\n    let getThingToLog = evaluateLater(expression)\n\n    effect(() => {\n        getThingToLog(thingToLog => {\n            console.log(thingToLog)\n        })\n    })\n})\n```\n\nLet's walk through the above code, line by line.\n\n```js\nlet getThingToLog = evaluateLater(expression)\n```\n\nHere, instead of immediately evaluating `message` and retrieving the result, we will convert the string expression (\"message\") into an actual JavaScript function that we can run at any time. If you're going to evaluate a JavaScript expression more than once, it is highly recommended to first generate a JavaScript function and use that rather than calling `evaluate()` directly. The reason being that the process to interpret a plain string as a JavaScript function is expensive and should be avoided when unnecessary.\n\n```js\neffect(() => {\n    ...\n})\n```\n\nBy passing in a callback to `effect()`, we are telling Alpine to run the callback immediately, then track any dependencies it uses (`x-data` properties like `message` in our case). Now as soon as one of the dependencies changes, this callback will be re-run. This gives us our \"reactivity\".\n\nYou may recognize this functionality from `x-effect`. It is the same mechanism under the hood.\n\nYou may also notice that `Alpine.effect()` exists and wonder why we're not using it here. The reason is that the `effect` function provided via the method parameter has special functionality that cleans itself up when the directive is removed from the page for any reason.\n\nFor example, if for some reason the element with `x-log` on it got removed from the page, by using `effect()` instead of `Alpine.effect()` when the `message` property is changed, the value will no longer be logged to the console.\n\n[→ Read more about reactivity in Alpine](/advanced/reactivity)\n\n```js\ngetThingToLog(thingToLog => {\n    console.log(thingToLog)\n})\n```\n\nNow we will call `getThingToLog`, which if you recall is the actual JavaScript function version of the string expression: \"message\".\n\nYou might expect `getThingToCall()` to return the result right away, but instead Alpine requires you to pass in a callback to receive the result.\n\nThe reason for this is to support async expressions like `await getMessage()`. By passing in a \"receiver\" callback instead of getting the result immediately, you are allowing your directive to work with async expressions as well.\n\n[→ Read more about async in Alpine](/advanced/async)\n\n<a name=\"cleaning-up\"></a>\n### Cleaning Up\n\nLet's say you needed to register an event listener from a custom directive. After that directive is removed from the page for any reason, you would want to remove the event listener as well.\n\nAlpine makes this simple by providing you with a `cleanup` function when registering custom directives.\n\nHere's an example:\n\n```js\nAlpine.directive('...', (el, {}, { cleanup }) => {\n    let handler = () => {}\n\n    window.addEventListener('click', handler)\n\n    cleanup(() => {\n        window.removeEventListener('click', handler)\n    })\n\n})\n```\n\nNow if the directive is removed from this element or the element is removed itself, the event listener will be removed as well.\n\n<a name=\"custom-order\"></a>\n### Custom order\n\nBy default, any new directive will run after the majority of the standard ones (with the exception of `x-teleport`). This is usually acceptable but some times you might need to run your custom directive before another specific one.\nThis can be achieved by chaining the `.before() function to `Alpine.directive()` and specifying which directive needs to run after your custom one.\n\n```js\nAlpine.directive('foo', (el, { value, modifiers, expression }) => {\n    Alpine.addScopeToNode(el, {foo: 'bar'})\n}).before('bind')\n```\n```alpine\n<div x-data>\n    <span x-foo x-bind:foo=\"foo\"></span>\n</div>\n```\n> Note, the directive name must be written without the `x-` prefix (or any other custom prefix you may use).\n\n<a name=\"custom-magics\"></a>\n## Custom magics\n\nAlpine allows you to register custom \"magics\" (properties or methods) using `Alpine.magic()`. Any magic you register will be available to all your application's Alpine code with the `$` prefix.\n\n<a name=\"method-signature\"></a>\n### Method Signature\n\n```js\nAlpine.magic('[name]', (el, { Alpine }) => {})\n```\n\n&nbsp; | &nbsp;\n---|---\nname | The name of the magic. The name \"foo\" for example would be consumed as `$foo`\nel | The DOM element the magic was triggered from\nAlpine | The Alpine global object\n\n<a name=\"magic-properties\"></a>\n### Magic Properties\n\nHere's a basic example of a \"$now\" magic helper to easily get the current time from anywhere in Alpine:\n\n```js\nAlpine.magic('now', () => {\n    return (new Date).toLocaleTimeString()\n})\n```\n```alpine\n<span x-text=\"$now\"></span>\n```\n\nNow the `<span>` tag will contain the current time, resembling something like \"12:00:00 PM\".\n\nAs you can see `$now` behaves like a static property, but under the hood is actually a getter that evaluates every time the property is accessed.\n\nBecause of this, you can implement magic \"functions\" by returning a function from the getter.\n\n<a name=\"magic-functions\"></a>\n### Magic Functions\n\nFor example, if we wanted to create a `$clipboard()` magic function that accepts a string to copy to clipboard, we could implement it like so:\n\n```js\nAlpine.magic('clipboard', () => {\n    return subject => navigator.clipboard.writeText(subject)\n})\n```\n```alpine\n<button @click=\"$clipboard('hello world')\">Copy \"Hello World\"</button>\n```\n\nNow that accessing `$clipboard` returns a function itself, we can immediately call it and pass it an argument like we see in the template with `$clipboard('hello world')`.\n\nYou can use the more brief syntax (a double arrow function) for returning a function from a function if you'd prefer:\n\n```js\nAlpine.magic('clipboard', () => subject => {\n    navigator.clipboard.writeText(subject)\n})\n```\n\n<a name=\"writing-and-sharing-plugins\"></a>\n## Writing and sharing plugins\n\nBy now you should see how friendly and simple it is to register your own custom directives and magics in your application, but what about sharing that functionality with others via an NPM package or something?\n\nYou can get started quickly with Alpine's official \"plugin-blueprint\" package. It's as simple as cloning the repository and running `npm install && npm run build` to get a plugin authored.\n\nFor demonstration purposes, let's create a pretend Alpine plugin from scratch called `Foo` that includes both a directive (`x-foo`) and a magic (`$foo`).\n\nWe'll start producing this plugin for consumption as a simple `<script>` tag alongside Alpine, then we'll level it up to a module for importing into a bundle:\n\n<a name=\"script-include\"></a>\n### Script include\n\nLet's start in reverse by looking at how our plugin will be included into a project:\n\n```alpine\n<html>\n    <script src=\"/js/foo.js\" defer></script>\n    <script src=\"/js/alpine.js\" defer></script>\n\n    <div x-data x-init=\"$foo()\">\n        <span x-foo=\"'hello world'\">\n    </div>\n</html>\n```\n\nNotice how our script is included BEFORE Alpine itself. This is important, otherwise, Alpine would have already been initialized by the time our plugin got loaded.\n\nNow let's look inside of `/js/foo.js`'s contents:\n\n```js\ndocument.addEventListener('alpine:init', () => {\n    window.Alpine.directive('foo', ...)\n\n    window.Alpine.magic('foo', ...)\n})\n```\n\nThat's it! Authoring a plugin for inclusion via a script tag is extremely simple with Alpine.\n\n<a name=\"bundle-module\"></a>\n### Bundle module\n\nNow let's say you wanted to author a plugin that someone could install via NPM and include into their bundle.\n\nLike the last example, we'll walk through this in reverse, starting with what it will look like to consume this plugin:\n\n```js\nimport Alpine from 'alpinejs'\n\nimport foo from 'foo'\nAlpine.plugin(foo)\n\nwindow.Alpine = Alpine\nwindow.Alpine.start()\n```\n\nYou'll notice a new API here: `Alpine.plugin()`. This is a convenience method Alpine exposes to prevent consumers of your plugin from having to register multiple different directives and magics themselves.\n\nNow let's look at the source of the plugin and what gets exported from `foo`:\n\n```js\nexport default function (Alpine) {\n    Alpine.directive('foo', ...)\n    Alpine.magic('foo', ...)\n}\n```\n\nYou'll see that `Alpine.plugin` is incredibly simple. It accepts a callback and immediately invokes it while providing the `Alpine` global as a parameter for use inside of it.\n\nThen you can go about extending Alpine as you please.\n\n<a name=\"deferring-initialization\"></a>\n## Deferring initialization\n\nAlpine initializes a tree of elements synchronously. Integrations that load JavaScript for a component asynchronously — a script module that registers an `Alpine.data()` provider, for example — can lose that race: Alpine evaluates `x-data=\"someComponent\"` before the registration exists.\n\n`Alpine.deferInit(el, promise)` suspends initialization of one element's tree until a promise settles. Nothing inside the tree initializes while it's suspended: directives don't evaluate, nodes added inside it wait, and attribute changes are held and replayed when the tree resumes. The rest of the page initializes normally.\n\n```js\nAlpine.interceptInit(el => {\n    if (el.hasAttribute('data-widget') && ! widgetIsLoaded(el)) {\n        Alpine.deferInit(el, loadWidget(el))\n    }\n})\n```\n\n(`Alpine.interceptInit()` is Alpine's low-level integration hook — its callback runs for every element just before that element initializes.)\n\nA few things to know about the contract:\n\n- Registering must happen synchronously — from an `Alpine.interceptInit()` callback before the element initializes, or on an already-initialized element to suspend future activity in its tree (a morph that's about to bring in new markup, for example).\n- Calling `deferInit()` on the same element again before it resumes adds another prerequisite: the tree initializes after every registered promise settles.\n- A rejected promise is reported through Alpine's error handler, then the tree initializes anyway — a failed prerequisite never leaves a tree permanently suspended.\n- If the element has left the DOM by the time the promise settles, nothing happens. If it re-enters later, it initializes like any other added node.\n- When a suspended tree resumes, init interceptors run again for elements that hadn't initialized yet. Only defer while your prerequisite is still outstanding — like the `widgetIsLoaded()` check above — so the resume pass initializes normally instead of suspending again.\n- `[x-cloak]` attributes inside a suspended tree stay in place until it resumes, so the existing cloaking pattern hides not-yet-ready content.\n- `alpine:initialized` does not wait for suspended trees — it fires when the synchronous pass over the page completes.\n- The promise is expected to settle. A prerequisite that never settles leaves its tree suspended indefinitely — put timeouts on operations that need them before handing the promise to Alpine.\n","frontmatter":{"order":3,"title":"Extending"},"isInternal":false,"tokens":3621,"sizeBytes":16111},{"name":"reactivity.md","path":"packages/docs/src/en/advanced/reactivity.md","rawUrl":"https://raw.githubusercontent.com/alpinejs/alpine/HEAD/packages/docs/src/en/advanced/reactivity.md","title":"Advanced Skill","category":"anthropic-skill","format":"markdown","content":"---\norder: 2\ntitle: Reactivity\n---\n\n# Reactivity\n\nAlpine is \"reactive\" in the sense that when you change a piece of data, everything that depends on that data \"reacts\" automatically to that change.\n\nEvery bit of reactivity that takes place in Alpine, happens because of two very important reactive functions in Alpine's core: `Alpine.reactive()`, and `Alpine.effect()`.\n\n> Alpine uses VueJS's reactivity engine under the hood to provide these functions.\n> [→ Browse the @vue/reactivity source](https://github.com/vuejs/core/tree/main/packages/reactivity)\n\nUnderstanding these two functions will give you super powers as an Alpine developer, but also just as a web developer in general.\n\n<a name=\"alpine-reactive\"></a>\n## Alpine.reactive()\n\nLet's first look at `Alpine.reactive()`. This function accepts a JavaScript object as its parameter and returns a \"reactive\" version of that object. For example:\n\n```js\nlet data = { count: 1 }\n\nlet reactiveData = Alpine.reactive(data)\n```\n\nUnder the hood, when `Alpine.reactive` receives `data`, it wraps it inside a custom JavaScript proxy.\n\nA proxy is a special kind of object in JavaScript that can intercept \"get\" and \"set\" calls to a JavaScript object.\n\n[→ Read more about JavaScript proxies](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy)\n\nAt face value, `reactiveData` should behave exactly like `data`. For example:\n\n```js\nconsole.log(data.count) // 1\nconsole.log(reactiveData.count) // 1\n\nreactiveData.count = 2\n\nconsole.log(data.count) // 2\nconsole.log(reactiveData.count) // 2\n```\n\nWhat you see here is that because `reactiveData` is a thin wrapper around `data`, any attempts to get or set a property will behave exactly as if you had interacted with `data` directly.\n\nThe main difference here is that any time you modify or retrieve (get or set) a value from `reactiveData`, Alpine is aware of it and can execute any other logic that depends on this data.\n\n`Alpine.reactive` is only the first half of the story. `Alpine.effect` is the other half, let's dig in.\n\n<a name=\"alpine-effect\"></a>\n## Alpine.effect()\n\n`Alpine.effect` accepts a single callback function. As soon as `Alpine.effect` is called, it runs the provided function and watches for reads from reactive data. Each reactive property read during that execution becomes a dependency. When one of those properties changes later, Alpine runs the callback again. For example:\n\n```js\nlet data = Alpine.reactive({ count: 1 })\n\nAlpine.effect(() => {\n    console.log(data.count)\n})\n```\n\nWhen this code is first run, \"1\" will be logged to the console. Any time `data.count` changes, its value will be logged to the console again.\n\nThis is the mechanism that unlocks all of the reactivity at the core of Alpine.\n\n### How dependency tracking works\n\nDependency collection happens while the effect callback is running. Reading `data.count` inside the callback registers that property with the effect. Changing `data.count` later notifies the effect, which runs again and collects the dependencies used by that execution.\n\nReads made after the callback has returned, such as inside a `setTimeout` callback, are not automatically tracked by the original effect.\n\nAlpine delegates this behavior to Vue's reactivity package. For a deeper explanation of the proxy, dependency-map, and `track`/`trigger` model, see [Vue's reactivity internals](https://frontendatlas.com/vue/trivia/vue-reactivity-system).\n\nTo connect the dots further, let's look at a simple \"counter\" component example without using Alpine syntax at all, only using `Alpine.reactive` and `Alpine.effect`:\n\n```alpine\n<button>Increment</button>\n\nCount: <span></span>\n```\n```js\nlet button = document.querySelector('button')\nlet span = document.querySelector('span')\n\nlet data = Alpine.reactive({ count: 1 })\n\nAlpine.effect(() => {\n    span.textContent = data.count\n})\n\nbutton.addEventListener('click', () => {\n    data.count = data.count + 1\n})\n```\n\n<!-- START_VERBATIM -->\n<div x-data=\"{ count: 1 }\" class=\"demo\">\n    <button @click=\"count++\">Increment</button>\n\n    <div>Count: <span x-text=\"count\"></span></div>\n</div>\n<!-- END_VERBATIM -->\n\nAs you can see, you can make any data reactive, and you can also wrap any functionality in `Alpine.effect`.\n\nThis combination unlocks an incredibly powerful programming paradigm for web development. Run wild and free.\n","frontmatter":{"order":2,"title":"Reactivity"},"isInternal":false,"tokens":1012,"sizeBytes":4368},{"name":"directives.md","path":"packages/docs/src/en/directives.md","rawUrl":"https://raw.githubusercontent.com/alpinejs/alpine/HEAD/packages/docs/src/en/directives.md","title":"En Skill","category":"anthropic-skill","format":"markdown","content":"---\norder: 4\ntitle: Directives\nprefix: x-\nfont-type: mono\ntype: sub-directory\n---\n","frontmatter":{"order":4,"title":"Directives","prefix":"x-","font-type":"mono","type":"sub-directory"},"isInternal":false,"tokens":26,"sizeBytes":82},{"name":"bind.md","path":"packages/docs/src/en/directives/bind.md","rawUrl":"https://raw.githubusercontent.com/alpinejs/alpine/HEAD/packages/docs/src/en/directives/bind.md","title":"Directives Skill","category":"anthropic-skill","format":"markdown","content":"---\norder: 4\ntitle: bind\n---\n\n# x-bind\n\n`x-bind` allows you to set HTML attributes on elements based on the result of JavaScript expressions.\n\nFor example, here's a component where we will use `x-bind` to set the placeholder value of an input.\n\n```alpine\n<div x-data=\"{ placeholderText: 'Type here...' }\">\n    <input type=\"text\" x-bind:placeholder=\"placeholderText\">\n</div>\n```\n\n<a name=\"shorthand-syntax\"></a>\n## Shorthand syntax\n\nIf `x-bind:` is too verbose for your liking, you can use the shorthand: `:`. For example, here is the same input element as above, but refactored to use the shorthand syntax.\n\n```alpine\n<input type=\"text\" :placeholder=\"placeholderText\">\n```\n\n> Despite not being included in the above snippet, `x-bind` cannot be used if no parent element has `x-data` defined. [→ Read more about `x-data`](/directives/data)\n\n<a name=\"binding-classes\"></a>\n## Binding classes\n\n`x-bind` is most often useful for setting specific classes on an element based on your Alpine state.\n\nHere's a simple example of a simple dropdown toggle, but instead of using `x-show`, we'll use a \"hidden\" class to toggle an element.\n\n```alpine\n<div x-data=\"{ open: false }\">\n    <button x-on:click=\"open = ! open\">Toggle Dropdown</button>\n\n    <div :class=\"open ? '' : 'hidden'\">\n        Dropdown Contents...\n    </div>\n</div>\n```\n\nNow, when `open` is `false`, the \"hidden\" class will be added to the dropdown.\n\n<a name=\"shorthand-conditionals\"></a>\n### Shorthand conditionals\n\nIn cases like these, if you prefer a less verbose syntax you can use JavaScript's short-circuit evaluation instead of standard conditionals:\n\n```alpine\n<div :class=\"show ? '' : 'hidden'\">\n<!-- Is equivalent to: -->\n<div :class=\"show || 'hidden'\">\n```\n\nThe inverse is also available to you. Suppose instead of `open`, we use a variable with the opposite value: `closed`.\n\n```alpine\n<div :class=\"closed ? 'hidden' : ''\">\n<!-- Is equivalent to: -->\n<div :class=\"closed && 'hidden'\">\n```\n\n<a name=\"class-object-syntax\"></a>\n### Class object syntax\n\nAlpine offers an additional syntax for toggling classes if you prefer. By passing a JavaScript object where the classes are the keys and booleans are the values, Alpine will know which classes to apply and which to remove. For example:\n\n```alpine\n<div :class=\"{ 'hidden': ! show }\">\n```\n\nThis technique offers a unique advantage to other methods. When using object-syntax, Alpine will NOT preserve original classes applied to an element's `class` attribute.\n\nFor example, if you wanted to apply the \"hidden\" class to an element before Alpine loads, AND use Alpine to toggle its existence you can only achieve that behavior using object-syntax:\n\n```alpine\n<div class=\"hidden\" :class=\"{ 'hidden': ! show }\">\n```\n\nIn case that confused you, let's dig deeper into how Alpine handles `x-bind:class` differently than other attributes.\n\n<a name=\"special-behavior\"></a>\n### Special behavior\n\n`x-bind:class` behaves differently than other attributes under the hood.\n\nConsider the following case.\n\n```alpine\n<div class=\"opacity-50\" :class=\"hide && 'hidden'\">\n```\n\nIf \"class\" were any other attribute, the `:class` binding would overwrite any existing class attribute, causing `opacity-50` to be overwritten by either `hidden` or `''`.\n\nHowever, Alpine treats `class` bindings differently. It's smart enough to preserve existing classes on an element.\n\nFor example, if `hide` is true, the above example will result in the following DOM element:\n\n```alpine\n<div class=\"opacity-50 hidden\">\n```\n\nIf `hide` is false, the DOM element will look like:\n\n```alpine\n<div class=\"opacity-50\">\n```\n\nThis behavior should be invisible and intuitive to most users, but it is worth mentioning explicitly for the inquiring developer or any special cases that might crop up.\n\n<a name=\"binding-styles\"></a>\n## Binding styles\n\nSimilar to the special syntax for binding classes with JavaScript objects, Alpine also offers an object-based syntax for binding `style` attributes.\n\nJust like the class objects, this syntax is entirely optional. Only use it if it affords you some advantage.\n\n```alpine\n<div :style=\"{ color: 'red', display: 'flex' }\">\n\n<!-- Will render: -->\n<div style=\"color: red; display: flex;\" ...>\n```\n\nConditional inline styling is possible using expressions just like with x-bind:class. Short circuit operators can be used here as well by using a styles object as the second operand.\n```alpine\n<div x-bind:style=\"true && { color: 'red' }\">\n\n<!-- Will render: -->\n<div style=\"color: red;\">\n```\n\nOne advantage of this approach is being able to mix it in with existing styles on an element:\n\n```alpine\n<div style=\"padding: 1rem;\" :style=\"{ color: 'red', display: 'flex' }\">\n\n<!-- Will render: -->\n<div style=\"padding: 1rem; color: red; display: flex;\" ...>\n```\n\nAnd like most expressions in Alpine, you can always use the result of a JavaScript expression as the reference:\n\n```alpine\n<div x-data=\"{ styles: { color: 'red', display: 'flex' }}\">\n    <div :style=\"styles\">\n</div>\n\n<!-- Will render: -->\n<div ...>\n    <div style=\"color: red; display: flex;\" ...>\n</div>\n```\n\n<a name=\"bind-directives\"></a>\n## Binding Alpine Directives Directly\n\n`x-bind` allows you to bind an object of different directives and attributes to an element.\n\nThe object keys can be anything you would normally write as an attribute name in Alpine. This includes Alpine directives and modifiers, but also plain HTML attributes. The object values are either plain strings, or in the case of dynamic Alpine directives, callbacks to be evaluated by Alpine.\n\n```alpine\n<div x-data=\"dropdown\">\n    <button x-bind=\"trigger\">Open Dropdown</button>\n\n    <span x-bind=\"dialogue\">Dropdown Contents</span>\n</div>\n\n<script>\n    document.addEventListener('alpine:init', () => {\n        Alpine.data('dropdown', () => ({\n            open: false,\n\n            trigger: {\n                ['x-ref']: 'trigger',\n                ['@click']() {\n                    this.open = true\n                },\n            },\n\n            dialogue: {\n                ['x-show']() {\n                    return this.open\n                },\n                ['@click.outside']() {\n                    this.open = false\n                },\n            },\n        }))\n    })\n</script>\n```\n\nThere are a couple of caveats to this usage of `x-bind`:\n\n> When the directive being \"bound\" or \"applied\" is `x-for`, you should return a normal expression string from the callback. For example: `['x-for']() { return 'item in items' }`\n","frontmatter":{"order":4,"title":"bind"},"isInternal":false,"tokens":1515,"sizeBytes":6464},{"name":"cloak.md","path":"packages/docs/src/en/directives/cloak.md","rawUrl":"https://raw.githubusercontent.com/alpinejs/alpine/HEAD/packages/docs/src/en/directives/cloak.md","title":"Directives Skill","category":"anthropic-skill","format":"markdown","content":"---\norder: 12\ntitle: cloak\n---\n\n# x-cloak\n\nSometimes, when you're using AlpineJS for a part of your template, there is a \"blip\" where you might see your uninitialized template after the page loads, but before Alpine loads.\n\n`x-cloak` addresses this scenario by hiding the element it's attached to until Alpine is fully loaded on the page.\n\nFor `x-cloak` to work however, you must add the following CSS to the page.\n\n```css\n[x-cloak] { display: none !important; }\n```\n\nThe following example will hide the `<span>` tag until its `x-show` is specifically set to true, preventing any \"blip\" of the hidden element onto screen as Alpine loads.\n\n```alpine\n<span x-cloak x-show=\"false\">This will not 'blip' onto screen at any point</span>\n```\n\n`x-cloak` doesn't just work on elements hidden by `x-show` or `x-if`: it also ensures that elements containing data are hidden until the data is correctly set. The following example will hide the `<span>` tag until Alpine has set its text content to the `message` property.\n\n```alpine\n<span x-cloak x-text=\"message\"></span>\n```\n\nWhen Alpine loads on the page, it removes all `x-cloak` property from the element, which also removes the `display: none;` applied by CSS, therefore showing the element.\n\n## Alternative to global syntax\n\nIf you'd like to achieve this same behavior, but avoid having to include a global style, you can use the following cool, but admittedly odd trick:\n\n```alpine\n<template x-if=\"true\">\n    <span x-text=\"message\"></span>\n</template>\n```\n\nThis will achieve the same goal as `x-cloak` by just leveraging the way `x-if` works.\n\nBecause `<template>` elements are \"hidden\" in browsers by default, you won't see the `<span>` until Alpine has had a chance to render the `x-if=\"true\"` and show it.\n\nAgain, this solution is not for everyone, but it's worth mentioning for special cases.\n","frontmatter":{"order":12,"title":"cloak"},"isInternal":false,"tokens":457,"sizeBytes":1842},{"name":"data.md","path":"packages/docs/src/en/directives/data.md","rawUrl":"https://raw.githubusercontent.com/alpinejs/alpine/HEAD/packages/docs/src/en/directives/data.md","title":"Directives Skill","category":"anthropic-skill","format":"markdown","content":"---\norder: 1\ntitle: data\n---\n\n# x-data\n\nEverything in Alpine starts with the `x-data` directive.\n\n`x-data` defines a chunk of HTML as an Alpine component and provides the reactive data for that component to reference.\n\nHere's an example of a contrived dropdown component:\n\n```alpine\n<div x-data=\"{ open: false }\">\n    <button @click=\"open = ! open\">Toggle Content</button>\n\n    <div x-show=\"open\">\n        Content...\n    </div>\n</div>\n```\n\nDon't worry about the other directives in this example (`@click` and `x-show`), we'll get to those in a bit. For now, let's focus on `x-data`.\n\n<a name=\"scope\"></a>\n## Scope\n\nProperties defined in an `x-data` directive are available to all element children. Even ones inside other, nested `x-data` components.\n\nFor example:\n\n```alpine\n<div x-data=\"{ foo: 'bar' }\">\n    <span x-text=\"foo\"><!-- Will output: \"bar\" --></span>\n\n    <div x-data=\"{ bar: 'baz' }\">\n        <span x-text=\"foo\"><!-- Will output: \"bar\" --></span>\n\n        <div x-data=\"{ foo: 'bob' }\">\n            <span x-text=\"foo\"><!-- Will output: \"bob\" --></span>\n        </div>\n    </div>\n</div>\n```\n\n<a name=\"methods\"></a>\n## Methods\n\nBecause `x-data` is evaluated as a normal JavaScript object, in addition to state, you can store methods and even getters.\n\nFor example, let's extract the \"Toggle Content\" behavior into a method on  `x-data`.\n\n```alpine\n<div x-data=\"{ open: false, toggle() { this.open = ! this.open } }\">\n    <button @click=\"toggle()\">Toggle Content</button>\n\n    <div x-show=\"open\">\n        Content...\n    </div>\n</div>\n```\n\nNotice the added `toggle() { this.open = ! this.open }` method on `x-data`. This method can now be called from anywhere inside the component.\n\nYou'll also notice the usage of `this.` to access state on the object itself. This is because Alpine evaluates this data object like any standard JavaScript object with a `this` context.\n\nIf you prefer, you can leave the calling parenthesis off of the `toggle` method completely. For example:\n\n```alpine\n<!-- Before -->\n<button @click=\"toggle()\">...</button>\n\n<!-- After -->\n<button @click=\"toggle\">...</button>\n```\n\n<a name=\"getters\"></a>\n## Getters\n\nJavaScript [getters](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/get) are handy when the sole purpose of a method is to return data based on other state.\n\nThink of them like \"computed properties\" (although, they are not cached like Vue's computed properties).\n\nLet's refactor our component to use a getter called `isOpen` instead of accessing `open` directly.\n\n```alpine\n<div x-data=\"{\n    open: false,\n    get isOpen() { return this.open },\n    toggle() { this.open = ! this.open },\n}\">\n    <button @click=\"toggle()\">Toggle Content</button>\n\n    <div x-show=\"isOpen\">\n        Content...\n    </div>\n</div>\n```\n\nNotice the \"Content\" now depends on the `isOpen` getter instead of the `open` property directly.\n\nIn this case there is no tangible benefit. But in some cases, getters are helpful for providing a more expressive syntax in your components.\n\n<a name=\"data-less-components\"></a>\n## Data-less components\n\nOccasionally, you want to create an Alpine component, but you don't need any data.\n\nIn these cases, you can always pass in an empty object.\n\n```alpine\n<div x-data=\"{}\">\n```\n\nHowever, if you wish, you can also eliminate the attribute value entirely if it looks better to you.\n\n```alpine\n<div x-data>\n```\n\n<a name=\"single-element-components\"></a>\n## Single-element components\n\nSometimes you may only have a single element inside your Alpine component, like the following:\n\n```alpine\n<div x-data=\"{ open: true }\">\n    <button @click=\"open = false\" x-show=\"open\">Hide Me</button>\n</div>\n```\n\nIn these cases, you can declare `x-data` directly on that single element:\n\n```alpine\n<button x-data=\"{ open: true }\" @click=\"open = false\" x-show=\"open\">\n    Hide Me\n</button>\n```\n\n<a name=\"re-usable-data\"></a>\n## Re-usable Data\n\nIf you find yourself duplicating the contents of `x-data`, or you find the inline syntax verbose, you can extract the `x-data` object out to a dedicated component using `Alpine.data`.\n\nHere's a quick example:\n\n```alpine\n<div x-data=\"dropdown\">\n    <button @click=\"toggle\">Toggle Content</button>\n\n    <div x-show=\"open\">\n        Content...\n    </div>\n</div>\n\n<script>\n    document.addEventListener('alpine:init', () => {\n        Alpine.data('dropdown', () => ({\n            open: false,\n\n            toggle() {\n                this.open = ! this.open\n            },\n        }))\n    })\n</script>\n```\n\n[→ Read more about `Alpine.data(...)`](/globals/alpine-data)\n","frontmatter":{"order":1,"title":"data"},"isInternal":false,"tokens":1129,"sizeBytes":4568},{"name":"effect.md","path":"packages/docs/src/en/directives/effect.md","rawUrl":"https://raw.githubusercontent.com/alpinejs/alpine/HEAD/packages/docs/src/en/directives/effect.md","title":"Directives Skill","category":"anthropic-skill","format":"markdown","content":"---\norder: 11\ntitle: effect\n---\n\n# x-effect\n\n`x-effect` is a useful directive for re-evaluating an expression when one of its dependencies change. You can think of it as a watcher where you don't have to specify what property to watch, it will watch all properties used within it.\n\nIf this definition is confusing for you, that's ok. It's better explained through an example:\n\n```alpine\n<div x-data=\"{ label: 'Hello' }\" x-effect=\"console.log(label)\">\n    <button @click=\"label += ' World!'\">Change Message</button>\n</div>\n```\n\nWhen this component is loaded, the `x-effect` expression will be run and \"Hello\" will be logged into the console.\n\nBecause Alpine knows about any property references contained within `x-effect`, when the button is clicked and `label` is changed, the effect will be re-triggered and \"Hello World!\" will be logged to the console.\n","frontmatter":{"order":11,"title":"effect"},"isInternal":false,"tokens":200,"sizeBytes":855},{"name":"for.md","path":"packages/docs/src/en/directives/for.md","rawUrl":"https://raw.githubusercontent.com/alpinejs/alpine/HEAD/packages/docs/src/en/directives/for.md","title":"Directives Skill","category":"anthropic-skill","format":"markdown","content":"---\norder: 8\ntitle: for\n---\n\n# x-for\n\nAlpine's `x-for` directive allows you to create DOM elements by iterating through a list. Here's a simple example of using it to create a list of colors based on an array.\n\n```alpine\n<ul x-data=\"{ colors: ['Red', 'Orange', 'Yellow'] }\">\n    <template x-for=\"color in colors\">\n        <li x-text=\"color\"></li>\n    </template>\n</ul>\n```\n\n<!-- START_VERBATIM -->\n<div class=\"demo\">\n    <ul x-data=\"{ colors: ['Red', 'Orange', 'Yellow'] }\">\n        <template x-for=\"color in colors\">\n            <li x-text=\"color\"></li>\n        </template>\n    </ul>\n</div>\n<!-- END_VERBATIM -->\n\nYou may also pass objects to `x-for`.\n\n```alpine\n<ul x-data=\"{ car: { make: 'Jeep', model: 'Grand Cherokee', color: 'Black' } }\">\n    <template x-for=\"(value, index) in car\">\n        <li>\n            <span x-text=\"index\"></span>: <span x-text=\"value\"></span>\n        </li>\n    </template>\n</ul>\n```\n\n<!-- START_VERBATIM -->\n<div class=\"demo\">\n    <ul x-data=\"{ car: { make: 'Jeep', model: 'Grand Cherokee', color: 'Black' } }\">\n        <template x-for=\"(value, index) in car\">\n            <li>\n                <span x-text=\"index\"></span>: <span x-text=\"value\"></span>\n            </li>\n        </template>\n    </ul>\n</div>\n<!-- END_VERBATIM -->\n\nThere are two rules worth noting about `x-for`:\n\n> `x-for` MUST be declared on a `<template>` element.\n> That `<template>` element MUST contain only one root element\n\n<a name=\"keys\"></a>\n## Keys\n\nIt is important to specify unique keys for each `x-for` iteration if you are going to be re-ordering items. Without dynamic keys, Alpine may have a hard time keeping track of what re-orders and will cause odd side-effects.\n\n```alpine\n<ul x-data=\"{ colors: [\n    { id: 1, label: 'Red' },\n    { id: 2, label: 'Orange' },\n    { id: 3, label: 'Yellow' },\n]}\">\n    <template x-for=\"color in colors\" :key=\"color.id\">\n        <li x-text=\"color.label\"></li>\n    </template>\n</ul>\n```\n\nNow if the colors are added, removed, re-ordered, or their \"id\"s change, Alpine will preserve or destroy the iterated `<li>`elements accordingly.\n\n<a name=\"accessing-indexes\"></a>\n## Accessing indexes\n\nIf you need to access the index of each item in the iteration, you can do so using the `([item], [index]) in [items]` syntax like so:\n\n```alpine\n<ul x-data=\"{ colors: ['Red', 'Orange', 'Yellow'] }\">\n    <template x-for=\"(color, index) in colors\">\n        <li>\n            <span x-text=\"index + ': '\"></span>\n            <span x-text=\"color\"></span>\n        </li>\n    </template>\n</ul>\n```\n\nYou can also access the index inside a dynamic `:key` expression.\n\n```alpine\n<template x-for=\"(color, index) in colors\" :key=\"index\">\n```\n\n<a name=\"iterating-over-a-range\"></a>\n## Iterating over a range\n\nIf you need to simply loop `n` number of times, rather than iterate through an array, Alpine offers a short syntax.\n\n```alpine\n<ul>\n    <template x-for=\"i in 10\">\n        <li x-text=\"i\"></li>\n    </template>\n</ul>\n```\n\n`i` in this case can be named anything you like.\n\n> Despite not being included in the above snippet, `x-for` cannot be used if no parent element has `x-data` defined. [→ Read more about `x-data`](/directives/data)\n\n<a name=\"contents-of-a-template\"></a>\n## Contents of a `<template>`\n\nAs mentioned above, an `<template>` tag must contain only one root element.\n\nFor example, the following code will not work:\n\n```alpine\n<template x-for=\"color in colors\">\n    <span>The next color is </span><span x-text=\"color\">\n</template>\n```\n\nbut this code will work:\n```alpine\n<template x-for=\"color in colors\">\n    <p>\n        <span>The next color is </span><span x-text=\"color\">\n    </p>\n</template>\n```\n","frontmatter":{"order":8,"title":"for"},"isInternal":false,"tokens":1002,"sizeBytes":3644},{"name":"html.md","path":"packages/docs/src/en/directives/html.md","rawUrl":"https://raw.githubusercontent.com/alpinejs/alpine/HEAD/packages/docs/src/en/directives/html.md","title":"Directives Skill","category":"anthropic-skill","format":"markdown","content":"---\norder: 7\ntitle: html\n---\n\n# x-html\n\n`x-html` sets the \"innerHTML\" property of an element to the result of a given expression.\n\n> ⚠️ Only use on trusted content and never on user-provided content. ⚠️\n> Dynamically rendering HTML from third parties can easily lead to XSS vulnerabilities.\n\nHere's a basic example of using `x-html` to display a user's username.\n\n```alpine\n<div x-data=\"{ username: '<strong>calebporzio</strong>' }\">\n    Username: <span x-html=\"username\"></span>\n</div>\n```\n\n<!-- START_VERBATIM -->\n<div class=\"demo\">\n    <div x-data=\"{ username: '<strong>calebporzio</strong>' }\">\n        Username: <span x-html=\"username\"></span>\n    </div>\n</div>\n<!-- END_VERBATIM -->\n\nNow the `<span>` tag's inner HTML will be set to \"<strong>calebporzio</strong>\".\n","frontmatter":{"order":7,"title":"html"},"isInternal":false,"tokens":214,"sizeBytes":779},{"name":"id.md","path":"packages/docs/src/en/directives/id.md","rawUrl":"https://raw.githubusercontent.com/alpinejs/alpine/HEAD/packages/docs/src/en/directives/id.md","title":"Directives Skill","category":"anthropic-skill","format":"markdown","content":"---\norder: 17\ntitle: id\n---\n\n# x-id\n\n`x-id` allows you to declare a new \"scope\" for any new IDs generated using `$id()`. It accepts an array of strings (ID names) and adds a suffix to each `$id('...')` generated within it that is unique to other IDs on the page.\n\n`x-id` is meant to be used in conjunction with the `$id(...)` magic.\n\n[Visit the $id documentation](/magics/id) for a better understanding of this feature.\n\nHere's a brief example of this directive in use:\n\n```alpine\n<div x-id=\"['text-input']\">\n    <label :for=\"$id('text-input')\">Username</label>\n    <!-- for=\"text-input-1\" -->\n\n    <input type=\"text\" :id=\"$id('text-input')\">\n    <!-- id=\"text-input-1\" -->\n</div>\n\n<div x-id=\"['text-input']\">\n    <label :for=\"$id('text-input')\">Username</label>\n    <!-- for=\"text-input-2\" -->\n\n    <input type=\"text\" :id=\"$id('text-input')\">\n    <!-- id=\"text-input-2\" -->\n</div>\n```\n\n> Despite not being included in the above snippet, `x-id` cannot be used if no parent element has `x-data` defined. [→ Read more about `x-data`](/directives/data)\n","frontmatter":{"order":17,"title":"id"},"isInternal":false,"tokens":297,"sizeBytes":1052},{"name":"if.md","path":"packages/docs/src/en/directives/if.md","rawUrl":"https://raw.githubusercontent.com/alpinejs/alpine/HEAD/packages/docs/src/en/directives/if.md","title":"Directives Skill","category":"anthropic-skill","format":"markdown","content":"---\norder: 16\ntitle: if\n---\n\n# x-if\n\n`x-if` is used for toggling elements on the page, similarly to `x-show`, however it completely adds and removes the element it's applied to rather than just changing its CSS display property to \"none\".\n\nBecause of this difference in behavior, `x-if` should not be applied directly to the element, but instead to a `<template>` tag that encloses the element. This way, Alpine can keep a record of the element once it's removed from the page.\n\n```alpine\n<template x-if=\"open\">\n    <div>Contents...</div>\n</template>\n```\n\n> Despite not being included in the above snippet, `x-if` cannot be used if no parent element has `x-data` defined. [→ Read more about `x-data`](/directives/data)\n\n## Caveats\n\nUnlike `x-show`, `x-if`, does NOT support transitioning toggles with `x-transition`.\n\n`<template>` tags can only contain one root element.\n","frontmatter":{"order":16,"title":"if"},"isInternal":false,"tokens":214,"sizeBytes":873},{"name":"ignore.md","path":"packages/docs/src/en/directives/ignore.md","rawUrl":"https://raw.githubusercontent.com/alpinejs/alpine/HEAD/packages/docs/src/en/directives/ignore.md","title":"Directives Skill","category":"anthropic-skill","format":"markdown","content":"---\norder: 11\ntitle: ignore\n---\n\n# x-ignore\n\nBy default, Alpine will crawl and initialize the entire DOM tree of an element containing `x-init` or `x-data`.\n\nIf for some reason, you don't want Alpine to touch a specific section of your HTML, you can prevent it from doing so using `x-ignore`.\n\n```alpine\n<div x-data=\"{ label: 'From Alpine' }\">\n    <div x-ignore>\n        <span x-text=\"label\"></span>\n    </div>\n</div>\n```\n\nIn the above example, the `<span>` tag will not contain \"From Alpine\" because we told Alpine to ignore the contents of the `div` completely.\n","frontmatter":{"order":11,"title":"ignore"},"isInternal":false,"tokens":144,"sizeBytes":564},{"name":"init.md","path":"packages/docs/src/en/directives/init.md","rawUrl":"https://raw.githubusercontent.com/alpinejs/alpine/HEAD/packages/docs/src/en/directives/init.md","title":"Directives Skill","category":"anthropic-skill","format":"markdown","content":"---\norder: 2\ntitle: init\n---\n\n# x-init\n\nThe `x-init` directive allows you to hook into the initialization phase of any element in Alpine.\n\n```alpine\n<div x-init=\"console.log('I\\'m being initialized!')\"></div>\n```\n\nIn the above example, \"I\\'m being initialized!\" will be output in the console before it makes further DOM updates.\n\nConsider another example where `x-init` is used to fetch some JSON and store it in `x-data` before the component is processed.\n\n```alpine\n<div\n    x-data=\"{ posts: [] }\"\n    x-init=\"posts = await (await fetch('/posts')).json()\"\n>...</div>\n```\n\n<a name=\"next-tick\"></a>\n## $nextTick\n\nSometimes, you want to wait until after Alpine has completely finished rendering to execute some code.\n\nThis would be something like `useEffect(..., [])` in react, or `mount` in Vue.\n\nBy using Alpine's internal `$nextTick` magic, you can make this happen.\n\n```alpine\n<div x-init=\"$nextTick(() => { ... })\"></div>\n```\n\n<a name=\"standalone-x-init\"></a>\n## Standalone `x-init`\n\nYou can add `x-init` to any elements inside or outside an `x-data` HTML block. For example:\n\n```alpine\n<div x-data>\n    <span x-init=\"console.log('I can initialize')\"></span>\n</div>\n\n<span x-init=\"console.log('I can initialize too')\"></span>\n```\n\n<a name=\"auto-evaluate-init-method\"></a>\n## Auto-evaluate init() method\n\nIf the `x-data` object of a component contains an `init()` method, it will be called automatically. For example:\n\n```alpine\n<div x-data=\"{\n    init() {\n        console.log('I am called automatically')\n    }\n}\">\n    ...\n</div>\n```\n\nThis is also the case for components that were registered using the `Alpine.data()` syntax.\n\n```js\nAlpine.data('dropdown', () => ({\n    init() {\n        console.log('I will get evaluated when initializing each \"dropdown\" component.')\n    },\n}))\n```\n\nIf you have both an `x-data` object containing an `init()` method and an `x-init` directive, the `x-data` method will be called before the directive.\n\n```alpine\n<div\n    x-data=\"{\n        init() {\n            console.log('I am called first')\n        }\n    }\"\n    x-init=\"console.log('I am called second')\"\n    >\n    ...\n</div>\n```\n","frontmatter":{"order":2,"title":"init"},"isInternal":false,"tokens":543,"sizeBytes":2120},{"name":"model.md","path":"packages/docs/src/en/directives/model.md","rawUrl":"https://raw.githubusercontent.com/alpinejs/alpine/HEAD/packages/docs/src/en/directives/model.md","title":"Directives Skill","category":"anthropic-skill","format":"markdown","content":"---\norder: 7\ntitle: model\n---\n\n# x-model\n\n`x-model` allows you to bind the value of an input element to Alpine data.\n\nHere's a simple example of using `x-model` to bind the value of a text field to a piece of data in Alpine.\n\n```alpine\n<div x-data=\"{ message: '' }\">\n    <input type=\"text\" x-model=\"message\">\n\n    <span x-text=\"message\"></span>\n</div>\n```\n\n<!-- START_VERBATIM -->\n<div class=\"demo\">\n    <div x-data=\"{ message: '' }\">\n        <input type=\"text\" x-model=\"message\" placeholder=\"Type message...\">\n\n        <div class=\"pt-4\" x-text=\"message\"></div>\n    </div>\n</div>\n<!-- END_VERBATIM -->\n\n\nNow as the user types into the text field, the `message` will be reflected in the `<span>` tag.\n\n`x-model` is two-way bound, meaning it both \"sets\" and \"gets\". In addition to changing data, if the data itself changes, the element will reflect the change.\n\n\nWe can use the same example as above but this time, we'll add a button to change the value of the `message` property.\n\n```alpine\n<div x-data=\"{ message: '' }\">\n    <input type=\"text\" x-model=\"message\">\n\n    <button x-on:click=\"message = 'changed'\">Change Message</button>\n</div>\n```\n\n<!-- START_VERBATIM -->\n<div class=\"demo\">\n    <div x-data=\"{ message: '' }\">\n        <input type=\"text\" x-model=\"message\" placeholder=\"Type message...\">\n\n        <button x-on:click=\"message = 'changed'\">Change Message</button>\n    </div>\n</div>\n<!-- END_VERBATIM -->\n\nNow when the `<button>` is clicked, the input element's value will instantly be updated to \"changed\".\n\n`x-model` works with the following input elements:\n\n* `<input type=\"text\">`\n* `<textarea>`\n* `<input type=\"checkbox\">`\n* `<input type=\"radio\">`\n* `<select>`\n* `<input type=\"range\">`\n\n<a name=\"text-inputs\"></a>\n## Text inputs\n\n```alpine\n<input type=\"text\" x-model=\"message\">\n\n<span x-text=\"message\"></span>\n```\n\n<!-- START_VERBATIM -->\n<div class=\"demo\">\n    <div x-data=\"{ message: '' }\">\n        <input type=\"text\" x-model=\"message\" placeholder=\"Type message\">\n\n        <div class=\"pt-4\" x-text=\"message\"></div>\n    </div>\n</div>\n<!-- END_VERBATIM -->\n\n> Despite not being included in the above snippet, `x-model` cannot be used if no parent element has `x-data` defined. [→ Read more about `x-data`](/directives/data)\n\n<a name=\"textarea-inputs\"></a>\n## Textarea inputs\n\n```alpine\n<textarea x-model=\"message\"></textarea>\n\n<span x-text=\"message\"></span>\n```\n\n<!-- START_VERBATIM -->\n<div class=\"demo\">\n    <div x-data=\"{ message: '' }\">\n        <textarea x-model=\"message\" placeholder=\"Type message\"></textarea>\n\n        <div class=\"pt-4\" x-text=\"message\"></div>\n    </div>\n</div>\n<!-- END_VERBATIM -->\n\n<a name=\"checkbox-inputs\"></a>\n## Checkbox inputs\n\n<a name=\"single-checkbox-with-boolean\"></a>\n### Single checkbox with boolean\n\n```alpine\n<input type=\"checkbox\" id=\"checkbox\" x-model=\"show\">\n\n<label for=\"checkbox\" x-text=\"show\"></label>\n```\n\n<!-- START_VERBATIM -->\n<div class=\"demo\">\n    <div x-data=\"{ open: '' }\">\n        <input type=\"checkbox\" id=\"checkbox\" x-model=\"open\">\n\n        <label for=\"checkbox\" x-text=\"open\"></label>\n    </div>\n</div>\n<!-- END_VERBATIM -->\n\n<a name=\"multiple-checkboxes-bound-to-array\"></a>\n### Multiple checkboxes bound to array\n\n```alpine\n<input type=\"checkbox\" value=\"red\" x-model=\"colors\">\n<input type=\"checkbox\" value=\"orange\" x-model=\"colors\">\n<input type=\"checkbox\" value=\"yellow\" x-model=\"colors\">\n\nColors: <span x-text=\"colors\"></span>\n```\n\n<!-- START_VERBATIM -->\n<div class=\"demo\">\n    <div x-data=\"{ colors: [] }\">\n        <input type=\"checkbox\" value=\"red\" x-model=\"colors\">\n        <input type=\"checkbox\" value=\"orange\" x-model=\"colors\">\n        <input type=\"checkbox\" value=\"yellow\" x-model=\"colors\">\n\n        <div class=\"pt-4\">Colors: <span x-text=\"colors\"></span></div>\n    </div>\n</div>\n<!-- END_VERBATIM -->\n\n<a name=\"radio-inputs\"></a>\n## Radio inputs\n\n```alpine\n<input type=\"radio\" value=\"yes\" x-model=\"answer\">\n<input type=\"radio\" value=\"no\" x-model=\"answer\">\n\nAnswer: <span x-text=\"answer\"></span>\n```\n\n<!-- START_VERBATIM -->\n<div class=\"demo\">\n    <div x-data=\"{ answer: '' }\">\n        <input type=\"radio\" value=\"yes\" x-model=\"answer\">\n        <input type=\"radio\" value=\"no\" x-model=\"answer\">\n\n        <div class=\"pt-4\">Answer: <span x-text=\"answer\"></span></div>\n    </div>\n</div>\n<!-- END_VERBATIM -->\n\n<a name=\"select-inputs\"></a>\n## Select inputs\n\n\n<a name=\"single-select\"></a>\n### Single select\n\n```alpine\n<select x-model=\"color\">\n    <option>Red</option>\n    <option>Orange</option>\n    <option>Yellow</option>\n</select>\n\nColor: <span x-text=\"color\"></span>\n```\n\n<!-- START_VERBATIM -->\n<div class=\"demo\">\n    <div x-data=\"{ color: '' }\">\n        <select x-model=\"color\">\n            <option>Red</option>\n            <option>Orange</option>\n            <option>Yellow</option>\n        </select>\n\n        <div class=\"pt-4\">Color: <span x-text=\"color\"></span></div>\n    </div>\n</div>\n<!-- END_VERBATIM -->\n\n<a name=\"single-select-with-placeholder\"></a>\n### Single select with placeholder\n\n```alpine\n<select x-model=\"color\">\n    <option value=\"\" disabled>Select A Color</option>\n    <option>Red</option>\n    <option>Orange</option>\n    <option>Yellow</option>\n</select>\n\nColor: <span x-text=\"color\"></span>\n```\n\n\n<!-- START_VERBATIM -->\n<div class=\"demo\">\n    <div x-data=\"{ color: '' }\">\n        <select x-model=\"color\">\n            <option value=\"\" disabled>Select A Color</option>\n            <option>Red</option>\n            <option>Orange</option>\n            <option>Yellow</option>\n        </select>\n\n        <div class=\"pt-4\">Color: <span x-text=\"color\"></span></div>\n    </div>\n</div>\n<!-- END_VERBATIM -->\n\n<a name=\"multiple-select\"></a>\n### Multiple select\n\n```alpine\n<select x-model=\"color\" multiple>\n    <option>Red</option>\n    <option>Orange</option>\n    <option>Yellow</option>\n</select>\n\nColors: <span x-text=\"color\"></span>\n```\n\n<!-- START_VERBATIM -->\n<div class=\"demo\">\n    <div x-data=\"{ color: '' }\">\n        <select x-model=\"color\" multiple>\n            <option>Red</option>\n            <option>Orange</option>\n            <option>Yellow</option>\n        </select>\n\n        <div class=\"pt-4\">Color: <span x-text=\"color\"></span></div>\n    </div>\n</div>\n<!-- END_VERBATIM -->\n\n<a name=\"dynamically-populated-select-options\"></a>\n### Dynamically populated Select Options\n\n```alpine\n<select x-model=\"color\">\n    <template x-for=\"color in ['Red', 'Orange', 'Yellow']\">\n        <option x-text=\"color\"></option>\n    </template>\n</select>\n\nColor: <span x-text=\"color\"></span>\n```\n\n<!-- START_VERBATIM -->\n<div class=\"demo\">\n    <div x-data=\"{ color: '' }\">\n        <select x-model=\"color\">\n            <template x-for=\"color in ['Red', 'Orange', 'Yellow']\">\n                <option x-text=\"color\"></option>\n            </template>\n        </select>\n\n        <div class=\"pt-4\">Color: <span x-text=\"color\"></span></div>\n    </div>\n</div>\n<!-- END_VERBATIM -->\n\n<a name=\"range-inputs\"></a>\n## Range inputs\n\n```alpine\n<input type=\"range\" x-model=\"range\" min=\"0\" max=\"1\" step=\"0.1\">\n\n<span x-text=\"range\"></span>\n```\n\n<!-- START_VERBATIM -->\n<div class=\"demo\">\n    <div x-data=\"{ range: 0.5 }\">\n        <input type=\"range\" x-model=\"range\" min=\"0\" max=\"1\" step=\"0.1\">\n\n        <div class=\"pt-4\" x-text=\"range\"></div>\n    </div>\n</div>\n<!-- END_VERBATIM -->\n\n\n<a name=\"modifiers\"></a>\n## Modifiers\n\n<a name=\"lazy\"></a>\n### `.lazy`\n\nOn text inputs, by default, `x-model` updates the property on every keystroke. By adding the `.lazy` modifier, you can force an `x-model` input to only update the property when user focuses away from the input element.\n\nThis is handy for things like real-time form-validation where you might not want to show an input validation error until the user \"tabs\" away from a field.\n\n```alpine\n<input type=\"text\" x-model.lazy=\"username\">\n<span x-show=\"username.length > 20\">The username is too long.</span>\n```\n\n<a name=\"change\"></a>\n### `.change`\n\n`.change` syncs the data only when the input loses focus and its value has changed (the native `change` event). This is functionally equivalent to `.lazy`.\n\n```alpine\n<input type=\"text\" x-model.change=\"username\">\n```\n\n<a name=\"blur\"></a>\n### `.blur`\n\n`.blur` syncs the data when the input loses focus, regardless of whether the value has changed.\n\n```alpine\n<input type=\"text\" x-model.blur=\"email\">\n```\n\n<a name=\"enter\"></a>\n### `.enter`\n\n`.enter` syncs the data when the user presses the Enter key. This is useful for search fields where you want to trigger an action only when the user explicitly submits.\n\n```alpine\n<input type=\"text\" x-model.enter=\"search\">\n```\n\n> Note: `.enter` does not prevent the default behavior. If the input is inside a form, the form will still submit.\n\n<a name=\"combining-event-modifiers\"></a>\n### Combining Event Modifiers\n\nThe `.change`, `.blur`, and `.enter` modifiers can be combined to sync on multiple events. This is useful when you want to give users flexibility in how they submit data.\n\n```alpine\n<!-- Sync on blur OR enter -->\n<input type=\"text\" x-model.blur.enter=\"search\" placeholder=\"Press Enter or click away\">\n\n<!-- Sync on change, blur, OR enter -->\n<input type=\"text\" x-model.change.blur.enter=\"message\">\n```\n\n<!-- START_VERBATIM -->\n<div class=\"demo\">\n    <div x-data=\"{ search: '' }\">\n        <input type=\"text\" x-model.blur.enter=\"search\" placeholder=\"Press Enter or click away\">\n\n        <div class=\"pt-4\">Search: <span x-text=\"search\"></span></div>\n    </div>\n</div>\n<!-- END_VERBATIM -->\n\n<a name=\"number\"></a>\n### `.number`\n\nBy default, any data stored in a property via `x-model` is stored as a string. To force Alpine to store the value as a JavaScript number, add the `.number` modifier.\n\n```alpine\n<input type=\"text\" x-model.number=\"age\">\n<span x-text=\"typeof age\"></span>\n```\n\n<a name=\"boolean\"></a>\n### `.boolean`\n\nBy default, any data stored in a property via `x-model` is stored as a string. To force Alpine to store the value as a JavaScript boolean, add the `.boolean` modifier. Both integers (1/0) and strings (true/false) are valid boolean values.\n\n```alpine\n<select x-model.boolean=\"isActive\">\n    <option value=\"true\">Yes</option>\n    <option value=\"false\">No</option>\n</select>\n<span x-text=\"typeof isActive\"></span>\n```\n\n<a name=\"debounce\"></a>\n### `.debounce`\n\nBy adding `.debounce` to `x-model`, you can easily debounce the updating of bound input.\n\nThis is useful for things like real-time search inputs that fetch new data from the server every time the search property changes.\n\n```alpine\n<input type=\"text\" x-model.debounce=\"search\">\n```\n\nThe default debounce time is 250 milliseconds, you can easily customize this by adding a time modifier like so.\n\n```alpine\n<input type=\"text\" x-model.debounce.500ms=\"search\">\n```\n\n<a name=\"throttle\"></a>\n### `.throttle`\n\nSimilar to `.debounce` you can limit the property update triggered by `x-model` to only updating on a specified interval.\n\n<input type=\"text\" x-model.throttle=\"search\">\n\nThe default throttle interval is 250 milliseconds, you can easily customize this by adding a time modifier like so.\n\n```alpine\n<input type=\"text\" x-model.throttle.500ms=\"search\">\n```\n\n<a name=\"fill\"></a>\n### `.fill`\n\nBy default, if an input has a value attribute, it is ignored by Alpine and instead, the value of the input is set to the value of the property bound using `x-model`.\n\nBut if a bound property is empty, then you can use an input's value attribute to populate the property by adding the `.fill` modifier.\n\n<div x-data=\"{ message: null }\">\n  <input type=\"text\" x-model.fill=\"message\" value=\"This is the default message.\">\n</div>\n\n<a name=\"programmatic access\"></a>\n## Programmatic access\n\nAlpine exposes under-the-hood utilities for getting and setting properties bound with `x-model`. This is useful for complex Alpine utilities that may want to override the default x-model behavior, or instances where you want to allow `x-model` on a non-input element.\n\nYou can access these utilities through a property called `_x_model` on the `x-model`ed element. `_x_model` has two methods to get and set the bound property:\n\n* `el._x_model.get()` (returns the value of the bound property)\n* `el._x_model.set()` (sets the value of the bound property)\n\n```alpine\n<div x-data=\"{ username: 'calebporzio' }\">\n    <div x-ref=\"div\" x-model=\"username\"></div>\n\n    <button @click=\"$refs.div._x_model.set('phantomatrix')\">\n        Change username to: 'phantomatrix'\n    </button>\n\n    <span x-text=\"$refs.div._x_model.get()\"></span>\n</div>\n```\n\n<!-- START_VERBATIM -->\n<div class=\"demo\">\n    <div x-data=\"{ username: 'calebporzio' }\">\n        <div x-ref=\"div\" x-model=\"username\"></div>\n\n        <button @click=\"$refs.div._x_model.set('phantomatrix')\">\n            Change username to: 'phantomatrix'\n        </button>\n\n        <span x-text=\"$refs.div._x_model.get()\"></span>\n    </div>\n</div>\n<!-- END_VERBATIM -->\n","frontmatter":{"order":7,"title":"model"},"isInternal":false,"tokens":3356,"sizeBytes":12782},{"name":"modelable.md","path":"packages/docs/src/en/directives/modelable.md","rawUrl":"https://raw.githubusercontent.com/alpinejs/alpine/HEAD/packages/docs/src/en/directives/modelable.md","title":"Directives Skill","category":"anthropic-skill","format":"markdown","content":"---\norder: 7\ntitle: modelable\n---\n\n# x-modelable\n\n`x-modelable` allows you to expose Alpine state as the target of the `x-model` directive.\n\nHere's a simple example of using `x-modelable` to expose a variable for binding with `x-model`.\n\n```alpine\n<div x-data=\"{ number: 5 }\">\n    <div x-data=\"{ count: 0 }\" x-modelable=\"count\" x-model=\"number\">\n        <button @click=\"count++\">Increment</button>\n    </div>\n\n    Number: <span x-text=\"number\"></span>\n</div>\n```\n\n<!-- START_VERBATIM -->\n<div class=\"demo\">\n    <div x-data=\"{ number: 5 }\">\n        <div x-data=\"{ count: 0 }\" x-modelable=\"count\" x-model=\"number\">\n            <button @click=\"count++\">Increment</button>\n        </div>\n\n        Number: <span x-text=\"number\"></span>\n    </div>\n</div>\n<!-- END_VERBATIM -->\n\nAs you can see the outer scope property \"number\" is now bound to the inner scope property \"count\".\n\nTypically this feature would be used in conjunction with a backend templating framework like Laravel Blade. It's useful for abstracting away Alpine components into backend templates and exposing state to the outside through `x-model` as if it were a native input.\n\n## Supported values\n\n`x-modelable` keeps its inner and outer state independent by cloning values as JSON. It is therefore intended for JSON-compatible state such as strings, numbers, booleans, `null`, arrays, and plain objects containing those values.\n\nBrowser objects and other state that cannot be represented as JSON won't cross this boundary intact. For example, a `File` loses properties such as its name, size, and type. The same limitation applies to values such as `FileList`, `Map`, `Set`, `Date`, class instances, and DOM nodes.\n\nFor a custom input that produces one of these values, omit `x-modelable` and [dispatch an `input` event](/magics/dispatch#dispatching-to-x-model) instead. `x-model` reads the value directly from the event without cloning it:\n\n```alpine\n<div x-data=\"{ files: [] }\">\n    <div x-model=\"files\">\n        <input\n            type=\"file\"\n            multiple\n            @change=\"$dispatch('input', Array.from($event.target.files))\"\n        >\n    </div>\n\n    <template x-for=\"file in files\" :key=\"file.name\">\n        <p x-text=\"file.name\"></p>\n    </template>\n</div>\n```\n","frontmatter":{"order":7,"title":"modelable"},"isInternal":false,"tokens":554,"sizeBytes":2240},{"name":"on.md","path":"packages/docs/src/en/directives/on.md","rawUrl":"https://raw.githubusercontent.com/alpinejs/alpine/HEAD/packages/docs/src/en/directives/on.md","title":"Directives Skill","category":"anthropic-skill","format":"markdown","content":"---\norder: 5\ntitle: on\n---\n\n# x-on\n\n`x-on` allows you to easily run code on dispatched DOM events.\n\nHere's an example of simple button that shows an alert when clicked.\n\n```alpine\n<button x-on:click=\"alert('Hello World!')\">Say Hi</button>\n```\n\n> `x-on` can only listen for events with lower case names, as HTML attributes are case-insensitive. Writing `x-on:CLICK` will listen for an event named `click`. If you need to listen for a custom event with a camelCase name, you can use the [`.camel` helper](#camel) to work around this limitation. Alternatively, you can use [`x-bind`](/directives/bind#bind-directives) to attach an `x-on` directive to an element in javascript code (where case will be preserved).\n\n<a name=\"shorthand-syntax\"></a>\n## Shorthand syntax\n\nIf `x-on:` is too verbose for your tastes, you can use the shorthand syntax: `@`.\n\nHere's the same component as above, but using the shorthand syntax instead:\n\n```alpine\n<button @click=\"alert('Hello World!')\">Say Hi</button>\n```\n\n> Despite not being included in the above snippet, `x-on` cannot be used if no parent element has `x-data` defined. [→ Read more about `x-data`](/directives/data)\n\n<a name=\"the-event-object\"></a>\n## The event object\n\nIf you wish to access the native JavaScript event object from your expression, you can use Alpine's magic `$event` property.\n\n```alpine\n<button @click=\"alert($event.target.getAttribute('message'))\" message=\"Hello World\">Say Hi</button>\n```\n\nIn addition, Alpine also passes the event object to any methods referenced without trailing parenthesis. For example:\n\n```alpine\n<button @click=\"handleClick\">...</button>\n\n<script>\n    function handleClick(e) {\n        // Now you can access the event object (e) directly\n    }\n</script>\n```\n\n<a name=\"keyboard-events\"></a>\n## Keyboard events\n\nAlpine makes it easy to listen for `keydown` and `keyup` events on specific keys.\n\nHere's an example of listening for the `Enter` key inside an input element.\n\n```alpine\n<input type=\"text\" @keyup.enter=\"alert('Submitted!')\">\n```\n\nYou can also chain these key modifiers to achieve more complex listeners.\n\nHere's a listener that runs when the `Shift` key is held and `Enter` is pressed, but not when `Enter` is pressed alone.\n\n```alpine\n<input type=\"text\" @keyup.shift.enter=\"alert('Submitted!')\">\n```\n\nYou can directly use any valid key names exposed via [`KeyboardEvent.key`](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key/Key_Values) as modifiers by converting them to kebab-case.\n\n```alpine\n<input type=\"text\" @keyup.page-down=\"alert('Submitted!')\">\n```\n\nFor easy reference, here is a list of common keys you may want to listen for.\n\n| Modifier                       | Keyboard Key                       |\n| ------------------------------ | ---------------------------------- |\n| `.shift`                       | Shift                              |\n| `.enter`                       | Enter                              |\n| `.space`                       | Space                              |\n| `.ctrl`                        | Ctrl                               |\n| `.cmd`                         | Cmd                                |\n| `.meta`                        | Cmd on Mac, Windows key on Windows |\n| `.alt`                         | Alt                                |\n| `.up` `.down` `.left` `.right` | Up/Down/Left/Right arrows          |\n| `.escape`                      | Escape                             |\n| `.tab`                         | Tab                                |\n| `.caps-lock`                   | Caps Lock                          |\n| `.equal`                       | Equal, `=`                         |\n| `.period`                      | Period, `.`                        |\n| `.comma`                       | Comma, `,`                         |\n| `.slash`                       | Forward Slash, `/`                 |\n\n<a name=\"mouse-events\"></a>\n## Mouse events\n\nLike the above Keyboard Events, Alpine allows the use of some key modifiers for handling `click` events.\n\n| Modifier | Event Key |\n| -------- | --------- |\n| `.shift` | shiftKey  |\n| `.ctrl`  | ctrlKey   |\n| `.cmd`   | metaKey   |\n| `.meta`  | metaKey   |\n| `.alt`   | altKey    |\n\nThese work on `click`, `auxclick`, `context` and `dblclick` events, and even `mouseover`, `mousemove`, `mouseenter`, `mouseleave`, `mouseout`, `mouseup` and `mousedown`.\n\nHere's an example of a button that changes behaviour when the `Shift` key is held down.\n\n```alpine\n<button type=\"button\"\n    x-data=\"{ message: 'select' }\"\n    @click=\"message = 'selected'\"\n    @click.shift=\"message = 'added to selection'\"\n    @mousemove.shift=\"message = 'add to selection'\"\n    @mouseout=\"message = 'select'\"\n    x-text=\"message\"></button>\n```\n\n<!-- START_VERBATIM -->\n<div class=\"demo\">\n    <div x-data=\"{ message: '' }\">\n        <button type=\"button\"\n            x-data=\"{ message: 'select' }\"\n            @click=\"message = 'selected'\"\n            @click.shift=\"message = 'added to selection'\"\n            @mousemove.shift=\"message = 'add to selection'\"\n            @mouseout=\"message = 'select'\"\n            x-text=\"message\"></button>\n    </div>\n</div>\n<!-- END_VERBATIM -->\n\n> Note: Normal click events with some modifiers (like `ctrl`) will automatically become `contextmenu` events in most browsers. Similarly, `right-click` events will trigger a `contextmenu` event, but will also trigger an `auxclick` event if the `contextmenu` event is prevented.\n\n<a name=\"custom-events\"></a>\n## Custom events\n\nAlpine event listeners are a wrapper for native DOM event listeners. Therefore, they can listen for ANY DOM event, including custom events.\n\nHere's an example of a component that dispatches a custom DOM event and listens for it as well.\n\n```alpine\n<div x-data @foo=\"alert('Button Was Clicked!')\">\n    <button @click=\"$event.target.dispatchEvent(new CustomEvent('foo', { bubbles: true }))\">...</button>\n</div>\n```\n\nWhen the button is clicked, the `@foo` listener will be called.\n\nBecause the `.dispatchEvent` API is verbose, Alpine offers a `$dispatch` helper to simplify things.\n\nHere's the same component re-written with the `$dispatch` magic property.\n\n```alpine\n<div x-data @foo=\"alert('Button Was Clicked!')\">\n    <button @click=\"$dispatch('foo')\">...</button>\n</div>\n```\n\n[→ Read more about `$dispatch`](/magics/dispatch)\n\n<a name=\"modifiers\"></a>\n## Modifiers\n\nAlpine offers a number of directive modifiers to customize the behavior of your event listeners.\n\n<a name=\"prevent\"></a>\n### .prevent\n\n`.prevent` is the equivalent of calling `.preventDefault()` inside a listener on the browser event object.\n\n```alpine\n<form @submit.prevent=\"console.log('submitted')\" action=\"/foo\">\n    <button>Submit</button>\n</form>\n```\n\nIn the above example, with the `.prevent`, clicking the button will NOT submit the form to the `/foo` endpoint. Instead, Alpine's listener will handle it and \"prevent\" the event from being handled any further.\n\n<a name=\"stop\"></a>\n### .stop\n\nSimilar to `.prevent`, `.stop` is the equivalent of calling `.stopPropagation()` inside a listener on the browser event object.\n\n```alpine\n<div @click=\"console.log('I will not get logged')\">\n    <button @click.stop>Click Me</button>\n</div>\n```\n\nIn the above example, clicking the button WON'T log the message. This is because we are stopping the propagation of the event immediately and not allowing it to \"bubble\" up to the `<div>` with the `@click` listener on it.\n\n<a name=\"outside\"></a>\n### .outside\n\n`.outside` is a convenience helper for listening for a click outside of the element it is attached to. Here's a simple dropdown component example to demonstrate:\n\n```alpine\n<div x-data=\"{ open: false }\">\n    <button @click=\"open = ! open\">Toggle</button>\n\n    <div x-show=\"open\" @click.outside=\"open = false\">\n        Contents...\n    </div>\n</div>\n```\n\nIn the above example, after showing the dropdown contents by clicking the \"Toggle\" button, you can close the dropdown by clicking anywhere on the page outside the content.\n\nThis is because `.outside` is listening for clicks that DON'T originate from the element it's registered on.\n\n> It's worth noting that the `.outside` expression will only be evaluated when the element it's registered on is visible on the page. Otherwise, there would be nasty race conditions where clicking the \"Toggle\" button would also fire the `@click.outside` handler when it is not visible.\n\n<a name=\"window\"></a>\n### .window\n\nWhen the `.window` modifier is present, Alpine will register the event listener on the root `window` object on the page instead of the element itself.\n\n```alpine\n<div @keyup.escape.window=\"...\">...</div>\n```\n\nThe above snippet will listen for the \"escape\" key to be pressed ANYWHERE on the page.\n\nAdding `.window` to listeners is extremely useful for these sorts of cases where a small part of your markup is concerned with events that take place on the entire page.\n\n<a name=\"document\"></a>\n### .document\n\n`.document` works similarly to `.window` only it registers listeners on the `document` global, instead of the `window` global.\n\n<a name=\"once\"></a>\n### .once\n\nBy adding `.once` to a listener, you are ensuring that the handler is only called ONCE.\n\n```alpine\n<button @click.once=\"console.log('I will only log once')\">...</button>\n```\n\n<a name=\"debounce\"></a>\n### .debounce\n\nSometimes it is useful to \"debounce\" an event handler so that it only is called after a certain period of inactivity (250 milliseconds by default).\n\nFor example if you have a search field that fires network requests as the user types into it, adding a debounce will prevent the network requests from firing on every single keystroke.\n\n```alpine\n<input @input.debounce=\"fetchResults\">\n```\n\nNow, instead of calling `fetchResults` after every keystroke, `fetchResults` will only be called after 250 milliseconds of no keystrokes.\n\nIf you wish to lengthen or shorten the debounce time, you can do so by trailing a duration after the `.debounce` modifier like so:\n\n```alpine\n<input @input.debounce.500ms=\"fetchResults\">\n```\n\nNow, `fetchResults` will only be called after 500 milliseconds of inactivity.\n\n<a name=\"throttle\"></a>\n### .throttle\n\n`.throttle` is similar to `.debounce` except it will release a handler call every 250 milliseconds instead of deferring it indefinitely.\n\nThis is useful for cases where there may be repeated and prolonged event firing and using `.debounce` won't work because you want to still handle the event every so often.\n\nFor example:\n\n```alpine\n<div @scroll.window.throttle=\"handleScroll\">...</div>\n```\n\nThe above example is a great use case of throttling. Without `.throttle`, the `handleScroll` method would be fired hundreds of times as the user scrolls down a page. This can really slow down a site. By adding `.throttle`, we are ensuring that `handleScroll` only gets called every 250 milliseconds.\n\n> Fun Fact: This exact strategy is used on this very documentation site to update the currently highlighted section in the right sidebar.\n\nJust like with `.debounce`, you can add a custom duration to your throttled event:\n\n```alpine\n<div @scroll.window.throttle.750ms=\"handleScroll\">...</div>\n```\n\nNow, `handleScroll` will only be called every 750 milliseconds.\n\n<a name=\"self\"></a>\n### .self\n\nBy adding `.self` to an event listener, you are ensuring that the event originated on the element it is declared on, and not from a child element.\n\n```alpine\n<button @click.self=\"handleClick\">\n    Click Me\n\n    <img src=\"...\">\n</button>\n```\n\nIn the above example, we have an `<img>` tag inside the `<button>` tag. Normally, any click originating within the `<button>` element (like on `<img>` for example), would be picked up by a `@click` listener on the button.\n\nHowever, in this case, because we've added a `.self`, only clicking the button itself will call `handleClick`. Only clicks originating on the `<img>` element will not be handled.\n\n<a name=\"camel\"></a>\n### .camel\n\n```alpine\n<div @custom-event.camel=\"handleCustomEvent\">\n    ...\n</div>\n```\n\nSometimes you may want to listen for camelCased events such as `customEvent` in our example. Because camelCasing inside HTML attributes is not supported, adding the `.camel` modifier is necessary for Alpine to camelCase the event name internally.\n\nBy adding `.camel` in the above example, Alpine is now listening for `customEvent` instead of `custom-event`.\n\n<a name=\"dot\"></a>\n### .dot\n\n```alpine\n<div @custom-event.dot=\"handleCustomEvent\">\n    ...\n</div>\n```\n\nSimilar to the `.camelCase` modifier there may be situations where you want to listen for events that have dots in their name (like `custom.event`). Since dots within the event name are reserved by Alpine you need to write them with dashes and add the `.dot` modifier.\n\nIn the code example above `custom-event.dot` will correspond to the event name `custom.event`.\n\n<a name=\"passive\"></a>\n### .passive\n\nBrowsers optimize scrolling on pages to be fast and smooth even when JavaScript is being executed on the page. However, improperly implemented touch and wheel listeners can block this optimization and cause poor site performance.\n\nIf you are listening for touch events, it's important to add `.passive` to your listeners to not block scroll performance.\n\n```alpine\n<div @touchstart.passive=\"...\">...</div>\n```\n\n[→ Read more about passive listeners](https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener#improving_scrolling_performance_with_passive_listeners)\n\n<a name=\"passive-false\"></a>\n### .passive.false\n\nIn modern browsers, touch and wheel event listeners are passive by default. Pass `.passive.false` to make these events cancelable, so that you can call `preventDefault` on them.\n\n```alpine\n<div @touchmove.passive.false=\"$event.preventDefault()\">...</div>\n```\n\n### .capture\n\nAdd this modifier if you want to execute this listener in the event's capturing phase, e.g. before the event bubbles from the target element up the DOM.\n\n```alpine\n<div @click.capture=\"console.log('I will log first')\">\n    <button @click=\"console.log('I will log second')\"></button>\n</div>\n```\n\n[→ Read more about the capturing and bubbling phase of events](https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener#usecapture)\n","frontmatter":{"order":5,"title":"on"},"isInternal":false,"tokens":3246,"sizeBytes":14217},{"name":"ref.md","path":"packages/docs/src/en/directives/ref.md","rawUrl":"https://raw.githubusercontent.com/alpinejs/alpine/HEAD/packages/docs/src/en/directives/ref.md","title":"Directives Skill","category":"anthropic-skill","format":"markdown","content":"---\norder: 11\ntitle: ref\n---\n\n# x-ref\n\n`x-ref` in combination with `$refs` is a useful utility for easily accessing DOM elements directly. It's most useful as a replacement for APIs like `getElementById` and `querySelector`.\n\n```alpine\n<button @click=\"$refs.text.remove()\">Remove Text</button>\n\n<span x-ref=\"text\">Hello 👋</span>\n```\n\n<!-- START_VERBATIM -->\n<div class=\"demo\">\n    <div x-data>\n        <button @click=\"$refs.text.remove()\">Remove Text</button>\n\n        <div class=\"pt-4\" x-ref=\"text\">Hello 👋</div>\n    </div>\n</div>\n<!-- END_VERBATIM -->\n\n> Despite not being included in the above snippet, `x-ref` cannot be used if no parent element has `x-data` defined. [→ Read more about `x-data`](/directives/data)\n","frontmatter":{"order":11,"title":"ref"},"isInternal":false,"tokens":192,"sizeBytes":727},{"name":"show.md","path":"packages/docs/src/en/directives/show.md","rawUrl":"https://raw.githubusercontent.com/alpinejs/alpine/HEAD/packages/docs/src/en/directives/show.md","title":"Directives Skill","category":"anthropic-skill","format":"markdown","content":"---\norder: 3\ntitle: show\n---\n\n# x-show\n\n`x-show` is one of the most useful and powerful directives in Alpine. It provides an expressive way to show and hide DOM elements.\n\nHere's an example of a simple dropdown component using `x-show`.\n\n```alpine\n<div x-data=\"{ open: false }\">\n    <button x-on:click=\"open = ! open\">Toggle Dropdown</button>\n\n    <div x-show=\"open\">\n        Dropdown Contents...\n    </div>\n</div>\n```\n\nWhen the \"Toggle Dropdown\" button is clicked, the dropdown will show and hide accordingly.\n\n> If the \"default\" state of an `x-show` on page load is \"false\", you may want to use `x-cloak` on the page to avoid \"page flicker\" (The effect that happens when the browser renders your content before Alpine is finished initializing and hiding it.) You can learn more about `x-cloak` in its documentation.\n\n<a name=\"with-transitions\"></a>\n## With transitions\n\nIf you want to apply smooth transitions to the `x-show` behavior, you can use it in conjunction with `x-transition`. You can learn more about that directive [here](/directives/transition), but here's a quick example of the same component as above, just with transitions applied.\n\n```alpine\n<div x-data=\"{ open: false }\">\n    <button x-on:click=\"open = ! open\">Toggle Dropdown</button>\n\n    <div x-show=\"open\" x-transition>\n        Dropdown Contents...\n    </div>\n</div>\n```\n\n<a name=\"using-the-important-modifier\"></a>\n## Using the important modifier\n\nSometimes you need to apply a little more force to actually hide an element. In cases where a CSS selector applies the `display` property with the `!important` flag, it will take precedence over the inline style set by Alpine.\n\nIn these cases you may use the `.important` modifier to set the inline style to `display: none !important`.\n\n```alpine\n<div x-data=\"{ open: false }\">\n    <button x-on:click=\"open = ! open\">Toggle Dropdown</button>\n\n    <div x-show.important=\"open\">\n        Dropdown Contents...\n    </div>\n</div>\n```\n","frontmatter":{"order":3,"title":"show"},"isInternal":false,"tokens":473,"sizeBytes":1952},{"name":"teleport.md","path":"packages/docs/src/en/directives/teleport.md","rawUrl":"https://raw.githubusercontent.com/alpinejs/alpine/HEAD/packages/docs/src/en/directives/teleport.md","title":"Directives Skill","category":"anthropic-skill","format":"markdown","content":"---\norder: 12\ntitle: teleport\ndescription: Send Alpine templates to other parts of the DOM\ngraph_image: https://alpinejs.dev/social_teleport.jpg\n---\n\n# x-teleport\n\nThe `x-teleport` directive allows you to transport part of your Alpine template to another part of the DOM on the page entirely.\n\nThis is useful for things like modals (especially nesting them), where it's helpful to break out of the z-index of the current Alpine component.\n\n<a name=\"x-teleport\"></a>\n## x-teleport\n\nBy attaching `x-teleport` to a `<template>` element, you are telling Alpine to \"append\" that element to the provided selector.\n\n> The `x-teleport` selector can be any string you would normally pass into something like `document.querySelector`. It will find the first element that matches, be it a tag name (`body`), class name (`.my-class`), ID (`#my-id`), or any other valid CSS selector.\n\n[→ Read more about `document.querySelector`](https://developer.mozilla.org/en-US/docs/Web/API/Document/querySelector)\n\nHere's a contrived modal example:\n\n```alpine\n<body>\n    <div x-data=\"{ open: false }\">\n        <button @click=\"open = ! open\">Toggle Modal</button>\n\n        <template x-teleport=\"body\">\n            <div x-show=\"open\">\n                Modal contents...\n            </div>\n        </template>\n    </div>\n\n    <div>Some other content placed AFTER the modal markup.</div>\n\n    ...\n\n</body>\n```\n\n<!-- START_VERBATIM -->\n<div class=\"demo\" x-ref=\"root\" id=\"modal2\">\n    <div x-data=\"{ open: false }\">\n        <button @click=\"open = ! open\">Toggle Modal</button>\n\n        <template x-teleport=\"#modal2\">\n            <div x-show=\"open\">\n                Modal contents...\n            </div>\n        </template>\n\n    </div>\n\n    <div class=\"py-4\">Some other content placed AFTER the modal markup.</div>\n</div>\n<!-- END_VERBATIM -->\n\nNotice how when toggling the modal, the actual modal contents show up AFTER the \"Some other content...\" element? This is because when Alpine is initializing, it sees `x-teleport=\"body\"` and appends and initializes that element to the provided element selector.\n\n<a name=\"forwarding-events\"></a>\n## Forwarding events\n\nAlpine tries its best to make the experience of teleporting seamless. Anything you would normally do in a template, you should be able to do inside an `x-teleport` template. Teleported content can access the normal Alpine scope of the component as well as other features like `$refs`, `$root`, etc...\n\nHowever, native DOM events have no concept of teleportation, so if, for example, you trigger a \"click\" event from inside a teleported element, that event will bubble up the DOM tree as it normally would.\n\nTo make this experience more seamless, you can \"forward\" events by simply registering event listeners on the `<template x-teleport...>` element itself like so:\n\n```alpine\n<div x-data=\"{ open: false }\">\n    <button @click=\"open = ! open\">Toggle Modal</button>\n\n    <template x-teleport=\"body\" @click=\"open = false\">\n        <div x-show=\"open\">\n            Modal contents...\n            (click to close)\n        </div>\n    </template>\n</div>\n```\n\n<!-- START_VERBATIM -->\n<div class=\"demo\" x-ref=\"root\" id=\"modal3\">\n    <div x-data=\"{ open: false }\">\n        <button @click=\"open = ! open\">Toggle Modal</button>\n\n        <template x-teleport=\"#modal3\" @click=\"open = false\">\n            <div x-show=\"open\">\n                Modal contents...\n                <div>(click to close)</div>\n            </div>\n        </template>\n    </div>\n</div>\n<!-- END_VERBATIM -->\n\nNotice how we are now able to listen for events dispatched from within the teleported element from outside the `<template>` element itself?\n\nAlpine does this by looking for event listeners registered on `<template x-teleport...>` and stops those events from propagating past the live, teleported, DOM element. Then, it creates a copy of that event and re-dispatches it from `<template x-teleport...>`.\n\n<a name=\"nesting\"></a>\n## Nesting\n\nTeleporting is especially helpful if you are trying to nest one modal within another. Alpine makes it simple to do so:\n\n```alpine\n<div x-data=\"{ open: false }\">\n    <button @click=\"open = ! open\">Toggle Modal</button>\n\n    <template x-teleport=\"body\">\n        <div x-show=\"open\">\n            Modal contents...\n\n            <div x-data=\"{ open: false }\">\n                <button @click=\"open = ! open\">Toggle Nested Modal</button>\n\n                <template x-teleport=\"body\">\n                    <div x-show=\"open\">\n                        Nested modal contents...\n                    </div>\n                </template>\n            </div>\n        </div>\n    </template>\n</div>\n```\n\n<!-- START_VERBATIM -->\n<div class=\"demo\" x-ref=\"root\" id=\"modal4\">\n    <div x-data=\"{ open: false }\">\n        <button @click=\"open = ! open\">Toggle Modal</button>\n\n        <template x-teleport=\"#modal4\">\n            <div x-show=\"open\">\n                <div class=\"py-4\">Modal contents...</div>\n\n                <div x-data=\"{ open: false }\">\n                    <button @click=\"open = ! open\">Toggle Nested Modal</button>\n\n                    <template x-teleport=\"#modal4\">\n                        <div class=\"pt-4\" x-show=\"open\">\n                            Nested modal contents...\n                        </div>\n                    </template>\n                </div>\n            </div>\n        </template>\n    </div>\n\n    <template x-teleport-target=\"modals3\"></template>\n</div>\n<!-- END_VERBATIM -->\n\nAfter toggling \"on\" both modals, they are authored as children, but will be rendered as sibling elements on the page, not within one another.\n","frontmatter":{"order":12,"title":"teleport","description":"Send Alpine templates to other parts of the DOM","graph_image":"https://alpinejs.dev/social_teleport.jpg"},"isInternal":false,"tokens":1310,"sizeBytes":5570},{"name":"text.md","path":"packages/docs/src/en/directives/text.md","rawUrl":"https://raw.githubusercontent.com/alpinejs/alpine/HEAD/packages/docs/src/en/directives/text.md","title":"Directives Skill","category":"anthropic-skill","format":"markdown","content":"---\norder: 6\ntitle: text\n---\n\n# x-text\n\n`x-text` sets the text content of an element to the result of a given expression.\n\nHere's a basic example of using `x-text` to display a user's username.\n\n```alpine\n<div x-data=\"{ username: 'calebporzio' }\">\n    Username: <strong x-text=\"username\"></strong>\n</div>\n```\n\n<!-- START_VERBATIM -->\n<div class=\"demo\">\n    <div x-data=\"{ username: 'calebporzio' }\">\n        Username: <strong x-text=\"username\"></strong>\n    </div>\n</div>\n<!-- END_VERBATIM -->\n\nNow the `<strong>` tag's inner text content will be set to \"calebporzio\".\n","frontmatter":{"order":6,"title":"text"},"isInternal":false,"tokens":162,"sizeBytes":569},{"name":"transition.md","path":"packages/docs/src/en/directives/transition.md","rawUrl":"https://raw.githubusercontent.com/alpinejs/alpine/HEAD/packages/docs/src/en/directives/transition.md","title":"Directives Skill","category":"anthropic-skill","format":"markdown","content":"---\norder: 10\ntitle: transition\n---\n\n# x-transition\n\nAlpine provides a robust transitions utility out of the box. With a few `x-transition` directives, you can create smooth transitions between when an element is shown or hidden.\n\nThere are two primary ways to handle transitions in Alpine:\n\n* [The Transition Helper](#the-transition-helper)\n* [Applying CSS Classes](#applying-css-classes)\n\n<a name=\"the-transition-helper\"></a>\n## The transition helper\n\nThe simplest way to achieve a transition using Alpine is by adding `x-transition` to an element with `x-show` on it. For example:\n\n```alpine\n<div x-data=\"{ open: false }\">\n    <button @click=\"open = ! open\">Toggle</button>\n\n    <div x-show=\"open\" x-transition>\n        Hello 👋\n    </div>\n</div>\n```\n\n<!-- START_VERBATIM -->\n<div class=\"demo\">\n    <div x-data=\"{ open: false }\">\n        <button @click=\"open = ! open\">Toggle</button>\n\n        <div x-show=\"open\" x-transition>\n            Hello 👋\n        </div>\n    </div>\n</div>\n<!-- END_VERBATIM -->\n\nAs you can see, by default, `x-transition` applies pleasant transition defaults to fade and scale the revealing element.\n\nYou can override these defaults with modifiers attached to `x-transition`. Let's take a look at those.\n\n<a name=\"customizing-duration\"></a>\n### Customizing duration\n\nInitially, the duration is set to be 150 milliseconds when entering, and 75 milliseconds when leaving.\n\nYou can configure the duration you want for a transition with the `.duration` modifier:\n\n```alpine\n<div ... x-transition.duration.500ms>\n```\n\nThe above `<div>` will transition for 500 milliseconds when entering, and 500 milliseconds when leaving.\n\nIf you wish to customize the durations specifically for entering and leaving, you can do that like so:\n\n```alpine\n<div ...\n    x-transition:enter.duration.500ms\n    x-transition:leave.duration.400ms\n>\n```\n\n> Despite not being included in the above snippet, `x-transition` cannot be used if no parent element has `x-data` defined. [→ Read more about `x-data`](/directives/data)\n\n<a name=\"customizing-delay\"></a>\n### Customizing delay\n\nYou can delay a transition using the `.delay` modifier like so:\n\n```alpine\n<div ... x-transition.delay.50ms>\n```\n\nThe above example will delay the transition and in and out of the element by 50 milliseconds.\n\n<a name=\"customizing-opacity\"></a>\n### Customizing opacity\n\nBy default, Alpine's `x-transition` applies both a scale and opacity transition to achieve a \"fade\" effect.\n\nIf you wish to only apply the opacity transition (no scale), you can accomplish that like so:\n\n```alpine\n<div ... x-transition.opacity>\n```\n\n<a name=\"customizing-scale\"></a>\n### Customizing scale\n\nSimilar to the `.opacity` modifier, you can configure `x-transition` to ONLY scale (and not transition opacity as well) like so:\n\n```alpine\n<div ... x-transition.scale>\n```\n\nThe `.scale` modifier also offers the ability to configure its scale values AND its origin values:\n\n```alpine\n<div ... x-transition.scale.80>\n```\n\nThe above snippet will scale the element up and down by 80%.\n\nAgain, you may customize these values separately for enter and leaving transitions like so:\n\n```alpine\n<div ...\n    x-transition:enter.scale.80\n    x-transition:leave.scale.90\n>\n```\n\nTo customize the origin of the scale transition, you can use the `.origin` modifier:\n\n```alpine\n<div ... x-transition.scale.origin.top>\n```\n\nNow the scale will be applied using the top of the element as the origin, instead of the center by default.\n\nLike you may have guessed, the possible values for this customization are: `top`, `bottom`, `left`, and `right`.\n\nIf you wish, you can also combine two origin values. For example, if you want the origin of the scale to be \"top right\", you can use: `.origin.top.right` as the modifier.\n\n\n<a name=\"applying-css-classes\"></a>\n## Applying CSS classes\n\nFor direct control over exactly what goes into your transitions, you can apply CSS classes at different stages of the transition.\n\n> The following examples use [TailwindCSS](https://tailwindcss.com/docs/transition-property) utility classes.\n\n```alpine\n<div x-data=\"{ open: false }\">\n    <button @click=\"open = ! open\">Toggle</button>\n\n    <div\n        x-show=\"open\"\n        x-transition:enter=\"transition ease-out duration-300\"\n        x-transition:enter-start=\"opacity-0 scale-90\"\n        x-transition:enter-end=\"opacity-100 scale-100\"\n        x-transition:leave=\"transition ease-in duration-300\"\n        x-transition:leave-start=\"opacity-100 scale-100\"\n        x-transition:leave-end=\"opacity-0 scale-90\"\n    >Hello 👋</div>\n</div>\n```\n\n<!-- START_VERBATIM -->\n<div class=\"demo\">\n    <div x-data=\"{ open: false }\">\n    <button @click=\"open = ! open\">Toggle</button>\n\n    <div\n        x-show=\"open\"\n        x-transition:enter=\"transition ease-out duration-300\"\n        x-transition:enter-start=\"opacity-0 transform scale-90\"\n        x-transition:enter-end=\"opacity-100 transform scale-100\"\n        x-transition:leave=\"transition ease-in duration-300\"\n        x-transition:leave-start=\"opacity-100 transform scale-100\"\n        x-transition:leave-end=\"opacity-0 transform scale-90\"\n    >Hello 👋</div>\n</div>\n</div>\n<!-- END_VERBATIM -->\n\n| Directive      | Description |\n| ---            | --- |\n| `:enter`       | Applied during the entire entering phase. |\n| `:enter-start` | Added before element is inserted, removed one frame after element is inserted. |\n| `:enter-end`   | Added one frame after element is inserted (at the same time `enter-start` is removed), removed when transition/animation finishes.\n| `:leave`       | Applied during the entire leaving phase. |\n| `:leave-start` | Added immediately when a leaving transition is triggered, removed after one frame. |\n| `:leave-end`   | Added one frame after a leaving transition is triggered (at the same time `leave-start` is removed), removed when the transition/animation finishes.\n","frontmatter":{"order":10,"title":"transition"},"isInternal":false,"tokens":1384,"sizeBytes":5873},{"name":"essentials.md","path":"packages/docs/src/en/essentials.md","rawUrl":"https://raw.githubusercontent.com/alpinejs/alpine/HEAD/packages/docs/src/en/essentials.md","title":"En Skill","category":"anthropic-skill","format":"markdown","content":"---\norder: 3\ntitle: Essentials\ntype: sub-directory\n---\n","frontmatter":{"order":3,"title":"Essentials","type":"sub-directory"},"isInternal":false,"tokens":16,"sizeBytes":55},{"name":"events.md","path":"packages/docs/src/en/essentials/events.md","rawUrl":"https://raw.githubusercontent.com/alpinejs/alpine/HEAD/packages/docs/src/en/essentials/events.md","title":"Essentials Skill","category":"anthropic-skill","format":"markdown","content":"---\norder: 4\ntitle: Events\n---\n\n# Events\n\nAlpine makes it simple to listen for browser events and react to them.\n\n<a name=\"listening-for-simple-events\"></a>\n## Listening for simple events\n\nBy using `x-on`, you can listen for browser events that are dispatched on or within an element.\n\nHere's a basic example of listening for a click on a button:\n\n```alpine\n<button x-on:click=\"console.log('clicked')\">...</button>\n```\n\nAs an alternative, you can use the event shorthand syntax if you prefer: `@`. Here's the same example as before, but using the shorthand syntax (which we'll be using from now on):\n\n```alpine\n<button @click=\"...\">...</button>\n```\n\nIn addition to `click`, you can listen for any browser event by name. For example: `@mouseenter`, `@keyup`, etc... are all valid syntax.\n\n<a name=\"listening-for-specific-keys\"></a>\n## Listening for specific keys\n\nLet's say you wanted to listen for the `enter` key to be pressed inside an `<input>` element. Alpine makes this easy by adding the `.enter` like so:\n\n```alpine\n<input @keyup.enter=\"...\">\n```\n\nYou can even combine key modifiers to listen for key combinations like pressing `enter` while holding `shift`:\n\n```alpine\n<input @keyup.shift.enter=\"...\">\n```\n\n<a name=\"preventing-default\"></a>\n## Preventing default\n\nWhen reacting to browser events, it is often necessary to \"prevent default\" (prevent the default behavior of the browser event).\n\nFor example, if you want to listen for a form submission but prevent the browser from submitting a form request, you can use `.prevent`:\n\n```alpine\n<form @submit.prevent=\"...\">...</form>\n```\n\nYou can also apply `.stop` to achieve the equivalent of `event.stopPropagation()`.\n\n<a name=\"accessing-the-event-object\"></a>\n## Accessing the event object\n\nSometimes you may want to access the native browser event object inside your own code. To make this easy, Alpine automatically injects an `$event` magic variable:\n\n```alpine\n<button @click=\"$event.target.remove()\">Remove Me</button>\n```\n\n<a name=\"dispatching-custom-events\"></a>\n## Dispatching custom events\n\nIn addition to listening for browser events, you can dispatch them as well. This is extremely useful for communicating with other Alpine components or triggering events in tools outside of Alpine itself.\n\nAlpine exposes a magic helper called `$dispatch` for this:\n\n```alpine\n<div @foo=\"console.log('foo was dispatched')\">\n    <button @click=\"$dispatch('foo')\"></button>\n</div>\n```\n\nAs you can see, when the button is clicked, Alpine will dispatch a browser event called \"foo\", and our `@foo` listener on the `<div>` will pick it up and react to it.\n\n<a name=\"listening-for-events-on-window\"></a>\n## Listening for events on window\n\nBecause of the nature of events in the browser, it is sometimes useful to listen to events on the top-level window object.\n\nThis allows you to communicate across components completely like the following example:\n\n\n```alpine\n<div x-data>\n    <button @click=\"$dispatch('foo')\"></button>\n</div>\n\n<div x-data @foo.window=\"console.log('foo was dispatched')\">...</div>\n```\n\nIn the above example, if we click the button in the first component, Alpine will dispatch the \"foo\" event. Because of the way events work in the browser, they \"bubble\" up through parent elements all the way to the top-level \"window\".\n\nNow, because in our second component we are listening for \"foo\" on the window (with `.window`), when the button is clicked, this listener will pick it up and log the \"foo was dispatched\" message.\n\n[→ Read more about x-on](/directives/on)\n","frontmatter":{"order":4,"title":"Events"},"isInternal":false,"tokens":808,"sizeBytes":3534},{"name":"installation.md","path":"packages/docs/src/en/essentials/installation.md","rawUrl":"https://raw.githubusercontent.com/alpinejs/alpine/HEAD/packages/docs/src/en/essentials/installation.md","title":"Essentials Skill","category":"anthropic-skill","format":"markdown","content":"---\norder: 1\ntitle: Installation\n---\n\n# Installation\n\nThere are 2 ways to include Alpine into your project:\n\n* Including it from a `<script>` tag\n* Importing it as a module\n\nEither is perfectly valid. It all depends on the project's needs and the developer's taste.\n\n<a name=\"from-a-script-tag\"></a>\n## From a script tag\n\nThis is by far the simplest way to get started with Alpine. Include the following `<script>` tag in the head of your HTML page.\n\n```alpine\n<html>\n    <head>\n        ...\n\n        <script defer src=\"https://cdn.jsdelivr.net/npm/alpinejs@3.x.x/dist/cdn.min.js\"></script>\n    </head>\n    ...\n</html>\n```\n\n> Don't forget the \"defer\" attribute in the `<script>` tag.\n\nNotice the `@3.x.x` in the provided CDN link. This will pull the latest version of Alpine version 3. For stability in production, it's recommended that you hardcode the latest version in the CDN link.\n\n```alpine\n<script defer src=\"https://cdn.jsdelivr.net/npm/alpinejs@3.17.5/dist/cdn.min.js\"></script>\n```\n\nThat's it! Alpine is now available for use inside your page.\n\nNote that you will still need to define a component with `x-data` in order for any Alpine.js attributes to work. See <https://github.com/alpinejs/alpine/discussions/3805> for more information.\n\n<a name=\"as-a-module\"></a>\n## As a module\n\nIf you prefer the more robust approach, you can install Alpine via NPM and import it into a bundle.\n\nRun the following command to install it.\n\n```shell\nnpm install alpinejs\n```\n\nNow import Alpine into your bundle and initialize it like so:\n\n```js\nimport Alpine from 'alpinejs'\n\nwindow.Alpine = Alpine\n\nAlpine.start()\n```\n\n> The `window.Alpine = Alpine` bit is optional, but is nice to have for freedom and flexibility. Like when tinkering with Alpine from the devtools for example.\n\n> If you imported Alpine into a bundle, you have to make sure you are registering any extension code IN BETWEEN when you import the `Alpine` global object, and when you initialize Alpine by calling `Alpine.start()`.\n\n> Ensure that `Alpine.start()` is only called once per page. Calling it more than once will result in multiple \"instances\" of Alpine running at the same time.\n\n\n[→ Read more about extending Alpine](/advanced/extending)\n","frontmatter":{"order":1,"title":"Installation"},"isInternal":false,"tokens":532,"sizeBytes":2212},{"name":"lifecycle.md","path":"packages/docs/src/en/essentials/lifecycle.md","rawUrl":"https://raw.githubusercontent.com/alpinejs/alpine/HEAD/packages/docs/src/en/essentials/lifecycle.md","title":"Essentials Skill","category":"anthropic-skill","format":"markdown","content":"---\norder: 5\ntitle: Lifecycle\n---\n\n# Lifecycle\n\nAlpine has a handful of different techniques for hooking into different parts of its lifecycle. Let's go through the most useful ones to familiarize yourself with:\n\n<a name=\"element-initialization\"></a>\n## Element initialization\n\nAnother extremely useful lifecycle hook in Alpine is the `x-init` directive.\n\n`x-init` can be added to any element on a page and will execute any JavaScript you call inside it when Alpine begins initializing that element.\n\n```alpine\n<button x-init=\"console.log('Im initing')\">\n```\n\nIn addition to the directive, Alpine will automatically call any `init()` methods stored on a data object. For example:\n\n```js\nAlpine.data('dropdown', () => ({\n    init() {\n        // I get called before the element using this data initializes.\n    }\n}))\n```\n\n<a name=\"after-a-state-change\"></a>\n## After a state change\n\nAlpine allows you to execute code when a piece of data (state) changes. It offers two different APIs for such a task: `$watch` and `x-effect`.\n\n<a name=\"watch\"></a>\n### `$watch`\n\n```alpine\n<div x-data=\"{ open: false }\" x-init=\"$watch('open', value => console.log(value))\">\n```\n\nAs you can see above, `$watch` allows you to hook into data changes using a dot-notation key. When that piece of data changes, Alpine will call the passed callback and pass it the new value. along with the old value before the change.\n\n[→ Read more about $watch](/magics/watch)\n\n<a name=\"x-effect\"></a>\n### `x-effect`\n\n`x-effect` uses the same mechanism under the hood as `$watch` but has very different usage.\n\nInstead of specifying which data key you wish to watch, `x-effect` will call the provided code and intelligently look for any Alpine data used within it. Now when one of those pieces of data changes, the `x-effect` expression will be re-run.\n\nHere's the same bit of code from the `$watch` example rewritten using `x-effect`:\n\n```alpine\n<div x-data=\"{ open: false }\" x-effect=\"console.log(open)\">\n```\n\nNow, this expression will be called right away, and re-called every time `open` is updated.\n\nThe two main behavioral differences with this approach are:\n\n1. The provided code will be run right away AND when data changes (`$watch` is \"lazy\" -- won't run until the first data change)\n2. No knowledge of the previous value. (The callback provided to `$watch` receives both the new value AND the old one)\n\n[→ Read more about x-effect](/directives/effect)\n\n<a name=\"alpine-initialization\"></a>\n## Alpine initialization\n\n<a name=\"alpine-initializing\"></a>\n### `alpine:init`\n\nEnsuring a bit of code executes after Alpine is loaded, but BEFORE it initializes itself on the page is a necessary task.\n\nThis hook allows you to register custom data, directives, magics, etc. before Alpine does its thing on a page.\n\nYou can hook into this point in the lifecycle by listening for an event that Alpine dispatches called: `alpine:init`\n\n```js\ndocument.addEventListener('alpine:init', () => {\n    Alpine.data(...)\n})\n```\n\n<a name=\"alpine-initialized\"></a>\n### `alpine:initialized`\n\nAlpine also offers a hook that you can use to execute code AFTER it's done initializing called `alpine:initialized`:\n\n```js\ndocument.addEventListener('alpine:initialized', () => {\n    //\n})\n```\n","frontmatter":{"order":5,"title":"Lifecycle"},"isInternal":false,"tokens":754,"sizeBytes":3236},{"name":"state.md","path":"packages/docs/src/en/essentials/state.md","rawUrl":"https://raw.githubusercontent.com/alpinejs/alpine/HEAD/packages/docs/src/en/essentials/state.md","title":"Essentials Skill","category":"anthropic-skill","format":"markdown","content":"---\norder: 2\ntitle: State\n---\n\n# State\n\nState (JavaScript data that Alpine watches for changes) is at the core of everything you do in Alpine. You can provide local data to a chunk of HTML, or make it globally available for use anywhere on a page using `x-data` or `Alpine.store()` respectively.\n\n<a name=\"local-state-x-data\"></a>\n## Local state\n\nAlpine allows you to declare an HTML block's state in a single `x-data` attribute without ever leaving your markup.\n\nHere's a basic example:\n\n```alpine\n<div x-data=\"{ open: false }\">\n    ...\n</div>\n```\n\nNow any other Alpine syntax on or within this element will be able to access `open`. And like you'd guess, when `open` changes for any reason, everything that depends on it will react automatically.\n\n[→ Read more about `x-data`](/directives/data)\n\n<a name=\"nesting-data\"></a>\n### Nesting data\n\nData is nestable in Alpine. For example, if you have two elements with Alpine data attached (one inside the other), you can access the parent's data from inside the child element.\n\n```alpine\n<div x-data=\"{ open: false }\">\n    <div x-data=\"{ label: 'Content:' }\">\n        <span x-text=\"label\"></span>\n        <span x-show=\"open\"></span>\n    </div>\n</div>\n```\n\nThis is similar to scoping in JavaScript itself (code within a function can access variables declared outside that function.)\n\nLike you may have guessed, if the child has a data property matching the name of a parent's property, the child property will take precedence.\n\n<a name=\"single-element-data\"></a>\n### Single-element data\n\nAlthough this may seem obvious to some, it's worth mentioning that Alpine data can be used within the same element. For example:\n\n```alpine\n<button x-data=\"{ label: 'Click Here' }\" x-text=\"label\"></button>\n```\n\n<a name=\"data-less-alpine\"></a>\n### Data-less Alpine\n\nSometimes you may want to use Alpine functionality, but don't need any reactive data. In these cases, you can opt out of passing an expression to `x-data` entirely. For example:\n\n```alpine\n<button x-data @click=\"alert('I\\'ve been clicked!')\">Click Me</button>\n```\n\n<a name=\"re-usable-data\"></a>\n### Re-usable data\n\nWhen using Alpine, you may find the need to re-use a chunk of data and/or its corresponding template.\n\nIf you are using a backend framework like Rails or Laravel, Alpine first recommends that you extract the entire block of HTML into a template partial or include.\n\nIf for some reason that isn't ideal for you or you're not in a back-end templating environment, Alpine allows you to globally register and re-use the data portion of a component using `Alpine.data(...)`.\n\n```js\nAlpine.data('dropdown', () => ({\n    open: false,\n\n    toggle() {\n        this.open = ! this.open\n    }\n}))\n```\n\nNow that you've registered the \"dropdown\" data, you can use it inside your markup in as many places as you like:\n\n```alpine\n<div x-data=\"dropdown\">\n    <button @click=\"toggle\">Expand</button>\n\n    <span x-show=\"open\">Content...</span>\n</div>\n\n<div x-data=\"dropdown\">\n    <button @click=\"toggle\">Expand</button>\n\n    <span x-show=\"open\">Some Other Content...</span>\n</div>\n```\n\n[→ Read more about using `Alpine.data()`](/globals/alpine-data)\n\n<a name=\"global-state\"></a>\n## Global state\n\nIf you wish to make some data available to every component on the page, you can do so using Alpine's \"global store\" feature.\n\nYou can register a store using `Alpine.store(...)`, and reference one with the magic `$store()` method.\n\nLet's look at a simple example. First we'll register the store globally:\n\n```js\nAlpine.store('tabs', {\n    current: 'first',\n\n    items: ['first', 'second', 'third'],\n})\n```\n\nNow we can access or modify its data from anywhere on our page:\n\n```alpine\n<div x-data>\n    <template x-for=\"tab in $store.tabs.items\">\n        ...\n    </template>\n</div>\n\n<div x-data>\n    <button @click=\"$store.tabs.current = 'first'\">First Tab</button>\n    <button @click=\"$store.tabs.current = 'second'\">Second Tab</button>\n    <button @click=\"$store.tabs.current = 'third'\">Third Tab</button>\n</div>\n```\n\n[→ Read more about `Alpine.store()`](/globals/alpine-store)\n","frontmatter":{"order":2,"title":"State"},"isInternal":false,"tokens":996,"sizeBytes":4072},{"name":"templating.md","path":"packages/docs/src/en/essentials/templating.md","rawUrl":"https://raw.githubusercontent.com/alpinejs/alpine/HEAD/packages/docs/src/en/essentials/templating.md","title":"Essentials Skill","category":"anthropic-skill","format":"markdown","content":"---\norder: 3\ntitle: Templating\n---\n\n# Templating\n\nAlpine offers a handful of useful directives for manipulating the DOM on a web page.\n\nLet's cover a few of the basic templating directives here, but be sure to look through the available directives in the sidebar for an exhaustive list.\n\n<a name=\"text-content\"></a>\n## Text content\n\nAlpine makes it easy to control the text content of an element with the `x-text` directive.\n\n```alpine\n<div x-data=\"{ title: 'Start Here' }\">\n    <h1 x-text=\"title\"></h1>\n</div>\n```\n\n<!-- START_VERBATIM -->\n<div x-data=\"{ title: 'Start Here' }\" class=\"demo\">\n    <strong x-text=\"title\"></strong>\n</div>\n<!-- END_VERBATIM -->\n\nNow, Alpine will set the text content of the `<h1>` with the value of `title` (\"Start Here\"). When `title` changes, so will the contents of `<h1>`.\n\nLike all directives in Alpine, you can use any JavaScript expression you like. For example:\n\n```alpine\n<span x-text=\"1 + 2\"></span>\n```\n\n<!-- START_VERBATIM -->\n<div class=\"demo\" x-data>\n    <span x-text=\"1 + 2\"></span>\n</div>\n<!-- END_VERBATIM -->\n\nThe `<span>` will now contain the sum of \"1\" and \"2\".\n\n[→ Read more about `x-text`](/directives/text)\n\n<a name=\"toggling-elements\"></a>\n## Toggling elements\n\nToggling elements is a common need in web pages and applications. Dropdowns, modals, dialogues, \"show-more\"s, etc... are all good examples.\n\nAlpine offers the `x-show` and `x-if` directives for toggling elements on a page.\n\n<a name=\"x-show\"></a>\n### `x-show`\n\nHere's a simple toggle component using `x-show`.\n\n```alpine\n<div x-data=\"{ open: false }\">\n    <button @click=\"open = ! open\">Expand</button>\n\n    <div x-show=\"open\">\n        Content...\n    </div>\n</div>\n```\n\n<!-- START_VERBATIM -->\n<div x-data=\"{ open: false }\" class=\"demo\">\n    <button @click=\"open = ! open\" :aria-pressed=\"open\">Expand</button>\n\n    <div x-show=\"open\">\n        Content...\n    </div>\n</div>\n<!-- END_VERBATIM -->\n\nNow the entire `<div>` containing the contents will be shown and hidden based on the value of `open`.\n\nUnder the hood, Alpine adds the CSS property `display: none;` to the element when it should be hidden.\n\n[→ Read more about `x-show`](/directives/show)\n\nThis works well for most cases, but sometimes you may want to completely add and remove the element from the DOM entirely. This is what `x-if` is for.\n\n<a name=\"x-if\"></a>\n### `x-if`\n\nHere is the same toggle from before, but this time using `x-if` instead of `x-show`.\n\n```alpine\n<div x-data=\"{ open: false }\">\n    <button @click=\"open = ! open\">Expand</button>\n\n    <template x-if=\"open\">\n        <div>\n            Content...\n        </div>\n    </template>\n</div>\n```\n\n<!-- START_VERBATIM -->\n<div x-data=\"{ open: false }\" class=\"demo\">\n    <button @click=\"open = ! open\" :aria-pressed=\"open\">Expand</button>\n\n    <template x-if=\"open\">\n        <div>\n            Content...\n        </div>\n    </template>\n</div>\n<!-- END_VERBATIM -->\n\nNotice that `x-if` must be declared on a `<template>` tag. This is so that Alpine can leverage the existing browser behavior of the `<template>` element and use it as the source of the target `<div>` to be added and removed from the page.\n\nWhen `open` is true, Alpine will append the `<div>` to the `<template>` tag, and remove it when `open` is false.\n\n[→ Read more about `x-if`](/directives/if)\n\n<a name=\"toggling-with-transitions\"></a>\n## Toggling with transitions\n\nAlpine makes it simple to smoothly transition between \"shown\" and \"hidden\" states using the `x-transition` directive.\n\n> `x-transition` only works with `x-show`, not with `x-if`.\n\nHere is, again, the simple toggle example, but this time with transitions applied:\n\n```alpine\n<div x-data=\"{ open: false }\">\n    <button @click=\"open = ! open\">Expands</button>\n\n    <div x-show=\"open\" x-transition>\n        Content...\n    </div>\n</div>\n```\n\n<!-- START_VERBATIM -->\n<div x-data=\"{ open: false }\" class=\"demo\">\n    <button @click=\"open = ! open\">Expands</button>\n\n    <div class=\"flex\">\n        <div x-show=\"open\" x-transition style=\"will-change: transform;\">\n            Content...\n        </div>\n    </div>\n</div>\n<!-- END_VERBATIM -->\n\nLet's zoom in on the portion of the template dealing with transitions:\n\n```alpine\n<div x-show=\"open\" x-transition>\n```\n\n`x-transition` by itself will apply sensible default transitions (fade and scale) to the toggle.\n\nThere are two ways to customize these transitions:\n\n* Transition helpers\n* Transition CSS classes.\n\nLet's take a look at each of these approaches:\n\n<a name=\"transition-helpers\"></a>\n### Transition helpers\n\nLet's say you wanted to make the duration of the transition longer, you can manually specify that using the `.duration` modifier like so:\n\n```alpine\n<div x-show=\"open\" x-transition.duration.500ms>\n```\n\n<!-- START_VERBATIM -->\n<div x-data=\"{ open: false }\" class=\"demo\">\n    <button @click=\"open = ! open\">Expands</button>\n\n    <div class=\"flex\">\n        <div x-show=\"open\" x-transition.duration.500ms style=\"will-change: transform;\">\n            Content...\n        </div>\n    </div>\n</div>\n<!-- END_VERBATIM -->\n\nNow the transition will last 500 milliseconds.\n\nIf you want to specify different values for in and out transitions, you can use `x-transition:enter` and `x-transition:leave`:\n\n```alpine\n<div\n    x-show=\"open\"\n    x-transition:enter.duration.500ms\n    x-transition:leave.duration.1000ms\n>\n```\n\n<!-- START_VERBATIM -->\n<div x-data=\"{ open: false }\" class=\"demo\">\n    <button @click=\"open = ! open\">Expands</button>\n\n    <div class=\"flex\">\n        <div x-show=\"open\" x-transition:enter.duration.500ms x-transition:leave.duration.1000ms style=\"will-change: transform;\">\n            Content...\n        </div>\n    </div>\n</div>\n<!-- END_VERBATIM -->\n\nAdditionally, you can add either `.opacity` or `.scale` to only transition that property. For example:\n\n```alpine\n<div x-show=\"open\" x-transition.opacity>\n```\n\n<!-- START_VERBATIM -->\n<div x-data=\"{ open: false }\" class=\"demo\">\n    <button @click=\"open = ! open\">Expands</button>\n\n    <div class=\"flex\">\n        <div x-show=\"open\" x-transition:enter.opacity.duration.500 x-transition:leave.opacity.duration.250>\n            Content...\n        </div>\n    </div>\n</div>\n<!-- END_VERBATIM -->\n\n[→ Read more about transition helpers](/directives/transition#the-transition-helper)\n\n<a name=\"transition-classes\"></a>\n### Transition classes\n\nIf you need more fine-grained control over the transitions in your application, you can apply specific CSS classes at specific phases of the transition using the following syntax (this example uses [Tailwind CSS](https://tailwindcss.com/)):\n\n```alpine\n<div\n    x-show=\"open\"\n    x-transition:enter=\"transition ease-out duration-300\"\n    x-transition:enter-start=\"opacity-0 transform scale-90\"\n    x-transition:enter-end=\"opacity-100 transform scale-100\"\n    x-transition:leave=\"transition ease-in duration-300\"\n    x-transition:leave-start=\"opacity-100 transform scale-100\"\n    x-transition:leave-end=\"opacity-0 transform scale-90\"\n>...</div>\n```\n\n<!-- START_VERBATIM -->\n<div x-data=\"{ open: false }\" class=\"demo\">\n    <button @click=\"open = ! open\">Expands</button>\n\n    <div class=\"flex\">\n        <div\n            x-show=\"open\"\n            x-transition:enter=\"transition ease-out duration-300\"\n            x-transition:enter-start=\"opacity-0 transform scale-90\"\n            x-transition:enter-end=\"opacity-100 transform scale-100\"\n            x-transition:leave=\"transition ease-in duration-300\"\n            x-transition:leave-start=\"opacity-100 transform scale-100\"\n            x-transition:leave-end=\"opacity-0 transform scale-90\"\n            style=\"will-change: transform\"\n        >\n            Content...\n        </div>\n    </div>\n</div>\n<!-- END_VERBATIM -->\n\n[→ Read more about transition classes](/directives/transition#applying-css-classes)\n\n<a name=\"binding-attributes\"></a>\n## Binding attributes\n\nYou can add HTML attributes like `class`, `style`, `disabled`, etc... to elements in Alpine using the `x-bind` directive.\n\nHere is an example of a dynamically bound `class` attribute:\n\n```alpine\n<button\n    x-data=\"{ red: false }\"\n    x-bind:class=\"red ? 'bg-red' : ''\"\n    @click=\"red = ! red\"\n>\n    Toggle Red\n</button>\n```\n\n<!-- START_VERBATIM -->\n<div class=\"demo\">\n    <button\n        x-data=\"{ red: false }\"\n        x-bind:style=\"red && 'background: red'\"\n        @click=\"red = ! red\"\n    >\n        Toggle Red\n    </button>\n</div>\n<!-- END_VERBATIM -->\n\n\nAs a shortcut, you can leave out the `x-bind` and use the shorthand `:` syntax directly:\n\n```alpine\n<button ... :class=\"red ? 'bg-red' : ''\">\n```\n\nToggling classes on and off based on data inside Alpine is a common need. Here's an example of toggling a class using Alpine's `class` binding object syntax: (Note: this syntax is only available for `class` attributes)\n\n```alpine\n<div x-data=\"{ open: true }\">\n    <span :class=\"{ 'hidden': ! open }\">...</span>\n</div>\n```\n\nNow the `hidden` class will be added to the element if `open` is false, and removed if `open` is true.\n\n<a name=\"looping-elements\"></a>\n## Looping elements\n\nAlpine allows for iterating parts of your template based on JavaScript data using the `x-for` directive. Here is a simple example:\n\n```alpine\n<div x-data=\"{ statuses: ['open', 'closed', 'archived'] }\">\n    <template x-for=\"status in statuses\">\n        <div x-text=\"status\"></div>\n    </template>\n</div>\n```\n\n<!-- START_VERBATIM -->\n<div x-data=\"{ statuses: ['open', 'closed', 'archived'] }\" class=\"demo\">\n    <template x-for=\"status in statuses\">\n        <div x-text=\"status\"></div>\n    </template>\n</div>\n<!-- END_VERBATIM -->\n\nSimilar to `x-if`, `x-for` must be applied to a `<template>` tag. Internally, Alpine will append the contents of `<template>` tag for every iteration in the loop.\n\nAs you can see the new `status` variable is available in the scope of the iterated templates.\n\n[→ Read more about `x-for`](/directives/for)\n\n<a name=\"inner-html\"></a>\n## Inner HTML\n\nAlpine makes it easy to control the HTML content of an element with the `x-html` directive.\n\n```alpine\n<div x-data=\"{ title: '<h1>Start Here</h1>' }\">\n    <div x-html=\"title\"></div>\n</div>\n```\n\n<!-- START_VERBATIM -->\n<div x-data=\"{ title: '<h1>Start Here</h1>' }\" class=\"demo\">\n    <div x-html=\"title\"></div>\n</div>\n<!-- END_VERBATIM -->\n\nNow, Alpine will set the text content of the `<div>` with the element `<h1>Start Here</h1>`. When `title` changes, so will the contents of `<h1>`.\n\n> ⚠️ Only use on trusted content and never on user-provided content. ⚠️\n> Dynamically rendering HTML from third parties can easily lead to XSS vulnerabilities.\n\n[→ Read more about `x-html`](/directives/html)\n","frontmatter":{"order":3,"title":"Templating"},"isInternal":false,"tokens":2740,"sizeBytes":10611},{"name":"globals.md","path":"packages/docs/src/en/globals.md","rawUrl":"https://raw.githubusercontent.com/alpinejs/alpine/HEAD/packages/docs/src/en/globals.md","title":"En Skill","category":"anthropic-skill","format":"markdown","content":"---\norder: 6\ntitle: Globals\nfont-type: mono\nprefix: Alpine.\ntype: sub-directory\n---\n","frontmatter":{"order":6,"title":"Globals","font-type":"mono","prefix":"Alpine.","type":"sub-directory"},"isInternal":false,"tokens":25,"sizeBytes":84},{"name":"alpine-bind.md","path":"packages/docs/src/en/globals/alpine-bind.md","rawUrl":"https://raw.githubusercontent.com/alpinejs/alpine/HEAD/packages/docs/src/en/globals/alpine-bind.md","title":"Globals Skill","category":"anthropic-skill","format":"markdown","content":"---\norder: 3\ntitle: bind()\n---\n\n# Alpine.bind\n\n`Alpine.bind(...)` provides a way to re-use [`x-bind`](/directives/bind#bind-directives) objects within your application.\n\nHere's a simple example. Rather than binding attributes manually with Alpine:\n\n```alpine\n<button type=\"button\" @click=\"doSomething()\" :disabled=\"shouldDisable\"></button>\n```\n\nYou can bundle these attributes up into a reusable object and use `x-bind` to bind to that:\n\n```alpine\n<button x-bind=\"SomeButton\"></button>\n\n<script>\n    document.addEventListener('alpine:init', () => {\n        Alpine.bind('SomeButton', () => ({\n            type: 'button',\n\n            '@click'() {\n                this.doSomething()\n            },\n\n            ':disabled'() {\n                return this.shouldDisable\n            },\n        }))\n    })\n</script>\n```\n","frontmatter":{"order":3,"title":"bind()"},"isInternal":false,"tokens":183,"sizeBytes":815},{"name":"alpine-data.md","path":"packages/docs/src/en/globals/alpine-data.md","rawUrl":"https://raw.githubusercontent.com/alpinejs/alpine/HEAD/packages/docs/src/en/globals/alpine-data.md","title":"Globals Skill","category":"anthropic-skill","format":"markdown","content":"---\norder: 1\ntitle: data()\n---\n\n# Alpine.data\n\n`Alpine.data(...)` provides a way to re-use `x-data` contexts within your application.\n\nHere's a contrived `dropdown` component for example:\n\n```alpine\n<div x-data=\"dropdown\">\n    <button @click=\"toggle\">...</button>\n\n    <div x-show=\"open\">...</div>\n</div>\n\n<script>\n    document.addEventListener('alpine:init', () => {\n        Alpine.data('dropdown', () => ({\n            open: false,\n\n            toggle() {\n                this.open = ! this.open\n            }\n        }))\n    })\n</script>\n```\n\nAs you can see we've extracted the properties and methods we would usually define directly inside `x-data` into a separate Alpine component object.\n\n<a name=\"registering-from-a-bundle\"></a>\n## Registering from a bundle\n\nIf you've chosen to use a build step for your Alpine code, you should register your components in the following way:\n\n```js\nimport Alpine from 'alpinejs'\nimport dropdown from './dropdown.js'\n\nAlpine.data('dropdown', dropdown)\n\nAlpine.start()\n```\n\nThis assumes you have a file called `dropdown.js` with the following contents:\n\n```js\nexport default () => ({\n    open: false,\n\n    toggle() {\n        this.open = ! this.open\n    }\n})\n```\n\n<a name=\"initial-parameters\"></a>\n## Initial parameters\n\nIn addition to referencing `Alpine.data` providers by their name plainly (like `x-data=\"dropdown\"`), you can also reference them as functions (`x-data=\"dropdown()\"`). By calling them as functions directly, you can pass in additional parameters to be used when creating the initial data object like so:\n\n```alpine\n<div x-data=\"dropdown(true)\">\n```\n```js\nAlpine.data('dropdown', (initialOpenState = false) => ({\n    open: initialOpenState\n}))\n```\n\nNow, you can re-use the `dropdown` object, but provide it with different parameters as you need to.\n\n<a name=\"init-functions\"></a>\n## Init functions\n\nIf your component contains an `init()` method, Alpine will automatically execute it before it renders the component. For example:\n\n```js\nAlpine.data('dropdown', () => ({\n    init() {\n        // This code will be executed before Alpine\n        // initializes the rest of the component.\n    }\n}))\n```\n\n<a name=\"destroy-functions\"></a>\n## Destroy functions\n\nIf your component contains a `destroy()` method, Alpine will automatically execute it before cleaning up the component.\n\nA primary example for this is when registering an event handler with another library or a browser API that isn't available through Alpine.\nSee the following example code on how to use the `destroy()` method to clean up such a handler.\n\n```js\nAlpine.data('timer', () => ({\n    timer: null,\n    counter: 0,\n    init() {\n      // Register an event handler that references the component instance\n      this.timer = setInterval(() => {\n        console.log('Increased counter to', ++this.counter);\n      }, 1000);\n    },\n    destroy() {\n        // Detach the handler, avoiding memory and side-effect leakage\n        clearInterval(this.timer);\n    },\n}))\n```\n\nAn example where a component is destroyed is when using one inside an `x-if`:\n\n```html\n<span x-data=\"{ enabled: false }\">\n    <button @click.prevent=\"enabled = !enabled\">Toggle</button>\n\n    <template x-if=\"enabled\">\n        <span x-data=\"timer\" x-text=\"counter\"></span>\n    </template>\n</span>\n```\n\n<a name=\"using-magic-properties\"></a>\n## Using magic properties\n\nIf you want to access magic methods or properties from a component object, you can do so using the `this` context:\n\n```js\nAlpine.data('dropdown', () => ({\n    open: false,\n\n    init() {\n        this.$watch('open', () => {...})\n    }\n}))\n```\n\n<a name=\"encapsulating-directives-with-x-bind\"></a>\n## Encapsulating directives with `x-bind`\n\nIf you wish to re-use more than just the data object of a component, you can encapsulate entire Alpine template directives using `x-bind`.\n\nThe following is an example of extracting the templating details of our previous dropdown component using `x-bind`:\n\n```alpine\n<div x-data=\"dropdown\">\n    <button x-bind=\"trigger\"></button>\n\n    <div x-bind=\"dialogue\"></div>\n</div>\n```\n\n```js\nAlpine.data('dropdown', () => ({\n    open: false,\n\n    trigger: {\n        ['@click']() {\n            this.open = ! this.open\n        },\n    },\n\n    dialogue: {\n        ['x-show']() {\n            return this.open\n        },\n    },\n}))\n```\n","frontmatter":{"order":1,"title":"data()"},"isInternal":false,"tokens":1000,"sizeBytes":4307},{"name":"alpine-store.md","path":"packages/docs/src/en/globals/alpine-store.md","rawUrl":"https://raw.githubusercontent.com/alpinejs/alpine/HEAD/packages/docs/src/en/globals/alpine-store.md","title":"Globals Skill","category":"anthropic-skill","format":"markdown","content":"---\norder: 2\ntitle: store()\n---\n\n# Alpine.store\n\nAlpine offers global state management through the `Alpine.store()` API.\n\n<a name=\"registering-a-store\"></a>\n## Registering A Store\n\nYou can either define an Alpine store inside of an `alpine:init` listener (in the case of including Alpine via a `<script>` tag), OR you can define it before manually calling `Alpine.start()` (in the case of importing Alpine into a build):\n\n**From a script tag:**\n```alpine\n<script>\n    document.addEventListener('alpine:init', () => {\n        Alpine.store('darkMode', {\n            on: false,\n\n            toggle() {\n                this.on = ! this.on\n            }\n        })\n    })\n</script>\n```\n\n**From a bundle:**\n```js\nimport Alpine from 'alpinejs'\n\nAlpine.store('darkMode', {\n    on: false,\n\n    toggle() {\n        this.on = ! this.on\n    }\n})\n\nAlpine.start()\n```\n\n<a name=\"accessing stores\"></a>\n## Accessing stores\n\nYou can access data from any store within Alpine expressions using the `$store` magic property:\n\n```alpine\n<div x-data :class=\"$store.darkMode.on && 'bg-black'\">...</div>\n```\n\nYou can also modify properties within the store and everything that depends on those properties will automatically react. For example:\n\n```alpine\n<button x-data @click=\"$store.darkMode.toggle()\">Toggle Dark Mode</button>\n```\n\nAdditionally, you can access a store externally using `Alpine.store()` by omitting the second parameter like so:\n\n```alpine\n<script>\n    Alpine.store('darkMode').toggle()\n</script>\n```\n\n<a name=\"initializing-stores\"></a>\n## Initializing stores\n\nIf you provide `init()` method in an Alpine store, it will be executed right after the store is registered. This is useful for initializing any state inside the store with sensible starting values.\n\n```alpine\n<script>\n    document.addEventListener('alpine:init', () => {\n        Alpine.store('darkMode', {\n            init() {\n                this.on = window.matchMedia('(prefers-color-scheme: dark)').matches\n            },\n\n            on: false,\n\n            toggle() {\n                this.on = ! this.on\n            }\n        })\n    })\n</script>\n```\n\nNotice the newly added `init()` method in the example above. With this addition, the `on` store variable will be set to the browser's color scheme preference before Alpine renders anything on the page.\n\n<a name=\"single-value-stores\"></a>\n## Single-value stores\n\nIf you don't need an entire object for a store, you can set and use any kind of data as a store.\n\nHere's the example from above but using it more simply as a boolean value:\n\n```alpine\n<button x-data @click=\"$store.darkMode = ! $store.darkMode\">Toggle Dark Mode</button>\n\n...\n\n<div x-data :class=\"$store.darkMode && 'bg-black'\">\n    ...\n</div>\n\n\n<script>\n    document.addEventListener('alpine:init', () => {\n        Alpine.store('darkMode', false)\n    })\n</script>\n```\n","frontmatter":{"order":2,"title":"store()"},"isInternal":false,"tokens":658,"sizeBytes":2841},{"name":"magics.md","path":"packages/docs/src/en/magics.md","rawUrl":"https://raw.githubusercontent.com/alpinejs/alpine/HEAD/packages/docs/src/en/magics.md","title":"En Skill","category":"anthropic-skill","format":"markdown","content":"---\norder: 5\ntitle: Magics\nprefix: $\nfont-type: mono\ntype: sub-directory\n---\n","frontmatter":{"order":5,"title":"Magics","prefix":"$","font-type":"mono","type":"sub-directory"},"isInternal":false,"tokens":25,"sizeBytes":77},{"name":"data.md","path":"packages/docs/src/en/magics/data.md","rawUrl":"https://raw.githubusercontent.com/alpinejs/alpine/HEAD/packages/docs/src/en/magics/data.md","title":"Magics Skill","category":"anthropic-skill","format":"markdown","content":"---\norder: 8\nprefix: $\ntitle: data\n---\n\n# $data\n\n`$data` is a magic property that gives you access to the current Alpine data scope (generally provided by `x-data`).\n\nMost of the time, you can just access Alpine data within expressions directly. for example `x-data=\"{ message: 'Hello Caleb!' }\"` will allow you to do things like `x-text=\"message\"`.\n\nHowever, sometimes it is helpful to have an actual object that encapsulates all scope that you can pass around to other functions:\n\n```alpine\n<div x-data=\"{ greeting: 'Hello' }\">\n    <div x-data=\"{ name: 'Caleb' }\">\n        <button @click=\"sayHello($data)\">Say Hello</button>\n    </div>\n</div>\n\n<script>\n    function sayHello({ greeting, name }) {\n        alert(greeting + ' ' + name + '!')\n    }\n</script>\n```\n\n<!-- START_VERBATIM -->\n<div x-data=\"{ greeting: 'Hello' }\" class=\"demo\">\n    <div x-data=\"{ name: 'Caleb' }\">\n        <button @click=\"sayHello($data)\">Say Hello</button>\n    </div>\n</div>\n\n<script>\n    function sayHello({ greeting, name }) {\n        alert(greeting + ' ' + name + '!')\n    }\n</script>\n<!-- END_VERBATIM -->\n\nNow when the button is pressed, the browser will alert `Hello Caleb!` because it was passed a data object that contained all the Alpine scope of the expression that called it (`@click=\"...\"`).\n\nMost applications won't need this magic property, but it can be very helpful for deeper, more complicated Alpine utilities.\n","frontmatter":{"order":8,"prefix":"$","title":"data"},"isInternal":false,"tokens":355,"sizeBytes":1406},{"name":"dispatch.md","path":"packages/docs/src/en/magics/dispatch.md","rawUrl":"https://raw.githubusercontent.com/alpinejs/alpine/HEAD/packages/docs/src/en/magics/dispatch.md","title":"Magics Skill","category":"anthropic-skill","format":"markdown","content":"---\norder: 5\ntitle: dispatch\n---\n\n# $dispatch\n\n`$dispatch` is a helpful shortcut for dispatching browser events.\n\n```alpine\n<div @notify=\"alert('Hello World!')\">\n    <button @click=\"$dispatch('notify')\">\n        Notify\n    </button>\n</div>\n```\n\n<!-- START_VERBATIM -->\n<div class=\"demo\">\n    <div x-data @notify=\"alert('Hello World!')\">\n        <button @click=\"$dispatch('notify')\">\n            Notify\n        </button>\n    </div>\n</div>\n<!-- END_VERBATIM -->\n\nYou can also pass data along with the dispatched event if you wish. This data will be accessible as the `.detail` property of the event:\n\n```alpine\n<div @notify=\"alert($event.detail.message)\">\n    <button @click=\"$dispatch('notify', { message: 'Hello World!' })\">\n        Notify\n    </button>\n</div>\n```\n\n<!-- START_VERBATIM -->\n<div class=\"demo\">\n    <div x-data @notify=\"alert($event.detail.message)\">\n        <button @click=\"$dispatch('notify', { message: 'Hello World!' })\">Notify</button>\n    </div>\n</div>\n<!-- END_VERBATIM -->\n\n\nUnder the hood, `$dispatch` is a wrapper for the more verbose API: `element.dispatchEvent(new CustomEvent(...))`\n\n**Note on event propagation**\n\nNotice that, because of [event bubbling](https://en.wikipedia.org/wiki/Event_bubbling), when you need to capture events dispatched from nodes that are under the same nesting hierarchy, you'll need to use the [`.window`](https://github.com/alpinejs/alpine#x-on) modifier:\n\n**Example:**\n\n```alpine\n<!-- 🚫 Won't work -->\n<div x-data>\n    <span @notify=\"...\"></span>\n    <button @click=\"$dispatch('notify')\">Notify</button>\n</div>\n\n<!-- ✅ Will work (because of .window) -->\n<div x-data>\n    <span @notify.window=\"...\"></span>\n    <button @click=\"$dispatch('notify')\">Notify</button>\n</div>\n```\n\n> The first example won't work because when `notify` is dispatched, it'll propagate to its common ancestor, the `div`, not its sibling, the `<span>`. The second example will work because the sibling is listening for `notify` at the `window` level, which the custom event will eventually bubble up to.\n\n<a name=\"dispatching-to-components\"></a>\n## Dispatching to other components\n\nYou can also take advantage of the previous technique to make your components talk to each other:\n\n**Example:**\n\n```alpine\n<div\n    x-data=\"{ title: 'Hello' }\"\n    @set-title.window=\"title = $event.detail\"\n>\n    <h1 x-text=\"title\"></h1>\n</div>\n\n<div x-data>\n    <button @click=\"$dispatch('set-title', 'Hello World!')\">Click me</button>\n</div>\n<!-- When clicked, the content of the h1 will set to \"Hello World!\". -->\n```\n\n<a name=\"dispatching-to-x-model\"></a>\n## Dispatching to x-model\n\nYou can also use `$dispatch()` to trigger data updates for `x-model` data bindings. For example:\n\n```alpine\n<div x-data=\"{ title: 'Hello' }\">\n    <span x-model=\"title\">\n        <button @click=\"$dispatch('input', 'Hello World!')\">Click me</button>\n        <!-- After the button is pressed, `x-model` will catch the bubbling \"input\" event, and update title. -->\n    </span>\n</div>\n```\n\nThis opens up the door for making custom input components whose value can be set via `x-model`.\n\n<a name=\"cancelable-events\"></a>\n## Cancelable events\n\nYou can use the returned value of `$dispatch` to check if the event was canceled or not. This is useful when you want to prevent the default behavior of an action.\n\n```alpine\n<div x-data x-on:open=\"$event.preventDefault()\">\n    <div x-data=\"{ open: false }\">\n        <button @click=\"if($dispatch('open')){ open = true; }\">Click me</button>\n        <!-- When the button is pressed an event is dispatched and only if the result is truthy (not prevented by any handler) the content will be shown. -->\n        \n        <div x-show=\"open\">\n            <h1>Hello</h1>\n        </div>\n    </div>\n</div>\n```\n\nThis could be useful when you want to prevent opening/closing a modal or something like that by using event handlers.\n\n<a name=\"overwriting-options\"></a>\n## Overwriting options\n\nYou can use the third parameter of `$dispatch` to overwrite the default options of the event. For example, you can set `bubbles` to `false`:\n\n```alpine\n<!-- 🚫 Won't work because the event is being listened on the parent element -->\n<div x-data=\"{ title: 'Hello' }\" x-on:update-title=\"title = $event.detail\">\n    <button @click=\"$dispatch('update-title', 'Hello World!', {bubbles: false})\">Click me</button>\n</div>\n\n<!-- ✅ Will work because the event is being listened on the same element -->\n<div x-data=\"{ title: 'Hello' }\">\n    <button x-on:update-title=\"title = $event.detail\" @click=\"$dispatch('update-title', 'Hello World!', {bubbles: false})\">Click me</button>\n</div>\n```\n\nThis is useful when you want to prevent the event from bubbling up to the parent elements.\n","frontmatter":{"order":5,"title":"dispatch"},"isInternal":false,"tokens":1182,"sizeBytes":4692},{"name":"el.md","path":"packages/docs/src/en/magics/el.md","rawUrl":"https://raw.githubusercontent.com/alpinejs/alpine/HEAD/packages/docs/src/en/magics/el.md","title":"Magics Skill","category":"anthropic-skill","format":"markdown","content":"---\norder: 1\nprefix: $\ntitle: el\n---\n\n# $el\n\n`$el` is a magic property that can be used to retrieve the current DOM node.\n\n```alpine\n<button @click=\"$el.innerHTML = 'Hello World!'\">Replace me with \"Hello World!\"</button>\n```\n\n<!-- START_VERBATIM -->\n<div class=\"demo\">\n    <div x-data>\n        <button @click=\"$el.textContent = 'Hello World!'\">Replace me with \"Hello World!\"</button>\n    </div>\n</div>\n<!-- END_VERBATIM -->\n","frontmatter":{"order":1,"prefix":"$","title":"el"},"isInternal":false,"tokens":119,"sizeBytes":424},{"name":"id.md","path":"packages/docs/src/en/magics/id.md","rawUrl":"https://raw.githubusercontent.com/alpinejs/alpine/HEAD/packages/docs/src/en/magics/id.md","title":"Magics Skill","category":"anthropic-skill","format":"markdown","content":"---\norder: 9\nprefix: $\ntitle: id\n---\n\n# $id\n\n`$id` is a magic property that can be used to generate an element's ID and ensure that it won't conflict with other IDs of the same name on the same page.\n\nThis utility is extremely helpful when building re-usable components (presumably in a back-end template) that might occur multiple times on a page, and make use of ID attributes.\n\nThings like input components, modals, listboxes, etc. will all benefit from this utility.\n\n<a name=\"basic-usage\"></a>\n## Basic usage\n\nSuppose you have two input elements on a page, and you want them to have a unique ID from each other, you can do the following:\n\n```alpine\n<input type=\"text\" :id=\"$id('text-input')\">\n<!-- id=\"text-input-1\" -->\n\n<input type=\"text\" :id=\"$id('text-input')\">\n<!-- id=\"text-input-2\" -->\n```\n\nAs you can see, `$id` takes in a string and spits out an appended suffix that is unique on the page.\n\n<a name=\"groups-with-x-id\"></a>\n## Grouping with x-id\n\nNow let's say you want to have those same two input elements, but this time you want `<label>` elements for each of them.\n\nThis presents a problem, you now need to be able to reference the same ID twice. One for the `<label>`'s `for` attribute, and the other for the `id` on the input.\n\nHere is a way that you might think to accomplish this and is totally valid:\n\n```alpine\n<div x-data=\"{ id: $id('text-input') }\">\n    <label :for=\"id\"> <!-- \"text-input-1\" -->\n    <input type=\"text\" :id=\"id\"> <!-- \"text-input-1\" -->\n</div>\n\n<div x-data=\"{ id: $id('text-input') }\">\n    <label :for=\"id\"> <!-- \"text-input-2\" -->\n    <input type=\"text\" :id=\"id\"> <!-- \"text-input-2\" -->\n</div>\n```\n\nThis approach is fine, however, having to name and store the ID in your component scope feels cumbersome.\n\nTo accomplish this same task in a more flexible way, you can use Alpine's `x-id` directive to declare an \"id scope\" for a set of IDs:\n\n```alpine\n<div x-id=\"['text-input']\">\n    <label :for=\"$id('text-input')\"> <!-- \"text-input-1\" -->\n    <input type=\"text\" :id=\"$id('text-input')\"> <!-- \"text-input-1\" -->\n</div>\n\n<div x-id=\"['text-input']\">\n    <label :for=\"$id('text-input')\"> <!-- \"text-input-2\" -->\n    <input type=\"text\" :id=\"$id('text-input')\"> <!-- \"text-input-2\" -->\n</div>\n```\n\nAs you can see, `x-id` accepts an array of ID names. Now any usages of `$id()` within that scope, will all use the same ID. Think of them as \"id groups\".\n\n<a name=\"nesting\"></a>\n## Nesting\n\nAs you might have intuited, you can freely nest these `x-id` groups, like so:\n\n```alpine\n<div x-id=\"['text-input']\">\n    <label :for=\"$id('text-input')\"> <!-- \"text-input-1\" -->\n    <input type=\"text\" :id=\"$id('text-input')\"> <!-- \"text-input-1\" -->\n\n    <div x-id=\"['text-input']\">\n        <label :for=\"$id('text-input')\"> <!-- \"text-input-2\" -->\n        <input type=\"text\" :id=\"$id('text-input')\"> <!-- \"text-input-2\" -->\n    </div>\n</div>\n```\n\n<a name=\"keyed-ids\"></a>\n## Keyed IDs (For Looping)\n\nSometimes, it is helpful to specify an additional suffix on the end of an ID for the purpose of identifying it within a loop.\n\nFor this, `$id()` accepts an optional second parameter that will be added as a suffix on the end of the generated ID.\n\nA common example of this need is something like a listbox component that uses the `aria-activedescendant` attribute to tell assistive technologies which element is \"active\" in the list:\n\n```alpine\n<ul\n    x-id=\"['list-item']\"\n    :aria-activedescendant=\"$id('list-item', activeItem.id)\"\n>\n    <template x-for=\"item in items\" :key=\"item.id\">\n        <li :id=\"$id('list-item', item.id)\">...</li>\n    </template>\n</ul>\n```\n\nThis is an incomplete example of a listbox, but it should still be helpful to demonstrate a scenario where you might need each ID in a group to still be unique to the page, but also be keyed within a loop so that you can reference individual IDs within that group.\n","frontmatter":{"order":9,"prefix":"$","title":"id"},"isInternal":false,"tokens":1053,"sizeBytes":3857},{"name":"nextTick.md","path":"packages/docs/src/en/magics/nextTick.md","rawUrl":"https://raw.githubusercontent.com/alpinejs/alpine/HEAD/packages/docs/src/en/magics/nextTick.md","title":"Magics Skill","category":"anthropic-skill","format":"markdown","content":"---\norder: 6\nprefix: $\ntitle: nextTick\n---\n\n# $nextTick\n\n`$nextTick` is a magic property that allows you to only execute a given expression AFTER Alpine has made its reactive DOM updates. This is useful for times you want to interact with the DOM state AFTER it's reflected any data updates you've made.\n\n```alpine\n<div x-data=\"{ title: 'Hello' }\">\n    <button\n        @click=\"\n            title = 'Hello World!';\n            $nextTick(() => { console.log($el.innerText) });\n        \"\n        x-text=\"title\"\n    ></button>\n</div>\n```\n\nIn the above example, rather than logging \"Hello\" to the console, \"Hello World!\" will be logged because `$nextTick` was used to wait until Alpine was finished updating the DOM.\n\n<a name=\"promises\"></a>\n\n## Promises\n\n`$nextTick` returns a promise, allowing the use of `$nextTick` to pause an async function until after pending dom updates. When used like this, `$nextTick` also does not require an argument to be passed.\n\n```alpine\n<div x-data=\"{ title: 'Hello' }\">\n    <button\n        @click=\"\n            title = 'Hello World!';\n            await $nextTick();\n            console.log($el.innerText);\n        \"\n        x-text=\"title\"\n    ></button>\n</div>\n```\n","frontmatter":{"order":6,"prefix":"$","title":"nextTick"},"isInternal":false,"tokens":290,"sizeBytes":1195},{"name":"refs.md","path":"packages/docs/src/en/magics/refs.md","rawUrl":"https://raw.githubusercontent.com/alpinejs/alpine/HEAD/packages/docs/src/en/magics/refs.md","title":"Magics Skill","category":"anthropic-skill","format":"markdown","content":"---\norder: 2\nprefix: $\ntitle: refs\n---\n\n# $refs\n\n`$refs` is a magic property that can be used to retrieve DOM elements marked with `x-ref` inside the component. This is useful when you need to manually manipulate DOM elements. It's often used as a more succinct, scoped, alternative to `document.querySelector`.\n\n```alpine\n<button @click=\"$refs.text.remove()\">Remove Text</button>\n\n<span x-ref=\"text\">Hello 👋</span>\n```\n\n<!-- START_VERBATIM -->\n<div class=\"demo\">\n    <div x-data>\n        <button @click=\"$refs.text.remove()\">Remove Text</button>\n\n        <div class=\"pt-4\" x-ref=\"text\">Hello 👋</div>\n    </div>\n</div>\n<!-- END_VERBATIM -->\n\nNow, when the `<button>` is pressed, the `<span>` will be removed.\n\n<a name=\"limitations\"></a>\n### Limitations\n\nIn V2 it was possible to bind `$refs` to elements dynamically, like seen below:\n\n```alpine\n<template x-for=\"item in items\" :key=\"item.id\" >\n    <div :x-ref=\"item.name\">\n    some content ...\n    </div>\n</template>\n```\n\nHowever, in V3, `$refs` can only be accessed for elements that are created statically. So for the example above: if you were expecting the value of `item.name` inside of `$refs` to be something like *Batteries*, you should be aware that `$refs` will actually contain the literal string `'item.name'` and not *Batteries*.\n","frontmatter":{"order":2,"prefix":"$","title":"refs"},"isInternal":false,"tokens":338,"sizeBytes":1299},{"name":"root.md","path":"packages/docs/src/en/magics/root.md","rawUrl":"https://raw.githubusercontent.com/alpinejs/alpine/HEAD/packages/docs/src/en/magics/root.md","title":"Magics Skill","category":"anthropic-skill","format":"markdown","content":"---\norder: 7\nprefix: $\ntitle: root\n---\n\n# $root\n\n`$root` is a magic property that can be used to retrieve the root element of any Alpine component. In other words the closest element up the DOM tree that contains `x-data`.\n\n```alpine\n<div x-data data-message=\"Hello World!\">\n    <button @click=\"alert($root.dataset.message)\">Say Hi</button>\n</div>\n```\n\n<!-- START_VERBATIM -->\n<div x-data data-message=\"Hello World!\" class=\"demo\">\n    <button @click=\"alert($root.dataset.message)\">Say Hi</button>\n</div>\n<!-- END_VERBATIM -->\n","frontmatter":{"order":7,"prefix":"$","title":"root"},"isInternal":false,"tokens":137,"sizeBytes":526},{"name":"store.md","path":"packages/docs/src/en/magics/store.md","rawUrl":"https://raw.githubusercontent.com/alpinejs/alpine/HEAD/packages/docs/src/en/magics/store.md","title":"Magics Skill","category":"anthropic-skill","format":"markdown","content":"---\norder: 3\nprefix: $\ntitle: store\n---\n\n# $store\n\nYou can use `$store` to conveniently access global Alpine stores registered using [`Alpine.store(...)`](/globals/alpine-store). For example:\n\n```alpine\n<button x-data @click=\"$store.darkMode.toggle()\">Toggle Dark Mode</button>\n\n...\n\n<div x-data :class=\"$store.darkMode.on && 'bg-black'\">\n    ...\n</div>\n\n\n<script>\n    document.addEventListener('alpine:init', () => {\n        Alpine.store('darkMode', {\n            on: false,\n\n            toggle() {\n                this.on = ! this.on\n            }\n        })\n    })\n</script>\n```\n\nGiven that we've registered the `darkMode` store and set `on` to \"false\", when the `<button>` is pressed, `on` will be \"true\" and the background color of the page will change to black.\n\n<a name=\"single-value-stores\"></a>\n## Single-value stores\n\nIf you don't need an entire object for a store, you can set and use any kind of data as a store.\n\nHere's the example from above but using it more simply as a boolean value:\n\n```alpine\n<button x-data @click=\"$store.darkMode = ! $store.darkMode\">Toggle Dark Mode</button>\n\n...\n\n<div x-data :class=\"$store.darkMode && 'bg-black'\">\n    ...\n</div>\n\n\n<script>\n    document.addEventListener('alpine:init', () => {\n        Alpine.store('darkMode', false)\n    })\n</script>\n```\n\n[→ Read more about Alpine stores](/globals/alpine-store)\n","frontmatter":{"order":3,"prefix":"$","title":"store"},"isInternal":false,"tokens":334,"sizeBytes":1356},{"name":"watch.md","path":"packages/docs/src/en/magics/watch.md","rawUrl":"https://raw.githubusercontent.com/alpinejs/alpine/HEAD/packages/docs/src/en/magics/watch.md","title":"Magics Skill","category":"anthropic-skill","format":"markdown","content":"---\norder: 4\ntitle: watch\n---\n\n# $watch\n\nYou can \"watch\" a component property using the `$watch` magic method. For example:\n\n```alpine\n<div x-data=\"{ open: false }\" x-init=\"$watch('open', value => console.log(value))\">\n    <button @click=\"open = ! open\">Toggle Open</button>\n</div>\n```\n\nIn the above example, when the button is pressed and `open` is changed, the provided callback will fire and `console.log` the new value:\n\nYou can watch deeply nested properties using \"dot\" notation\n\n```alpine\n<div x-data=\"{ foo: { bar: 'baz' }}\" x-init=\"$watch('foo.bar', value => console.log(value))\">\n    <button @click=\"foo.bar = 'bob'\">Toggle Open</button>\n</div>\n```\n\nWhen the `<button>` is pressed, `foo.bar` will be set to \"bob\", and \"bob\" will be logged to the console.\n\n<a name=\"getting-the-old-value\"></a>\n### Getting the \"old\" value\n\n`$watch` keeps track of the previous value of the property being watched, You can access it using the optional second argument to the callback like so:\n\n```alpine\n<div x-data=\"{ open: false }\" x-init=\"$watch('open', (value, oldValue) => console.log(value, oldValue))\">\n    <button @click=\"open = ! open\">Toggle Open</button>\n</div>\n```\n\n<a name=\"deep-watching\"></a>\n### Deep watching\n\n`$watch` automatically watches from changes at any level but you should keep in mind that, when a change is detected, the watcher will return the value of the observed property, not the value of the subproperty that has changed.\n\n```alpine\n<div x-data=\"{ foo: { bar: 'baz' }}\" x-init=\"$watch('foo', (value, oldValue) => console.log(value, oldValue))\">\n    <button @click=\"foo.bar = 'bob'\">Update</button>\n</div>\n```\n\nWhen the `<button>` is pressed, `foo.bar` will be set to \"bob\", and \"{bar: 'bob'} {bar: 'baz'}\" will be logged to the console (new and old value).\n\n> ⚠️ Changing a property of a \"watched\" object as a side effect of the `$watch` callback will generate an infinite loop and eventually error. \n\n```alpine\n<!-- 🚫 Infinite loop -->\n<div x-data=\"{ foo: { bar: 'baz', bob: 'lob' }}\" x-init=\"$watch('foo', value => foo.bob = foo.bar)\">\n    <button @click=\"foo.bar = 'bob'\">Update</button>\n</div>\n```\n","frontmatter":{"order":4,"title":"watch"},"isInternal":false,"tokens":579,"sizeBytes":2133},{"name":"plugins.md","path":"packages/docs/src/en/plugins.md","rawUrl":"https://raw.githubusercontent.com/alpinejs/alpine/HEAD/packages/docs/src/en/plugins.md","title":"En Skill","category":"anthropic-skill","format":"markdown","content":"---\norder: 7\ntitle: Plugins\nfont-type: mono\ntype: sub-directory\n---\n","frontmatter":{"order":7,"title":"Plugins","font-type":"mono","type":"sub-directory"},"isInternal":false,"tokens":21,"sizeBytes":68},{"name":"anchor.md","path":"packages/docs/src/en/plugins/anchor.md","rawUrl":"https://raw.githubusercontent.com/alpinejs/alpine/HEAD/packages/docs/src/en/plugins/anchor.md","title":"Plugins Skill","category":"anthropic-skill","format":"markdown","content":"---\norder: 7\ntitle: Anchor\ndescription: Anchor an element's positioning to another element on the page\ngraph_image: https://alpinejs.dev/social_anchor.jpg\n---\n\n# Anchor Plugin\n\nAlpine's Anchor plugin allows you to easily anchor an element's positioning to another element on the page.\n\nThis functionality is useful when creating dropdown menus, popovers, dialogs, and tooltips with Alpine.\n\nThe \"anchoring\" functionality used in this plugin is provided by the [Floating UI](https://floating-ui.com/) project.\n\n<a name=\"installation\"></a>\n## Installation\n\nYou can use this plugin by either including it from a `<script>` tag or installing it via NPM:\n\n### Via CDN\n\nYou can include the CDN build of this plugin as a `<script>` tag, just make sure to include it BEFORE Alpine's core JS file.\n\n```alpine\n<!-- Alpine Plugins -->\n<script defer src=\"https://cdn.jsdelivr.net/npm/@alpinejs/anchor@3.x.x/dist/cdn.min.js\"></script>\n\n<!-- Alpine Core -->\n<script defer src=\"https://cdn.jsdelivr.net/npm/alpinejs@3.x.x/dist/cdn.min.js\"></script>\n```\n\n### Via NPM\n\nYou can install Anchor from NPM for use inside your bundle like so:\n\n```shell\nnpm install @alpinejs/anchor\n```\n\nThen initialize it from your bundle:\n\n```js\nimport Alpine from 'alpinejs'\nimport anchor from '@alpinejs/anchor'\n\nAlpine.plugin(anchor)\n\n...\n```\n\n<a name=\"x-anchor\"></a>\n## x-anchor\n\nThe primary API for using this plugin is the `x-anchor` directive.\n\nTo use this plugin, add the `x-anchor` directive to any element and pass it a reference to the element you want to anchor it's position to (often a button on the page).\n\nBy default, `x-anchor` will set the element's CSS to `position: absolute` and the appropriate `top` and `left` values. If the anchored element is normally displayed below the reference element but doesn't have room on the page, it's styling will be adjusted to render above the element.\n\nFor example, here's a simple dropdown anchored to the button that toggles it:\n\n```alpine\n<div x-data=\"{ open: false }\">\n    <button x-ref=\"button\" @click=\"open = ! open\">Toggle</button>\n\n    <div x-show=\"open\" x-anchor=\"$refs.button\">\n        Dropdown content\n    </div>\n</div>\n```\n\n<!-- START_VERBATIM -->\n<div x-data=\"{ open: false }\" class=\"demo overflow-hidden\">\n    <div class=\"flex justify-center\">\n        <button x-ref=\"button\" @click=\"open = ! open\">Toggle</button>\n    </div>\n\n    <div x-show=\"open\" x-anchor=\"$refs.button\" class=\"bg-white rounded p-4 border shadow z-10\">\n        Dropdown content\n    </div>\n</div>\n<!-- END_VERBATIM -->\n\n<a name=\"positioning\"></a>\n## Positioning\n\n`x-anchor` allows you to customize the positioning of the anchored element using the following modifiers:\n\n* Bottom: `.bottom`, `.bottom-start`, `.bottom-end`\n* Top: `.top`, `.top-start`, `.top-end`\n* Left: `.left`, `.left-start`, `.left-end`\n* Right: `.right`, `.right-start`, `.right-end`\n\nHere is an example of using `.bottom-start` to position a dropdown below and to the right of the reference element:\n\n```alpine\n<div x-data=\"{ open: false }\">\n    <button x-ref=\"button\" @click=\"open = ! open\">Toggle</button>\n\n    <div x-show=\"open\" x-anchor.bottom-start=\"$refs.button\">\n        Dropdown content\n    </div>\n</div>\n```\n\n<!-- START_VERBATIM -->\n<div x-data=\"{ open: false }\" class=\"demo overflow-hidden\">\n    <div class=\"flex justify-center\">\n        <button x-ref=\"button\" @click=\"open = ! open\">Toggle</button>\n    </div>\n\n    <div x-show=\"open\" x-anchor.bottom-start=\"$refs.button\" class=\"bg-white rounded p-4 border shadow z-10\">\n        Dropdown content\n    </div>\n</div>\n<!-- END_VERBATIM -->\n\n<a name=\"fixed-positioning\"></a>\n### Fixed positioning\n\nBy default, `x-anchor` applies `position: absolute` to the anchored element. This is fine for most cases, but it falls apart when the reference element lives inside a container with `overflow: hidden`, `overflow: clip`, or `overflow: auto`—the anchored element is clipped along with it.\n\nYou can instruct Floating UI to use a fixed positioning strategy instead by adding the `.fixed` modifier:\n\n```html\n<div x-data=\"{ open: false }\">\n    <button x-ref=\"button\" @click=\"open = ! open\">Toggle</button>\n\n    <div x-show=\"open\" x-anchor.fixed=\"$refs.button\">\n        Dropdown content\n    </div>\n</div>\n```\n\n<!-- START_VERBATIM -->\n<div x-data=\"{ open: false }\" class=\"demo overflow-hidden\">\n    <div class=\"flex justify-center\">\n        <button x-ref=\"button\" @click=\"open = ! open\">Toggle</button>\n    </div>\n\n    <div x-show=\"open\" x-anchor.fixed=\"$refs.button\" class=\"bg-white rounded p-4 border shadow z-10\">\n        Dropdown content\n    </div>\n</div>\n<!-- END_VERBATIM -->\n\n> **Heads up:** a `transform`, `filter`, `perspective`, `backdrop-filter`, `will-change`, or `contain` on any ancestor element creates a new containing block for `position: fixed` descendants ([per the CSS spec](https://developer.mozilla.org/en-US/docs/Web/CSS/position#fixed_positioning)). When that happens, `.fixed` will behave like `position: absolute` relative to that ancestor—and won't escape its `overflow: hidden`. If `.fixed` seems to be doing nothing, check for a transformed ancestor.\n\n<a name=\"offset\"></a>\n## Offset\n\nYou can add an offset to your anchored element using the `.offset.[px value]` modifier like so:\n\n```alpine\n<div x-data=\"{ open: false }\">\n    <button x-ref=\"button\" @click=\"open = ! open\">Toggle</button>\n\n    <div x-show=\"open\" x-anchor.offset.10=\"$refs.button\">\n        Dropdown content\n    </div>\n</div>\n```\n\n<!-- START_VERBATIM -->\n<div x-data=\"{ open: false }\" class=\"demo overflow-hidden\">\n    <div class=\"flex justify-center\">\n        <button x-ref=\"button\" @click=\"open = ! open\">Toggle</button>\n    </div>\n\n    <div x-show=\"open\" x-anchor.offset.10=\"$refs.button\" class=\"bg-white rounded p-4 border shadow z-10\">\n        Dropdown content\n    </div>\n</div>\n<!-- END_VERBATIM -->\n\n<a name=\"prevent-flipping\"></a>\n## Prevent flipping position\n\nBy default, `x-anchor` will flip the position of the anchored element if it doesn't have enough room to render below the reference element.\n\nYou can prevent this behavior by adding the `.noflip` modifier:\n\n```alpine\n<div x-data=\"{ open: false }\">\n    <button x-ref=\"button\" @click=\"open = ! open\">Toggle</button>\n\n    <div x-show=\"open\" x-anchor.noflip=\"$refs.button\">\n        Dropdown content\n    </div>\n</div>\n```\n\n<!-- START_VERBATIM -->\n<div x-data=\"{ open: false }\" class=\"demo overflow-hidden\">\n    <div class=\"flex justify-center\">\n        <button x-ref=\"button\" @click=\"open = ! open\">Toggle</button>\n    </div>\n\n    <div x-show=\"open\" x-anchor.noflip=\"$refs.button\" class=\"bg-white rounded p-4 border shadow z-10\">\n        Dropdown content\n    </div>\n</div>\n<!-- END_VERBATIM -->\n\n<a name=\"manual-styling\"></a>\n## Manual styling\n\nBy default, `x-anchor` applies the positioning styles to your element under the hood. If you'd prefer full control over styling, you can pass the `.no-style` modifer and use the `$anchor` magic to access the values inside another Alpine expression.\n\nBelow is an example of bypassing `x-anchor`'s internal styling and instead applying the styles yourself using `x-bind:style`:\n\n```alpine\n<div x-data=\"{ open: false }\">\n    <button x-ref=\"button\" @click=\"open = ! open\">Toggle</button>\n\n    <div\n        x-show=\"open\"\n        x-anchor.no-style=\"$refs.button\"\n        x-bind:style=\"{ position: 'absolute', top: $anchor.y+'px', left: $anchor.x+'px' }\"\n    >\n        Dropdown content\n    </div>\n</div>\n```\n\n<!-- START_VERBATIM -->\n<div x-data=\"{ open: false }\" class=\"demo overflow-hidden\">\n    <div class=\"flex justify-center\">\n        <button x-ref=\"button\" @click=\"open = ! open\">Toggle</button>\n    </div>\n\n    <div\n        x-show=\"open\"\n        x-anchor.no-style=\"$refs.button\"\n        x-bind:style=\"{ position: 'absolute', top: $anchor.y+'px', left: $anchor.x+'px' }\"\n        class=\"bg-white rounded p-4 border shadow z-10\"\n    >\n        Dropdown content\n    </div>\n</div>\n<!-- END_VERBATIM -->\n\n> **Combining `.no-style` with `.fixed`:** when you opt out of Alpine's internal styling and also want fixed positioning, remember to set `position: 'fixed'` yourself. `$anchor.x` and `$anchor.y` are returned in the coordinate space of whichever strategy is active—absolute coordinates are relative to the offset parent, fixed coordinates are relative to the viewport—so applying the wrong `position` will put your element in the wrong place.\n>\n> ```alpine\n> <div\n>     x-show=\"open\"\n>     x-anchor.no-style.fixed=\"$refs.button\"\n>     x-bind:style=\"{ position: 'fixed', top: $anchor.y+'px', left: $anchor.x+'px' }\"\n> >\n>     Dropdown content\n> </div>\n> ```\n\n<a name=\"from-id\"></a>\n## Anchor to an ID\n\nThe examples thus far have all been anchoring to other elements using Alpine refs.\n\nBecause `x-anchor` accepts a reference to any DOM element, you can use utilities like `document.getElementById()` to anchor to an element by its `id` attribute:\n\n```alpine\n<div x-data=\"{ open: false }\">\n    <button id=\"trigger\" @click=\"open = ! open\">Toggle</button>\n\n    <div x-show=\"open\" x-anchor=\"document.getElementById('trigger')\">\n        Dropdown content\n    </div>\n</div>\n```\n\n<!-- START_VERBATIM -->\n<div x-data=\"{ open: false }\" class=\"demo overflow-hidden\">\n    <div class=\"flex justify-center\">\n        <button class=\"trigger\" @click=\"open = ! open\">Toggle</button>\n    </div>\n\n\n    <div x-show=\"open\" x-anchor=\"document.querySelector('.trigger')\">\n        Dropdown content\n    </div>\n</div>\n<!-- END_VERBATIM -->\n","frontmatter":{"order":7,"title":"Anchor","description":"Anchor an element's positioning to another element on the page","graph_image":"https://alpinejs.dev/social_anchor.jpg"},"isInternal":false,"tokens":2386,"sizeBytes":9436},{"name":"collapse.md","path":"packages/docs/src/en/plugins/collapse.md","rawUrl":"https://raw.githubusercontent.com/alpinejs/alpine/HEAD/packages/docs/src/en/plugins/collapse.md","title":"Plugins Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/alpinejs/alpine?path=packages%2Fdocs%2Fsrc%2Fen%2Fplugins%2Fcollapse.md -->","frontmatter":{"order":6,"title":"Collapse","description":"Collapse and expand elements with robust animations","graph_image":"https://alpinejs.dev/social_collapse.jpg"},"isInternal":false,"tokens":1099,"sizeBytes":4449},{"name":"focus.md","path":"packages/docs/src/en/plugins/focus.md","rawUrl":"https://raw.githubusercontent.com/alpinejs/alpine/HEAD/packages/docs/src/en/plugins/focus.md","title":"Plugins Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/alpinejs/alpine?path=packages%2Fdocs%2Fsrc%2Fen%2Fplugins%2Ffocus.md -->","frontmatter":{"order":5,"title":"Focus","description":"Easily manage focus within the page","graph_image":"https://alpinejs.dev/social_focus.jpg"},"isInternal":false,"tokens":3503,"sizeBytes":13948},{"name":"intersect.md","path":"packages/docs/src/en/plugins/intersect.md","rawUrl":"https://raw.githubusercontent.com/alpinejs/alpine/HEAD/packages/docs/src/en/plugins/intersect.md","title":"Plugins Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/alpinejs/alpine?path=packages%2Fdocs%2Fsrc%2Fen%2Fplugins%2Fintersect.md -->","frontmatter":{"order":2,"title":"Intersect","description":"An Alpine convenience wrapper for Intersection Observer that allows you to easily react when an element enters the viewport.","graph_image":"https://alpinejs.dev/social_intersect.jpg"},"isInternal":false,"tokens":1915,"sizeBytes":7840},{"name":"mask.md","path":"packages/docs/src/en/plugins/mask.md","rawUrl":"https://raw.githubusercontent.com/alpinejs/alpine/HEAD/packages/docs/src/en/plugins/mask.md","title":"Plugins Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/alpinejs/alpine?path=packages%2Fdocs%2Fsrc%2Fen%2Fplugins%2Fmask.md -->","frontmatter":{"order":1,"title":"Mask","description":"Automatically format text fields as users type","graph_image":"https://alpinejs.dev/social_mask.jpg"},"isInternal":false,"tokens":1432,"sizeBytes":5584},{"name":"morph.md","path":"packages/docs/src/en/plugins/morph.md","rawUrl":"https://raw.githubusercontent.com/alpinejs/alpine/HEAD/packages/docs/src/en/plugins/morph.md","title":"Plugins Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/alpinejs/alpine?path=packages%2Fdocs%2Fsrc%2Fen%2Fplugins%2Fmorph.md -->","frontmatter":{"order":8,"title":"Morph","description":"Morph an element into the provided HTML","graph_image":"https://alpinejs.dev/social_morph.jpg"},"isInternal":false,"tokens":2475,"sizeBytes":9769},{"name":"persist.md","path":"packages/docs/src/en/plugins/persist.md","rawUrl":"https://raw.githubusercontent.com/alpinejs/alpine/HEAD/packages/docs/src/en/plugins/persist.md","title":"Plugins Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/alpinejs/alpine?path=packages%2Fdocs%2Fsrc%2Fen%2Fplugins%2Fpersist.md -->","frontmatter":{"order":4,"title":"Persist","description":"Easily persist data across page loads using localStorage","graph_image":"https://alpinejs.dev/social_persist.jpg"},"isInternal":false,"tokens":1675,"sizeBytes":7085},{"name":"resize.md","path":"packages/docs/src/en/plugins/resize.md","rawUrl":"https://raw.githubusercontent.com/alpinejs/alpine/HEAD/packages/docs/src/en/plugins/resize.md","title":"Plugins Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/alpinejs/alpine?path=packages%2Fdocs%2Fsrc%2Fen%2Fplugins%2Fresize.md -->","frontmatter":{"order":3,"title":"Resize","description":"An Alpine convenience wrapper for the Resize Observer API that allows you to easily react when an element is resized.","graph_image":"https://alpinejs.dev/social_resize.jpg"},"isInternal":false,"tokens":933,"sizeBytes":3637},{"name":"sort.md","path":"packages/docs/src/en/plugins/sort.md","rawUrl":"https://raw.githubusercontent.com/alpinejs/alpine/HEAD/packages/docs/src/en/plugins/sort.md","title":"Plugins Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/alpinejs/alpine?path=packages%2Fdocs%2Fsrc%2Fen%2Fplugins%2Fsort.md -->","frontmatter":{"order":9,"title":"Sort","description":"Easily re-order elements by dragging them with your mouse","graph_image":"https://alpinejs.dev/social_sort.jpg"},"isInternal":false,"tokens":3106,"sizeBytes":11978},{"name":"start-here.md","path":"packages/docs/src/en/start-here.md","rawUrl":"https://raw.githubusercontent.com/alpinejs/alpine/HEAD/packages/docs/src/en/start-here.md","title":"En Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/alpinejs/alpine?path=packages%2Fdocs%2Fsrc%2Fen%2Fstart-here.md -->","frontmatter":{"order":1,"title":"Start Here"},"isInternal":false,"tokens":2984,"sizeBytes":12299},{"name":"upgrade-guide.md","path":"packages/docs/src/en/upgrade-guide.md","rawUrl":"https://raw.githubusercontent.com/alpinejs/alpine/HEAD/packages/docs/src/en/upgrade-guide.md","title":"En Skill","category":"anthropic-skill","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/alpinejs/alpine?path=packages%2Fdocs%2Fsrc%2Fen%2Fupgrade-guide.md -->","frontmatter":{"order":2,"title":"Upgrade From V2"},"isInternal":false,"tokens":2837,"sizeBytes":11139}],"systemPromptSnippet":"<yakaai_skills repo=\"alpinejs/alpine\">\n<!-- File: CLAUDE.md (Tokens: ~775 | Category: claude-rule) -->\n# Alpine.js Development Guidelines\n\n## Pull Request Evaluation Criteria\n\nWhen evaluating pull requests for Alpine.js, assess the following:\n\n### 1. Tests\n- Are tests provided for the change?\n- Do existing tests still pass?\n- For configuration changes (package.json, build scripts), tests may not be required\n\n### 2. Code Style\n- Does the code match Alpine's existing patterns?\n- Check indentation, naming conventions, and structure\n- For package.json changes, ensure consistency with other packages in the monorepo\n\n### 3. Code Quality\n- Is the code clean and maintainable?\n- Is the change focused and minimal?\n- Are there any unnecessary changes or complexity?\n- Does this PR contain changes that should apply elsewhere?\n\n### 4. Simplicity\n- Is this a simple, focused change?\n- Does it follow Alpine's philosophy of simplicity?\n- Could it be implemented more simply?\n- Are the proposed additions intuitive for users? or do they require extra knowledge that they have to dig for.\n\n### 5. Precedent\n- Does this PR (both public facing additions and internal implementation) follow established precedents in the project\n- Does it use terms that are unfamiliar to the project as of yet?\n\n### 6. Description Quality\n- Is there a clear explanation of what/why/how?\n- Are breaking changes documented?\n- Is backward compatibility addressed?\n\n### 7. Community Engagement\n- Are there comments, reviews, or discussions?\n- Has it been approved by maintainers?\n- Are there any conflicting opinions or unresolved concerns?\n\n### Mergeability Rating\nBased on the above, rate as:\n- **HIGH**: Ready to merge (all criteria met, approved)\n- **MEDIUM**: Needs attention (technically sound but missing reviews/tests)\n- **LOW**: Requires work (has issues or conflicts to resolve)\n\n## Project Structure\n\nAlpine.js is a monorepo with packages in `/packages/`:\n- Each package has its own package.json\n- Build outputs go to `dist/` with `.cjs.js`, `.esm.js`, and `.min.js` versions\n- Browser tests use Cypress, unit tests use Vitest\n- CI runs on GitHub Actions\n\n## Common Commands\n\n```bash\n# Build\nnpm run build                # Build all packages\n\n# Browser tests (Cypress)\nnpm test                     # Run all tests\nnpx cypress run --spec ./tests/cypress/integration/[filename].spec.js  # Run single spec\n\n# Unit tests (Vitest)\nnpx vitest run tests/vitest/[filename].spec.js  # Run single spec\n\n# Review PRs\ngh pr list                   # List open PRs\ngh pr view [number]          # View PR details\ngh pr diff [number]          # View code changes\ngh pr checks [number]        # Check CI status\n```\n\n## Manual Testing\n\n1. Edit `./index.html` at project root\n2. Open in browser at `http://alpine.test/` (assumes local dev server mapped to directory name)\n\n## Summary\n\nAfter assessing the pull request on the above qualities, provide a summary explaining the problem this PR addresses and the fix, and why it's a good or bad fix. Do it in plain language as if you are personally advising me on what the PR is and weather or not I should merge it. And if not, what might need to be addressed first. If things need to be addressed, offer to address them yourself.\n\nPlease use code snippets to establish a starting point and and ending point if helpful. For example, when explaining the problem, it is often easier to provide a brief explanation alongside a code snippet of what is currently problematic, then when explaining the solution, showing what new code will allow a fix if applicable.\n\n<!-- File: .claude/skills/review-pr/SKILL.md (Tokens: ~3080 | Category: anthropic-skill) -->\n---\nname: review-pr\ndescription: Review an open PR like a maintainer — checkout, fix issues, push changes, post a structured verdict comment. You just merge or close.\ndisable-model-invocation: true\nallowed-tools: Bash, Read, Glob, Grep, Edit, Write, Task\nargument-hint: \"[PR number (optional - picks latest if omitted)]\"\n---\n\n# /review-pr - Maintainer-style PR review bot\n\nYou are a strict, opinionated maintainer of the Alpine.js project. Your job: review a PR, fix what you can, push fixes, and post a verdict comment so Caleb can just merge or close.\n\n**IMPORTANT: Every numbered step below is mandatory. Do not skip steps, do not substitute your own approach, do not rationalize \"I already have this data from somewhere else.\" Run the exact commands listed. If a command fails, retry it — do not silently move on. Complete each step fully before starting the next.**\n\n## Step 1: Pick a PR\n\nIf `$ARGUMENTS` is provided, use that as the PR number. Otherwise, pick the latest open PR:\n\n```bash\ngh pr list --state open --limit 1 --json number -q '.[0].number'\n```\n\n## Step 2: Check if already reviewed\n\nLook for the `<!-- claude-review -->` marker in PR comments:\n\n```bash\ngh pr view {number} --json comments -q '.comments[].body' | grep -q '<!-- claude-review -->'\n```\n\nIf found, tell the user this PR was already reviewed and stop. Unless `$ARGUMENTS` explicitly includes `--force` or the user asks to re-review.\n\n## Step 3: Fetch PR data\n\nRun ALL FOUR of these commands in parallel. If any fail, retry them. Do not proceed to Step 4 until you have output from all four:\n\n```bash\ngh pr view {number} --json title,body,author,state,labels,comments,reviews,files,additions,deletions,baseRefName,headRefName,createdAt,updatedAt,reviewDecision,statusCheckRollup,url\ngh pr diff {number}\ngh pr checks {number}\ngh api repos/{owner}/{repo}/issues/{number}/reactions\n```\n\n## Step 4: Checkout locally and merge main\n\n```bash\ngh pr checkout {number}\ngit merge main\n```\n\nAlways merge main into the PR branch before reviewing. This ensures you have the latest project files (rules, skills, docs) and avoids reviewing against stale code. If the merge has conflicts, resolve them or flag for the contributor.\n\n## Step 5: Read and classify\n\nRead through the diff and PR body. Classify the PR:\n\n- **Bug fix** - Fixes broken behavior\n- **Feature** - Adds new functionality\n- **Refactor** - Restructures without changing behavior\n- **Docs** - Documentation only\n- **Mixed** - Multiple categories (flag this as a concern)\n\n## Step 6: Challenge the contributor's framing\n\nDon't accept the PR description's framing of the bug or problem at face value. Verify independently:\n\n1. **Identify the root cause yourself.** Read the code the PR modifies. Understand *why* the bug exists before looking at how the PR fixes it.\n2. **Does the test actually isolate that root cause?** Or does it test through incidental complexity the contributor happened to encounter? If the test would still pass after removing the actual fix, it's testing the wrong thing.\n3. **If the test encodes a wrong mental model, rewrite it.** Strip it to the minimum reproduction that targets the real bug. Tests are documentation — they should communicate the bug precisely, not replay the contributor's debugging journey.\n4. **Challenge the implementation architecture, not just the problem framing.** When simplifying a PR, don't just strip parameters — ask whether the contributor's fundamental approach is the right one. A simpler version of a bad approach is still a bad approach. Ask: \"What's the laziest correct solution? Does the language/framework already handle this if I just let it?\"\n\n## Step 7: Evaluate\n\n### For bug fixes\n\n1. **Has a test?** If not, write one. The test should fail on `main` and pass on the PR branch.\n2. **Test covers the actual fix?** Including edge cases?\n3. **Actually verify regression.** Don't just reason about whether the test fails without the fix — prove it. Stash the fix (`git stash -- <fix files>`), rebuild (`npm run build`), run the test. If it passes without the fix, the test is not testing the fix. Unstash and rewrite the test. This is non-negotiable for bug fix PRs.\n4. **Test isolates root cause?** Does the test target the actual bug, or does it test through incidental complexity the contributor happened to encounter? Strip tests to the minimum reproduction. Tests are documentation — they should communicate the bug precisely.\n5. **Naming quality?** Review all test names, component names, variable names. Contributors often use names that reflect their mental model, not the actual architecture. Fix these before merging — they become permanent.\n6. **Unnecessary fixtures/setup?** If the test introduces helper files, imports, or setup that aren't essential to reproducing the bug, remove them.\n7. **For visual/browser bugs, test observable behavior, not DOM state.** Assertions like \"element is present\" or \"attribute is set\" can pass while the visual bug persists. For animation bugs: assert on `document.getAnimations()` state. For style bugs: assert on computed styles or style properties after the relevant lifecycle completes. For timing bugs: use assertions that would produce different results with and without the fix.\n8. **Fix is surgical/minimal?** No unrelated changes?\n9. **Regression risk?** Could this break something else?\n\n### For features\n\nAddress EVERY item below. Do not skip any — even to say \"N/A\":\n\n1. **Already possible without new API?** Default stance: reject new public API surface. Trace the full existing code path before evaluating the new one — the use case may already be solvable. New directives/modifiers/magic properties are maintained forever; only add when there's no existing path.\n2. **Community demand?** Check reactions on the PR and linked issues. Low engagement = higher bar.\n3. **Intuitive API?** Single-word modifiers preferred (`x-transition.opacity` not `x-transition.opacity-only`). Alpine favors short, expressive directive syntax.\n4. **Precedent?** Does it build on existing patterns or introduce new ones? New patterns need strong justification.\n5. **Scope?** Should this be a core Alpine feature or a separate plugin package? Alpine core should stay minimal.\n6. **Docs included?** Features need documentation.\n7. **Registration complete?** Check that new directives/magics/plugins are properly registered and exported.\n\n### For all PRs\n\nAddress EVERY item below:\n\n1. **Project style?**\n   - JS: no semicolons, `let` not `const`\n   - Follows Alpine's existing patterns and conventions\n2. **Single responsibility?** Flag PRs doing too many things.\n3. **Security?** Extra scrutiny for: `x-html`, expression evaluation, `Alpine.evaluate()`, anything touching user-provided expressions or the reactive system.\n4. **Built JS assets in diff?** Check the file list from `gh pr diff --name-only` for `dist/` files. These should NOT be committed. Remove them.\n5. **\"No for now\" bias.** When in doubt, lean toward not merging. It's easier to add later than remove.\n6. **Async timing fixes are treacherous.** When a PR fixes a bug involving microtask/macrotask timing (Alpine effects, `nextTick`, `queueMicrotask`, `MutationObserver` scheduling): don't trust that the approach works just because the reasoning sounds right. Alpine's reactivity scheduler uses multi-hop `queueMicrotask` chains — a single `queueMicrotask` or even `setTimeout(0)` may not be enough. If you can't verify the timing empirically, flag it for discussion.\n7. **\"What's the laziest correct solution?\"** Before evaluating the PR's implementation details, independently brainstorm the simplest possible fix. The contributor's approach is often shaped by their discovery path, not by what's optimal.\n\n## Step 8: Run relevant tests only\n\n**NEVER run the full test suite.** Only run tests the PR adds or touches:\n\n```bash\n# Find test files in the diff\ngh pr diff {number} --name-only | grep -E '\\.spec\\.js$'\n```\n\nRun those specific tests:\n\n```bash\n# For Cypress browser tests\nnpx cypress run --spec ./tests/cypress/integration/{test-file}.spec.js\n\n# For Vitest unit tests\nnpx vitest run tests/vitest/{test-file}.spec.js\n```\n\nIf the PR doesn't touch test files but you wrote tests in step 6, run those.\n\nAlso check CI status:\n\n```bash\ngh pr checks {number}\n```\n\n## Step 8b: If the PR has no fix, write one\n\nIf the PR only adds a failing test (or describes a bug without a fix), don't just review the test and stop. **Explore solution paths and try to fix the bug yourself.** This is the most valuable thing you can do.\n\n1. Identify 2-3 possible fix approaches\n2. Evaluate trade-offs of each (surgical vs broad, risk of regressions, etc.)\n3. Present the options to Caleb with a brief explanation of each\n4. Once Caleb picks a direction, implement and test it\n\n## Step 9: Make fixes directly\n\nFix issues you find. Common fixes:\n\n- **Style violations**: Remove semicolons from JS, change `const` to `let`\n- **Built assets in diff**: `git checkout main -- dist/` (or whatever the build output path is)\n- **Missing tests**: Write them\n- **Small refactors**: Simplify overly complex code\n- **Missing registration**: Add to package index files, etc.\n- **Before committing a simplified version of the contributor's code, do a smell test:** Could this be done in fewer lines with a completely different approach? The best code is the code you delete.\n\nStage and commit fixes:\n\n```bash\ngit add -A\ngit commit -m \"Review fixes: [brief description]\n\nCo-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>\"\n```\n\n## Step 10: Push to PR branch\n\nTry to push to the contributor's branch:\n\n```bash\ngit push\n```\n\n### If push fails (fork doesn't allow maintainer edits)\n\n1. Create a new branch from `main`\n2. Cherry-pick the contributor's commits\n3. Apply your fixes on top\n4. Push the new branch\n5. Create a new PR:\n\n```bash\ngh pr create --title \"{original title}\" --body \"$(cat <<'EOF'\nCloses #{original_number}\n\nCherry-picked from #{original_number} by @{author} with review fixes applied.\n\n## Original description\n{original_body}\n\n## Review fixes applied\n{list of fixes}\nEOF\n)\"\n```\n\n6. Comment on the original PR explaining the new PR.\n\n## Step 11: Post verdict comment\n\nPost a structured comment on the PR:\n\n```bash\ngh pr comment {number} --body \"$(cat <<'EOF'\n<!-- claude-review -->\n## PR Review: #{number} — {title}\n\n**Type**: {Bug fix | Feature | Refactor | Docs | Mixed}\n**Verdict**: {Merge | Request changes | Needs discussion | Close}\n\n### What's happening (plain English)\n{Explain the PR like Caleb is a 3-year-old who happens to be an expert in Alpine internals but has zero context on this specific PR. Use a numbered step-by-step walkthrough of the exact sequence that triggers the bug/feature. No jargon beyond what Alpine devs already know. Be crystal clear and concise — this is the most important section.}\n\n### Other approaches considered\n{Briefly list 2-3 alternative ways this could have been solved, with one sentence each on why the PR's approach is better (or worse). If there's only one reasonable approach, say so and explain why. This helps Caleb quickly evaluate whether the chosen path is the right one.}\n\n### Changes Made\n{List of fixups you pushed, or \"No changes made\" if none}\n\n### Test Results\n{Which tests ran, pass/fail status, CI status}\n\n### Code Review\n{Specific feedback with file:line references. What's good, what's concerning.}\n\n### Security\n{Any security considerations, or \"No security concerns identified.\"}\n\n### Verdict\n{Your reasoning for the verdict. Be direct. If it should be merged, say why. If closed, say why kindly but clearly.}\n\n---\n*Reviewed by Claude*\nEOF\n)\"\n```\n\n## Verdict guidelines\n\n- **Merge**: Code is correct, tests pass, style is clean, feature is wanted. You've fixed any minor issues.\n- **Request changes**: Significant issues you can't fix yourself (architectural problems, missing context, needs author input).\n- **Needs discussion**: Feature scope questions, API design debates, core vs plugin questions. Tag these for Caleb.\n- **Close**: PR is stale with no response, duplicates existing functionality, or solves a problem that shouldn't be solved. Be kind.\n\n## Important rules\n\n- NEVER run the full test suite. Only run tests the PR touches or that you wrote.\n- Always use the `<!-- claude-review -->` marker so you can detect previous reviews.\n- Be opinionated. This project has strong conventions — enforce them.\n- Fix what you can. Don't just point out problems if you can solve them.\n- Security is non-negotiable. If you see a security issue, verdict is always \"Request changes\" regardless of everything else.\n- Match the project voice: practical, direct, minimal.\n- Don't accept the contributor's framing of the problem at face value. Verify the root cause independently, then ensure the test targets that root cause — not the contributor's incidental path to discovering it.\n- \"Should this exist?\" before \"Is this correct?\" — Don't get pulled into reviewing implementation details (code quality, edge cases, naming) until you've decided the feature itself is justified. Implementation nits imply acceptance.\n- Tests are documentation. A sloppy test that passes is not good enough — it should precisely communicate what broke and why.\n- Review contributor naming as critically as contributor code. Bad names get merged and become permanent.\n\n<!-- File: .claude/skills/summarize-activity/SKILL.md (Tokens: ~1691 | Category: anthropic-skill) -->\n---\nname: summarize-activity\ndescription: Summarize recent GitHub activity — discussions, PRs, issues, events, traffic — into an actionable report so you can stay on top of the project without reading everything.\ndisable-model-invocation: true\nallowed-tools: Bash, Read, Task\nargument-hint: \"[timeframe: 24h (default), 48h, 7d, 1w]\"\n---\n\n# /summarize-activity - GitHub activity digest\n\nYou generate a concise, actionable summary of recent Alpine.js GitHub activity for Caleb.\n\n**IMPORTANT: Every numbered step below is mandatory. Do not skip steps, do not substitute your own approach. Run the exact commands listed. If a command fails, retry it — do not silently move on. Complete each step fully before starting the next.**\n\n## Step 1: Parse timeframe\n\nParse `$ARGUMENTS` into a cutoff timestamp. Supported formats:\n- `24h`, `48h`, `72h` — hours (default: `24h` if no argument)\n- `7d`, `14d`, `30d` — days\n- `1w`, `2w` — weeks (1w = 7d)\n\nCompute the ISO 8601 cutoff timestamp:\n\n```bash\n# Example for 24h:\ndate -u -v-24H '+%Y-%m-%dT%H:%M:%SZ'\n# Example for 7d:\ndate -u -v-7d '+%Y-%m-%dT%H:%M:%SZ'\n```\n\nStore the cutoff timestamp and the human-readable timeframe label (e.g., \"last 24 hours\", \"last 7 days\") for use in later steps.\n\n## Step 2: Fetch activity in parallel\n\nRun ALL FIVE of these commands in parallel using the Bash tool. If any fail, retry them. Do not proceed to Step 3 until you have output from all five.\n\n**Owner/repo:** `alpinejs/alpine`\n\n### 2a. Discussions (GraphQL)\n\n```bash\ngh api graphql -f query='\n{\n  repository(owner: \"alpinejs\", name: \"alpine\") {\n    discussions(first: 50, orderBy: {field: UPDATED_AT, direction: DESC}) {\n      nodes {\n        title\n        url\n        author { login }\n        category { name }\n        comments { totalCount }\n        body\n        answer { author { login } body createdAt }\n        createdAt\n        updatedAt\n      }\n    }\n  }\n}'\n```\n\n### 2b. Pull Requests\n\n```bash\ngh pr list --repo alpinejs/alpine --state all --limit 50 --json number,title,url,author,state,labels,createdAt,updatedAt,additions,deletions,headRefName,baseRefName,reviewDecision,comments\n```\n\n### 2c. Issues\n\n```bash\ngh issue list --repo alpinejs/alpine --state all --limit 50 --json number,title,url,author,state,labels,createdAt,updatedAt,comments\n```\n\n### 2d. Events\n\n```bash\ngh api repos/alpinejs/alpine/events --paginate --jq '.[] | {type, actor: .actor.login, created_at: .created_at, payload_action: .payload.action, ref: .payload.ref, ref_type: .payload.ref_type}' | head -100\n```\n\n### 2e. Traffic & stars\n\n```bash\ngh api repos/alpinejs/alpine/traffic/views 2>/dev/null; echo \"---SEPARATOR---\"; gh api repos/alpinejs/alpine/traffic/clones 2>/dev/null; echo \"---SEPARATOR---\"; gh api repos/alpinejs/alpine --jq '{stargazers_count, forks_count, open_issues_count, watchers_count}'\n```\n\nNote: Traffic endpoints require push access. If they return 403, skip traffic data and note it in the report.\n\n## Step 3: Fetch comment threads for active items\n\nFor discussions that have comments updated within the timeframe, fetch full comment bodies via GraphQL. Batch up to 10 discussions per query:\n\n```bash\ngh api graphql -f query='\n{\n  repository(owner: \"alpinejs\", name: \"alpine\") {\n    discussion(number: {NUMBER}) {\n      comments(last: 10) {\n        nodes {\n          author { login }\n          body\n          createdAt\n          updatedAt\n        }\n      }\n    }\n  }\n}'\n```\n\nFor the most active PRs and issues (those with comments updated in timeframe), fetch recent comments:\n\n```bash\ngh api repos/alpinejs/alpine/issues/{number}/comments --jq '.[] | select(.updated_at > \"{CUTOFF}\") | {user: .user.login, body: .body, created_at: .created_at}'\n```\n\nOnly fetch threads that are clearly within the timeframe. Don't fetch everything — be selective.\n\n## Step 4: Filter by timeframe\n\nDiscard anything with `updatedAt` / `updated_at` before the cutoff timestamp. Keep items where:\n- The item was created within the timeframe\n- The item received new comments within the timeframe\n- The item changed state (opened, closed, merged) within the timeframe\n\n## Step 5: Analyze and write report\n\nOutput a markdown report with these sections. Be concise — this is a digest, not a novel.\n\n---\n\n### Report format:\n\n```markdown\n# Alpine.js Activity — {timeframe label}\n_{start date} to {end date}_\n\n## TL;DR\n{2-3 sentences. What's the pulse? Any fires? Anything exciting? Give Caleb the vibe in 10 seconds.}\n\n## Needs Your Attention\n{Actionable items only. Each with a recommended next step: reply, merge, close, investigate, etc.}\n\n- **[Title](url)** by @author — {why it needs attention}. **Action:** {specific recommendation}\n\n{If nothing needs attention, say \"Nothing urgent right now.\"}\n\n## Hot Discussions\n{Discussions with the most activity or notable sentiment. Include key quotes if illuminating.}\n\n- **[Title](url)** ({category}) — {N} comments — {brief summary, sentiment note}\n\n{If no notable discussions, say \"Quiet on the discussion front.\"}\n\n## PR Activity\n\n### Opened\n- **[#N Title](url)** by @author — {one-line summary} {+additions/-deletions}\n\n### Merged\n- **[#N Title](url)** by @author — {one-line summary}\n\n### Closed (not merged)\n- **[#N Title](url)** by @author — {one-line summary, why closed if clear}\n\n{Omit empty subsections.}\n\n## Issue Activity\n\n### Opened\n- **[#N Title](url)** by @author — {one-line summary}\n\n### Closed\n- **[#N Title](url)** — {one-line summary}\n\n{Omit empty subsections.}\n\n## Repo Pulse\n| Metric | Value |\n|--------|-------|\n| Stars | {total} |\n| Views (14d) | {count} |\n| Clones (14d) | {count} |\n| Open issues | {count} |\n| PRs opened | {count in timeframe} |\n| PRs merged | {count in timeframe} |\n| PRs closed | {count in timeframe} |\n\n{If traffic data is unavailable (403), omit those rows and note \"Traffic data requires push access.\"}\n```\n\n---\n\n## Important rules\n\n- Every item must include a `[title](url)` link so Caleb can click through.\n- Include @author for attribution.\n- Keep summaries to ONE line per item. This is a digest.\n- The \"Needs Your Attention\" section is the most important. Be opinionated about what deserves Caleb's time.\n- If a discussion or issue has heated sentiment, note it (e.g., \"heated\", \"confused users\", \"strong demand\").\n- Omit empty sections entirely — don't show \"No activity\" headers.\n- For PRs, mention if CI is failing when relevant.\n- Don't editorialize beyond what's helpful for triage. Be practical, not chatty.\n\n<!-- File: packages/docs/package.json (Tokens: ~89 | Category: anthropic-skill) -->\n{\n    \"name\": \"@alpinejs/docs\",\n    \"version\": \"3.17.5\",\n    \"description\": \"The documentation for Alpine\",\n    \"repository\": {\n        \"type\": \"git\",\n        \"url\": \"https://github.com/alpinejs/alpine.git\",\n        \"directory\": \"packages/docs\"\n    },\n    \"author\": \"Caleb Porzio\",\n    \"license\": \"MIT\"\n}\n\n<!-- File: packages/docs/src/en/advanced.md (Tokens: ~16 | Category: anthropic-skill) -->\n---\norder: 8\ntitle: Advanced\ntype: sub-directory\n---\n\n<!-- File: packages/docs/src/en/advanced/async.md (Tokens: ~256 | Category: anthropic-skill) -->\n---\norder: 4\ntitle: Async\n---\n\n# Async\n\nAlpine is built to support asynchronous functions in most places it supports standard ones.\n\nFor example, let's say you have a simple function called `getLabel()` that you use as the input to an `x-text` directive:\n\n```js\nfunction getLabel() {\n    return 'Hello World!'\n}\n```\n```alpine\n<span x-text=\"getLabel()\"></span>\n```\n\nBecause `getLabel` is synchronous, everything works as expected.\n\nNow let's pretend that `getLabel` makes a network request to retrieve the label and can't return one instantaneously (asynchronous). By making `getLabel` an async function, you can call it from Alpine using JavaScript's `await` syntax.\n\n```js\nasync function getLabel() {\n    let response = await fetch('/api/label')\n\n    return await response.text()\n}\n```\n```alpine\n<span x-text=\"await getLabel()\"></span>\n```\n\nAdditionally, if you prefer calling methods in Alpine without the trailing parenthesis, you can leave them out and Alpine will detect that the provided function is async and handle it accordingly. For example:\n\n```alpine\n<span x-text=\"getLabel\"></span>\n```\n\n<!-- File: packages/docs/src/en/advanced/csp.md (Tokens: ~1511 | Category: anthropic-skill) -->\n---\norder: 1\ntitle: CSP\n---\n\n# CSP (Content-Security Policy) Build\n\nIn order for Alpine to execute JavaScript expressions from HTML attributes like `x-on:click=\"console.log()\"`, it needs to use utilities that violate the \"unsafe-eval\" [Content Security Policy](https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP) that some applications enforce for security purposes.\n\n> Under the hood, Alpine doesn't actually use eval() itself because it's slow and problematic. Instead it uses Function declarations, which are much better, but still violate \"unsafe-eval\".\n\nAlpine offers an alternate build that doesn't violate \"unsafe-eval\" and supports most of Alpine's inline expression syntax.\n\n<a name=\"installation\"></a>\n## Installation\n\nYou can use this build by either including it from a `<script>` tag or installing it via NPM:\n\n### Via CDN\n\nYou can include this build's CDN as a `<script>` tag just like you would normally with standard Alpine build:\n\n```alpine\n<!-- Alpine's CSP-friendly Core -->\n<script defer src=\"https://cdn.jsdelivr.net/npm/@alpinejs/csp@3.x.x/dist/cdn.min.js\"></script>\n```\n\n### Via NPM\n\nYou can alternatively install this build from NPM for use inside your bundle like so:\n\n```shell\nnpm install @alpinejs/csp\n```\n\nThen initialize it from your bundle:\n\n```js\nimport Alpine from '@alpinejs/csp'\n\nwindow.Alpine = Alpine\n\nAlpine.start()\n```\n\n<a name=\"basic-example\"></a>\n## Basic Example\n\nHere's a working counter component using Alpine's CSP build. Notice how most expressions work exactly like regular Alpine:\n\n```alpine\n<html>\n    <head>\n        <meta http-equiv=\"Content-Security-Policy\" content=\"default-src 'self'; script-src 'nonce-a23gbfz9e'\">\n        <script defer nonce=\"a23gbfz9e\" src=\"https://cdn.jsdelivr.net/npm/@alpinejs/csp@3.x.x/dist/cdn.min.js\"></script>\n    </head>\n    <body>\n        <div x-data=\"{ count: 0, message: 'Hello' }\">\n            <button x-on:click=\"count++\">Increment</button>\n            <button x-on:click=\"count = 0\">Reset</button>\n\n            <span x-text=\"count\"></span>\n            <span x-text=\"message + ' World'\"></span>\n            <span x-show=\"count > 5\">Count is greater than 5!</span>\n        </div>\n    </body>\n</html>\n```\n\n<a name=\"whats-supported\"></a>\n## What's Supported\n\nThe CSP build supports most JavaScript expressions you'd want to use in Alpine:\n\n### Object and Array Literals\n```alpine\n<!-- ✅ These work -->\n<div x-data=\"{ user: { name: 'John', age: 30 }, items: [1, 2, 3] }\">\n    <span x-text=\"user.name\"></span>\n    <span x-text=\"items[0]\"></span>\n</div>\n```\n\n### Basic Operations\n```alpine\n<!-- ✅ These work -->\n<div x-data=\"{ count: 5, name: 'Alpine' }\">\n    <span x-text=\"count + 10\"></span>\n    <span x-text=\"count > 3\"></span>\n    <span x-text=\"count === 5 ? 'Yes' : 'No'\"></span>\n    <span x-text=\"'Hello ' + name\"></span>\n    <div x-show=\"!loading && count > 0\"></div>\n</div>\n```\n\n### Assignments and Updates\n```alpine\n<!-- ✅ These work -->\n<div x-data=\"{ count: 0, user: { name: '' } }\">\n    <button x-on:click=\"count++\">Increment</button>\n    <button x-on:click=\"count = 0\">Reset</button>\n    <input x-model=\"user.name\">\n</div>\n```\n\n### Method Calls\n```alpine\n<!-- ✅ These work -->\n<div x-data=\"{ items: ['a', 'b'] }\">\n    <button x-on:click=\"items.push('c')\">Add Item</button>\n</div>\n```\n\n<a name=\"whats-not-supported\"></a>\n## What's Not Supported\n\nSome advanced and potentially dangerous JavaScript features aren't supported:\n\n### Complex Expressions\n```alpine\n<!-- ❌ These don't work -->\n<div x-data=\"{ user: { name: '' } }\">\n    <!-- Property assignments -->\n    <button x-on:click=\"user.name = 'John'\">Bad</button>\n\n    <!-- Arrow functions -->\n    <button x-on:click=\"() => console.log('hi')\">Bad</button>\n\n    <!-- Destructuring -->\n    <div x-text=\"{ name } = user\">Bad</div>\n\n    <!-- Template literals -->\n    <div x-text=\"`Hello ${name}`\">Bad</div>\n\n    <!-- Spread operator -->\n    <div x-data=\"{ ...defaults }\">Bad</div>\n</div>\n```\n\n### Global Variables and Functions\n```alpine\n<!-- ❌ These don't work -->\n<div x-data>\n    <button x-on:click=\"console.log('hi')\"></button>\n    <span x-text=\"document.title\"></span>\n    <span x-text=\"window.innerWidth\"></span>\n    <span x-text=\"Math.max(count, 100)\"></span>\n    <span x-text=\"parseInt('123') + count\"></span>\n    <span x-text=\"JSON.stringify({ value: count })\"></span>\n</div>\n```\n\n### HTML Injection\n```alpine\n<!-- ❌ These don't work -->\n<div x-data=\"{ message: 'Hello <span>World</span>' }\">\n    <span x-html=\"message\"></span>\n    <span x-init=\"$el.insertAdjacentHTML('beforeend', message)\"></span>\n</div>\n```\n\n<a name=\"when-to-extract-logic\"></a>\n## When to Extract Logic\n\nWhile the CSP build supports simple inline expressions, you'll want to extract complex logic into dedicated functions or Alpine.data() components for better organization:\n\n```alpine\n<!-- Instead of this -->\n<div x-data=\"{ users: [] }\" x-show=\"users.filter(u => u.active && u.role === 'admin').length > 0\">\n```\n\n```alpine\n<!-- Do this -->\n<div x-data=\"userManager\" x-show=\"hasActiveAdmins\">\n\n<script nonce=\"...\">\n    Alpine.data('userManager', () => ({\n        users: [],\n\n        get hasActiveAdmins() {\n            return this.users.filter(u => u.active && u.role === 'admin').length > 0\n        }\n    }))\n</script>\n```\n\nThis approach makes your code more readable, testable, and maintainable, especially for complex applications.\n\n<a name=\"csp-headers\"></a>\n## CSP Headers\n\nHere's an example CSP header that works with Alpine's CSP build:\n\n```\nContent-Security-Policy: default-src 'self'; script-src 'nonce-[random]' 'strict-dynamic';\n```\n\nThe key is removing `'unsafe-eval'` from your `script-src` directive while still allowing your nonce-based scripts to run.\n\n<!-- File: packages/docs/src/en/advanced/extending.md (Tokens: ~3621 | Category: anthropic-skill) -->\n---\norder: 3\ntitle: Extending\n---\n\n# Extending\n\nAlpine has a very open codebase that allows for extension in a number of ways. In fact, every available directive and magic in Alpine itself uses these exact APIs. In theory you could rebuild all of Alpine's functionality using them yourself.\n\n<a name=\"lifecycle-concerns\"></a>\n## Lifecycle concerns\nBefore we dive into each individual API, let's first talk about where in your codebase you should consume these APIs.\n\nBecause these APIs have an impact on how Alpine initializes the page, they must be registered AFTER Alpine is downloaded and available on the page, but BEFORE it has initialized the page itself.\n\nThere are two different techniques depending on if you are importing Alpine into a bundle, or including it directly via a `<script>` tag. Let's look at them both:\n\n<a name=\"via-script-tag\"></a>\n### Via a script tag\n\nIf you are including Alpine via a script tag, you will need to register any custom extension code inside an `alpine:init` event listener.\n\nHere's an example:\n\n```alpine\n<html>\n    <script src=\"/js/alpine.js\" defer></script>\n\n    <div x-data x-foo></div>\n\n    <script>\n        document.addEventListener('alpine:init', () => {\n            Alpine.directive('foo', ...)\n        })\n    </script>\n</html>\n```\n\nIf you want to extract your extension code into an external file, you will need to make sure that file's `<script>` tag is located BEFORE Alpine's like so:\n\n```alpine\n<html>\n    <script src=\"/js/foo.js\" defer></script>\n    <script src=\"/js/alpine.js\" defer></script>\n\n    <div x-data x-foo></div>\n</html>\n```\n\n<a name=\"via-npm\"></a>\n### Via an NPM module\n\nIf you imported Alpine into a bundle, you have to make sure you are registering any extension code IN BETWEEN when you import the `Alpine` global object, and when you initialize Alpine by calling `Alpine.start()`. For example:\n\n```js\nimport Alpine from 'alpinejs'\n\nAlpine.directive('foo', ...)\n\nwindow.Alpine = Alpine\nwindow.Alpine.start()\n```\n\nNow that we know where to use these extension APIs, let's look more closely at how to use each one:\n\n<a name=\"custom-directives\"></a>\n## Custom directives\n\nAlpine allows you to register your own custom directives using the `Alpine.directive()` API.\n\n<a name=\"method-signature\"></a>\n### Method Signature\n\n```js\nAlpine.directive('[name]', (el, { value, modifiers, expression }, { Alpine, effect, cleanup }) => {})\n```\n\n&nbsp; | &nbsp;\n---|---\nname | The name of the directive. The name \"foo\" for example would be consumed as `x-foo`\nel | The DOM element the directive is added to\nvalue | If provided, the part of the directive after a colon. Ex: `'bar'` in `x-foo:bar`\nmodifiers | An array of dot-separated trailing additions to the directive. Ex: `['baz', 'lob']` from `x-foo.baz.lob`\nexpression | The attribute value portion of the directive. Ex: `law` from `x-foo=\"law\"`\nAlpine | The Alpine global object\neffect | A function to create reactive effects that will auto-cleanup after this directive is removed from the DOM\ncleanup | A function you can pass bespoke callbacks to that will run when this directive is removed from the DOM\n\n<a name=\"simple-example\"></a>\n### Simple Example\n\nHere's an example of a simple directive we're going to create called: `x-uppercase`:\n\n```js\nAlpine.directive('uppercase', el => {\n    el.textContent = el.textContent.toUpperCase()\n})\n```\n```alpine\n<div x-data>\n    <span x-uppercase>Hello World!</span>\n</div>\n```\n\n<a name=\"evaluating-expressions\"></a>\n### Evaluating expressions\n\nWhen registering a custom directive, you may want to evaluate a user-supplied JavaScript expression:\n\nFor example, let's say you wanted to create a custom directive as a shortcut to `console.log()`. Something like:\n\n```alpine\n<div x-data=\"{ message: 'Hello World!' }\">\n    <div x-log=\"message\"></div>\n</div>\n```\n\nYou need to retrieve the actual value of `message` by evaluating it as a JavaScript expression with the `x-data` scope.\n\nFortunately, Alpine exposes its system for evaluating JavaScript expressions with an `evaluate()` API. Here's an example:\n\n```js\nAlpine.directive('log', (el, { expression }, { evaluate }) => {\n    // expression === 'message'\n\n    console.log(\n        evaluate(expression)\n    )\n})\n```\n\nNow, when Alpine initializes the `<div x-log...>`, it will retrieve the expression passed into the directive (\"message\" in this case), and evaluate it in the context of the current element's Alpine component scope.\n\n<a name=\"introducing-reactivity\"></a>\n### Introducing reactivity\n\nBuilding on the `x-log` example from before, let's say we wanted `x-log` to log the value of `message` and also log it if the value changes.\n\nGiven the following template:\n\n```alpine\n<div x-data=\"{ message: 'Hello World!' }\">\n    <div x-log=\"message\"></div>\n\n    <button @click=\"message = 'yolo'\">Change</button>\n</div>\n```\n\nWe want \"Hello World!\" to be logged initially, then we want \"yolo\" to be logged after pressing the `<button>`.\n\nWe can adjust the implementation of `x-log` and introduce two new APIs to achieve this: `evaluateLater()` and `effect()`:\n\n```js\nAlpine.directive('log', (el, { expression }, { evaluateLater, effect }) => {\n    let getThingToLog = evaluateLater(expression)\n\n    effect(() => {\n        getThingToLog(thingToLog => {\n            console.log(thingToLog)\n        })\n    })\n})\n```\n\nLet's walk through the above code, line by line.\n\n```js\nlet getThingToLog = evaluateLater(expression)\n```\n\nHere, instead of immediately evaluating `message` and retrieving the result, we will convert the string expression (\"message\") into an actual JavaScript function that we can run at any time. If you're going to evaluate a JavaScript expression more than once, it is highly recommended to first generate a JavaScript function and use that rather than calling `evaluate()` directly. The reason being that the process to interpret a plain string as a JavaScript function is expensive and should be avoided when unnecessary.\n\n```js\neffect(() => {\n    ...\n})\n```\n\nBy passing in a callback to `effect()`, we are telling Alpine to run the callback immediately, then track any dependencies it uses (`x-data` properties like `message` in our case). Now as soon as one of the dependencies changes, this callback will be re-run. This gives us our \"reactivity\".\n\nYou may recognize this functionality from `x-effect`. It is the same mechanism under the hood.\n\nYou may also notice that `Alpine.effect()` exists and wonder why we're not using it here. The reason is that the `effect` function provided via the method parameter has special functionality that cleans itself up when the directive is removed from the page for any reason.\n\nFor example, if for some reason the element with `x-log` on it got removed from the page, by using `effect()` instead of `Alpine.effect()` when the `message` property is changed, the value will no longer be logged to the console.\n\n[→ Read more about reactivity in Alpine](/advanced/reactivity)\n\n```js\ngetThingToLog(thingToLog => {\n    console.log(thingToLog)\n})\n```\n\nNow we will call `getThingToLog`, which if you recall is the actual JavaScript function version of the string expression: \"message\".\n\nYou might expect `getThingToCall()` to return the result right away, but instead Alpine requires you to pass in a callback to receive the result.\n\nThe reason for this is to support async expressions like `await getMessage()`. By passing in a \"receiver\" callback instead of getting the result immediately, you are allowing your directive to work with async expressions as well.\n\n[→ Read more about async in Alpine](/advanced/async)\n\n<a name=\"cleaning-up\"></a>\n### Cleaning Up\n\nLet's say you needed to register an event listener from a custom directive. After that directive is removed from the page for any reason, you would want to remove the event listener as well.\n\nAlpine makes this simple by providing you with a `cleanup` function when registering custom directives.\n\nHere's an example:\n\n```js\nAlpine.directive('...', (el, {}, { cleanup }) => {\n    let handler = () => {}\n\n    window.addEventListener('click', handler)\n\n    cleanup(() => {\n        window.removeEventListener('click', handler)\n    })\n\n})\n```\n\nNow if the directive is removed from this element or the element is removed itself, the event listener will be removed as well.\n\n<a name=\"custom-order\"></a>\n### Custom order\n\nBy default, any new directive will run after the majority of the standard ones (with the exception of `x-teleport`). This is usually acceptable but some times you might need to run your custom directive before another specific one.\nThis can be achieved by chaining the `.before() function to `Alpine.directive()` and specifying which directive needs to run after your custom one.\n\n```js\nAlpine.directive('foo', (el, { value, modifiers, expression }) => {\n    Alpine.addScopeToNode(el, {foo: 'bar'})\n}).before('bind')\n```\n```alpine\n<div x-data>\n    <span x-foo x-bind:foo=\"foo\"></span>\n</div>\n```\n> Note, the directive name must be written without the `x-` prefix (or any other custom prefix you may use).\n\n<a name=\"custom-magics\"></a>\n## Custom magics\n\nAlpine allows you to register custom \"magics\" (properties or methods) using `Alpine.magic()`. Any magic you register will be available to all your application's Alpine code with the `$` prefix.\n\n<a name=\"method-signature\"></a>\n### Method Signature\n\n```js\nAlpine.magic('[name]', (el, { Alpine }) => {})\n```\n\n&nbsp; | &nbsp;\n---|---\nname | The name of the magic. The name \"foo\" for example would be consumed as `$foo`\nel | The DOM element the magic was triggered from\nAlpine | The Alpine global object\n\n<a name=\"magic-properties\"></a>\n### Magic Properties\n\nHere's a basic example of a \"$now\" magic helper to easily get the current time from anywhere in Alpine:\n\n```js\nAlpine.magic('now', () => {\n    return (new Date).toLocaleTimeString()\n})\n```\n```alpine\n<span x-text=\"$now\"></span>\n```\n\nNow the `<span>` tag will contain the current time, resembling something like \"12:00:00 PM\".\n\nAs you can see `$now` behaves like a static property, but under the hood is actually a getter that evaluates every time the property is accessed.\n\nBecause of this, you can implement magic \"functions\" by returning a function from the getter.\n\n<a name=\"magic-functions\"></a>\n### Magic Functions\n\nFor example, if we wanted to create a `$clipboard()` magic function that accepts a string to copy to clipboard, we could implement it like so:\n\n```js\nAlpine.magic('clipboard', () => {\n    return subject => navigator.clipboard.writeText(subject)\n})\n```\n```alpine\n<button @click=\"$clipboard('hello world')\">Copy \"Hello World\"</button>\n```\n\nNow that accessing `$clipboard` returns a function itself, we can immediately call it and pass it an argument like we see in the template with `$clipboard('hello world')`.\n\nYou can use the more brief syntax (a double arrow function) for returning a function from a function if you'd prefer:\n\n```js\nAlpine.magic('clipboard', () => subject => {\n    navigator.clipboard.writeText(subject)\n})\n```\n\n<a name=\"writing-and-sharing-plugins\"></a>\n## Writing and sharing plugins\n\nBy now you should see how friendly and simple it is to register your own custom directives and magics in your application, but what about sharing that functionality with others via an NPM package or something?\n\nYou can get started quickly with Alpine's official \"plugin-blueprint\" package. It's as simple as cloning the repository and running `npm install && npm run build` to get a plugin authored.\n\nFor demonstration purposes, let's create a pretend Alpine plugin from scratch called `Foo` that includes both a directive (`x-foo`) and a magic (`$foo`).\n\nWe'll start producing this plugin for consumption as a simple `<script>` tag alongside Alpine, then we'll level it up to a module for importing into a bundle:\n\n<a name=\"script-include\"></a>\n### Script include\n\nLet's start in reverse by looking at how our plugin will be included into a project:\n\n```alpine\n<html>\n    <script src=\"/js/foo.js\" defer></script>\n    <script src=\"/js/alpine.js\" defer></script>\n\n    <div x-data x-init=\"$foo()\">\n        <span x-foo=\"'hello world'\">\n    </div>\n</html>\n```\n\nNotice how our script is included BEFORE Alpine itself. This is important, otherwise, Alpine would have already been initialized by the time our plugin got loaded.\n\nNow let's look inside of `/js/foo.js`'s contents:\n\n```js\ndocument.addEventListener('alpine:init', () => {\n    window.Alpine.directive('foo', ...)\n\n    window.Alpine.magic('foo', ...)\n})\n```\n\nThat's it! Authoring a plugin for inclusion via a script tag is extremely simple with Alpine.\n\n<a name=\"bundle-module\"></a>\n### Bundle module\n\nNow let's say you wanted to author a plugin that someone could install via NPM and include into their bundle.\n\nLike the last example, we'll walk through this in reverse, starting with what it will look like to consume this plugin:\n\n```js\nimport Alpine from 'alpinejs'\n\nimport foo from 'foo'\nAlpine.plugin(foo)\n\nwindow.Alpine = Alpine\nwindow.Alpine.start()\n```\n\nYou'll notice a new API here: `Alpine.plugin()`. This is a convenience method Alpine exposes to prevent consumers of your plugin from having to register multiple different directives and magics themselves.\n\nNow let's look at the source of the plugin and what gets exported from `foo`:\n\n```js\nexport default function (Alpine) {\n    Alpine.directive('foo', ...)\n    Alpine.magic('foo', ...)\n}\n```\n\nYou'll see that `Alpine.plugin` is incredibly simple. It accepts a callback and immediately invokes it while providing the `Alpine` global as a parameter for use inside of it.\n\nThen you can go about extending Alpine as you please.\n\n<a name=\"deferring-initialization\"></a>\n## Deferring initialization\n\nAlpine initializes a tree of elements synchronously. Integrations that load JavaScript for a component asynchronously — a script module that registers an `Alpine.data()` provider, for example — can lose that race: Alpine evaluates `x-data=\"someComponent\"` before the registration exists.\n\n`Alpine.deferInit(el, promise)` suspends initialization of one element's tree until a promise settles. Nothing inside the tree initializes while it's suspended: directives don't evaluate, nodes added inside it wait, and attribute changes are held and replayed when the tree resumes. The rest of the page initializes normally.\n\n```js\nAlpine.interceptInit(el => {\n    if (el.hasAttribute('data-widget') && ! widgetIsLoaded(el)) {\n        Alpine.deferInit(el, loadWidget(el))\n    }\n})\n```\n\n(`Alpine.interceptInit()` is Alpine's low-level integration hook — its callback runs for every element just before that element initializes.)\n\nA few things to know about the contract:\n\n- Registering must happen synchronously — from an `Alpine.interceptInit()` callback before the element initializes, or on an already-initialized element to suspend future activity in its tree (a morph that's about to bring in new markup, for example).\n- Calling `deferInit()` on the same element again before it resumes adds another prerequisite: the tree initializes after every registered promise settles.\n- A rejected promise is reported through Alpine's error handler, then the tree initializes anyway — a failed prerequisite never leaves a tree permanently suspended.\n- If the element has left the DOM by the time the promise settles, nothing happens. If it re-enters later, it initializes like any other added node.\n- When a suspended tree resumes, init interceptors run again for elements that hadn't initialized yet. Only defer while your prerequisite is still outstanding — like the `widgetIsLoaded()` check above — so the resume pass initializes normally instead of suspending again.\n- `[x-cloak]` attributes inside a suspended tree stay in place until it resumes, so the existing cloaking pattern hides not-yet-ready content.\n- `alpine:initialized` does not wait for suspended trees — it fires when the synchronous pass over the page completes.\n- The promise is expected to settle. A prerequisite that never settles leaves its tree suspended indefinitely — put timeouts on operations that need them before handing the promise to Alpine.\n\n<!-- File: packages/docs/src/en/advanced/reactivity.md (Tokens: ~1012 | Category: anthropic-skill) -->\n---\norder: 2\ntitle: Reactivity\n---\n\n# Reactivity\n\nAlpine is \"reactive\" in the sense that when you change a piece of data, everything that depends on that data \"reacts\" automatically to that change.\n\nEvery bit of reactivity that takes place in Alpine, happens because of two very important reactive functions in Alpine's core: `Alpine.reactive()`, and `Alpine.effect()`.\n\n> Alpine uses VueJS's reactivity engine under the hood to provide these functions.\n> [→ Browse the @vue/reactivity source](https://github.com/vuejs/core/tree/main/packages/reactivity)\n\nUnderstanding these two functions will give you super powers as an Alpine developer, but also just as a web developer in general.\n\n<a name=\"alpine-reactive\"></a>\n## Alpine.reactive()\n\nLet's first look at `Alpine.reactive()`. This function accepts a JavaScript object as its parameter and returns a \"reactive\" version of that object. For example:\n\n```js\nlet data = { count: 1 }\n\nlet reactiveData = Alpine.reactive(data)\n```\n\nUnder the hood, when `Alpine.reactive` receives `data`, it wraps it inside a custom JavaScript proxy.\n\nA proxy is a special kind of object in JavaScript that can intercept \"get\" and \"set\" calls to a JavaScript object.\n\n[→ Read more about JavaScript proxies](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy)\n\nAt face value, `reactiveData` should behave exactly like `data`. For example:\n\n```js\nconsole.log(data.count) // 1\nconsole.log(reactiveData.count) // 1\n\nreactiveData.count = 2\n\nconsole.log(data.count) // 2\nconsole.log(reactiveData.count) // 2\n```\n\nWhat you see here is that because `reactiveData` is a thin wrapper around `data`, any attempts to get or set a property will behave exactly as if you had interacted with `data` directly.\n\nThe main difference here is that any time you modify or retrieve (get or set) a value from `reactiveData`, Alpine is aware of it and can execute any other logic that depends on this data.\n\n`Alpine.reactive` is only the first half of the story. `Alpine.effect` is the other half, let's dig in.\n\n<a name=\"alpine-effect\"></a>\n## Alpine.effect()\n\n`Alpine.effect` accepts a single callback function. As soon as `Alpine.effect` is called, it runs the provided function and watches for reads from reactive data. Each reactive property read during that execution becomes a dependency. When one of those properties changes later, Alpine runs the callback again. For example:\n\n```js\nlet data = Alpine.reactive({ count: 1 })\n\nAlpine.effect(() => {\n    console.log(data.count)\n})\n```\n\nWhen this code is first run, \"1\" will be logged to the console. Any time `data.count` changes, its value will be logged to the console again.\n\nThis is the mechanism that unlocks all of the reactivity at the core of Alpine.\n\n### How dependency tracking works\n\nDependency collection happens while the effect callback is running. Reading `data.count` inside the callback registers that property with the effect. Changing `data.count` later notifies the effect, which runs again and collects the dependencies used by that execution.\n\nReads made after the callback has returned, such as inside a `setTimeout` callback, are not automatically tracked by the original effect.\n\nAlpine delegates this behavior to Vue's reactivity package. For a deeper explanation of the proxy, dependency-map, and `track`/`trigger` model, see [Vue's reactivity internals](https://frontendatlas.com/vue/trivia/vue-reactivity-system).\n\nTo connect the dots further, let's look at a simple \"counter\" component example without using Alpine syntax at all, only using `Alpine.reactive` and `Alpine.effect`:\n\n```alpine\n<button>Increment</button>\n\nCount: <span></span>\n```\n```js\nlet button = document.querySelector('button')\nlet span = document.querySelector('span')\n\nlet data = Alpine.reactive({ count: 1 })\n\nAlpine.effect(() => {\n    span.textContent = data.count\n})\n\nbutton.addEventListener('click', () => {\n    data.count = data.count + 1\n})\n```\n\n<!-- START_VERBATIM -->\n<div x-data=\"{ count: 1 }\" class=\"demo\">\n    <button @click=\"count++\">Increment</button>\n\n    <div>Count: <span x-text=\"count\"></span></div>\n</div>\n<!-- END_VERBATIM -->\n\nAs you can see, you can make any data reactive, and you can also wrap any functionality in `Alpine.effect`.\n\nThis combination unlocks an incredibly powerful programming paradigm for web development. Run wild and free.\n\n<!-- File: packages/docs/src/en/directives.md (Tokens: ~26 | Category: anthropic-skill) -->\n---\norder: 4\ntitle: Directives\nprefix: x-\nfont-type: mono\ntype: sub-directory\n---\n\n<!-- File: packages/docs/src/en/directives/bind.md (Tokens: ~1515 | Category: anthropic-skill) -->\n---\norder: 4\ntitle: bind\n---\n\n# x-bind\n\n`x-bind` allows you to set HTML attributes on elements based on the result of JavaScript expressions.\n\nFor example, here's a component where we will use `x-bind` to set the placeholder value of an input.\n\n```alpine\n<div x-data=\"{ placeholderText: 'Type here...' }\">\n    <input type=\"text\" x-bind:placeholder=\"placeholderText\">\n</div>\n```\n\n<a name=\"shorthand-syntax\"></a>\n## Shorthand syntax\n\nIf `x-bind:` is too verbose for your liking, you can use the shorthand: `:`. For example, here is the same input element as above, but refactored to use the shorthand syntax.\n\n```alpine\n<input type=\"text\" :placeholder=\"placeholderText\">\n```\n\n> Despite not being included in the above snippet, `x-bind` cannot be used if no parent element has `x-data` defined. [→ Read more about `x-data`](/directives/data)\n\n<a name=\"binding-classes\"></a>\n## Binding classes\n\n`x-bind` is most often useful for setting specific classes on an element based on your Alpine state.\n\nHere's a simple example of a simple dropdown toggle, but instead of using `x-show`, we'll use a \"hidden\" class to toggle an element.\n\n```alpine\n<div x-data=\"{ open: false }\">\n    <button x-on:click=\"open = ! open\">Toggle Dropdown</button>\n\n    <div :class=\"open ? '' : 'hidden'\">\n        Dropdown Contents...\n    </div>\n</div>\n```\n\nNow, when `open` is `false`, the \"hidden\" class will be added to the dropdown.\n\n<a name=\"shorthand-conditionals\"></a>\n### Shorthand conditionals\n\nIn cases like these, if you prefer a less verbose syntax you can use JavaScript's short-circuit evaluation instead of standard conditionals:\n\n```alpine\n<div :class=\"show ? '' : 'hidden'\">\n<!-- Is equivalent to: -->\n<div :class=\"show || 'hidden'\">\n```\n\nThe inverse is also available to you. Suppose instead of `open`, we use a variable with the opposite value: `closed`.\n\n```alpine\n<div :class=\"closed ? 'hidden' : ''\">\n<!-- Is equivalent to: -->\n<div :class=\"closed && 'hidden'\">\n```\n\n<a name=\"class-object-syntax\"></a>\n### Class object syntax\n\nAlpine offers an additional syntax for toggling classes if you prefer. By passing a JavaScript object where the classes are the keys and booleans are the values, Alpine will know which classes to apply and which to remove. For example:\n\n```alpine\n<div :class=\"{ 'hidden': ! show }\">\n```\n\nThis technique offers a unique advantage to other methods. When using object-syntax, Alpine will NOT preserve original classes applied to an element's `class` attribute.\n\nFor example, if you wanted to apply the \"hidden\" class to an element before Alpine loads, AND use Alpine to toggle its existence you can only achieve that behavior using object-syntax:\n\n```alpine\n<div class=\"hidden\" :class=\"{ 'hidden': ! show }\">\n```\n\nIn case that confused you, let's dig deeper into how Alpine handles `x-bind:class` differently than other attributes.\n\n<a name=\"special-behavior\"></a>\n### Special behavior\n\n`x-bind:class` behaves differently than other attributes under the hood.\n\nConsider the following case.\n\n```alpine\n<div class=\"opacity-50\" :class=\"hide && 'hidden'\">\n```\n\nIf \"class\" were any other attribute, the `:class` binding would overwrite any existing class attribute, causing `opacity-50` to be overwritten by either `hidden` or `''`.\n\nHowever, Alpine treats `class` bindings differently. It's smart enough to preserve existing classes on an element.\n\nFor example, if `hide` is true, the above example will result in the following DOM element:\n\n```alpine\n<div class=\"opacity-50 hidden\">\n```\n\nIf `hide` is false, the DOM element will look like:\n\n```alpine\n<div class=\"opacity-50\">\n```\n\nThis behavior should be invisible and intuitive to most users, but it is worth mentioning explicitly for the inquiring developer or any special cases that might crop up.\n\n<a name=\"binding-styles\"></a>\n## Binding styles\n\nSimilar to the special syntax for binding classes with JavaScript objects, Alpine also offers an object-based syntax for binding `style` attributes.\n\nJust like the class objects, this syntax is entirely optional. Only use it if it affords you some advantage.\n\n```alpine\n<div :style=\"{ color: 'red', display: 'flex' }\">\n\n<!-- Will render: -->\n<div style=\"color: red; display: flex;\" ...>\n```\n\nConditional inline styling is possible using expressions just like with x-bind:class. Short circuit operators can be used here as well by using a styles object as the second operand.\n```alpine\n<div x-bind:style=\"true && { color: 'red' }\">\n\n<!-- Will render: -->\n<div style=\"color: red;\">\n```\n\nOne advantage of this approach is being able to mix it in with existing styles on an element:\n\n```alpine\n<div style=\"padding: 1rem;\" :style=\"{ color: 'red', display: 'flex' }\">\n\n<!-- Will render: -->\n<div style=\"padding: 1rem; color: red; display: flex;\" ...>\n```\n\nAnd like most expressions in Alpine, you can always use the result of a JavaScript expression as the reference:\n\n```alpine\n<div x-data=\"{ styles: { color: 'red', display: 'flex' }}\">\n    <div :style=\"styles\">\n</div>\n\n<!-- Will render: -->\n<div ...>\n    <div style=\"color: red; display: flex;\" ...>\n</div>\n```\n\n<a name=\"bind-directives\"></a>\n## Binding Alpine Directives Directly\n\n`x-bind` allows you to bind an object of different directives and attributes to an element.\n\nThe object keys can be anything you would normally write as an attribute name in Alpine. This includes Alpine directives and modifiers, but also plain HTML attributes. The object values are either plain strings, or in the case of dynamic Alpine directives, callbacks to be evaluated by Alpine.\n\n```alpine\n<div x-data=\"dropdown\">\n    <button x-bind=\"trigger\">Open Dropdown</button>\n\n    <span x-bind=\"dialogue\">Dropdown Contents</span>\n</div>\n\n<script>\n    document.addEventListener('alpine:init', () => {\n        Alpine.data('dropdown', () => ({\n            open: false,\n\n            trigger: {\n                ['x-ref']: 'trigger',\n                ['@click']() {\n                    this.open = true\n                },\n            },\n\n            dialogue: {\n                ['x-show']() {\n                    return this.open\n                },\n                ['@click.outside']() {\n                    this.open = false\n                },\n            },\n        }))\n    })\n</script>\n```\n\nThere are a couple of caveats to this usage of `x-bind`:\n\n> When the directive being \"bound\" or \"applied\" is `x-for`, you should return a normal expression string from the callback. For example: `['x-for']() { return 'item in items' }`\n\n<!-- File: packages/docs/src/en/directives/cloak.md (Tokens: ~457 | Category: anthropic-skill) -->\n---\norder: 12\ntitle: cloak\n---\n\n# x-cloak\n\nSometimes, when you're using AlpineJS for a part of your template, there is a \"blip\" where you might see your uninitialized template after the page loads, but before Alpine loads.\n\n`x-cloak` addresses this scenario by hiding the element it's attached to until Alpine is fully loaded on the page.\n\nFor `x-cloak` to work however, you must add the following CSS to the page.\n\n```css\n[x-cloak] { display: none !important; }\n```\n\nThe following example will hide the `<span>` tag until its `x-show` is specifically set to true, preventing any \"blip\" of the hidden element onto screen as Alpine loads.\n\n```alpine\n<span x-cloak x-show=\"false\">This will not 'blip' onto screen at any point</span>\n```\n\n`x-cloak` doesn't just work on elements hidden by `x-show` or `x-if`: it also ensures that elements containing data are hidden until the data is correctly set. The following example will hide the `<span>` tag until Alpine has set its text content to the `message` property.\n\n```alpine\n<span x-cloak x-text=\"message\"></span>\n```\n\nWhen Alpine loads on the page, it removes all `x-cloak` property from the element, which also removes the `display: none;` applied by CSS, therefore showing the element.\n\n## Alternative to global syntax\n\nIf you'd like to achieve this same behavior, but avoid having to include a global style, you can use the following cool, but admittedly odd trick:\n\n```alpine\n<template x-if=\"true\">\n    <span x-text=\"message\"></span>\n</template>\n```\n\nThis will achieve the same goal as `x-cloak` by just leveraging the way `x-if` works.\n\nBecause `<template>` elements are \"hidden\" in browsers by default, you won't see the `<span>` until Alpine has had a chance to render the `x-if=\"true\"` and show it.\n\nAgain, this solution is not for everyone, but it's worth mentioning for special cases.\n\n<!-- File: packages/docs/src/en/directives/data.md (Tokens: ~1129 | Category: anthropic-skill) -->\n---\norder: 1\ntitle: data\n---\n\n# x-data\n\nEverything in Alpine starts with the `x-data` directive.\n\n`x-data` defines a chunk of HTML as an Alpine component and provides the reactive data for that component to reference.\n\nHere's an example of a contrived dropdown component:\n\n```alpine\n<div x-data=\"{ open: false }\">\n    <button @click=\"open = ! open\">Toggle Content</button>\n\n    <div x-show=\"open\">\n        Content...\n    </div>\n</div>\n```\n\nDon't worry about the other directives in this example (`@click` and `x-show`), we'll get to those in a bit. For now, let's focus on `x-data`.\n\n<a name=\"scope\"></a>\n## Scope\n\nProperties defined in an `x-data` directive are available to all element children. Even ones inside other, nested `x-data` components.\n\nFor example:\n\n```alpine\n<div x-data=\"{ foo: 'bar' }\">\n    <span x-text=\"foo\"><!-- Will output: \"bar\" --></span>\n\n    <div x-data=\"{ bar: 'baz' }\">\n        <span x-text=\"foo\"><!-- Will output: \"bar\" --></span>\n\n        <div x-data=\"{ foo: 'bob' }\">\n            <span x-text=\"foo\"><!-- Will output: \"bob\" --></span>\n        </div>\n    </div>\n</div>\n```\n\n<a name=\"methods\"></a>\n## Methods\n\nBecause `x-data` is evaluated as a normal JavaScript object, in addition to state, you can store methods and even getters.\n\nFor example, let's extract the \"Toggle Content\" behavior into a method on  `x-data`.\n\n```alpine\n<div x-data=\"{ open: false, toggle() { this.open = ! this.open } }\">\n    <button @click=\"toggle()\">Toggle Content</button>\n\n    <div x-show=\"open\">\n        Content...\n    </div>\n</div>\n```\n\nNotice the added `toggle() { this.open = ! this.open }` method on `x-data`. This method can now be called from anywhere inside the component.\n\nYou'll also notice the usage of `this.` to access state on the object itself. This is because Alpine evaluates this data object like any standard JavaScript object with a `this` context.\n\nIf you prefer, you can leave the calling parenthesis off of the `toggle` method completely. For example:\n\n```alpine\n<!-- Before -->\n<button @click=\"toggle()\">...</button>\n\n<!-- After -->\n<button @click=\"toggle\">...</button>\n```\n\n<a name=\"getters\"></a>\n## Getters\n\nJavaScript [getters](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/get) are handy when the sole purpose of a method is to return data based on other state.\n\nThink of them like \"computed properties\" (although, they are not cached like Vue's computed properties).\n\nLet's refactor our component to use a getter called `isOpen` instead of accessing `open` directly.\n\n```alpine\n<div x-data=\"{\n    open: false,\n    get isOpen() { return this.open },\n    toggle() { this.open = ! this.open },\n}\">\n    <button @click=\"toggle()\">Toggle Content</button>\n\n    <div x-show=\"isOpen\">\n        Content...\n    </div>\n</div>\n```\n\nNotice the \"Content\" now depends on the `isOpen` getter instead of the `open` property directly.\n\nIn this case there is no tangible benefit. But in some cases, getters are helpful for providing a more expressive syntax in your components.\n\n<a name=\"data-less-components\"></a>\n## Data-less components\n\nOccasionally, you want to create an Alpine component, but you don't need any data.\n\nIn these cases, you can always pass in an empty object.\n\n```alpine\n<div x-data=\"{}\">\n```\n\nHowever, if you wish, you can also eliminate the attribute value entirely if it looks better to you.\n\n```alpine\n<div x-data>\n```\n\n<a name=\"single-element-components\"></a>\n## Single-element components\n\nSometimes you may only have a single element inside your Alpine component, like the following:\n\n```alpine\n<div x-data=\"{ open: true }\">\n    <button @click=\"open = false\" x-show=\"open\">Hide Me</button>\n</div>\n```\n\nIn these cases, you can declare `x-data` directly on that single element:\n\n```alpine\n<button x-data=\"{ open: true }\" @click=\"open = false\" x-show=\"open\">\n    Hide Me\n</button>\n```\n\n<a name=\"re-usable-data\"></a>\n## Re-usable Data\n\nIf you find yourself duplicating the contents of `x-data`, or you find the inline syntax verbose, you can extract the `x-data` object out to a dedicated component using `Alpine.data`.\n\nHere's a quick example:\n\n```alpine\n<div x-data=\"dropdown\">\n    <button @click=\"toggle\">Toggle Content</button>\n\n    <div x-show=\"open\">\n        Content...\n    </div>\n</div>\n\n<script>\n    document.addEventListener('alpine:init', () => {\n        Alpine.data('dropdown', () => ({\n            open: false,\n\n            toggle() {\n                this.open = ! this.open\n            },\n        }))\n    })\n</script>\n```\n\n[→ Read more about `Alpine.data(...)`](/globals/alpine-data)\n\n<!-- File: packages/docs/src/en/directives/effect.md (Tokens: ~200 | Category: anthropic-skill) -->\n---\norder: 11\ntitle: effect\n---\n\n# x-effect\n\n`x-effect` is a useful directive for re-evaluating an expression when one of its dependencies change. You can think of it as a watcher where you don't have to specify what property to watch, it will watch all properties used within it.\n\nIf this definition is confusing for you, that's ok. It's better explained through an example:\n\n```alpine\n<div x-data=\"{ label: 'Hello' }\" x-effect=\"console.log(label)\">\n    <button @click=\"label += ' World!'\">Change Message</button>\n</div>\n```\n\nWhen this component is loaded, the `x-effect` expression will be run and \"Hello\" will be logged into the console.\n\nBecause Alpine knows about any property references contained within `x-effect`, when the button is clicked and `label` is changed, the effect will be re-triggered and \"Hello World!\" will be logged to the console.\n\n<!-- File: packages/docs/src/en/directives/for.md (Tokens: ~1002 | Category: anthropic-skill) -->\n---\norder: 8\ntitle: for\n---\n\n# x-for\n\nAlpine's `x-for` directive allows you to create DOM elements by iterating through a list. Here's a simple example of using it to create a list of colors based on an array.\n\n```alpine\n<ul x-data=\"{ colors: ['Red', 'Orange', 'Yellow'] }\">\n    <template x-for=\"color in colors\">\n        <li x-text=\"color\"></li>\n    </template>\n</ul>\n```\n\n<!-- START_VERBATIM -->\n<div class=\"demo\">\n    <ul x-data=\"{ colors: ['Red', 'Orange', 'Yellow'] }\">\n        <template x-for=\"color in colors\">\n            <li x-text=\"color\"></li>\n        </template>\n    </ul>\n</div>\n<!-- END_VERBATIM -->\n\nYou may also pass objects to `x-for`.\n\n```alpine\n<ul x-data=\"{ car: { make: 'Jeep', model: 'Grand Cherokee', color: 'Black' } }\">\n    <template x-for=\"(value, index) in car\">\n        <li>\n            <span x-text=\"index\"></span>: <span x-text=\"value\"></span>\n        </li>\n    </template>\n</ul>\n```\n\n<!-- START_VERBATIM -->\n<div class=\"demo\">\n    <ul x-data=\"{ car: { make: 'Jeep', model: 'Grand Cherokee', color: 'Black' } }\">\n        <template x-for=\"(value, index) in car\">\n            <li>\n                <span x-text=\"index\"></span>: <span x-text=\"value\"></span>\n            </li>\n        </template>\n    </ul>\n</div>\n<!-- END_VERBATIM -->\n\nThere are two rules worth noting about `x-for`:\n\n> `x-for` MUST be declared on a `<template>` element.\n> That `<template>` element MUST contain only one root element\n\n<a name=\"keys\"></a>\n## Keys\n\nIt is important to specify unique keys for each `x-for` iteration if you are going to be re-ordering items. Without dynamic keys, Alpine may have a hard time keeping track of what re-orders and will cause odd side-effects.\n\n```alpine\n<ul x-data=\"{ colors: [\n    { id: 1, label: 'Red' },\n    { id: 2, label: 'Orange' },\n    { id: 3, label: 'Yellow' },\n]}\">\n    <template x-for=\"color in colors\" :key=\"color.id\">\n        <li x-text=\"color.label\"></li>\n    </template>\n</ul>\n```\n\nNow if the colors are added, removed, re-ordered, or their \"id\"s change, Alpine will preserve or destroy the iterated `<li>`elements accordingly.\n\n<a name=\"accessing-indexes\"></a>\n## Accessing indexes\n\nIf you need to access the index of each item in the iteration, you can do so using the `([item], [index]) in [items]` syntax like so:\n\n```alpine\n<ul x-data=\"{ colors: ['Red', 'Orange', 'Yellow'] }\">\n    <template x-for=\"(color, index) in colors\">\n        <li>\n            <span x-text=\"index + ': '\"></span>\n            <span x-text=\"color\"></span>\n        </li>\n    </template>\n</ul>\n```\n\nYou can also access the index inside a dynamic `:key` expression.\n\n```alpine\n<template x-for=\"(color, index) in colors\" :key=\"index\">\n```\n\n<a name=\"iterating-over-a-range\"></a>\n## Iterating over a range\n\nIf you need to simply loop `n` number of times, rather than iterate through an array, Alpine offers a short syntax.\n\n```alpine\n<ul>\n    <template x-for=\"i in 10\">\n        <li x-text=\"i\"></li>\n    </template>\n</ul>\n```\n\n`i` in this case can be named anything you like.\n\n> Despite not being included in the above snippet, `x-for` cannot be used if no parent element has `x-data` defined. [→ Read more about `x-data`](/directives/data)\n\n<a name=\"contents-of-a-template\"></a>\n## Contents of a `<template>`\n\nAs mentioned above, an `<template>` tag must contain only one root element.\n\nFor example, the following code will not work:\n\n```alpine\n<template x-for=\"color in colors\">\n    <span>The next color is </span><span x-text=\"color\">\n</template>\n```\n\nbut this code will work:\n```alpine\n<template x-for=\"color in colors\">\n    <p>\n        <span>The next color is </span><span x-text=\"color\">\n    </p>\n</template>\n```\n\n<!-- File: packages/docs/src/en/directives/html.md (Tokens: ~214 | Category: anthropic-skill) -->\n---\norder: 7\ntitle: html\n---\n\n# x-html\n\n`x-html` sets the \"innerHTML\" property of an element to the result of a given expression.\n\n> ⚠️ Only use on trusted content and never on user-provided content. ⚠️\n> Dynamically rendering HTML from third parties can easily lead to XSS vulnerabilities.\n\nHere's a basic example of using `x-html` to display a user's username.\n\n```alpine\n<div x-data=\"{ username: '<strong>calebporzio</strong>' }\">\n    Username: <span x-html=\"username\"></span>\n</div>\n```\n\n<!-- START_VERBATIM -->\n<div class=\"demo\">\n    <div x-data=\"{ username: '<strong>calebporzio</strong>' }\">\n        Username: <span x-html=\"username\"></span>\n    </div>\n</div>\n<!-- END_VERBATIM -->\n\nNow the `<span>` tag's inner HTML will be set to \"<strong>calebporzio</strong>\".\n\n<!-- File: packages/docs/src/en/directives/id.md (Tokens: ~297 | Category: anthropic-skill) -->\n---\norder: 17\ntitle: id\n---\n\n# x-id\n\n`x-id` allows you to declare a new \"scope\" for any new IDs generated using `$id()`. It accepts an array of strings (ID names) and adds a suffix to each `$id('...')` generated within it that is unique to other IDs on the page.\n\n`x-id` is meant to be used in conjunction with the `$id(...)` magic.\n\n[Visit the $id documentation](/magics/id) for a better understanding of this feature.\n\nHere's a brief example of this directive in use:\n\n```alpine\n<div x-id=\"['text-input']\">\n    <label :for=\"$id('text-input')\">Username</label>\n    <!-- for=\"text-input-1\" -->\n\n    <input type=\"text\" :id=\"$id('text-input')\">\n    <!-- id=\"text-input-1\" -->\n</div>\n\n<div x-id=\"['text-input']\">\n    <label :for=\"$id('text-input')\">Username</label>\n    <!-- for=\"text-input-2\" -->\n\n    <input type=\"text\" :id=\"$id('text-input')\">\n    <!-- id=\"text-input-2\" -->\n</div>\n```\n\n> Despite not being included in the above snippet, `x-id` cannot be used if no parent element has `x-data` defined. [→ Read more about `x-data`](/directives/data)\n\n<!-- File: packages/docs/src/en/directives/if.md (Tokens: ~214 | Category: anthropic-skill) -->\n---\norder: 16\ntitle: if\n---\n\n# x-if\n\n`x-if` is used for toggling elements on the page, similarly to `x-show`, however it completely adds and removes the element it's applied to rather than just changing its CSS display property to \"none\".\n\nBecause of this difference in behavior, `x-if` should not be applied directly to the element, but instead to a `<template>` tag that encloses the element. This way, Alpine can keep a record of the element once it's removed from the page.\n\n```alpine\n<template x-if=\"open\">\n    <div>Contents...</div>\n</template>\n```\n\n> Despite not being included in the above snippet, `x-if` cannot be used if no parent element has `x-data` defined. [→ Read more about `x-data`](/directives/data)\n\n## Caveats\n\nUnlike `x-show`, `x-if`, does NOT support transitioning toggles with `x-transition`.\n\n`<template>` tags can only contain one root element.\n\n<!-- File: packages/docs/src/en/directives/ignore.md (Tokens: ~144 | Category: anthropic-skill) -->\n---\norder: 11\ntitle: ignore\n---\n\n# x-ignore\n\nBy default, Alpine will crawl and initialize the entire DOM tree of an element containing `x-init` or `x-data`.\n\nIf for some reason, you don't want Alpine to touch a specific section of your HTML, you can prevent it from doing so using `x-ignore`.\n\n```alpine\n<div x-data=\"{ label: 'From Alpine' }\">\n    <div x-ignore>\n        <span x-text=\"label\"></span>\n    </div>\n</div>\n```\n\nIn the above example, the `<span>` tag will not contain \"From Alpine\" because we told Alpine to ignore the contents of the `div` completely.\n\n<!-- File: packages/docs/src/en/directives/init.md (Tokens: ~543 | Category: anthropic-skill) -->\n---\norder: 2\ntitle: init\n---\n\n# x-init\n\nThe `x-init` directive allows you to hook into the initialization phase of any element in Alpine.\n\n```alpine\n<div x-init=\"console.log('I\\'m being initialized!')\"></div>\n```\n\nIn the above example, \"I\\'m being initialized!\" will be output in the console before it makes further DOM updates.\n\nConsider another example where `x-init` is used to fetch some JSON and store it in `x-data` before the component is processed.\n\n```alpine\n<div\n    x-data=\"{ posts: [] }\"\n    x-init=\"posts = await (await fetch('/posts')).json()\"\n>...</div>\n```\n\n<a name=\"next-tick\"></a>\n## $nextTick\n\nSometimes, you want to wait until after Alpine has completely finished rendering to execute some code.\n\nThis would be something like `useEffect(..., [])` in react, or `mount` in Vue.\n\nBy using Alpine's internal `$nextTick` magic, you can make this happen.\n\n```alpine\n<div x-init=\"$nextTick(() => { ... })\"></div>\n```\n\n<a name=\"standalone-x-init\"></a>\n## Standalone `x-init`\n\nYou can add `x-init` to any elements inside or outside an `x-data` HTML block. For example:\n\n```alpine\n<div x-data>\n    <span x-init=\"console.log('I can initialize')\"></span>\n</div>\n\n<span x-init=\"console.log('I can initialize too')\"></span>\n```\n\n<a name=\"auto-evaluate-init-method\"></a>\n## Auto-evaluate init() method\n\nIf the `x-data` object of a component contains an `init()` method, it will be called automatically. For example:\n\n```alpine\n<div x-data=\"{\n    init() {\n        console.log('I am called automatically')\n    }\n}\">\n    ...\n</div>\n```\n\nThis is also the case for components that were registered using the `Alpine.data()` syntax.\n\n```js\nAlpine.data('dropdown', () => ({\n    init() {\n        console.log('I will get evaluated when initializing each \"dropdown\" component.')\n    },\n}))\n```\n\nIf you have both an `x-data` object containing an `init()` method and an `x-init` directive, the `x-data` method will be called before the directive.\n\n```alpine\n<div\n    x-data=\"{\n        init() {\n            console.log('I am called first')\n        }\n    }\"\n    x-init=\"console.log('I am called second')\"\n    >\n    ...\n</div>\n```\n\n<!-- File: packages/docs/src/en/directives/model.md (Tokens: ~3356 | Category: anthropic-skill) -->\n---\norder: 7\ntitle: model\n---\n\n# x-model\n\n`x-model` allows you to bind the value of an input element to Alpine data.\n\nHere's a simple example of using `x-model` to bind the value of a text field to a piece of data in Alpine.\n\n```alpine\n<div x-data=\"{ message: '' }\">\n    <input type=\"text\" x-model=\"message\">\n\n    <span x-text=\"message\"></span>\n</div>\n```\n\n<!-- START_VERBATIM -->\n<div class=\"demo\">\n    <div x-data=\"{ message: '' }\">\n        <input type=\"text\" x-model=\"message\" placeholder=\"Type message...\">\n\n        <div class=\"pt-4\" x-text=\"message\"></div>\n    </div>\n</div>\n<!-- END_VERBATIM -->\n\n\nNow as the user types into the text field, the `message` will be reflected in the `<span>` tag.\n\n`x-model` is two-way bound, meaning it both \"sets\" and \"gets\". In addition to changing data, if the data itself changes, the element will reflect the change.\n\n\nWe can use the same example as above but this time, we'll add a button to change the value of the `message` property.\n\n```alpine\n<div x-data=\"{ message: '' }\">\n    <input type=\"text\" x-model=\"message\">\n\n    <button x-on:click=\"message = 'changed'\">Change Message</button>\n</div>\n```\n\n<!-- START_VERBATIM -->\n<div class=\"demo\">\n    <div x-data=\"{ message: '' }\">\n        <input type=\"text\" x-model=\"message\" placeholder=\"Type message...\">\n\n        <button x-on:click=\"message = 'changed'\">Change Message</button>\n    </div>\n</div>\n<!-- END_VERBATIM -->\n\nNow when the `<button>` is clicked, the input element's value will instantly be updated to \"changed\".\n\n`x-model` works with the following input elements:\n\n* `<input type=\"text\">`\n* `<textarea>`\n* `<input type=\"checkbox\">`\n* `<input type=\"radio\">`\n* `<select>`\n* `<input type=\"range\">`\n\n<a name=\"text-inputs\"></a>\n## Text inputs\n\n```alpine\n<input type=\"text\" x-model=\"message\">\n\n<span x-text=\"message\"></span>\n```\n\n<!-- START_VERBATIM -->\n<div class=\"demo\">\n    <div x-data=\"{ message: '' }\">\n        <input type=\"text\" x-model=\"message\" placeholder=\"Type message\">\n\n        <div class=\"pt-4\" x-text=\"message\"></div>\n    </div>\n</div>\n<!-- END_VERBATIM -->\n\n> Despite not being included in the above snippet, `x-model` cannot be used if no parent element has `x-data` defined. [→ Read more about `x-data`](/directives/data)\n\n<a name=\"textarea-inputs\"></a>\n## Textarea inputs\n\n```alpine\n<textarea x-model=\"message\"></textarea>\n\n<span x-text=\"message\"></span>\n```\n\n<!-- START_VERBATIM -->\n<div class=\"demo\">\n    <div x-data=\"{ message: '' }\">\n        <textarea x-model=\"message\" placeholder=\"Type message\"></textarea>\n\n        <div class=\"pt-4\" x-text=\"message\"></div>\n    </div>\n</div>\n<!-- END_VERBATIM -->\n\n<a name=\"checkbox-inputs\"></a>\n## Checkbox inputs\n\n<a name=\"single-checkbox-with-boolean\"></a>\n### Single checkbox with boolean\n\n```alpine\n<input type=\"checkbox\" id=\"checkbox\" x-model=\"show\">\n\n<label for=\"checkbox\" x-text=\"show\"></label>\n```\n\n<!-- START_VERBATIM -->\n<div class=\"demo\">\n    <div x-data=\"{ open: '' }\">\n        <input type=\"checkbox\" id=\"checkbox\" x-model=\"open\">\n\n        <label for=\"checkbox\" x-text=\"open\"></label>\n    </div>\n</div>\n<!-- END_VERBATIM -->\n\n<a name=\"multiple-checkboxes-bound-to-array\"></a>\n### Multiple checkboxes bound to array\n\n```alpine\n<input type=\"checkbox\" value=\"red\" x-model=\"colors\">\n<input type=\"checkbox\" value=\"orange\" x-model=\"colors\">\n<input type=\"checkbox\" value=\"yellow\" x-model=\"colors\">\n\nColors: <span x-text=\"colors\"></span>\n```\n\n<!-- START_VERBATIM -->\n<div class=\"demo\">\n    <div x-data=\"{ colors: [] }\">\n        <input type=\"checkbox\" value=\"red\" x-model=\"colors\">\n        <input type=\"checkbox\" value=\"orange\" x-model=\"colors\">\n        <input type=\"checkbox\" value=\"yellow\" x-model=\"colors\">\n\n        <div class=\"pt-4\">Colors: <span x-text=\"colors\"></span></div>\n    </div>\n</div>\n<!-- END_VERBATIM -->\n\n<a name=\"radio-inputs\"></a>\n## Radio inputs\n\n```alpine\n<input type=\"radio\" value=\"yes\" x-model=\"answer\">\n<input type=\"radio\" value=\"no\" x-model=\"answer\">\n\nAnswer: <span x-text=\"answer\"></span>\n```\n\n<!-- START_VERBATIM -->\n<div class=\"demo\">\n    <div x-data=\"{ answer: '' }\">\n        <input type=\"radio\" value=\"yes\" x-model=\"answer\">\n        <input type=\"radio\" value=\"no\" x-model=\"answer\">\n\n        <div class=\"pt-4\">Answer: <span x-text=\"answer\"></span></div>\n    </div>\n</div>\n<!-- END_VERBATIM -->\n\n<a name=\"select-inputs\"></a>\n## Select inputs\n\n\n<a name=\"single-select\"></a>\n### Single select\n\n```alpine\n<select x-model=\"color\">\n    <option>Red</option>\n    <option>Orange</option>\n    <option>Yellow</option>\n</select>\n\nColor: <span x-text=\"color\"></span>\n```\n\n<!-- START_VERBATIM -->\n<div class=\"demo\">\n    <div x-data=\"{ color: '' }\">\n        <select x-model=\"color\">\n            <option>Red</option>\n            <option>Orange</option>\n            <option>Yellow</option>\n        </select>\n\n        <div class=\"pt-4\">Color: <span x-text=\"color\"></span></div>\n    </div>\n</div>\n<!-- END_VERBATIM -->\n\n<a name=\"single-select-with-placeholder\"></a>\n### Single select with placeholder\n\n```alpine\n<select x-model=\"color\">\n    <option value=\"\" disabled>Select A Color</option>\n    <option>Red</option>\n    <option>Orange</option>\n    <option>Yellow</option>\n</select>\n\nColor: <span x-text=\"color\"></span>\n```\n\n\n<!-- START_VERBATIM -->\n<div class=\"demo\">\n    <div x-data=\"{ color: '' }\">\n        <select x-model=\"color\">\n            <option value=\"\" disabled>Select A Color</option>\n            <option>Red</option>\n            <option>Orange</option>\n            <option>Yellow</option>\n        </select>\n\n        <div class=\"pt-4\">Color: <span x-text=\"color\"></span></div>\n    </div>\n</div>\n<!-- END_VERBATIM -->\n\n<a name=\"multiple-select\"></a>\n### Multiple select\n\n```alpine\n<select x-model=\"color\" multiple>\n    <option>Red</option>\n    <option>Orange</option>\n    <option>Yellow</option>\n</select>\n\nColors: <span x-text=\"color\"></span>\n```\n\n<!-- START_VERBATIM -->\n<div class=\"demo\">\n    <div x-data=\"{ color: '' }\">\n        <select x-model=\"color\" multiple>\n            <option>Red</option>\n            <option>Orange</option>\n            <option>Yellow</option>\n        </select>\n\n        <div class=\"pt-4\">Color: <span x-text=\"color\"></span></div>\n    </div>\n</div>\n<!-- END_VERBATIM -->\n\n<a name=\"dynamically-populated-select-options\"></a>\n### Dynamically populated Select Options\n\n```alpine\n<select x-model=\"color\">\n    <template x-for=\"color in ['Red', 'Orange', 'Yellow']\">\n        <option x-text=\"color\"></option>\n    </template>\n</select>\n\nColor: <span x-text=\"color\"></span>\n```\n\n<!-- START_VERBATIM -->\n<div class=\"demo\">\n    <div x-data=\"{ color: '' }\">\n        <select x-model=\"color\">\n            <template x-for=\"color in ['Red', 'Orange', 'Yellow']\">\n                <option x-text=\"color\"></option>\n            </template>\n        </select>\n\n        <div class=\"pt-4\">Color: <span x-text=\"color\"></span></div>\n    </div>\n</div>\n<!-- END_VERBATIM -->\n\n<a name=\"range-inputs\"></a>\n## Range inputs\n\n```alpine\n<input type=\"range\" x-model=\"range\" min=\"0\" max=\"1\" step=\"0.1\">\n\n<span x-text=\"range\"></span>\n```\n\n<!-- START_VERBATIM -->\n<div class=\"demo\">\n    <div x-data=\"{ range: 0.5 }\">\n        <input type=\"range\" x-model=\"range\" min=\"0\" max=\"1\" step=\"0.1\">\n\n        <div class=\"pt-4\" x-text=\"range\"></div>\n    </div>\n</div>\n<!-- END_VERBATIM -->\n\n\n<a name=\"modifiers\"></a>\n## Modifiers\n\n<a name=\"lazy\"></a>\n### `.lazy`\n\nOn text inputs, by default, `x-model` updates the property on every keystroke. By adding the `.lazy` modifier, you can force an `x-model` input to only update the property when user focuses away from the input element.\n\nThis is handy for things like real-time form-validation where you might not want to show an input validation error until the user \"tabs\" away from a field.\n\n```alpine\n<input type=\"text\" x-model.lazy=\"username\">\n<span x-show=\"username.length > 20\">The username is too long.</span>\n```\n\n<a name=\"change\"></a>\n### `.change`\n\n`.change` syncs the data only when the input loses focus and its value has changed (the native `change` event). This is functionally equivalent to `.lazy`.\n\n```alpine\n<input type=\"text\" x-model.change=\"username\">\n```\n\n<a name=\"blur\"></a>\n### `.blur`\n\n`.blur` syncs the data when the input loses focus, regardless of whether the value has changed.\n\n```alpine\n<input type=\"text\" x-model.blur=\"email\">\n```\n\n<a name=\"enter\"></a>\n### `.enter`\n\n`.enter` syncs the data when the user presses the Enter key. This is useful for search fields where you want to trigger an action only when the user explicitly submits.\n\n```alpine\n<input type=\"text\" x-model.enter=\"search\">\n```\n\n> Note: `.enter` does not prevent the default behavior. If the input is inside a form, the form will still submit.\n\n<a name=\"combining-event-modifiers\"></a>\n### Combining Event Modifiers\n\nThe `.change`, `.blur`, and `.enter` modifiers can be combined to sync on multiple events. This is useful when you want to give users flexibility in how they submit data.\n\n```alpine\n<!-- Sync on blur OR enter -->\n<input type=\"text\" x-model.blur.enter=\"search\" placeholder=\"Press Enter or click away\">\n\n<!-- Sync on change, blur, OR enter -->\n<input type=\"text\" x-model.change.blur.enter=\"message\">\n```\n\n<!-- START_VERBATIM -->\n<div class=\"demo\">\n    <div x-data=\"{ search: '' }\">\n        <input type=\"text\" x-model.blur.enter=\"search\" placeholder=\"Press Enter or click away\">\n\n        <div class=\"pt-4\">Search: <span x-text=\"search\"></span></div>\n    </div>\n</div>\n<!-- END_VERBATIM -->\n\n<a name=\"number\"></a>\n### `.number`\n\nBy default, any data stored in a property via `x-model` is stored as a string. To force Alpine to store the value as a JavaScript number, add the `.number` modifier.\n\n```alpine\n<input type=\"text\" x-model.number=\"age\">\n<span x-text=\"typeof age\"></span>\n```\n\n<a name=\"boolean\"></a>\n### `.boolean`\n\nBy default, any data stored in a property via `x-model` is stored as a string. To force Alpine to store the value as a JavaScript boolean, add the `.boolean` modifier. Both integers (1/0) and strings (true/false) are valid boolean values.\n\n```alpine\n<select x-model.boolean=\"isActive\">\n    <option value=\"true\">Yes</option>\n    <option value=\"false\">No</option>\n</select>\n<span x-text=\"typeof isActive\"></span>\n```\n\n<a name=\"debounce\"></a>\n### `.debounce`\n\nBy adding `.debounce` to `x-model`, you can easily debounce the updating of bound input.\n\nThis is useful for things like real-time search inputs that fetch new data from the server every time the search property changes.\n\n```alpine\n<input type=\"text\" x-model.debounce=\"search\">\n```\n\nThe default debounce time is 250 milliseconds, you can easily customize this by adding a time modifier like so.\n\n```alpine\n<input type=\"text\" x-model.debounce.500ms=\"search\">\n```\n\n<a name=\"throttle\"></a>\n### `.throttle`\n\nSimilar to `.debounce` you can limit the property update triggered by `x-model` to only updating on a specified interval.\n\n<input type=\"text\" x-model.throttle=\"search\">\n\nThe default throttle interval is 250 milliseconds, you can easily customize this by adding a time modifier like so.\n\n```alpine\n<input type=\"text\" x-model.throttle.500ms=\"search\">\n```\n\n<a name=\"fill\"></a>\n### `.fill`\n\nBy default, if an input has a value attribute, it is ignored by Alpine and instead, the value of the input is set to the value of the property bound using `x-model`.\n\nBut if a bound property is empty, then you can use an input's value attribute to populate the property by adding the `.fill` modifier.\n\n<div x-data=\"{ message: null }\">\n  <input type=\"text\" x-model.fill=\"message\" value=\"This is the default message.\">\n</div>\n\n<a name=\"programmatic access\"></a>\n## Programmatic access\n\nAlpine exposes under-the-hood utilities for getting and setting properties bound with `x-model`. This is useful for complex Alpine utilities that may want to override the default x-model behavior, or instances where you want to allow `x-model` on a non-input element.\n\nYou can access these utilities through a property called `_x_model` on the `x-model`ed element. `_x_model` has two methods to get and set the bound property:\n\n* `el._x_model.get()` (returns the value of the bound property)\n* `el._x_model.set()` (sets the value of the bound property)\n\n```alpine\n<div x-data=\"{ username: 'calebporzio' }\">\n    <div x-ref=\"div\" x-model=\"username\"></div>\n\n    <button @click=\"$refs.div._x_model.set('phantomatrix')\">\n        Change username to: 'phantomatrix'\n    </button>\n\n    <span x-text=\"$refs.div._x_model.get()\"></span>\n</div>\n```\n\n<!-- START_VERBATIM -->\n<div class=\"demo\">\n    <div x-data=\"{ username: 'calebporzio' }\">\n        <div x-ref=\"div\" x-model=\"username\"></div>\n\n        <button @click=\"$refs.div._x_model.set('phantomatrix')\">\n            Change username to: 'phantomatrix'\n        </button>\n\n        <span x-text=\"$refs.div._x_model.get()\"></span>\n    </div>\n</div>\n<!-- END_VERBATIM -->\n\n<!-- File: packages/docs/src/en/directives/modelable.md (Tokens: ~554 | Category: anthropic-skill) -->\n---\norder: 7\ntitle: modelable\n---\n\n# x-modelable\n\n`x-modelable` allows you to expose Alpine state as the target of the `x-model` directive.\n\nHere's a simple example of using `x-modelable` to expose a variable for binding with `x-model`.\n\n```alpine\n<div x-data=\"{ number: 5 }\">\n    <div x-data=\"{ count: 0 }\" x-modelable=\"count\" x-model=\"number\">\n        <button @click=\"count++\">Increment</button>\n    </div>\n\n    Number: <span x-text=\"number\"></span>\n</div>\n```\n\n<!-- START_VERBATIM -->\n<div class=\"demo\">\n    <div x-data=\"{ number: 5 }\">\n        <div x-data=\"{ count: 0 }\" x-modelable=\"count\" x-model=\"number\">\n            <button @click=\"count++\">Increment</button>\n        </div>\n\n        Number: <span x-text=\"number\"></span>\n    </div>\n</div>\n<!-- END_VERBATIM -->\n\nAs you can see the outer scope property \"number\" is now bound to the inner scope property \"count\".\n\nTypically this feature would be used in conjunction with a backend templating framework like Laravel Blade. It's useful for abstracting away Alpine components into backend templates and exposing state to the outside through `x-model` as if it were a native input.\n\n## Supported values\n\n`x-modelable` keeps its inner and outer state independent by cloning values as JSON. It is therefore intended for JSON-compatible state such as strings, numbers, booleans, `null`, arrays, and plain objects containing those values.\n\nBrowser objects and other state that cannot be represented as JSON won't cross this boundary intact. For example, a `File` loses properties such as its name, size, and type. The same limitation applies to values such as `FileList`, `Map`, `Set`, `Date`, class instances, and DOM nodes.\n\nFor a custom input that produces one of these values, omit `x-modelable` and [dispatch an `input` event](/magics/dispatch#dispatching-to-x-model) instead. `x-model` reads the value directly from the event without cloning it:\n\n```alpine\n<div x-data=\"{ files: [] }\">\n    <div x-model=\"files\">\n        <input\n            type=\"file\"\n            multiple\n            @change=\"$dispatch('input', Array.from($event.target.files))\"\n        >\n    </div>\n\n    <template x-for=\"file in files\" :key=\"file.name\">\n        <p x-text=\"file.name\"></p>\n    </template>\n</div>\n```\n\n<!-- File: packages/docs/src/en/directives/on.md (Tokens: ~3246 | Category: anthropic-skill) -->\n---\norder: 5\ntitle: on\n---\n\n# x-on\n\n`x-on` allows you to easily run code on dispatched DOM events.\n\nHere's an example of simple button that shows an alert when clicked.\n\n```alpine\n<button x-on:click=\"alert('Hello World!')\">Say Hi</button>\n```\n\n> `x-on` can only listen for events with lower case names, as HTML attributes are case-insensitive. Writing `x-on:CLICK` will listen for an event named `click`. If you need to listen for a custom event with a camelCase name, you can use the [`.camel` helper](#camel) to work around this limitation. Alternatively, you can use [`x-bind`](/directives/bind#bind-directives) to attach an `x-on` directive to an element in javascript code (where case will be preserved).\n\n<a name=\"shorthand-syntax\"></a>\n## Shorthand syntax\n\nIf `x-on:` is too verbose for your tastes, you can use the shorthand syntax: `@`.\n\nHere's the same component as above, but using the shorthand syntax instead:\n\n```alpine\n<button @click=\"alert('Hello World!')\">Say Hi</button>\n```\n\n> Despite not being included in the above snippet, `x-on` cannot be used if no parent element has `x-data` defined. [→ Read more about `x-data`](/directives/data)\n\n<a name=\"the-event-object\"></a>\n## The event object\n\nIf you wish to access the native JavaScript event object from your expression, you can use Alpine's magic `$event` property.\n\n```alpine\n<button @click=\"alert($event.target.getAttribute('message'))\" message=\"Hello World\">Say Hi</button>\n```\n\nIn addition, Alpine also passes the event object to any methods referenced without trailing parenthesis. For example:\n\n```alpine\n<button @click=\"handleClick\">...</button>\n\n<script>\n    function handleClick(e) {\n        // Now you can access the event object (e) directly\n    }\n</script>\n```\n\n<a name=\"keyboard-events\"></a>\n## Keyboard events\n\nAlpine makes it easy to listen for `keydown` and `keyup` events on specific keys.\n\nHere's an example of listening for the `Enter` key inside an input element.\n\n```alpine\n<input type=\"text\" @keyup.enter=\"alert('Submitted!')\">\n```\n\nYou can also chain these key modifiers to achieve more complex listeners.\n\nHere's a listener that runs when the `Shift` key is held and `Enter` is pressed, but not when `Enter` is pressed alone.\n\n```alpine\n<input type=\"text\" @keyup.shift.enter=\"alert('Submitted!')\">\n```\n\nYou can directly use any valid key names exposed via [`KeyboardEvent.key`](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key/Key_Values) as modifiers by converting them to kebab-case.\n\n```alpine\n<input type=\"text\" @keyup.page-down=\"alert('Submitted!')\">\n```\n\nFor easy reference, here is a list of common keys you may want to listen for.\n\n| Modifier                       | Keyboard Key                       |\n| ------------------------------ | ---------------------------------- |\n| `.shift`                       | Shift                              |\n| `.enter`                       | Enter                              |\n| `.space`                       | Space                              |\n| `.ctrl`                        | Ctrl                               |\n| `.cmd`                         | Cmd                                |\n| `.meta`                        | Cmd on Mac, Windows key on Windows |\n| `.alt`                         | Alt                                |\n| `.up` `.down` `.left` `.right` | Up/Down/Left/Right arrows          |\n| `.escape`                      | Escape                             |\n| `.tab`                         | Tab                                |\n| `.caps-lock`                   | Caps Lock                          |\n| `.equal`                       | Equal, `=`                         |\n| `.period`                      | Period, `.`                        |\n| `.comma`                       | Comma, `,`                         |\n| `.slash`                       | Forward Slash, `/`                 |\n\n<a name=\"mouse-events\"></a>\n## Mouse events\n\nLike the above Keyboard Events, Alpine allows the use of some key modifiers for handling `click` events.\n\n| Modifier | Event Key |\n| -------- | --------- |\n| `.shift` | shiftKey  |\n| `.ctrl`  | ctrlKey   |\n| `.cmd`   | metaKey   |\n| `.meta`  | metaKey   |\n| `.alt`   | altKey    |\n\nThese work on `click`, `auxclick`, `context` and `dblclick` events, and even `mouseover`, `mousemove`, `mouseenter`, `mouseleave`, `mouseout`, `mouseup` and `mousedown`.\n\nHere's an example of a button that changes behaviour when the `Shift` key is held down.\n\n```alpine\n<button type=\"button\"\n    x-data=\"{ message: 'select' }\"\n    @click=\"message = 'selected'\"\n    @click.shift=\"message = 'added to selection'\"\n    @mousemove.shift=\"message = 'add to selection'\"\n    @mouseout=\"message = 'select'\"\n    x-text=\"message\"></button>\n```\n\n<!-- START_VERBATIM -->\n<div class=\"demo\">\n    <div x-data=\"{ message: '' }\">\n        <button type=\"button\"\n            x-data=\"{ message: 'select' }\"\n            @click=\"message = 'selected'\"\n            @click.shift=\"message = 'added to selection'\"\n            @mousemove.shift=\"message = 'add to selection'\"\n            @mouseout=\"message = 'select'\"\n            x-text=\"message\"></button>\n    </div>\n</div>\n<!-- END_VERBATIM -->\n\n> Note: Normal click events with some modifiers (like `ctrl`) will automatically become `contextmenu` events in most browsers. Similarly, `right-click` events will trigger a `contextmenu` event, but will also trigger an `auxclick` event if the `contextmenu` event is prevented.\n\n<a name=\"custom-events\"></a>\n## Custom events\n\nAlpine event listeners are a wrapper for native DOM event listeners. Therefore, they can listen for ANY DOM event, including custom events.\n\nHere's an example of a component that dispatches a custom DOM event and listens for it as well.\n\n```alpine\n<div x-data @foo=\"alert('Button Was Clicked!')\">\n    <button @click=\"$event.target.dispatchEvent(new CustomEvent('foo', { bubbles: true }))\">...</button>\n</div>\n```\n\nWhen the button is clicked, the `@foo` listener will be called.\n\nBecause the `.dispatchEvent` API is verbose, Alpine offers a `$dispatch` helper to simplify things.\n\nHere's the same component re-written with the `$dispatch` magic property.\n\n```alpine\n<div x-data @foo=\"alert('Button Was Clicked!')\">\n    <button @click=\"$dispatch('foo')\">...</button>\n</div>\n```\n\n[→ Read more about `$dispatch`](/magics/dispatch)\n\n<a name=\"modifiers\"></a>\n## Modifiers\n\nAlpine offers a number of directive modifiers to customize the behavior of your event listeners.\n\n<a name=\"prevent\"></a>\n### .prevent\n\n`.prevent` is the equivalent of calling `.preventDefault()` inside a listener on the browser event object.\n\n```alpine\n<form @submit.prevent=\"console.log('submitted')\" action=\"/foo\">\n    <button>Submit</button>\n</form>\n```\n\nIn the above example, with the `.prevent`, clicking the button will NOT submit the form to the `/foo` endpoint. Instead, Alpine's listener will handle it and \"prevent\" the event from being handled any further.\n\n<a name=\"stop\"></a>\n### .stop\n\nSimilar to `.prevent`, `.stop` is the equivalent of calling `.stopPropagation()` inside a listener on the browser event object.\n\n```alpine\n<div @click=\"console.log('I will not get logged')\">\n    <button @click.stop>Click Me</button>\n</div>\n```\n\nIn the above example, clicking the button WON'T log the message. This is because we are stopping the propagation of the event immediately and not allowing it to \"bubble\" up to the `<div>` with the `@click` listener on it.\n\n<a name=\"outside\"></a>\n### .outside\n\n`.outside` is a convenience helper for listening for a click outside of the element it is attached to. Here's a simple dropdown component example to demonstrate:\n\n```alpine\n<div x-data=\"{ open: false }\">\n    <button @click=\"open = ! open\">Toggle</button>\n\n    <div x-show=\"open\" @click.outside=\"open = false\">\n        Contents...\n    </div>\n</div>\n```\n\nIn the above example, after showing the dropdown contents by clicking the \"Toggle\" button, you can close the dropdown by clicking anywhere on the page outside the content.\n\nThis is because `.outside` is listening for clicks that DON'T originate from the element it's registered on.\n\n> It's worth noting that the `.outside` expression will only be evaluated when the element it's registered on is visible on the page. Otherwise, there would be nasty race conditions where clicking the \"Toggle\" button would also fire the `@click.outside` handler when it is not visible.\n\n<a name=\"window\"></a>\n### .window\n\nWhen the `.window` modifier is present, Alpine will register the event listener on the root `window` object on the page instead of the element itself.\n\n```alpine\n<div @keyup.escape.window=\"...\">...</div>\n```\n\nThe above snippet will listen for the \"escape\" key to be pressed ANYWHERE on the page.\n\nAdding `.window` to listeners is extremely useful for these sorts of cases where a small part of your markup is concerned with events that take place on the entire page.\n\n<a name=\"document\"></a>\n### .document\n\n`.document` works similarly to `.window` only it registers listeners on the `document` global, instead of the `window` global.\n\n<a name=\"once\"></a>\n### .once\n\nBy adding `.once` to a listener, you are ensuring that the handler is only called ONCE.\n\n```alpine\n<button @click.once=\"console.log('I will only log once')\">...</button>\n```\n\n<a name=\"debounce\"></a>\n### .debounce\n\nSometimes it is useful to \"debounce\" an event handler so that it only is called after a certain period of inactivity (250 milliseconds by default).\n\nFor example if you have a search field that fires network requests as the user types into it, adding a debounce will prevent the network requests from firing on every single keystroke.\n\n```alpine\n<input @input.debounce=\"fetchResults\">\n```\n\nNow, instead of calling `fetchResults` after every keystroke, `fetchResults` will only be called after 250 milliseconds of no keystrokes.\n\nIf you wish to lengthen or shorten the debounce time, you can do so by trailing a duration after the `.debounce` modifier like so:\n\n```alpine\n<input @input.debounce.500ms=\"fetchResults\">\n```\n\nNow, `fetchResults` will only be called after 500 milliseconds of inactivity.\n\n<a name=\"throttle\"></a>\n### .throttle\n\n`.throttle` is similar to `.debounce` except it will release a handler call every 250 milliseconds instead of deferring it indefinitely.\n\nThis is useful for cases where there may be repeated and prolonged event firing and using `.debounce` won't work because you want to still handle the event every so often.\n\nFor example:\n\n```alpine\n<div @scroll.window.throttle=\"handleScroll\">...</div>\n```\n\nThe above example is a great use case of throttling. Without `.throttle`, the `handleScroll` method would be fired hundreds of times as the user scrolls down a page. This can really slow down a site. By adding `.throttle`, we are ensuring that `handleScroll` only gets called every 250 milliseconds.\n\n> Fun Fact: This exact strategy is used on this very documentation site to update the currently highlighted section in the right sidebar.\n\nJust like with `.debounce`, you can add a custom duration to your throttled event:\n\n```alpine\n<div @scroll.window.throttle.750ms=\"handleScroll\">...</div>\n```\n\nNow, `handleScroll` will only be called every 750 milliseconds.\n\n<a name=\"self\"></a>\n### .self\n\nBy adding `.self` to an event listener, you are ensuring that the event originated on the element it is declared on, and not from a child element.\n\n```alpine\n<button @click.self=\"handleClick\">\n    Click Me\n\n    <img src=\"...\">\n</button>\n```\n\nIn the above example, we have an `<img>` tag inside the `<button>` tag. Normally, any click originating within the `<button>` element (like on `<img>` for example), would be picked up by a `@click` listener on the button.\n\nHowever, in this case, because we've added a `.self`, only clicking the button itself will call `handleClick`. Only clicks originating on the `<img>` element will not be handled.\n\n<a name=\"camel\"></a>\n### .camel\n\n```alpine\n<div @custom-event.camel=\"handleCustomEvent\">\n    ...\n</div>\n```\n\nSometimes you may want to listen for camelCased events such as `customEvent` in our example. Because camelCasing inside HTML attributes is not supported, adding the `.camel` modifier is necessary for Alpine to camelCase the event name internally.\n\nBy adding `.camel` in the above example, Alpine is now listening for `customEvent` instead of `custom-event`.\n\n<a name=\"dot\"></a>\n### .dot\n\n```alpine\n<div @custom-event.dot=\"handleCustomEvent\">\n    ...\n</div>\n```\n\nSimilar to the `.camelCase` modifier there may be situations where you want to listen for events that have dots in their name (like `custom.event`). Since dots within the event name are reserved by Alpine you need to write them with dashes and add the `.dot` modifier.\n\nIn the code example above `custom-event.dot` will correspond to the event name `custom.event`.\n\n<a name=\"passive\"></a>\n### .passive\n\nBrowsers optimize scrolling on pages to be fast and smooth even when JavaScript is being executed on the page. However, improperly implemented touch and wheel listeners can block this optimization and cause poor site performance.\n\nIf you are listening for touch events, it's important to add `.passive` to your listeners to not block scroll performance.\n\n```alpine\n<div @touchstart.passive=\"...\">...</div>\n```\n\n[→ Read more about passive listeners](https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener#improving_scrolling_performance_with_passive_listeners)\n\n<a name=\"passive-false\"></a>\n### .passive.false\n\nIn modern browsers, touch and wheel event listeners are passive by default. Pass `.passive.false` to make these events cancelable, so that you can call `preventDefault` on them.\n\n```alpine\n<div @touchmove.passive.false=\"$event.preventDefault()\">...</div>\n```\n\n### .capture\n\nAdd this modifier if you want to execute this listener in the event's capturing phase, e.g. before the event bubbles from the target element up the DOM.\n\n```alpine\n<div @click.capture=\"console.log('I will log first')\">\n    <button @click=\"console.log('I will log second')\"></button>\n</div>\n```\n\n[→ Read more about the capturing and bubbling phase of events](https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener#usecapture)\n\n<!-- File: packages/docs/src/en/directives/ref.md (Tokens: ~192 | Category: anthropic-skill) -->\n---\norder: 11\ntitle: ref\n---\n\n# x-ref\n\n`x-ref` in combination with `$refs` is a useful utility for easily accessing DOM elements directly. It's most useful as a replacement for APIs like `getElementById` and `querySelector`.\n\n```alpine\n<button @click=\"$refs.text.remove()\">Remove Text</button>\n\n<span x-ref=\"text\">Hello 👋</span>\n```\n\n<!-- START_VERBATIM -->\n<div class=\"demo\">\n    <div x-data>\n        <button @click=\"$refs.text.remove()\">Remove Text</button>\n\n        <div class=\"pt-4\" x-ref=\"text\">Hello 👋</div>\n    </div>\n</div>\n<!-- END_VERBATIM -->\n\n> Despite not being included in the above snippet, `x-ref` cannot be used if no parent element has `x-data` defined. [→ Read more about `x-data`](/directives/data)\n\n<!-- File: packages/docs/src/en/directives/show.md (Tokens: ~473 | Category: anthropic-skill) -->\n---\norder: 3\ntitle: show\n---\n\n# x-show\n\n`x-show` is one of the most useful and powerful directives in Alpine. It provides an expressive way to show and hide DOM elements.\n\nHere's an example of a simple dropdown component using `x-show`.\n\n```alpine\n<div x-data=\"{ open: false }\">\n    <button x-on:click=\"open = ! open\">Toggle Dropdown</button>\n\n    <div x-show=\"open\">\n        Dropdown Contents...\n    </div>\n</div>\n```\n\nWhen the \"Toggle Dropdown\" button is clicked, the dropdown will show and hide accordingly.\n\n> If the \"default\" state of an `x-show` on page load is \"false\", you may want to use `x-cloak` on the page to avoid \"page flicker\" (The effect that happens when the browser renders your content before Alpine is finished initializing and hiding it.) You can learn more about `x-cloak` in its documentation.\n\n<a name=\"with-transitions\"></a>\n## With transitions\n\nIf you want to apply smooth transitions to the `x-show` behavior, you can use it in conjunction with `x-transition`. You can learn more about that directive [here](/directives/transition), but here's a quick example of the same component as above, just with transitions applied.\n\n```alpine\n<div x-data=\"{ open: false }\">\n    <button x-on:click=\"open = ! open\">Toggle Dropdown</button>\n\n    <div x-show=\"open\" x-transition>\n        Dropdown Contents...\n    </div>\n</div>\n```\n\n<a name=\"using-the-important-modifier\"></a>\n## Using the important modifier\n\nSometimes you need to apply a little more force to actually hide an element. In cases where a CSS selector applies the `display` property with the `!important` flag, it will take precedence over the inline style set by Alpine.\n\nIn these cases you may use the `.important` modifier to set the inline style to `display: none !important`.\n\n```alpine\n<div x-data=\"{ open: false }\">\n    <button x-on:click=\"open = ! open\">Toggle Dropdown</button>\n\n    <div x-show.important=\"open\">\n        Dropdown Contents...\n    </div>\n</div>\n```\n\n<!-- File: packages/docs/src/en/directives/teleport.md (Tokens: ~1310 | Category: anthropic-skill) -->\n---\norder: 12\ntitle: teleport\ndescription: Send Alpine templates to other parts of the DOM\ngraph_image: https://alpinejs.dev/social_teleport.jpg\n---\n\n# x-teleport\n\nThe `x-teleport` directive allows you to transport part of your Alpine template to another part of the DOM on the page entirely.\n\nThis is useful for things like modals (especially nesting them), where it's helpful to break out of the z-index of the current Alpine component.\n\n<a name=\"x-teleport\"></a>\n## x-teleport\n\nBy attaching `x-teleport` to a `<template>` element, you are telling Alpine to \"append\" that element to the provided selector.\n\n> The `x-teleport` selector can be any string you would normally pass into something like `document.querySelector`. It will find the first element that matches, be it a tag name (`body`), class name (`.my-class`), ID (`#my-id`), or any other valid CSS selector.\n\n[→ Read more about `document.querySelector`](https://developer.mozilla.org/en-US/docs/Web/API/Document/querySelector)\n\nHere's a contrived modal example:\n\n```alpine\n<body>\n    <div x-data=\"{ open: false }\">\n        <button @click=\"open = ! open\">Toggle Modal</button>\n\n        <template x-teleport=\"body\">\n            <div x-show=\"open\">\n                Modal contents...\n            </div>\n        </template>\n    </div>\n\n    <div>Some other content placed AFTER the modal markup.</div>\n\n    ...\n\n</body>\n```\n\n<!-- START_VERBATIM -->\n<div class=\"demo\" x-ref=\"root\" id=\"modal2\">\n    <div x-data=\"{ open: false }\">\n        <button @click=\"open = ! open\">Toggle Modal</button>\n\n        <template x-teleport=\"#modal2\">\n            <div x-show=\"open\">\n                Modal contents...\n            </div>\n        </template>\n\n    </div>\n\n    <div class=\"py-4\">Some other content placed AFTER the modal markup.</div>\n</div>\n<!-- END_VERBATIM -->\n\nNotice how when toggling the modal, the actual modal contents show up AFTER the \"Some other content...\" element? This is because when Alpine is initializing, it sees `x-teleport=\"body\"` and appends and initializes that element to the provided element selector.\n\n<a name=\"forwarding-events\"></a>\n## Forwarding events\n\nAlpine tries its best to make the experience of teleporting seamless. Anything you would normally do in a template, you should be able to do inside an `x-teleport` template. Teleported content can access the normal Alpine scope of the component as well as other features like `$refs`, `$root`, etc...\n\nHowever, native DOM events have no concept of teleportation, so if, for example, you trigger a \"click\" event from inside a teleported element, that event will bubble up the DOM tree as it normally would.\n\nTo make this experience more seamless, you can \"forward\" events by simply registering event listeners on the `<template x-teleport...>` element itself like so:\n\n```alpine\n<div x-data=\"{ open: false }\">\n    <button @click=\"open = ! open\">Toggle Modal</button>\n\n    <template x-teleport=\"body\" @click=\"open = false\">\n        <div x-show=\"open\">\n            Modal contents...\n            (click to close)\n        </div>\n    </template>\n</div>\n```\n\n<!-- START_VERBATIM -->\n<div class=\"demo\" x-ref=\"root\" id=\"modal3\">\n    <div x-data=\"{ open: false }\">\n        <button @click=\"open = ! open\">Toggle Modal</button>\n\n        <template x-teleport=\"#modal3\" @click=\"open = false\">\n            <div x-show=\"open\">\n                Modal contents...\n                <div>(click to close)</div>\n            </div>\n        </template>\n    </div>\n</div>\n<!-- END_VERBATIM -->\n\nNotice how we are now able to listen for events dispatched from within the teleported element from outside the `<template>` element itself?\n\nAlpine does this by looking for event listeners registered on `<template x-teleport...>` and stops those events from propagating past the live, teleported, DOM element. Then, it creates a copy of that event and re-dispatches it from `<template x-teleport...>`.\n\n<a name=\"nesting\"></a>\n## Nesting\n\nTeleporting is especially helpful if you are trying to nest one modal within another. Alpine makes it simple to do so:\n\n```alpine\n<div x-data=\"{ open: false }\">\n    <button @click=\"open = ! open\">Toggle Modal</button>\n\n    <template x-teleport=\"body\">\n        <div x-show=\"open\">\n            Modal contents...\n\n            <div x-data=\"{ open: false }\">\n                <button @click=\"open = ! open\">Toggle Nested Modal</button>\n\n                <template x-teleport=\"body\">\n                    <div x-show=\"open\">\n                        Nested modal contents...\n                    </div>\n                </template>\n            </div>\n        </div>\n    </template>\n</div>\n```\n\n<!-- START_VERBATIM -->\n<div class=\"demo\" x-ref=\"root\" id=\"modal4\">\n    <div x-data=\"{ open: false }\">\n        <button @click=\"open = ! open\">Toggle Modal</button>\n\n        <template x-teleport=\"#modal4\">\n            <div x-show=\"open\">\n                <div class=\"py-4\">Modal contents...</div>\n\n                <div x-data=\"{ open: false }\">\n                    <button @click=\"open = ! open\">Toggle Nested Modal</button>\n\n                    <template x-teleport=\"#modal4\">\n                        <div class=\"pt-4\" x-show=\"open\">\n                            Nested modal contents...\n                        </div>\n                    </template>\n                </div>\n            </div>\n        </template>\n    </div>\n\n    <template x-teleport-target=\"modals3\"></template>\n</div>\n<!-- END_VERBATIM -->\n\nAfter toggling \"on\" both modals, they are authored as children, but will be rendered as sibling elements on the page, not within one another.\n\n<!-- File: packages/docs/src/en/directives/text.md (Tokens: ~162 | Category: anthropic-skill) -->\n---\norder: 6\ntitle: text\n---\n\n# x-text\n\n`x-text` sets the text content of an element to the result of a given expression.\n\nHere's a basic example of using `x-text` to display a user's username.\n\n```alpine\n<div x-data=\"{ username: 'calebporzio' }\">\n    Username: <strong x-text=\"username\"></strong>\n</div>\n```\n\n<!-- START_VERBATIM -->\n<div class=\"demo\">\n    <div x-data=\"{ username: 'calebporzio' }\">\n        Username: <strong x-text=\"username\"></strong>\n    </div>\n</div>\n<!-- END_VERBATIM -->\n\nNow the `<strong>` tag's inner text content will be set to \"calebporzio\".\n\n<!-- File: packages/docs/src/en/directives/transition.md (Tokens: ~1384 | Category: anthropic-skill) -->\n---\norder: 10\ntitle: transition\n---\n\n# x-transition\n\nAlpine provides a robust transitions utility out of the box. With a few `x-transition` directives, you can create smooth transitions between when an element is shown or hidden.\n\nThere are two primary ways to handle transitions in Alpine:\n\n* [The Transition Helper](#the-transition-helper)\n* [Applying CSS Classes](#applying-css-classes)\n\n<a name=\"the-transition-helper\"></a>\n## The transition helper\n\nThe simplest way to achieve a transition using Alpine is by adding `x-transition` to an element with `x-show` on it. For example:\n\n```alpine\n<div x-data=\"{ open: false }\">\n    <button @click=\"open = ! open\">Toggle</button>\n\n    <div x-show=\"open\" x-transition>\n        Hello 👋\n    </div>\n</div>\n```\n\n<!-- START_VERBATIM -->\n<div class=\"demo\">\n    <div x-data=\"{ open: false }\">\n        <button @click=\"open = ! open\">Toggle</button>\n\n        <div x-show=\"open\" x-transition>\n            Hello 👋\n        </div>\n    </div>\n</div>\n<!-- END_VERBATIM -->\n\nAs you can see, by default, `x-transition` applies pleasant transition defaults to fade and scale the revealing element.\n\nYou can override these defaults with modifiers attached to `x-transition`. Let's take a look at those.\n\n<a name=\"customizing-duration\"></a>\n### Customizing duration\n\nInitially, the duration is set to be 150 milliseconds when entering, and 75 milliseconds when leaving.\n\nYou can configure the duration you want for a transition with the `.duration` modifier:\n\n```alpine\n<div ... x-transition.duration.500ms>\n```\n\nThe above `<div>` will transition for 500 milliseconds when entering, and 500 milliseconds when leaving.\n\nIf you wish to customize the durations specifically for entering and leaving, you can do that like so:\n\n```alpine\n<div ...\n    x-transition:enter.duration.500ms\n    x-transition:leave.duration.400ms\n>\n```\n\n> Despite not being included in the above snippet, `x-transition` cannot be used if no parent element has `x-data` defined. [→ Read more about `x-data`](/directives/data)\n\n<a name=\"customizing-delay\"></a>\n### Customizing delay\n\nYou can delay a transition using the `.delay` modifier like so:\n\n```alpine\n<div ... x-transition.delay.50ms>\n```\n\nThe above example will delay the transition and in and out of the element by 50 milliseconds.\n\n<a name=\"customizing-opacity\"></a>\n### Customizing opacity\n\nBy default, Alpine's `x-transition` applies both a scale and opacity transition to achieve a \"fade\" effect.\n\nIf you wish to only apply the opacity transition (no scale), you can accomplish that like so:\n\n```alpine\n<div ... x-transition.opacity>\n```\n\n<a name=\"customizing-scale\"></a>\n### Customizing scale\n\nSimilar to the `.opacity` modifier, you can configure `x-transition` to ONLY scale (and not transition opacity as well) like so:\n\n```alpine\n<div ... x-transition.scale>\n```\n\nThe `.scale` modifier also offers the ability to configure its scale values AND its origin values:\n\n```alpine\n<div ... x-transition.scale.80>\n```\n\nThe above snippet will scale the element up and down by 80%.\n\nAgain, you may customize these values separately for enter and leaving transitions like so:\n\n```alpine\n<div ...\n    x-transition:enter.scale.80\n    x-transition:leave.scale.90\n>\n```\n\nTo customize the origin of the scale transition, you can use the `.origin` modifier:\n\n```alpine\n<div ... x-transition.scale.origin.top>\n```\n\nNow the scale will be applied using the top of the element as the origin, instead of the center by default.\n\nLike you may have guessed, the possible values for this customization are: `top`, `bottom`, `left`, and `right`.\n\nIf you wish, you can also combine two origin values. For example, if you want the origin of the scale to be \"top right\", you can use: `.origin.top.right` as the modifier.\n\n\n<a name=\"applying-css-classes\"></a>\n## Applying CSS classes\n\nFor direct control over exactly what goes into your transitions, you can apply CSS classes at different stages of the transition.\n\n> The following examples use [TailwindCSS](https://tailwindcss.com/docs/transition-property) utility classes.\n\n```alpine\n<div x-data=\"{ open: false }\">\n    <button @click=\"open = ! open\">Toggle</button>\n\n    <div\n        x-show=\"open\"\n        x-transition:enter=\"transition ease-out duration-300\"\n        x-transition:enter-start=\"opacity-0 scale-90\"\n        x-transition:enter-end=\"opacity-100 scale-100\"\n        x-transition:leave=\"transition ease-in duration-300\"\n        x-transition:leave-start=\"opacity-100 scale-100\"\n        x-transition:leave-end=\"opacity-0 scale-90\"\n    >Hello 👋</div>\n</div>\n```\n\n<!-- START_VERBATIM -->\n<div class=\"demo\">\n    <div x-data=\"{ open: false }\">\n    <button @click=\"open = ! open\">Toggle</button>\n\n    <div\n        x-show=\"open\"\n        x-transition:enter=\"transition ease-out duration-300\"\n        x-transition:enter-start=\"opacity-0 transform scale-90\"\n        x-transition:enter-end=\"opacity-100 transform scale-100\"\n        x-transition:leave=\"transition ease-in duration-300\"\n        x-transition:leave-start=\"opacity-100 transform scale-100\"\n        x-transition:leave-end=\"opacity-0 transform scale-90\"\n    >Hello 👋</div>\n</div>\n</div>\n<!-- END_VERBATIM -->\n\n| Directive      | Description |\n| ---            | --- |\n| `:enter`       | Applied during the entire entering phase. |\n| `:enter-start` | Added before element is inserted, removed one frame after element is inserted. |\n| `:enter-end`   | Added one frame after element is inserted (at the same time `enter-start` is removed), removed when transition/animation finishes.\n| `:leave`       | Applied during the entire leaving phase. |\n| `:leave-start` | Added immediately when a leaving transition is triggered, removed after one frame. |\n| `:leave-end`   | Added one frame after a leaving transition is triggered (at the same time `leave-start` is removed), removed when the transition/animation finishes.\n\n<!-- File: packages/docs/src/en/essentials.md (Tokens: ~16 | Category: anthropic-skill) -->\n---\norder: 3\ntitle: Essentials\ntype: sub-directory\n---\n\n<!-- File: packages/docs/src/en/essentials/events.md (Tokens: ~808 | Category: anthropic-skill) -->\n---\norder: 4\ntitle: Events\n---\n\n# Events\n\nAlpine makes it simple to listen for browser events and react to them.\n\n<a name=\"listening-for-simple-events\"></a>\n## Listening for simple events\n\nBy using `x-on`, you can listen for browser events that are dispatched on or within an element.\n\nHere's a basic example of listening for a click on a button:\n\n```alpine\n<button x-on:click=\"console.log('clicked')\">...</button>\n```\n\nAs an alternative, you can use the event shorthand syntax if you prefer: `@`. Here's the same example as before, but using the shorthand syntax (which we'll be using from now on):\n\n```alpine\n<button @click=\"...\">...</button>\n```\n\nIn addition to `click`, you can listen for any browser event by name. For example: `@mouseenter`, `@keyup`, etc... are all valid syntax.\n\n<a name=\"listening-for-specific-keys\"></a>\n## Listening for specific keys\n\nLet's say you wanted to listen for the `enter` key to be pressed inside an `<input>` element. Alpine makes this easy by adding the `.enter` like so:\n\n```alpine\n<input @keyup.enter=\"...\">\n```\n\nYou can even combine key modifiers to listen for key combinations like pressing `enter` while holding `shift`:\n\n```alpine\n<input @keyup.shift.enter=\"...\">\n```\n\n<a name=\"preventing-default\"></a>\n## Preventing default\n\nWhen reacting to browser events, it is often necessary to \"prevent default\" (prevent the default behavior of the browser event).\n\nFor example, if you want to listen for a form submission but prevent the browser from submitting a form request, you can use `.prevent`:\n\n```alpine\n<form @submit.prevent=\"...\">...</form>\n```\n\nYou can also apply `.stop` to achieve the equivalent of `event.stopPropagation()`.\n\n<a name=\"accessing-the-event-object\"></a>\n## Accessing the event object\n\nSometimes you may want to access the native browser event object inside your own code. To make this easy, Alpine automatically injects an `$event` magic variable:\n\n```alpine\n<button @click=\"$event.target.remove()\">Remove Me</button>\n```\n\n<a name=\"dispatching-custom-events\"></a>\n## Dispatching custom events\n\nIn addition to listening for browser events, you can dispatch them as well. This is extremely useful for communicating with other Alpine components or triggering events in tools outside of Alpine itself.\n\nAlpine exposes a magic helper called `$dispatch` for this:\n\n```alpine\n<div @foo=\"console.log('foo was dispatched')\">\n    <button @click=\"$dispatch('foo')\"></button>\n</div>\n```\n\nAs you can see, when the button is clicked, Alpine will dispatch a browser event called \"foo\", and our `@foo` listener on the `<div>` will pick it up and react to it.\n\n<a name=\"listening-for-events-on-window\"></a>\n## Listening for events on window\n\nBecause of the nature of events in the browser, it is sometimes useful to listen to events on the top-level window object.\n\nThis allows you to communicate across components completely like the following example:\n\n\n```alpine\n<div x-data>\n    <button @click=\"$dispatch('foo')\"></button>\n</div>\n\n<div x-data @foo.window=\"console.log('foo was dispatched')\">...</div>\n```\n\nIn the above example, if we click the button in the first component, Alpine will dispatch the \"foo\" event. Because of the way events work in the browser, they \"bubble\" up through parent elements all the way to the top-level \"window\".\n\nNow, because in our second component we are listening for \"foo\" on the window (with `.window`), when the button is clicked, this listener will pick it up and log the \"foo was dispatched\" message.\n\n[→ Read more about x-on](/directives/on)\n\n<!-- ... +30 more modular skills available via /api/skills/alpinejs/alpine?path={path} -->\n</yakaai_skills>"}