native-document 1.0.107 → 1.0.109

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.
@@ -4,94 +4,181 @@ import TemplateBinding from "./TemplateBinding";
4
4
  const cloneBindingsDataCache = new WeakMap();
5
5
 
6
6
 
7
- const bindAttributes = (node, bindDingData, data) => {
8
- let attributes = null;
9
- if(bindDingData.attributes) {
10
- attributes = {};
11
- for (const attr in bindDingData.attributes) {
12
- attributes[attr] = bindDingData.attributes[attr].apply(null, data);
13
- }
7
+ const hydrateFull = (node, bindDingData, data) => {
8
+ const cacheAttributes = bindDingData._cache;
9
+
10
+ for(let i = 0, length = bindDingData._flatAttributesLength; i < length; i++) {
11
+ const attr = bindDingData._flatAttributes[i];
12
+ cacheAttributes[attr.name] = attr.value.apply(null, data);
14
13
  }
15
14
 
16
- if(bindDingData.classes) {
17
- attributes = attributes || {};
18
- attributes.class = {};
19
- for (const className in bindDingData.classes) {
20
- attributes.class[className] = bindDingData.classes[className].apply(null, data);
21
- }
15
+ for(let i = 0, length = bindDingData._flatDynamiqueLength; i < length; i++) {
16
+ const dyn = bindDingData._flatDynamique[i];
17
+ cacheAttributes[dyn.name][dyn.key] = dyn.value.apply(null, data);
22
18
  }
23
19
 
24
- if(bindDingData.styles) {
25
- attributes = attributes || {};
26
- attributes.style = {};
27
- for (const property in bindDingData.styles) {
28
- attributes.style[property] = bindDingData.styles[property].apply(null, data);
29
- }
20
+ ElementCreator.processAttributesDirect(node, cacheAttributes);
21
+ return true;
22
+ };
23
+
24
+ const hydrateDynamic = (node, bindDingData, data) => {
25
+ const cacheAttributes = bindDingData._cache;
26
+
27
+ for(let i = 0, length = bindDingData._flatDynamiqueLength; i < length; i++) {
28
+ const dyn = bindDingData._flatDynamique[i];
29
+ cacheAttributes[dyn.name][dyn.key] = dyn.value.apply(null, data);
30
30
  }
31
31
 
32
- if(attributes) {
33
- ElementCreator.processAttributes(node, attributes);
34
- return true;
32
+ ElementCreator.processAttributesDirect(node, cacheAttributes);
33
+ return true;
34
+ };
35
+
36
+ const hydrateAttributes = (node, bindDingData, data) => {
37
+ const cacheAttributes = bindDingData._cache;
38
+
39
+ for(let i = 0, length = bindDingData._flatAttributesLength; i < length; i++) {
40
+ const attr = bindDingData._flatAttributes[i];
41
+ cacheAttributes[attr.name] = attr.value.apply(null, data);
35
42
  }
36
43
 
37
- return null;
44
+ ElementCreator.processAttributesDirect(node, cacheAttributes);
45
+ return true;
46
+ };
47
+
48
+ const getHydrator = (bindDingData) => {
49
+ if(!bindDingData._cache) {
50
+ return noUpdate;
51
+ }
52
+ if(bindDingData._flatAttributesLength && bindDingData._flatDynamiqueLength) {
53
+ return hydrateFull;
54
+ }
55
+ if(bindDingData._flatAttributesLength) {
56
+ return hydrateAttributes;
57
+ }
58
+ return hydrateDynamic;
38
59
  };
39
60
 
40
61
  const $hydrateFn = function(hydrateFunction, targetType, element, property) {
41
62
  if(!cloneBindingsDataCache.has(element)) {
42
- // { classes, styles, attributes, value, attach }
43
- cloneBindingsDataCache.set(element, {});
63
+ cloneBindingsDataCache.set(element, { attach: [] });
44
64
  }
45
65
  const hydrationState = cloneBindingsDataCache.get(element);
66
+
46
67
  if(targetType === 'value') {
47
68
  hydrationState.value = hydrateFunction;
48
69
  return;
49
70
  }
71
+ if(targetType === 'attach') {
72
+ hydrationState.attach = hydrationState.attach || [];
73
+ hydrationState.attach.push({ methodName: property, fn: hydrateFunction});
74
+ return;
75
+ }
50
76
  hydrationState[targetType] = hydrationState[targetType] || {};
51
77
  hydrationState[targetType][property] = hydrateFunction;
52
- }
78
+ };
53
79
 
54
80
  const bindAttachMethods = (node, bindDingData, data) => {
55
- if(!bindDingData.attach) {
56
- return null;
57
- }
58
- for(const methodName in bindDingData.attach) {
59
- node.nd[methodName](function(...args) {
60
- bindDingData.attach[methodName].apply(this, [...args, ...data]);
81
+ for(let i = 0, length = bindDingData._attachLength; i < length; i++) {
82
+ const method = bindDingData.attach[i];
83
+ node.nd[method.methodName](function() {
84
+ method.fn.call(this, ...arguments, ...data);
61
85
  });
62
86
  }
63
87
  };
64
88
 
65
89
 
66
- const applyBindingTreePath = (root, target, data, path) => {
67
- if(path.fn) {
68
- if(typeof path.fn === 'string') {
69
- ElementCreator.bindTextNode(target, data[0][path.fn]);
90
+ const $applyBindingParents = [];
91
+ const applyBindingTreePath = (root, data, paths, pathSize) => {
92
+ const rootPath = paths.at(-1);
93
+ $applyBindingParents[rootPath.id] = root;
94
+ const rootPathFn = rootPath.fn;
95
+ rootPathFn(data, root, root);
96
+
97
+
98
+ for(let i = 0; i < pathSize; i++) {
99
+ const path = paths[i];
100
+ const target = $applyBindingParents[path.parentId].childNodes[path.index];
101
+
102
+ $applyBindingParents[path.id] = target;
103
+ const pathFn = path.fn;
104
+ pathFn(data, target, root);
105
+ }
106
+ $applyBindingParents.length = 0;
107
+ };
108
+ const buildAttributesCache = (bindDingData) => {
109
+ const cache = { };
110
+ if(bindDingData.attributes) cache.attributes = {};
111
+ if(bindDingData.classes) cache.class = {};
112
+ if(bindDingData.styles) cache.style = {};
113
+ bindDingData._cache = cache;
114
+ };
115
+
116
+ const prepareBindingMetadata = (bindDingData) => {
117
+ const attributes = [];
118
+ const classAndStyles = [];
119
+
120
+ if(bindDingData.attributes) {
121
+ for (const attr in bindDingData.attributes) {
122
+ attributes.push({
123
+ name: attr,
124
+ value: bindDingData.attributes[attr]
125
+ });
70
126
  }
71
- else {
72
- path.fn(data, target, root);
127
+ }
128
+
129
+ if(bindDingData.classes) {
130
+ for (const className in bindDingData.classes) {
131
+ classAndStyles.push({
132
+ name: 'class',
133
+ key: className,
134
+ value: bindDingData.classes[className]
135
+ });
73
136
  }
74
137
  }
75
- if(path.children) {
76
- for(let i = 0, length = path.children.length; i < length; i++) {
77
- const currentPath = path.children[i];
78
- const pathTargetNode = target.childNodes[currentPath.index];
79
- applyBindingTreePath(root, pathTargetNode, data, currentPath);
138
+
139
+ if(bindDingData.styles) {
140
+ for (const property in bindDingData.styles) {
141
+ classAndStyles.push({
142
+ name: 'style',
143
+ key: property,
144
+ value: bindDingData.styles[property]
145
+ });
80
146
  }
81
147
  }
148
+
149
+ bindDingData._flatAttributes = attributes;
150
+ bindDingData._flatAttributesLength = attributes.length;
151
+ bindDingData._flatDynamique = classAndStyles;
152
+ bindDingData._flatDynamiqueLength = classAndStyles.length;
153
+ bindDingData._attachLength = bindDingData.attach.length;
154
+ };
155
+
156
+ const optimizeBindingData = (bindDingData) => {
157
+ if(!bindDingData) {
158
+ return;
159
+ }
160
+ buildAttributesCache(bindDingData);
161
+ prepareBindingMetadata(bindDingData);
82
162
  };
83
163
 
164
+ const noUpdate = () => {};
84
165
  export function TemplateCloner($fn) {
85
166
  let $node = null;
86
167
  let $hasBindingData = false;
87
168
 
88
- const $bindingTreePath = {
89
- fn: null,
90
- children: [],
91
- };
169
+ let $bindingTreePathSize = 0;
170
+ const $bindingTreePath = [
171
+ {
172
+ id: 0,
173
+ parentId: null,
174
+ fn: noUpdate,
175
+ }
176
+ ];
92
177
 
178
+ let pathCounter = 0;
93
179
  const clone = (node, data, currentPath) => {
94
180
  const bindDingData = cloneBindingsDataCache.get(node);
181
+ optimizeBindingData(bindDingData);
95
182
  if(node.nodeType === 3) {
96
183
  if(bindDingData && bindDingData.value) {
97
184
  currentPath.fn = bindDingData.value;
@@ -107,35 +194,51 @@ export function TemplateCloner($fn) {
107
194
  }
108
195
  const nodeCloned = node.cloneNode();
109
196
  if(bindDingData) {
110
- bindAttributes(nodeCloned, bindDingData, data);
197
+ const hydrator = getHydrator(bindDingData);
198
+ hydrator(nodeCloned, bindDingData, data);
111
199
  bindAttachMethods(nodeCloned, bindDingData, data);
112
- currentPath.fn = (data, targetNode) => {
113
- bindAttributes(targetNode, bindDingData, data);
114
- bindAttachMethods(targetNode, bindDingData, data);
115
- };
200
+
201
+ const hasAttributes = bindDingData.classes || bindDingData.styles || bindDingData.attributes;
202
+ const hasAttachMethods = bindDingData.attach.length;
203
+
204
+ currentPath.fn = noUpdate;
205
+ if(hasAttributes && hasAttachMethods) {
206
+ currentPath.fn = (data, targetNode) => {
207
+ hydrator(targetNode, bindDingData, data);
208
+ bindAttachMethods(targetNode, bindDingData, data);
209
+ };
210
+ }
211
+ else if(hasAttributes) {
212
+ currentPath.fn = (data, targetNode) => {
213
+ hydrator(targetNode, bindDingData, data);
214
+ };
215
+ }
216
+ else if(hasAttachMethods) {
217
+ currentPath.fn = (data, targetNode) => {
218
+ bindAttachMethods(targetNode, bindDingData, data);
219
+ };
220
+ }
116
221
  }
117
222
  const childNodes = node.childNodes;
118
- const bindingPathChildren = [];
223
+ const parentId = currentPath.id;
224
+
119
225
  for(let i = 0, length = childNodes.length; i < length; i++) {
120
226
  const childNode = childNodes[i];
121
- const path = { index: i, fn: null };
227
+ const path = { parentId, id: ++pathCounter, index: i, fn: noUpdate };
122
228
  const childNodeCloned = clone(childNode, data, path);
123
- if(path.children || path.fn) {
124
- bindingPathChildren.push(path);
229
+ if(path.hasChildren || path.fn !== noUpdate) {
230
+ $bindingTreePath.push(path);
231
+ currentPath.hasChildren = true;
125
232
  }
126
233
  nodeCloned.appendChild(childNodeCloned);
127
234
  }
128
- if(bindingPathChildren.length) {
129
- currentPath.children = currentPath.children || [];
130
- currentPath.children = bindingPathChildren;
131
- }
132
235
  return nodeCloned;
133
236
  };
134
237
 
135
238
  const cloneWithBindingPaths = (data) => {
136
239
  let root = $node.cloneNode(true);
137
240
 
138
- applyBindingTreePath(root, root, data, $bindingTreePath);
241
+ applyBindingTreePath(root, data, $bindingTreePath, $bindingTreePathSize);
139
242
  return root;
140
243
  };
141
244
 
@@ -146,7 +249,10 @@ export function TemplateCloner($fn) {
146
249
  return $node.cloneNode(true);
147
250
  }
148
251
 
149
- const firstClone = clone($node, data, $bindingTreePath);
252
+ const firstClone = clone($node, data, $bindingTreePath[0]);
253
+ $bindingTreePath.reverse();
254
+ $bindingTreePathSize = $bindingTreePath.length - 1;
255
+
150
256
  this.clone = cloneWithBindingPaths;
151
257
  return firstClone;
152
258
  };
@@ -170,7 +276,9 @@ export function TemplateCloner($fn) {
170
276
  }
171
277
  this.value = (callbackOrProperty) => {
172
278
  if(typeof callbackOrProperty !== 'function') {
173
- return createBinding(callbackOrProperty, 'value');
279
+ return createBinding((data, textNode) => {
280
+ ElementCreator.bindTextNode(textNode, data[0][callbackOrProperty]);
281
+ }, 'value');
174
282
  }
175
283
  return createBinding((data, textNode) => {
176
284
  ElementCreator.bindTextNode(textNode, callbackOrProperty(...data));
@@ -183,16 +291,18 @@ export function TemplateCloner($fn) {
183
291
  this.attach = (fn) => {
184
292
  return createBinding(fn, 'attach');
185
293
  };
294
+ this.callback = this.attach;
186
295
 
187
296
  }
188
297
 
189
298
  export function useCache(fn) {
190
299
  let $cache = null;
191
300
 
192
- const wrapper = function(args) {
193
- if(!$cache) {
194
- $cache = new TemplateCloner(fn);
195
- }
301
+ let wrapper = function(args) {
302
+ $cache = new TemplateCloner(fn);
303
+ wrapper = function(args) {
304
+ return $cache.clone(args);
305
+ };
196
306
  return $cache.clone(args);
197
307
  };
198
308
 
@@ -3,7 +3,6 @@ import {NDElement} from "../NDElement";
3
3
  import TemplateBinding from "../TemplateBinding";
4
4
  import {ElementCreator} from "../ElementCreator";
5
5
  import PluginsManager from "../../utils/plugins-manager";
6
- import Validator from "../../utils/validator";
7
6
  import ObservableChecker from "../../data/ObservableChecker";
8
7
 
9
8
  String.prototype.toNdElement = function () {
@@ -36,10 +36,11 @@ const waitForVisualEnd = (el, timeout = 1000) => {
36
36
 
37
37
  NDElement.prototype.transitionOut = function(transitionName) {
38
38
  const exitClass = transitionName + '-exit';
39
+ const el = this.$element;
39
40
  this.beforeUnmount('transition-exit', async function() {
40
- this.$element.classes.add(exitClass);
41
- await waitForVisualEnd(this.$element);
42
- this.$element.classes.remove(exitClass);
41
+ el.classes.add(exitClass);
42
+ await waitForVisualEnd(el);
43
+ el.classes.remove(exitClass);
43
44
  });
44
45
  return this;
45
46
  };
@@ -48,16 +49,18 @@ NDElement.prototype.transitionIn = function(transitionName) {
48
49
  const startClass = transitionName + '-enter-from';
49
50
  const endClass = transitionName + '-enter-to';
50
51
 
51
- this.$element.classes.add(startClass);
52
+ const el = this.$element;
53
+
54
+ el.classes.add(startClass);
52
55
 
53
56
  this.mounted(() => {
54
57
  requestAnimationFrame(() => {
55
58
  requestAnimationFrame(() => {
56
- this.$element.classes.remove(startClass);
57
- this.$element.classes.add(endClass);
59
+ el.classes.remove(startClass);
60
+ el.classes.add(endClass);
58
61
 
59
- waitForVisualEnd(this.$element).then(() => {
60
- this.$element.classes.remove(endClass);
62
+ waitForVisualEnd(el).then(() => {
63
+ el.classes.remove(endClass);
61
64
  });
62
65
  });
63
66
  });
@@ -73,10 +76,11 @@ NDElement.prototype.transition = function (transitionName) {
73
76
  };
74
77
 
75
78
  NDElement.prototype.animate = function(animationName) {
76
- this.$element.classes.add(animationName);
79
+ const el = this.$element;
80
+ el.classes.add(animationName);
77
81
 
78
- waitForVisualEnd(this.$element).then(() => {
79
- this.$element.classes.remove(animationName);
82
+ waitForVisualEnd(el).then(() => {
83
+ el.classes.remove(animationName);
80
84
  });
81
85
 
82
86
  return this;
@@ -268,3 +268,14 @@ Router.forward = function(name = null) {
268
268
  Router.back = function(name = null) {
269
269
  return Router.get(name).back();
270
270
  };
271
+
272
+ Router.redirectTo = function(pathOrRouteName, params = null, name = null) {
273
+ let target = pathOrRouteName;
274
+ const router = Router.get(name);
275
+ const route = router.resolve({ name: pathOrRouteName, params });
276
+ if(route) {
277
+ target = { name: pathOrRouteName, params}
278
+ }
279
+ console.log(target);
280
+ return router.push(target);
281
+ };
@@ -1,5 +1,6 @@
1
1
  import Validator from "../core/utils/validator";
2
2
  import {Anchor} from "../../elements";
3
+ import {ElementCreator} from "../core/wrappers/ElementCreator";
3
4
 
4
5
  /**
5
6
  *
@@ -73,7 +74,7 @@ export function RouterComponent(router, container) {
73
74
  cleanContainer();
74
75
  const anchor = getNodeAnchorForLayout(nodeToInsert, path);
75
76
 
76
- $currentLayout = layout(anchor);
77
+ $currentLayout = ElementCreator.getChild(layout(anchor));
77
78
  $layoutCache.set(nodeToInsert, $currentLayout);
78
79
  container.appendChild($currentLayout);
79
80
  }
@@ -37,6 +37,7 @@ export declare class TemplateCloner {
37
37
  property(fn: (...data: any[]) => any): BindingHydrator;
38
38
 
39
39
  attach(fn: (element: Element, ...data: any[]) => void): BindingHydrator;
40
+ callback(fn: (element: Element, ...data: any[]) => void): BindingHydrator;
40
41
  }
41
42
 
42
43
  export declare function useCache(fn: TemplateBuilder): CachedTemplateFunction;