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.
Files changed (45) hide show
  1. package/ChangeLog +15 -0
  2. package/example/lunes/index.html +3 -0
  3. package/example/lunes/index.js +22 -0
  4. package/example/menu/index.html +1 -0
  5. package/example/menu/index.js +12 -1
  6. package/lunes/actions/index.js +7 -0
  7. package/lunes/actions/up.json +5 -0
  8. package/lunes/compiler/compiler.js +5 -0
  9. package/lunes/engine/engine.js +16 -0
  10. package/lunes/engine/listen.js +61 -0
  11. package/lunes/engine/position/get-position.js +35 -0
  12. package/lunes/hydrate-menu.js +34 -0
  13. package/lunes/importmap.js +9 -0
  14. package/lunes/lunes.js +102 -0
  15. package/lunes/menu.css +65 -0
  16. package/lunes/render/render.js +16 -0
  17. package/lunes/render/rules/build-menu/fixture/build-menu.js +9 -0
  18. package/lunes/render/rules/build-menu/fixture/no-cursor-fix.js +9 -0
  19. package/lunes/render/rules/build-menu/fixture/no-cursor.js +9 -0
  20. package/lunes/{rules → render/rules}/build-menu/index.js +21 -27
  21. package/lunes/render/rules/index.js +5 -0
  22. package/lunes/state/convert-menu-to-state/convert-menu-to-state.js +7 -3
  23. package/lunes/state/{README.md → rules/README.md} +1 -0
  24. package/lunes/state/rules/add-cursor/fixture/add-cursor.js +9 -0
  25. package/lunes/state/{add-cursor → rules/add-cursor}/fixture/down-fix.js +2 -2
  26. package/lunes/state/{add-cursor → rules/add-cursor}/fixture/down.js +3 -3
  27. package/lunes/state/{add-cursor → rules/add-cursor}/fixture/up-fix.js +2 -2
  28. package/lunes/state/{add-cursor → rules/add-cursor}/fixture/up.js +3 -3
  29. package/lunes/state/{add-cursor → rules/add-cursor}/index.js +2 -6
  30. package/lunes/state/rules/apply-visibility/fixture/apply-visibility-fix.js +9 -0
  31. package/lunes/state/{add-cursor/fixture/add-cursor.js → rules/apply-visibility/fixture/apply-visibility.js} +2 -2
  32. package/lunes/state/rules/apply-visibility/index.js +29 -0
  33. package/lunes/state/{cursor.js → rules/cursor.js} +1 -1
  34. package/lunes/state/{move-cursor → rules/move-cursor}/fixture/move-cursor-fix.js +2 -2
  35. package/lunes/state/{move-cursor → rules/move-cursor}/fixture/move-cursor.js +2 -2
  36. package/lunes/state/state.js +12 -5
  37. package/menu/addons/set-position/set-position.js +1 -1
  38. package/menu/hydrate-menu.js +0 -2
  39. package/nemo/hydrate-menu.js +0 -2
  40. package/package.json +3 -2
  41. package/lunes/rules/build-menu/fixture/build-menu.js +0 -9
  42. /package/{menu/addons/set-position → lunes/engine/position}/calculate.js +0 -0
  43. /package/lunes/{rules → render/rules}/README.md +0 -0
  44. /package/lunes/{rules → render/rules}/build-menu/fixture/build-menu-fix.js +0 -0
  45. /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,3 @@
1
+ <script src="index.js" type="module"></script>
2
+
3
+ <body data-name="lunes"></body>
@@ -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
+ });
@@ -1 +1,2 @@
1
1
  <script src="index.js" type="module"></script>
2
+ <body data-name="aleman-example"></body>
@@ -5,4 +5,15 @@ const menuData = {
5
5
  world: () => alert('y'),
6
6
  };
7
7
 
