PageSourceSearch

https://invoicecraftly.com/_assets/js/features/workspace-layout/workspace-split-panel.6edf1218f65c.js

js invoicecraftly.com collected 2026-10-02 01:33:54 UTC 2,761 bytes, 74 lines download raw bytes

1const STORAGE_KEY = 'ic.workspace.split';
2const DEFAULT_PREF = { lhsWidth: '30%', collapsed: false };
3const MIN_LHS_PX = 280;
4const MAX_LHS_RATIO = 0.6;
5const WIDTH_PATTERN = /^\d+(\.\d+)?(%|px)$/;
6
7function readPref() {
8  try {
9    const raw = localStorage.getItem(STORAGE_KEY);
10    if (!raw) return { ...DEFAULT_PREF };
11    const parsed = JSON.parse(raw);
12    return {
13      lhsWidth: typeof parsed.lhsWidth === 'string' && WIDTH_PATTERN.test(parsed.lhsWidth) ? parsed.lhsWidth : DEFAULT_PREF.lhsWidth,
14      collapsed: Boolean(parsed.collapsed)
15    };
16  } catch (error) {
17    return { ...DEFAULT_PREF };
18  }
19}
20
21function writePref(pref) {
22  try {
23    localStorage.setItem(STORAGE_KEY, JSON.stringify(pref));
24  } catch (error) {
25    // Private browsing or storage quota — the split simply won't persist.
26  }
27}
28
29function applyPref(pref) {
30  document.documentElement.style.setProperty('--lhs-width', pref.lhsWidth);
31  document.documentElement.classList.toggle('is-preview-collapsed', pref.collapsed);
32}
33
34export function installWorkspaceSplitPanel() {
35  const workspace = document.getElementById('view-editor');
36  const divider = document.getElementById('workspace-divider');
37  const toggle = document.getElementById('workspace-collapse-toggle');
38  if (!workspace || !divider || !toggle) return;
39
40  applyPref(readPref());
41
42  divider.addEventListener('pointerdown', (event) => {
43    if (document.documentElement.classList.contains('is-preview-collapsed')) return;
44    event.preventDefault();
45    divider.setPointerCapture(event.pointerId);
46    const rect = workspace.getBoundingClientRect();
47
48    const onMove = (moveEvent) => {
49      const maxPx = rect.width * MAX_LHS_RATIO;
50      const px = Math.min(Math.max(moveEvent.clientX - rect.left, MIN_LHS_PX), maxPx);
51      const pct = ((px / rect.width) * 100).toFixed(2) + '%';
52      document.documentElement.style.setProperty('--lhs-width', pct);
53    };
54    const onUp = () => {
55      divider.releasePointerCapture(event.pointerId);
56      divider.removeEventListener('pointermove', onMove);
57      divider.removeEventListener('pointerup', onUp);
58      const lhsWidth = document.documentElement.style.getPropertyValue('--lhs-width').trim() || DEFAULT_PREF.lhsWidth;
59      writePref({ ...readPref(), lhsWidth });
60    };
61    divider.addEventListener('pointermove', onMove);
62    divider.addEventListener('pointerup', onUp);
63  });
64
65  toggle.addEventListener('click', () => {
66    const pref = readPref();
67    const next = { ...pref, collapsed: !pref.collapsed };
68    applyPref(next);
69    writePref(next);
70    toggle.setAttribute('aria-expanded', String(!next.collapsed));
71    toggle.title = next.collapsed ? 'Expand preview panel' : 'Collapse preview panel';
72    toggle.setAttribute('aria-label', toggle.title);
73  });
74}

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.