pawajs 1.4.16 → 1.4.18

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 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.14 fixed issues for resuming component
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@1.2.0/cdn/index.js"></script>
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
@@ -336,6 +336,7 @@ let stateContext = {
336
336
  _template: '',
337
337
  _serializedData:{},
338
338
  _static: [],
339
+ _id:""
339
340
  }
340
341
 
341
342
  export const getCurrentContext = () => {
@@ -887,6 +888,7 @@ const component = (el, resume = false, attr, notRender, stopResume) => {
887
888
  }
888
889
  } else if (isComment.nodeType === 1) {
889
890
  if( !isComment.hasAttribute('p:store')){
891
+ isComment.setAttribute('by',id)
890
892
  children.push(isComment)
891
893
  }
892
894
  getEndComment(isComment)
@@ -1232,6 +1234,7 @@ export const render = (el, contexts = {}, notRender, isName) => {
1232
1234
  number.index = isIndex
1233
1235
  isIndex++
1234
1236
  if (number.notRender !== null && isIndex <= number.notRender) return
1237
+ if (child.hasAttribute('by'))return
1235
1238
  render(child, context, number, isName)
1236
1239
  })
1237
1240
  el._callMount()
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pawajs",
3
- "version": "1.4.16",
3
+ "version": "1.4.18",
4
4
  "type":"module",
5
5
  "description": "pawajs library (reactive web runtime) for easily building web ui, enhancing html element, micro frontend etc ",
6
6
  "main": "index.js",
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
- const directive = attr.name.substring(3); // from 'on-click.prevent' to 'click.prevent'
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
- ${attr.value}
274
+ ${attr.value}
156
275
  }catch(error){
157
- console.error(error.message,error.stack)
158
- __pawaDev.setError({el:e.target,msg:error.message,stack:error.stack,directives:'on-event'})
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
- // Early return modifiers
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('left') && 'button' in e && e.button !== 0) return;
166
- if (modifiers.has('middle') && 'button' in e && e.button !== 1) return;
167
- if (modifiers.has('right') && 'button' in e && e.button !== 2) return;
168
- if (modifiers.has('ctrl') && !e.ctrlKey) return;
169
- if (modifiers.has('alt') && !e.altKey) return;
170
- if (modifiers.has('shift') && !e.shiftKey) return;
171
- if (modifiers.has('meta') && !e.metaKey) return;
172
- if (modifiers.has('exact')) {
173
- if (e.ctrlKey && !modifiers.has('ctrl')) return;
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
- try {
220
- func(e, ...values)
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
- el.addEventListener(eventType, handler, options)
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 keys = Object.keys(el._context);
245
- const resolvePath = (path, obj) => {
246
- return path.split('.').reduce((acc, key) => acc?.[key], obj);
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 keys = Object.keys(el._context);
273
- const resolvePath = (path, obj) => {
274
- return path.split('.').reduce((acc, key) => acc?.[key], obj);
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(Array.isArray(${attr.value}.value)){
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
- const directive = attr.name.substring(4); // from 'out-click.prevent' to 'click.prevent'
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
- ${attr.value}
490
+ ${attr.value}
420
491
  }catch(error){
421
- console.error(error.message,error.stack)
422
- __pawaDev.setError({msg:error.message,stack:error.stack,directives:'out-event'})
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
- // Modifier checks
427
- if (modifiers.has('left') && 'button' in e && e.button !== 0) return;
428
- if (modifiers.has('middle') && 'button' in e && e.button !== 1) return;
429
- if (modifiers.has('right') && 'button' in e && e.button !== 2) return;
430
- if (modifiers.has('ctrl') && !e.ctrlKey) return;
431
- if (modifiers.has('alt') && !e.altKey) return;
432
- if (modifiers.has('shift') && !e.shiftKey) return;
433
- if (modifiers.has('meta') && !e.metaKey) return;
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
- try {
482
- const $element=el
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
- export const After=(el,attr)=>{
524
- if (el._running) return
525
- const getTime=attr.name.match(/\[(.*?)\]/)[1]
526
- const keys = Object.keys(el._context);
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
- const resolvePath = (path, obj) => {
552
- return path.split('.').reduce((acc, key) => acc?.[key], obj);
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
- const timeout=setInterval(() => {
563
- func(...values)
564
- }, getTime);
565
- el._setUnMount(()=>{
566
- clearInterval(timeout)
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)) {