@mozaic-ds/angular 2.0.44 → 2.0.46
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/fesm2022/mozaic-ds-angular.mjs +1097 -126
- package/fesm2022/mozaic-ds-angular.mjs.map +1 -1
- package/package.json +1 -1
- package/types/mozaic-ds-angular.d.ts +257 -28
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { input, computed, ChangeDetectionStrategy, Component, contentChild, ViewEncapsulation, signal, forwardRef, output, ContentChild, viewChild, inject, model, InjectionToken, HostListener, Injector, Injectable, TemplateRef, afterNextRender, Directive, linkedSignal, EnvironmentInjector, createComponent, ChangeDetectorRef, NgZone, viewChildren, EventEmitter, effect, Output, ContentChildren, ApplicationRef, Renderer2, ElementRef, Input, booleanAttribute, contentChildren, DestroyRef } from '@angular/core';
|
|
2
|
+
import { input, computed, ChangeDetectionStrategy, Component, contentChild, ViewEncapsulation, signal, forwardRef, output, ContentChild, viewChild, inject, model, InjectionToken, HostListener, Injector, Injectable, TemplateRef, afterNextRender, Directive, linkedSignal, EnvironmentInjector, createComponent, ChangeDetectorRef, NgZone, viewChildren, EventEmitter, effect, Output, ContentChildren, ApplicationRef, Renderer2, ElementRef, Input, booleanAttribute, contentChildren, DestroyRef, untracked } from '@angular/core';
|
|
3
3
|
import { RouterLink, RouterLinkActive, RouterLinkWithHref } from '@angular/router';
|
|
4
4
|
import { NgTemplateOutlet, NgClass, NgComponentOutlet, JsonPipe, DOCUMENT } from '@angular/common';
|
|
5
5
|
import * as i1 from '@angular/forms';
|
|
6
6
|
import { FormsModule, ReactiveFormsModule, NG_VALUE_ACCESSOR } from '@angular/forms';
|
|
7
|
-
import { WarningCircle32, Uploading32, CheckCircle32, CrossCircleFilled20, Refresh32, Refresh20, Eye20, Upload24, Cross24, ChevronLeft24, ChevronRight24, ChevronLeft20, ChevronRight20, CrossCircleFilled24, More24, Less24, InfoCircle32, CrossCircle32, Cross20, CrossCircle24, ImageAlt32, ChevronDown24, CheckCircleFilled32, WarningCircleFilled32, CrossCircleFilled32, InfoCircleFilled32, SidebarExpand24, ChevronDown20, InfoCircleFilled24, WarningCircleFilled24, CheckCircleFilled24, ArrowBottomRight24, ArrowTopRight24, StarHalf32, StarFilled32, Star32, StarHalf24, StarFilled24, Star24, StarHalf20, StarFilled20, Star20, Check20, Check24, ArrowBack24, ArrowNext24, HelpCircle24, Menu24, Notification24, Search24, PauseCircle24, PlayCircle24,
|
|
7
|
+
import { WarningCircle32, Uploading32, CheckCircle32, CrossCircleFilled20, Refresh32, Refresh20, Eye20, Upload24, Cross24, ChevronLeft24, ChevronRight24, ChevronLeft20, ChevronRight20, CrossCircleFilled24, More24, Less24, InfoCircle32, CrossCircle32, Cross20, CrossCircle24, ImageAlt32, ChevronDown24, CheckCircleFilled32, WarningCircleFilled32, CrossCircleFilled32, InfoCircleFilled32, SidebarExpand24, ChevronDown20, InfoCircleFilled24, WarningCircleFilled24, CheckCircleFilled24, ArrowBottomRight24, ArrowTopRight24, StarHalf32, StarFilled32, Star32, StarHalf24, StarFilled24, Star24, StarHalf20, StarFilled20, Star20, Check20, Check24, ArrowBack24, ArrowNext24, HelpCircle24, Menu24, Notification24, Search24, PauseCircle24, PlayCircle24, Folder48, Search48, Drag20, ListAdd20, ChevronUp20, Filter20, Settings20, ErrorFilled24, ViewGridX420, FullscreenEnter20, FullscreenExit20, Download20, Keyboard20, CheckCircle24 } from '@mozaic-ds/icons-angular';
|
|
8
8
|
import { Overlay, OverlayConfig, OverlayPositionBuilder, CdkConnectedOverlay, CdkOverlayOrigin } from '@angular/cdk/overlay';
|
|
9
9
|
import { CdkPortalOutlet, ComponentPortal } from '@angular/cdk/portal';
|
|
10
10
|
import { Subject, take, tap, of, firstValueFrom } from 'rxjs';
|
|
11
11
|
import parsePhoneNumberFromString, { getCountries, getExampleNumber, isValidPhoneNumber, getCountryCallingCode } from 'libphonenumber-js';
|
|
12
12
|
import examples from 'libphonenumber-js/mobile/examples';
|
|
13
|
+
import { moveItemInArray, CdkDropList, CdkDrag, CdkDragHandle } from '@angular/cdk/drag-drop';
|
|
13
14
|
import * as i1$1 from '@angular/cdk/scrolling';
|
|
14
15
|
import { VIRTUAL_SCROLL_STRATEGY, ScrollingModule } from '@angular/cdk/scrolling';
|
|
15
|
-
import { moveItemInArray, CdkDropList, CdkDrag, CdkDragHandle } from '@angular/cdk/drag-drop';
|
|
16
16
|
import { ComponentHarness, TestKey } from '@angular/cdk/testing';
|
|
17
17
|
|
|
18
18
|
class MozBreadcrumbComponent {
|
|
@@ -4887,8 +4887,11 @@ class GridStateManager {
|
|
|
4887
4887
|
groupColumns = signal([], ...(ngDevMode ? [{ debugName: "groupColumns" }] : /* istanbul ignore next */ []));
|
|
4888
4888
|
expandedGroups = signal(new Set(), ...(ngDevMode ? [{ debugName: "expandedGroups" }] : /* istanbul ignore next */ []));
|
|
4889
4889
|
// --- Filter ---
|
|
4890
|
-
|
|
4891
|
-
|
|
4890
|
+
/**
|
|
4891
|
+
* Unified filter state: single source of truth for the multi-condition
|
|
4892
|
+
* builder. The tag-bar displays a derived view via `FilterEngine.toLabel()`.
|
|
4893
|
+
*/
|
|
4894
|
+
filterModel = signal({ conditions: [] }, ...(ngDevMode ? [{ debugName: "filterModel" }] : /* istanbul ignore next */ []));
|
|
4892
4895
|
// --- Pagination ---
|
|
4893
4896
|
pageIndex = signal(0, ...(ngDevMode ? [{ debugName: "pageIndex" }] : /* istanbul ignore next */ []));
|
|
4894
4897
|
pageSize = signal(20, ...(ngDevMode ? [{ debugName: "pageSize" }] : /* istanbul ignore next */ []));
|
|
@@ -5168,87 +5171,257 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
|
|
|
5168
5171
|
type: Injectable
|
|
5169
5172
|
}] });
|
|
5170
5173
|
|
|
5174
|
+
/**
|
|
5175
|
+
* Filter model — multi-condition filter builder with AND/OR combinators.
|
|
5176
|
+
*
|
|
5177
|
+
* Evaluation is left-associative (no operator precedence). Grouped / parenthesised
|
|
5178
|
+
* conditions (`(a AND b) OR c`) are out of scope for the MVP; see docs.
|
|
5179
|
+
*/
|
|
5180
|
+
/**
|
|
5181
|
+
* Default operator sets per data type. Consumers can restrict the set via
|
|
5182
|
+
* `ColumnDef.filterOperators`.
|
|
5183
|
+
*/
|
|
5184
|
+
const DEFAULT_OPERATORS = {
|
|
5185
|
+
text: [
|
|
5186
|
+
'contains',
|
|
5187
|
+
'notContains',
|
|
5188
|
+
'equals',
|
|
5189
|
+
'notEquals',
|
|
5190
|
+
'startsWith',
|
|
5191
|
+
'endsWith',
|
|
5192
|
+
'blank',
|
|
5193
|
+
'notBlank',
|
|
5194
|
+
],
|
|
5195
|
+
number: ['equals', 'notEquals', 'gt', 'gte', 'lt', 'lte', 'between', 'blank', 'notBlank'],
|
|
5196
|
+
date: ['equals', 'notEquals', 'gt', 'gte', 'lt', 'lte', 'between', 'blank', 'notBlank'],
|
|
5197
|
+
set: ['in', 'notIn', 'blank', 'notBlank'],
|
|
5198
|
+
boolean: ['equals', 'blank', 'notBlank'],
|
|
5199
|
+
};
|
|
5200
|
+
const DEFAULT_OPERATOR_PER_TYPE = {
|
|
5201
|
+
text: 'contains',
|
|
5202
|
+
number: 'equals',
|
|
5203
|
+
date: 'equals',
|
|
5204
|
+
set: 'in',
|
|
5205
|
+
boolean: 'equals',
|
|
5206
|
+
};
|
|
5207
|
+
/** Human-readable operator labels (used by `toLabel`). */
|
|
5208
|
+
const OPERATOR_LABELS = {
|
|
5209
|
+
contains: 'contains',
|
|
5210
|
+
notContains: 'does not contain',
|
|
5211
|
+
equals: 'equals',
|
|
5212
|
+
notEquals: 'does not equal',
|
|
5213
|
+
startsWith: 'starts with',
|
|
5214
|
+
endsWith: 'ends with',
|
|
5215
|
+
gt: '>',
|
|
5216
|
+
gte: '≥',
|
|
5217
|
+
lt: '<',
|
|
5218
|
+
lte: '≤',
|
|
5219
|
+
between: 'between',
|
|
5220
|
+
in: 'in',
|
|
5221
|
+
notIn: 'not in',
|
|
5222
|
+
blank: 'is blank',
|
|
5223
|
+
notBlank: 'is not blank',
|
|
5224
|
+
};
|
|
5225
|
+
/** Operators that do not require a user-entered value. */
|
|
5226
|
+
const VALUELESS_OPERATORS = new Set([
|
|
5227
|
+
'blank',
|
|
5228
|
+
'notBlank',
|
|
5229
|
+
]);
|
|
5230
|
+
/** Operators that need a secondary value (`between`). */
|
|
5231
|
+
const RANGE_OPERATORS = new Set(['between']);
|
|
5232
|
+
/** Small helper for generating condition ids without pulling in a uuid dep. */
|
|
5233
|
+
function generateConditionId() {
|
|
5234
|
+
return `cond-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`;
|
|
5235
|
+
}
|
|
5236
|
+
/** True when a condition has enough information to participate in evaluation. */
|
|
5237
|
+
function isConditionComplete(condition) {
|
|
5238
|
+
if (!condition.field)
|
|
5239
|
+
return false;
|
|
5240
|
+
if (VALUELESS_OPERATORS.has(condition.operator))
|
|
5241
|
+
return true;
|
|
5242
|
+
const { value, valueTo } = condition.value;
|
|
5243
|
+
if (value == null || value === '')
|
|
5244
|
+
return false;
|
|
5245
|
+
if (RANGE_OPERATORS.has(condition.operator)) {
|
|
5246
|
+
if (valueTo == null || valueTo === '')
|
|
5247
|
+
return false;
|
|
5248
|
+
}
|
|
5249
|
+
return true;
|
|
5250
|
+
}
|
|
5251
|
+
|
|
5171
5252
|
class FilterEngine {
|
|
5172
5253
|
state = inject(GridStateManager);
|
|
5173
|
-
|
|
5174
|
-
|
|
5175
|
-
|
|
5176
|
-
|
|
5177
|
-
|
|
5178
|
-
|
|
5179
|
-
|
|
5180
|
-
|
|
5181
|
-
|
|
5182
|
-
|
|
5183
|
-
|
|
5184
|
-
|
|
5185
|
-
|
|
5186
|
-
|
|
5187
|
-
|
|
5188
|
-
|
|
5189
|
-
|
|
5190
|
-
});
|
|
5191
|
-
this.state.
|
|
5192
|
-
|
|
5193
|
-
|
|
5194
|
-
|
|
5195
|
-
|
|
5196
|
-
|
|
5254
|
+
/** Latest mutation, used by the grid shell to emit `filterChange` once. */
|
|
5255
|
+
lastChange = signal(null, ...(ngDevMode ? [{ debugName: "lastChange" }] : /* istanbul ignore next */ []));
|
|
5256
|
+
conditions = computed(() => this.state.filterModel().conditions, ...(ngDevMode ? [{ debugName: "conditions" }] : /* istanbul ignore next */ []));
|
|
5257
|
+
hasActiveFilters = computed(() => this.conditions().length > 0, ...(ngDevMode ? [{ debugName: "hasActiveFilters" }] : /* istanbul ignore next */ []));
|
|
5258
|
+
lastEvent = this.lastChange.asReadonly();
|
|
5259
|
+
// ------------------------------------------------------------------
|
|
5260
|
+
// Mutations
|
|
5261
|
+
// ------------------------------------------------------------------
|
|
5262
|
+
/** Replaces the whole model in one go. Used by the drawer's Apply button. */
|
|
5263
|
+
setModel(model, reason = 'replace') {
|
|
5264
|
+
this.state.filterModel.set({ conditions: [...model.conditions] });
|
|
5265
|
+
this.state.pageIndex.set(0);
|
|
5266
|
+
this.notify(reason, null);
|
|
5267
|
+
}
|
|
5268
|
+
addCondition(condition) {
|
|
5269
|
+
this.state.filterModel.update((m) => ({
|
|
5270
|
+
conditions: [...m.conditions, condition],
|
|
5271
|
+
}));
|
|
5272
|
+
this.state.pageIndex.set(0);
|
|
5273
|
+
this.notify('add', condition);
|
|
5274
|
+
}
|
|
5275
|
+
updateCondition(id, patch) {
|
|
5276
|
+
let updated = null;
|
|
5277
|
+
this.state.filterModel.update((m) => ({
|
|
5278
|
+
conditions: m.conditions.map((c) => {
|
|
5279
|
+
if (c.id !== id)
|
|
5280
|
+
return c;
|
|
5281
|
+
const next = { ...c, ...patch, value: { ...c.value, ...(patch.value ?? {}) } };
|
|
5282
|
+
updated = next;
|
|
5197
5283
|
return next;
|
|
5198
|
-
}
|
|
5199
|
-
|
|
5284
|
+
}),
|
|
5285
|
+
}));
|
|
5286
|
+
this.state.pageIndex.set(0);
|
|
5287
|
+
if (updated)
|
|
5288
|
+
this.notify('update', updated);
|
|
5289
|
+
}
|
|
5290
|
+
removeCondition(id) {
|
|
5291
|
+
const removed = this.state.filterModel().conditions.find((c) => c.id === id) ?? null;
|
|
5292
|
+
this.state.filterModel.update((m) => ({
|
|
5293
|
+
conditions: m.conditions.filter((c) => c.id !== id),
|
|
5294
|
+
}));
|
|
5295
|
+
this.state.pageIndex.set(0);
|
|
5296
|
+
this.notify('remove', removed);
|
|
5297
|
+
}
|
|
5298
|
+
reorderConditions(fromIndex, toIndex) {
|
|
5299
|
+
this.state.filterModel.update((m) => {
|
|
5300
|
+
if (fromIndex === toIndex)
|
|
5301
|
+
return m;
|
|
5302
|
+
const next = [...m.conditions];
|
|
5303
|
+
const [item] = next.splice(fromIndex, 1);
|
|
5304
|
+
if (!item)
|
|
5305
|
+
return m;
|
|
5306
|
+
next.splice(toIndex, 0, item);
|
|
5307
|
+
return { conditions: next };
|
|
5200
5308
|
});
|
|
5201
5309
|
this.state.pageIndex.set(0);
|
|
5310
|
+
this.notify('reorder', null);
|
|
5202
5311
|
}
|
|
5203
|
-
|
|
5204
|
-
this.state.
|
|
5205
|
-
|
|
5312
|
+
clearAll() {
|
|
5313
|
+
if (this.state.filterModel().conditions.length === 0)
|
|
5314
|
+
return;
|
|
5315
|
+
this.state.filterModel.set({ conditions: [] });
|
|
5206
5316
|
this.state.pageIndex.set(0);
|
|
5317
|
+
this.notify('clear', null);
|
|
5207
5318
|
}
|
|
5208
|
-
|
|
5209
|
-
|
|
5210
|
-
this.state.
|
|
5319
|
+
/** Convenience: drop all conditions that target a given field. */
|
|
5320
|
+
removeByField(field) {
|
|
5321
|
+
const before = this.state.filterModel().conditions;
|
|
5322
|
+
const after = before.filter((c) => c.field !== field);
|
|
5323
|
+
if (after.length === before.length)
|
|
5324
|
+
return;
|
|
5325
|
+
this.state.filterModel.set({ conditions: after });
|
|
5211
5326
|
this.state.pageIndex.set(0);
|
|
5327
|
+
this.notify('replace', null);
|
|
5212
5328
|
}
|
|
5329
|
+
// ------------------------------------------------------------------
|
|
5330
|
+
// Evaluation
|
|
5331
|
+
// ------------------------------------------------------------------
|
|
5332
|
+
/**
|
|
5333
|
+
* Evaluates the current model against the provided data. In `server` mode,
|
|
5334
|
+
* the grid delegates filtering to the consumer so we return the input as-is.
|
|
5335
|
+
*/
|
|
5213
5336
|
filterData(data) {
|
|
5214
|
-
|
|
5215
|
-
|
|
5337
|
+
if (this.state.mode() === 'server')
|
|
5338
|
+
return data;
|
|
5339
|
+
const conditions = this.state.filterModel().conditions.filter(isConditionComplete);
|
|
5340
|
+
if (conditions.length === 0)
|
|
5216
5341
|
return data;
|
|
5217
5342
|
const defMap = this.state.columnDefMap();
|
|
5343
|
+
const prepared = conditions.map((c) => ({
|
|
5344
|
+
cond: c,
|
|
5345
|
+
col: defMap.get(c.field),
|
|
5346
|
+
type: resolveFilterType(defMap.get(c.field)),
|
|
5347
|
+
}));
|
|
5218
5348
|
return data.filter((row) => {
|
|
5219
|
-
|
|
5220
|
-
|
|
5221
|
-
const
|
|
5222
|
-
|
|
5223
|
-
|
|
5224
|
-
|
|
5225
|
-
|
|
5349
|
+
let pass = matchOne(row, prepared[0].cond, prepared[0].col, prepared[0].type);
|
|
5350
|
+
for (let i = 1; i < prepared.length; i++) {
|
|
5351
|
+
const step = prepared[i];
|
|
5352
|
+
const result = matchOne(row, step.cond, step.col, step.type);
|
|
5353
|
+
pass = step.cond.combinator === 'and' ? pass && result : pass || result;
|
|
5354
|
+
}
|
|
5355
|
+
return pass;
|
|
5226
5356
|
});
|
|
5227
5357
|
}
|
|
5228
|
-
|
|
5229
|
-
|
|
5230
|
-
|
|
5231
|
-
|
|
5232
|
-
|
|
5233
|
-
const
|
|
5234
|
-
|
|
5235
|
-
|
|
5236
|
-
|
|
5237
|
-
|
|
5238
|
-
|
|
5239
|
-
|
|
5240
|
-
|
|
5241
|
-
|
|
5242
|
-
|
|
5243
|
-
case 'lt':
|
|
5244
|
-
return Number(value) < Number(filterValue);
|
|
5245
|
-
case 'in': {
|
|
5246
|
-
const arr = Array.isArray(filterValue) ? filterValue : [filterValue];
|
|
5247
|
-
return arr.some((v) => String(v).toLowerCase() === strValue);
|
|
5248
|
-
}
|
|
5249
|
-
default:
|
|
5250
|
-
return true;
|
|
5358
|
+
// ------------------------------------------------------------------
|
|
5359
|
+
// Helpers
|
|
5360
|
+
// ------------------------------------------------------------------
|
|
5361
|
+
/** Returns a human-readable label for a condition ("Status equals En stock"). */
|
|
5362
|
+
toLabel(condition) {
|
|
5363
|
+
const def = this.state.columnDefMap().get(condition.field);
|
|
5364
|
+
const col = def?.headerName ?? condition.field;
|
|
5365
|
+
const op = OPERATOR_LABELS[condition.operator] ?? condition.operator;
|
|
5366
|
+
if (VALUELESS_OPERATORS.has(condition.operator)) {
|
|
5367
|
+
return `${col} ${op}`;
|
|
5368
|
+
}
|
|
5369
|
+
const value = formatValue(condition.value.value, def);
|
|
5370
|
+
if (RANGE_OPERATORS.has(condition.operator)) {
|
|
5371
|
+
const to = formatValue(condition.value.valueTo, def);
|
|
5372
|
+
return `${col} ${op} ${value} – ${to}`;
|
|
5251
5373
|
}
|
|
5374
|
+
return `${col} ${op} ${value}`;
|
|
5375
|
+
}
|
|
5376
|
+
/** Returns the filter data type inferred for a column. */
|
|
5377
|
+
getFilterType(field) {
|
|
5378
|
+
return resolveFilterType(this.state.columnDefMap().get(field));
|
|
5379
|
+
}
|
|
5380
|
+
/**
|
|
5381
|
+
* Builds the column descriptors consumed by the filter builder UI. The
|
|
5382
|
+
* returned list includes only filterable columns.
|
|
5383
|
+
*/
|
|
5384
|
+
describeFilterableColumns() {
|
|
5385
|
+
const defs = this.state.columnDefs();
|
|
5386
|
+
return defs.filter((d) => d.filterable && !d.filterTemplate).map((d) => this.describeColumn(d));
|
|
5387
|
+
}
|
|
5388
|
+
describeColumn(def) {
|
|
5389
|
+
const type = resolveFilterType(def);
|
|
5390
|
+
const operators = def.filterOperators && def.filterOperators.length > 0
|
|
5391
|
+
? def.filterOperators
|
|
5392
|
+
: DEFAULT_OPERATORS[type];
|
|
5393
|
+
const defaultOp = def.defaultFilterOperator ?? DEFAULT_OPERATOR_PER_TYPE[type];
|
|
5394
|
+
return {
|
|
5395
|
+
field: def.field,
|
|
5396
|
+
headerName: def.headerName ?? def.field,
|
|
5397
|
+
filterType: type,
|
|
5398
|
+
operators,
|
|
5399
|
+
defaultOperator: operators.includes(defaultOp) ? defaultOp : operators[0],
|
|
5400
|
+
options: def.filterOptions ?? inferOptionsFromData(this.state.sourceData(), def, type),
|
|
5401
|
+
};
|
|
5402
|
+
}
|
|
5403
|
+
/** Factory for new conditions created by the UI. */
|
|
5404
|
+
makeCondition(field, isFirst, overrides = {}) {
|
|
5405
|
+
const def = this.state.columnDefMap().get(field);
|
|
5406
|
+
const descriptor = def ? this.describeColumn(def) : null;
|
|
5407
|
+
return {
|
|
5408
|
+
id: generateConditionId(),
|
|
5409
|
+
combinator: isFirst ? 'and' : 'and',
|
|
5410
|
+
field,
|
|
5411
|
+
operator: descriptor?.defaultOperator ?? 'contains',
|
|
5412
|
+
value: {},
|
|
5413
|
+
...overrides,
|
|
5414
|
+
};
|
|
5415
|
+
}
|
|
5416
|
+
// ------------------------------------------------------------------
|
|
5417
|
+
// Internal
|
|
5418
|
+
// ------------------------------------------------------------------
|
|
5419
|
+
notify(reason, condition) {
|
|
5420
|
+
this.lastChange.set({
|
|
5421
|
+
model: { conditions: this.state.filterModel().conditions.slice() },
|
|
5422
|
+
condition,
|
|
5423
|
+
reason,
|
|
5424
|
+
});
|
|
5252
5425
|
}
|
|
5253
5426
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: FilterEngine, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
5254
5427
|
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: FilterEngine });
|
|
@@ -5256,6 +5429,181 @@ class FilterEngine {
|
|
|
5256
5429
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: FilterEngine, decorators: [{
|
|
5257
5430
|
type: Injectable
|
|
5258
5431
|
}] });
|
|
5432
|
+
// --------------------------------------------------------------------
|
|
5433
|
+
// Pure helpers
|
|
5434
|
+
// --------------------------------------------------------------------
|
|
5435
|
+
function resolveFilterType(def) {
|
|
5436
|
+
if (!def)
|
|
5437
|
+
return 'text';
|
|
5438
|
+
if (def.filterType)
|
|
5439
|
+
return def.filterType;
|
|
5440
|
+
switch (def.cellEditor) {
|
|
5441
|
+
case 'number':
|
|
5442
|
+
return 'number';
|
|
5443
|
+
case 'date':
|
|
5444
|
+
return 'date';
|
|
5445
|
+
case 'select':
|
|
5446
|
+
return 'set';
|
|
5447
|
+
case 'checkbox':
|
|
5448
|
+
case 'toggle':
|
|
5449
|
+
return 'boolean';
|
|
5450
|
+
default:
|
|
5451
|
+
return 'text';
|
|
5452
|
+
}
|
|
5453
|
+
}
|
|
5454
|
+
function matchOne(row, condition, col, type) {
|
|
5455
|
+
const raw = col?.valueGetter
|
|
5456
|
+
? col.valueGetter(row)
|
|
5457
|
+
: row[condition.field];
|
|
5458
|
+
const predicate = PREDICATES[type]?.[condition.operator];
|
|
5459
|
+
if (!predicate)
|
|
5460
|
+
return true;
|
|
5461
|
+
return predicate(raw, condition.value);
|
|
5462
|
+
}
|
|
5463
|
+
function formatValue(value, def) {
|
|
5464
|
+
if (value == null || value === '')
|
|
5465
|
+
return '';
|
|
5466
|
+
if (Array.isArray(value)) {
|
|
5467
|
+
return value.map((v) => formatSingleOption(v, def)).join(', ');
|
|
5468
|
+
}
|
|
5469
|
+
return formatSingleOption(value, def);
|
|
5470
|
+
}
|
|
5471
|
+
function formatSingleOption(value, def) {
|
|
5472
|
+
if (def?.filterOptions) {
|
|
5473
|
+
const opt = def.filterOptions.find((o) => String(o.value) === String(value));
|
|
5474
|
+
if (opt)
|
|
5475
|
+
return String(opt.label);
|
|
5476
|
+
}
|
|
5477
|
+
return String(value);
|
|
5478
|
+
}
|
|
5479
|
+
function inferOptionsFromData(data, def, type) {
|
|
5480
|
+
if (type !== 'set')
|
|
5481
|
+
return undefined;
|
|
5482
|
+
const seen = new Set();
|
|
5483
|
+
const out = [];
|
|
5484
|
+
for (const row of data) {
|
|
5485
|
+
const v = def.valueGetter ? def.valueGetter(row) : row[def.field];
|
|
5486
|
+
if (v == null)
|
|
5487
|
+
continue;
|
|
5488
|
+
const key = String(v);
|
|
5489
|
+
if (seen.has(key))
|
|
5490
|
+
continue;
|
|
5491
|
+
seen.add(key);
|
|
5492
|
+
out.push({ value: v, label: key });
|
|
5493
|
+
if (out.length >= 200)
|
|
5494
|
+
break;
|
|
5495
|
+
}
|
|
5496
|
+
return out;
|
|
5497
|
+
}
|
|
5498
|
+
// --------------------------------------------------------------------
|
|
5499
|
+
// Predicate table — dispatched by (filterType, operator)
|
|
5500
|
+
// --------------------------------------------------------------------
|
|
5501
|
+
const textContains = (cell, { value }) => String(cell ?? '')
|
|
5502
|
+
.toLowerCase()
|
|
5503
|
+
.includes(String(value ?? '').toLowerCase());
|
|
5504
|
+
const textNotContains = (cell, v) => !textContains(cell, v);
|
|
5505
|
+
const textEquals = (cell, { value }) => String(cell ?? '').toLowerCase() === String(value ?? '').toLowerCase();
|
|
5506
|
+
const textNotEquals = (cell, v) => !textEquals(cell, v);
|
|
5507
|
+
const textStartsWith = (cell, { value }) => String(cell ?? '')
|
|
5508
|
+
.toLowerCase()
|
|
5509
|
+
.startsWith(String(value ?? '').toLowerCase());
|
|
5510
|
+
const textEndsWith = (cell, { value }) => String(cell ?? '')
|
|
5511
|
+
.toLowerCase()
|
|
5512
|
+
.endsWith(String(value ?? '').toLowerCase());
|
|
5513
|
+
const blank = (cell) => cell == null || cell === '';
|
|
5514
|
+
const notBlank = (cell) => !blank(cell, { value: undefined });
|
|
5515
|
+
const numEquals = (cell, { value }) => toNum(cell) === toNum(value);
|
|
5516
|
+
const numNotEquals = (cell, v) => !numEquals(cell, v);
|
|
5517
|
+
const numGt = (cell, { value }) => toNum(cell) > toNum(value);
|
|
5518
|
+
const numGte = (cell, { value }) => toNum(cell) >= toNum(value);
|
|
5519
|
+
const numLt = (cell, { value }) => toNum(cell) < toNum(value);
|
|
5520
|
+
const numLte = (cell, { value }) => toNum(cell) <= toNum(value);
|
|
5521
|
+
const numBetween = (cell, { value, valueTo }) => {
|
|
5522
|
+
const n = toNum(cell);
|
|
5523
|
+
return n >= toNum(value) && n <= toNum(valueTo);
|
|
5524
|
+
};
|
|
5525
|
+
const dateEquals = (cell, { value }) => toTime(cell) === toTime(value);
|
|
5526
|
+
const dateNotEquals = (cell, v) => !dateEquals(cell, v);
|
|
5527
|
+
const dateGt = (cell, { value }) => toTime(cell) > toTime(value);
|
|
5528
|
+
const dateGte = (cell, { value }) => toTime(cell) >= toTime(value);
|
|
5529
|
+
const dateLt = (cell, { value }) => toTime(cell) < toTime(value);
|
|
5530
|
+
const dateLte = (cell, { value }) => toTime(cell) <= toTime(value);
|
|
5531
|
+
const dateBetween = (cell, { value, valueTo }) => {
|
|
5532
|
+
const t = toTime(cell);
|
|
5533
|
+
return t >= toTime(value) && t <= toTime(valueTo);
|
|
5534
|
+
};
|
|
5535
|
+
const setIn = (cell, { value }) => {
|
|
5536
|
+
const arr = Array.isArray(value) ? value : [value];
|
|
5537
|
+
if (arr.length === 0)
|
|
5538
|
+
return true;
|
|
5539
|
+
return arr.some((v) => String(v) === String(cell));
|
|
5540
|
+
};
|
|
5541
|
+
const setNotIn = (cell, v) => !setIn(cell, v);
|
|
5542
|
+
const boolEquals = (cell, { value }) => {
|
|
5543
|
+
const expected = value === true || value === 'true' || value === 1;
|
|
5544
|
+
const actual = cell === true || cell === 'true' || cell === 1;
|
|
5545
|
+
return expected === actual;
|
|
5546
|
+
};
|
|
5547
|
+
function toNum(v) {
|
|
5548
|
+
const n = typeof v === 'number' ? v : Number(v);
|
|
5549
|
+
return Number.isFinite(n) ? n : NaN;
|
|
5550
|
+
}
|
|
5551
|
+
function toTime(v) {
|
|
5552
|
+
if (v instanceof Date)
|
|
5553
|
+
return v.getTime();
|
|
5554
|
+
if (typeof v === 'number')
|
|
5555
|
+
return v;
|
|
5556
|
+
if (typeof v === 'string') {
|
|
5557
|
+
const parsed = Date.parse(v);
|
|
5558
|
+
return Number.isFinite(parsed) ? parsed : NaN;
|
|
5559
|
+
}
|
|
5560
|
+
return NaN;
|
|
5561
|
+
}
|
|
5562
|
+
const PREDICATES = {
|
|
5563
|
+
text: {
|
|
5564
|
+
contains: textContains,
|
|
5565
|
+
notContains: textNotContains,
|
|
5566
|
+
equals: textEquals,
|
|
5567
|
+
notEquals: textNotEquals,
|
|
5568
|
+
startsWith: textStartsWith,
|
|
5569
|
+
endsWith: textEndsWith,
|
|
5570
|
+
blank,
|
|
5571
|
+
notBlank,
|
|
5572
|
+
},
|
|
5573
|
+
number: {
|
|
5574
|
+
equals: numEquals,
|
|
5575
|
+
notEquals: numNotEquals,
|
|
5576
|
+
gt: numGt,
|
|
5577
|
+
gte: numGte,
|
|
5578
|
+
lt: numLt,
|
|
5579
|
+
lte: numLte,
|
|
5580
|
+
between: numBetween,
|
|
5581
|
+
blank,
|
|
5582
|
+
notBlank,
|
|
5583
|
+
},
|
|
5584
|
+
date: {
|
|
5585
|
+
equals: dateEquals,
|
|
5586
|
+
notEquals: dateNotEquals,
|
|
5587
|
+
gt: dateGt,
|
|
5588
|
+
gte: dateGte,
|
|
5589
|
+
lt: dateLt,
|
|
5590
|
+
lte: dateLte,
|
|
5591
|
+
between: dateBetween,
|
|
5592
|
+
blank,
|
|
5593
|
+
notBlank,
|
|
5594
|
+
},
|
|
5595
|
+
set: {
|
|
5596
|
+
in: setIn,
|
|
5597
|
+
notIn: setNotIn,
|
|
5598
|
+
blank,
|
|
5599
|
+
notBlank,
|
|
5600
|
+
},
|
|
5601
|
+
boolean: {
|
|
5602
|
+
equals: boolEquals,
|
|
5603
|
+
blank,
|
|
5604
|
+
notBlank,
|
|
5605
|
+
},
|
|
5606
|
+
};
|
|
5259
5607
|
|
|
5260
5608
|
class GroupEngine {
|
|
5261
5609
|
state = inject(GridStateManager);
|
|
@@ -7737,6 +8085,7 @@ class StatePersistenceEngine {
|
|
|
7737
8085
|
pinned: col.pinned,
|
|
7738
8086
|
})),
|
|
7739
8087
|
sorts: this.state.activeSorts(),
|
|
8088
|
+
filters: this.state.filterModel().conditions.map(({ id: _id, ...rest }) => rest),
|
|
7740
8089
|
};
|
|
7741
8090
|
try {
|
|
7742
8091
|
localStorage.setItem(storageKey, JSON.stringify(persisted));
|
|
@@ -7780,6 +8129,11 @@ class StatePersistenceEngine {
|
|
|
7780
8129
|
: { ...s, sort: null, sortIndex: null };
|
|
7781
8130
|
}));
|
|
7782
8131
|
}
|
|
8132
|
+
if (persisted.filters?.length) {
|
|
8133
|
+
this.state.filterModel.set({
|
|
8134
|
+
conditions: persisted.filters.map((f) => ({ ...f, id: generateConditionId() })),
|
|
8135
|
+
});
|
|
8136
|
+
}
|
|
7783
8137
|
return true;
|
|
7784
8138
|
}
|
|
7785
8139
|
catch {
|
|
@@ -8147,13 +8501,343 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
|
|
|
8147
8501
|
}]
|
|
8148
8502
|
}], propDecorators: { slot: [{ type: i0.Input, args: [{ isSignal: true, alias: "mozGridToolbarDef", required: false }] }] } });
|
|
8149
8503
|
|
|
8504
|
+
/**
|
|
8505
|
+
* Marks a `<ng-template>` projected into `<moz-grid>` as the renderer for
|
|
8506
|
+
* the empty state. Register one or two templates:
|
|
8507
|
+
*
|
|
8508
|
+
* ```html
|
|
8509
|
+
* <moz-grid [data]="rows">
|
|
8510
|
+
* <ng-template mozGridEmptyDef>
|
|
8511
|
+
* <p>Aucune donnée pour le moment</p>
|
|
8512
|
+
* </ng-template>
|
|
8513
|
+
*
|
|
8514
|
+
* <ng-template mozGridEmptyDef="no-results" let-ctx>
|
|
8515
|
+
* <p>Aucun résultat pour vos filtres ({{ ctx.activeFilterCount }})</p>
|
|
8516
|
+
* <button (click)="ctx.clearFilters()">Réinitialiser</button>
|
|
8517
|
+
* </ng-template>
|
|
8518
|
+
* </moz-grid>
|
|
8519
|
+
* ```
|
|
8520
|
+
*
|
|
8521
|
+
* The implicit context (`let-ctx`) exposes `{ activeFilterCount, clearFilters }`.
|
|
8522
|
+
*/
|
|
8523
|
+
class MozGridEmptyDef {
|
|
8524
|
+
kind = input('no-data', { ...(ngDevMode ? { debugName: "kind" } : /* istanbul ignore next */ {}), alias: 'mozGridEmptyDef' });
|
|
8525
|
+
template = inject(TemplateRef);
|
|
8526
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: MozGridEmptyDef, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
8527
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.9", type: MozGridEmptyDef, isStandalone: true, selector: "[mozGridEmptyDef]", inputs: { kind: { classPropertyName: "kind", publicName: "mozGridEmptyDef", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0 });
|
|
8528
|
+
}
|
|
8529
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: MozGridEmptyDef, decorators: [{
|
|
8530
|
+
type: Directive,
|
|
8531
|
+
args: [{
|
|
8532
|
+
selector: '[mozGridEmptyDef]',
|
|
8533
|
+
}]
|
|
8534
|
+
}], propDecorators: { kind: [{ type: i0.Input, args: [{ isSignal: true, alias: "mozGridEmptyDef", required: false }] }] } });
|
|
8535
|
+
|
|
8536
|
+
/**
|
|
8537
|
+
* Default empty-state shown by `<moz-grid>` when the body has no rows.
|
|
8538
|
+
* Two visual variants are dispatched on the `kind` input:
|
|
8539
|
+
* - `'no-data'` : the dataset is empty (folder icon, neutral copy).
|
|
8540
|
+
* - `'no-results'` : filters/search produced zero rows (search icon, CTA).
|
|
8541
|
+
*
|
|
8542
|
+
* Consumers can fully replace this component by projecting a
|
|
8543
|
+
* `<ng-template mozGridEmptyDef>` into the grid; see `MozGridEmptyDef`.
|
|
8544
|
+
*/
|
|
8545
|
+
class MozGridEmptyStateComponent {
|
|
8546
|
+
kind = input.required(...(ngDevMode ? [{ debugName: "kind" }] : /* istanbul ignore next */ []));
|
|
8547
|
+
title = input('', ...(ngDevMode ? [{ debugName: "title" }] : /* istanbul ignore next */ []));
|
|
8548
|
+
description = input('', ...(ngDevMode ? [{ debugName: "description" }] : /* istanbul ignore next */ []));
|
|
8549
|
+
/**
|
|
8550
|
+
* Optional CTA label. When falsy the button is not rendered. The grid
|
|
8551
|
+
* shell wires this to "Clear filters" for the `no-results` variant.
|
|
8552
|
+
*/
|
|
8553
|
+
actionLabel = input('', ...(ngDevMode ? [{ debugName: "actionLabel" }] : /* istanbul ignore next */ []));
|
|
8554
|
+
action = output();
|
|
8555
|
+
resolvedTitle = computed(() => {
|
|
8556
|
+
if (this.title())
|
|
8557
|
+
return this.title();
|
|
8558
|
+
return this.kind() === 'no-results' ? 'No matching results' : 'No data to display';
|
|
8559
|
+
}, ...(ngDevMode ? [{ debugName: "resolvedTitle" }] : /* istanbul ignore next */ []));
|
|
8560
|
+
resolvedDescription = computed(() => {
|
|
8561
|
+
if (this.description())
|
|
8562
|
+
return this.description();
|
|
8563
|
+
return this.kind() === 'no-results'
|
|
8564
|
+
? 'Try adjusting your filters or clearing them to see more rows.'
|
|
8565
|
+
: 'There is nothing to show here yet.';
|
|
8566
|
+
}, ...(ngDevMode ? [{ debugName: "resolvedDescription" }] : /* istanbul ignore next */ []));
|
|
8567
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: MozGridEmptyStateComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
8568
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: MozGridEmptyStateComponent, isStandalone: true, selector: "moz-grid-empty-state", inputs: { kind: { classPropertyName: "kind", publicName: "kind", isSignal: true, isRequired: true, transformFunction: null }, title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null }, description: { classPropertyName: "description", publicName: "description", isSignal: true, isRequired: false, transformFunction: null }, actionLabel: { classPropertyName: "actionLabel", publicName: "actionLabel", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { action: "action" }, ngImport: i0, template: "<div\n class=\"grid-empty-state\"\n [class.grid-empty-state--no-results]=\"kind() === 'no-results'\"\n role=\"status\"\n aria-live=\"polite\"\n>\n <div class=\"grid-empty-state__icon\" aria-hidden=\"true\">\n @if (kind() === 'no-results') {\n <Search48 />\n } @else {\n <Folder48 />\n }\n </div>\n\n <p class=\"grid-empty-state__title\">{{ resolvedTitle() }}</p>\n\n @if (resolvedDescription()) {\n <p class=\"grid-empty-state__description\">{{ resolvedDescription() }}</p>\n } @if (actionLabel()) {\n <button moz-button [outlined]=\"true\" size=\"s\" (click)=\"action.emit()\">\n {{ actionLabel() }}\n </button>\n }\n</div>\n", styles: [".grid-empty-state{display:flex;flex-direction:column;align-items:center;justify-content:center;text-align:center;gap:8px;padding:32px 24px;width:100%;height:100%;min-height:240px;color:var(--Text-Secondary, #555)}.grid-empty-state__icon{color:var(--Neutral-Grey-400, #97a1a8);margin-bottom:4px;display:inline-flex}.grid-empty-state__title{margin:0;font-size:16px;font-weight:600;color:var(--Text-Primary, #222)}.grid-empty-state__description{margin:0;max-width:360px;font-size:14px;line-height:1.4}.grid-empty-state--no-results .grid-empty-state__icon{color:var(--Status-Standalone-element-Primary, #0071ce)}\n"], dependencies: [{ kind: "component", type: Folder48, selector: "Folder48", inputs: ["hostClass"] }, { kind: "component", type: Search48, selector: "Search48", inputs: ["hostClass"] }, { kind: "component", type: MozButtonComponent, selector: "button[moz-button]", inputs: ["appearance", "size", "disabled", "ghost", "outlined", "iconPosition", "type", "isLoading"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
8569
|
+
}
|
|
8570
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: MozGridEmptyStateComponent, decorators: [{
|
|
8571
|
+
type: Component,
|
|
8572
|
+
args: [{ selector: 'moz-grid-empty-state', changeDetection: ChangeDetectionStrategy.OnPush, imports: [Folder48, Search48, MozButtonComponent], template: "<div\n class=\"grid-empty-state\"\n [class.grid-empty-state--no-results]=\"kind() === 'no-results'\"\n role=\"status\"\n aria-live=\"polite\"\n>\n <div class=\"grid-empty-state__icon\" aria-hidden=\"true\">\n @if (kind() === 'no-results') {\n <Search48 />\n } @else {\n <Folder48 />\n }\n </div>\n\n <p class=\"grid-empty-state__title\">{{ resolvedTitle() }}</p>\n\n @if (resolvedDescription()) {\n <p class=\"grid-empty-state__description\">{{ resolvedDescription() }}</p>\n } @if (actionLabel()) {\n <button moz-button [outlined]=\"true\" size=\"s\" (click)=\"action.emit()\">\n {{ actionLabel() }}\n </button>\n }\n</div>\n", styles: [".grid-empty-state{display:flex;flex-direction:column;align-items:center;justify-content:center;text-align:center;gap:8px;padding:32px 24px;width:100%;height:100%;min-height:240px;color:var(--Text-Secondary, #555)}.grid-empty-state__icon{color:var(--Neutral-Grey-400, #97a1a8);margin-bottom:4px;display:inline-flex}.grid-empty-state__title{margin:0;font-size:16px;font-weight:600;color:var(--Text-Primary, #222)}.grid-empty-state__description{margin:0;max-width:360px;font-size:14px;line-height:1.4}.grid-empty-state--no-results .grid-empty-state__icon{color:var(--Status-Standalone-element-Primary, #0071ce)}\n"] }]
|
|
8573
|
+
}], propDecorators: { kind: [{ type: i0.Input, args: [{ isSignal: true, alias: "kind", required: true }] }], title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: false }] }], description: [{ type: i0.Input, args: [{ isSignal: true, alias: "description", required: false }] }], actionLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "actionLabel", required: false }] }], action: [{ type: i0.Output, args: ["action"] }] } });
|
|
8574
|
+
|
|
8575
|
+
class MozGridFilterBuilderComponent {
|
|
8576
|
+
model = input.required(...(ngDevMode ? [{ debugName: "model" }] : /* istanbul ignore next */ []));
|
|
8577
|
+
availableColumns = input.required(...(ngDevMode ? [{ debugName: "availableColumns" }] : /* istanbul ignore next */ []));
|
|
8578
|
+
applyMode = input('auto', ...(ngDevMode ? [{ debugName: "applyMode" }] : /* istanbul ignore next */ []));
|
|
8579
|
+
/** Hint: when true, renders a "Show rows" sub-title (used inside the overlay). */
|
|
8580
|
+
showSubtitle = input(true, ...(ngDevMode ? [{ debugName: "showSubtitle" }] : /* istanbul ignore next */ []));
|
|
8581
|
+
modelChange = output();
|
|
8582
|
+
// Draft (what the user sees). Synced from `model` input on change.
|
|
8583
|
+
draft = signal([], ...(ngDevMode ? [{ debugName: "draft" }] : /* istanbul ignore next */ []));
|
|
8584
|
+
constructor() {
|
|
8585
|
+
effect(() => {
|
|
8586
|
+
const incoming = this.model().conditions;
|
|
8587
|
+
// Avoid clobbering local mutations: only sync when the incoming model
|
|
8588
|
+
// differs by id-set or values from the current draft.
|
|
8589
|
+
const current = untracked(() => this.draft());
|
|
8590
|
+
if (!conditionsEqual(incoming, current)) {
|
|
8591
|
+
this.draft.set(incoming.map((c) => ({ ...c, value: { ...c.value } })));
|
|
8592
|
+
}
|
|
8593
|
+
});
|
|
8594
|
+
}
|
|
8595
|
+
columnsById = computed(() => {
|
|
8596
|
+
const m = new Map();
|
|
8597
|
+
for (const c of this.availableColumns())
|
|
8598
|
+
m.set(c.field, c);
|
|
8599
|
+
return m;
|
|
8600
|
+
}, ...(ngDevMode ? [{ debugName: "columnsById" }] : /* istanbul ignore next */ []));
|
|
8601
|
+
operatorLabels = OPERATOR_LABELS;
|
|
8602
|
+
// ------------------------------------------------------------------
|
|
8603
|
+
// Mutations
|
|
8604
|
+
// ------------------------------------------------------------------
|
|
8605
|
+
addCondition() {
|
|
8606
|
+
const cols = this.availableColumns();
|
|
8607
|
+
if (cols.length === 0)
|
|
8608
|
+
return;
|
|
8609
|
+
const first = cols[0];
|
|
8610
|
+
const isFirst = this.draft().length === 0;
|
|
8611
|
+
const condition = {
|
|
8612
|
+
id: generateConditionId(),
|
|
8613
|
+
combinator: isFirst ? 'and' : 'and',
|
|
8614
|
+
field: first.field,
|
|
8615
|
+
operator: first.defaultOperator,
|
|
8616
|
+
value: {},
|
|
8617
|
+
};
|
|
8618
|
+
this.draft.update((list) => [...list, condition]);
|
|
8619
|
+
this.commit();
|
|
8620
|
+
}
|
|
8621
|
+
removeCondition(id) {
|
|
8622
|
+
this.draft.update((list) => list.filter((c) => c.id !== id));
|
|
8623
|
+
this.commit();
|
|
8624
|
+
}
|
|
8625
|
+
onCombinatorChange(id, combinator) {
|
|
8626
|
+
this.draft.update((list) => list.map((c) => (c.id === id ? { ...c, combinator } : c)));
|
|
8627
|
+
this.commit();
|
|
8628
|
+
}
|
|
8629
|
+
onFieldChange(id, field) {
|
|
8630
|
+
const col = this.columnsById().get(field);
|
|
8631
|
+
this.draft.update((list) => list.map((c) => c.id === id
|
|
8632
|
+
? {
|
|
8633
|
+
...c,
|
|
8634
|
+
field,
|
|
8635
|
+
operator: col?.defaultOperator ?? c.operator,
|
|
8636
|
+
value: {},
|
|
8637
|
+
}
|
|
8638
|
+
: c));
|
|
8639
|
+
this.commit();
|
|
8640
|
+
}
|
|
8641
|
+
onOperatorChange(id, operator) {
|
|
8642
|
+
this.draft.update((list) => list.map((c) => (c.id === id ? { ...c, operator, value: resetValueFor(operator, c.value) } : c)));
|
|
8643
|
+
this.commit();
|
|
8644
|
+
}
|
|
8645
|
+
onValueChange(id, patch) {
|
|
8646
|
+
this.draft.update((list) => list.map((c) => c.id === id
|
|
8647
|
+
? {
|
|
8648
|
+
...c,
|
|
8649
|
+
value: { ...c.value, ...patch },
|
|
8650
|
+
}
|
|
8651
|
+
: c));
|
|
8652
|
+
this.commit();
|
|
8653
|
+
}
|
|
8654
|
+
onSetValueChange(id, event) {
|
|
8655
|
+
const select = event.target;
|
|
8656
|
+
const values = Array.from(select.selectedOptions).map((o) => o.value);
|
|
8657
|
+
this.onValueChange(id, { value: values });
|
|
8658
|
+
}
|
|
8659
|
+
onDrop(event) {
|
|
8660
|
+
this.draft.update((list) => {
|
|
8661
|
+
const next = [...list];
|
|
8662
|
+
moveItemInArray(next, event.previousIndex, event.currentIndex);
|
|
8663
|
+
return next;
|
|
8664
|
+
});
|
|
8665
|
+
this.commit();
|
|
8666
|
+
}
|
|
8667
|
+
// ------------------------------------------------------------------
|
|
8668
|
+
// Value editor helpers (for the template)
|
|
8669
|
+
// ------------------------------------------------------------------
|
|
8670
|
+
needsValue(op) {
|
|
8671
|
+
return !VALUELESS_OPERATORS.has(op);
|
|
8672
|
+
}
|
|
8673
|
+
needsRange(op) {
|
|
8674
|
+
return RANGE_OPERATORS.has(op);
|
|
8675
|
+
}
|
|
8676
|
+
getSelectedSetValues(condition) {
|
|
8677
|
+
const v = condition.value.value;
|
|
8678
|
+
if (Array.isArray(v))
|
|
8679
|
+
return v.map((x) => String(x));
|
|
8680
|
+
if (v == null || v === '')
|
|
8681
|
+
return [];
|
|
8682
|
+
return [String(v)];
|
|
8683
|
+
}
|
|
8684
|
+
isSetValueSelected(condition, value) {
|
|
8685
|
+
return this.getSelectedSetValues(condition).includes(String(value));
|
|
8686
|
+
}
|
|
8687
|
+
inputTypeFor(op, type) {
|
|
8688
|
+
if (type === 'number')
|
|
8689
|
+
return 'number';
|
|
8690
|
+
if (type === 'date')
|
|
8691
|
+
return 'date';
|
|
8692
|
+
return 'text';
|
|
8693
|
+
}
|
|
8694
|
+
// ------------------------------------------------------------------
|
|
8695
|
+
// Internals
|
|
8696
|
+
// ------------------------------------------------------------------
|
|
8697
|
+
commit() {
|
|
8698
|
+
this.modelChange.emit({ conditions: this.draft().map((c) => ({ ...c, value: { ...c.value } })) });
|
|
8699
|
+
}
|
|
8700
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: MozGridFilterBuilderComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
8701
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: MozGridFilterBuilderComponent, isStandalone: true, selector: "moz-grid-filter-builder", inputs: { model: { classPropertyName: "model", publicName: "model", isSignal: true, isRequired: true, transformFunction: null }, availableColumns: { classPropertyName: "availableColumns", publicName: "availableColumns", isSignal: true, isRequired: true, transformFunction: null }, applyMode: { classPropertyName: "applyMode", publicName: "applyMode", isSignal: true, isRequired: false, transformFunction: null }, showSubtitle: { classPropertyName: "showSubtitle", publicName: "showSubtitle", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { modelChange: "modelChange" }, ngImport: i0, template: "<div class=\"filter-builder\">\n @if (showSubtitle()) {\n <p class=\"filter-builder__subtitle\">Show rows</p>\n }\n\n <div class=\"filter-builder__rows\" cdkDropList (cdkDropListDropped)=\"onDrop($event)\">\n @for (cond of draft(); track cond.id; let idx = $index; let first = $first) {\n <div class=\"filter-builder__row\" cdkDrag>\n <!-- Combinator -->\n <div class=\"filter-builder__combinator\">\n @if (first) {\n <span class=\"filter-builder__combinator-label\">Where</span>\n } @else {\n <select\n class=\"filter-builder__select filter-builder__select--combinator\"\n [value]=\"cond.combinator\"\n [attr.aria-label]=\"'Combinator for condition ' + (idx + 1)\"\n (change)=\"onCombinatorChange(cond.id, $any($event.target).value)\"\n >\n <option value=\"and\">And</option>\n <option value=\"or\">Or</option>\n </select>\n }\n </div>\n\n <!-- Column -->\n <select\n class=\"filter-builder__select filter-builder__select--column\"\n [value]=\"cond.field\"\n [attr.aria-label]=\"'Column for condition ' + (idx + 1)\"\n (change)=\"onFieldChange(cond.id, $any($event.target).value)\"\n >\n @for (col of availableColumns(); track col.field) {\n <option [value]=\"col.field\">{{ col.headerName }}</option>\n }\n </select>\n\n <!-- Operator -->\n <select\n class=\"filter-builder__select filter-builder__select--operator\"\n [value]=\"cond.operator\"\n [attr.aria-label]=\"'Operator for condition ' + (idx + 1)\"\n (change)=\"onOperatorChange(cond.id, $any($event.target).value)\"\n >\n @for (op of columnsById().get(cond.field)?.operators ?? []; track op) {\n <option [value]=\"op\">{{ operatorLabels[op] }}</option>\n }\n </select>\n\n <!-- Value -->\n <div class=\"filter-builder__value\">\n @if (needsValue(cond.operator)) { @let col = columnsById().get(cond.field); @if\n (col?.filterType === 'set') {\n <select\n class=\"filter-builder__select filter-builder__select--set\"\n multiple\n size=\"4\"\n [attr.aria-label]=\"'Values for condition ' + (idx + 1)\"\n (change)=\"onSetValueChange(cond.id, $event)\"\n >\n @for (opt of col?.options ?? []; track $any(opt.value)) {\n <option [value]=\"opt.value\" [selected]=\"isSetValueSelected(cond, opt.value)\">\n {{ opt.label }}\n </option>\n }\n </select>\n } @else if (col?.filterType === 'boolean') {\n <select\n class=\"filter-builder__select\"\n [value]=\"cond.value.value === true ? 'true' : 'false'\"\n [attr.aria-label]=\"'Value for condition ' + (idx + 1)\"\n (change)=\"onValueChange(cond.id, { value: $any($event.target).value === 'true' })\"\n >\n <option value=\"true\">True</option>\n <option value=\"false\">False</option>\n </select>\n } @else {\n <input\n class=\"filter-builder__input\"\n [type]=\"inputTypeFor(cond.operator, col?.filterType ?? 'text')\"\n [value]=\"cond.value.value ?? ''\"\n [attr.aria-label]=\"'Value for condition ' + (idx + 1)\"\n (input)=\"onValueChange(cond.id, { value: $any($event.target).value })\"\n />\n @if (needsRange(cond.operator)) {\n <span class=\"filter-builder__range-sep\">\u2013</span>\n <input\n class=\"filter-builder__input\"\n [type]=\"inputTypeFor(cond.operator, col?.filterType ?? 'text')\"\n [value]=\"cond.value.valueTo ?? ''\"\n [attr.aria-label]=\"'Upper bound for condition ' + (idx + 1)\"\n (input)=\"onValueChange(cond.id, { valueTo: $any($event.target).value })\"\n />\n } } }\n </div>\n\n <!-- Delete -->\n <button\n type=\"button\"\n moz-button\n [ghost]=\"true\"\n [size]=\"'s'\"\n [iconPosition]=\"'only'\"\n [attr.aria-label]=\"'Remove condition ' + (idx + 1)\"\n (click)=\"removeCondition(cond.id)\"\n >\n <Cross20 icon />\n </button>\n\n <!-- Drag handle -->\n <span\n class=\"filter-builder__drag\"\n cdkDragHandle\n [attr.aria-label]=\"'Reorder condition ' + (idx + 1)\"\n >\n <Drag20 />\n </span>\n </div>\n }\n </div>\n\n <button\n type=\"button\"\n class=\"filter-builder__add\"\n [disabled]=\"availableColumns().length === 0\"\n (click)=\"addCondition()\"\n >\n <ListAdd20 />\n <span>Add condition</span>\n </button>\n</div>\n", styles: [":host{display:block;background:var(--Background-Primary, #fff);border:1px solid var(--Border-Primary, #cdd4d8);border-radius:6px;box-shadow:0 4px 16px #0000001f}.filter-builder{display:flex;flex-direction:column;gap:12px;padding:16px}.filter-builder__subtitle{margin:0;font-size:12px;font-weight:600;text-transform:uppercase;letter-spacing:.06em;color:var(--Text-Secondary, #555)}.filter-builder__rows{display:flex;flex-direction:column;gap:8px}.filter-builder__row{display:flex;align-items:center;gap:8px;padding:6px 8px;border:1px solid var(--Border-Primary, #e0e0e0);border-radius:6px;background:var(--Background-Primary, #fff)}.filter-builder__row.cdk-drag-preview{box-shadow:0 2px 8px #0000001f}.filter-builder__row.cdk-drag-placeholder{opacity:.3}.filter-builder__combinator{min-width:64px;flex:0 0 64px}.filter-builder__combinator-label{display:inline-block;width:100%;padding:6px 8px;font-weight:600;color:var(--Text-Secondary, #555)}.filter-builder__select,.filter-builder__input{font:inherit;padding:6px 8px;border:1px solid var(--Border-Primary, #ccc);border-radius:4px;background:#fff;min-height:32px;box-sizing:border-box}.filter-builder__select--combinator{width:100%}.filter-builder__select--column,.filter-builder__select--operator{flex:1 1 120px;min-width:0}.filter-builder__select--set{min-width:160px;height:auto}.filter-builder__value{display:flex;align-items:center;gap:4px;flex:1 1 160px;min-width:0}.filter-builder__input{flex:1 1 0;min-width:0}.filter-builder__range-sep{color:var(--Text-Secondary, #777)}.filter-builder__drag{display:inline-flex;cursor:grab;color:var(--Text-Secondary, #777)}.filter-builder__drag:active{cursor:grabbing}.filter-builder__add{display:inline-flex;align-items:center;gap:6px;align-self:flex-start;padding:6px 10px;background:transparent;border:none;color:var(--Status-Standalone-element-Primary, #0071ce);font:inherit;cursor:pointer;border-radius:4px}.filter-builder__add:hover:not([disabled]){background:var(--Background-Secondary, #f4f4f4)}.filter-builder__add[disabled]{cursor:not-allowed;opacity:.5}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: CdkDropList, selector: "[cdkDropList], cdk-drop-list", inputs: ["cdkDropListConnectedTo", "cdkDropListData", "cdkDropListOrientation", "id", "cdkDropListLockAxis", "cdkDropListDisabled", "cdkDropListSortingDisabled", "cdkDropListEnterPredicate", "cdkDropListSortPredicate", "cdkDropListAutoScrollDisabled", "cdkDropListAutoScrollStep", "cdkDropListElementContainer", "cdkDropListHasAnchor"], outputs: ["cdkDropListDropped", "cdkDropListEntered", "cdkDropListExited", "cdkDropListSorted"], exportAs: ["cdkDropList"] }, { kind: "directive", type: CdkDrag, selector: "[cdkDrag]", inputs: ["cdkDragData", "cdkDragLockAxis", "cdkDragRootElement", "cdkDragBoundary", "cdkDragStartDelay", "cdkDragFreeDragPosition", "cdkDragDisabled", "cdkDragConstrainPosition", "cdkDragPreviewClass", "cdkDragPreviewContainer", "cdkDragScale"], outputs: ["cdkDragStarted", "cdkDragReleased", "cdkDragEnded", "cdkDragEntered", "cdkDragExited", "cdkDragDropped", "cdkDragMoved"], exportAs: ["cdkDrag"] }, { kind: "directive", type: CdkDragHandle, selector: "[cdkDragHandle]", inputs: ["cdkDragHandleDisabled"] }, { kind: "component", type: MozButtonComponent, selector: "button[moz-button]", inputs: ["appearance", "size", "disabled", "ghost", "outlined", "iconPosition", "type", "isLoading"] }, { kind: "component", type: Drag20, selector: "Drag20", inputs: ["hostClass"] }, { kind: "component", type: Cross20, selector: "Cross20", inputs: ["hostClass"] }, { kind: "component", type: ListAdd20, selector: "ListAdd20", inputs: ["hostClass"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
8702
|
+
}
|
|
8703
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: MozGridFilterBuilderComponent, decorators: [{
|
|
8704
|
+
type: Component,
|
|
8705
|
+
args: [{ selector: 'moz-grid-filter-builder', changeDetection: ChangeDetectionStrategy.OnPush, imports: [
|
|
8706
|
+
FormsModule,
|
|
8707
|
+
CdkDropList,
|
|
8708
|
+
CdkDrag,
|
|
8709
|
+
CdkDragHandle,
|
|
8710
|
+
MozButtonComponent,
|
|
8711
|
+
Drag20,
|
|
8712
|
+
Cross20,
|
|
8713
|
+
ListAdd20,
|
|
8714
|
+
], template: "<div class=\"filter-builder\">\n @if (showSubtitle()) {\n <p class=\"filter-builder__subtitle\">Show rows</p>\n }\n\n <div class=\"filter-builder__rows\" cdkDropList (cdkDropListDropped)=\"onDrop($event)\">\n @for (cond of draft(); track cond.id; let idx = $index; let first = $first) {\n <div class=\"filter-builder__row\" cdkDrag>\n <!-- Combinator -->\n <div class=\"filter-builder__combinator\">\n @if (first) {\n <span class=\"filter-builder__combinator-label\">Where</span>\n } @else {\n <select\n class=\"filter-builder__select filter-builder__select--combinator\"\n [value]=\"cond.combinator\"\n [attr.aria-label]=\"'Combinator for condition ' + (idx + 1)\"\n (change)=\"onCombinatorChange(cond.id, $any($event.target).value)\"\n >\n <option value=\"and\">And</option>\n <option value=\"or\">Or</option>\n </select>\n }\n </div>\n\n <!-- Column -->\n <select\n class=\"filter-builder__select filter-builder__select--column\"\n [value]=\"cond.field\"\n [attr.aria-label]=\"'Column for condition ' + (idx + 1)\"\n (change)=\"onFieldChange(cond.id, $any($event.target).value)\"\n >\n @for (col of availableColumns(); track col.field) {\n <option [value]=\"col.field\">{{ col.headerName }}</option>\n }\n </select>\n\n <!-- Operator -->\n <select\n class=\"filter-builder__select filter-builder__select--operator\"\n [value]=\"cond.operator\"\n [attr.aria-label]=\"'Operator for condition ' + (idx + 1)\"\n (change)=\"onOperatorChange(cond.id, $any($event.target).value)\"\n >\n @for (op of columnsById().get(cond.field)?.operators ?? []; track op) {\n <option [value]=\"op\">{{ operatorLabels[op] }}</option>\n }\n </select>\n\n <!-- Value -->\n <div class=\"filter-builder__value\">\n @if (needsValue(cond.operator)) { @let col = columnsById().get(cond.field); @if\n (col?.filterType === 'set') {\n <select\n class=\"filter-builder__select filter-builder__select--set\"\n multiple\n size=\"4\"\n [attr.aria-label]=\"'Values for condition ' + (idx + 1)\"\n (change)=\"onSetValueChange(cond.id, $event)\"\n >\n @for (opt of col?.options ?? []; track $any(opt.value)) {\n <option [value]=\"opt.value\" [selected]=\"isSetValueSelected(cond, opt.value)\">\n {{ opt.label }}\n </option>\n }\n </select>\n } @else if (col?.filterType === 'boolean') {\n <select\n class=\"filter-builder__select\"\n [value]=\"cond.value.value === true ? 'true' : 'false'\"\n [attr.aria-label]=\"'Value for condition ' + (idx + 1)\"\n (change)=\"onValueChange(cond.id, { value: $any($event.target).value === 'true' })\"\n >\n <option value=\"true\">True</option>\n <option value=\"false\">False</option>\n </select>\n } @else {\n <input\n class=\"filter-builder__input\"\n [type]=\"inputTypeFor(cond.operator, col?.filterType ?? 'text')\"\n [value]=\"cond.value.value ?? ''\"\n [attr.aria-label]=\"'Value for condition ' + (idx + 1)\"\n (input)=\"onValueChange(cond.id, { value: $any($event.target).value })\"\n />\n @if (needsRange(cond.operator)) {\n <span class=\"filter-builder__range-sep\">\u2013</span>\n <input\n class=\"filter-builder__input\"\n [type]=\"inputTypeFor(cond.operator, col?.filterType ?? 'text')\"\n [value]=\"cond.value.valueTo ?? ''\"\n [attr.aria-label]=\"'Upper bound for condition ' + (idx + 1)\"\n (input)=\"onValueChange(cond.id, { valueTo: $any($event.target).value })\"\n />\n } } }\n </div>\n\n <!-- Delete -->\n <button\n type=\"button\"\n moz-button\n [ghost]=\"true\"\n [size]=\"'s'\"\n [iconPosition]=\"'only'\"\n [attr.aria-label]=\"'Remove condition ' + (idx + 1)\"\n (click)=\"removeCondition(cond.id)\"\n >\n <Cross20 icon />\n </button>\n\n <!-- Drag handle -->\n <span\n class=\"filter-builder__drag\"\n cdkDragHandle\n [attr.aria-label]=\"'Reorder condition ' + (idx + 1)\"\n >\n <Drag20 />\n </span>\n </div>\n }\n </div>\n\n <button\n type=\"button\"\n class=\"filter-builder__add\"\n [disabled]=\"availableColumns().length === 0\"\n (click)=\"addCondition()\"\n >\n <ListAdd20 />\n <span>Add condition</span>\n </button>\n</div>\n", styles: [":host{display:block;background:var(--Background-Primary, #fff);border:1px solid var(--Border-Primary, #cdd4d8);border-radius:6px;box-shadow:0 4px 16px #0000001f}.filter-builder{display:flex;flex-direction:column;gap:12px;padding:16px}.filter-builder__subtitle{margin:0;font-size:12px;font-weight:600;text-transform:uppercase;letter-spacing:.06em;color:var(--Text-Secondary, #555)}.filter-builder__rows{display:flex;flex-direction:column;gap:8px}.filter-builder__row{display:flex;align-items:center;gap:8px;padding:6px 8px;border:1px solid var(--Border-Primary, #e0e0e0);border-radius:6px;background:var(--Background-Primary, #fff)}.filter-builder__row.cdk-drag-preview{box-shadow:0 2px 8px #0000001f}.filter-builder__row.cdk-drag-placeholder{opacity:.3}.filter-builder__combinator{min-width:64px;flex:0 0 64px}.filter-builder__combinator-label{display:inline-block;width:100%;padding:6px 8px;font-weight:600;color:var(--Text-Secondary, #555)}.filter-builder__select,.filter-builder__input{font:inherit;padding:6px 8px;border:1px solid var(--Border-Primary, #ccc);border-radius:4px;background:#fff;min-height:32px;box-sizing:border-box}.filter-builder__select--combinator{width:100%}.filter-builder__select--column,.filter-builder__select--operator{flex:1 1 120px;min-width:0}.filter-builder__select--set{min-width:160px;height:auto}.filter-builder__value{display:flex;align-items:center;gap:4px;flex:1 1 160px;min-width:0}.filter-builder__input{flex:1 1 0;min-width:0}.filter-builder__range-sep{color:var(--Text-Secondary, #777)}.filter-builder__drag{display:inline-flex;cursor:grab;color:var(--Text-Secondary, #777)}.filter-builder__drag:active{cursor:grabbing}.filter-builder__add{display:inline-flex;align-items:center;gap:6px;align-self:flex-start;padding:6px 10px;background:transparent;border:none;color:var(--Status-Standalone-element-Primary, #0071ce);font:inherit;cursor:pointer;border-radius:4px}.filter-builder__add:hover:not([disabled]){background:var(--Background-Secondary, #f4f4f4)}.filter-builder__add[disabled]{cursor:not-allowed;opacity:.5}\n"] }]
|
|
8715
|
+
}], ctorParameters: () => [], propDecorators: { model: [{ type: i0.Input, args: [{ isSignal: true, alias: "model", required: true }] }], availableColumns: [{ type: i0.Input, args: [{ isSignal: true, alias: "availableColumns", required: true }] }], applyMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "applyMode", required: false }] }], showSubtitle: [{ type: i0.Input, args: [{ isSignal: true, alias: "showSubtitle", required: false }] }], modelChange: [{ type: i0.Output, args: ["modelChange"] }] } });
|
|
8716
|
+
function resetValueFor(op, previous) {
|
|
8717
|
+
if (VALUELESS_OPERATORS.has(op))
|
|
8718
|
+
return {};
|
|
8719
|
+
if (RANGE_OPERATORS.has(op))
|
|
8720
|
+
return { value: previous.value ?? '', valueTo: previous.valueTo ?? '' };
|
|
8721
|
+
return { value: previous.value ?? '' };
|
|
8722
|
+
}
|
|
8723
|
+
function conditionsEqual(a, b) {
|
|
8724
|
+
if (a.length !== b.length)
|
|
8725
|
+
return false;
|
|
8726
|
+
for (let i = 0; i < a.length; i++) {
|
|
8727
|
+
const ca = a[i];
|
|
8728
|
+
const cb = b[i];
|
|
8729
|
+
if (ca.id !== cb.id ||
|
|
8730
|
+
ca.combinator !== cb.combinator ||
|
|
8731
|
+
ca.field !== cb.field ||
|
|
8732
|
+
ca.operator !== cb.operator ||
|
|
8733
|
+
ca.value.value !== cb.value.value ||
|
|
8734
|
+
ca.value.valueTo !== cb.value.valueTo) {
|
|
8735
|
+
return false;
|
|
8736
|
+
}
|
|
8737
|
+
}
|
|
8738
|
+
return true;
|
|
8739
|
+
}
|
|
8740
|
+
|
|
8741
|
+
/**
|
|
8742
|
+
* Programmatically opens a CDK overlay anchored on the host element that
|
|
8743
|
+
* renders the filter builder. Unlike the action-listbox directive, the
|
|
8744
|
+
* overlay does not toggle on click — the host is simply the anchor. Open
|
|
8745
|
+
* the overlay by injecting this directive via a template ref (`#filter`)
|
|
8746
|
+
* and calling `filter.open(options)`.
|
|
8747
|
+
*/
|
|
8748
|
+
class MozGridFilterOverlayDirective {
|
|
8749
|
+
overlay = inject(Overlay);
|
|
8750
|
+
host = inject((ElementRef));
|
|
8751
|
+
injector = inject(Injector);
|
|
8752
|
+
engine = inject(FilterEngine, { optional: true });
|
|
8753
|
+
overlayRef = null;
|
|
8754
|
+
componentRef = null;
|
|
8755
|
+
/** Opens the overlay anchored on the host. No-op if already open. */
|
|
8756
|
+
open(options) {
|
|
8757
|
+
if (this.overlayRef)
|
|
8758
|
+
return;
|
|
8759
|
+
if (!this.engine)
|
|
8760
|
+
return;
|
|
8761
|
+
const positions = [
|
|
8762
|
+
{ originX: 'start', originY: 'bottom', overlayX: 'start', overlayY: 'top', offsetY: 4 },
|
|
8763
|
+
{ originX: 'end', originY: 'bottom', overlayX: 'end', overlayY: 'top', offsetY: 4 },
|
|
8764
|
+
{ originX: 'start', originY: 'top', overlayX: 'start', overlayY: 'bottom', offsetY: -4 },
|
|
8765
|
+
];
|
|
8766
|
+
const positionStrategy = this.overlay
|
|
8767
|
+
.position()
|
|
8768
|
+
.flexibleConnectedTo(this.host)
|
|
8769
|
+
.withPositions(positions)
|
|
8770
|
+
.withPush(true)
|
|
8771
|
+
.withViewportMargin(8);
|
|
8772
|
+
const config = new OverlayConfig({
|
|
8773
|
+
hasBackdrop: true,
|
|
8774
|
+
backdropClass: 'cdk-overlay-transparent-backdrop',
|
|
8775
|
+
panelClass: 'moz-grid-filter-overlay',
|
|
8776
|
+
positionStrategy,
|
|
8777
|
+
scrollStrategy: this.overlay.scrollStrategies.reposition(),
|
|
8778
|
+
});
|
|
8779
|
+
const overlayRef = this.overlay.create(config);
|
|
8780
|
+
this.overlayRef = overlayRef;
|
|
8781
|
+
// Seed the draft with a new condition targeting the clicked column, if any
|
|
8782
|
+
const seededModel = options.seedField && options.model.conditions.length === 0
|
|
8783
|
+
? { conditions: [this.engine.makeCondition(options.seedField, true)] }
|
|
8784
|
+
: options.model;
|
|
8785
|
+
const portal = new ComponentPortal(MozGridFilterBuilderComponent, null, this.injector);
|
|
8786
|
+
const compRef = overlayRef.attach(portal);
|
|
8787
|
+
compRef.setInput('model', seededModel);
|
|
8788
|
+
compRef.setInput('availableColumns', options.columns);
|
|
8789
|
+
compRef.setInput('applyMode', 'auto');
|
|
8790
|
+
compRef.setInput('showSubtitle', true);
|
|
8791
|
+
compRef.instance.modelChange.subscribe((next) => {
|
|
8792
|
+
compRef.setInput('model', next);
|
|
8793
|
+
options.onChange(next);
|
|
8794
|
+
});
|
|
8795
|
+
this.componentRef = compRef;
|
|
8796
|
+
overlayRef.backdropClick().subscribe(() => this.close());
|
|
8797
|
+
overlayRef.keydownEvents().subscribe((event) => {
|
|
8798
|
+
if (event.key === 'Escape')
|
|
8799
|
+
this.close();
|
|
8800
|
+
});
|
|
8801
|
+
}
|
|
8802
|
+
close() {
|
|
8803
|
+
this.overlayRef?.dispose();
|
|
8804
|
+
this.overlayRef = null;
|
|
8805
|
+
this.componentRef = null;
|
|
8806
|
+
}
|
|
8807
|
+
ngOnDestroy() {
|
|
8808
|
+
this.close();
|
|
8809
|
+
}
|
|
8810
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: MozGridFilterOverlayDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
8811
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.9", type: MozGridFilterOverlayDirective, isStandalone: true, selector: "[mozGridFilterOverlay]", exportAs: ["mozGridFilterOverlay"], ngImport: i0 });
|
|
8812
|
+
}
|
|
8813
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: MozGridFilterOverlayDirective, decorators: [{
|
|
8814
|
+
type: Directive,
|
|
8815
|
+
args: [{
|
|
8816
|
+
selector: '[mozGridFilterOverlay]',
|
|
8817
|
+
exportAs: 'mozGridFilterOverlay',
|
|
8818
|
+
}]
|
|
8819
|
+
}] });
|
|
8820
|
+
|
|
8150
8821
|
class MozGridHeaderCellComponent {
|
|
8151
8822
|
state = inject(GridStateManager);
|
|
8823
|
+
filterEngine = inject(FilterEngine);
|
|
8152
8824
|
columnState = input.required(...(ngDevMode ? [{ debugName: "columnState" }] : /* istanbul ignore next */ []));
|
|
8153
8825
|
def = input.required(...(ngDevMode ? [{ debugName: "def" }] : /* istanbul ignore next */ []));
|
|
8154
8826
|
isLast = input(false, ...(ngDevMode ? [{ debugName: "isLast" }] : /* istanbul ignore next */ []));
|
|
8155
8827
|
pinnedEnd = input(false, ...(ngDevMode ? [{ debugName: "pinnedEnd" }] : /* istanbul ignore next */ []));
|
|
8156
8828
|
reorderable = input(false, ...(ngDevMode ? [{ debugName: "reorderable" }] : /* istanbul ignore next */ []));
|
|
8829
|
+
filterOverlay = viewChild(MozGridFilterOverlayDirective, ...(ngDevMode ? [{ debugName: "filterOverlay" }] : /* istanbul ignore next */ []));
|
|
8830
|
+
/** True when at least one active condition targets this column. */
|
|
8831
|
+
hasActiveFilter = computed(() => this.filterEngine.conditions().some((c) => c.field === this.columnState().field), ...(ngDevMode ? [{ debugName: "hasActiveFilter" }] : /* istanbul ignore next */ []));
|
|
8832
|
+
/** Tooltip for the gear / filter button (count + short summary). */
|
|
8833
|
+
filterTooltip = computed(() => {
|
|
8834
|
+
const field = this.columnState().field;
|
|
8835
|
+
const matching = this.filterEngine.conditions().filter((c) => c.field === field);
|
|
8836
|
+
if (matching.length === 0)
|
|
8837
|
+
return 'Column settings';
|
|
8838
|
+
const summary = matching.map((c) => this.filterEngine.toLabel(c)).join(', ');
|
|
8839
|
+
return `${matching.length} filter${matching.length > 1 ? 's' : ''}: ${summary}`;
|
|
8840
|
+
}, ...(ngDevMode ? [{ debugName: "filterTooltip" }] : /* istanbul ignore next */ []));
|
|
8157
8841
|
resolvedMinWidth = computed(() => {
|
|
8158
8842
|
const def = this.def();
|
|
8159
8843
|
return def.minWidth ? parseInt(def.minWidth, 10) || 50 : 50;
|
|
@@ -8175,6 +8859,14 @@ class MozGridHeaderCellComponent {
|
|
|
8175
8859
|
if (def.sortable !== false) {
|
|
8176
8860
|
items.push({ id: 'sort-asc', icon: ChevronUp20, label: 'Sort A → Z' }, { id: 'sort-desc', icon: ChevronDown20, label: 'Sort Z → A' });
|
|
8177
8861
|
}
|
|
8862
|
+
if (def.filterable) {
|
|
8863
|
+
items.push({
|
|
8864
|
+
id: 'filter-column',
|
|
8865
|
+
label: 'Filter in this column',
|
|
8866
|
+
icon: Filter20,
|
|
8867
|
+
divider: items.length > 0,
|
|
8868
|
+
});
|
|
8869
|
+
}
|
|
8178
8870
|
if (def.groupable) {
|
|
8179
8871
|
items.push({
|
|
8180
8872
|
id: 'group-column',
|
|
@@ -8220,24 +8912,58 @@ class MozGridHeaderCellComponent {
|
|
|
8220
8912
|
}
|
|
8221
8913
|
}
|
|
8222
8914
|
onMenuItemClick(item) {
|
|
8223
|
-
this.
|
|
8224
|
-
|
|
8225
|
-
|
|
8226
|
-
|
|
8915
|
+
const field = this.columnState().field;
|
|
8916
|
+
const actionId = item.id;
|
|
8917
|
+
// Intercept "Filter in this column": when the column does not provide a
|
|
8918
|
+
// custom `filterTemplate`, open the overlay anchored on the gear button
|
|
8919
|
+
// instead of delegating to the grid shell (which would toggle the legacy
|
|
8920
|
+
// per-column search input). Columns that ship a filterTemplate keep their
|
|
8921
|
+
// legacy behaviour — the grid handles them via `onMenuAction`.
|
|
8922
|
+
if (actionId === 'filter-column' && !this.def().filterTemplate) {
|
|
8923
|
+
this.openFilterOverlay(field);
|
|
8924
|
+
return;
|
|
8925
|
+
}
|
|
8926
|
+
this.menuAction.emit({ field, actionId });
|
|
8927
|
+
}
|
|
8928
|
+
openFilterOverlay(seedField) {
|
|
8929
|
+
// Defer so the action-listbox has time to tear down its overlay before
|
|
8930
|
+
// we attach a new one at roughly the same location. Without this, the
|
|
8931
|
+
// lingering mouseup from the menu-item click can land on the freshly
|
|
8932
|
+
// mounted filter backdrop and close it instantly.
|
|
8933
|
+
setTimeout(() => {
|
|
8934
|
+
const overlay = this.filterOverlay();
|
|
8935
|
+
if (!overlay)
|
|
8936
|
+
return;
|
|
8937
|
+
overlay.open({
|
|
8938
|
+
columns: this.filterEngine.describeFilterableColumns(),
|
|
8939
|
+
model: { conditions: this.filterEngine.conditions().slice() },
|
|
8940
|
+
seedField,
|
|
8941
|
+
onChange: (next) => {
|
|
8942
|
+
this.filterEngine.setModel(next, 'replace');
|
|
8943
|
+
},
|
|
8944
|
+
});
|
|
8945
|
+
}, 0);
|
|
8227
8946
|
}
|
|
8228
8947
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: MozGridHeaderCellComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
8229
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: MozGridHeaderCellComponent, isStandalone: true, selector: "moz-grid-header-cell", inputs: { columnState: { classPropertyName: "columnState", publicName: "columnState", isSignal: true, isRequired: true, transformFunction: null }, def: { classPropertyName: "def", publicName: "def", isSignal: true, isRequired: true, transformFunction: null }, isLast: { classPropertyName: "isLast", publicName: "isLast", isSignal: true, isRequired: false, transformFunction: null }, pinnedEnd: { classPropertyName: "pinnedEnd", publicName: "pinnedEnd", isSignal: true, isRequired: false, transformFunction: null }, reorderable: { classPropertyName: "reorderable", publicName: "reorderable", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { sortClick: "sortClick", menuAction: "menuAction", resizeStart: "resizeStart" }, host: { properties: { "style.flex": "isLast() ? \"1 0 auto\" : \"0 0 auto\"", "style.width.px": "isLast() ? undefined : columnState().currentWidth", "style.min-width.px": "isLast() ? columnState().currentWidth : resolvedMinWidth()", "class.grid-header-cell-host--dragging": "isDragging()", "class.grid-header-cell-host--reorderable": "reorderable()" } }, ngImport: i0, template: "<div\n class=\"grid-header-cell\"\n [class.grid-header-cell--sorted]=\"columnState().sort !== null\"\n [class.grid-header-cell--last]=\"isLast()\"\n [class.grid-header-cell--pinned-end]=\"pinnedEnd()\"\n>\n <div class=\"grid-header-cell__content\" (click)=\"onHeaderClick($event)\">\n <span class=\"grid-header-cell__label\">{{ label() }}</span>\n @if (columnState().sort === 'asc') {\n <ChevronUp20 class=\"grid-header-cell__sort-icon\" />\n } @if (columnState().sort === 'desc') {\n <ChevronDown20 class=\"grid-header-cell__sort-icon\" />\n }\n </div>\n\n @if (!def().headerMenuDisabled) {\n <button\n type=\"button\"\n class=\"grid-header-cell__menu-trigger\"\n [attr.aria-label]=\"'Column settings for ' + label()\"\n [mozActionListboxTrigger]=\"menuItems()\"\n actionListboxPosition=\"below\"\n (itemClick)=\"onMenuItemClick($event)\"\n (click)=\"$event.stopPropagation()\"\n >\n <Settings20 />\n </button>\n } @if (def().resizable !== false && (!isLast() || pinnedEnd())) {\n <div\n class=\"grid-header-cell__resize-handle\"\n [class.grid-header-cell__resize-handle--left]=\"pinnedEnd()\"\n (mousedown)=\"resizeStart.emit($event)\"\n ></div>\n }\n</div>\n", styles: [":host{display:block;height:100%}.grid-header-cell{display:flex;align-items:center;position:relative;height:100%;padding:0 var(--spacing-s, 8px);border-right:1px solid var(--color-border-primary);-webkit-user-select:none;user-select:none;box-sizing:border-box;min-width:0;background:inherit}.grid-header-cell--pinned-end{border-right:none;border-left:1px solid var(--color-border-primary)}:host(:first-child) .grid-header-cell--pinned-end{border-left:none}.grid-header-cell--last{border-right:none}.grid-header-cell__content{display:flex;align-items:center;gap:var(--spacing-xs, 4px);flex:1;min-width:0;cursor:pointer}.grid-header-cell__label{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--color-text-secondary);font-family:LeroyMerlin,sans-serif;font-size:var(--font-size-50);font-weight:700;text-transform:uppercase}.grid-header-cell__sort-icon{flex-shrink:0;color:var(--color-text-primary)}.grid-header-cell__menu-trigger{display:flex;align-items:center;justify-content:center;flex-shrink:0;width:28px;height:28px;padding:0;border:none;border-radius:var(--border-radius-s, 4px);background:transparent;cursor:pointer;color:var(--color-text-secondary);opacity:0;transition:opacity .15s ease}.grid-header-cell__menu-trigger:hover{background:var(--color-background-tertiary, rgba(0, 0, 0, .06));color:var(--color-text-primary)}.grid-header-cell:hover .grid-header-cell__menu-trigger{opacity:1}.grid-header-cell__resize-handle{position:absolute;right:0;top:0;bottom:0;width:4px;cursor:col-resize;z-index:1}.grid-header-cell__resize-handle:hover{background:var(--color-background-accent-inverse)}.grid-header-cell__resize-handle--left{right:auto;left:0}:host(.grid-header-cell-host--reorderable) .grid-header-cell__content{cursor:grab}:host(.grid-header-cell-host--dragging){outline:2px solid var(--color-background-accent-inverse);outline-offset:-2px;opacity:.85;z-index:1}\n"], dependencies: [{ kind: "component", type: ChevronDown20, selector: "ChevronDown20", inputs: ["hostClass"] }, { kind: "component", type: ChevronUp20, selector: "ChevronUp20", inputs: ["hostClass"] }, { kind: "component", type: Settings20, selector: "Settings20", inputs: ["hostClass"] }, { kind: "directive", type: MozActionListboxTriggerDirective, selector: "[mozActionListboxTrigger]", inputs: ["mozActionListboxTrigger", "actionListboxTitle", "actionListboxPosition"], outputs: ["itemClick"], exportAs: ["mozActionListboxTrigger"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
8948
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: MozGridHeaderCellComponent, isStandalone: true, selector: "moz-grid-header-cell", inputs: { columnState: { classPropertyName: "columnState", publicName: "columnState", isSignal: true, isRequired: true, transformFunction: null }, def: { classPropertyName: "def", publicName: "def", isSignal: true, isRequired: true, transformFunction: null }, isLast: { classPropertyName: "isLast", publicName: "isLast", isSignal: true, isRequired: false, transformFunction: null }, pinnedEnd: { classPropertyName: "pinnedEnd", publicName: "pinnedEnd", isSignal: true, isRequired: false, transformFunction: null }, reorderable: { classPropertyName: "reorderable", publicName: "reorderable", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { sortClick: "sortClick", menuAction: "menuAction", resizeStart: "resizeStart" }, host: { properties: { "style.flex": "isLast() ? \"1 0 auto\" : \"0 0 auto\"", "style.width.px": "isLast() ? undefined : columnState().currentWidth", "style.min-width.px": "isLast() ? columnState().currentWidth : resolvedMinWidth()", "class.grid-header-cell-host--dragging": "isDragging()", "class.grid-header-cell-host--reorderable": "reorderable()" } }, viewQueries: [{ propertyName: "filterOverlay", first: true, predicate: MozGridFilterOverlayDirective, descendants: true, isSignal: true }], ngImport: i0, template: "<div\n class=\"grid-header-cell\"\n [class.grid-header-cell--sorted]=\"columnState().sort !== null\"\n [class.grid-header-cell--last]=\"isLast()\"\n [class.grid-header-cell--pinned-end]=\"pinnedEnd()\"\n>\n <div class=\"grid-header-cell__content\" (click)=\"onHeaderClick($event)\">\n <span class=\"grid-header-cell__label\">{{ label() }}</span>\n @if (columnState().sort === 'asc') {\n <ChevronUp20 class=\"grid-header-cell__sort-icon\" />\n } @if (columnState().sort === 'desc') {\n <ChevronDown20 class=\"grid-header-cell__sort-icon\" />\n }\n </div>\n\n @if (!def().headerMenuDisabled) {\n <button\n type=\"button\"\n class=\"grid-header-cell__menu-trigger\"\n [class.grid-header-cell__menu-trigger--filtered]=\"hasActiveFilter()\"\n [attr.aria-label]=\"'Column settings for ' + label()\"\n [attr.title]=\"filterTooltip()\"\n [mozActionListboxTrigger]=\"menuItems()\"\n actionListboxPosition=\"below\"\n mozGridFilterOverlay\n (itemClick)=\"onMenuItemClick($event)\"\n (click)=\"$event.stopPropagation()\"\n >\n @if (hasActiveFilter()) {\n <Filter20 />\n } @else {\n <Settings20 />\n }\n </button>\n } @if (def().resizable !== false && (!isLast() || pinnedEnd())) {\n <div\n class=\"grid-header-cell__resize-handle\"\n [class.grid-header-cell__resize-handle--left]=\"pinnedEnd()\"\n (mousedown)=\"resizeStart.emit($event)\"\n ></div>\n }\n</div>\n", styles: [":host{display:block;height:100%}.grid-header-cell{display:flex;align-items:center;position:relative;height:100%;padding:0 var(--spacing-s, 8px);border-right:1px solid var(--color-border-primary);-webkit-user-select:none;user-select:none;box-sizing:border-box;min-width:0;background:inherit}.grid-header-cell--pinned-end{border-right:none;border-left:1px solid var(--color-border-primary)}:host(:first-child) .grid-header-cell--pinned-end{border-left:none}.grid-header-cell--last{border-right:none}.grid-header-cell__content{display:flex;align-items:center;gap:var(--spacing-xs, 4px);flex:1;min-width:0;cursor:pointer}.grid-header-cell__label{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--color-text-secondary);font-family:LeroyMerlin,sans-serif;font-size:var(--font-size-50);font-weight:700;text-transform:uppercase}.grid-header-cell__sort-icon{flex-shrink:0;color:var(--color-text-primary)}.grid-header-cell__menu-trigger{display:flex;align-items:center;justify-content:center;flex-shrink:0;width:28px;height:28px;padding:0;border:none;border-radius:var(--border-radius-s, 4px);background:transparent;cursor:pointer;color:var(--color-text-secondary);opacity:0;transition:opacity .15s ease}.grid-header-cell__menu-trigger:hover{background:var(--color-background-tertiary, rgba(0, 0, 0, .06));color:var(--color-text-primary)}.grid-header-cell:hover .grid-header-cell__menu-trigger{opacity:1}.grid-header-cell__menu-trigger--filtered{opacity:1;color:var(--Status-Standalone-element-Primary, #0071ce)}.grid-header-cell__resize-handle{position:absolute;right:0;top:0;bottom:0;width:4px;cursor:col-resize;z-index:1}.grid-header-cell__resize-handle:hover{background:var(--color-background-accent-inverse)}.grid-header-cell__resize-handle--left{right:auto;left:0}:host(.grid-header-cell-host--reorderable) .grid-header-cell__content{cursor:grab}:host(.grid-header-cell-host--dragging){outline:2px solid var(--color-background-accent-inverse);outline-offset:-2px;opacity:.85;z-index:1}\n"], dependencies: [{ kind: "component", type: ChevronDown20, selector: "ChevronDown20", inputs: ["hostClass"] }, { kind: "component", type: ChevronUp20, selector: "ChevronUp20", inputs: ["hostClass"] }, { kind: "component", type: Settings20, selector: "Settings20", inputs: ["hostClass"] }, { kind: "component", type: Filter20, selector: "Filter20", inputs: ["hostClass"] }, { kind: "directive", type: MozActionListboxTriggerDirective, selector: "[mozActionListboxTrigger]", inputs: ["mozActionListboxTrigger", "actionListboxTitle", "actionListboxPosition"], outputs: ["itemClick"], exportAs: ["mozActionListboxTrigger"] }, { kind: "directive", type: MozGridFilterOverlayDirective, selector: "[mozGridFilterOverlay]", exportAs: ["mozGridFilterOverlay"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
8230
8949
|
}
|
|
8231
8950
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: MozGridHeaderCellComponent, decorators: [{
|
|
8232
8951
|
type: Component,
|
|
8233
|
-
args: [{ selector: 'moz-grid-header-cell', changeDetection: ChangeDetectionStrategy.OnPush, imports: [
|
|
8952
|
+
args: [{ selector: 'moz-grid-header-cell', changeDetection: ChangeDetectionStrategy.OnPush, imports: [
|
|
8953
|
+
ChevronDown20,
|
|
8954
|
+
ChevronUp20,
|
|
8955
|
+
Settings20,
|
|
8956
|
+
Filter20,
|
|
8957
|
+
MozActionListboxTriggerDirective,
|
|
8958
|
+
MozGridFilterOverlayDirective,
|
|
8959
|
+
], host: {
|
|
8234
8960
|
'[style.flex]': 'isLast() ? "1 0 auto" : "0 0 auto"',
|
|
8235
8961
|
'[style.width.px]': 'isLast() ? undefined : columnState().currentWidth',
|
|
8236
8962
|
'[style.min-width.px]': 'isLast() ? columnState().currentWidth : resolvedMinWidth()',
|
|
8237
8963
|
'[class.grid-header-cell-host--dragging]': 'isDragging()',
|
|
8238
8964
|
'[class.grid-header-cell-host--reorderable]': 'reorderable()',
|
|
8239
|
-
}, template: "<div\n class=\"grid-header-cell\"\n [class.grid-header-cell--sorted]=\"columnState().sort !== null\"\n [class.grid-header-cell--last]=\"isLast()\"\n [class.grid-header-cell--pinned-end]=\"pinnedEnd()\"\n>\n <div class=\"grid-header-cell__content\" (click)=\"onHeaderClick($event)\">\n <span class=\"grid-header-cell__label\">{{ label() }}</span>\n @if (columnState().sort === 'asc') {\n <ChevronUp20 class=\"grid-header-cell__sort-icon\" />\n } @if (columnState().sort === 'desc') {\n <ChevronDown20 class=\"grid-header-cell__sort-icon\" />\n }\n </div>\n\n @if (!def().headerMenuDisabled) {\n <button\n type=\"button\"\n class=\"grid-header-cell__menu-trigger\"\n [attr.aria-label]=\"'Column settings for ' + label()\"\n [mozActionListboxTrigger]=\"menuItems()\"\n actionListboxPosition=\"below\"\n (itemClick)=\"onMenuItemClick($event)\"\n (click)=\"$event.stopPropagation()\"\n >\n <Settings20 />\n </button>\n } @if (def().resizable !== false && (!isLast() || pinnedEnd())) {\n <div\n class=\"grid-header-cell__resize-handle\"\n [class.grid-header-cell__resize-handle--left]=\"pinnedEnd()\"\n (mousedown)=\"resizeStart.emit($event)\"\n ></div>\n }\n</div>\n", styles: [":host{display:block;height:100%}.grid-header-cell{display:flex;align-items:center;position:relative;height:100%;padding:0 var(--spacing-s, 8px);border-right:1px solid var(--color-border-primary);-webkit-user-select:none;user-select:none;box-sizing:border-box;min-width:0;background:inherit}.grid-header-cell--pinned-end{border-right:none;border-left:1px solid var(--color-border-primary)}:host(:first-child) .grid-header-cell--pinned-end{border-left:none}.grid-header-cell--last{border-right:none}.grid-header-cell__content{display:flex;align-items:center;gap:var(--spacing-xs, 4px);flex:1;min-width:0;cursor:pointer}.grid-header-cell__label{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--color-text-secondary);font-family:LeroyMerlin,sans-serif;font-size:var(--font-size-50);font-weight:700;text-transform:uppercase}.grid-header-cell__sort-icon{flex-shrink:0;color:var(--color-text-primary)}.grid-header-cell__menu-trigger{display:flex;align-items:center;justify-content:center;flex-shrink:0;width:28px;height:28px;padding:0;border:none;border-radius:var(--border-radius-s, 4px);background:transparent;cursor:pointer;color:var(--color-text-secondary);opacity:0;transition:opacity .15s ease}.grid-header-cell__menu-trigger:hover{background:var(--color-background-tertiary, rgba(0, 0, 0, .06));color:var(--color-text-primary)}.grid-header-cell:hover .grid-header-cell__menu-trigger{opacity:1}.grid-header-cell__resize-handle{position:absolute;right:0;top:0;bottom:0;width:4px;cursor:col-resize;z-index:1}.grid-header-cell__resize-handle:hover{background:var(--color-background-accent-inverse)}.grid-header-cell__resize-handle--left{right:auto;left:0}:host(.grid-header-cell-host--reorderable) .grid-header-cell__content{cursor:grab}:host(.grid-header-cell-host--dragging){outline:2px solid var(--color-background-accent-inverse);outline-offset:-2px;opacity:.85;z-index:1}\n"] }]
|
|
8240
|
-
}], propDecorators: { columnState: [{ type: i0.Input, args: [{ isSignal: true, alias: "columnState", required: true }] }], def: [{ type: i0.Input, args: [{ isSignal: true, alias: "def", required: true }] }], isLast: [{ type: i0.Input, args: [{ isSignal: true, alias: "isLast", required: false }] }], pinnedEnd: [{ type: i0.Input, args: [{ isSignal: true, alias: "pinnedEnd", required: false }] }], reorderable: [{ type: i0.Input, args: [{ isSignal: true, alias: "reorderable", required: false }] }], sortClick: [{ type: i0.Output, args: ["sortClick"] }], menuAction: [{ type: i0.Output, args: ["menuAction"] }], resizeStart: [{ type: i0.Output, args: ["resizeStart"] }] } });
|
|
8965
|
+
}, template: "<div\n class=\"grid-header-cell\"\n [class.grid-header-cell--sorted]=\"columnState().sort !== null\"\n [class.grid-header-cell--last]=\"isLast()\"\n [class.grid-header-cell--pinned-end]=\"pinnedEnd()\"\n>\n <div class=\"grid-header-cell__content\" (click)=\"onHeaderClick($event)\">\n <span class=\"grid-header-cell__label\">{{ label() }}</span>\n @if (columnState().sort === 'asc') {\n <ChevronUp20 class=\"grid-header-cell__sort-icon\" />\n } @if (columnState().sort === 'desc') {\n <ChevronDown20 class=\"grid-header-cell__sort-icon\" />\n }\n </div>\n\n @if (!def().headerMenuDisabled) {\n <button\n type=\"button\"\n class=\"grid-header-cell__menu-trigger\"\n [class.grid-header-cell__menu-trigger--filtered]=\"hasActiveFilter()\"\n [attr.aria-label]=\"'Column settings for ' + label()\"\n [attr.title]=\"filterTooltip()\"\n [mozActionListboxTrigger]=\"menuItems()\"\n actionListboxPosition=\"below\"\n mozGridFilterOverlay\n (itemClick)=\"onMenuItemClick($event)\"\n (click)=\"$event.stopPropagation()\"\n >\n @if (hasActiveFilter()) {\n <Filter20 />\n } @else {\n <Settings20 />\n }\n </button>\n } @if (def().resizable !== false && (!isLast() || pinnedEnd())) {\n <div\n class=\"grid-header-cell__resize-handle\"\n [class.grid-header-cell__resize-handle--left]=\"pinnedEnd()\"\n (mousedown)=\"resizeStart.emit($event)\"\n ></div>\n }\n</div>\n", styles: [":host{display:block;height:100%}.grid-header-cell{display:flex;align-items:center;position:relative;height:100%;padding:0 var(--spacing-s, 8px);border-right:1px solid var(--color-border-primary);-webkit-user-select:none;user-select:none;box-sizing:border-box;min-width:0;background:inherit}.grid-header-cell--pinned-end{border-right:none;border-left:1px solid var(--color-border-primary)}:host(:first-child) .grid-header-cell--pinned-end{border-left:none}.grid-header-cell--last{border-right:none}.grid-header-cell__content{display:flex;align-items:center;gap:var(--spacing-xs, 4px);flex:1;min-width:0;cursor:pointer}.grid-header-cell__label{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--color-text-secondary);font-family:LeroyMerlin,sans-serif;font-size:var(--font-size-50);font-weight:700;text-transform:uppercase}.grid-header-cell__sort-icon{flex-shrink:0;color:var(--color-text-primary)}.grid-header-cell__menu-trigger{display:flex;align-items:center;justify-content:center;flex-shrink:0;width:28px;height:28px;padding:0;border:none;border-radius:var(--border-radius-s, 4px);background:transparent;cursor:pointer;color:var(--color-text-secondary);opacity:0;transition:opacity .15s ease}.grid-header-cell__menu-trigger:hover{background:var(--color-background-tertiary, rgba(0, 0, 0, .06));color:var(--color-text-primary)}.grid-header-cell:hover .grid-header-cell__menu-trigger{opacity:1}.grid-header-cell__menu-trigger--filtered{opacity:1;color:var(--Status-Standalone-element-Primary, #0071ce)}.grid-header-cell__resize-handle{position:absolute;right:0;top:0;bottom:0;width:4px;cursor:col-resize;z-index:1}.grid-header-cell__resize-handle:hover{background:var(--color-background-accent-inverse)}.grid-header-cell__resize-handle--left{right:auto;left:0}:host(.grid-header-cell-host--reorderable) .grid-header-cell__content{cursor:grab}:host(.grid-header-cell-host--dragging){outline:2px solid var(--color-background-accent-inverse);outline-offset:-2px;opacity:.85;z-index:1}\n"] }]
|
|
8966
|
+
}], propDecorators: { columnState: [{ type: i0.Input, args: [{ isSignal: true, alias: "columnState", required: true }] }], def: [{ type: i0.Input, args: [{ isSignal: true, alias: "def", required: true }] }], isLast: [{ type: i0.Input, args: [{ isSignal: true, alias: "isLast", required: false }] }], pinnedEnd: [{ type: i0.Input, args: [{ isSignal: true, alias: "pinnedEnd", required: false }] }], reorderable: [{ type: i0.Input, args: [{ isSignal: true, alias: "reorderable", required: false }] }], filterOverlay: [{ type: i0.ViewChild, args: [i0.forwardRef(() => MozGridFilterOverlayDirective), { isSignal: true }] }], sortClick: [{ type: i0.Output, args: ["sortClick"] }], menuAction: [{ type: i0.Output, args: ["menuAction"] }], resizeStart: [{ type: i0.Output, args: ["resizeStart"] }] } });
|
|
8241
8967
|
|
|
8242
8968
|
function trackDisplayRow(_index, row) {
|
|
8243
8969
|
if (row.type === 'group') {
|
|
@@ -8490,6 +9216,12 @@ class AutoSizeVirtualScrollStrategy {
|
|
|
8490
9216
|
const viewportSize = this._viewport.getViewportSize();
|
|
8491
9217
|
const dataLength = this._viewport.getDataLength();
|
|
8492
9218
|
if (dataLength === 0) {
|
|
9219
|
+
// IMPORTANT: also reset the cache. Otherwise, when data comes back to
|
|
9220
|
+
// the same length as before the empty state (e.g. filter matching N,
|
|
9221
|
+
// then 0, then N again), the range we compute below equals the stale
|
|
9222
|
+
// `_lastRenderedRange` and `setRenderedRange` is skipped — the viewport
|
|
9223
|
+
// stays stuck on empty until a scroll event forces a re-render.
|
|
9224
|
+
this._lastRenderedRange = { start: 0, end: 0 };
|
|
8493
9225
|
this._viewport.setRenderedRange({ start: 0, end: 0 });
|
|
8494
9226
|
this._viewport.setRenderedContentOffset(0);
|
|
8495
9227
|
return;
|
|
@@ -8637,8 +9369,9 @@ class AutoSizeVirtualScrollStrategy {
|
|
|
8637
9369
|
// Quick check: if the first child matches the default height,
|
|
8638
9370
|
// assume all rows are uniform and skip the full measurement pass.
|
|
8639
9371
|
const firstHeight = children[0].offsetHeight;
|
|
8640
|
-
if (firstHeight > 0 &&
|
|
8641
|
-
|
|
9372
|
+
if (firstHeight > 0 &&
|
|
9373
|
+
Math.abs(firstHeight - this._defaultItemSize) <= 0.5 &&
|
|
9374
|
+
this._heightMap.size === 0) {
|
|
8642
9375
|
return;
|
|
8643
9376
|
}
|
|
8644
9377
|
let changed = false;
|
|
@@ -8765,13 +9498,36 @@ class MozGridCellComponent {
|
|
|
8765
9498
|
const editorEl = this.elRef.nativeElement.querySelector('.grid-cell__editor');
|
|
8766
9499
|
if (!editorEl)
|
|
8767
9500
|
return;
|
|
8768
|
-
// Temporarily remove overflow constraint to measure natural content width
|
|
8769
9501
|
const cell = this.elRef.nativeElement.querySelector('.grid-cell');
|
|
9502
|
+
// The cell-level `overflow: hidden`, the editor's `width: 100%`, the
|
|
9503
|
+
// `flex-wrap: wrap` on `.grid-cell__editor-custom` and the global
|
|
9504
|
+
// `.grid-cell__editor ::ng-deep * { max-width: 100% }` rule all collapse
|
|
9505
|
+
// the editor's content back inside the current column width. Lift each of
|
|
9506
|
+
// those — on the editor and every descendant — so scrollWidth reports
|
|
9507
|
+
// the true natural width. Restore everything after measuring.
|
|
9508
|
+
const prevCellOverflow = cell?.style.overflow ?? '';
|
|
9509
|
+
const prevEditorCss = editorEl.style.cssText;
|
|
9510
|
+
const descendants = editorEl.querySelectorAll('*');
|
|
9511
|
+
const prevDescendantCss = [];
|
|
9512
|
+
descendants.forEach((el) => {
|
|
9513
|
+
prevDescendantCss.push(el.style.cssText);
|
|
9514
|
+
el.style.maxWidth = 'none';
|
|
9515
|
+
el.style.minWidth = 'max-content';
|
|
9516
|
+
el.style.flexWrap = 'nowrap';
|
|
9517
|
+
el.style.overflow = 'visible';
|
|
9518
|
+
});
|
|
8770
9519
|
if (cell)
|
|
8771
9520
|
cell.style.overflow = 'visible';
|
|
9521
|
+
editorEl.style.width = 'max-content';
|
|
9522
|
+
editorEl.style.maxWidth = 'none';
|
|
9523
|
+
editorEl.style.overflow = 'visible';
|
|
8772
9524
|
const contentWidth = editorEl.scrollWidth + 16; // 16 = cell horizontal padding (8px × 2)
|
|
8773
9525
|
if (cell)
|
|
8774
|
-
cell.style.overflow =
|
|
9526
|
+
cell.style.overflow = prevCellOverflow;
|
|
9527
|
+
editorEl.style.cssText = prevEditorCss;
|
|
9528
|
+
descendants.forEach((el, i) => {
|
|
9529
|
+
el.style.cssText = prevDescendantCss[i];
|
|
9530
|
+
});
|
|
8775
9531
|
if (contentWidth > currentWidth) {
|
|
8776
9532
|
this.state.updateColumnState(field, { currentWidth: contentWidth });
|
|
8777
9533
|
}
|
|
@@ -8950,7 +9706,7 @@ class MozGridCellComponent {
|
|
|
8950
9706
|
});
|
|
8951
9707
|
}
|
|
8952
9708
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: MozGridCellComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
8953
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: MozGridCellComponent, isStandalone: true, selector: "moz-grid-cell", inputs: { row: { classPropertyName: "row", publicName: "row", isSignal: true, isRequired: true, transformFunction: null }, rowIndex: { classPropertyName: "rowIndex", publicName: "rowIndex", isSignal: true, isRequired: true, transformFunction: null }, colIndex: { classPropertyName: "colIndex", publicName: "colIndex", isSignal: true, isRequired: true, transformFunction: null }, colState: { classPropertyName: "colState", publicName: "colState", isSignal: true, isRequired: true, transformFunction: null }, def: { classPropertyName: "def", publicName: "def", isSignal: true, isRequired: true, transformFunction: null }, isLast: { classPropertyName: "isLast", publicName: "isLast", isSignal: true, isRequired: false, transformFunction: null }, pinnedEnd: { classPropertyName: "pinnedEnd", publicName: "pinnedEnd", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { commitEdit: "commitEdit", cancelEdit: "cancelEdit" }, host: { properties: { "style.flex": "isLast() ? \"1 0 auto\" : \"0 0 auto\"", "style.width.px": "isLast() ? undefined : colState().currentWidth", "style.min-width.px": "isLast() ? colState().currentWidth : resolvedMinWidth()" } }, ngImport: i0, template: "<div\n class=\"grid-cell\"\n [class.grid-cell--focused]=\"isFocused()\"\n [class.grid-cell--in-range]=\"isInRange()\"\n [class.grid-cell--in-fill-range]=\"isInFillRange()\"\n [class.grid-cell--in-fill-reject-range]=\"isInFillRejectRange()\"\n [class.grid-cell--cut]=\"cutEdges().any\"\n [class.grid-cell--last]=\"isLast()\"\n [class.grid-cell--pinned-end]=\"pinnedEnd()\"\n [class.grid-cell--readonly]=\"!def().editable\"\n [class.grid-cell--error]=\"cellError()\"\n [attr.aria-invalid]=\"cellError() ? 'true' : null\"\n (click)=\"onCellClick($event)\"\n (dblclick)=\"onDoubleClick()\"\n (mousedown)=\"onMouseDown($event)\"\n (mouseenter)=\"onMouseEnter()\"\n>\n @if (isEditing()) {\n <div class=\"grid-cell__editor\" (focusout)=\"onEditorBlur($event)\">\n @if (editTemplate()) {\n <div class=\"grid-cell__editor-custom\">\n <ng-container\n [ngTemplateOutlet]=\"editTemplate()!\"\n [ngTemplateOutletContext]=\"{\n $implicit: value(),\n row: row(),\n field: def().field,\n draft: editState().draftValue,\n updateDraft: updateDraftFn,\n commitEdit: commitEditFn\n }\"\n />\n </div>\n } @else { @switch (editorType()) { @case ('text') {\n <input\n class=\"grid-cell__input grid-cell__input--plain\"\n type=\"text\"\n [value]=\"editState().draftValue\"\n (input)=\"onEditorInput($event)\"\n />\n } @case ('number') {\n <input\n class=\"grid-cell__input grid-cell__input--plain\"\n type=\"number\"\n [value]=\"editState().draftValue\"\n (input)=\"onEditorInput($event)\"\n />\n } @case ('select') {\n <moz-select\n name=\"cell-editor\"\n [options]=\"def().cellEditorOptions ?? []\"\n [ngModel]=\"editState().draftValue\"\n (change)=\"onSelectChange($event)\"\n [size]=\"'s'\"\n />\n } @case ('checkbox') {\n <moz-checkbox\n [id]=\"'grid-cell-editor-' + rowIndex() + '-' + colIndex()\"\n [ngModel]=\"!!editState().draftValue\"\n (change)=\"onCheckboxChange($event)\"\n />\n } @case ('date') {\n <moz-datepicker\n [id]=\"'grid-cell-editor-' + rowIndex() + '-' + colIndex()\"\n size=\"s\"\n [ngModel]=\"editState().draftValue\"\n (ngModelChange)=\"onDateChange($event)\"\n />\n } @default {\n <input\n class=\"grid-cell__input grid-cell__input--plain\"\n type=\"text\"\n [value]=\"editState().draftValue\"\n (input)=\"onEditorInput($event)\"\n />\n } } }\n </div>\n } @else { @if (cellTemplate()) {\n <div class=\"grid-cell__custom\">\n <ng-container\n [ngTemplateOutlet]=\"cellTemplate()!\"\n [ngTemplateOutletContext]=\"{ $implicit: value(), row: row(), field: def().field }\"\n />\n </div>\n } @else {\n <span class=\"grid-cell__value\">{{ displayValue() }}</span>\n } } @if (cutEdges(); as edges) { @if (edges.top) {\n <div class=\"grid-cell__cut-mark grid-cell__cut-mark--top\"></div>\n } @if (edges.bottom) {\n <div class=\"grid-cell__cut-mark grid-cell__cut-mark--bottom\"></div>\n } @if (edges.left) {\n <div class=\"grid-cell__cut-mark grid-cell__cut-mark--left\"></div>\n } @if (edges.right) {\n <div class=\"grid-cell__cut-mark grid-cell__cut-mark--right\"></div>\n } } @if (isFocused() && !isEditing() && def().editable) {\n <div class=\"grid-cell__fill-handle\" (mousedown)=\"onFillHandleMouseDown($event)\"></div>\n } @if (cellError(); as error) {\n <div\n class=\"grid-cell__error-icon\"\n [mozTooltip]=\"error.message\"\n tooltipPosition=\"top\"\n aria-label=\"Erreur de validation\"\n >\n <ErrorFilled24 />\n </div>\n }\n</div>\n", styles: ["@charset \"UTF-8\";:host{display:block;height:100%;min-width:0}.grid-cell{display:flex;align-items:center;position:relative;padding:0 var(--spacing-s, 8px);height:100%;border-right:1px solid var(--color-border-primary);overflow:hidden;box-sizing:border-box;min-width:0;background:inherit;cursor:pointer}.grid-cell--last{border-right:none}.grid-cell--pinned-end{border-right:none;border-left:1px solid var(--color-border-primary)}:host(:first-child) .grid-cell--pinned-end{border-left:none}.grid-cell__value{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:var(--font-size-s, 14px);color:var(--color-text-primary);position:relative;z-index:1}.grid-cell__editor{width:100%;min-width:0;max-width:100%;height:100%;display:flex;align-items:center;overflow:hidden;box-sizing:border-box;position:relative;z-index:1}.grid-cell__editor-custom{width:100%;min-width:0;max-width:100%;overflow:hidden;box-sizing:border-box;display:flex;align-items:center;flex-wrap:wrap;gap:4px}.grid-cell__editor input,.grid-cell__editor moz-select{width:100%;min-width:0;box-sizing:border-box}.grid-cell__input--plain{border:none;outline:none;background:transparent;font-family:inherit;font-size:var(--font-size-s, 14px);color:var(--color-text-primary);padding:0;height:100%;width:100%;min-width:0;box-sizing:border-box}.grid-cell__input--plain:focus{outline:none}.grid-cell__input--plain[type=number]::-webkit-inner-spin-button,.grid-cell__input--plain[type=number]::-webkit-outer-spin-button{-webkit-appearance:none;margin:0}.grid-cell__input--plain[type=number]{-moz-appearance:textfield}.grid-cell__editor ::ng-deep .text-input{width:100%;min-width:0;box-sizing:border-box}.grid-cell__editor ::ng-deep .select,.grid-cell__editor ::ng-deep .select__trigger{min-width:0;width:100%}.grid-cell__editor ::ng-deep *{max-width:100%}.grid-cell__editor moz-datepicker{width:100%;min-width:0;box-sizing:border-box}.grid-cell__editor ::ng-deep .mc-datepicker,.grid-cell__editor ::ng-deep .mc-text-input{width:100%;min-width:0;box-sizing:border-box;height:28px;font-size:var(--font-size-xs, 12px)}.grid-cell__editor ::ng-deep moz-datepicker label{display:none}.grid-cell>*:not(.grid-cell__fill-handle){position:relative;z-index:1}.grid-cell:before{content:\"\";position:absolute;inset:3px;border-radius:4px;pointer-events:none;z-index:0}.grid-cell:hover:before{background:#f1f3f4}.grid-cell--focused:hover:before,.grid-cell--in-range:hover:before,.grid-cell--in-fill-range:hover:before,.grid-cell--in-fill-reject-range:hover:before{background:transparent}.grid-cell--focused{z-index:2}.grid-cell--focused:after{content:\"\";position:absolute;inset:0;border:2px solid var(--color-background-accent-inverse);border-radius:4px;pointer-events:none}.grid-cell--in-range{background:var(--color-background-accent)}.grid-cell--readonly .grid-cell__value{color:var(--color-text-secondary, #666)}.grid-cell--in-fill-range{background:#34a85314}.grid-cell--in-fill-range:after{content:\"\";position:absolute;inset:0;border:1px dashed var(--color-success, #34a853);border-radius:4px;pointer-events:none}.grid-cell--in-fill-reject-range{background:#ea302d1f;cursor:not-allowed;z-index:2}.grid-cell--in-fill-reject-range:after{content:\"\";position:absolute;inset:0;border:2px dashed var(--Status-Standalone-element-Error, #ea302d);border-radius:4px;pointer-events:none;z-index:3}.grid-cell--cut{background:#1a73e80f}.grid-cell__cut-mark{position:absolute;pointer-events:none;z-index:5;--cut-color: var(--color-background-accent-inverse, #1a73e8)}.grid-cell__cut-mark--top,.grid-cell__cut-mark--bottom{left:0;right:0;height:2px;background-image:linear-gradient(90deg,var(--cut-color) 50%,transparent 50%);background-size:8px 2px;background-repeat:repeat-x;animation:moz-grid-marching-ants-x .5s linear infinite}.grid-cell__cut-mark--top{top:0}.grid-cell__cut-mark--bottom{bottom:0}.grid-cell__cut-mark--left,.grid-cell__cut-mark--right{top:0;bottom:0;width:2px;background-image:linear-gradient(180deg,var(--cut-color) 50%,transparent 50%);background-size:2px 8px;background-repeat:repeat-y;animation:moz-grid-marching-ants-y .5s linear infinite}.grid-cell__cut-mark--left{left:0}.grid-cell__cut-mark--right{right:0}@keyframes moz-grid-marching-ants-x{0%{background-position-x:0}to{background-position-x:8px}}@keyframes moz-grid-marching-ants-y{0%{background-position-y:0}to{background-position-y:8px}}.grid-cell__fill-handle{position:absolute;right:0;bottom:0;width:8px;height:8px;background:var(--color-background-accent-inverse);cursor:crosshair;z-index:4}.grid-cell--error{background:var(--Background-Primary, #fff);outline:1px solid var(--Status-Border-Error, #ef5f5c);outline-offset:-2px;z-index:1;border-radius:4px}.grid-cell--error:hover:before{background:transparent}.grid-cell__error-icon{display:flex;align-items:center;justify-content:center;flex-shrink:0;margin-left:auto;cursor:help;position:relative;z-index:2}.grid-cell__error-icon ::ng-deep svg{fill:var(--Status-Standalone-element-Error, #ea302d)}\n"], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: MozSelectComponent, selector: "moz-select", inputs: ["id", "name", "options", "placeholder", "isInvalid", "disabled", "readonly", "size"] }, { kind: "component", type: MozCheckboxComponent, selector: "moz-checkbox", inputs: ["id", "name", "label", "indeterminate", "isInvalid", "disabled", "indented"] }, { kind: "component", type: MozDatepickerComponent, selector: "moz-datepicker", inputs: ["id", "disabled", "readonly", "invalid", "error", "clearable", "size", "label"] }, { kind: "directive", type: MozTooltipDirective, selector: "[mozTooltip]", inputs: ["mozTooltip", "tooltipPosition", "tooltipNoPointer"] }, { kind: "component", type: ErrorFilled24, selector: "ErrorFilled24", inputs: ["hostClass"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
9709
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: MozGridCellComponent, isStandalone: true, selector: "moz-grid-cell", inputs: { row: { classPropertyName: "row", publicName: "row", isSignal: true, isRequired: true, transformFunction: null }, rowIndex: { classPropertyName: "rowIndex", publicName: "rowIndex", isSignal: true, isRequired: true, transformFunction: null }, colIndex: { classPropertyName: "colIndex", publicName: "colIndex", isSignal: true, isRequired: true, transformFunction: null }, colState: { classPropertyName: "colState", publicName: "colState", isSignal: true, isRequired: true, transformFunction: null }, def: { classPropertyName: "def", publicName: "def", isSignal: true, isRequired: true, transformFunction: null }, isLast: { classPropertyName: "isLast", publicName: "isLast", isSignal: true, isRequired: false, transformFunction: null }, pinnedEnd: { classPropertyName: "pinnedEnd", publicName: "pinnedEnd", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { commitEdit: "commitEdit", cancelEdit: "cancelEdit" }, host: { properties: { "style.flex": "isLast() ? \"1 0 auto\" : \"0 0 auto\"", "style.width.px": "isLast() ? undefined : colState().currentWidth", "style.min-width.px": "isLast() ? colState().currentWidth : resolvedMinWidth()" } }, ngImport: i0, template: "<div\n class=\"grid-cell\"\n [class.grid-cell--focused]=\"isFocused()\"\n [class.grid-cell--in-range]=\"isInRange()\"\n [class.grid-cell--in-fill-range]=\"isInFillRange()\"\n [class.grid-cell--in-fill-reject-range]=\"isInFillRejectRange()\"\n [class.grid-cell--cut]=\"cutEdges().any\"\n [class.grid-cell--last]=\"isLast()\"\n [class.grid-cell--pinned-end]=\"pinnedEnd()\"\n [class.grid-cell--readonly]=\"!def().editable\"\n [class.grid-cell--error]=\"cellError()\"\n [attr.aria-invalid]=\"cellError() ? 'true' : null\"\n (click)=\"onCellClick($event)\"\n (dblclick)=\"onDoubleClick()\"\n (mousedown)=\"onMouseDown($event)\"\n (mouseenter)=\"onMouseEnter()\"\n>\n @if (isEditing()) {\n <div class=\"grid-cell__editor\" (focusout)=\"onEditorBlur($event)\">\n @if (editTemplate()) {\n <div class=\"grid-cell__editor-custom\">\n <ng-container\n [ngTemplateOutlet]=\"editTemplate()!\"\n [ngTemplateOutletContext]=\"{\n $implicit: value(),\n row: row(),\n field: def().field,\n draft: editState().draftValue,\n updateDraft: updateDraftFn,\n commitEdit: commitEditFn\n }\"\n />\n </div>\n } @else { @switch (editorType()) { @case ('text') {\n <input\n class=\"grid-cell__input grid-cell__input--plain\"\n type=\"text\"\n [value]=\"editState().draftValue\"\n (input)=\"onEditorInput($event)\"\n />\n } @case ('number') {\n <input\n class=\"grid-cell__input grid-cell__input--plain\"\n type=\"number\"\n [value]=\"editState().draftValue\"\n (input)=\"onEditorInput($event)\"\n />\n } @case ('select') {\n <moz-select\n name=\"cell-editor\"\n [options]=\"def().cellEditorOptions ?? []\"\n [ngModel]=\"editState().draftValue\"\n (change)=\"onSelectChange($event)\"\n [size]=\"'s'\"\n />\n } @case ('checkbox') {\n <moz-checkbox\n [id]=\"'grid-cell-editor-' + rowIndex() + '-' + colIndex()\"\n [ngModel]=\"!!editState().draftValue\"\n (change)=\"onCheckboxChange($event)\"\n />\n } @case ('date') {\n <moz-datepicker\n [id]=\"'grid-cell-editor-' + rowIndex() + '-' + colIndex()\"\n size=\"s\"\n [ngModel]=\"editState().draftValue\"\n (ngModelChange)=\"onDateChange($event)\"\n />\n } @default {\n <input\n class=\"grid-cell__input grid-cell__input--plain\"\n type=\"text\"\n [value]=\"editState().draftValue\"\n (input)=\"onEditorInput($event)\"\n />\n } } }\n </div>\n } @else { @if (cellTemplate()) {\n <div class=\"grid-cell__custom\">\n <ng-container\n [ngTemplateOutlet]=\"cellTemplate()!\"\n [ngTemplateOutletContext]=\"{ $implicit: value(), row: row(), field: def().field }\"\n />\n </div>\n } @else {\n <span class=\"grid-cell__value\">{{ displayValue() }}</span>\n } } @if (cutEdges(); as edges) { @if (edges.top) {\n <div class=\"grid-cell__cut-mark grid-cell__cut-mark--top\"></div>\n } @if (edges.bottom) {\n <div class=\"grid-cell__cut-mark grid-cell__cut-mark--bottom\"></div>\n } @if (edges.left) {\n <div class=\"grid-cell__cut-mark grid-cell__cut-mark--left\"></div>\n } @if (edges.right) {\n <div class=\"grid-cell__cut-mark grid-cell__cut-mark--right\"></div>\n } } @if (isFocused() && !isEditing() && def().editable) {\n <div class=\"grid-cell__fill-handle\" (mousedown)=\"onFillHandleMouseDown($event)\"></div>\n } @if (cellError(); as error) {\n <div\n class=\"grid-cell__error-icon\"\n [mozTooltip]=\"error.message\"\n tooltipPosition=\"top\"\n aria-label=\"Erreur de validation\"\n >\n <ErrorFilled24 />\n </div>\n }\n</div>\n", styles: ["@charset \"UTF-8\";:host{display:block;height:100%;min-width:0}.grid-cell{display:flex;align-items:center;position:relative;padding:0 var(--spacing-s, 8px);height:100%;border-right:1px solid var(--color-border-primary);overflow:hidden;box-sizing:border-box;min-width:0;background:inherit;cursor:pointer}.grid-cell--last{border-right:none}.grid-cell--pinned-end{border-right:none;border-left:1px solid var(--color-border-primary)}:host(:first-child) .grid-cell--pinned-end{border-left:none}.grid-cell__value{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:var(--font-size-s, 14px);color:var(--color-text-primary);position:relative;z-index:1}.grid-cell__editor{width:100%;min-width:0;max-width:100%;height:100%;display:flex;align-items:center;overflow:hidden;box-sizing:border-box;position:relative;z-index:1}.grid-cell__editor-custom{width:100%;min-width:0;max-width:100%;overflow:hidden;box-sizing:border-box;display:flex;align-items:center;flex-wrap:wrap;gap:4px}.grid-cell__editor input,.grid-cell__editor moz-select{width:100%;min-width:0;box-sizing:border-box}.grid-cell__input--plain{border:none;outline:none;background:transparent;font-family:inherit;font-size:var(--font-size-s, 14px);color:var(--color-text-primary);padding:0;height:100%;width:100%;min-width:0;box-sizing:border-box}.grid-cell__input--plain:focus{outline:none}.grid-cell__input--plain[type=number]::-webkit-inner-spin-button,.grid-cell__input--plain[type=number]::-webkit-outer-spin-button{-webkit-appearance:none;margin:0}.grid-cell__input--plain[type=number]{-moz-appearance:textfield}.grid-cell__editor ::ng-deep .text-input{width:100%;min-width:0;box-sizing:border-box}.grid-cell__editor ::ng-deep .select,.grid-cell__editor ::ng-deep .select__trigger{min-width:0;width:100%}.grid-cell__editor ::ng-deep *{max-width:100%}.grid-cell__editor moz-datepicker{width:100%;min-width:0;box-sizing:border-box}.grid-cell__editor ::ng-deep .mc-datepicker,.grid-cell__editor ::ng-deep .mc-text-input{width:100%;min-width:0;box-sizing:border-box;height:28px;font-size:var(--font-size-xs, 12px)}.grid-cell__editor ::ng-deep moz-datepicker label{display:none}.grid-cell>*:not(.grid-cell__fill-handle){position:relative;z-index:1}.grid-cell:before{content:\"\";position:absolute;inset:3px;border-radius:4px;pointer-events:none;z-index:0}.grid-cell:hover:before{background:#f1f3f4}.grid-cell--focused:hover:before,.grid-cell--in-range:hover:before,.grid-cell--in-fill-range:hover:before,.grid-cell--in-fill-reject-range:hover:before{background:transparent}.grid-cell--focused{z-index:2}.grid-cell--focused:after{content:\"\";position:absolute;inset:0;border:2px solid var(--color-background-accent-inverse);border-radius:4px;pointer-events:none}.grid-cell--in-range{background:var(--color-background-accent)}.grid-cell--readonly .grid-cell__value{color:var(--color-text-secondary, #666)}.grid-cell--in-fill-range{background:#34a85314}.grid-cell--in-fill-range:after{content:\"\";position:absolute;inset:0;border:1px dashed var(--color-success, #34a853);border-radius:4px;pointer-events:none}.grid-cell--in-fill-reject-range{background:#ea302d1f;cursor:not-allowed;z-index:2}.grid-cell--in-fill-reject-range:after{content:\"\";position:absolute;inset:0;border:2px dashed var(--Status-Standalone-element-Error, #ea302d);border-radius:4px;pointer-events:none;z-index:3}.grid-cell--cut{background:#1a73e80f}.grid-cell__cut-mark{position:absolute;pointer-events:none;z-index:5;--cut-color: var(--color-background-accent-inverse, #1a73e8)}.grid-cell__cut-mark--top,.grid-cell__cut-mark--bottom{left:0;right:0;height:2px;background-image:linear-gradient(90deg,var(--cut-color) 50%,transparent 50%);background-size:8px 2px;background-repeat:repeat-x;animation:moz-grid-marching-ants-x .5s linear infinite}.grid-cell__cut-mark--top{top:0}.grid-cell__cut-mark--bottom{bottom:0}.grid-cell__cut-mark--left,.grid-cell__cut-mark--right{top:0;bottom:0;width:2px;background-image:linear-gradient(180deg,var(--cut-color) 50%,transparent 50%);background-size:2px 8px;background-repeat:repeat-y;animation:moz-grid-marching-ants-y .5s linear infinite}.grid-cell__cut-mark--left{left:0}.grid-cell__cut-mark--right{right:0}@keyframes moz-grid-marching-ants-x{0%{background-position-x:0}to{background-position-x:8px}}@keyframes moz-grid-marching-ants-y{0%{background-position-y:0}to{background-position-y:8px}}.grid-cell__fill-handle{position:absolute;right:0;bottom:0;width:8px;height:8px;background:var(--color-background-accent-inverse);cursor:crosshair;z-index:4}.grid-cell--error{outline:1px solid var(--Status-Border-Error, #ef5f5c);outline-offset:-2px;z-index:1;border-radius:4px}.grid-cell--error:hover:before{background:transparent}.grid-cell__error-icon{display:flex;align-items:center;justify-content:center;flex-shrink:0;margin-left:auto;cursor:help;position:relative;z-index:2;fill:var(--Status-Standalone-element-Error, #ea302d)}\n"], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: MozSelectComponent, selector: "moz-select", inputs: ["id", "name", "options", "placeholder", "isInvalid", "disabled", "readonly", "size"] }, { kind: "component", type: MozCheckboxComponent, selector: "moz-checkbox", inputs: ["id", "name", "label", "indeterminate", "isInvalid", "disabled", "indented"] }, { kind: "component", type: MozDatepickerComponent, selector: "moz-datepicker", inputs: ["id", "disabled", "readonly", "invalid", "error", "clearable", "size", "label"] }, { kind: "directive", type: MozTooltipDirective, selector: "[mozTooltip]", inputs: ["mozTooltip", "tooltipPosition", "tooltipNoPointer"] }, { kind: "component", type: ErrorFilled24, selector: "ErrorFilled24", inputs: ["hostClass"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
8954
9710
|
}
|
|
8955
9711
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: MozGridCellComponent, decorators: [{
|
|
8956
9712
|
type: Component,
|
|
@@ -8966,7 +9722,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
|
|
|
8966
9722
|
'[style.flex]': 'isLast() ? "1 0 auto" : "0 0 auto"',
|
|
8967
9723
|
'[style.width.px]': 'isLast() ? undefined : colState().currentWidth',
|
|
8968
9724
|
'[style.min-width.px]': 'isLast() ? colState().currentWidth : resolvedMinWidth()',
|
|
8969
|
-
}, template: "<div\n class=\"grid-cell\"\n [class.grid-cell--focused]=\"isFocused()\"\n [class.grid-cell--in-range]=\"isInRange()\"\n [class.grid-cell--in-fill-range]=\"isInFillRange()\"\n [class.grid-cell--in-fill-reject-range]=\"isInFillRejectRange()\"\n [class.grid-cell--cut]=\"cutEdges().any\"\n [class.grid-cell--last]=\"isLast()\"\n [class.grid-cell--pinned-end]=\"pinnedEnd()\"\n [class.grid-cell--readonly]=\"!def().editable\"\n [class.grid-cell--error]=\"cellError()\"\n [attr.aria-invalid]=\"cellError() ? 'true' : null\"\n (click)=\"onCellClick($event)\"\n (dblclick)=\"onDoubleClick()\"\n (mousedown)=\"onMouseDown($event)\"\n (mouseenter)=\"onMouseEnter()\"\n>\n @if (isEditing()) {\n <div class=\"grid-cell__editor\" (focusout)=\"onEditorBlur($event)\">\n @if (editTemplate()) {\n <div class=\"grid-cell__editor-custom\">\n <ng-container\n [ngTemplateOutlet]=\"editTemplate()!\"\n [ngTemplateOutletContext]=\"{\n $implicit: value(),\n row: row(),\n field: def().field,\n draft: editState().draftValue,\n updateDraft: updateDraftFn,\n commitEdit: commitEditFn\n }\"\n />\n </div>\n } @else { @switch (editorType()) { @case ('text') {\n <input\n class=\"grid-cell__input grid-cell__input--plain\"\n type=\"text\"\n [value]=\"editState().draftValue\"\n (input)=\"onEditorInput($event)\"\n />\n } @case ('number') {\n <input\n class=\"grid-cell__input grid-cell__input--plain\"\n type=\"number\"\n [value]=\"editState().draftValue\"\n (input)=\"onEditorInput($event)\"\n />\n } @case ('select') {\n <moz-select\n name=\"cell-editor\"\n [options]=\"def().cellEditorOptions ?? []\"\n [ngModel]=\"editState().draftValue\"\n (change)=\"onSelectChange($event)\"\n [size]=\"'s'\"\n />\n } @case ('checkbox') {\n <moz-checkbox\n [id]=\"'grid-cell-editor-' + rowIndex() + '-' + colIndex()\"\n [ngModel]=\"!!editState().draftValue\"\n (change)=\"onCheckboxChange($event)\"\n />\n } @case ('date') {\n <moz-datepicker\n [id]=\"'grid-cell-editor-' + rowIndex() + '-' + colIndex()\"\n size=\"s\"\n [ngModel]=\"editState().draftValue\"\n (ngModelChange)=\"onDateChange($event)\"\n />\n } @default {\n <input\n class=\"grid-cell__input grid-cell__input--plain\"\n type=\"text\"\n [value]=\"editState().draftValue\"\n (input)=\"onEditorInput($event)\"\n />\n } } }\n </div>\n } @else { @if (cellTemplate()) {\n <div class=\"grid-cell__custom\">\n <ng-container\n [ngTemplateOutlet]=\"cellTemplate()!\"\n [ngTemplateOutletContext]=\"{ $implicit: value(), row: row(), field: def().field }\"\n />\n </div>\n } @else {\n <span class=\"grid-cell__value\">{{ displayValue() }}</span>\n } } @if (cutEdges(); as edges) { @if (edges.top) {\n <div class=\"grid-cell__cut-mark grid-cell__cut-mark--top\"></div>\n } @if (edges.bottom) {\n <div class=\"grid-cell__cut-mark grid-cell__cut-mark--bottom\"></div>\n } @if (edges.left) {\n <div class=\"grid-cell__cut-mark grid-cell__cut-mark--left\"></div>\n } @if (edges.right) {\n <div class=\"grid-cell__cut-mark grid-cell__cut-mark--right\"></div>\n } } @if (isFocused() && !isEditing() && def().editable) {\n <div class=\"grid-cell__fill-handle\" (mousedown)=\"onFillHandleMouseDown($event)\"></div>\n } @if (cellError(); as error) {\n <div\n class=\"grid-cell__error-icon\"\n [mozTooltip]=\"error.message\"\n tooltipPosition=\"top\"\n aria-label=\"Erreur de validation\"\n >\n <ErrorFilled24 />\n </div>\n }\n</div>\n", styles: ["@charset \"UTF-8\";:host{display:block;height:100%;min-width:0}.grid-cell{display:flex;align-items:center;position:relative;padding:0 var(--spacing-s, 8px);height:100%;border-right:1px solid var(--color-border-primary);overflow:hidden;box-sizing:border-box;min-width:0;background:inherit;cursor:pointer}.grid-cell--last{border-right:none}.grid-cell--pinned-end{border-right:none;border-left:1px solid var(--color-border-primary)}:host(:first-child) .grid-cell--pinned-end{border-left:none}.grid-cell__value{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:var(--font-size-s, 14px);color:var(--color-text-primary);position:relative;z-index:1}.grid-cell__editor{width:100%;min-width:0;max-width:100%;height:100%;display:flex;align-items:center;overflow:hidden;box-sizing:border-box;position:relative;z-index:1}.grid-cell__editor-custom{width:100%;min-width:0;max-width:100%;overflow:hidden;box-sizing:border-box;display:flex;align-items:center;flex-wrap:wrap;gap:4px}.grid-cell__editor input,.grid-cell__editor moz-select{width:100%;min-width:0;box-sizing:border-box}.grid-cell__input--plain{border:none;outline:none;background:transparent;font-family:inherit;font-size:var(--font-size-s, 14px);color:var(--color-text-primary);padding:0;height:100%;width:100%;min-width:0;box-sizing:border-box}.grid-cell__input--plain:focus{outline:none}.grid-cell__input--plain[type=number]::-webkit-inner-spin-button,.grid-cell__input--plain[type=number]::-webkit-outer-spin-button{-webkit-appearance:none;margin:0}.grid-cell__input--plain[type=number]{-moz-appearance:textfield}.grid-cell__editor ::ng-deep .text-input{width:100%;min-width:0;box-sizing:border-box}.grid-cell__editor ::ng-deep .select,.grid-cell__editor ::ng-deep .select__trigger{min-width:0;width:100%}.grid-cell__editor ::ng-deep *{max-width:100%}.grid-cell__editor moz-datepicker{width:100%;min-width:0;box-sizing:border-box}.grid-cell__editor ::ng-deep .mc-datepicker,.grid-cell__editor ::ng-deep .mc-text-input{width:100%;min-width:0;box-sizing:border-box;height:28px;font-size:var(--font-size-xs, 12px)}.grid-cell__editor ::ng-deep moz-datepicker label{display:none}.grid-cell>*:not(.grid-cell__fill-handle){position:relative;z-index:1}.grid-cell:before{content:\"\";position:absolute;inset:3px;border-radius:4px;pointer-events:none;z-index:0}.grid-cell:hover:before{background:#f1f3f4}.grid-cell--focused:hover:before,.grid-cell--in-range:hover:before,.grid-cell--in-fill-range:hover:before,.grid-cell--in-fill-reject-range:hover:before{background:transparent}.grid-cell--focused{z-index:2}.grid-cell--focused:after{content:\"\";position:absolute;inset:0;border:2px solid var(--color-background-accent-inverse);border-radius:4px;pointer-events:none}.grid-cell--in-range{background:var(--color-background-accent)}.grid-cell--readonly .grid-cell__value{color:var(--color-text-secondary, #666)}.grid-cell--in-fill-range{background:#34a85314}.grid-cell--in-fill-range:after{content:\"\";position:absolute;inset:0;border:1px dashed var(--color-success, #34a853);border-radius:4px;pointer-events:none}.grid-cell--in-fill-reject-range{background:#ea302d1f;cursor:not-allowed;z-index:2}.grid-cell--in-fill-reject-range:after{content:\"\";position:absolute;inset:0;border:2px dashed var(--Status-Standalone-element-Error, #ea302d);border-radius:4px;pointer-events:none;z-index:3}.grid-cell--cut{background:#1a73e80f}.grid-cell__cut-mark{position:absolute;pointer-events:none;z-index:5;--cut-color: var(--color-background-accent-inverse, #1a73e8)}.grid-cell__cut-mark--top,.grid-cell__cut-mark--bottom{left:0;right:0;height:2px;background-image:linear-gradient(90deg,var(--cut-color) 50%,transparent 50%);background-size:8px 2px;background-repeat:repeat-x;animation:moz-grid-marching-ants-x .5s linear infinite}.grid-cell__cut-mark--top{top:0}.grid-cell__cut-mark--bottom{bottom:0}.grid-cell__cut-mark--left,.grid-cell__cut-mark--right{top:0;bottom:0;width:2px;background-image:linear-gradient(180deg,var(--cut-color) 50%,transparent 50%);background-size:2px 8px;background-repeat:repeat-y;animation:moz-grid-marching-ants-y .5s linear infinite}.grid-cell__cut-mark--left{left:0}.grid-cell__cut-mark--right{right:0}@keyframes moz-grid-marching-ants-x{0%{background-position-x:0}to{background-position-x:8px}}@keyframes moz-grid-marching-ants-y{0%{background-position-y:0}to{background-position-y:8px}}.grid-cell__fill-handle{position:absolute;right:0;bottom:0;width:8px;height:8px;background:var(--color-background-accent-inverse);cursor:crosshair;z-index:4}.grid-cell--error{
|
|
9725
|
+
}, template: "<div\n class=\"grid-cell\"\n [class.grid-cell--focused]=\"isFocused()\"\n [class.grid-cell--in-range]=\"isInRange()\"\n [class.grid-cell--in-fill-range]=\"isInFillRange()\"\n [class.grid-cell--in-fill-reject-range]=\"isInFillRejectRange()\"\n [class.grid-cell--cut]=\"cutEdges().any\"\n [class.grid-cell--last]=\"isLast()\"\n [class.grid-cell--pinned-end]=\"pinnedEnd()\"\n [class.grid-cell--readonly]=\"!def().editable\"\n [class.grid-cell--error]=\"cellError()\"\n [attr.aria-invalid]=\"cellError() ? 'true' : null\"\n (click)=\"onCellClick($event)\"\n (dblclick)=\"onDoubleClick()\"\n (mousedown)=\"onMouseDown($event)\"\n (mouseenter)=\"onMouseEnter()\"\n>\n @if (isEditing()) {\n <div class=\"grid-cell__editor\" (focusout)=\"onEditorBlur($event)\">\n @if (editTemplate()) {\n <div class=\"grid-cell__editor-custom\">\n <ng-container\n [ngTemplateOutlet]=\"editTemplate()!\"\n [ngTemplateOutletContext]=\"{\n $implicit: value(),\n row: row(),\n field: def().field,\n draft: editState().draftValue,\n updateDraft: updateDraftFn,\n commitEdit: commitEditFn\n }\"\n />\n </div>\n } @else { @switch (editorType()) { @case ('text') {\n <input\n class=\"grid-cell__input grid-cell__input--plain\"\n type=\"text\"\n [value]=\"editState().draftValue\"\n (input)=\"onEditorInput($event)\"\n />\n } @case ('number') {\n <input\n class=\"grid-cell__input grid-cell__input--plain\"\n type=\"number\"\n [value]=\"editState().draftValue\"\n (input)=\"onEditorInput($event)\"\n />\n } @case ('select') {\n <moz-select\n name=\"cell-editor\"\n [options]=\"def().cellEditorOptions ?? []\"\n [ngModel]=\"editState().draftValue\"\n (change)=\"onSelectChange($event)\"\n [size]=\"'s'\"\n />\n } @case ('checkbox') {\n <moz-checkbox\n [id]=\"'grid-cell-editor-' + rowIndex() + '-' + colIndex()\"\n [ngModel]=\"!!editState().draftValue\"\n (change)=\"onCheckboxChange($event)\"\n />\n } @case ('date') {\n <moz-datepicker\n [id]=\"'grid-cell-editor-' + rowIndex() + '-' + colIndex()\"\n size=\"s\"\n [ngModel]=\"editState().draftValue\"\n (ngModelChange)=\"onDateChange($event)\"\n />\n } @default {\n <input\n class=\"grid-cell__input grid-cell__input--plain\"\n type=\"text\"\n [value]=\"editState().draftValue\"\n (input)=\"onEditorInput($event)\"\n />\n } } }\n </div>\n } @else { @if (cellTemplate()) {\n <div class=\"grid-cell__custom\">\n <ng-container\n [ngTemplateOutlet]=\"cellTemplate()!\"\n [ngTemplateOutletContext]=\"{ $implicit: value(), row: row(), field: def().field }\"\n />\n </div>\n } @else {\n <span class=\"grid-cell__value\">{{ displayValue() }}</span>\n } } @if (cutEdges(); as edges) { @if (edges.top) {\n <div class=\"grid-cell__cut-mark grid-cell__cut-mark--top\"></div>\n } @if (edges.bottom) {\n <div class=\"grid-cell__cut-mark grid-cell__cut-mark--bottom\"></div>\n } @if (edges.left) {\n <div class=\"grid-cell__cut-mark grid-cell__cut-mark--left\"></div>\n } @if (edges.right) {\n <div class=\"grid-cell__cut-mark grid-cell__cut-mark--right\"></div>\n } } @if (isFocused() && !isEditing() && def().editable) {\n <div class=\"grid-cell__fill-handle\" (mousedown)=\"onFillHandleMouseDown($event)\"></div>\n } @if (cellError(); as error) {\n <div\n class=\"grid-cell__error-icon\"\n [mozTooltip]=\"error.message\"\n tooltipPosition=\"top\"\n aria-label=\"Erreur de validation\"\n >\n <ErrorFilled24 />\n </div>\n }\n</div>\n", styles: ["@charset \"UTF-8\";:host{display:block;height:100%;min-width:0}.grid-cell{display:flex;align-items:center;position:relative;padding:0 var(--spacing-s, 8px);height:100%;border-right:1px solid var(--color-border-primary);overflow:hidden;box-sizing:border-box;min-width:0;background:inherit;cursor:pointer}.grid-cell--last{border-right:none}.grid-cell--pinned-end{border-right:none;border-left:1px solid var(--color-border-primary)}:host(:first-child) .grid-cell--pinned-end{border-left:none}.grid-cell__value{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:var(--font-size-s, 14px);color:var(--color-text-primary);position:relative;z-index:1}.grid-cell__editor{width:100%;min-width:0;max-width:100%;height:100%;display:flex;align-items:center;overflow:hidden;box-sizing:border-box;position:relative;z-index:1}.grid-cell__editor-custom{width:100%;min-width:0;max-width:100%;overflow:hidden;box-sizing:border-box;display:flex;align-items:center;flex-wrap:wrap;gap:4px}.grid-cell__editor input,.grid-cell__editor moz-select{width:100%;min-width:0;box-sizing:border-box}.grid-cell__input--plain{border:none;outline:none;background:transparent;font-family:inherit;font-size:var(--font-size-s, 14px);color:var(--color-text-primary);padding:0;height:100%;width:100%;min-width:0;box-sizing:border-box}.grid-cell__input--plain:focus{outline:none}.grid-cell__input--plain[type=number]::-webkit-inner-spin-button,.grid-cell__input--plain[type=number]::-webkit-outer-spin-button{-webkit-appearance:none;margin:0}.grid-cell__input--plain[type=number]{-moz-appearance:textfield}.grid-cell__editor ::ng-deep .text-input{width:100%;min-width:0;box-sizing:border-box}.grid-cell__editor ::ng-deep .select,.grid-cell__editor ::ng-deep .select__trigger{min-width:0;width:100%}.grid-cell__editor ::ng-deep *{max-width:100%}.grid-cell__editor moz-datepicker{width:100%;min-width:0;box-sizing:border-box}.grid-cell__editor ::ng-deep .mc-datepicker,.grid-cell__editor ::ng-deep .mc-text-input{width:100%;min-width:0;box-sizing:border-box;height:28px;font-size:var(--font-size-xs, 12px)}.grid-cell__editor ::ng-deep moz-datepicker label{display:none}.grid-cell>*:not(.grid-cell__fill-handle){position:relative;z-index:1}.grid-cell:before{content:\"\";position:absolute;inset:3px;border-radius:4px;pointer-events:none;z-index:0}.grid-cell:hover:before{background:#f1f3f4}.grid-cell--focused:hover:before,.grid-cell--in-range:hover:before,.grid-cell--in-fill-range:hover:before,.grid-cell--in-fill-reject-range:hover:before{background:transparent}.grid-cell--focused{z-index:2}.grid-cell--focused:after{content:\"\";position:absolute;inset:0;border:2px solid var(--color-background-accent-inverse);border-radius:4px;pointer-events:none}.grid-cell--in-range{background:var(--color-background-accent)}.grid-cell--readonly .grid-cell__value{color:var(--color-text-secondary, #666)}.grid-cell--in-fill-range{background:#34a85314}.grid-cell--in-fill-range:after{content:\"\";position:absolute;inset:0;border:1px dashed var(--color-success, #34a853);border-radius:4px;pointer-events:none}.grid-cell--in-fill-reject-range{background:#ea302d1f;cursor:not-allowed;z-index:2}.grid-cell--in-fill-reject-range:after{content:\"\";position:absolute;inset:0;border:2px dashed var(--Status-Standalone-element-Error, #ea302d);border-radius:4px;pointer-events:none;z-index:3}.grid-cell--cut{background:#1a73e80f}.grid-cell__cut-mark{position:absolute;pointer-events:none;z-index:5;--cut-color: var(--color-background-accent-inverse, #1a73e8)}.grid-cell__cut-mark--top,.grid-cell__cut-mark--bottom{left:0;right:0;height:2px;background-image:linear-gradient(90deg,var(--cut-color) 50%,transparent 50%);background-size:8px 2px;background-repeat:repeat-x;animation:moz-grid-marching-ants-x .5s linear infinite}.grid-cell__cut-mark--top{top:0}.grid-cell__cut-mark--bottom{bottom:0}.grid-cell__cut-mark--left,.grid-cell__cut-mark--right{top:0;bottom:0;width:2px;background-image:linear-gradient(180deg,var(--cut-color) 50%,transparent 50%);background-size:2px 8px;background-repeat:repeat-y;animation:moz-grid-marching-ants-y .5s linear infinite}.grid-cell__cut-mark--left{left:0}.grid-cell__cut-mark--right{right:0}@keyframes moz-grid-marching-ants-x{0%{background-position-x:0}to{background-position-x:8px}}@keyframes moz-grid-marching-ants-y{0%{background-position-y:0}to{background-position-y:8px}}.grid-cell__fill-handle{position:absolute;right:0;bottom:0;width:8px;height:8px;background:var(--color-background-accent-inverse);cursor:crosshair;z-index:4}.grid-cell--error{outline:1px solid var(--Status-Border-Error, #ef5f5c);outline-offset:-2px;z-index:1;border-radius:4px}.grid-cell--error:hover:before{background:transparent}.grid-cell__error-icon{display:flex;align-items:center;justify-content:center;flex-shrink:0;margin-left:auto;cursor:help;position:relative;z-index:2;fill:var(--Status-Standalone-element-Error, #ea302d)}\n"] }]
|
|
8970
9726
|
}], ctorParameters: () => [], propDecorators: { row: [{ type: i0.Input, args: [{ isSignal: true, alias: "row", required: true }] }], rowIndex: [{ type: i0.Input, args: [{ isSignal: true, alias: "rowIndex", required: true }] }], colIndex: [{ type: i0.Input, args: [{ isSignal: true, alias: "colIndex", required: true }] }], colState: [{ type: i0.Input, args: [{ isSignal: true, alias: "colState", required: true }] }], def: [{ type: i0.Input, args: [{ isSignal: true, alias: "def", required: true }] }], isLast: [{ type: i0.Input, args: [{ isSignal: true, alias: "isLast", required: false }] }], pinnedEnd: [{ type: i0.Input, args: [{ isSignal: true, alias: "pinnedEnd", required: false }] }], commitEdit: [{ type: i0.Output, args: ["commitEdit"] }], cancelEdit: [{ type: i0.Output, args: ["cancelEdit"] }] } });
|
|
8971
9727
|
|
|
8972
9728
|
class MozGridRowComponent {
|
|
@@ -9541,6 +10297,34 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
|
|
|
9541
10297
|
args: [{ selector: 'moz-grid-keyboard-shortcuts-drawer', changeDetection: ChangeDetectionStrategy.OnPush, imports: [MozButtonComponent, MozDrawerFooterDirective], template: "<div class=\"shortcuts\">\n @for (group of groups; track group.title) {\n <section class=\"shortcuts__group\">\n <h4 class=\"shortcuts__group-title\">{{ group.title }}</h4>\n <dl class=\"shortcuts__list\">\n @for (item of group.items; track item.keys) {\n <div class=\"shortcuts__item\">\n <dt class=\"shortcuts__keys\">\n @for (part of item.parts; track $index) { @if (part === '+' || part === '/') {\n <span class=\"shortcuts__separator\">{{ part }}</span>\n } @else {\n <kbd class=\"shortcuts__key\">{{ part }}</kbd>\n } }\n </dt>\n <dd class=\"shortcuts__label\">{{ item.label }}</dd>\n </div>\n }\n </dl>\n </section>\n }\n</div>\n\n<ng-template mozDrawerFooter>\n <button moz-button (click)=\"close()\">Close</button>\n</ng-template>\n", styles: [".shortcuts{padding-bottom:24px}.shortcuts__group{margin-bottom:24px}.shortcuts__group:last-child{margin-bottom:0}.shortcuts__group-title{margin:0 0 8px;font-size:var(--font-size-s, 14px);font-weight:700;color:var(--color-text-secondary);text-transform:uppercase;letter-spacing:.5px}.shortcuts__list{display:flex;flex-direction:column;margin:0;padding:0}.shortcuts__item{display:flex;align-items:center;justify-content:space-between;gap:16px;padding:10px 0;border-bottom:1px solid var(--color-border-primary)}.shortcuts__item:last-child{border-bottom:none}.shortcuts__label{margin:0;flex:1;font-size:var(--font-size-s, 14px);color:var(--color-text-primary)}.shortcuts__keys{display:flex;align-items:center;flex-wrap:wrap;gap:4px;flex-shrink:0;margin:0}.shortcuts__key{display:inline-flex;align-items:center;justify-content:center;min-width:24px;height:24px;padding:0 6px;background:var(--color-background-secondary, #f5f5f5);border:1px solid var(--color-border-primary);border-radius:var(--border-radius-s, 4px);font-family:var(--font-family-monospace, \"SFMono-Regular\", Consolas, monospace);font-size:var(--font-size-50, 12px);font-weight:600;color:var(--color-text-primary);box-shadow:inset 0 -1px #00000014}.shortcuts__separator{font-size:var(--font-size-s, 14px);color:var(--color-text-secondary);padding:0 2px}\n"] }]
|
|
9542
10298
|
}] });
|
|
9543
10299
|
|
|
10300
|
+
class MozGridFilterDrawerComponent {
|
|
10301
|
+
drawerRef = inject(MozDrawerRef);
|
|
10302
|
+
data = inject(DRAWER_DATA);
|
|
10303
|
+
availableColumns = this.data.availableColumns;
|
|
10304
|
+
draft = signal({
|
|
10305
|
+
conditions: this.data.model.conditions.map((c) => ({ ...c, value: { ...c.value } })),
|
|
10306
|
+
}, ...(ngDevMode ? [{ debugName: "draft" }] : /* istanbul ignore next */ []));
|
|
10307
|
+
activeCount = computed(() => this.draft().conditions.length, ...(ngDevMode ? [{ debugName: "activeCount" }] : /* istanbul ignore next */ []));
|
|
10308
|
+
onDraftChange(model) {
|
|
10309
|
+
this.draft.set(model);
|
|
10310
|
+
}
|
|
10311
|
+
apply() {
|
|
10312
|
+
this.drawerRef.close({ model: this.draft(), applied: true });
|
|
10313
|
+
}
|
|
10314
|
+
clearAll() {
|
|
10315
|
+
this.draft.set({ conditions: [] });
|
|
10316
|
+
}
|
|
10317
|
+
cancel() {
|
|
10318
|
+
this.drawerRef.close({ model: this.data.model, applied: false });
|
|
10319
|
+
}
|
|
10320
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: MozGridFilterDrawerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
10321
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.9", type: MozGridFilterDrawerComponent, isStandalone: true, selector: "moz-grid-filter-drawer", ngImport: i0, template: "<div class=\"filter-drawer\">\n <p class=\"filter-drawer__subtitle\">{{ activeCount() }} active filter(s)</p>\n <moz-grid-filter-builder\n [model]=\"draft()\"\n [availableColumns]=\"availableColumns\"\n [applyMode]=\"'manual'\"\n [showSubtitle]=\"false\"\n (modelChange)=\"onDraftChange($event)\"\n />\n</div>\n\n<ng-template mozDrawerFooter>\n <button moz-button [appearance]=\"'accent'\" (click)=\"apply()\">Apply</button>\n <button moz-button [outlined]=\"true\" (click)=\"clearAll()\">Clear all</button>\n</ng-template>\n", styles: [".filter-drawer{padding-bottom:16px}.filter-drawer__subtitle{margin:0 16px 8px;font-size:12px;font-weight:600;text-transform:uppercase;letter-spacing:.06em;color:var(--Text-Secondary, #555)}\n"], dependencies: [{ kind: "component", type: MozGridFilterBuilderComponent, selector: "moz-grid-filter-builder", inputs: ["model", "availableColumns", "applyMode", "showSubtitle"], outputs: ["modelChange"] }, { kind: "component", type: MozButtonComponent, selector: "button[moz-button]", inputs: ["appearance", "size", "disabled", "ghost", "outlined", "iconPosition", "type", "isLoading"] }, { kind: "directive", type: MozDrawerFooterDirective, selector: "[mozDrawerFooter]" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
10322
|
+
}
|
|
10323
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: MozGridFilterDrawerComponent, decorators: [{
|
|
10324
|
+
type: Component,
|
|
10325
|
+
args: [{ selector: 'moz-grid-filter-drawer', changeDetection: ChangeDetectionStrategy.OnPush, imports: [MozGridFilterBuilderComponent, MozButtonComponent, MozDrawerFooterDirective], template: "<div class=\"filter-drawer\">\n <p class=\"filter-drawer__subtitle\">{{ activeCount() }} active filter(s)</p>\n <moz-grid-filter-builder\n [model]=\"draft()\"\n [availableColumns]=\"availableColumns\"\n [applyMode]=\"'manual'\"\n [showSubtitle]=\"false\"\n (modelChange)=\"onDraftChange($event)\"\n />\n</div>\n\n<ng-template mozDrawerFooter>\n <button moz-button [appearance]=\"'accent'\" (click)=\"apply()\">Apply</button>\n <button moz-button [outlined]=\"true\" (click)=\"clearAll()\">Clear all</button>\n</ng-template>\n", styles: [".filter-drawer{padding-bottom:16px}.filter-drawer__subtitle{margin:0 16px 8px;font-size:12px;font-weight:600;text-transform:uppercase;letter-spacing:.06em;color:var(--Text-Secondary, #555)}\n"] }]
|
|
10326
|
+
}] });
|
|
10327
|
+
|
|
9544
10328
|
class MozGridComponent {
|
|
9545
10329
|
state = inject(GridStateManager);
|
|
9546
10330
|
gridEngine = inject(GridEngine);
|
|
@@ -9568,6 +10352,7 @@ class MozGridComponent {
|
|
|
9568
10352
|
// --- Content children ---
|
|
9569
10353
|
columnDefs = contentChildren(MozGridColumnDef, ...(ngDevMode ? [{ debugName: "columnDefs" }] : /* istanbul ignore next */ []));
|
|
9570
10354
|
toolbarDefs = contentChildren(MozGridToolbarDef, ...(ngDevMode ? [{ debugName: "toolbarDefs" }] : /* istanbul ignore next */ []));
|
|
10355
|
+
emptyDefs = contentChildren(MozGridEmptyDef, ...(ngDevMode ? [{ debugName: "emptyDefs" }] : /* istanbul ignore next */ []));
|
|
9571
10356
|
// --- Inputs ---
|
|
9572
10357
|
data = input([], ...(ngDevMode ? [{ debugName: "data" }] : /* istanbul ignore next */ []));
|
|
9573
10358
|
mode = input('client', ...(ngDevMode ? [{ debugName: "mode" }] : /* istanbul ignore next */ []));
|
|
@@ -9584,6 +10369,17 @@ class MozGridComponent {
|
|
|
9584
10369
|
fullscreen = input(false, ...(ngDevMode ? [{ debugName: "fullscreen" }] : /* istanbul ignore next */ []));
|
|
9585
10370
|
reorderable = input(false, ...(ngDevMode ? [{ debugName: "reorderable" }] : /* istanbul ignore next */ []));
|
|
9586
10371
|
stateKey = input(null, ...(ngDevMode ? [{ debugName: "stateKey" }] : /* istanbul ignore next */ []));
|
|
10372
|
+
// --- Empty state customization ---
|
|
10373
|
+
/** Title for the default "no data" empty state. */
|
|
10374
|
+
emptyDataTitle = input('', ...(ngDevMode ? [{ debugName: "emptyDataTitle" }] : /* istanbul ignore next */ []));
|
|
10375
|
+
/** Description for the default "no data" empty state. */
|
|
10376
|
+
emptyDataDescription = input('', ...(ngDevMode ? [{ debugName: "emptyDataDescription" }] : /* istanbul ignore next */ []));
|
|
10377
|
+
/** Title for the default "no results" empty state (active filters). */
|
|
10378
|
+
noResultsTitle = input('', ...(ngDevMode ? [{ debugName: "noResultsTitle" }] : /* istanbul ignore next */ []));
|
|
10379
|
+
/** Description for the default "no results" empty state. */
|
|
10380
|
+
noResultsDescription = input('', ...(ngDevMode ? [{ debugName: "noResultsDescription" }] : /* istanbul ignore next */ []));
|
|
10381
|
+
/** CTA label on the "no results" state. Empty disables the button. */
|
|
10382
|
+
noResultsActionLabel = input('Clear filters', ...(ngDevMode ? [{ debugName: "noResultsActionLabel" }] : /* istanbul ignore next */ []));
|
|
9587
10383
|
exportable = input(false, ...(ngDevMode ? [{ debugName: "exportable" }] : /* istanbul ignore next */ []));
|
|
9588
10384
|
horizontalVirtualScroll = input(false, ...(ngDevMode ? [{ debugName: "horizontalVirtualScroll" }] : /* istanbul ignore next */ []));
|
|
9589
10385
|
loadingStrategy = input('pagination', ...(ngDevMode ? [{ debugName: "loadingStrategy" }] : /* istanbul ignore next */ []));
|
|
@@ -9608,7 +10404,88 @@ class MozGridComponent {
|
|
|
9608
10404
|
// --- Internal ---
|
|
9609
10405
|
isFullscreen = signal(false, ...(ngDevMode ? [{ debugName: "isFullscreen" }] : /* istanbul ignore next */ []));
|
|
9610
10406
|
groupPanelOpen = signal(false, ...(ngDevMode ? [{ debugName: "groupPanelOpen" }] : /* istanbul ignore next */ []));
|
|
9611
|
-
|
|
10407
|
+
/**
|
|
10408
|
+
* Mode controlling how the builder emits `filterChange`:
|
|
10409
|
+
* - `auto` : each mutation triggers an event (default in `client` mode).
|
|
10410
|
+
* - `manual` : only an explicit Apply emits (default in `server` mode).
|
|
10411
|
+
*/
|
|
10412
|
+
filterApplyMode = input(null, ...(ngDevMode ? [{ debugName: "filterApplyMode" }] : /* istanbul ignore next */ []));
|
|
10413
|
+
resolvedFilterApplyMode = computed(() => {
|
|
10414
|
+
const override = this.filterApplyMode();
|
|
10415
|
+
if (override)
|
|
10416
|
+
return override;
|
|
10417
|
+
return this.state.mode() === 'server' ? 'manual' : 'auto';
|
|
10418
|
+
}, ...(ngDevMode ? [{ debugName: "resolvedFilterApplyMode" }] : /* istanbul ignore next */ []));
|
|
10419
|
+
/** Display descriptors for the "FILTERED BY" tag bar. */
|
|
10420
|
+
activeFilters = computed(() => {
|
|
10421
|
+
return this.filterEngine.conditions().map((c) => ({
|
|
10422
|
+
id: c.id,
|
|
10423
|
+
field: c.field,
|
|
10424
|
+
label: this.filterEngine.toLabel(c),
|
|
10425
|
+
removable: true,
|
|
10426
|
+
}));
|
|
10427
|
+
}, ...(ngDevMode ? [{ debugName: "activeFilters" }] : /* istanbul ignore next */ []));
|
|
10428
|
+
activeFilterCount = computed(() => this.filterEngine.conditions().length, ...(ngDevMode ? [{ debugName: "activeFilterCount" }] : /* istanbul ignore next */ []));
|
|
10429
|
+
/**
|
|
10430
|
+
* Kind of empty state to show, or `'none'` when rows are present:
|
|
10431
|
+
* - `'no-data'` : no rows have been loaded (and the source is empty).
|
|
10432
|
+
* - `'no-results'` : the source has rows but the active filters yield 0.
|
|
10433
|
+
*
|
|
10434
|
+
* Loading and infinite-scroll loading-more states are *not* treated as
|
|
10435
|
+
* empty (we let the loading indicator drive the UX instead).
|
|
10436
|
+
*/
|
|
10437
|
+
emptyStateKind = computed(() => {
|
|
10438
|
+
if (this.gridEngine.displayRows().length > 0)
|
|
10439
|
+
return 'none';
|
|
10440
|
+
if (this.state.isLoading())
|
|
10441
|
+
return 'none';
|
|
10442
|
+
const hasFilters = this.filterEngine.conditions().length > 0;
|
|
10443
|
+
const sourceCount = this.state.mode() === 'server' ? this.state.totalItems() : this.state.sourceData().length;
|
|
10444
|
+
// In server mode `totalItems` may not reflect filters, so trust active
|
|
10445
|
+
// filters as the discriminator. Same heuristic in client mode.
|
|
10446
|
+
if (hasFilters)
|
|
10447
|
+
return 'no-results';
|
|
10448
|
+
if (sourceCount === 0)
|
|
10449
|
+
return 'no-data';
|
|
10450
|
+
// Source has rows, no filters, but display is empty (e.g. group with no
|
|
10451
|
+
// matching rows after pagination). Fall back to `no-results` which
|
|
10452
|
+
// offers the "Clear filters" CTA — harmless when no filters are active
|
|
10453
|
+
// because we hide the button when the count is zero.
|
|
10454
|
+
return 'no-results';
|
|
10455
|
+
}, ...(ngDevMode ? [{ debugName: "emptyStateKind" }] : /* istanbul ignore next */ []));
|
|
10456
|
+
/** Resolves the projected `<ng-template mozGridEmptyDef>` for the kind. */
|
|
10457
|
+
emptyTemplate = computed(() => {
|
|
10458
|
+
const kind = this.emptyStateKind();
|
|
10459
|
+
if (kind === 'none')
|
|
10460
|
+
return null;
|
|
10461
|
+
const defs = this.emptyDefs();
|
|
10462
|
+
const exact = defs.find((d) => d.kind() === kind);
|
|
10463
|
+
if (exact)
|
|
10464
|
+
return exact.template;
|
|
10465
|
+
// Fallback to a `no-data` template for the `no-results` kind.
|
|
10466
|
+
return defs.find((d) => d.kind() === 'no-data')?.template ?? null;
|
|
10467
|
+
}, ...(ngDevMode ? [{ debugName: "emptyTemplate" }] : /* istanbul ignore next */ []));
|
|
10468
|
+
/** Context object exposed to projected empty-state templates. */
|
|
10469
|
+
emptyContext = computed(() => ({
|
|
10470
|
+
activeFilterCount: this.filterEngine.conditions().length,
|
|
10471
|
+
clearFilters: () => this.filterEngine.clearAll(),
|
|
10472
|
+
}), ...(ngDevMode ? [{ debugName: "emptyContext" }] : /* istanbul ignore next */ []));
|
|
10473
|
+
/**
|
|
10474
|
+
* Wrap the empty context for `ngTemplateOutlet` so consumers can use
|
|
10475
|
+
* either `let-ctx` (positional, via `$implicit`) or named bindings
|
|
10476
|
+
* (`let-clearFilters="clearFilters"`) without having to choose at
|
|
10477
|
+
* declaration time.
|
|
10478
|
+
*/
|
|
10479
|
+
emptyTemplateContext = computed(() => {
|
|
10480
|
+
const ctx = this.emptyContext();
|
|
10481
|
+
return { $implicit: ctx, ...ctx };
|
|
10482
|
+
}, ...(ngDevMode ? [{ debugName: "emptyTemplateContext" }] : /* istanbul ignore next */ []));
|
|
10483
|
+
/** CTA label for the default no-results state — hidden when no filters. */
|
|
10484
|
+
resolvedNoResultsActionLabel = computed(() => {
|
|
10485
|
+
if (this.filterEngine.conditions().length === 0)
|
|
10486
|
+
return '';
|
|
10487
|
+
return this.noResultsActionLabel();
|
|
10488
|
+
}, ...(ngDevMode ? [{ debugName: "resolvedNoResultsActionLabel" }] : /* istanbul ignore next */ []));
|
|
9612
10489
|
hasHiddenColumns = computed(() => this.state.columnStates().some((col) => !col.visible), ...(ngDevMode ? [{ debugName: "hasHiddenColumns" }] : /* istanbul ignore next */ []));
|
|
9613
10490
|
hiddenColumnsList = computed(() => {
|
|
9614
10491
|
const defMap = this.state.columnDefMap();
|
|
@@ -9799,7 +10676,7 @@ class MozGridComponent {
|
|
|
9799
10676
|
this.persistenceEngine.restore(key);
|
|
9800
10677
|
}
|
|
9801
10678
|
}, { allowSignalWrites: true });
|
|
9802
|
-
// Auto-save state on column/sort changes
|
|
10679
|
+
// Auto-save state on column/sort/filter changes
|
|
9803
10680
|
effect(() => {
|
|
9804
10681
|
const key = this.stateKey();
|
|
9805
10682
|
if (!key)
|
|
@@ -9807,8 +10684,19 @@ class MozGridComponent {
|
|
|
9807
10684
|
// Read signals to track them
|
|
9808
10685
|
this.state.columnStates();
|
|
9809
10686
|
this.state.activeSorts();
|
|
10687
|
+
this.state.filterModel();
|
|
9810
10688
|
this.persistenceEngine.save(key);
|
|
9811
10689
|
});
|
|
10690
|
+
// Emit `filterChange` once per mutation. The engine's `lastEvent` signal
|
|
10691
|
+
// is set synchronously from every mutation path, guaranteeing we emit
|
|
10692
|
+
// exactly once per reason (add / update / remove / reorder / clear / replace).
|
|
10693
|
+
effect(() => {
|
|
10694
|
+
const event = this.filterEngine.lastEvent();
|
|
10695
|
+
if (!event)
|
|
10696
|
+
return;
|
|
10697
|
+
this.filterChange.emit(event);
|
|
10698
|
+
this.resetInfiniteScrollIfActive();
|
|
10699
|
+
});
|
|
9812
10700
|
// Initialize plugins
|
|
9813
10701
|
effect(() => {
|
|
9814
10702
|
const pluginList = this.plugins();
|
|
@@ -10306,17 +11194,27 @@ class MozGridComponent {
|
|
|
10306
11194
|
this.state.activeSelectionMode.set('none');
|
|
10307
11195
|
this.selectionChange.emit(this.rowSelectionEngine.getSelectionEvent());
|
|
10308
11196
|
}
|
|
10309
|
-
|
|
10310
|
-
|
|
10311
|
-
this.
|
|
10312
|
-
this.resetInfiniteScrollIfActive();
|
|
11197
|
+
/** Removes a single condition by id (tag "×" button). */
|
|
11198
|
+
onRemoveFilter(id) {
|
|
11199
|
+
this.filterEngine.removeCondition(id);
|
|
10313
11200
|
}
|
|
11201
|
+
/** Clears the whole filter model ("Remove all" button). */
|
|
10314
11202
|
onRemoveAllFilters() {
|
|
10315
|
-
|
|
10316
|
-
|
|
10317
|
-
|
|
10318
|
-
|
|
10319
|
-
|
|
11203
|
+
this.filterEngine.clearAll();
|
|
11204
|
+
}
|
|
11205
|
+
// --- Filter drawer ---
|
|
11206
|
+
onFiltersClick() {
|
|
11207
|
+
const data = {
|
|
11208
|
+
model: { conditions: this.filterEngine.conditions().slice() },
|
|
11209
|
+
availableColumns: this.filterEngine.describeFilterableColumns(),
|
|
11210
|
+
applyMode: this.resolvedFilterApplyMode(),
|
|
11211
|
+
};
|
|
11212
|
+
const ref = this.drawerService.open(MozGridFilterDrawerComponent, { title: 'Filters', data, extended: true });
|
|
11213
|
+
ref.afterClosed().subscribe((result) => {
|
|
11214
|
+
if (result?.applied) {
|
|
11215
|
+
this.filterEngine.setModel(result.model, 'replace');
|
|
11216
|
+
}
|
|
11217
|
+
});
|
|
10320
11218
|
}
|
|
10321
11219
|
onRestoreColumn(field) {
|
|
10322
11220
|
this.state.updateColumnState(field, { visible: true });
|
|
@@ -10535,21 +11433,37 @@ class MozGridComponent {
|
|
|
10535
11433
|
return;
|
|
10536
11434
|
try {
|
|
10537
11435
|
const text = await navigator.clipboard.readText();
|
|
10538
|
-
const rows = text
|
|
11436
|
+
const rows = text
|
|
11437
|
+
.replace(/\r?\n$/, '')
|
|
11438
|
+
.split('\n')
|
|
11439
|
+
.map((line) => line.split('\t'));
|
|
10539
11440
|
const cols = this.state.visibleColumns();
|
|
10540
|
-
//
|
|
10541
|
-
|
|
10542
|
-
|
|
10543
|
-
|
|
10544
|
-
|
|
10545
|
-
|
|
10546
|
-
|
|
10547
|
-
|
|
11441
|
+
// Excel-style: a single clipboard value pasted over a multi-cell selection
|
|
11442
|
+
// fills the entire selection rather than only the focused anchor.
|
|
11443
|
+
const isSingleValue = rows.length === 1 && rows[0].length === 1;
|
|
11444
|
+
const selection = this.cellSelectionEngine.getNormalizedRange();
|
|
11445
|
+
const isMultiCellSelection = !!selection &&
|
|
11446
|
+
(selection.start.row !== selection.end.row || selection.start.col !== selection.end.col);
|
|
11447
|
+
let pasteRange;
|
|
11448
|
+
let pasteChanges;
|
|
11449
|
+
if (isSingleValue && isMultiCellSelection && selection) {
|
|
11450
|
+
pasteRange = selection;
|
|
11451
|
+
pasteChanges = this.clipboardEngine.fillSelection(selection, rows[0][0]);
|
|
11452
|
+
}
|
|
11453
|
+
else {
|
|
11454
|
+
pasteRange = {
|
|
11455
|
+
start: { row: focused.row, col: focused.col },
|
|
11456
|
+
end: {
|
|
11457
|
+
row: Math.min(focused.row + rows.length - 1, this.state.sourceData().length - 1),
|
|
11458
|
+
col: Math.min(focused.col + (rows[0]?.length ?? 1) - 1, cols.length - 1),
|
|
11459
|
+
},
|
|
11460
|
+
};
|
|
11461
|
+
pasteChanges = this.clipboardEngine.applyPaste(pasteRange, rows);
|
|
11462
|
+
}
|
|
10548
11463
|
// If a cut is pending, first wipe the source cells so cut+paste == move,
|
|
10549
11464
|
// and fold both halves into a single undoable history op.
|
|
10550
11465
|
const cutSource = this.state.cutSource();
|
|
10551
11466
|
const clearChanges = cutSource ? this.clipboardEngine.clearRange(cutSource) : [];
|
|
10552
|
-
const pasteChanges = this.clipboardEngine.applyPaste(pasteRange, rows);
|
|
10553
11467
|
const allChanges = [...clearChanges, ...pasteChanges];
|
|
10554
11468
|
if (allChanges.length > 0) {
|
|
10555
11469
|
this.historyEngine.record(cutSource ? 'cut' : 'paste', allChanges);
|
|
@@ -10800,7 +11714,7 @@ class MozGridComponent {
|
|
|
10800
11714
|
return value;
|
|
10801
11715
|
}
|
|
10802
11716
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: MozGridComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
10803
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: MozGridComponent, isStandalone: true, selector: "moz-grid", inputs: { data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: false, transformFunction: null }, mode: { classPropertyName: "mode", publicName: "mode", isSignal: true, isRequired: false, transformFunction: null }, totalItems: { classPropertyName: "totalItems", publicName: "totalItems", isSignal: true, isRequired: false, transformFunction: null }, pagination: { classPropertyName: "pagination", publicName: "pagination", isSignal: true, isRequired: false, transformFunction: null }, pageSize: { classPropertyName: "pageSize", publicName: "pageSize", isSignal: true, isRequired: false, transformFunction: null }, pageSizeOptions: { classPropertyName: "pageSizeOptions", publicName: "pageSizeOptions", isSignal: true, isRequired: false, transformFunction: null }, rowHeight: { classPropertyName: "rowHeight", publicName: "rowHeight", isSignal: true, isRequired: false, transformFunction: null }, loading: { classPropertyName: "loading", publicName: "loading", isSignal: true, isRequired: false, transformFunction: null }, rowSelection: { classPropertyName: "rowSelection", publicName: "rowSelection", isSignal: true, isRequired: false, transformFunction: null }, expandable: { classPropertyName: "expandable", publicName: "expandable", isSignal: true, isRequired: false, transformFunction: null }, rowIdField: { classPropertyName: "rowIdField", publicName: "rowIdField", isSignal: true, isRequired: false, transformFunction: null }, detailTemplate: { classPropertyName: "detailTemplate", publicName: "detailTemplate", isSignal: true, isRequired: false, transformFunction: null }, fullscreen: { classPropertyName: "fullscreen", publicName: "fullscreen", isSignal: true, isRequired: false, transformFunction: null }, reorderable: { classPropertyName: "reorderable", publicName: "reorderable", isSignal: true, isRequired: false, transformFunction: null }, stateKey: { classPropertyName: "stateKey", publicName: "stateKey", isSignal: true, isRequired: false, transformFunction: null }, exportable: { classPropertyName: "exportable", publicName: "exportable", isSignal: true, isRequired: false, transformFunction: null }, horizontalVirtualScroll: { classPropertyName: "horizontalVirtualScroll", publicName: "horizontalVirtualScroll", isSignal: true, isRequired: false, transformFunction: null }, loadingStrategy: { classPropertyName: "loadingStrategy", publicName: "loadingStrategy", isSignal: true, isRequired: false, transformFunction: null }, scrollThreshold: { classPropertyName: "scrollThreshold", publicName: "scrollThreshold", isSignal: true, isRequired: false, transformFunction: null }, plugins: { classPropertyName: "plugins", publicName: "plugins", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { sortChange: "sortChange", pageChange: "pageChange", loadMore: "loadMore", cellEdit: "cellEdit", cellEditCancel: "cellEditCancel", selectionChange: "selectionChange", cellSelectionChange: "cellSelectionChange", groupChange: "groupChange", filterChange: "filterChange", bulkEdit: "bulkEdit", bulkCopy: "bulkCopy", bulkPaste: "bulkPaste", bulkDelete: "bulkDelete", fillDown: "fillDown", settingsChange: "settingsChange" }, providers: [
|
|
11717
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: MozGridComponent, isStandalone: true, selector: "moz-grid", inputs: { data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: false, transformFunction: null }, mode: { classPropertyName: "mode", publicName: "mode", isSignal: true, isRequired: false, transformFunction: null }, totalItems: { classPropertyName: "totalItems", publicName: "totalItems", isSignal: true, isRequired: false, transformFunction: null }, pagination: { classPropertyName: "pagination", publicName: "pagination", isSignal: true, isRequired: false, transformFunction: null }, pageSize: { classPropertyName: "pageSize", publicName: "pageSize", isSignal: true, isRequired: false, transformFunction: null }, pageSizeOptions: { classPropertyName: "pageSizeOptions", publicName: "pageSizeOptions", isSignal: true, isRequired: false, transformFunction: null }, rowHeight: { classPropertyName: "rowHeight", publicName: "rowHeight", isSignal: true, isRequired: false, transformFunction: null }, loading: { classPropertyName: "loading", publicName: "loading", isSignal: true, isRequired: false, transformFunction: null }, rowSelection: { classPropertyName: "rowSelection", publicName: "rowSelection", isSignal: true, isRequired: false, transformFunction: null }, expandable: { classPropertyName: "expandable", publicName: "expandable", isSignal: true, isRequired: false, transformFunction: null }, rowIdField: { classPropertyName: "rowIdField", publicName: "rowIdField", isSignal: true, isRequired: false, transformFunction: null }, detailTemplate: { classPropertyName: "detailTemplate", publicName: "detailTemplate", isSignal: true, isRequired: false, transformFunction: null }, fullscreen: { classPropertyName: "fullscreen", publicName: "fullscreen", isSignal: true, isRequired: false, transformFunction: null }, reorderable: { classPropertyName: "reorderable", publicName: "reorderable", isSignal: true, isRequired: false, transformFunction: null }, stateKey: { classPropertyName: "stateKey", publicName: "stateKey", isSignal: true, isRequired: false, transformFunction: null }, emptyDataTitle: { classPropertyName: "emptyDataTitle", publicName: "emptyDataTitle", isSignal: true, isRequired: false, transformFunction: null }, emptyDataDescription: { classPropertyName: "emptyDataDescription", publicName: "emptyDataDescription", isSignal: true, isRequired: false, transformFunction: null }, noResultsTitle: { classPropertyName: "noResultsTitle", publicName: "noResultsTitle", isSignal: true, isRequired: false, transformFunction: null }, noResultsDescription: { classPropertyName: "noResultsDescription", publicName: "noResultsDescription", isSignal: true, isRequired: false, transformFunction: null }, noResultsActionLabel: { classPropertyName: "noResultsActionLabel", publicName: "noResultsActionLabel", isSignal: true, isRequired: false, transformFunction: null }, exportable: { classPropertyName: "exportable", publicName: "exportable", isSignal: true, isRequired: false, transformFunction: null }, horizontalVirtualScroll: { classPropertyName: "horizontalVirtualScroll", publicName: "horizontalVirtualScroll", isSignal: true, isRequired: false, transformFunction: null }, loadingStrategy: { classPropertyName: "loadingStrategy", publicName: "loadingStrategy", isSignal: true, isRequired: false, transformFunction: null }, scrollThreshold: { classPropertyName: "scrollThreshold", publicName: "scrollThreshold", isSignal: true, isRequired: false, transformFunction: null }, plugins: { classPropertyName: "plugins", publicName: "plugins", isSignal: true, isRequired: false, transformFunction: null }, filterApplyMode: { classPropertyName: "filterApplyMode", publicName: "filterApplyMode", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { sortChange: "sortChange", pageChange: "pageChange", loadMore: "loadMore", cellEdit: "cellEdit", cellEditCancel: "cellEditCancel", selectionChange: "selectionChange", cellSelectionChange: "cellSelectionChange", groupChange: "groupChange", filterChange: "filterChange", bulkEdit: "bulkEdit", bulkCopy: "bulkCopy", bulkPaste: "bulkPaste", bulkDelete: "bulkDelete", fillDown: "fillDown", settingsChange: "settingsChange" }, providers: [
|
|
10804
11718
|
GridStateManager,
|
|
10805
11719
|
GridEngine,
|
|
10806
11720
|
SortEngine,
|
|
@@ -10824,7 +11738,7 @@ class MozGridComponent {
|
|
|
10824
11738
|
PaginationEngine,
|
|
10825
11739
|
InfiniteScrollEngine,
|
|
10826
11740
|
Overlay,
|
|
10827
|
-
], queries: [{ propertyName: "columnDefs", predicate: MozGridColumnDef, isSignal: true }, { propertyName: "toolbarDefs", predicate: MozGridToolbarDef, isSignal: true }], viewQueries: [{ propertyName: "gridBody", first: true, predicate: MozGridBodyComponent, descendants: true, isSignal: true }, { propertyName: "gridContainer", first: true, predicate: ["gridContainer"], descendants: true, isSignal: true }], ngImport: i0, template: `
|
|
11741
|
+
], queries: [{ propertyName: "columnDefs", predicate: MozGridColumnDef, isSignal: true }, { propertyName: "toolbarDefs", predicate: MozGridToolbarDef, isSignal: true }, { propertyName: "emptyDefs", predicate: MozGridEmptyDef, isSignal: true }], viewQueries: [{ propertyName: "gridBody", first: true, predicate: MozGridBodyComponent, descendants: true, isSignal: true }, { propertyName: "gridContainer", first: true, predicate: ["gridContainer"], descendants: true, isSignal: true }], ngImport: i0, template: `
|
|
10828
11742
|
<div class="moz-grid-wrapper" [class.moz-grid-wrapper--fullscreen]="isFullscreen()">
|
|
10829
11743
|
<!-- Toolbar (outside .moz-grid) -->
|
|
10830
11744
|
<div class="moz-grid__toolbar">
|
|
@@ -10854,15 +11768,24 @@ class MozGridComponent {
|
|
|
10854
11768
|
<Download20 icon />
|
|
10855
11769
|
</moz-icon-button>
|
|
10856
11770
|
}
|
|
10857
|
-
<
|
|
11771
|
+
<button
|
|
11772
|
+
type="button"
|
|
11773
|
+
moz-button
|
|
10858
11774
|
id="grid-filter"
|
|
10859
11775
|
size="s"
|
|
10860
11776
|
[ghost]="true"
|
|
10861
|
-
ariaLabel="
|
|
10862
|
-
|
|
11777
|
+
[ariaLabel]="'Filters'"
|
|
11778
|
+
class="moz-grid__toolbar-filter-btn"
|
|
11779
|
+
(click)="onFiltersClick()"
|
|
10863
11780
|
>
|
|
10864
11781
|
<Filter20 icon />
|
|
10865
|
-
|
|
11782
|
+
<span>Filters</span>
|
|
11783
|
+
@if (activeFilterCount() > 0) {
|
|
11784
|
+
<span class="moz-grid__toolbar-filter-badge" aria-hidden="true">
|
|
11785
|
+
{{ activeFilterCount() }}
|
|
11786
|
+
</span>
|
|
11787
|
+
}
|
|
11788
|
+
</button>
|
|
10866
11789
|
<moz-icon-button
|
|
10867
11790
|
id="grid-settings"
|
|
10868
11791
|
size="s"
|
|
@@ -10972,15 +11895,15 @@ class MozGridComponent {
|
|
|
10972
11895
|
</button>
|
|
10973
11896
|
}
|
|
10974
11897
|
</div>
|
|
10975
|
-
} @if (
|
|
11898
|
+
} @if (activeFilters().length > 0) {
|
|
10976
11899
|
<div class="moz-grid__tag-bar">
|
|
10977
11900
|
<span class="moz-grid__tag-bar-label">FILTERED BY</span>
|
|
10978
|
-
@for (filter of
|
|
11901
|
+
@for (filter of activeFilters(); track filter.id) {
|
|
10979
11902
|
<moz-tag
|
|
10980
11903
|
[type]="filter.removable ? 'removable' : 'informative'"
|
|
10981
11904
|
size="s"
|
|
10982
|
-
[id]="'filter-' + filter.
|
|
10983
|
-
(removeTag)="onRemoveFilter(filter.
|
|
11905
|
+
[id]="'filter-' + filter.id"
|
|
11906
|
+
(removeTag)="onRemoveFilter(filter.id)"
|
|
10984
11907
|
>{{ filter.label }}</moz-tag
|
|
10985
11908
|
>
|
|
10986
11909
|
}
|
|
@@ -11022,6 +11945,25 @@ class MozGridComponent {
|
|
|
11022
11945
|
(rowSelectionToggle)="onRowSelectionToggle()"
|
|
11023
11946
|
/>
|
|
11024
11947
|
|
|
11948
|
+
<!-- Empty state overlay (consumer template wins, fallback default) -->
|
|
11949
|
+
@if (emptyStateKind() !== 'none') {
|
|
11950
|
+
<div class="moz-grid__empty-overlay">
|
|
11951
|
+
@if (emptyTemplate(); as tpl) {
|
|
11952
|
+
<ng-container *ngTemplateOutlet="tpl; context: emptyTemplateContext()" />
|
|
11953
|
+
} @else {
|
|
11954
|
+
<moz-grid-empty-state
|
|
11955
|
+
[kind]="$any(emptyStateKind())"
|
|
11956
|
+
[title]="emptyStateKind() === 'no-results' ? noResultsTitle() : emptyDataTitle()"
|
|
11957
|
+
[description]="
|
|
11958
|
+
emptyStateKind() === 'no-results' ? noResultsDescription() : emptyDataDescription()
|
|
11959
|
+
"
|
|
11960
|
+
[actionLabel]="emptyStateKind() === 'no-results' ? resolvedNoResultsActionLabel() : ''"
|
|
11961
|
+
(action)="onRemoveAllFilters()"
|
|
11962
|
+
/>
|
|
11963
|
+
}
|
|
11964
|
+
</div>
|
|
11965
|
+
}
|
|
11966
|
+
|
|
11025
11967
|
<!-- Footer: pagination or infinite scroll loading indicator -->
|
|
11026
11968
|
@if (showPagination()) {
|
|
11027
11969
|
<moz-grid-footer
|
|
@@ -11042,7 +11984,7 @@ class MozGridComponent {
|
|
|
11042
11984
|
/>
|
|
11043
11985
|
</div>
|
|
11044
11986
|
</div>
|
|
11045
|
-
`, isInline: true, styles: [":host{display:block;height:100%}.moz-grid-wrapper{display:flex;flex-direction:column;font-family:var(--font-family-primary);height:100%;min-height:0;gap:16px}.moz-grid-wrapper--fullscreen{position:fixed;top:0;left:0;width:100vw;height:100vh;z-index:9999;background:var(--color-background-primary)}.moz-grid{display:flex;flex-direction:column;border-radius:var(--border-radius-l);overflow:hidden;background:var(--color-background-primary);flex:1;min-height:0;position:relative;box-shadow:0 0 6px #cdd4d8}.moz-grid:focus{outline:none}.moz-grid--loading{opacity:.6;pointer-events:none}.moz-grid__toolbar{display:flex;align-items:center;justify-content:space-between;flex-shrink:0;min-height:48px;gap:var(--spacing-s, 8px)}.moz-grid__toolbar-left,.moz-grid__toolbar-right{display:flex;align-items:center;gap:var(--spacing-xs, 4px)}.moz-grid__selection-banner{display:flex;align-items:center;gap:var(--spacing-s, 8px);flex:1;justify-content:center;border-radius:var(--border-radius-s);border:1px solid var(--Border-Primary, #cdd4d8);background:var(--Neutral-Grey-000, #fff)}.moz-grid__selection-text{font-size:var(--font-size-s, 14px);color:var(--color-text-primary);white-space:nowrap}.moz-grid__selection-link{padding:0;border:none;background:transparent;color:var(--color-background-accent-inverse);font-size:var(--font-size-s, 14px);font-weight:600;cursor:pointer;white-space:nowrap;text-decoration:underline}.moz-grid__selection-link:hover{color:var(--color-primary-dark, #1557b0)}.moz-grid__tag-bar{display:flex;align-items:center;flex-wrap:wrap;gap:var(--spacing-xs, 4px);padding:var(--spacing-xxs, 2px) var(--spacing-s, 8px);flex-shrink:0}.moz-grid__tag-bar-label{width:100%;font-size:var(--font-size-xs, 12px);text-transform:uppercase;white-space:nowrap;color:var(--text-icon-tertiary);font-size:var(--Typography-Font-size-Body-XS, 12px);font-weight:400}.moz-grid__tag-action-btn{padding:2px 8px;border:none;background:transparent;color:var(--color-background-accent-inverse);font-size:var(--font-size-xs, 12px);font-weight:600;cursor:pointer}.moz-grid__tag-action-btn:hover{text-decoration:underline}.moz-grid__group-tag-btn{display:inline-flex;align-items:center;gap:2px;padding:0;border:none;background:transparent;cursor:pointer;font:inherit;color:inherit;line-height:1}.moz-grid__group-tag-btn ::ng-deep svg{fill:#fff!important;width:16px;height:16px}\n"], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: MozGridHeaderComponent, selector: "moz-grid-header", inputs: ["showCheckbox", "showExpand", "reorderable"], outputs: ["sortClick", "menuAction", "resizeStart", "selectAllToggle", "columnReorder"] }, { kind: "component", type: MozGridBodyComponent, selector: "moz-grid-body", inputs: ["showCheckbox", "showExpand", "detailTemplate"], outputs: ["cellEdit", "cellEditCancel", "rowSelectionToggle", "groupToggle"] }, { kind: "component", type: MozGridFooterComponent, selector: "moz-grid-footer", inputs: ["pageSizeOptions"], outputs: ["pageChange"] }, { kind: "component", type: MozGridLoadingIndicatorComponent, selector: "moz-grid-loading-indicator" }, { kind: "component", type: MozGridSelectionBarComponent, selector: "moz-grid-selection-bar", outputs: ["editClick", "copyClick", "pasteClick", "deleteClick", "exportClick"] }, { kind: "component", type: MozTagComponent, selector: "moz-tag", inputs: ["type", "size", "id", "name", "disabled", "contextualisedNumber", "removableLabel"], outputs: ["removeTag"] }, { kind: "component", type: MozIconButtonComponent, selector: "moz-icon-button", inputs: ["id", "appearance", "size", "disabled", "ghost", "outlined", "type", "ariaLabel"], outputs: ["activated"] }, { kind: "component", type: ViewGridX420, selector: "ViewGridX420", inputs: ["hostClass"] }, { kind: "component", type: Filter20, selector: "Filter20", inputs: ["hostClass"] }, { kind: "component", type: Settings20, selector: "Settings20", inputs: ["hostClass"] }, { kind: "component", type: FullscreenEnter20, selector: "FullscreenEnter20", inputs: ["hostClass"] }, { kind: "component", type: FullscreenExit20, selector: "FullscreenExit20", inputs: ["hostClass"] }, { kind: "component", type: Download20, selector: "Download20", inputs: ["hostClass"] }, { kind: "component", type: ChevronUp20, selector: "ChevronUp20", inputs: ["hostClass"] }, { kind: "component", type: ChevronDown20, selector: "ChevronDown20", inputs: ["hostClass"] }, { kind: "component", type: Keyboard20, selector: "Keyboard20", inputs: ["hostClass"] }, { kind: "component", type: MozButtonComponent, selector: "button[moz-button]", inputs: ["appearance", "size", "disabled", "ghost", "outlined", "iconPosition", "type", "isLoading"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
11987
|
+
`, isInline: true, styles: [":host{display:block;height:100%}.moz-grid-wrapper{display:flex;flex-direction:column;font-family:var(--font-family-primary);height:100%;min-height:0;gap:16px}.moz-grid-wrapper--fullscreen{position:fixed;top:0;left:0;width:100vw;height:100vh;z-index:9999;background:var(--color-background-primary)}.moz-grid{display:flex;flex-direction:column;border-radius:var(--border-radius-l);overflow:hidden;background:var(--color-background-primary);flex:1;min-height:0;position:relative;box-shadow:0 0 6px #cdd4d8}.moz-grid__empty-overlay{position:absolute;inset:0;top:var(--moz-grid-header-height, 48px);display:flex;align-items:center;justify-content:center;background:var(--Background-Primary, #fff);z-index:1}.moz-grid:focus{outline:none}.moz-grid--loading{opacity:.6;pointer-events:none}.moz-grid__toolbar{display:flex;align-items:center;justify-content:space-between;flex-shrink:0;min-height:48px;gap:var(--spacing-s, 8px)}.moz-grid__toolbar-left,.moz-grid__toolbar-right{display:flex;align-items:center;gap:var(--spacing-xs, 4px)}.moz-grid__toolbar-filter-btn{display:inline-flex;align-items:center;gap:4px}.moz-grid__toolbar-filter-badge{display:inline-flex;align-items:center;justify-content:center;min-width:18px;height:18px;padding:0 6px;border-radius:9px;background:var(--Status-Standalone-element-Primary, #0071ce);color:#fff;font-size:11px;font-weight:600;line-height:1}.moz-grid__selection-banner{display:flex;align-items:center;gap:var(--spacing-s, 8px);flex:1;justify-content:center;border-radius:var(--border-radius-s);border:1px solid var(--Border-Primary, #cdd4d8);background:var(--Neutral-Grey-000, #fff)}.moz-grid__selection-text{font-size:var(--font-size-s, 14px);color:var(--color-text-primary);white-space:nowrap}.moz-grid__selection-link{padding:0;border:none;background:transparent;color:var(--color-background-accent-inverse);font-size:var(--font-size-s, 14px);font-weight:600;cursor:pointer;white-space:nowrap;text-decoration:underline}.moz-grid__selection-link:hover{color:var(--color-primary-dark, #1557b0)}.moz-grid__tag-bar{display:flex;align-items:center;flex-wrap:wrap;gap:var(--spacing-xs, 4px);padding:var(--spacing-xxs, 2px) var(--spacing-s, 8px);flex-shrink:0}.moz-grid__tag-bar-label{width:100%;font-size:var(--font-size-xs, 12px);text-transform:uppercase;white-space:nowrap;color:var(--text-icon-tertiary);font-size:var(--Typography-Font-size-Body-XS, 12px);font-weight:400}.moz-grid__tag-action-btn{padding:2px 8px;border:none;background:transparent;color:var(--color-background-accent-inverse);font-size:var(--font-size-xs, 12px);font-weight:600;cursor:pointer}.moz-grid__tag-action-btn:hover{text-decoration:underline}.moz-grid__group-tag-btn{display:inline-flex;align-items:center;gap:2px;padding:0;border:none;background:transparent;cursor:pointer;font:inherit;color:inherit;line-height:1}.moz-grid__group-tag-btn ::ng-deep svg{fill:#fff!important;width:16px;height:16px}\n"], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: MozGridHeaderComponent, selector: "moz-grid-header", inputs: ["showCheckbox", "showExpand", "reorderable"], outputs: ["sortClick", "menuAction", "resizeStart", "selectAllToggle", "columnReorder"] }, { kind: "component", type: MozGridBodyComponent, selector: "moz-grid-body", inputs: ["showCheckbox", "showExpand", "detailTemplate"], outputs: ["cellEdit", "cellEditCancel", "rowSelectionToggle", "groupToggle"] }, { kind: "component", type: MozGridFooterComponent, selector: "moz-grid-footer", inputs: ["pageSizeOptions"], outputs: ["pageChange"] }, { kind: "component", type: MozGridLoadingIndicatorComponent, selector: "moz-grid-loading-indicator" }, { kind: "component", type: MozGridSelectionBarComponent, selector: "moz-grid-selection-bar", outputs: ["editClick", "copyClick", "pasteClick", "deleteClick", "exportClick"] }, { kind: "component", type: MozGridEmptyStateComponent, selector: "moz-grid-empty-state", inputs: ["kind", "title", "description", "actionLabel"], outputs: ["action"] }, { kind: "component", type: MozTagComponent, selector: "moz-tag", inputs: ["type", "size", "id", "name", "disabled", "contextualisedNumber", "removableLabel"], outputs: ["removeTag"] }, { kind: "component", type: MozIconButtonComponent, selector: "moz-icon-button", inputs: ["id", "appearance", "size", "disabled", "ghost", "outlined", "type", "ariaLabel"], outputs: ["activated"] }, { kind: "component", type: ViewGridX420, selector: "ViewGridX420", inputs: ["hostClass"] }, { kind: "component", type: Filter20, selector: "Filter20", inputs: ["hostClass"] }, { kind: "component", type: Settings20, selector: "Settings20", inputs: ["hostClass"] }, { kind: "component", type: FullscreenEnter20, selector: "FullscreenEnter20", inputs: ["hostClass"] }, { kind: "component", type: FullscreenExit20, selector: "FullscreenExit20", inputs: ["hostClass"] }, { kind: "component", type: Download20, selector: "Download20", inputs: ["hostClass"] }, { kind: "component", type: ChevronUp20, selector: "ChevronUp20", inputs: ["hostClass"] }, { kind: "component", type: ChevronDown20, selector: "ChevronDown20", inputs: ["hostClass"] }, { kind: "component", type: Keyboard20, selector: "Keyboard20", inputs: ["hostClass"] }, { kind: "component", type: MozButtonComponent, selector: "button[moz-button]", inputs: ["appearance", "size", "disabled", "ghost", "outlined", "iconPosition", "type", "isLoading"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
11046
11988
|
}
|
|
11047
11989
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: MozGridComponent, decorators: [{
|
|
11048
11990
|
type: Component,
|
|
@@ -11077,6 +12019,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
|
|
|
11077
12019
|
MozGridFooterComponent,
|
|
11078
12020
|
MozGridLoadingIndicatorComponent,
|
|
11079
12021
|
MozGridSelectionBarComponent,
|
|
12022
|
+
MozGridEmptyStateComponent,
|
|
11080
12023
|
MozTagComponent,
|
|
11081
12024
|
MozIconButtonComponent,
|
|
11082
12025
|
ViewGridX420,
|
|
@@ -11119,15 +12062,24 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
|
|
|
11119
12062
|
<Download20 icon />
|
|
11120
12063
|
</moz-icon-button>
|
|
11121
12064
|
}
|
|
11122
|
-
<
|
|
12065
|
+
<button
|
|
12066
|
+
type="button"
|
|
12067
|
+
moz-button
|
|
11123
12068
|
id="grid-filter"
|
|
11124
12069
|
size="s"
|
|
11125
12070
|
[ghost]="true"
|
|
11126
|
-
ariaLabel="
|
|
11127
|
-
|
|
12071
|
+
[ariaLabel]="'Filters'"
|
|
12072
|
+
class="moz-grid__toolbar-filter-btn"
|
|
12073
|
+
(click)="onFiltersClick()"
|
|
11128
12074
|
>
|
|
11129
12075
|
<Filter20 icon />
|
|
11130
|
-
|
|
12076
|
+
<span>Filters</span>
|
|
12077
|
+
@if (activeFilterCount() > 0) {
|
|
12078
|
+
<span class="moz-grid__toolbar-filter-badge" aria-hidden="true">
|
|
12079
|
+
{{ activeFilterCount() }}
|
|
12080
|
+
</span>
|
|
12081
|
+
}
|
|
12082
|
+
</button>
|
|
11131
12083
|
<moz-icon-button
|
|
11132
12084
|
id="grid-settings"
|
|
11133
12085
|
size="s"
|
|
@@ -11237,15 +12189,15 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
|
|
|
11237
12189
|
</button>
|
|
11238
12190
|
}
|
|
11239
12191
|
</div>
|
|
11240
|
-
} @if (
|
|
12192
|
+
} @if (activeFilters().length > 0) {
|
|
11241
12193
|
<div class="moz-grid__tag-bar">
|
|
11242
12194
|
<span class="moz-grid__tag-bar-label">FILTERED BY</span>
|
|
11243
|
-
@for (filter of
|
|
12195
|
+
@for (filter of activeFilters(); track filter.id) {
|
|
11244
12196
|
<moz-tag
|
|
11245
12197
|
[type]="filter.removable ? 'removable' : 'informative'"
|
|
11246
12198
|
size="s"
|
|
11247
|
-
[id]="'filter-' + filter.
|
|
11248
|
-
(removeTag)="onRemoveFilter(filter.
|
|
12199
|
+
[id]="'filter-' + filter.id"
|
|
12200
|
+
(removeTag)="onRemoveFilter(filter.id)"
|
|
11249
12201
|
>{{ filter.label }}</moz-tag
|
|
11250
12202
|
>
|
|
11251
12203
|
}
|
|
@@ -11287,6 +12239,25 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
|
|
|
11287
12239
|
(rowSelectionToggle)="onRowSelectionToggle()"
|
|
11288
12240
|
/>
|
|
11289
12241
|
|
|
12242
|
+
<!-- Empty state overlay (consumer template wins, fallback default) -->
|
|
12243
|
+
@if (emptyStateKind() !== 'none') {
|
|
12244
|
+
<div class="moz-grid__empty-overlay">
|
|
12245
|
+
@if (emptyTemplate(); as tpl) {
|
|
12246
|
+
<ng-container *ngTemplateOutlet="tpl; context: emptyTemplateContext()" />
|
|
12247
|
+
} @else {
|
|
12248
|
+
<moz-grid-empty-state
|
|
12249
|
+
[kind]="$any(emptyStateKind())"
|
|
12250
|
+
[title]="emptyStateKind() === 'no-results' ? noResultsTitle() : emptyDataTitle()"
|
|
12251
|
+
[description]="
|
|
12252
|
+
emptyStateKind() === 'no-results' ? noResultsDescription() : emptyDataDescription()
|
|
12253
|
+
"
|
|
12254
|
+
[actionLabel]="emptyStateKind() === 'no-results' ? resolvedNoResultsActionLabel() : ''"
|
|
12255
|
+
(action)="onRemoveAllFilters()"
|
|
12256
|
+
/>
|
|
12257
|
+
}
|
|
12258
|
+
</div>
|
|
12259
|
+
}
|
|
12260
|
+
|
|
11290
12261
|
<!-- Footer: pagination or infinite scroll loading indicator -->
|
|
11291
12262
|
@if (showPagination()) {
|
|
11292
12263
|
<moz-grid-footer
|
|
@@ -11307,8 +12278,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
|
|
|
11307
12278
|
/>
|
|
11308
12279
|
</div>
|
|
11309
12280
|
</div>
|
|
11310
|
-
`, styles: [":host{display:block;height:100%}.moz-grid-wrapper{display:flex;flex-direction:column;font-family:var(--font-family-primary);height:100%;min-height:0;gap:16px}.moz-grid-wrapper--fullscreen{position:fixed;top:0;left:0;width:100vw;height:100vh;z-index:9999;background:var(--color-background-primary)}.moz-grid{display:flex;flex-direction:column;border-radius:var(--border-radius-l);overflow:hidden;background:var(--color-background-primary);flex:1;min-height:0;position:relative;box-shadow:0 0 6px #cdd4d8}.moz-grid:focus{outline:none}.moz-grid--loading{opacity:.6;pointer-events:none}.moz-grid__toolbar{display:flex;align-items:center;justify-content:space-between;flex-shrink:0;min-height:48px;gap:var(--spacing-s, 8px)}.moz-grid__toolbar-left,.moz-grid__toolbar-right{display:flex;align-items:center;gap:var(--spacing-xs, 4px)}.moz-grid__selection-banner{display:flex;align-items:center;gap:var(--spacing-s, 8px);flex:1;justify-content:center;border-radius:var(--border-radius-s);border:1px solid var(--Border-Primary, #cdd4d8);background:var(--Neutral-Grey-000, #fff)}.moz-grid__selection-text{font-size:var(--font-size-s, 14px);color:var(--color-text-primary);white-space:nowrap}.moz-grid__selection-link{padding:0;border:none;background:transparent;color:var(--color-background-accent-inverse);font-size:var(--font-size-s, 14px);font-weight:600;cursor:pointer;white-space:nowrap;text-decoration:underline}.moz-grid__selection-link:hover{color:var(--color-primary-dark, #1557b0)}.moz-grid__tag-bar{display:flex;align-items:center;flex-wrap:wrap;gap:var(--spacing-xs, 4px);padding:var(--spacing-xxs, 2px) var(--spacing-s, 8px);flex-shrink:0}.moz-grid__tag-bar-label{width:100%;font-size:var(--font-size-xs, 12px);text-transform:uppercase;white-space:nowrap;color:var(--text-icon-tertiary);font-size:var(--Typography-Font-size-Body-XS, 12px);font-weight:400}.moz-grid__tag-action-btn{padding:2px 8px;border:none;background:transparent;color:var(--color-background-accent-inverse);font-size:var(--font-size-xs, 12px);font-weight:600;cursor:pointer}.moz-grid__tag-action-btn:hover{text-decoration:underline}.moz-grid__group-tag-btn{display:inline-flex;align-items:center;gap:2px;padding:0;border:none;background:transparent;cursor:pointer;font:inherit;color:inherit;line-height:1}.moz-grid__group-tag-btn ::ng-deep svg{fill:#fff!important;width:16px;height:16px}\n"] }]
|
|
11311
|
-
}], ctorParameters: () => [], propDecorators: { gridBody: [{ type: i0.ViewChild, args: [i0.forwardRef(() => MozGridBodyComponent), { isSignal: true }] }], gridContainer: [{ type: i0.ViewChild, args: ['gridContainer', { isSignal: true }] }], columnDefs: [{ type: i0.ContentChildren, args: [i0.forwardRef(() => MozGridColumnDef), { isSignal: true }] }], toolbarDefs: [{ type: i0.ContentChildren, args: [i0.forwardRef(() => MozGridToolbarDef), { isSignal: true }] }], data: [{ type: i0.Input, args: [{ isSignal: true, alias: "data", required: false }] }], mode: [{ type: i0.Input, args: [{ isSignal: true, alias: "mode", required: false }] }], totalItems: [{ type: i0.Input, args: [{ isSignal: true, alias: "totalItems", required: false }] }], pagination: [{ type: i0.Input, args: [{ isSignal: true, alias: "pagination", required: false }] }], pageSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "pageSize", required: false }] }], pageSizeOptions: [{ type: i0.Input, args: [{ isSignal: true, alias: "pageSizeOptions", required: false }] }], rowHeight: [{ type: i0.Input, args: [{ isSignal: true, alias: "rowHeight", required: false }] }], loading: [{ type: i0.Input, args: [{ isSignal: true, alias: "loading", required: false }] }], rowSelection: [{ type: i0.Input, args: [{ isSignal: true, alias: "rowSelection", required: false }] }], expandable: [{ type: i0.Input, args: [{ isSignal: true, alias: "expandable", required: false }] }], rowIdField: [{ type: i0.Input, args: [{ isSignal: true, alias: "rowIdField", required: false }] }], detailTemplate: [{ type: i0.Input, args: [{ isSignal: true, alias: "detailTemplate", required: false }] }], fullscreen: [{ type: i0.Input, args: [{ isSignal: true, alias: "fullscreen", required: false }] }], reorderable: [{ type: i0.Input, args: [{ isSignal: true, alias: "reorderable", required: false }] }], stateKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "stateKey", required: false }] }], exportable: [{ type: i0.Input, args: [{ isSignal: true, alias: "exportable", required: false }] }], horizontalVirtualScroll: [{ type: i0.Input, args: [{ isSignal: true, alias: "horizontalVirtualScroll", required: false }] }], loadingStrategy: [{ type: i0.Input, args: [{ isSignal: true, alias: "loadingStrategy", required: false }] }], scrollThreshold: [{ type: i0.Input, args: [{ isSignal: true, alias: "scrollThreshold", required: false }] }], plugins: [{ type: i0.Input, args: [{ isSignal: true, alias: "plugins", required: false }] }], sortChange: [{ type: i0.Output, args: ["sortChange"] }], pageChange: [{ type: i0.Output, args: ["pageChange"] }], loadMore: [{ type: i0.Output, args: ["loadMore"] }], cellEdit: [{ type: i0.Output, args: ["cellEdit"] }], cellEditCancel: [{ type: i0.Output, args: ["cellEditCancel"] }], selectionChange: [{ type: i0.Output, args: ["selectionChange"] }], cellSelectionChange: [{ type: i0.Output, args: ["cellSelectionChange"] }], groupChange: [{ type: i0.Output, args: ["groupChange"] }], filterChange: [{ type: i0.Output, args: ["filterChange"] }], bulkEdit: [{ type: i0.Output, args: ["bulkEdit"] }], bulkCopy: [{ type: i0.Output, args: ["bulkCopy"] }], bulkPaste: [{ type: i0.Output, args: ["bulkPaste"] }], bulkDelete: [{ type: i0.Output, args: ["bulkDelete"] }], fillDown: [{ type: i0.Output, args: ["fillDown"] }], settingsChange: [{ type: i0.Output, args: ["settingsChange"] }] } });
|
|
12281
|
+
`, styles: [":host{display:block;height:100%}.moz-grid-wrapper{display:flex;flex-direction:column;font-family:var(--font-family-primary);height:100%;min-height:0;gap:16px}.moz-grid-wrapper--fullscreen{position:fixed;top:0;left:0;width:100vw;height:100vh;z-index:9999;background:var(--color-background-primary)}.moz-grid{display:flex;flex-direction:column;border-radius:var(--border-radius-l);overflow:hidden;background:var(--color-background-primary);flex:1;min-height:0;position:relative;box-shadow:0 0 6px #cdd4d8}.moz-grid__empty-overlay{position:absolute;inset:0;top:var(--moz-grid-header-height, 48px);display:flex;align-items:center;justify-content:center;background:var(--Background-Primary, #fff);z-index:1}.moz-grid:focus{outline:none}.moz-grid--loading{opacity:.6;pointer-events:none}.moz-grid__toolbar{display:flex;align-items:center;justify-content:space-between;flex-shrink:0;min-height:48px;gap:var(--spacing-s, 8px)}.moz-grid__toolbar-left,.moz-grid__toolbar-right{display:flex;align-items:center;gap:var(--spacing-xs, 4px)}.moz-grid__toolbar-filter-btn{display:inline-flex;align-items:center;gap:4px}.moz-grid__toolbar-filter-badge{display:inline-flex;align-items:center;justify-content:center;min-width:18px;height:18px;padding:0 6px;border-radius:9px;background:var(--Status-Standalone-element-Primary, #0071ce);color:#fff;font-size:11px;font-weight:600;line-height:1}.moz-grid__selection-banner{display:flex;align-items:center;gap:var(--spacing-s, 8px);flex:1;justify-content:center;border-radius:var(--border-radius-s);border:1px solid var(--Border-Primary, #cdd4d8);background:var(--Neutral-Grey-000, #fff)}.moz-grid__selection-text{font-size:var(--font-size-s, 14px);color:var(--color-text-primary);white-space:nowrap}.moz-grid__selection-link{padding:0;border:none;background:transparent;color:var(--color-background-accent-inverse);font-size:var(--font-size-s, 14px);font-weight:600;cursor:pointer;white-space:nowrap;text-decoration:underline}.moz-grid__selection-link:hover{color:var(--color-primary-dark, #1557b0)}.moz-grid__tag-bar{display:flex;align-items:center;flex-wrap:wrap;gap:var(--spacing-xs, 4px);padding:var(--spacing-xxs, 2px) var(--spacing-s, 8px);flex-shrink:0}.moz-grid__tag-bar-label{width:100%;font-size:var(--font-size-xs, 12px);text-transform:uppercase;white-space:nowrap;color:var(--text-icon-tertiary);font-size:var(--Typography-Font-size-Body-XS, 12px);font-weight:400}.moz-grid__tag-action-btn{padding:2px 8px;border:none;background:transparent;color:var(--color-background-accent-inverse);font-size:var(--font-size-xs, 12px);font-weight:600;cursor:pointer}.moz-grid__tag-action-btn:hover{text-decoration:underline}.moz-grid__group-tag-btn{display:inline-flex;align-items:center;gap:2px;padding:0;border:none;background:transparent;cursor:pointer;font:inherit;color:inherit;line-height:1}.moz-grid__group-tag-btn ::ng-deep svg{fill:#fff!important;width:16px;height:16px}\n"] }]
|
|
12282
|
+
}], ctorParameters: () => [], propDecorators: { gridBody: [{ type: i0.ViewChild, args: [i0.forwardRef(() => MozGridBodyComponent), { isSignal: true }] }], gridContainer: [{ type: i0.ViewChild, args: ['gridContainer', { isSignal: true }] }], columnDefs: [{ type: i0.ContentChildren, args: [i0.forwardRef(() => MozGridColumnDef), { isSignal: true }] }], toolbarDefs: [{ type: i0.ContentChildren, args: [i0.forwardRef(() => MozGridToolbarDef), { isSignal: true }] }], emptyDefs: [{ type: i0.ContentChildren, args: [i0.forwardRef(() => MozGridEmptyDef), { isSignal: true }] }], data: [{ type: i0.Input, args: [{ isSignal: true, alias: "data", required: false }] }], mode: [{ type: i0.Input, args: [{ isSignal: true, alias: "mode", required: false }] }], totalItems: [{ type: i0.Input, args: [{ isSignal: true, alias: "totalItems", required: false }] }], pagination: [{ type: i0.Input, args: [{ isSignal: true, alias: "pagination", required: false }] }], pageSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "pageSize", required: false }] }], pageSizeOptions: [{ type: i0.Input, args: [{ isSignal: true, alias: "pageSizeOptions", required: false }] }], rowHeight: [{ type: i0.Input, args: [{ isSignal: true, alias: "rowHeight", required: false }] }], loading: [{ type: i0.Input, args: [{ isSignal: true, alias: "loading", required: false }] }], rowSelection: [{ type: i0.Input, args: [{ isSignal: true, alias: "rowSelection", required: false }] }], expandable: [{ type: i0.Input, args: [{ isSignal: true, alias: "expandable", required: false }] }], rowIdField: [{ type: i0.Input, args: [{ isSignal: true, alias: "rowIdField", required: false }] }], detailTemplate: [{ type: i0.Input, args: [{ isSignal: true, alias: "detailTemplate", required: false }] }], fullscreen: [{ type: i0.Input, args: [{ isSignal: true, alias: "fullscreen", required: false }] }], reorderable: [{ type: i0.Input, args: [{ isSignal: true, alias: "reorderable", required: false }] }], stateKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "stateKey", required: false }] }], emptyDataTitle: [{ type: i0.Input, args: [{ isSignal: true, alias: "emptyDataTitle", required: false }] }], emptyDataDescription: [{ type: i0.Input, args: [{ isSignal: true, alias: "emptyDataDescription", required: false }] }], noResultsTitle: [{ type: i0.Input, args: [{ isSignal: true, alias: "noResultsTitle", required: false }] }], noResultsDescription: [{ type: i0.Input, args: [{ isSignal: true, alias: "noResultsDescription", required: false }] }], noResultsActionLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "noResultsActionLabel", required: false }] }], exportable: [{ type: i0.Input, args: [{ isSignal: true, alias: "exportable", required: false }] }], horizontalVirtualScroll: [{ type: i0.Input, args: [{ isSignal: true, alias: "horizontalVirtualScroll", required: false }] }], loadingStrategy: [{ type: i0.Input, args: [{ isSignal: true, alias: "loadingStrategy", required: false }] }], scrollThreshold: [{ type: i0.Input, args: [{ isSignal: true, alias: "scrollThreshold", required: false }] }], plugins: [{ type: i0.Input, args: [{ isSignal: true, alias: "plugins", required: false }] }], sortChange: [{ type: i0.Output, args: ["sortChange"] }], pageChange: [{ type: i0.Output, args: ["pageChange"] }], loadMore: [{ type: i0.Output, args: ["loadMore"] }], cellEdit: [{ type: i0.Output, args: ["cellEdit"] }], cellEditCancel: [{ type: i0.Output, args: ["cellEditCancel"] }], selectionChange: [{ type: i0.Output, args: ["selectionChange"] }], cellSelectionChange: [{ type: i0.Output, args: ["cellSelectionChange"] }], groupChange: [{ type: i0.Output, args: ["groupChange"] }], filterChange: [{ type: i0.Output, args: ["filterChange"] }], bulkEdit: [{ type: i0.Output, args: ["bulkEdit"] }], bulkCopy: [{ type: i0.Output, args: ["bulkCopy"] }], bulkPaste: [{ type: i0.Output, args: ["bulkPaste"] }], bulkDelete: [{ type: i0.Output, args: ["bulkDelete"] }], fillDown: [{ type: i0.Output, args: ["fillDown"] }], settingsChange: [{ type: i0.Output, args: ["settingsChange"] }], filterApplyMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "filterApplyMode", required: false }] }] } });
|
|
11312
12283
|
|
|
11313
12284
|
const DEFAULT_GRID_OPTIONS = {
|
|
11314
12285
|
mode: 'client',
|
|
@@ -12924,5 +13895,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
|
|
|
12924
13895
|
* Generated bundle index. Do not edit.
|
|
12925
13896
|
*/
|
|
12926
13897
|
|
|
12927
|
-
export { ACTION_LISTBOX_CONFIG, ActionListboxContainerComponent, ActionListboxRef, BuiltInMenuComponent, CellSelectionEngine, CellValidationEngine, ColumnReorderEngine, ColumnResizeEngine, DEFAULT_ACTION_LISTBOX_CONFIG, DEFAULT_GRID_OPTIONS, DEFAULT_MODAL_CONFIG, DEFAULT_TOASTER_CONFIG, DRAWER_CONFIG, DRAWER_DATA, DrawerContainerComponent, ExpandableRowEngine, ExportEngine, FilterEngine, GridEngine, GridGroupDrawerComponent, GridSettingsDrawerComponent, GridStateManager, GroupEngine, HorizontalVirtualScrollEngine, InfiniteScrollEngine, InlineEditEngine, KeyboardEngine, MODAL_CONFIG, MODAL_DATA, MozAccordionComponent, MozAccordionContentComponent, MozAccordionHeaderComponent, MozAccordionPanelComponent, MozActionBottomBarComponent, MozActionListboxComponent, MozActionListboxTriggerDirective, MozAvatarComponent, MozBreadcrumbComponent, MozButtonComponent, MozCalloutComponent, MozCarouselComponent, MozCheckListMenuComponent, MozCheckboxComponent, MozCheckboxGroupComponent, MozCircularProgressBarComponent, MozComboboxComponent, MozComboboxHarness, MozComboboxOptionHarness, MozDatepickerComponent, MozDividerComponent, MozDrawerComponent, MozDrawerFooterDirective, MozDrawerRef, MozDrawerService, MozFieldComponent, MozFieldGroupComponent, MozFileUploaderComponent, MozFileUploaderItemComponent, MozFlagComponent, MozGridBodyComponent, MozGridCellComponent, MozGridColumnDef, MozGridColumnVisibilityPanelComponent, MozGridComponent, MozGridDetailRowComponent, MozGridFooterComponent, MozGridGroupRowComponent, MozGridHeaderCellComponent, MozGridHeaderComponent, MozGridHeaderMenuComponent, MozGridLoadingIndicatorComponent, MozGridRowComponent, MozGridToolbarDef, MozIconButtonComponent, MozKpiComponent, MozLinearProgressBarBufferComponent, MozLinearProgressBarPercentageComponent, MozLinkComponent, MozLoaderComponent, MozLoadingOverlayComponent, MozModalComponent, MozModalFooterDirective, MozModalRef, MozModalService, MozNavigationIndicatorComponent, MozNumberBadgeComponent, MozOverlayComponent, MozPageHeaderComponent, MozPaginationComponent, MozPasswordInputDirective, MozPhoneNumberComponent, MozPincodeInputComponent, MozPopoverComponent, MozPopoverFooterDirective, MozPopoverTriggerDirective, MozQuantitySelectorComponent, MozRadioComponent, MozRadioGroupComponent, MozSegmentedControlComponent, MozSelectComponent, MozSidebarComponent, MozStarRatingComponent, MozStatusBadgeComponent, MozStatusDotComponent, MozStatusMessageComponent, MozStatusNotificationComponent, MozStepperBottomBarComponent, MozStepperCompactComponent, MozStepperInlineComponent, MozStepperStackedComponent, MozTabComponent, MozTabsComponent, MozTagComponent, MozTextInput, MozTextarea, MozTileComponent, MozTileExpandableComponent, MozTileSelectableComponent, MozToasterComponent, MozToasterRef, MozToasterService, MozToggleComponent, MozTooltipComponent, MozTooltipDirective, MozTreeComponent, MozTreeNodeComponent, MozTreeNodeTemplateDirective, POPOVER_CONFIG, POPOVER_DATA, PaginationEngine, PopoverContainerComponent, PopoverRef, PopoverService, RowSelectionEngine, SortEngine, StatePersistenceEngine, TOASTER_CONFIG, TreeEngine, TreeKeyboardService, TreeSelectionService, TreeStateService, isSection, trackByField, trackDisplayRow };
|
|
13898
|
+
export { ACTION_LISTBOX_CONFIG, ActionListboxContainerComponent, ActionListboxRef, BuiltInMenuComponent, CellSelectionEngine, CellValidationEngine, ColumnReorderEngine, ColumnResizeEngine, DEFAULT_ACTION_LISTBOX_CONFIG, DEFAULT_GRID_OPTIONS, DEFAULT_MODAL_CONFIG, DEFAULT_TOASTER_CONFIG, DRAWER_CONFIG, DRAWER_DATA, DrawerContainerComponent, ExpandableRowEngine, ExportEngine, FilterEngine, GridEngine, GridGroupDrawerComponent, GridSettingsDrawerComponent, GridStateManager, GroupEngine, HorizontalVirtualScrollEngine, InfiniteScrollEngine, InlineEditEngine, KeyboardEngine, MODAL_CONFIG, MODAL_DATA, MozAccordionComponent, MozAccordionContentComponent, MozAccordionHeaderComponent, MozAccordionPanelComponent, MozActionBottomBarComponent, MozActionListboxComponent, MozActionListboxTriggerDirective, MozAvatarComponent, MozBreadcrumbComponent, MozButtonComponent, MozCalloutComponent, MozCarouselComponent, MozCheckListMenuComponent, MozCheckboxComponent, MozCheckboxGroupComponent, MozCircularProgressBarComponent, MozComboboxComponent, MozComboboxHarness, MozComboboxOptionHarness, MozDatepickerComponent, MozDividerComponent, MozDrawerComponent, MozDrawerFooterDirective, MozDrawerRef, MozDrawerService, MozFieldComponent, MozFieldGroupComponent, MozFileUploaderComponent, MozFileUploaderItemComponent, MozFlagComponent, MozGridBodyComponent, MozGridCellComponent, MozGridColumnDef, MozGridColumnVisibilityPanelComponent, MozGridComponent, MozGridDetailRowComponent, MozGridEmptyDef, MozGridFooterComponent, MozGridGroupRowComponent, MozGridHeaderCellComponent, MozGridHeaderComponent, MozGridHeaderMenuComponent, MozGridLoadingIndicatorComponent, MozGridRowComponent, MozGridToolbarDef, MozIconButtonComponent, MozKpiComponent, MozLinearProgressBarBufferComponent, MozLinearProgressBarPercentageComponent, MozLinkComponent, MozLoaderComponent, MozLoadingOverlayComponent, MozModalComponent, MozModalFooterDirective, MozModalRef, MozModalService, MozNavigationIndicatorComponent, MozNumberBadgeComponent, MozOverlayComponent, MozPageHeaderComponent, MozPaginationComponent, MozPasswordInputDirective, MozPhoneNumberComponent, MozPincodeInputComponent, MozPopoverComponent, MozPopoverFooterDirective, MozPopoverTriggerDirective, MozQuantitySelectorComponent, MozRadioComponent, MozRadioGroupComponent, MozSegmentedControlComponent, MozSelectComponent, MozSidebarComponent, MozStarRatingComponent, MozStatusBadgeComponent, MozStatusDotComponent, MozStatusMessageComponent, MozStatusNotificationComponent, MozStepperBottomBarComponent, MozStepperCompactComponent, MozStepperInlineComponent, MozStepperStackedComponent, MozTabComponent, MozTabsComponent, MozTagComponent, MozTextInput, MozTextarea, MozTileComponent, MozTileExpandableComponent, MozTileSelectableComponent, MozToasterComponent, MozToasterRef, MozToasterService, MozToggleComponent, MozTooltipComponent, MozTooltipDirective, MozTreeComponent, MozTreeNodeComponent, MozTreeNodeTemplateDirective, POPOVER_CONFIG, POPOVER_DATA, PaginationEngine, PopoverContainerComponent, PopoverRef, PopoverService, RowSelectionEngine, SortEngine, StatePersistenceEngine, TOASTER_CONFIG, TreeEngine, TreeKeyboardService, TreeSelectionService, TreeStateService, isSection, trackByField, trackDisplayRow };
|
|
12928
13899
|
//# sourceMappingURL=mozaic-ds-angular.mjs.map
|