8
- await createMenu(document.body, {}, menuData);
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,7 @@
1
+ import up from './up.json' with {
2
+ type: 'json',
3
+ };
4
+
5
+ export const actions = [
6
+ up,
7
+ ];
@@ -0,0 +1,5 @@
1
+ {
2
+ "keys": ["ArrowUp"],
3
+ "preventDefault": true,
4
+ "operations": ["up"]
5
+ }
@@ -0,0 +1,5 @@
1
+ export const createCompiler = (element, {commit, render}) => (operation, cursor) => {
2
+ const state = commit(operation);
3
+
4
+ element.innerHTML = render(state, cursor);
5
+ };
@@ -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
+ };
@@ -0,0 +1,9 @@
1
+ ['on', {
2
+ view,
3
+ edit,
4
+ rename,
5
+ new: ['on', 'cursor', {
6
+ file,
7
+ directory,
8
+ }],
9
+ }];
@@ -0,0 +1,9 @@
1
+ ['on', 'no-cursor', {
2
+ view,
3
+ edit,
4
+ rename,
5
+ new: ['off', {
6
+ file,
7
+ directory,
8
+ }],
9
+ }];
@@ -0,0 +1,9 @@
1
+ ['on', 'no-cursor', {
2
+ view,
3
+ edit,
4
+ rename,
5
+ new: ['off', {
6
+ file,
7
+ directory,
8
+ }],
9
+ }];
@@ -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 selected = path.node.value.value === 'cursor';
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 (show)
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 selected = path.node.elements[1].value === 'cursor';
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 parsePosition = (path) => {
93
- const [left, top] = path
94
- .node
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
 
@@ -0,0 +1,5 @@
1
+ import * as buildMenu from './build-menu/index.js';
2
+
3
+ export const rules = {
4
+ 'build-menu': buildMenu,
5
+ };
@@ -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
- return `['close',{${result.join(',')}}]`;
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);
@@ -0,0 +1,9 @@
1
+ ['on', 'no-cursor', {
2
+ view,
3
+ edit,
4
+ rename,
5
+ new: ['off', {
6
+ file,
7
+ directory,
8
+ }],
9
+ }];
@@ -1,8 +1,8 @@
1
- ['open', 'view', {
1
+ ['on', {
2
2
  view: 'cursor',
3
3
  edit,
4
4
  rename,
5
- new: ['close', {
5
+ new: ['off', {
6
6
  file,
7
7
  directory,
8
8
  }],
@@ -1,9 +1,9 @@
1
- ['open', 'no-cursor', {
1
+ ['on', 'no-cursor', {
2
2
  view,
3
3
  edit,
4
4
  rename,
5
- new: ['close', {
5
+ new: ['off', {
6
6
  file,
7
7
  directory,
8
- }]
8
+ }],
9
9
  }];
@@ -1,8 +1,8 @@
1
- ['open', 'new', {
1
+ ['on', {
2
2
  view,
3
3
  edit,
4
4
  rename,
5
- new: ['cursor', 'close', {
5
+ new: ['off', 'cursor', {
6
6
  file,
7
7
  directory,
8
8
  }],
@@ -1,9 +1,9 @@
1
- ['open', 'no-cursor', {
1
+ ['on', 'no-cursor', {
2
2
  view,
3
3
  edit,
4
4
  rename,
5
- new: ['close', {
5
+ new: ['off', {
6
6
  file,
7
7
  directory,
8
- }]
8
+ }],
9
9
  }];
@@ -5,7 +5,7 @@ import {
5
5
  setCursor,
6
6
  } from '../cursor.js';
7
7
 
8
- const {setLiteralValue} = operator;
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,9 @@
1
+ ['on', 'no-cursor', {
2
+ view,
3
+ edit,
4
+ rename,
5
+ new: ['off', {
6
+ file,
7
+ directory,
8
+ }],
9
+ }];
@@ -1,8 +1,8 @@
1
- ['open', 'no-cursor', {
1
+ ['off', 'no-cursor', {
2
2
  view,
3
3
  edit,
4
4
  rename,
5
- new: ['close', {
5
+ new: ['off', {
6
6
  file,
7
7
  directory,
8
8
  }]
@@ -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
+ });
@@ -36,7 +36,7 @@ export function setCursor(path) {
36
36
  }
37
37
 
38
38
  if (isArrayExpression(valuePath))
39
- valuePath.node.elements.unshift(stringLiteral('cursor'));
39
+ valuePath.node.elements.splice(1, 0, stringLiteral('cursor'));
40
40
  }
41
41
 
42
42
  export function prev(path) {
@@ -1,8 +1,8 @@
1
- ['open', '10:20', {
1
+ ['on', {
2
2
  view,
3
3
  edit,
4
4
  rename,
5
- new: ['cursor', 'close', {
5
+ new: ['off', 'cursor', {
6
6
  file,
7
7
  directory,
8
8
  }],
@@ -1,8 +1,8 @@
1
- ['open', '10:20', {
1
+ ['on', {
2
2
  view: 'cursor',
3
3
  edit,
4
4
  rename,
5
- new: ['close', {
5
+ new: ['off', {
6
6
  file,
7
7
  directory,
8
8
  }],
@@ -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
- updateState: createUpdateState(state),
11
+ commit: createCommit(state),
11
12
  };
12
13
  };
13
14
 
14
- function createUpdateState(state, options) {
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
+ };
@@ -1,4 +1,4 @@
1
- import {calculate} from './calculate.js';
1
+ import {calculate} from '../../../lunes/engine/position/calculate.js';
2
2
 
3
3
  export const setPosition = (name, event) => {
4
4
  const element = document.querySelector(`[data-name="${name}"]`);
@@ -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
 
@@ -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",
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",
@@ -1,9 +0,0 @@
1
- ['open', '100:20', {
2
- view,
3
- edit,
4
- rename,
5
- new: ['open', 'cursor', {
6
- file,
7
- directory,
8
- }]
9
- }];
File without changes