@matdata/yasgui 5.16.0 → 5.18.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (59) hide show
  1. package/build/ts/src/Tab.js +12 -2
  2. package/build/ts/src/Tab.js.map +1 -1
  3. package/build/ts/src/TabContextMenu.d.ts +1 -0
  4. package/build/ts/src/TabContextMenu.js +42 -0
  5. package/build/ts/src/TabContextMenu.js.map +1 -1
  6. package/build/ts/src/TabSettingsModal.d.ts +0 -1
  7. package/build/ts/src/TabSettingsModal.js +22 -25
  8. package/build/ts/src/TabSettingsModal.js.map +1 -1
  9. package/build/ts/src/index.d.ts +6 -0
  10. package/build/ts/src/index.js +42 -0
  11. package/build/ts/src/index.js.map +1 -1
  12. package/build/ts/src/prefixUtils.d.ts +1 -0
  13. package/build/ts/src/prefixUtils.js +23 -0
  14. package/build/ts/src/prefixUtils.js.map +1 -0
  15. package/build/ts/src/queryManagement/QueryBrowser.d.ts +8 -0
  16. package/build/ts/src/queryManagement/QueryBrowser.js +283 -116
  17. package/build/ts/src/queryManagement/QueryBrowser.js.map +1 -1
  18. package/build/ts/src/queryManagement/QueryHistoryModal.d.ts +35 -0
  19. package/build/ts/src/queryManagement/QueryHistoryModal.js +266 -0
  20. package/build/ts/src/queryManagement/QueryHistoryModal.js.map +1 -0
  21. package/build/ts/src/queryManagement/WorkspaceSettingsForm.js +8 -5
  22. package/build/ts/src/queryManagement/WorkspaceSettingsForm.js.map +1 -1
  23. package/build/ts/src/queryManagement/backends/GitWorkspaceBackend.d.ts +1 -0
  24. package/build/ts/src/queryManagement/backends/GitWorkspaceBackend.js +33 -0
  25. package/build/ts/src/queryManagement/backends/GitWorkspaceBackend.js.map +1 -1
  26. package/build/ts/src/queryManagement/backends/SparqlWorkspaceBackend.d.ts +1 -0
  27. package/build/ts/src/queryManagement/backends/SparqlWorkspaceBackend.js +3 -0
  28. package/build/ts/src/queryManagement/backends/SparqlWorkspaceBackend.js.map +1 -1
  29. package/build/ts/src/queryManagement/backends/WorkspaceBackend.d.ts +1 -0
  30. package/build/ts/src/queryManagement/countManagedQueries.d.ts +2 -0
  31. package/build/ts/src/queryManagement/countManagedQueries.js +35 -0
  32. package/build/ts/src/queryManagement/countManagedQueries.js.map +1 -0
  33. package/build/ts/src/tabNavigationHistory.d.ts +3 -0
  34. package/build/ts/src/tabNavigationHistory.js +13 -0
  35. package/build/ts/src/tabNavigationHistory.js.map +1 -0
  36. package/build/ts/src/version.d.ts +1 -1
  37. package/build/ts/src/version.js +1 -1
  38. package/build/yasgui.min.css +1 -1
  39. package/build/yasgui.min.css.map +3 -3
  40. package/build/yasgui.min.js +244 -232
  41. package/build/yasgui.min.js.map +4 -4
  42. package/package.json +3 -3
  43. package/src/Tab.ts +22 -3
  44. package/src/TabContextMenu.ts +42 -0
  45. package/src/TabSettingsModal.ts +22 -29
  46. package/src/index.ts +50 -0
  47. package/src/prefixUtils.ts +26 -0
  48. package/src/queryManagement/QueryBrowser.scss +85 -0
  49. package/src/queryManagement/QueryBrowser.ts +429 -213
  50. package/src/queryManagement/QueryHistoryModal.scss +239 -0
  51. package/src/queryManagement/QueryHistoryModal.ts +346 -0
  52. package/src/queryManagement/WorkspaceSettingsForm.ts +8 -5
  53. package/src/queryManagement/backends/GitWorkspaceBackend.ts +39 -0
  54. package/src/queryManagement/backends/SparqlWorkspaceBackend.ts +5 -0
  55. package/src/queryManagement/backends/WorkspaceBackend.ts +8 -0
  56. package/src/queryManagement/countManagedQueries.ts +28 -0
  57. package/src/tabNavigationHistory.ts +17 -0
  58. package/src/themes.scss +2 -0
  59. package/src/version.ts +1 -1
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@matdata/yasgui",
3
3
  "description": "Yet Another SPARQL GUI",
