pawajs 1.4.15 → 1.4.17
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.md +2 -1
- package/README.md +8 -6
- package/index.js +4 -0
- package/package.json +1 -1
- package/pawaElement.js +7 -0
- package/power.js +226 -217
package/CHANGELOG.md
CHANGED
|
@@ -5,4 +5,5 @@ CHANGELOG.md
|
|
|
5
5
|
+ version 1.4.7 - 1.4.10 solving resuming issue when wrapping with template
|
|
6
6
|
+ version 1.4.11 - added more event modifiers
|
|
7
7
|
+ version 1.4.12 - fixed pluginsMap pawaAttribute to pawa-ssr 1.3.3
|
|
8
|
-
+ version 1.4.13 - 1.4.
|
|
8
|
+
+ version 1.4.13 - 1.4.16 fixed issues for resuming component
|
|
9
|
+
+ version 1.4.18 fixed issue with component inside template and added event modifiers
|
package/README.md
CHANGED
|
@@ -5,7 +5,7 @@ pawajs - power the web (reactivity and html runtime)
|
|
|
5
5
|
|
|
6
6
|
**A lightweight and reactive JavaScript library for building modern web interfaces with a simple, declarative syntax.**
|
|
7
7
|
|
|
8
|
-
PawaJS is a JavaScript library designed for building dynamic user interfaces. It combines a component-based architecture and progressive enhancement with a powerful reactivity system no v-dom. Its intuitive, directive-based templating feels familiar and makes it easy to create interactive applications, from simple widgets to complex single-page apps. With built-in support for server-side rendering, PawaJS is equipped for performance and scalability.
|
|
8
|
+
PawaJS (reactive web runtime) is a JavaScript library designed for building dynamic user interfaces. It combines a component-based architecture and progressive enhancement with a powerful reactivity system no v-dom. Its intuitive, directive-based templating feels familiar and makes it easy to create interactive applications, from simple widgets to complex single-page apps. With built-in support for server-side rendering using pawa-ssr (server rendering runtime) and pawajs-continue (continuous rendering), PawaJS is equipped for performance and scalability.
|
|
9
9
|
|
|
10
10
|
🌐 **Website:** [pawajs.vercel.app](https://pawajs.vercel.app)
|
|
11
11
|
|
|
@@ -15,7 +15,7 @@ PawaJS is a JavaScript library designed for building dynamic user interfaces. It
|
|
|
15
15
|
|
|
16
16
|
- **Declarative Rendering:** Use a clean, HTML-based template syntax with powerful directives (`if`, `for-each`, `on-event`, etc.) to describe your UI.
|
|
17
17
|
- **Reactive State Management:** Effortlessly create reactive state that automatically updates the DOM when it changes using the `$state` utility.
|
|
18
|
-
- **Component-Based Architecture:** Build encapsulated components that manage their own state, making your code more reusable and maintainable.
|
|
18
|
+
- **Component-Based Architecture:** Build encapsulated components with just js function that manage their own state, making your code more reusable and maintainable.
|
|
19
19
|
- **Async Components:** First-class support for asynchronous components, allowing you to fetch data directly within your component definition.
|
|
20
20
|
- **Efficient List Rendering:** Render lists of data with the `for-each` directive, including support for keyed updates for optimal performance.
|
|
21
21
|
- **Lifecycle Hooks:** Tap into a component's lifecycle with `mount` and `unmount` directives, or the `runEffect` hook for more complex side effects.
|
|
@@ -39,7 +39,7 @@ CDN
|
|
|
39
39
|
</head>
|
|
40
40
|
<body>
|
|
41
41
|
<div id="app"></div>
|
|
42
|
-
<script type="module" src="https://cdn.jsdelivr.net/npm/pawajs@
|
|
42
|
+
<script type="module" src="https://cdn.jsdelivr.net/npm/pawajs@latestVersion/index.js"></script>
|
|
43
43
|
<script type="module">
|
|
44
44
|
window.$pawa.pawaStartApp(document.getElementById('app'));
|
|
45
45
|
</script>
|
|
@@ -276,18 +276,20 @@ For rendering lists from an array. Use `for-key` to give each element a unique i
|
|
|
276
276
|
</ul>
|
|
277
277
|
```
|
|
278
278
|
|
|
279
|
-
#### `on-<event
|
|
279
|
+
#### `on-<event>..chainModifiers`
|
|
280
|
+
modifiers - 'self','prevent','once','capture' etc
|
|
280
281
|
For handling DOM events.
|
|
281
282
|
|
|
282
283
|
```html
|
|
283
284
|
<button on-click="addTodo()">Add Todo</button>
|
|
284
285
|
<input on-input="newTodoText.value = e.target.value" />
|
|
285
286
|
```
|
|
286
|
-
#### `out-<event
|
|
287
|
+
#### `out-<event>.chainModifiers`
|
|
288
|
+
modifiers - 'self','prevent','once','capture' etc
|
|
287
289
|
For handling DOM events.
|
|
288
290
|
|
|
289
291
|
```html
|
|
290
|
-
<button out-click="console.log('outside')">Add Todo</button>
|
|
292
|
+
<button out-click.once="console.log('outside')">Add Todo</button>
|
|
291
293
|
```
|
|
292
294
|
|
|
293
295
|
### Component Props
|
package/index.js
CHANGED
|
@@ -887,6 +887,7 @@ const component = (el, resume = false, attr, notRender, stopResume) => {
|
|
|
887
887
|
}
|
|
888
888
|
} else if (isComment.nodeType === 1) {
|
|
889
889
|
if( !isComment.hasAttribute('p:store')){
|
|
890
|
+
isComment.setAttribute('by',id)
|
|
890
891
|
children.push(isComment)
|
|
891
892
|
}
|
|
892
893
|
getEndComment(isComment)
|
|
@@ -1226,6 +1227,9 @@ export const render = (el, contexts = {}, notRender, isName) => {
|
|
|
1226
1227
|
const number = { notRender: null, index: null }
|
|
1227
1228
|
let isIndex=0
|
|
1228
1229
|
Array.from(el.children).forEach((child, index) => {
|
|
1230
|
+
if (child.hasAttribute('p:store')) {
|
|
1231
|
+
return
|
|
1232
|
+
}
|
|
1229
1233
|
number.index = isIndex
|
|
1230
1234
|
isIndex++
|
|
1231
1235
|
if (number.notRender !== null && isIndex <= number.notRender) return
|
package/package.json
CHANGED
package/pawaElement.js
CHANGED
|
@@ -323,6 +323,13 @@ export class PawaElement {
|
|
|
323
323
|
return
|
|
324
324
|
}
|
|
325
325
|
if (this._componentName) {
|
|
326
|
+
const hasPC=this._el.hasAttribute('p:c')
|
|
327
|
+
if (hasPC) {
|
|
328
|
+
Array.from(this._el.attributes).forEach(attr => {
|
|
329
|
+
if (attr.name.startsWith('c-') || attr.name === 'by') return
|
|
330
|
+
this._attributes.push({name:attr.name,value:attr.value})
|
|
331
|
+
});
|
|
332
|
+
}
|
|
326
333
|
const pawaAttribute=getPawaAttributes()
|
|
327
334
|
const dependAttribute=getDependentAttribute()
|
|
328
335
|
this._attributes.forEach((attr) => {
|
package/power.js
CHANGED
|
@@ -7,6 +7,123 @@ import {normal_If} from './normal/If.js'
|
|
|
7
7
|
import {normal_For} from './normal/For.js'
|
|
8
8
|
import {resumer} from './resumer.js'
|
|
9
9
|
import { normal_key } from './normal/Key.js';
|
|
10
|
+
|
|
11
|
+
// Shared helper to check common event modifiers
|
|
12
|
+
const checkCommonModifiers = (e, modifiers) => {
|
|
13
|
+
// Mouse buttons
|
|
14
|
+
if (modifiers.has('left') && 'button' in e && e.button !== 0) return false;
|
|
15
|
+
if (modifiers.has('middle') && 'button' in e && e.button !== 1) return false;
|
|
16
|
+
if (modifiers.has('right') && 'button' in e && e.button !== 2) return false;
|
|
17
|
+
// System keys
|
|
18
|
+
if (modifiers.has('ctrl') && !e.ctrlKey) return false;
|
|
19
|
+
if (modifiers.has('alt') && !e.altKey) return false;
|
|
20
|
+
if (modifiers.has('shift') && !e.shiftKey) return false;
|
|
21
|
+
if (modifiers.has('meta') && !e.metaKey) return false;
|
|
22
|
+
// Exact modifier
|
|
23
|
+
if (modifiers.has('exact')) {
|
|
24
|
+
if (e.ctrlKey && !modifiers.has('ctrl')) return false;
|
|
25
|
+
if (e.altKey && !modifiers.has('alt')) return false;
|
|
26
|
+
if (e.shiftKey && !modifiers.has('shift')) return false;
|
|
27
|
+
if (e.metaKey && !modifiers.has('meta')) return false;
|
|
28
|
+
}
|
|
29
|
+
// Wheel direction
|
|
30
|
+
if (modifiers.has('wheel-up') && e.deltaY >= 0) return false;
|
|
31
|
+
if (modifiers.has('wheel-down') && e.deltaY <= 0) return false;
|
|
32
|
+
if (modifiers.has('wheel-left') && e.deltaX >= 0) return false;
|
|
33
|
+
if (modifiers.has('wheel-right') && e.deltaX <= 0) return false;
|
|
34
|
+
return true;
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
// Shared helper to check key modifiers
|
|
38
|
+
const checkKeyModifiers = (e, modifiers, eventType) => {
|
|
39
|
+
if (!eventType.startsWith('key')) return true;
|
|
40
|
+
|
|
41
|
+
// Separate system modifiers from actual key modifiers
|
|
42
|
+
const systemMods = ['ctrl', 'alt', 'shift', 'meta'];
|
|
43
|
+
const keyAliases = {
|
|
44
|
+
'enter': 'Enter', 'tab': 'Tab', 'delete': ['Backspace', 'Delete'],
|
|
45
|
+
'esc': 'Escape', 'space': ' ', 'up': 'ArrowUp', 'down': 'ArrowDown',
|
|
46
|
+
'left': 'ArrowLeft', 'right': 'ArrowRight', 'home': 'Home',
|
|
47
|
+
'end': 'End', 'pageup': 'PageUp', 'pagedown': 'PageDown'
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
// Extract key-specific modifiers (the actual key to press)
|
|
51
|
+
let targetKey = null;
|
|
52
|
+
let keyModifiers = [];
|
|
53
|
+
|
|
54
|
+
for (const mod of modifiers) {
|
|
55
|
+
if (keyAliases[mod]) {
|
|
56
|
+
targetKey = mod;
|
|
57
|
+
} else if (!systemMods.includes(mod) && mod !== 'exact') {
|
|
58
|
+
// For single letters like 's', 'a', etc.
|
|
59
|
+
targetKey = mod;
|
|
60
|
+
} else if (systemMods.includes(mod)) {
|
|
61
|
+
keyModifiers.push(mod);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// Check system modifiers (Ctrl, Alt, etc.)
|
|
66
|
+
if (modifiers.has('ctrl') && !e.ctrlKey) return false;
|
|
67
|
+
if (modifiers.has('alt') && !e.altKey) return false;
|
|
68
|
+
if (modifiers.has('shift') && !e.shiftKey) return false;
|
|
69
|
+
if (modifiers.has('meta') && !e.metaKey) return false;
|
|
70
|
+
|
|
71
|
+
// Check exact modifier combination
|
|
72
|
+
if (modifiers.has('exact')) {
|
|
73
|
+
if (e.ctrlKey && !modifiers.has('ctrl')) return false;
|
|
74
|
+
if (e.altKey && !modifiers.has('alt')) return false;
|
|
75
|
+
if (e.shiftKey && !modifiers.has('shift')) return false;
|
|
76
|
+
if (e.metaKey && !modifiers.has('meta')) return false;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// If there's a target key to check
|
|
80
|
+
if (targetKey) {
|
|
81
|
+
const expectedKey = keyAliases[targetKey] ||
|
|
82
|
+
(targetKey.length === 1 ? targetKey : null);
|
|
83
|
+
|
|
84
|
+
if (expectedKey) {
|
|
85
|
+
if (Array.isArray(expectedKey)) {
|
|
86
|
+
return expectedKey.includes(e.key);
|
|
87
|
+
}
|
|
88
|
+
return e.key === expectedKey;
|
|
89
|
+
}
|
|
90
|
+
// For single letters like 's'
|
|
91
|
+
if (targetKey.length === 1) {
|
|
92
|
+
return e.key.toLowerCase() === targetKey.toLowerCase() ||
|
|
93
|
+
e.code === `Key${targetKey.toUpperCase()}`;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// If no specific key modifier, return true (system modifiers already checked)
|
|
98
|
+
return true;
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
// Shared helper to execute event with debounce/throttle/error handling
|
|
102
|
+
const processEventExecution = (el, attrName, modifiers, callback, eventType, directiveName) => {
|
|
103
|
+
const execute = () => {
|
|
104
|
+
try { callback(); }
|
|
105
|
+
catch (error) { setPawaDevError({ message: `Error from ${directiveName}-${eventType} directive ${error.message}`, error, template: el._template }); }
|
|
106
|
+
};
|
|
107
|
+
if (!el._eventTimers) el._eventTimers = {};
|
|
108
|
+
const delay = parseInt([...modifiers].find(m => /^\d+$/.test(m)) || '300');
|
|
109
|
+
if (modifiers.has('debounce')) {
|
|
110
|
+
const timerKey = `${attrName}_debounce`;
|
|
111
|
+
clearTimeout(el._eventTimers[timerKey]);
|
|
112
|
+
el._eventTimers[timerKey] = setTimeout(execute, delay);
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
if (modifiers.has('throttle')) {
|
|
116
|
+
const timerKey = `${attrName}_throttle_last`;
|
|
117
|
+
const now = Date.now();
|
|
118
|
+
if (!el._eventTimers[timerKey] || now - el._eventTimers[timerKey] >= delay) {
|
|
119
|
+
el._eventTimers[timerKey] = now;
|
|
120
|
+
execute();
|
|
121
|
+
}
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
execute();
|
|
125
|
+
};
|
|
126
|
+
|
|
10
127
|
export const If = (el, attr, stateContext,resume=false,notRender,stopResume) => {
|
|
11
128
|
el._checkStatic()
|
|
12
129
|
if (el._running || checkKeywordsExistence(el._staticContext,attr.value)) {
|
|
@@ -135,10 +252,11 @@ export const Switch = (el, attr, stateContext,resume=false,notRender,stopResume)
|
|
|
135
252
|
|
|
136
253
|
export const event = (el, attr, stateContext) => {
|
|
137
254
|
el._checkStatic()
|
|
138
|
-
if (el._running || checkKeywordsExistence(el._staticContext,attr.value)) {
|
|
255
|
+
if (el._running || checkKeywordsExistence(el._staticContext, attr.value)) {
|
|
139
256
|
return
|
|
140
257
|
}
|
|
141
|
-
|
|
258
|
+
|
|
259
|
+
const directive = attr.name.substring(3); // 'on-click.prevent' → 'click.prevent'
|
|
142
260
|
const parts = directive.split('.');
|
|
143
261
|
const eventType = parts[0];
|
|
144
262
|
const modifiers = new Set(parts.slice(1));
|
|
@@ -150,81 +268,36 @@ export const event = (el, attr, stateContext) => {
|
|
|
150
268
|
return path.split('.').reduce((acc, key) => acc?.[key], obj);
|
|
151
269
|
};
|
|
152
270
|
const values = keys.map((key) => resolvePath(key, context));
|
|
271
|
+
|
|
153
272
|
const func = new Function('e', ...keys, `
|
|
154
273
|
try{
|
|
155
|
-
|
|
274
|
+
${attr.value}
|
|
156
275
|
}catch(error){
|
|
157
|
-
|
|
158
|
-
|
|
276
|
+
console.error(error.message, error.stack)
|
|
277
|
+
__pawaDev.setError({el: e.target, msg: error.message, stack: error.stack, directives: 'on-event'})
|
|
159
278
|
}
|
|
160
279
|
`)
|
|
161
280
|
|
|
162
281
|
const handler = (e) => {
|
|
163
|
-
|
|
282
|
+
if (!checkCommonModifiers(e, modifiers)) return;
|
|
283
|
+
if (!checkKeyModifiers(e, modifiers, eventType)) return;
|
|
284
|
+
|
|
285
|
+
// ========== TARGET MODIFIERS ==========
|
|
164
286
|
if (modifiers.has('self') && e.target !== el) return;
|
|
165
|
-
if (modifiers.has('
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
if (modifiers.has('
|
|
169
|
-
if (modifiers.has('
|
|
170
|
-
if (modifiers.has('
|
|
171
|
-
if (modifiers.has('
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
if (e.altKey && !modifiers.has('alt')) return;
|
|
175
|
-
if (e.shiftKey && !modifiers.has('shift')) return;
|
|
176
|
-
if (e.metaKey && !modifiers.has('meta')) return;
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
// Key modifiers
|
|
180
|
-
if (eventType.startsWith('key')) {
|
|
181
|
-
const keyAlias = {
|
|
182
|
-
'enter': 'Enter',
|
|
183
|
-
'tab': 'Tab',
|
|
184
|
-
'delete': ['Backspace', 'Delete'],
|
|
185
|
-
'esc': 'Escape',
|
|
186
|
-
'space': ' ',
|
|
187
|
-
'up': 'ArrowUp',
|
|
188
|
-
'down': 'ArrowDown',
|
|
189
|
-
'left': 'ArrowLeft',
|
|
190
|
-
'right': 'ArrowRight'
|
|
191
|
-
};
|
|
192
|
-
|
|
193
|
-
let shouldRun = false;
|
|
194
|
-
let hasKeyModifier = false;
|
|
195
|
-
for (const mod of modifiers) {
|
|
196
|
-
if (keyAlias[mod]) {
|
|
197
|
-
hasKeyModifier = true;
|
|
198
|
-
const expectedKey = keyAlias[mod];
|
|
199
|
-
if (Array.isArray(expectedKey)) {
|
|
200
|
-
if (expectedKey.includes(e.key)) {
|
|
201
|
-
shouldRun = true;
|
|
202
|
-
break;
|
|
203
|
-
}
|
|
204
|
-
} else if (e.key === expectedKey) {
|
|
205
|
-
shouldRun = true;
|
|
206
|
-
break;
|
|
207
|
-
}
|
|
208
|
-
}
|
|
209
|
-
}
|
|
210
|
-
if (hasKeyModifier && !shouldRun) {
|
|
211
|
-
return;
|
|
212
|
-
}
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
// Action modifiers
|
|
287
|
+
if (modifiers.has('not-self') && e.target === el) return;
|
|
288
|
+
|
|
289
|
+
// ========== FORM MODIFIERS ==========
|
|
290
|
+
if (modifiers.has('dirty') && !e.target.value) return;
|
|
291
|
+
if (modifiers.has('pristine') && e.target.value) return;
|
|
292
|
+
if (modifiers.has('valid') && !e.target.checkValidity()) return;
|
|
293
|
+
if (modifiers.has('invalid') && e.target.checkValidity()) return;
|
|
294
|
+
|
|
295
|
+
// ========== ACTION MODIFIERS ==========
|
|
216
296
|
if (modifiers.has('prevent')) e.preventDefault();
|
|
217
297
|
if (modifiers.has('stop')) e.stopPropagation();
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
} catch (error) {
|
|
222
|
-
setPawaDevError({
|
|
223
|
-
message: `Error from on-${eventType} directive ${error.message}`,
|
|
224
|
-
error: error,
|
|
225
|
-
template: el._template
|
|
226
|
-
})
|
|
227
|
-
}
|
|
298
|
+
|
|
299
|
+
// ========== EXECUTION ==========
|
|
300
|
+
processEventExecution(el, attr.name, modifiers, () => func(e, ...values), eventType, 'on');
|
|
228
301
|
};
|
|
229
302
|
|
|
230
303
|
const options = {
|
|
@@ -233,60 +306,52 @@ export const event = (el, attr, stateContext) => {
|
|
|
233
306
|
passive: modifiers.has('passive')
|
|
234
307
|
};
|
|
235
308
|
|
|
236
|
-
|
|
309
|
+
const target = modifiers.has('window') ? window : el;
|
|
310
|
+
target.addEventListener(eventType, handler, options);
|
|
311
|
+
|
|
312
|
+
el._MountFunctions.push(() => target.addEventListener(eventType, handler, options));
|
|
313
|
+
el._setUnMount(() => {
|
|
314
|
+
target.removeEventListener(eventType, handler, options);
|
|
315
|
+
});
|
|
237
316
|
}
|
|
238
317
|
|
|
318
|
+
const createBoundCallback = (el, code) => {
|
|
319
|
+
const keys = Object.keys(el._context);
|
|
320
|
+
const resolvePath = (path, obj) => path.split('.').reduce((acc, key) => acc?.[key], obj);
|
|
321
|
+
const values = keys.map((key) => resolvePath(key, el._context));
|
|
322
|
+
const func = new Function(...keys, code);
|
|
323
|
+
return () => func(...values);
|
|
324
|
+
};
|
|
325
|
+
|
|
239
326
|
export const mountElement = (el, attr) => {
|
|
240
|
-
if (el._running)
|
|
241
|
-
return
|
|
242
|
-
}
|
|
327
|
+
if (el._running) return;
|
|
243
328
|
try {
|
|
244
|
-
const
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
};
|
|
248
|
-
const values = keys.map((key) => resolvePath(key, el._context));
|
|
249
|
-
const newFunc = new Function(...keys, `${attr.value}`)
|
|
250
|
-
const func = () => {
|
|
251
|
-
newFunc(...values)
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
el._MountFunctions.push(func)
|
|
255
|
-
el.removeAttribute(attr.name)
|
|
329
|
+
const func = createBoundCallback(el, attr.value);
|
|
330
|
+
el._MountFunctions.push(func);
|
|
331
|
+
el.removeAttribute(attr.name);
|
|
256
332
|
} catch (error) {
|
|
257
333
|
setPawaDevError({
|
|
258
334
|
message: `Error from Mount directive ${error.message}`,
|
|
259
335
|
error: error,
|
|
260
336
|
template: el._template
|
|
261
|
-
})
|
|
337
|
+
});
|
|
262
338
|
}
|
|
263
|
-
}
|
|
264
|
-
|
|
265
|
-
|
|
339
|
+
};
|
|
266
340
|
|
|
267
341
|
export const unMountElement = (el, attr) => {
|
|
268
|
-
if (el._running)
|
|
269
|
-
return
|
|
270
|
-
}
|
|
342
|
+
if (el._running) return;
|
|
271
343
|
try {
|
|
272
|
-
const
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
};
|
|
276
|
-
const values = keys.map((key) => resolvePath(key, el._context));
|
|
277
|
-
const func = () => {
|
|
278
|
-
new Function(...keys, `${attr.value}`)(...values)
|
|
279
|
-
}
|
|
280
|
-
el._unMountFunctions.push(func)
|
|
281
|
-
el.removeAttribute(attr.name)
|
|
344
|
+
const func = createBoundCallback(el, attr.value);
|
|
345
|
+
el._unMountFunctions.push(func);
|
|
346
|
+
el.removeAttribute(attr.name);
|
|
282
347
|
} catch (error) {
|
|
283
348
|
setPawaDevError({
|
|
284
349
|
message: `Error from UnMount directive ${error.message}`,
|
|
285
350
|
error: error,
|
|
286
351
|
template: el._template
|
|
287
|
-
})
|
|
352
|
+
});
|
|
288
353
|
}
|
|
289
|
-
}
|
|
354
|
+
};
|
|
290
355
|
|
|
291
356
|
export const For = (el, attr, stateContext,resume=false,notRender,stopResume) => {
|
|
292
357
|
el._checkStatic()
|
|
@@ -334,7 +399,12 @@ export const ref = (el, attr) => {
|
|
|
334
399
|
const values = keys.map((key) => resolvePath(key, el._context))
|
|
335
400
|
const returned=new Function('el', ...keys, `
|
|
336
401
|
try{
|
|
337
|
-
if(
|
|
402
|
+
if (typeof ${attr.value} === 'function') {
|
|
403
|
+
const cleanUp=${attr.value}(el)
|
|
404
|
+
if(typeof cleanUp === 'function'){
|
|
405
|
+
el._setUnMount(cleanUp)
|
|
406
|
+
}
|
|
407
|
+
}else if(Array.isArray(${attr.value}.value)){
|
|
338
408
|
${attr.value}.value.push(el)
|
|
339
409
|
}else if(typeof ${attr.value} === 'string'){
|
|
340
410
|
return {
|
|
@@ -399,10 +469,11 @@ export const States = (el, attr) => {
|
|
|
399
469
|
|
|
400
470
|
export const documentEvent = (el, attr) => {
|
|
401
471
|
el._checkStatic()
|
|
402
|
-
if (el._running || checkKeywordsExistence(el._staticContext,attr.value)) {
|
|
472
|
+
if (el._running || checkKeywordsExistence(el._staticContext, attr.value)) {
|
|
403
473
|
return
|
|
404
474
|
}
|
|
405
|
-
|
|
475
|
+
|
|
476
|
+
const directive = attr.name.substring(4); // 'out-click.prevent' → 'click.prevent'
|
|
406
477
|
const parts = directive.split('.');
|
|
407
478
|
const eventType = parts[0];
|
|
408
479
|
const modifiers = new Set(parts.slice(1));
|
|
@@ -414,80 +485,29 @@ export const documentEvent = (el, attr) => {
|
|
|
414
485
|
const resolvePath = (path, obj) => {
|
|
415
486
|
return path.split('.').reduce((acc, key) => acc?.[key], obj);
|
|
416
487
|
};
|
|
417
|
-
const func = new Function('e','$element', ...keys, `
|
|
488
|
+
const func = new Function('e', '$element', ...keys, `
|
|
418
489
|
try{
|
|
419
|
-
|
|
490
|
+
${attr.value}
|
|
420
491
|
}catch(error){
|
|
421
|
-
|
|
422
|
-
|
|
492
|
+
console.error(error.message, error.stack)
|
|
493
|
+
__pawaDev.setError({msg: error.message, stack: error.stack, directives: 'out-event'})
|
|
423
494
|
}`)
|
|
424
495
|
const values = keys.map((key) => resolvePath(key, el._context));
|
|
496
|
+
|
|
425
497
|
const handler = (e) => {
|
|
426
|
-
|
|
427
|
-
if (
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
if (modifiers.has('
|
|
431
|
-
if (modifiers.has('
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
if (modifiers.has('exact')) {
|
|
435
|
-
if (e.ctrlKey && !modifiers.has('ctrl')) return;
|
|
436
|
-
if (e.altKey && !modifiers.has('alt')) return;
|
|
437
|
-
if (e.shiftKey && !modifiers.has('shift')) return;
|
|
438
|
-
if (e.metaKey && !modifiers.has('meta')) return;
|
|
439
|
-
}
|
|
440
|
-
|
|
441
|
-
// Key modifiers
|
|
442
|
-
if (eventType.startsWith('key')) {
|
|
443
|
-
const keyAlias = {
|
|
444
|
-
'enter': 'Enter',
|
|
445
|
-
'tab': 'Tab',
|
|
446
|
-
'delete': ['Backspace', 'Delete'],
|
|
447
|
-
'esc': 'Escape',
|
|
448
|
-
'space': ' ',
|
|
449
|
-
'up': 'ArrowUp',
|
|
450
|
-
'down': 'ArrowDown',
|
|
451
|
-
'left': 'ArrowLeft',
|
|
452
|
-
'right': 'ArrowRight'
|
|
453
|
-
};
|
|
454
|
-
|
|
455
|
-
let shouldRun = false;
|
|
456
|
-
let hasKeyModifier = false;
|
|
457
|
-
for (const mod of modifiers) {
|
|
458
|
-
if (keyAlias[mod]) {
|
|
459
|
-
hasKeyModifier = true;
|
|
460
|
-
const expectedKey = keyAlias[mod];
|
|
461
|
-
if (Array.isArray(expectedKey)) {
|
|
462
|
-
if (expectedKey.includes(e.key)) {
|
|
463
|
-
shouldRun = true;
|
|
464
|
-
break;
|
|
465
|
-
}
|
|
466
|
-
} else if (e.key === expectedKey) {
|
|
467
|
-
shouldRun = true;
|
|
468
|
-
break;
|
|
469
|
-
}
|
|
470
|
-
}
|
|
471
|
-
}
|
|
472
|
-
if (hasKeyModifier && !shouldRun) {
|
|
473
|
-
return;
|
|
474
|
-
}
|
|
475
|
-
}
|
|
476
|
-
|
|
477
|
-
// Action modifiers
|
|
498
|
+
if (!checkCommonModifiers(e, modifiers)) return;
|
|
499
|
+
if (!checkKeyModifiers(e, modifiers, eventType)) return;
|
|
500
|
+
|
|
501
|
+
// ========== TARGET MODIFIERS ==========
|
|
502
|
+
if (modifiers.has('self') && (e.target === el || el.contains(e.target))) return;
|
|
503
|
+
if (modifiers.has('not-self') && e.target === el) return;
|
|
504
|
+
|
|
505
|
+
// ========== ACTION MODIFIERS ==========
|
|
478
506
|
if (modifiers.has('prevent')) e.preventDefault();
|
|
479
507
|
if (modifiers.has('stop')) e.stopPropagation();
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
func(e,$element, ...values)
|
|
484
|
-
} catch (error) {
|
|
485
|
-
setPawaDevError({
|
|
486
|
-
message: `Error from out-${eventType} directive ${error.message}`,
|
|
487
|
-
error: error,
|
|
488
|
-
template: el._template
|
|
489
|
-
})
|
|
490
|
-
}
|
|
508
|
+
|
|
509
|
+
// ========== EXECUTION ==========
|
|
510
|
+
processEventExecution(el, attr.name, modifiers, () => func(e, el, ...values), eventType, 'out');
|
|
491
511
|
}
|
|
492
512
|
|
|
493
513
|
const options = {
|
|
@@ -495,11 +515,11 @@ export const documentEvent = (el, attr) => {
|
|
|
495
515
|
once: modifiers.has('once'),
|
|
496
516
|
passive: modifiers.has('passive')
|
|
497
517
|
};
|
|
518
|
+
|
|
498
519
|
const target = modifiers.has('window') ? window : document;
|
|
499
520
|
el._MountFunctions.push(() => target.addEventListener(eventType, handler, options))
|
|
500
521
|
const unMount = () => target.removeEventListener(eventType, handler, options);
|
|
501
522
|
el._setUnMount(unMount)
|
|
502
|
-
|
|
503
523
|
}
|
|
504
524
|
export const exitTransition=(el,attr)=>{
|
|
505
525
|
if (el._running) {
|
|
@@ -520,52 +540,41 @@ if (el._running) {
|
|
|
520
540
|
}
|
|
521
541
|
el.removeAttribute(attr.name)
|
|
522
542
|
}
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
const
|
|
527
|
-
el.removeAttribute(attr.name)
|
|
528
|
-
const resolvePath = (path, obj) => {
|
|
529
|
-
return path.split('.').reduce((acc, key) => acc?.[key], obj);
|
|
530
|
-
};
|
|
531
|
-
const func = new Function( ...keys, `
|
|
532
|
-
try{
|
|
533
|
-
${attr.value}
|
|
534
|
-
}catch(error){
|
|
535
|
-
console.error(error.message,error.stack,'at ${attr.name}')
|
|
536
|
-
__pawaDev({msg:error.message,stack:error.stack,directives:'${attr.name}'})
|
|
537
|
-
}`)
|
|
538
|
-
const values = keys.map((key) => resolvePath(key, el._context));
|
|
539
|
-
const timeout=setTimeout(() => {
|
|
540
|
-
func(...values)
|
|
541
|
-
}, getTime);
|
|
542
|
-
el._setUnMount(()=>{
|
|
543
|
-
clearTimeout(timeout)
|
|
544
|
-
})
|
|
545
|
-
}
|
|
546
|
-
export const Every=(el,attr)=>{
|
|
547
|
-
if (el._running) return
|
|
548
|
-
const getTime=attr.name.match(/\[(.*?)\]/)[1]
|
|
549
|
-
el.removeAttribute(attr.name)
|
|
543
|
+
|
|
544
|
+
const createTimedExecutable = (el, attr, useInterval) => {
|
|
545
|
+
if (el._running) return;
|
|
546
|
+
const getTime = attr.name.match(/\[(.*?)\]/)[1];
|
|
550
547
|
const keys = Object.keys(el._context);
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
const func = new Function( ...keys, `
|
|
555
|
-
try{
|
|
556
|
-
${attr.value}
|
|
557
|
-
}catch(error){
|
|
558
|
-
console.error(error.message,error.stack,'at ${attr.name}')
|
|
559
|
-
__pawaDev({msg:error.message,stack:error.stack,directives:'${attr.name}'})
|
|
560
|
-
}`)
|
|
548
|
+
el.removeAttribute(attr.name);
|
|
549
|
+
|
|
550
|
+
const resolvePath = (path, obj) => path.split('.').reduce((acc, key) => acc?.[key], obj);
|
|
561
551
|
const values = keys.map((key) => resolvePath(key, el._context));
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
}
|
|
552
|
+
|
|
553
|
+
const func = new Function(...keys, `
|
|
554
|
+
try {
|
|
555
|
+
${attr.value}
|
|
556
|
+
} catch(error) {
|
|
557
|
+
console.error(error.message, error.stack, 'at ${attr.name}');
|
|
558
|
+
__pawaDev({msg: error.message, stack: error.stack, directives: '${attr.name}'});
|
|
559
|
+
}
|
|
560
|
+
`);
|
|
561
|
+
|
|
562
|
+
const execute = () => func(...values);
|
|
563
|
+
|
|
564
|
+
const timer = useInterval ? setInterval(execute, getTime) : setTimeout(execute, getTime);
|
|
565
|
+
const clear = useInterval ? clearInterval : clearTimeout;
|
|
566
|
+
|
|
567
|
+
el._setUnMount(() => clear(timer));
|
|
568
|
+
};
|
|
569
|
+
|
|
570
|
+
export const After = (el, attr) => {
|
|
571
|
+
createTimedExecutable(el, attr, false);
|
|
572
|
+
};
|
|
573
|
+
|
|
574
|
+
export const Every = (el, attr) => {
|
|
575
|
+
createTimedExecutable(el, attr, true);
|
|
576
|
+
};
|
|
577
|
+
|
|
569
578
|
export const Key = (el, attr, stateContext,resume=false,notRender,stopResume) => {
|
|
570
579
|
el._checkStatic()
|
|
571
580
|
if (el._running || checkKeywordsExistence(el._staticContext,attr.value)) {
|