Skip to content

Commit ce41319

Browse files
authored
Disable 'Select Element' button while element picker is active (#137)
1 parent e9fa5fc commit ce41319

File tree

3 files changed

+78
-0
lines changed

3 files changed

+78
-0
lines changed

src/managers/preview-bar-manager.test.ts

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,73 @@ describe('preview-bar-manager', () => {
191191
});
192192
});
193193

194+
describe('element picker button disabled state', () => {
195+
function getSelectBtn(): HTMLButtonElement {
196+
return document.querySelector<HTMLButtonElement>(
197+
'#gist-preview-bar .gist-pb-select-elem-btn'
198+
)!;
199+
}
200+
201+
function getPickerOverlay(): HTMLElement | null {
202+
return document.querySelector<HTMLElement>('.gist-pb-picker-overlay');
203+
}
204+
205+
it('select element button is not disabled initially', () => {
206+
initBarWithMessage([], 'inline');
207+
expect(getSelectBtn().disabled).toBe(false);
208+
});
209+
210+
it('disables the button when element picker is activated', () => {
211+
initBarWithMessage([], 'inline');
212+
const btn = getSelectBtn();
213+
btn.click();
214+
expect(btn.disabled).toBe(true);
215+
expect(getPickerOverlay()).not.toBeNull();
216+
});
217+
218+
it('re-enables the button after picker is cancelled with Escape', () => {
219+
initBarWithMessage([], 'inline');
220+
getSelectBtn().click();
221+
expect(getSelectBtn().disabled).toBe(true);
222+
223+
document.dispatchEvent(new KeyboardEvent('keydown', { key: 'Escape' }));
224+
225+
expect(getPickerOverlay()).toBeNull();
226+
expect(getSelectBtn().disabled).toBe(false);
227+
});
228+
229+
it('re-enables the button after an element is picked', () => {
230+
// Add a target element for the picker to find
231+
const target = document.createElement('div');
232+
target.id = 'pick-target';
233+
document.body.appendChild(target);
234+
235+
// Stub CSS.escape since jsdom doesn't support it
236+
const globalCSS = globalThis as unknown as Record<string, unknown>;
237+
const origCSS = globalCSS.CSS;
238+
globalCSS.CSS = { escape: (v: string) => v };
239+
240+
initBarWithMessage([], 'inline');
241+
getSelectBtn().click();
242+
expect(getSelectBtn().disabled).toBe(true);
243+
244+
const overlay = getPickerOverlay()!;
245+
// Simulate clicking on the overlay — elementFromPoint will return the target
246+
const origElementFromPoint = document.elementFromPoint;
247+
document.elementFromPoint = vi.fn(
248+
() => target
249+
) as unknown as typeof document.elementFromPoint;
250+
251+
overlay.dispatchEvent(new MouseEvent('click', { bubbles: true }));
252+
253+
document.elementFromPoint = origElementFromPoint;
254+
globalCSS.CSS = origCSS;
255+
256+
expect(getPickerOverlay()).toBeNull();
257+
expect(getSelectBtn().disabled).toBe(false);
258+
});
259+
});
260+
194261
describe('updatePreviewBarStep', () => {
195262
it('updates the bar when step changes', () => {
196263
const steps: StepDisplayConfig[] = [

src/managers/preview-bar-manager.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -267,6 +267,7 @@ function buildElementSelectorControl(settings: DisplaySettings, row: HTMLElement
267267
className: 'gist-pb-select-elem-btn',
268268
textContent: 'Select Element',
269269
});
270+
if (pickerActive) selectBtn.disabled = true;
270271
selectBtn.addEventListener('click', () => startElementPicker(selectorInput));
271272

272273
const inputRow = el('div', { className: 'gist-pb-inline-row' });
@@ -441,6 +442,12 @@ function startElementPicker(target: HTMLInputElement) {
441442
if (pickerActive) return;
442443
pickerActive = true;
443444

445+
// Disable the "Select Element" button while picker is active
446+
const selectElemBtn = document.querySelector<HTMLButtonElement>(
447+
`#${BAR_ID} .gist-pb-select-elem-btn`
448+
);
449+
if (selectElemBtn) selectElemBtn.disabled = true;
450+
444451
const settingsBeforePicker = { ...currentSettings };
445452
const msg =
446453
Gist.currentMessages.find((m: GistMessage) => m.instanceId === currentInstanceId) ?? null;
@@ -523,6 +530,7 @@ function startElementPicker(target: HTMLInputElement) {
523530
}
524531
}
525532
cleanup();
533+
renderBar();
526534
};
527535

528536
const cleanup = () => {

src/managers/preview-bar-styles.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,9 @@ export const PREVIEW_BAR_CSS = `
108108
min-width: auto; box-sizing: border-box;
109109
-webkit-appearance: none; appearance: none;
110110
}
111+
.gist-pb-select-elem-btn:disabled {
112+
opacity: 0.4; cursor: not-allowed;
113+
}
111114
.gist-pb-spacer { flex: 1; min-width: 0; }
112115
.gist-pb-save-btn {
113116
height: 36px; padding: 0 18px;

0 commit comments

Comments
 (0)