compelem 0.3.0-b1 → 0.3.1-b1
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.js +2 -3644
- package/package.json +1 -1
package/index.js
CHANGED
|
@@ -1,3649 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* compelem v0.3.
|
|
2
|
+
* compelem v0.3.1-b1.1739106920
|
|
3
3
|
* A modern, reactive, fast, lightweight and flexible lib for building web components
|
|
4
4
|
* @holyhigh2
|
|
5
5
|
* https://github.com/holyhigh2/compelem
|
|
6
6
|
*/
|
|
7
|
-
import { toPath, get, isObject, isDefined, isUndefined, isEmpty, has, concat, defaults, merge, cloneDeep, each, kebabCase, toArray, last, startsWith, isFunction, isArray, initial, isBlank, join, split, set, camelCase, isEqual, replace, isPlainObject, flatMap, isString, test, size, assign, first, debounce, closest, once, bind as bind$1, isNil, trim, some, isNull, fval, omit, groupBy, reject, filter, slice, compact, remove, includes, find, throttle, map, replaceAll, snakeCase, toString, reduce, isMatch, clone, findIndex, call } from 'myfx';
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* 共享内容
|
|
11
|
-
*/
|
|
12
|
-
const ChangedMap = new WeakMap;
|
|
13
|
-
const EXP_KEY = /\s+\.?key\s*=/;
|
|
14
|
-
var CollectorType;
|
|
15
|
-
(function (CollectorType) {
|
|
16
|
-
CollectorType[CollectorType["CSS"] = 1] = "CSS";
|
|
17
|
-
CollectorType[CollectorType["COMPUTED"] = 2] = "COMPUTED";
|
|
18
|
-
})(CollectorType || (CollectorType = {}));
|
|
19
|
-
var DecoratorKey;
|
|
20
|
-
(function (DecoratorKey) {
|
|
21
|
-
DecoratorKey["PROPS"] = "__deco_props";
|
|
22
|
-
DecoratorKey["STATES"] = "__deco_states";
|
|
23
|
-
DecoratorKey["COMPUTED"] = "__deco_computed";
|
|
24
|
-
DecoratorKey["WATCH"] = "__deco_watch";
|
|
25
|
-
DecoratorKey["EVENTS"] = "__deco_events";
|
|
26
|
-
})(DecoratorKey || (DecoratorKey = {}));
|
|
27
|
-
|
|
28
|
-
function showError(msg) {
|
|
29
|
-
console.error(`[CompElem]`, msg);
|
|
30
|
-
}
|
|
31
|
-
function showTagError(tagName, msg) {
|
|
32
|
-
console.error(`[CompElem <${tagName}>]`, msg);
|
|
33
|
-
}
|
|
34
|
-
function showWarn(...args) {
|
|
35
|
-
console.warn(`[CompElem]`, ...args);
|
|
36
|
-
}
|
|
37
|
-
//为依赖收集提供标准地址
|
|
38
|
-
function _toUpdatePath(varPath) {
|
|
39
|
-
return toPath(varPath).join("-");
|
|
40
|
-
}
|
|
41
|
-
//获取父类构造
|
|
42
|
-
function _getSuper(cls) {
|
|
43
|
-
return Object.getPrototypeOf(cls);
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
//装饰器类型
|
|
47
|
-
var DecoratorType;
|
|
48
|
-
(function (DecoratorType) {
|
|
49
|
-
DecoratorType["CLASS"] = "class";
|
|
50
|
-
DecoratorType["FIELD"] = "field";
|
|
51
|
-
DecoratorType["METHOD"] = "method";
|
|
52
|
-
})(DecoratorType || (DecoratorType = {}));
|
|
53
|
-
/**
|
|
54
|
-
* 用于构造装饰器
|
|
55
|
-
* @author holyhigh2
|
|
56
|
-
*/
|
|
57
|
-
class Decorator {
|
|
58
|
-
/**
|
|
59
|
-
* 优先级,越大越先执行
|
|
60
|
-
*/
|
|
61
|
-
static get priority() {
|
|
62
|
-
return 0;
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
const GetKeyFnName = 'getKey';
|
|
67
|
-
const _DecoratorsKey = '__decorators';
|
|
68
|
-
const _DecoratorMap = new WeakMap;
|
|
69
|
-
/**
|
|
70
|
-
* 装饰器包装类
|
|
71
|
-
* 用于框架内部,表示class上的一个装饰器属性定义
|
|
72
|
-
* 该定义在实例初始化时会产生装饰器实例属性
|
|
73
|
-
*/
|
|
74
|
-
class DecoratorWrapper {
|
|
75
|
-
//execute 参数
|
|
76
|
-
args;
|
|
77
|
-
//装饰器参数
|
|
78
|
-
metadata;
|
|
79
|
-
decoratorClass;
|
|
80
|
-
instanceMap;
|
|
81
|
-
key; //装饰器唯一key
|
|
82
|
-
priority = 0;
|
|
83
|
-
constructor(args, metadata, decoratorClass) {
|
|
84
|
-
this.args = args;
|
|
85
|
-
this.metadata = metadata;
|
|
86
|
-
this.decoratorClass = decoratorClass;
|
|
87
|
-
this.priority = get(decoratorClass, 'priority', 0);
|
|
88
|
-
this.instanceMap = new WeakMap;
|
|
89
|
-
}
|
|
90
|
-
//在组件构造时调用
|
|
91
|
-
create(comp) {
|
|
92
|
-
let ins = new this.decoratorClass(...this.args);
|
|
93
|
-
//1. 校验targets
|
|
94
|
-
let targets = ins.targets;
|
|
95
|
-
let decoType = undefined;
|
|
96
|
-
let descriptor = this.metadata[2];
|
|
97
|
-
if (isObject(descriptor) && isDefined(get(descriptor, 'configurable'))) {
|
|
98
|
-
decoType = DecoratorType.METHOD;
|
|
99
|
-
}
|
|
100
|
-
else if (isUndefined(this.metadata[2])) {
|
|
101
|
-
decoType = DecoratorType.FIELD;
|
|
102
|
-
}
|
|
103
|
-
if (isEmpty(targets) || !decoType || !targets.includes(decoType)) {
|
|
104
|
-
showError(`Decorator '${this.decoratorClass.name}' is out of targets, expect '${targets.join(',')}' bug got '${decoType}'`);
|
|
105
|
-
return;
|
|
106
|
-
}
|
|
107
|
-
ins.created(comp, ...this.metadata);
|
|
108
|
-
this.instanceMap.set(comp, ins);
|
|
109
|
-
}
|
|
110
|
-
beforeMount(comp, setReactive) {
|
|
111
|
-
let ins = this.instanceMap.get(comp);
|
|
112
|
-
ins.beforeMount(comp, setReactive, ...this.metadata);
|
|
113
|
-
}
|
|
114
|
-
mounted(comp, setReactive) {
|
|
115
|
-
let ins = this.instanceMap.get(comp);
|
|
116
|
-
ins.mounted(comp, setReactive, ...this.metadata);
|
|
117
|
-
}
|
|
118
|
-
updated(comp, changed) {
|
|
119
|
-
this.instanceMap.get(comp).updated(comp, changed);
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
//每个装饰器类中不同组件类中的重复key
|
|
123
|
-
const DecoKeyMap = new WeakMap();
|
|
124
|
-
/**
|
|
125
|
-
* 该函数用于创建一个装饰器
|
|
126
|
-
* @param decoClass 装饰器构造
|
|
127
|
-
* @returns 装饰器函数
|
|
128
|
-
*/
|
|
129
|
-
function decorator(decoClass) {
|
|
130
|
-
let fn = (...args) => {
|
|
131
|
-
return (...metadata) => {
|
|
132
|
-
let ctor = metadata[0].constructor;
|
|
133
|
-
let ary = get(ctor, _DecoratorsKey);
|
|
134
|
-
if (!has(ctor, _DecoratorsKey)) {
|
|
135
|
-
//继承父类
|
|
136
|
-
let parentAry = get(Object.getPrototypeOf(ctor), _DecoratorsKey);
|
|
137
|
-
ary = parentAry ? concat(parentAry) : [];
|
|
138
|
-
Reflect.defineProperty(ctor, _DecoratorsKey, {
|
|
139
|
-
configurable: false,
|
|
140
|
-
enumerable: false,
|
|
141
|
-
value: ary
|
|
142
|
-
});
|
|
143
|
-
}
|
|
144
|
-
let kMap = {};
|
|
145
|
-
let k;
|
|
146
|
-
let getKey = get(decoClass, GetKeyFnName);
|
|
147
|
-
if (getKey) {
|
|
148
|
-
let compMap = DecoKeyMap.get(decoClass);
|
|
149
|
-
if (!compMap) {
|
|
150
|
-
compMap = new WeakMap;
|
|
151
|
-
DecoKeyMap.set(decoClass, compMap);
|
|
152
|
-
}
|
|
153
|
-
kMap = compMap.get(ctor);
|
|
154
|
-
if (!kMap) {
|
|
155
|
-
kMap = {};
|
|
156
|
-
compMap.set(ctor, kMap);
|
|
157
|
-
}
|
|
158
|
-
k = getKey(...args);
|
|
159
|
-
if (kMap[k])
|
|
160
|
-
return kMap[k];
|
|
161
|
-
}
|
|
162
|
-
let dw = new DecoratorWrapper(args, metadata, decoClass);
|
|
163
|
-
kMap[k] = dw;
|
|
164
|
-
ary?.push(dw);
|
|
165
|
-
return dw;
|
|
166
|
-
};
|
|
167
|
-
};
|
|
168
|
-
_DecoratorMap.set(fn, true);
|
|
169
|
-
return fn;
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
//每个类需要监控的属性
|
|
173
|
-
const ObservedAttrsMap = new WeakMap;
|
|
174
|
-
function prop(options) {
|
|
175
|
-
if (arguments.length === 1) {
|
|
176
|
-
return (target, propertyKey, descriptor) => {
|
|
177
|
-
options.required = options.required || false;
|
|
178
|
-
options.attribute = options.attribute === false ? false : true;
|
|
179
|
-
defineProp(target, propertyKey, options, descriptor);
|
|
180
|
-
};
|
|
181
|
-
}
|
|
182
|
-
let target = arguments[0], propertyKey = arguments[1], descriptor = arguments[2];
|
|
183
|
-
options = { type: undefined, required: false, attribute: true };
|
|
184
|
-
if (descriptor && typeof descriptor.type === 'function') {
|
|
185
|
-
options = defaults(descriptor, options);
|
|
186
|
-
descriptor = undefined;
|
|
187
|
-
}
|
|
188
|
-
defineProp(target, propertyKey, options, descriptor);
|
|
189
|
-
}
|
|
190
|
-
function defineProp(target, propertyKey, options, descriptor) {
|
|
191
|
-
if (!/[a-z]/.test(propertyKey[0])) {
|
|
192
|
-
showError(`Prop '${propertyKey}' must be in CamelCase`);
|
|
193
|
-
}
|
|
194
|
-
let attrSet;
|
|
195
|
-
if (!has(target.constructor, DecoratorKey.PROPS)) {
|
|
196
|
-
const mixinProps = {};
|
|
197
|
-
let parentCtor = target.constructor;
|
|
198
|
-
while ((parentCtor = _getSuper(parentCtor)) !== CompElem) {
|
|
199
|
-
merge(mixinProps, parentCtor[DecoratorKey.PROPS] ? cloneDeep(parentCtor[DecoratorKey.PROPS]) : {});
|
|
200
|
-
}
|
|
201
|
-
Reflect.defineProperty(target.constructor, DecoratorKey.PROPS, {
|
|
202
|
-
configurable: false,
|
|
203
|
-
enumerable: false,
|
|
204
|
-
value: mixinProps
|
|
205
|
-
});
|
|
206
|
-
attrSet = new Set();
|
|
207
|
-
each(mixinProps, (v, k) => {
|
|
208
|
-
if (v.attribute) {
|
|
209
|
-
let kbb = kebabCase(k);
|
|
210
|
-
attrSet?.add(kbb);
|
|
211
|
-
}
|
|
212
|
-
});
|
|
213
|
-
ObservedAttrsMap.set(target.constructor, attrSet);
|
|
214
|
-
}
|
|
215
|
-
if (descriptor) {
|
|
216
|
-
if (descriptor.get)
|
|
217
|
-
options.getter = descriptor.get;
|
|
218
|
-
if (descriptor.set)
|
|
219
|
-
options.setter = descriptor.set;
|
|
220
|
-
}
|
|
221
|
-
if (options.attribute) {
|
|
222
|
-
if (!attrSet) {
|
|
223
|
-
attrSet = ObservedAttrsMap.get(target.constructor);
|
|
224
|
-
}
|
|
225
|
-
let kbb = kebabCase(propertyKey);
|
|
226
|
-
attrSet?.add(kbb);
|
|
227
|
-
}
|
|
228
|
-
//observeAttrs
|
|
229
|
-
if (!has(target.constructor, 'observedAttributes')) {
|
|
230
|
-
target.constructor.observedAttributes = [];
|
|
231
|
-
}
|
|
232
|
-
target.constructor.observedAttributes = toArray(attrSet);
|
|
233
|
-
target.constructor[DecoratorKey.PROPS][propertyKey] = options;
|
|
234
|
-
}
|
|
235
|
-
//内部接口
|
|
236
|
-
const emptySet = new Set;
|
|
237
|
-
function _getObservedAttrs(ctor) {
|
|
238
|
-
return ObservedAttrsMap.get(ctor) ?? emptySet;
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
/**
|
|
242
|
-
* 用于提供全局state状态管理
|
|
243
|
-
* @author holyhigh2
|
|
244
|
-
*/
|
|
245
|
-
const EVENT_UPDATE = 'update';
|
|
246
|
-
const Collector = {
|
|
247
|
-
collectWatch(comp, updater, subPath) {
|
|
248
|
-
let collectVarMap = WATCH_MAP.get(comp);
|
|
249
|
-
if (!collectVarMap) {
|
|
250
|
-
collectVarMap = {};
|
|
251
|
-
WATCH_MAP.set(comp, collectVarMap);
|
|
252
|
-
}
|
|
253
|
-
let list = collectVarMap[subPath];
|
|
254
|
-
if (!list)
|
|
255
|
-
list = collectVarMap[subPath] = [];
|
|
256
|
-
list.push(updater);
|
|
257
|
-
},
|
|
258
|
-
startCollect(comp, type) {
|
|
259
|
-
this.__collectType = type;
|
|
260
|
-
this.__collecting = comp;
|
|
261
|
-
},
|
|
262
|
-
setUpdater(updater) {
|
|
263
|
-
this.__updater = updater;
|
|
264
|
-
},
|
|
265
|
-
endCollect() {
|
|
266
|
-
this.__collecting = null;
|
|
267
|
-
},
|
|
268
|
-
//仅用于指令在构造时获取
|
|
269
|
-
__directiveQ: [],
|
|
270
|
-
setDirectiveQ(val) {
|
|
271
|
-
let lastVar = last(this.__directiveQ);
|
|
272
|
-
const vj = val ? val.join(',') : '';
|
|
273
|
-
const lj = lastVar ? lastVar.join(',') : '';
|
|
274
|
-
if (lastVar && vj === lj)
|
|
275
|
-
return;
|
|
276
|
-
if (lastVar && lastVar.length < val.length && startsWith(vj, lj)) {
|
|
277
|
-
this.__directiveQ[this.__directiveQ.length - 1] = val;
|
|
278
|
-
return;
|
|
279
|
-
}
|
|
280
|
-
this.__directiveQ.push(val);
|
|
281
|
-
},
|
|
282
|
-
popDirectiveQ() {
|
|
283
|
-
let rs = concat(this.__directiveQ);
|
|
284
|
-
this.__directiveQ = [];
|
|
285
|
-
return rs;
|
|
286
|
-
},
|
|
287
|
-
startRender(context) {
|
|
288
|
-
this.__renderCollecting = true;
|
|
289
|
-
this.__renderContext = context;
|
|
290
|
-
},
|
|
291
|
-
endRender(component) {
|
|
292
|
-
//注册依赖
|
|
293
|
-
this.__renderCollection.forEach((varPath) => {
|
|
294
|
-
component._regDeps(varPath, this.__renderContext);
|
|
295
|
-
});
|
|
296
|
-
this.__renderCollection.clear();
|
|
297
|
-
this.__renderCollecting = false;
|
|
298
|
-
this.__renderContext = null;
|
|
299
|
-
},
|
|
300
|
-
collect(prop) {
|
|
301
|
-
this.__renderCollection.add(prop);
|
|
302
|
-
},
|
|
303
|
-
clear() {
|
|
304
|
-
this.__directiveQ = [];
|
|
305
|
-
},
|
|
306
|
-
__updater: null,
|
|
307
|
-
__collecting: null,
|
|
308
|
-
__collectType: -1,
|
|
309
|
-
__renderCollection: new Set(),
|
|
310
|
-
__renderContext: null,
|
|
311
|
-
__renderCollecting: false,
|
|
312
|
-
__skipCheck: false
|
|
313
|
-
};
|
|
314
|
-
const OBJECT_META_DATA = new WeakMap();
|
|
315
|
-
const OBJECT_VAR_PATH = new WeakMap();
|
|
316
|
-
const COMPUTED_MAP = new WeakMap();
|
|
317
|
-
const CSS_MAP = new WeakMap();
|
|
318
|
-
const WATCH_MAP = new WeakMap();
|
|
319
|
-
/**
|
|
320
|
-
* 1. 初始化时obj都是普通对象
|
|
321
|
-
* 2. OBJECT_VAR_PATH 首次是普通对象
|
|
322
|
-
* 3. OBJECT_META_DATA 直接绑定代理对象
|
|
323
|
-
* @param obj
|
|
324
|
-
* @param context
|
|
325
|
-
* @returns
|
|
326
|
-
*/
|
|
327
|
-
function reactive(obj, context) {
|
|
328
|
-
if (!isObject(obj))
|
|
329
|
-
return obj;
|
|
330
|
-
const proxyObject = obj.__proxy ? obj : new Proxy(obj, {
|
|
331
|
-
get(target, prop, receiver) {
|
|
332
|
-
if (!prop)
|
|
333
|
-
return undefined;
|
|
334
|
-
const value = Reflect.get(target, prop, receiver);
|
|
335
|
-
if ((Collector.__renderCollecting || Collector.__collecting) && target.hasOwnProperty(prop)) {
|
|
336
|
-
let chain = OBJECT_VAR_PATH.get(receiver) ?? [];
|
|
337
|
-
let subChain = concat(chain, [prop]);
|
|
338
|
-
let subChainStr = subChain.join('-');
|
|
339
|
-
if (Collector.__renderCollecting) {
|
|
340
|
-
Collector.collect(_toUpdatePath(subChain));
|
|
341
|
-
Collector.setDirectiveQ(subChain);
|
|
342
|
-
}
|
|
343
|
-
else if (Collector.__collecting) {
|
|
344
|
-
let collectVarMap;
|
|
345
|
-
switch (Collector.__collectType) {
|
|
346
|
-
case CollectorType.COMPUTED:
|
|
347
|
-
collectVarMap = COMPUTED_MAP.get(Collector.__collecting);
|
|
348
|
-
if (!collectVarMap) {
|
|
349
|
-
collectVarMap = {};
|
|
350
|
-
COMPUTED_MAP.set(Collector.__collecting, collectVarMap);
|
|
351
|
-
}
|
|
352
|
-
break;
|
|
353
|
-
case CollectorType.CSS:
|
|
354
|
-
collectVarMap = CSS_MAP.get(Collector.__collecting);
|
|
355
|
-
if (!collectVarMap) {
|
|
356
|
-
collectVarMap = {};
|
|
357
|
-
CSS_MAP.set(Collector.__collecting, collectVarMap);
|
|
358
|
-
}
|
|
359
|
-
break;
|
|
360
|
-
}
|
|
361
|
-
let list = collectVarMap[subChainStr];
|
|
362
|
-
if (!list)
|
|
363
|
-
list = collectVarMap[subChainStr] = [];
|
|
364
|
-
list.push(Collector.__updater);
|
|
365
|
-
}
|
|
366
|
-
}
|
|
367
|
-
return value;
|
|
368
|
-
},
|
|
369
|
-
set(target, prop, newValue, receiver) {
|
|
370
|
-
if (!prop)
|
|
371
|
-
return false;
|
|
372
|
-
let ov = target[prop];
|
|
373
|
-
if (!isObject(ov) && ov === newValue)
|
|
374
|
-
return true;
|
|
375
|
-
if (Number.isNaN(newValue) && Number.isNaN(ov))
|
|
376
|
-
return true;
|
|
377
|
-
let chain = OBJECT_VAR_PATH.get(receiver) ?? [];
|
|
378
|
-
let subChain = concat(chain, [prop]);
|
|
379
|
-
let sourceContext = OBJECT_META_DATA.get(receiver).from;
|
|
380
|
-
let propDefs = get(sourceContext.constructor, DecoratorKey.PROPS);
|
|
381
|
-
let stateDefs = get(sourceContext.constructor, DecoratorKey.STATES);
|
|
382
|
-
let hasChanged = get(propDefs, [subChain[0], 'hasChanged']) || get(stateDefs, [subChain[0], 'hasChanged']);
|
|
383
|
-
if (hasChanged) {
|
|
384
|
-
if (!hasChanged.call(sourceContext, newValue, ov))
|
|
385
|
-
return true;
|
|
386
|
-
}
|
|
387
|
-
else {
|
|
388
|
-
//默认对比算法
|
|
389
|
-
if (ov === newValue && !ChangedMap.has(ov)) {
|
|
390
|
-
return true;
|
|
391
|
-
}
|
|
392
|
-
}
|
|
393
|
-
if (propDefs && propDefs[prop] && target.__isData) {
|
|
394
|
-
if (propDefs[prop].sync) {
|
|
395
|
-
sourceContext.emit(EVENT_UPDATE + ":" + prop, { value: newValue });
|
|
396
|
-
}
|
|
397
|
-
}
|
|
398
|
-
let deps = OBJECT_META_DATA.get(receiver)?.contextSet;
|
|
399
|
-
//get oldValue from sourceContext
|
|
400
|
-
let nv = newValue;
|
|
401
|
-
if (isObject(newValue) && !isFunction(newValue) && !(newValue instanceof Node) && !Object.isFrozen(newValue)) {
|
|
402
|
-
deps.forEach(dep => {
|
|
403
|
-
let pathMap = OBJECT_META_DATA.get(receiver)?.pathMap;
|
|
404
|
-
let pathAry = pathMap?.get(dep);
|
|
405
|
-
if (!pathAry)
|
|
406
|
-
return;
|
|
407
|
-
subChain = concat(pathAry, [prop]);
|
|
408
|
-
OBJECT_VAR_PATH.set(nv, subChain);
|
|
409
|
-
nv = reactive(nv, dep);
|
|
410
|
-
OBJECT_VAR_PATH.set(nv, subChain);
|
|
411
|
-
});
|
|
412
|
-
}
|
|
413
|
-
let rs = Reflect.set(target, prop, nv);
|
|
414
|
-
let pathMap = OBJECT_META_DATA.get(receiver).pathMap;
|
|
415
|
-
deps.forEach(dep => {
|
|
416
|
-
//view update
|
|
417
|
-
let pathAry = pathMap.get(dep);
|
|
418
|
-
if (!pathAry)
|
|
419
|
-
return;
|
|
420
|
-
if (dep === sourceContext) {
|
|
421
|
-
//fix the index change of array item
|
|
422
|
-
if (chain.length > 1 && pathAry.length > 1 && chain[0] === pathAry[0]) {
|
|
423
|
-
pathAry = chain;
|
|
424
|
-
}
|
|
425
|
-
}
|
|
426
|
-
//数组length属性变动直接通知为数组自身变动
|
|
427
|
-
subChain = concat(pathAry, prop == 'length' && isArray(receiver) ? [] : [prop]);
|
|
428
|
-
//computed
|
|
429
|
-
let computedMap = COMPUTED_MAP.get(dep);
|
|
430
|
-
//css
|
|
431
|
-
let cssMap = CSS_MAP.get(dep);
|
|
432
|
-
//watch
|
|
433
|
-
let watchMap = WATCH_MAP.get(dep);
|
|
434
|
-
//recur path
|
|
435
|
-
if (computedMap || cssMap || watchMap) {
|
|
436
|
-
let i = subChain.length;
|
|
437
|
-
while (i) {
|
|
438
|
-
let subPath = subChain.slice(0, i).join('-');
|
|
439
|
-
if (watchMap) {
|
|
440
|
-
const watchList = watchMap[subPath];
|
|
441
|
-
if (i === subChain.length) {
|
|
442
|
-
watchList?.forEach((wk) => {
|
|
443
|
-
let updater = wk();
|
|
444
|
-
updater.ov = ov;
|
|
445
|
-
// wk()(ov)
|
|
446
|
-
Queue.pushWatch(updater);
|
|
447
|
-
});
|
|
448
|
-
}
|
|
449
|
-
else {
|
|
450
|
-
watchList?.forEach((wk) => {
|
|
451
|
-
let updater = wk();
|
|
452
|
-
if (get(updater, 'deep')) {
|
|
453
|
-
// updater(ov)
|
|
454
|
-
updater.ov = ov;
|
|
455
|
-
Queue.pushWatch(updater);
|
|
456
|
-
}
|
|
457
|
-
});
|
|
458
|
-
}
|
|
459
|
-
}
|
|
460
|
-
if (computedMap) {
|
|
461
|
-
let computedList = computedMap[subPath];
|
|
462
|
-
if (!isEmpty(computedList)) {
|
|
463
|
-
for (let l = 0; l < computedList.length; l++) {
|
|
464
|
-
const updater = computedList[l];
|
|
465
|
-
// updater()
|
|
466
|
-
Queue.pushComputed(updater);
|
|
467
|
-
}
|
|
468
|
-
}
|
|
469
|
-
}
|
|
470
|
-
if (cssMap) {
|
|
471
|
-
let computedCssList = cssMap[subPath];
|
|
472
|
-
if (!isEmpty(computedCssList)) {
|
|
473
|
-
for (let l = 0; l < computedCssList.length; l++) {
|
|
474
|
-
const updater = computedCssList[l];
|
|
475
|
-
// updater()
|
|
476
|
-
Queue.pushCss(updater);
|
|
477
|
-
}
|
|
478
|
-
}
|
|
479
|
-
}
|
|
480
|
-
i--;
|
|
481
|
-
}
|
|
482
|
-
}
|
|
483
|
-
let updater = dep._notify(ov, subChain);
|
|
484
|
-
Queue.pushNext(updater);
|
|
485
|
-
});
|
|
486
|
-
return rs;
|
|
487
|
-
}
|
|
488
|
-
});
|
|
489
|
-
if (!obj.__proxy) {
|
|
490
|
-
Reflect.defineProperty(obj, "__proxy", {
|
|
491
|
-
enumerable: false,
|
|
492
|
-
writable: false,
|
|
493
|
-
configurable: false,
|
|
494
|
-
value: true,
|
|
495
|
-
});
|
|
496
|
-
}
|
|
497
|
-
let chain = OBJECT_VAR_PATH.get(obj) ?? [];
|
|
498
|
-
if (Object.isExtensible(obj) && !OBJECT_META_DATA.get(proxyObject)) {
|
|
499
|
-
let contextSet = new Set();
|
|
500
|
-
contextSet.add(context);
|
|
501
|
-
//对象所属context
|
|
502
|
-
let pathMap = new WeakMap();
|
|
503
|
-
pathMap.set(context, chain);
|
|
504
|
-
OBJECT_META_DATA.set(proxyObject, {
|
|
505
|
-
from: context,
|
|
506
|
-
contextSet,
|
|
507
|
-
pathMap
|
|
508
|
-
});
|
|
509
|
-
}
|
|
510
|
-
else {
|
|
511
|
-
let deps = OBJECT_META_DATA.get(proxyObject).contextSet;
|
|
512
|
-
deps.add(context);
|
|
513
|
-
let pathMap = OBJECT_META_DATA.get(proxyObject).pathMap;
|
|
514
|
-
let chains = pathMap.get(context);
|
|
515
|
-
let subChain = concat(chain);
|
|
516
|
-
if (chains && chains.join('') !== subChain.join('')) {
|
|
517
|
-
let parentVar = get(context, initial(chains));
|
|
518
|
-
//处理数组元素更新,如 ary.1 -> ary.0
|
|
519
|
-
if (!isArray(parentVar)) {
|
|
520
|
-
showWarn(`The object is referenced by more than one @state '${subChain.join('.')},${chains.join('.')}'`);
|
|
521
|
-
}
|
|
522
|
-
chains = subChain;
|
|
523
|
-
}
|
|
524
|
-
else {
|
|
525
|
-
pathMap.set(context, subChain);
|
|
526
|
-
}
|
|
527
|
-
}
|
|
528
|
-
for (let k in obj) {
|
|
529
|
-
const v = obj[k];
|
|
530
|
-
if (isObject(v) && !v.__proxy && !isFunction(v) && !(v instanceof Node) && !Object.isFrozen(v)) {
|
|
531
|
-
OBJECT_VAR_PATH.set(v, concat(chain, [k]));
|
|
532
|
-
obj[k] = reactive(v, context);
|
|
533
|
-
OBJECT_VAR_PATH.set(obj[k], concat(chain, [k]));
|
|
534
|
-
}
|
|
535
|
-
}
|
|
536
|
-
return proxyObject;
|
|
537
|
-
}
|
|
538
|
-
class Queue {
|
|
539
|
-
static watchSet = new Set();
|
|
540
|
-
static computedSet = new Set();
|
|
541
|
-
static cssSet = new Set();
|
|
542
|
-
static nextSet = new Set();
|
|
543
|
-
static nextPending = false;
|
|
544
|
-
static next;
|
|
545
|
-
static {
|
|
546
|
-
const p = Promise.resolve();
|
|
547
|
-
const nextFn = Queue.flush;
|
|
548
|
-
Queue.next = () => {
|
|
549
|
-
p.then(nextFn);
|
|
550
|
-
};
|
|
551
|
-
}
|
|
552
|
-
static flush() {
|
|
553
|
-
Queue.nextPending = false;
|
|
554
|
-
let wq = Array.from(Queue.watchSet);
|
|
555
|
-
Queue.watchSet.clear();
|
|
556
|
-
let cq = Array.from(Queue.computedSet);
|
|
557
|
-
Queue.computedSet.clear();
|
|
558
|
-
let sq = Array.from(Queue.cssSet);
|
|
559
|
-
Queue.cssSet.clear();
|
|
560
|
-
let nq = Array.from(Queue.nextSet);
|
|
561
|
-
Queue.nextSet.clear();
|
|
562
|
-
wq.forEach(u => u(get(u, 'ov')));
|
|
563
|
-
cq.forEach(u => u());
|
|
564
|
-
sq.forEach(u => u());
|
|
565
|
-
nq.forEach(u => u());
|
|
566
|
-
}
|
|
567
|
-
static pushWatch(updater) {
|
|
568
|
-
Queue.watchSet.add(updater);
|
|
569
|
-
}
|
|
570
|
-
static pushComputed(updater) {
|
|
571
|
-
Queue.computedSet.add(updater);
|
|
572
|
-
}
|
|
573
|
-
static pushCss(updater) {
|
|
574
|
-
Queue.cssSet.add(updater);
|
|
575
|
-
}
|
|
576
|
-
static pushNext(updater) {
|
|
577
|
-
Queue.nextSet.add(updater);
|
|
578
|
-
if (!Queue.nextPending) {
|
|
579
|
-
Queue.nextPending = true;
|
|
580
|
-
Queue.next();
|
|
581
|
-
}
|
|
582
|
-
}
|
|
583
|
-
}
|
|
584
|
-
|
|
585
|
-
/**
|
|
586
|
-
* 视图基类 为组件视图及指令子视图提供统一服务
|
|
587
|
-
* @param spuerClass
|
|
588
|
-
* @returns
|
|
589
|
-
*/
|
|
590
|
-
function View(spuerClass) {
|
|
591
|
-
//mixin class
|
|
592
|
-
return class extends spuerClass {
|
|
593
|
-
__updatePoints;
|
|
594
|
-
/**
|
|
595
|
-
* 渲染上下文所属组件,仅用于指令
|
|
596
|
-
*/
|
|
597
|
-
renderComponent;
|
|
598
|
-
buildView(tmpl) {
|
|
599
|
-
let comp = this instanceof CompElem ? this : this.renderComponent;
|
|
600
|
-
let [html, vars] = buildHTML(comp, tmpl);
|
|
601
|
-
let updatePoints = [];
|
|
602
|
-
let nodes = buildTmplate(updatePoints, html, vars, comp, this);
|
|
603
|
-
this.__updatePoints = updatePoints;
|
|
604
|
-
return nodes;
|
|
605
|
-
}
|
|
606
|
-
updateView(tmpl) {
|
|
607
|
-
if (isBlank(join(tmpl.strings)))
|
|
608
|
-
return;
|
|
609
|
-
if (!this.__updatePoints)
|
|
610
|
-
return;
|
|
611
|
-
let { vars } = tmpl;
|
|
612
|
-
let comp = this instanceof CompElem ? this : this.renderComponent;
|
|
613
|
-
for (let i = 0; i < this.__updatePoints.length; i++) {
|
|
614
|
-
const up = this.__updatePoints[i];
|
|
615
|
-
let varIndex = up.varIndex;
|
|
616
|
-
let oldValue = up.value;
|
|
617
|
-
let newValue = vars;
|
|
618
|
-
let node = up.node;
|
|
619
|
-
let indexSegs = split(varIndex, '-');
|
|
620
|
-
for (let l = 0; l < indexSegs.length; l++) {
|
|
621
|
-
const seg = indexSegs[l];
|
|
622
|
-
newValue = get(newValue, seg);
|
|
623
|
-
if (newValue && newValue.vars && i < indexSegs.length - 1) {
|
|
624
|
-
newValue = newValue.vars;
|
|
625
|
-
}
|
|
626
|
-
}
|
|
627
|
-
//check
|
|
628
|
-
if (!isObject(oldValue) && oldValue === newValue)
|
|
629
|
-
continue;
|
|
630
|
-
let elNode = node;
|
|
631
|
-
if (up.isDirective) {
|
|
632
|
-
if (!oldValue.di)
|
|
633
|
-
continue; //指令还在异步执行中,不更新
|
|
634
|
-
//指令
|
|
635
|
-
newValue.di = oldValue.di;
|
|
636
|
-
newValue.di.renderParams = newValue.varChain;
|
|
637
|
-
newValue.di._renderArgs = newValue.args;
|
|
638
|
-
newValue.point = oldValue.point;
|
|
639
|
-
newValue.varPath = oldValue.varPath;
|
|
640
|
-
oldValue.update(oldValue.point, newValue.args, oldValue.args);
|
|
641
|
-
}
|
|
642
|
-
else if (up.isToggleProp) {
|
|
643
|
-
//布尔特性
|
|
644
|
-
if ((!!newValue) === oldValue)
|
|
645
|
-
continue;
|
|
646
|
-
elNode.toggleAttribute(up.attrName, !!newValue);
|
|
647
|
-
set(elNode, up.attrName, !!newValue);
|
|
648
|
-
}
|
|
649
|
-
else if (up.isProp) {
|
|
650
|
-
//子组件属性
|
|
651
|
-
if (!isObject(newValue) && newValue === oldValue)
|
|
652
|
-
continue;
|
|
653
|
-
let ck = camelCase(up.attrName);
|
|
654
|
-
let propDefs = get(up.node.constructor, DecoratorKey.PROPS);
|
|
655
|
-
if (propDefs) {
|
|
656
|
-
let propDef = propDefs[ck];
|
|
657
|
-
if (propDef && propDef.hasChanged && !propDef.hasChanged.call(this, newValue, oldValue))
|
|
658
|
-
continue;
|
|
659
|
-
}
|
|
660
|
-
// if (isPlainObject(newValue) && isEqual(newValue, oldValue)) continue;
|
|
661
|
-
// if (isArray(newValue) && isArray(oldValue) && isEqual(newValue, oldValue)) continue;
|
|
662
|
-
//如果node是slot则触发组件的slot更新
|
|
663
|
-
if (node instanceof CompElem) {
|
|
664
|
-
node._updateProps({ [up.attrName]: newValue });
|
|
665
|
-
}
|
|
666
|
-
else if (node instanceof HTMLSlotElement) {
|
|
667
|
-
comp._updateSlot(node.getAttribute('name') || 'default', up.attrName, newValue);
|
|
668
|
-
}
|
|
669
|
-
}
|
|
670
|
-
else if (up.attrName && !up.isEvent) {
|
|
671
|
-
//特性
|
|
672
|
-
if (!isEqual(oldValue, newValue)) {
|
|
673
|
-
switch (up.attrName) {
|
|
674
|
-
case 'value':
|
|
675
|
-
if (node instanceof HTMLInputElement) {
|
|
676
|
-
node.value = newValue;
|
|
677
|
-
break;
|
|
678
|
-
}
|
|
679
|
-
default:
|
|
680
|
-
node.setAttribute(up.attrName, replace(up.attrTmpl, PLACEHOLDER_EXP, newValue + ''));
|
|
681
|
-
}
|
|
682
|
-
}
|
|
683
|
-
}
|
|
684
|
-
else if (up.isTmpl) {
|
|
685
|
-
//这里一定是子视图更新,子视图仅更新内部__expose
|
|
686
|
-
if (newValue.strings.join() !== oldValue.tmpl.strings.join()) {
|
|
687
|
-
up.value.updateView(newValue);
|
|
688
|
-
}
|
|
689
|
-
else if (newValue.vars.some((v) => isObject(v) && !isPlainObject(v)) || oldValue.tmpl.vars.some((v) => isObject(v) && !isPlainObject(v)) || !isEqual(newValue.vars, oldValue.tmpl.vars)) {
|
|
690
|
-
up.value.updateView(newValue);
|
|
691
|
-
}
|
|
692
|
-
oldValue.tmpl = newValue;
|
|
693
|
-
newValue = oldValue; //new SubView(newValue)
|
|
694
|
-
}
|
|
695
|
-
else if (up.isText) {
|
|
696
|
-
let textNode = up.textNode.nextSibling;
|
|
697
|
-
if (textNode && textNode === up.node.previousSibling) {
|
|
698
|
-
textNode.textContent = newValue;
|
|
699
|
-
}
|
|
700
|
-
else {
|
|
701
|
-
DomUtil.remove(up.textNode, up.node);
|
|
702
|
-
DomUtil.insertBefore(up.node, [newValue]);
|
|
703
|
-
}
|
|
704
|
-
}
|
|
705
|
-
up.value = newValue;
|
|
706
|
-
} //endfor
|
|
707
|
-
}
|
|
708
|
-
};
|
|
709
|
-
}
|
|
710
|
-
/**
|
|
711
|
-
* 子视图,用于组件视图模板中的非指令子模版
|
|
712
|
-
*/
|
|
713
|
-
class SubView extends View(Object) {
|
|
714
|
-
tmpl;
|
|
715
|
-
constructor(tmpl) {
|
|
716
|
-
super();
|
|
717
|
-
this._renderVars = get(tmpl, '_renderVars');
|
|
718
|
-
this.tmpl = tmpl;
|
|
719
|
-
}
|
|
720
|
-
}
|
|
721
|
-
|
|
722
|
-
const ATTR_CSS_LINK = "css-link";
|
|
723
|
-
const PropTypeMap = {
|
|
724
|
-
boolean: Boolean,
|
|
725
|
-
string: String,
|
|
726
|
-
number: Number,
|
|
727
|
-
object: Object,
|
|
728
|
-
array: Array,
|
|
729
|
-
function: Function,
|
|
730
|
-
bigint: BigInt,
|
|
731
|
-
symbol: Symbol,
|
|
732
|
-
undefined: Object
|
|
733
|
-
};
|
|
734
|
-
const PrivatePreffix = '#';
|
|
735
|
-
//组件静态样式
|
|
736
|
-
const ComponentStyleMap = new WeakMap();
|
|
737
|
-
let DefaultCss = [];
|
|
738
|
-
/**
|
|
739
|
-
* CompElem基类,意为组件元素。提供了基本内置属性及生命周期等必备接口
|
|
740
|
-
* 每个组件都需要继承自该类
|
|
741
|
-
*
|
|
742
|
-
* @author holyhigh2
|
|
743
|
-
*/
|
|
744
|
-
class CompElem extends View(HTMLElement) {
|
|
745
|
-
static __l_globalRule = document.createElement("style");
|
|
746
|
-
static {
|
|
747
|
-
document.head.appendChild(CompElem.__l_globalRule);
|
|
748
|
-
}
|
|
749
|
-
//设置全局/组件默认属性
|
|
750
|
-
static defaults(options) {
|
|
751
|
-
DefaultCss = flatMap(options.css, c => {
|
|
752
|
-
if (isString(c)) {
|
|
753
|
-
let sheet = new CSSStyleSheet();
|
|
754
|
-
sheet.replaceSync(c);
|
|
755
|
-
return sheet;
|
|
756
|
-
}
|
|
757
|
-
else if (c instanceof CSSStyleSheet) {
|
|
758
|
-
return c;
|
|
759
|
-
}
|
|
760
|
-
return [];
|
|
761
|
-
});
|
|
762
|
-
//todo...
|
|
763
|
-
options.global;
|
|
764
|
-
each(options, (v, k) => {
|
|
765
|
-
if (test(k[0], /[A-Z]/)) ;
|
|
766
|
-
});
|
|
767
|
-
}
|
|
768
|
-
#slotPropsMap = {};
|
|
769
|
-
#data = { '#slots': {} };
|
|
770
|
-
#reactiveData = {};
|
|
771
|
-
#updateSources = {};
|
|
772
|
-
#shadow;
|
|
773
|
-
#selfObserver;
|
|
774
|
-
//保存所有渲染上下文 {CompElem/Directive}
|
|
775
|
-
#renderContextList = {};
|
|
776
|
-
__events = {};
|
|
777
|
-
get [Symbol.toStringTag]() {
|
|
778
|
-
return this.constructor.name;
|
|
779
|
-
}
|
|
780
|
-
get reactiveData() {
|
|
781
|
-
return this.#reactiveData;
|
|
782
|
-
}
|
|
783
|
-
get attrs() {
|
|
784
|
-
return this.#attrs;
|
|
785
|
-
}
|
|
786
|
-
get props() {
|
|
787
|
-
return this.#props;
|
|
788
|
-
}
|
|
789
|
-
get renderRoot() {
|
|
790
|
-
return this.#renderRoot;
|
|
791
|
-
}
|
|
792
|
-
get renderRoots() {
|
|
793
|
-
return this.#renderRoots;
|
|
794
|
-
}
|
|
795
|
-
get parentComponent() {
|
|
796
|
-
return this.#parentComponent;
|
|
797
|
-
}
|
|
798
|
-
get slotHooks() {
|
|
799
|
-
return this.#slotHooks;
|
|
800
|
-
}
|
|
801
|
-
get css() {
|
|
802
|
-
return ComponentStyleMap.get(this.constructor);
|
|
803
|
-
}
|
|
804
|
-
get isMounted() {
|
|
805
|
-
return this.#mounted;
|
|
806
|
-
}
|
|
807
|
-
//slots列表中绝对不会出现slot元素
|
|
808
|
-
get slots() {
|
|
809
|
-
return this.#data['#slots'];
|
|
810
|
-
}
|
|
811
|
-
#attrs;
|
|
812
|
-
#props;
|
|
813
|
-
#renderRoot;
|
|
814
|
-
#renderRoots;
|
|
815
|
-
#parentComponent;
|
|
816
|
-
#slotsEl = {};
|
|
817
|
-
#slotHooks = {};
|
|
818
|
-
#slotNodes = {};
|
|
819
|
-
#mounted = false;
|
|
820
|
-
/**
|
|
821
|
-
* 是否自动插入插槽,如果需要控制插槽类型时,可以设置为false
|
|
822
|
-
*/
|
|
823
|
-
static get autoSlot() {
|
|
824
|
-
return true;
|
|
825
|
-
}
|
|
826
|
-
//////////////////////////////////// styles
|
|
827
|
-
/**
|
|
828
|
-
* 组件样式,CSSStyleSheet可动态变更
|
|
829
|
-
*/
|
|
830
|
-
static get styles() {
|
|
831
|
-
return [];
|
|
832
|
-
}
|
|
833
|
-
static get globalStyles() {
|
|
834
|
-
return [];
|
|
835
|
-
}
|
|
836
|
-
get styles() {
|
|
837
|
-
return [];
|
|
838
|
-
}
|
|
839
|
-
#inited = false;
|
|
840
|
-
constructor(...args) {
|
|
841
|
-
super();
|
|
842
|
-
//init props via constructor
|
|
843
|
-
if (size(args) === 1) {
|
|
844
|
-
this.#props = {};
|
|
845
|
-
assign(this.#props, first(args));
|
|
846
|
-
}
|
|
847
|
-
let render = this.render.bind(this);
|
|
848
|
-
this.render = function () {
|
|
849
|
-
let rs;
|
|
850
|
-
Collector.startRender(this);
|
|
851
|
-
rs = render();
|
|
852
|
-
Collector.endRender(this);
|
|
853
|
-
return rs;
|
|
854
|
-
};
|
|
855
|
-
/////////////////////////////////////////////////// styles
|
|
856
|
-
//global styles
|
|
857
|
-
let globalStyles = get(this.constructor, "globalStyles");
|
|
858
|
-
let beAttached = get(this.constructor, '_global_style_attached');
|
|
859
|
-
if (!isEmpty(globalStyles) && beAttached !== '1') {
|
|
860
|
-
let globalTextContent = "";
|
|
861
|
-
globalStyles.forEach((st) => {
|
|
862
|
-
if (isString(st)) {
|
|
863
|
-
globalTextContent += st + "\n";
|
|
864
|
-
}
|
|
865
|
-
});
|
|
866
|
-
CompElem.__l_globalRule.textContent += globalTextContent;
|
|
867
|
-
set(this.constructor, '_global_style_attached', '1');
|
|
868
|
-
}
|
|
869
|
-
//component styles
|
|
870
|
-
let beAttached2 = ComponentStyleMap.get(this.constructor);
|
|
871
|
-
let styleSheets = beAttached2 ?? [];
|
|
872
|
-
if (!beAttached2) {
|
|
873
|
-
each(get(this.constructor, "styles"), (st) => {
|
|
874
|
-
if (isString(st)) {
|
|
875
|
-
let sheet = new CSSStyleSheet();
|
|
876
|
-
sheet.replaceSync(st);
|
|
877
|
-
styleSheets.push(sheet);
|
|
878
|
-
}
|
|
879
|
-
else {
|
|
880
|
-
styleSheets.push(st);
|
|
881
|
-
}
|
|
882
|
-
});
|
|
883
|
-
ComponentStyleMap.set(this.constructor, styleSheets);
|
|
884
|
-
}
|
|
885
|
-
/////////////////////////////////////////////////// shadow
|
|
886
|
-
this.#shadow = this.attachShadow({
|
|
887
|
-
mode: "open",
|
|
888
|
-
slotAssignment: get(this.constructor, "autoSlot", true) ? "named" : "manual",
|
|
889
|
-
});
|
|
890
|
-
this.#shadow.adoptedStyleSheets = [...DefaultCss, ...styleSheets];
|
|
891
|
-
//check link
|
|
892
|
-
let cssLink = this.attributes.getNamedItem(ATTR_CSS_LINK)?.value;
|
|
893
|
-
if (cssLink) {
|
|
894
|
-
const link = document.createElement("style");
|
|
895
|
-
link.textContent = `@import "${cssLink}"`;
|
|
896
|
-
this.#shadow.appendChild(link);
|
|
897
|
-
}
|
|
898
|
-
let filterSlotFn = debounce(this.#filterSlot, 20);
|
|
899
|
-
this.#selfObserver = new MutationObserver(mutations => {
|
|
900
|
-
for (let i = 0; i < mutations.length; i++) {
|
|
901
|
-
const mutation = mutations[i];
|
|
902
|
-
if (mutation.type === 'childList') {
|
|
903
|
-
filterSlotFn.call(this);
|
|
904
|
-
}
|
|
905
|
-
}
|
|
906
|
-
});
|
|
907
|
-
//slots prop map
|
|
908
|
-
this._slotsPropMap = { default: [] };
|
|
909
|
-
/////////////////////////////////////////////////// decorators create
|
|
910
|
-
let ary = get(this.constructor, _DecoratorsKey);
|
|
911
|
-
ary && ary.sort((a, b) => b.priority - a.priority).forEach(dw => dw.create(this));
|
|
912
|
-
this.#updatedD = this.#update.bind(this);
|
|
913
|
-
}
|
|
914
|
-
#updatedD;
|
|
915
|
-
connectedCallback() {
|
|
916
|
-
//parent
|
|
917
|
-
let node = closest(this.parentNode, (node) => node instanceof CompElem || node.host instanceof CompElem, "parentNode");
|
|
918
|
-
this.#parentComponent = node
|
|
919
|
-
? node instanceof CompElem
|
|
920
|
-
? node
|
|
921
|
-
: node.host
|
|
922
|
-
: null;
|
|
923
|
-
this.__init();
|
|
924
|
-
}
|
|
925
|
-
disconnectedCallback() {
|
|
926
|
-
this.#selfObserver.disconnect();
|
|
927
|
-
}
|
|
928
|
-
//////////////////////////////////// lifecycles
|
|
929
|
-
//********************************** 首次渲染
|
|
930
|
-
//构造时上级传递的参数
|
|
931
|
-
__init() {
|
|
932
|
-
if (this.#inited)
|
|
933
|
-
return;
|
|
934
|
-
/////////////////////////////////////////////////// slots
|
|
935
|
-
this.#updateSlotsAry();
|
|
936
|
-
//check props
|
|
937
|
-
const props = this.#initProps();
|
|
938
|
-
this.propsReady(props);
|
|
939
|
-
for (const key in props) {
|
|
940
|
-
const v = props[key];
|
|
941
|
-
this.#data[key] = v;
|
|
942
|
-
}
|
|
943
|
-
this.#initStates();
|
|
944
|
-
//define reactive
|
|
945
|
-
each(this.#data, (v, k) => {
|
|
946
|
-
let descr = Reflect.getOwnPropertyDescriptor(this.#data, k);
|
|
947
|
-
Reflect.defineProperty(this, k, {
|
|
948
|
-
get() {
|
|
949
|
-
let v = Reflect.get(this.#reactiveData, k);
|
|
950
|
-
return descr?.get ? descr?.get() : v;
|
|
951
|
-
},
|
|
952
|
-
set(v) {
|
|
953
|
-
if (descr?.set) {
|
|
954
|
-
descr?.set(v);
|
|
955
|
-
}
|
|
956
|
-
else {
|
|
957
|
-
Reflect.set(this.#reactiveData, k, v);
|
|
958
|
-
}
|
|
959
|
-
},
|
|
960
|
-
});
|
|
961
|
-
});
|
|
962
|
-
Reflect.defineProperty(this.#data, '__isData', {
|
|
963
|
-
enumerable: false,
|
|
964
|
-
value: true
|
|
965
|
-
});
|
|
966
|
-
this.#reactiveData = reactive(this.#data, this);
|
|
967
|
-
//render
|
|
968
|
-
let tmpl = this.render();
|
|
969
|
-
let nodes = this.buildView(tmpl);
|
|
970
|
-
if (nodes) {
|
|
971
|
-
let children = toArray(nodes);
|
|
972
|
-
children.forEach((c) => {
|
|
973
|
-
this.#shadow.appendChild(c);
|
|
974
|
-
});
|
|
975
|
-
this.#renderRoots = children;
|
|
976
|
-
this.#renderRoot = children[0];
|
|
977
|
-
}
|
|
978
|
-
//filter slot before append to dom
|
|
979
|
-
this.#filterSlot();
|
|
980
|
-
this.beforeMount();
|
|
981
|
-
this.#selfObserver.observe(this, { childList: true });
|
|
982
|
-
/////////////////////////////////////////////////// before mount
|
|
983
|
-
const that = this;
|
|
984
|
-
let ary = get(this.constructor, _DecoratorsKey);
|
|
985
|
-
ary && ary.sort((a, b) => b.priority - a.priority).forEach(dw => {
|
|
986
|
-
dw.beforeMount(this, (key, value) => {
|
|
987
|
-
that.#reactiveData[key] = value;
|
|
988
|
-
return that.#reactiveData[key];
|
|
989
|
-
});
|
|
990
|
-
});
|
|
991
|
-
//watch
|
|
992
|
-
let watchMap = get(this.constructor, DecoratorKey.WATCH);
|
|
993
|
-
each(watchMap, (watchList, k) => {
|
|
994
|
-
watchList.forEach(v => {
|
|
995
|
-
let { source, options, handler } = v;
|
|
996
|
-
let fn = handler.bind(this);
|
|
997
|
-
let onceWatch = get(options, "once", false);
|
|
998
|
-
if (onceWatch) {
|
|
999
|
-
fn = once(fn);
|
|
1000
|
-
}
|
|
1001
|
-
const updater = (function (ov) {
|
|
1002
|
-
let nv = get(this, source.replaceAll('-', '.'));
|
|
1003
|
-
fn(nv, ov, source);
|
|
1004
|
-
}).bind(this);
|
|
1005
|
-
let deep = get(options, "deep", false);
|
|
1006
|
-
updater.deep = deep;
|
|
1007
|
-
Collector.collectWatch(this, () => updater, k);
|
|
1008
|
-
let immediate = get(options, "immediate", false);
|
|
1009
|
-
if (!immediate)
|
|
1010
|
-
return;
|
|
1011
|
-
let nv = get(this, source.replaceAll('-', '.'));
|
|
1012
|
-
fn(nv, nv, source);
|
|
1013
|
-
});
|
|
1014
|
-
});
|
|
1015
|
-
//computed
|
|
1016
|
-
let computedMap = get(this.constructor, DecoratorKey.COMPUTED);
|
|
1017
|
-
each(computedMap, (getter, propKey) => {
|
|
1018
|
-
Collector.startCollect(this, CollectorType.COMPUTED);
|
|
1019
|
-
Collector.setUpdater(() => {
|
|
1020
|
-
this.#reactiveData[propKey] = getter.call(this);
|
|
1021
|
-
});
|
|
1022
|
-
this.#data[propKey] = getter.call(this);
|
|
1023
|
-
Collector.endCollect();
|
|
1024
|
-
Reflect.defineProperty(this, propKey, {
|
|
1025
|
-
get() {
|
|
1026
|
-
return Reflect.get(this.#reactiveData, propKey);
|
|
1027
|
-
},
|
|
1028
|
-
set(v) {
|
|
1029
|
-
showTagError(this.tagName, "Cannot set a computed property '" + propKey + "'");
|
|
1030
|
-
},
|
|
1031
|
-
});
|
|
1032
|
-
});
|
|
1033
|
-
//events
|
|
1034
|
-
let eventList = get(this.constructor, DecoratorKey.EVENTS);
|
|
1035
|
-
eventList && eventList.forEach((ev) => {
|
|
1036
|
-
let name = ev.name;
|
|
1037
|
-
let options = assign({ target: document, once: false, passive: false, capture: false }, ev.options);
|
|
1038
|
-
let listener = bind$1(ev.fn, this);
|
|
1039
|
-
let target = options.target;
|
|
1040
|
-
if (isFunction(target)) {
|
|
1041
|
-
target = target.call(this, this);
|
|
1042
|
-
}
|
|
1043
|
-
if (!target) {
|
|
1044
|
-
showTagError(this.tagName, "The target of @event('" + name + "',...) is invalid");
|
|
1045
|
-
return;
|
|
1046
|
-
}
|
|
1047
|
-
target.addEventListener(name, listener, options);
|
|
1048
|
-
});
|
|
1049
|
-
//slot hook
|
|
1050
|
-
each(this.#slotHooks, (v, k) => {
|
|
1051
|
-
this.#updateSlot(k);
|
|
1052
|
-
});
|
|
1053
|
-
//instance dynamic style
|
|
1054
|
-
Collector.startCollect(this, CollectorType.CSS);
|
|
1055
|
-
let cssAry = [];
|
|
1056
|
-
this.styles.forEach(st => {
|
|
1057
|
-
if (!isFunction(st))
|
|
1058
|
-
return;
|
|
1059
|
-
let cssss = new CSSStyleSheet();
|
|
1060
|
-
cssAry.push(cssss);
|
|
1061
|
-
Collector.setUpdater(() => {
|
|
1062
|
-
let css = st() ?? '';
|
|
1063
|
-
cssss.replaceSync(css);
|
|
1064
|
-
});
|
|
1065
|
-
let css = st();
|
|
1066
|
-
if (isBlank(css))
|
|
1067
|
-
return;
|
|
1068
|
-
cssss.replaceSync(css);
|
|
1069
|
-
});
|
|
1070
|
-
Collector.endCollect();
|
|
1071
|
-
this.#shadow.adoptedStyleSheets = [...this.#shadow.adoptedStyleSheets, ...cssAry];
|
|
1072
|
-
setTimeout(() => {
|
|
1073
|
-
this.#mounted = true;
|
|
1074
|
-
this.mounted();
|
|
1075
|
-
ary && ary.forEach(dw => {
|
|
1076
|
-
dw.mounted(this, (key, value) => {
|
|
1077
|
-
that.#reactiveData[key] = value;
|
|
1078
|
-
return that.#reactiveData[key];
|
|
1079
|
-
});
|
|
1080
|
-
});
|
|
1081
|
-
}, 0);
|
|
1082
|
-
this.#inited = true;
|
|
1083
|
-
}
|
|
1084
|
-
propsReady(props) { }
|
|
1085
|
-
render() {
|
|
1086
|
-
throw Error(`[CompElem <${this.tagName}>] Missing render()`);
|
|
1087
|
-
}
|
|
1088
|
-
beforeMount() { }
|
|
1089
|
-
mounted() { }
|
|
1090
|
-
#onSlogChange(slot, name) {
|
|
1091
|
-
//1. 更新 _slotsPropMap & slots
|
|
1092
|
-
this.#updateSlotsAry();
|
|
1093
|
-
//2. 设置attrs
|
|
1094
|
-
let props = get(this.#slotPropsMap[name], 'props');
|
|
1095
|
-
if (props) {
|
|
1096
|
-
each(this.slots, (nodeAry, k) => {
|
|
1097
|
-
nodeAry.filter(node => node.nodeType === Node.ELEMENT_NODE).forEach((node) => {
|
|
1098
|
-
if (node instanceof CompElem) {
|
|
1099
|
-
// node._setParentProps(props)
|
|
1100
|
-
node._updateProps(props);
|
|
1101
|
-
return;
|
|
1102
|
-
}
|
|
1103
|
-
each(props, (v, k) => {
|
|
1104
|
-
if (node instanceof HTMLSlotElement) {
|
|
1105
|
-
let compOfSlot = get(node, '__l_comp');
|
|
1106
|
-
if (compOfSlot) {
|
|
1107
|
-
let sname = node.name || 'default';
|
|
1108
|
-
let slotMap = compOfSlot.#slotPropsMap[sname];
|
|
1109
|
-
if (!slotMap) {
|
|
1110
|
-
slotMap = compOfSlot.#slotPropsMap[sname] = { props: {} };
|
|
1111
|
-
}
|
|
1112
|
-
if (!slotMap.props) {
|
|
1113
|
-
slotMap.props = {};
|
|
1114
|
-
}
|
|
1115
|
-
slotMap.props[k] = v;
|
|
1116
|
-
compOfSlot.#onSlogChange(node, sname);
|
|
1117
|
-
}
|
|
1118
|
-
}
|
|
1119
|
-
else {
|
|
1120
|
-
node.setAttribute(k, v);
|
|
1121
|
-
}
|
|
1122
|
-
});
|
|
1123
|
-
});
|
|
1124
|
-
});
|
|
1125
|
-
}
|
|
1126
|
-
//3. callback
|
|
1127
|
-
this.slotChange(slot, name);
|
|
1128
|
-
}
|
|
1129
|
-
slotChange(slot, name) { }
|
|
1130
|
-
attributeChangedCallback(attributeName, oldValue, newValue) {
|
|
1131
|
-
this.#attrChanged(attributeName, oldValue, newValue);
|
|
1132
|
-
}
|
|
1133
|
-
//********************************** 更新
|
|
1134
|
-
/**
|
|
1135
|
-
* 是否需要更新,可获取变更属性
|
|
1136
|
-
* 返回true时更新
|
|
1137
|
-
*/
|
|
1138
|
-
shouldUpdate(changed) {
|
|
1139
|
-
return true;
|
|
1140
|
-
}
|
|
1141
|
-
/**
|
|
1142
|
-
* 1. 调用render
|
|
1143
|
-
* 2. 更新@query/all
|
|
1144
|
-
* 3. 更新ref
|
|
1145
|
-
* 4. 更新prop到attr的映射
|
|
1146
|
-
* @param changed
|
|
1147
|
-
*/
|
|
1148
|
-
updated(changed) { }
|
|
1149
|
-
/**
|
|
1150
|
-
* 抛出自定义事件
|
|
1151
|
-
* @param evName 事件名称
|
|
1152
|
-
* @param args 自定义参数
|
|
1153
|
-
*/
|
|
1154
|
-
emit(evName, arg = {}, options) {
|
|
1155
|
-
if (options && options.event) {
|
|
1156
|
-
arg.event = options.event;
|
|
1157
|
-
}
|
|
1158
|
-
arg.target = this;
|
|
1159
|
-
this.dispatchEvent(new CustomEvent(evName, {
|
|
1160
|
-
bubbles: get(options, "bubbles", false),
|
|
1161
|
-
composed: get(options, "composed", false),
|
|
1162
|
-
cancelable: true,
|
|
1163
|
-
detail: arg,
|
|
1164
|
-
}));
|
|
1165
|
-
}
|
|
1166
|
-
#rootEvs = {};
|
|
1167
|
-
/**
|
|
1168
|
-
* 在root上绑定事件
|
|
1169
|
-
* @param evName
|
|
1170
|
-
* @param hook
|
|
1171
|
-
*/
|
|
1172
|
-
on(evName, hook) {
|
|
1173
|
-
if (!this.#rootEvs[evName]) {
|
|
1174
|
-
this.#rootEvs[evName] = [];
|
|
1175
|
-
}
|
|
1176
|
-
let cbk = hook.bind(this);
|
|
1177
|
-
this.#rootEvs[evName].push(cbk);
|
|
1178
|
-
this.addEventListener(evName, cbk);
|
|
1179
|
-
}
|
|
1180
|
-
/**
|
|
1181
|
-
* 下一帧执行
|
|
1182
|
-
* @param cbk
|
|
1183
|
-
*/
|
|
1184
|
-
nextTick(cbk) {
|
|
1185
|
-
Queue.pushNext(cbk);
|
|
1186
|
-
}
|
|
1187
|
-
/**
|
|
1188
|
-
* 强制更新一次视图
|
|
1189
|
-
*/
|
|
1190
|
-
forceUpdate() {
|
|
1191
|
-
each(this.#reactiveData, (v, k) => {
|
|
1192
|
-
this.#updateSources[k] = {
|
|
1193
|
-
value: undefined,
|
|
1194
|
-
chain: undefined,
|
|
1195
|
-
};
|
|
1196
|
-
});
|
|
1197
|
-
this.#update();
|
|
1198
|
-
}
|
|
1199
|
-
/**
|
|
1200
|
-
* 由监控变量调用
|
|
1201
|
-
* @param stateKey
|
|
1202
|
-
* @param ov
|
|
1203
|
-
* @param rootStateKey 如果是对象内部属性变更,会返回根属性名
|
|
1204
|
-
* @returns
|
|
1205
|
-
*/
|
|
1206
|
-
_notify(ov, chain) {
|
|
1207
|
-
//todo 1. 取消data - 0这个层级的监控;需要验证删除行时的路径
|
|
1208
|
-
let varPath = [];
|
|
1209
|
-
for (let i = 0; i < chain.length; i++) {
|
|
1210
|
-
const seg = chain[i];
|
|
1211
|
-
varPath.push(seg);
|
|
1212
|
-
let v = get(this, varPath);
|
|
1213
|
-
let pathStr = _toUpdatePath(varPath);
|
|
1214
|
-
this.#updateSources[pathStr] = { value: v, chain: pathStr === "slots" ? ['slots'] : varPath, oldValue: ov, end: varPath.length === chain.length };
|
|
1215
|
-
if (isObject(v) && pathStr[0] != PrivatePreffix) {
|
|
1216
|
-
ChangedMap.set(v, pathStr);
|
|
1217
|
-
}
|
|
1218
|
-
}
|
|
1219
|
-
return this.#updatedD;
|
|
1220
|
-
}
|
|
1221
|
-
#update() {
|
|
1222
|
-
if (size(this.#updateSources) < 1)
|
|
1223
|
-
return;
|
|
1224
|
-
const changed = this.#updateSources;
|
|
1225
|
-
this.#updateSources = {};
|
|
1226
|
-
//update decorators
|
|
1227
|
-
let ary = get(this.constructor, _DecoratorsKey);
|
|
1228
|
-
ary && ary.sort((a, b) => b.priority - a.priority).forEach(dw => {
|
|
1229
|
-
dw.updated(this, changed);
|
|
1230
|
-
});
|
|
1231
|
-
let toBreak = !this.shouldUpdate(changed);
|
|
1232
|
-
if (toBreak)
|
|
1233
|
-
return;
|
|
1234
|
-
let renderContextList = new Set();
|
|
1235
|
-
//1. filter context
|
|
1236
|
-
each(changed, ({ value, chain, oldValue }, k) => {
|
|
1237
|
-
if (this.#renderContextList[k]) {
|
|
1238
|
-
this.#renderContextList[k].forEach(cx => {
|
|
1239
|
-
renderContextList.add(cx);
|
|
1240
|
-
});
|
|
1241
|
-
}
|
|
1242
|
-
});
|
|
1243
|
-
//2. update context
|
|
1244
|
-
renderContextList.forEach(context => {
|
|
1245
|
-
if (context === this) {
|
|
1246
|
-
this.updateView(this.render());
|
|
1247
|
-
}
|
|
1248
|
-
else {
|
|
1249
|
-
//指令在这里仅更新视图
|
|
1250
|
-
let rs = context.render(...(context._renderArgs ? context._renderArgs : []));
|
|
1251
|
-
if (rs)
|
|
1252
|
-
context.updateView(rs);
|
|
1253
|
-
}
|
|
1254
|
-
});
|
|
1255
|
-
//update slot view
|
|
1256
|
-
this.#updateSlots.forEach((v) => {
|
|
1257
|
-
this.#updateSlot(v);
|
|
1258
|
-
});
|
|
1259
|
-
this.updated(changed);
|
|
1260
|
-
each(changed, ({ value, chain, oldValue }, k) => {
|
|
1261
|
-
if (isObject(value) && ChangedMap.has(value)) {
|
|
1262
|
-
ChangedMap.delete(value);
|
|
1263
|
-
}
|
|
1264
|
-
});
|
|
1265
|
-
}
|
|
1266
|
-
/**
|
|
1267
|
-
* 1. 初始props中并未包含的属性,可从attributes取,且定义类型不是string时自动转换
|
|
1268
|
-
* 2. 如果attributes中也未出现且必填报错
|
|
1269
|
-
* 3. 否则设置默认值
|
|
1270
|
-
* @returns 非props的attr集合
|
|
1271
|
-
*/
|
|
1272
|
-
#initProps() {
|
|
1273
|
-
let propDefs = get(this.constructor, DecoratorKey.PROPS);
|
|
1274
|
-
let attrs = this.attributes;
|
|
1275
|
-
let tagName = this.tagName;
|
|
1276
|
-
let parentProps = this.#props;
|
|
1277
|
-
let filterAttrs = {};
|
|
1278
|
-
each(attrs, ({ name, value }) => {
|
|
1279
|
-
if (name[0] === ATTR_PREFIX_EVENT ||
|
|
1280
|
-
name[0] === ATTR_PREFIX_PROP ||
|
|
1281
|
-
name[0] === ATTR_PREFIX_BOOLEAN ||
|
|
1282
|
-
name === ATTR_REF || name === 'slot')
|
|
1283
|
-
return;
|
|
1284
|
-
let camelName = camelCase(name);
|
|
1285
|
-
if (propDefs && !propDefs[camelName]) {
|
|
1286
|
-
filterAttrs[name] = value;
|
|
1287
|
-
}
|
|
1288
|
-
});
|
|
1289
|
-
this.#attrs = this.#attrs ? assign(this.#attrs, filterAttrs) : filterAttrs;
|
|
1290
|
-
let rs = {};
|
|
1291
|
-
each(propDefs, (def, key) => {
|
|
1292
|
-
let propDef = propDefs[key];
|
|
1293
|
-
let isInited = has(parentProps, key);
|
|
1294
|
-
let defaultVal = get(this, key);
|
|
1295
|
-
if (!('_defaultValue' in propDef)) {
|
|
1296
|
-
//在构造结束后
|
|
1297
|
-
propDef._defaultValue = defaultVal;
|
|
1298
|
-
if (!propDef.type) {
|
|
1299
|
-
if (isUndefined(defaultVal)) {
|
|
1300
|
-
showTagError(tagName, "Prop '" + key + "' has neither propType nor defaultValue be used for type inference");
|
|
1301
|
-
}
|
|
1302
|
-
let type = typeof defaultVal;
|
|
1303
|
-
if (isArray(defaultVal))
|
|
1304
|
-
type = 'array';
|
|
1305
|
-
let inferredType = PropTypeMap[type];
|
|
1306
|
-
propDef.type = inferredType;
|
|
1307
|
-
}
|
|
1308
|
-
}
|
|
1309
|
-
let val = undefined;
|
|
1310
|
-
if (isInited) {
|
|
1311
|
-
val = isNil(parentProps[key]) ? defaultVal : parentProps[key];
|
|
1312
|
-
}
|
|
1313
|
-
else {
|
|
1314
|
-
val = defaultVal;
|
|
1315
|
-
let attr = attrs.getNamedItem(kebabCase(key)) ||
|
|
1316
|
-
attrs.getNamedItem(ATTR_PREFIX_PROP + kebabCase(key));
|
|
1317
|
-
if (attr) {
|
|
1318
|
-
isInited = true;
|
|
1319
|
-
val = attr.value;
|
|
1320
|
-
}
|
|
1321
|
-
}
|
|
1322
|
-
//required check
|
|
1323
|
-
let isRequired = propDef.required;
|
|
1324
|
-
if (isRequired && !isInited) {
|
|
1325
|
-
showTagError(tagName, "Prop '" + key + "' is required");
|
|
1326
|
-
return false;
|
|
1327
|
-
}
|
|
1328
|
-
val = this.#propTypeCheck(propDefs, key, val);
|
|
1329
|
-
let getter = get(propDefs, [key, 'getter']);
|
|
1330
|
-
if (getter)
|
|
1331
|
-
getter = bind$1(getter, this);
|
|
1332
|
-
let setter = get(propDefs, [key, 'setter']);
|
|
1333
|
-
if (setter)
|
|
1334
|
-
setter = bind$1(setter, this);
|
|
1335
|
-
if (getter || setter) {
|
|
1336
|
-
Reflect.defineProperty(this.#data, key, {
|
|
1337
|
-
set: setter || function (v) { },
|
|
1338
|
-
get: getter
|
|
1339
|
-
});
|
|
1340
|
-
}
|
|
1341
|
-
if (propDef.attribute && isDefined(val) && !isObject(val)) {
|
|
1342
|
-
this.setAttribute(kebabCase(key), trim(val));
|
|
1343
|
-
}
|
|
1344
|
-
this.#data[key] = val;
|
|
1345
|
-
rs[key] = val;
|
|
1346
|
-
});
|
|
1347
|
-
return Object.seal(rs);
|
|
1348
|
-
}
|
|
1349
|
-
//属性值检测
|
|
1350
|
-
#propTypeCheck(propDefs, propKey, newValue) {
|
|
1351
|
-
let propDef = propDefs[propKey];
|
|
1352
|
-
if (!propDef)
|
|
1353
|
-
return newValue;
|
|
1354
|
-
let validator = propDef.isValid;
|
|
1355
|
-
let expectType = propDef.type;
|
|
1356
|
-
let expectTypeAry = isArray(expectType) ? expectType : [expectType];
|
|
1357
|
-
let typeConverter = propDef.converter;
|
|
1358
|
-
let val = newValue;
|
|
1359
|
-
if (!some(expectTypeAry, (et) => et === String) && isString(val) && !isNull(val)) {
|
|
1360
|
-
try {
|
|
1361
|
-
val = typeConverter ? typeConverter(val) : fval(val, { html });
|
|
1362
|
-
}
|
|
1363
|
-
catch (error) {
|
|
1364
|
-
showTagError(this.tagName, `Convert attribute '${propKey}' error with ` + val);
|
|
1365
|
-
}
|
|
1366
|
-
} //endif
|
|
1367
|
-
//extra work
|
|
1368
|
-
for (let i = 0; i < expectTypeAry.length; i++) {
|
|
1369
|
-
const et = expectTypeAry[i];
|
|
1370
|
-
if (et.name === 'Boolean') {
|
|
1371
|
-
if (isString(val) && /(?:^true$)|(?:^false$)/.test(val)) {
|
|
1372
|
-
val = fval(val);
|
|
1373
|
-
}
|
|
1374
|
-
else if (isUndefined(val) || isBlank(val)) {
|
|
1375
|
-
val = true;
|
|
1376
|
-
}
|
|
1377
|
-
}
|
|
1378
|
-
}
|
|
1379
|
-
let realType = typeof val;
|
|
1380
|
-
let matched = isDefined(val) ? false : true;
|
|
1381
|
-
for (let i = 0; i < expectTypeAry.length; i++) {
|
|
1382
|
-
const et = expectTypeAry[i];
|
|
1383
|
-
if (
|
|
1384
|
-
//base form
|
|
1385
|
-
test(realType, et.name, "i") ||
|
|
1386
|
-
//object form
|
|
1387
|
-
val instanceof et || (Object.prototype.toString.call(val) === Object.prototype.toString.call(et.prototype))) {
|
|
1388
|
-
matched = true;
|
|
1389
|
-
break;
|
|
1390
|
-
}
|
|
1391
|
-
}
|
|
1392
|
-
if (!matched) {
|
|
1393
|
-
showTagError(this.tagName, `Invalid prop '${propKey}'. expected '${expectTypeAry.map((t) => t.name || t)}' but got '${realType}'`);
|
|
1394
|
-
}
|
|
1395
|
-
if (validator) {
|
|
1396
|
-
if (!validator.call(this, val, this.#data)) {
|
|
1397
|
-
showTagError(this.tagName, `Invalid prop '${propKey}'. IsValid() check failed`);
|
|
1398
|
-
}
|
|
1399
|
-
}
|
|
1400
|
-
return val;
|
|
1401
|
-
}
|
|
1402
|
-
#initStates() {
|
|
1403
|
-
let stateDefs = get(this.constructor, DecoratorKey.STATES);
|
|
1404
|
-
each(stateDefs, (def, key) => {
|
|
1405
|
-
let stateDef = stateDefs[key];
|
|
1406
|
-
let val = get(this, key);
|
|
1407
|
-
if (stateDef) {
|
|
1408
|
-
let propName = stateDef.prop;
|
|
1409
|
-
val = propName ? cloneDeep(this.#data[propName]) : get(this, key);
|
|
1410
|
-
}
|
|
1411
|
-
this.#data[key] = val;
|
|
1412
|
-
});
|
|
1413
|
-
}
|
|
1414
|
-
/**
|
|
1415
|
-
* 由外部调用,在初始化及更新时。
|
|
1416
|
-
* @param props
|
|
1417
|
-
* @param attrs
|
|
1418
|
-
*/
|
|
1419
|
-
#propsReady = debounce(this.propsReady, 100);
|
|
1420
|
-
/**
|
|
1421
|
-
* @deprecated
|
|
1422
|
-
*/
|
|
1423
|
-
_setParentProps(props, attrs) {
|
|
1424
|
-
if (this.#inited) {
|
|
1425
|
-
let propDefs = get(this.constructor, DecoratorKey.PROPS);
|
|
1426
|
-
//存在attrs表示已初始化完成
|
|
1427
|
-
each(props, (v, k) => {
|
|
1428
|
-
let ck = camelCase(k);
|
|
1429
|
-
let propDef = propDefs[ck];
|
|
1430
|
-
if (!propDef)
|
|
1431
|
-
return;
|
|
1432
|
-
let ov = this.#data[ck];
|
|
1433
|
-
v = this.#propTypeCheck(propDefs, ck, v);
|
|
1434
|
-
if (propDef.hasChanged && !propDef.hasChanged.call(this, v, ov))
|
|
1435
|
-
return;
|
|
1436
|
-
this.#data[ck] = v;
|
|
1437
|
-
this._notify(ov, [ck]);
|
|
1438
|
-
});
|
|
1439
|
-
assign(this.#props, props);
|
|
1440
|
-
assign(this.#attrs, attrs);
|
|
1441
|
-
this.#propsReady(this.#props);
|
|
1442
|
-
}
|
|
1443
|
-
}
|
|
1444
|
-
//todo 这里需要直接修改prop
|
|
1445
|
-
_updateProps(props) {
|
|
1446
|
-
let propDefs = get(this.constructor, DecoratorKey.PROPS);
|
|
1447
|
-
//存在attrs表示已初始化完成
|
|
1448
|
-
each(props, (v, k) => {
|
|
1449
|
-
let ck = camelCase(k);
|
|
1450
|
-
let propDef = propDefs[ck];
|
|
1451
|
-
if (!propDef)
|
|
1452
|
-
return;
|
|
1453
|
-
let ov = this.#data[ck];
|
|
1454
|
-
v = this.#propTypeCheck(propDefs, ck, v);
|
|
1455
|
-
if (propDef.hasChanged && !propDef.hasChanged.call(this, v, ov))
|
|
1456
|
-
return;
|
|
1457
|
-
Collector.__skipCheck = true;
|
|
1458
|
-
set(this, ck, v);
|
|
1459
|
-
Collector.__skipCheck = false;
|
|
1460
|
-
});
|
|
1461
|
-
assign(this.#props, props);
|
|
1462
|
-
this.#propsReady(this.#props);
|
|
1463
|
-
}
|
|
1464
|
-
_initProps(props, attrs) {
|
|
1465
|
-
this.#props = merge(this.#props || {}, props);
|
|
1466
|
-
this.#attrs = merge({}, attrs);
|
|
1467
|
-
}
|
|
1468
|
-
/**
|
|
1469
|
-
* 绑定slot标签,render时调用
|
|
1470
|
-
*/
|
|
1471
|
-
_bindSlot(slot, name, props) {
|
|
1472
|
-
//1. 设置map
|
|
1473
|
-
if (!this.#slotsEl[name]) {
|
|
1474
|
-
this.#slotsEl[name] = slot;
|
|
1475
|
-
Reflect.defineProperty(slot, '__l_comp', {
|
|
1476
|
-
value: this
|
|
1477
|
-
});
|
|
1478
|
-
}
|
|
1479
|
-
slot.addEventListener('slotchange', (e) => {
|
|
1480
|
-
if (this.#inited)
|
|
1481
|
-
this.#onSlogChange(slot, name === 'default' ? '' : name);
|
|
1482
|
-
});
|
|
1483
|
-
//3. 保存参数
|
|
1484
|
-
if (!isEmpty(props)) {
|
|
1485
|
-
let slotMap = this.#slotPropsMap[name];
|
|
1486
|
-
if (!slotMap) {
|
|
1487
|
-
slotMap = this.#slotPropsMap[name] = {};
|
|
1488
|
-
}
|
|
1489
|
-
if (props.nodeFilter) {
|
|
1490
|
-
slotMap.filter = props.nodeFilter;
|
|
1491
|
-
}
|
|
1492
|
-
slotMap.props = omit(props, 'nodeFilter');
|
|
1493
|
-
}
|
|
1494
|
-
}
|
|
1495
|
-
_bindSlotHook(name, hook) {
|
|
1496
|
-
this.#slotHooks[name] = hook;
|
|
1497
|
-
}
|
|
1498
|
-
//slot变量变动时触发
|
|
1499
|
-
#updateSlots = new Set();
|
|
1500
|
-
_updateSlot(name, propName, value) {
|
|
1501
|
-
let slotEl = this.#slotsEl[name];
|
|
1502
|
-
let hook = this.#slotHooks[name];
|
|
1503
|
-
if (!hook && !slotEl)
|
|
1504
|
-
return;
|
|
1505
|
-
let slotMap = this.#slotPropsMap[name];
|
|
1506
|
-
if (propName) {
|
|
1507
|
-
if (!slotMap.props) {
|
|
1508
|
-
slotMap.props = {};
|
|
1509
|
-
}
|
|
1510
|
-
slotMap.props[propName] = value;
|
|
1511
|
-
}
|
|
1512
|
-
if (!!hook) {
|
|
1513
|
-
this.#updateSlots.add(name);
|
|
1514
|
-
}
|
|
1515
|
-
else {
|
|
1516
|
-
//update nodes
|
|
1517
|
-
let els = slotEl.assignedElements({ flatten: true });
|
|
1518
|
-
for (let i = 0; i < els.length; i++) {
|
|
1519
|
-
const el = els[i];
|
|
1520
|
-
el.setAttribute(propName, value + '');
|
|
1521
|
-
}
|
|
1522
|
-
}
|
|
1523
|
-
}
|
|
1524
|
-
#updateSlotsAry() {
|
|
1525
|
-
const cs = flatMap(this.childNodes, node => {
|
|
1526
|
-
if (node.nodeType === Node.COMMENT_NODE)
|
|
1527
|
-
return [];
|
|
1528
|
-
if (node instanceof HTMLSlotElement)
|
|
1529
|
-
return node.assignedNodes({ flatten: true });
|
|
1530
|
-
return node;
|
|
1531
|
-
});
|
|
1532
|
-
let groups = groupBy(cs, node => {
|
|
1533
|
-
// if (node.nodeType === Node.COMMENT_NODE) return ''
|
|
1534
|
-
if (node.nodeType === Node.TEXT_NODE)
|
|
1535
|
-
return 'default';
|
|
1536
|
-
if (node instanceof Element) {
|
|
1537
|
-
return node.getAttribute('slot') || 'default';
|
|
1538
|
-
}
|
|
1539
|
-
});
|
|
1540
|
-
if (isEmpty(groups)) {
|
|
1541
|
-
if (!isEmpty(this.#data['#slots'])) {
|
|
1542
|
-
this.#inited ? this.#reactiveData['#slots'] = {} : this.#data['#slots'] = {};
|
|
1543
|
-
}
|
|
1544
|
-
return;
|
|
1545
|
-
}
|
|
1546
|
-
each(groups, (nodeAry, k) => {
|
|
1547
|
-
if (!k)
|
|
1548
|
-
return;
|
|
1549
|
-
while (nodeAry.length > 0) {
|
|
1550
|
-
let node = nodeAry[0];
|
|
1551
|
-
if ((node.nodeType === Node.TEXT_NODE && isBlank(node.textContent)) ||
|
|
1552
|
-
(node instanceof HTMLSlotElement && isEmpty(node.assignedNodes({ flatten: true })))) {
|
|
1553
|
-
nodeAry.shift();
|
|
1554
|
-
continue;
|
|
1555
|
-
}
|
|
1556
|
-
break;
|
|
1557
|
-
}
|
|
1558
|
-
while (nodeAry.length > 0) {
|
|
1559
|
-
let node = last(nodeAry);
|
|
1560
|
-
if ((node.nodeType === Node.TEXT_NODE && isBlank(node.textContent)) ||
|
|
1561
|
-
(node instanceof HTMLSlotElement && isEmpty(node.assignedNodes({ flatten: true })))) {
|
|
1562
|
-
nodeAry.pop();
|
|
1563
|
-
continue;
|
|
1564
|
-
}
|
|
1565
|
-
break;
|
|
1566
|
-
}
|
|
1567
|
-
});
|
|
1568
|
-
let rs = {};
|
|
1569
|
-
each(groups, (v, k) => {
|
|
1570
|
-
if (!isEmpty(v)) {
|
|
1571
|
-
rs[k] = v;
|
|
1572
|
-
}
|
|
1573
|
-
});
|
|
1574
|
-
this.#inited ? this.#reactiveData['#slots'] = rs : this.#data['#slots'] = rs;
|
|
1575
|
-
}
|
|
1576
|
-
#updateSlot(name) {
|
|
1577
|
-
let hook = this.#slotHooks[name];
|
|
1578
|
-
if (!hook)
|
|
1579
|
-
return;
|
|
1580
|
-
let slotMap = this.#slotPropsMap[name];
|
|
1581
|
-
let slot = this.#data['#slots'][name];
|
|
1582
|
-
//slot not ready yet
|
|
1583
|
-
//1. 可能是if/each等指令还未插入
|
|
1584
|
-
if (!slot)
|
|
1585
|
-
return;
|
|
1586
|
-
//组件通知渲染异步指令
|
|
1587
|
-
this.renderAsync(hook, get(slotMap, 'props'));
|
|
1588
|
-
const rc = this._asyncDirectives.get(hook);
|
|
1589
|
-
//todo 如果要做成通用异步指令,元素必须插入到指令挂载的位置,并且slot的插入节点还要去掉注释
|
|
1590
|
-
let nodes = rc?.buildView(hook(get(slotMap, 'props')));
|
|
1591
|
-
let nnodes = reject(toArray(nodes), n => n.nodeType === Node.COMMENT_NODE);
|
|
1592
|
-
if (nnodes) {
|
|
1593
|
-
let slottedNodes = this.#slotNodes[name];
|
|
1594
|
-
if (!isEmpty(slottedNodes)) {
|
|
1595
|
-
for (let i = 0; i < slottedNodes.length; i++) {
|
|
1596
|
-
const n = slottedNodes[i];
|
|
1597
|
-
n.parentNode?.removeChild(n);
|
|
1598
|
-
}
|
|
1599
|
-
}
|
|
1600
|
-
this.#slotNodes[name] = nnodes;
|
|
1601
|
-
this.append(...nnodes);
|
|
1602
|
-
this.#updateSlots.clear();
|
|
1603
|
-
}
|
|
1604
|
-
}
|
|
1605
|
-
_asyncDirectives = new WeakMap();
|
|
1606
|
-
renderAsync(cbk, ...args) {
|
|
1607
|
-
}
|
|
1608
|
-
//children变化时触发
|
|
1609
|
-
#filterSlot() {
|
|
1610
|
-
if (isEmpty(this.#slotPropsMap))
|
|
1611
|
-
return;
|
|
1612
|
-
each(this.slots, (slottedNodes, k) => {
|
|
1613
|
-
if (isEmpty(slottedNodes))
|
|
1614
|
-
return;
|
|
1615
|
-
let slotMap = this.#slotPropsMap[k];
|
|
1616
|
-
let filterNodes = slottedNodes;
|
|
1617
|
-
if (slotMap) {
|
|
1618
|
-
let filterFn = slotMap.filter;
|
|
1619
|
-
if (isFunction(filterFn)) {
|
|
1620
|
-
filterNodes = filterFn(slottedNodes);
|
|
1621
|
-
}
|
|
1622
|
-
else if (isObject(filterFn)) {
|
|
1623
|
-
let type = filterFn.type;
|
|
1624
|
-
let maxCount = filterFn.maxCount;
|
|
1625
|
-
if (type) {
|
|
1626
|
-
let ts = isArray(type) ? type : [type];
|
|
1627
|
-
filterNodes = filter(slottedNodes, n => some(ts, t => n instanceof t));
|
|
1628
|
-
}
|
|
1629
|
-
if (maxCount > 0) {
|
|
1630
|
-
filterNodes = slice(slottedNodes, 0, maxCount);
|
|
1631
|
-
}
|
|
1632
|
-
}
|
|
1633
|
-
}
|
|
1634
|
-
if (this.#shadow.slotAssignment === 'named') {
|
|
1635
|
-
let removeNodes = [];
|
|
1636
|
-
for (let i = 0; i < slottedNodes.length; i++) {
|
|
1637
|
-
const c = slottedNodes[i];
|
|
1638
|
-
if (!filterNodes.includes(c)) {
|
|
1639
|
-
removeNodes.push(c);
|
|
1640
|
-
}
|
|
1641
|
-
}
|
|
1642
|
-
while (removeNodes.length > 0) {
|
|
1643
|
-
let n = removeNodes.pop();
|
|
1644
|
-
n.parentNode?.removeChild(n);
|
|
1645
|
-
}
|
|
1646
|
-
}
|
|
1647
|
-
else {
|
|
1648
|
-
this.#slotsEl[k].assign(...filterNodes);
|
|
1649
|
-
}
|
|
1650
|
-
if (this.#inited)
|
|
1651
|
-
this.#onSlogChange(this.#slotsEl[k], k === 'default' ? '' : k);
|
|
1652
|
-
});
|
|
1653
|
-
}
|
|
1654
|
-
#attrChanged(name, oldValue, newValue) {
|
|
1655
|
-
if (!this.isMounted)
|
|
1656
|
-
return;
|
|
1657
|
-
let observedAttrs = _getObservedAttrs(this.constructor);
|
|
1658
|
-
if (observedAttrs.has(name)) {
|
|
1659
|
-
let camelName = camelCase(name);
|
|
1660
|
-
if (isNull(newValue)) {
|
|
1661
|
-
let propDefs = get(this.constructor, DecoratorKey.PROPS);
|
|
1662
|
-
//使用默认值
|
|
1663
|
-
newValue = propDefs[camelName]._defaultValue;
|
|
1664
|
-
}
|
|
1665
|
-
this._updateProps({ [camelName]: newValue });
|
|
1666
|
-
}
|
|
1667
|
-
}
|
|
1668
|
-
/**
|
|
1669
|
-
* todo
|
|
1670
|
-
* 1. 取消上溯递归路径
|
|
1671
|
-
*/
|
|
1672
|
-
_regDeps(varPath, renderContext) {
|
|
1673
|
-
let list = this.#renderContextList[varPath];
|
|
1674
|
-
if (!list) {
|
|
1675
|
-
list = this.#renderContextList[varPath] = new Set();
|
|
1676
|
-
}
|
|
1677
|
-
list.add(renderContext);
|
|
1678
|
-
let restPath = varPath.split('-');
|
|
1679
|
-
restPath.pop();
|
|
1680
|
-
if (restPath.length < 1)
|
|
1681
|
-
return;
|
|
1682
|
-
let upperPath = restPath.join('-');
|
|
1683
|
-
list = this.#renderContextList[upperPath];
|
|
1684
|
-
if (!list) {
|
|
1685
|
-
list = this.#renderContextList[upperPath] = new Set();
|
|
1686
|
-
}
|
|
1687
|
-
list.add(renderContext);
|
|
1688
|
-
}
|
|
1689
|
-
}
|
|
1690
|
-
|
|
1691
|
-
/**
|
|
1692
|
-
* @author holyhigh2
|
|
1693
|
-
*/
|
|
1694
|
-
var DirectiveUpdateTag;
|
|
1695
|
-
(function (DirectiveUpdateTag) {
|
|
1696
|
-
DirectiveUpdateTag["NONE"] = "NONE";
|
|
1697
|
-
DirectiveUpdateTag["REMOVE"] = "REMOVE";
|
|
1698
|
-
DirectiveUpdateTag["REPLACE"] = "REPLACE";
|
|
1699
|
-
DirectiveUpdateTag["UPDATE"] = "UPDATE";
|
|
1700
|
-
DirectiveUpdateTag["APPEND"] = "APPEND";
|
|
1701
|
-
})(DirectiveUpdateTag || (DirectiveUpdateTag = {}));
|
|
1702
|
-
/**
|
|
1703
|
-
* 视图更新点
|
|
1704
|
-
*/
|
|
1705
|
-
class UpdatePoint {
|
|
1706
|
-
//在子视图中的平级key
|
|
1707
|
-
key;
|
|
1708
|
-
//表达式对应的vars位置
|
|
1709
|
-
varIndex;
|
|
1710
|
-
value;
|
|
1711
|
-
isText = false;
|
|
1712
|
-
//是否模板
|
|
1713
|
-
isTmpl = false;
|
|
1714
|
-
isDirective = false;
|
|
1715
|
-
//表达式所在节点,可能是元素/文本
|
|
1716
|
-
node;
|
|
1717
|
-
//如果是文本位置,与node一起构成插入范围
|
|
1718
|
-
textNode;
|
|
1719
|
-
//是否组件
|
|
1720
|
-
isComponent = false;
|
|
1721
|
-
//如果在属性中,属性名
|
|
1722
|
-
attrName;
|
|
1723
|
-
//属性值模板
|
|
1724
|
-
attrTmpl;
|
|
1725
|
-
//是否组件属性
|
|
1726
|
-
isProp = false;
|
|
1727
|
-
//是否布尔属性
|
|
1728
|
-
isToggleProp = false;
|
|
1729
|
-
//是否事件
|
|
1730
|
-
isEvent;
|
|
1731
|
-
constructor(varIndex, node, attrName, attrTmpl) {
|
|
1732
|
-
this.varIndex = varIndex;
|
|
1733
|
-
this.node = node;
|
|
1734
|
-
if (attrName)
|
|
1735
|
-
this.attrName = attrName;
|
|
1736
|
-
if (attrTmpl) {
|
|
1737
|
-
this.attrTmpl = attrTmpl;
|
|
1738
|
-
}
|
|
1739
|
-
}
|
|
1740
|
-
}
|
|
1741
|
-
|
|
1742
|
-
/**
|
|
1743
|
-
* 属性定义
|
|
1744
|
-
*/
|
|
1745
|
-
var EnterPointType;
|
|
1746
|
-
(function (EnterPointType) {
|
|
1747
|
-
EnterPointType["ATTR"] = "attr";
|
|
1748
|
-
EnterPointType["PROP"] = "prop";
|
|
1749
|
-
EnterPointType["TEXT"] = "text";
|
|
1750
|
-
EnterPointType["CLASS"] = "class";
|
|
1751
|
-
EnterPointType["STYLE"] = "style";
|
|
1752
|
-
EnterPointType["SLOT"] = "slot";
|
|
1753
|
-
EnterPointType["TAG"] = "tag"; //在标签内但不是属性内
|
|
1754
|
-
})(EnterPointType || (EnterPointType = {}));
|
|
1755
|
-
/**
|
|
1756
|
-
* 交互点信息
|
|
1757
|
-
*/
|
|
1758
|
-
class EnterPoint {
|
|
1759
|
-
startNode; //依赖节点
|
|
1760
|
-
endNode; //依赖节点2
|
|
1761
|
-
type; //依赖类型
|
|
1762
|
-
attrName; //依赖属性名
|
|
1763
|
-
varIndex;
|
|
1764
|
-
expressionChain; //所在层级序号 [parentVarIndex-varIndex-]+,如1-6 表示根的第2个表达式下的context的第7个表达式
|
|
1765
|
-
nodes; //如果是插入节点,保存插入的节点数组
|
|
1766
|
-
constructor(node, attrName, type) {
|
|
1767
|
-
this.startNode = node;
|
|
1768
|
-
this.attrName = attrName;
|
|
1769
|
-
this.type = type;
|
|
1770
|
-
}
|
|
1771
|
-
setVarIndex(varIndex) {
|
|
1772
|
-
this.varIndex = varIndex;
|
|
1773
|
-
}
|
|
1774
|
-
getNodes() {
|
|
1775
|
-
let nextNode = this.startNode.nextSibling;
|
|
1776
|
-
if (!this.endNode)
|
|
1777
|
-
return [nextNode];
|
|
1778
|
-
let rs = [];
|
|
1779
|
-
while (nextNode && nextNode !== this.endNode) {
|
|
1780
|
-
rs.push(nextNode);
|
|
1781
|
-
nextNode = nextNode?.nextSibling;
|
|
1782
|
-
}
|
|
1783
|
-
return rs;
|
|
1784
|
-
}
|
|
1785
|
-
}
|
|
1786
|
-
var MovePosition;
|
|
1787
|
-
(function (MovePosition) {
|
|
1788
|
-
MovePosition["AFTER_BEGIN"] = "afterbegin";
|
|
1789
|
-
})(MovePosition || (MovePosition = {}));
|
|
1790
|
-
/**
|
|
1791
|
-
* Delay the actual time of execution of directive
|
|
1792
|
-
*/
|
|
1793
|
-
class DirectiveWrapper extends Function {
|
|
1794
|
-
diClass;
|
|
1795
|
-
args;
|
|
1796
|
-
di;
|
|
1797
|
-
varPath;
|
|
1798
|
-
point;
|
|
1799
|
-
slotComponent;
|
|
1800
|
-
varChain;
|
|
1801
|
-
constructor(diClass, ...args) {
|
|
1802
|
-
super();
|
|
1803
|
-
this.diClass = diClass;
|
|
1804
|
-
this.args = args;
|
|
1805
|
-
this.varChain = Collector.popDirectiveQ();
|
|
1806
|
-
this.di = new this.diClass();
|
|
1807
|
-
this.di.renderParams = this.varChain;
|
|
1808
|
-
}
|
|
1809
|
-
//校验scope
|
|
1810
|
-
checkScope(scopeType) {
|
|
1811
|
-
let scopes = get(this.diClass, 'scopes');
|
|
1812
|
-
if (!isEmpty(scopes) && !test(scopes.join(','), scopeType)) {
|
|
1813
|
-
showError(`Directive '${this.diClass.name}' is out of scopes, expect '${scopes.join(',')}' bug got '${scopeType}'`);
|
|
1814
|
-
return;
|
|
1815
|
-
}
|
|
1816
|
-
}
|
|
1817
|
-
render(component) {
|
|
1818
|
-
let di = this.di;
|
|
1819
|
-
this.args;
|
|
1820
|
-
if (!di.renderComponent) {
|
|
1821
|
-
di.renderComponent = component;
|
|
1822
|
-
// for (let i = 0; i < args.length; i++) {
|
|
1823
|
-
// const arg = args[i];
|
|
1824
|
-
// if (isFunction(arg)) {
|
|
1825
|
-
// args[i] = arg.bind(component)
|
|
1826
|
-
// }
|
|
1827
|
-
// }
|
|
1828
|
-
}
|
|
1829
|
-
this.di = di;
|
|
1830
|
-
di._renderArgs = this.args;
|
|
1831
|
-
// let [nodes, expPos, expPosMap] = di.renderContext(...this.args)
|
|
1832
|
-
// if (expPosMap) {
|
|
1833
|
-
// di.__expPosMap = expPosMap
|
|
1834
|
-
// } else if (expPos) {
|
|
1835
|
-
// di.__expPos = expPos
|
|
1836
|
-
// }
|
|
1837
|
-
return this.di.render(...this.args);
|
|
1838
|
-
}
|
|
1839
|
-
update(point, newArgs, oldArgs) {
|
|
1840
|
-
let tag = this.di.update(point, newArgs, oldArgs);
|
|
1841
|
-
if (tag === DirectiveUpdateTag.NONE)
|
|
1842
|
-
return;
|
|
1843
|
-
let nodes = point.getNodes();
|
|
1844
|
-
if (tag === DirectiveUpdateTag.REMOVE) {
|
|
1845
|
-
for (let i = 0; i < nodes.length; i++) {
|
|
1846
|
-
const n = nodes[i];
|
|
1847
|
-
n.parentNode?.removeChild(n);
|
|
1848
|
-
}
|
|
1849
|
-
}
|
|
1850
|
-
else if (tag === DirectiveUpdateTag.REPLACE) {
|
|
1851
|
-
let newNodes = [];
|
|
1852
|
-
for (let i = 0; i < nodes.length; i++) {
|
|
1853
|
-
const n = nodes[i];
|
|
1854
|
-
n.parentNode?.removeChild(n);
|
|
1855
|
-
}
|
|
1856
|
-
let rs = this.di.render(...newArgs);
|
|
1857
|
-
let nnodes = this.di.buildView(rs);
|
|
1858
|
-
newNodes = toArray(nnodes);
|
|
1859
|
-
let fragment = document.createDocumentFragment();
|
|
1860
|
-
fragment.append(...newNodes);
|
|
1861
|
-
point.endNode.parentNode.insertBefore(fragment, point.endNode);
|
|
1862
|
-
}
|
|
1863
|
-
else if (tag === DirectiveUpdateTag.UPDATE) {
|
|
1864
|
-
let newKeys = {};
|
|
1865
|
-
let nodesToUpdate;
|
|
1866
|
-
//原节点顺序
|
|
1867
|
-
let oldSeq = [];
|
|
1868
|
-
let newSeq = [];
|
|
1869
|
-
let updateRs = this.di.render(...newArgs);
|
|
1870
|
-
if (!updateRs) {
|
|
1871
|
-
updateRs = new Template([], []);
|
|
1872
|
-
}
|
|
1873
|
-
if (isEmpty(nodes)) {
|
|
1874
|
-
let nodes = this.di.buildView(updateRs);
|
|
1875
|
-
point.startNode.after(...nodes);
|
|
1876
|
-
return;
|
|
1877
|
-
}
|
|
1878
|
-
let newTmpls = {};
|
|
1879
|
-
if (updateRs instanceof Template) {
|
|
1880
|
-
updateRs.vars.forEach(v => {
|
|
1881
|
-
if (v instanceof Template) {
|
|
1882
|
-
const k = v.getKey();
|
|
1883
|
-
newTmpls[k] = v;
|
|
1884
|
-
newKeys[k] = true;
|
|
1885
|
-
newSeq.push(k);
|
|
1886
|
-
}
|
|
1887
|
-
});
|
|
1888
|
-
}
|
|
1889
|
-
//UPDATE仅处理元素节点
|
|
1890
|
-
nodes = filter(compact(nodes), n => n.nodeType === Node.ELEMENT_NODE);
|
|
1891
|
-
nodesToUpdate = filter(compact(toArray(nodesToUpdate)), n => n.nodeType === Node.ELEMENT_NODE);
|
|
1892
|
-
let oldNodeMap = {};
|
|
1893
|
-
let dupKey = '';
|
|
1894
|
-
let keyQ = {};
|
|
1895
|
-
for (let i = 0; i < nodes.length; i++) {
|
|
1896
|
-
const node = nodes[i];
|
|
1897
|
-
let treeNode = node;
|
|
1898
|
-
let k = treeNode.getAttribute("key");
|
|
1899
|
-
if (!k)
|
|
1900
|
-
continue;
|
|
1901
|
-
if (oldNodeMap[k]) {
|
|
1902
|
-
dupKey = k;
|
|
1903
|
-
break;
|
|
1904
|
-
}
|
|
1905
|
-
oldNodeMap[k] = treeNode;
|
|
1906
|
-
oldSeq.push(k);
|
|
1907
|
-
keyQ[k] = true;
|
|
1908
|
-
}
|
|
1909
|
-
if (dupKey) {
|
|
1910
|
-
showError(`${camelCase(this.diClass.name)} - duplicate key '${dupKey}'`);
|
|
1911
|
-
return;
|
|
1912
|
-
}
|
|
1913
|
-
let updateQ = newKeys;
|
|
1914
|
-
const parentNode = point.startNode.parentNode;
|
|
1915
|
-
//compare
|
|
1916
|
-
let adds = [];
|
|
1917
|
-
let dels = [];
|
|
1918
|
-
//计算del
|
|
1919
|
-
each(keyQ, (v, k) => {
|
|
1920
|
-
if (!updateQ[k]) {
|
|
1921
|
-
dels.push(k);
|
|
1922
|
-
delete keyQ[k];
|
|
1923
|
-
remove(oldSeq, k);
|
|
1924
|
-
}
|
|
1925
|
-
});
|
|
1926
|
-
//计算move
|
|
1927
|
-
if (!isEmpty(newSeq)) {
|
|
1928
|
-
let lastMoveNodeId = '';
|
|
1929
|
-
let lastMoveIndex = -1;
|
|
1930
|
-
let lastGroup = [];
|
|
1931
|
-
let idWeightMap = new Map();
|
|
1932
|
-
for (let i = 0; i < newSeq.length; i++) {
|
|
1933
|
-
const nodeId = newSeq[i];
|
|
1934
|
-
let oldI = oldSeq.findIndex(c => c === nodeId);
|
|
1935
|
-
if (oldI > -1 && oldI !== i) {
|
|
1936
|
-
if (lastMoveIndex < 0 || lastMoveIndex - oldI == 1) {
|
|
1937
|
-
let lastEl = last(lastGroup);
|
|
1938
|
-
lastGroup.push({ nodeId, targetId: i === 0 ? MovePosition.AFTER_BEGIN : (lastEl ? lastEl.nodeId : newSeq[i - 1]) });
|
|
1939
|
-
}
|
|
1940
|
-
else {
|
|
1941
|
-
idWeightMap.set(lastGroup.length, { group: lastGroup, targetId: '' });
|
|
1942
|
-
// idWeightMap[lastGroup.length] = { group: lastGroup, targetId: '' }
|
|
1943
|
-
lastGroup = [];
|
|
1944
|
-
lastGroup.push({ nodeId, targetId: oldSeq[oldI] });
|
|
1945
|
-
}
|
|
1946
|
-
lastMoveIndex = oldI;
|
|
1947
|
-
}
|
|
1948
|
-
else if (oldI < 0) {
|
|
1949
|
-
let prev = lastMoveNodeId ? oldNodeMap[lastMoveNodeId] || point.endNode : point.startNode;
|
|
1950
|
-
//add
|
|
1951
|
-
adds.push({ prevNode: prev, newkey: nodeId });
|
|
1952
|
-
}
|
|
1953
|
-
lastMoveNodeId = nodeId;
|
|
1954
|
-
}
|
|
1955
|
-
if (isEmpty(idWeightMap) && lastGroup.length > 0) {
|
|
1956
|
-
idWeightMap.set(lastGroup.length, { group: lastGroup, targetId: '' });
|
|
1957
|
-
// idWeightMap[lastGroup.length] = { group: lastGroup, targetId: '' }
|
|
1958
|
-
}
|
|
1959
|
-
let keys = idWeightMap.keys().toArray();
|
|
1960
|
-
let keyNums = keys.sort((a, b) => a - b);
|
|
1961
|
-
if (keys.length > 0) {
|
|
1962
|
-
if (keys.length < 2) {
|
|
1963
|
-
//如果仅有一组,留最后一个节点
|
|
1964
|
-
let { group } = idWeightMap.get(keyNums[0]); //idWeightMap[keyNums[0]]
|
|
1965
|
-
initial(group).forEach(({ targetId, nodeId }) => {
|
|
1966
|
-
let srcEl = oldNodeMap[nodeId];
|
|
1967
|
-
let target;
|
|
1968
|
-
if (targetId === MovePosition.AFTER_BEGIN) {
|
|
1969
|
-
target = point.startNode;
|
|
1970
|
-
target.after(srcEl);
|
|
1971
|
-
}
|
|
1972
|
-
else {
|
|
1973
|
-
target = oldNodeMap[targetId];
|
|
1974
|
-
target.after(srcEl);
|
|
1975
|
-
}
|
|
1976
|
-
});
|
|
1977
|
-
}
|
|
1978
|
-
else {
|
|
1979
|
-
//如果多组,留最后一组
|
|
1980
|
-
console.debug('todo....');
|
|
1981
|
-
}
|
|
1982
|
-
} //endif
|
|
1983
|
-
console.debug('test....');
|
|
1984
|
-
}
|
|
1985
|
-
if (adds.length > 0) {
|
|
1986
|
-
this.#addNodes(adds, newTmpls, newSeq);
|
|
1987
|
-
}
|
|
1988
|
-
adds.forEach(v => {
|
|
1989
|
-
let k = v.newkey;
|
|
1990
|
-
let treeNode = this.newNodeMap[k];
|
|
1991
|
-
let prevNode = v.prevNode;
|
|
1992
|
-
if (prevNode === point.endNode) {
|
|
1993
|
-
prevNode.before(treeNode);
|
|
1994
|
-
}
|
|
1995
|
-
else if (prevNode === point.startNode) {
|
|
1996
|
-
prevNode.after(treeNode);
|
|
1997
|
-
}
|
|
1998
|
-
else {
|
|
1999
|
-
prevNode.after(treeNode);
|
|
2000
|
-
}
|
|
2001
|
-
});
|
|
2002
|
-
dels.forEach(k => {
|
|
2003
|
-
let vi = oldSeq.findIndex(s => s == k);
|
|
2004
|
-
this.#removeNode(vi);
|
|
2005
|
-
// remove(adjustedQ, ak => ak === k)
|
|
2006
|
-
let treeNode = oldNodeMap[k];
|
|
2007
|
-
if (treeNode && treeNode.parentNode) {
|
|
2008
|
-
parentNode.removeChild(treeNode);
|
|
2009
|
-
}
|
|
2010
|
-
});
|
|
2011
|
-
//reset varIndex
|
|
2012
|
-
this.di.__updatePoints.forEach(up => {
|
|
2013
|
-
if (!up.key) {
|
|
2014
|
-
up.key = up.value.tmpl.getKey();
|
|
2015
|
-
}
|
|
2016
|
-
const i = newSeq.findIndex(s => s == up.key);
|
|
2017
|
-
up.varIndex = i;
|
|
2018
|
-
});
|
|
2019
|
-
this.di.updateView(updateRs);
|
|
2020
|
-
}
|
|
2021
|
-
}
|
|
2022
|
-
getDirective() {
|
|
2023
|
-
return this.di;
|
|
2024
|
-
}
|
|
2025
|
-
newNodeMap = {};
|
|
2026
|
-
#addNodes(adds, newTmpls, newSeq) {
|
|
2027
|
-
const combStrings = [];
|
|
2028
|
-
const combVars = [];
|
|
2029
|
-
adds.forEach(add => {
|
|
2030
|
-
let k = add.newkey;
|
|
2031
|
-
combStrings.push('');
|
|
2032
|
-
combVars.push(newTmpls[k]);
|
|
2033
|
-
});
|
|
2034
|
-
combStrings.push('');
|
|
2035
|
-
let tmpl = new Template(combStrings, combVars);
|
|
2036
|
-
let originalUps = this.di.__updatePoints;
|
|
2037
|
-
let nodes = this.di.buildView(tmpl);
|
|
2038
|
-
this.di.__updatePoints.forEach((up, i) => {
|
|
2039
|
-
const k = up.value.tmpl.getKey();
|
|
2040
|
-
up.key = k;
|
|
2041
|
-
});
|
|
2042
|
-
this.di.__updatePoints.push(...originalUps);
|
|
2043
|
-
nodes.forEach((n) => {
|
|
2044
|
-
if (n instanceof HTMLElement)
|
|
2045
|
-
this.newNodeMap[n.getAttribute('key')] = n;
|
|
2046
|
-
});
|
|
2047
|
-
}
|
|
2048
|
-
//对于foreach指令,key就是序号
|
|
2049
|
-
#removeNode(key) {
|
|
2050
|
-
remove(this.di.__updatePoints, (v, k) => {
|
|
2051
|
-
if (v.varIndex == key) {
|
|
2052
|
-
DomUtil.remove(v.node, v.textNode);
|
|
2053
|
-
return true;
|
|
2054
|
-
}
|
|
2055
|
-
});
|
|
2056
|
-
}
|
|
2057
|
-
}
|
|
2058
|
-
/**
|
|
2059
|
-
* 返回指令调用函数
|
|
2060
|
-
* @param di
|
|
2061
|
-
* @returns
|
|
2062
|
-
*/
|
|
2063
|
-
function directive(diClass) {
|
|
2064
|
-
return (...args) => {
|
|
2065
|
-
let wrapper = null;
|
|
2066
|
-
//todo 可能存在非返回模板函数开启了依赖监控
|
|
2067
|
-
args.forEach((v, i) => {
|
|
2068
|
-
if (isFunction(v)) {
|
|
2069
|
-
let cbk = v;
|
|
2070
|
-
args[i] = function (...ps) {
|
|
2071
|
-
let di = wrapper.di;
|
|
2072
|
-
Collector.startRender(di);
|
|
2073
|
-
let rs = cbk.call(di.renderComponent, ...ps);
|
|
2074
|
-
Collector.endRender(di.renderComponent);
|
|
2075
|
-
return rs;
|
|
2076
|
-
};
|
|
2077
|
-
}
|
|
2078
|
-
});
|
|
2079
|
-
wrapper = new DirectiveWrapper(diClass, ...args);
|
|
2080
|
-
return wrapper;
|
|
2081
|
-
};
|
|
2082
|
-
}
|
|
2083
|
-
|
|
2084
|
-
/*************************************************************
|
|
2085
|
-
* 扩展事件
|
|
2086
|
-
* @author holyhigh2
|
|
2087
|
-
*
|
|
2088
|
-
* resize
|
|
2089
|
-
* outside[.mousedown/up/click/dblclick] 默认click
|
|
2090
|
-
* mutate[.attr/child/char/tree]
|
|
2091
|
-
*
|
|
2092
|
-
*************************************************************/
|
|
2093
|
-
const ExtEvNames = ['resize', 'outside', 'mutate'];
|
|
2094
|
-
///////////////////////////////////////////////// resize
|
|
2095
|
-
const AllResizeEls = new WeakMap;
|
|
2096
|
-
const AllOutsideDownEls = [];
|
|
2097
|
-
const resizeObserver = new ResizeObserver((entries) => {
|
|
2098
|
-
for (const entry of entries) {
|
|
2099
|
-
const contentBoxSize = Array.isArray(entry.contentBoxSize)
|
|
2100
|
-
? entry.contentBoxSize[0]
|
|
2101
|
-
: entry.contentBoxSize;
|
|
2102
|
-
const borderBoxSize = Array.isArray(entry.borderBoxSize)
|
|
2103
|
-
? entry.borderBoxSize[0]
|
|
2104
|
-
: entry.borderBoxSize;
|
|
2105
|
-
let cbk = AllResizeEls.get(entry.target);
|
|
2106
|
-
if (cbk) {
|
|
2107
|
-
let ev = new CustomEvent('resize', {
|
|
2108
|
-
bubbles: false,
|
|
2109
|
-
cancelable: false,
|
|
2110
|
-
detail: {
|
|
2111
|
-
borderBox: { w: borderBoxSize.inlineSize, h: borderBoxSize.blockSize },
|
|
2112
|
-
contentBox: { w: contentBoxSize.inlineSize, h: contentBoxSize.blockSize },
|
|
2113
|
-
},
|
|
2114
|
-
});
|
|
2115
|
-
cbk(ev, entry.target);
|
|
2116
|
-
}
|
|
2117
|
-
}
|
|
2118
|
-
});
|
|
2119
|
-
function addResize(node, cbk) {
|
|
2120
|
-
if (AllResizeEls.has(node))
|
|
2121
|
-
return;
|
|
2122
|
-
AllResizeEls.set(node, cbk);
|
|
2123
|
-
resizeObserver.observe(node);
|
|
2124
|
-
}
|
|
2125
|
-
///////////////////////////////////////////////// mutate
|
|
2126
|
-
var MutationType;
|
|
2127
|
-
(function (MutationType) {
|
|
2128
|
-
MutationType["Child"] = "child";
|
|
2129
|
-
MutationType["Tree"] = "tree";
|
|
2130
|
-
MutationType["Attr"] = "attr";
|
|
2131
|
-
MutationType["Char"] = "char";
|
|
2132
|
-
})(MutationType || (MutationType = {}));
|
|
2133
|
-
const AllMutationEls = new WeakMap;
|
|
2134
|
-
const mutationObserver = new MutationObserver(mutations => {
|
|
2135
|
-
for (let i = 0; i < mutations.length; i++) {
|
|
2136
|
-
const mutation = mutations[i];
|
|
2137
|
-
let map = AllMutationEls.get(mutation.target);
|
|
2138
|
-
if (!map)
|
|
2139
|
-
return;
|
|
2140
|
-
let detail = {
|
|
2141
|
-
target: mutation.target
|
|
2142
|
-
};
|
|
2143
|
-
let cbk = null;
|
|
2144
|
-
switch (mutation.type) {
|
|
2145
|
-
case 'subtree':
|
|
2146
|
-
detail.type = MutationType.Tree;
|
|
2147
|
-
cbk = map[MutationType.Tree];
|
|
2148
|
-
break;
|
|
2149
|
-
case "childList":
|
|
2150
|
-
detail.type = MutationType.Child;
|
|
2151
|
-
detail.addedNodes = mutation.addedNodes;
|
|
2152
|
-
detail.removedNodes = mutation.removedNodes;
|
|
2153
|
-
cbk = map[MutationType.Child];
|
|
2154
|
-
break;
|
|
2155
|
-
case "attributes":
|
|
2156
|
-
detail.type = MutationType.Attr;
|
|
2157
|
-
detail.attributeName = mutation.attributeName;
|
|
2158
|
-
detail.oldValue = mutation.oldValue;
|
|
2159
|
-
cbk = map[MutationType.Attr];
|
|
2160
|
-
break;
|
|
2161
|
-
case "characterData":
|
|
2162
|
-
detail.type = MutationType.Char;
|
|
2163
|
-
detail.oldValue = mutation.oldValue;
|
|
2164
|
-
cbk = map[MutationType.Char];
|
|
2165
|
-
break;
|
|
2166
|
-
}
|
|
2167
|
-
if (cbk) {
|
|
2168
|
-
let ev = new CustomEvent('mutate', {
|
|
2169
|
-
bubbles: false,
|
|
2170
|
-
cancelable: false,
|
|
2171
|
-
detail
|
|
2172
|
-
});
|
|
2173
|
-
cbk(ev, mutation.target);
|
|
2174
|
-
}
|
|
2175
|
-
}
|
|
2176
|
-
});
|
|
2177
|
-
function addMutation(node, cbk, parts) {
|
|
2178
|
-
let child = includes(parts, 'child');
|
|
2179
|
-
let attr = includes(parts, 'attr');
|
|
2180
|
-
let char = includes(parts, 'char');
|
|
2181
|
-
let tree = includes(parts, 'tree');
|
|
2182
|
-
let map = AllMutationEls.get(node);
|
|
2183
|
-
if (map)
|
|
2184
|
-
return;
|
|
2185
|
-
map = {};
|
|
2186
|
-
AllMutationEls.set(node, map);
|
|
2187
|
-
if (child) {
|
|
2188
|
-
map[MutationType.Child] = cbk;
|
|
2189
|
-
}
|
|
2190
|
-
if (attr) {
|
|
2191
|
-
map[MutationType.Attr] = cbk;
|
|
2192
|
-
}
|
|
2193
|
-
if (char) {
|
|
2194
|
-
map[MutationType.Char] = cbk;
|
|
2195
|
-
}
|
|
2196
|
-
if (tree) {
|
|
2197
|
-
map[MutationType.Tree] = cbk;
|
|
2198
|
-
}
|
|
2199
|
-
mutationObserver.observe(node, {
|
|
2200
|
-
childList: child,
|
|
2201
|
-
attributes: attr,
|
|
2202
|
-
characterData: char,
|
|
2203
|
-
subtree: tree
|
|
2204
|
-
});
|
|
2205
|
-
}
|
|
2206
|
-
///////////////////////////////////////////////// outside
|
|
2207
|
-
document.addEventListener('mousedown', e => {
|
|
2208
|
-
let t = e.target;
|
|
2209
|
-
AllOutsideDownEls.forEach(([node, cbk]) => {
|
|
2210
|
-
if (!node.contains(t)) {
|
|
2211
|
-
let ev = new CustomEvent('outside', {
|
|
2212
|
-
bubbles: false,
|
|
2213
|
-
cancelable: false,
|
|
2214
|
-
detail: {
|
|
2215
|
-
currentTarget: node,
|
|
2216
|
-
event: e
|
|
2217
|
-
},
|
|
2218
|
-
});
|
|
2219
|
-
cbk(ev, node);
|
|
2220
|
-
}
|
|
2221
|
-
});
|
|
2222
|
-
}, false);
|
|
2223
|
-
function addOutsideMouseDown(node, cbk) {
|
|
2224
|
-
AllOutsideDownEls.push([node, cbk]);
|
|
2225
|
-
}
|
|
2226
|
-
function isExtEvent(evName) {
|
|
2227
|
-
return ExtEvNames.includes(evName);
|
|
2228
|
-
}
|
|
2229
|
-
function addExtEvent(evName, node, cbk, parts) {
|
|
2230
|
-
if (evName === 'resize') {
|
|
2231
|
-
addResize(node, cbk);
|
|
2232
|
-
}
|
|
2233
|
-
else if (evName === 'outside') {
|
|
2234
|
-
switch (parts[0]) {
|
|
2235
|
-
case 'mousedown':
|
|
2236
|
-
addOutsideMouseDown(node, cbk);
|
|
2237
|
-
break;
|
|
2238
|
-
}
|
|
2239
|
-
}
|
|
2240
|
-
else if (evName === 'mutate') {
|
|
2241
|
-
addMutation(node, cbk, parts);
|
|
2242
|
-
}
|
|
2243
|
-
}
|
|
2244
|
-
|
|
2245
|
-
const MODI_EV_DEBOUNCE = /,|^(debounce:.+)|(debounce$)/;
|
|
2246
|
-
const MODI_EV_THROTTLE = /,|^(throttle:.+)|(throttle$)/;
|
|
2247
|
-
const MODI_EV_SELF = 'self';
|
|
2248
|
-
const MODI_EV_STOP = 'stop';
|
|
2249
|
-
const MODI_EV_PREVENT = 'prevent';
|
|
2250
|
-
const MODI_EV_ONCE = 'once';
|
|
2251
|
-
const MODI_EV_MOUSE_LEFT = 'left';
|
|
2252
|
-
const MODI_EV_MOUSE_RIGHT = 'right';
|
|
2253
|
-
const MODI_EV_MOUSE_MIDDLE = 'middle';
|
|
2254
|
-
const MODI_EV_KEYBOARD_COMBO_CTRL = 'ctrl';
|
|
2255
|
-
const MODI_EV_KEYBOARD_COMBO_ALT = 'alt';
|
|
2256
|
-
const MODI_EV_KEYBOARD_COMBO_SHIFT = 'shift';
|
|
2257
|
-
const MODI_EV_KEYBOARD_COMBO_META = 'meta';
|
|
2258
|
-
const MODI_EV_KEYBOARD_KEY_MAP = {
|
|
2259
|
-
'esc': 'escape'
|
|
2260
|
-
};
|
|
2261
|
-
const MODI_PARAM_DIVIDER = ":";
|
|
2262
|
-
function addEvent(fullName, cbk, node, component) {
|
|
2263
|
-
let parts = fullName.split('.');
|
|
2264
|
-
let evName = parts.shift();
|
|
2265
|
-
let isOnce = parts.includes(MODI_EV_ONCE);
|
|
2266
|
-
let c = cbk;
|
|
2267
|
-
let modi;
|
|
2268
|
-
if (modi = find(parts, x => MODI_EV_DEBOUNCE.test(x))) {
|
|
2269
|
-
let params = modi.split(MODI_PARAM_DIVIDER);
|
|
2270
|
-
c = debounce(c, parseInt(params[1]) || 100);
|
|
2271
|
-
}
|
|
2272
|
-
if (modi = find(parts, x => MODI_EV_THROTTLE.test(x))) {
|
|
2273
|
-
let params = modi.split(MODI_PARAM_DIVIDER);
|
|
2274
|
-
c = throttle(c, parseInt(params[1]) || 100);
|
|
2275
|
-
}
|
|
2276
|
-
if (isOnce) {
|
|
2277
|
-
c = once(c);
|
|
2278
|
-
}
|
|
2279
|
-
if (isExtEvent(evName)) {
|
|
2280
|
-
addExtEvent(evName, node, c, parts);
|
|
2281
|
-
return c;
|
|
2282
|
-
}
|
|
2283
|
-
let listener = (e) => {
|
|
2284
|
-
if (parts.includes(MODI_EV_PREVENT))
|
|
2285
|
-
e.preventDefault();
|
|
2286
|
-
if (parts.includes(MODI_EV_STOP))
|
|
2287
|
-
e.stopPropagation();
|
|
2288
|
-
if (parts.includes(MODI_EV_SELF) && e.target !== e.currentTarget)
|
|
2289
|
-
return;
|
|
2290
|
-
if (e instanceof MouseEvent) {
|
|
2291
|
-
if (parts.includes(MODI_EV_MOUSE_LEFT) && e.button != 0)
|
|
2292
|
-
return;
|
|
2293
|
-
if (parts.includes(MODI_EV_MOUSE_RIGHT) && e.button != 2)
|
|
2294
|
-
return;
|
|
2295
|
-
if (parts.includes(MODI_EV_MOUSE_MIDDLE) && e.button != 1)
|
|
2296
|
-
return;
|
|
2297
|
-
}
|
|
2298
|
-
else if (e instanceof KeyboardEvent) {
|
|
2299
|
-
if (remove(parts, p => p == MODI_EV_KEYBOARD_COMBO_CTRL)[0] && !e.ctrlKey)
|
|
2300
|
-
return;
|
|
2301
|
-
if (remove(parts, p => p == MODI_EV_KEYBOARD_COMBO_ALT)[0] && !e.altKey)
|
|
2302
|
-
return;
|
|
2303
|
-
if (remove(parts, p => p == MODI_EV_KEYBOARD_COMBO_SHIFT)[0] && !e.shiftKey)
|
|
2304
|
-
return;
|
|
2305
|
-
if (remove(parts, p => p == MODI_EV_KEYBOARD_COMBO_META)[0] && !e.metaKey)
|
|
2306
|
-
return;
|
|
2307
|
-
let checkKeys = map(parts, k => MODI_EV_KEYBOARD_KEY_MAP[k] || k);
|
|
2308
|
-
if (!checkKeys.includes(e.key.toLowerCase()))
|
|
2309
|
-
return;
|
|
2310
|
-
}
|
|
2311
|
-
c(e, node);
|
|
2312
|
-
};
|
|
2313
|
-
node.addEventListener(evName, listener);
|
|
2314
|
-
//record
|
|
2315
|
-
let evAry = component.__events[evName];
|
|
2316
|
-
if (!evAry)
|
|
2317
|
-
evAry = component.__events[evName] = [];
|
|
2318
|
-
evAry.push([node, listener]);
|
|
2319
|
-
return listener;
|
|
2320
|
-
}
|
|
2321
|
-
|
|
2322
|
-
const ATTR_PREFIX_EVENT = "@";
|
|
2323
|
-
const ATTR_PREFIX_PROP = ".";
|
|
2324
|
-
const ATTR_PREFIX_BOOLEAN = "?";
|
|
2325
|
-
const ATTR_PREFIX_REF = "*";
|
|
2326
|
-
const ATTR_PROP_DELIMITER = ":";
|
|
2327
|
-
const ATTR_REF = "ref";
|
|
2328
|
-
const EXP_ATTR_CHECK = /[.?-a-z]+\s*=\s*(['"])\s*([^='"]*<\!--c_ui-pl_df-->){2,}.*?\1/ims;
|
|
2329
|
-
const EXP_PLACEHOLDER = /<\s*[a-z0-9-]+([^>]*<\!--c_ui-pl_df-->)*[^>]*?(?<!-)>/imgs;
|
|
2330
|
-
const SLOT_KEY_PROPS = 'slot-props';
|
|
2331
|
-
/**
|
|
2332
|
-
* 提供渲染函数相关操作
|
|
2333
|
-
* @author holyhigh2
|
|
2334
|
-
*/
|
|
2335
|
-
/**
|
|
2336
|
-
* 高性能dom生成及变量绑定算法
|
|
2337
|
-
* 1. 使用占位符拼接HTML字符串,占位符与变量需要按照顺序对应
|
|
2338
|
-
* 2. 插入dom片段,并遍历元素+注释节点, 搜索占位符
|
|
2339
|
-
* 1. 按顺序遍历所有attr,发现一个属性值含有占位符时,标记节点及属性名,以便变量可以进行绑定( 如果key是事件/ref则内容仅允许一个占位符)
|
|
2340
|
-
* 2. 如果是注释节点
|
|
2341
|
-
* 1. 在后面追加同内容注释节点,标记两个节点,以便变量可以进行绑定
|
|
2342
|
-
* 2. 在中间插入变量内容
|
|
2343
|
-
* 3. 只有表达式是一个指令时才能绑定依赖
|
|
2344
|
-
* @param component
|
|
2345
|
-
* @param tmpl
|
|
2346
|
-
* @returns [html,vars]
|
|
2347
|
-
*/
|
|
2348
|
-
function buildHTML(component, tmpl) {
|
|
2349
|
-
let html = "";
|
|
2350
|
-
let vars = concat(tmpl.vars);
|
|
2351
|
-
let l = tmpl.strings.length - 1;
|
|
2352
|
-
let vl = tmpl.vars.length - 1;
|
|
2353
|
-
for (let i = 0; i <= l; i++) {
|
|
2354
|
-
const str = tmpl.strings[i];
|
|
2355
|
-
let val = get(tmpl.vars, i, '');
|
|
2356
|
-
if (val && val.di) {
|
|
2357
|
-
let rs = val.render(component);
|
|
2358
|
-
if (rs instanceof Template) {
|
|
2359
|
-
let [h, v] = buildHTML(component, rs);
|
|
2360
|
-
Reflect.defineProperty(val, '_renderVars', { value: v });
|
|
2361
|
-
// set(val, '_renderVars', v)
|
|
2362
|
-
val = PLACEHOLDER_DI_START + h + PLACEHOLDER_DI_END;
|
|
2363
|
-
}
|
|
2364
|
-
else {
|
|
2365
|
-
val = rs ?? PLACEHOLDER;
|
|
2366
|
-
}
|
|
2367
|
-
}
|
|
2368
|
-
else if (val instanceof Template) {
|
|
2369
|
-
let [h, v] = buildHTML(component, val);
|
|
2370
|
-
Reflect.defineProperty(val, '_renderVars', { value: v });
|
|
2371
|
-
// set(val, '_renderVars', v)
|
|
2372
|
-
val = PLACEHOLDER_TMPL_START + h + PLACEHOLDER_TMPL_END;
|
|
2373
|
-
// vars.splice(i + offset, 1, ...v)
|
|
2374
|
-
// offset += v.length
|
|
2375
|
-
}
|
|
2376
|
-
else {
|
|
2377
|
-
val = i > vl ? "" : PLACEHOLDER;
|
|
2378
|
-
}
|
|
2379
|
-
html += str + val;
|
|
2380
|
-
}
|
|
2381
|
-
//attr check
|
|
2382
|
-
let rs = html.match(EXP_ATTR_CHECK);
|
|
2383
|
-
if (rs) {
|
|
2384
|
-
let errorMsg = replaceAll(rs[0], PLACEHOLDER, '${...}');
|
|
2385
|
-
showError(`Parse error: attribute value can be set only one interpolation —— \n ${errorMsg}`);
|
|
2386
|
-
return ['', vars];
|
|
2387
|
-
}
|
|
2388
|
-
let i = 0;
|
|
2389
|
-
html = html.replace(EXP_PLACEHOLDER, (a, b) => {
|
|
2390
|
-
let rs = replaceAll(a, PLACEHOLDER, () => PLACEHOLDER.replace('-->', '') + (i++));
|
|
2391
|
-
return rs;
|
|
2392
|
-
});
|
|
2393
|
-
html = html.replace(EXP_STR, '$1><').trim();
|
|
2394
|
-
return [html, vars];
|
|
2395
|
-
}
|
|
2396
|
-
const PLACEHOLDER_DI_START = "<!--c_ui-pl_di-start-->";
|
|
2397
|
-
const PLACEHOLDER_DI_END = "<!--c_ui-pl_di-end-->";
|
|
2398
|
-
const PLACEHOLDER_TMPL_START = "<!--c_ui-pl_tmpl-start-->";
|
|
2399
|
-
const PLACEHOLDER_TMPL_END = "<!--c_ui-pl_tmpl-end-->";
|
|
2400
|
-
const PLACEHOLDER = "<!--c_ui-pl_df-->";
|
|
2401
|
-
const PLACEHOLDER_PREFFIX = "<!--c_ui-pl_df";
|
|
2402
|
-
const PLACEHOLDER_EXP = /<!--c_ui-pl_df\d*(-->)?/;
|
|
2403
|
-
/**
|
|
2404
|
-
* 构建模板为DOM结构
|
|
2405
|
-
* @param html
|
|
2406
|
-
*/
|
|
2407
|
-
function buildTmplate(updatePoints, html, vars, component, viewContext) {
|
|
2408
|
-
const container = document.createElement("div");
|
|
2409
|
-
container.innerHTML = html;
|
|
2410
|
-
//遍历dom
|
|
2411
|
-
const nodeIterator = document.createNodeIterator(container, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_COMMENT);
|
|
2412
|
-
let currentNode;
|
|
2413
|
-
let varIndex = 0;
|
|
2414
|
-
let slotComponent = null;
|
|
2415
|
-
let startDiCommentNode;
|
|
2416
|
-
let startDiCommentNodeStack = [];
|
|
2417
|
-
let startDiStack = [];
|
|
2418
|
-
let startDiUpdatePointStack = [];
|
|
2419
|
-
let updatePointsStack = [updatePoints];
|
|
2420
|
-
let varStack = [];
|
|
2421
|
-
let varIndexStack = [];
|
|
2422
|
-
while ((currentNode = nodeIterator.nextNode())) {
|
|
2423
|
-
if (currentNode instanceof HTMLElement || currentNode instanceof SVGElement) {
|
|
2424
|
-
if (currentNode instanceof CompElem) {
|
|
2425
|
-
slotComponent = currentNode;
|
|
2426
|
-
}
|
|
2427
|
-
else {
|
|
2428
|
-
if (!slotComponent?.contains(currentNode)) {
|
|
2429
|
-
slotComponent = null;
|
|
2430
|
-
}
|
|
2431
|
-
}
|
|
2432
|
-
let props = {};
|
|
2433
|
-
let attrs = toArray(currentNode.attributes);
|
|
2434
|
-
for (let i = 0; i < attrs.length; i++) {
|
|
2435
|
-
const attr = attrs[i];
|
|
2436
|
-
let { name, value } = attr;
|
|
2437
|
-
if (name === SLOT_KEY_PROPS) {
|
|
2438
|
-
let slotName = currentNode.getAttribute('name') || 'default';
|
|
2439
|
-
if (slotComponent) {
|
|
2440
|
-
let ary = slotComponent._slotsPropMap[slotName];
|
|
2441
|
-
if (!ary) {
|
|
2442
|
-
ary = slotComponent._slotsPropMap[slotName] = [];
|
|
2443
|
-
}
|
|
2444
|
-
ary.push(currentNode);
|
|
2445
|
-
}
|
|
2446
|
-
} //endif
|
|
2447
|
-
if (startsWith(name, PLACEHOLDER_PREFFIX)) {
|
|
2448
|
-
let val = vars[varIndex];
|
|
2449
|
-
//support directive only for now
|
|
2450
|
-
if (val instanceof DirectiveWrapper) {
|
|
2451
|
-
val.checkScope(EnterPointType.TAG);
|
|
2452
|
-
let point = new EnterPoint(currentNode, name.substring(1), EnterPointType.TAG);
|
|
2453
|
-
val.point = point;
|
|
2454
|
-
val.di.slotComponent = slotComponent;
|
|
2455
|
-
val.di.renderComponent = component;
|
|
2456
|
-
let po = new UpdatePoint(varIndex, currentNode);
|
|
2457
|
-
po.isDirective = true;
|
|
2458
|
-
po.value = val;
|
|
2459
|
-
po.isComponent = !!slotComponent;
|
|
2460
|
-
updatePoints.push(po);
|
|
2461
|
-
varIndex++;
|
|
2462
|
-
val.di.created(point, ...val.args);
|
|
2463
|
-
}
|
|
2464
|
-
currentNode.removeAttribute(name);
|
|
2465
|
-
continue;
|
|
2466
|
-
} //endif
|
|
2467
|
-
//@event.stop.prevent.debounce
|
|
2468
|
-
if (name[0] === ATTR_PREFIX_EVENT) {
|
|
2469
|
-
let cbk = (e) => { };
|
|
2470
|
-
if (PLACEHOLDER_EXP.test(value)) {
|
|
2471
|
-
let val = vars[varIndex];
|
|
2472
|
-
if (!isFunction(val)) {
|
|
2473
|
-
showTagError(currentNode.tagName, `Event '${name}' must be a function`);
|
|
2474
|
-
continue;
|
|
2475
|
-
}
|
|
2476
|
-
cbk = val.bind(component);
|
|
2477
|
-
let po = new UpdatePoint(varIndex, currentNode, name.replace(/\.|\?|@/, ''), value);
|
|
2478
|
-
po.isComponent = !!slotComponent;
|
|
2479
|
-
po.isEvent = true;
|
|
2480
|
-
updatePoints.push(po);
|
|
2481
|
-
varIndex++;
|
|
2482
|
-
}
|
|
2483
|
-
addEvent(name.substring(1), cbk, currentNode, component);
|
|
2484
|
-
currentNode.removeAttribute(name);
|
|
2485
|
-
continue;
|
|
2486
|
-
} //endif
|
|
2487
|
-
if (name === ATTR_REF) {
|
|
2488
|
-
if (PLACEHOLDER_EXP.test(value)) {
|
|
2489
|
-
let val = vars[varIndex];
|
|
2490
|
-
if (!has(val, 'current')) {
|
|
2491
|
-
showTagError(currentNode.tagName, `Ref must be a RefObject`);
|
|
2492
|
-
continue;
|
|
2493
|
-
}
|
|
2494
|
-
varIndex++;
|
|
2495
|
-
val.current = currentNode;
|
|
2496
|
-
}
|
|
2497
|
-
currentNode.removeAttribute(name);
|
|
2498
|
-
continue;
|
|
2499
|
-
} //endif
|
|
2500
|
-
//校验变量必须是表达式
|
|
2501
|
-
if (name[0] === ATTR_PREFIX_PROP && !PLACEHOLDER_EXP.test(value)) {
|
|
2502
|
-
showTagError(currentNode.tagName, `Prop '${name}' must be an interpolation`);
|
|
2503
|
-
continue;
|
|
2504
|
-
}
|
|
2505
|
-
if (PLACEHOLDER_EXP.test(value)) {
|
|
2506
|
-
let val = vars[varIndex];
|
|
2507
|
-
let po = new UpdatePoint(varIndex, currentNode, name.replace(/\.|\?|@/, ''), value);
|
|
2508
|
-
updatePoints.push(po);
|
|
2509
|
-
po.isComponent = !!slotComponent;
|
|
2510
|
-
if (name[0] === ATTR_PREFIX_PROP ||
|
|
2511
|
-
name[0] === ATTR_PREFIX_BOOLEAN ||
|
|
2512
|
-
name[0] === ATTR_PREFIX_REF) {
|
|
2513
|
-
if (val instanceof DirectiveWrapper) {
|
|
2514
|
-
val.checkScope(EnterPointType.PROP);
|
|
2515
|
-
let point = new EnterPoint(currentNode, name.substring(1), EnterPointType.PROP);
|
|
2516
|
-
val.point = point;
|
|
2517
|
-
val.slotComponent = slotComponent;
|
|
2518
|
-
po.value = val;
|
|
2519
|
-
po.isDirective = true;
|
|
2520
|
-
if (val) {
|
|
2521
|
-
val.di.created(val.point, ...val.args);
|
|
2522
|
-
}
|
|
2523
|
-
}
|
|
2524
|
-
else if (name[0] === ATTR_PREFIX_BOOLEAN) {
|
|
2525
|
-
po.isToggleProp = true;
|
|
2526
|
-
po.value = !!val;
|
|
2527
|
-
if (po.value)
|
|
2528
|
-
currentNode.setAttribute(name.substring(1), '');
|
|
2529
|
-
}
|
|
2530
|
-
else if (name[0] === ATTR_PREFIX_REF) {
|
|
2531
|
-
po.value = val;
|
|
2532
|
-
let refNames = name.substring(1);
|
|
2533
|
-
const [refNamec, prop] = refNames.split(ATTR_PROP_DELIMITER);
|
|
2534
|
-
let refName = refNamec;
|
|
2535
|
-
switch (prop) {
|
|
2536
|
-
case 'camel':
|
|
2537
|
-
refName = camelCase(refName);
|
|
2538
|
-
break;
|
|
2539
|
-
case 'kebab':
|
|
2540
|
-
refName = kebabCase(refName);
|
|
2541
|
-
break;
|
|
2542
|
-
case 'snake':
|
|
2543
|
-
refName = snakeCase(refName);
|
|
2544
|
-
break;
|
|
2545
|
-
}
|
|
2546
|
-
po.attrName = refName;
|
|
2547
|
-
currentNode.setAttribute(refName, val);
|
|
2548
|
-
}
|
|
2549
|
-
else {
|
|
2550
|
-
if (!(currentNode instanceof CompElem) && currentNode.tagName !== 'SLOT') {
|
|
2551
|
-
showTagError(currentNode.tagName, `Prop '${name}' can only be set on a CompElem or a slot`);
|
|
2552
|
-
}
|
|
2553
|
-
else {
|
|
2554
|
-
let propName = camelCase(name.substring(1));
|
|
2555
|
-
if (!(propName in currentNode) && currentNode.tagName !== 'SLOT') {
|
|
2556
|
-
showTagError(currentNode.tagName, `Prop '${name}' is not defined in ${currentNode.tagName}`);
|
|
2557
|
-
}
|
|
2558
|
-
po.value = val;
|
|
2559
|
-
po.isProp = true;
|
|
2560
|
-
props[propName] = val;
|
|
2561
|
-
}
|
|
2562
|
-
}
|
|
2563
|
-
currentNode.removeAttribute(name);
|
|
2564
|
-
val = '';
|
|
2565
|
-
}
|
|
2566
|
-
else {
|
|
2567
|
-
po.value = val;
|
|
2568
|
-
let dw;
|
|
2569
|
-
if (val instanceof DirectiveWrapper) {
|
|
2570
|
-
let type = EnterPointType.ATTR;
|
|
2571
|
-
if (name === "class") {
|
|
2572
|
-
type = EnterPointType.CLASS;
|
|
2573
|
-
}
|
|
2574
|
-
else if (name === "style") {
|
|
2575
|
-
type = EnterPointType.STYLE;
|
|
2576
|
-
}
|
|
2577
|
-
val.checkScope(type);
|
|
2578
|
-
po.isDirective = true;
|
|
2579
|
-
let point = new EnterPoint(currentNode, name, type);
|
|
2580
|
-
val.point = point;
|
|
2581
|
-
val.di.slotComponent = slotComponent;
|
|
2582
|
-
val.di.renderComponent = component;
|
|
2583
|
-
dw = val;
|
|
2584
|
-
// val.di.created(point, ...val.args)
|
|
2585
|
-
val = '';
|
|
2586
|
-
}
|
|
2587
|
-
value = replace(value, PLACEHOLDER_EXP, val);
|
|
2588
|
-
//回填
|
|
2589
|
-
attr.value = value;
|
|
2590
|
-
if (dw) {
|
|
2591
|
-
dw.di.created(dw.point, ...dw.args);
|
|
2592
|
-
}
|
|
2593
|
-
}
|
|
2594
|
-
varIndex++;
|
|
2595
|
-
} //endif
|
|
2596
|
-
} //endfor
|
|
2597
|
-
if (currentNode instanceof CompElem) {
|
|
2598
|
-
currentNode._initProps(props);
|
|
2599
|
-
}
|
|
2600
|
-
else if (currentNode instanceof HTMLSlotElement) {
|
|
2601
|
-
component._bindSlot(currentNode, currentNode.name || 'default', props);
|
|
2602
|
-
}
|
|
2603
|
-
}
|
|
2604
|
-
else {
|
|
2605
|
-
let comment = currentNode;
|
|
2606
|
-
let ph = `<!--${comment.nodeValue}-->`;
|
|
2607
|
-
if (ph === PLACEHOLDER_DI_START) {
|
|
2608
|
-
if (startDiCommentNode) {
|
|
2609
|
-
startDiCommentNodeStack.push(startDiCommentNode);
|
|
2610
|
-
}
|
|
2611
|
-
startDiCommentNode = comment;
|
|
2612
|
-
let val = vars[varIndex];
|
|
2613
|
-
let po = new UpdatePoint(varIndex, currentNode);
|
|
2614
|
-
po.isComponent = !!slotComponent;
|
|
2615
|
-
po.isDirective = true;
|
|
2616
|
-
po.value = val;
|
|
2617
|
-
let pType = slotComponent ? EnterPointType.SLOT : EnterPointType.TEXT;
|
|
2618
|
-
let point = new EnterPoint(startDiCommentNode, "", pType);
|
|
2619
|
-
val.point = point;
|
|
2620
|
-
val.di.slotComponent = slotComponent;
|
|
2621
|
-
val.di.renderComponent = component;
|
|
2622
|
-
startDiStack.push(val);
|
|
2623
|
-
updatePoints.push(po);
|
|
2624
|
-
startDiUpdatePointStack.push(po);
|
|
2625
|
-
//stack updatePoints
|
|
2626
|
-
updatePoints = [];
|
|
2627
|
-
updatePointsStack.push(updatePoints);
|
|
2628
|
-
varIndex++;
|
|
2629
|
-
//stack vars
|
|
2630
|
-
varIndexStack.push(varIndex);
|
|
2631
|
-
varStack.push(vars);
|
|
2632
|
-
vars = val._renderVars;
|
|
2633
|
-
varIndex = 0;
|
|
2634
|
-
continue;
|
|
2635
|
-
}
|
|
2636
|
-
else if (ph === PLACEHOLDER_DI_END) {
|
|
2637
|
-
startDiUpdatePointStack.pop().textNode = comment;
|
|
2638
|
-
let startDi = startDiStack.pop();
|
|
2639
|
-
startDi.point.endNode = comment;
|
|
2640
|
-
//结束时调用created
|
|
2641
|
-
startDi.di.created(startDi.point, ...startDi.args);
|
|
2642
|
-
startDiCommentNode = startDiCommentNodeStack.pop();
|
|
2643
|
-
startDi.di.__updatePoints = updatePoints;
|
|
2644
|
-
updatePointsStack.pop();
|
|
2645
|
-
updatePoints = last(updatePointsStack);
|
|
2646
|
-
//restore vars
|
|
2647
|
-
vars = varStack.pop();
|
|
2648
|
-
varIndex = varIndexStack.pop();
|
|
2649
|
-
}
|
|
2650
|
-
else if (ph === PLACEHOLDER_TMPL_START) {
|
|
2651
|
-
if (startDiCommentNode) {
|
|
2652
|
-
startDiCommentNodeStack.push(startDiCommentNode);
|
|
2653
|
-
}
|
|
2654
|
-
startDiCommentNode = comment;
|
|
2655
|
-
let val = vars[varIndex];
|
|
2656
|
-
let po = new UpdatePoint(varIndex, currentNode);
|
|
2657
|
-
po.isComponent = !!slotComponent;
|
|
2658
|
-
po.isTmpl = true;
|
|
2659
|
-
let parentDi = last(startDiStack);
|
|
2660
|
-
if (parentDi && get(parentDi, 'diClass.name') === 'ForEach') {
|
|
2661
|
-
po.key = val.getKey();
|
|
2662
|
-
}
|
|
2663
|
-
else if (viewContext.constructor.name == 'ForEach') {
|
|
2664
|
-
po.key = val.getKey();
|
|
2665
|
-
}
|
|
2666
|
-
val = po.value = new SubView(val);
|
|
2667
|
-
let pType = slotComponent ? EnterPointType.SLOT : EnterPointType.TEXT;
|
|
2668
|
-
let point = new EnterPoint(startDiCommentNode, "", pType);
|
|
2669
|
-
val.point = point;
|
|
2670
|
-
val.slotComponent = slotComponent;
|
|
2671
|
-
val.renderComponent = component;
|
|
2672
|
-
startDiStack.push(val);
|
|
2673
|
-
updatePoints.push(po);
|
|
2674
|
-
startDiUpdatePointStack.push(po);
|
|
2675
|
-
//stack updatePoints
|
|
2676
|
-
updatePoints = [];
|
|
2677
|
-
updatePointsStack.push(updatePoints);
|
|
2678
|
-
varIndex++;
|
|
2679
|
-
//stack vars
|
|
2680
|
-
varIndexStack.push(varIndex);
|
|
2681
|
-
varStack.push(vars);
|
|
2682
|
-
vars = val._renderVars;
|
|
2683
|
-
varIndex = 0;
|
|
2684
|
-
continue;
|
|
2685
|
-
}
|
|
2686
|
-
else if (ph === PLACEHOLDER_TMPL_END) {
|
|
2687
|
-
startDiUpdatePointStack.pop().textNode = comment;
|
|
2688
|
-
let startDi = startDiStack.pop();
|
|
2689
|
-
startDi.point.endNode = comment;
|
|
2690
|
-
startDiCommentNode = startDiCommentNodeStack.pop();
|
|
2691
|
-
startDi.__updatePoints = updatePoints;
|
|
2692
|
-
updatePointsStack.pop();
|
|
2693
|
-
updatePoints = last(updatePointsStack);
|
|
2694
|
-
//restore vars
|
|
2695
|
-
vars = varStack.pop();
|
|
2696
|
-
varIndex = varIndexStack.pop();
|
|
2697
|
-
}
|
|
2698
|
-
if (ph !== PLACEHOLDER) {
|
|
2699
|
-
continue;
|
|
2700
|
-
}
|
|
2701
|
-
let po = new UpdatePoint(varIndex, currentNode);
|
|
2702
|
-
updatePoints.push(po);
|
|
2703
|
-
po.isComponent = !!slotComponent;
|
|
2704
|
-
po.isText = true;
|
|
2705
|
-
let val = vars[varIndex];
|
|
2706
|
-
let startComment;
|
|
2707
|
-
//插入start占位符
|
|
2708
|
-
startComment = document.createComment(`compelem-ui-${varIndex}-child-start`);
|
|
2709
|
-
comment.parentNode.insertBefore(startComment, comment);
|
|
2710
|
-
comment.nodeValue = `compelem-ui-${varIndex}-child-end`;
|
|
2711
|
-
po.textNode = startComment;
|
|
2712
|
-
if (val instanceof DirectiveWrapper) {
|
|
2713
|
-
po.isDirective = true;
|
|
2714
|
-
po.value = val;
|
|
2715
|
-
let pType = slotComponent ? EnterPointType.SLOT : EnterPointType.TEXT;
|
|
2716
|
-
// directives.push(val)
|
|
2717
|
-
let point = new EnterPoint(startComment, "", pType);
|
|
2718
|
-
point.endNode = comment;
|
|
2719
|
-
val.point = point;
|
|
2720
|
-
val.di.slotComponent = slotComponent;
|
|
2721
|
-
val.di.renderComponent = component;
|
|
2722
|
-
val.di.created(point, ...val.args);
|
|
2723
|
-
val = '';
|
|
2724
|
-
}
|
|
2725
|
-
else if (val instanceof Template) {
|
|
2726
|
-
po.isTmpl = true;
|
|
2727
|
-
po.value = val;
|
|
2728
|
-
let [html, vars] = buildHTML(component, val);
|
|
2729
|
-
val = buildTmplate(updatePoints, html, vars, component, viewContext);
|
|
2730
|
-
}
|
|
2731
|
-
else {
|
|
2732
|
-
po.value = val;
|
|
2733
|
-
}
|
|
2734
|
-
varIndex++;
|
|
2735
|
-
if (isUndefined(val))
|
|
2736
|
-
continue;
|
|
2737
|
-
if (val instanceof NodeList) {
|
|
2738
|
-
let fragment = document.createDocumentFragment();
|
|
2739
|
-
fragment.append(...val);
|
|
2740
|
-
comment.parentNode.insertBefore(fragment, comment);
|
|
2741
|
-
}
|
|
2742
|
-
else if (val instanceof Element) {
|
|
2743
|
-
comment.parentNode.insertBefore(val, comment);
|
|
2744
|
-
}
|
|
2745
|
-
else if (trim(val)) {
|
|
2746
|
-
let text = document.createTextNode(val);
|
|
2747
|
-
comment.parentNode.insertBefore(text, comment);
|
|
2748
|
-
}
|
|
2749
|
-
}
|
|
2750
|
-
}
|
|
2751
|
-
return container.childNodes;
|
|
2752
|
-
}
|
|
2753
|
-
const DomUtil = {
|
|
2754
|
-
insertBefore: function (node, newNodes) {
|
|
2755
|
-
if (!node.parentNode)
|
|
2756
|
-
return;
|
|
2757
|
-
let fragment = document.createDocumentFragment();
|
|
2758
|
-
fragment.append(...newNodes);
|
|
2759
|
-
node.parentNode.insertBefore(fragment, node);
|
|
2760
|
-
},
|
|
2761
|
-
remove: function (startNode, endNode) {
|
|
2762
|
-
if (startNode === endNode) {
|
|
2763
|
-
startNode?.parentNode?.removeChild(startNode);
|
|
2764
|
-
return;
|
|
2765
|
-
}
|
|
2766
|
-
let nextNode = startNode.nextSibling;
|
|
2767
|
-
while (nextNode && nextNode !== endNode) {
|
|
2768
|
-
nextNode?.parentNode?.removeChild(nextNode);
|
|
2769
|
-
nextNode = startNode.nextSibling;
|
|
2770
|
-
}
|
|
2771
|
-
}
|
|
2772
|
-
};
|
|
2773
|
-
//////////////////////////////////////////////////// interfaces
|
|
2774
|
-
/**
|
|
2775
|
-
* 标签函数,用于构建模板
|
|
2776
|
-
* @param strings
|
|
2777
|
-
* @param vars
|
|
2778
|
-
*/
|
|
2779
|
-
function html(strings, ...vars) {
|
|
2780
|
-
return new Template(isString(strings) ? [strings] : strings, vars);
|
|
2781
|
-
}
|
|
2782
|
-
const EXP_STR = /([a-z0-9"'])\s*>\s*</img;
|
|
2783
|
-
/**
|
|
2784
|
-
* 使用初始值创建一个引用对象
|
|
2785
|
-
* @param initValue
|
|
2786
|
-
* @returns
|
|
2787
|
-
*/
|
|
2788
|
-
function createRef(initValue) {
|
|
2789
|
-
return { current: initValue };
|
|
2790
|
-
}
|
|
2791
|
-
|
|
2792
|
-
/**
|
|
2793
|
-
* 视图模板
|
|
2794
|
-
* @author holyhigh2
|
|
2795
|
-
*/
|
|
2796
|
-
class Template {
|
|
2797
|
-
strings;
|
|
2798
|
-
vars;
|
|
2799
|
-
constructor(strings, vars) {
|
|
2800
|
-
this.strings = concat(strings);
|
|
2801
|
-
this.vars = vars;
|
|
2802
|
-
}
|
|
2803
|
-
//解析模板中的key
|
|
2804
|
-
getKey() {
|
|
2805
|
-
let vars = this.vars;
|
|
2806
|
-
let k = '';
|
|
2807
|
-
each(this.strings, (str, i) => {
|
|
2808
|
-
if (EXP_KEY.test(str)) {
|
|
2809
|
-
k = toString(vars[i]);
|
|
2810
|
-
return false;
|
|
2811
|
-
}
|
|
2812
|
-
});
|
|
2813
|
-
return k;
|
|
2814
|
-
}
|
|
2815
|
-
getKeys() {
|
|
2816
|
-
let vars = this.vars;
|
|
2817
|
-
let ks = [];
|
|
2818
|
-
for (let i = 0; i < this.strings.length; i++) {
|
|
2819
|
-
const str = this.strings[i];
|
|
2820
|
-
if (EXP_KEY.test(str)) {
|
|
2821
|
-
let k = toString(vars[i]);
|
|
2822
|
-
ks.push(k);
|
|
2823
|
-
}
|
|
2824
|
-
}
|
|
2825
|
-
if (isEmpty(ks)) {
|
|
2826
|
-
vars.forEach(v => {
|
|
2827
|
-
if (v instanceof Template) {
|
|
2828
|
-
let k = v.getKey();
|
|
2829
|
-
ks.push(k);
|
|
2830
|
-
}
|
|
2831
|
-
});
|
|
2832
|
-
}
|
|
2833
|
-
return ks;
|
|
2834
|
-
}
|
|
2835
|
-
/**
|
|
2836
|
-
* 追加tmpl
|
|
2837
|
-
* 交接处模板进行合并
|
|
2838
|
-
* @param tmpl
|
|
2839
|
-
*/
|
|
2840
|
-
append(tmpl) {
|
|
2841
|
-
let lastStr = last(this.strings);
|
|
2842
|
-
tmpl.strings.forEach((str, i) => {
|
|
2843
|
-
if (i == 0) {
|
|
2844
|
-
this.strings[this.strings.length - 1] = lastStr + str;
|
|
2845
|
-
return;
|
|
2846
|
-
}
|
|
2847
|
-
this.strings.push(str);
|
|
2848
|
-
});
|
|
2849
|
-
this.vars = concat(this.vars, tmpl.vars);
|
|
2850
|
-
return this;
|
|
2851
|
-
}
|
|
2852
|
-
/**
|
|
2853
|
-
* 指定位置插入模板
|
|
2854
|
-
* @param position 字符模板位置
|
|
2855
|
-
* @param tmpl
|
|
2856
|
-
* @returns
|
|
2857
|
-
*/
|
|
2858
|
-
insert(position, tmpl) {
|
|
2859
|
-
let firstStr = tmpl.strings.shift();
|
|
2860
|
-
this.strings[position] += firstStr;
|
|
2861
|
-
this.strings.splice(position + 1, 0, ...tmpl.strings);
|
|
2862
|
-
this.vars.splice(position, 0, ...tmpl.vars);
|
|
2863
|
-
return this;
|
|
2864
|
-
}
|
|
2865
|
-
getHTML(comp) {
|
|
2866
|
-
let [html, vars] = buildHTML(comp, this);
|
|
2867
|
-
let nodes = buildTmplate([], html, vars, comp, comp);
|
|
2868
|
-
return reduce(nodes, (a, v) => a + v.outerHTML, '');
|
|
2869
|
-
}
|
|
2870
|
-
}
|
|
2871
|
-
|
|
2872
|
-
function computed(target, propertyKey, descriptor) {
|
|
2873
|
-
if (!descriptor.get) {
|
|
2874
|
-
showError(`Computed '${propertyKey}' must be a getter`);
|
|
2875
|
-
}
|
|
2876
|
-
if (!has(target.constructor, DecoratorKey.COMPUTED)) {
|
|
2877
|
-
target.constructor[DecoratorKey.COMPUTED] = isEmpty(target.constructor[DecoratorKey.COMPUTED]) ? {} : cloneDeep(target.constructor[DecoratorKey.COMPUTED]);
|
|
2878
|
-
}
|
|
2879
|
-
target.constructor[DecoratorKey.COMPUTED][propertyKey] = descriptor.get;
|
|
2880
|
-
}
|
|
2881
|
-
|
|
2882
|
-
/**
|
|
2883
|
-
* 绑定非视图事件,如window/document等
|
|
2884
|
-
* @param eventName 事件名
|
|
2885
|
-
* @param immediate 立即执行
|
|
2886
|
-
* @param deep 深度监控
|
|
2887
|
-
*/
|
|
2888
|
-
function event(eventName, options) {
|
|
2889
|
-
return (target, name, descriptor) => {
|
|
2890
|
-
if (!has(target.constructor, DecoratorKey.EVENTS)) {
|
|
2891
|
-
target.constructor[DecoratorKey.EVENTS] = isEmpty(target.constructor[DecoratorKey.EVENTS]) ? [] : cloneDeep(target.constructor[DecoratorKey.EVENTS]);
|
|
2892
|
-
}
|
|
2893
|
-
target.constructor[DecoratorKey.EVENTS].push({ name: eventName, options, fn: target[name] });
|
|
2894
|
-
};
|
|
2895
|
-
}
|
|
2896
|
-
|
|
2897
|
-
/**
|
|
2898
|
-
* 缓存策略
|
|
2899
|
-
*/
|
|
2900
|
-
var QueryCache;
|
|
2901
|
-
(function (QueryCache) {
|
|
2902
|
-
QueryCache["ONCE"] = "once";
|
|
2903
|
-
QueryCache["UPDATABLE"] = "updatable"; //每次update结束都会更新缓存
|
|
2904
|
-
})(QueryCache || (QueryCache = {}));
|
|
2905
|
-
/**
|
|
2906
|
-
* css查询装饰器
|
|
2907
|
-
* @example
|
|
2908
|
-
* @query('l-popup', QueryCache.ONCE)
|
|
2909
|
-
*/
|
|
2910
|
-
class QueryDecorator extends Decorator {
|
|
2911
|
-
static get priority() {
|
|
2912
|
-
return Number.MAX_VALUE;
|
|
2913
|
-
}
|
|
2914
|
-
created(component, classProto, fieldName, ...args) {
|
|
2915
|
-
}
|
|
2916
|
-
mounted(component, setReactive, ...args) {
|
|
2917
|
-
}
|
|
2918
|
-
get targets() {
|
|
2919
|
-
return [DecoratorType.FIELD];
|
|
2920
|
-
}
|
|
2921
|
-
selector;
|
|
2922
|
-
cache;
|
|
2923
|
-
result;
|
|
2924
|
-
constructor(selector, cache) {
|
|
2925
|
-
super();
|
|
2926
|
-
this.selector = selector;
|
|
2927
|
-
this.cache = cache;
|
|
2928
|
-
}
|
|
2929
|
-
static getKey(selector) {
|
|
2930
|
-
return selector;
|
|
2931
|
-
}
|
|
2932
|
-
getter(component) {
|
|
2933
|
-
this.result = component.shadowRoot?.querySelector(this.selector);
|
|
2934
|
-
}
|
|
2935
|
-
beforeMount(component, setReactive, classProto, fieldName, ...args) {
|
|
2936
|
-
const that = this;
|
|
2937
|
-
Reflect.defineProperty(component, fieldName, {
|
|
2938
|
-
get() {
|
|
2939
|
-
if (that.result && that.cache) {
|
|
2940
|
-
return that.result;
|
|
2941
|
-
}
|
|
2942
|
-
that.getter(component);
|
|
2943
|
-
return that.result;
|
|
2944
|
-
}
|
|
2945
|
-
});
|
|
2946
|
-
}
|
|
2947
|
-
updated(component, changed) {
|
|
2948
|
-
if (this.cache !== QueryCache.UPDATABLE)
|
|
2949
|
-
return;
|
|
2950
|
-
this.getter(component);
|
|
2951
|
-
}
|
|
2952
|
-
}
|
|
2953
|
-
class QueryAllDecorator extends QueryDecorator {
|
|
2954
|
-
getter(component) {
|
|
2955
|
-
this.result = component.shadowRoot?.querySelectorAll(this.selector);
|
|
2956
|
-
}
|
|
2957
|
-
}
|
|
2958
|
-
const query = decorator(QueryDecorator);
|
|
2959
|
-
const queryAll = decorator(QueryAllDecorator);
|
|
2960
|
-
|
|
2961
|
-
function state(options) {
|
|
2962
|
-
if (arguments.length === 1) {
|
|
2963
|
-
return (target, stateKey) => {
|
|
2964
|
-
defineState(target, stateKey, options);
|
|
2965
|
-
};
|
|
2966
|
-
}
|
|
2967
|
-
let target = arguments[0], stateKey = arguments[1];
|
|
2968
|
-
defineState(target, stateKey, { prop: "" });
|
|
2969
|
-
}
|
|
2970
|
-
function defineState(target, stateKey, options) {
|
|
2971
|
-
if (!has(target.constructor, DecoratorKey.STATES)) {
|
|
2972
|
-
const mixinStates = {};
|
|
2973
|
-
let parentCtor = target.constructor;
|
|
2974
|
-
while ((parentCtor = _getSuper(parentCtor)) !== CompElem) {
|
|
2975
|
-
merge(mixinStates, parentCtor[DecoratorKey.STATES] ? cloneDeep(parentCtor[DecoratorKey.STATES]) : {});
|
|
2976
|
-
}
|
|
2977
|
-
Reflect.defineProperty(target.constructor, DecoratorKey.STATES, {
|
|
2978
|
-
configurable: false,
|
|
2979
|
-
enumerable: false,
|
|
2980
|
-
value: mixinStates
|
|
2981
|
-
});
|
|
2982
|
-
}
|
|
2983
|
-
target.constructor[DecoratorKey.STATES][stateKey] = options;
|
|
2984
|
-
}
|
|
2985
|
-
/**
|
|
2986
|
-
* 同@state装饰器,但可用于构造器中调用
|
|
2987
|
-
* @param ctor 类构造函数
|
|
2988
|
-
* @param stateKey state 名称
|
|
2989
|
-
* @param options
|
|
2990
|
-
*/
|
|
2991
|
-
function makeState(ctor, stateKey, options) {
|
|
2992
|
-
defineState(ctor.prototype, stateKey, options || { prop: "" });
|
|
2993
|
-
}
|
|
2994
|
-
|
|
2995
|
-
/**
|
|
2996
|
-
* class用注解,用于自动注册自定义组件
|
|
2997
|
-
* @param name 自定义组件名称
|
|
2998
|
-
*/
|
|
2999
|
-
function tag(name) {
|
|
3000
|
-
return (target) => {
|
|
3001
|
-
if (target) {
|
|
3002
|
-
//attrChange
|
|
3003
|
-
if (target.prototype.hasOwnProperty('attributeChangedCallback')) {
|
|
3004
|
-
let cbk = target.prototype.attributeChangedCallback;
|
|
3005
|
-
target.prototype.attributeChangedCallback = function (name, oldValue, newValue) {
|
|
3006
|
-
CompElem.prototype.attributeChangedCallback.call(this, name, oldValue, newValue);
|
|
3007
|
-
cbk.call(this, name, oldValue, newValue);
|
|
3008
|
-
};
|
|
3009
|
-
}
|
|
3010
|
-
//connectedCallback
|
|
3011
|
-
if (target.prototype.hasOwnProperty('connectedCallback')) {
|
|
3012
|
-
let cbk = target.prototype.connectedCallback;
|
|
3013
|
-
target.prototype.connectedCallback = function () {
|
|
3014
|
-
CompElem.prototype.connectedCallback.call(this);
|
|
3015
|
-
cbk.call(this);
|
|
3016
|
-
};
|
|
3017
|
-
}
|
|
3018
|
-
//disconnectedCallback
|
|
3019
|
-
if (target.prototype.hasOwnProperty('disconnectedCallback')) {
|
|
3020
|
-
let cbk = target.prototype.connectedCallback;
|
|
3021
|
-
target.prototype.disconnectedCallback = function () {
|
|
3022
|
-
CompElem.prototype.disconnectedCallback.call(this);
|
|
3023
|
-
cbk.call(this);
|
|
3024
|
-
};
|
|
3025
|
-
}
|
|
3026
|
-
customElements.define(name, target);
|
|
3027
|
-
}
|
|
3028
|
-
};
|
|
3029
|
-
}
|
|
3030
|
-
|
|
3031
|
-
function watch(source, options) {
|
|
3032
|
-
return (target, name) => {
|
|
3033
|
-
if (!has(target.constructor, DecoratorKey.WATCH)) {
|
|
3034
|
-
target.constructor[DecoratorKey.WATCH] = isEmpty(target.constructor[DecoratorKey.WATCH]) ? {} : cloneDeep(target.constructor[DecoratorKey.WATCH]);
|
|
3035
|
-
}
|
|
3036
|
-
const sources = isArray(source) ? source : [source];
|
|
3037
|
-
sources.forEach(src => {
|
|
3038
|
-
let watchKey = src.replaceAll('.', '-');
|
|
3039
|
-
let srcList = target.constructor[DecoratorKey.WATCH][watchKey];
|
|
3040
|
-
if (!isArray(srcList)) {
|
|
3041
|
-
srcList = target.constructor[DecoratorKey.WATCH][watchKey] = [];
|
|
3042
|
-
}
|
|
3043
|
-
srcList.push({ source: src, options, handler: target[name] });
|
|
3044
|
-
});
|
|
3045
|
-
};
|
|
3046
|
-
}
|
|
3047
|
-
|
|
3048
|
-
/**
|
|
3049
|
-
* 用于解析HTML模板
|
|
3050
|
-
* @author holyhigh2
|
|
3051
|
-
*/
|
|
3052
|
-
class Directive extends View(Object) {
|
|
3053
|
-
//render参数,仅保存上次指令所在context变更时的数据,用于指令内部context更新时
|
|
3054
|
-
_renderArgs;
|
|
3055
|
-
/**
|
|
3056
|
-
* 指令使用范围,超出范围会报错
|
|
3057
|
-
*/
|
|
3058
|
-
static get scopes() {
|
|
3059
|
-
return [];
|
|
3060
|
-
}
|
|
3061
|
-
/**
|
|
3062
|
-
* 指令渲染参数变量链
|
|
3063
|
-
*/
|
|
3064
|
-
renderParams;
|
|
3065
|
-
}
|
|
3066
|
-
|
|
3067
|
-
const Ignores = ['key'];
|
|
3068
|
-
/**
|
|
3069
|
-
* 绑定属性到节点上,如果节点是组件会使用in操作符判断是否props
|
|
3070
|
-
* @param styles 对象/数组/字符串
|
|
3071
|
-
*/
|
|
3072
|
-
class Bind extends Directive {
|
|
3073
|
-
created(point, obj) {
|
|
3074
|
-
let el = point.startNode;
|
|
3075
|
-
if (el instanceof CompElem) {
|
|
3076
|
-
//判断是否prop
|
|
3077
|
-
let props = {};
|
|
3078
|
-
let attrs = {};
|
|
3079
|
-
each(obj, (v, k) => {
|
|
3080
|
-
if (Ignores.includes(k))
|
|
3081
|
-
return;
|
|
3082
|
-
if (k in el) {
|
|
3083
|
-
props[k] = v;
|
|
3084
|
-
}
|
|
3085
|
-
else {
|
|
3086
|
-
attrs[k] = v + '';
|
|
3087
|
-
}
|
|
3088
|
-
});
|
|
3089
|
-
// el._setParentProps(props, attrs)
|
|
3090
|
-
el._initProps(props, attrs);
|
|
3091
|
-
}
|
|
3092
|
-
else {
|
|
3093
|
-
each(obj, (v, k) => {
|
|
3094
|
-
el.setAttribute(k, v);
|
|
3095
|
-
});
|
|
3096
|
-
}
|
|
3097
|
-
}
|
|
3098
|
-
update(point, newArgs, oldArgs) {
|
|
3099
|
-
return DirectiveUpdateTag.NONE;
|
|
3100
|
-
}
|
|
3101
|
-
static get scopes() {
|
|
3102
|
-
return [EnterPointType.TAG];
|
|
3103
|
-
}
|
|
3104
|
-
render(obj) {
|
|
3105
|
-
}
|
|
3106
|
-
}
|
|
3107
|
-
const bind = directive(Bind);
|
|
3108
|
-
|
|
3109
|
-
/**
|
|
3110
|
-
* 根据变量内容自动插入class,仅能用于class属性
|
|
3111
|
-
* @param styles 对象/数组/字符串
|
|
3112
|
-
*/
|
|
3113
|
-
class Classes extends Directive {
|
|
3114
|
-
created(point, clazz) {
|
|
3115
|
-
let rs = [];
|
|
3116
|
-
if (isArray(clazz)) {
|
|
3117
|
-
rs = compact(clazz);
|
|
3118
|
-
}
|
|
3119
|
-
else if (isObject(clazz)) {
|
|
3120
|
-
rs = flatMap(clazz, (v, k) => v ? k : []);
|
|
3121
|
-
}
|
|
3122
|
-
else if (isString(clazz)) {
|
|
3123
|
-
rs = clazz.split(' ');
|
|
3124
|
-
}
|
|
3125
|
-
let el = point.startNode;
|
|
3126
|
-
each(this.lastCls, cls => {
|
|
3127
|
-
el.classList.remove(cls);
|
|
3128
|
-
});
|
|
3129
|
-
each(rs, cls => {
|
|
3130
|
-
el.classList.add(cls);
|
|
3131
|
-
});
|
|
3132
|
-
this.lastCls = concat(rs);
|
|
3133
|
-
}
|
|
3134
|
-
update(point, newArgs, oldArgs) {
|
|
3135
|
-
this.created(point, newArgs[0]);
|
|
3136
|
-
return DirectiveUpdateTag.NONE;
|
|
3137
|
-
}
|
|
3138
|
-
static get scopes() {
|
|
3139
|
-
return [EnterPointType.CLASS];
|
|
3140
|
-
}
|
|
3141
|
-
lastCls;
|
|
3142
|
-
render(clazz) {
|
|
3143
|
-
}
|
|
3144
|
-
}
|
|
3145
|
-
const classes = directive(Classes);
|
|
3146
|
-
|
|
3147
|
-
/**
|
|
3148
|
-
* 循环列表并自动优化列表更新
|
|
3149
|
-
* foreach循环的只能是节点,且必须有key属性。非节点元素会被过滤掉
|
|
3150
|
-
* 使用序号作为key时可能会导致异常问题
|
|
3151
|
-
*/
|
|
3152
|
-
class ForEach extends Directive {
|
|
3153
|
-
created(point, ...args) {
|
|
3154
|
-
}
|
|
3155
|
-
update(point, newArgs, oldArgs) {
|
|
3156
|
-
if (isEmpty(point.getNodes()) && (!newArgs || isEmpty(newArgs[0])))
|
|
3157
|
-
return DirectiveUpdateTag.NONE;
|
|
3158
|
-
if (isMatch(this.lastAry, newArgs[0]) && this.lastAry.length === newArgs[0].length)
|
|
3159
|
-
return DirectiveUpdateTag.NONE;
|
|
3160
|
-
if (!isEmpty(this.renderParams)) {
|
|
3161
|
-
let rp = last(this.renderParams);
|
|
3162
|
-
if (!isArray(rp)) {
|
|
3163
|
-
rp = [rp];
|
|
3164
|
-
}
|
|
3165
|
-
this.renderParams = rp;
|
|
3166
|
-
}
|
|
3167
|
-
this.lastAry = clone(newArgs[0]);
|
|
3168
|
-
return DirectiveUpdateTag.UPDATE;
|
|
3169
|
-
}
|
|
3170
|
-
constructor(point) {
|
|
3171
|
-
super();
|
|
3172
|
-
if (!isEmpty(this.renderParams))
|
|
3173
|
-
this.renderParams = toArray(last(this.renderParams));
|
|
3174
|
-
}
|
|
3175
|
-
static get scopes() {
|
|
3176
|
-
return [EnterPointType.TEXT, EnterPointType.SLOT];
|
|
3177
|
-
}
|
|
3178
|
-
lastAry;
|
|
3179
|
-
lastRenderTmpl;
|
|
3180
|
-
render(value, cbk) {
|
|
3181
|
-
//1. 产生模板
|
|
3182
|
-
let tmpls = map(value, (v, k) => {
|
|
3183
|
-
return cbk(v, k);
|
|
3184
|
-
});
|
|
3185
|
-
if (tmpls.length < 1) {
|
|
3186
|
-
this.lastRenderTmpl = new Template([], []);
|
|
3187
|
-
return this.lastRenderTmpl;
|
|
3188
|
-
}
|
|
3189
|
-
//2. 检查 & 合并模板
|
|
3190
|
-
let keyAry = [];
|
|
3191
|
-
let strs = [];
|
|
3192
|
-
const combStrings = [];
|
|
3193
|
-
const combVars = [];
|
|
3194
|
-
for (let l = 0; l < tmpls.length; l++) {
|
|
3195
|
-
const tmpl = tmpls[l];
|
|
3196
|
-
let lastStr = last(strs);
|
|
3197
|
-
let vars = tmpl.vars;
|
|
3198
|
-
let hasNoKey = true;
|
|
3199
|
-
let tmplStrs = tmpl.strings;
|
|
3200
|
-
for (let i = 0; i < tmplStrs.length; i++) {
|
|
3201
|
-
const str = tmplStrs[i];
|
|
3202
|
-
if (EXP_KEY.test(str)) {
|
|
3203
|
-
let key = vars[i] + '';
|
|
3204
|
-
if (keyAry.includes(key)) {
|
|
3205
|
-
showError(`forEach - duplicate key '${key}'`);
|
|
3206
|
-
return;
|
|
3207
|
-
}
|
|
3208
|
-
keyAry.push(key);
|
|
3209
|
-
hasNoKey = false;
|
|
3210
|
-
}
|
|
3211
|
-
if (i == 0 && lastStr) {
|
|
3212
|
-
strs[strs.length - 1] = lastStr + str;
|
|
3213
|
-
continue;
|
|
3214
|
-
}
|
|
3215
|
-
strs.push(str);
|
|
3216
|
-
}
|
|
3217
|
-
if (hasNoKey) {
|
|
3218
|
-
showError("forEach - missing 'key' prop");
|
|
3219
|
-
return;
|
|
3220
|
-
}
|
|
3221
|
-
let lastVar = last(combStrings);
|
|
3222
|
-
if (lastVar && tmplStrs.length > 0) {
|
|
3223
|
-
combStrings[combStrings.length - 1] = trim(lastVar) + tmplStrs.shift();
|
|
3224
|
-
}
|
|
3225
|
-
combStrings.push('');
|
|
3226
|
-
combVars.push(tmpl);
|
|
3227
|
-
}
|
|
3228
|
-
this.lastAry = clone(value);
|
|
3229
|
-
combStrings.push('');
|
|
3230
|
-
this.lastRenderTmpl = new Template(combStrings, combVars);
|
|
3231
|
-
return this.lastRenderTmpl;
|
|
3232
|
-
}
|
|
3233
|
-
}
|
|
3234
|
-
const forEach = directive(ForEach);
|
|
3235
|
-
|
|
3236
|
-
/**
|
|
3237
|
-
* 条件为真时返回参数1,否则返回参数2,仅能用于文本节点
|
|
3238
|
-
* @param condition 条件
|
|
3239
|
-
* @param tmpl 模板
|
|
3240
|
-
*/
|
|
3241
|
-
class IfElse extends Directive {
|
|
3242
|
-
created(point, ...args) {
|
|
3243
|
-
}
|
|
3244
|
-
//todo 缓存后会导致缓存内容无法更新,需要按照新的结构修改后进行缓存
|
|
3245
|
-
ifNodes;
|
|
3246
|
-
elseNodes;
|
|
3247
|
-
static get scopes() {
|
|
3248
|
-
return [EnterPointType.TEXT, EnterPointType.SLOT];
|
|
3249
|
-
}
|
|
3250
|
-
update(point, newArgs, oldArgs) {
|
|
3251
|
-
if (!!newArgs[0] === !!oldArgs[0]) {
|
|
3252
|
-
return DirectiveUpdateTag.NONE;
|
|
3253
|
-
}
|
|
3254
|
-
if (newArgs[0]) {
|
|
3255
|
-
//缓存else
|
|
3256
|
-
// if (isEmpty(this.elseNodes)) {
|
|
3257
|
-
// this.elseNodes = concat(nodes)
|
|
3258
|
-
// }
|
|
3259
|
-
return DirectiveUpdateTag.REPLACE;
|
|
3260
|
-
}
|
|
3261
|
-
else {
|
|
3262
|
-
//缓存if
|
|
3263
|
-
// if (isEmpty(this.ifNodes)) {
|
|
3264
|
-
// this.ifNodes = concat(nodes)
|
|
3265
|
-
// }
|
|
3266
|
-
return DirectiveUpdateTag.REPLACE;
|
|
3267
|
-
}
|
|
3268
|
-
}
|
|
3269
|
-
render(condition, tmplFn1, tmplFn2) {
|
|
3270
|
-
return condition ? tmplFn1(condition) : tmplFn2(condition);
|
|
3271
|
-
}
|
|
3272
|
-
}
|
|
3273
|
-
const ifElse = directive(IfElse);
|
|
3274
|
-
|
|
3275
|
-
/**
|
|
3276
|
-
* 条件为真时返回内容,仅能用于文本节点
|
|
3277
|
-
* @param condition 条件
|
|
3278
|
-
* @param tmpl 模板
|
|
3279
|
-
*/
|
|
3280
|
-
class IfTrue extends Directive {
|
|
3281
|
-
created(point, ...args) {
|
|
3282
|
-
}
|
|
3283
|
-
static get scopes() {
|
|
3284
|
-
return [EnterPointType.TEXT, EnterPointType.SLOT];
|
|
3285
|
-
}
|
|
3286
|
-
update(point, newArgs, oldArgs) {
|
|
3287
|
-
if (newArgs[0] === oldArgs[0])
|
|
3288
|
-
return DirectiveUpdateTag.NONE;
|
|
3289
|
-
if (newArgs[0]) {
|
|
3290
|
-
return DirectiveUpdateTag.REPLACE;
|
|
3291
|
-
}
|
|
3292
|
-
// this.cacheNodes = nodes;
|
|
3293
|
-
return DirectiveUpdateTag.REMOVE;
|
|
3294
|
-
}
|
|
3295
|
-
render(condition, tmplFn) {
|
|
3296
|
-
return condition ? tmplFn() : html ``;
|
|
3297
|
-
}
|
|
3298
|
-
}
|
|
3299
|
-
const ifTrue = directive(IfTrue);
|
|
3300
|
-
|
|
3301
|
-
var ModelTriggerType;
|
|
3302
|
-
(function (ModelTriggerType) {
|
|
3303
|
-
ModelTriggerType["CHANGE"] = "change";
|
|
3304
|
-
ModelTriggerType["INPUT"] = "input";
|
|
3305
|
-
})(ModelTriggerType || (ModelTriggerType = {}));
|
|
3306
|
-
/**
|
|
3307
|
-
* 实现双向绑定(仅支持静态路径,动态增加的属性路径无法识别)
|
|
3308
|
-
* 当用于组件时,监控 @update:value 事件
|
|
3309
|
-
* 当用于元素时,
|
|
3310
|
-
* - 对于 input/textarea 监控 @input,并设置 value 属性
|
|
3311
|
-
* - 对于 checkbox/radio 监控 @change,并设置 checked 属性
|
|
3312
|
-
* - 对于 select 监控 @change,并设置 value 属性
|
|
3313
|
-
* @param modelValue 双向绑定的组件变量
|
|
3314
|
-
*/
|
|
3315
|
-
class Model extends Directive {
|
|
3316
|
-
created(point, modelValue, modelPath) {
|
|
3317
|
-
if (!this.modelPath)
|
|
3318
|
-
this.modelPath = last(this.renderParams);
|
|
3319
|
-
if (modelPath) {
|
|
3320
|
-
this.modelPath = toPath(modelPath);
|
|
3321
|
-
}
|
|
3322
|
-
const node = point.startNode;
|
|
3323
|
-
if (get(node, '_model') === 'binded')
|
|
3324
|
-
return;
|
|
3325
|
-
if (!isObject(modelValue) && !trim(modelValue))
|
|
3326
|
-
modelValue = '';
|
|
3327
|
-
if (node instanceof CompElem) {
|
|
3328
|
-
node._initProps({ value: modelValue });
|
|
3329
|
-
node.addEventListener('update:value', (e) => {
|
|
3330
|
-
console.debug('Model =>', this.modelPath);
|
|
3331
|
-
set(this.renderComponent, this.modelPath, e.detail.value);
|
|
3332
|
-
});
|
|
3333
|
-
set(node, '_model', 'binded');
|
|
3334
|
-
}
|
|
3335
|
-
else if (node instanceof HTMLTextAreaElement) {
|
|
3336
|
-
node.setAttribute('value', modelValue + '');
|
|
3337
|
-
node.addEventListener('input', (e) => {
|
|
3338
|
-
console.debug('Model =>', this.modelPath);
|
|
3339
|
-
let t = e.target;
|
|
3340
|
-
set(this.renderComponent, this.modelPath, t.value);
|
|
3341
|
-
});
|
|
3342
|
-
set(node, '_model', 'binded');
|
|
3343
|
-
}
|
|
3344
|
-
else if (node instanceof HTMLInputElement) {
|
|
3345
|
-
let propName = '';
|
|
3346
|
-
let evName = '';
|
|
3347
|
-
switch (node.type) {
|
|
3348
|
-
case 'checkbox':
|
|
3349
|
-
case 'radio':
|
|
3350
|
-
propName = 'checked';
|
|
3351
|
-
evName = 'change';
|
|
3352
|
-
break;
|
|
3353
|
-
case 'text':
|
|
3354
|
-
case 'email':
|
|
3355
|
-
case 'number':
|
|
3356
|
-
case 'password':
|
|
3357
|
-
case 'search':
|
|
3358
|
-
case 'tel':
|
|
3359
|
-
case 'url':
|
|
3360
|
-
propName = 'value';
|
|
3361
|
-
evName = 'input';
|
|
3362
|
-
break;
|
|
3363
|
-
default:
|
|
3364
|
-
propName = 'value';
|
|
3365
|
-
evName = 'input';
|
|
3366
|
-
break;
|
|
3367
|
-
}
|
|
3368
|
-
node.setAttribute(propName, modelValue + '');
|
|
3369
|
-
node.addEventListener(evName, (e) => {
|
|
3370
|
-
console.debug('Model =>', this.modelPath);
|
|
3371
|
-
let t = e.target;
|
|
3372
|
-
set(this.renderComponent, this.modelPath, t.value);
|
|
3373
|
-
});
|
|
3374
|
-
set(node, '_model', 'binded');
|
|
3375
|
-
}
|
|
3376
|
-
else if (node instanceof HTMLSelectElement) {
|
|
3377
|
-
node.setAttribute('value', modelValue + '');
|
|
3378
|
-
node.addEventListener('change', (e) => {
|
|
3379
|
-
console.debug('Model =>', this.modelPath);
|
|
3380
|
-
let t = e.target;
|
|
3381
|
-
set(this.renderComponent, this.modelPath, t.value);
|
|
3382
|
-
});
|
|
3383
|
-
set(node, '_model', 'binded');
|
|
3384
|
-
}
|
|
3385
|
-
}
|
|
3386
|
-
update(point, newArgs, oldArgs) {
|
|
3387
|
-
if (!this.modelPath)
|
|
3388
|
-
this.modelPath = last(this.renderParams);
|
|
3389
|
-
if (!isEqual(newArgs, oldArgs)) {
|
|
3390
|
-
const node = point.startNode;
|
|
3391
|
-
if (node instanceof CompElem) {
|
|
3392
|
-
node._updateProps({ value: newArgs[0] });
|
|
3393
|
-
}
|
|
3394
|
-
else if (node instanceof HTMLTextAreaElement || node instanceof HTMLSelectElement) {
|
|
3395
|
-
node.setAttribute('value', newArgs[0] + '');
|
|
3396
|
-
}
|
|
3397
|
-
else if (node instanceof HTMLInputElement) {
|
|
3398
|
-
switch (node.type) {
|
|
3399
|
-
case 'checkbox':
|
|
3400
|
-
case 'radio':
|
|
3401
|
-
if (!!newArgs[0]) {
|
|
3402
|
-
node.setAttribute('checked', '');
|
|
3403
|
-
}
|
|
3404
|
-
else {
|
|
3405
|
-
node.removeAttribute('checked');
|
|
3406
|
-
}
|
|
3407
|
-
break;
|
|
3408
|
-
case 'text':
|
|
3409
|
-
case 'email':
|
|
3410
|
-
case 'number':
|
|
3411
|
-
case 'password':
|
|
3412
|
-
case 'search':
|
|
3413
|
-
case 'tel':
|
|
3414
|
-
case 'url':
|
|
3415
|
-
node.setAttribute('value', newArgs[0] + '');
|
|
3416
|
-
break;
|
|
3417
|
-
default:
|
|
3418
|
-
node.setAttribute('value', newArgs[0] + '');
|
|
3419
|
-
break;
|
|
3420
|
-
}
|
|
3421
|
-
}
|
|
3422
|
-
}
|
|
3423
|
-
return DirectiveUpdateTag.NONE;
|
|
3424
|
-
}
|
|
3425
|
-
static get scopes() {
|
|
3426
|
-
return [EnterPointType.TAG];
|
|
3427
|
-
}
|
|
3428
|
-
modelPath;
|
|
3429
|
-
render(modelValue, modelPath) {
|
|
3430
|
-
}
|
|
3431
|
-
}
|
|
3432
|
-
const model = directive(Model);
|
|
3433
|
-
|
|
3434
|
-
/**
|
|
3435
|
-
* display的快捷指令
|
|
3436
|
-
* 如果
|
|
3437
|
-
* @param isvisible 是否显示
|
|
3438
|
-
*/
|
|
3439
|
-
class Show extends Directive {
|
|
3440
|
-
created(point, isVisible) {
|
|
3441
|
-
let el = point.startNode;
|
|
3442
|
-
if (isUndefined(this.display)) {
|
|
3443
|
-
this.display = el.style.display;
|
|
3444
|
-
}
|
|
3445
|
-
this.renderComponent.nextTick(() => {
|
|
3446
|
-
el.style.display = isVisible ? this.display : 'none';
|
|
3447
|
-
});
|
|
3448
|
-
}
|
|
3449
|
-
update(point, newArgs, oldArgs) {
|
|
3450
|
-
this.created(point, newArgs[0]);
|
|
3451
|
-
return DirectiveUpdateTag.NONE;
|
|
3452
|
-
}
|
|
3453
|
-
display = undefined;
|
|
3454
|
-
static get scopes() {
|
|
3455
|
-
return [EnterPointType.TAG];
|
|
3456
|
-
}
|
|
3457
|
-
constructor(point) {
|
|
3458
|
-
super();
|
|
3459
|
-
this.point = point;
|
|
3460
|
-
}
|
|
3461
|
-
render(isVisible) {
|
|
3462
|
-
}
|
|
3463
|
-
}
|
|
3464
|
-
const show = directive(Show);
|
|
3465
|
-
|
|
3466
|
-
/**
|
|
3467
|
-
* 创建一个动态插槽内容
|
|
3468
|
-
* @param cbk 回调函数,函数接收插槽上定义得变量
|
|
3469
|
-
* @param slotName 插槽名词,默认default
|
|
3470
|
-
*/
|
|
3471
|
-
class Slot extends Directive {
|
|
3472
|
-
created(point, cbk, slotName) {
|
|
3473
|
-
cbk = cbk.bind(this.renderComponent);
|
|
3474
|
-
this.slotComponent._bindSlotHook(slotName || 'default', cbk);
|
|
3475
|
-
}
|
|
3476
|
-
update(point, newArgs, oldArgs) {
|
|
3477
|
-
return DirectiveUpdateTag.NONE;
|
|
3478
|
-
}
|
|
3479
|
-
static get scopes() {
|
|
3480
|
-
return [EnterPointType.SLOT];
|
|
3481
|
-
}
|
|
3482
|
-
render(cbk, slotName) {
|
|
3483
|
-
}
|
|
3484
|
-
}
|
|
3485
|
-
const slot = directive(Slot);
|
|
3486
|
-
|
|
3487
|
-
/**
|
|
3488
|
-
* Css 辅助类
|
|
3489
|
-
*/
|
|
3490
|
-
class CssHelper {
|
|
3491
|
-
/**
|
|
3492
|
-
* 用于转换style对象为标准style字符串,会自动转换对象key为短横线格式
|
|
3493
|
-
* @param styles 样式对象
|
|
3494
|
-
* @returns
|
|
3495
|
-
*/
|
|
3496
|
-
static getCssText(styles) {
|
|
3497
|
-
if (isString(styles))
|
|
3498
|
-
return styles;
|
|
3499
|
-
return join(map(styles, (v, k) => kebabCase(k) + ":" + v), ';');
|
|
3500
|
-
}
|
|
3501
|
-
/**
|
|
3502
|
-
* 设置样式
|
|
3503
|
-
* @param styles 样式字符串或样式对象
|
|
3504
|
-
* @param node HTML元素
|
|
3505
|
-
* @returns 每个样式的旧值map
|
|
3506
|
-
*/
|
|
3507
|
-
static setStyle(styles, node) {
|
|
3508
|
-
if (isString(styles) && !trim(styles))
|
|
3509
|
-
return {};
|
|
3510
|
-
let css = CssHelper.getCssText(styles);
|
|
3511
|
-
let oldValueMap = {};
|
|
3512
|
-
each(css.split(';'), prop => {
|
|
3513
|
-
let kv = prop.split(':');
|
|
3514
|
-
let k = trim(kv[0]);
|
|
3515
|
-
let v = trim(kv[1]);
|
|
3516
|
-
oldValueMap[k] = node.style.getPropertyValue(k);
|
|
3517
|
-
node.style.setProperty(k, v);
|
|
3518
|
-
});
|
|
3519
|
-
return oldValueMap;
|
|
3520
|
-
}
|
|
3521
|
-
}
|
|
3522
|
-
|
|
3523
|
-
/**
|
|
3524
|
-
* 根据变量内容自动插入class,仅能用于style属性
|
|
3525
|
-
* @param styles 对象/字符串
|
|
3526
|
-
*/
|
|
3527
|
-
class Styles extends Directive {
|
|
3528
|
-
created(point, styles) {
|
|
3529
|
-
CssHelper.setStyle(styles, point.startNode);
|
|
3530
|
-
}
|
|
3531
|
-
update(point, newArgs, oldArgs) {
|
|
3532
|
-
this.created(point, newArgs[0]);
|
|
3533
|
-
return DirectiveUpdateTag.NONE;
|
|
3534
|
-
}
|
|
3535
|
-
constructor(point) {
|
|
3536
|
-
super();
|
|
3537
|
-
this.point = point;
|
|
3538
|
-
}
|
|
3539
|
-
static get scopes() {
|
|
3540
|
-
return [EnterPointType.STYLE];
|
|
3541
|
-
}
|
|
3542
|
-
render(styles) {
|
|
3543
|
-
}
|
|
3544
|
-
}
|
|
3545
|
-
const styles = directive(Styles);
|
|
3546
|
-
|
|
3547
|
-
/**
|
|
3548
|
-
* 类似Model,实现属性的同步跟踪
|
|
3549
|
-
* 设置组件prop,并监控 @update:prop 事件
|
|
3550
|
-
* @param syncValue 双向绑定的组件变量
|
|
3551
|
-
*/
|
|
3552
|
-
class Sync extends Directive {
|
|
3553
|
-
created(point, syncValue) {
|
|
3554
|
-
if (!this.modelPath)
|
|
3555
|
-
this.modelPath = last(this.renderParams);
|
|
3556
|
-
const targetComponent = point.startNode;
|
|
3557
|
-
let attrName = point.attrName;
|
|
3558
|
-
//todo _setParentProps接口不应该外部使用
|
|
3559
|
-
targetComponent._initProps({ [attrName]: syncValue });
|
|
3560
|
-
targetComponent.addEventListener('update:' + attrName, (e) => {
|
|
3561
|
-
set(this.renderComponent, this.modelPath, e.detail.value);
|
|
3562
|
-
});
|
|
3563
|
-
}
|
|
3564
|
-
update(point, newArgs, oldArgs) {
|
|
3565
|
-
if (!isEqual(newArgs, oldArgs)) {
|
|
3566
|
-
const targetComponent = point.startNode;
|
|
3567
|
-
let attrName = point.attrName;
|
|
3568
|
-
targetComponent._updateProps({ [attrName]: newArgs[0] });
|
|
3569
|
-
}
|
|
3570
|
-
return DirectiveUpdateTag.NONE;
|
|
3571
|
-
}
|
|
3572
|
-
static get scopes() {
|
|
3573
|
-
return [EnterPointType.PROP];
|
|
3574
|
-
}
|
|
3575
|
-
modelPath;
|
|
3576
|
-
constructor(point) {
|
|
3577
|
-
super();
|
|
3578
|
-
}
|
|
3579
|
-
render(syncValue) {
|
|
3580
|
-
}
|
|
3581
|
-
}
|
|
3582
|
-
const sync = directive(Sync);
|
|
3583
|
-
|
|
3584
|
-
/**
|
|
3585
|
-
* 分支指令,具有switch / if else 两种模式
|
|
3586
|
-
* @example
|
|
3587
|
-
* switch 模式
|
|
3588
|
-
* ${when(var, {
|
|
3589
|
-
closed: () => html``, //case 1
|
|
3590
|
-
connecting: () => html``, //case 2
|
|
3591
|
-
default: () => html``// default
|
|
3592
|
-
})}
|
|
3593
|
-
|
|
3594
|
-
if else 模式
|
|
3595
|
-
* ${when(this.editingTitle, [
|
|
3596
|
-
[(v: any) => v.substring(2) > 0, () => html`<div style="${PageHome.tunnelLight}"></div>`],
|
|
3597
|
-
[(v: any) => v == 'closed', () => html`<div style="${PageHome.tunnelLight}"></div>`],
|
|
3598
|
-
[() => true, () => html`默认`]
|
|
3599
|
-
])}
|
|
3600
|
-
*
|
|
3601
|
-
* @param condition 条件
|
|
3602
|
-
* @param tmpl 模板
|
|
3603
|
-
*/
|
|
3604
|
-
class When extends Directive {
|
|
3605
|
-
created(point, ...args) {
|
|
3606
|
-
}
|
|
3607
|
-
static get scopes() {
|
|
3608
|
-
return [EnterPointType.TEXT, EnterPointType.SLOT];
|
|
3609
|
-
}
|
|
3610
|
-
update(point, newArgs, oldArgs) {
|
|
3611
|
-
if (isEqual(newArgs, oldArgs)) {
|
|
3612
|
-
return DirectiveUpdateTag.NONE;
|
|
3613
|
-
}
|
|
3614
|
-
//todo 缓存
|
|
3615
|
-
return DirectiveUpdateTag.REPLACE;
|
|
3616
|
-
}
|
|
3617
|
-
render(value, cases) {
|
|
3618
|
-
let defaultFn = () => html ``;
|
|
3619
|
-
let conditionList = [];
|
|
3620
|
-
let tmplList = [];
|
|
3621
|
-
each(cases, (v, k) => {
|
|
3622
|
-
if (isFunction(v)) {
|
|
3623
|
-
conditionList.push(k);
|
|
3624
|
-
tmplList.push(v);
|
|
3625
|
-
}
|
|
3626
|
-
else {
|
|
3627
|
-
let condiFn = v[0];
|
|
3628
|
-
let tmplFn = v[1];
|
|
3629
|
-
conditionList.push(condiFn);
|
|
3630
|
-
tmplList.push(tmplFn);
|
|
3631
|
-
}
|
|
3632
|
-
if (k === 'default') {
|
|
3633
|
-
defaultFn = v;
|
|
3634
|
-
}
|
|
3635
|
-
});
|
|
3636
|
-
let i = findIndex(conditionList, c => {
|
|
3637
|
-
if (isFunction(c)) {
|
|
3638
|
-
return c(value);
|
|
3639
|
-
}
|
|
3640
|
-
else {
|
|
3641
|
-
return c == value;
|
|
3642
|
-
}
|
|
3643
|
-
});
|
|
3644
|
-
return call(tmplList[i] ?? defaultFn);
|
|
3645
|
-
}
|
|
3646
|
-
}
|
|
3647
|
-
const when = directive(When);
|
|
3648
|
-
|
|
3649
|
-
export { CompElem, CssHelper, Decorator, DecoratorType, DecoratorWrapper, Directive, DirectiveUpdateTag, DirectiveWrapper, EnterPoint, EnterPointType, GetKeyFnName, ModelTriggerType, QueryCache, Template, UpdatePoint, _DecoratorMap, _DecoratorsKey, _getObservedAttrs, bind, buildHTML, classes, computed, createRef, decorator, directive, event, forEach, html, ifElse, ifTrue, makeState, model, prop, query, queryAll, show, slot, state, styles, sync, tag, watch, when };
|
|
7
|
+
import{toPath as t,get as e,isObject as s,isDefined as r,isUndefined as n,isEmpty as i,has as o,concat as a,defaults as l,merge as c,cloneDeep as d,each as h,kebabCase as u,toArray as p,last as f,startsWith as g,isFunction as m,isArray as _,initial as E,isBlank as b,join as v,split as C,set as y,camelCase as S,isEqual as N,replace as T,isPlainObject as P,flatMap as x,isString as w,test as A,size as M,assign as O,first as k,debounce as R,closest as L,once as D,bind as V,isNil as H,trim as I,some as $,isNull as W,fval as j,omit as U,groupBy as B,reject as z,filter as F,slice as K,compact as Q,remove as X,includes as G,find as q,throttle as Y,map as Z,replaceAll as J,snakeCase as tt,toString as et,reduce as st,isMatch as rt,clone as nt,findIndex as it,call as ot}from"myfx";const at=new WeakMap,lt=/\s+\.?key\s*=/;var ct,dt,ht;function ut(t){console.error("[CompElem]",t)}function pt(t,e){console.error(`[CompElem <${t}>]`,e)}function ft(e){return t(e).join("-")}function gt(t){return Object.getPrototypeOf(t)}!function(t){t[t.CSS=1]="CSS",t[t.COMPUTED=2]="COMPUTED"}(ct||(ct={})),function(t){t.PROPS="__deco_props",t.STATES="__deco_states",t.COMPUTED="__deco_computed",t.WATCH="__deco_watch",t.EVENTS="__deco_events"}(dt||(dt={})),function(t){t.CLASS="class",t.FIELD="field",t.METHOD="method"}(ht||(ht={}));class mt{static get priority(){return 0}}const _t="getKey",Et="__decorators",bt=new WeakMap;class vt{args;metadata;decoratorClass;instanceMap;key;priority=0;constructor(t,s,r){this.args=t,this.metadata=s,this.decoratorClass=r,this.priority=e(r,"priority",0),this.instanceMap=new WeakMap}create(t){let o,a=new this.decoratorClass(...this.args),l=a.targets,c=this.metadata[2];s(c)&&r(e(c,"configurable"))?o=ht.METHOD:n(this.metadata[2])&&(o=ht.FIELD),!i(l)&&o&&l.includes(o)?(a.created(t,...this.metadata),this.instanceMap.set(t,a)):ut(`Decorator '${this.decoratorClass.name}' is out of targets, expect '${l.join(",")}' bug got '${o}'`)}beforeMount(t,e){this.instanceMap.get(t).beforeMount(t,e,...this.metadata)}mounted(t,e){this.instanceMap.get(t).mounted(t,e,...this.metadata)}updated(t,e){this.instanceMap.get(t).updated(t,e)}}const Ct=new WeakMap;function yt(t){let s=(...s)=>(...r)=>{let n=r[0].constructor,i=e(n,Et);if(!o(n,Et)){let t=e(Object.getPrototypeOf(n),Et);i=t?a(t):[],Reflect.defineProperty(n,Et,{configurable:!1,enumerable:!1,value:i})}let l,c={},d=e(t,_t);if(d){let e=Ct.get(t);if(e||(e=new WeakMap,Ct.set(t,e)),c=e.get(n),c||(c={},e.set(n,c)),l=d(...s),c[l])return c[l]}let h=new vt(s,r,t);return c[l]=h,i?.push(h),h};return bt.set(s,!0),s}const St=new WeakMap;function Nt(t){if(1===arguments.length)return(e,s,r)=>{t.required=t.required||!1,t.attribute=!1!==t.attribute,Tt(e,s,t,r)};let e=arguments[0],s=arguments[1],r=arguments[2];t={type:void 0,required:!1,attribute:!0},r&&"function"==typeof r.type&&(t=l(r,t),r=void 0),Tt(e,s,t,r)}function Tt(t,e,s,r){let n;if(/[a-z]/.test(e[0])||ut(`Prop '${e}' must be in CamelCase`),!o(t.constructor,dt.PROPS)){const e={};let s=t.constructor;for(;(s=gt(s))!==jt;)c(e,s[dt.PROPS]?d(s[dt.PROPS]):{});Reflect.defineProperty(t.constructor,dt.PROPS,{configurable:!1,enumerable:!1,value:e}),n=new Set,h(e,((t,e)=>{if(t.attribute){let t=u(e);n?.add(t)}})),St.set(t.constructor,n)}if(r&&(r.get&&(s.getter=r.get),r.set&&(s.setter=r.set)),s.attribute){n||(n=St.get(t.constructor));let s=u(e);n?.add(s)}o(t.constructor,"observedAttributes")||(t.constructor.observedAttributes=[]),t.constructor.observedAttributes=p(n),t.constructor[dt.PROPS][e]=s}const Pt=new Set;function xt(t){return St.get(t)??Pt}const wt={collectWatch(t,e,s){let r=Rt.get(t);r||(r={},Rt.set(t,r));let n=r[s];n||(n=r[s]=[]),n.push(e)},startCollect(t,e){this.__collectType=e,this.__collecting=t},setUpdater(t){this.__updater=t},endCollect(){this.__collecting=null},__directiveQ:[],setDirectiveQ(t){let e=f(this.__directiveQ);const s=t?t.join(","):"",r=e?e.join(","):"";e&&s===r||(e&&e.length<t.length&&g(s,r)?this.__directiveQ[this.__directiveQ.length-1]=t:this.__directiveQ.push(t))},popDirectiveQ(){let t=a(this.__directiveQ);return this.__directiveQ=[],t},startRender(t){this.__renderCollecting=!0,this.__renderContext=t},endRender(t){this.__renderCollection.forEach((e=>{t._regDeps(e,this.__renderContext)})),this.__renderCollection.clear(),this.__renderCollecting=!1,this.__renderContext=null},collect(t){this.__renderCollection.add(t)},clear(){this.__directiveQ=[]},__updater:null,__collecting:null,__collectType:-1,__renderCollection:new Set,__renderContext:null,__renderCollecting:!1,__skipCheck:!1},At=new WeakMap,Mt=new WeakMap,Ot=new WeakMap,kt=new WeakMap,Rt=new WeakMap;function Lt(t,r){if(!s(t))return t;const n=t.__proxy?t:new Proxy(t,{get(t,e,s){if(!e)return;const r=Reflect.get(t,e,s);if("string"!=typeof e&&"number"!=typeof e)return r;let n=e in t;if((wt.__renderCollecting||wt.__collecting)&&(n&&t.hasOwnProperty(e)||!n)){let t=Mt.get(s)??[],r=a(t,[e]),n=r.join("-");if(wt.__renderCollecting)wt.collect(ft(r)),wt.setDirectiveQ(r);else if(wt.__collecting){let t;switch(wt.__collectType){case ct.COMPUTED:t=Ot.get(wt.__collecting),t||(t={},Ot.set(wt.__collecting,t));break;case ct.CSS:t=kt.get(wt.__collecting),t||(t={},kt.set(wt.__collecting,t))}let e=t[n];e||(e=t[n]=[]),e.push(wt.__updater)}}return r},set(t,r,n,o){if(!r)return!1;let l=t[r];if(!s(l)&&l===n)return!0;if(Number.isNaN(n)&&Number.isNaN(l))return!0;let c=Mt.get(o)??[],d=a(c,[r]),h=At.get(o).from,u=e(h.constructor,dt.PROPS),p=e(h.constructor,dt.STATES),f=e(u,[d[0],"hasChanged"])||e(p,[d[0],"hasChanged"]);if(f){if(!f.call(h,n,l))return!0}else if(l===n&&!at.has(l))return!0;u&&u[r]&&t.__isData&&u[r].sync&&h.emit("update:"+r,{value:n});let g=At.get(o)?.contextSet,E=n;!s(n)||m(n)||n instanceof Node||Object.isFrozen(n)||g.forEach((t=>{let e=At.get(o)?.pathMap,s=e?.get(t);s&&(d=a(s,[r]),Mt.set(E,d),E=Lt(E,t),Mt.set(E,d))}));let b=Reflect.set(t,r,E),v=At.get(o).pathMap;return g.forEach((t=>{let s=v.get(t);if(!s)return;t===h&&c.length>1&&s.length>1&&c[0]===s[0]&&(s=c),d=a(s,"length"==r&&_(o)?[]:[r]);let n=Ot.get(t),u=kt.get(t),p=Rt.get(t);if(n||u||p){let t=d.length;for(;t;){let s=d.slice(0,t).join("-");if(p){const r=p[s];t===d.length?r?.forEach((t=>{let e=t();e.ov=l,Dt.pushWatch(e)})):r?.forEach((t=>{let s=t();e(s,"deep")&&(s.ov=l,Dt.pushWatch(s))}))}if(n){let t=n[s];if(!i(t))for(let e=0;e<t.length;e++){const s=t[e];Dt.pushComputed(s)}}if(u){let t=u[s];if(!i(t))for(let e=0;e<t.length;e++){const s=t[e];Dt.pushCss(s)}}t--}}let f=t._notify(l,d);Dt.pushNext(f)})),b}});t.__proxy||Reflect.defineProperty(t,"__proxy",{enumerable:!1,writable:!1,configurable:!1,value:!0});let o=Mt.get(t)??[];if(Object.isExtensible(t)&&!At.get(n)){let t=new Set;t.add(r);let e=new WeakMap;e.set(r,o),At.set(n,{from:r,contextSet:t,pathMap:e})}else{At.get(n).contextSet.add(r);let t=At.get(n).pathMap,s=t.get(r),i=a(o);if(s&&s.join("")!==i.join("")){let t=e(r,E(s));_(t)||function(...t){console.warn("[CompElem]",...t)}(`The object is referenced by more than one @state '${i.join(".")},${s.join(".")}'`),s=i}else t.set(r,i)}for(let e in t){const n=t[e];!s(n)||n.__proxy||m(n)||n instanceof Node||Object.isFrozen(n)||(Mt.set(n,a(o,[e])),t[e]=Lt(n,r),Mt.set(t[e],a(o,[e])))}return n}class Dt{static watchSet=new Set;static computedSet=new Set;static cssSet=new Set;static nextSet=new Set;static nextPending=!1;static next;static{const t=Promise.resolve(),e=Dt.flush;Dt.next=()=>{t.then(e)}}static flush(){Dt.nextPending=!1;let t=Array.from(Dt.watchSet);Dt.watchSet.clear();let s=Array.from(Dt.computedSet);Dt.computedSet.clear();let r=Array.from(Dt.cssSet);Dt.cssSet.clear();let n=Array.from(Dt.nextSet);Dt.nextSet.clear(),t.forEach((t=>t(e(t,"ov")))),s.forEach((t=>t())),r.forEach((t=>t())),n.forEach((t=>t()))}static pushWatch(t){Dt.watchSet.add(t)}static pushComputed(t){Dt.computedSet.add(t)}static pushCss(t){Dt.cssSet.add(t)}static pushNext(t){Dt.nextSet.add(t),Dt.nextPending||(Dt.nextPending=!0,Dt.next())}}function Vt(t){return class extends t{__updatePoints;renderComponent;buildView(t){let e=this instanceof jt?this:this.renderComponent,[s,r]=we(e,t),n=[],i=Ve(n,s,r,e,this);return this.__updatePoints=n,i}updateView(t){if(b(v(t.strings)))return;if(!this.__updatePoints)return;let{vars:r}=t,n=this instanceof jt?this:this.renderComponent;for(let t=0;t<this.__updatePoints.length;t++){const i=this.__updatePoints[t];let o=i.varIndex,a=i.value,l=r,c=i.node,d=C(o,"-");for(let s=0;s<d.length;s++){const r=d[s];l=e(l,r),l&&l.vars&&t<d.length-1&&(l=l.vars)}if(!s(a)&&a===l)continue;let h=c;if(i.isDirective){if(!a.di)continue;l.di=a.di,l.di.renderParams=l.varChain,l.di._renderArgs=l.args,l.point=a.point,l.varPath=a.varPath,a.update(a.point,l.args,a.args)}else if(i.isToggleProp){if(!!l===a)continue;h.toggleAttribute(i.attrName,!!l),y(h,i.attrName,!!l)}else if(i.isProp){if(!s(l)&&l===a)continue;let t=S(i.attrName),r=e(i.node.constructor,dt.PROPS);if(r){let e=r[t];if(e&&e.hasChanged&&!e.hasChanged.call(this,l,a))continue}c instanceof jt?c._updateProps({[i.attrName]:l}):c instanceof HTMLSlotElement&&n._updateSlot(c.getAttribute("name")||"default",i.attrName,l)}else if(i.attrName&&!i.isEvent){if(!N(a,l))switch(i.attrName){case"value":if(c instanceof HTMLInputElement){c.value=l;break}default:c.setAttribute(i.attrName,T(i.attrTmpl,De,l+""))}}else if(i.isTmpl)(l.strings.join()!==a.tmpl.strings.join()||l.vars.some((t=>s(t)&&!P(t)))||a.tmpl.vars.some((t=>s(t)&&!P(t)))||!N(l.vars,a.tmpl.vars))&&i.value.updateView(l),a.tmpl=l,l=a;else if(i.isText){let t=i.textNode.nextSibling;t&&t===i.node.previousSibling?t.textContent=l:(He.remove(i.textNode,i.node),He.insertBefore(i.node,[l]))}i.value=l}}}}class Ht extends(Vt(Object)){tmpl;constructor(t){super(),this._renderVars=e(t,"_renderVars"),this.tmpl=t}}const It={boolean:Boolean,string:String,number:Number,object:Object,array:Array,function:Function,bigint:BigInt,symbol:Symbol,undefined:Object},$t=new WeakMap;let Wt=[];class jt extends(Vt(HTMLElement)){static __l_globalRule=document.createElement("style");static{document.head.appendChild(jt.__l_globalRule)}static defaults(t){Wt=x(t.css,(t=>{if(w(t)){let e=new CSSStyleSheet;return e.replaceSync(t),e}return t instanceof CSSStyleSheet?t:[]})),t.global,h(t,((t,e)=>{A(e[0],/[A-Z]/)}))}#t={};#e={"#slots":{}};#s={};#r={};#n;#i;#o={};__events={};get[Symbol.toStringTag](){return this.constructor.name}get reactiveData(){return this.#s}get attrs(){return this.#a}get props(){return this.#l}get renderRoot(){return this.#c}get renderRoots(){return this.#d}get parentComponent(){return this.#h}get slotHooks(){return this.#u}get css(){return $t.get(this.constructor)}get isMounted(){return this.#p}get slots(){return this.#e["#slots"]}#a;#l;#c;#d;#h;#f={};#u={};#g={};#p=!1;static get autoSlot(){return!0}static get styles(){return[]}static get globalStyles(){return[]}get styles(){return[]}#m=!1;constructor(...t){super(),1===M(t)&&(this.#l={},O(this.#l,k(t)));let s=this.render.bind(this);this.render=function(){let t;return wt.startRender(this),t=s(),wt.endRender(this),t};let r=e(this.constructor,"globalStyles"),n=e(this.constructor,"_global_style_attached");if(!i(r)&&"1"!==n){let t="";r.forEach((e=>{w(e)&&(t+=e+"\n")})),jt.__l_globalRule.textContent+=t,y(this.constructor,"_global_style_attached","1")}let o=$t.get(this.constructor),a=o??[];o||(h(e(this.constructor,"styles"),(t=>{if(w(t)){let e=new CSSStyleSheet;e.replaceSync(t),a.push(e)}else a.push(t)})),$t.set(this.constructor,a)),this.#n=this.attachShadow({mode:"open",slotAssignment:e(this.constructor,"autoSlot",!0)?"named":"manual"}),this.#n.adoptedStyleSheets=[...Wt,...a];let l=this.attributes.getNamedItem("css-link")?.value;if(l){const t=document.createElement("style");t.textContent=`@import "${l}"`,this.#n.appendChild(t)}let c=R(this.#_,20);this.#i=new MutationObserver((t=>{for(let e=0;e<t.length;e++){"childList"===t[e].type&&c.call(this)}})),this._slotsPropMap={default:[]};let d=e(this.constructor,Et);d&&d.sort(((t,e)=>e.priority-t.priority)).forEach((t=>t.create(this))),this.#E=this.#b.bind(this)}#E;connectedCallback(){let t=L(this.parentNode,(t=>t instanceof jt||t.host instanceof jt),"parentNode");this.#h=t?t instanceof jt?t:t.host:null,this.__init()}disconnectedCallback(){this.#i.disconnect()}__init(){if(this.#m)return;this.#v();const t=this.#C();this.propsReady(t);for(const e in t){const s=t[e];this.#e[e]=s}this.#y(),h(this.#e,((t,e)=>{let s=Reflect.getOwnPropertyDescriptor(this.#e,e);Reflect.defineProperty(this,e,{get(){let t=Reflect.get(this.#s,e);return s?.get?s?.get():t},set(t){s?.set?s?.set(t):Reflect.set(this.#s,e,t)}})})),Reflect.defineProperty(this.#e,"__isData",{enumerable:!1,value:!0}),this.#s=Lt(this.#e,this);let s=this.render(),r=this.buildView(s);if(r){let t=p(r);t.forEach((t=>{this.#n.appendChild(t)})),this.#d=t,this.#c=t[0]}this.#_(),this.beforeMount(),this.#i.observe(this,{childList:!0});const n=this;let i=e(this.constructor,Et);i&&i.sort(((t,e)=>e.priority-t.priority)).forEach((t=>{t.beforeMount(this,((t,e)=>(n.#s[t]=e,n.#s[t])))}));let o=e(this.constructor,dt.WATCH);h(o,((t,s)=>{t.forEach((t=>{let{source:r,options:n,handler:i}=t,o=i.bind(this);e(n,"once",!1)&&(o=D(o));const a=function(t){let s=e(this,r.replaceAll("-","."));o(s,t,r)}.bind(this);let l=e(n,"deep",!1);if(a.deep=l,wt.collectWatch(this,(()=>a),s),!e(n,"immediate",!1))return;let c=e(this,r.replaceAll("-","."));o(c,c,r)}))}));let a=e(this.constructor,dt.COMPUTED);h(a,((t,e)=>{wt.startCollect(this,ct.COMPUTED),wt.setUpdater((()=>{this.#s[e]=t.call(this)})),this.#e[e]=t.call(this),wt.endCollect(),Reflect.defineProperty(this,e,{get(){return Reflect.get(this.#s,e)},set(t){pt(this.tagName,"Cannot set a computed property '"+e+"'")}})}));let l=e(this.constructor,dt.EVENTS);l&&l.forEach((t=>{let e=t.name,s=O({target:document,once:!1,passive:!1,capture:!1},t.options),r=V(t.fn,this),n=s.target;m(n)&&(n=n.call(this,this)),n?n.addEventListener(e,r,s):pt(this.tagName,"The target of @event('"+e+"',...) is invalid")})),h(this.#u,((t,e)=>{this.#S(e)})),wt.startCollect(this,ct.CSS);let c=[];this.styles.forEach((t=>{if(!m(t))return;let e=new CSSStyleSheet;c.push(e),wt.setUpdater((()=>{let s=t()??"";e.replaceSync(s)}));let s=t();b(s)||e.replaceSync(s)})),wt.endCollect(),this.#n.adoptedStyleSheets=[...this.#n.adoptedStyleSheets,...c],setTimeout((()=>{this.#p=!0,this.mounted(),i&&i.forEach((t=>{t.mounted(this,((t,e)=>(n.#s[t]=e,n.#s[t])))}))}),0),this.#m=!0}propsReady(t){}render(){throw Error(`[CompElem <${this.tagName}>] Missing render()`)}beforeMount(){}mounted(){}#N(t,s){this.#v();let r=e(this.#t[s],"props");r&&h(this.slots,((t,s)=>{t.filter((t=>t.nodeType===Node.ELEMENT_NODE)).forEach((t=>{t instanceof jt?t._updateProps(r):h(r,((s,r)=>{if(t instanceof HTMLSlotElement){let n=e(t,"__l_comp");if(n){let e=t.name||"default",i=n.#t[e];i||(i=n.#t[e]={props:{}}),i.props||(i.props={}),i.props[r]=s,n.#N(t,e)}}else t.setAttribute(r,s)}))}))})),this.slotChange(t,s)}slotChange(t,e){}attributeChangedCallback(t,e,s){this.#T(t,e,s)}shouldUpdate(t){return!0}updated(t){}emit(t,s={},r){r&&r.event&&(s.event=r.event),s.target=this,this.dispatchEvent(new CustomEvent(t,{bubbles:e(r,"bubbles",!1),composed:e(r,"composed",!1),cancelable:!0,detail:s}))}#P={};on(t,e){this.#P[t]||(this.#P[t]=[]);let s=e.bind(this);this.#P[t].push(s),this.addEventListener(t,s)}nextTick(t){Dt.pushNext(t)}forceUpdate(){h(this.#s,((t,e)=>{this.#r[e]={value:void 0,chain:void 0}})),this.#b()}_notify(t,r){let n=[];for(let i=0;i<r.length;i++){const o=r[i];n.push(o);let a=e(this,n),l=ft(n);this.#r[l]={value:a,chain:"slots"===l?["slots"]:n,oldValue:t,end:n.length===r.length},s(a)&&"#"!=l[0]&&at.set(a,l)}return this.#E}#b(){if(M(this.#r)<1)return;const t=this.#r;this.#r={};let r=e(this.constructor,Et);if(r&&r.sort(((t,e)=>e.priority-t.priority)).forEach((e=>{e.updated(this,t)})),!this.shouldUpdate(t))return;let n=new Set;h(t,(({value:t,chain:e,oldValue:s},r)=>{this.#o[r]&&this.#o[r].forEach((t=>{n.add(t)}))})),n.forEach((t=>{if(t===this)this.updateView(this.render());else{let e=t.render(...t._renderArgs?t._renderArgs:[]);e&&t.updateView(e)}})),this.#x.forEach((t=>{this.#S(t)})),this.updated(t),h(t,(({value:t,chain:e,oldValue:r},n)=>{s(t)&&at.has(t)&&at.delete(t)}))}#C(){let t=e(this.constructor,dt.PROPS),i=this.attributes,a=this.tagName,l=this.#l,c={};h(i,(({name:e,value:s})=>{if(e[0]===be||e[0]===ve||e[0]===Ce||e===Ne||"slot"===e)return;let r=S(e);t&&!t[r]&&(c[e]=s)})),this.#a=this.#a?O(this.#a,c):c;let d={};return h(t,((c,h)=>{let p,f=t[h],g=o(l,h),m=e(this,h);if(!("_defaultValue"in f)&&(f._defaultValue=m,!f.type)){n(m)&&pt(a,"Prop '"+h+"' has neither propType nor defaultValue be used for type inference");let t=typeof m;_(m)&&(t="array");let e=It[t];f.type=e}if(g)p=H(l[h])?m:l[h];else{p=m;let t=i.getNamedItem(u(h))||i.getNamedItem(ve+u(h));t&&(g=!0,p=t.value)}if(f.required&&!g)return pt(a,"Prop '"+h+"' is required"),!1;p=this.#w(t,h,p);let E=e(t,[h,"getter"]);E&&(E=V(E,this));let b=e(t,[h,"setter"]);b&&(b=V(b,this)),(E||b)&&Reflect.defineProperty(this.#e,h,{set:b||function(t){},get:E}),f.attribute&&r(p)&&!s(p)&&this.setAttribute(u(h),I(p)),this.#e[h]=p,d[h]=p})),Object.seal(d)}#w(t,e,s){let i=t[e];if(!i)return s;let o=i.isValid,a=i.type,l=_(a)?a:[a],c=i.converter,d=s;if(!$(l,(t=>t===String))&&w(d)&&!W(d))try{d=c?c(d):j(d,{html:Ie})}catch(t){pt(this.tagName,`Convert attribute '${e}' error with `+d)}for(let t=0;t<l.length;t++){"Boolean"===l[t].name&&(w(d)&&/(?:^true$)|(?:^false$)/.test(d)?d=j(d):(n(d)||b(d))&&(d=!0))}let h=typeof d,u=!r(d);for(let t=0;t<l.length;t++){const e=l[t];if(A(h,e.name,"i")||d instanceof e||Object.prototype.toString.call(d)===Object.prototype.toString.call(e.prototype)){u=!0;break}}return u||pt(this.tagName,`Invalid prop '${e}'. expected '${l.map((t=>t.name||t))}' but got '${h}'`),o&&(o.call(this,d,this.#e)||pt(this.tagName,`Invalid prop '${e}'. IsValid() check failed`)),d}#y(){let t=e(this.constructor,dt.STATES);h(t,((s,r)=>{let n=t[r],i=e(this,r);if(n){let t=n.prop;i=t?d(this.#e[t]):e(this,r)}this.#e[r]=i}))}#A=R(this.propsReady,100);_setParentProps(t,s){if(this.#m){let r=e(this.constructor,dt.PROPS);h(t,((t,e)=>{let s=S(e),n=r[s];if(!n)return;let i=this.#e[s];t=this.#w(r,s,t),n.hasChanged&&!n.hasChanged.call(this,t,i)||(this.#e[s]=t,this._notify(i,[s]))})),O(this.#l,t),O(this.#a,s),this.#A(this.#l)}}_updateProps(t){let s=e(this.constructor,dt.PROPS);h(t,((t,e)=>{let r=S(e),n=s[r];if(!n)return;let i=this.#e[r];t=this.#w(s,r,t),n.hasChanged&&!n.hasChanged.call(this,t,i)||(wt.__skipCheck=!0,y(this,r,t),wt.__skipCheck=!1)})),O(this.#l,t),this.#A(this.#l)}_initProps(t,e){this.#l=c(this.#l||{},t),this.#a=c({},e)}_bindSlot(t,e,s){if(this.#f[e]||(this.#f[e]=t,Reflect.defineProperty(t,"__l_comp",{value:this})),t.addEventListener("slotchange",(s=>{this.#m&&this.#N(t,"default"===e?"":e)})),!i(s)){let t=this.#t[e];t||(t=this.#t[e]={}),s.nodeFilter&&(t.filter=s.nodeFilter),t.props=U(s,"nodeFilter")}}_bindSlotHook(t,e){this.#u[t]=e}#x=new Set;_updateSlot(t,e,s){let r=this.#f[t],n=this.#u[t];if(!n&&!r)return;let i=this.#t[t];if(e&&(i.props||(i.props={}),i.props[e]=s),n)this.#x.add(t);else{let t=r.assignedElements({flatten:!0});for(let r=0;r<t.length;r++){t[r].setAttribute(e,s+"")}}}#v(){const t=x(this.childNodes,(t=>t.nodeType===Node.COMMENT_NODE?[]:t instanceof HTMLSlotElement?t.assignedNodes({flatten:!0}):t));let e=B(t,(t=>t.nodeType===Node.TEXT_NODE?"default":t instanceof Element?t.getAttribute("slot")||"default":void 0));if(i(e))return void(i(this.#e["#slots"])||(this.#m?this.#s["#slots"]={}:this.#e["#slots"]={}));h(e,((t,e)=>{if(e){for(;t.length>0;){let e=t[0];if(!(e.nodeType===Node.TEXT_NODE&&b(e.textContent)||e instanceof HTMLSlotElement&&i(e.assignedNodes({flatten:!0}))))break;t.shift()}for(;t.length>0;){let e=f(t);if(!(e.nodeType===Node.TEXT_NODE&&b(e.textContent)||e instanceof HTMLSlotElement&&i(e.assignedNodes({flatten:!0}))))break;t.pop()}}}));let s={};h(e,((t,e)=>{i(t)||(s[e]=t)})),this.#m?this.#s["#slots"]=s:this.#e["#slots"]=s}#S(t){let s=this.#u[t];if(!s)return;let r=this.#t[t];if(!this.#e["#slots"][t])return;this.renderAsync(s,e(r,"props"));const n=this._asyncDirectives.get(s);let o=n?.buildView(s(e(r,"props"))),a=z(p(o),(t=>t.nodeType===Node.COMMENT_NODE));if(a){let e=this.#g[t];if(!i(e))for(let t=0;t<e.length;t++){const s=e[t];s.parentNode?.removeChild(s)}this.#g[t]=a,this.append(...a),this.#x.clear()}}_asyncDirectives=new WeakMap;renderAsync(t,...e){}#_(){i(this.#t)||h(this.slots,((t,e)=>{if(i(t))return;let r=this.#t[e],n=t;if(r){let e=r.filter;if(m(e))n=e(t);else if(s(e)){let s=e.type,r=e.maxCount;if(s){let e=_(s)?s:[s];n=F(t,(t=>$(e,(e=>t instanceof e))))}r>0&&(n=K(t,0,r))}}if("named"===this.#n.slotAssignment){let e=[];for(let s=0;s<t.length;s++){const r=t[s];n.includes(r)||e.push(r)}for(;e.length>0;){let t=e.pop();t.parentNode?.removeChild(t)}}else this.#f[e].assign(...n);this.#m&&this.#N(this.#f[e],"default"===e?"":e)}))}#T(t,s,r){if(!this.isMounted)return;if(xt(this.constructor).has(t)){let s=S(t);if(W(r)){r=e(this.constructor,dt.PROPS)[s]._defaultValue}this._updateProps({[s]:r})}}_regDeps(t,e){let s=this.#o[t];s||(s=this.#o[t]=new Set),s.add(e);let r=t.split("-");if(r.pop(),r.length<1)return;let n=r.join("-");s=this.#o[n],s||(s=this.#o[n]=new Set),s.add(e)}}var Ut,Bt,zt;!function(t){t.NONE="NONE",t.REMOVE="REMOVE",t.REPLACE="REPLACE",t.UPDATE="UPDATE",t.APPEND="APPEND"}(Ut||(Ut={}));class Ft{key;varIndex;value;isText=!1;isTmpl=!1;isDirective=!1;node;textNode;isComponent=!1;attrName;attrTmpl;isProp=!1;isToggleProp=!1;isEvent;constructor(t,e,s,r){this.varIndex=t,this.node=e,s&&(this.attrName=s),r&&(this.attrTmpl=r)}}!function(t){t.ATTR="attr",t.PROP="prop",t.TEXT="text",t.CLASS="class",t.STYLE="style",t.SLOT="slot",t.TAG="tag"}(Bt||(Bt={}));class Kt{startNode;endNode;type;attrName;varIndex;expressionChain;nodes;constructor(t,e,s){this.startNode=t,this.attrName=e,this.type=s}setVarIndex(t){this.varIndex=t}getNodes(){let t=this.startNode.nextSibling;if(!this.endNode)return[t];let e=[];for(;t&&t!==this.endNode;)e.push(t),t=t?.nextSibling;return e}}!function(t){t.AFTER_BEGIN="afterbegin"}(zt||(zt={}));class Qt extends Function{diClass;args;di;varPath;point;slotComponent;varChain;constructor(t,...e){super(),this.diClass=t,this.args=e,this.varChain=wt.popDirectiveQ(),this.di=new this.diClass,this.di.renderParams=this.varChain}checkScope(t){let s=e(this.diClass,"scopes");i(s)||A(s.join(","),t)||ut(`Directive '${this.diClass.name}' is out of scopes, expect '${s.join(",")}' bug got '${t}'`)}render(t){let e=this.di;return this.args,e.renderComponent||(e.renderComponent=t),this.di=e,e._renderArgs=this.args,this.di.render(...this.args)}update(t,e,s){let r=this.di.update(t,e,s);if(r===Ut.NONE)return;let n=t.getNodes();if(r===Ut.REMOVE)for(let t=0;t<n.length;t++){const e=n[t];e.parentNode?.removeChild(e)}else if(r===Ut.REPLACE){let s=[];for(let t=0;t<n.length;t++){const e=n[t];e.parentNode?.removeChild(e)}let r=this.di.render(...e),i=this.di.buildView(r);s=p(i);let o=document.createDocumentFragment();o.append(...s),t.endNode.parentNode.insertBefore(o,t.endNode)}else if(r===Ut.UPDATE){let s,r={},o=[],a=[],l=this.di.render(...e);if(l||(l=new je([],[])),i(n)){let e=this.di.buildView(l);return void t.startNode.after(...e)}let c={};l instanceof je&&l.vars.forEach((t=>{if(t instanceof je){const e=t.getKey();c[e]=t,r[e]=!0,a.push(e)}})),n=F(Q(n),(t=>t.nodeType===Node.ELEMENT_NODE)),s=F(Q(p(s)),(t=>t.nodeType===Node.ELEMENT_NODE));let d={},u="",g={};for(let t=0;t<n.length;t++){let e=n[t],s=e.getAttribute("key");if(s){if(d[s]){u=s;break}d[s]=e,o.push(s),g[s]=!0}}if(u)return void ut(`${S(this.diClass.name)} - duplicate key '${u}'`);let m=r;const _=t.startNode.parentNode;let b=[],v=[];if(h(g,((t,e)=>{m[e]||(v.push(e),delete g[e],X(o,e))})),!i(a)){let e="",s=-1,r=[],n=new Map;for(let i=0;i<a.length;i++){const l=a[i];let c=o.findIndex((t=>t===l));if(c>-1&&c!==i){if(s<0||s-c==1){let t=f(r);r.push({nodeId:l,targetId:0===i?zt.AFTER_BEGIN:t?t.nodeId:a[i-1]})}else n.set(r.length,{group:r,targetId:""}),r=[],r.push({nodeId:l,targetId:o[c]});s=c}else if(c<0){let s=e?d[e]||t.endNode:t.startNode;b.push({prevNode:s,newkey:l})}e=l}i(n)&&r.length>0&&n.set(r.length,{group:r,targetId:""});let l=n.keys().toArray(),c=l.sort(((t,e)=>t-e));if(l.length>0&&l.length<2){let{group:e}=n.get(c[0]);E(e).forEach((({targetId:e,nodeId:s})=>{let r,n=d[s];e===zt.AFTER_BEGIN?(r=t.startNode,r.after(n)):(r=d[e],r.after(n))}))}}b.length>0&&this.#M(b,c,a),b.forEach((e=>{let s=e.newkey,r=this.newNodeMap[s],n=e.prevNode;n===t.endNode?n.before(r):(t.startNode,n.after(r))})),v.forEach((t=>{let e=o.findIndex((e=>e==t));this.#O(e);let s=d[t];s&&s.parentNode&&_.removeChild(s)})),this.di.__updatePoints.forEach((t=>{t.key||(t.key=t.value.tmpl.getKey());const e=a.findIndex((e=>e==t.key));t.varIndex=e})),this.di.updateView(l)}}getDirective(){return this.di}newNodeMap={};#M(t,e,s){const r=[],n=[];t.forEach((t=>{let s=t.newkey;r.push(""),n.push(e[s])})),r.push("");let i=new je(r,n),o=this.di.__updatePoints,a=this.di.buildView(i);this.di.__updatePoints.forEach(((t,e)=>{const s=t.value.tmpl.getKey();t.key=s})),this.di.__updatePoints.push(...o),a.forEach((t=>{t instanceof HTMLElement&&(this.newNodeMap[t.getAttribute("key")]=t)}))}#O(t){X(this.di.__updatePoints,((e,s)=>{if(e.varIndex==t)return He.remove(e.node,e.textNode),!0}))}}function Xt(t){return(...e)=>{let s=null;return e.forEach(((t,r)=>{if(m(t)){let n=t;e[r]=function(...t){let e=s.di;wt.startRender(e);let r=n.call(e.renderComponent,...t);return wt.endRender(e.renderComponent),r}}})),s=new Qt(t,...e),s}}const Gt=["resize","outside","mutate"],qt=new WeakMap,Yt=[],Zt=new ResizeObserver((t=>{for(const e of t){const t=Array.isArray(e.contentBoxSize)?e.contentBoxSize[0]:e.contentBoxSize,s=Array.isArray(e.borderBoxSize)?e.borderBoxSize[0]:e.borderBoxSize;let r=qt.get(e.target);if(r){r(new CustomEvent("resize",{bubbles:!1,cancelable:!1,detail:{borderBox:{w:s.inlineSize,h:s.blockSize},contentBox:{w:t.inlineSize,h:t.blockSize}}}),e.target)}}}));var Jt;!function(t){t.Child="child",t.Tree="tree",t.Attr="attr",t.Char="char"}(Jt||(Jt={}));const te=new WeakMap,ee=new MutationObserver((t=>{for(let e=0;e<t.length;e++){const s=t[e];let r=te.get(s.target);if(!r)return;let n={target:s.target},i=null;switch(s.type){case"subtree":n.type=Jt.Tree,i=r[Jt.Tree];break;case"childList":n.type=Jt.Child,n.addedNodes=s.addedNodes,n.removedNodes=s.removedNodes,i=r[Jt.Child];break;case"attributes":n.type=Jt.Attr,n.attributeName=s.attributeName,n.oldValue=s.oldValue,i=r[Jt.Attr];break;case"characterData":n.type=Jt.Char,n.oldValue=s.oldValue,i=r[Jt.Char]}if(i){i(new CustomEvent("mutate",{bubbles:!1,cancelable:!1,detail:n}),s.target)}}}));function se(t,e,s,r){if("resize"===t)!function(t,e){qt.has(t)||(qt.set(t,e),Zt.observe(t))}(e,s);else if("outside"===t){if("mousedown"===r[0])!function(t,e){Yt.push([t,e])}(e,s)}else"mutate"===t&&function(t,e,s){let r=G(s,"child"),n=G(s,"attr"),i=G(s,"char"),o=G(s,"tree"),a=te.get(t);a||(a={},te.set(t,a),r&&(a[Jt.Child]=e),n&&(a[Jt.Attr]=e),i&&(a[Jt.Char]=e),o&&(a[Jt.Tree]=e),ee.observe(t,{childList:r,attributes:n,characterData:i,subtree:o}))}(e,s,r)}document.addEventListener("mousedown",(t=>{let e=t.target;Yt.forEach((([s,r])=>{if(!s.contains(e)){r(new CustomEvent("outside",{bubbles:!1,cancelable:!1,detail:{currentTarget:s,event:t}}),s)}}))}),!1);const re=/,|^(debounce:.+)|(debounce$)/,ne=/,|^(throttle:.+)|(throttle$)/,ie="self",oe="stop",ae="prevent",le="once",ce="left",de="right",he="middle",ue="ctrl",pe="alt",fe="shift",ge="meta",me={esc:"escape"},_e=":";function Ee(t,e,s,r){let n,i=t.split("."),o=i.shift(),a=i.includes(le),l=e;if(n=q(i,(t=>re.test(t)))){let t=n.split(_e);l=R(l,parseInt(t[1])||100)}if(n=q(i,(t=>ne.test(t)))){let t=n.split(_e);l=Y(l,parseInt(t[1])||100)}if(a&&(l=D(l)),function(t){return Gt.includes(t)}(o))return se(o,s,l,i),l;let c=t=>{if(i.includes(ae)&&t.preventDefault(),i.includes(oe)&&t.stopPropagation(),!i.includes(ie)||t.target===t.currentTarget){if(t instanceof MouseEvent){if(i.includes(ce)&&0!=t.button)return;if(i.includes(de)&&2!=t.button)return;if(i.includes(he)&&1!=t.button)return}else if(t instanceof KeyboardEvent){if(X(i,(t=>t==ue))[0]&&!t.ctrlKey)return;if(X(i,(t=>t==pe))[0]&&!t.altKey)return;if(X(i,(t=>t==fe))[0]&&!t.shiftKey)return;if(X(i,(t=>t==ge))[0]&&!t.metaKey)return;if(!Z(i,(t=>me[t]||t)).includes(t.key.toLowerCase()))return}l(t,s)}};s.addEventListener(o,c);let d=r.__events[o];return d||(d=r.__events[o]=[]),d.push([s,c]),c}const be="@",ve=".",Ce="?",ye="*",Se=":",Ne="ref",Te=/[.?-a-z]+\s*=\s*(['"])\s*([^='"]*<\!--c_ui-pl_df-->){2,}.*?\1/ims,Pe=/<\s*[a-z0-9-]+([^>]*<\!--c_ui-pl_df-->)*[^>]*?(?<!-)>/gims,xe="slot-props";function we(t,s){let r="",n=a(s.vars),i=s.strings.length-1,o=s.vars.length-1;for(let n=0;n<=i;n++){const i=s.strings[n];let a=e(s.vars,n,"");if(a&&a.di){let e=a.render(t);if(e instanceof je){let[s,r]=we(t,e);Reflect.defineProperty(a,"_renderVars",{value:r}),a=Ae+s+Me}else a=e??Re}else if(a instanceof je){let[e,s]=we(t,a);Reflect.defineProperty(a,"_renderVars",{value:s}),a=Oe+e+ke}else a=n>o?"":Re;r+=i+a}let l=r.match(Te);if(l){return ut(`Parse error: attribute value can be set only one interpolation —— \n ${J(l[0],Re,"${...}")}`),["",n]}let c=0;return r=r.replace(Pe,((t,e)=>J(t,Re,(()=>Re.replace("--\x3e","")+c++)))),r=r.replace($e,"$1><").trim(),[r,n]}const Ae="\x3c!--c_ui-pl_di-start--\x3e",Me="\x3c!--c_ui-pl_di-end--\x3e",Oe="\x3c!--c_ui-pl_tmpl-start--\x3e",ke="\x3c!--c_ui-pl_tmpl-end--\x3e",Re="\x3c!--c_ui-pl_df--\x3e",Le="\x3c!--c_ui-pl_df",De=/<!--c_ui-pl_df\d*(-->)?/;function Ve(t,s,r,i,a){const l=document.createElement("div");l.innerHTML=s;const c=document.createNodeIterator(l,NodeFilter.SHOW_ELEMENT|NodeFilter.SHOW_COMMENT);let d,h,_=0,E=null,b=[],v=[],C=[],y=[t],N=[],P=[];for(;d=c.nextNode();)if(d instanceof HTMLElement||d instanceof SVGElement){d instanceof jt?E=d:E?.contains(d)||(E=null);let e={},s=p(d.attributes);for(let n=0;n<s.length;n++){const a=s[n];let{name:l,value:c}=a;if(l===xe){let t=d.getAttribute("name")||"default";if(E){let e=E._slotsPropMap[t];e||(e=E._slotsPropMap[t]=[]),e.push(d)}}if(g(l,Le)){let e=r[_];if(e instanceof Qt){e.checkScope(Bt.TAG);let s=new Kt(d,l.substring(1),Bt.TAG);e.point=s,e.di.slotComponent=E,e.di.renderComponent=i;let r=new Ft(_,d);r.isDirective=!0,r.value=e,r.isComponent=!!E,t.push(r),_++,e.di.created(s,...e.args)}d.removeAttribute(l)}else if(l[0]!==be)if(l!==Ne)if(l[0]!==ve||De.test(c)){if(De.test(c)){let s=r[_],n=new Ft(_,d,l.replace(/\.|\?|@/,""),c);if(t.push(n),n.isComponent=!!E,l[0]===ve||l[0]===Ce||l[0]===ye){if(s instanceof Qt){s.checkScope(Bt.PROP);let t=new Kt(d,l.substring(1),Bt.PROP);s.point=t,s.slotComponent=E,n.value=s,n.isDirective=!0,s&&s.di.created(s.point,...s.args)}else if(l[0]===Ce)n.isToggleProp=!0,n.value=!!s,n.value&&d.setAttribute(l.substring(1),"");else if(l[0]===ye){n.value=s;let t=l.substring(1);const[e,r]=t.split(Se);let i=e;switch(r){case"camel":i=S(i);break;case"kebab":i=u(i);break;case"snake":i=tt(i)}n.attrName=i,d.setAttribute(i,s)}else if(d instanceof jt||"SLOT"===d.tagName){let t=S(l.substring(1));t in d||"SLOT"===d.tagName||pt(d.tagName,`Prop '${l}' is not defined in ${d.tagName}`),n.value=s,n.isProp=!0,e[t]=s}else pt(d.tagName,`Prop '${l}' can only be set on a CompElem or a slot`);d.removeAttribute(l),s=""}else{let t;if(n.value=s,s instanceof Qt){let e=Bt.ATTR;"class"===l?e=Bt.CLASS:"style"===l&&(e=Bt.STYLE),s.checkScope(e),n.isDirective=!0;let r=new Kt(d,l,e);s.point=r,s.di.slotComponent=E,s.di.renderComponent=i,t=s,s=""}c=T(c,De,s),a.value=c,t&&t.di.created(t.point,...t.args)}_++}}else pt(d.tagName,`Prop '${l}' must be an interpolation`);else{if(De.test(c)){let t=r[_];if(!o(t,"current")){pt(d.tagName,"Ref must be a RefObject");continue}_++,t.current=d}d.removeAttribute(l)}else{let e=t=>{};if(De.test(c)){let s=r[_];if(!m(s)){pt(d.tagName,`Event '${l}' must be a function`);continue}e=s.bind(i);let n=new Ft(_,d,l.replace(/\.|\?|@/,""),c);n.isComponent=!!E,n.isEvent=!0,t.push(n),_++}Ee(l.substring(1),e,d,i),d.removeAttribute(l)}}d instanceof jt?d._initProps(e):d instanceof HTMLSlotElement&&i._bindSlot(d,d.name||"default",e)}else{let s=d,o=`\x3c!--${s.nodeValue}--\x3e`;if(o===Ae){h&&b.push(h),h=s;let e=r[_],n=new Ft(_,d);n.isComponent=!!E,n.isDirective=!0,n.value=e;let o=E?Bt.SLOT:Bt.TEXT,a=new Kt(h,"",o);e.point=a,e.di.slotComponent=E,e.di.renderComponent=i,v.push(e),t.push(n),C.push(n),t=[],y.push(t),_++,P.push(_),N.push(r),r=e._renderVars,_=0;continue}if(o===Me){C.pop().textNode=s;let e=v.pop();e.point.endNode=s,e.di.created(e.point,...e.args),h=b.pop(),e.di.__updatePoints=t,y.pop(),t=f(y),r=N.pop(),_=P.pop()}else{if(o===Oe){h&&b.push(h),h=s;let n=r[_],o=new Ft(_,d);o.isComponent=!!E,o.isTmpl=!0;let l=f(v);(l&&"ForEach"===e(l,"diClass.name")||"ForEach"==a.constructor.name)&&(o.key=n.getKey()),n=o.value=new Ht(n);let c=E?Bt.SLOT:Bt.TEXT,u=new Kt(h,"",c);n.point=u,n.slotComponent=E,n.renderComponent=i,v.push(n),t.push(o),C.push(o),t=[],y.push(t),_++,P.push(_),N.push(r),r=n._renderVars,_=0;continue}if(o===ke){C.pop().textNode=s;let e=v.pop();e.point.endNode=s,h=b.pop(),e.__updatePoints=t,y.pop(),t=f(y),r=N.pop(),_=P.pop()}}if(o!==Re)continue;let l=new Ft(_,d);t.push(l),l.isComponent=!!E,l.isText=!0;let c,u=r[_];if(c=document.createComment(`compelem-ui-${_}-child-start`),s.parentNode.insertBefore(c,s),s.nodeValue=`compelem-ui-${_}-child-end`,l.textNode=c,u instanceof Qt){l.isDirective=!0,l.value=u;let t=E?Bt.SLOT:Bt.TEXT,e=new Kt(c,"",t);e.endNode=s,u.point=e,u.di.slotComponent=E,u.di.renderComponent=i,u.di.created(e,...u.args),u=""}else if(u instanceof je){l.isTmpl=!0,l.value=u;let[e,s]=we(i,u);u=Ve(t,e,s,i,a)}else l.value=u;if(_++,n(u))continue;if(u instanceof NodeList){let t=document.createDocumentFragment();t.append(...u),s.parentNode.insertBefore(t,s)}else if(u instanceof Element)s.parentNode.insertBefore(u,s);else if(I(u)){let t=document.createTextNode(u);s.parentNode.insertBefore(t,s)}}return l.childNodes}const He={insertBefore:function(t,e){if(!t.parentNode)return;let s=document.createDocumentFragment();s.append(...e),t.parentNode.insertBefore(s,t)},remove:function(t,e){if(t===e)return void t?.parentNode?.removeChild(t);let s=t.nextSibling;for(;s&&s!==e;)s?.parentNode?.removeChild(s),s=t.nextSibling}};function Ie(t,...e){return new je(w(t)?[t]:t,e)}const $e=/([a-z0-9"'])\s*>\s*</gim;function We(t){return{current:t}}class je{strings;vars;constructor(t,e){this.strings=a(t),this.vars=e}getKey(){let t=this.vars,e="";return h(this.strings,((s,r)=>{if(lt.test(s))return e=et(t[r]),!1})),e}getKeys(){let t=this.vars,e=[];for(let s=0;s<this.strings.length;s++){const r=this.strings[s];if(lt.test(r)){let r=et(t[s]);e.push(r)}}return i(e)&&t.forEach((t=>{if(t instanceof je){let s=t.getKey();e.push(s)}})),e}append(t){let e=f(this.strings);return t.strings.forEach(((t,s)=>{0!=s?this.strings.push(t):this.strings[this.strings.length-1]=e+t})),this.vars=a(this.vars,t.vars),this}insert(t,e){let s=e.strings.shift();return this.strings[t]+=s,this.strings.splice(t+1,0,...e.strings),this.vars.splice(t,0,...e.vars),this}getHTML(t){let[e,s]=we(t,this),r=Ve([],e,s,t,t);return st(r,((t,e)=>t+e.outerHTML),"")}}function Ue(t,e,s){s.get||ut(`Computed '${e}' must be a getter`),o(t.constructor,dt.COMPUTED)||(t.constructor[dt.COMPUTED]=i(t.constructor[dt.COMPUTED])?{}:d(t.constructor[dt.COMPUTED])),t.constructor[dt.COMPUTED][e]=s.get}function Be(t,e){return(s,r,n)=>{o(s.constructor,dt.EVENTS)||(s.constructor[dt.EVENTS]=i(s.constructor[dt.EVENTS])?[]:d(s.constructor[dt.EVENTS])),s.constructor[dt.EVENTS].push({name:t,options:e,fn:s[r]})}}var ze;!function(t){t.ONCE="once",t.UPDATABLE="updatable"}(ze||(ze={}));class Fe extends mt{static get priority(){return Number.MAX_VALUE}created(t,e,s,...r){}mounted(t,e,...s){}get targets(){return[ht.FIELD]}selector;cache;result;constructor(t,e){super(),this.selector=t,this.cache=e}static getKey(t){return t}getter(t){this.result=t.shadowRoot?.querySelector(this.selector)}beforeMount(t,e,s,r,...n){const i=this;Reflect.defineProperty(t,r,{get:()=>(i.result&&i.cache||i.getter(t),i.result)})}updated(t,e){this.cache===ze.UPDATABLE&&this.getter(t)}}const Ke=yt(Fe),Qe=yt(class extends Fe{getter(t){this.result=t.shadowRoot?.querySelectorAll(this.selector)}});function Xe(t){if(1===arguments.length)return(e,s)=>{Ge(e,s,t)};Ge(arguments[0],arguments[1],{prop:""})}function Ge(t,e,s){if(!o(t.constructor,dt.STATES)){const e={};let s=t.constructor;for(;(s=gt(s))!==jt;)c(e,s[dt.STATES]?d(s[dt.STATES]):{});Reflect.defineProperty(t.constructor,dt.STATES,{configurable:!1,enumerable:!1,value:e})}t.constructor[dt.STATES][e]=s}function qe(t,e,s){Ge(t.prototype,e,s||{prop:""})}function Ye(t){return e=>{if(e){if(e.prototype.hasOwnProperty("attributeChangedCallback")){let t=e.prototype.attributeChangedCallback;e.prototype.attributeChangedCallback=function(e,s,r){jt.prototype.attributeChangedCallback.call(this,e,s,r),t.call(this,e,s,r)}}if(e.prototype.hasOwnProperty("connectedCallback")){let t=e.prototype.connectedCallback;e.prototype.connectedCallback=function(){jt.prototype.connectedCallback.call(this),t.call(this)}}if(e.prototype.hasOwnProperty("disconnectedCallback")){let t=e.prototype.connectedCallback;e.prototype.disconnectedCallback=function(){jt.prototype.disconnectedCallback.call(this),t.call(this)}}customElements.define(t,e)}}}function Ze(t,e){return(s,r)=>{o(s.constructor,dt.WATCH)||(s.constructor[dt.WATCH]=i(s.constructor[dt.WATCH])?{}:d(s.constructor[dt.WATCH]));(_(t)?t:[t]).forEach((t=>{let n=t.replaceAll(".","-"),i=s.constructor[dt.WATCH][n];_(i)||(i=s.constructor[dt.WATCH][n]=[]),i.push({source:t,options:e,handler:s[r]})}))}}class Je extends(Vt(Object)){_renderArgs;static get scopes(){return[]}renderParams}const ts=["key"];const es=Xt(class extends Je{created(t,e){let s=t.startNode;if(s instanceof jt){let t={},r={};h(e,((e,n)=>{ts.includes(n)||(n in s?t[n]=e:r[n]=e+"")})),s._initProps(t,r)}else h(e,((t,e)=>{s.setAttribute(e,t)}))}update(t,e,s){return Ut.NONE}static get scopes(){return[Bt.TAG]}render(t){}});const ss=Xt(class extends Je{created(t,e){let r=[];_(e)?r=Q(e):s(e)?r=x(e,((t,e)=>t?e:[])):w(e)&&(r=e.split(" "));let n=t.startNode;h(this.lastCls,(t=>{n.classList.remove(t)})),h(r,(t=>{n.classList.add(t)})),this.lastCls=a(r)}update(t,e,s){return this.created(t,e[0]),Ut.NONE}static get scopes(){return[Bt.CLASS]}lastCls;render(t){}});const rs=Xt(class extends Je{created(t,...e){}update(t,e,s){if(i(t.getNodes())&&(!e||i(e[0])))return Ut.NONE;if(rt(this.lastAry,e[0])&&this.lastAry.length===e[0].length)return Ut.NONE;if(!i(this.renderParams)){let t=f(this.renderParams);_(t)||(t=[t]),this.renderParams=t}return this.lastAry=nt(e[0]),Ut.UPDATE}constructor(t){super(),i(this.renderParams)||(this.renderParams=p(f(this.renderParams)))}static get scopes(){return[Bt.TEXT,Bt.SLOT]}lastAry;lastRenderTmpl;render(t,e){let s=Z(t,((t,s)=>e(t,s)));if(s.length<1)return this.lastRenderTmpl=new je([],[]),this.lastRenderTmpl;let r=[],n=[];const i=[],o=[];for(let t=0;t<s.length;t++){const e=s[t];let a=f(n),l=e.vars,c=!0,d=e.strings;for(let t=0;t<d.length;t++){const e=d[t];if(lt.test(e)){let e=l[t]+"";if(r.includes(e))return void ut(`forEach - duplicate key '${e}'`);r.push(e),c=!1}0==t&&a?n[n.length-1]=a+e:n.push(e)}if(c)return void ut("forEach - missing 'key' prop");let h=f(i);h&&d.length>0&&(i[i.length-1]=I(h)+d.shift()),i.push(""),o.push(e)}return this.lastAry=nt(t),i.push(""),this.lastRenderTmpl=new je(i,o),this.lastRenderTmpl}});const ns=Xt(class extends Je{created(t,...e){}ifNodes;elseNodes;static get scopes(){return[Bt.TEXT,Bt.SLOT]}update(t,e,s){return!!e[0]==!!s[0]?Ut.NONE:(e[0],Ut.REPLACE)}render(t,e,s){return t?e(t):s(t)}});const is=Xt(class extends Je{created(t,...e){}static get scopes(){return[Bt.TEXT,Bt.SLOT]}update(t,e,s){return e[0]===s[0]?Ut.NONE:e[0]?Ut.REPLACE:Ut.REMOVE}render(t,e){return t?e():Ie``}});var os;!function(t){t.CHANGE="change",t.INPUT="input"}(os||(os={}));const as=Xt(class extends Je{created(r,n,i){this.modelPath||(this.modelPath=f(this.renderParams)),i&&(this.modelPath=t(i));const o=r.startNode;if("binded"!==e(o,"_model"))if(s(n)||I(n)||(n=""),o instanceof jt)o._initProps({value:n}),o.addEventListener("update:value",(t=>{y(this.renderComponent,this.modelPath,t.detail.value)})),y(o,"_model","binded");else if(o instanceof HTMLTextAreaElement)o.setAttribute("value",n+""),o.addEventListener("input",(t=>{let e=t.target;y(this.renderComponent,this.modelPath,e.value)})),y(o,"_model","binded");else if(o instanceof HTMLInputElement){let t="",e="";switch(o.type){case"checkbox":case"radio":t="checked",e="change";break;default:t="value",e="input"}o.setAttribute(t,n+""),o.addEventListener(e,(t=>{let e=t.target;y(this.renderComponent,this.modelPath,e.value)})),y(o,"_model","binded")}else o instanceof HTMLSelectElement&&(o.setAttribute("value",n+""),o.addEventListener("change",(t=>{let e=t.target;y(this.renderComponent,this.modelPath,e.value)})),y(o,"_model","binded"))}update(t,e,s){if(this.modelPath||(this.modelPath=f(this.renderParams)),!N(e,s)){const s=t.startNode;if(s instanceof jt)s._updateProps({value:e[0]});else if(s instanceof HTMLTextAreaElement||s instanceof HTMLSelectElement)s.setAttribute("value",e[0]+"");else if(s instanceof HTMLInputElement)switch(s.type){case"checkbox":case"radio":e[0]?s.setAttribute("checked",""):s.removeAttribute("checked");break;default:s.setAttribute("value",e[0]+"")}}return Ut.NONE}static get scopes(){return[Bt.TAG]}modelPath;render(t,e){}});const ls=Xt(class extends Je{created(t,e){let s=t.startNode;n(this.display)&&(this.display=s.style.display),this.renderComponent.nextTick((()=>{s.style.display=e?this.display:"none"}))}update(t,e,s){return this.created(t,e[0]),Ut.NONE}display=void 0;static get scopes(){return[Bt.TAG]}constructor(t){super(),this.point=t}render(t){}});const cs=Xt(class extends Je{created(t,e,s){e=e.bind(this.renderComponent),this.slotComponent._bindSlotHook(s||"default",e)}update(t,e,s){return Ut.NONE}static get scopes(){return[Bt.SLOT]}render(t,e){}});class ds{static getCssText(t){return w(t)?t:v(Z(t,((t,e)=>u(e)+":"+t)),";")}static setStyle(t,e){if(w(t)&&!I(t))return{};let s=ds.getCssText(t),r={};return h(s.split(";"),(t=>{let s=t.split(":"),n=I(s[0]),i=I(s[1]);r[n]=e.style.getPropertyValue(n),e.style.setProperty(n,i)})),r}}const hs=Xt(class extends Je{created(t,e){ds.setStyle(e,t.startNode)}update(t,e,s){return this.created(t,e[0]),Ut.NONE}constructor(t){super(),this.point=t}static get scopes(){return[Bt.STYLE]}render(t){}});const us=Xt(class extends Je{created(t,e){this.modelPath||(this.modelPath=f(this.renderParams));const s=t.startNode;let r=t.attrName;s._initProps({[r]:e}),s.addEventListener("update:"+r,(t=>{y(this.renderComponent,this.modelPath,t.detail.value)}))}update(t,e,s){if(!N(e,s)){const s=t.startNode;let r=t.attrName;s._updateProps({[r]:e[0]})}return Ut.NONE}static get scopes(){return[Bt.PROP]}modelPath;constructor(t){super()}render(t){}});const ps=Xt(class extends Je{created(t,...e){}static get scopes(){return[Bt.TEXT,Bt.SLOT]}update(t,e,s){return N(e,s)?Ut.NONE:Ut.REPLACE}render(t,e){let s=()=>Ie``,r=[],n=[];h(e,((t,e)=>{if(m(t))r.push(e),n.push(t);else{let e=t[0],s=t[1];r.push(e),n.push(s)}"default"===e&&(s=t)}));let i=it(r,(e=>m(e)?e(t):e==t));return ot(n[i]??s)}});export{jt as CompElem,ds as CssHelper,mt as Decorator,ht as DecoratorType,vt as DecoratorWrapper,Je as Directive,Ut as DirectiveUpdateTag,Qt as DirectiveWrapper,Kt as EnterPoint,Bt as EnterPointType,_t as GetKeyFnName,os as ModelTriggerType,ze as QueryCache,je as Template,Ft as UpdatePoint,bt as _DecoratorMap,Et as _DecoratorsKey,xt as _getObservedAttrs,es as bind,we as buildHTML,ss as classes,Ue as computed,We as createRef,yt as decorator,Xt as directive,Be as event,rs as forEach,Ie as html,ns as ifElse,is as ifTrue,qe as makeState,as as model,Nt as prop,Ke as query,Qe as queryAll,ls as show,cs as slot,Xe as state,hs as styles,us as sync,Ye as tag,Ze as watch,ps as when};
|