File size: 2,296 Bytes
6918275
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
// Inline button two-click confirmation for destructive actions.
// First click arms, second click confirms, timeout resets.

import { ICON_SELECTOR, getIconName, setIconName } from "./icons.js";

const CONFIRM_TIMEOUT = 2000;
const CONFIRM_CLASS = 'confirming';
const CONFIRM_ICON = 'check';
const CONFIRM_TEXT = 'Confirm';

const buttonStates = new WeakMap();

// Handles inline two-click confirmation for a button.
export function confirmClick(event, action) {
  const button = event.currentTarget;
  if (!button) return;

  const state = buttonStates.get(button);

  if (state?.confirming) {
    clearTimeout(state.timeoutId);
    resetButton(button, state);
    buttonStates.delete(button);
    action();
  } else {
    const iconEl = button.querySelector(ICON_SELECTOR);
    const isIconButton = iconEl && button.textContent.trim() === iconEl.textContent.trim();
    
    const newState = {
      confirming: true,
      isIconButton,
      originalIcon: getIconName(iconEl),
      originalHTML: isIconButton ? null : button.innerHTML,
      timeoutId: setTimeout(() => {
        resetButton(button, newState);
        buttonStates.delete(button);
      }, CONFIRM_TIMEOUT)
    };
    
    buttonStates.set(button, newState);
    button.classList.add(CONFIRM_CLASS);
    
    if (isIconButton && iconEl) {
      // Icon-only button: just swap icon
      setIconName(iconEl, CONFIRM_ICON);
    } else {
      // Text button: show icon + optional "Confirm" text
      const originalText = button.textContent.trim();
      const confirmContent = originalText.length >= 4
        ? `<x-icon name="${CONFIRM_ICON}"></x-icon>${CONFIRM_TEXT}`
        : `<x-icon name="${CONFIRM_ICON}"></x-icon>`;
      button.innerHTML = confirmContent;
    }
  }
}

// Reset button to original state
function resetButton(button, state) {
  button.classList.remove(CONFIRM_CLASS);
  if (state.isIconButton) {
    const iconEl = button.querySelector(ICON_SELECTOR);
    if (iconEl && state.originalIcon) {
      setIconName(iconEl, state.originalIcon);
    }
  } else if (state.originalHTML) {
    button.innerHTML = state.originalHTML;
  }
}

// Register Alpine magic helper
export function registerAlpineMagic() {
  if (globalThis.Alpine) {
    globalThis.Alpine.magic('confirmClick', () => confirmClick);
  }
}