mirror of
https://github.com/DeNNiiInc/dbgate.git
synced 2026-04-28 14:06:00 +00:00
dropdown menu implementation
This commit is contained in:
13
packages/web/modals/CurrentDropDownMenu.svelte
Normal file
13
packages/web/modals/CurrentDropDownMenu.svelte
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
<script>
|
||||||
|
import { currentDropDownMenu } from '../src/stores';
|
||||||
|
import DropDownMenu from './DropDownMenu.svelte';
|
||||||
|
</script>
|
||||||
|
|
||||||
|
{#if $currentDropDownMenu}
|
||||||
|
<DropDownMenu
|
||||||
|
left={$currentDropDownMenu.left}
|
||||||
|
top={$currentDropDownMenu.top}
|
||||||
|
items={$currentDropDownMenu.items}
|
||||||
|
on:close={() => ($currentDropDownMenu = null)}
|
||||||
|
/>
|
||||||
|
{/if}
|
||||||
77
packages/web/modals/DropDownMenu.svelte
Normal file
77
packages/web/modals/DropDownMenu.svelte
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
<script>
|
||||||
|
import clickOutside from '../src/utility/clickOutside';
|
||||||
|
import { createEventDispatcher } from 'svelte';
|
||||||
|
|
||||||
|
export let items;
|
||||||
|
export let top;
|
||||||
|
export let left;
|
||||||
|
|
||||||
|
const dispatch = createEventDispatcher();
|
||||||
|
|
||||||
|
function handleClick(item) {
|
||||||
|
dispatch('close');
|
||||||
|
if (item.onClick) item.onClick();
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<ul style={`left: ${left}px; top: ${top}px`} use:clickOutside on:clickOutside={() => dispatch('close')}>
|
||||||
|
{#each items as item}
|
||||||
|
{#if item.divider}
|
||||||
|
<li class="divider" />
|
||||||
|
{:else}
|
||||||
|
<li>
|
||||||
|
<a on:click={() => handleClick(item)}>
|
||||||
|
{item.text}
|
||||||
|
{#if item.keyText}
|
||||||
|
<span class="keyText">{item.keyText}</span>
|
||||||
|
{/if}
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
{/if}
|
||||||
|
{/each}
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
ul {
|
||||||
|
position: absolute;
|
||||||
|
list-style: none;
|
||||||
|
background-color: #fff;
|
||||||
|
border-radius: 4px;
|
||||||
|
border: 1px solid rgba(0, 0, 0, 0.15);
|
||||||
|
box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175);
|
||||||
|
padding: 5px 0;
|
||||||
|
margin: 2px 0 0;
|
||||||
|
font-size: 14px;
|
||||||
|
text-align: left;
|
||||||
|
min-width: 160px;
|
||||||
|
z-index: 1050;
|
||||||
|
cursor: default;
|
||||||
|
}
|
||||||
|
|
||||||
|
.keyText {
|
||||||
|
font-style: italic;
|
||||||
|
font-weight: bold;
|
||||||
|
text-align: right;
|
||||||
|
margin-left: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
padding: 3px 20px;
|
||||||
|
line-height: 1.42;
|
||||||
|
display: block;
|
||||||
|
white-space: nop-wrap;
|
||||||
|
color: #262626;
|
||||||
|
}
|
||||||
|
|
||||||
|
a:hover {
|
||||||
|
background-color: #f5f5f5;
|
||||||
|
text-decoration: none;
|
||||||
|
color: #262626;
|
||||||
|
}
|
||||||
|
|
||||||
|
.divider {
|
||||||
|
margin: 9px 0px 9px 0px;
|
||||||
|
border-top: 1px solid #f2f2f2;
|
||||||
|
border-bottom: 1px solid #fff;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -7,7 +7,7 @@
|
|||||||
import CommandPalette from './commands/CommandPalette.svelte';
|
import CommandPalette from './commands/CommandPalette.svelte';
|
||||||
import Toolbar from './widgets/Toolbar.svelte';
|
import Toolbar from './widgets/Toolbar.svelte';
|
||||||
import splitterDrag from './utility/splitterDrag';
|
import splitterDrag from './utility/splitterDrag';
|
||||||
import { update } from 'lodash';
|
import CurrentDropDownMenu from '../modals/CurrentDropDownMenu.svelte';
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class={`${$currentTheme} root`}>
|
<div class={`${$currentTheme} root`}>
|
||||||
@@ -43,6 +43,7 @@
|
|||||||
<Toolbar />
|
<Toolbar />
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
|
<CurrentDropDownMenu />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
|||||||
@@ -46,6 +46,7 @@
|
|||||||
if (command.getSubCommands) {
|
if (command.getSubCommands) {
|
||||||
parentCommand = command;
|
parentCommand = command;
|
||||||
domInput.focus();
|
domInput.focus();
|
||||||
|
filter = '';
|
||||||
selectedIndex = 0;
|
selectedIndex = 0;
|
||||||
} else {
|
} else {
|
||||||
$visibleCommandPalette = false;
|
$visibleCommandPalette = false;
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ export const currentTheme = writableWithStorage('theme-light', 'currentTheme');
|
|||||||
export const activeTabId = derived([openedTabs], ([$openedTabs]) => $openedTabs.find(x => x.selected)?.tabid);
|
export const activeTabId = derived([openedTabs], ([$openedTabs]) => $openedTabs.find(x => x.selected)?.tabid);
|
||||||
export const visibleToolbar = writableWithStorage(1, 'visibleToolbar');
|
export const visibleToolbar = writableWithStorage(1, 'visibleToolbar');
|
||||||
export const leftPanelWidth = writable(300);
|
export const leftPanelWidth = writable(300);
|
||||||
|
export const currentDropDownMenu = writable(null);
|
||||||
|
|
||||||
subscribeCssVariable(selectedWidget, x => (x ? 1 : 0), '--dim-visible-left-panel');
|
subscribeCssVariable(selectedWidget, x => (x ? 1 : 0), '--dim-visible-left-panel');
|
||||||
subscribeCssVariable(visibleToolbar, x => (x ? 1 : 0), '--dim-visible-toolbar');
|
subscribeCssVariable(visibleToolbar, x => (x ? 1 : 0), '--dim-visible-toolbar');
|
||||||
|
|||||||
19
packages/web/src/utility/contextMenu.ts
Normal file
19
packages/web/src/utility/contextMenu.ts
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
import _ from 'lodash';
|
||||||
|
import { currentDropDownMenu } from '../stores';
|
||||||
|
|
||||||
|
export default function contextMenu(node, items) {
|
||||||
|
const handleContextMenu = e => {
|
||||||
|
e.preventDefault();
|
||||||
|
const left = e.pageX;
|
||||||
|
const top = e.pageY;
|
||||||
|
currentDropDownMenu.set({ left, top, items: _.isFunction(items) ? items() : items });
|
||||||
|
};
|
||||||
|
|
||||||
|
node.addEventListener('contextmenu', handleContextMenu);
|
||||||
|
|
||||||
|
return {
|
||||||
|
destroy() {
|
||||||
|
node.removeEventListener('contextmenu', handleContextMenu);
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -25,6 +25,7 @@
|
|||||||
|
|
||||||
import { currentDatabase, openedTabs } from '../stores';
|
import { currentDatabase, openedTabs } from '../stores';
|
||||||
import { setSelectedTab } from '../utility/common';
|
import { setSelectedTab } from '../utility/common';
|
||||||
|
import contextMenu from '../utility/contextMenu';
|
||||||
|
|
||||||
$: currentDbKey =
|
$: currentDbKey =
|
||||||
$currentDatabase && $currentDatabase.name && $currentDatabase.connection
|
$currentDatabase && $currentDatabase.name && $currentDatabase.connection
|
||||||
@@ -100,6 +101,13 @@
|
|||||||
closeTab(tabid);
|
closeTab(tabid);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const tabContextMenu = tabid => () => [
|
||||||
|
{
|
||||||
|
text: 'Close',
|
||||||
|
onClick: () => closeTab(tabid),
|
||||||
|
},
|
||||||
|
];
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#each dbKeys as dbKey}
|
{#each dbKeys as dbKey}
|
||||||
@@ -115,6 +123,7 @@
|
|||||||
class:selected={tab.selected}
|
class:selected={tab.selected}
|
||||||
on:click={e => handleTabClick(e, tab.tabid)}
|
on:click={e => handleTabClick(e, tab.tabid)}
|
||||||
on:mouseup={e => handleMouseUp(e, tab.tabid)}
|
on:mouseup={e => handleMouseUp(e, tab.tabid)}
|
||||||
|
use:contextMenu={tabContextMenu(tab.tabid)}
|
||||||
>
|
>
|
||||||
<FontIcon icon={tab.busy ? 'icon loading' : tab.icon} />
|
<FontIcon icon={tab.busy ? 'icon loading' : tab.icon} />
|
||||||
<span class="file-name">
|
<span class="file-name">
|
||||||
|
|||||||
Reference in New Issue
Block a user