@pacem/pacem-core 1.0.0-abel

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.
Files changed (41) hide show
  1. package/LICENSE +191 -0
  2. package/NOTICE +4 -0
  3. package/dist/browser/pacem-core.js +9099 -0
  4. package/dist/browser/pacem-core.js.map +1 -0
  5. package/dist/browser/pacem-core.min.js +2 -0
  6. package/dist/browser/pacem-core.min.js.map +1 -0
  7. package/dist/bundle/pacem-core.min.mjs +3 -0
  8. package/dist/bundle/pacem-core.mjs +8479 -0
  9. package/dist/bundle/pacem-core.mjs.map +7 -0
  10. package/dist/esm/adapter.js +7 -0
  11. package/dist/esm/command.js +10 -0
  12. package/dist/esm/comparers.js +8 -0
  13. package/dist/esm/converters.js +70 -0
  14. package/dist/esm/decorators-next.js +783 -0
  15. package/dist/esm/decorators.js +736 -0
  16. package/dist/esm/defaults.js +5 -0
  17. package/dist/esm/events.js +89 -0
  18. package/dist/esm/eventtarget.js +131 -0
  19. package/dist/esm/expression.js +228 -0
  20. package/dist/esm/index-animations.js +1 -0
  21. package/dist/esm/index-behaviors.js +1 -0
  22. package/dist/esm/index-components.js +1 -0
  23. package/dist/esm/index-iife.js +3 -0
  24. package/dist/esm/index-logging.js +1 -0
  25. package/dist/esm/index-net.js +1 -0
  26. package/dist/esm/index-root.js +20 -0
  27. package/dist/esm/index-ui.js +1 -0
  28. package/dist/esm/index.js +7 -0
  29. package/dist/esm/logger.js +11 -0
  30. package/dist/esm/prefix.js +6 -0
  31. package/dist/esm/promise.js +34 -0
  32. package/dist/esm/regex.js +22 -0
  33. package/dist/esm/storage.js +56 -0
  34. package/dist/esm/template.js +4 -0
  35. package/dist/esm/transforms.js +248 -0
  36. package/dist/esm/types.js +10 -0
  37. package/dist/esm/utils-customelement.js +524 -0
  38. package/dist/esm/utils-customevent.js +60 -0
  39. package/dist/esm/utils.js +1073 -0
  40. package/package.json +37 -0
  41. package/typings/index.d.ts +2521 -0
