Move Menu into a separate component
This commit is contained in:
parent
e23e4a82dd
commit
e629b404a6
|
@ -9,58 +9,6 @@
|
|||
flex-direction: column;
|
||||
position: relative;
|
||||
|
||||
.menu {
|
||||
font-family: $font-family-menu;
|
||||
font-size: $font-size;
|
||||
background: $theme-color;
|
||||
color: $white;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
position: relative;
|
||||
|
||||
.button {
|
||||
width: $menu-button-size;
|
||||
height: $menu-button-size;
|
||||
border: none;
|
||||
background: transparent;
|
||||
color: white;
|
||||
cursor: pointer;
|
||||
padding: 0;
|
||||
|
||||
&:hover,
|
||||
&:focus {
|
||||
background: rgba(255, 255, 255, 0.3);
|
||||
}
|
||||
|
||||
&:disabled {
|
||||
color: rgba(255, 255, 255, 0.5);
|
||||
background: transparent;
|
||||
}
|
||||
}
|
||||
|
||||
.space {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.separator {
|
||||
$margin: 3px;
|
||||
|
||||
background: rgba(255, 255, 255, 0.15);
|
||||
box-sizing: border-box;
|
||||
width: 1px;
|
||||
height: $menu-button-size - 2 * $margin;
|
||||
margin: $margin;
|
||||
}
|
||||
|
||||
.search-box-container {
|
||||
position: absolute;
|
||||
top: 100%;
|
||||
right: $search-box-offset + 20px; // keep space for scrollbar
|
||||
margin-top: $search-box-offset;
|
||||
z-index: 2;
|
||||
}
|
||||
}
|
||||
|
||||
.hidden-input-label {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
|
|
|
@ -13,9 +13,6 @@
|
|||
SCROLL_DURATION,
|
||||
STATE_PROPS
|
||||
} from './constants.js'
|
||||
import SearchBox from './SearchBox.svelte'
|
||||
import Icon from 'svelte-awesome'
|
||||
import { faCut, faClone, faCopy, faPaste, faSearch, faUndo, faRedo } from '@fortawesome/free-solid-svg-icons'
|
||||
import { createHistory } from './history.js'
|
||||
import JSONNode from './JSONNode.svelte'
|
||||
import {
|
||||
|
@ -37,6 +34,7 @@
|
|||
import jump from './assets/jump.js/src/jump.js'
|
||||
import { expandPath, stateUtils } from './utils/stateUtils.js'
|
||||
import { getNextKeys, patchProps } from './utils/updateProps.js'
|
||||
import Menu from './Menu.svelte'
|
||||
|
||||
let divContents
|
||||
let domHiddenInput
|
||||
|
@ -247,27 +245,22 @@
|
|||
}
|
||||
}
|
||||
|
||||
async function changeSearchText (text) {
|
||||
async function handleSearchText (text) {
|
||||
searchText = text
|
||||
await tick() // await for the search results to be updated
|
||||
focusActiveSearchResult(searchResult && searchResult.activeItem)
|
||||
}
|
||||
|
||||
async function nextSearchResult () {
|
||||
async function handleNextSearchResult () {
|
||||
searchResult = searchNext(searchResult)
|
||||
focusActiveSearchResult(searchResult && searchResult.activeItem)
|
||||
}
|
||||
|
||||
function previousSearchResult () {
|
||||
function handlePreviousSearchResult () {
|
||||
searchResult = searchPrevious(searchResult)
|
||||
focusActiveSearchResult(searchResult && searchResult.activeItem)
|
||||
}
|
||||
|
||||
function clearSearchResult () {
|
||||
showSearch = false
|
||||
searchText = ''
|
||||
}
|
||||
|
||||
async function focusActiveSearchResult (activeItem) {
|
||||
if (activeItem) {
|
||||
state = expandPath(state, activeItem.path)
|
||||
|
@ -316,10 +309,6 @@
|
|||
// should never be called on the root
|
||||
}
|
||||
|
||||
function handleToggleSearch() {
|
||||
showSearch = !showSearch
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggle expanded state of a node
|
||||
* @param {Path} path
|
||||
|
@ -440,88 +429,25 @@
|
|||
</script>
|
||||
|
||||
<div class="jsoneditor" on:keydown={handleKeyDown}>
|
||||
<div class="menu">
|
||||
<button
|
||||
class="button cut"
|
||||
on:click={handleCut}
|
||||
disabled={!hasSelectionContents}
|
||||
title="Cut (Ctrl+X)"
|
||||
>
|
||||
<Icon data={faCut} />
|
||||
</button>
|
||||
<button
|
||||
class="button copy"
|
||||
on:click={handleCopy}
|
||||
disabled={!hasSelectionContents}
|
||||
title="Copy (Ctrl+C)"
|
||||
>
|
||||
<Icon data={faCopy} />
|
||||
</button>
|
||||
<button
|
||||
class="button paste"
|
||||
on:click={handlePaste}
|
||||
disabled={!hasClipboardContents}
|
||||
title="Paste (Ctrl+V)"
|
||||
>
|
||||
<Icon data={faPaste} />
|
||||
</button>
|
||||
<Menu
|
||||
historyState={historyState}
|
||||
searchText={searchText}
|
||||
searchResult={searchResult}
|
||||
bind:showSearch
|
||||
hasSelectionContents={hasSelectionContents}
|
||||
hasClipboardContents={hasClipboardContents}
|
||||
|
||||
<div class="separator"></div>
|
||||
onCut={handleCut}
|
||||
onCopy={handleCopy}
|
||||
onPaste={handlePaste}
|
||||
onDuplicate={handleDuplicate}
|
||||
onUndo={handleUndo}
|
||||
onRedo={handleRedo}
|
||||
|
||||
<button
|
||||
class="button duplicate"
|
||||
on:click={handleDuplicate}
|
||||
disabled={!hasSelectionContents}
|
||||
title="Duplicate (Ctrl+D)"
|
||||
>
|
||||
<Icon data={faClone} />
|
||||
</button>
|
||||
|
||||
<div class="separator"></div>
|
||||
|
||||
<button
|
||||
class="button search"
|
||||
on:click={handleToggleSearch}
|
||||
title="Search (Ctrl+F)"
|
||||
>
|
||||
<Icon data={faSearch} />
|
||||
</button>
|
||||
|
||||
<div class="separator"></div>
|
||||
|
||||
<button
|
||||
class="button undo"
|
||||
disabled={!historyState.canUndo}
|
||||
on:click={handleUndo}
|
||||
title="Undo (Ctrl+Z)"
|
||||
>
|
||||
<Icon data={faUndo} />
|
||||
</button>
|
||||
<button
|
||||
class="button redo"
|
||||
disabled={!historyState.canRedo}
|
||||
on:click={handleRedo}
|
||||
title="Redo (Ctrl+Shift+Z)"
|
||||
>
|
||||
<Icon data={faRedo} />
|
||||
</button>
|
||||
|
||||
<div class="space"></div>
|
||||
|
||||
{#if showSearch}
|
||||
<div class="search-box-container">
|
||||
<SearchBox
|
||||
text={searchText}
|
||||
resultCount={searchResult ? searchResult.count : 0}
|
||||
activeIndex={searchResult ? searchResult.activeIndex : 0}
|
||||
onChange={changeSearchText}
|
||||
onNext={nextSearchResult}
|
||||
onPrevious={previousSearchResult}
|
||||
onClose={clearSearchResult}
|
||||
/>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
onSearchText={handleSearchText}
|
||||
onNextSearchResult={handleNextSearchResult}
|
||||
onPreviousSearchResult={handlePreviousSearchResult}
|
||||
/>
|
||||
<label class="hidden-input-label">
|
||||
<input
|
||||
class="hidden-input"
|
||||
|
|
|
@ -0,0 +1,53 @@
|
|||
@import './styles.scss';
|
||||
|
||||
.menu {
|
||||
font-family: $font-family-menu;
|
||||
font-size: $font-size;
|
||||
background: $theme-color;
|
||||
color: $white;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
position: relative;
|
||||
|
||||
.button {
|
||||
width: $menu-button-size;
|
||||
height: $menu-button-size;
|
||||
border: none;
|
||||
background: transparent;
|
||||
color: white;
|
||||
cursor: pointer;
|
||||
padding: 0;
|
||||
|
||||
&:hover,
|
||||
&:focus {
|
||||
background: rgba(255, 255, 255, 0.3);
|
||||
}
|
||||
|
||||
&:disabled {
|
||||
color: rgba(255, 255, 255, 0.5);
|
||||
background: transparent;
|
||||
}
|
||||
}
|
||||
|
||||
.space {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.separator {
|
||||
$margin: 3px;
|
||||
|
||||
background: rgba(255, 255, 255, 0.15);
|
||||
box-sizing: border-box;
|
||||
width: 1px;
|
||||
height: $menu-button-size - 2 * $margin;
|
||||
margin: $margin;
|
||||
}
|
||||
|
||||
.search-box-container {
|
||||
position: absolute;
|
||||
top: 100%;
|
||||
right: $search-box-offset + 20px; // keep space for scrollbar
|
||||
margin-top: $search-box-offset;
|
||||
z-index: 2;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,118 @@
|
|||
<script>
|
||||
import Icon from 'svelte-awesome'
|
||||
import { faCut, faClone, faCopy, faPaste, faSearch, faUndo, faRedo } from '@fortawesome/free-solid-svg-icons'
|
||||
import SearchBox from './SearchBox.svelte'
|
||||
|
||||
export let searchText
|
||||
export let searchResult
|
||||
export let showSearch = false
|
||||
export let hasSelectionContents
|
||||
export let hasClipboardContents
|
||||
export let historyState
|
||||
|
||||
export let onCut
|
||||
export let onCopy
|
||||
export let onPaste
|
||||
export let onDuplicate
|
||||
export let onUndo
|
||||
export let onRedo
|
||||
|
||||
export let onSearchText
|
||||
export let onNextSearchResult
|
||||
export let onPreviousSearchResult
|
||||
|
||||
function handleToggleSearch() {
|
||||
showSearch = !showSearch
|
||||
}
|
||||
|
||||
function clearSearchResult () {
|
||||
showSearch = false
|
||||
onSearchText('')
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<div class="menu">
|
||||
<button
|
||||
class="button cut"
|
||||
on:click={onCut}
|
||||
disabled={!hasSelectionContents}
|
||||
title="Cut (Ctrl+X)"
|
||||
>
|
||||
<Icon data={faCut} />
|
||||
</button>
|
||||
<button
|
||||
class="button copy"
|
||||
on:click={onCopy}
|
||||
disabled={!hasSelectionContents}
|
||||
title="Copy (Ctrl+C)"
|
||||
>
|
||||
<Icon data={faCopy} />
|
||||
</button>
|
||||
<button
|
||||
class="button paste"
|
||||
on:click={onPaste}
|
||||
disabled={!hasClipboardContents}
|
||||
title="Paste (Ctrl+V)"
|
||||
>
|
||||
<Icon data={faPaste} />
|
||||
</button>
|
||||
|
||||
<div class="separator"></div>
|
||||
|
||||
<button
|
||||
class="button duplicate"
|
||||
on:click={onDuplicate}
|
||||
disabled={!hasSelectionContents}
|
||||
title="Duplicate (Ctrl+D)"
|
||||
>
|
||||
<Icon data={faClone} />
|
||||
</button>
|
||||
|
||||
<div class="separator"></div>
|
||||
|
||||
<button
|
||||
class="button search"
|
||||
on:click={handleToggleSearch}
|
||||
title="Search (Ctrl+F)"
|
||||
>
|
||||
<Icon data={faSearch} />
|
||||
</button>
|
||||
|
||||
<div class="separator"></div>
|
||||
|
||||
<button
|
||||
class="button undo"
|
||||
disabled={!historyState.canUndo}
|
||||
on:click={onUndo}
|
||||
title="Undo (Ctrl+Z)"
|
||||
>
|
||||
<Icon data={faUndo} />
|
||||
</button>
|
||||
<button
|
||||
class="button redo"
|
||||
disabled={!historyState.canRedo}
|
||||
on:click={onRedo}
|
||||
title="Redo (Ctrl+Shift+Z)"
|
||||
>
|
||||
<Icon data={faRedo} />
|
||||
</button>
|
||||
|
||||
<div class="space"></div>
|
||||
|
||||
{#if showSearch}
|
||||
<div class="search-box-container">
|
||||
<SearchBox
|
||||
text={searchText}
|
||||
resultCount={searchResult ? searchResult.count : 0}
|
||||
activeIndex={searchResult ? searchResult.activeIndex : 0}
|
||||
onChange={onSearchText}
|
||||
onNext={onNextSearchResult}
|
||||
onPrevious={onPreviousSearchResult}
|
||||
onClose={clearSearchResult}
|
||||
/>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<style src="Menu.scss"></style>
|
Loading…
Reference in New Issue