@pacem/pacem 1.0.0-bessel → 1.0.0-dirac

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 (66) hide show
  1. package/dist/browser/pacem-2d.js +149 -2
  2. package/dist/browser/pacem-2d.js.map +1 -1
  3. package/dist/browser/pacem-2d.min.js +1 -1
  4. package/dist/browser/pacem-3d.js +646 -2
  5. package/dist/browser/pacem-3d.js.map +1 -1
  6. package/dist/browser/pacem-3d.min.js +1 -1
  7. package/dist/browser/pacem-charts.js +21 -1
  8. package/dist/browser/pacem-charts.js.map +1 -1
  9. package/dist/browser/pacem-charts.min.js +1 -1
  10. package/dist/browser/pacem-cms.js +118 -3
  11. package/dist/browser/pacem-cms.js.map +1 -1
  12. package/dist/browser/pacem-cms.min.js +1 -1
  13. package/dist/browser/pacem-core.js +870 -9
  14. package/dist/browser/pacem-core.js.map +1 -1
  15. package/dist/browser/pacem-core.min.js +2 -2
  16. package/dist/browser/pacem-foundation.js +296 -1
  17. package/dist/browser/pacem-foundation.js.map +1 -1
  18. package/dist/browser/pacem-foundation.min.js +1 -1
  19. package/dist/browser/pacem-fx.js +18 -1
  20. package/dist/browser/pacem-fx.js.map +1 -1
  21. package/dist/browser/pacem-fx.min.js +1 -1
  22. package/dist/browser/pacem-logging.js +15 -1
  23. package/dist/browser/pacem-logging.js.map +1 -1
  24. package/dist/browser/pacem-logging.min.js +1 -1
  25. package/dist/browser/pacem-maps.js +97 -1
  26. package/dist/browser/pacem-maps.js.map +1 -1
  27. package/dist/browser/pacem-maps.min.js +1 -1
  28. package/dist/browser/pacem-media.js +14 -1
  29. package/dist/browser/pacem-media.js.map +1 -1
  30. package/dist/browser/pacem-media.min.js +1 -1
  31. package/dist/browser/pacem-networking.js +22 -1
  32. package/dist/browser/pacem-networking.js.map +1 -1
  33. package/dist/browser/pacem-networking.min.js +1 -1
  34. package/dist/browser/pacem-numerical.js +360 -1
  35. package/dist/browser/pacem-numerical.js.map +1 -1
  36. package/dist/browser/pacem-numerical.min.js +1 -1
  37. package/dist/browser/pacem-plus.js +195 -4
  38. package/dist/browser/pacem-plus.js.map +1 -1
  39. package/dist/browser/pacem-plus.min.js +1 -1
  40. package/dist/browser/pacem-scaffolding.js +420 -38
  41. package/dist/browser/pacem-scaffolding.js.map +1 -1
  42. package/dist/browser/pacem-scaffolding.min.js +2 -2
  43. package/dist/browser/pacem-ui.js +143 -19
  44. package/dist/browser/pacem-ui.js.map +1 -1
  45. package/dist/browser/pacem-ui.min.js +2 -2
  46. package/dist/bundle/pacem.min.mjs +147 -147
  47. package/dist/bundle/pacem.mjs +2905 -1417
  48. package/dist/bundle/pacem.mjs.map +3 -3
  49. package/dist/docs/pacem-2d.json +11549 -0
  50. package/dist/docs/pacem-3d.json +29096 -0
  51. package/dist/docs/pacem-charts.json +4244 -0
  52. package/dist/docs/pacem-cms.json +9325 -0
  53. package/dist/docs/pacem-core.json +40109 -0
  54. package/dist/docs/pacem-foundation.json +8941 -0
  55. package/dist/docs/pacem-fx.json +3121 -0
  56. package/dist/docs/pacem-logging.json +941 -0
  57. package/dist/docs/pacem-maps.json +17387 -0
  58. package/dist/docs/pacem-media.json +1203 -0
  59. package/dist/docs/pacem-networking.json +1798 -0
  60. package/dist/docs/pacem-numerical.json +13706 -0
  61. package/dist/docs/pacem-plus.json +8468 -0
  62. package/dist/docs/pacem-scaffolding.json +34788 -0
  63. package/dist/docs/pacem-ui.json +18628 -0
  64. package/dist/typings/index.d.ts +4109 -31
  65. package/dist/vscode.html-custom.json +1303 -741
  66. package/package.json +4 -2
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * @pacem/pacem v1.0.0-bessel (https://js.pacem.it)
2
+ * @pacem/pacem v1.0.0-dirac (https://js.pacem.it)
3
3
  * Pacem (https://pacem.it)
4
4
  * Licensed under Apache-2.0
5
5
  */
@@ -24,22 +24,39 @@
24
24
  output['css'] = css;
25
25
  return output;
26
26
  }
27
+ /**
28
+ * Collection of ready-made {@link Easing} functions, each paired with its CSS timing-function equivalent.
29
+ */
27
30
  const Easings = {
31
+ /** No easing: progress is proportional to elapsed time. */
28
32
  linear: assembleEasing(EASINGS.linear, "linear"),
33
+ /** Sine ease-in: starts slow, accelerates towards the end. */
29
34
  sineIn: assembleEasing(EASINGS.sineIn, 'cubic-bezier(0.12, 0, 0.39, 0)'),
35
+ /** Sine ease-out: starts fast, decelerates towards the end. */
30
36
  sineOut: assembleEasing(EASINGS.sineOut, 'cubic-bezier(0.61, 1, 0.88, 1)'),
37
+ /** Sine ease-in-out: accelerates then decelerates, symmetric around the midpoint. */
31
38
  sineInOut: assembleEasing(EASINGS.sineInOut, 'cubic-bezier(0.37, 0, 0.63, 1)'),
32
39
  // TODO: set correct pairing
40
+ /** Exponential ease-in: starts very slow, accelerates sharply towards the end. */
33
41
  expoIn: assembleEasing(EASINGS.expoIn, 'cubic-bezier(0.7, 0, 0.84, 0)'),
42
+ /** Exponential ease-out: starts very fast, decelerates sharply towards the end. */
34
43
  expoOut: assembleEasing(EASINGS.expoOut, 'cubic-bezier(0.16, 1, 0.3, 1)'),
44
+ /** Exponential ease-in-out: sharp acceleration then sharp deceleration, symmetric around the midpoint. */
35
45
  expoInOut: assembleEasing(EASINGS.expoInOut, 'cubic-bezier(0.87, 0, 0.13, 1)'),
36
46
  };
37
47
  //}
38
48
 
39
49
  // namespace Pacem {
50
+ /**
51
+ * Recursively clones plain objects, arrays, `Date`s and `RegExp`s, preserving reference cycles/shared
52
+ * references within a single `clone` call (via an internal `WeakMap`). DOM `Element`s, `FileSystemHandle`s
53
+ * and `File`s are returned as-is (not cloned) - they aren't meaningfully deep-cloneable and are typically
54
+ * meant to be referenced, not duplicated.
55
+ */
40
56
  class DeepCloner {
41
57
  constructor() {
42
58
  }
59
+ /** Deep-clones `obj`; see {@link DeepCloner} for what gets cloned vs. passed through by reference. */
43
60
  static clone(obj) {
44
61
  return new DeepCloner()._clone(obj);
45
62
  }
@@ -110,13 +127,27 @@
110
127
  this._jsonFnWeakMap.delete(fn);
111
128
  }
112
129
  }
130
+ /**
131
+ * A `JSON.stringify`/`JSON.parse` superset able to round-trip values plain JSON can't represent: circular/
132
+ * shared object references (`$#ref_N` markers), `RegExp` instances, DOM `Element`s (serialized by `id`
133
+ * and revived via `document.getElementById`, so they must have one), and - depending on
134
+ * {@link JsonSerializationOptions.functions} - functions themselves. The source object is deep-cloned
135
+ * first (via {@link DeepCloner}) so serialization never mutates the input.
136
+ */
113
137
  class Json {
114
138
  constructor(_options) {
115
139
  this._options = _options;
116
140
  }
141
+ /**
142
+ * Serializes `obj` to a JSON string, extended to support circular/shared references, `RegExp`s,
143
+ * `Element`s (by `id`) and, per `options`, functions.
144
+ * @param obj Value to serialize.
145
+ * @param options Controls how function-valued properties are handled.
146
+ */
117
147
  static serialize(obj, options) {
118
148
  return new Json(options)._serialize(obj);
119
149
  }
150
+ /** Deserializes a string produced by {@link serialize}, restoring references, `RegExp`s, `Element`s and functions. */
120
151
  static deserialize(json) {
121
152
  return new Json()._deserialize(json);
122
153
  }
@@ -240,6 +271,12 @@
240
271
  //}
241
272
 
242
273
  //namespace Pacem {
274
+ /**
275
+ * A `PromiseLike<T>` whose resolution is externalized: unlike a plain `Promise`, the executor isn't
276
+ * passed a callback up front - instead, `resolve`/`reject` are exposed for the caller to invoke later,
277
+ * via the {@link defer} static factory. Useful when the completion of an operation is driven by code
278
+ * that doesn't naturally live inside a `Promise` executor (e.g. event callbacks, decorator plumbing).
279
+ */
243
280
  class DeferPromise {
244
281
  constructor() {
245
282
  this.deferred = null;
@@ -248,6 +285,7 @@
248
285
  me.deferred = { 'resolve': resolve, 'reject': reject, 'promise': me };
249
286
  });
250
287
  }
288
+ /** Standard `PromiseLike.then`, delegating to the underlying native `Promise`. */
251
289
  then(onCompleted, onFailed) {
252
290
  return this.promise.then(onCompleted, onFailed);
253
291
  }
@@ -259,14 +297,17 @@
259
297
  this.promise.then(callback, callback);
260
298
  return this;
261
299
  }
300
+ /** Registers a fulfillment-only callback (fluent, chainable alternative to `then(callback)`). */
262
301
  success(callback) {
263
302
  this.promise.then(callback, null);
264
303
  return this;
265
304
  }
305
+ /** Registers a rejection-only callback (fluent, chainable alternative to `then(null, callback)`). */
266
306
  error(callback) {
267
307
  this.promise.then(null, callback);
268
308
  return this;
269
309
  }
310
+ /** Creates a new deferred promise and returns its controller: `{ resolve, reject, promise }`. */
270
311
  static defer() {
271
312
  var q = new DeferPromise();
272
313
  return q.deferred;
@@ -277,40 +318,56 @@
277
318
  // namespace Pacem {
278
319
  const PACEM_CORE_DEFAULT = 'pacem';
279
320
  const DEFAULT_DOWNLOAD_FILENAME = 'download';
321
+ /** Ready-to-use event listener that only calls `evt.stopPropagation()`; handy as an `addEventListener` callback without allocating a closure. */
280
322
  const stopPropagationHandler = (evt) => {
281
323
  evt.stopPropagation();
282
324
  };
325
+ /** Ready-to-use event listener that only calls `evt.preventDefault()`; handy as an `addEventListener` callback without allocating a closure. */
283
326
  const preventDefaultHandler = (evt) => {
284
327
  evt.preventDefault();
285
328
  };
329
+ /** Ready-to-use event listener that calls both `evt.preventDefault()` and `evt.stopPropagation()`. */
286
330
  const avoidHandler = (evt) => {
287
331
  evt.preventDefault();
288
332
  evt.stopPropagation();
289
333
  };
290
334
  const SEGMENT_PATTERN = /^\/[^\/]+/;
291
335
  const ROUTE_SEGMENT_PATTERN = /\/\{([a-z\$_][\w]*)\??\}/;
336
+ /**
337
+ * The framework's static utility grab-bag: general helpers plus namespaced sub-modules (`Json`, `Dates`,
338
+ * `Css`, `Strings`, `Blobs`, `Images`, `Browsers`, `Cookies`, `URIs`) re-exposing (and in some cases
339
+ * extending) functionality from `@pacem/pacem-foundation`. Also the home of `Utils.core`, the global
340
+ * registry object used for cross-cutting framework state (e.g. registered {@link Transformer}s).
341
+ */
292
342
  class Utils {
343
+ /** The framework's global scratch/registry object (`window[id]`, where `id` defaults to `'pacem'` and is configurable via `window.Pacem.Configuration.core`); created on first access. Used e.g. to store {@link Transformer}-registered transform functions. */
293
344
  static get core() {
294
345
  const root = window['Pacem'];
295
346
  var id = (root && root.Configuration && root.Configuration.core) || PACEM_CORE_DEFAULT;
296
347
  return window[id] = window[id] || {};
297
348
  }
349
+ /** The platform's (native or polyfilled) `customElements` registry. */
298
350
  static get customElements() {
299
351
  return window['customElements'];
300
352
  }
301
353
  // #region GENERAL
354
+ /** Generates a unique numeric-ish id string. */
302
355
  static uniqueId() {
303
356
  return pacemFoundation.Keys.uniqueId();
304
357
  }
358
+ /** Generates a unique short code string. */
305
359
  static uniqueCode() {
306
360
  return pacemFoundation.Keys.uniqueCode();
307
361
  }
362
+ /** Generates a random string of the given `length`. */
308
363
  static randomString(length) {
309
364
  return pacemFoundation.Keys.randomString(length);
310
365
  }
366
+ /** Parses a date-like value (ISO string, `Date`, or timestamp) into a `Date`. */
311
367
  static parseDate(input) {
312
368
  return pacemFoundation.Dates.parse(input);
313
369
  }
370
+ /** Writes `input` to the system clipboard, using the async Clipboard API when available and falling back to `document.execCommand('copy')` otherwise. */
314
371
  static copyToClipboard(input) {
315
372
  if (navigator.clipboard) {
316
373
  return navigator.clipboard.writeText(input);
@@ -378,6 +435,7 @@
378
435
  return filter;
379
436
  }
380
437
  }
438
+ /** Escapes `input` for safe use as a CSS identifier/selector fragment. */
381
439
  static cssEscape(input) {
382
440
  return escape(input).replace('%', '\\');
383
441
  }
@@ -385,9 +443,11 @@
385
443
  static { this.Css = {
386
444
  colorize: Utils.colorize,
387
445
  escape: Utils.cssEscape,
446
+ /** Reads a CSS custom property's current value off the document root (`:root`/`html`). */
388
447
  getVariableValue(name) {
389
448
  return getComputedStyle(document.documentElement).getPropertyValue(name);
390
449
  },
450
+ /** Sets a CSS custom property's value on the document root (`:root`/`html`). */
391
451
  setVariable(name, value) {
392
452
  getComputedStyle(document.documentElement).setProperty(name, value);
393
453
  },
@@ -417,6 +477,7 @@
417
477
  }
418
478
  return false;
419
479
  },
480
+ /** Parses an element's (or style declaration's) computed `transform: matrix(...)` CSS value into its 2D affine matrix components; identity if unset. */
420
481
  deserializeTransform(element) {
421
482
  const style = element instanceof Element ? getComputedStyle(element) : element;
422
483
  let a = 1, b = 0, c = 0, d = 1, x = 0, y = 0, matches = /^matrix\((.*)\)$/.exec(style.transform), mij;
@@ -443,6 +504,7 @@
443
504
  leftPad: pacemFoundation.Strings.leftPad,
444
505
  format: pacemFoundation.Strings.format,
445
506
  diff: pacemFoundation.Strings.diff,
507
+ /** Strips HTML markup from `html`, returning its plain-text content. */
446
508
  stripHTML: (html) => {
447
509
  let doc = new DOMParser().parseFromString(html, 'text/html');
448
510
  return doc.body.textContent || '';
@@ -461,6 +523,7 @@
461
523
  load: pacemFoundation.Imaging.loadImage,
462
524
  resize: pacemFoundation.Imaging.resizeImage
463
525
  }; }
526
+ /** Loads an image from `src` and resolves with the `HTMLImageElement` once ready (or rejects on error). */
464
527
  static loadImage(src) {
465
528
  return new Promise((resolve, reject) => {
466
529
  const img = new Image();
@@ -478,15 +541,19 @@
478
541
  }
479
542
  });
480
543
  }
544
+ /** Converts a `Blob` to a `data:` URL string. */
481
545
  static blobToDataURL(blob) {
482
546
  return Utils.Blobs.toDataURL(blob);
483
547
  }
548
+ /** Converts a `data:` URL string back into a `Blob`. */
484
549
  static dataURLToBlob(dataURL) {
485
550
  return Utils.Blobs.fromDataURL(dataURL);
486
551
  }
552
+ /** Reads a `Blob`'s content as text, using the given `encoding` (default UTF-8). */
487
553
  static blobToText(blob, encoding) {
488
554
  return Utils.Blobs.toText(blob, encoding);
489
555
  }
556
+ /** Wraps `content` in a `Blob` of the given MIME `type` (default `'text/plain'`). */
490
557
  static textToBlob(content, type = 'text/plain') {
491
558
  return Utils.Blobs.fromText(content, type);
492
559
  }
@@ -572,6 +639,7 @@
572
639
  el.src = url;
573
640
  return deferred.promise;
574
641
  }
642
+ /** Returns the list of vendor-prefixed `getUserMedia` implementations available on `navigator`, if any. */
575
643
  static getUserMediaFunctions() {
576
644
  var _getUserMedia = [];
577
645
  let methods = [navigator['getUserMedia'], navigator['webkitGetUserMedia'], navigator['msGetUserMedia'], navigator['mozGetUserMedia']];
@@ -818,10 +886,12 @@
818
886
  }
819
887
  // #endregion
820
888
  // #region DOM
889
+ /** Whether the document (including module scripts) has fully finished loading (`document.readyState === 'complete'`). */
821
890
  static isDOMReady() {
822
891
  // Must exclude 'interactive' state since module script haven't been processed yet.
823
892
  return /* document.readyState === 'interactive' ||*/ document.readyState === 'complete';
824
893
  }
894
+ /** Registers `listener` to run once the document (and its resources, e.g. images) has fully loaded (the `window` `'load'` event). */
825
895
  static onDOMReady(listener) {
826
896
  //window.addEventListener('DOMContentLoaded', listener, false);
827
897
  // window 'load' event fires after 'DOMCOntentLoaded' since includes images load.
@@ -850,13 +920,16 @@
850
920
  }
851
921
  return dom;
852
922
  }
923
+ /** Cross-browser `Element.matches(selector)`, falling back to vendor-prefixed variants. */
853
924
  static is(el, selector) {
854
925
  return (el.matches || el.matchesSelector || el.msMatchesSelector || el.mozMatchesSelector || el.webkitMatchesSelector || el.oMatchesSelector)
855
926
  .call(el, selector);
856
927
  }
928
+ /** Resolves the effective language for `el`: its own `lang` attribute, else the document's, else the browser's. */
857
929
  static lang(el) {
858
930
  return el.lang || document.documentElement.lang || navigator.language;
859
931
  }
