diff --git a/package.json b/package.json
index 1ec78edc..9e5dc344 100644
--- a/package.json
+++ b/package.json
@@ -6,7 +6,7 @@
"main": "index.js",
"scripts": {
"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": [],
"author": "Misode",
diff --git a/src/app/hooks/renderHtml.ts b/src/app/hooks/renderHtml.ts
index 85528071..cfbed461 100644
--- a/src/app/hooks/renderHtml.ts
+++ b/src/app/hooks/renderHtml.ts
@@ -86,7 +86,9 @@ export const renderHtml: Hook<[any, Mounter], [string, string, string]> = {
${help(childPath, mounter)}
${cPrefix}
-
+
${cSuffix}
${cBody ? `
${cBody}
` : ''}
@@ -125,7 +127,9 @@ export const renderHtml: Hook<[any, Mounter], [string, string, string]> = {
${help(childPath, mounter)}
${cPrefix}
-
+
${cSuffix}
${cBody ? `${cBody}
` : ''}
@@ -180,7 +184,9 @@ export const renderHtml: Hook<[any, Mounter], [string, string, string]> = {
${error(childPath, mounter)}
${help(childPath, mounter)}
${cPrefix}
-
+
${cSuffix}
${cBody ? `${cBody}
` : ''}
@@ -259,7 +265,6 @@ function hashString(str: string) {
}
function pathLocale(path: Path, params?: string[]): string {
- // return path.getContext().slice(-5).join('.')
return segmentedLocale(path.getContext(), params)
?? path.getContext()[path.getContext().length - 1] ?? ''
}
@@ -287,3 +292,57 @@ const popupIcon = (type: string, icon: keyof typeof Octicon, popup: string, moun
${Octicon[icon]}
`
}
+
+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', ``)
+
+ const context = path.getContext().join('.')
+ popup.insertAdjacentHTML('beforeend', `
+ `)
+ 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}"`
+}
diff --git a/src/styles/nodes.css b/src/styles/nodes.css
index 8b259989..7bf3cdf9 100644
--- a/src/styles/nodes.css
+++ b/src/styles/nodes.css
@@ -12,6 +12,7 @@
--node-indent-border: #b9b9b9;
--node-popup-background: #1f2020e6;
--node-popup-text: #dadada;
+ --node-popup-text-dimmed: #b4b4b4;
--category-predicate: #65b5b8;
--category-predicate-border: #187e81;
--category-predicate-background: #95c5c7;
@@ -37,6 +38,7 @@
--node-indent-border: #454749;
--node-popup-background: #0a0a0ae6;
--node-popup-text: #dadada;
+ --node-popup-text-dimmed: #b4b4b4;
--category-predicate: #306163;
--category-predicate-border: #224849;
--category-predicate-background: #1d3333;
@@ -52,8 +54,9 @@
.node-header {
display: inline-flex;
+ position: relative;
align-items: center;
- max-width: 100%;
+ width: 100%;
}
.node-header > * {
@@ -68,6 +71,7 @@
padding: 0 9px;
line-height: 1.94rem;
white-space: nowrap;
+ user-select: none;
background-color: var(--node-background-label);
}
@@ -221,6 +225,54 @@ button.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 {