alpine-components.ts
typescript
sha256:3ff9c9863a9891bdcde71b4a43228f66d0493e38b7cc1d09fe9eb7de774046b2
feat: add repair-commit wire endpoint (API parity with repa…
Opus 4.8
minor
⚠ breaking
1 day ago
| 1 | /** |
| 2 | * alpine-components.ts — Alpine.js CSP-compatible component registrations. |
| 3 | * |
| 4 | * All components use the Alpine CSP build (`@alpinejs/csp`), which replaces |
| 5 | * the expression evaluator with registered function references. Inline |
| 6 | * JavaScript expressions in Alpine directives are not allowed; all directives |
| 7 | * must reference properties or methods by name. |
| 8 | * |
| 9 | * Registered during `alpine:init` so they are available before Alpine |
| 10 | * initialises the DOM. |
| 11 | */ |
| 12 | |
| 13 | type AlpineRoot = HTMLElement & { dataset: DOMStringMap }; |
| 14 | |
| 15 | document.addEventListener('alpine:init', () => { |
| 16 | const Alpine = window.Alpine; |
| 17 | if (!Alpine) return; |
| 18 | |
| 19 | // ── tabSwitcher — CLI / MCP / REST tab panel (issue_detail.html) ────────── |
| 20 | // |
| 21 | // Usage: x-data="tabSwitcher" |
| 22 | // Buttons: :class="cliClass" @click="setCliTab" |
| 23 | // Panes: x-show="showCli" |
| 24 | |
| 25 | Alpine.data('tabSwitcher', () => ({ |
| 26 | tab: 'cli' as string, |
| 27 | get showCli() { return (this as { tab: string }).tab === 'cli'; }, |
| 28 | get showMcp() { return (this as { tab: string }).tab === 'mcp'; }, |
| 29 | get showRest() { return (this as { tab: string }).tab === 'rest'; }, |
| 30 | get cliClass() { return { 'is-active': (this as { tab: string }).tab === 'cli' }; }, |
| 31 | get mcpClass() { return { 'is-active': (this as { tab: string }).tab === 'mcp' }; }, |
| 32 | get restClass() { return { 'is-active': (this as { tab: string }).tab === 'rest' }; }, |
| 33 | setCliTab() { (this as { tab: string }).tab = 'cli'; }, |
| 34 | setMcpTab() { (this as { tab: string }).tab = 'mcp'; }, |
| 35 | setRestTab() { (this as { tab: string }).tab = 'rest'; }, |
| 36 | })); |
| 37 | |
| 38 | // ── newRepoForm — initialisation toggle (new_repo.html) ────────────────── |
| 39 | // |
| 40 | // Topics are managed entirely by TypeScript (initTagInput in new-repo.ts). |
| 41 | // Only the "add initial commit / show branch name" toggle lives here. |
| 42 | // |
| 43 | // Usage: x-data="newRepoForm" |
| 44 | // Checkbox: x-model="showBranch" |
| 45 | // Row: x-show="showBranch" |
| 46 | |
| 47 | Alpine.data('newRepoForm', () => ({ |
| 48 | showBranch: true as boolean, |
| 49 | })); |
| 50 | |
| 51 | // ── settingsPage — settings navigation + confirmation modals ───────────── |
| 52 | // |
| 53 | // The active section is seeded from the root element's data-initial-section |
| 54 | // attribute so Jinja2 can set it server-side without an inline expression. |
| 55 | // |
| 56 | // Usage: x-data="settingsPage" data-initial-section="{{ active_section }}" |
| 57 | // Nav links: :class="generalNavClass" @click.prevent="setSection" data-section="general" |
| 58 | // Panels: x-show="showGeneral" |
| 59 | // Modals: x-show="archiveOpen" @click="openArchive" @click="closeArchive" |
| 60 | |
| 61 | Alpine.data('settingsPage', () => ({ |
| 62 | section: 'general' as string, |
| 63 | archiveOpen: false as boolean, |
| 64 | transferOpen: false as boolean, |
| 65 | deleteOpen: false as boolean, |
| 66 | init() { |
| 67 | const root = (this as unknown as { $el: AlpineRoot }).$el; |
| 68 | (this as { section: string }).section = root.dataset['initialSection'] ?? 'general'; |
| 69 | }, |
| 70 | get showGeneral() { return (this as { section: string }).section === 'general'; }, |
| 71 | get showCollaboration() { return (this as { section: string }).section === 'collaboration'; }, |
| 72 | get showMerge() { return (this as { section: string }).section === 'merge'; }, |
| 73 | get showDanger() { return (this as { section: string }).section === 'danger'; }, |
| 74 | get generalNavClass() { return { active: (this as { section: string }).section === 'general' }; }, |
| 75 | get collaborationNavClass() { return { active: (this as { section: string }).section === 'collaboration' }; }, |
| 76 | get mergeNavClass() { return { active: (this as { section: string }).section === 'merge' }; }, |
| 77 | get dangerNavClass() { return { active: (this as { section: string }).section === 'danger' }; }, |
| 78 | setSection(e: Event) { |
| 79 | const el = e.currentTarget as HTMLElement; |
| 80 | (this as { section: string }).section = el.dataset['section'] ?? 'general'; |
| 81 | }, |
| 82 | openArchive() { (this as { archiveOpen: boolean }).archiveOpen = true; }, |
| 83 | closeArchive() { (this as { archiveOpen: boolean }).archiveOpen = false; }, |
| 84 | openTransfer() { (this as { transferOpen: boolean }).transferOpen = true; }, |
| 85 | closeTransfer() { (this as { transferOpen: boolean }).transferOpen = false; }, |
| 86 | openDelete() { (this as { deleteOpen: boolean }).deleteOpen = true; }, |
| 87 | closeDelete() { (this as { deleteOpen: boolean }).deleteOpen = false; }, |
| 88 | })); |
| 89 | }); |
File History
1 commit
sha256:3ff9c9863a9891bdcde71b4a43228f66d0493e38b7cc1d09fe9eb7de774046b2
feat: add repair-commit wire endpoint (API parity with repa…
Opus 4.8
minor
⚠
1 day ago