aleman 2.0.3 → 2.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/ChangeLog +15 -0
- package/example/lunes/index.html +3 -0
- package/example/lunes/index.js +22 -0
- package/example/menu/index.html +1 -0
- package/example/menu/index.js +12 -1
- package/lunes/actions/index.js +7 -0
- package/lunes/actions/up.json +5 -0
- package/lunes/compiler/compiler.js +5 -0
- package/lunes/engine/engine.js +16 -0
- package/lunes/engine/listen.js +61 -0
- package/lunes/engine/position/get-position.js +35 -0
- package/lunes/hydrate-menu.js +34 -0
- package/lunes/importmap.js +9 -0
- package/lunes/lunes.js +102 -0
- package/lunes/menu.css +65 -0
- package/lunes/render/render.js +16 -0
- package/lunes/render/rules/build-menu/fixture/build-menu.js +9 -0
- package/lunes/render/rules/build-menu/fixture/no-cursor-fix.js +9 -0
- package/lunes/render/rules/build-menu/fixture/no-cursor.js +9 -0
- package/lunes/{rules → render/rules}/build-menu/index.js +21 -27
- package/lunes/render/rules/index.js +5 -0
- package/lunes/state/convert-menu-to-state/convert-menu-to-state.js +7 -3
- package/lunes/state/{README.md → rules/README.md} +1 -0
- package/lunes/state/rules/add-cursor/fixture/add-cursor.js +9 -0
- package/lunes/state/{add-cursor → rules/add-cursor}/fixture/down-fix.js +2 -2
- package/lunes/state/{add-cursor → rules/add-cursor}/fixture/down.js +3 -3
- package/lunes/state/{add-cursor → rules/add-cursor}/fixture/up-fix.js +2 -2
- package/lunes/state/{add-cursor → rules/add-cursor}/fixture/up.js +3 -3
- package/lunes/state/{add-cursor → rules/add-cursor}/index.js +2 -6
- package/lunes/state/rules/apply-visibility/fixture/apply-visibility-fix.js +9 -0
- package/lunes/state/{add-cursor/fixture/add-cursor.js → rules/apply-visibility/fixture/apply-visibility.js} +2 -2
- package/lunes/state/rules/apply-visibility/index.js +29 -0
- package/lunes/state/{cursor.js → rules/cursor.js} +1 -1
- package/lunes/state/{move-cursor → rules/move-cursor}/fixture/move-cursor-fix.js +2 -2
- package/lunes/state/{move-cursor → rules/move-cursor}/fixture/move-cursor.js +2 -2
- package/lunes/state/state.js +12 -5
- package/menu/addons/set-position/set-position.js +1 -1
- package/menu/hydrate-menu.js +0 -2
- package/nemo/hydrate-menu.js +0 -2
- package/package.json +3 -2
- package/lunes/rules/build-menu/fixture/build-menu.js +0 -9
- /package/{menu/addons/set-position → lunes/engine/position}/calculate.js +0 -0
- /package/lunes/{rules → render/rules}/README.md +0 -0
- /package/lunes/{rules → render/rules}/build-menu/fixture/build-menu-fix.js +0 -0
- /package/lunes/state/{move-cursor → rules/move-cursor}/index.js +0 -0
package/ChangeLog
CHANGED
|
@@ -1,3 +1,18 @@
|
|
|
1
|
+
2026.05.27, v2.0.4
|
|
2
|
+
|
|
3
|
+
fix:
|
|
4
|
+
- 79ad4aa aleman: menu: rm afterHydrate
|
|
5
|
+
- 98c1d80 example: menu
|
|
6
|
+
|
|
7
|
+
feature:
|
|
8
|
+
- fe3cf8c lunes: Escape
|
|
9
|
+
- b592739 lunes: apply-visibility: add
|
|
10
|
+
- f2b6589 lunes: render
|
|
11
|
+
- 17ac3a2 lunes: event loop
|
|
12
|
+
- af911e2 lunes: hydrate
|
|
13
|
+
- ed3bf43 lunes: cursor
|
|
14
|
+
- 6408584 lunes: build-menu: open/close -> on/off
|
|
15
|
+
|
|
1
16
|
2026.05.24, v2.0.3
|
|
2
17
|
|
|
3
18
|
feature:
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import {createMenu} from '../../lunes/lunes.js';
|
|
2
|
+
|
|
3
|
+
const menuData = {
|
|
4
|
+
hello: () => alert('x'),
|
|
5
|
+
world: () => alert('y'),
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
const options = {
|
|
9
|
+
name: 'menu',
|
|
10
|
+
infiniteScroll: true,
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
const {name} = document.body.dataset;
|
|
14
|
+
const menu = await createMenu(name, options, menuData);
|
|
15
|
+
|
|
16
|
+
globalThis.addEventListener('keydown', (event) => {
|
|
17
|
+
if (event.key === 'F9')
|
|
18
|
+
menu.show();
|
|
19
|
+
|
|
20
|
+
if (event.key === 'Escape')
|
|
21
|
+
menu.hide();
|
|
22
|
+
});
|
package/example/menu/index.html
CHANGED
package/example/menu/index.js
CHANGED
|
@@ -5,4 +5,15 @@ const menuData = {
|
|
|
5
5
|
world: () => alert('y'),
|
|
6
6
|
};
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
const options = {
|
|
9
|
+
name: 'menu',
|
|
10
|
+
infiniteScroll: true,
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
const {name} = document.body.dataset;
|
|
14
|
+
const menu = await createMenu(name, options, menuData);
|
|
15
|
+
|
|
16
|
+
globalThis.addEventListener('keydown', (event) => {
|
|
17
|
+
if (event.key === 'F9')
|
|
18
|
+
menu.show();
|
|
19
|
+
});
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import {listen} from './listen.js';
|
|
2
|
+
|
|
3
|
+
export const createLoop = (element, {actions, compile}) => {
|
|
4
|
+
setTimeout(async () => {
|
|
5
|
+
await loop({
|
|
6
|
+
actions,
|
|
7
|
+
compile,
|
|
8
|
+
});
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
const loop = async ({actions, compile}) => {
|
|
13
|
+
for await (const [operation, cursor] of listen(actions)) {
|
|
14
|
+
compile(operation, cursor);
|
|
15
|
+
}
|
|
16
|
+
};
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
export const listen = (events = ['click'], overrides = {}) => ({
|
|
2
|
+
[Symbol.asyncIterator]() {
|
|
3
|
+
const {
|
|
4
|
+
addEventListener = globalThis.addEventListener,
|
|
5
|
+
removeEventListener = globalThis.removeEventListener,
|
|
6
|
+
} = overrides;
|
|
7
|
+
|
|
8
|
+
const queue = [];
|
|
9
|
+
let resolveNext;
|
|
10
|
+
|
|
11
|
+
const handlers = events.map((event) => {
|
|
12
|
+
const fn = () => {
|
|
13
|
+
if (resolveNext) {
|
|
14
|
+
resolveNext({
|
|
15
|
+
value: event,
|
|
16
|
+
done: false,
|
|
17
|
+
});
|
|
18
|
+
resolveNext = null;
|
|
19
|
+
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
queue.push(event);
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
addEventListener(event, fn);
|
|
27
|
+
|
|
28
|
+
return {
|
|
29
|
+
event,
|
|
30
|
+
fn,
|
|
31
|
+
};
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
const cleanup = () => {
|
|
35
|
+
for (const h of handlers) {
|
|
36
|
+
removeEventListener(h.event, h.fn);
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
return {
|
|
41
|
+
next() {
|
|
42
|
+
if (queue.length)
|
|
43
|
+
return Promise.resolve({
|
|
44
|
+
value: queue.shift(),
|
|
45
|
+
done: false,
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
return new Promise((resolve) => {
|
|
49
|
+
resolveNext = resolve;
|
|
50
|
+
});
|
|
51
|
+
},
|
|
52
|
+
|
|
53
|
+
return() {
|
|
54
|
+
cleanup();
|
|
55
|
+
return Promise.resolve({
|
|
56
|
+
done: true,
|
|
57
|
+
});
|
|
58
|
+
},
|
|
59
|
+
};
|
|
60
|
+
},
|
|
61
|
+
});
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import {calculate} from './calculate.js';
|
|
2
|
+
|
|
3
|
+
export const getPosition = (name, event) => {
|
|
4
|
+
const element = document.querySelector(`[data-name="${name}"]`);
|
|
5
|
+
const heightMenu = getMenuHeight(element);
|
|
6
|
+
const widthMenu = getMenuWidth(element);
|
|
7
|
+
const {innerHeight, innerWidth} = globalThis;
|
|
8
|
+
|
|
9
|
+
const {x, y} = calculate(event, {
|
|
10
|
+
heightMenu,
|
|
11
|
+
widthMenu,
|
|
12
|
+
innerWidth,
|
|
13
|
+
innerHeight,
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
const left = x;
|
|
17
|
+
const top = y;
|
|
18
|
+
|
|
19
|
+
return {
|
|
20
|
+
position: {
|
|
21
|
+
left,
|
|
22
|
+
top,
|
|
23
|
+
},
|
|
24
|
+
};
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
function getMenuHeight(element) {
|
|
28
|
+
const {height} = getComputedStyle(element);
|
|
29
|
+
return parseInt(height, 10);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function getMenuWidth(element) {
|
|
33
|
+
const {width} = getComputedStyle(element);
|
|
34
|
+
return parseInt(width, 10);
|
|
35
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import {createState} from './state/state.js';
|
|
2
|
+
import {render} from './render/render.js';
|
|
3
|
+
import {actions} from './actions/index.js';
|
|
4
|
+
import {createLoop} from './engine/engine.js';
|
|
5
|
+
import {createCompiler} from './compiler/compiler.js';
|
|
6
|
+
|
|
7
|
+
export const hydrateMenu = (elementName, {hydrateElement, menu}) => {
|
|
8
|
+
const {commit} = createState(menu);
|
|
9
|
+
const compile = createCompiler(hydrateElement, {
|
|
10
|
+
commit,
|
|
11
|
+
render,
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
createLoop(hydrateElement, {
|
|
15
|
+
compile,
|
|
16
|
+
actions,
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
return {
|
|
20
|
+
show: (top = 0, left = 0) => {
|
|
21
|
+
compile('show', {
|
|
22
|
+
position: {
|
|
23
|
+
top,
|
|
24
|
+
left,
|
|
25
|
+
},
|
|
26
|
+
});
|
|
27
|
+
},
|
|
28
|
+
hide: () => {
|
|
29
|
+
compile('hide', {
|
|
30
|
+
position: {},
|
|
31
|
+
});
|
|
32
|
+
},
|
|
33
|
+
};
|
|
34
|
+
};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export const importmap = {
|
|
2
|
+
imports: {
|
|
3
|
+
'putout': 'https://esm.sh/@putout/bundle@5.5.0',
|
|
4
|
+
'@putout/processor-html': 'https://esm.sh/@putout/processor-html',
|
|
5
|
+
'fullstore': 'https://esm.sh/fullstore',
|
|
6
|
+
'jessy': 'https://esm.sh/jessy',
|
|
7
|
+
'#aleman': '../aleman/aleman.js',
|
|
8
|
+
},
|
|
9
|
+
};
|
package/lunes/lunes.js
ADDED
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
const {stringify} = JSON;
|
|
2
|
+
|
|
3
|
+
export const createMenu = async (elementName, options, menu) => {
|
|
4
|
+
options.name = options.name || 'menu';
|
|
5
|
+
const {name} = options;
|
|
6
|
+
|
|
7
|
+
const hydrateElement = createHydrate(name);
|
|
8
|
+
|
|
9
|
+
await createMap();
|
|
10
|
+
await loadStyle();
|
|
11
|
+
|
|
12
|
+
const {hydrateMenu} = await import('./hydrate-menu.js');
|
|
13
|
+
|
|
14
|
+
return hydrateMenu(elementName, {
|
|
15
|
+
hydrateElement,
|
|
16
|
+
options,
|
|
17
|
+
menu,
|
|
18
|
+
});
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
async function loadStyle() {
|
|
22
|
+
const name = 'aleman-menu-style';
|
|
23
|
+
|
|
24
|
+
if (findByName(name))
|
|
25
|
+
return;
|
|
26
|
+
|
|
27
|
+
const [error] = await tryToCatch(importCSS);
|
|
28
|
+
|
|
29
|
+
if (!error)
|
|
30
|
+
return;
|
|
31
|
+
|
|
32
|
+
createLink();
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function createLink() {
|
|
36
|
+
const link = document.createElement('link');
|
|
37
|
+
|
|
38
|
+
link.rel = 'stylesheet';
|
|
39
|
+
link.href = new URL('menu.css', import.meta.url).pathname;
|
|
40
|
+
document.head.appendChild(link);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
async function importCSS() {
|
|
44
|
+
const content = await import('./menu.css', {
|
|
45
|
+
with: {
|
|
46
|
+
type: 'css',
|
|
47
|
+
},
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
const style = document.createElement('style');
|
|
51
|
+
|
|
52
|
+
style.dataset.name = name;
|
|
53
|
+
|
|
54
|
+
for (const rule of content.default.cssRules) {
|
|
55
|
+
style.innerHTML += rule.cssText;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
document.head.appendChild(style);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function createHydrate(name) {
|
|
62
|
+
const hydrateElement = findByName(name);
|
|
63
|
+
|
|
64
|
+
if (hydrateElement)
|
|
65
|
+
return hydrateElement;
|
|
66
|
+
|
|
67
|
+
const section = document.createElement('section');
|
|
68
|
+
|
|
69
|
+
section.dataset.name = `aleman-hydrate-${name}`;
|
|
70
|
+
section.innerHTML = `<ul data-name="${name}" class="menu menu-hidden"></ul>`;
|
|
71
|
+
document.body.append(section);
|
|
72
|
+
|
|
73
|
+
return section;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
async function createMap() {
|
|
77
|
+
const name = 'aleman-importmap';
|
|
78
|
+
|
|
79
|
+
if (findByName(name))
|
|
80
|
+
return;
|
|
81
|
+
|
|
82
|
+
const script = document.createElement('script');
|
|
83
|
+
|
|
84
|
+
const {importmap} = await import('./importmap.js');
|
|
85
|
+
|
|
86
|
+
script.dataset.name = name;
|
|
87
|
+
script.type = 'importmap';
|
|
88
|
+
script.innerHTML = stringify(importmap, null, 4);
|
|
89
|
+
document.body.append(script);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
function findByName(name) {
|
|
93
|
+
return document.querySelector(`[data-name=${name}]`);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
async function tryToCatch(fn, args) {
|
|
97
|
+
try {
|
|
98
|
+
return [null, await fn(...args)];
|
|
99
|
+
} catch(error) {
|
|
100
|
+
return [error];
|
|
101
|
+
}
|
|
102
|
+
}
|
package/lunes/menu.css
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
.menu-hidden {
|
|
2
|
+
display: none;
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
.menu {
|
|
6
|
+
position : absolute;
|
|
7
|
+
z-index : 2;
|
|
8
|
+
padding : 0;
|
|
9
|
+
font-size : 14px;
|
|
10
|
+
list-style : none;
|
|
11
|
+
color : #222;
|
|
12
|
+
background : rgb(255 255 255 / 90%);
|
|
13
|
+
border-color : rgb(49 123 249 / 40%);
|
|
14
|
+
border-style : solid;
|
|
15
|
+
border-width : 1px;
|
|
16
|
+
border-radius : 5px;
|
|
17
|
+
-webkit-user-select : none;
|
|
18
|
+
-moz-user-select : none;
|
|
19
|
+
-ms-user-select : none;
|
|
20
|
+
user-select : none;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
.menu-button {
|
|
24
|
+
background: white;
|
|
25
|
+
border: 0;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
.menu-item {
|
|
29
|
+
position: relative;
|
|
30
|
+
padding: 3px 20px;
|
|
31
|
+
white-space: nowrap;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
.menu-item::after {
|
|
35
|
+
content: attr(data-key);
|
|
36
|
+
float: right;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
.menu-item:hover, .menu-item-selected {
|
|
40
|
+
background-color: #e3f2ff;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
.menu-item > .menu {
|
|
44
|
+
top: 0;
|
|
45
|
+
left: 100%;
|
|
46
|
+
display: none;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
.menu-submenu-show > .menu, .menu-item:hover > .menu {
|
|
50
|
+
display: block;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
.menu-submenu > label::after {
|
|
54
|
+
display: block;
|
|
55
|
+
float: right;
|
|
56
|
+
width: 0;
|
|
57
|
+
height: 0;
|
|
58
|
+
margin-top: 3px;
|
|
59
|
+
margin-right: -10px;
|
|
60
|
+
border-color: transparent;
|
|
61
|
+
border-left-color: rgb(49 123 249);
|
|
62
|
+
border-style: solid;
|
|
63
|
+
border-width: 5px 0 5px 5px;
|
|
64
|
+
content: ' ';
|
|
65
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import {putout} from 'putout';
|
|
2
|
+
import {merge} from '@putout/processor-html';
|
|
3
|
+
import * as buildMenu from './rules/build-menu/index.js';
|
|
4
|
+
|
|
5
|
+
export const render = (state, options) => {
|
|
6
|
+
const {code} = putout(state, {
|
|
7
|
+
rules: {
|
|
8
|
+
'lunes/build-menu': ['on', options],
|
|
9
|
+
},
|
|
10
|
+
plugins: [
|
|
11
|
+
['lunes/build-menu', buildMenu],
|
|
12
|
+
],
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
return merge('', [code]);
|
|
16
|
+
};
|
|
@@ -17,6 +17,20 @@ const {
|
|
|
17
17
|
setAttributeValue,
|
|
18
18
|
} = operator;
|
|
19
19
|
|
|
20
|
+
const isOn = ({node}) => {
|
|
21
|
+
if (isObjectProperty(node))
|
|
22
|
+
return node.value.value;
|
|
23
|
+
|
|
24
|
+
return node.elements[0].value === 'on';
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
const isSelected = ({node}) => {
|
|
28
|
+
if (isObjectProperty(node))
|
|
29
|
+
return node.value.value;
|
|
30
|
+
|
|
31
|
+
return node.elements[1].value === 'cursor';
|
|
32
|
+
};
|
|
33
|
+
|
|
20
34
|
export const report = () => `Build menu`;
|
|
21
35
|
export const include = () => [
|
|
22
36
|
'ObjectProperty',
|
|
@@ -46,8 +60,7 @@ const createMenuItem = (path) => {
|
|
|
46
60
|
return submenu;
|
|
47
61
|
}
|
|
48
62
|
|
|
49
|
-
const
|
|
50
|
-
const classSelected = selected ? ' menu-item-selected' : '';
|
|
63
|
+
const classSelected = isSelected(path) ? 'menu-item-selected' : '';
|
|
51
64
|
|
|
52
65
|
const node = template.ast.fresh(`
|
|
53
66
|
<li data-name="menu-item" className="menu-item${classSelected}">
|
|
@@ -59,12 +72,11 @@ const createMenuItem = (path) => {
|
|
|
59
72
|
};
|
|
60
73
|
|
|
61
74
|
const createUL = (path) => {
|
|
62
|
-
const show = path.node.elements[0].value === 'open';
|
|
63
75
|
const node = template.ast.fresh(`
|
|
64
76
|
<ul className="menu menu-hidden"></ul>
|
|
65
77
|
`);
|
|
66
78
|
|
|
67
|
-
if (
|
|
79
|
+
if (isOn(path))
|
|
68
80
|
removeClassName(node, 'menu-hidden');
|
|
69
81
|
|
|
70
82
|
return node;
|
|
@@ -72,12 +84,8 @@ const createUL = (path) => {
|
|
|
72
84
|
|
|
73
85
|
const createSubmenu = (path) => {
|
|
74
86
|
const {name} = path.parentPath.node.key;
|
|
75
|
-
|
|
76
|
-
const
|
|
77
|
-
const show = path.node.elements[0].value === 'open';
|
|
78
|
-
|
|
79
|
-
const menuHidden = show ? '' : ' menu-hidden';
|
|
80
|
-
const classSelected = selected ? ' menu-item-selected' : '';
|
|
87
|
+
const menuHidden = isOn(path) ? '' : ' menu-hidden';
|
|
88
|
+
const classSelected = isSelected(path) ? ' menu-item-selected' : '';
|
|
81
89
|
|
|
82
90
|
const node = template.ast.fresh(`
|
|
83
91
|
<li data-name="menu-item" className="menu-item${classSelected}">
|
|
@@ -89,21 +97,10 @@ const createSubmenu = (path) => {
|
|
|
89
97
|
return node;
|
|
90
98
|
};
|
|
91
99
|
|
|
92
|
-
const
|
|
93
|
-
const
|
|
94
|
-
|
|
95
|
-
.elements
|
|
96
|
-
.at(-2)
|
|
97
|
-
.value
|
|
98
|
-
.split(':');
|
|
100
|
+
export const fix = (path, {options}) => {
|
|
101
|
+
const {position} = options;
|
|
102
|
+
const {top, left} = position;
|
|
99
103
|
|
|
100
|
-
return {
|
|
101
|
-
left,
|
|
102
|
-
top,
|
|
103
|
-
};
|
|
104
|
-
};
|
|
105
|
-
|
|
106
|
-
export const fix = (path) => {
|
|
107
104
|
if (isObjectProperty(path)) {
|
|
108
105
|
replaceWith(path, createMenuItem(path));
|
|
109
106
|
return;
|
|
@@ -114,9 +111,6 @@ export const fix = (path) => {
|
|
|
114
111
|
|
|
115
112
|
if (isExpressionStatement(path.parentPath)) {
|
|
116
113
|
replaceWith(path, ul);
|
|
117
|
-
|
|
118
|
-
const {left, top} = parsePosition(path);
|
|
119
|
-
|
|
120
114
|
setAttributeValue(ul, 'style', `left: ${left}px; top: ${top}px`);
|
|
121
115
|
}
|
|
122
116
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
const {entries} = Object;
|
|
2
2
|
const isObject = (a) => a && typeof a === 'object';
|
|
3
3
|
|
|
4
|
-
export function convertMenuToState(menu) {
|
|
4
|
+
export function convertMenuToState(menu, {submenu} = {}) {
|
|
5
5
|
const result = [];
|
|
6
6
|
|
|
7
7
|
for (const [key, value] of entries(menu)) {
|
|
@@ -10,8 +10,12 @@ export function convertMenuToState(menu) {
|
|
|
10
10
|
continue;
|
|
11
11
|
}
|
|
12
12
|
|
|
13
|
-
result.push(`${key}: ${convertMenuToState(value
|
|
13
|
+
result.push(`${key}: ${convertMenuToState(value, {
|
|
14
|
+
submenu: true,
|
|
15
|
+
})}`);
|
|
14
16
|
}
|
|
15
17
|
|
|
16
|
-
|
|
18
|
+
const noCursor = submenu ? '' : `'no-cursor', `;
|
|
19
|
+
|
|
20
|
+
return `['off', ${noCursor} {${result.join(', ')}}]`;
|
|
17
21
|
}
|
|
@@ -2,3 +2,4 @@
|
|
|
2
2
|
|
|
3
3
|
- [add-cursor](https://putout.cloudcmd.io/#/gist/0d0be0b7d19949be48c4122416654936/0cf8e1c512a0503f8c4bd0abf2af221b6680630b);
|
|
4
4
|
- [move-cursor](https://putout.cloudcmd.io/#/gist/54ff76b9673e0caf216b0f0f33d9f8bb/dad16ba0f861073a3ab7549e553dd2b97d252729);
|
|
5
|
+
- [apply-visibility](https://putout.cloudcmd.io/#/gist/7b97aaec7fcc518de4f6eef4ecc3dd58/f38db01fb9af051d49bd114bfb7bb04d2298c501);
|
|
@@ -5,7 +5,7 @@ import {
|
|
|
5
5
|
setCursor,
|
|
6
6
|
} from '../cursor.js';
|
|
7
7
|
|
|
8
|
-
const {
|
|
8
|
+
const {remove} = operator;
|
|
9
9
|
|
|
10
10
|
const operations = {
|
|
11
11
|
last,
|
|
@@ -30,9 +30,5 @@ export const fix = (path, {options}) => {
|
|
|
30
30
|
const cursorPath = getCursor(path);
|
|
31
31
|
|
|
32
32
|
setCursor(cursorPath);
|
|
33
|
-
|
|
34
|
-
const keyPath = cursorPath.get('key');
|
|
35
|
-
const {name} = keyPath.node;
|
|
36
|
-
|
|
37
|
-
setLiteralValue(path.node, name);
|
|
33
|
+
remove(path);
|
|
38
34
|
};
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import {types} from 'putout';
|
|
2
|
+
|
|
3
|
+
const {isExpressionStatement} = types;
|
|
4
|
+
|
|
5
|
+
export const report = () => `Apply visibility`;
|
|
6
|
+
|
|
7
|
+
export const match = ({options}) => {
|
|
8
|
+
const {operation = 'show'} = options;
|
|
9
|
+
|
|
10
|
+
return {
|
|
11
|
+
'"off"': (vars, path) => {
|
|
12
|
+
if (operation !== 'show')
|
|
13
|
+
return false;
|
|
14
|
+
|
|
15
|
+
return isExpressionStatement(path.parentPath.parentPath);
|
|
16
|
+
},
|
|
17
|
+
'"on"': (vars, path) => {
|
|
18
|
+
if (operation !== 'hide')
|
|
19
|
+
return false;
|
|
20
|
+
|
|
21
|
+
return isExpressionStatement(path.parentPath.parentPath);
|
|
22
|
+
},
|
|
23
|
+
};
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
export const replace = () => ({
|
|
27
|
+
'"off"': '"on"',
|
|
28
|
+
'"on"': '"off"',
|
|
29
|
+
});
|
package/lunes/state/state.js
CHANGED
|
@@ -1,27 +1,34 @@
|
|
|
1
1
|
import {putout} from 'putout';
|
|
2
2
|
import {convertMenuToState} from './convert-menu-to-state/convert-menu-to-state.js';
|
|
3
|
-
import * as addCursor from './add-cursor/index.js';
|
|
4
|
-
import * as moveCursor from './move-cursor/index.js';
|
|
3
|
+
import * as addCursor from './rules/add-cursor/index.js';
|
|
4
|
+
import * as moveCursor from './rules/move-cursor/index.js';
|
|
5
|
+
import * as applyVisibility from './rules/apply-visibility/index.js';
|
|
5
6
|
|
|
6
7
|
export const createState = (menu) => {
|
|
7
8
|
const state = convertMenuToState(menu);
|
|
8
9
|
|
|
9
10
|
return {
|
|
10
|
-
|
|
11
|
+
commit: createCommit(state),
|
|
11
12
|
};
|
|
12
13
|
};
|
|
13
14
|
|
|
14
|
-
|
|
15
|
+
const createCommit = (state) => (operation) => {
|
|
16
|
+
const options = {
|
|
17
|
+
operation,
|
|
18
|
+
};
|
|
19
|
+
|
|
15
20
|
const {code} = putout(state, {
|
|
16
21
|
rules: {
|
|
17
22
|
'add-cursor': ['on', options],
|
|
18
23
|
'move-cursor': ['on', options],
|
|
24
|
+
'apply-visibility': ['on', options],
|
|
19
25
|
},
|
|
20
26
|
plugins: [
|
|
21
27
|
['add-cursor', addCursor],
|
|
22
28
|
['move-cursor', moveCursor],
|
|
29
|
+
['apply-visibility', applyVisibility],
|
|
23
30
|
],
|
|
24
31
|
});
|
|
25
32
|
|
|
26
33
|
return code;
|
|
27
|
-
}
|
|
34
|
+
};
|
package/menu/hydrate-menu.js
CHANGED
|
@@ -6,7 +6,6 @@ import {createMouseEnter} from './addons/mouse-leave/index.js';
|
|
|
6
6
|
import {createItemClick} from './addons/item-click/item-click.js';
|
|
7
7
|
import * as click from './addons/click/click.js';
|
|
8
8
|
import {createContextMenu} from './addons/context-menu.js';
|
|
9
|
-
import {setPosition} from './addons/set-position/set-position.js';
|
|
10
9
|
|
|
11
10
|
const {assign} = Object;
|
|
12
11
|
|
|
@@ -29,7 +28,6 @@ export const hydrateMenu = (elementName, {hydrateElement, options, menu}) => {
|
|
|
29
28
|
...addons,
|
|
30
29
|
],
|
|
31
30
|
rules,
|
|
32
|
-
afterHydrate: setPosition,
|
|
33
31
|
stateName: `aleman-state-${name}`,
|
|
34
32
|
});
|
|
35
33
|
|
package/nemo/hydrate-menu.js
CHANGED
|
@@ -6,7 +6,6 @@ import {createMouseEnter} from './addons/mouse-leave/index.js';
|
|
|
6
6
|
import {createItemClick} from './addons/item-click/item-click.js';
|
|
7
7
|
import * as click from './addons/click/click.js';
|
|
8
8
|
import {createContextMenu} from './addons/context-menu.js';
|
|
9
|
-
import {setPosition} from './addons/set-position/set-position.js';
|
|
10
9
|
|
|
11
10
|
const {assign} = Object;
|
|
12
11
|
|
|
@@ -29,7 +28,6 @@ export const hydrateMenu = (elementName, {hydrateElement, options, menu}) => {
|
|
|
29
28
|
...addons,
|
|
30
29
|
],
|
|
31
30
|
rules,
|
|
32
|
-
afterHydrate: setPosition,
|
|
33
31
|
stateName: `aleman-state-${name}`,
|
|
34
32
|
});
|
|
35
33
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "aleman",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.4",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"author": "coderaiser <mnemonic.enemy@gmail.com> (https://github.com/coderaiser)",
|
|
6
6
|
"description": "🐊Putout-based framework for web",
|
|
@@ -25,7 +25,8 @@
|
|
|
25
25
|
"report": "madrun report"
|
|
26
26
|
},
|
|
27
27
|
"imports": {
|
|
28
|
-
"#test": "./test/create-test.js"
|
|
28
|
+
"#test": "./test/create-test.js",
|
|
29
|
+
"#aleman": "./aleman/lib/index.js"
|
|
29
30
|
},
|
|
30
31
|
"dependencies": {
|
|
31
32
|
"@putout/processor-html": "^14.0.2",
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|