aleman 1.0.16 → 1.1.0

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 (95) hide show
  1. package/aleman/add-listeners.js +94 -0
  2. package/aleman/index.js +44 -0
  3. package/aleman/render.js +58 -0
  4. package/aleman/state.js +78 -0
  5. package/example/index.html +1 -0
  6. package/example/index.js +8 -0
  7. package/index-buttons.html +2 -2
  8. package/index.html +2 -3
  9. package/menu/addons/click.js +6 -0
  10. package/menu/addons/context-menu.js +13 -0
  11. package/menu/addons/down.js +16 -0
  12. package/menu/addons/enter.js +16 -0
  13. package/menu/addons/escape.js +6 -0
  14. package/menu/addons/f9.js +9 -0
  15. package/menu/addons/index.js +21 -0
  16. package/menu/addons/item-click.js +16 -0
  17. package/menu/addons/mouse-enter.js +5 -0
  18. package/menu/addons/up.js +12 -0
  19. package/menu/hydrate-menu.js +22 -0
  20. package/menu/importmap.json +9 -0
  21. package/menu/menu.js +40 -23
  22. package/{lib → menu}/rules/index.js +4 -10
  23. package/{lib → menu}/rules/select/fixture/select-fix.js +1 -1
  24. package/{lib → menu}/rules/select/index.js +29 -5
  25. package/menu/rules/set-position/fixture/no-style.js +2 -0
  26. package/menu/rules/set-position/fixture/set-position-fix.js +2 -0
  27. package/{lib → menu}/rules/set-position/index.js +29 -4
  28. package/{lib → menu}/rules/unselect-all/index.js +6 -1
  29. package/menu/state.js +15 -0
  30. package/package.json +3 -6
  31. package/lib/addons/additional/fixture/start-click-fix.html +0 -0
  32. package/lib/addons/additional/fixture/start-click.html +0 -1
  33. package/lib/addons/additional/fixture/stop-click-fix.html +0 -0
  34. package/lib/addons/additional/fixture/stop-click.html +0 -1
  35. package/lib/addons/additional/input-change.js +0 -39
  36. package/lib/addons/additional/start-click.js +0 -7
  37. package/lib/addons/additional/stop-click.js +0 -7
  38. package/lib/addons/menu-item-click.js +0 -27
  39. package/lib/addons/menu-mouse-over.js +0 -6
  40. package/lib/addons/show-menu-click.js +0 -12
  41. package/lib/aleman/add-listeners.js +0 -116
  42. package/lib/aleman/aleman.js +0 -47
  43. package/lib/aleman/load.js +0 -5
  44. package/lib/aleman/render.js +0 -107
  45. package/lib/globals/menu/click.js +0 -21
  46. package/lib/globals/menu/context-menu.js +0 -18
  47. package/lib/globals/menu/down.js +0 -21
  48. package/lib/globals/menu/enter.js +0 -33
  49. package/lib/globals/menu/escape.js +0 -19
  50. package/lib/globals/menu/f9.js +0 -27
  51. package/lib/globals/menu/menu.js +0 -34
  52. package/lib/globals/menu/up.js +0 -19
  53. package/lib/globals/menu.js +0 -17
  54. package/lib/main.js +0 -35
  55. package/lib/menu/menu.js +0 -4
  56. package/lib/rules/README.md +0 -10
  57. package/lib/rules/remove-button/fixture/remove-button-fix.js +0 -2
  58. package/lib/rules/remove-button/fixture/remove-button.js +0 -2
  59. package/lib/rules/remove-button/index.js +0 -27
  60. package/lib/rules/set-value/fixture/data-name.js +0 -1
  61. package/lib/rules/set-value/fixture/no-data-name.js +0 -1
  62. package/lib/rules/set-value/fixture/not-label.js +0 -1
  63. package/lib/rules/set-value/fixture/set-value-fix.js +0 -1
  64. package/lib/rules/set-value/fixture/set-value.js +0 -1
  65. package/lib/rules/set-value/index.js +0 -34
  66. package/lib/rules/unselect/fixture/no-data-name.js +0 -4
  67. package/lib/rules/unselect/fixture/no-parent.js +0 -2
  68. package/lib/rules/unselect/fixture/unselect-fix.js +0 -8
  69. package/lib/rules/unselect/fixture/unselect.js +0 -8
  70. package/lib/rules/unselect/index.js +0 -39
  71. package/menu/index.html +0 -4
  72. package/menu/main.js +0 -29
  73. /package/{lib → menu}/rules/build-menu/fixture/build-menu-fix.js +0 -0
  74. /package/{lib → menu}/rules/build-menu/fixture/build-menu.js +0 -0
  75. /package/{lib → menu}/rules/build-menu/fixture/built.js +0 -0
  76. /package/{lib → menu}/rules/build-menu/index.js +0 -0
  77. /package/{lib → menu}/rules/check-data-name.js +0 -0
  78. /package/{lib → menu}/rules/menu/fixture/hide-menu-fix.js +0 -0
  79. /package/{lib → menu}/rules/menu/fixture/hide-menu.js +0 -0
  80. /package/{lib → menu}/rules/menu/fixture/no-menu.js +0 -0
  81. /package/{lib → menu}/rules/menu/fixture/show-menu-fix.js +0 -0
  82. /package/{lib → menu}/rules/menu/fixture/show-menu.js +0 -0
  83. /package/{lib → menu}/rules/menu/index.js +0 -0
  84. /package/{lib → menu}/rules/select/fixture/no-data-name.js +0 -0
  85. /package/{lib → menu}/rules/select/fixture/no-next.js +0 -0
  86. /package/{lib → menu}/rules/select/fixture/no-parent.js +0 -0
  87. /package/{lib → menu}/rules/select/fixture/select.js +0 -0
  88. /package/{lib → menu}/rules/select/fixture/wrong-data-name.js +0 -0
  89. /package/{lib/rules/set-position/fixture/set-position-fix.js → menu/rules/set-position/fixture/no-style-fix.js} +0 -0
  90. /package/{lib → menu}/rules/set-position/fixture/not-menu.js +0 -0
  91. /package/{lib → menu}/rules/set-position/fixture/set-position.js +0 -0
  92. /package/{lib → menu}/rules/unselect-all/fixture/no-data-name.js +0 -0
  93. /package/{lib → menu}/rules/unselect-all/fixture/no-parent.js +0 -0
  94. /package/{lib → menu}/rules/unselect-all/fixture/unselect-all-fix.js +0 -0
  95. /package/{lib → menu}/rules/unselect-all/fixture/unselect-all.js +0 -0
