Instruções SQL
Fechar aba?
Fechar todas as abas?
+Todo o texto SQL e os resultados destas abas serão perdidos. Uma nova aba será aberta.
+Modo offline indisponível
buildTableHtml: () => buildTableHtml, buildTablePopulationPlan: () => buildTablePopulationPlan, canSelectSqlMapTable: () => canSelectSqlMapTable, + cancelCloseAllSqlTabs: () => cancelCloseAllSqlTabs, + cancelCloseAllTabsBtn: () => cancelCloseAllTabsBtn, cancelCloseSqlTab: () => cancelCloseSqlTab, cancelCloseTabBtn: () => cancelCloseTabBtn, cancelExportBtn: () => cancelExportBtn, @@ -27845,9 +27958,11 @@Modo offline indisponível
clearStoredFileHandles: () => clearStoredFileHandles, clearTablePopulationErrors: () => clearTablePopulationErrors, cloneSettingsValue: () => cloneSettingsValue, - closeActiveSqlTabBtn: () => closeActiveSqlTabBtn, closeAllSqlTabs: () => closeAllSqlTabs, closeAllTabsBtn: () => closeAllTabsBtn, + closeAllTabsConfirmModal: () => closeAllTabsConfirmModal, + closeAllTabsConfirmText: () => closeAllTabsConfirmText, + closeAllTabsTitle: () => closeAllTabsTitle, closeDatabaseConnection: () => closeDatabaseConnection, closeDatabaseMenu: () => closeDatabaseMenu, closeEditorMoreActions: () => closeEditorMoreActions, @@ -27888,6 +28003,8 @@Modo offline indisponível
configureSqlMapGraphEffects: () => configureSqlMapGraphEffects, configureSqlMapRenderInteractions: () => configureSqlMapRenderInteractions, configureSqlTabActions: () => configureSqlTabActions, + confirmCloseAllSqlTabs: () => confirmCloseAllSqlTabs, + confirmCloseAllTabsBtn: () => confirmCloseAllTabsBtn, confirmCloseSqlTab: () => confirmCloseSqlTab, confirmCloseTabBtn: () => confirmCloseTabBtn, confirmExportBtn: () => confirmExportBtn, @@ -28238,7 +28355,6 @@Modo offline indisponível
releaseNotesModal: () => releaseNotesModal, releaseNotesSummary: () => releaseNotesSummary, removeSqlMapVirtualRelationship: () => removeSqlMapVirtualRelationship, - renameActiveSqlTabBtn: () => renameActiveSqlTabBtn, renderAllResults: () => renderAllResults, renderAutocomplete: () => renderAutocomplete, renderCellValue: () => renderCellValue, @@ -28267,6 +28383,7 @@Modo offline indisponível
replaceDatabaseSession: () => replaceDatabaseSession, replaceEditorRange: () => replaceEditorRange, replaceSqlTabsItems: () => replaceSqlTabsItems, + requestCloseAllSqlTabs: () => requestCloseAllSqlTabs, requestCloseSqlTab: () => requestCloseSqlTab2, resetAllSqlTabResultStates: () => resetAllSqlTabResultStates, resetAllTabResultsForNewDatabase: () => resetAllTabResultsForNewDatabase, @@ -28437,11 +28554,13 @@Modo offline indisponível
sqlReplaceOneBtn: () => sqlReplaceOneBtn, sqlRunningBar: () => sqlRunningBar, sqlRunningText: () => sqlRunningText, + sqlTabActionsLayer: () => sqlTabActionsLayer, sqlTabsController: () => sqlTabsController, sqlTabsEl: () => sqlTabsEl, sqlTabsOverflowList: () => sqlTabsOverflowList, sqlTabsOverflowMenu: () => sqlTabsOverflowMenu, sqlTabsStorage: () => sqlTabsStorage, + sqlTabsStrip: () => sqlTabsStrip, startInlineTabRename: () => startInlineTabRename, starterSqlController: () => starterSqlController, starterSqlToggle: () => starterSqlToggle, @@ -30261,6 +30380,11 @@Modo offline indisponível
["tabs.created", "New tab created: {title}", "Nova aba criada: {title}", "Nueva pesta\xF1a creada: {title}"], ["tabs.keepOne", "Keep at least one tab open.", "Mantenha pelo menos uma aba aberta.", "Mantenga al menos una pesta\xF1a abierta."], ["tabs.allClosed", "All tabs were closed. A new tab was created.", "Todas as abas foram fechadas. Uma nova aba foi criada.", "Se cerraron todas las pesta\xF1as. Se cre\xF3 una nueva pesta\xF1a."], + ["tabs.closeAll", "Close all tabs", "Fechar todas as abas", "Cerrar todas las pesta\xF1as"], + ["tabs.closeAllTitleGeneric", "Close all tabs?", "Fechar todas as abas?", "\xBFCerrar todas las pesta\xF1as?"], + ["tabs.closeAllTitle", "Close all {count} tabs?", "Fechar todas as {count} abas?", "\xBFCerrar las {count} pesta\xF1as?"], + ["tabs.closeAllWarningGeneric", "All query text and results in these tabs will be lost. A new tab will open.", "Todo o texto SQL e os resultados destas abas ser\xE3o perdidos. Uma nova aba ser\xE1 aberta.", "Todo el texto SQL y los resultados de estas pesta\xF1as se perder\xE1n. Se abrir\xE1 una nueva pesta\xF1a."], + ["tabs.closeAllWarning", "All query text and results in these {count} tabs will be lost. A new tab will open.", "Todo o texto SQL e os resultados destas {count} abas ser\xE3o perdidos. Uma nova aba ser\xE1 aberta.", "Todo el texto SQL y los resultados de estas {count} pesta\xF1as se perder\xE1n. Se abrir\xE1 una nueva pesta\xF1a."], ["results.emptyValue", "empty", "vazio", "vac\xEDo"], ["database.creating", "Creating...", "Criando...", "Creando..."], ["population.strategy.automatic", "Automatic", "Autom\xE1tico", "Autom\xE1tico"], @@ -31107,10 +31231,10 @@Modo offline indisponível
var exportCsvBtn = document.getElementById("exportCsvBtn"); var exportJsonBtn = document.getElementById("exportJsonBtn"); var sqlTabsEl = document.getElementById("sqlTabs"); + var sqlTabActionsLayer = document.getElementById("sqlTabActionsLayer"); + var sqlTabsStrip = document.getElementById("sqlTabsStrip"); var sqlTabsOverflowMenu = document.getElementById("sqlTabsOverflowMenu"); var sqlTabsOverflowList = document.getElementById("sqlTabsOverflowList"); - var renameActiveSqlTabBtn = document.getElementById("renameActiveSqlTabBtn"); - var closeActiveSqlTabBtn = document.getElementById("closeActiveSqlTabBtn"); var newSqlTabBtn = document.getElementById("newSqlTabBtn"); var sqlEditorTitle = document.getElementById("sqlEditorTitle"); var closeTabConfirmModal = document.getElementById("closeTabConfirmModal"); @@ -31118,6 +31242,11 @@Modo offline indisponível
var closeTabPreview = document.getElementById("closeTabPreview"); var cancelCloseTabBtn = document.getElementById("cancelCloseTabBtn"); var confirmCloseTabBtn = document.getElementById("confirmCloseTabBtn"); + var closeAllTabsConfirmModal = document.getElementById("closeAllTabsConfirmModal"); + var closeAllTabsTitle = document.getElementById("closeAllTabsTitle"); + var closeAllTabsConfirmText = document.getElementById("closeAllTabsConfirmText"); + var cancelCloseAllTabsBtn = document.getElementById("cancelCloseAllTabsBtn"); + var confirmCloseAllTabsBtn = document.getElementById("confirmCloseAllTabsBtn"); var sqlEditor = document.getElementById("sqlEditor"); var sqlFindPanel = document.getElementById("sqlFindPanel"); var sqlFindInput = document.getElementById("sqlFindInput"); @@ -32619,20 +32748,9 @@Modo offline indisponível
}; var requestCloseSqlTab = () => { }; - var headerActionsBound = false; function configureSqlTabActions(actions) { switchSqlTab = actions.switchSqlTab; requestCloseSqlTab = actions.requestCloseSqlTab; - if (headerActionsBound) return; - renameActiveSqlTabBtn?.addEventListener("click", () => { - const activeTabId = getActiveSqlTabId(); - if (activeTabId) startInlineTabRename(activeTabId); - }); - closeActiveSqlTabBtn?.addEventListener("click", () => { - const activeTabId = getActiveSqlTabId(); - if (activeTabId) requestCloseSqlTab(activeTabId); - }); - headerActionsBound = true; } function startInlineTabRename(tabId) { const tab = findSqlTabById(tabId); @@ -32708,6 +32826,7 @@Modo offline indisponível
const sqlTabs = getSqlTabsItems(); const activeTabId = getActiveSqlTabId(); sqlTabsEl.innerHTML = ""; + sqlTabActionsLayer.innerHTML = ""; for (let tabIndex = 0; tabIndex < sqlTabs.length; tabIndex += 1) { const tab = sqlTabs[tabIndex]; const hasResult = tab.resultSets && tab.resultSets.some((rs) => rs.columns && rs.columns.length); @@ -32830,22 +32949,90 @@Modo offline indisponível
finishInlineTabRename(tab.id, input.value); }); } + const inlineActions = document.createElement("div"); + inlineActions.className = `sql-tab-actions-portal ${isActive ? "active" : ""}`; + inlineActions.setAttribute("role", "presentation"); + inlineActions.dataset.tabActionsId = tab.id; + const renameButton = document.createElement("button"); + renameButton.className = "ui-button ui-button-icon sql-tab-inline-action sql-tab-inline-rename"; + renameButton.type = "button"; + renameButton.dataset.tabRenameId = tab.id; + renameButton.disabled = isEditing; + renameButton.title = t("tabs.renameNamedLabel", { title: tab.title }); + renameButton.setAttribute("aria-label", t("tabs.renameNamedLabel", { title: tab.title })); + renameButton.innerHTML = ` + + `; + renameButton.addEventListener("click", (event) => { + event.preventDefault(); + event.stopPropagation(); + startInlineTabRename(tab.id); + }); + inlineActions.appendChild(renameButton); + const closeButton = document.createElement("button"); + closeButton.className = "ui-button ui-button-icon sql-tab-inline-action sql-tab-inline-close"; + closeButton.type = "button"; + closeButton.dataset.tabCloseId = tab.id; + closeButton.disabled = sqlTabs.length <= 1 || isEditing; + closeButton.title = t("tabs.closeNamedLabel", { title: tab.title }); + closeButton.setAttribute("aria-label", t("tabs.closeNamedLabel", { title: tab.title })); + closeButton.innerHTML = ` + + `; + closeButton.addEventListener("click", (event) => { + event.preventDefault(); + event.stopPropagation(); + requestCloseSqlTab(tab.id); + }); + inlineActions.appendChild(closeButton); + let concealActionsTimer = null; + const revealActions = () => { + if (concealActionsTimer) clearTimeout(concealActionsTimer); + inlineActions.classList.add("is-revealed"); + }; + const concealActions = () => { + if (concealActionsTimer) clearTimeout(concealActionsTimer); + concealActionsTimer = setTimeout(() => { + const activeElement = document.activeElement; + const hasActionFocus = activeElement && inlineActions.contains(activeElement); + if (!inlineActions.matches(":hover") && !button.matches(":focus") && !hasActionFocus) { + inlineActions.classList.remove("is-revealed"); + } + }, 40); + }; + item.addEventListener("mouseenter", revealActions); + item.addEventListener("mouseleave", concealActions); + button.addEventListener("focus", revealActions); + button.addEventListener("blur", concealActions); + inlineActions.addEventListener("mouseenter", revealActions); + inlineActions.addEventListener("mouseleave", concealActions); item.appendChild(button); if (renameField) item.appendChild(renameField); sqlTabsEl.appendChild(item); + sqlTabActionsLayer.appendChild(inlineActions); + requestAnimationFrame(() => { + inlineActions.style.left = `${item.offsetLeft}px`; + inlineActions.style.top = `${item.offsetTop}px`; + inlineActions.style.width = `${item.offsetWidth}px`; + inlineActions.style.height = `${item.offsetHeight}px`; + }); } renderSqlTabsOverflowMenu(); const activeTab = findSqlTabById(activeTabId); - const isRenamingActiveTab = getEditingSqlTabId() === activeTabId; - if (renameActiveSqlTabBtn) { - renameActiveSqlTabBtn.disabled = !activeTab || isRenamingActiveTab; - renameActiveSqlTabBtn.title = t("tabs.renameLabel"); - renameActiveSqlTabBtn.setAttribute("aria-label", t("tabs.renameNamedLabel", { title: activeTab?.title || t("tabs.defaultTitle") })); - } - if (closeActiveSqlTabBtn) { - closeActiveSqlTabBtn.disabled = sqlTabs.length <= 1 || isRenamingActiveTab; - closeActiveSqlTabBtn.title = t("tabs.closeLabel"); - closeActiveSqlTabBtn.setAttribute("aria-label", t("tabs.closeNamedLabel", { title: activeTab?.title || t("tabs.defaultTitle") })); + if (closeAllTabsBtn) { + closeAllTabsBtn.disabled = sqlTabs.length <= 1; + closeAllTabsBtn.title = t("tabs.closeAll"); + closeAllTabsBtn.setAttribute("aria-label", t("tabs.closeAll")); } newSqlTabBtn.disabled = sqlTabs.length >= MAX_SQL_TABS; newSqlTabBtn.title = sqlTabs.length >= MAX_SQL_TABS ? t("tabs.limitReached", { count: MAX_SQL_TABS }) : t("tabs.newTitle"); @@ -32867,17 +33054,17 @@Modo offline indisponível
}); } function updateSqlTabsOverflow() { - if (!sqlTabsEl) return; - const header = sqlTabsEl.closest(".sql-tabs-header"); - const hasOverflow = sqlTabsEl.scrollWidth > sqlTabsEl.clientWidth + 1; - sqlTabsEl.classList.toggle("is-overflowing", hasOverflow); + if (!sqlTabsStrip) return; + const header = sqlTabsStrip.closest(".sql-tabs-header"); + const hasOverflow = sqlTabsStrip.scrollWidth > sqlTabsStrip.clientWidth + 1; + sqlTabsStrip.classList.toggle("is-overflowing", hasOverflow); if (sqlTabsOverflowMenu) { sqlTabsOverflowMenu.hidden = !hasOverflow; if (!hasOverflow) closeSqlTabsOverflowMenu(); } if (!header) return; - const canScrollLeft = hasOverflow && sqlTabsEl.scrollLeft > 1; - const canScrollRight = hasOverflow && sqlTabsEl.scrollLeft + sqlTabsEl.clientWidth < sqlTabsEl.scrollWidth - 1; + const canScrollLeft = hasOverflow && sqlTabsStrip.scrollLeft > 1; + const canScrollRight = hasOverflow && sqlTabsStrip.scrollLeft + sqlTabsStrip.clientWidth < sqlTabsStrip.scrollWidth - 1; header.classList.toggle("can-scroll-left", canScrollLeft); header.classList.toggle("can-scroll-right", canScrollRight); } @@ -33212,6 +33399,12 @@Modo offline indisponível
setSqlTabsState({ isSwitching: false }); saveSqlTabsToStorage(); } + function focusActiveSqlTab() { + requestAnimationFrame(() => { + const activeTab = sqlTabsEl?.querySelector(".sql-tab.active"); + if (activeTab && typeof activeTab.focus === "function") activeTab.focus(); + }); + } var sqlTabsController = { init() { const restored = loadSqlTabsFromStorage(); @@ -33310,8 +33503,26 @@Modo offline indisponível
renderSqlTabs(); saveSqlTabsToStorage(); } + focusActiveSqlTab(); setStatus(t("tabs.closed"), "ok"); }, + requestCloseAll() { + const count = getSqlTabsItems().length; + if (count <= 1) { + setStatus(t("tabs.keepOne"), "warn"); + return; + } + closeAllTabsTitle.textContent = t("tabs.closeAllTitle", { count }); + closeAllTabsConfirmText.textContent = t("tabs.closeAllWarning", { count }); + modalController.open(closeAllTabsConfirmModal); + }, + cancelCloseAll() { + modalController.close(closeAllTabsConfirmModal); + }, + confirmCloseAll() { + modalController.close(closeAllTabsConfirmModal); + this.closeAll(); + }, closeAll() { const freshTab = createEmptyTab(); setSqlTabsState({ @@ -33319,6 +33530,7 @@Modo offline indisponível
activeTabId: freshTab.id }); loadTabState(freshTab); + focusActiveSqlTab(); setStatus(t("tabs.allClosed"), "ok"); saveSqlTabsToStorage(); } @@ -33348,6 +33560,15 @@Modo offline indisponível
function closeAllSqlTabs() { sqlTabsController.closeAll(); } + function requestCloseAllSqlTabs() { + sqlTabsController.requestCloseAll(); + } + function cancelCloseAllSqlTabs() { + sqlTabsController.cancelCloseAll(); + } + function confirmCloseAllSqlTabs() { + sqlTabsController.confirmCloseAll(); + } function initSqlTabs() { sqlTabsController.init(); } @@ -36344,7 +36565,7 @@Modo offline indisponível
schemaCollapseBtn.addEventListener("click", toggleSchemaPanel); schemaToggleRail.addEventListener("click", toggleSchemaPanel); newSqlTabBtn.addEventListener("click", addSqlTab); - sqlTabsEl.addEventListener("scroll", updateSqlTabsOverflow, { passive: true }); + sqlTabsStrip.addEventListener("scroll", updateSqlTabsOverflow, { passive: true }); window.addEventListener("resize", updateSqlTabsOverflow); openSqlBtn.addEventListener("click", () => openSqlFilePicker(false)); openRunSqlBtn.addEventListener("click", () => openSqlFilePicker(true)); @@ -36353,7 +36574,7 @@Modo offline indisponível
}); copySqlBtn.addEventListener("click", copyFullSql); clearSqlBtn.addEventListener("click", clearSqlEditor); - if (closeAllTabsBtn) closeAllTabsBtn.addEventListener("click", closeAllSqlTabs); + if (closeAllTabsBtn) closeAllTabsBtn.addEventListener("click", requestCloseAllSqlTabs); clearPasteSqlBtn.addEventListener("click", clearAndPasteSql); } @@ -38588,6 +38809,11 @@Modo offline indisponível
closeTabConfirmModal.addEventListener("click", (event) => { if (modalController.isBackdropClick(event, closeTabConfirmModal)) cancelCloseSqlTab(); }); + cancelCloseAllTabsBtn.addEventListener("click", cancelCloseAllSqlTabs); + confirmCloseAllTabsBtn.addEventListener("click", confirmCloseAllSqlTabs); + closeAllTabsConfirmModal.addEventListener("click", (event) => { + if (modalController.isBackdropClick(event, closeAllTabsConfirmModal)) cancelCloseAllSqlTabs(); + }); } function bindBootRecoveryUi() { if (!bootRetryBtn) return; diff --git a/scripts/validate-accessibility.mjs b/scripts/validate-accessibility.mjs index b111cd5..c6d63ff 100644 --- a/scripts/validate-accessibility.mjs +++ b/scripts/validate-accessibility.mjs @@ -86,10 +86,12 @@ if (!tabButtonTemplate || /]*role="tablist"[^>]*><\/div>\s*Schema
Instruções SQL
Fechar aba?
Fechar todas as abas?
+Todo o texto SQL e os resultados destas abas serão perdidos. Uma nova aba será aberta.
+