@@ -0,0 +1,524 @@
1
+ /// <reference path="expression.ts" />
2
+ /// <reference path="promise.ts" />
3
+ /// <reference path="prefix.ts" />
4
+ /// <reference path="trees/json.ts" />
5
+ /// <reference path="utils.ts" />
6
+ import { Utils } from './utils';
7
+ import { INSTANCE_SCOPE_VAR, WATCH_PROPS_VAR, INSTANCE_HOST_VAR, INSTANCE_BINDINGS_VAR } from './types';
8
+ import { PCSS } from './prefix';
9
+ import { Expression } from './expression';
10
+ import { TemplateElement } from './template';
11
+ // namespace Pacem {
12
+ const PACEM_BAG = '__pacem__';
13
+ // {{ binding.expression }}
14
+ const bindingPattern = /^\{\{(.|\n)+\}\}$/;
15
+ // TODO: CSP-proof binding (no unsafe-eval)
16
+ // binding syntax example: `{ binding: { source: ^item.property.path, binder: $pacem.func, parameters: [ ^index, 'foo', : host._baz], mode: 'twoway' } }`
17
+ export class CustomElementUtils {
18
+ static get polyfilling() {
19
+ return customElements instanceof window['CustomElementRegistry'];
20
+ }
21
+ static camelToKebab(camelCased) {
22
+ return camelCased && camelCased.replace(/([A-Z])/g, '-$1').toLowerCase();
23
+ }
24
+ static kebabToCamel(kebabCased) {
25
+ return kebabCased && kebabCased.replace(/(-[a-z])/g, (m) => {
26
+ return m[1].toUpperCase();
27
+ });
28
+ }
29
+ static getWatchedProperties(target, includeInherited = true) {
30
+ var properties = [];
31
+ var chain = target instanceof HTMLElement ? target.constructor : target;
32
+ do {
33
+ let additional = this.getAttachedPropertyValue(chain, WATCH_PROPS_VAR) || [];
34
+ let pblic = additional.filter(p => !p.name.startsWith('_'));
35
+ Array.prototype.splice.apply(properties, [0, 0].concat(pblic));
36
+ } while (includeInherited && (chain = Object.getPrototypeOf(chain)));
37
+ return properties;
38
+ }
39
+ static getWatchedProperty(target, name) {
40
+ return this.getWatchedProperties(target, true).find(p => p.name === name);
41
+ }
42
+ static importjs(src, integrity = null, crossorigin = false) {
43
+ var attrs = { 'type': 'text\/javascript', 'src': src };
44
+ if (!Utils.isNullOrEmpty(integrity))
45
+ Utils.extend(attrs, { integrity: integrity });
46
+ if (crossorigin)
47
+ Utils.extend(attrs, { 'crossorigin': '' });
48
+ return CustomElementUtils.import(src, 'script', attrs, (document.head || document.getElementsByTagName("head")[0]));
49
+ }
50
+ static importcss(src, integrity = null, crossorigin = false) {
51
+ var attrs = { 'rel': 'stylesheet', 'href': src };
52
+ if (!Utils.isNullOrEmpty(integrity))
53
+ Utils.extend(attrs, { integrity: integrity });
54
+ if (crossorigin)
55
+ Utils.extend(attrs, { 'crossorigin': 'anonymous' });
56
+ return CustomElementUtils.import(src, 'link', attrs, (document.head || document.getElementsByTagName("head")[0]));
57
+ }
58
+ static import(key, tagName, attrs, appendTo = document.body) {
59
+ const _p = Utils.core;
60
+ var _imports = _p['imports'] = _p['imports'] || {};
61
+ return _imports[key] = _imports[key] || new Promise((resolve, reject) => {
62
+ // try to find the equivalent element in the DOM
63
+ var selector = tagName;
64
+ for (let attr in attrs || {}) {
65
+ selector += `[${attr}="${attrs[attr]}"]`;
66
+ }
67
+ var script = document.querySelector(selector);
68
+ if (!Utils.isNull(script)) {
69
+ // best guess: since element was already there, it is hopefully fully loaded
70
+ resolve(script);
71
+ }
72
+ else {
73
+ script = document.createElement(tagName);
74
+ script.onerror = e => {
75
+ reject(e);
76
+ };
77
+ script.onload = () => {
78
+ resolve(script);
79
+ };
80
+ for (var attr in (attrs || {})) {
81
+ script.setAttribute(attr, attrs[attr]);
82
+ }
83
+ appendTo.appendChild(script);
84
+ }
85
+ });
86
+ }
87
+ static { this.Theme = {
88
+ importWebFonts() {
89
+ function cleanupQuotes(input) {
90
+ // check if the string is wrapped around quotes to escape ';' chars
91
+ if (/^('|").*\1$/.test(input)) {
92
+ return input.substring(1, input.length - 1);
93
+ }
94
+ return input;
95
+ }
96
+ function downloadFont(fontFace) {
97
+ return Utils.isNullOrEmpty(fontFace) ? Promise.resolve() : document.fonts.load('1rem ' + fontFace);
98
+ }
99
+ const promises = ['icons', 'std', 'main', 'tech', 'btn'].map(f => {
100
+ const fontFace = Utils.Css.getVariableValue(`--${PCSS}-font-${f}`).split(',')[0];
101
+ const url = cleanupQuotes(Utils.Css.getVariableValue(`--${PCSS}-font-${f}-api-url`));
102
+ if (Utils.isNullOrEmpty(url)) {
103
+ return downloadFont(fontFace);
104
+ }
105
+ else {
106
+ return CustomElementUtils.importcss(url).then(_ => downloadFont(fontFace));
107
+ }
108
+ });
109
+ const atLeast1FontFaceReady = new Promise((resolve) => {
110
+ function check(count = 0) {
111
+ // size against the specs: https://developer.mozilla.org/en-US/docs/Web/API/FontFaceSet/size#specifications
112
+ if (count > 4 || !('size' in document.fonts) || typeof document.fonts.size === 'number' && document.fonts.size > 0) {
113
+ document.fonts.ready.then(resolve);
114
+ }
115
+ else {
116
+ setTimeout(check, 250, count++);
117
+ }
118
+ }
119
+ check();
120
+ });
121
+ promises.push(atLeast1FontFaceReady);
122
+ return Promise.all(promises);
123
+ }
124
+ }; }
125
+ static setAttachedPropertyValue(target, name, value) {
126
+ /*(target[PACEM_BAG] = target[PACEM_BAG] || {})[name] = value;*/
127
+ if (Utils.isNull(target))
128
+ return;
129
+ const propKey = Object.getOwnPropertyDescriptor(target, PACEM_BAG);
130
+ const bag = (propKey && propKey.value)
131
+ || Object.defineProperty(target, PACEM_BAG, {
132
+ value: {}, enumerable: false, writable: false, configurable: false
133
+ })[PACEM_BAG];
134
+ if (Utils.isNull(value))
135
+ delete bag[name];
136
+ else
137
+ bag[name] = value;
138
+ }
139
+ static deleteAttachedPropertyValue(target, name) {
140
+ CustomElementUtils.setAttachedPropertyValue(target, name, undefined);
141
+ }
142
+ static getAttachedPropertyValue(target, name, ensureValue) {
143
+ const propKey = Object.getOwnPropertyDescriptor(target, PACEM_BAG), bag = propKey && propKey.value;
144
+ if (Utils.isNull(bag && bag[name]) && !Utils.isNull(ensureValue)) {
145
+ CustomElementUtils.setAttachedPropertyValue(target, name, ensureValue);
146
+ return ensureValue;
147
+ }
148
+ return bag && bag[name];
149
+ }
150
+ /**
151
+ * Resolves a dotted path into actual values.
152
+ * @param path Dotted path
153
+ * @param scope Root of the path
154
+ */
155
+ static resolvePath(path, scope) {
156
+ if (!path || !scope)
157
+ return undefined;
158
+ if (/[\(\)\{\}]/.test(path))
159
+ throw `Security alert: not allowed to process paths like ${path}.`;
160
+ const trunks = path.split('.');
161
+ var root = scope, ref = root, parent, core = trunks[0];
162
+ trunks.forEach((t, i) => {
163
+ var trunksSq = t.split('[');
164
+ trunksSq.forEach((t2, j) => {
165
+ parent = ref;
166
+ if (/\]$/.test(t2)) {
167
+ t2 = t2.substring(0, t2.length - 1);
168
+ if (/^('|").+[^\\]\1$/.test(t2)) {
169
+ t2 = t2.substr(1, t2.length - 2);
170
+ }
171
+ }
172
+ ref = ref[t2];
173
+ });
174
+ });
175
+ var name, ndx;
176
+ if (/\]$/.test(path)) {
177
+ ndx = path.lastIndexOf('[');
178
+ name = path.substring(ndx + 1);
179
+ name = name.substring(0, name.length - 1);
180
+ }
181
+ else {
182
+ ndx = path.lastIndexOf('.');
183
+ name = path.substring(ndx + 1);
184
+ }
185
+ return { target: { value: ref, name: name }, parent: { value: parent || scope, path: path.substring(0, ndx) }, root: { value: root, property: core } };
186
+ }
187
+ static set(element, path, value) {
188
+ var obj = CustomElementUtils.resolvePath(path, element);
189
+ var current = obj.target.value;
190
+ if (current !== value) {
191
+ if (obj.parent.value != obj.root.value /* nested property scenario */
192
+ && !(obj.parent.value instanceof HTMLElement) /* and not targeting an HTMLElement (which will eventually fire autonomously) */) {
193
+ // 1. set new value (won't fire 'propertychange' since it's a nested property)
194
+ obj.parent.value[obj.target.name] = value;
195
+ // 2. clone the resulting object (will be set as the new one at 4.)
196
+ const set_val = Utils.clone(obj.root.value[obj.root.property]);
197
+ // 3. reset to previous value (so that when 4. will trigger the 'propertychange' we'll have meaningful arguments)
198
+ obj.parent.value[obj.target.name] = current;
199
+ // repeater-item?
200
+ let repItem;
201
+ if (obj.root.property === 'item' && !Utils.isNull(repItem = RepeaterItem.getRepeaterItem(obj.root.value))) {
202
+ // kind of ugly solution, I know. it works however...
203
+ // trigger array update
204
+ repItem.repeater && repItem.repeater.datasource && repItem.repeater.datasource.splice(repItem.index, 1, repItem.item = set_val);
205
+ }
206
+ else {
207
+ // 4. force root property change
208
+ obj.root.value[obj.root.property] = set_val;
209
+ }
210
+ }
211
+ else {
212
+ // parent === root, property change event fires automatically
213
+ obj.parent.value[obj.target.name] = value;
214
+ }
215
+ }
216
+ }
217
+ static get(element, path) {
218
+ var obj = CustomElementUtils.resolvePath(path, element);
219
+ return obj && obj.target && obj.target.value;
220
+ }
221
+ /**
222
+ * Works for unit-test contexts.
223
+ * @param element
224
+ */
225
+ static _findScopeContextLegacy(element) {
226
+ // old impl...
227
+ let el = element;
228
+ let retval;
229
+ do {
230
+ el = el.parentNode;
231
+ } while (el != null && (el != (retval = element.ownerDocument) || (el instanceof HTMLElement && (retval = el.shadowRoot) != null)));
232
+ //let logFn: (message?: string) => void;
233
+ //if (retval == null && console && (logFn = console.debug))
234
+ // logFn(`Element "${element.constructor.name}" isn't attached to any context yet.`);
235
+ return retval;
236
+ }
237
+ static findScopeContext(element) {
238
+ let retval = (element.isConnected) ?
239
+ element.getRootNode()
240
+ : CustomElementUtils.getAttachedPropertyValue(element, INSTANCE_SCOPE_VAR);
241
+ return retval ?? /* in Jasmine TESTS `element.isConnected` always returns false (attached to #document-fragment) */ CustomElementUtils._findScopeContextLegacy(element);
242
+ }
243
+ static findAncestor(element, predicate) {
244
+ let el = element;
245
+ let retval;
246
+ while (el && (el = el.parentNode || el.getRootNode()?.host) != null) {
247
+ if (el['host'] instanceof HTMLElement)
248
+ el = el['host'];
249
+ if (predicate.apply(el, [el])) {
250
+ retval = el;
251
+ break;
252
+ }
253
+ }
254
+ return retval;
255
+ }
256
+ static findAncestorShell(element) {
257
+ return CustomElementUtils.findAncestor(element, el => Utils.is(el, `.${PCSS}-body`) || el === document.body);
258
+ }
259
+ static findAncestorOfType(element, ctor) {
260
+ return CustomElementUtils.findAncestor(element, el => el instanceof ctor);
261
+ }
262
+ static findDescendants(element, predicate, firstOnly = false) {
263
+ const walker = document.createTreeWalker(element, NodeFilter.SHOW_ELEMENT);
264
+ var retval = [];
265
+ while (walker.nextNode()) {
266
+ let n = walker.currentNode;
267
+ if (predicate(n) === true) {
268
+ retval.push(n);
269
+ if (firstOnly) {
270
+ return retval;
271
+ }
272
+ }
273
+ }
274
+ return retval;
275
+ }
276
+ static findFirstDescendant(element, predicate) {
277
+ const any = CustomElementUtils.findDescendants(element, predicate, true);
278
+ return Utils.isNullOrEmpty(any) ? void 0 : any[0];
279
+ }
280
+ static findAll(selector = '[pacem]', filter = (e) => true) {
281
+ const retval = [];
282
+ document.querySelectorAll(selector).forEach((e, i, arr) => {
283
+ if (filter(e) === true) {
284
+ retval.push(e);
285
+ }
286
+ });
287
+ return retval;
288
+ }
289
+ /**
290
+ * To be used back again when Edge will allow Comment subclassing
291
+ * https://github.com/Microsoft/ChakraCore/issues/2999 and https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/12080908/
292
+ * @param element
293
+ * @param ctor
294
+ * @param upLevels
295
+ */
296
+ static findPreviousSiblingOrAncestorOfType(element, ctor, upLevels = 0) {
297
+ let el = element;
298
+ let retval = null;
299
+ let levels = 0;
300
+ do {
301
+ el = el.previousSibling || el.parentNode;
302
+ if (el instanceof ctor) {
303
+ if (levels >= upLevels) {
304
+ retval = el;
305
+ break;
306
+ }
307
+ else {
308
+ el = el.parentNode;
309
+ }
310
+ levels++;
311
+ }
312
+ } while (el != null);
313
+ return retval;
314
+ }
315
+ /**
316
+ * To be removed when Edge will allow Comment subclassing
317
+ * https://github.com/Microsoft/ChakraCore/issues/2999 and https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/12080908/
318
+ * @param element
319
+ * @param predicate
320
+ * @param upLevels
321
+ */
322
+ static findPreviousSiblingOrAncestor(element, predicate, upLevels = 0) {
323
+ let el = element;
324
+ let retval = null;
325
+ let levels = 0;
326
+ do {
327
+ el = el.previousSibling || el.parentNode;
328
+ if (el && predicate.apply(el, [el])) {
329
+ if (levels >= upLevels) {
330
+ retval = el;
331
+ break;
332
+ }
333
+ else {
334
+ el = el.parentNode;
335
+ }
336
+ levels++;
337
+ }
338
+ } while (el != null);
339
+ return retval;
340
+ }
341
+ static assignHostContext(host, template) {
342
+ // navigate through the DOM hierarchy
343
+ const walker = document.createTreeWalker(template.content, NodeFilter.SHOW_ELEMENT + /* traverse templates' content */ NodeFilter.SHOW_DOCUMENT_FRAGMENT);
344
+ while (walker.nextNode()) {
345
+ var node = walker.currentNode;
346
+ /*if (node instanceof HTMLTemplateElement)
347
+ CustomElementUtils.assignHostContext(host, node);
348
+ else*/ if (Utils.isNull(CustomElementUtils.getAttachedPropertyValue(node, INSTANCE_HOST_VAR))) {
349
+ CustomElementUtils.setAttachedPropertyValue(node, INSTANCE_HOST_VAR, host);
350
+ }
351
+ }
352
+ }
353
+ static findHostContext(element) {
354
+ let el = element;
355
+ let retval;
356
+ // not connected to the DOM? then exit and return undefined
357
+ if (!el.isConnected) {
358
+ return retval;
359
+ }
360
+ /*const root = element.getRootNode({ composed: false });
361
+ if (root instanceof ShadowRoot) {
362
+ return root.host as HTMLElement;
363
+ }*/
364
+ while (el != null) {
365
+ retval = CustomElementUtils.getAttachedPropertyValue(el, INSTANCE_HOST_VAR);
366
+ if (retval instanceof HTMLElement)
367
+ break;
368
+ el = el.parentElement;
369
+ }
370
+ let logFn;
371
+ if (retval == null && console && (logFn = console.warn))
372
+ logFn(`Element "${element.constructor.name}" isn't a descendant of a templated component.`);
373
+ return retval;
374
+ }
375
+ static isBindingAttribute(attr) {
376
+ /*if (/^\s*\{\s*binding\s+.*\}\s*$/.test(attr)) {
377
+
378
+ // { binding ... } syntax
379
+ var fn = attr.replace('binding', '').trim();
380
+ fn = fn.substring(1, fn.length - 1);
381
+ let twoway = /,\s*twoway\s*=\s*true\s*$/.test(fn);
382
+ let commaNdx = fn.indexOf(',');
383
+ if (commaNdx == -1)
384
+ commaNdx = fn.length;
385
+ var expression = Expression.parse(fn.substr(0, commaNdx), element);
386
+ (expression && expression.dependencies).forEach(d => {
387
+ d.twoway = d.twowayAllowed && twoway && expression.dependencies.length == 1;
388
+ });
389
+ return expression;
390
+ }
391
+ else*/
392
+ return bindingPattern.test(attr);
393
+ }
394
+ static extractBindingAttributeExpression(attr) {
395
+ if (CustomElementUtils.isBindingAttribute(attr)) {
396
+ return attr.substr(2, attr.length - 4);
397
+ }
398
+ else {
399
+ throw `Invalid attribute: incorrect binding syntax.`;
400
+ }
401
+ }
402
+ static parseBindingAttribute(attr, element) {
403
+ // loose syntax {{ ... }}
404
+ let expression = CustomElementUtils.extractBindingAttributeExpression(attr);
405
+ const arr = /,\s*(twoway|once)\s*$/.exec(expression), mode = arr && arr.length > 1 && arr[1];
406
+ if (!Utils.isNullOrEmpty(mode)) {
407
+ expression = expression.substr(0, expression.lastIndexOf(','));
408
+ }
409
+ var expr = Expression.parse(expression, element);
410
+ (expr && expr.dependencies).forEach(d => {
411
+ switch (mode) {
412
+ case 'twoway':
413
+ d.mode = (d.twowayAllowed && expr.dependencies.length == 1) ? 'twoway' : undefined;
414
+ break;
415
+ case 'once':
416
+ d.mode = mode;
417
+ break;
418
+ }
419
+ });
420
+ return expr;
421
+ }
422
+ static ensureMember(o, name, attributes) {
423
+ let original = Object.getOwnPropertyDescriptor(o, name);
424
+ if (original != undefined)
425
+ return original;
426
+ Object.defineProperty(o, name, attributes);
427
+ return Object.getOwnPropertyDescriptor(o, name);
428
+ }
429
+ /**
430
+ * Strips all the observed attributes of an element and its descendants, in order to seal that dom branch and to avoid bindings evaluation.
431
+ * @param element Input element
432
+ */
433
+ static stripObservedAttributes(element) {
434
+ avoidObservedAttributes(element, false);
435
+ }
436
+ /**
437
+ * Freezes all the observed attributes of an element and its descendants, in order to seal that dom branch and to avoid bindings evaluation.
438
+ * @param element Input element
439
+ */
440
+ static freezeObservedAttributes(element) {
441
+ avoidObservedAttributes(element);
442
+ }
443
+ }
444
+ function avoidObservedAttributes(element, freeze = true) {
445
+ const walker = document.createTreeWalker(element, NodeFilter.SHOW_ELEMENT);
446
+ do {
447
+ var node = walker.currentNode;
448
+ if (node instanceof HTMLElement) {
449
+ const attrs = node.constructor['observedAttributes'];
450
+ if (!Utils.isNull(attrs)) {
451
+ CustomElementUtils.deleteAttachedPropertyValue(node, INSTANCE_BINDINGS_VAR);
452
+ let revertFn = function (v) {
453
+ if (Utils.isArray(v)) {
454
+ return '[' + v.map(revertFn).join(',') + ']';
455
+ }
456
+ if (v instanceof Element) {
457
+ const vid = v.id = v.id || ('_' + Utils.uniqueCode());
458
+ return `#${vid}`;
459
+ }
460
+ else {
461
+ return `${Utils.Json.stringify(v)}`;
462
+ }
463
+ };
464
+ for (var attr of attrs) {
465
+ if (attr in node.attributes) {
466
+ let prop;
467
+ let val;
468
+ if (freeze && !Utils.isNull(val = node[prop = CustomElementUtils.kebabToCamel(attr)])) {
469
+ let reverted = revertFn(val);
470
+ node.setAttribute(attr, `{{ ${reverted} }}`);
471
+ }
472
+ else
473
+ node.removeAttribute(attr);
474
+ }
475
+ }
476
+ }
477
+ }
478
+ } while (walker.nextNode());
479
+ }
480
+ const GET_VAL = CustomElementUtils.getAttachedPropertyValue;
481
+ const SET_VAL = CustomElementUtils.setAttachedPropertyValue;
482
+ const REPEATERITEM_PLACEHOLDER = 'pacem:repeater-item';
483
+ export class Repeater {
484
+ /**
485
+ * Seeks for a PacemRepeaterItem element upwards through the DOM tree, given a starting element and the number of nesting levels.
486
+ * @param element {HTMLElement} Element to start the upward search from
487
+ * @param Optional upLevels {Number} 0-based nesting level
488
+ */
489
+ static findItemContext(element, upLevels = 0, logFn = console.warn) {
490
+ let retval = RepeaterItem.findUpwards(element, upLevels, logFn);
491
+ if (retval == null && logFn && element instanceof HTMLElement && element['isConnected']) {
492
+ logFn(`Couldn't find a ${RepeaterItem.name} up ${upLevels} level${((upLevels === 1) ? "" : "s")} from element "${element.constructor.name}".`);
493
+ }
494
+ return retval;
495
+ }
496
+ }
497
+ export class RepeaterItem {
498
+ static findUpwards(element, upLevels = 0, logFn = console.warn) {
499
+ if (Utils.isNull(element) || element.localName === 'template' || element instanceof /* template-like element? */ TemplateElement) {
500
+ return null;
501
+ }
502
+ let item = null;
503
+ let predicate = (node) => !Utils.isNull(item = RepeaterItem.getRepeaterItem(node));
504
+ let retval = CustomElementUtils.findPreviousSiblingOrAncestor(element, predicate, upLevels);
505
+ if (retval == null && logFn && element instanceof HTMLElement && element['isConnected']) {
506
+ logFn(`Couldn't find a ${RepeaterItem.name} up ${upLevels} level${((upLevels === 1) ? "" : "s")} from element "${element.constructor.name}".`);
507
+ }
508
+ return item;
509
+ }
510
+ static isRepeaterItem(node) {
511
+ return !Utils.isNull(GET_VAL(node, REPEATERITEM_PLACEHOLDER));
512
+ }
513
+ static getRepeaterItem(node) {
514
+ return GET_VAL(node, REPEATERITEM_PLACEHOLDER);
515
+ }
516
+ constructor(_placeholder) {
517
+ this._placeholder = _placeholder;
518
+ SET_VAL(_placeholder, REPEATERITEM_PLACEHOLDER, this);
519
+ }
520
+ get placeholder() {
521
+ return this._placeholder;
522
+ }
523
+ }
524
+ // }
@@ -0,0 +1,60 @@
1
+ import { Utils } from './utils';
2
+ export var EventKeyModifier;
3
+ (function (EventKeyModifier) {
4
+ EventKeyModifier["AltKey"] = "Alt";
5
+ EventKeyModifier["CtrlKey"] = "Ctrl";
6
+ EventKeyModifier["ShiftKey"] = "Shift";
7
+ EventKeyModifier["MetaKey"] = "Cmd";
8
+ })(EventKeyModifier || (EventKeyModifier = {}));
9
+ export class CustomEventUtils {
10
+ static isInstanceOf(evt, type) {
11
+ return evt instanceof type;
12
+ // || CustomElementUtils.getAttachedPropertyValue(evt, 'pacem:custom-event') === evt.type;
13
+ }
14
+ static getEventCoordinates(evt) {
15
+ var src;
16
+ if ('touches' in evt) {
17
+ if (!Utils.isNullOrEmpty(evt.touches)) {
18
+ src = evt.touches[0];
19
+ }
20
+ else if (!Utils.isNullOrEmpty(evt.changedTouches)) {
21
+ src = evt.changedTouches[0];
22
+ }
23
+ }
24
+ else {
25
+ src = evt;
26
+ }
27
+ return {
28
+ page: { x: src.pageX, y: src.pageY },
29
+ screen: { x: src.screenX, y: src.screenY },
30
+ client: { x: src.clientX, y: src.clientY }
31
+ };
32
+ }
33
+ static getEventKeyModifiers(evt) {
34
+ var which = evt.which;
35
+ if (evt instanceof MouseEvent) {
36
+ which = evt.button;
37
+ }
38
+ return {
39
+ which: which, shiftKey: evt.shiftKey, altKey: evt.altKey, ctrlKey: evt.ctrlKey, metaKey: evt.metaKey
40
+ };
41
+ }
42
+ static matchModifiers(evt, ...args) {
43
+ const modifiers = !Utils.isNull(args) && (args.length === 1 && Utils.isArray(args[0]) ? args[0] : Array.from(args).filter(i => !Utils.isNullOrEmpty(i))), lowerCaseModifiers = (modifiers || []).map(i => i.toLowerCase());
44
+ const altKey = lowerCaseModifiers.indexOf('alt') >= 0 || lowerCaseModifiers.indexOf('option') >= 0, shiftKey = lowerCaseModifiers.indexOf('shift') >= 0, ctrlKey = lowerCaseModifiers.indexOf('ctrl') >= 0, metaKey = lowerCaseModifiers.indexOf('win') >= 0 || lowerCaseModifiers.indexOf('cmd') >= 0;
45
+ if (altKey !== evt.altKey
46
+ || shiftKey !== evt.shiftKey
47
+ || metaKey !== evt.metaKey
48
+ || ctrlKey !== evt.ctrlKey) {
49
+ return false;
50
+ }
51
+ return true;
52
+ }
53
+ static fixEdgeCustomEventSubClassInstance(evt, type) {
54
+ // this an optimistic BUGGED workaround due to a damn' Edge bug: https://github.com/Microsoft/ChakraCore/issues/3952
55
+ if (!(evt instanceof type)) {
56
+ Object.setPrototypeOf(evt, type);
57
+ }
58
+ }
59
+ }
60
+ //}