4
- "version": "5.16.0",
4
+ "version": "5.18.0",
5
5
  "main": "build/yasgui.min.js",
6
6
  "types": "build/ts/src/index.d.ts",
7
7
  "license": "MIT",
@@ -33,8 +33,8 @@
33
33
  "jsuri": "^1.3.1",
34
34
  "lodash-es": "^4.17.15",
35
35
  "sortablejs": "^1.10.2",
36
- "@matdata/yasgui-graph-plugin": "^1.4.1",
37
- "@matdata/yasgui-table-plugin": "^1.1.0"
36
+ "@matdata/yasgui-graph-plugin": "^1.6.1",
37
+ "@matdata/yasgui-table-plugin": "^1.3.0"
38
38
  },
39
39
  "devDependencies": {
40
40
  "@types/autosuggest-highlight": "^3.1.0",
package/src/Tab.ts CHANGED
@@ -3,7 +3,13 @@ import { addClass, removeClass, getAsValue } from "@matdata/yasgui-utils";
3
3
  import { TabListEl } from "./TabElements";
4
4
  import TabSettingsModal from "./TabSettingsModal";
5
5
  import { default as Yasqe, RequestConfig, PlainRequestConfig, PartialConfig as YasqeConfig } from "@matdata/yasqe";
6
- import { default as Yasr, Parser, Config as YasrConfig, PersistentConfig as YasrPersistentConfig } from "@matdata/yasr";
6
+ import {
7
+ default as Yasr,
8
+ Parser,
9
+ Config as YasrConfig,
10
+ PersistentConfig as YasrPersistentConfig,
11
+ PluginQueryOptions as YasrPluginQueryOptions,
12
+ } from "@matdata/yasr";
7
13
  import { mapValues, eq, mergeWith, words, deburr, invert } from "lodash-es";
8
14
  import * as shareLink from "./linkUtils";
9
15
  import EndpointSelect from "./endpointSelect";
@@ -430,6 +436,15 @@ export class Tab extends EventEmitter {
430
436
  private handleKeyDown = (event: KeyboardEvent) => {
431
437
  if (event.defaultPrevented) return;
432
438
 
439
+ // Ctrl+, → backward (less recently used), Ctrl+Alt+, → forward (more recently used)
440
+ // Ctrl+Tab / Ctrl+Shift+Tab cannot be used: the browser intercepts them before keydown fires
441
+ const isTabSwitchShortcut = (event.ctrlKey || event.metaKey) && !event.shiftKey && event.key === ",";
442
+ if (isTabSwitchShortcut) {
443
+ event.preventDefault();
444
+ this.yasgui.selectRecentlyUsedTab(event.altKey ? "forward" : "backward");
445
+ return;
446
+ }
447
+
433
448
  const saveModalOpen = !!document.querySelector(".saveManagedQueryModalOverlay.open");
434
449
  if (!saveModalOpen) {
435
450
  const isSaveShortcut =
@@ -1584,6 +1599,7 @@ WHERE {
1584
1599
  {
1585
1600
  customQuery: query,
1586
1601
  customAccept: "text/turtle",
1602
+ silent: true,
1587
1603
  },
1588
1604
  );
1589
1605
 
@@ -1672,12 +1688,15 @@ WHERE {
1672
1688
  // Add default renderers to the end, to give our custom ones priority.
1673
1689
  ...(Yasr.defaults.errorRenderers || []),
1674
1690
  ],
1675
- executeQuery: async (query: string, options?: { acceptHeader?: string }) => {
1691
+ executeQuery: async (query: string, options?: YasrPluginQueryOptions) => {
1676
1692
  if (!this.yasqe) throw new Error("No YASQE instance available");
1677
- return Yasqe.Sparql.executeQuery(this.yasqe, undefined, {
1693
+ const response = await Yasqe.Sparql.executeQuery(this.yasqe, undefined, {
1678
1694
  customQuery: query,
1679
1695
  customAccept: options?.acceptHeader,
1696
+ signal: options?.signal,
1697
+ silent: true,
1680
1698
  });
1699
+ return response;
1681
1700
  },
1682
1701
  };
1683
1702
  // Allow getDownloadFilName to be overwritten by the global config
@@ -3,6 +3,8 @@ import { default as Yasgui, getRandomId } from "./";
3
3
  import Tab from "./Tab";
4
4
  import { TabListEl } from "./TabElements";
5
5
  import { cloneDeep } from "lodash-es";
6
+ import { getWorkspaceBackend } from "./queryManagement/backends/getWorkspaceBackend";
7
+ import type { GitQueryRef, SparqlQueryRef } from "./queryManagement/types";
6
8
  import "./TabContextMenu.scss";
7
9
  export interface TabContextConfig {
8
10
  name: string;
@@ -17,6 +19,7 @@ export default class TabContextMenu {
17
19
  private duplicateTabEl!: HTMLElement;
18
20
  private saveManagedQueryEl!: HTMLElement;
19
21
  private saveAsRqFileEl!: HTMLElement;
22
+ private copyManagedQueryUriEl!: HTMLElement;
20
23
  private closeTabEl!: HTMLElement;
21
24
  private closeOtherTabsEl!: HTMLElement;
22
25
  private reOpenOldTab!: HTMLElement;
@@ -55,6 +58,8 @@ export default class TabContextMenu {
55
58
 
56
59
  this.saveAsRqFileEl = this.getMenuItemEl("Save as .rq file");
57
60
 
61
+ this.copyManagedQueryUriEl = this.getMenuItemEl("Copy URI");
62
+
58
63
  this.closeTabEl = this.getMenuItemEl("Close Tab");
59
64
 
60
65
  this.closeOtherTabsEl = this.getMenuItemEl("Close other tabs");
@@ -67,6 +72,7 @@ export default class TabContextMenu {
67
72
  dropDownList.appendChild(this.duplicateTabEl);
68
73
  dropDownList.appendChild(this.saveManagedQueryEl);
69
74
  dropDownList.appendChild(this.saveAsRqFileEl);
75
+ dropDownList.appendChild(this.copyManagedQueryUriEl);
70
76
  // Add divider
71
77
  dropDownList.appendChild(document.createElement("hr"));
72
78
  dropDownList.appendChild(this.closeTabEl);
@@ -125,6 +131,42 @@ export default class TabContextMenu {
125
131
  this.closeConfigMenu();
126
132
  };
127
133
 
134
+ // Copy URI for managed query tabs
135
+ const meta = tab?.getManagedQueryMetadata();
136
+ if (meta) {
137
+ const workspaceConfig = this.yasgui.persistentConfig?.getWorkspaces().find((w) => w.id === meta.workspaceId);
138
+ if (workspaceConfig) {
139
+ const queryId =
140
+ meta.backendType === "git"
141
+ ? (meta.queryRef as GitQueryRef).path
142
+ : (meta.queryRef as SparqlQueryRef).managedQueryIri;
143
+ if (queryId) {
144
+ const backend = getWorkspaceBackend(workspaceConfig, {
145
+ persistentConfig: this.yasgui.persistentConfig,
146
+ });
147
+ const uri = backend.getQueryUri?.(queryId);
148
+ if (uri) {
149
+ this.copyManagedQueryUriEl.onclick = async () => {
150
+ try {
151
+ await navigator.clipboard.writeText(uri);
152
+ } catch {
153
+ window.prompt("Copy this URI:", uri);
154
+ }
155
+ this.closeConfigMenu();
156
+ };
157
+ } else {
158
+ addClass(this.copyManagedQueryUriEl, "disabled");
159
+ }
160
+ } else {
161
+ addClass(this.copyManagedQueryUriEl, "disabled");
162
+ }
163
+ } else {
164
+ addClass(this.copyManagedQueryUriEl, "disabled");
165
+ }
166
+ } else {
167
+ addClass(this.copyManagedQueryUriEl, "disabled");
168
+ }
169
+
128
170
  // Close tab functionality
129
171
  this.closeTabEl.onclick = () => tab?.close();
130
172
 
@@ -5,6 +5,7 @@ import * as ConfigExportImport from "./ConfigExportImport";
5
5
  import { VERSION } from "./version";
6
6
  import * as OAuth2Utils from "./OAuth2Utils";
7
7
  import PersistentConfig from "./PersistentConfig";
8
+ import { deduplicatePrefixes } from "./prefixUtils";
8
9
  import { WorkspaceSettingsForm } from "./queryManagement/WorkspaceSettingsForm";
9
10
 
10
11
  const AcceptOptionsMap: { key: string; value: string }[] = [
@@ -847,7 +848,12 @@ export default class TabSettingsModal {
847
848
 
848
849
  private renderEndpointsList(container: HTMLElement) {
849
850
  container.innerHTML = "";
850
- const configs = this.tab.yasgui.persistentConfig.getEndpointConfigs();
851
+ const configs = [...this.tab.yasgui.persistentConfig.getEndpointConfigs()];
852
+ configs.sort((a, b) => {
853
+ const aKey = (a.label || a.endpoint).toLowerCase();
854
+ const bKey = (b.label || b.endpoint).toLowerCase();
855
+ return aKey.localeCompare(bKey);
856
+ });
851
857
 
852
858
  // Create table (even if empty, we'll show add form)
853
859
  const table = document.createElement("table");
@@ -1687,7 +1693,7 @@ export default class TabSettingsModal {
1687
1693
  const autoCapture = this.autoCaptureCheckbox.checked;
1688
1694
 
1689
1695
  // Parse and deduplicate prefixes
1690
- const deduplicated = this.deduplicatePrefixes(prefixText);
1696
+ const deduplicated = deduplicatePrefixes(prefixText);
1691
1697
  this.tab.yasgui.persistentConfig.setPrefixes(deduplicated);
1692
1698
  this.tab.yasgui.persistentConfig.setAutoCaptureEnabled(autoCapture);
1693
1699
 
@@ -1798,32 +1804,6 @@ export default class TabSettingsModal {
1798
1804
  this.close();
1799
1805
  }
1800
1806
 
1801
- private deduplicatePrefixes(prefixText: string): string {
1802
- const lines = prefixText.split("\n");
1803
- const seen = new Map<string, string>();
1804
- const result: string[] = [];
1805
-
1806
- for (const line of lines) {
1807
- const trimmed = line.trim();
1808
- if (!trimmed) continue;
1809
-
1810
- // Extract prefix label from line
1811
- const match = trimmed.match(/^\s*PREFIX\s+(\w+):\s*<(.+)>\s*$/i);
1812
- if (match) {
1813
- const label = match[1].toLowerCase();
1814
- if (!seen.has(label)) {
1815
- seen.set(label, trimmed);
1816
- result.push(trimmed);
1817
- }
1818
- } else {
1819
- // Keep non-prefix lines as-is
1820
- result.push(trimmed);
1821
- }
1822
- }
1823
-
1824
- return result.join("\n");
1825
- }
1826
-
1827
1807
  private insertPrefixesIntoQuery() {
1828
1808
  const yasqe = this.tab.getYasqe();
1829
1809
  if (!yasqe) return;
@@ -1885,7 +1865,7 @@ export default class TabSettingsModal {
1885
1865
  // Merge with existing prefixes
1886
1866
  const existingPrefixes = this.tab.yasgui.persistentConfig.getPrefixes();
1887
1867
  const combined = existingPrefixes + "\n" + newPrefixLines.join("\n");
1888
- const deduplicated = this.deduplicatePrefixes(combined);
1868
+ const deduplicated = deduplicatePrefixes(combined);
1889
1869
 
1890
1870
  this.tab.yasgui.persistentConfig.setPrefixes(deduplicated);
1891
1871
  }
@@ -2078,6 +2058,19 @@ export default class TabSettingsModal {
2078
2058
  { keys: ["Esc"], description: "Exit fullscreen mode" },
2079
2059
  ],
2080
2060
  },
2061
+ {
2062
+ category: "YASGUI Tabs",
2063
+ shortcuts: [
2064
+ {
2065
+ keys: ["Ctrl+Alt+Tab", "Cmd+Alt+Tab"],
2066
+ description: "Switch to previously used YASGUI tab",
2067
+ },
2068
+ {
2069
+ keys: ["Ctrl+Alt+Shift+Tab", "Cmd+Alt+Shift+Tab"],
2070
+ description: "Switch to next YASGUI tab in recently used order",
2071
+ },
2072
+ ],
2073
+ },
2081
2074
  ];
2082
2075
 
2083
2076
  shortcutsData.forEach((section) => {
package/src/index.ts CHANGED
@@ -13,6 +13,7 @@ import { addClass, removeClass } from "@matdata/yasgui-utils";
13
13
  import GeoPlugin from "yasgui-geo-tg";
14
14
  import GraphPlugin from "@matdata/yasgui-graph-plugin";
15
15
  import TablePlugin from "@matdata/yasgui-table-plugin";
16
+ import { moveTabIdToFront, removeTabId } from "./tabNavigationHistory";
16
17
  import "@matdata/yasgui-graph-plugin/dist/yasgui-graph-plugin.min.css";
17
18
  import "@matdata/yasgui-table-plugin/dist/yasgui-table-plugin.min.css";
18
19
  import { ThemeManager, Theme } from "./ThemeManager";
@@ -155,6 +156,9 @@ export class Yasgui extends EventEmitter {
155
156
  public persistentConfig: PersistentConfig;
156
157
  public themeManager: ThemeManager;
157
158
  public queryBrowser: QueryBrowser;
159
+ private recentTabIds: string[] = [];
160
+ private navigationSnapshot: string[] | null = null;
161
+ private navigationCursor = 0;
158
162
  public static Tab = Tab;
159
163
  constructor(parent: HTMLElement, config: PartialConfig) {
160
164
  super();
@@ -185,6 +189,9 @@ export class Yasgui extends EventEmitter {
185
189
  this.tabPanelsEl = document.createElement("div");
186
190
 
187
191
  this.queryBrowser = new QueryBrowser(this);
192
+ this.on("tabClose", (_yasgui, tab) => {
193
+ this.removeTabFromRecentHistory(tab.getId());
194
+ });
188
195
 
189
196
  this.rootEl.appendChild(this.tabElements.drawTabsList());
190
197
  this.rootEl.appendChild(this.tabPanelsEl);
@@ -227,6 +234,7 @@ export class Yasgui extends EventEmitter {
227
234
  const newTab = this.addTab(true);
228
235
  this.persistentConfig.setActive(newTab.getId());
229
236
  this.emit("tabChange", this, newTab);
237
+ this.recordTabInRecentHistory(newTab.getId());
230
238
  } else {
231
239
  for (const tabId of tabs) {
232
240
  this._tabs[tabId] = new Tab(this, this.persistentConfig.getTab(tabId));
@@ -237,6 +245,7 @@ export class Yasgui extends EventEmitter {
237
245
  const activeTabId = this.persistentConfig.getActiveId();
238
246
  if (activeTabId) {
239
247
  this.markTabSelected(activeTabId);
248
+ this.recordTabInRecentHistory(activeTabId);
240
249
  if (executeIdAfterInit && executeIdAfterInit === activeTabId) {
241
250
  (this.getTab(activeTabId) as Tab).query().catch(() => {});
242
251
  }
@@ -300,6 +309,7 @@ export class Yasgui extends EventEmitter {
300
309
  const tab = this.getTab();
301
310
  if (tab && tab.getId() !== tabId) {
302
311
  if (this.markTabSelected(tabId)) {
312
+ this.recordTabInRecentHistory(tabId);
303
313
  //emit
304
314
  this.emit("tabSelect", this, tabId);
305
315
  this.persistentConfig.setActive(tabId);
@@ -307,6 +317,45 @@ export class Yasgui extends EventEmitter {
307
317
  }
308
318
  return tab;
309
319
  }
320
+ private recordTabInRecentHistory(tabId: string) {
321
+ // Any non-navigation selection commits the navigation and ends navigation mode.
322
+ this.navigationSnapshot = null;
323
+ this.recentTabIds = moveTabIdToFront(this.recentTabIds, tabId);
324
+ }
325
+ private removeTabFromRecentHistory(tabId: string) {
326
+ this.recentTabIds = removeTabId(this.recentTabIds, tabId);
327
+ }
328
+ public selectRecentlyUsedTab(direction: "backward" | "forward" = "backward"): void {
329
+ const activeTab = this.getTab();
330
+ if (!activeTab) return;
331
+ const activeTabId = activeTab.getId();
332
+
333
+ // Initialize (or re-initialize) the navigation snapshot when starting a new navigation
334
+ // sequence or when the active tab no longer matches the cursor position.
335
+ // Snapshotting the history order lets repeated presses cycle through all tabs
336
+ // instead of ping-ponging between the two most-recently-used ones.
337
+ if (this.navigationSnapshot === null || this.navigationSnapshot[this.navigationCursor] !== activeTabId) {
338
+ this.navigationSnapshot = [...this.recentTabIds];
339
+ const activeIdx = this.navigationSnapshot.indexOf(activeTabId);
340
+ this.navigationCursor = activeIdx >= 0 ? activeIdx : 0;
341
+ }
342
+
343
+ if (direction === "backward") {
344
+ this.navigationCursor = Math.min(this.navigationCursor + 1, this.navigationSnapshot.length - 1);
345
+ } else {
346
+ this.navigationCursor = Math.max(this.navigationCursor - 1, 0);
347
+ }
348
+
349
+ const nextTabId = this.navigationSnapshot[this.navigationCursor];
350
+ if (!nextTabId || nextTabId === activeTabId) return;
351
+
352
+ // Select the tab without updating recentTabIds. The history is committed when the
353
+ // user performs any non-navigation action that calls recordTabInRecentHistory.
354
+ if (this.markTabSelected(nextTabId)) {
355
+ this.emit("tabSelect", this, nextTabId);
356
+ this.persistentConfig.setActive(nextTabId);
357
+ }
358
+ }
310
359
  /**
311
360
  * Checks if two persistent tab configuration are the same based.
312
361
  * It isnt a strict equality, as falsy values (e.g. a header that isnt set in one tabjson) isnt taken into consideration
@@ -417,6 +466,7 @@ export class Yasgui extends EventEmitter {
417
466
  if (setActive) {
418
467
  this.persistentConfig.setActive(tabId);
419
468
  this._tabs[tabId].show();
469
+ this.recordTabInRecentHistory(tabId);
420
470
  }
421
471
  return this._tabs[tabId];
422
472
  }
@@ -0,0 +1,26 @@
1
+ export function deduplicatePrefixes(prefixText: string): string {
2
+ const lines = prefixText.split("\n");
3
+ const seen = new Set<string>();
4
+ const result: string[] = [];
5
+
6
+ for (const line of lines) {
7
+ const trimmed = line.trim();
8
+ if (!trimmed) continue;
9
+
10
+ // Allow an empty prefix label so the default prefix form `PREFIX : <...>` is
11
+ // deduplicated together with named prefixes, while keeping the original
12
+ // word-character restriction for named labels.
13
+ const match = trimmed.match(/^\s*PREFIX\s+(\w*):\s*<([^>]+)>\s*$/i);
14
+ if (match) {
15
+ const label = match[1].toLowerCase();
16
+ if (!seen.has(label)) {
17
+ seen.add(label);
18
+ result.push(trimmed);
19
+ }
20
+ } else {
21
+ result.push(trimmed);
22
+ }
23
+ }
24
+
25
+ return result.join("\n");
26
+ }
@@ -325,6 +325,91 @@
325
325
  white-space: nowrap;
326
326
  }
327
327
 
328
+ &__context-menu {
329
+ position: fixed;
330
+ z-index: 10001;
331
+ list-style: none;
332
+ padding: 4px 0;
333
+ margin: 0;
334
+ min-width: 140px;
335
+ background: var(--yasgui-bg-primary, white);
336
+ border: 1px solid var(--yasgui-border-color, #e0e0e0);
337
+ border-radius: 4px;
338
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
339
+ }
340
+
341
+ &__context-menu-item {
342
+ padding: 7px 16px;
343
+ cursor: pointer;
344
+ white-space: nowrap;
345
+ color: var(--yasgui-text-primary, #000);
346
+ font-size: 13px;
347
+ line-height: 1.4;
348
+
349
+ &:hover {
350
+ background: var(--yasgui-bg-secondary, #f5f5f5);
351
+ color: var(--yasgui-button-hover, #000);
352
+ }
353
+
354
+ &--danger {
355
+ color: var(--yasgui-error-color, #c00);
356
+
357
+ &:hover {
358
+ background: var(--yasgui-bg-secondary, #f5f5f5);
359
+ color: var(--yasgui-error-color, #c00);
360
+ }
361
+ }
362
+ }
363
+
364
+ &__rename-input {
365
+ flex: 1;
366
+ min-width: 0;
367
+ font: inherit;
368
+ font-size: 13px;
369
+ color: var(--yasgui-text-primary, #000);
370
+ background: var(--yasgui-bg-primary, white);
371
+ border: 1px solid var(--yasgui-accent-color, #337ab7);
372
+ border-radius: 3px;
373
+ padding: 1px 4px;
374
+ outline: none;
375
+ box-shadow: 0 0 0 2px rgba(51, 122, 183, 0.25);
376
+ }
377
+
378
+ &__inline-confirm {
379
+ flex: 1;
380
+ font-size: 13px;
381
+ color: var(--yasgui-text-primary, #000);
382
+ white-space: nowrap;
383
+ overflow: hidden;
384
+ text-overflow: ellipsis;
385
+ }
386
+
387
+ &__inline-confirm-btn {
388
+ appearance: none;
389
+ background: transparent;
390
+ border: 1px solid var(--yasgui-border-color, #e0e0e0);
391
+ border-radius: 3px;
392
+ padding: 1px 8px;
393
+ font: inherit;
394
+ font-size: 12px;
395
+ cursor: pointer;
396
+ color: var(--yasgui-text-primary, #000);
397
+ flex-shrink: 0;
398
+
399
+ &:hover {
400
+ background: var(--yasgui-bg-secondary, #f5f5f5);
401
+ }
402
+
403
+ &--danger {
404
+ color: var(--yasgui-error-color, #c00);
405
+ border-color: var(--yasgui-error-color, #c00);
406
+
407
+ &:hover {
408
+ background: rgba(204, 0, 0, 0.08);
409
+ }
410
+ }
411
+ }
412
+
328
413
  &__tree-meta {
329
414
  padding: 4px 8px;
330
415
  font-size: 13px;