native-document 1.0.36 → 1.0.38
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/dist/native-document.dev.js +183 -133
- package/dist/native-document.dev.js.map +1 -1
- package/dist/native-document.devtools.min.js +1 -0
- package/dist/native-document.min.js +1 -1
- package/elements.d.ts +1 -0
- package/index.js +4 -5
- package/package.json +2 -1
- package/rollup.config.js +36 -6
- package/src/devtools/app/App.js +66 -0
- package/src/devtools/app/app.css +0 -0
- package/src/devtools/index.js +18 -0
- package/src/devtools/plugin.js +15 -0
- package/src/devtools/widget/DevToolsWidget.js +26 -0
- package/src/utils/plugins-manager.js +6 -2
- package/src/wrappers/NDElement.js +145 -2
- package/src/wrappers/TemplateCloner.js +35 -20
- package/types/control-flow.d.ts +8 -4
- package/types/elements.d.ts +74 -610
- package/types/forms.d.ts +17 -1
- package/types/images.d.ts +8 -4
- package/types/nd-element.d.ts +611 -0
- package/types/observable.d.ts +6 -19
- package/types/polyfill.d.ts +1 -1
- package/types/template-cloner.ts +7 -2
- package/src/wrappers/NDElementEventPrototypes.js +0 -116
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import DocumentObserver from "./DocumentObserver";
|
|
2
|
-
import { EVENTS } from "../utils/events";
|
|
3
2
|
import PluginsManager from "../utils/plugins-manager";
|
|
3
|
+
import Validator from "../utils/validator";
|
|
4
|
+
import {EVENTS} from "../utils/events";
|
|
4
5
|
|
|
5
6
|
export function NDElement(element) {
|
|
6
7
|
this.$element = element;
|
|
@@ -65,7 +66,149 @@ NDElement.prototype.htmlElement = function() {
|
|
|
65
66
|
|
|
66
67
|
NDElement.prototype.node = NDElement.prototype.htmlElement;
|
|
67
68
|
|
|
69
|
+
NDElement.prototype.shadow = function(mode, style = null) {
|
|
70
|
+
const $element = this.$element;
|
|
71
|
+
const children = Array.from($element.childNodes)
|
|
72
|
+
const shadowRoot = $element.attachShadow({ mode });
|
|
73
|
+
if(style) {
|
|
74
|
+
const styleNode = document.createElement("style");
|
|
75
|
+
styleNode.textContent = style;
|
|
76
|
+
shadowRoot.appendChild(styleNode);
|
|
77
|
+
}
|
|
78
|
+
$element.append = shadowRoot.append.bind(shadowRoot);
|
|
79
|
+
$element.appendChild = shadowRoot.appendChild.bind(shadowRoot);
|
|
80
|
+
shadowRoot.append(...children);
|
|
81
|
+
|
|
82
|
+
return this;
|
|
83
|
+
};
|
|
84
|
+
NDElement.prototype.openShadow = function(style = null) {
|
|
85
|
+
return this.shadow('open', style);
|
|
86
|
+
};
|
|
87
|
+
NDElement.prototype.closedShadow = function(style = null) {
|
|
88
|
+
return this.shadow('closed', style);
|
|
89
|
+
};
|
|
90
|
+
|
|
68
91
|
NDElement.prototype.attach = function(bindingHydrator) {
|
|
69
92
|
bindingHydrator.$hydrate(this.$element);
|
|
70
93
|
return this.$element;
|
|
71
|
-
};
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
*
|
|
99
|
+
* ND events API
|
|
100
|
+
*
|
|
101
|
+
*/
|
|
102
|
+
|
|
103
|
+
const DelegatedEventsCallbackStore = {};
|
|
104
|
+
|
|
105
|
+
const addCallbackToCallbacksStore = function(element, eventName, callback) {
|
|
106
|
+
if(!element) return;
|
|
107
|
+
if(!DelegatedEventsCallbackStore[eventName]) {
|
|
108
|
+
const eventStore = new WeakMap();
|
|
109
|
+
DelegatedEventsCallbackStore[eventName] = eventStore;
|
|
110
|
+
eventStore.set(element, callback);
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
const eventStore = DelegatedEventsCallbackStore[eventName];
|
|
114
|
+
|
|
115
|
+
if(!eventStore.has(element)) {
|
|
116
|
+
eventStore.set(element, callback);
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
const existingCallbacks = eventStore.get(element);
|
|
120
|
+
if(!Validator.isArray(existingCallbacks)) {
|
|
121
|
+
eventStore.set(element, [store[eventName], callback]);
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
existingCallbacks.push(callback);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
const handleDelegatedCallbacks = function(container, eventName) {
|
|
128
|
+
container.addEventListener(eventName, (event) => {
|
|
129
|
+
const eventStore = DelegatedEventsCallbackStore[eventName];
|
|
130
|
+
if(!eventStore) {
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
let target = event.target;
|
|
134
|
+
while(target && target !== container) {
|
|
135
|
+
const callback = eventStore.get(target);
|
|
136
|
+
if(!callback) {
|
|
137
|
+
target = target.parentElement;
|
|
138
|
+
continue;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
if(Validator.isFunction(callback)) {
|
|
142
|
+
callback.call(target, event);
|
|
143
|
+
}
|
|
144
|
+
else {
|
|
145
|
+
for(let i = 0; i < callback.length; i++) {
|
|
146
|
+
callback[i].call(target, event);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
151
|
+
});
|
|
152
|
+
};
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
const preventDefaultWrapper = function(element, eventName, callback) {
|
|
156
|
+
element.addEventListener(eventName, (event) => {
|
|
157
|
+
event.preventDefault();
|
|
158
|
+
callback && callback.call(element, event);
|
|
159
|
+
});
|
|
160
|
+
return this;
|
|
161
|
+
}
|
|
162
|
+
const stopPropagationWrapper = function(element, eventName, callback) {
|
|
163
|
+
element.addEventListener(eventName, (event) => {
|
|
164
|
+
event.stopPropagation();
|
|
165
|
+
callback && callback.call(element, event);
|
|
166
|
+
});
|
|
167
|
+
return this;
|
|
168
|
+
};
|
|
169
|
+
const preventDefaultAndStopPropagationWrapper = function(element, eventName, callback) {
|
|
170
|
+
element.addEventListener(eventName, (event) => {
|
|
171
|
+
event.stopPropagation();
|
|
172
|
+
event.preventDefault();
|
|
173
|
+
callback && callback.call(element, event);
|
|
174
|
+
});
|
|
175
|
+
return this;
|
|
176
|
+
};
|
|
177
|
+
const captureEventWrapper = function(element, eventName, directHandler) {
|
|
178
|
+
if(directHandler) {
|
|
179
|
+
element.addEventListener(eventName, directHandler);
|
|
180
|
+
return this;
|
|
181
|
+
}
|
|
182
|
+
handleDelegatedCallbacks(element, eventName);
|
|
183
|
+
return this;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
for(const event of EVENTS) {
|
|
187
|
+
const eventName = event.toLowerCase();
|
|
188
|
+
NDElement.prototype['on'+event] = function(callback) {
|
|
189
|
+
this.$element.addEventListener(eventName, callback);
|
|
190
|
+
return this;
|
|
191
|
+
};
|
|
192
|
+
NDElement.prototype['onPrevent'+event] = function(callback) {
|
|
193
|
+
preventDefaultWrapper(this.$element, eventName, callback);
|
|
194
|
+
return this;
|
|
195
|
+
};
|
|
196
|
+
NDElement.prototype['onStop'+event] = function(callback) {
|
|
197
|
+
stopPropagationWrapper(this.$element, eventName, callback);
|
|
198
|
+
return this;
|
|
199
|
+
};
|
|
200
|
+
NDElement.prototype['onPreventStop'+event] = function(callback) {
|
|
201
|
+
preventDefaultAndStopPropagationWrapper(this.$element, eventName, callback);
|
|
202
|
+
return this;
|
|
203
|
+
};
|
|
204
|
+
|
|
205
|
+
NDElement.prototype['when'+event] = function(callback) {
|
|
206
|
+
addCallbackToCallbacksStore(this.$element, eventName, callback);
|
|
207
|
+
return this;
|
|
208
|
+
};
|
|
209
|
+
|
|
210
|
+
NDElement.prototype['capture'+event] = function(directHandler) {
|
|
211
|
+
captureEventWrapper(this.$element, eventName, directHandler);
|
|
212
|
+
return this;
|
|
213
|
+
};
|
|
214
|
+
}
|
|
@@ -37,6 +37,23 @@ const bindAttributes = (node, bindDingData, data) => {
|
|
|
37
37
|
return null;
|
|
38
38
|
};
|
|
39
39
|
|
|
40
|
+
const $hydrateFn = function(hydrateFunction, target, element, property) {
|
|
41
|
+
if(!cloneBindingsDataCache.has(element)) {
|
|
42
|
+
// { classes, styles, attributes, value, attach }
|
|
43
|
+
cloneBindingsDataCache.set(element, {});
|
|
44
|
+
}
|
|
45
|
+
const hydrationState = cloneBindingsDataCache.get(element);
|
|
46
|
+
if(target === 'value') {
|
|
47
|
+
hydrationState.value = hydrateFunction;
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
if(target === 'attach') {
|
|
51
|
+
hydrationState.attach = hydrateFunction;
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
hydrationState[target] = hydrationState[target] || {};
|
|
55
|
+
hydrationState[target][property] = hydrateFunction;
|
|
56
|
+
}
|
|
40
57
|
|
|
41
58
|
const bindAttachMethods = function(node, bindDingData, data) {
|
|
42
59
|
if(!bindDingData.attach) {
|
|
@@ -47,6 +64,7 @@ const bindAttachMethods = function(node, bindDingData, data) {
|
|
|
47
64
|
|
|
48
65
|
export function TemplateCloner($fn) {
|
|
49
66
|
let $node = null;
|
|
67
|
+
let $hasBindingData = false;
|
|
50
68
|
|
|
51
69
|
const clone = (node, data) => {
|
|
52
70
|
const bindDingData = cloneBindingsDataCache.get(node);
|
|
@@ -56,11 +74,14 @@ export function TemplateCloner($fn) {
|
|
|
56
74
|
}
|
|
57
75
|
return node.cloneNode(true);
|
|
58
76
|
}
|
|
59
|
-
const nodeCloned = node.cloneNode();
|
|
77
|
+
const nodeCloned = node.cloneNode(node.fullCloneNode);
|
|
60
78
|
if(bindDingData) {
|
|
61
79
|
bindAttributes(nodeCloned, bindDingData, data);
|
|
62
80
|
bindAttachMethods(nodeCloned, bindDingData, data);
|
|
63
81
|
}
|
|
82
|
+
if(node.fullCloneNode) {
|
|
83
|
+
return nodeCloned;
|
|
84
|
+
}
|
|
64
85
|
const childNodes = node.childNodes;
|
|
65
86
|
for(let i = 0, length = childNodes.length; i < length; i++) {
|
|
66
87
|
const childNode = childNodes[i];
|
|
@@ -73,31 +94,25 @@ export function TemplateCloner($fn) {
|
|
|
73
94
|
this.clone = (data) => {
|
|
74
95
|
if(!$node) {
|
|
75
96
|
$node = $fn(this);
|
|
97
|
+
if(!$hasBindingData) {
|
|
98
|
+
const nodeCloned = $node.cloneNode(true);
|
|
99
|
+
nodeCloned.fullCloneNode = true;
|
|
100
|
+
return nodeCloned;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
if(!$hasBindingData) {
|
|
104
|
+
return $node.cloneNode(true);
|
|
76
105
|
}
|
|
77
106
|
return clone($node, data);
|
|
78
107
|
};
|
|
79
108
|
|
|
80
|
-
const $hydrateFn = function(hydrateFunction, target, element, property) {
|
|
81
|
-
if(!cloneBindingsDataCache.has(element)) {
|
|
82
|
-
// { classes, styles, attributes, value, attach }
|
|
83
|
-
cloneBindingsDataCache.set(element, {});
|
|
84
|
-
}
|
|
85
|
-
const hydrationState = cloneBindingsDataCache.get(element);
|
|
86
|
-
if(target === 'value') {
|
|
87
|
-
hydrationState.value = hydrateFunction;
|
|
88
|
-
return;
|
|
89
|
-
}
|
|
90
|
-
if(target === 'attach') {
|
|
91
|
-
hydrationState.attach = hydrateFunction;
|
|
92
|
-
return;
|
|
93
|
-
}
|
|
94
|
-
hydrationState[target] = hydrationState[target] || {};
|
|
95
|
-
hydrationState[target][property] = hydrateFunction;
|
|
96
|
-
}
|
|
97
109
|
|
|
98
110
|
const createBinding = (hydrateFunction, target) => {
|
|
99
111
|
return {
|
|
100
|
-
$hydrate : (element, property) =>
|
|
112
|
+
$hydrate : (element, property) => {
|
|
113
|
+
$hasBindingData = true;
|
|
114
|
+
$hydrateFn(hydrateFunction, target, element, property)
|
|
115
|
+
},
|
|
101
116
|
}
|
|
102
117
|
};
|
|
103
118
|
|
|
@@ -147,4 +162,4 @@ export function useCache(fn) {
|
|
|
147
162
|
return function(_, __, ...args) {
|
|
148
163
|
return wrapper([_, __, ...args]);
|
|
149
164
|
};
|
|
150
|
-
}
|
|
165
|
+
}
|
package/types/control-flow.d.ts
CHANGED
|
@@ -4,11 +4,11 @@ import { ValidChild } from './elements';
|
|
|
4
4
|
|
|
5
5
|
// Control Flow Functions
|
|
6
6
|
export interface ShowIfFunction {
|
|
7
|
-
(condition: ObservableItem<boolean> | ObservableChecker<boolean>, child: ValidChild, comment?: string): DocumentFragment;
|
|
7
|
+
(condition: ObservableItem<boolean> | ObservableChecker<boolean>, child: ValidChild, options?: { comment?: string | null; shouldKeepInCache?: boolean }): DocumentFragment;
|
|
8
8
|
}
|
|
9
9
|
|
|
10
10
|
export interface HideIfFunction {
|
|
11
|
-
(condition: ObservableItem<boolean> | ObservableChecker<boolean>, child: ValidChild, comment?: string): DocumentFragment;
|
|
11
|
+
(condition: ObservableItem<boolean> | ObservableChecker<boolean>, child: ValidChild, options?: { comment?: string | null; shouldKeepInCache?: boolean }): DocumentFragment;
|
|
12
12
|
}
|
|
13
13
|
|
|
14
14
|
export interface MatchFunction {
|
|
@@ -31,14 +31,18 @@ export interface ForEachFunction {
|
|
|
31
31
|
<T>(data: T[] | Record<string, T> | ObservableItem<T[]> | ObservableItem<Record<string, T>>,
|
|
32
32
|
callback: (item: T, index?: ObservableItem<number>) => ValidChild,
|
|
33
33
|
key?: string | ((item: T, defaultKey: string | number) => string),
|
|
34
|
-
configs?: { shouldKeepItemsInCache: boolean, isParentUniqueChild: boolean
|
|
34
|
+
configs?: { shouldKeepItemsInCache: boolean, isParentUniqueChild: boolean, }): DocumentFragment,
|
|
35
35
|
}
|
|
36
36
|
|
|
37
37
|
export interface ForEachArrayFunction {
|
|
38
38
|
<T>(data: ObservableArray<T>,
|
|
39
39
|
callback: (item: T, index?: ObservableItem<number>) => ValidChild,
|
|
40
40
|
key?: string | ((item: T, defaultKey: number) => string),
|
|
41
|
-
configs?: { pushDelay?: (items: T[]) => number, isParentUniqueChild: boolean }): DocumentFragment;
|
|
41
|
+
configs?: { pushDelay?: (items: T[]) => number, isParentUniqueChild: boolean, shouldKeepItemsInCache?: boolean }): DocumentFragment;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export interface HideIfNotFunction {
|
|
45
|
+
(condition: ObservableItem<boolean> | ObservableChecker<boolean>, child: ValidChild, options?: { comment?: string | null; shouldKeepInCache?: boolean }): DocumentFragment;
|
|
42
46
|
}
|
|
43
47
|
|
|
44
48
|
// Control Flow Components
|