@@ -1,18 +1,36 @@
1
- import {operator} from 'putout';
1
+ import {operator, types} from 'putout';
2
2
  import {checkDataName} from '../check-data-name.js';
3
3
 
4
+ const {
5
+ stringLiteral,
6
+ jsxIdentifier,
7
+ jsxAttribute,
8
+ } = types;
9
+
4
10
  const {setLiteralValue} = operator;
5
11
 
6
12
  export const report = () => `Set position`;
7
13
 
8
- export const fix = ({attr, left, top}) => {
14
+ export const fix = ({path, attr, left, top}) => {
9
15
  const style = `left: ${left}px; top: ${top}px;`;
10
- setLiteralValue(attr.value, style);
16
+
17
+ if (attr) {
18
+ setLiteralValue(attr.value, style);
19
+
20
+ return;
21
+ }
22
+
23
+ const {attributes} = path.node;
24
+
25
+ const attribute = jsxAttribute(jsxIdentifier('style'), stringLiteral(style));
26
+
27
+ attributes.push(attribute);
11
28
  };
12
29
 
13
30
  export const traverse = ({options, push}) => ({
14
31
  JSXOpeningElement(path) {
15
- const {left = 0, top = 20} = options;
32
+ const {position = {}} = options;
33
+ const {left = 0, top = 20} = position;
16
34
 
17
35
  if (!checkDataName(path.parentPath, 'menu'))
18
36
  return;
@@ -32,7 +50,14 @@ export const traverse = ({options, push}) => ({
32
50
  left,
33
51
  top,
34
52
  });
53
+ return;
35
54
  }
55
+
56
+ push({
57
+ path,
58
+ left,
59
+ top,
60
+ });
36
61
  },
37
62
  });
