PageSourceSearch

https://healthylifenetwork.com.au/assets/controllers/va-drawer_controller-ZD_1PeE.js

js healthylifenetwork.com.au collected 2026-10-02 15:59:51 UTC 3,494 bytes, 91 lines download raw bytes

1import { Controller } from '@hotwired/stimulus';
2
3/**
4 * VA-drawer — the in-page "mini VA" (VA_MOUNT_SPEC D6).
5 *
6 * Lives once per page (templates/_partials/va_drawer.html.twig, included from
7 * base.html.twig only when the tenant has the va_mounts flag). On first open it
8 * creates a same-origin iframe of /workspace/embed, so the heavy va-chat
9 * controller only loads when someone actually asks for it.
10 *
11 * On wide screens the drawer DOCKS: the page is pushed left by the drawer's width
12 * (body padding) so it becomes a right-hand column of the page instead of covering
13 * it. Below the lg breakpoint there is no room to push, so it overlays.
14 *
15 * Exposes window.openVaDrawer(opts) — the contract va-launch already calls — so
16 * existing "Create with AI" / "Audit with AI" buttons open in-page instead of a
17 * new tab. opts: { mount?: string, entityId?: string|number }.
18 */
19export default class extends Controller {
20    static targets = ['panel', 'frameHost'];
21
22    connect() {
23        this._open = (opts = {}) => this.open(opts);
24        window.openVaDrawer = this._open;
25        this._onKey = (e) => { if (e.key === 'Escape') this.close(); };
26        this._onResize = () => { if (this._isOpen()) this._dock(); };
27        document.addEventListener('keydown', this._onKey);
28        window.addEventListener('resize', this._onResize);
29    }
30
31    disconnect() {
32        if (window.openVaDrawer === this._open) delete window.openVaDrawer;
33        document.removeEventListener('keydown', this._onKey);
34        window.removeEventListener('resize', this._onResize);
35        this._undock();
36    }
37
38    open(opts = {}) {
39        const params = new URLSearchParams();
40        if (opts.mount) params.set('mount', String(opts.mount));
41        if (opts.entityId !== undefined && opts.entityId !== null && opts.entityId !== '') {
42            params.set('entity_id', String(opts.entityId));
43        }
44        const qs = params.toString();
45        const src = '/workspace/embed' + (qs ? `?${qs}` : '');
46
47        let frame = this.frameHostTarget.querySelector('iframe');
48        if (!frame) {
49            frame = document.createElement('iframe');
50            frame.className = 'w-full h-full border-0';
51            frame.title = 'Workplace VA';
52            this.frameHostTarget.appendChild(frame);
53        }
54        // Reload only when the thread changes; re-opening the same one keeps its state.
55        if (frame.dataset.src !== src) {
56            frame.dataset.src = src;
57            frame.src = src;
58        } else if (!opts.mount) {
59            // va-launch may have queued a new prefill prompt for the main thread.
60            frame.src = src;
61        }
62
63        this.panelTarget.classList.remove('hidden');
64        this.panelTarget.setAttribute('aria-hidden', 'false');
65        this._dock();
66    }
67
68    close() {
69        this.panelTarget.classList.add('hidden');
70        this.panelTarget.setAttribute('aria-hidden', 'true');
71        this._undock();
72    }
73
74    _isOpen() {
75        return !this.panelTarget.classList.contains('hidden');
76    }
77
78    /** Push the page left by the drawer's width when there is room (lg+). */
79    _dock() {
80        if (!window.matchMedia('(min-width: 1024px)').matches) {
81            this._undock();
82            return;
83        }
84        document.body.style.transition = 'padding-right 150ms ease-out';
85        document.body.style.paddingRight = `${this.panelTarget.offsetWidth}px`;
86    }
87
88    _undock() {
89        document.body.style.paddingRight = '';
90    }
91}

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.