932
+ /** JSON-stringifies `obj` (via {@link Json}), or passes through `null`/`undefined` unchanged. */
860
933
  static jsonSortStringify(obj) {
861
934
  if (Utils.isNull(obj)) {
862
935
  return obj;
@@ -866,6 +939,7 @@
866
939
  static { this.Browsers = {
867
940
  detect: pacemFoundation.detect
868
941
  }; }
942
+ /** Parses a `document.cookie`-style string (or `document.cookie` itself, by default) into a name/value map. */
869
943
  static cookies(cookie) {
870
944
  const cookies = (cookie ?? document.cookie).split(';'), retval = {};
871
945
  for (var pair of cookies) {
@@ -881,7 +955,9 @@
881
955
  }
882
956
  return retval;
883
957
  }
958
+ /** Cookie helpers, preferring the native `cookieStore` API when available and falling back to `document.cookie` parsing otherwise. */
884
959
  static { this.Cookies = {
960
+ /** Retrieves all cookies (or just `cookieName`, if given) as {@link CookieData} entries. */
885
961
  getAll: async (cookieName) => {
886
962
  const store = 'cookieStore' in window ? window.cookieStore : null;
887
963
  const retval = [];
@@ -899,6 +975,7 @@
899
975
  return await store.getAll(cookieName);
900
976
  }
901
977
  },
978
+ /** Serializes a {@link CookieData} descriptor into a `document.cookie`-assignable string (including `domain`/`path`/`max-age`/`expires`/`Partitioned`/`SameSite`/`Secure` attributes, as provided). */
902
979
  stringify: (data) => {
903
980
  let retval = `${data.name}=${encodeURIComponent(data.value ?? '')}`;
904
981
  if (!Utils.isNullOrEmpty(data.domain)) {
@@ -925,6 +1002,7 @@
925
1002
  return retval;
926
1003
  }
927
1004
  }; }
1005
+ /** Tests whether `el` is currently visible (via the `checkVisibility` API when available, falling back to a CSS-visibility/size heuristic). */
928
1006
  static isVisible(el) {
929
1007
  if ('checkVisibility' in el) {
930
1008
  return el.checkVisibility({ checkOpacity: true, checkVisibilityCSS: true });
@@ -932,6 +1010,7 @@
932
1010
  return getComputedStyle(el).visibility !== 'hidden' && (el.clientWidth > 0 || el.clientHeight > 0);
933
1011
  }
934
1012
  //#region classList DOMTokenList (css)
1013
+ /** Tests whether `el` has `className` set, using `classList` when available (with a regex-based fallback). */
935
1014
  static hasClass(el, className) {
936
1015
  if (el.classList) {
937
1016
  return el.classList.contains(className);
@@ -940,6 +1019,7 @@
940
1019
  return new RegExp('(^| )' + className + '( |$)', 'gi').test(el.className);
941
1020
  }
942
1021
  }
1022
+ /** Adds one or more (space-separated) classes to `el`, using `classList` when available. */
943
1023
  static addClass(el, className) {
944
1024
  const css = className.trim();
945
1025
  if (el.classList) {
@@ -949,6 +1029,7 @@
949
1029
  el.setAttribute('class', el.className + ' ' + css);
950
1030
  }
951
1031
  }
1032
+ /** Removes one or more (space-separated) classes from `el`, using `classList` when available. */
952
1033
  static removeClass(el, className) {
953
1034
  const css = className.trim();
954
1035
  if (el.classList) {
@@ -958,6 +1039,7 @@
958
1039
  el.setAttribute('class', el.className.replace(new RegExp('(^|\\b)' + css.split(' ').join('|') + '(\\b|$)', 'gi'), ' '));
959
1040
  }
960
1041
  }
1042
+ /** Adds or removes `className` on `el` depending on `on`; see {@link addClass}/{@link removeClass}. */
961
1043
  static toggleClass(el, className, on) {
962
1044
  if (on) {
963
1045
  Utils.addClass(el, className);
@@ -968,15 +1050,19 @@
968
1050
  }
969
1051
  //#endregion
970
1052
  //#region part DOMTokenList (shadow-DOM)
1053
+ /** Tests whether `el`'s `part` attribute (CSS Shadow Parts) contains `partName`. */
971
1054
  static hasPart(el, partName) {
972
1055
  return el.part.contains(partName);
973
1056
  }
1057
+ /** Adds one or more (space-separated) shadow-part names to `el`'s `part` attribute. */
974
1058
  static addPart(el, partName) {
975
1059
  DOMTokenList.prototype.add.apply(el.part, partName.trim().split(' '));
976
1060
  }
1061
+ /** Removes one or more (space-separated) shadow-part names from `el`'s `part` attribute. */
977
1062
  static removePart(el, partName) {
978
1063
  DOMTokenList.prototype.remove.apply(el.part, partName.trim().split(' '));
979
1064
  }
1065
+ /** Adds or removes `partName` on `el`'s `part` attribute depending on `on`; see {@link addPart}/{@link removePart}. */
980
1066
  static togglePart(el, partName, on) {
981
1067
  if (on) {
982
1068
  Utils.addPart(el, partName);
@@ -1012,9 +1098,11 @@
1012
1098
  height: rect.height
1013
1099
  };
1014
1100
  }
1101
+ /** Sums `offsetTop` up the `offsetParent` chain, giving `el`'s vertical position relative to the document rather than just its nearest positioned ancestor. */
1015
1102
  static naturalOffsetTop(el) {
1016
1103
  return (el?.offsetTop ?? 0) + ((el?.offsetParent && el.offsetParent instanceof HTMLElement) ? this.naturalOffsetTop(el.offsetParent) : 0);
1017
1104
  }
1105
+ /** Sums `offsetTop` up the `offsetParent` chain (note: mirrors {@link naturalOffsetTop}'s calculation, not `offsetLeft`), giving `el`'s horizontal position relative to the document. */
1018
1106
  static naturalOffsetLeft(el) {
1019
1107
  return (el?.offsetTop ?? 0) + ((el?.offsetParent && el.offsetParent instanceof HTMLElement) ? this.naturalOffsetLeft(el.offsetParent) : 0);
1020
1108
  }
@@ -1042,9 +1130,11 @@
1042
1130
  static deserializeTransform(obj) {
1043
1131
  return Utils.Css.deserializeTransform(obj);
1044
1132
  }
1133
+ /** Sets the window's vertical scroll position, keeping the current horizontal position. */
1045
1134
  static set scrollTop(y) {
1046
1135
  window.scrollTo(Utils.scrollLeft, y);
1047
1136
  }
1137
+ /** Sets the window's horizontal scroll position, keeping the current vertical position. */
1048
1138
  static set scrollLeft(x) {
1049
1139
  window.scrollTo(x, Utils.scrollTop);
1050
1140
  }
@@ -1055,12 +1145,15 @@
1055
1145
  const behavior = (yFirst ? y : smooth) ? 'smooth' : 'instant';
1056
1146
  window.scrollTo({ behavior, left, top });
1057
1147
  }
1148
+ /** The window's current vertical scroll position, with fallbacks for older browsers. */
1058
1149
  static get scrollTop() {
1059
1150
  return window.scrollY /*window.pageYOffset*/ || document.documentElement.scrollTop || document.body.scrollTop || 0;
1060
1151
  }
1152
+ /** The window's current horizontal scroll position, with fallbacks for older browsers. */
1061
1153
  static get scrollLeft() {
1062
1154
  return window.scrollX /*window.pageXOffset*/ || document.documentElement.scrollLeft || document.body.scrollLeft || 0;
1063
1155
  }
1156
+ /** The window's current viewport size (`{ width, height }`), with fallbacks for older browsers. */
1064
1157
  static get windowSize() {
1065
1158
  let win = window;
1066
1159
  return {
@@ -1136,16 +1229,20 @@
1136
1229
  }
1137
1230
  // #endregion
1138
1231
  // #region other
1232
+ /** Tests whether `obj` is "empty" (per {@link NullChecker.isEmpty}: `null`/`undefined`/`''`/an empty array or object), excluding DOM `Node`s (which are never considered empty here). */
1139
1233
  static isEmpty(obj) {
1140
1234
  return pacemFoundation.NullChecker.isEmpty(obj) && !(obj instanceof Node);
1141
1235
  }
1236
+ /** Type-guarding test for `obj` being `null` or `undefined`. */
1142
1237
  static isNull(obj) {
1143
1238
  return pacemFoundation.NullChecker.isNull(obj);
1144
1239
  }
1145
1240
  // legacy
1241
+ /** Type-guarding test for `val` being an array. */
1146
1242
  static isArray(val) {
1147
1243
  return Array.isArray(val);
1148
1244
  }
1245
+ /** Tests whether `val` is `null`/`undefined` or "empty"; see {@link isNull}/{@link isEmpty}. */
1149
1246
  static isNullOrEmpty(val) {
1150
1247
  return Utils.isNull(val) || Utils.isEmpty(val);
1151
1248
  }
@@ -1164,6 +1261,7 @@
1164
1261
  }
1165
1262
  /** Legacy alias for Object.assign(). */
1166
1263
  static { this.extend = Object.assign; }
1264
+ /** Deep-clones `obj`; see {@link DeepCloner}. */
1167
1265
  static clone(obj) {
1168
1266
  if (obj === undefined)
1169
1267
  return undefined;
@@ -1173,6 +1271,7 @@
1173
1271
  static fromResult(v) {
1174
1272
  return Promise.resolve(v);
1175
1273
  }
1274
+ /** Runs `task` on the next animation frame and wraps its result in a `Promise`. */
1176
1275
  static fromResultAsync(task) {
1177
1276
  return new Promise(resolve => requestAnimationFrame(() => resolve(task())));
1178
1277
  }
@@ -1196,7 +1295,15 @@
1196
1295
  }
1197
1296
  //#endregion
1198
1297
  //#region Net
1298
+ /** URL/route parsing and formatting helpers, chiefly backing the router (`{segment}`/`{segment?}` template resolution, query-string parsing, route metadata). */
1199
1299
  static { this.URIs = {
1300
+ /**
1301
+ * Substitutes each `{name}`/`{name?}` template segment in `url` with the matching entry of `parameters`
1302
+ * (URL-encoded), then strips out any remaining unmatched *optional* segments.
1303
+ * @param url URL/route template containing `{name}`/`{name?}` segments.
1304
+ * @param parameters Values to substitute, keyed by segment name.
1305
+ * @param removeMatchedParameters When `true`, consumed entries are deleted from `parameters`.
1306
+ */
1200
1307
  format: function (url, parameters, removeMatchedParameters) {
1201
1308
  // replace segments
1202
1309
  for (let name in parameters || {}) {
@@ -1219,6 +1326,14 @@
1219
1326
  }
1220
1327
  return url;
1221
1328
  },
1329
+ /**
1330
+ * Appends `parameters` to `url`'s query string (or hash fragment, when `hash` is `true`), URL-encoding
1331
+ * names and values, and correctly choosing `?`/`&` (or `#`/`&`) as the joining separator.
1332
+ * @param url Base URL.
1333
+ * @param parameters Values to append, keyed by parameter name.
1334
+ * @param removeNullEntries When `true`, entries whose value is `null`/`undefined` are omitted instead of appended as empty.
1335
+ * @param hash When `true`, appends to the URL's hash fragment instead of its query string.
1336
+ */
1222
1337
  appendQuery: function (url, parameters, removeNullEntries = false, hash = false) {
1223
1338
  const char = hash ? '#' : '?', pattern = hash ? /#/ : /\?/;
1224
1339
  const query = (pattern.test(url) ? '&' : char) +
@@ -1227,6 +1342,7 @@
1227
1342
  .map(k => encodeURIComponent(k) + '=' + encodeURIComponent(parameters[k] ?? '')).join('&');
1228
1343
  return url + (query.length > 1 ? query : '');
1229
1344
  },
1345
+ /** Parses a query string (or a `Location`'s `.search`, defaulting to `window.location`) into a name/value map. */
1230
1346
  parseQuery: (query = window.location) => {
1231
1347
  if (typeof query !== 'string') {
1232
1348
  query = query.search;
@@ -1237,9 +1353,11 @@
1237
1353
  });
1238
1354
  return obj;
1239
1355
  },
1356
+ /** Tests whether `url` contains at least one non-optional `{name}` template segment (as opposed to only `{name?}` ones). */
1240
1357
  hasMandatoryTemplateSegments: function (url) {
1241
1358
  return /(^|\/)\{\.*\}(\/|$)/.test(url);
1242
1359
  },
1360
+ /** Parses a route template's `{name}`/`{name?}` segments into an ordered list of {@link RouteMetadata} descriptors, consumed by {@link parseState}. */
1243
1361
  parseRoute: function (pathTemplate) {
1244
1362
  let tmpl = pathTemplate;
1245
1363
  const trunks = [];
@@ -1259,6 +1377,7 @@
1259
1377
  }
1260
1378
  return trunks;
1261
1379
  },
1380
+ /** Splits `url` into its `protocol`, `domain`, `path`, `query` (including leading `?`) and `hash` (including leading `#`) parts, or `null` if it can't be parsed. */
1262
1381
  split: function (url) {
1263
1382
  const URL_PATTERN = /^((https?:)?\/\/[^\/]+)?([^\?#]+)(\?[^#]*)?(#[^#]*)?$/;
1264
1383
  const regArr = URL_PATTERN.exec(url);
@@ -1267,6 +1386,16 @@
1267
1386
  }
1268
1387
  return { domain: regArr[2] ?? '', protocol: regArr[1] ?? '', path: regArr[3] ?? '', query: regArr[4] ?? '', hash: regArr[5] ?? '' };
1269
1388
  },
1389
+ /**
1390
+ * Builds a {@link RouterState} for `url`, extracting named route segments per `metadata` (see
1391
+ * {@link parseRoute}) as top-level properties, alongside the standard `$path`/`$pathname`/`$querystring`/
1392
+ * `$query`/`$hash` keys. Throws if a non-optional route segment declared in `metadata` isn't present in `path`.
1393
+ * @param metadata Route segment descriptors, as produced by {@link parseRoute}.
1394
+ * @param url Full URL/path being navigated to.
1395
+ * @param path Path component override; parsed out of `url` via {@link split} when omitted.
1396
+ * @param query Query-string override (including leading `?`); parsed out of `url` when omitted.
1397
+ * @param hash Hash-fragment override (including leading `#`); parsed out of `url` when omitted.
1398
+ */
1270
1399
  parseState: function (metadata, url, path, query, hash) {
1271
1400
  let fullPath = url;
1272
1401
  if (Utils.isNullOrEmpty(path)) {
@@ -1351,6 +1480,7 @@
1351
1480
  }
1352
1481
  // }
1353
1482
 
1483
+ /** String tokens accepted by {@link CustomEventUtils.matchModifiers} to describe a keyboard/mouse modifier. */
1354
1484
  var EventKeyModifier;
1355
1485
  (function (EventKeyModifier) {
1356
1486
  EventKeyModifier["AltKey"] = "Alt";
@@ -1358,11 +1488,24 @@
1358
1488
  EventKeyModifier["ShiftKey"] = "Shift";
1359
1489
  EventKeyModifier["MetaKey"] = "Cmd";
1360
1490
  })(EventKeyModifier || (EventKeyModifier = {}));
1491
+ /** Static helpers for inspecting and normalizing native/custom events (coordinates, keyboard modifiers, type checks). */
1361
1492
  class CustomEventUtils {
1493
+ /**
1494
+ * Type-guarding check for whether `evt` is an instance of the given event `type`.
1495
+ * @param evt Event to test.
1496
+ * @param type Event constructor to test against.
1497
+ * @returns `true` (narrowing `evt` to `TEvent`) if `evt instanceof type`.
1498
+ */
1362
1499
  static isInstanceOf(evt, type) {
1363
1500
  return evt instanceof type;
1364
1501
  // || CustomElementUtils.getAttachedPropertyValue(evt, 'pacem:custom-event') === evt.type;
1365
1502
  }
1503
+ /**
1504
+ * Extracts page/client/screen coordinates from a mouse or (single-)touch event, using the first
1505
+ * active touch (`touches[0]`, falling back to `changedTouches[0]`) for `TouchEvent`s.
1506
+ * @param evt Source mouse/touch event, or an already-extracted {@link UIEventLike}.
1507
+ * @returns The event's position in all three coordinate systems.
1508
+ */
1366
1509
  static getEventCoordinates(evt) {
1367
1510
  var src;
1368
1511
  if ('touches' in evt) {
@@ -1382,6 +1525,11 @@
1382
1525
  client: { x: src.clientX, y: src.clientY }
1383
1526
  };
1384
1527
  }
1528
+ /**
1529
+ * Extracts the keyboard-modifier flags (and, for mouse events, the pressed button as `which`) from a native event.
1530
+ * @param evt Source keyboard/mouse/touch event, or an already-extracted {@link KeyEventLike}.
1531
+ * @returns The captured modifier flags.
1532
+ */
1385
1533
  static getEventKeyModifiers(evt) {
1386
1534
  var which = evt.which;
1387
1535
  if (evt instanceof MouseEvent) {
@@ -1402,6 +1550,13 @@
1402
1550
  }
1403
1551
  return true;
1404
1552
  }
1553
+ /**
1554
+ * Works around a legacy Edge/ChakraCore bug (see {@link https://github.com/Microsoft/ChakraCore/issues/3952})
1555
+ * where an instance built via `super(...)` from a `CustomEvent` subclass constructor doesn't correctly
1556
+ * pass `instanceof` checks against that subclass; forcibly resets its prototype when so.
1557
+ * @param evt Event instance to fix up.
1558
+ * @param type The subclass constructor `evt` is supposed to be an instance of.
1559
+ */
1405
1560
  static fixEdgeCustomEventSubClassInstance(evt, type) {
1406
1561
  // this an optimistic BUGGED workaround due to a damn' Edge bug: https://github.com/Microsoft/ChakraCore/issues/3952
1407
1562
  if (!(evt instanceof type)) {
@@ -1413,7 +1568,17 @@
1413
1568
 
1414
1569
  /// <reference path="utils-customevent.ts" />
1415
1570
  // namespace Pacem {
1571
+ /**
1572
+ * Base class for framework custom events whose `detail` payload is strongly typed as `TDetail`.
1573
+ * Thin wrapper around the native `CustomEvent<TDetail>` that also works around an old Edge bug
1574
+ * (see {@link CustomEventUtils.fixEdgeCustomEventSubClassInstance}) affecting `CustomEvent` subclasses.
1575
+ */
1416
1576
  class CustomTypedEvent extends CustomEvent /* new in TypeScript v2.7.1 -> */ {
1577
+ /**
1578
+ * @param type Event name.
1579
+ * @param detail Strongly-typed payload, exposed as `event.detail`.
1580
+ * @param eventInit Standard `CustomEvent` initialization options (`bubbles`, `cancelable`, `composed`).
1581
+ */
1417
1582
  constructor(type, detail, eventInit) {
1418
1583
  super(type, Utils.extend({ detail: detail }, eventInit || {}));
1419
1584
  CustomEventUtils.fixEdgeCustomEventSubClassInstance(this, this.constructor);
@@ -1432,7 +1597,20 @@
1432
1597
  return false;
1433
1598
  }
1434
1599
  // TODO: make inherit from CustomTypedEvent
1600
+ /**
1601
+ * Base class for UI-originated custom events: like {@link CustomTypedEvent}, but additionally captures
1602
+ * the mouse/touch/keyboard modifiers and coordinates of the originating native event (when supplied),
1603
+ * exposing them through the {@link UIEventLike} surface (`which`, `altKey`, `pageX`, `clientY`, ...).
1604
+ * Useful for events that are re-dispatched/synthesized (e.g. drag & drop) from an original pointer or
1605
+ * keyboard event, so that consumers can still inspect that original event's modifiers/position.
1606
+ */
1435
1607
  class CustomUIEvent extends CustomEvent {
1608
+ /**
1609
+ * @param type Event name.
1610
+ * @param detail Either the strongly-typed payload, or (when it satisfies `CustomEventInit`, i.e. has a `detail` key) the full event-init object.
1611
+ * @param eventInit Either standard `CustomEvent` init options, or the original native event this custom event derives from (in which case its coordinates/modifiers get captured).
1612
+ * @param orig The original native mouse/touch/keyboard event this custom event derives from, when `eventInit` is itself the init options.
1613
+ */
1436
1614
  constructor(type, detail, eventInit, orig) {
1437
1615
  super(type, Utils.extend((isEventInit(detail || {}) ? detail : { detail: detail }), (!(eventInit instanceof Event) && eventInit) || {}));
1438
1616
  const originalEvent = orig || eventInit;
@@ -1485,27 +1663,44 @@
1485
1663
  return this.#coords?.screen.y;
1486
1664
  }
1487
1665
  }
1666
+ /** Event name dispatched whenever an observed attribute changes; see {@link AttributeChangeEvent}. */
1488
1667
  const AttributeChangeEventName = 'attributechange';
1668
+ /**
1669
+ * Dispatched by elements registered with the {@link CustomElement} decorator whenever one of their
1670
+ * observed attributes changes, mirroring the native `attributeChangedCallback` as a DOM event.
1671
+ */
1489
1672
  class AttributeChangeEvent extends CustomTypedEvent {
1490
1673
  constructor(args) {
1491
1674
  super(AttributeChangeEventName, args);
1492
1675
  }
1493
1676
  }
1677
+ /** Event name dispatched whenever a `@Watch`-decorated property changes value; see {@link PropertyChangeEvent}. */
1494
1678
  const PropertyChangeEventName = 'propertychange';
1679
+ /**
1680
+ * Dispatched whenever a property decorated with {@link Watch} changes value (unless that decorator's
1681
+ * `emit` option is set to `false`). This is the mechanism data-bound expressions listen to in order to
1682
+ * re-evaluate themselves when one of their dependencies changes.
1683
+ */
1495
1684
  class PropertyChangeEvent extends CustomTypedEvent {
1496
1685
  constructor(args) {
1497
1686
  super(PropertyChangeEventName, args);
1498
1687
  }
1499
1688
  }
1500
1689
  // #region NAVIGATING
1690
+ /** Event name dispatched by a router *before* a navigation is committed; see {@link RouterNavigatingEvent}. Cancelable: calling `preventDefault()` aborts the navigation. */
1501
1691
  const RouterNavigatingEventName = 'navigating';
1692
+ /** Event name dispatched by a router *after* a navigation has been committed; see {@link RouterNavigateEvent}. */
1502
1693
  const RouterNavigateEventName = 'navigate';
1694
+ /** Dispatched by a router once it has navigated to a new `path` (not cancelable — the navigation already happened). */
1503
1695
  class RouterNavigateEvent extends CustomTypedEvent {
1696
+ /** @param path Either the destination path alone, or the full navigation args (path, title, referrer). */
1504
1697
  constructor(path) {
1505
1698
  super(RouterNavigateEventName, typeof path === 'string' ? { path } : path, { cancelable: false, bubbles: false });
1506
1699
  }
1507
1700
  }
1701
+ /** Dispatched by a router right before navigating to `path`; cancelable, so a listener can call `preventDefault()` to abort the navigation. */
1508
1702
  class RouterNavigatingEvent extends CustomTypedEvent {
1703
+ /** @param path Destination path about to be navigated to. */
1509
1704
  constructor(path) {
1510
1705
  super(RouterNavigatingEventName, path, { cancelable: true, bubbles: false });
1511
1706
  }
@@ -1513,16 +1708,25 @@
1513
1708
  // #endregion
1514
1709
  //}
1515
1710
 
1711
+ /**
1712
+ * `step` event dispatched on every animation frame of a running tween, carrying the current progress and value.
1713
+ */
1516
1714
  class AnimationEvent extends CustomTypedEvent {
1517
1715
  constructor(args) {
1518
1716
  super("step", args);
1519
1717
  }
1520
1718
  }
1719
+ /**
1720
+ * `end` event dispatched once a tween/animation completes.
1721
+ */
1521
1722
  class AnimationEndEvent extends CustomEvent {
1522
1723
  constructor() {
1523
1724
  super('end');
1524
1725
  }
1525
1726
  }
1727
+ /**
1728
+ * `start` event dispatched when a tween/animation begins.
1729
+ */
1526
1730
  class AnimationStartEvent extends CustomEvent {
1527
1731
  constructor() {
1528
1732
  super('start');
@@ -1531,7 +1735,20 @@
1531
1735
  //}
1532
1736
 
1533
1737
  //namespace Pacem.Animations {
1738
+ /**
1739
+ * Runs `requestAnimationFrame`-driven numeric tweens between two values, invoking a callback on each frame.
1740
+ */
1534
1741
  class TweenService {
1742
+ /**
1743
+ * Tweens a numeric value from `from` to `to` over `duration` milliseconds, invoking `callback` on every animation frame.
1744
+ * @param from Starting value.
1745
+ * @param to Ending value.
1746
+ * @param duration Tween duration, in milliseconds.
1747
+ * @param delay Delay before the tween starts, in milliseconds (default `0`).
1748
+ * @param easing Easing function applied to the normalized `[0,1]` time (defaults to {@link Easings.linear}).
1749
+ * @param callback Invoked on every frame (and once more with `time === 1.0`) with the normalized time and the current value.
1750
+ * @returns A promise resolved when the tween completes.
1751
+ */
1535
1752
  run(from, to, duration, delay = 0, easing = Easings.linear, callback = null) {
1536
1753
  return new Promise((resolve, _) => {
1537
1754
  const now = (performance && performance.now()) || Date.now();
@@ -1564,6 +1781,10 @@
1564
1781
  //}
1565
1782
 
1566
1783
  // namespace Pacem.Animations {
1784
+ /**
1785
+ * `requestAnimationFrame`-driven timer that invokes a callback at (approximately) a given frame rate.
1786
+ * Instances are created via the static {@link Timer.run} factory rather than `new`.
1787
+ */
1567
1788
  class Timer {
1568
1789
  #fps;
1569
1790
  #callback;
@@ -1584,9 +1805,15 @@
1584
1805
  this.#handle = requestAnimationFrame(this._run);
1585
1806
  }
1586
1807
  #then;
1808
+ /**
1809
+ * Creates and starts a new {@link Timer}.
1810
+ * @param callback Invoked on every tick with the current frame timestamp.
1811
+ * @param fps Target frame rate, in frames per second (default `60`).
1812
+ */
1587
1813
  static run(callback, fps = 60) {
1588
1814
  return new Timer(callback, fps);
1589
1815
  }
1816
+ /** Stops the timer, cancelling any pending animation frame. */
1590
1817
  stop() {
1591
1818
  cancelAnimationFrame(this.#handle);
1592
1819
  }
@@ -1604,6 +1831,7 @@
1604
1831
  });
1605
1832
 
1606
1833
  //namespace Pacem.Net {
1834
+ /** HTTP verbs accepted by {@link Fetcher.method} / {@link Http}. */
1607
1835
  var HttpMethod;
1608
1836
  (function (HttpMethod) {
1609
1837
  HttpMethod["Get"] = "GET";
@@ -1616,10 +1844,15 @@
1616
1844
  HttpMethod["Connect"] = "CONNECT";
1617
1845
  HttpMethod["Trace"] = "TRACE";
1618
1846
  })(HttpMethod || (HttpMethod = {}));
1847
+ /** Event name dispatched with the raw fetch result payload; see {@link Fetcher.result}. */
1619
1848
  const FetchResultEventName = 'fetchresult';
1849
+ /** Event name dispatched when a {@link Fetcher}'s request fails. */
1620
1850
  const FetchErrorEventName = 'error';
1851
+ /** Event name dispatched when a {@link Fetcher}'s request completes successfully. */
1621
1852
  const FetchSuccessEventName = 'success';
1853
+ /** Static helpers for working with fetch `Response`s. */
1622
1854
  class Fetcher {
1855
+ /** Tests whether a response carries no body (HTTP 204, or an explicit `Content-Length: 0`). */
1623
1856
  static isEmpty(r) {
1624
1857
  return r.status === 204 || r.headers.get("Content-Length") === "0";
1625
1858
  }
@@ -1629,17 +1862,22 @@
1629
1862
  /// <reference path="../promise.ts" />
1630
1863
  // namespace Pacem.Net {
1631
1864
  const noop = () => { };
1865
+ /** Error thrown by {@link Http.request} when a request fails outright or completes with a non-2xx status. */
1632
1866
  class StatusCodeError extends Error {
1867
+ /** @param statusCode HTTP status code (`500` for network-level failures). @param statusText Status text / error message. */
1633
1868
  constructor(statusCode, statusText) {
1634
1869
  super(statusText);
1635
1870
  this.statusCode = statusCode;
1636
1871
  }
1872
+ /** The HTTP status code that caused this error. */
1637
1873
  get status() {
1638
1874
  return this.statusCode;
1639
1875
  }
1640
1876
  }
1641
- /** @deprecated */
1877
+ /** Wraps a completed `XMLHttpRequest` produced by {@link Http.request}, exposing its status, headers and body in convenient forms.
1878
+ * @deprecated */
1642
1879
  class Response {
1880
+ /** @param req The completed `XMLHttpRequest`. @param processTime Elapsed request time, in milliseconds. */
1643
1881
  constructor(req, processTime) {
1644
1882
  if (!req)
1645
1883
  return;
@@ -1650,20 +1888,25 @@
1650
1888
  this._allHeadersRaw = req.getAllResponseHeaders();
1651
1889
  this._processTime = processTime;
1652
1890
  }
1891
+ /** Elapsed request time, in milliseconds. */
1653
1892
  get processTime() {
1654
1893
  return this._processTime;
1655
1894
  }
1895
+ /** Response headers, parsed into a name/value map (lazily, on first access). */
1656
1896
  get headers() {
1657
1897
  if (this._headers === undefined && this._allHeadersRaw)
1658
1898
  this._parseHeaders();
1659
1899
  return this._headers;
1660
1900
  }
1901
+ /** The `Content-Length` response header, parsed as a number. */
1661
1902
  get size() {
1662
1903
  return +this.headers['Content-Length'];
1663
1904
  }
1905
+ /** The `Content-Type` response header. */
1664
1906
  get mime() {
1665
1907
  return this.headers['Content-Type'];
1666
1908
  }
1909
+ /** The `Date` response header, parsed into a `Date`. */
1667
1910
  get date() {
1668
1911
  return new Date(Date.parse(this.headers['Date']));
1669
1912
  }
@@ -1679,9 +1922,13 @@
1679
1922
  });
1680
1923
  this._headers = headers;
1681
1924
  }
1925
+ /** HTTP status code. */
1682
1926
  get status() { return this._status; }
1927
+ /** Raw response body as text. */
1683
1928
  get text() { return this._text; }
1929
+ /** Response body, typed per `XMLHttpRequest.responseType` (see {@link type}). */
1684
1930
  get content() { return this._body; }
1931
+ /** The `XMLHttpRequest.responseType` used for this request. */
1685
1932
  get type() { return this._type; }
1686
1933
  /**
1687
1934
  * Short-hand utility for getting or parsing json content (if any).
@@ -1698,7 +1945,11 @@
1698
1945
  }
1699
1946
  }
1700
1947
  }
1701
- /** @deprecated */
1948
+ /**
1949
+ * Legacy `XMLHttpRequest`-based HTTP client, superseded by the standard `fetch` API and {@link Fetcher}.
1950
+ * Kept for backward compatibility.
1951
+ * @deprecated
1952
+ */
1702
1953
  class Http {
1703
1954
  constructor() { }
1704
1955
  /**
@@ -1844,6 +2095,9 @@
1844
2095
  /** Terminating the drag-drop activities. */
1845
2096
  DragDropEventType["End"] = "dragend";
1846
2097
  })(DragDropEventType || (DragDropEventType = {}));
2098
+ /**
2099
+ * Base class shared by the drag & drop event-args classes; wraps a {@link DragDropEventArgs} builder and exposes its common, read-only facets.
2100
+ */
1847
2101
  class DragDropEventArgsBaseClass {
1848
2102
  constructor(_builder) {
1849
2103
  this._builder = _builder;
@@ -1870,32 +2124,46 @@
1870
2124
  return pacemFoundation.Point.add(args.initialDelta, /* included in `initialDelta` for perf sake => { x: this._builder.scroll.left, y: this._builder.scroll.top },*/ pacemFoundation.Point.subtract(args.origin, args.currentPosition));
1871
2125
  }
1872
2126
  }
2127
+ /**
2128
+ * Event args dispatched with the {@link DragDropEventType.Init} event, mutable so listeners can override
2129
+ * the `placeholder` and `data` before the drag actually starts.
2130
+ */
1873
2131
  class DragDropInitEventArgsClass extends DragDropEventArgsBaseClass {
1874
2132
  constructor(_builder) {
1875
2133
  super(_builder);
1876
2134
  this.placeholder = _builder.placeholder;
1877
2135
  this.data = _builder.data;
1878
2136
  }
2137
+ /** Builds a new {@link DragDropInitEventArgsClass} out of a plain {@link DragDropEventArgs} builder. */
1879
2138
  static fromArgs(builder) {
1880
2139
  return new DragDropInitEventArgsClass(Utils.extend({}, builder));
1881
2140
  }
1882
2141
  }
2142
+ /**
2143
+ * Read-only event args dispatched with the drag/drop lifecycle events other than `draginit` (start, drag, drop, over, out, end).
2144
+ */
1883
2145
  class DragDropEventArgsClass extends DragDropEventArgsBaseClass {
1884
2146
  constructor(_builder, _placeholder = _builder.placeholder, _data = _builder.data) {
1885
2147
  super(_builder);
1886
2148
  this._placeholder = _placeholder;
1887
2149
  this._data = _data;
1888
2150
  }
2151
+ /** @readonly Gets the element used as a dragging placeholder. */
1889
2152
  get placeholder() {
1890
2153
  return this._placeholder;
1891
2154
  }
2155
+ /** @readonly Gets the logical payload being dragged. */
1892
2156
  get data() {
1893
2157
  return this._data;
1894
2158
  }
2159
+ /** Builds a new {@link DragDropEventArgsClass} out of a plain {@link DragDropEventArgs} builder. */
1895
2160
  static fromArgs(builder) {
1896
2161
  return new DragDropEventArgsClass(Utils.extend({}, builder));
1897
2162
  }
1898
2163
  }
2164
+ /**
2165
+ * Custom UI event dispatched throughout the drag & drop lifecycle (see {@link DragDropEventType}).
2166
+ */
1899
2167
  class DragDropEvent extends CustomUIEvent {
1900
2168
  constructor(type, args, eventInit, evt) {
1901
2169
  super(type, args, eventInit, evt);
@@ -1904,40 +2172,65 @@
1904
2172
  //}
1905
2173
 
1906
2174
  //namespace Pacem.UI {
2175
+ /**
2176
+ * Enumerates the resize handles a {@link Rescaler} can expose around a rescalable element.
2177
+ */
1907
2178
  var RescaleHandle;
1908
2179
  (function (RescaleHandle) {
2180
+ /** All four sides/corners are enabled. */
1909
2181
  RescaleHandle["All"] = "all";
2182
+ /** The top edge (and its corners) is enabled. */
1910
2183
  RescaleHandle["Top"] = "top";
2184
+ /** The left edge (and its corners) is enabled. */
1911
2185
  RescaleHandle["Left"] = "left";
2186
+ /** The right edge (and its corners) is enabled. */
1912
2187
  RescaleHandle["Right"] = "right";
2188
+ /** The bottom edge (and its corners) is enabled. */
1913
2189
  RescaleHandle["Bottom"] = "bottom";
1914
2190
  })(RescaleHandle || (RescaleHandle = {}));
2191
+ /**
2192
+ * Enumerates the events dispatched throughout the rescale gesture lifecycle.
2193
+ */
1915
2194
  var RescaleEventType;
1916
2195
  (function (RescaleEventType) {
2196
+ /** First rescaling act. */
1917
2197
  RescaleEventType["Start"] = "rescalestart";
2198
+ /** Any rescaling act. */
1918
2199
  RescaleEventType["Rescale"] = "rescale";
2200
+ /** Terminating the rescaling activities. */
1919
2201
  RescaleEventType["End"] = "rescaleend";
1920
2202
  })(RescaleEventType || (RescaleEventType = {}));
2203
+ /**
2204
+ * Read-only event args dispatched with the rescale gesture lifecycle events.
2205
+ */
1921
2206
  class RescaleEventArgsClass {
1922
2207
  constructor(_builder) {
1923
2208
  this._builder = _builder;
1924
2209
  }
2210
+ /** @readonly Gets the current pointer position. */
1925
2211
  get currentPosition() {
1926
2212
  return this._builder.currentPosition;
1927
2213
  }
2214
+ /** @readonly Gets the rectangle the element is being resized to. */
1928
2215
  get targetRect() {
1929
2216
  return this._builder.targetRect;
1930
2217
  }
2218
+ /** @readonly Gets the element being resized. */
1931
2219
  get element() {
1932
2220
  return this._builder.element;
1933
2221
  }
2222
+ /** @readonly Gets the handle being dragged (see {@link RescaleHandle}). */
1934
2223
  get handle() {
1935
2224
  return this._builder.handle;
1936
2225
  }
2226
+ /** Builds a new {@link RescaleEventArgsClass} out of a plain {@link RescaleEventArgs} builder. */
1937
2227
  static fromArgs(builder) {
1938
2228
  return new RescaleEventArgsClass(Utils.extend({}, builder));
1939
2229
  }
1940
2230
  }
2231
+ /**
2232
+ * Custom UI event dispatched throughout the rescale gesture lifecycle (see {@link RescaleEventType}).
2233
+ */
1941
2234
  class RescaleEvent extends CustomUIEvent {
1942
2235
  constructor(type, args, eventInit, evt) {
1943
2236
  super(type, args, eventInit, evt);
@@ -1945,32 +2238,49 @@
1945
2238
  }
1946
2239
  //}
1947
2240
 
2241
+ /**
2242
+ * Enumerates the events dispatched throughout the rotate gesture lifecycle.
2243
+ */
1948
2244
  var RotateEventType;
1949
2245
  (function (RotateEventType) {
2246
+ /** First rotating act. */
1950
2247
  RotateEventType["Start"] = "rotatestart";
2248
+ /** Any rotating act. */
1951
2249
  RotateEventType["Rotate"] = "rotate";
2250
+ /** Terminating the rotating activities. */
1952
2251
  RotateEventType["End"] = "rotateend";
1953
2252
  })(RotateEventType || (RotateEventType = {}));
2253
+ /**
2254
+ * Read-only event args dispatched with the rotate gesture lifecycle events.
2255
+ */
1954
2256
  class RotateEventArgsClass {
1955
2257
  constructor(_builder) {
1956
2258
  this._builder = _builder;
1957
2259
  }
2260
+ /** @readonly Gets the current pointer position. */
1958
2261
  get currentPosition() {
1959
2262
  return this._builder.currentPosition;
1960
2263
  }
2264
+ /** @readonly Gets the current rotation, in radians. */
1961
2265
  get rotation() {
1962
2266
  return this._builder.rotation;
1963
2267
  }
2268
+ /** @readonly Gets the element being rotated. */
1964
2269
  get element() {
1965
2270
  return this._builder.element;
1966
2271
  }
2272
+ /** @readonly Gets the pivot point the element is rotating around. */
1967
2273
  get center() {
1968
2274
  return this._builder.center;
1969
2275
  }
2276
+ /** Builds a new {@link RotateEventArgsClass} out of a plain {@link RotateEventArgs} builder. */
1970
2277
  static fromArgs(builder) {
1971
2278
  return new RotateEventArgsClass(Utils.extend({}, builder));
1972
2279
  }
1973
2280
  }
2281
+ /**
2282
+ * Custom UI event dispatched throughout the rotate gesture lifecycle (see {@link RotateEventType}).
2283
+ */
1974
2284
  class RotateEvent extends CustomUIEvent {
1975
2285
  constructor(type, args, eventInit, evt) {
1976
2286
  super(type, args, eventInit, evt);
@@ -1978,21 +2288,38 @@
1978
2288
  }
1979
2289
  //}
1980
2290
 
2291
+ /**
2292
+ * Enumerates the events dispatched throughout the swipe gesture lifecycle.
2293
+ */
1981
2294
  var SwipeEventType;
1982
2295
  (function (SwipeEventType) {
2296
+ /** Dispatched when the swipe gesture ends (release). */
1983
2297
  SwipeEventType["Swipe"] = "swipe";
2298
+ /** Dispatched while the pointer is dragging the element around. */
1984
2299
  SwipeEventType["Pan"] = "pan";
2300
+ /** Dispatched when the swipe ends and its resolved direction is leftward. */
1985
2301
  SwipeEventType["SwipeLeft"] = "swipeleft";
2302
+ /** Dispatched when the swipe ends and its resolved direction is rightward. */
1986
2303
  SwipeEventType["SwipeRight"] = "swiperight";
2304
+ /** Dispatched when the swipe ends and its resolved direction is upward. */
1987
2305
  SwipeEventType["SwipeUp"] = "swipeup";
2306
+ /** Dispatched when the swipe ends and its resolved direction is downward. */
1988
2307
  SwipeEventType["SwipeDown"] = "swipedown";
1989
2308
  // end of swipe animation
2309
+ /** Dispatched when the snap/bounce-back animation following a swipe completes. */
1990
2310
  SwipeEventType["SwipeAnimationEnd"] = "swipeanimationend";
2311
+ /** Dispatched when the snap/bounce-back animation following a leftward swipe completes. */
1991
2312
  SwipeEventType["SwipeLeftAnimationEnd"] = "swipeleftanimationend";
2313
+ /** Dispatched when the snap/bounce-back animation following a rightward swipe completes. */
1992
2314
  SwipeEventType["SwipeRightAnimationEnd"] = "swiperightanimationend";
2315
+ /** Dispatched when the snap/bounce-back animation following an upward swipe completes. */
1993
2316
  SwipeEventType["SwipeUpAnimationEnd"] = "swipeupanimationend";
2317
+ /** Dispatched when the snap/bounce-back animation following a downward swipe completes. */
1994
2318
  SwipeEventType["SwipeDownAnimationEnd"] = "swipedownanimationend";
1995
2319
  })(SwipeEventType || (SwipeEventType = {}));
2320
+ /**
2321
+ * Read-only event args dispatched with the swipe gesture lifecycle events.
2322
+ */
1996
2323
  class SwipeEventArgsClass {
1997
2324
  constructor(_builder) {
1998
2325
  this._builder = _builder;
@@ -2002,6 +2329,7 @@
2002
2329
  const isVertical = vertical ?? (Math.abs(horizontalspeed) < Math.abs(verticalspeed));
2003
2330
  return isVertical;
2004
2331
  }
2332
+ /** @readonly Gets the resolved swipe direction (`'up'`, `'down'`, `'left'` or `'right'`). */
2005
2333
  get direction() {
2006
2334
  return this.#isVertical
2007
2335
  ? (this._builder.verticalspeed > 0 ? 'down' : 'up')
@@ -2033,13 +2361,18 @@
2033
2361
  const inertia = this._builder.inertia ?? 8;
2034
2362
  return -Math.log(.01 /* v/v0 where v ~ 0 <=> 1% of v0 */) / inertia;
2035
2363
  }
2364
+ /** @readonly Gets the element being swiped. */
2036
2365
  get element() {
2037
2366
  return this._builder.element;
2038
2367
  }
2368
+ /** Builds a new {@link SwipeEventArgsClass} out of a plain {@link SwipeEventArgs} builder. */
2039
2369
  static fromArgs(builder) {
2040
2370
  return new SwipeEventArgsClass(Utils.extend({}, builder));
2041
2371
  }
2042
2372
  }
2373
+ /**
2374
+ * Custom typed event dispatched throughout the swipe gesture lifecycle (see {@link SwipeEventType}).
2375
+ */
2043
2376
  class SwipeEvent extends CustomTypedEvent {
2044
2377
  constructor(type, args, eventInit) {
2045
2378
  super(type, args, eventInit);
@@ -2068,6 +2401,7 @@
2068
2401
  get SwipeEventType () { return SwipeEventType; }
2069
2402
  });
2070
2403
 
2404
+ /** Dispatched by an {@link Iterative} container whenever its `index` changes. */
2071
2405
  class CurrentIndexChangeEvent extends CustomTypedEvent {
2072
2406
  constructor(args) {
2073
2407
  super('currentindexchange', args);
@@ -2076,11 +2410,16 @@
2076
2410
  //}
2077
2411
 
2078
2412
  /// <reference path="events.ts" />
2413
+ /** Runtime value (aliasing the built-in `Function`) usable where a constructor reference is needed as a value, paired with the {@link Type} interface for typing it. */
2079
2414
  const Type = Function;
2080
2415
  // #region CONSTS
2416
+ /** Key used to attach, on an element's constructor, the list of its `@Watch`-decorated (watched) property descriptors. */
2081
2417
  const WATCH_PROPS_VAR = 'pacem:properties';
2418
+ /** Key used to attach, on an element instance, the list of attribute names currently holding a pending (not-yet-evaluable) binding expression. */
2082
2419
  const INSTANCE_BINDINGS_VAR = 'pacem:custom-element:bindings';
2420
+ /** Key used to attach, on a templated node, a reference to the custom element instance ("host") whose template produced it — used to resolve binding expression scope. */
2083
2421
  const INSTANCE_HOST_VAR = 'pacem:custom-element:host';
2422
+ /** Key used to attach, on an element instance, its binding-expression evaluation scope object. */
2084
2423
  const INSTANCE_SCOPE_VAR = 'pacem:custom-element:scope';
2085
2424
  // #endregion
2086
2425
  //}
@@ -2089,37 +2428,66 @@
2089
2428
  var root;
2090
2429
  /** the overall customelement prefix */
2091
2430
  const P = (root = window['Pacem'])?.Configuration?.prefix ?? 'pacem';
2431
+ /** The prefix used for CSS custom properties and classes (e.g. `--{PCSS}-font-main`); configurable independently of the element tag prefix {@link P} via `window.Pacem.Configuration.css`, defaults to {@link P}. */
2092
2432
  const PCSS = root?.Configuration?.css ?? P;
2093
2433
  //}
2094
2434
 
2095
2435
  //namespace Pacem {
2436
+ /** Marker base class for elements that behave like `<template>` (e.g. a custom template-proxy element), so template-detection logic can treat them the same as a native `HTMLTemplateElement`. */
2096
2437
  class TemplateElement extends HTMLElement {
2097
2438
  }
2098
2439
  //}
2099
2440
 
2100
- /// <reference path="expression.ts" />
2101
- /// <reference path="promise.ts" />
2102
- /// <reference path="prefix.ts" />
2103
- /// <reference path="trees/json.ts" />
2104
- /// <reference path="utils.ts" />
2105
2441
  // namespace Pacem {
2106
2442
  const PACEM_BAG = '__pacem__';
2107
2443
  // {{ binding.expression }}
2108
2444
  const bindingPattern = /^\{\{(.|\n)+\}\}$/;
2109
2445
  // TODO: CSP-proof binding (no unsafe-eval)
2110
2446
  // binding syntax example: `{ binding: { source: ^item.property.path, binder: $pacem.func, parameters: [ ^index, 'foo', : host._baz], mode: 'twoway' } }`
2447
+ /**
2448
+ * Static grab-bag of low-level helpers underpinning the {@link CustomElement}/{@link Watch} decorators
2449
+ * and the binding-expression engine: attached-property storage (a per-instance, non-enumerable "bag"
2450
+ * used instead of expando properties), attribute/property name conversion, DOM tree traversal, host/
2451
+ * scope resolution for templated content, and binding-attribute parsing.
2452
+ */
2111
2453
  class CustomElementUtils {
2454
+ /** `true` when the platform's `customElements` registry is the Custom Elements polyfill rather than a native implementation. */
2112
2455
  static get polyfilling() {
2113
2456
  return customElements instanceof window['CustomElementRegistry'];
2114
2457
  }
2458
+ /** Converts a camelCase property name to its kebab-case attribute-name equivalent (e.g. `myProp` → `my-prop`). */
2115
2459
  static camelToKebab(camelCased) {
2116
2460
  return camelCased && camelCased.replace(/([A-Z])/g, '-$1').toLowerCase();
2117
2461
  }
2462
+ /** Converts a kebab-case attribute name to its camelCase property-name equivalent (e.g. `my-prop` → `myProp`). */
2118
2463
  static kebabToCamel(kebabCased) {
2119
2464
  return kebabCased && kebabCased.replace(/(-[a-z])/g, (m) => {
2120
2465
  return m[1].toUpperCase();
2121
2466
  });
2122
2467
  }
2468
+ /** Waits for the specified alement to be ready. */
2469
+ static waitForReady(element) {
2470
+ return new Promise((resolve, reject) => {
2471
+ if (Utils.isNull(element)) {
2472
+ reject('Not found.');
2473
+ }
2474
+ // if (element.isConnected && !(element instanceof PacemEventTarget)){
2475
+ // reject('Invalid element.');
2476
+ // }
2477
+ if (element.isReady) {
2478
+ resolve();
2479
+ }
2480
+ const callback = () => {
2481
+ element.removeEventListener('load', callback);
2482
+ resolve();
2483
+ };
2484
+ element.addEventListener('load', callback);
2485
+ });
2486
+ }
2487
+ /** Waits for the specified element to be ready, then executes the provided callback. */
2488
+ static whenReady(element, callback) {
2489
+ CustomElementUtils.waitForReady(element).then(callback);
2490
+ }
2123
2491
  static getWatchedProperties(target, includeInherited = true) {
2124
2492
  var properties = [];
2125
2493
  var chain = target instanceof HTMLElement ? target.constructor : target;
@@ -2130,9 +2498,16 @@
2130
2498
  } while (includeInherited && (chain = Object.getPrototypeOf(chain)));
2131
2499
  return properties;
2132
2500
  }
2501
+ /** Retrieves a single `@Watch`-decorated property descriptor by name; see {@link getWatchedProperties}. */
2133
2502
  static getWatchedProperty(target, name) {
2134
2503
  return this.getWatchedProperties(target, true).find(p => p.name === name);
2135
2504
  }
2505
+ /**
2506
+ * Loads a `<script>` tag once (deduplicated by `src`, cached via {@link import}), resolving when it fires `load`.
2507
+ * @param src Script URL.
2508
+ * @param integrity Optional Subresource Integrity hash.
2509
+ * @param crossorigin Whether to set `crossorigin` on the tag.
2510
+ */
2136
2511
  static importjs(src, integrity = null, crossorigin = false) {
2137
2512
  var attrs = { 'type': 'text\/javascript', 'src': src };
2138
2513
  if (!Utils.isNullOrEmpty(integrity))
@@ -2141,6 +2516,12 @@
2141
2516
  Utils.extend(attrs, { 'crossorigin': '' });
2142
2517
  return CustomElementUtils.import(src, 'script', attrs, (document.head || document.getElementsByTagName("head")[0]));
2143
2518
  }
2519
+ /**
2520
+ * Loads a `<link rel="stylesheet">` tag once (deduplicated by `src`, cached via {@link import}), resolving when it fires `load`.
2521
+ * @param src Stylesheet URL.
2522
+ * @param integrity Optional Subresource Integrity hash.
2523
+ * @param crossorigin Whether to set `crossorigin="anonymous"` on the tag.
2524
+ */
2144
2525
  static importcss(src, integrity = null, crossorigin = false) {
2145
2526
  var attrs = { 'rel': 'stylesheet', 'href': src };
2146
2527
  if (!Utils.isNullOrEmpty(integrity))
@@ -2149,6 +2530,15 @@
2149
2530
  Utils.extend(attrs, { 'crossorigin': 'anonymous' });
2150
2531
  return CustomElementUtils.import(src, 'link', attrs, (document.head || document.getElementsByTagName("head")[0]));
2151
2532
  }
2533
+ /**
2534
+ * Creates (or reuses an already-present, matching) element of `tagName` with the given attributes and
2535
+ * appends it to the DOM, returning a promise that resolves once it loads (or rejects on error). Results
2536
+ * are cached per `key` (under `Utils.core.imports`) so repeated calls with the same key are a no-op.
2537
+ * @param key Cache/dedupe key (typically the resource URL).
2538
+ * @param tagName Tag name of the element to create (e.g. `'script'`, `'link'`).
2539
+ * @param attrs Attributes to set on the element, also used to build a matching CSS selector to detect a pre-existing element.
2540
+ * @param appendTo Node to append the newly created element to, if none was found. Defaults to `document.body`.
2541
+ */
2152
2542
  static import(key, tagName, attrs, appendTo = document.body) {
2153
2543
  const _p = Utils.core;
2154
2544
  var _imports = _p['imports'] = _p['imports'] || {};
@@ -2178,7 +2568,9 @@
2178
2568
  }
2179
2569
  });
2180
2570
  }
2571
+ /** Theming-related helpers. */
2181
2572
  static { this.Theme = {
2573
+ /** Downloads the web fonts referenced by the current theme's `--{@link PCSS}-font-*` CSS custom properties, resolving once at least one font face is ready (or after a short timeout). */
2182
2574
  importWebFonts() {
2183
2575
  function cleanupQuotes(input) {
2184
2576
  // check if the string is wrapped around quotes to escape ';' chars
@@ -2216,6 +2608,14 @@
2216
2608
  return Promise.all(promises);
2217
2609
  }
2218
2610
  }; }
2611
+ /**
2612
+ * Stores an arbitrary value "attached" to `target` under `name`, in a private, non-enumerable bag
2613
+ * (rather than as a plain expando property) so it doesn't show up in `for...in`/`Object.keys`/JSON
2614
+ * serialization. Setting `value` to `null`/`undefined` removes the entry. See {@link getAttachedPropertyValue}.
2615
+ * @param target Object to attach the value to.
2616
+ * @param name Key under which the value is stored.
2617
+ * @param value Value to store, or `null`/`undefined` to remove the entry.
2618
+ */
2219
2619
  static setAttachedPropertyValue(target, name, value) {
2220
2620
  /*(target[PACEM_BAG] = target[PACEM_BAG] || {})[name] = value;*/
2221
2621
  if (Utils.isNull(target))
@@ -2230,9 +2630,16 @@
2230
2630
  else
2231
2631
  bag[name] = value;
2232
2632
  }
2633
+ /** Removes a value previously stored via {@link setAttachedPropertyValue}. */
2233
2634
  static deleteAttachedPropertyValue(target, name) {
2234
2635
  CustomElementUtils.setAttachedPropertyValue(target, name, undefined);
2235
2636
  }
2637
+ /**
2638
+ * Reads a value previously stored via {@link setAttachedPropertyValue}.
2639
+ * @param target Object the value is attached to.
2640
+ * @param name Key the value is stored under.
2641
+ * @param ensureValue If provided and no value is currently stored, this value is stored and returned (lazy-initialization).
2642
+ */
2236
2643
  static getAttachedPropertyValue(target, name, ensureValue) {
2237
2644
  const propKey = Object.getOwnPropertyDescriptor(target, PACEM_BAG), bag = propKey && propKey.value;
2238
2645
  if (Utils.isNull(bag && bag[name]) && !Utils.isNull(ensureValue)) {
@@ -2278,6 +2685,17 @@
2278
2685
  }
2279
2686
  return { target: { value: ref, name: name }, parent: { value: parent || scope, path: path.substring(0, ndx) }, root: { value: root, property: core } };
2280
2687
  }
2688
+ /**
2689
+ * Writes `value` at the given dotted `path`, rooted at `element` (see {@link resolvePath}), triggering
2690
+ * the appropriate `propertychange` notification. For paths nested more than one level deep (and not
2691
+ * targeting an `HTMLElement`, which fires change notifications autonomously), the whole root property
2692
+ * is cloned, mutated and reassigned so that a `propertychange` fires with meaningful old/new values -
2693
+ * a plain nested assignment wouldn't otherwise be observed. Repeater-bound `item` paths are special-cased
2694
+ * to update the owning {@link Repeater}'s `datasource` array in place.
2695
+ * @param element Root element the path is resolved against.
2696
+ * @param path Dotted path (e.g. `'foo.bar[0].baz'`) to the target property.
2697
+ * @param value New value to assign.
2698
+ */
2281
2699
  static set(element, path, value) {
2282
2700
  var obj = CustomElementUtils.resolvePath(path, element);
2283
2701
  var current = obj.target.value;
@@ -2308,6 +2726,7 @@
2308
2726
  }
2309
2727
  }
2310
2728
  }
2729
+ /** Reads the value at the given dotted `path`, rooted at `element`; see {@link resolvePath}. */
2311
2730
  static get(element, path) {
2312
2731
  var obj = CustomElementUtils.resolvePath(path, element);
2313
2732
  return obj && obj.target && obj.target.value;
@@ -2328,12 +2747,27 @@
2328
2747
  // logFn(`Element "${element.constructor.name}" isn't attached to any context yet.`);
2329
2748
  return retval;
2330
2749
  }
2750
+ /**
2751
+ * Finds the `Document` or `ShadowRoot` that `element` belongs to - used as the root for resolving
2752
+ * scoped binding expressions (e.g. `$document`/`$host` lookups). Falls back to the previously-attached
2753
+ * scope value (see `INSTANCE_SCOPE_VAR`, set on `connectedCallback`) when `element` is currently
2754
+ * disconnected, and to a legacy manual-walk implementation as a last resort (needed under Jasmine tests,
2755
+ * where `element.isConnected` never reports `true`).
2756
+ * @param element Element to resolve the containing document/shadow-root scope for.
2757
+ */
2331
2758
  static findScopeContext(element) {
2332
2759
  let retval = (element.isConnected) ?
2333
2760
  element.getRootNode()
2334
2761
  : CustomElementUtils.getAttachedPropertyValue(element, INSTANCE_SCOPE_VAR);
2335
2762
  return retval ?? /* in Jasmine TESTS `element.isConnected` always returns false (attached to #document-fragment) */ CustomElementUtils._findScopeContextLegacy(element);
2336
2763
  }
2764
+ /**
2765
+ * Walks up from `element` (crossing shadow-root boundaries via the host element) looking for the
2766
+ * first ancestor matching `predicate`.
2767
+ * @param element Element to start the upward search from.
2768
+ * @param predicate Test invoked (as `this`-bound and argument-passed) against each ancestor.
2769
+ * @returns The first matching ancestor, or `undefined` if none matches.
2770
+ */
2337
2771
  static findAncestor(element, predicate) {
2338
2772
  let el = element;
2339
2773
  let retval;
@@ -2347,12 +2781,20 @@
2347
2781
  }
2348
2782
  return retval;
2349
2783
  }
2784
+ /** Finds the nearest ancestor "shell" element - matching `.{@link PCSS}-body` - or falls back to `document.body`; see {@link findAncestor}. */
2350
2785
  static findAncestorShell(element) {
2351
2786
  return CustomElementUtils.findAncestor(element, el => Utils.is(el, `.${PCSS}-body`) || el === document.body);
2352
2787
  }
2788
+ /** Finds the nearest ancestor that is an instance of `ctor`; see {@link findAncestor}. */
2353
2789
  static findAncestorOfType(element, ctor) {
2354
2790
  return CustomElementUtils.findAncestor(element, el => el instanceof ctor);
2355
2791
  }
2792
+ /**
2793
+ * Collects the descendants of `element` matching `predicate`, via a `TreeWalker` over element nodes.
2794
+ * @param element Root element to search from (exclusive - the walker starts on its descendants).
2795
+ * @param predicate Test invoked against each descendant element.
2796
+ * @param firstOnly When `true`, stops and returns as soon as one match is found.
2797
+ */
2356
2798
  static findDescendants(element, predicate, firstOnly = false) {
2357
2799
  const walker = document.createTreeWalker(element, NodeFilter.SHOW_ELEMENT);
2358
2800
  var retval = [];
@@ -2367,10 +2809,16 @@
2367
2809
  }
2368
2810
  return retval;
2369
2811
  }
2812
+ /** Finds the first descendant of `element` matching `predicate`, or `undefined` if none matches; see {@link findDescendants}. */
2370
2813
  static findFirstDescendant(element, predicate) {
2371
2814
  const any = CustomElementUtils.findDescendants(element, predicate, true);
2372
2815
  return Utils.isNullOrEmpty(any) ? void 0 : any[0];
2373
2816
  }
2817
+ /**
2818
+ * Queries the whole document for elements matching `selector`, additionally filtered by `filter`.
2819
+ * @param selector CSS selector to query for. Defaults to `'[pacem]'` (every Pacem custom element, which all carry that attribute once connected).
2820
+ * @param filter Extra predicate applied to each matched element. Defaults to accepting everything.
2821
+ */
2374
2822
  static findAll(selector = '[pacem]', filter = (e) => true) {
2375
2823
  const retval = [];
2376
2824
  document.querySelectorAll(selector).forEach((e, i, arr) => {
@@ -2432,6 +2880,14 @@
2432
2880
  } while (el != null);
2433
2881
  return retval;
2434
2882
  }
2883
+ /**
2884
+ * Tags every element/document-fragment node inside `template`'s content (that isn't already tagged)
2885
+ * with `host` under `INSTANCE_HOST_VAR`, so that once cloned and inserted into the DOM, binding
2886
+ * expressions in that fragment can resolve back to the custom element instance ("host") that owns
2887
+ * this template. See {@link findHostContext}.
2888
+ * @param host The custom element instance whose template this is.
2889
+ * @param template Template whose content's descendants should be tagged.
2890
+ */
2435
2891
  static assignHostContext(host, template) {
2436
2892
  // navigate through the DOM hierarchy
2437
2893
  const walker = document.createTreeWalker(template.content, NodeFilter.SHOW_ELEMENT + /* traverse templates' content */ NodeFilter.SHOW_DOCUMENT_FRAGMENT);
@@ -2444,6 +2900,13 @@
2444
2900
  }
2445
2901
  }
2446
2902
  }
2903
+ /**
2904
+ * Walks up from `element` looking for the nearest ancestor (inclusive) tagged with a host reference
2905
+ * via {@link assignHostContext}; this is the custom element instance whose template produced `element`,
2906
+ * used to resolve `$host`/scope references in binding expressions. Returns `undefined` (with a console
2907
+ * warning) if `element` is disconnected or isn't part of any templated component.
2908
+ * @param element Element to resolve the owning host for.
2909
+ */
2447
2910
  static findHostContext(element) {
2448
2911
  let el = element;
2449
2912
  let retval;
@@ -2466,6 +2929,7 @@
2466
2929
  logFn(`Element "${element.constructor.name}" isn't a descendant of a templated component.`);
2467
2930
  return retval;
2468
2931
  }
2932
+ /** Tests whether an attribute's raw string value has binding-expression syntax (`{{ ... }}`). */
2469
2933
  static isBindingAttribute(attr) {
2470
2934
  /*if (/^\s*\{\s*binding\s+.*\}\s*$/.test(attr)) {
2471
2935
 
@@ -2485,6 +2949,7 @@
2485
2949
  else*/
2486
2950
  return bindingPattern.test(attr);
2487
2951
  }
2952
+ /** Strips the `{{ }}` delimiters off a binding attribute's raw value, returning the bare expression text. Throws if `attr` isn't a valid binding attribute; see {@link isBindingAttribute}. */
2488
2953
  static extractBindingAttributeExpression(attr) {
2489
2954
  if (CustomElementUtils.isBindingAttribute(attr)) {
2490
2955
  return attr.substr(2, attr.length - 4);
@@ -2493,6 +2958,13 @@
2493
2958
  throw `Invalid attribute: incorrect binding syntax.`;
2494
2959
  }
2495
2960
  }
2961
+ /**
2962
+ * Parses a `{{ ... }}` binding attribute value into an {@link Expression}, recognizing the optional
2963
+ * trailing `, twoway` / `, once` modifier and stamping it onto the expression's dependencies (`twoway`
2964
+ * only applies when the expression has exactly one dependency that itself allows two-way binding).
2965
+ * @param attr Raw binding attribute value, including the `{{ }}` delimiters.
2966
+ * @param element Element the expression is evaluated/bound against (used to resolve scope references).
2967
+ */
2496
2968
  static parseBindingAttribute(attr, element) {
2497
2969
  // loose syntax {{ ... }}
2498
2970
  let expression = CustomElementUtils.extractBindingAttributeExpression(attr);
@@ -2513,6 +2985,14 @@
2513
2985
  });
2514
2986
  return expr;
2515
2987
  }
2988
+ /**
2989
+ * Defines an own property `name` on `o` with `attributes`, unless `o` already has an own property
2990
+ * descriptor for that name (in which case the existing descriptor is returned untouched).
2991
+ * @param o Object to define the property on.
2992
+ * @param name Property name.
2993
+ * @param attributes Property descriptor to apply if the property isn't already defined.
2994
+ * @returns The (possibly pre-existing) property descriptor.
2995
+ */
2516
2996
  static ensureMember(o, name, attributes) {
2517
2997
  let original = Object.getOwnPropertyDescriptor(o, name);
2518
2998
  if (original != undefined)
@@ -2573,6 +3053,7 @@
2573
3053
  const GET_VAL$6 = CustomElementUtils.getAttachedPropertyValue;
2574
3054
  const SET_VAL$5 = CustomElementUtils.setAttachedPropertyValue;
2575
3055
  const REPEATERITEM_PLACEHOLDER = 'pacem:repeater-item';
3056
+ /** Static lookup helpers for locating the {@link RepeaterItem} context a given element belongs to. */
2576
3057
  class Repeater {
2577
3058
  /**
2578
3059
  * Seeks for a PacemRepeaterItem element upwards through the DOM tree, given a starting element and the number of nesting levels.
@@ -2587,7 +3068,22 @@
2587
3068
  return retval;
2588
3069
  }
2589
3070
  }
3071
+ /**
3072
+ * Base class tracking a single rendered repetition of a {@link Repeater}'s template: it associates a
3073
+ * DOM placeholder node with the `item`/`index` scope values that template's binding expressions
3074
+ * evaluate against, and is itself attached to that placeholder (see {@link getRepeaterItem}) so
3075
+ * descendant elements can find their way back to it via {@link findUpwards}.
3076
+ */
2590
3077
  let RepeaterItem$1 = class RepeaterItem {
3078
+ /**
3079
+ * Seeks upwards from `element` (previous siblings, then parent, repeated) for the nearest ancestor
3080
+ * placeholder tagged as a {@link RepeaterItem}, skipping `upLevels` matches before returning one -
3081
+ * this is how deeply-nested repeaters resolve which repetition (of which ancestor repeater) an
3082
+ * expression's `^item`/`^^item`/... token refers to.
3083
+ * @param element Element to start the upward search from.
3084
+ * @param upLevels 0-based number of matching ancestors to skip before returning one (`0` = nearest).
3085
+ * @param logFn Called with a warning message if no match is found and `element` is connected to the DOM.
3086
+ */
2591
3087
  static findUpwards(element, upLevels = 0, logFn = console.warn) {
2592
3088
  if (Utils.isNull(element) || element.localName === 'template' || element instanceof /* template-like element? */ TemplateElement) {
2593
3089
  return null;
@@ -2600,16 +3096,20 @@
2600
3096
  }
2601
3097
  return item;
2602
3098
  }
3099
+ /** Tests whether `node` is the placeholder of some {@link RepeaterItem}. */
2603
3100
  static isRepeaterItem(node) {
2604
3101
  return !Utils.isNull(GET_VAL$6(node, REPEATERITEM_PLACEHOLDER));
2605
3102
  }
3103
+ /** Retrieves the {@link RepeaterItem} attached to `node`, if `node` is a repeater-item placeholder; see {@link isRepeaterItem}. */
2606
3104
  static getRepeaterItem(node) {
2607
3105
  return GET_VAL$6(node, REPEATERITEM_PLACEHOLDER);
2608
3106
  }
3107
+ /** @param _placeholder DOM node (typically a comment) that stands in for this repetition and gets tagged so {@link getRepeaterItem} can retrieve this instance back from it. */
2609
3108
  constructor(_placeholder) {
2610
3109
  this._placeholder = _placeholder;
2611
3110
  SET_VAL$5(_placeholder, REPEATERITEM_PLACEHOLDER, this);
2612
3111
  }
3112
+ /** The DOM placeholder node standing in for this repetition. */
2613
3113
  get placeholder() {
2614
3114
  return this._placeholder;
2615
3115
  }
@@ -2655,32 +3155,53 @@
2655
3155
  // * ...
2656
3156
  // */
2657
3157
  //const purePropertyPathPattern = /^[\w\.\$]+/;
3158
+ /**
3159
+ * A parsed, compiled binding expression (the content of a `{{ ... }}` attribute value). Parsing
3160
+ * (see {@link parse}) rewrites special tokens found in the source text - `:host.`, `^item`/`^^item`/...,
3161
+ * `^index`/`^^index`/..., `#id`, `::hostProp` - into references resolvable at evaluation time, and
3162
+ * records each of them as a {@link PropertyDependency} so the owning element can be notified (via
3163
+ * {@link PropertyChangeEvent}) and re-evaluate the expression whenever a dependency changes - this is
3164
+ * what powers the two-way/live data binding wired up by the {@link CustomElement} decorator.
3165
+ * Expressions with no dependencies are flagged `independent` (effectively a constant) and can be
3166
+ * evaluated immediately without waiting for the DOM/scope to be ready.
3167
+ */
2658
3168
  class Expression {
2659
3169
  constructor() {
2660
3170
  this._pending = false;
2661
3171
  this._independent = false;
2662
3172
  }
3173
+ /** The resolved property dependencies (element + property + path) this expression re-evaluates on change. Empty for {@link independent} expressions. */
2663
3174
  get dependencies() {
2664
3175
  return this._dependencies;
2665
3176
  }
3177
+ /** The compiled function body used by {@link evaluate}/{@link evaluateAsync} (a `return <expr>;` statement, guarded by a try/catch). */
2666
3178
  get functionBody() {
2667
3179
  return this._fnBody;
2668
3180
  }
3181
+ /** The compiled function body used by {@link evaluatePlus} (a bare, non-`return`ing statement, guarded by a try/catch) - suited for expressions run for their side effects, e.g. `on-*` event handlers. */
2669
3182
  get voidBody() {
2670
3183
  return this._voidBody;
2671
3184
  }
3185
+ /**
3186
+ * `true` when this expression couldn't be resolved against a scope yet (the element wasn't connected
3187
+ * to a document/shadow-root at parse time) - a shared, inert placeholder singleton returned by
3188
+ * {@link parse} in that case; evaluating it is a no-op. Callers should re-parse once the element is ready.
3189
+ */
2672
3190
  get pending() {
2673
3191
  return this._pending;
2674
3192
  }
3193
+ /** `true` when the expression has no dependencies (a constant) and can be evaluated immediately, without a resolved scope. */
2675
3194
  get independent() {
2676
3195
  return this._independent;
2677
3196
  }
3197
+ /** Evaluates the expression and returns its result, swallowing any runtime error (returning `undefined`). */
2678
3198
  evaluate() {
2679
3199
  if (!this._fn) {
2680
3200
  this._fn = new Function('$pacem', CONTEXT_PREFIX, this._fnBody);
2681
3201
  }
2682
3202
  return this._fn.apply(null, [Utils.core, this._args]);
2683
3203
  }
3204
+ /** Promise-wrapped variant of {@link evaluate} (resolves synchronously with the same result - kept for call-site uniformity with genuinely async evaluation paths). */
2684
3205
  evaluateAsync() {
2685
3206
  const deferred = DeferPromise.defer();
2686
3207
  if (!this._fn) {
@@ -2689,6 +3210,12 @@
2689
3210
  deferred.resolve(this._fn.apply(null, [Utils.core, this._args]));
2690
3211
  return deferred.promise;
2691
3212
  }
3213
+ /**
3214
+ * Executes the expression for its side effects (using {@link voidBody}, so no value is returned),
3215
+ * with extra named variables merged into scope alongside the expression's own dependencies -
3216
+ * used to expose e.g. `$event` to `on-*` event handler expressions.
3217
+ * @param args Extra name/value pairs made available to the expression, in addition to its resolved dependencies.
3218
+ */
2692
3219
  evaluatePlus(args = {}) {
2693
3220
  if (!this._fn) {
2694
3221
  let argNames = [CONTEXT_PREFIX];
@@ -2713,6 +3240,15 @@
2713
3240
  }
2714
3241
  return Expression._pendingExpression;
2715
3242
  }
3243
+ /**
3244
+ * Parses a binding expression's source text (the bare content of a `{{ ... }}` attribute, without the
3245
+ * delimiters - see {@link CustomElementUtils.extractBindingAttributeExpression}) into an {@link Expression},
3246
+ * resolving its special tokens against `element`'s scope (see {@link CustomElementUtils.findScopeContext}).
3247
+ * Throws if the expression matches the unsafe-code guard (`new`, `window.`, `document.`, `eval(`).
3248
+ * @param expression Bare expression source text.
3249
+ * @param element Element the expression is bound to; provides the scope special tokens (`:host.`, `#id`, `^item`, ...) resolve against.
3250
+ * @returns A constant expression if it has no dependencies; a shared pending placeholder if `element` isn't attached to a scope yet; otherwise a fully resolved expression.
3251
+ */
2716
3252
  static parse(expression, element) {
2717
3253
  var context = CustomElementUtils.findScopeContext(element);
2718
3254
  var args = { '$this': element };
@@ -2843,13 +3379,20 @@
2843
3379
  // }
2844
3380
 
2845
3381
  //namespace Pacem.Logging {
3382
+ /** Severity levels accepted by {@link Logger.log}, and used by {@link PacemEventTarget.log}. */
2846
3383
  var LogLevel;
2847
3384
  (function (LogLevel) {
3385
+ /** Fine-grained diagnostic detail. */
2848
3386
  LogLevel["Trace"] = "trace";
3387
+ /** Development-time diagnostic detail. */
2849
3388
  LogLevel["Debug"] = "debug";
3389
+ /** Recoverable but noteworthy condition. */
2850
3390
  LogLevel["Warn"] = "warn";
3391
+ /** Unrecoverable or unexpected failure. */
2851
3392
  LogLevel["Error"] = "error";
3393
+ /** General informational message. */
2852
3394
  LogLevel["Info"] = "info";
3395
+ /** Generic/default-severity message. */
2853
3396
  LogLevel["Log"] = "log";
2854
3397
  })(LogLevel || (LogLevel = {}));
2855
3398
  //}
@@ -2903,6 +3446,11 @@
2903
3446
  convert: (attr) => pacemFoundation.Rect.parse(attr),
2904
3447
  convertBack: (prop) => `${prop.x || 0} ${prop.y || 0} ${prop.width || 0} ${prop.height || 0}`
2905
3448
  };
3449
+ /**
3450
+ * Built-in {@link PropertyConverter} implementations, keyed by the type they convert to/from. Passed as
3451
+ * the `converter` option of a {@link Watch}-decorated property (e.g. `@Watch({ converter: PropertyConverters.Number })`)
3452
+ * to control how that property's attribute string is parsed and, on change, reflected back.
3453
+ */
2906
3454
  const PropertyConverters /*: { [name: string]: PropertyConverter }*/ = {
2907
3455
  None: NonePropertyConverter,
2908
3456
  String: StringPropertyConverter,
@@ -3050,6 +3598,31 @@
3050
3598
  }
3051
3599
  return promises;
3052
3600
  }
3601
+ /**
3602
+ * Class decorator that turns a class extending `HTMLElement` (typically {@link PacemEventTarget}) into a
3603
+ * fully-fledged Pacem custom element: it registers the tag with the custom elements registry and wraps
3604
+ * the standard `connectedCallback`/`disconnectedCallback`/`attributeChangedCallback`/`propertyChangedCallback`
3605
+ * lifecycle hooks (calling through to any hooks already defined on the class) so that:
3606
+ *
3607
+ * - `observedAttributes` is computed automatically from the class's {@link Watch}-decorated properties
3608
+ * (in kebab-case), merged with any statically-declared `observedAttributes`.
3609
+ * - On first connection, `config.template`/`config.templateUrl` (if provided) is fetched, parsed and
3610
+ * injected — into a Shadow Root when `config.shadow` is `true`, otherwise as light-DOM children,
3611
+ * splicing any pre-existing light-DOM content into a `<pacem-content>` placeholder if present.
3612
+ * - Attribute changes are converted to property values via each watched property's {@link PropertyConverter},
3613
+ * and dispatched as an {@link AttributeChangeEvent}.
3614
+ * - Property changes are dispatched as a {@link PropertyChangeEvent} (unless the property's `@Watch`
3615
+ * config sets `emit: false`) and, when `reflectBack` is enabled, written back onto the corresponding
3616
+ * attribute via the converter's `convertBack`.
3617
+ * - Binding expression attributes (`{{ ... }}`) are parsed and kept live: dependent properties are
3618
+ * re-evaluated whenever one of the expression's upstream properties fires a {@link PropertyChangeEvent}.
3619
+ * - Once the template (and all descendant templated custom elements) have finished rendering, the
3620
+ * `cloak` attribute is removed and `viewActivatedCallback` fires — this is the right place for logic
3621
+ * that depends on the element's full DOM (light or shadow) being in place.
3622
+ *
3623
+ * @param config Tag name, optional native `customElements.define` options, and optional template/templateUrl/shadow settings.
3624
+ * @returns A class decorator to apply to the custom element's class declaration.
3625
+ */
3053
3626
  const CustomElement = (config) => {
3054
3627
  return (target) => {
3055
3628
  // might be already registered
@@ -3384,6 +3957,27 @@
3384
3957
  // #endregion
3385
3958
  // #region WATCH PROPERTIES
3386
3959
  const DefaultPropertyConverter = PropertyConverters.None;
3960
+ /**
3961
+ * Property decorator that turns a plain class field (or accessor) into a Pacem "watched" property:
3962
+ * a property whose changes are detected (via reference/value comparison, see {@link DefaultComparer}),
3963
+ * optionally converted from/to its corresponding attribute string via a {@link PropertyConverter}
3964
+ * (see {@link PropertyConverters}), and notified through `propertyChangedCallback` plus a
3965
+ * {@link PropertyChangeEvent} (unless `config.emit` is `false`).
3966
+ *
3967
+ * Must be paired with the {@link CustomElement} class decorator, which is what actually reads the list
3968
+ * of watched properties (via `WATCH_PROPS_VAR`) to compute `observedAttributes` and wire up attribute/
3969
+ * property change plumbing — `@Watch` alone, on a class not decorated with `@CustomElement`, only sets
3970
+ * up the getter/setter and change notification, with no attribute involvement.
3971
+ *
3972
+ * Array-valued properties are additionally instrumented: their mutating methods (`push`, `pop`, `splice`,
3973
+ * `shift`, `unshift`, `copyWithin`) are patched so in-place mutations also trigger a change notification.
3974
+ *
3975
+ * @param config Optional behavior: `converter` (attribute↔property conversion, default `PropertyConverters.None`),
3976
+ * `emit` (whether to dispatch a {@link PropertyChangeEvent}, default `true`), `debounce` (delay the
3977
+ * change notification, either by a fixed number of milliseconds or `true` for one animation frame),
3978
+ * and `reflectBack` (write the property value back onto the attribute on change, default `false`).
3979
+ * @returns A property decorator to apply to the watched field/accessor.
3980
+ */
3387
3981
  function Watch(config) {
3388
3982
  return (target, prop, descriptor) => {
3389
3983
  var watchableProperties = GET_VAL$5(target.constructor, WATCH_PROPS_VAR, []);
@@ -3502,6 +4096,17 @@
3502
4096
  }
3503
4097
  };
3504
4098
  }
4099
+ /**
4100
+ * Property decorator that turns a class field into a lazily-resolved, cached reference to a descendant
4101
+ * element matching `selector`. Resolution happens on first read (via `shadowRoot.querySelectorAll` when
4102
+ * available, falling back to the element itself), and only nodes whose `INSTANCE_HOST_VAR` points back
4103
+ * at `this` are considered — this keeps the lookup scoped to the current element's own template output,
4104
+ * skipping over descendants that belong to a nested custom element's own template. The cache is reset
4105
+ * whenever the host element reconnects to the DOM (`connectedCallback`, see the {@link CustomElement} decorator).
4106
+ *
4107
+ * @param selector CSS selector identifying the child element to bind to.
4108
+ * @returns A property decorator to apply to the view-child field (read-only; no setter is defined).
4109
+ */
3505
4110
  function ViewChild(selector) {
3506
4111
  return (target, prop, descriptor) => {
3507
4112
  const key = `${prop}_${Utils.uniqueCode()}`;
@@ -3534,6 +4139,15 @@
3534
4139
  }
3535
4140
  // #endregion
3536
4141
  // #region CONCURRENT/DEBOUNCE EXECUTION
4142
+ /**
4143
+ * Method decorator that serializes calls to an async (promise-returning) method on a per-instance basis:
4144
+ * while an invocation is in flight, further calls are queued (their arguments buffered) instead of running
4145
+ * concurrently, and each queued call gets its own promise that resolves/rejects once it eventually runs.
4146
+ * Once the in-flight call settles, the oldest buffered call (if any) is dequeued and executed next.
4147
+ * Methods that don't return a promise-like value are simply invoked synchronously with no queuing.
4148
+ *
4149
+ * @returns A method decorator to apply to an async instance method.
4150
+ */
3537
4151
  function Concurrent() {
3538
4152
  function isPromiseLike(obj) {
3539
4153
  return obj && typeof obj.then === 'function';
@@ -3584,6 +4198,15 @@
3584
4198
  };
3585
4199
  };
3586
4200
  }
4201
+ /**
4202
+ * Method decorator that debounces calls to an instance method: repeated calls within the debounce window
4203
+ * cancel the previously scheduled invocation and reschedule it, so only the last call in a rapid burst
4204
+ * actually runs (with its own arguments), after the window elapses.
4205
+ *
4206
+ * @param msecs Debounce delay in milliseconds, or `true` to debounce to the next animation frame (`requestAnimationFrame`) instead of a fixed delay. Defaults to `50`.
4207
+ * @param keyFactory Computes the per-instance timer key from the method name and call arguments; override to scope debouncing per argument (e.g. debounce separately per id) instead of per method. Defaults to a single shared key per method.
4208
+ * @returns A method decorator to apply to the instance method to debounce.
4209
+ */
3587
4210
  function Debounce(msecs = 50, keyFactory = (key, ...args) => `pacem:debouncer:${key}`) {
3588
4211
  return function (target /* type, actually */, key, descriptor) {
3589
4212
  const originalMethod = descriptor.value;
@@ -3609,6 +4232,16 @@
3609
4232
  }
3610
4233
  };
3611
4234
  }
4235
+ /**
4236
+ * Method decorator that throttles calls to an instance method: the first call in a window runs immediately;
4237
+ * further calls arriving before the window elapses are not dropped but coalesced — only the most recent
4238
+ * set of arguments is remembered and, once the window elapses, one trailing call runs with those arguments
4239
+ * (mirroring a classic "leading + trailing" throttle).
4240
+ *
4241
+ * @param msecs Throttle window in milliseconds, or `true` to use a single animation frame (`requestAnimationFrame`) as the window. Defaults to `50`.
4242
+ * @param keyFactory Computes the per-instance timer key from the method name and call arguments; override to scope throttling per argument instead of per method. Defaults to a single shared key per method.
4243
+ * @returns A method decorator to apply to the instance method to throttle.
4244
+ */
3612
4245
  function Throttle(msecs = 50, keyFactory = (key, ...args) => `pacem:throttler:${key}`) {
3613
4246
  return function (target /* type, actually */, key, descriptor) {
3614
4247
  const originalMethod = descriptor.value;
@@ -3658,6 +4291,14 @@
3658
4291
  }
3659
4292
  }
3660
4293
  };
4294
+ /**
4295
+ * Method decorator that registers a static/instance method as a globally-named {@link TransformFunction},
4296
+ * making it callable by name from template binding expressions (e.g. `{{ ^value | myTransform }}`).
4297
+ * The registration is global (attached under `Utils.core`, dot-segmented by `name`), not per-instance.
4298
+ *
4299
+ * @param name Dot-separated registration path (e.g. `'strings.upper'`); segments before the last create/reuse nested namespaces under `Utils.core`. Defaults to the decorated method's own name when omitted.
4300
+ * @returns A method decorator to apply to the transform function.
4301
+ */
3661
4302
  function Transformer(name) {
3662
4303
  return function (target, key, descriptor) {
3663
4304
  const method = descriptor.value;
@@ -3675,6 +4316,16 @@
3675
4316
  return c > 3 && r && Object.defineProperty(target, key, r), r;
3676
4317
  };
3677
4318
  //namespace Pacem.Components {
4319
+ /**
4320
+ * Base class for (almost) every Pacem custom element. Extends `HTMLElement` with the framework's
4321
+ * common lifecycle/event plumbing: `on-{event-type}` attribute handlers (see {@link emit}), a
4322
+ * {@link disabled} property that suppresses both outgoing (`dispatchEvent`) and incoming
4323
+ * (`emitHandler`) events, an optional {@link logger} sink, and an {@link isReady} flag toggled once
4324
+ * `viewActivatedCallback` has fired (see the {@link CustomElement} decorator for when that happens).
4325
+ * Concrete elements are expected to be decorated with `@CustomElement` and typically override
4326
+ * `propertyChangedCallback`/`viewActivatedCallback`/`connectedCallback`/`disconnectedCallback`,
4327
+ * calling `super.xxxCallback()` first/last as documented on each.
4328
+ */
3678
4329
  class PacemEventTarget extends HTMLElement {
3679
4330
  constructor() {
3680
4331
  super();
@@ -3857,12 +4508,14 @@
3857
4508
  return this._aria.attrs;
3858
4509
  }
3859
4510
  }
4511
+ /** Common base class for Pacem custom elements: adds ARIA support, CSS class/part/style bags, visibility, tab order and behaviors. */
3860
4512
  class PacemElement extends PacemEventTarget {
3861
4513
  constructor(role, aria) {
3862
4514
  super();
3863
4515
  this.#cssBag = [];
3864
4516
  this.#parts = [];
3865
4517
  this._tabIndex = -1;
4518
+ /** Gets or sets the list of behaviors to attach to this element. */
3866
4519
  this.behaviors = [];
3867
4520
  this._aria = new ElementAria(this, role, aria);
3868
4521
  }
@@ -4047,6 +4700,7 @@
4047
4700
  __decorate$H([
4048
4701
  Watch({ emit: false })
4049
4702
  ], PacemElement.prototype, "behaviors", void 0);
4703
+ /** Base class for elements whose (sanitized) inner content is driven by a `content` property, restoring the original markup on disconnect. */
4050
4704
  class PacemContentElement extends PacemElement {
4051
4705
  propertyChangedCallback(name, old, val, first) {
4052
4706
  super.propertyChangedCallback(name, old, val, first);
@@ -4090,11 +4744,13 @@
4090
4744
  __decorate$H([
4091
4745
  Watch({ emit: false, converter: PropertyConverters.String })
4092
4746
  ], PacemContentElement.prototype, "content", void 0);
4747
+ /** {@link PacemContentElement} variant that renders `content` verbatim, without any sanitization. */
4093
4748
  class PacemUnsafeContentElement extends PacemContentElement {
4094
4749
  sanitize(html) {
4095
4750
  return html;
4096
4751
  }
4097
4752
  }
4753
+ /** {@link PacemContentElement} variant that strips out `<script>` blocks (and, for `Node` content, `<script>` elements) before rendering `content`. */
4098
4754
  class PacemSafeContentElement extends PacemContentElement {
4099
4755
  _sanitizeLegacy(html) {
4100
4756
  if (Utils.isNullOrEmpty(html)) {
@@ -4126,6 +4782,7 @@
4126
4782
  }
4127
4783
  //}
4128
4784
 
4785
+ /** Base class for pluggable adapters that drive the focus/navigation behavior of a {@link PacemIterativeElement}. */
4129
4786
  class PacemAdapter extends PacemElement {
4130
4787
  constructor() {
4131
4788
  super(...arguments);
@@ -4254,6 +4911,10 @@
4254
4911
  const current = this._getAvailable();
4255
4912
  return ndx === this._getNextAvailable(current);
4256
4913
  }
4914
+ /**
4915
+ * Sets the master's index to the closest available item to the provided one.
4916
+ * @param ndx Desired index
4917
+ */
4257
4918
  select(ndx) {
4258
4919
  this._element.index = this._getAvailable(ndx);
4259
4920
  }
@@ -4277,6 +4938,7 @@
4277
4938
  return c > 3 && r && Object.defineProperty(target, key, r), r;
4278
4939
  };
4279
4940
  //namespace Pacem.Components {
4941
+ /** Removes itself from the DOM as soon as it gets connected; handy to strip out placeholder markup at runtime. */
4280
4942
  let PacemAnnihilatorElement = class PacemAnnihilatorElement extends HTMLElement {
4281
4943
  constructor() {
4282
4944
  super();
@@ -4297,6 +4959,7 @@
4297
4959
  return c > 3 && r && Object.defineProperty(target, key, r), r;
4298
4960
  };
4299
4961
  //namespace Pacem.Components {
4962
+ /** Warns the user (native `beforeunload` prompt or router-driven confirm dialog) before leaving the page. */
4300
4963
  let PacemBeforeunloadElement = class PacemBeforeunloadElement extends PacemEventTarget {
4301
4964
  constructor() {
4302
4965
  super(...arguments);
@@ -4343,9 +5006,11 @@
4343
5006
  return c > 3 && r && Object.defineProperty(target, key, r), r;
4344
5007
  };
4345
5008
  //namespace Pacem.Components {
5009
+ /** Wraps a {@link BroadcastChannel}, sending/receiving messages to/from other same-origin browsing contexts. */
4346
5010
  let PacemBroadcastChannelProxyElement = class PacemBroadcastChannelProxyElement extends PacemEventTarget {
4347
5011
  constructor() {
4348
5012
  super(...arguments);
5013
+ /** Gets or sets whether to automatically send `message` as soon as it changes (default `true`). */
4349
5014
  this.autosend = true;
4350
5015
  this._messageHandler = (evt) => {
4351
5016
  this.result = evt.data;
@@ -4381,6 +5046,10 @@
4381
5046
  this._disposeChannel();
4382
5047
  super.disconnectedCallback();
4383
5048
  }
5049
+ /**
5050
+ * Posts a message through the channel.
5051
+ * @param message Message to send; defaults to the current `message` property
5052
+ */
4384
5053
  send(message = this.message) {
4385
5054
  if (this.disabled) {
4386
5055
  return;
@@ -4433,6 +5102,7 @@
4433
5102
  return c > 3 && r && Object.defineProperty(target, key, r), r;
4434
5103
  };
4435
5104
  //namespace Pacem.Components {
5105
+ /** Detects the name and version of the current (or a provided) browser user agent. */
4436
5106
  let PacemBrowserDetectElement = class PacemBrowserDetectElement extends PacemEventTarget {
4437
5107
  viewActivatedCallback() {
4438
5108
  super.viewActivatedCallback();
@@ -4446,9 +5116,11 @@
4446
5116
  }
4447
5117
  #browser;
4448
5118
  #version;
5119
+ /** @readonly Gets the detected browser name. */
4449
5120
  get browser() {
4450
5121
  return this.#browser;
4451
5122
  }
5123
+ /** @readonly Gets the detected browser version. */
4452
5124
  get version() {
4453
5125
  return this.#version;
4454
5126
  }
@@ -4475,6 +5147,12 @@
4475
5147
 
4476
5148
  //namespace Pacem {
4477
5149
  const EXPIRATION_FIELD = '_exp';
5150
+ /**
5151
+ * JSON-serializing wrapper around `sessionStorage`/`localStorage` that transparently supports per-key
5152
+ * expiration: values stored with a `duration` are stamped with an expiry timestamp and evicted lazily
5153
+ * (checked on the next {@link getPropertyValue} call for that key, not via a timer). Session storage and
5154
+ * local storage are treated as a single logical namespace - storing a key in one clears any same-named entry in the other.
5155
+ */
4478
5156
  class Storage {
4479
5157
  _getStorage(persistent) {
4480
5158
  return !!persistent ? window.localStorage : window.sessionStorage;
@@ -4509,10 +5187,16 @@
4509
5187
  storage = this._getStorage(!persistent);
4510
5188
  storage.removeItem(name);
4511
5189
  }
5190
+ /**
5191
+ * Retrieves a previously stored value by `name`, checking session storage first, then local storage.
5192
+ * Returns `null` if not found, or if found but past its expiration.
5193
+ * @param name The unique key.
5194
+ */
4512
5195
  getPropertyValue(name) {
4513
5196
  return this._parseValue(this._getStorage(false), name)
4514
5197
  || this._parseValue(this._getStorage(true), name);
4515
5198
  }
5199
+ /** Clears both session and local storage entirely. */
4516
5200
  clear() {
4517
5201
  var storage = this._getStorage(true);
4518
5202
  storage.clear();
@@ -4520,6 +5204,7 @@
4520
5204
  storage.clear();
4521
5205
  }
4522
5206
  ;
5207
+ /** Removes a single entry by `name` from both session and local storage. */
4523
5208
  removeProperty(name) {
4524
5209
  var storage = this._getStorage(true);
4525
5210
  storage.removeItem(name);
@@ -4536,6 +5221,7 @@
4536
5221
  return c > 3 && r && Object.defineProperty(target, key, r), r;
4537
5222
  };
4538
5223
  //namespace Pacem.Components {
5224
+ /** Holds an arbitrary data model, optionally persisting it to local storage and debouncing/throttling change notifications. */
4539
5225
  let PacemDataElement = class PacemDataElement extends PacemEventTarget {
4540
5226
  constructor(storage = new Storage()) {
4541
5227
  super();
@@ -4731,6 +5417,7 @@
4731
5417
  return c > 3 && r && Object.defineProperty(target, key, r), r;
4732
5418
  };
4733
5419
  //namespace Pacem.Components {
5420
+ /** Base class for elements that move their own content to another DOM location, restoring nothing on disconnect. */
4734
5421
  class PacemTransferProxyElement extends PacemEventTarget {
4735
5422
  constructor() {
4736
5423
  super(...arguments);
@@ -4836,6 +5523,7 @@
4836
5523
  return PropertyConverters.Element.convertBack(prop, element);
4837
5524
  }
4838
5525
  };
5526
+ /** Listens for an arbitrary DOM event on a `target` element (or `window`) and re-dispatches it as its own `emit` event. */
4839
5527
  let PacemEventProxyElement = class PacemEventProxyElement extends PacemEventTarget {
4840
5528
  constructor() {
4841
5529
  super(...arguments);
@@ -4908,11 +5596,13 @@
4908
5596
  };
4909
5597
  //namespace Pacem.Components {
4910
5598
  const ABORT_MESSAGE = "New incoming request overrides the ongoing one. Aborting.";
5599
+ /** Declarative wrapper around the `fetch()` API, debouncing/aborting requests as its properties change and exposing the parsed `result`. */
4911
5600
  let PacemFetchElement = class PacemFetchElement extends PacemEventTarget {
4912
5601
  constructor() {
4913
5602
  super(...arguments);
4914
5603
  /** Gets or sets whether to trigger a fetch whenever a significant property has changed (default: true). */
4915
5604
  this.autofetch = true;
5605
+ /** Gets or sets the debounce delay (in milliseconds) applied before auto-triggered fetches (default `100`). */
4916
5606
  this.debounce = 100;
4917
5607
  }
4918
5608
  viewActivatedCallback() {
@@ -5171,6 +5861,7 @@
5171
5861
  super(type, { detail });
5172
5862
  }
5173
5863
  }
5864
+ /** Keeps track of an undo/redo-capable history of an arbitrary state. */
5174
5865
  let PacemHistoryElement = class PacemHistoryElement extends PacemEventTarget {
5175
5866
  #history;
5176
5867
  propertyChangedCallback(name, old, val, first) {
@@ -5204,6 +5895,7 @@
5204
5895
  this.#history = new pacemFoundation.HistoryService(val, this.maxlength);
5205
5896
  }
5206
5897
  }
5898
+ /** Moves the state forward one step, if `canRedo` is `true`. */
5207
5899
  redo() {
5208
5900
  const h = this.#history;
5209
5901
  if (!Utils.isNull(h)) {
@@ -5212,6 +5904,7 @@
5212
5904
  this._synchronize('redo');
5213
5905
  }
5214
5906
  }
5907
+ /** Clears the history stack, keeping only the current state. */
5215
5908
  reset() {
5216
5909
  const h = this.#history;
5217
5910
  if (!Utils.isNull(h)) {
@@ -5220,6 +5913,7 @@
5220
5913
  this._synchronize('reset');
5221
5914
  }
5222
5915
  }
5916
+ /** Moves the state back one step, if `canUndo` is `true`. */
5223
5917
  undo() {
5224
5918
  const h = this.#history;
5225
5919
  if (!Utils.isNull(h)) {
@@ -5261,6 +5955,7 @@
5261
5955
  return c > 3 && r && Object.defineProperty(target, key, r), r;
5262
5956
  };
5263
5957
  //namespace Pacem.Components {
5958
+ /** Sets (or removes) an attribute on the document's root `<html>` element. */
5264
5959
  let PacemHtmlProxyElement = class PacemHtmlProxyElement extends PacemEventTarget {
5265
5960
  constructor() {
5266
5961
  super(...arguments);
@@ -5309,6 +6004,7 @@
5309
6004
  return c > 3 && r && Object.defineProperty(target, key, r), r;
5310
6005
  };
5311
6006
  //namespace Pacem.Components {
6007
+ /** Conditionally shows or clears its own inner content, restoring the original markup whenever `match` becomes truthy again. */
5312
6008
  let PacemIfElement = class PacemIfElement extends HTMLElement {
5313
6009
  #innerHTML;
5314
6010
  propertyChangedCallback(name, old, val, first) {
@@ -5339,6 +6035,7 @@
5339
6035
  return c > 3 && r && Object.defineProperty(target, key, r), r;
5340
6036
  };
5341
6037
  //namespace Pacem.Components {
6038
+ /** Base class for elements that register themselves against an ancestor {@link PacemItemsContainerElement}. */
5342
6039
  class PacemItemElement extends PacemElement {
5343
6040
  get container() {
5344
6041
  return this._container;
@@ -5444,6 +6141,7 @@
5444
6141
  __decorate$u([
5445
6142
  Watch( /* can only be databound or assigned at runtime */)
5446
6143
  ], PacemCrossItemsContainerElement.prototype, "items", void 0);
6144
+ /** Base class for container elements holding a registry of {@link PacemItemElement} children. */
5447
6145
  class PacemItemsContainerElement extends PacemElement {
5448
6146
  constructor(role, aria) {
5449
6147
  super(role, aria);
@@ -5476,6 +6174,7 @@
5476
6174
  return c > 3 && r && Object.defineProperty(target, key, r), r;
5477
6175
  };
5478
6176
  //namespace Pacem.Components {
6177
+ /** Base class for items belonging to a {@link PacemIterativeElement}, forwarding their property changes to the master's `adapter`. */
5479
6178
  class PacemIterableElement extends PacemItemElement {
5480
6179
  /** @overrides */
5481
6180
  findContainer() {
@@ -5491,6 +6190,7 @@
5491
6190
  && iter.adapter.itemPropertyChangedCallback(index, name, old, val, first);
5492
6191
  }
5493
6192
  }
6193
+ /** Base class for container elements whose items are driven by a pluggable {@link PacemAdapter}, tracking a `current` `index`. */
5494
6194
  class PacemIterativeElement extends PacemItemsContainerElement {
5495
6195
  propertyChangedCallback(name, old, val, first) {
5496
6196
  super.propertyChangedCallback(name, old, val, first);
@@ -5548,6 +6248,7 @@
5548
6248
  //namespace Pacem.Components {
5549
6249
  const REMOVE_VALUE = 'false';
5550
6250
  const EMPTY_VALUE = 'true';
6251
+ /** Sets (or removes) an attribute on the closest ancestor shell element, e.g. to drive layout-wide CSS state. */
5551
6252
  let PacemLayoutProxyElement = class PacemLayoutProxyElement extends PacemEventTarget {
5552
6253
  #shell;
5553
6254
  connectedCallback() {
@@ -5601,6 +6302,7 @@
5601
6302
  return c > 3 && r && Object.defineProperty(target, key, r), r;
5602
6303
  };
5603
6304
  //namespace Pacem.Components {
6305
+ /** Creates, updates or removes a `<meta>` element in the document `<head>`, keyed by either `name` or `itemprop`. */
5604
6306
  let PacemMetaProxyElement = class PacemMetaProxyElement extends PacemEventTarget {
5605
6307
  propertyChangedCallback(name, old, val, first) {
5606
6308
  super.propertyChangedCallback(name, old, val, first);
@@ -5662,6 +6364,7 @@
5662
6364
  return c > 3 && r && Object.defineProperty(target, key, r), r;
5663
6365
  };
5664
6366
  //namespace Pacem.Components {
6367
+ /** Tracks the browser's network connectivity (`navigator.onLine`), updating `online` on `online`/`offline` events. */
5665
6368
  let PacemOnlineStatusElement = class PacemOnlineStatusElement extends PacemEventTarget {
5666
6369
  constructor() {
5667
6370
  super(...arguments);
@@ -5704,6 +6407,7 @@
5704
6407
  return c > 3 && r && Object.defineProperty(target, key, r), r;
5705
6408
  };
5706
6409
  //namespace Pacem.Components {
6410
+ /** Plain generic-purpose container element, useful as a databinding/behaviors host wherever a `<div>` would do. */
5707
6411
  let PacemPanelElement = class PacemPanelElement extends PacemSafeContentElement {
5708
6412
  };
5709
6413
  PacemPanelElement = __decorate$p([
@@ -5713,7 +6417,12 @@
5713
6417
 
5714
6418
  /// <reference path="events.ts" />
5715
6419
  //namespace Pacem {
6420
+ /** Event name dispatched to signal a generic, named command invocation; see {@link CommandEvent}. */
5716
6421
  const CommandEventName = 'command';
6422
+ /**
6423
+ * Bubbling, cancelable event representing a generic UI command (e.g. a button's `command`/`command-argument`
6424
+ * attributes), letting ancestor elements handle named actions without wiring a dedicated listener per command.
6425
+ */
5717
6426
  class CommandEvent extends CustomTypedEvent {
5718
6427
  constructor(args) {
5719
6428
  super(CommandEventName, args, { bubbles: true, cancelable: true });
@@ -5728,6 +6437,7 @@
5728
6437
  return c > 3 && r && Object.defineProperty(target, key, r), r;
5729
6438
  };
5730
6439
  //namespace Pacem.Components {
6440
+ /** Redirects consumers (e.g. {@link PacemRepeaterElement}) to an external `<template>` element, firing a `templatechange` event when it changes. */
5731
6441
  let PacemTemplateProxyElement = class PacemTemplateProxyElement extends /*PacemEventTarget*/ /*PacemEventTarget*/ TemplateElement {
5732
6442
  propertyChangedCallback(name, old, val, first) {
5733
6443
  // super.propertyChangedCallback(name, old, val, first);
@@ -5782,6 +6492,8 @@
5782
6492
  }
5783
6493
  //
5784
6494
  /**
6495
+ * Repeats its `<template>` content once per `datasource` item, keeping the rendered items in sync as the datasource changes.
6496
+ * @example
5785
6497
  * <pacem-repeater datasource="[{id:'first', items:['a','b','c']}, ...]">
5786
6498
  * <ol>
5787
6499
  * <li>
@@ -5813,6 +6525,7 @@
5813
6525
  this._databind();
5814
6526
  };
5815
6527
  }
6528
+ /** Removes the rendered item at the given index. */
5816
6529
  removeItem(index) {
5817
6530
  this._removeItems(index, index);
5818
6531
  }
@@ -5841,6 +6554,7 @@
5841
6554
  item.remove();
5842
6555
  }
5843
6556
  }
6557
+ /** Forces a full re-render of the items against the current `datasource`. */
5844
6558
  databind() {
5845
6559
  this._databind();
5846
6560
  }
@@ -6038,6 +6752,7 @@
6038
6752
  }
6039
6753
  }
6040
6754
  const BORDER_BOX = { box: 'border-box' };
6755
+ /** Observes size (and, optionally, position) changes of itself or a `target` element, firing a `resize` event accordingly. */
6041
6756
  let PacemResizeElement = class PacemResizeElement extends PacemEventTarget {
6042
6757
  constructor() {
6043
6758
  super(...arguments);
@@ -6136,6 +6851,7 @@
6136
6851
  this._dispatchResize();
6137
6852
  }
6138
6853
  }
6854
+ /** @readonly Gets the last measured size (and position, if `watchPosition` is set) of the observed target. */
6139
6855
  get currentSize() {
6140
6856
  var args = { height: this._previousHeight, width: this._previousWidth };
6141
6857
  if (this.watchPosition) {
@@ -6175,6 +6891,7 @@
6175
6891
  };
6176
6892
  //namespace Pacem.Components {
6177
6893
  const CHECK_PATTERN = /^([\w\.]:)?\/\/[^\/]+/;
6894
+ /** Client-side router: parses/generates paths against a template and drives the browser History API. */
6178
6895
  let PacemRouterElement = class PacemRouterElement extends PacemEventTarget {
6179
6896
  constructor() {
6180
6897
  super(...arguments);
@@ -6196,6 +6913,10 @@
6196
6913
  }
6197
6914
  #cancelingNavigation;
6198
6915
  #template;
6916
+ /**
6917
+ * Merges the provided partial state into the current one and returns the resulting parsed {@link RouterState}, without navigating.
6918
+ * @param state Piece of new state to be merged
6919
+ */
6199
6920
  parseState(state = {}) {
6200
6921
  const path = this._stringifyMergedState(state);
6201
6922
  const segments = this._segmentateUrl(path);
@@ -6455,6 +7176,7 @@
6455
7176
  }
6456
7177
  return output;
6457
7178
  }
7179
+ /** Registers a service worker and manages its (optional) Push API subscription. */
6458
7180
  let PacemServiceWorkerProxyElement = class PacemServiceWorkerProxyElement extends PacemEventTarget {
6459
7181
  viewActivatedCallback() {
6460
7182
  super.viewActivatedCallback();
@@ -6507,6 +7229,10 @@
6507
7229
  }
6508
7230
  });
6509
7231
  }
7232
+ /**
7233
+ * Unsubscribes from push notifications.
7234
+ * @param subscription Subscription to cancel; defaults to the current `pushSubscription`
7235
+ */
6510
7236
  unsubscribe(subscription = this.pushSubscription) {
6511
7237
  return new Promise((resolve, reject) => {
6512
7238
  if (!Utils.isNull(subscription)) {
@@ -6524,6 +7250,10 @@
6524
7250
  }
6525
7251
  });
6526
7252
  }
7253
+ /**
7254
+ * Subscribes to push notifications through the registered service worker.
7255
+ * @param publicKey VAPID public key (base64url or raw bytes); defaults to `publicKey`
7256
+ */
6527
7257
  subscribe(publicKey = this.publicKey) {
6528
7258
  return new Promise((resolve, reject) => {
6529
7259
  if (typeof publicKey === 'string') {
@@ -6611,6 +7341,7 @@
6611
7341
  || (/^arrow/.test(key) && (piece === key.substr(5)));
6612
7342
  }
6613
7343
  const KeyboardShortcutExecuteEventName = "execute";
7344
+ /** Listens for a keyboard shortcut (optionally chorded, e.g. `"ctrl+k, s"`) on a target and fires an `execute` event when matched. */
6614
7345
  let PacemShortcutElement = class PacemShortcutElement extends PacemEventTarget {
6615
7346
  constructor() {
6616
7347
  super(...arguments);
@@ -6668,6 +7399,7 @@
6668
7399
  return c > 3 && r && Object.defineProperty(target, key, r), r;
6669
7400
  };
6670
7401
  //namespace Pacem.Components {
7402
+ /** Sets its own `textContent` to the `text` property, escaping any markup. */
6671
7403
  let PacemSpanElement = class PacemSpanElement extends PacemSafeContentElement {
6672
7404
  propertyChangedCallback(name, old, val, first) {
6673
7405
  super.propertyChangedCallback(name, old, val, first);
@@ -6697,6 +7429,7 @@
6697
7429
  return c > 3 && r && Object.defineProperty(target, key, r), r;
6698
7430
  };
6699
7431
  //namespace Pacem.Components {
7432
+ /** Injects a `<style>` element into the document `<head>`, populated either inline (`cssText`) or by fetching `src`. */
6700
7433
  let PacemStyleProxyElement = class PacemStyleProxyElement extends PacemEventTarget {
6701
7434
  propertyChangedCallback(name, old, val, first) {
6702
7435
  super.propertyChangedCallback(name, old, val, first);
@@ -6797,6 +7530,7 @@
6797
7530
  return c > 3 && r && Object.defineProperty(target, key, r), r;
6798
7531
  };
6799
7532
  //namespace Pacem.Components {
7533
+ /** Renders the `text` property as its own plain-text content, replacing any existing child markup. */
6800
7534
  let PacemTextElement = class PacemTextElement extends HTMLElement {
6801
7535
  constructor() {
6802
7536
  super();
@@ -6828,6 +7562,7 @@
6828
7562
  return c > 3 && r && Object.defineProperty(target, key, r), r;
6829
7563
  };
6830
7564
  //namespace Pacem.Components {
7565
+ /** Fires a `tick` event on a regular interval, as long as it's enabled and `interval` is greater than zero. */
6831
7566
  let PacemTimerElement = class PacemTimerElement extends PacemEventTarget {
6832
7567
  constructor() {
6833
7568
  super();
@@ -6874,6 +7609,7 @@
6874
7609
  return c > 3 && r && Object.defineProperty(target, key, r), r;
6875
7610
  };
6876
7611
  //namespace Pacem.Components {
7612
+ /** Sets `document.title` to `value` whenever it changes. */
6877
7613
  let PacemTitleProxyElement = class PacemTitleProxyElement extends PacemEventTarget {
6878
7614
  propertyChangedCallback(name, old, val, first) {
6879
7615
  super.propertyChangedCallback(name, old, val, first);
@@ -6909,10 +7645,12 @@
6909
7645
  return c > 3 && r && Object.defineProperty(target, key, r), r;
6910
7646
  };
6911
7647
  //namespace Pacem.Components {
7648
+ /** Animates a numeric `value` from `from` to `to` over `duration`, dispatching animation lifecycle events along the way. */
6912
7649
  let PacemTweenElement = class PacemTweenElement extends PacemEventTarget {
6913
7650
  constructor(_tweener = new TweenService()) {
6914
7651
  super();
6915
7652
  this._tweener = _tweener;
7653
+ /** Gets or sets the animation duration, in milliseconds (default `1000`). */
6916
7654
  this.duration = 1000;
6917
7655
  }
6918
7656
  propertyChangedCallback(name, old, val, first) {
@@ -6922,6 +7660,7 @@
6922
7660
  this._animate();
6923
7661
  }
6924
7662
  }
7663
+ /** Starts the animation programmatically and returns a promise resolved once it completes. */
6925
7664
  run() {
6926
7665
  return this._animate();
6927
7666
  }
@@ -7071,9 +7810,11 @@
7071
7810
  return c > 3 && r && Object.defineProperty(target, key, r), r;
7072
7811
  };
7073
7812
  //namespace Pacem.Components {
7813
+ /** Wraps a {@link Worker}, sending/receiving messages to/from a web worker script. */
7074
7814
  let PacemWebWorkerProxyElement = class PacemWebWorkerProxyElement extends PacemEventTarget {
7075
7815
  constructor() {
7076
7816
  super(...arguments);
7817
+ /** Gets or sets whether to automatically send `message` as soon as it changes (default `true`). */
7077
7818
  this.autosend = true;
7078
7819
  this._messageHandler = (evt) => {
7079
7820
  this.result = evt.data;
@@ -7109,6 +7850,10 @@
7109
7850
  this._disposeWorker();
7110
7851
  super.disconnectedCallback();
7111
7852
  }
7853
+ /**
7854
+ * Posts a message to the worker.
7855
+ * @param message Message to send; defaults to the current `message` property
7856
+ */
7112
7857
  send(message = this.message) {
7113
7858
  if (this.disabled) {
7114
7859
  return;
@@ -7154,8 +7899,16 @@
7154
7899
  //}
7155
7900
 
7156
7901
  //namespace Pacem.Behaviors{
7902
+ /**
7903
+ * Base class for the "behavior" custom elements (drag & drop, swipe, rotate, rescale, ...) that attach
7904
+ * gesture-driven functionality to a set of registered elements without rendering anything of their own.
7905
+ */
7157
7906
  class PacemBehavior extends PacemEventTarget {
7158
7907
  #items = new WeakSet();
7908
+ /**
7909
+ * Registers an element with this behavior, decorating it if it wasn't already registered.
7910
+ * @param element Element to register.
7911
+ */
7159
7912
  register(element) {
7160
7913
  var container = this.#items;
7161
7914
  if (!container.has(element)) {
@@ -7163,6 +7916,10 @@
7163
7916
  this.decorate(element);
7164
7917
  }
7165
7918
  }
7919
+ /**
7920
+ * Unregisters a previously registered element, undecorating it.
7921
+ * @param element Element to unregister.
7922
+ */
7166
7923
  unregister(element) {
7167
7924
  var container = this.#items;
7168
7925
  if (container.has(element)) {
@@ -7170,6 +7927,7 @@
7170
7927
  container.delete(element);
7171
7928
  }
7172
7929
  }
7930
+ /** @readonly Determines whether the given element is currently registered with this behavior. */
7173
7931
  has(element) {
7174
7932
  return this.#items.has(element);
7175
7933
  }
@@ -7591,7 +8349,8 @@
7591
8349
  }
7592
8350
  }
7593
8351
  /**
7594
- * Pacem Drag & Drop element adapter.
8352
+ * Pacem Drag & Drop element adapter: implements {@link DragDropper} on top of {@link PacemBehavior} to make
8353
+ * registered elements draggable and, optionally, sortable/droppable onto {@link dropTargets}.
7595
8354
  */
7596
8355
  let PacemDragDropElement = class PacemDragDropElement extends PacemBehavior {
7597
8356
  constructor() {
@@ -7655,23 +8414,28 @@
7655
8414
  /** Gets or sets the drag mode ("self", "alias", "copy"). */
7656
8415
  this.mode = DragDataMode.Self;
7657
8416
  }
8417
+ /** Wires up the `mousedown`/`touchstart` listeners that arm the drag gesture on the given element. */
7658
8418
  decorate(element) {
7659
8419
  const options = { capture: false, passive: false };
7660
8420
  // TODO: add special effects starting the drag process after a while (timeout) the element is pressed.
7661
8421
  element.addEventListener('mousedown', this._startHandler, false);
7662
8422
  element.addEventListener('touchstart', this._startHandler, options);
7663
8423
  }
8424
+ /** Removes the listeners set up by {@link decorate}. */
7664
8425
  undecorate(element) {
7665
8426
  const options = { capture: false, passive: false };
7666
8427
  element.removeEventListener('mousedown', this._startHandler, false);
7667
8428
  element.removeEventListener('touchstart', this._startHandler, options);
7668
8429
  }
8430
+ /** Registers a listener for a {@link DragDropEventType} lifecycle event. */
7669
8431
  addEventListener(type, listener, useCapture) {
7670
8432
  super.addEventListener(type, listener, useCapture);
7671
8433
  }
8434
+ /** Unregisters a listener previously added for a {@link DragDropEventType} lifecycle event. */
7672
8435
  removeEventListener(type, listener, useCapture) {
7673
8436
  super.removeEventListener(type, listener, useCapture);
7674
8437
  }
8438
+ /** Dispatches a {@link DragDropEvent}, clearing internal per-element bookkeeping once the drag ends. */
7675
8439
  dispatchEvent(evt) {
7676
8440
  if (evt.type === DragDropEventType.End) {
7677
8441
  DEL_VAL$3(evt.detail.element, MOUSE_DOWN$2);
@@ -7854,6 +8618,10 @@
7854
8618
  const RESCALE_FRAME = 'pacem:rescale:frame';
7855
8619
  const MOUSE_DOWN$1 = 'pacem:rescale:origin';
7856
8620
  const DELEGATE$1 = 'pacem:rescale:delegate';
8621
+ /**
8622
+ * Pacem Rescale element adapter: implements {@link Rescaler} on top of {@link PacemBehavior}, decorating
8623
+ * registered elements with draggable resize handles (see {@link RescaleHandle}).
8624
+ */
7857
8625
  let PacemRescaleElement = class PacemRescaleElement extends PacemBehavior {
7858
8626
  constructor() {
7859
8627
  super(...arguments);
@@ -7881,11 +8649,13 @@
7881
8649
  /* logging */ (level, message, category) => this.log.apply(this, [level, message, category])));
7882
8650
  };
7883
8651
  }
8652
+ /** Adds the resize-handle frame (see {@link RescaleHandle}) around the given element. */
7884
8653
  decorate(element) {
7885
8654
  const el = element; getComputedStyle(el);
7886
8655
  Utils.addClass(el, PCSS + '-rescalable');
7887
8656
  this._setFrame(el);
7888
8657
  }
8658
+ /** Removes the resize-handle frame set up by {@link decorate}. */
7889
8659
  undecorate(element) {
7890
8660
  const el = element;
7891
8661
  Utils.removeClass(el, PCSS + '-rescalable');
@@ -8069,6 +8839,10 @@
8069
8839
  return x;
8070
8840
  }
8071
8841
  }
8842
+ /**
8843
+ * Pacem Rotate element adapter: implements {@link Rotator} on top of {@link PacemBehavior} to make
8844
+ * registered elements rotatable around a pivot point via mouse/touch drag.
8845
+ */
8072
8846
  let PacemRotateElement = class PacemRotateElement extends PacemBehavior {
8073
8847
  constructor() {
8074
8848
  super(...arguments);
@@ -8106,6 +8880,7 @@
8106
8880
  /* logging */ (level, message, category) => this.log.apply(this, [level, message, category])));
8107
8881
  };
8108
8882
  }
8883
+ /** Wires up the `mousedown`/`touchstart` listeners that arm the rotate gesture on the given element. */
8109
8884
  decorate(element) {
8110
8885
  const el = element;
8111
8886
  Utils.addClass(el, PCSS + '-rotatable');
@@ -8113,6 +8888,7 @@
8113
8888
  element.addEventListener('mousedown', this._startHandler, false);
8114
8889
  element.addEventListener('touchstart', this._startHandler, options);
8115
8890
  }
8891
+ /** Removes the listeners set up by {@link decorate}. */
8116
8892
  undecorate(element) {
8117
8893
  const el = element;
8118
8894
  Utils.removeClass(el, PCSS + '-rotatable');
@@ -8344,6 +9120,10 @@
8344
9120
  window.removeEventListener('pointerup', this._endHandler);
8345
9121
  }
8346
9122
  }
9123
+ /**
9124
+ * Pacem Swipe element adapter: implements {@link Swiper} on top of {@link PacemBehavior} to make
9125
+ * registered elements draggable along one axis, with snap points and fling/bounce-back detection.
9126
+ */
8347
9127
  let PacemSwipeElement = class PacemSwipeElement extends PacemBehavior {
8348
9128
  constructor() {
8349
9129
  super(...arguments);
@@ -8396,6 +9176,7 @@
8396
9176
  this._undo(el);
8397
9177
  };
8398
9178
  }
9179
+ /** Wires up the `pointerdown` listener that arms the swipe gesture on the given element. */
8399
9180
  decorate(element) {
8400
9181
  // https://docs.microsoft.com/en-us/microsoft-edge/dev-guide/dom/pointer-events
8401
9182
  if (element instanceof HTMLElement || element instanceof SVGElement) {
@@ -8403,6 +9184,7 @@
8403
9184
  }
8404
9185
  element.addEventListener('pointerdown', this._prepareHandler, false);
8405
9186
  }
9187
+ /** Removes the listener set up by {@link decorate}. */
8406
9188
  undecorate(element) {
8407
9189
  if (element instanceof HTMLElement || element instanceof SVGElement) {
8408
9190
  Utils.removeClass(element, PCSS + '-swipe');
@@ -8467,6 +9249,10 @@
8467
9249
  const EasingConverter = {
8468
9250
  convert: (attr) => Easings[attr] ?? Easings.linear
8469
9251
  };
9252
+ /**
9253
+ * Abstract base class for the `@CustomElement` animation items (color/number/point animations) that can be
9254
+ * hosted within a {@link PacemStoryboardElement}. Implements {@link Timeline}.
9255
+ */
8470
9256
  class AnimationElement extends PacemItemElement {
8471
9257
  }
8472
9258
  __decorate$5([
@@ -8490,15 +9276,21 @@
8490
9276
  __decorate$5([
8491
9277
  Watch({ emit: false, converter: PropertyConverters.String })
8492
9278
  ], AnimationElement.prototype, "direction", void 0);
9279
+ /**
9280
+ * Base class for animation elements that interpolate their `from`/`to` value via {@link TweenService}.
9281
+ * Concrete subclasses only need to supply {@link tweenInterpolationCallback} to map normalized progress to a value of type `T`.
9282
+ */
8493
9283
  class TweenAnimationElement extends AnimationElement {
8494
9284
  constructor(_tweener = new TweenService()) {
8495
9285
  super();
8496
9286
  this._tweener = _tweener;
8497
9287
  }
9288
+ /** @readonly Gets the {@link TweenService} instance driving this animation. */
8498
9289
  get tweener() {
8499
9290
  return this._tweener;
8500
9291
  }
8501
9292
  #cancelToken = false;
9293
+ /** Starts (or restarts) the tween and returns a promise resolved once it completes. */
8502
9294
  startAnimation() {
8503
9295
  this.#cancelToken = false;
8504
9296
  return new Promise((resolve, _) => {
@@ -8511,6 +9303,7 @@
8511
9303
  .then(resolve);
8512
9304
  });
8513
9305
  }
9306
+ /** Cancels the running tween. */
8514
9307
  cancelAnimation() {
8515
9308
  this.#cancelToken = true;
8516
9309
  }
@@ -8525,6 +9318,7 @@
8525
9318
  //namespace Pacem.Components {
8526
9319
  const DEFAULT_FROM$2 = { h: 0, l: 0, s: 0.5, a: 1 };
8527
9320
  const DEFAULT_TO$2 = { h: 0, l: 1, s: 0.5, a: 1 };
9321
+ /** Animates a CSS color `target[property]` from `from` to `to` (interpolated in HSLA space) over `duration`. */
8528
9322
  let PacemColorAnimationElement = class PacemColorAnimationElement extends TweenAnimationElement {
8529
9323
  propertyChangedCallback(name, old, val, first) {
8530
9324
  super.propertyChangedCallback(name, old, val, first);
@@ -8568,6 +9362,7 @@
8568
9362
  _parseColor(clr) {
8569
9363
  return pacemFoundation.Colors.hsl(pacemFoundation.Colors.parse(clr));
8570
9364
  }
9365
+ /** @inheritdoc */
8571
9366
  tweenInterpolationCallback(time, progress) {
8572
9367
  const from = this.#from, to = this.#to;
8573
9368
  const hsla = {
@@ -8598,7 +9393,9 @@
8598
9393
  //namespace Pacem.Components {
8599
9394
  const DEFAULT_FROM$1 = 0;
8600
9395
  const DEFAULT_TO$1 = 1;
9396
+ /** Animates a numeric `target[property]` from `from` to `to` over `duration`. */
8601
9397
  let PacemNumberAnimationElement = class PacemNumberAnimationElement extends TweenAnimationElement {
9398
+ /** @inheritdoc */
8602
9399
  tweenInterpolationCallback(time, progress) {
8603
9400
  const to = this.to ?? DEFAULT_TO$1, from = this.from ?? DEFAULT_FROM$1;
8604
9401
  return (to - from) * progress + from;
@@ -8623,7 +9420,9 @@
8623
9420
  //namespace Pacem.Components {
8624
9421
  const DEFAULT_FROM = { x: 0, y: 0 };
8625
9422
  const DEFAULT_TO = { x: 1, y: 1 };
9423
+ /** Animates a {@link Point} `target[property]` from `from` to `to` over `duration`. */
8626
9424
  let PacemPointAnimationElement = class PacemPointAnimationElement extends TweenAnimationElement {
9425
+ /** @inheritdoc */
8627
9426
  tweenInterpolationCallback(time, progress) {
8628
9427
  const to = this.to ?? DEFAULT_TO, from = this.from ?? DEFAULT_FROM;
8629
9428
  return {
@@ -8650,7 +9449,12 @@
8650
9449
  return c > 3 && r && Object.defineProperty(target, key, r), r;
8651
9450
  };
8652
9451
  //namespace Pacem.Components {
9452
+ /**
9453
+ * Groups one or more {@link Timeline}s (either {@link AnimationElement} child items or an explicit
9454
+ * `datasource`) and starts/cancels them together, optionally on view activation via `autostart`.
9455
+ */
8653
9456
  let PacemStoryboardElement = class PacemStoryboardElement extends PacemItemsContainerElement {
9457
+ /** @inheritdoc */
8654
9458
  validate(item) {
8655
9459
  return item instanceof AnimationElement;
8656
9460
  }
@@ -8691,12 +9495,14 @@
8691
9495
  }
8692
9496
  return Promise.all(promises);
8693
9497
  }
9498
+ /** Cancels every running {@link Timeline} in this storyboard. */
8694
9499
  cancelAnimation() {
8695
9500
  const ds = this._adaptedDatasource || [];
8696
9501
  for (let timeline of ds) {
8697
9502
  timeline.cancelAnimation();
8698
9503
  }
8699
9504
  }
9505
+ /** Starts (or restarts) every {@link Timeline} in this storyboard. */
8700
9506
  startAnimation() {
8701
9507
  return this._animate(true);
8702
9508
  }
@@ -8806,13 +9612,16 @@
8806
9612
  });
8807
9613
 
8808
9614
  //namespace Pacem {
9615
+ /** Framework-wide default settings. */
8809
9616
  const Defaults = {
8810
9617
  USE_SHADOW_ROOT: /*'attachShadow' in Element.prototype &&*/ false /* <- wait until html-imports */
8811
9618
  };
8812
9619
  //}
8813
9620
 
8814
9621
  //namespace Pacem.RegularExpressions {
9622
+ /** A pattern that can never match any string (`/a^/`); useful as a safe no-op default for optional matcher parameters. */
8815
9623
  const EMPTY_MATCHER = /a^/;
9624
+ /** Static regular-expression helpers. */
8816
9625
  class Regex {
8817
9626
  /**
8818
9627
  * Splits an input string into segments based on a matching pattern.
@@ -8868,7 +9677,21 @@
8868
9677
  cssRemove: cssRemove ?? 'fill-red-container',
8869
9678
  };
8870
9679
  }
9680
+ /**
9681
+ * The framework's built-in library of template-expression transform functions. Each static method here
9682
+ * is registered, via the {@link Transformer} decorator, under `Utils.core` (mostly by its own method
9683
+ * name - see each method's `@Transformer(...)` name override where present) so it becomes callable by
9684
+ * name from binding expressions (e.g. `{{ ^value | size }}`). Not part of the module's exported surface -
9685
+ * consumers use these by their registered transform name, not by importing this class.
9686
+ */
8871
9687
  class Transforms {
9688
+ /**
9689
+ * Wraps every case-insensitive occurrence of each whitespace-separated token of `query` found in `src`
9690
+ * (skipping matches inside HTML tags) with a `<span class="{css}">` highlight wrapper.
9691
+ * @param src Source HTML/text to search within.
9692
+ * @param query Whitespace-separated search terms.
9693
+ * @param css CSS class applied to the highlight `<span>`. Defaults to `{PCSS}-highlight`.
9694
+ */
8872
9695
  static highlight(src, query, css = PCSS + '-highlight') {
8873
9696
  if (!query || !src)
8874
9697
  return src;
@@ -8911,9 +9734,11 @@
8911
9734
  return acc;
8912
9735
  }, '');
8913
9736
  }
9737
+ /** Left-pads `src` (stringified) to `length` characters using `pad`; see {@link Utils.leftPad}. */
8914
9738
  static padleft(src, length, pad) {
8915
9739
  return Utils.leftPad('' + src, length, pad);
8916
9740
  }
9741
+ /** Formats a byte count `src` as a human-readable size string (`B`/`kB`/`MB`/`GB`), or `'-'` if not a positive number. */
8917
9742
  static size(src) {
8918
9743
  // TODO: use logarithms
8919
9744
  if (!(src > 0))
@@ -8926,12 +9751,25 @@
8926
9751
  return (src / 1_048_576).toFixed(2) + ' MB';
8927
9752
  return (src / 1_073_741_824).toFixed(2) + ' GB';
8928
9753
  }
9754
+ /**
9755
+ * Formats a decimal-degrees number `src` as degrees/minutes/seconds (e.g. `41° 53' 24"`).
9756
+ * @param src Decimal degrees value (sign indicates direction).
9757
+ * @param degSeparator Text following the degrees component.
9758
+ * @param minSeparator Text following the minutes component.
9759
+ * @param secSeparator Text following the seconds component.
9760
+ */
8929
9761
  static decToDeg(src, degSeparator = '° ', minSeparator = '\' ', secSeparator = '"') {
8930
9762
  const sign = Math.sign(src);
8931
9763
  src = Math.abs(src);
8932
9764
  const deg = Math.floor(src), min0 = (src - deg) * 60, min = Math.floor(min0), sec0 = (min0 - min) * 60, sec = Math.floor(sec0);
8933
9765
  return (sign < 0 ? '-' : '') + deg + degSeparator + min + minSeparator + sec + secSeparator;
8934
9766
  }
9767
+ /**
9768
+ * Formats a date-like value `src` (parsed via {@link Utils.parseDate}) as text.
9769
+ * @param src Date, timestamp, or parseable date string.
9770
+ * @param format Either a named shorthand (`'iso'`, `'isodate'`, `'localdate'`, `'time'`/`'localtime'`, `'full'`, or the default locale date format) or an `Intl.DateTimeFormatOptions` object.
9771
+ * @param culture BCP 47 locale to format with. Defaults to the browser's language.
9772
+ */
8935
9773
  static date(src, format, culture) {
8936
9774
  var date = Utils.parseDate(src), lang = culture || navigator.language;
8937
9775
  if (Utils.isNull(format) || typeof format === 'string') {
@@ -8959,6 +9797,13 @@
8959
9797
  return date.toLocaleString(culture, format);
8960
9798
  }
8961
9799
  }
9800
+ /**
9801
+ * Formats the elapsed time between `start` and `end`.
9802
+ * @param start Start date-like value.
9803
+ * @param end End date-like value.
9804
+ * @param format Either an `Intl.DateTimeFormatOptions` (formatted as a UTC duration, optionally sign-prefixed via `sign: true`), or omitted for the legacy `"{d}d {h}h {m}m {s}s {ms}ms"` textual format.
9805
+ * @param culture BCP 47 locale to format with (only used with `Intl.DateTimeFormatOptions`). Defaults to the browser's language.
9806
+ */
8962
9807
  static timespan(start, end, format, culture) {
8963
9808
  const startDate = Utils.parseDate(start), endDate = Utils.parseDate(end), span = endDate.valueOf() - startDate.valueOf(), sign = span < 0 ? '-' : '', elapsed = Math.abs(span);
8964
9809
  if (typeof format === 'object') {
@@ -8969,18 +9814,26 @@
8969
9814
  const msecsPerDay = 86400000, msecsPerHr = 3600000, msecsPerMin = 60000, days = Math.floor(elapsed / msecsPerDay), hrs = Math.floor((elapsed % msecsPerDay) / msecsPerHr), mins = Math.floor((elapsed % msecsPerHr) / msecsPerMin), secs = Math.floor((elapsed % msecsPerMin) / 1000), msecs = Math.floor(elapsed % 1000);
8970
9815
  return `${sign}${days}d ${hrs}h ${mins}m ${secs}s ${msecs}ms`;
8971
9816
  }
9817
+ /** Formats `src` as a currency amount using `Intl.NumberFormat`. @param currency ISO 4217 currency code. @param culture BCP 47 locale. Defaults to the browser's language. */
8972
9818
  static currency(src, currency, culture) {
8973
9819
  return new Intl.NumberFormat(culture ?? navigator.language, { style: 'currency', currency: currency }).format(src);
8974
9820
  }
9821
+ /**
9822
+ * Formats `src` as a number using `Intl.NumberFormat`.
9823
+ * @param formatOrCulture Either a BCP 47 locale string, or `Intl.NumberFormatOptions` (in which case `culture` supplies the locale).
9824
+ * @param culture BCP 47 locale, used only when `formatOrCulture` is a format-options object. Defaults to the browser's language.
9825
+ */
8975
9826
  static number(src, formatOrCulture, culture) {
8976
9827
  if (typeof formatOrCulture === 'string') {
8977
9828
  return new Intl.NumberFormat(formatOrCulture || navigator.language).format(src);
8978
9829
  }
8979
9830
  return new Intl.NumberFormat(culture ?? navigator.language, formatOrCulture).format(src);
8980
9831
  }
9832
+ /** Filters `src` with `filter`; a thin wrapper over `Array.prototype.filter` usable from template expressions. */
8981
9833
  static filter(src, filter) {
8982
9834
  return src.filter(filter);
8983
9835
  }
9836
+ /** Sorts `src` in place (ascending, via `>`/`<` comparison), optionally by a property path when items are objects. @param prop Property name to sort by; omit to compare items directly. */
8984
9837
  static orderby(src, prop) {
8985
9838
  return src.sort((a, b) => {
8986
9839
  if (!Utils.isNullOrEmpty(prop)) {
@@ -8991,31 +9844,39 @@
8991
9844
  });
8992
9845
  }
8993
9846
  // #region RegExp
9847
+ /** Tests `input` against a `RegExp` built from `pattern`/`flags`. Registered as `regex.isMatch`. */
8994
9848
  static isMatch(input, pattern, flags) {
8995
9849
  return new RegExp(pattern, flags).test(input);
8996
9850
  }
8997
9851
  // #endregion
8998
9852
  // #region shortcuts from 'Utils'
9853
+ /** Template-expression shortcut for {@link Utils.isEmpty}. */
8999
9854
  static isEmpty(obj) {
9000
9855
  return Utils.isEmpty(obj);
9001
9856
  }
9857
+ /** Template-expression shortcut for {@link Utils.isNull}. */
9002
9858
  static isNull(obj) {
9003
9859
  return Utils.isNull(obj);
9004
9860
  }
9861
+ /** Template-expression shortcut for {@link Utils.isNullOrEmpty}. */
9005
9862
  static isNullOrEmpty(obj) {
9006
9863
  return Utils.isNullOrEmpty(obj);
9007
9864
  }
9865
+ /** Reads a CSS custom property's value off the document; see {@link Utils.Css.getVariableValue}. Registered as `cssvar`. */
9008
9866
  static getCssVariable(name) {
9009
9867
  return Utils.Css.getVariableValue(name);
9010
9868
  }
9869
+ /** Reads a query-string parameter's value off the current URL; see {@link Utils.URIs.parseQuery}. Registered as `querystring`. */
9011
9870
  static getQuerystring(name) {
9012
9871
  return Utils.URIs.parseQuery()[name];
9013
9872
  }
9014
9873
  // #endregion
9015
9874
  // #region shortcuts from 'CustomElementUtils'
9875
+ /** Template-expression shortcut for {@link CustomElementUtils.Theme}'s `importWebFonts`. */
9016
9876
  static importThemeWebFonts() {
9017
9877
  return CustomElementUtils.Theme.importWebFonts();
9018
9878
  }
9879
+ /** Template-expression shortcut for {@link CustomElementUtils.findHostContext}. Registered as `host`. */
9019
9880
  static findHostContext(element) {
9020
9881
  return CustomElementUtils.findHostContext(element);
9021
9882
  }