pawajs 1.4.37 → 1.4.39

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/index.d.ts CHANGED
@@ -10,6 +10,7 @@ export interface PawaElement extends HTMLElement {
10
10
  _terminateEffects: Set<Function>;
11
11
  _deleteEffects: () => void;
12
12
  _slots: DocumentFragment;
13
+ _stateContext: any;
13
14
  _mainAttribute: Record<string, any>;
14
15
  _preRenderAvoid: string[];
15
16
  _lazy: boolean;
@@ -74,6 +75,7 @@ export interface PawaElement extends HTMLElement {
74
75
  mount(): void;
75
76
  elementType(): void;
76
77
  setProps(): void;
78
+ safeEval(context: any, expr: string, error?: string, element?: boolean): any;
77
79
  }
78
80
 
79
81
  export interface PawaComment extends Comment {
@@ -157,6 +159,9 @@ export function pluginsMap(): {
157
159
  fullNamePlugin: Set<string>;
158
160
  externalPlugin: Record<string, Function>;
159
161
  externalPluginMap: Map<string, string[]>;
162
+ primaryDirective: Set<string>;
163
+ pawaAttributes: Set<string>;
164
+ allowAsProp: Set<string>;
160
165
  };
161
166
 
162
167
  export const escapePawaAttribute: Set<string>;
@@ -178,6 +183,19 @@ export function keepContext(context: any): void;
178
183
 
179
184
  export const components: Map<string, Function>;
180
185
 
186
+ export const lazyComponents: Map<string, any>;
187
+
188
+ /**
189
+ * Internal registry for tracking elements awaiting lazy component loading.
190
+ */
191
+ export const lazyComponentElement: Map<string, { element: PawaElement; func: Function }[]>;
192
+
193
+ export function addLazyComponentElement(element: PawaElement, func: Function): void;
194
+
195
+ export function createIntersectionObserver(element: HTMLElement, observeBy?: HTMLElement): IntersectionObserver;
196
+
197
+ export const HmrComponentMap: Map<string, any>;
198
+
181
199
  export function getCurrentContext(): any;
182
200
 
183
201
  export function setPawaAttributes(...attr: string[]): void;
@@ -278,6 +296,12 @@ export function useAsync(): { $async: <T>(callback: () => T) => T ,onSuspense:(h
278
296
  */
279
297
  export function isResume(): boolean;
280
298
 
299
+ /**
300
+ * Forwards props to the child component.
301
+ * @param {Record<string, any>} [props] - Props to forward.
302
+ */
303
+ export function forwardProps(props?: Record<string, any>): void;
304
+
281
305
  /**
282
306
  * Exposes variables to the template scope.
283
307
  * @param {Record<string, any>} [obj] - Variables to expose.
@@ -335,7 +359,10 @@ declare const Pawa: {
335
359
  setContext: typeof setContext;
336
360
  $state: typeof $state;
337
361
  pawaStartApp: typeof pawaStartApp;
362
+ useAsync: typeof useAsync;
363
+ useInnerContext: typeof useInnerContext;
338
364
  RegisterComponent: typeof RegisterComponent;
365
+ forwardProps: typeof forwardProps;
339
366
  runEffect: typeof runEffect;
340
367
  html: typeof html;
341
368
  };
package/index.js CHANGED
@@ -75,6 +75,7 @@ const startsWithSet = new Set()
75
75
  const fullNamePlugin = new Set()
76
76
  const externalPlugin = {}
77
77
  const externalPluginMap = new Map()
78
+ const allowAsProp= new Set()
78
79
  let pawaAttributes = new Set()
79
80
  let primaryDirective = new Set()
80
81
 
@@ -90,6 +91,7 @@ const mapsPlugins = {
90
91
  externalPluginMap,
91
92
  primaryDirective,
92
93
  pawaAttributes,
94
+ allowAsProp
93
95
  }
94
96
  export const pluginsMap = () => mapsPlugins
95
97
  export const escapePawaAttribute = new Set()
@@ -120,7 +122,8 @@ const applyMode = (mode, callback) => {
120
122
  }
121
123
  }
122
124
  /**
123
- * @typedef {{startsWith:string,mode:null |'client'|'server',dependency:Array<string>,fullName:string,plugin:(el:HTMLElement | PawaElement,attr:object)=>void}} AttriPlugin
125
+ * @typedef {{startsWith:string,mode:null |'client'|'server',dependency:Array<string>,
126
+ * allowAsProp:boolean,fullName:string,plugin:(el:HTMLElement | PawaElement,attr:object)=>void}} AttriPlugin
124
127
  */
125
128
  /**
126
129
  * @typedef {{
@@ -155,8 +158,12 @@ func.forEach(fn => {
155
158
  dependentPawaAttribute.add(dp); extPluginArray.push(dp)
156
159
  })
157
160
  }
161
+
158
162
  const name = attrPlugins.fullName || attrPlugins.startsWith, set = attrPlugins.fullName ? fullNamePlugin : startsWithSet
159
163
  if (pawaAttributes.has(name)) { console.warn(`attribute plugin already exist ${name}`); return }
164
+ if (attrPlugins?.allowAsProp) {
165
+ allowAsProp.add(name)
166
+ }
160
167
  applyMode(attrPlugins?.mode, () => {
161
168
  pawaAttributes.add(name); set.add(name); externalPlugin[name] = attrPlugins.plugin
162
169
  if (extPluginArray.length) externalPluginMap.set(name, extPluginArray)
@@ -227,9 +234,9 @@ const setPrimaryAttibute = (...name) => {
227
234
 
228
235
  export const getPrimaryDirectives=()=>primaryDirective
229
236
 
230
- setPrimaryAttibute('if', 'else-if', 'for-each', 'else','switch','case','default','case','key')
237
+ setPrimaryAttibute('if', 'else-if', 'for-each', 'else','switch','case','s-default','key')
231
238
  setPawaAttributes('if', 'else-if', 'for-each', 'else', 'mount',
232
- 'unmount', 'forKey', 'state-', 'on-', 'out-','key','switch','case','default')
239
+ 'unmount', 'forKey', 'state-', 'on-', 'out-','key','switch','case','s-default')
233
240
  export const getDependentAttribute = () => dependentPawaAttribute
234
241
  export const getPawaAttributes = () => {
235
242
  return pawaAttributes
@@ -237,10 +244,11 @@ export const getPawaAttributes = () => {
237
244
  let laziler
238
245
  export const lazyComponentElement=new Map()
239
246
  export const addLazyComponentElement=(element,func)=>{
240
- if (lazyComponentElement.has(element.tagName)) {
241
- lazyComponentElement.get(element.tagName).push({element:element,func})
247
+ const tagName=splitAndAdd(element.tagName)
248
+ if (lazyComponentElement.has(tagName)) {
249
+ lazyComponentElement.get(tagName).push({element:element,func})
242
250
  }else{
243
- lazyComponentElement.set(element.tagName, [{element:element,func}])
251
+ lazyComponentElement.set(tagName, [{element:element,func}])
244
252
  }
245
253
  }
246
254
  /**
@@ -279,7 +287,7 @@ export const createIntersectionObserver = (element, observeBy) => {
279
287
  const observer = new IntersectionObserver(entries => {
280
288
  entries.forEach(entry => {
281
289
  if (entry.isIntersecting) {
282
- const tagName = element.tagName;
290
+ const tagName = splitAndAdd(element.tagName);
283
291
  const lazyData = lazyComponents.get(tagName);
284
292
 
285
293
  if (!lazyData) return;
@@ -306,6 +314,7 @@ export const createIntersectionObserver = (element, observeBy) => {
306
314
  el._stateContext._hasRun = true;
307
315
  }
308
316
  }
317
+ lazyComponentElement.delete(tagName)
309
318
  observer.disconnect();
310
319
  }).catch(err => console.error(`Lazy load failed for ${tagName}:`, err));
311
320
  }
@@ -406,13 +415,13 @@ RegisterComponent.lazy=async(...args)=>{
406
415
  }
407
416
  },{
408
417
  _terminateEffects:terminateEffect
409
- })
418
+ },)
410
419
  if (terminateEffect.size > 0) {
411
420
  window.addEventListener('beforeunload',()=>{
412
421
  terminateEffect.forEach(fn =>{
413
422
  fn()
414
423
  })
415
- })
424
+ },deps?.update)
416
425
  }
417
426
  }
418
427
  } else if (Array.isArray(deps)) {
@@ -587,6 +596,14 @@ export const isResume = () => {
587
596
  return false
588
597
  }
589
598
  }
599
+ export const forwardProps=(props={})=>{
600
+ if (client) {
601
+ if (isResume())return
602
+ stateContext._restProps=Object.entries(props).length > 0 ? props : {bPAr:''}
603
+ }else{
604
+ return serverInstance.forwardProps?.(props)
605
+ }
606
+ }
590
607
  /**
591
608
  * Insert into the html context in component
592
609
  * @param {object} obj
@@ -655,6 +672,7 @@ export const setStateContext = (context) => {
655
672
  stateContext._serializedData={}
656
673
  stateContext._formerContext = formerStateContext
657
674
  stateContext._reactiveProps = {}
675
+ stateContext._restProps={}
658
676
  stateContext._template = ''
659
677
  stateContext._resume = false
660
678
  stateContext._suspense=''
@@ -840,13 +858,14 @@ export const restoreContext = (state_context) => {
840
858
  stateContext = state_context._formerContext
841
859
  }
842
860
  export const HmrComponentMap=new Map()
861
+ const renderedComponentsRusumed=new Set()
843
862
  /**
844
863
  *
845
864
  * @param {PawaElement|HTMLElement} el
846
865
  * @returns null
847
866
  */
848
867
  const component = (el, resume = false, attr, notRender, stopResume) => {
849
- if (el._running) {
868
+ if (el._running || (resume && renderedComponentsRusumed.has(attr.value))) {
850
869
  return
851
870
  }
852
871
  el._running = true
@@ -854,6 +873,7 @@ const component = (el, resume = false, attr, notRender, stopResume) => {
854
873
  if (!resume) {
855
874
  if (el._lazy) {
856
875
  // pas the normal component to lazy handler
876
+ el.style.opacity=0
857
877
  addLazyComponentElement(el,()=>normal_component(el, stateContext, setStateContext, mapsPlugins, formerStateContext, pawaContext, stateWatch))
858
878
  return
859
879
  }else{
@@ -861,7 +881,7 @@ const component = (el, resume = false, attr, notRender, stopResume) => {
861
881
  }
862
882
  } else {
863
883
  stopResume.stop = true
864
- let name
884
+ let name=''
865
885
  let comment
866
886
  let endComment
867
887
  const children = []
@@ -917,12 +937,14 @@ const component = (el, resume = false, attr, notRender, stopResume) => {
917
937
  numberComponentChildren = notRender.index + children.length -1
918
938
  }
919
939
  notRender.notRender = numberComponentChildren
920
- if (lazyComponents.has(name)) {
940
+ renderedComponentsRusumed.add(attr.value)
941
+
942
+ if (lazyComponents.has(name.toUpperCase())) {
921
943
  const trackElement=document.createElement(name)
922
944
  trackElement._stateContext=el._stateContext
923
945
  addLazyComponentElement(trackElement,()=>resumer.resume_component?.(el, attr, setStateContext, mapsPlugins, formerStateContext, pawaContext, stateWatch, { comment, endComment, name, serialized, id, children }))
924
- if (!lazyComponentElement.has(name)) {
925
- createInsectObserver(trackElement,el)
946
+ if (lazyComponentElement.has(name.toUpperCase())) {
947
+ createIntersectionObserver(trackElement,el)
926
948
  }
927
949
  }else{
928
950
  resumer.resume_component?.(el, attr, setStateContext, mapsPlugins, formerStateContext, pawaContext, stateWatch, { comment, endComment, name, serialized, id, children })
@@ -992,7 +1014,9 @@ const mainAttribute = (el, exp) => {
992
1014
  el.value = value;
993
1015
  el.setAttribute(exp.name, value);
994
1016
  } else {
995
- if (exp.name === 'class' && !enter) {
1017
+ if ((exp.name === 'class' || exp.name === 'style') && enter) {
1018
+ console.log('entered',enter);
1019
+
996
1020
  requestAnimationFrame(()=>{
997
1021
  el.setAttribute(exp.name, value);
998
1022
  })
@@ -1132,11 +1156,7 @@ export const render = (el, contexts = {}, notRender, isName) => {
1132
1156
  }
1133
1157
  }
1134
1158
 
1135
- if (Array.from(el.childNodes).some(node =>
1136
- node.nodeType === Node.TEXT_NODE && node.nodeValue.includes('@{')
1137
- ) && !el._avoidPawaRender) {
1138
- textContentHandler(el, isName)
1139
- }
1159
+
1140
1160
  let startAttribute = false
1141
1161
  const startObject = {}
1142
1162
  //get startsWith plugin
@@ -1152,27 +1172,31 @@ export const render = (el, contexts = {}, notRender, isName) => {
1152
1172
  })
1153
1173
  })
1154
1174
  const number = { notRender: null }
1175
+ const isAcomponent=el._componentName?true:false
1176
+
1155
1177
  el._attributes.forEach(attr => {
1156
1178
 
1157
1179
  if (stopResume.stop || el._hasRun) return
1158
1180
  if (directives[attr.name]) {
1159
1181
  directives[attr.name](el, attr, stateContext)
1160
- } else if (attr.name.startsWith('on-')) {
1182
+ } else if (attr.name.startsWith('on-') && !isAcomponent) {
1161
1183
  event(el, attr, stateContext)
1162
1184
  } else if (attr.value.includes('@{') && !attr.name.startsWith('c-at-')) {
1163
1185
  mainAttribute(el, attr, isName)
1164
1186
  } else if (attr.name.startsWith('state-')) {
1165
1187
  States(el, attr, getCurrentContext())
1166
- } else if (attr.name.startsWith('out-')) {
1188
+ } else if (attr.name.startsWith('out-') && !isAcomponent) {
1167
1189
  documentEvent(el, attr)
1168
- } else if (attr.name.startsWith('after-[') && attr.name.endsWith(']')) {
1190
+ } else if (attr.name.startsWith('after-[') && attr.name.endsWith(']') && !isAcomponent) {
1169
1191
  After(el, attr)
1170
1192
  }
1171
- else if (attr.name.startsWith('every-[') && attr.name.endsWith(']')) {
1193
+ else if (attr.name.startsWith('every-[') && attr.name.endsWith(']') && !isAcomponent) {
1172
1194
  Every(el, attr)
1173
1195
  }
1174
1196
  else if (attr.name.startsWith('c-c-')) {
1175
1197
  stopResume.stop = true
1198
+
1199
+
1176
1200
  component(el, true, attr, notRender, stopResume)// component continuity
1177
1201
  } else if (attr.name.startsWith('c-at-')) {
1178
1202
  resumer.resume_attribute?.(el, attr, notRender) //attribute continuity
@@ -1221,7 +1245,13 @@ export const render = (el, contexts = {}, notRender, isName) => {
1221
1245
 
1222
1246
  })
1223
1247
  }
1248
+
1224
1249
  if (stopResume.stop) return
1250
+ if (Array.from(el.childNodes).some(node =>
1251
+ node.nodeType === Node.TEXT_NODE && node.nodeValue.includes('@{')
1252
+ ) && !el._avoidPawaRender) {
1253
+ textContentHandler(el, isName)
1254
+ }
1225
1255
  if (el._componentName && !el._avoidPawaRender) {
1226
1256
  component(el)
1227
1257
  return
package/merger/for.js CHANGED
@@ -11,6 +11,8 @@ export const merger_for = (el, stateContext, attr, arrayName, arrayItem, indexes
11
11
  let func
12
12
  let context=el._context
13
13
  const keyOrder=keyOrders || new Map()
14
+ let noKey
15
+ let array
14
16
  const evaluate = () => {
15
17
  if (endComment.parentElement === null) {
16
18
  el._deleteEffects()
@@ -19,7 +21,7 @@ export const merger_for = (el, stateContext, attr, arrayName, arrayItem, indexes
19
21
  if (!func) {
20
22
  func=el.safeEval(context, arrayName, 'for-each');
21
23
  }
22
- let array = func(...getEvalValues(context))
24
+ array = func(...getEvalValues(context))
23
25
  let update;
24
26
  if (!firstEnter) {
25
27
  const div = document.createElement('div')
@@ -50,9 +52,12 @@ export const merger_for = (el, stateContext, attr, arrayName, arrayItem, indexes
50
52
  keyComment._index = lookLike.getAttribute('data-for-index')
51
53
  }
52
54
  if (!el.getAttribute('for-key')) {
55
+ noKey=true
56
+ lookLike=true
53
57
  return
54
58
  }
55
59
  if(lookLike) return
60
+
56
61
  if (lookLike === null) {
57
62
  elementArray.delete(keyComment)
58
63
 
@@ -79,7 +84,7 @@ export const merger_for = (el, stateContext, attr, arrayName, arrayItem, indexes
79
84
  let indexKey=0
80
85
  keyOrder.forEach((value,key)=>{
81
86
  if(update)return;
82
- if(div.children[indexKey]?.getAttribute('data-for-index') !== key){
87
+ if(div.children[indexKey]?.getAttribute('data-for-index') && indexKey !== key){
83
88
  update=true
84
89
  }
85
90
  indexKey++
@@ -87,7 +92,7 @@ export const merger_for = (el, stateContext, attr, arrayName, arrayItem, indexes
87
92
  }
88
93
  const next = () => Promise.all(removeElement).then(async (res) => {
89
94
  if (res) {
90
- if (update) {
95
+ if (update && !noKey) {
91
96
  const keyMap = new Map()
92
97
  elementArray.forEach(child => {
93
98
  keyMap.set(child._forKey, child)
@@ -182,22 +187,7 @@ export const merger_for = (el, stateContext, attr, arrayName, arrayItem, indexes
182
187
  stateContext._hasRun = true
183
188
  elementArray.add(keyComment)
184
189
  })
185
-
186
- } else {
187
- if(!resume)return
188
- if(once)return
189
- const number={notRender:null,index:null}
190
- elementArray.forEach((keyComment) => {
191
- if(keyComment.nextElementSibling === null) return
192
- const itemContext = {
193
- [arrayItem]: array[keyComment._index],
194
- [indexes]: keyComment._index,
195
- ...context
196
- }
197
- render(keyComment.nextElementSibling, itemContext,{notRender:false,index:null})
198
- })
199
- once=true
200
- }
190
+ }
201
191
  firstEnter = false
202
192
  } catch (error) {
203
193
  setPawaDevError({
@@ -1,4 +1,4 @@
1
- import {propsValidator, setPawaDevError, pawaWayRemover, checkKeywordsExistence, sanitizeTemplate } from '../utils.js';
1
+ import {propsValidator, setPawaDevError, pawaWayRemover, checkKeywordsExistence, sanitizeTemplate, splitAndAdd } from '../utils.js';
2
2
  import {PawaElement,PawaComment} from '../pawaElement.js';
3
3
  import {keepContext,render, HmrComponentMap } from '../index.js'
4
4
  import {createEffect} from '../reactive.js'
@@ -61,7 +61,7 @@ export const normal_component=(el,stateContext,setStateContext,mapsPlugin,former
61
61
  console.error(error.message)
62
62
  }
63
63
  }
64
- const div = document.createElement('div')
64
+ let div =el._compoToSvg?document.createElementNS('http://www.w3.org/2000/svg', 'svg'): document.createElement('div')
65
65
  el._componentTerminate=() => {
66
66
  comment._terminateByComponent(endComment)
67
67
  }
@@ -151,16 +151,54 @@ export const normal_component=(el,stateContext,setStateContext,mapsPlugin,former
151
151
  if (component?._insert) {
152
152
  Object.assign(el._context,component._insert)
153
153
  }
154
+ const restProps={}
155
+ if (Object.entries(stateContexts._restProps).length > 0) {
156
+ const props=el._restProps
157
+ if (stateContexts._restProps['className'] && props['class']) {
158
+ restProps['class']={...props['class']}
159
+ }
160
+ if (stateContexts._restProps['defaultValue'] && props['default']) {
161
+ restProps['default']={...props['default']}
162
+ }
163
+
164
+ for (const key in props) {
165
+ let name=key
166
+ name=name.replace(/-([a-z])/g, (g) => g[1].toUpperCase());
167
+ if (stateContexts._restProps[name]) {
168
+ restProps[key]={...props[key]}
169
+ }
170
+ }
171
+ }else{
172
+ Object.assign(restProps,el._restProps)
173
+ }
154
174
  const context=el._context
155
- const propsSetter=()=>{
175
+ const getAsChild=()=>{
176
+ const asChild=div.firstElementChild
177
+ if (splitAndAdd(asChild?.tagName|| '') === 'ASCHILD') {
178
+ const getChildren=asChild.firstElementChild
179
+ Array.from(asChild.attributes).forEach(attr=>{
180
+ if (getChildren.hasAttribute(attr.name)) {
181
+ let attrName=getChildren.getAttribute(attr.name)
182
+ attrName=attr.value +' '+attrName
183
+ getChildren.setAttribute(attr.name, attrName)
184
+ }else{
185
+ getChildren.setAttribute(attr.name, attr.value)
186
+ }
187
+ })
188
+ asChild.remove()
189
+ div.appendChild(getChildren)
190
+ }
191
+ }
192
+ const propsSetter=()=>{
193
+ getAsChild()
156
194
  const findElement=div.querySelector('[--]') || div.querySelector('[rest]')
157
195
  if (findElement) {
158
196
  findElement.removeAttribute('--')
159
197
  findElement.removeAttribute('rest')
160
198
  }
161
- if(Object.entries(el._restProps).length > 0){
199
+ if(Object.entries(restProps).length > 0){
162
200
  if (findElement) {
163
- for (const [key,value] of Object.entries(el._restProps)) {
201
+ for (const [key,value] of Object.entries(restProps)) {
164
202
  findElement.setAttribute(value.name,value.value)
165
203
  }
166
204
  }
@@ -183,7 +221,7 @@ export const normal_component=(el,stateContext,setStateContext,mapsPlugin,former
183
221
  bfm._sent=true
184
222
  const result= bfm(comment)
185
223
  if (typeof result === 'function') {
186
- el._unMountFunctions.push(result)
224
+ el._beforeUnMountFunctions.push(result)
187
225
  }
188
226
  })
189
227
 
@@ -230,7 +268,7 @@ export const normal_component=(el,stateContext,setStateContext,mapsPlugin,former
230
268
  if (hook.deps?.component) {
231
269
  createEffect(() => {
232
270
  return effect()
233
- },el)
271
+ },el,hook.deps?.update)
234
272
  } else {
235
273
  createEffect(() => {
236
274
  return effect()
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pawajs",
3
- "version": "1.4.37",
3
+ "version": "1.4.39",
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
@@ -1,4 +1,4 @@
1
- import {components,lazyComponents ,escapePawaAttribute,getPawaAttributes,getDependentAttribute,getPrimaryDirectives } from './index.js';
1
+ import {components,lazyComponents ,escapePawaAttribute,getPawaAttributes,getDependentAttribute,getPrimaryDirectives, pluginsMap } from './index.js';
2
2
  import {splitAndAdd,replaceTemplateOperators,setPawaDevError,getEvalValues, checkKeywordsExistence} from './utils.js';
3
3
  import PawaComponent from './pawaComponent.js';
4
4
  import { createIntersectionObserver } from './index.js';
@@ -23,12 +23,12 @@ export class PawaElement {
23
23
  _el: element, _out: false, _stateContext: null, _terminateEffects: new Set(), _deleteEffects: this.terminateEffects,
24
24
  _slots: document.createDocumentFragment(), _mainAttribute: {}, _preRenderAvoid: [], _running: false,
25
25
  _hasForOrIf: this.hasForOrIf, _elementContent: element.textContent, _textContent: {}, _attributes: [],
26
- _template: div.outerHTML, _exitAnimation: null, _component: null, _unMountFunctions: [], _MountFunctions: [],
26
+ _template: div.outerHTML, _exitAnimation: null, _component: null, _unMountFunctions: [], _MountFunctions: [],_beforeUnMountFunctions:[],
27
27
  _elementType: '', _getNode: this.getNode, _componentOrTemplate: false, _props: {}, _isView: null,
28
- _isElementComponent: false, _pawaAttribute: {}, _setUnMount: this.setUnMounts, _componentName: '',
28
+ _isElementComponent: false, _pawaAttribute: {}, _setUnMount: this.setUnMounts, _componentName: '',_compoToSvg: false,_asChild: false,
29
29
  _attrElement: this.getNewElementByRemovingAttr, _attr: {}, _staticContext: [], _checkStatic: this.reCheckStaticContext,
30
30
  _callMount: this.mount, _callUnmount: this.unMount, _remove: this.remove, _componentChildren: undefined,
31
- _pawaElementComponent: null, _componentTerminate: null, _cacheSetUp: false, _effectsCarrier: null,
31
+ _pawaElementComponent: null, _componentTerminate: null, _cacheSetUp: false, _effectsCarrier: null,_beforeUnMount:this.beforeUnMount,
32
32
  _pawaElementComponentName: '', _reCallEffect: this.reCallEffect, _ElementEffects: new Map(),
33
33
  _deCompositionElement: false, _restProps: {}, _kill: null, _isKill: false, _scriptFetching: element.hasAttribute('script'),
34
34
  _scriptDone: false, _underControl: null, safeEval: this.safeEval, _reactiveProps: {},
@@ -97,8 +97,11 @@ export class PawaElement {
97
97
  const pawaAttr=this._el.getAttribute('p:c')
98
98
  const array=pawaAttr.split(';')
99
99
  array.forEach(value =>{
100
- if(!this._el.hasAttribute(value)) return
101
- this._attributes.push({name:value,value:this._el.getAttribute(value)})
100
+ if(!this._el.hasAttribute(value.toLowerCase())) {
101
+ return
102
+ }
103
+ this._attributes.push({name:value,value:this._el.getAttribute(value.toLowerCase())})
104
+ // console.log(this._el,this._attributes);
102
105
  })
103
106
  }else{
104
107
  this._attributes=Array.from(this._el.attributes)
@@ -172,10 +175,8 @@ export class PawaElement {
172
175
  }
173
176
  }
174
177
  async remove(callback){
175
- if (typeof this._kill === 'function' && this._isKill && this._deCompositionElement) {
176
- this._kill()
177
- return
178
- }
178
+
179
+ await this._beforeUnMount()
179
180
  if (typeof this._exitAnimation === 'function') {
180
181
 
181
182
  try {
@@ -200,6 +201,15 @@ export class PawaElement {
200
201
  }
201
202
  return true
202
203
  }
204
+ if (typeof this._kill === 'function' && this._isKill && this._deCompositionElement) {
205
+ this._kill()
206
+ return
207
+ }
208
+ }
209
+ async beforeUnMount(){
210
+ this._beforeUnMountFunctions.forEach(func => {
211
+ func()
212
+ });
203
213
  }
204
214
  async unMount(){
205
215
  if (this._component && this._pawaElementComponentName === '') {
@@ -291,10 +301,17 @@ export class PawaElement {
291
301
  });
292
302
  }
293
303
  const pawaAttribute=getPawaAttributes()
304
+ const {allowAsProp}=pluginsMap()
294
305
  const dependAttribute=getDependentAttribute()
295
306
  this._attributes.forEach((attr) => {
296
-
297
- if (!attr.name.startsWith(':') && !pawaAttribute.has(attr.name) && !dependAttribute.has(attr.name)) {
307
+ if (attr.name === 'svg') {
308
+ this._compoToSvg = true
309
+ return
310
+ }else if(attr.name === 'aschild' || attr.name === 'as-child'){
311
+ this._asChild = true
312
+ return
313
+ }
314
+ if (!attr.name.startsWith(':') && (!pawaAttribute.has(attr.name) && !dependAttribute.has(attr.name) )) {
298
315
  let name=''
299
316
  if (attr.name.startsWith('-')) {
300
317
  name=attr.name.slice(1)
@@ -316,7 +333,7 @@ export class PawaElement {
316
333
  }
317
334
  });
318
335
  return value
319
- }else if( attr.name.startsWith('on-') || attr.name.startsWith('out-')){
336
+ }else if( attr.name.startsWith('on-') || attr.name.startsWith('out-') || attr.name === 'ref'){
320
337
  const res=this.safeEval(context,`(e)=>{
321
338
  ${attr.value}
322
339
  }`, 'props',true)
@@ -335,7 +352,7 @@ export class PawaElement {
335
352
  this._props[name]=setProps
336
353
  }
337
354
 
338
- this._restProps[name]={name:name,value:attr.value}
355
+ this._restProps[attr.name]={name:attr.name,value:attr.value}
339
356
  }else if(!pawaAttribute.has(attr.name) && attr.name.startsWith(':')){
340
357
 
341
358
  const propsName=attr.name.slice(1)
package/power.js CHANGED
@@ -388,7 +388,7 @@ export const For = (el, attr, stateContext,resume=false,notRender,stopResume) =>
388
388
 
389
389
  export const ref = (el, attr) => {
390
390
  el._checkStatic()
391
- if (el._running || checkKeywordsExistence(el._staticContext,attr.value)) {
391
+ if (el._running || checkKeywordsExistence(el._staticContext,attr.value) || el._componentName) {
392
392
  return
393
393
  }
394
394
  try {
@@ -519,26 +519,29 @@ export const documentEvent = (el, attr) => {
519
519
  const unMount = () => target.removeEventListener(eventType, handler, options);
520
520
  el._setUnMount(unMount)
521
521
  }
522
- export const exitTransition=(el,attr)=>{
523
- if (el._running) {
524
- return
522
+
523
+ export const exitTransition = (el, attr) => {
524
+ if (el._running || el._componentName) {
525
+ return
526
+ }
527
+ const maxWait = 5000 // 5 seconds max
528
+ const promise = (resolve, startTime = Date.now()) => {
529
+ setTimeout(() => {
530
+ const animations = el.getAnimations({ subtree: false })
531
+ if (animations.length === 0 ) {
532
+ resolve()
533
+ return
534
+ }
535
+ Promise.all(animations.map(a => a.finished))
536
+ .then(() => promise(resolve, startTime))
537
+ .catch(() => promise(resolve, startTime))
538
+ }, 50)
525
539
  }
526
- el._exitAnimation=()=>{
527
- return new Promise((resolve)=>{
528
- requestAnimationFrame(()=>{
529
- const animations =el.getAnimations({subtree:false})
530
- if (animations.length === 0) {
531
- resolve()
532
- return
533
- }
534
-
535
- Promise.all(animations.map(a=>a.finished)).then(resolve).catch(resolve)
536
- })
537
- })
538
- }
539
- el.removeAttribute(attr.name)
540
+ el._exitAnimation = () => {
541
+ return new Promise(promise)
542
+ }
543
+ el.removeAttribute(attr.name)
540
544
  }
541
-
542
545
  const createTimedExecutable = (el, attr, useInterval) => {
543
546
  if (el._running) return;
544
547
  const getTime = attr.name.match(/\[(.*?)\]/)[1];
package/reactive.js CHANGED
@@ -27,6 +27,10 @@ function scheduleRenderWithTimeBudget() {
27
27
 
28
28
  for (const fn of scheduled) {
29
29
  const cleanUp = fn();
30
+ if (fn?._sideEffect) {
31
+ const cleared=fn?._sideEffect?.()
32
+ if(typeof cleared === 'function')cleared()
33
+ }
30
34
  if (typeof cleanUp === 'function') cleanUp();
31
35
  processed.push(fn);
32
36
  if (performance.now() - start > FRAME_BUDGET) {
@@ -75,7 +79,7 @@ export const queueEffect = (effect,depsMap) => {
75
79
  };
76
80
 
77
81
  // Add parent tracking to effects
78
- export const createEffect = (fn, el) => {
82
+ export const createEffect = (fn, el,update=null) => {
79
83
  const effect = () => {
80
84
  activeEffect = effect;
81
85
  effect.el = el;
@@ -86,6 +90,8 @@ export const queueEffect = (effect,depsMap) => {
86
90
  return cleanUp
87
91
  }
88
92
  };
93
+ update?.()
94
+ effect._sideEffect=update
89
95
  effect._id=crypto.randomUUID()
90
96
  effect._done=false
91
97
  effect._dep=null
@@ -117,7 +123,7 @@ if (el) {
117
123
  // console.log(el,effect._dep);
118
124
  }
119
125
 
120
- el._terminateEffects.add(deletes)
126
+ el?._terminateEffects.add(deletes)
121
127
 
122
128
  }
123
129
  return effect;
@@ -131,6 +137,7 @@ export const track = (target, key) => {
131
137
 
132
138
  let depsMap = targetMap.get(target);
133
139
  if (!depsMap) {
140
+
134
141
  targetMap.set(target, (depsMap = new Map()));
135
142
  }
136
143
  let dep = depsMap.get(key);
package/server.js CHANGED
@@ -10,6 +10,7 @@ const serverInstance={
10
10
  accessChild:null,
11
11
  useServer:null,
12
12
  useAsync:null,
13
+ forwardPops:null
13
14
  }
14
15
  export const getServerInstance=()=>serverInstance
15
16
  export const setServer=(obj={})=>{