mirror of
https://github.com/misode/misode.github.io.git
synced 2026-05-04 14:42:53 +00:00
Add context menu allowing you to copy context path
This commit is contained in:
+1
-1
@@ -6,7 +6,7 @@
|
|||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "webpack-cli -p",
|
"build": "webpack-cli -p",
|
||||||
"start": "webpack-dev-server -d --content-base ./public"
|
"start": "webpack-dev-server -d --content-base ./public --host 0.0.0.0"
|
||||||
},
|
},
|
||||||
"keywords": [],
|
"keywords": [],
|
||||||
"author": "Misode",
|
"author": "Misode",
|
||||||
|
|||||||
@@ -86,7 +86,9 @@ export const renderHtml: Hook<[any, Mounter], [string, string, string]> = {
|
|||||||
${help(childPath, mounter)}
|
${help(childPath, mounter)}
|
||||||
<button class="remove" data-id="${removeId}">${Octicon.trashcan}</button>
|
<button class="remove" data-id="${removeId}">${Octicon.trashcan}</button>
|
||||||
${cPrefix}
|
${cPrefix}
|
||||||
<label>${htmlEncode(pathLocale(path.contextPush('entry'), [`${index}`]))}</label>
|
<label ${contextMenu(childPath, mounter)}>
|
||||||
|
${htmlEncode(pathLocale(path.contextPush('entry'), [`${index}`]))}
|
||||||
|
</label>
|
||||||
${cSuffix}
|
${cSuffix}
|
||||||
</div>
|
</div>
|
||||||
${cBody ? `<div class="node-body">${cBody}</div>` : ''}
|
${cBody ? `<div class="node-body">${cBody}</div>` : ''}
|
||||||
@@ -125,7 +127,9 @@ export const renderHtml: Hook<[any, Mounter], [string, string, string]> = {
|
|||||||
${help(childPath, mounter)}
|
${help(childPath, mounter)}
|
||||||
<button class="remove" data-id="${removeId}">${Octicon.trashcan}</button>
|
<button class="remove" data-id="${removeId}">${Octicon.trashcan}</button>
|
||||||
${cPrefix}
|
${cPrefix}
|
||||||
<label>${htmlEncode(key)}</label>
|
<label ${contextMenu(childPath, mounter)}>
|
||||||
|
${htmlEncode(key)}
|
||||||
|
</label>
|
||||||
${cSuffix}
|
${cSuffix}
|
||||||
</div>
|
</div>
|
||||||
${cBody ? `<div class="node-body">${cBody}</div>` : ''}
|
${cBody ? `<div class="node-body">${cBody}</div>` : ''}
|
||||||
@@ -180,7 +184,9 @@ export const renderHtml: Hook<[any, Mounter], [string, string, string]> = {
|
|||||||
${error(childPath, mounter)}
|
${error(childPath, mounter)}
|
||||||
${help(childPath, mounter)}
|
${help(childPath, mounter)}
|
||||||
${cPrefix}
|
${cPrefix}
|
||||||
<label>${htmlEncode(fieldSettings?.name ?? pathLocale(childPath))}</label>
|
<label ${contextMenu(childPath, mounter)}>
|
||||||
|
${htmlEncode(fieldSettings?.name ?? pathLocale(childPath))}
|
||||||
|
</label>
|
||||||
${cSuffix}
|
${cSuffix}
|
||||||
</div>
|
</div>
|
||||||
${cBody ? `<div class="node-body">${cBody}</div>` : ''}
|
${cBody ? `<div class="node-body">${cBody}</div>` : ''}
|
||||||
@@ -259,7 +265,6 @@ function hashString(str: string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function pathLocale(path: Path, params?: string[]): string {
|
function pathLocale(path: Path, params?: string[]): string {
|
||||||
// return path.getContext().slice(-5).join('.')
|
|
||||||
return segmentedLocale(path.getContext(), params)
|
return segmentedLocale(path.getContext(), params)
|
||||||
?? path.getContext()[path.getContext().length - 1] ?? ''
|
?? path.getContext()[path.getContext().length - 1] ?? ''
|
||||||
}
|
}
|
||||||
@@ -287,3 +292,57 @@ const popupIcon = (type: string, icon: keyof typeof Octicon, popup: string, moun
|
|||||||
<span class="icon-popup">${popup}</span>${Octicon[icon]}
|
<span class="icon-popup">${popup}</span>${Octicon[icon]}
|
||||||
</div>`
|
</div>`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const contextMenu = (path: ModelPath, mounter: Mounter) => {
|
||||||
|
const id = mounter.register(el => {
|
||||||
|
const openMenu = () => {
|
||||||
|
const popup = document.createElement('div')
|
||||||
|
popup.classList.add('node-menu')
|
||||||
|
|
||||||
|
const helpMessage = segmentedLocale(path.contextPush('help').getContext(), [], 6)
|
||||||
|
if (helpMessage) popup.insertAdjacentHTML('beforeend', `<span class="menu-item help-item">${helpMessage}</span>`)
|
||||||
|
|
||||||
|
const context = path.getContext().join('.')
|
||||||
|
popup.insertAdjacentHTML('beforeend', `
|
||||||
|
<div class="menu-item">
|
||||||
|
<span class="btn">${Octicon.clippy}</span>
|
||||||
|
Context: 
|
||||||
|
<span class="menu-item-context">${context}</span>
|
||||||
|
</div>`)
|
||||||
|
popup.querySelector('.menu-item .btn')?.addEventListener('click', () => {
|
||||||
|
const inputEl = document.createElement('input')
|
||||||
|
inputEl.value = context
|
||||||
|
el.appendChild(inputEl)
|
||||||
|
inputEl.select()
|
||||||
|
document.execCommand('copy')
|
||||||
|
el.removeChild(inputEl)
|
||||||
|
})
|
||||||
|
|
||||||
|
el.appendChild(popup)
|
||||||
|
document.body.addEventListener('click', () => {
|
||||||
|
try {el.removeChild(popup)} catch (e) {}
|
||||||
|
}, { capture: true, once: true })
|
||||||
|
document.body.addEventListener('contextmenu', () => {
|
||||||
|
try {el.removeChild(popup)} catch (e) {}
|
||||||
|
}, { capture: true, once: true })
|
||||||
|
}
|
||||||
|
el.addEventListener('contextmenu', evt => {
|
||||||
|
openMenu()
|
||||||
|
evt.preventDefault()
|
||||||
|
})
|
||||||
|
let timer: any = null
|
||||||
|
el.addEventListener('touchstart', () => {
|
||||||
|
timer = setTimeout(() => {
|
||||||
|
openMenu()
|
||||||
|
timer = null
|
||||||
|
}, 800)
|
||||||
|
})
|
||||||
|
el.addEventListener('touchend', () => {
|
||||||
|
if (timer) {
|
||||||
|
clearTimeout(timer)
|
||||||
|
timer = null
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
return `data-id="${id}"`
|
||||||
|
}
|
||||||
|
|||||||
+53
-1
@@ -12,6 +12,7 @@
|
|||||||
--node-indent-border: #b9b9b9;
|
--node-indent-border: #b9b9b9;
|
||||||
--node-popup-background: #1f2020e6;
|
--node-popup-background: #1f2020e6;
|
||||||
--node-popup-text: #dadada;
|
--node-popup-text: #dadada;
|
||||||
|
--node-popup-text-dimmed: #b4b4b4;
|
||||||
--category-predicate: #65b5b8;
|
--category-predicate: #65b5b8;
|
||||||
--category-predicate-border: #187e81;
|
--category-predicate-border: #187e81;
|
||||||
--category-predicate-background: #95c5c7;
|
--category-predicate-background: #95c5c7;
|
||||||
@@ -37,6 +38,7 @@
|
|||||||
--node-indent-border: #454749;
|
--node-indent-border: #454749;
|
||||||
--node-popup-background: #0a0a0ae6;
|
--node-popup-background: #0a0a0ae6;
|
||||||
--node-popup-text: #dadada;
|
--node-popup-text: #dadada;
|
||||||
|
--node-popup-text-dimmed: #b4b4b4;
|
||||||
--category-predicate: #306163;
|
--category-predicate: #306163;
|
||||||
--category-predicate-border: #224849;
|
--category-predicate-border: #224849;
|
||||||
--category-predicate-background: #1d3333;
|
--category-predicate-background: #1d3333;
|
||||||
@@ -52,8 +54,9 @@
|
|||||||
|
|
||||||
.node-header {
|
.node-header {
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
|
position: relative;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
max-width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.node-header > * {
|
.node-header > * {
|
||||||
@@ -68,6 +71,7 @@
|
|||||||
padding: 0 9px;
|
padding: 0 9px;
|
||||||
line-height: 1.94rem;
|
line-height: 1.94rem;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
|
user-select: none;
|
||||||
background-color: var(--node-background-label);
|
background-color: var(--node-background-label);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -221,6 +225,54 @@ button.remove {
|
|||||||
fill: var(--node-remove);
|
fill: var(--node-remove);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.node-menu {
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
top: 100%;
|
||||||
|
width: min-content;
|
||||||
|
margin-top: 4px;
|
||||||
|
margin-left: 4px;
|
||||||
|
z-index: 1;
|
||||||
|
color: var(--node-popup-text);
|
||||||
|
font-size: 16px;
|
||||||
|
border-radius: 3px;
|
||||||
|
background-color: var(--node-popup-background);
|
||||||
|
}
|
||||||
|
|
||||||
|
.node-menu::after {
|
||||||
|
content: "";
|
||||||
|
position: absolute;
|
||||||
|
bottom: 100%;
|
||||||
|
left: 0;
|
||||||
|
margin-left: 6px;
|
||||||
|
border-width: 5px;
|
||||||
|
border-style: solid;
|
||||||
|
border-color: transparent transparent var(--node-popup-background) transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
.menu-item {
|
||||||
|
padding: 4px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
white-space: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
.menu-item > * {
|
||||||
|
margin-right: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.menu-item .btn {
|
||||||
|
padding: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
span.menu-item {
|
||||||
|
padding: 4px 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.menu-item-context {
|
||||||
|
color: var(--node-popup-text-dimmed);
|
||||||
|
}
|
||||||
|
|
||||||
/* Node body and list entry */
|
/* Node body and list entry */
|
||||||
|
|
||||||
.node {
|
.node {
|
||||||
|
|||||||
Reference in New Issue
Block a user