38
63
 
@@ -13,8 +13,13 @@ export const fix = ({path}) => {
13
13
  setLiteralValue(value, newValue);
14
14
  };
15
15
 
16
- export const traverse = ({push}) => ({
16
+ export const traverse = ({push, options}) => ({
17
17
  JSXOpeningElement(path) {
18
+ const {index} = options;
19
+
20
+ if (index !== -1)
21
+ return;
22
+
18
23
  if (path.node.name.name !== 'li')
19
24
  return;
20
25
 
package/menu/state.js ADDED
@@ -0,0 +1,15 @@
1
+ const {keys} = Object;
2
+
3
+ export const initState = ({menu}) => {
4
+ const count = keys(menu);
5
+
6
+ return {
7
+ command: 'hide',
8
+ index: -1,
9
+ count,
10
+ position: {
11
+ left: 0,
12
+ top: 20,
13
+ },
14
+ };
15
+ };
package/package.json CHANGED
@@ -1,11 +1,11 @@
1
1
  {
2
2
  "name": "aleman",
3
- "version": "1.0.16",
3
+ "version": "1.1.0",
4
4
  "type": "module",
5
5
  "author": "coderaiser <mnemonic.enemy@gmail.com> (https://github.com/coderaiser)",
6
6
  "description": "🐊Putout-based framework for web",
7
7
  "homepage": "https://github.com/putoutjs/aleman#readme",
8
- "main": "lib/aleman/aleman.js",
8
+ "main": "aleman/index.js",
9
9
  "release": false,
10
10
  "tag": false,
11
11
  "changelog": false,
@@ -13,10 +13,6 @@
13
13
  "type": "git",
14
14
  "url": "git+https://github.com/coderaiser/putout.git"
15
15
  },
16
- "imports": {
17
- "#test": "./test/test.js",
18
- "#rules": "./lib/rules/index.js"
19
- },
20
16
  "exports": {
21
17
  "./menu": "./menu/menu.js"
22
18
  },
@@ -32,6 +28,7 @@
32
28
  },
33
29
  "dependencies": {
34
30
  "@putout/processor-html": "^14.0.2",
31
+ "fullstore": "^3.0.0",
35
32
  "html-escaper": "^3.0.3",
36
33
  "once": "^1.4.0",
37
34
  "putout": "^40.5.1"
@@ -1 +0,0 @@
1
- <button data-name="start">world</button>
File without changes
@@ -1 +0,0 @@
1
- <button data-name="stop">world</button>
@@ -1,39 +0,0 @@
1
- export const name = 'input';
2
- export const events = [
3
- 'keyup',
4
- 'change',
5
- ];
6
-
7
- export const filter = ({event}) => {
8
- const {key} = event;
9
- const keys = [
10
- 'Shift',
11
- 'Meta',
12
- 'ArrowLeft',
13
- 'ArrowRight',
14
- ];
15
-
16
- return !keys.includes(key);
17
- };
18
-
19
- export const listener = ({render, event, element}) => {
20
- const {key} = event;
21
- let {value} = element;
22
-
23
- if (isTextSelected(element) && key === 'Backspace')
24
- value = '';
25
-
26
- render('set-value', {
27
- name: 'value',
28
- value,
29
- });
30
-
31
- element.focus();
32
- };
33
-
34
- function isTextSelected(input) {
35
- if (!input.value)
36
- return false;
37
-
38
- return !input.selectionStart && input.selectionEnd === input.value.length;
39
- }
@@ -1,7 +0,0 @@
1
- export const name = 'start';
2
- export const events = ['click'];
3
- export const listener = ({render}) => {
4
- return render('remove-button', {
5
- name: 'start',
6
- });
7
- };
@@ -1,7 +0,0 @@
1
- export const name = 'stop';
2
- export const events = ['click'];
3
- export const listener = ({render}) => {
4
- render('remove-button', {
5
- name: 'stop',
6
- });
7
- };
@@ -1,27 +0,0 @@
1
- import {menu} from '../menu/menu.js';
2
- import {hideMenu} from '../globals/menu/menu.js';
3
-
4
- export const name = 'menu';
5
- export const events = ['click'];
6
- export const listener = ({event, render, element, state}) => {
7
- const index = element.index ?? -1;
8
-
9
- const menuItemElement = document.elementFromPoint(event.clientX, event.clientY);
10
- const name = menuItemElement.textContent.trim();
11
- const fn = menu[name];
12
-
13
- fn();
14
-
15
- hideMenu({
16
- render,
17
- state,
18
- });
19
-
20
- render('unselect', {
21
- index: index - 1,
22
- });
23
-
24
- render('select', {
25
- index,
26
- });
27
- };
@@ -1,6 +0,0 @@
1
- export const name = 'menu';
2
- export const events = ['mouseenter'];
3
- export const listener = ({render, storage}) => {
4
- storage.set('index', -1);
5
- render('unselect-all');
6
- };
@@ -1,12 +0,0 @@
1
- import {menu} from '../menu/menu.js';
2
-
3
- export const name = 'menu-toggler';
4
- export const events = ['click'];
5
- export const listener = ({render, element}) => {
6
- const command = element.command === 'show' ? 'hide' : 'show';
7
-
8
- render(['build-menu', 'menu'], {
9
- command,
10
- menu,
11
- });
12
- };
@@ -1,116 +0,0 @@
1
- const isFn = (a) => typeof a === 'function';
2
- const {addEventListener} = globalThis.document || {};
3
-
4
- export function addGlobalKeyListener({render, state, keys, storage}) {
5
- const listeners = {};
6
-
7
- for (const {key, listener, filter} of keys) {
8
- listeners[key] = createListener({
9
- name: 'document',
10
- filter,
11
- render,
12
- listener,
13
- storage,
14
- state,
15
- });
16
- }
17
-
18
- addEventListener('keydown', (event) => {
19
- listeners[event.key]?.(event);
20
- });
21
- }
22
-
23
- export function addGlobalListeners({render, state, globals, storage}) {
24
- for (const {events, listener, filter} of globals) {
25
- for (const event of events) {
26
- addEventListener(event, createListener({
27
- filter,
28
- name: 'document',
29
- render,
30
- listener,
31
- storage,
32
- state,
33
- }));
34
- }
35
- }
36
- }
37
-
38
- const success = () => true;
39
-
40
- const createListener = ({name, filter = success, state, render, listener, storage}) => (event) => {
41
- const is = filter({
42
- event,
43
- state,
44
- });
45
-
46
- if (!is)
47
- return;
48
-
49
- listener({
50
- render: render(name),
51
- event,
52
- element: createElement(name, storage),
53
- state,
54
- storage,
55
- });
56
- };
57
-
58
- export function addListeners({render, addons, storage, state}) {
59
- for (const {name, events, listener, filter} of addons) {
60
- for (const event of events) {
61
- const element = document.querySelector(`[data-name='${name}']`);
62
-
63
- if (!element)
64
- continue;
65
-
66
- element.addEventListener(event, createListener({
67
- name,
68
- render,
69
- listener,
70
- filter,
71
- storage,
72
- state,
73
- }));
74
- }
75
- }
76
- }
77
-
78
- const createSet = (name, storage) => (target, key, value) => {
79
- const element = document.querySelector(`[data-name='${name}']`);
80
-
81
- if (!element) {
82
- storage.set(key, value);
83
- return true;
84
- }
85
-
86
- element[key] = value;
87
-
88
- return true;
89
- };
90
-
91
- const createGet = (name, storage) => (target, key) => {
92
- const element = document.querySelector(`[data-name='${name}']`);
93
-
94
- if (!element)
95
- return storage.get(key);
96
-
97
- const result = element[key];
98
-
99
- if (!result)
100
- return element.getAttribute(key) || '';
101
-
102
- if (isFn(result))
103
- return result.bind(element);
104
-
105
- return result;
106
- };
107
-
108
- const createElement = (name, storage) => {
109
- const get = createGet(name, storage);
110
- const set = createSet(name, storage);
111
-
112
- return new Proxy({}, {
113
- get,
114
- set,
115
- });
116
- };
@@ -1,47 +0,0 @@
1
- import {
2
- addListeners,
3
- addGlobalListeners,
4
- addGlobalKeyListener,
5
- } from './add-listeners.js';
6
- import {createRender} from './render.js';
7
-
8
- const isKey = ({key}) => key;
9
- const notKey = ({key}) => !key;
10
-
11
- export const hydrate = ({element, rules, addons, globals, state = {}}) => {
12
- element = element || document.querySelector('[data-name="hydrate"]') || document.body;
13
- const html = `<section>${element.innerHTML}</section>`;
14
- const storage = new Map();
15
-
16
- const render = createRender(html, {
17
- rules,
18
- addons,
19
- element,
20
- storage,
21
- state,
22
- });
23
-
24
- addListeners({
25
- render,
26
- addons,
27
- storage,
28
- state,
29
- });
30
-
31
- const keys = globals.filter(isKey);
32
- const other = globals.filter(notKey);
33
-
34
- addGlobalListeners({
35
- render,
36
- globals: other,
37
- storage,
38
- state,
39
- });
40
-
41
- addGlobalKeyListener({
42
- render,
43
- keys,
44
- storage,
45
- state,
46
- });
47
- };
@@ -1,5 +0,0 @@
1
- document.addEventListener('DOMContentLoaded', async function load() {
2
- const {createMenu} = await import('../main.js');
3
- await createMenu();
4
- document.removeEventListener('DOMContentLoaded', load);
5
- });
@@ -1,107 +0,0 @@
1
- import {
2
- parse,
3
- transform,
4
- print,
5
- findPlaces,
6
- } from 'putout';
7
- import {branch, merge} from '@putout/processor-html';
8
- import {escape} from 'html-escaper';
9
- import {addListeners} from './add-listeners.js';
10
-
11
- const {isArray} = Array;
12
- const maybeArray = (a) => isArray(a) ? a : [a];
13
- const {assign, entries} = Object;
14
-
15
- export const createRender = (html, {headless, state, storage, rules, addons, element}) => {
16
- const {source} = branch(html)[0];
17
- const ast = parse(source);
18
-
19
- return function render(elementName = 'document') {
20
- return (names, options = {}) => {
21
- assign(state, {
22
- [elementName]: options,
23
- });
24
-
25
- assign(options, {
26
- escape,
27
- });
28
-
29
- const plugins = [];
30
- const currentRules = {};
31
-
32
- for (const [name, rule] of entries(rules)) {
33
- for (const currentName of maybeArray(names)) {
34
- if (name === currentName) {
35
- plugins.push([name, rule]);
36
- currentRules[name] = ['on', options];
37
- }
38
- }
39
- }
40
-
41
- const places = findPlaces(ast, source, {
42
- rules: currentRules,
43
- plugins,
44
- });
45
-
46
- if (!places.length) {
47
- restoreState({
48
- state,
49
- element,
50
- storage,
51
- });
52
- return;
53
- }
54
-
55
- transform(ast, '', {
56
- rules: currentRules,
57
- plugins,
58
- });
59
-
60
- const code = print(ast, {
61
- printer: ['putout', {
62
- format: {
63
- newline: '',
64
- endOfFile: '',
65
- },
66
- }],
67
- });
68
-
69
- const prefix = '<section>';
70
- const suffix = '<\\section>';
71
-
72
- element.innerHTML = merge('', [code]).slice(prefix.length, -suffix.length);
73
-
74
- if (headless)
75
- return;
76
-
77
- addListeners({
78
- render,
79
- addons,
80
- storage,
81
- state,
82
- });
83
-
84
- restoreState({
85
- state,
86
- element,
87
- storage,
88
- });
89
- };
90
- };
91
- };
92
-
93
- function restoreState({state, element, storage}) {
94
- for (const [name, options] of entries(state)) {
95
- const el = element.querySelector(`[data-name='${name}']`);
96
-
97
- if (!el && name === 'document')
98
- for (const [key, value] of entries(options)) {
99
- storage.set(key, value);
100
- }
101
-
102
- if (!el)
103
- continue;
104
-
105
- assign(el, options);
106
- }
107
- }
@@ -1,21 +0,0 @@
1
- import {
2
- hideMenu,
3
- filter as menuFilter,
4
- } from '../menu/menu.js';
5
-
6
- export const events = ['click'];
7
- export const filter = ({event, state}) => {
8
- if (!menuFilter({state}))
9
- return false;
10
-
11
- const {target} = event;
12
-
13
- return target.dataset.name !== 'menu-toggler';
14
- };
15
-
16
- export const listener = ({render, state}) => {
17
- hideMenu({
18
- render,
19
- state,
20
- });
21
- };
@@ -1,18 +0,0 @@
1
- import {showMenu} from '../menu/menu.js';
2
-
3
- export const events = [
4
- 'contextmenu',
5
- ];
6
-
7
- export const listener = ({render, state, event}) => {
8
- event.preventDefault();
9
- showMenu({
10
- render,
11
- state,
12
- });
13
-
14
- render('set-position', {
15
- left: event.clientX,
16
- top: event.clientY - 14,
17
- });
18
- };
@@ -1,21 +0,0 @@
1
- import {menu} from '../../menu/menu.js';
2
- import {select} from './menu.js';
3
-
4
- const {keys} = Object;
5
-
6
- export const key = 'ArrowDown';
7
-
8
- export {filter} from './menu.js';
9
-
10
- export const listener = ({render, element}) => {
11
- let index = element.index ?? -1;
12
- const n = keys(menu).length - 1;
13
-
14
- if (index < n)
15
- ++index;
16
-
17
- select({
18
- render,
19
- index,
20
- });
21
- };
@@ -1,33 +0,0 @@
1
- import {menu} from '../../menu/menu.js';
2
- import {hideMenu, select} from './menu.js';
3
-
4
- const {values} = Object;
5
-
6
- export const key = 'Enter';
7
-
8
- export {filter} from './menu.js';
9
-
10
- export const listener = ({render, element, state}) => {
11
- let index = element.index ?? -1;
12
-
13
- run({
14
- index,
15
- render,
16
- state,
17
- });
18
- index = -1;
19
-
20
- select({
21
- render,
22
- index,
23
- });
24
- };
25
-
26
- function run({index, render, state}) {
27
- const fn = values(menu)[index];
28
- fn();
29
- hideMenu({
30
- render,
31
- state,
32
- });
33
- }
@@ -1,19 +0,0 @@
1
- import {hideMenu, select} from './menu.js';
2
-
3
- export const key = 'Escape';
4
-
5
- export {filter} from './menu.js';
6
-
7
- export const listener = ({render, state}) => {
8
- const index = -1;
9
-
10
- hideMenu({
11
- render,
12
- state,
13
- });
14
-
15
- select({
16
- render,
17
- index,
18
- });
19
- };
@@ -1,27 +0,0 @@
1
- import {select, showMenu} from './menu.js';
2
-
3
- export const key = 'F9';
4
-
5
- export const filter = ({state}) => {
6
- const {command} = state['menu-toggler'];
7
- return command !== 'show';
8
- };
9
-
10
- export const listener = ({render, state}) => {
11
- const index = -1;
12
-
13
- showMenu({
14
- render,
15
- state,
16
- });
17
-
18
- select({
19
- render,
20
- index,
21
- });
22
-
23
- render('set-position', {
24
- left: 0,
25
- top: 20,
26
- });
27
- };