aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorHsieh Chin Fan <pham@topo.tw>2024-09-30 17:59:05 +0800
committerHsieh Chin Fan <pham@topo.tw>2024-10-01 11:35:11 +0800
commitf4fe9ff6c1ce2811fe9aa0272333b4732a6ebcdc (patch)
tree6bde54a5c2afe37fb4bea6a00b492e74a0720e16
parent193ba872c455296bff55e5f6a7d6dbbbb85c265e (diff)
refactor: move menu feature from editor to dumbymap
-rw-r--r--src/MenuItem.mjs5
-rw-r--r--src/css/dumbymap.css69
-rw-r--r--src/css/index.css67
-rw-r--r--src/dumbymap.mjs51
-rw-r--r--src/editor.mjs34
5 files changed, 123 insertions, 103 deletions
diff --git a/src/MenuItem.mjs b/src/MenuItem.mjs
index f4cd518..74138ec 100644
--- a/src/MenuItem.mjs
+++ b/src/MenuItem.mjs
@@ -89,7 +89,10 @@ export const pickLayoutItem = dumbymap =>
89 items: [ 89 items: [
90 new Item({ 90 new Item({
91 text: 'EDIT', 91 text: 'EDIT',
92 onclick: () => document.body.setAttribute('data-mode', 'editing'), 92 onclick: () =>
93 dumbymap.container
94 .closest('.playground')
95 .setAttribute('data-mode', 'editing'),
93 }).element, 96 }).element,
94 ...dumbymap.layouts.map( 97 ...dumbymap.layouts.map(
95 layout => 98 layout =>
diff --git a/src/css/dumbymap.css b/src/css/dumbymap.css
index f6275ab..822353f 100644
--- a/src/css/dumbymap.css
+++ b/src/css/dumbymap.css
@@ -226,7 +226,7 @@ root {
226 padding: 0; 226 padding: 0;
227 227
228 position: relative; 228 position: relative;
229 overflow-x: auto; 229 overflow: visible;
230 230
231 &::after { 231 &::after {
232 content: 'Layout: ' attr(data-layout); 232 content: 'Layout: ' attr(data-layout);
@@ -609,3 +609,70 @@ root {
609.bold-options { 609.bold-options {
610 font-weight: bold; 610 font-weight: bold;
611} 611}
612
613.menu {
614 display: none;
615 width: fit-content;
616
617 position: absolute;
618 z-index: 9999;
619
620 border: 2px solid gray;
621 border-radius: 6px;
622
623 background: white;
624 min-width: 10rem;
625 max-height: 40vh;
626 overflow-y: scroll;
627}
628
629.menu-item {
630 display: flex;
631 box-sizing: border-box;
632 justify-content: space-between;
633 padding: 0.5rem;
634
635 z-index: 9999;
636
637 border: 2px solid transparent;
638 border-radius: 5px;
639
640 cursor: pointer;
641 text-wrap: nowrap;
642
643 &:hover {
644 background: rgb(226 232 240);
645 }
646
647 .info {
648 padding-inline: 1em;
649
650 color: steelblue;
651 font-weight: bold;
652 }
653}
654
655.folder::after {
656 content: '⏵';
657}
658
659.sub-menu {
660 overflow: scroll;
661 width: fit-content;
662
663 position: absolute;
664 z-index: 100;
665
666 border: 2px solid gray;
667 border-radius: 6px;
668
669 background: white;
670 min-width: 6rem;
671 max-height: 40vh;
672
673 .menu-item {
674 margin: 0 auto;
675 padding-inline: 0.5em;
676 min-width: 5em;
677 }
678}
diff --git a/src/css/index.css b/src/css/index.css
index 069bf85..b13a45d 100644
--- a/src/css/index.css
+++ b/src/css/index.css
@@ -104,22 +104,6 @@ body {
104 } 104 }
105} 105}
106 106
107#menu {
108 display: none;
109 width: fit-content;
110
111 position: absolute;
112 z-index: 9999;
113
114 border: 2px solid gray;
115 border-radius: 6px;
116
117 background: white;
118 min-width: 10rem;
119 max-height: 40vh;
120 overflow-y: scroll;
121}
122
123.container__suggestion { 107.container__suggestion {
124 display: flex; 108 display: flex;
125 overflow: hidden; 109 overflow: hidden;
@@ -161,54 +145,3 @@ body {
161 } 145 }
162 } 146 }
163} 147}
164
165.menu-item {
166 display: flex;
167 box-sizing: border-box;
168 justify-content: space-between;
169 padding: 0.5rem;
170
171 z-index: 9999;
172
173 border: 2px solid transparent;
174 border-radius: 5px;
175
176 cursor: pointer;
177 text-wrap: nowrap;
178
179 &:hover {
180 background: rgb(226 232 240);
181 }
182
183 .info {
184 padding-inline: 1em;
185
186 color: steelblue;
187 font-weight: bold;
188 }
189}
190
191.folder::after {
192 content: '⏵';
193}
194
195.sub-menu {
196 overflow: scroll;
197 width: fit-content;
198
199 position: absolute;
200 z-index: 100;
201
202 border: 2px solid gray;
203 border-radius: 6px;
204
205 background: white;
206 min-width: 6rem;
207 max-height: 40vh;
208
209 .menu-item {
210 margin: 0 auto;
211 padding-inline: 0.5em;
212 min-width: 5em;
213 }
214}
diff --git a/src/dumbymap.mjs b/src/dumbymap.mjs
index 67376c7..d365712 100644
--- a/src/dumbymap.mjs
+++ b/src/dumbymap.mjs
@@ -8,6 +8,7 @@ import { renderWith, defaultAliases, parseConfigsFromYaml } from 'mapclay';
8import { onRemove, animateRectTransition, throttle } from './utils'; 8import { onRemove, animateRectTransition, throttle } from './utils';
9import { Layout, SideBySide, Overlay } from './Layout'; 9import { Layout, SideBySide, Overlay } from './Layout';
10import * as utils from './dumbyUtils'; 10import * as utils from './dumbyUtils';
11import * as menuItem from './MenuItem';
11 12
12const docLinkSelector = 'a[href^="#"][title^="=>"]'; 13const docLinkSelector = 'a[href^="#"][title^="=>"]';
13const geoLinkSelector = 'a[href^="geo:"]'; 14const geoLinkSelector = 'a[href^="geo:"]';
@@ -520,7 +521,57 @@ export const generateMaps = (container, { delay, mapCallback }) => {
520 clearTimeout(timer); 521 clearTimeout(timer);
521 }); 522 });
522 }); 523 });
524 // }}}
525
526 // Menu {{{
527 const menu = document.createElement('div');
528 menu.className = 'menu';
529 menu.onclick = () => (menu.style.display = 'none');
530 new MutationObserver(() => {
531 if (menu.style.display === 'none') {
532 menu.style.cssText = '';
533 menu.replaceChildren();
534 }
535 }).observe(menu, {
536 attributes: true,
537 attributeFilter: ['style'],
538 });
539 container.appendChild(menu);
540
541 // Menu Items
542 container.oncontextmenu = e => {
543 const selection = document.getSelection();
544 const range = selection.getRangeAt(0);
545 if (selection) {
546 e.preventDefault();
547 menu.innerHTML = '';
548 const addGeoLink = new menuItem.GeoLink({ range });
549 menu.appendChild(addGeoLink.createElement());
550 }
551 menu.style.cssText = `overflow: visible; display: block; left: ${e.clientX + 10}px; top: ${e.clientY + 5}px;`;
552 menu.appendChild(menuItem.modal);
553 menu.appendChild(menuItem.pickMapItem(dumbymap));
554 menu.appendChild(menuItem.pickBlockItem(dumbymap));
555 menu.appendChild(menuItem.pickLayoutItem(dumbymap));
556 };
523 557
558 // Remove menu when click outside
559 const actionOutsideMenu = e => {
560 if (menu.style.display === 'none') return;
561 const rect = menu.getBoundingClientRect();
562 if (
563 e.clientX < rect.left ||
564 e.clientX > rect.left + rect.width ||
565 e.clientY < rect.top ||
566 e.clientY > rect.top + rect.height
567 ) {
568 menu.style.display = 'none';
569 }
570 };
571 document.addEventListener('click', actionOutsideMenu);
572 onRemove(htmlHolder, () =>
573 document.removeEventListener('click', actionOutsideMenu),
574 );
524 //}}} 575 //}}}
525 return Object.seal(dumbymap); 576 return Object.seal(dumbymap);
526}; 577};
diff --git a/src/editor.mjs b/src/editor.mjs
index 9946686..760e2e1 100644
--- a/src/editor.mjs
+++ b/src/editor.mjs
@@ -661,39 +661,5 @@ layoutObserver.observe(HtmlContainer, {
661 attributeOldValue: true, 661 attributeOldValue: true,
662}); 662});
663// }}} 663// }}}
664// ContextMenu {{{
665document.oncontextmenu = e => {
666 if (cm.hasFocus()) return;
667
668 const selection = document.getSelection();
669 const range = selection.getRangeAt(0);
670 if (selection) {
671 e.preventDefault();
672 menu.innerHTML = '';
673 const addGeoLink = new menuItem.GeoLink({ range });
674 menu.appendChild(addGeoLink.createElement());
675 }
676 menu.style.cssText = `overflow: visible; display: block; left: ${e.clientX + 10}px; top: ${e.clientY + 5}px;`;
677 menu.appendChild(menuItem.pickMapItem(dumbymap));
678 menu.appendChild(menuItem.pickBlockItem(dumbymap));
679 menu.appendChild(menuItem.pickLayoutItem(dumbymap));
680};
681
682const actionOutsideMenu = e => {
683 if (menu.style.display === 'none' || cm.hasFocus()) return;
684 const rect = menu.getBoundingClientRect();
685 if (
686 e.clientX < rect.left ||
687 e.clientX > rect.left + rect.width ||
688 e.clientY < rect.top ||
689 e.clientY > rect.top + rect.height
690 ) {
691 menu.style.display = 'none';
692 }
693};
694
695document.addEventListener('click', actionOutsideMenu);
696
697// }}}
698 664
699// vim: sw=2 ts=2 foldmethod=marker foldmarker={{{,}}} 665// vim: sw=2 ts=2 foldmethod=marker foldmarker={{{,}}}