eru-grid 0.0.53 → 0.0.55

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.
@@ -194,9 +194,23 @@ const SELF_COLOURED_DATATYPES = new Set(['status', 'priority', 'tag', 'progress'
194
194
  */
195
195
  const ACTION_COLUMN_MIN_WIDTH = 56;
196
196
  const SEEDED_FIELD_KEYS = [
197
- 'dynamic_number', 'display_number_as', 'symbol_field', 'date_format', 'label',
197
+ 'dynamic_number', 'display_number_as', 'symbol_field', 'date_format',
198
198
  'storage_name', 'folder_name', 'default_upload',
199
199
  ];
200
+ /**
201
+ * Keys the model seeds only until the design panel overrides them EXPLICITLY,
202
+ * tracked by a companion flag rather than by "does the column hold a value".
203
+ *
204
+ * `label` is the case that forced this: it is in SEEDED_FIELD_KEYS' spirit —
205
+ * the model's label is the default and a grid may shorten it — but a column
206
+ * never arrives without one, so the seeded test ("column already has a value,
207
+ * leave it alone") was true from the first render and the model's label never
208
+ * reached a mapped column. A query-derived column kept showing its raw result
209
+ * key as the heading.
210
+ */
211
+ const EXPLICITLY_OVERRIDDEN_FIELD_KEYS = {
212
+ label: 'label_overridden',
213
+ };
200
214
  /**
201
215
  * Datatype aliases the data model emits that mean an existing DataTypes value.
202
216
  *
@@ -1288,7 +1302,10 @@ class PivotTransformService {
1288
1302
  const enableColumnSubtotals = gridConfiguration?.config?.enableColumnSubtotals ?? false;
1289
1303
  const enableGrandTotal = gridConfiguration?.config?.enableGrandTotal ?? false;
1290
1304
  const enableColumnGrandTotal = gridConfiguration?.config?.enableColumnGrandTotal ?? false;
1291
- if (enableRowSubtotals || enableColumnSubtotals || enableGrandTotal || enableColumnGrandTotal) {
1305
+ // Nothing to total when there are no rows — a grand total of an empty set
1306
+ // would render a row of zeros under a result that has no data.
1307
+ if (pivotRows.length > 0 &&
1308
+ (enableRowSubtotals || enableColumnSubtotals || enableGrandTotal || enableColumnGrandTotal)) {
1292
1309
  pivotRows = this.addSubtotals(pivotRows, configuration, pivotColumns, gridConfiguration, sourceData);
1293
1310
  }
1294
1311
  // Step 5: Generate column definitions (including subtotal columns)
@@ -3896,6 +3913,11 @@ class EruGridStore {
3896
3913
  // Pivot-specific signals
3897
3914
  _pivotConfiguration = signal(null, ...(ngDevMode ? [{ debugName: "_pivotConfiguration" }] : []));
3898
3915
  _pivotResult = signal(null, ...(ngDevMode ? [{ debugName: "_pivotResult" }] : []));
3916
+ /**
3917
+ * Widths for generated pivot leaves that have no field to hold them.
3918
+ * Keyed by leaf name — see updateColumnWidth.
3919
+ */
3920
+ _pivotLeafWidths = signal(new Map(), ...(ngDevMode ? [{ debugName: "_pivotLeafWidths" }] : []));
3899
3921
  _drilldown = signal(null, ...(ngDevMode ? [{ debugName: "_drilldown" }] : []));
3900
3922
  _actionClick = signal(null, ...(ngDevMode ? [{ debugName: "_actionClick" }] : []));
3901
3923
  _columnResize = signal(null, ...(ngDevMode ? [{ debugName: "_columnResize" }] : []));
@@ -3985,6 +4007,7 @@ class EruGridStore {
3985
4007
  // Pivot-specific readonly signals
3986
4008
  pivotConfiguration = this._pivotConfiguration.asReadonly();
3987
4009
  pivotResult = this._pivotResult.asReadonly();
4010
+ pivotLeafWidths = this._pivotLeafWidths.asReadonly();
3988
4011
  drilldown = this._drilldown.asReadonly();
3989
4012
  actionClick = this._actionClick.asReadonly();
3990
4013
  columnResize = this._columnResize.asReadonly();
@@ -4068,33 +4091,34 @@ class EruGridStore {
4068
4091
  }
4069
4092
  return this.rows();
4070
4093
  }, ...(ngDevMode ? [{ debugName: "displayData" }] : []));
4094
+ // The frozen grand total is the row the transform appended (or prepended) to
4095
+ // the pivot data, so it is only there when the transform actually produced
4096
+ // one. It skips totalling an empty result, so `data` can be [] with the
4097
+ // grand-total config still on; indexing it then yields undefined and the
4098
+ // frozen-row template renders a row that has no `_rowKey`. Read the row
4099
+ // positionally but keep it only when it really is the grand total.
4100
+ frozenGrandTotalRow = computed(() => {
4101
+ if (!this.isPivotMode() || !this.pivotResult())
4102
+ return null;
4103
+ const config = this.configuration().config;
4104
+ if (!config?.enableGrandTotal || !config?.freezeGrandTotal)
4105
+ return null;
4106
+ const data = this.pivotResult().data;
4107
+ const row = config?.grandTotalPosition === 'before' ? data[0] : data[data.length - 1];
4108
+ return row?._isGrandTotal ? row : null;
4109
+ }, ...(ngDevMode ? [{ debugName: "frozenGrandTotalRow" }] : []));
4071
4110
  // Type-safe accessors for specific modes
4072
4111
  pivotGrandTotalData = computed(() => {
4073
- let pd = [];
4074
- if (this.isPivotMode() && this.pivotResult()) {
4075
- if (this.configuration().config?.enableGrandTotal) {
4076
- if (this.configuration().config?.freezeGrandTotal) {
4077
- if (this.configuration().config?.grandTotalPosition === 'before') {
4078
- pd = [this.pivotResult().data[0]];
4079
- }
4080
- else {
4081
- pd = [this.pivotResult().data[this.pivotResult().data.length - 1]];
4082
- }
4083
- }
4084
- }
4085
- }
4086
- return pd;
4112
+ const row = this.frozenGrandTotalRow();
4113
+ return row ? [row] : [];
4087
4114
  }, ...(ngDevMode ? [{ debugName: "pivotGrandTotalData" }] : []));
4088
4115
  // Type-safe accessors for specific modes
4089
4116
  pivotDisplayData = computed(() => {
4090
4117
  if (this.isPivotMode() && this.pivotResult()) {
4091
- if (this.configuration().config?.enableGrandTotal && this.configuration().config?.freezeGrandTotal) {
4092
- if (this.configuration().config?.grandTotalPosition === 'before') {
4093
- return this.pivotResult().data.slice(1);
4094
- }
4095
- else {
4096
- return this.pivotResult().data;
4097
- }
4118
+ // Only drop the leading row when it is the frozen grand total that the
4119
+ // header renders separately, never a real data row.
4120
+ if (this.frozenGrandTotalRow() && this.configuration().config?.grandTotalPosition === 'before') {
4121
+ return this.pivotResult().data.slice(1);
4098
4122
  }
4099
4123
  return this.pivotResult().data;
4100
4124
  }
@@ -4401,8 +4425,20 @@ class EruGridStore {
4401
4425
  });
4402
4426
  return;
4403
4427
  }
4404
- const columns = this.columns().map(col => col.name === owner ? { ...col, field_size: field_size } : col);
4405
- this._columns.set(columns);
4428
+ const columns = this.columns();
4429
+ if (!columns.some(col => col.name === owner)) {
4430
+ // A pivot dimension the grid has no column for — the author put a field
4431
+ // in the pivot's rows that is not in the column set. There is no owner to
4432
+ // hold the width, so it is held against the leaf name. Without this the
4433
+ // resize reached the cells (the directive styles them directly) but
4434
+ // nothing else: the next change detection re-asserted the old width, and
4435
+ // the table total, which is summed from the leaves, never moved.
4436
+ const next = new Map(this._pivotLeafWidths());
4437
+ next.set(owner, field_size);
4438
+ this._pivotLeafWidths.set(next);
4439
+ return;
4440
+ }
4441
+ this._columns.set(columns.map(col => (col.name === owner ? { ...col, field_size: field_size } : col)));
4406
4442
  }
4407
4443
  setCellValueChange(change) {
4408
4444
  this._cellValueChange.set(change);
@@ -4481,6 +4517,56 @@ class EruGridStore {
4481
4517
  const rows = this.rows().map(row => row.entity_id === rowId ? { ...row, ...updates } : row);
4482
4518
  this._rows.set(rows);
4483
4519
  }
4520
+ /**
4521
+ * Merge field values into the record with this id, wherever the grid is
4522
+ * holding it — the flat row list AND the per-group buckets a board fills.
4523
+ *
4524
+ * For a consumer that edits a record somewhere else on the page and needs the
4525
+ * grid to agree without refetching. `updateRow` is not enough on two counts:
4526
+ * it only looks at `_rows`, so a grouped/board grid keeps the stale copy, and
4527
+ * it replaces top-level row keys rather than merging into `entity_data`,
4528
+ * where an entity-backed row keeps its fields.
4529
+ *
4530
+ * Unknown ids are ignored, so a caller can announce a change blindly.
4531
+ */
4532
+ patchRecord(entityId, fields) {
4533
+ if (!entityId || !fields)
4534
+ return;
4535
+ const entries = Object.entries(fields);
4536
+ if (entries.length === 0)
4537
+ return;
4538
+ const patch = (row) => {
4539
+ if (!row || row.entity_id !== entityId)
4540
+ return row;
4541
+ const next = { ...row };
4542
+ if (next.entity_data && typeof next.entity_data === 'object') {
4543
+ next.entity_data = { ...next.entity_data, ...fields };
4544
+ }
4545
+ // An array-sourced row carries its fields at the top level instead. Only
4546
+ // keys the row already has are touched, so this never invents columns.
4547
+ for (const [key, value] of entries) {
4548
+ if (key !== 'entity_data' && Object.prototype.hasOwnProperty.call(next, key)) {
4549
+ next[key] = value;
4550
+ }
4551
+ }
4552
+ return next;
4553
+ };
4554
+ const holdsRecord = (rows) => rows.some(row => row?.entity_id === entityId);
4555
+ if (holdsRecord(this._rows())) {
4556
+ this._rows.set(this._rows().map(patch));
4557
+ }
4558
+ this._groupRows.update(current => {
4559
+ let touched = false;
4560
+ const next = new Map(current);
4561
+ current.forEach((rows, groupId) => {
4562
+ if (!holdsRecord(rows))
4563
+ return;
4564
+ next.set(groupId, rows.map(patch));
4565
+ touched = true;
4566
+ });
4567
+ return touched ? next : current;
4568
+ });
4569
+ }
4484
4570
  // Selection methods
4485
4571
  selectRow(rowId) {
4486
4572
  const selectedRowIds = new Set(this.selectedRowIds());
@@ -4721,16 +4807,16 @@ class EruGridStore {
4721
4807
  }
4722
4808
  if (!pivotConfig)
4723
4809
  return;
4724
- // No source rows: publish an EMPTY pivot rather than returning and leaving
4725
- // the previous result on screen. Bailing here is what kept the last
4726
- // filter's rows — and their subtotals — rendered after a query came back
4727
- // with nothing, since the pivot view reads _pivotResult and not the row
4728
- // stores that had already been cleared.
4729
- if (sourceData.length === 0) {
4730
- if (this._pivotResult() !== null)
4731
- this._pivotResult.set(null);
4732
- return;
4733
- }
4810
+ // No source rows still goes through the transform, producing a pivot with
4811
+ // the row-dimension columns and no data rows.
4812
+ //
4813
+ // Two things this must NOT do. Bailing out leaves the previous filter's
4814
+ // rows and subtotals on screen, since the pivot view reads _pivotResult and
4815
+ // not the row stores that were already cleared. Publishing null empties it
4816
+ // but drops the pivot's own column definitions, so displayColumns() falls
4817
+ // back to the raw source columns and an empty pivot reads as a table. The
4818
+ // transform on an empty set yields neither: column values and measures
4819
+ // cannot be derived from nothing, so only the row dimensions remain.
4734
4820
  this.setLoading(true);
4735
4821
  this.setError(null);
4736
4822
  try {
@@ -13735,9 +13821,13 @@ class ColumnDesignPanelComponent {
13735
13821
  * drift apart: a key that is inherited is always locked, and vice versa.
13736
13822
  *
13737
13823
  * SEEDED_FIELD_KEYS are the exception the resolver makes too: the model seeds
13738
- * them, this grid may then override them, so they stay editable here.
13824
+ * them, this grid may then override them, so they stay editable here. So are
13825
+ * EXPLICITLY_OVERRIDDEN_FIELD_KEYS, seeded the same way but tracked by a flag
13826
+ * — `label` among them, which must stay typeable for the flag to ever be set.
13739
13827
  */
13740
- static INHERITED_KEYS = new Set(INHERITED_FIELD_KEYS.filter(k => !SEEDED_FIELD_KEYS.includes(k) && k !== 'datatype'));
13828
+ static INHERITED_KEYS = new Set(INHERITED_FIELD_KEYS.filter(k => !SEEDED_FIELD_KEYS.includes(k) &&
13829
+ !EXPLICITLY_OVERRIDDEN_FIELD_KEYS[k] &&
13830
+ k !== 'datatype'));
13741
13831
  isInherited(key) {
13742
13832
  return this.isEntityMapped() && ColumnDesignPanelComponent.INHERITED_KEYS.has(key);
13743
13833
  }
@@ -14024,6 +14114,20 @@ class ColumnDesignPanelComponent {
14024
14114
  this.gridStore.updateColumnMeta(name, { [key]: value });
14025
14115
  }
14026
14116
  onText(key, value) {
14117
+ // A typed heading is the author's, and stops the mapped field's label from
14118
+ // seeding it on the next resolve; clearing the box hands the column back to
14119
+ // the data model rather than pinning it to an empty header.
14120
+ const flag = EXPLICITLY_OVERRIDDEN_FIELD_KEYS[key];
14121
+ if (flag) {
14122
+ const name = this.gridStore.selectedDesignColumn();
14123
+ if (!name)
14124
+ return;
14125
+ const typed = String(value ?? '').trim();
14126
+ this.gridStore.updateColumnMeta(name, typed
14127
+ ? { [key]: value, [flag]: true }
14128
+ : { [key]: null, [flag]: null });
14129
+ return;
14130
+ }
14027
14131
  this.patch(key, value);
14028
14132
  }
14029
14133
  onNumber(key, value) {
@@ -14584,7 +14688,6 @@ class EruGridComponent {
14584
14688
  return !!row && this.gridStore.activeBoardRow() === row;
14585
14689
  }
14586
14690
  initialMinHeight = 400;
14587
- initialTotalWidth = 0;
14588
14691
  viewport;
14589
14692
  groupsViewport;
14590
14693
  groupsScrollContainerEl;
@@ -14889,10 +14992,21 @@ class EruGridComponent {
14889
14992
  this.viewport?.getRenderedRange();
14890
14993
  this.firstTr = this.viewport?.getRenderedRange()?.start || 0;
14891
14994
  }
14995
+ /**
14996
+ * The sum of the rendered column widths — what every table in the grid is
14997
+ * forced to via `--table-total-width`.
14998
+ *
14999
+ * A signal, not a value captured at init. A resize writes the new width to
15000
+ * the column (or, in pivot mode, to the measure the leaf came from), and the
15001
+ * cells and `<col>`s follow it; a cached total does not, so the table stayed
15002
+ * at its old width while its columns changed underneath — leaving the header
15003
+ * and body tables wider or narrower than the columns they contain, and the
15004
+ * horizontal scroll range wrong. Pivot mode also changes its leaf SET as the
15005
+ * data changes, so even without a resize the total goes stale.
15006
+ */
15007
+ totalTableWidth = computed(() => this.getLeafColumns().reduce((total, column) => total + (column?.field_size || 0), 0), ...(ngDevMode ? [{ debugName: "totalTableWidth" }] : []));
14892
15008
  getTotalTableWidth() {
14893
- const columns = this.getLeafColumns();
14894
- let totalWidth = columns.reduce((total, column) => total + column.field_size, 0);
14895
- return totalWidth;
15009
+ return this.totalTableWidth();
14896
15010
  }
14897
15011
  /* getContainerHeight(): number {
14898
15012
  const element = this.rowContainer?.nativeElement;
@@ -15120,7 +15234,6 @@ class EruGridComponent {
15120
15234
  this.initializeColumnWidths();
15121
15235
  this.firstDataRowIndex.set(this.maxDepth() + 1);
15122
15236
  this.initialMinHeight = this.getMinHeightPx();
15123
- this.initialTotalWidth = this.getTotalTableWidth();
15124
15237
  this.columnsInitialized.set(true);
15125
15238
  }
15126
15239
  });
@@ -15322,7 +15435,6 @@ class EruGridComponent {
15322
15435
  // initializeGroups() moved to effect in constructor to handle timing
15323
15436
  this.firstDataRowIndex.set(this.maxDepth() + 1);
15324
15437
  this.initialMinHeight = this.getMinHeightPx();
15325
- this.initialTotalWidth = this.getTotalTableWidth();
15326
15438
  }
15327
15439
  ngAfterViewInit() {
15328
15440
  this.applyTokens();
@@ -15419,12 +15531,12 @@ class EruGridComponent {
15419
15531
  return this.initialMinHeight;
15420
15532
  }
15421
15533
  getInitialTotalWidth() {
15422
- return this.initialTotalWidth;
15534
+ return this.totalTableWidth();
15423
15535
  }
15424
15536
  applyCdkWidth() {
15425
15537
  const element = this.rowContainer?.nativeElement;
15426
15538
  if (element) {
15427
- return element.clientWidth > this.initialTotalWidth;
15539
+ return element.clientWidth > this.totalTableWidth();
15428
15540
  }
15429
15541
  return false;
15430
15542
  }
@@ -15760,7 +15872,7 @@ class EruGridComponent {
15760
15872
  }
15761
15873
  }
15762
15874
  trackByPivotRowFn(index, pivotRow) {
15763
- return pivotRow._rowKey || `pivot-row-${index}`;
15875
+ return pivotRow?._rowKey || `pivot-row-${index}`;
15764
15876
  }
15765
15877
  trackByRowFn(index, row) {
15766
15878
  // Use both entity_id and index to ensure uniqueness even with duplicate entity_ids
@@ -15828,6 +15940,7 @@ class EruGridComponent {
15828
15940
  const leaves = pivotResult.headerStructure.leafColumns;
15829
15941
  const aggregations = this.gridStore.configuration()?.pivot?.aggregations || [];
15830
15942
  const sourceColumns = this.gridStore.columns() || [];
15943
+ const leafWidths = this.gridStore.pivotLeafWidths();
15831
15944
  // Carry configuration from the field a leaf came from onto the leaf itself.
15832
15945
  // The pivot transform builds leaves with a handful of hard-coded keys — it
15833
15946
  // types every aggregated column as plain 'number' whatever the measure says,
@@ -15841,15 +15954,20 @@ class EruGridComponent {
15841
15954
  const owner = leaf.aggregationFunction
15842
15955
  ? aggregations.find(a => a.name === this.designTargetFor(leaf))
15843
15956
  : sourceColumns.find(c => c.name === leaf.name);
15844
- if (!owner)
15845
- return leaf;
15846
15957
  const patch = {};
15847
- for (const key of EruGridComponent.PIVOT_INHERITED_KEYS) {
15848
- const value = owner[key];
15849
- // `false` is meaningful (enableDrilldown), blank/absent is not.
15850
- if (value !== undefined && value !== null && value !== '')
15851
- patch[key] = value;
15958
+ if (owner) {
15959
+ for (const key of EruGridComponent.PIVOT_INHERITED_KEYS) {
15960
+ const value = owner[key];
15961
+ // `false` is meaningful (enableDrilldown), blank/absent is not.
15962
+ if (value !== undefined && value !== null && value !== '')
15963
+ patch[key] = value;
15964
+ }
15852
15965
  }
15966
+ // A resize of a leaf with no owning field is held against the leaf name
15967
+ // instead — see EruGridStore.updateColumnWidth.
15968
+ const width = leafWidths.get(leaf.name);
15969
+ if (typeof width === 'number' && width > 0)
15970
+ patch.field_size = width;
15853
15971
  return Object.keys(patch).length ? { ...leaf, ...patch } : leaf;
15854
15972
  });
15855
15973
  }
@@ -16086,6 +16204,11 @@ class EruGridComponent {
16086
16204
  * including an explicit `false` on a checkbox — wins from then on. Without the
16087
16205
  * column in hand there is no way to tell "not set" from "set to the opposite",
16088
16206
  * so an override was overwritten on every resolve.
16207
+ *
16208
+ * EXPLICITLY_OVERRIDDEN_FIELD_KEYS work the same way but ask a companion flag
16209
+ * instead, for keys a column always holds a value for — `label`, whose
16210
+ * "already set" was true from the first render, so the model's label never
16211
+ * won and a mapped column kept its raw result key as the heading.
16089
16212
  */
16090
16213
  buildMappedColumnPatch(meta, col) {
16091
16214
  const patch = {};
@@ -16097,6 +16220,9 @@ class EruGridComponent {
16097
16220
  continue;
16098
16221
  if (seeded.has(k) && !isUnset(col?.[k]))
16099
16222
  continue;
16223
+ const overrideFlag = EXPLICITLY_OVERRIDDEN_FIELD_KEYS[k];
16224
+ if (overrideFlag && col?.[overrideFlag])
16225
+ continue;
16100
16226
  patch[k] = v;
16101
16227
  }
16102
16228
  // setColumns() stores the canonical datatype ('r_status' -> 'status'), so a
@@ -16998,5 +17124,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.2", ngImpor
16998
17124
  * Generated bundle index. Do not edit.
16999
17125
  */
17000
17126
 
17001
- export { ACTION_COLUMN_MIN_WIDTH, AttachmentComponent, CELL_RULE_OPERATORS, CheckboxComponent, ChipListComponent, ColumnConstraintsService, CompositeComponent, CurrencyComponent, CustomVirtualScrollStrategy, DATA_TYPES, DATETIME_FORMATS, DATE_FORMATS, DateComponent, DatetimeComponent, DurationComponent, EmailComponent, EruGridComponent, EruGridService, EruGridStore, GRID_COLOR_TOKENS, INHERITED_FIELD_KEYS, LocationComponent, MATERIAL_MODULES, MATERIAL_PROVIDERS, MONTH_SHORT_NAMES, NumberComponent, NumericInputDirective, PRESENTATION_DATATYPES, PRESET_CONFIG_DEFAULTS, PRESET_MANAGED_FIELDS, PeopleComponent, PhoneComponent, PriorityComponent, ProgressComponent, RatingComponent, SEEDED_FIELD_KEYS, SELF_COLOURED_DATATYPES, SelectComponent, StatusComponent, TagComponent, TextareaComponent, TextboxComponent, ThemeService, ThemeToggleComponent, WebsiteComponent, abbreviateNumber, abbreviationScaleFor, cellRuleBarPercent, cellRuleMatches, cellRuleToCss, cellStatAlias, cellTextStyleToCss, collectColumnStatRequests, columnCellRules, composeColorValue, effectiveValueDatatype, evaluateRowCondition, formatCellValue, formatDateTimeWithPattern, formatDateWithPattern, formatNumberValue, hasOwnCellRules, matchCellRule, matchColorRange, normalizeCellRender, normalizeDatatype, normalizeDateFormat, normalizeDateTimeFormat, parseCellDate, parseCellDateTime, parseColorValue, parseDateWithPattern, readRowValue, resolveColumnRules, resolveRowValue, resolveStatValue, rowSelectionKey, statusPillColors, tagPillColors, toDateOnlyString, toDateTimeString };
17127
+ export { ACTION_COLUMN_MIN_WIDTH, AttachmentComponent, CELL_RULE_OPERATORS, CheckboxComponent, ChipListComponent, ColumnConstraintsService, CompositeComponent, CurrencyComponent, CustomVirtualScrollStrategy, DATA_TYPES, DATETIME_FORMATS, DATE_FORMATS, DateComponent, DatetimeComponent, DurationComponent, EXPLICITLY_OVERRIDDEN_FIELD_KEYS, EmailComponent, EruGridComponent, EruGridService, EruGridStore, GRID_COLOR_TOKENS, INHERITED_FIELD_KEYS, LocationComponent, MATERIAL_MODULES, MATERIAL_PROVIDERS, MONTH_SHORT_NAMES, NumberComponent, NumericInputDirective, PRESENTATION_DATATYPES, PRESET_CONFIG_DEFAULTS, PRESET_MANAGED_FIELDS, PeopleComponent, PhoneComponent, PriorityComponent, ProgressComponent, RatingComponent, SEEDED_FIELD_KEYS, SELF_COLOURED_DATATYPES, SelectComponent, StatusComponent, TagComponent, TextareaComponent, TextboxComponent, ThemeService, ThemeToggleComponent, WebsiteComponent, abbreviateNumber, abbreviationScaleFor, cellRuleBarPercent, cellRuleMatches, cellRuleToCss, cellStatAlias, cellTextStyleToCss, collectColumnStatRequests, columnCellRules, composeColorValue, effectiveValueDatatype, evaluateRowCondition, formatCellValue, formatDateTimeWithPattern, formatDateWithPattern, formatNumberValue, hasOwnCellRules, matchCellRule, matchColorRange, normalizeCellRender, normalizeDatatype, normalizeDateFormat, normalizeDateTimeFormat, parseCellDate, parseCellDateTime, parseColorValue, parseDateWithPattern, readRowValue, resolveColumnRules, resolveRowValue, resolveStatValue, rowSelectionKey, statusPillColors, tagPillColors, toDateOnlyString, toDateTimeString };
17002
17128
  //# sourceMappingURL=eru-grid.mjs.map