@pacem/pacem 1.0.0-bessel → 1.0.0-binet

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-binet (https://js.pacem.it)
3
3
  * Pacem (https://pacem.it)
4
4
  * Licensed under Apache-2.0
5
5
  */
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * @pacem/pacem v1.0.0-bessel (https://js.pacem.it)
2
+ * @pacem/pacem v1.0.0-binet (https://js.pacem.it)
3
3
  * Pacem (https://pacem.it)
4
4
  * Licensed under Apache-2.0
5
5
  */
@@ -12,15 +12,24 @@
12
12
  else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
13
13
  return c > 3 && r && Object.defineProperty(target, key, r), r;
14
14
  };
15
+ /**
16
+ * Base class shared by {@link PacemDataCellElement} and {@link PacemHeadCellElement}: both are bound to the
17
+ * same `metadata`/`state`/`gridState` triple describing their column, both position themselves within the
18
+ * grid's CSS-grid layout according to `gridState.orderedColumns`, and both toggle their own visibility from
19
+ * `state.hidden`. Concrete subclasses only need to implement {@link updateLayout} to (re)build their own
20
+ * content whenever `metadata` changes.
21
+ */
15
22
  class PacemBaseCellElement extends pacemCore.Components.PacemSafeContentElement {
16
23
  viewActivatedCallback() {
17
24
  super.viewActivatedCallback();
18
25
  this.updateColumnPosition();
19
26
  this.updateLayout(this.metadata);
20
27
  }
28
+ /** Positions this cell within the grid's CSS-grid layout according to `gridState.orderedColumns`. */
21
29
  updateColumnPosition(metadata = this.metadata, state = this.gridState) {
22
30
  this.style.gridColumn = (state.orderedColumns.indexOf(metadata.prop) + 1).toString();
23
31
  }
32
+ /** Shows/hides this cell according to `state.hidden`. */
24
33
  updateVisibility(state = this.state) {
25
34
  this.hide = !!state.hidden;
26
35
  }
@@ -68,6 +77,7 @@
68
77
  return null;
69
78
  }
70
79
  };
80
+ /** Namespaced helpers for working with {@link PacemDataGridElement} column metadata, e.g. localization. */
71
81
  class DataGrids {
72
82
  /**
73
83
  * Localizes the metadata of a data grid **in place** using a translation dictionary.
@@ -117,10 +127,16 @@
117
127
  return c > 3 && r && Object.defineProperty(target, key, r), r;
118
128
  };
119
129
  const UI$5 = pacemUi.Components.UI;
120
- /** @deprecated*/
130
+ /**
131
+ * @deprecated Superseded by composing a `${P}-repeater`/`${P}-slideshow` pair directly (see the template this
132
+ * element generates below for reference). Renders a `datasource` of {@link CarouselDataItem}s as a full-bleed,
133
+ * auto-advancing slideshow with a per-slide image, title and caption, applying 'previous'/'next'/'focus' CSS
134
+ * classes to neighbouring slides so they can be animated in/out as the current slide changes.
135
+ */
121
136
  let PacemCarouselElement = class PacemCarouselElement extends UI$5.PacemAdaptedIterativeElement {
122
137
  constructor() {
123
138
  super(...arguments);
139
+ /** Gets or sets the interval (in milliseconds) between automatic slide transitions. Default: `4000`. */
124
140
  this.interval = 4000;
125
141
  }
126
142
  };
@@ -171,6 +187,13 @@
171
187
  };
172
188
  const UI$4 = pacemUi.Components.UI;
173
189
  //namespace Pacem.Components.Plus {
190
+ /**
191
+ * Base class for the items registered within a {@link PacemContextMenuElement}: either a command button
192
+ * ({@link PacemContextMenuItemCommandElement}) or a separator ({@link PacemContextMenuItemSeparatorElement}).
193
+ * Subclasses only need to implement {@link createMenuItemElement} to produce the actual DOM element rendered
194
+ * inside the menu's balloon; this base class takes care of the `pacem-context-menuitem` CSS class and of
195
+ * notifying the owning {@link PacemContextMenuElement} (via `refresh()`) whenever one of its properties changes.
196
+ */
174
197
  class PacemContextMenuItemElement extends pacemCore.Components.PacemItemElement {
175
198
  connectedCallback() {
176
199
  super.connectedCallback();
@@ -184,6 +207,7 @@
184
207
  }
185
208
  }
186
209
  }
210
+ /** A {@link PacemContextMenuElement} item rendered as a clickable command button ({@link UI.PacemButtonElement}). */
187
211
  let PacemContextMenuItemCommandElement = class PacemContextMenuItemCommandElement extends PacemContextMenuItemElement {
188
212
  createMenuItemElement() {
189
213
  const retval = new UI$4.PacemButtonElement();
@@ -226,6 +250,7 @@
226
250
  PacemContextMenuItemCommandElement = __decorate$9([
227
251
  pacemCore.CustomElement({ tagName: pacemCore.P + '-context-menuitem-command' })
228
252
  ], PacemContextMenuItemCommandElement);
253
+ /** A {@link PacemContextMenuElement} item rendered as a non-interactive `<hr>` separator between commands. */
229
254
  let PacemContextMenuItemSeparatorElement = class PacemContextMenuItemSeparatorElement extends PacemContextMenuItemElement {
230
255
  createMenuItemElement() {
231
256
  const retval = document.createElement('hr');
@@ -237,6 +262,13 @@
237
262
  pacemCore.CustomElement({ tagName: pacemCore.P + '-context-menuitem-separator' })
238
263
  ], PacemContextMenuItemSeparatorElement);
239
264
  // <${P}-button class="button-flat ${PCSS}-margin margin-0"><${P}-icon icon="{{ :host.icon || 'more_horiz' }}"></${P}-icon></${P}-button>
265
+ /**
266
+ * A button that pops out a floating balloon menu built from its {@link PacemContextMenuItemElement} children
267
+ * (commands and separators). If a `slot="button"` element is provided by the consumer it's used as the trigger;
268
+ * otherwise a default icon button is generated. Menu items are rendered lazily into a {@link UI.PacemBalloonElement}
269
+ * appended to the nearest shell, and kept in sync with the registered items whenever they (or their attributes)
270
+ * change - see `refresh`.
271
+ */
240
272
  let PacemContextMenuElement = class PacemContextMenuElement extends pacemCore.Components.PacemItemsContainerElement {
241
273
  constructor() {
242
274
  super(...arguments);
@@ -255,6 +287,7 @@
255
287
  }
256
288
  };
257
289
  }
290
+ /** Only accepts {@link PacemContextMenuItemElement} instances (commands or separators) as registrable items. */
258
291
  validate(item) {
259
292
  return item instanceof PacemContextMenuItemElement;
260
293
  }
@@ -309,6 +342,7 @@
309
342
  shell.appendChild(balloon);
310
343
  return this.#balloon = balloon;
311
344
  }
345
+ /** Registers a menu item, wiring its attribute-change notifications and rebuilding the rendered menu. */
312
346
  register(item) {
313
347
  const retval = super.register(item);
314
348
  if (retval) {
@@ -317,6 +351,7 @@
317
351
  }
318
352
  return retval;
319
353
  }
354
+ /** Unregisters a menu item and rebuilds the rendered menu. */
320
355
  unregister(item) {
321
356
  const retval = super.unregister(item);
322
357
  if (retval) {
@@ -374,6 +409,7 @@
374
409
  this._disposeBalloon();
375
410
  super.disconnectedCallback();
376
411
  }
412
+ /** Forces the balloon's menu items to be rebuilt from the currently registered items. */
377
413
  refresh() {
378
414
  this._refreshMenuItems();
379
415
  }
@@ -459,13 +495,25 @@
459
495
  const UI$3 = pacemUi.Components.UI;
460
496
  const Scaffolding = pacemScaffolding.Components.Scaffolding;
461
497
  //namespace Pacem.Components.Plus {
498
+ /** The kind of inline content a {@link PacemEditElement} edits, and the editor UI it swaps in accordingly. */
462
499
  var EditMode;
463
500
  (function (EditMode) {
501
+ /** Plain text, edited via a `${P}-textarea`. */
464
502
  EditMode["Text"] = "text";
503
+ /** Rich HTML, edited via a `${P}-contenteditable`. */
465
504
  EditMode["Html"] = "html";
505
+ /** An image URL, edited via a `${P}-edit-image` (with optional upload/snapshot support). */
466
506
  EditMode["Image"] = "image";
507
+ /** Markdown source, edited via a `${P}-textarea` and rendered back through the markdown service. */
467
508
  EditMode["Markdown"] = "markdown";
468
509
  })(EditMode || (EditMode = {}));
510
+ /**
511
+ * Makes an arbitrary piece of content (`target`, or this element's first child when unset) inline-editable:
512
+ * overlays an edit button that, on click, opens a modal `${P}-dialog` hosting the editor matching `type`
513
+ * (text, HTML, markdown or image - see {@link EditMode}), and writes the result back into the target element
514
+ * once confirmed. The dialog and its editors (textarea/contenteditable/edit-image) are created once, lazily,
515
+ * on connect, and shown/hidden according to `type` rather than being recreated on every edit.
516
+ */
469
517
  let PacemEditElement = class PacemEditElement extends pacemCore.Components.PacemElement {
470
518
  constructor(_markdown = new UI$3.MarkdownService()) {
471
519
  super();
@@ -725,6 +773,11 @@
725
773
  break;
726
774
  }
727
775
  }
776
+ /**
777
+ * Opens the modal editor over `target`'s current content. On 'Ok' the edited value is written back into
778
+ * `target` and a `commit` event is dispatched with `{ value }`; on 'Cancel' the target's original content
779
+ * is restored.
780
+ */
728
781
  edit(evt) {
729
782
  pacemCore.avoidHandler(evt);
730
783
  var cnt = this._target;
@@ -791,6 +844,7 @@
791
844
  return c > 3 && r && Object.defineProperty(target, key, r), r;
792
845
  };
793
846
  const UI$2 = pacemUi.Components.UI;
847
+ /** Builds the markup for a single `${P}-slide`, embedding `captionTemplate`'s markup and reading the image from `imageProperty`. */
794
848
  function getGallerySlideShowTemplate(captionTemplate = getDefaultCaptionTemplate(), imageProperty = 'image') {
795
849
  return `<${pacemCore.P}-slide class="${pacemCore.PCSS}-gallery-item"
796
850
  css-class="{{ { '${pacemCore.PCSS}-gallery-previous': :host.isPrevious(^index, ::_slideshow.index), '${pacemCore.PCSS}-gallery-next': :host.isNext(^index, ::_slideshow.index), '${pacemCore.PCSS}-gallery-focus': ^index === ::_slideshow.index } }}"
@@ -802,11 +856,19 @@ ${captionTemplate}
802
856
 
803
857
  </${pacemCore.P}-slide>`;
804
858
  }
859
+ /** Default caption markup: a simple panel bound to `captionProperty`, hidden when the value is empty. */
805
860
  function getDefaultCaptionTemplate(captionProperty = 'caption') {
806
861
  return `<${pacemCore.P}-panel hide="{{ $pacem.isNullOrEmpty(^item.${captionProperty}) }}" class="${pacemCore.PCSS}-gallery-caption gallery-caption-default">
807
862
  <${pacemCore.P}-span class="paragraph" text="{{ ^item.${captionProperty} }}"></${pacemCore.P}-span>
808
863
  </${pacemCore.P}-panel>`;
809
864
  }
865
+ /**
866
+ * A lightbox photo gallery: renders `datasource` (a list of {@link GalleryDataItem}, or any shape when a custom
867
+ * `captionTemplate`/`imageProperty`/`captionProperty` is supplied) as a `${P}-lightbox`-hosted `${P}-slideshow`,
868
+ * opened via {@link open} with an optional 'hero' image-morph transition animating from the triggering thumbnail
869
+ * into the lightbox. The per-slide markup (image + caption) is generated dynamically from `captionTemplate`
870
+ * (or a default caption panel) so consumers can customize the caption's content without overriding the whole slide.
871
+ */
810
872
  let PacemGalleryElement = class PacemGalleryElement extends UI$2.PacemAdaptedIterativeElement {
811
873
  constructor() {
812
874
  super(...arguments);
@@ -880,6 +942,7 @@ ${captionTemplate}
880
942
  rep.datasource = this.datasource;
881
943
  }
882
944
  }
945
+ /** @readonly Gets the `${P}-adapter` driving the gallery's slideshow. */
883
946
  get adapter() {
884
947
  return this._adapter;
885
948
  }
@@ -911,6 +974,13 @@ ${captionTemplate}
911
974
  pImg.remove();
912
975
  }
913
976
  }
977
+ /**
978
+ * Opens the lightbox at `startIndex`, animating a morph from `heroFrom` (typically the thumbnail that
979
+ * triggered the gallery) into the lightbox's hero placeholder, when provided.
980
+ * @param startIndex Index of the slide to open the gallery on.
981
+ * @param heroFrom Optional element to morph the opening transition from.
982
+ * @param src Optional image URL to use for the morph, when different from `heroFrom`'s own `src`.
983
+ */
914
984
  open(startIndex, heroFrom, src) {
915
985
  this._poppingUp = true;
916
986
  this._lightbox.show = true;
@@ -977,13 +1047,23 @@ ${captionTemplate}
977
1047
  const UI$1 = pacemUi.Components.UI;
978
1048
  //namespace Pacem.Components.Plus {
979
1049
  // TODO: use onewaytosource as a binding mode
1050
+ /**
1051
+ * A modal, `${P}-lightbox`-hosted CRUD form: wraps an autogenerated `${P}-form` bound to `state`/`metadata`,
1052
+ * relays its submit/success/fail events, and turns 'Ok' into a `${P}-fetch` request (`method`) to `action`
1053
+ * before committing the dialog - or, when `action` is empty, commits immediately without any network call.
1054
+ * Extends {@link UI.PacemDialogBase}, so it's opened the same way (`open(state)`) and resolves the same
1055
+ * `{ button, state }` result once committed.
1056
+ */
980
1057
  let PacemModalFormElement = PacemModalFormElement_1 = class PacemModalFormElement extends UI$1.PacemDialogBase {
1058
+ /** @readonly Gets the underlying `${P}-form` element. */
981
1059
  get form() {
982
1060
  return this._form;
983
1061
  }
984
1062
  constructor() {
985
1063
  super();
1064
+ /** Gets or sets whether the 'Ok' button stays disabled until the form is both valid and dirty. Default: `true`. */
986
1065
  this.suddenValidation = true;
1066
+ /** Gets or sets the HTTP method used to submit the form to `action`. Default: `Net.HttpMethod.Post`. */
987
1067
  this.method = pacemCore.Net.HttpMethod.Post;
988
1068
  this._keyupHandler = (evt) => {
989
1069
  if (evt.keyCode === /* Enter */ 13
@@ -1059,6 +1139,7 @@ ${captionTemplate}
1059
1139
  }
1060
1140
  return retval;
1061
1141
  }
1142
+ /** Commits the dialog, then - unless `keepStateOnCommit` was requested on `open` - resets `state` to `{}` once the closing animation ends. */
1062
1143
  commit(btn, evt) {
1063
1144
  super.commit(btn, evt);
1064
1145
  if (!this.#keepStateOnCommit) {
@@ -1166,11 +1247,23 @@ ${captionTemplate}
1166
1247
  return c > 3 && r && Object.defineProperty(target, key, r), r;
1167
1248
  };
1168
1249
  //namespace Pacem.Components.Plus {
1250
+ /**
1251
+ * Two-way syncs a plain `state` object with the URL hash's query-string (`#...`) through a
1252
+ * {@link Components.PacemRouterElement}: reading the hash into `state` on navigation, and pushing `state`
1253
+ * back into the hash (merged with `default`, minus anything already matching `default`) whenever `state`
1254
+ * changes. Values are normalized to strings for the URL (see `normalizedState`) and denormalized back to
1255
+ * their original type using `default` as a type mold, so booleans/numbers/dates/regexes round-trip correctly.
1256
+ * Navigation events lock the element (`#locked`) to avoid feedback loops between the router-driven read and
1257
+ * the state-driven write while a navigation is in flight.
1258
+ */
1169
1259
  let PacemRouterHashStateElement = class PacemRouterHashStateElement extends pacemCore.PacemEventTarget {
1170
1260
  constructor() {
1171
1261
  super(...arguments);
1262
+ /** Gets or sets the default/mold values: used both to fill in missing `state` entries and to infer each value's original type when denormalizing from the URL. */
1172
1263
  this.default = {};
1264
+ /** Gets or sets the current state, kept in sync with the URL hash's query-string. */
1173
1265
  this.state = {};
1266
+ /** @readonly Gets the string-normalized projection of `state` actually written to the URL hash. */
1174
1267
  this.normalizedState = {};
1175
1268
  this._routerNavigatingHandler = (_) => {
1176
1269
  this.#locked = true;
@@ -1425,8 +1518,8 @@ ${captionTemplate}
1425
1518
  return c > 3 && r && Object.defineProperty(target, key, r), r;
1426
1519
  };
1427
1520
  /**
1428
- * Bridges a {@link Components.PacemRouterElement}'s persisted scroll position (`state.$scrollY`, populated
1429
- * when `PacemRouterElement.scrollRestoration` is enabled) with a {@link ComponentsUI.UI.PacemViewElement}'s
1521
+ * Bridges a {@link Pacem.Components.PacemRouterElement}'s persisted scroll position (`state.$scrollY`, populated
1522
+ * when `PacemRouterElement.scrollRestoration` is enabled) with a {@link Pacem.Components.UI.PacemViewElement}'s
1430
1523
  * content lifecycle: navigating to a new page starts at the top, navigating back restores where the user
1431
1524
  * left off - without either the router or the view needing to know about the other.
1432
1525
  *
@@ -1538,9 +1631,15 @@ ${captionTemplate}
1538
1631
  return c > 3 && r && Object.defineProperty(target, key, r), r;
1539
1632
  };
1540
1633
  //namespace Pacem.Components.Plus {
1634
+ /**
1635
+ * A simple search box: a `${P}-input-search`'s `hint` text feeds a debounced `${P}-fetch` against `url` as
1636
+ * the `hintParameter` query-string parameter, and the results are rendered through a `${P}-repeater`
1637
+ * (customize the row markup via the element's default `${P}-content` slot).
1638
+ */
1541
1639
  let PacemSearchElement = class PacemSearchElement extends pacemCore.Components.PacemElement {
1542
1640
  constructor() {
1543
1641
  super(...arguments);
1642
+ /** Gets or sets the name of the query-string parameter `hint` is sent as. Default: `'q'`. */
1544
1643
  this.hintParameter = 'q';
1545
1644
  }
1546
1645
  propertyChangedCallback(name, old, val, first) {
@@ -1588,7 +1687,13 @@ ${captionTemplate}
1588
1687
  return c > 3 && r && Object.defineProperty(target, key, r), r;
1589
1688
  };
1590
1689
  //namespace Pacem.Components.Plus {
1690
+ /** Name of the {@link DataRowSelectChangeEvent}. */
1591
1691
  const DataRowSelectChangeEventName = "datarowselectchange";
1692
+ /**
1693
+ * Dispatched by a {@link PacemDataGridElement} whenever its row selection is about to change (e.g. a row was
1694
+ * clicked while in 'row' select mode). Cancelable: a listener can call `preventDefault()` and instead assign
1695
+ * its own `detail.selectedRows` to override which rows actually end up selected.
1696
+ */
1592
1697
  class DataRowSelectChangeEvent extends CustomEvent {
1593
1698
  constructor(detail) {
1594
1699
  super(DataRowSelectChangeEventName, { detail, bubbles: false, cancelable: true });
@@ -1596,6 +1701,13 @@ ${captionTemplate}
1596
1701
  }
1597
1702
  const EMPTY_CSS = {};
1598
1703
  const EMPTY_CSSCLASS = [];
1704
+ /**
1705
+ * The `<td>`-like cell of a {@link PacemDataGridElement}'s body: renders `dataitem`'s `metadata.prop` value
1706
+ * according to `metadata.dataType`/`metadata.dataCell.format` (numbers, currency, percentages, dates,
1707
+ * booleans, ...), or through a custom `metadata.dataCell.format` function when one is supplied. Also derives
1708
+ * the cell's CSS class(es)/inline style from `metadata.dataCell`, and reflects the grid's row-selection state
1709
+ * (`gridState.selectedRows`) via the `datarow-selected`/`datacell-filled`/`datacell-primary` CSS classes.
1710
+ */
1599
1711
  let PacemDataCellElement = class PacemDataCellElement extends PacemBaseCellElement {
1600
1712
  updateLayout(metadata = this.metadata) {
1601
1713
  this._setup(metadata);
@@ -1799,18 +1911,38 @@ ${captionTemplate}
1799
1911
  };
1800
1912
  const UI = pacemUi.Components.UI;
1801
1913
  //namespace Pacem.Components.Plus {
1914
+ /** Name of the {@link DataColumnSortEvent}. */
1802
1915
  const DataColumnSortEventName = "datacolumnsort";
1916
+ /**
1917
+ * Dispatched by a {@link PacemHeadCellElement} when its sort button is clicked, and re-dispatched by the
1918
+ * owning {@link PacemDataGridElement} after it updates its internal sort state. Cancelable: a listener can
1919
+ * call `preventDefault()` to veto the sort, or normalize/override `detail` (e.g. fetch a re-sorted datasource)
1920
+ * before the grid applies it.
1921
+ */
1803
1922
  class DataColumnSortEvent extends CustomEvent {
1804
1923
  constructor(detail) {
1805
1924
  super(DataColumnSortEventName, { detail, bubbles: false, cancelable: true });
1806
1925
  }
1807
1926
  }
1927
+ /** Name of the {@link DataColumnRescaleEvent}. */
1808
1928
  const DataColumnRescaleEventName = "datacolumnrescale";
1929
+ /**
1930
+ * Dispatched by a {@link PacemHeadCellElement} while its rescale handle is being dragged, and re-dispatched
1931
+ * by the owning {@link PacemDataGridElement} after it updates the column's pixel width. Cancelable: a
1932
+ * listener can call `preventDefault()` and override `detail.width` to clamp/snap the resulting width.
1933
+ */
1809
1934
  class DataColumnRescaleEvent extends CustomEvent {
1810
1935
  constructor(detail) {
1811
1936
  super(DataColumnRescaleEventName, { detail, bubbles: false, cancelable: true });
1812
1937
  }
1813
1938
  }
1939
+ /**
1940
+ * The `<th>`-like cell of a {@link PacemDataGridElement}'s header row: renders `metadata.headCell.name`
1941
+ * (falling back to `metadata.prop`), and - depending on `metadata` flags - a sort button that dispatches
1942
+ * {@link DataColumnSortEvent}, a rescale handle (backed by a `${P}-rescale` behavior appended to the shell)
1943
+ * that dispatches {@link DataColumnRescaleEvent}, and a description tooltip balloon rendered as plain text,
1944
+ * HTML or Markdown according to `metadata.headCell.tooltip`.
1945
+ */
1814
1946
  let PacemHeadCellElement = class PacemHeadCellElement extends PacemBaseCellElement {
1815
1947
  constructor(_md = new UI.MarkdownService()) {
1816
1948
  super();
@@ -2035,16 +2167,33 @@ ${captionTemplate}
2035
2167
  deleteIcon: 'delete'
2036
2168
  }
2037
2169
  };
2170
+ /**
2171
+ * Dispatched by a {@link PacemDataGridElement} right after its `datasource` changes and before row selection
2172
+ * is cleared; a listener can set `detail.keepRowSelection` to `true` to preserve the current selection instead
2173
+ * of the default reset-on-rebind behavior.
2174
+ */
2038
2175
  class DataGridBindEvent extends CustomEvent {
2039
2176
  constructor(detail) {
2040
2177
  super('databind', { cancelable: false, bubbles: false, detail });
2041
2178
  }
2042
2179
  }
2180
+ /**
2181
+ * Dispatched by a {@link PacemDataGridElement} for every UI event bubbling up from one of its data cells
2182
+ * (see `Components.PacemElement.emittedEventTypes`), re-typed as `'datacell' + originalType` (e.g. a cell's
2183
+ * `click` becomes `datacellclick`) and enriched with the originating cell/item/row-index. An un-prevented
2184
+ * `click` while in `'row'` select mode additionally toggles that row's selection.
2185
+ */
2043
2186
  class DataCellUIEvent extends pacemCore.CustomUIEvent {
2044
2187
  constructor(type, detail, orig) {
2045
2188
  super(type, detail, { bubbles: false, cancelable: true }, orig);
2046
2189
  }
2047
2190
  }
2191
+ /**
2192
+ * Declarative, `<${P}-datacolumn>`-authored description of a {@link PacemDataGridElement} column: field
2193
+ * binding, label, sort/resize/toggle flags and per-column CSS. Registering, unregistering or changing one of
2194
+ * these items causes the owning grid to recompute its adapted column metadata and rebuild its rendered
2195
+ * columns/state accordingly.
2196
+ */
2048
2197
  let PacemDataColumnElement = class PacemDataColumnElement extends pacemCore.Components.PacemItemElement {
2049
2198
  propertyChangedCallback(name, old, val, first) {
2050
2199
  super.propertyChangedCallback(name, old, val, first);
@@ -2105,31 +2254,55 @@ ${captionTemplate}
2105
2254
  PacemDataColumnElement = __decorate([
2106
2255
  pacemCore.CustomElement({ tagName: pacemCore.P + '-datacolumn' })
2107
2256
  ], PacemDataColumnElement);
2257
+ /** Builds the bindable `${P}-headcell` markup for a single column, wired to relay sort/rescale requests up to the grid. */
2108
2258
  function headColumnHtml(c) {
2109
2259
  return `<${pacemCore.P}-headcell metadata="{{ :host._getColumnMetadata('${c.prop}') }}" state="{{ :host._columnState.${c.prop} }}" grid-state="{{ :host._gridState }}"
2110
2260
  on-${DataColumnSortEventName}=":host._broadcastSortCommand($event)"
2111
2261
  on-${DataColumnRescaleEventName}=":host._broadcastRescaleCommand($event)"></${pacemCore.P}-headcell>`;
2112
2262
  }
2263
+ /** Builds the bindable `${P}-datacell` markup for a single column/row, appending `extra` (typically the UI event relays) to the tag. */
2113
2264
  function dataColumnHtml(c, extra) {
2114
2265
  return `<${pacemCore.P}-datacell metadata="{{ :host._getColumnMetadata('${c.prop}') }}" state="{{ :host._columnState.${c.prop} }}" grid-state="{{ :host._gridState }}"
2115
2266
  dataitem="{{ ^item }}" rowindex="{{ ^index }}" ${extra}></${pacemCore.P}-datacell>`;
2116
2267
  }
2268
+ /**
2269
+ * A CSS-grid-based data table driven by an array of {@link PacemDataColumnElement} children and/or a
2270
+ * `metadata` array (columns declared as elements are merged on top of `metadata` by matching `field`/`prop`,
2271
+ * see `_adaptColumnMetadata`). For each bound `datasource` row, one `${P}-datacell` is generated per column,
2272
+ * matched by a `${P}-headcell` per column in the header row; columns can independently be sortable,
2273
+ * rescalable and togglable, coordinated through `_gridState`/`_columnState` and the head cell's
2274
+ * {@link DataColumnSortEvent}/{@link DataColumnRescaleEvent}.
2275
+ *
2276
+ * The grid's markup is fully re-generated (`innerHTML` on the internal grid container, see `_buildUpGrid`)
2277
+ * whenever the adapted column metadata changes, so adding/removing/reordering `${P}-datacolumn` children -
2278
+ * or changing `metadata` directly - keeps the grid's markup, `grid-template-columns` and per-cell bindings
2279
+ * in sync. Row selection is centralized here (`setRowSelection`, `_gridState.selectedRows`) and exposed both
2280
+ * as the public, mergeable `state` and as bubbling {@link DataRowSelectChangeEvent}s/{@link DataCellUIEvent}s
2281
+ * relayed from the individual cells.
2282
+ */
2117
2283
  let PacemDataGridElement = class PacemDataGridElement extends pacemCore.Components.PacemItemsContainerElement {
2118
2284
  constructor(_key = pacemCore.Utils.uniqueCode()) {
2119
2285
  super();
2120
2286
  this._key = _key;
2287
+ /** Gets or sets the grid's public state (currently just row selection); merged into, and kept in sync with, the internal `_gridState`. */
2121
2288
  this.state = {};
2122
2289
  // TODO: allow to persist states (key) on the session or location level...
2290
+ /** @readonly Per-column runtime state (visibility, rescaled width), keyed by `prop`; fed into each cell's `state`. */
2123
2291
  this._columnState = {};
2292
+ /** @readonly The grid's internal, always-consistent state (sort, selection, column order); `state` is merged from/into this. */
2124
2293
  this._gridState = { sort: {}, orderedColumns: [], selectedRows: [] };
2294
+ /** A registered column's display-affecting properties changed (field/label/css/sort/resize/toggle flags): re-adapt the column metadata so the grid rebuilds. */
2125
2295
  this._itemDataColumnRebuildHandler = (evt) => {
2126
2296
  this._adaptColumnMetadata(this.items || []);
2127
2297
  };
2298
+ /** A registered column's order/hide state changed: re-adapt the column metadata so the grid rebuilds. */
2128
2299
  this._itemDataColumnChangeHandler = (evt) => {
2129
2300
  this._adaptColumnMetadata(this.items || []);
2130
2301
  };
2302
+ /** Per-column-`prop` cache of {@link DataColumnMetadata} lookups (see `_getColumnMetadata`), invalidated whenever `_adaptedColumnMetadata` is recomputed. */
2131
2303
  this._memoizer = {};
2132
2304
  }
2305
+ /** Only accepts {@link PacemDataColumnElement} instances as registrable items. */
2133
2306
  validate(item) {
2134
2307
  return item instanceof PacemDataColumnElement;
2135
2308
  }
@@ -2170,6 +2343,7 @@ dataitem="{{ ^item }}" rowindex="{{ ^index }}" ${extra}></${pacemCore.P}-datacel
2170
2343
  }
2171
2344
  }
2172
2345
  }
2346
+ /** Registers a column item, wiring its rebuild/state-change notifications so the grid re-adapts its metadata whenever the column changes. */
2173
2347
  register(item) {
2174
2348
  if (super.register(item)) {
2175
2349
  // add listeners
@@ -2179,6 +2353,7 @@ dataitem="{{ ^item }}" rowindex="{{ ^index }}" ${extra}></${pacemCore.P}-datacel
2179
2353
  }
2180
2354
  return false;
2181
2355
  }
2356
+ /** Unregisters a column item and removes its rebuild/state-change listeners. */
2182
2357
  unregister(item) {
2183
2358
  if (super.unregister(item)) {
2184
2359
  // remove listeners
@@ -2196,6 +2371,7 @@ dataitem="{{ ^item }}" rowindex="{{ ^index }}" ${extra}></${pacemCore.P}-datacel
2196
2371
  const indices = Array.from(args);
2197
2372
  this._setRowSelection(indices);
2198
2373
  }
2374
+ /** Dispatches a cancelable {@link DataRowSelectChangeEvent} for `indices`, then applies `event.detail.selectedRows` (possibly overridden by a listener) as the new selection - unless the event was prevented. */
2199
2375
  _setRowSelection(indices) {
2200
2376
  const args = (indices || []).map(i => { return { item: this.datasource[i], index: i }; });
2201
2377
  const evt = new DataRowSelectChangeEvent({ selectedRows: args });
@@ -2208,6 +2384,7 @@ dataitem="{{ ^item }}" rowindex="{{ ^index }}" ${extra}></${pacemCore.P}-datacel
2208
2384
  this._doSetRowSelection(retval.map(i => (i?.index ?? -1)).filter(i => i >= 0));
2209
2385
  }
2210
2386
  }
2387
+ /** Merges the given `selectedRows` indices into `_gridState`/`state`. */
2211
2388
  _doSetRowSelection(selectedRows) {
2212
2389
  const selection = { selectedRows };
2213
2390
  this._mergeState(selection);
@@ -2224,6 +2401,7 @@ dataitem="{{ ^item }}" rowindex="{{ ^index }}" ${extra}></${pacemCore.P}-datacel
2224
2401
  // does not trigger propertychange event (does not have to).
2225
2402
  this.state = pacemCore.Utils.extend(this.state ?? {}, newState);
2226
2403
  }
2404
+ /** Recomputes `_adaptedColumnMetadata` by projecting each {@link PacemDataColumnElement} item into a {@link DataColumnMetadata} and concatenating the plain `metadata` array after it. Debounced, since several column items/attributes typically change together. */
2227
2405
  _adaptColumnMetadata(items = this.items, metadata = this.metadata) {
2228
2406
  const output = Array.prototype.concat.apply((items || []).map(i => {
2229
2407
  const retval = {
@@ -2247,9 +2425,15 @@ dataitem="{{ ^item }}" rowindex="{{ ^index }}" ${extra}></${pacemCore.P}-datacel
2247
2425
  this._memoizer = {};
2248
2426
  this._adaptedColumnMetadata = output;
2249
2427
  }
2428
+ /** Looks up (and memoizes) a column's {@link DataColumnMetadata} by `prop`; bound from each generated head/data cell's `metadata` attribute. */
2250
2429
  _getColumnMetadata(prop) {
2251
2430
  return this._memoizer[prop] = this._memoizer[prop] || this._adaptedColumnMetadata.find(m => m.prop === prop);
2252
2431
  }
2432
+ /**
2433
+ * (Re)generates the grid's entire markup - the CSS grid-template-columns, one `${P}-headcell` and one
2434
+ * `${P}-datacell` per column (repeated per `datasource` row via a `${P}-repeater`), plus the optional
2435
+ * multi-select gutter column - and assigns it as `innerHTML` of the internal grid container.
2436
+ */
2253
2437
  _buildUpGrid(metadata) {
2254
2438
  const container = this._tableContainer;
2255
2439
  if (pacemCore.Utils.isNull(container)) {
@@ -2290,6 +2474,7 @@ dataitem="{{ ^item }}" rowindex="{{ ^index }}" ${extra}></${pacemCore.P}-datacel
2290
2474
  </${pacemCore.P}-panel>`;
2291
2475
  container.innerHTML = html;
2292
2476
  }
2477
+ /** Patches the static `grid-template-columns` track list with any per-column overrides from `_columnState` (`auto` when hidden, a pixel width when rescaled). Bound as the grid container's `css['grid-template-columns']`. */
2293
2478
  _getColumnSizes(state = this._columnState, css, grid = this._gridState) {
2294
2479
  if (pacemCore.Utils.isNullOrEmpty(state)) {
2295
2480
  return css;
@@ -2307,6 +2492,7 @@ dataitem="{{ ^item }}" rowindex="{{ ^index }}" ${extra}></${pacemCore.P}-datacel
2307
2492
  }
2308
2493
  return split.join(' ');
2309
2494
  }
2495
+ /** Computes a column's initial CSS grid-template-columns track (`auto`, a flex `fr` unit, or a `minmax()`) from its `width`/`minPixelWidth`/`maxPixelWidth`. */
2310
2496
  _getColumnSize(c) {
2311
2497
  if (c.hide) {
2312
2498
  return 'auto';
@@ -2328,6 +2514,7 @@ dataitem="{{ ^item }}" rowindex="{{ ^index }}" ${extra}></${pacemCore.P}-datacel
2328
2514
  }
2329
2515
  //#endregion
2330
2516
  //#region events
2517
+ /** Relays a bubbled `CommandEvent` (e.g. from an autogenerated row-command button) as the grid's own `itemcommand`/`item<cmd>` events. */
2331
2518
  _onCommand(evt) {
2332
2519
  // DO NOT stop bubbling! Might be 'handy' in autogenerated forms...
2333
2520
  // Pacem.stopPropagationHandler(evt);
@@ -2338,6 +2525,7 @@ dataitem="{{ ^item }}" rowindex="{{ ^index }}" ${extra}></${pacemCore.P}-datacel
2338
2525
  // custom 'item<cmd>' event fires next
2339
2526
  this.dispatchEvent(new pacemCore.Components.CustomItemCommandEvent(/* 'originalEvent' */ evt));
2340
2527
  }
2528
+ /** Relays a UI event bubbled from a data cell as a {@link DataCellUIEvent} (`'datacell' + type`) on the grid, and toggles the row's selection on an un-prevented `click` while in `'row'` select mode. */
2341
2529
  _broadcastUiEvent(item, index, evt) {
2342
2530
  const evtType = evt.type.toLowerCase(), type = 'datacell' + evtType;
2343
2531
  const args = { dataitem: item, rowindex: index, datacell: evt.srcElement }, uiEvt = (evt instanceof MouseEvent || evt instanceof TouchEvent || evt instanceof KeyboardEvent) ? new DataCellUIEvent(type, args, evt) : new DataCellUIEvent(type, args);
@@ -2354,6 +2542,7 @@ dataitem="{{ ^item }}" rowindex="{{ ^index }}" ${extra}></${pacemCore.P}-datacel
2354
2542
  }
2355
2543
  }
2356
2544
  }
2545
+ /** Relays a head cell's {@link DataColumnSortEvent} up as the grid's own event, then - unless prevented - normalizes and applies the resulting sort into `_gridState.sort`. */
2357
2546
  _broadcastSortCommand(evt) {
2358
2547
  const sort = evt.detail;
2359
2548
  const event = new DataColumnSortEvent(sort);
@@ -2369,6 +2558,7 @@ dataitem="{{ ^item }}" rowindex="{{ ^index }}" ${extra}></${pacemCore.P}-datacel
2369
2558
  this._gridState = pacemCore.Utils.extend({}, this._gridState, /* let it be manipulated on the "other side" */ { sort: sort2 });
2370
2559
  }
2371
2560
  }
2561
+ /** Relays a head cell's {@link DataColumnRescaleEvent} up as the grid's own event, then - unless prevented - stores the resulting pixel width into that column's `_columnState`. */
2372
2562
  _broadcastRescaleCommand(evt) {
2373
2563
  const rescale = evt.detail;
2374
2564
  const event = new DataColumnRescaleEvent(rescale);
@@ -2384,6 +2574,7 @@ dataitem="{{ ^item }}" rowindex="{{ ^index }}" ${extra}></${pacemCore.P}-datacel
2384
2574
  this._columnState = pacemCore.Utils.extend({}, this._columnState, newState);
2385
2575
  }
2386
2576
  }
2577
+ /** Toggles `toggledRowIndex` in/out of the current row selection, honoring `options.allowMultiSelect`/`allowSelect` (logging a warning and doing nothing if selection isn't allowed at all), then applies it via `_setRowSelection`. */
2387
2578
  _broadcastSelectCommand(toggledRowIndex) {
2388
2579
  let actualRows = (this._gridState.selectedRows || []).slice(0);
2389
2580
  const ndx = actualRows.indexOf(toggledRowIndex);