`;
const root = shadow;
ui = {
host,
shadow,
dialog: root.querySelector('dialog'),
heading: root.querySelector('h2.settings-heading'),
range: root.querySelector('#github-fluid-width-percent-range'),
percent: root.querySelector('#github-fluid-width-percent-number'),
gutter: root.querySelector('#github-fluid-width-gutter'),
override: root.querySelector('#github-fluid-width-override'),
hideIssuePrHeader: root.querySelector('#github-fluid-width-hide-issue-pr-header'),
status: root.querySelector('.status'),
reset: root.querySelector('[data-reset]'),
close: root.querySelector('[data-close]'),
};
bindSettingsUi();
(settingsDocument.body || settingsDocument.documentElement).appendChild(host);
registerSettingsMenu();
renderSettings();
return ui;
}
function bindSettingsUi() {
if (!ui) return;
ui.close.addEventListener('click', close);
ui.reset.addEventListener('click', () => {
resetDefaults();
flushSettings().catch(() => {});
});
ui.range.addEventListener('input', () => setConfig({contentWidthPercent: ui.range.value}));
ui.percent.addEventListener('input', () => {
const value = Number(ui.percent.value);
if (Number.isFinite(value) && value >= 1 && value <= 100) setConfig({contentWidthPercent: value});
});
ui.percent.addEventListener('change', () => {
if (ui.percent.value !== '') setConfig({contentWidthPercent: ui.percent.value});
renderSettings({forceNumbers: true});
flushSettings().catch(() => {});
});
ui.percent.addEventListener('blur', () => renderSettings({forceNumbers: true}));
ui.gutter.addEventListener('input', () => {
const value = Number(ui.gutter.value);
if (Number.isFinite(value) && value >= 16 && value <= 128) setConfig({minGutterPx: value});
});
ui.gutter.addEventListener('change', () => {
if (ui.gutter.value !== '') setConfig({minGutterPx: ui.gutter.value});
renderSettings({forceNumbers: true});
flushSettings().catch(() => {});
});
ui.gutter.addEventListener('blur', () => renderSettings({forceNumbers: true}));
ui.range.addEventListener('change', () => flushSettings().catch(() => {}));
ui.override.addEventListener('change', () => {
setConfig({overrideFullWidthPages: ui.override.checked});
flushSettings().catch(() => {});
});
ui.hideIssuePrHeader.addEventListener('change', () => {
setConfig({HideIssuePRHeader: ui.hideIssuePrHeader.checked});
flushSettings().catch(() => {});
});
ui.dialog.addEventListener('cancel', (event) => {
event.preventDefault();
event.stopPropagation();
close();
});
ui.dialog.addEventListener('close', () => {
pointerDownOutside = false;
setRootLock(false);
flushSettings().catch(() => {});
if (lastFocus && typeof lastFocus.focus === 'function') lastFocus.focus();
});
ui.dialog.addEventListener('pointerdown', handleDialogPointerDown);
ui.dialog.addEventListener('pointercancel', () => { pointerDownOutside = false; });
ui.dialog.addEventListener('click', handleDialogClick);
ui.dialog.addEventListener('wheel', (event) => {
if (isOpen() && event.target === ui.dialog && isOutsideDialogPoint(event)) event.preventDefault();
}, {passive: false});
ui.dialog.addEventListener('submit', (event) => event.preventDefault());
ui.dialog.addEventListener('keydown', (event) => {
if (event.key !== 'Tab') return;
const focusable = Array.from(ui.dialog.querySelectorAll('button, input, [href], select, textarea'))
.filter((element) => !element.disabled && element.offsetParent !== null);
if (focusable.length === 0) return;
const first = focusable[0];
const last = focusable[focusable.length - 1];
const active = ui.shadow.activeElement || settingsDocument.activeElement;
if (event.shiftKey && (active === first || active === ui.heading)) {
event.preventDefault();
last.focus();
} else if (!event.shiftKey && active === last) {
event.preventDefault();
first.focus();
}
});
}
function isOpen() {
return !!(ui && ui.dialog && (ui.dialog.open || ui.dialog.hasAttribute('open')));
}
function isPrimaryPointer(event) {
if (!event || event.isPrimary === false) return false;
return event.pointerType !== 'mouse' || event.button === undefined || event.button === 0;
}
function isOutsideDialogPoint(event) {
if (!ui || !ui.dialog || !event || typeof ui.dialog.getBoundingClientRect !== 'function') return false;
const rect = ui.dialog.getBoundingClientRect();
const x = Number(event.clientX);
const y = Number(event.clientY);
if (!Number.isFinite(x) || !Number.isFinite(y)) return false;
return x < rect.left || x > rect.right || y < rect.top || y > rect.bottom;
}
function handleDialogPointerDown(event) {
pointerDownOutside = isOpen()
&& isPrimaryPointer(event)
&& event.target === ui.dialog
&& isOutsideDialogPoint(event);
}
function handleDialogClick(event) {
// Click PointerEvents default isPrimary to false; primary validation ran on pointerdown.
const shouldClose = pointerDownOutside
&& isOpen()
&& (typeof event.button !== 'number' || event.button === 0)
&& event.target === ui.dialog
&& isOutsideDialogPoint(event);
pointerDownOutside = false;
if (shouldClose) {
event.preventDefault();
event.stopPropagation();
close();
}
}
function show() {
if (ui && isOpen()) {
return;
}
const mounted = ensureMounted();
if (!mounted) return;
lastFocus = ui.shadow.activeElement || settingsDocument.activeElement || null;
renderSettings();
updateBackdropTheme();
if (typeof ui.dialog.showModal !== 'function') {
if (typeof console !== 'undefined' && typeof console.warn === 'function') console.warn('[GitHub Fluid Width] Native modal dialogs are unavailable; settings remain closed.');
setRootLock(false);
return;
}
try {
if (!ui.dialog.open) ui.dialog.showModal();
} catch (error) {
setRootLock(false);
if (typeof console !== 'undefined' && typeof console.warn === 'function') console.warn('[GitHub Fluid Width] Native settings modal could not open; settings remain closed.', error);
return;
}
setRootLock(isOpen());
if (ui.heading && typeof ui.heading.focus === 'function') ui.heading.focus({preventScroll: true});
}
function close() {
if (!ui) return;
setRootLock(false);
flushSettings().catch(() => {});
if (typeof ui.dialog.close === 'function' && ui.dialog.open) ui.dialog.close();
else ui.dialog.removeAttribute('open');
if (lastFocus && typeof lastFocus.focus === 'function') lastFocus.focus();
}
function renderSettings(options = {}) {
if (!ui) return;
const active = ui.shadow && ui.shadow.activeElement;
const forceNumbers = options.forceNumbers === true;
ui.range.value = String(current.contentWidthPercent);
if (forceNumbers || active !== ui.percent) ui.percent.value = String(current.contentWidthPercent);
if (forceNumbers || active !== ui.gutter) ui.gutter.value = String(current.minGutterPx);
ui.override.checked = current.overrideFullWidthPages;
ui.hideIssuePrHeader.checked = current.HideIssuePRHeader;
ui.status.textContent = storageError && storageState === 'write-error'
? storageError.message || statusText(storageState)
: statusText(storageState);
ui.status.dataset.state = storageState;
}
return {initialize, ensureMounted, show, close, setConfig, resetDefaults, flush: flushSettings};
}
function normalizeSettingValue(key, value, fallback) {
if (key === 'contentWidthPercent') return finiteClamp(value, fallback, 1, 100);
if (key === 'minGutterPx') return Math.round(finiteClamp(value, fallback, 16, 128));
if (key === 'overrideFullWidthPages') return value !== false;
if (key === 'HideIssuePRHeader') return value === true;
return value;
}
function normalizeSettingsConfig(values) {
return {
contentWidthPercent: normalizeSettingValue('contentWidthPercent', values.contentWidthPercent, SETTINGS_DEFAULTS.contentWidthPercent),
minGutterPx: normalizeSettingValue('minGutterPx', values.minGutterPx, SETTINGS_DEFAULTS.minGutterPx),
overrideFullWidthPages: normalizeSettingValue('overrideFullWidthPages', values.overrideFullWidthPages, SETTINGS_DEFAULTS.overrideFullWidthPages),
HideIssuePRHeader: normalizeSettingValue('HideIssuePRHeader', values.HideIssuePRHeader, SETTINGS_DEFAULTS.HideIssuePRHeader),
};
}
function copySettingsConfig(values) {
return {
contentWidthPercent: values.contentWidthPercent,
minGutterPx: values.minGutterPx,
overrideFullWidthPages: values.overrideFullWidthPages,
HideIssuePRHeader: values.HideIssuePRHeader,
};
}
function findSettingsStorage(runtime) {
const legacyGet = runtime && runtime.GM_getValue;
const legacySet = runtime && runtime.GM_setValue;
if (typeof legacyGet === 'function' && typeof legacySet === 'function') {
return {
get: (key) => legacyGet.call(runtime, key),
set: (key, value) => legacySet.call(runtime, key, value),
};
}
const gm = runtime && runtime.GM;
if (gm && typeof gm.getValue === 'function' && typeof gm.setValue === 'function') {
return {
get: (key) => gm.getValue(key),
set: (key, value) => gm.setValue(key, value),
};
}
return null;
}
})();