gabriel / musehub public
alpine-components.ts typescript
89 lines 4.4 KB
Raw
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