monkey-style-guide 21.2.11 → 21.2.13
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/assets/scss/partials/_breakpoints.scss +20 -4
- package/fesm2022/monkey-style-guide.mjs +934 -1979
- package/fesm2022/monkey-style-guide.mjs.map +1 -1
- package/monkey-style-guide-21.2.13.tgz +0 -0
- package/package.json +1 -1
- package/types/monkey-style-guide.d.ts +179 -430
- package/monkey-style-guide-21.2.11.tgz +0 -0
|
@@ -2,7 +2,7 @@ import { trigger, state, style, transition, animate, keyframes } from '@angular/
|
|
|
2
2
|
import * as i1 from '@angular/common';
|
|
3
3
|
import { CommonModule, NgTemplateOutlet, CurrencyPipe, AsyncPipe } from '@angular/common';
|
|
4
4
|
import * as i0 from '@angular/core';
|
|
5
|
-
import { Injectable, input, Component, TemplateRef, inject, booleanAttribute, Input, HostBinding, ViewEncapsulation, output, InjectionToken, EventEmitter, Output, ViewContainerRef, ElementRef, NgZone, DestroyRef, Optional, Inject, Directive, LOCALE_ID, signal, computed, HostListener, effect, ContentChildren, ChangeDetectorRef, DEFAULT_CURRENCY_CODE, ContentChild, NgModule, ViewChild, ChangeDetectionStrategy, Injector, forwardRef, viewChild,
|
|
5
|
+
import { Injectable, input, Component, TemplateRef, inject, booleanAttribute, Input, HostBinding, ViewEncapsulation, output, InjectionToken, EventEmitter, Output, ViewContainerRef, ElementRef, NgZone, DestroyRef, Optional, Inject, Directive, LOCALE_ID, signal, computed, HostListener, effect, ContentChildren, ChangeDetectorRef, DEFAULT_CURRENCY_CODE, ContentChild, NgModule, ViewChild, ChangeDetectionStrategy, Injector, forwardRef, viewChild, untracked, afterNextRender, ViewChildren, model, contentChild, contentChildren, DOCUMENT } from '@angular/core';
|
|
6
6
|
import { takeUntilDestroyed, toSignal } from '@angular/core/rxjs-interop';
|
|
7
7
|
import * as i1$1 from '@angular/forms';
|
|
8
8
|
import { Validators, NgControl, FormsModule, ReactiveFormsModule, FormControlDirective, NgModel, FormControlName, FormGroupDirective, NG_VALUE_ACCESSOR, NG_VALIDATORS } from '@angular/forms';
|
|
@@ -1325,6 +1325,42 @@ class MonkeyDictionaryService {
|
|
|
1325
1325
|
'NOT-SELECTABLE': 'Esta linha não pode ser selecionada'
|
|
1326
1326
|
}
|
|
1327
1327
|
},
|
|
1328
|
+
'FILTER-BAR': {
|
|
1329
|
+
ADD: 'Filtro',
|
|
1330
|
+
'ADD-ARIA': 'Adicionar filtro',
|
|
1331
|
+
REMOVE: 'Remover filtro',
|
|
1332
|
+
CLEAR: 'Limpar filtros',
|
|
1333
|
+
SEARCH: 'Buscar filtro',
|
|
1334
|
+
'SELECT-CONDITION': 'Selecione condição',
|
|
1335
|
+
SELECT: 'Selecione',
|
|
1336
|
+
CONFIRM: 'Confirmar',
|
|
1337
|
+
'RANGE-FROM': 'Valor inicial',
|
|
1338
|
+
'RANGE-TO': 'Valor final',
|
|
1339
|
+
SELECTED: '{count} selecionados',
|
|
1340
|
+
DATE: {
|
|
1341
|
+
'WEEK-AFTER': '1 semana a partir de hoje',
|
|
1342
|
+
'MONTH-AFTER': '1 mês a partir de hoje',
|
|
1343
|
+
'QUARTER-AFTER': '3 meses a partir de hoje',
|
|
1344
|
+
'WEEK-BEFORE': '1 semana antes de hoje',
|
|
1345
|
+
'MONTH-BEFORE': '1 mês antes de hoje',
|
|
1346
|
+
'QUARTER-BEFORE': '3 meses antes de hoje',
|
|
1347
|
+
CUSTOM: 'Personalizado'
|
|
1348
|
+
},
|
|
1349
|
+
OPERATOR: {
|
|
1350
|
+
EQ: 'É igual',
|
|
1351
|
+
NEQ: 'Não é igual',
|
|
1352
|
+
LIKE: 'Contém',
|
|
1353
|
+
NOT_LIKE: 'Não contém',
|
|
1354
|
+
STARTS_WITH: 'Começa com',
|
|
1355
|
+
ENDS_WITH: 'Termina com',
|
|
1356
|
+
IS_EMPTY: 'Vazio',
|
|
1357
|
+
BETWEEN: 'Entre',
|
|
1358
|
+
GT: 'Maior que',
|
|
1359
|
+
LT: 'Menor que',
|
|
1360
|
+
BEFORE: 'Antes de',
|
|
1361
|
+
AFTER: 'Depois de'
|
|
1362
|
+
}
|
|
1363
|
+
},
|
|
1328
1364
|
'DATE-RANGE': {
|
|
1329
1365
|
'START-DATE': 'Data de início',
|
|
1330
1366
|
'END-DATE': 'Data de término',
|
|
@@ -1398,6 +1434,42 @@ class MonkeyDictionaryService {
|
|
|
1398
1434
|
'NOT-SELECTABLE': 'Esta fila no se puede seleccionar'
|
|
1399
1435
|
}
|
|
1400
1436
|
},
|
|
1437
|
+
'FILTER-BAR': {
|
|
1438
|
+
ADD: 'Filtro',
|
|
1439
|
+
'ADD-ARIA': 'Agregar filtro',
|
|
1440
|
+
REMOVE: 'Eliminar filtro',
|
|
1441
|
+
CLEAR: 'Limpiar filtros',
|
|
1442
|
+
SEARCH: 'Buscar filtro',
|
|
1443
|
+
'SELECT-CONDITION': 'Seleccione condición',
|
|
1444
|
+
SELECT: 'Seleccione',
|
|
1445
|
+
CONFIRM: 'Confirmar',
|
|
1446
|
+
'RANGE-FROM': 'Valor inicial',
|
|
1447
|
+
'RANGE-TO': 'Valor final',
|
|
1448
|
+
SELECTED: '{count} seleccionados',
|
|
1449
|
+
DATE: {
|
|
1450
|
+
'WEEK-AFTER': '1 semana a partir de hoy',
|
|
1451
|
+
'MONTH-AFTER': '1 mes a partir de hoy',
|
|
1452
|
+
'QUARTER-AFTER': '3 meses a partir de hoy',
|
|
1453
|
+
'WEEK-BEFORE': '1 semana antes de hoy',
|
|
1454
|
+
'MONTH-BEFORE': '1 mes antes de hoy',
|
|
1455
|
+
'QUARTER-BEFORE': '3 meses antes de hoy',
|
|
1456
|
+
CUSTOM: 'Personalizado'
|
|
1457
|
+
},
|
|
1458
|
+
OPERATOR: {
|
|
1459
|
+
EQ: 'Es igual',
|
|
1460
|
+
NEQ: 'No es igual',
|
|
1461
|
+
LIKE: 'Contiene',
|
|
1462
|
+
NOT_LIKE: 'No contiene',
|
|
1463
|
+
STARTS_WITH: 'Empieza con',
|
|
1464
|
+
ENDS_WITH: 'Termina con',
|
|
1465
|
+
IS_EMPTY: 'Vacío',
|
|
1466
|
+
BETWEEN: 'Entre',
|
|
1467
|
+
GT: 'Mayor que',
|
|
1468
|
+
LT: 'Menor que',
|
|
1469
|
+
BEFORE: 'Antes de',
|
|
1470
|
+
AFTER: 'Después de'
|
|
1471
|
+
}
|
|
1472
|
+
},
|
|
1401
1473
|
'DATE-RANGE': {
|
|
1402
1474
|
'START-DATE': 'Fecha de inicio',
|
|
1403
1475
|
'END-DATE': 'Fecha de termino',
|
|
@@ -1471,6 +1543,42 @@ class MonkeyDictionaryService {
|
|
|
1471
1543
|
'NOT-SELECTABLE': 'Esta fila no se puede seleccionar'
|
|
1472
1544
|
}
|
|
1473
1545
|
},
|
|
1546
|
+
'FILTER-BAR': {
|
|
1547
|
+
ADD: 'Filtro',
|
|
1548
|
+
'ADD-ARIA': 'Agregar filtro',
|
|
1549
|
+
REMOVE: 'Eliminar filtro',
|
|
1550
|
+
CLEAR: 'Limpiar filtros',
|
|
1551
|
+
SEARCH: 'Buscar filtro',
|
|
1552
|
+
'SELECT-CONDITION': 'Seleccione condición',
|
|
1553
|
+
SELECT: 'Seleccione',
|
|
1554
|
+
CONFIRM: 'Confirmar',
|
|
1555
|
+
'RANGE-FROM': 'Valor inicial',
|
|
1556
|
+
'RANGE-TO': 'Valor final',
|
|
1557
|
+
SELECTED: '{count} seleccionados',
|
|
1558
|
+
DATE: {
|
|
1559
|
+
'WEEK-AFTER': '1 semana a partir de hoy',
|
|
1560
|
+
'MONTH-AFTER': '1 mes a partir de hoy',
|
|
1561
|
+
'QUARTER-AFTER': '3 meses a partir de hoy',
|
|
1562
|
+
'WEEK-BEFORE': '1 semana antes de hoy',
|
|
1563
|
+
'MONTH-BEFORE': '1 mes antes de hoy',
|
|
1564
|
+
'QUARTER-BEFORE': '3 meses antes de hoy',
|
|
1565
|
+
CUSTOM: 'Personalizado'
|
|
1566
|
+
},
|
|
1567
|
+
OPERATOR: {
|
|
1568
|
+
EQ: 'Es igual',
|
|
1569
|
+
NEQ: 'No es igual',
|
|
1570
|
+
LIKE: 'Contiene',
|
|
1571
|
+
NOT_LIKE: 'No contiene',
|
|
1572
|
+
STARTS_WITH: 'Empieza con',
|
|
1573
|
+
ENDS_WITH: 'Termina con',
|
|
1574
|
+
IS_EMPTY: 'Vacío',
|
|
1575
|
+
BETWEEN: 'Entre',
|
|
1576
|
+
GT: 'Mayor que',
|
|
1577
|
+
LT: 'Menor que',
|
|
1578
|
+
BEFORE: 'Antes de',
|
|
1579
|
+
AFTER: 'Después de'
|
|
1580
|
+
}
|
|
1581
|
+
},
|
|
1474
1582
|
'DATE-RANGE': {
|
|
1475
1583
|
'START-DATE': 'Fecha de inicio',
|
|
1476
1584
|
'END-DATE': 'Fecha de termino',
|
|
@@ -1544,6 +1652,42 @@ class MonkeyDictionaryService {
|
|
|
1544
1652
|
'NOT-SELECTABLE': 'This row cannot be selected'
|
|
1545
1653
|
}
|
|
1546
1654
|
},
|
|
1655
|
+
'FILTER-BAR': {
|
|
1656
|
+
ADD: 'Filter',
|
|
1657
|
+
'ADD-ARIA': 'Add filter',
|
|
1658
|
+
REMOVE: 'Remove filter',
|
|
1659
|
+
CLEAR: 'Clear filters',
|
|
1660
|
+
SEARCH: 'Search filter',
|
|
1661
|
+
'SELECT-CONDITION': 'Select condition',
|
|
1662
|
+
SELECT: 'Select',
|
|
1663
|
+
CONFIRM: 'Confirm',
|
|
1664
|
+
'RANGE-FROM': 'From',
|
|
1665
|
+
'RANGE-TO': 'To',
|
|
1666
|
+
SELECTED: '{count} selected',
|
|
1667
|
+
DATE: {
|
|
1668
|
+
'WEEK-AFTER': '1 week from today',
|
|
1669
|
+
'MONTH-AFTER': '1 month from today',
|
|
1670
|
+
'QUARTER-AFTER': '3 months from today',
|
|
1671
|
+
'WEEK-BEFORE': '1 week before today',
|
|
1672
|
+
'MONTH-BEFORE': '1 month before today',
|
|
1673
|
+
'QUARTER-BEFORE': '3 months before today',
|
|
1674
|
+
CUSTOM: 'Custom'
|
|
1675
|
+
},
|
|
1676
|
+
OPERATOR: {
|
|
1677
|
+
EQ: 'Is equal to',
|
|
1678
|
+
NEQ: 'Is not equal to',
|
|
1679
|
+
LIKE: 'Contains',
|
|
1680
|
+
NOT_LIKE: 'Does not contain',
|
|
1681
|
+
STARTS_WITH: 'Starts with',
|
|
1682
|
+
ENDS_WITH: 'Ends with',
|
|
1683
|
+
IS_EMPTY: 'Is empty',
|
|
1684
|
+
BETWEEN: 'Between',
|
|
1685
|
+
GT: 'Greater than',
|
|
1686
|
+
LT: 'Less than',
|
|
1687
|
+
BEFORE: 'Before',
|
|
1688
|
+
AFTER: 'After'
|
|
1689
|
+
}
|
|
1690
|
+
},
|
|
1547
1691
|
'DATE-RANGE': {
|
|
1548
1692
|
'START-DATE': 'Start date',
|
|
1549
1693
|
'END-DATE': 'End Date',
|
|
@@ -5644,1008 +5788,94 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImpor
|
|
|
5644
5788
|
* This style guide was developed by Monkey Exchange Team
|
|
5645
5789
|
* MIT Licence
|
|
5646
5790
|
************************* */
|
|
5647
|
-
class MonkeyRadioButtonComponent {
|
|
5648
|
-
get classes() {
|
|
5649
|
-
return `${this.position} ${this.size}`;
|
|
5650
|
-
}
|
|
5651
|
-
get disabled() {
|
|
5652
|
-
if (this.ngControl && this.ngControl.disabled !== null) {
|
|
5653
|
-
return this.ngControl.disabled;
|
|
5654
|
-
}
|
|
5655
|
-
return this._disabled;
|
|
5656
|
-
}
|
|
5657
|
-
set disabled(value) {
|
|
5658
|
-
this._disabled = value;
|
|
5659
|
-
if (this.focused) {
|
|
5660
|
-
this.focused = false;
|
|
5661
|
-
this.stateChanges.next();
|
|
5662
|
-
}
|
|
5663
|
-
}
|
|
5664
|
-
get required() {
|
|
5665
|
-
return this._required ?? this.ngControl?.control?.hasValidator(Validators.required) ?? false;
|
|
5666
|
-
}
|
|
5667
|
-
set required(value) {
|
|
5668
|
-
this._required = value;
|
|
5669
|
-
this.stateChanges.next();
|
|
5670
|
-
}
|
|
5671
|
-
set value(value) {
|
|
5672
|
-
if (this._value !== value) {
|
|
5673
|
-
this._value = value;
|
|
5674
|
-
this._onChange(value);
|
|
5675
|
-
}
|
|
5676
|
-
}
|
|
5677
|
-
get value() {
|
|
5678
|
-
return this._value;
|
|
5679
|
-
}
|
|
5680
|
-
constructor(changeDetectorRef, formField) {
|
|
5681
|
-
this.changeDetectorRef = changeDetectorRef;
|
|
5682
|
-
this.formField = formField;
|
|
5683
|
-
this.tabIndex = 0;
|
|
5684
|
-
this.onChange = new EventEmitter();
|
|
5685
|
-
this.onSearch = new EventEmitter();
|
|
5686
|
-
this.position = 'horizontal';
|
|
5687
|
-
this.size = 'lg';
|
|
5688
|
-
this._value = null;
|
|
5689
|
-
this._destroyRef = inject(DestroyRef);
|
|
5690
|
-
this.idGenerator = inject(IdGenerator);
|
|
5691
|
-
this.ngControl = inject(NgControl, { self: true, optional: true });
|
|
5692
|
-
this._elementRef = inject(ElementRef);
|
|
5693
|
-
this.focused = false;
|
|
5694
|
-
this._disabled = false;
|
|
5695
|
-
this.id = this.idGenerator.getId('monkey-radiobutton-');
|
|
5696
|
-
this.stateChanges = new Subject();
|
|
5697
|
-
this.type = 'radio-button';
|
|
5698
|
-
this._onChange = () => { };
|
|
5699
|
-
this._onTouched = () => { };
|
|
5700
|
-
if (this.ngControl) {
|
|
5701
|
-
this.ngControl.valueAccessor = this;
|
|
5702
|
-
}
|
|
5703
|
-
}
|
|
5704
|
-
changeSelected() {
|
|
5705
|
-
setTimeout(() => {
|
|
5706
|
-
if (this.options) {
|
|
5707
|
-
this.options.forEach((opt) => {
|
|
5708
|
-
opt.onSelect(opt.value() === this.value);
|
|
5709
|
-
});
|
|
5710
|
-
}
|
|
5711
|
-
this.changeDetectorRef.markForCheck();
|
|
5712
|
-
});
|
|
5713
|
-
}
|
|
5714
|
-
initializeOptions() {
|
|
5715
|
-
setTimeout(() => {
|
|
5716
|
-
this.options?.forEach((option) => {
|
|
5717
|
-
option.type = 'radio';
|
|
5718
|
-
if (!option.action) {
|
|
5719
|
-
option.action = this.selectOption.bind(this, option);
|
|
5720
|
-
}
|
|
5721
|
-
});
|
|
5722
|
-
this.changeDetectorRef.markForCheck();
|
|
5723
|
-
}, 0);
|
|
5724
|
-
}
|
|
5725
|
-
ngAfterContentInit() {
|
|
5726
|
-
this.initializeOptions();
|
|
5727
|
-
this.options.changes.pipe(takeUntilDestroyed(this._destroyRef)).subscribe(() => {
|
|
5728
|
-
this.initializeOptions();
|
|
5729
|
-
this.changeSelected();
|
|
5730
|
-
});
|
|
5731
|
-
}
|
|
5732
|
-
selectOption(option) {
|
|
5733
|
-
if (!option.disabled && !this.disabled) {
|
|
5734
|
-
this.value = option.value();
|
|
5735
|
-
this._onChange(this.value);
|
|
5736
|
-
this.onChange.emit(this.value);
|
|
5737
|
-
this.options.forEach((opt) => {
|
|
5738
|
-
opt.onSelect(opt.value() === this.value);
|
|
5739
|
-
});
|
|
5740
|
-
}
|
|
5741
|
-
}
|
|
5742
|
-
writeValue(value) {
|
|
5743
|
-
this.value = value;
|
|
5744
|
-
this.changeSelected();
|
|
5745
|
-
}
|
|
5746
|
-
onContainerClick(event) {
|
|
5747
|
-
if (this.disabled)
|
|
5748
|
-
return;
|
|
5749
|
-
this._elementRef.nativeElement.focus();
|
|
5750
|
-
}
|
|
5751
|
-
_onFocus() {
|
|
5752
|
-
if (!this.disabled) {
|
|
5753
|
-
this.focused = true;
|
|
5754
|
-
this._onTouched();
|
|
5755
|
-
this.stateChanges.next();
|
|
5756
|
-
}
|
|
5757
|
-
}
|
|
5758
|
-
_onBlur() {
|
|
5759
|
-
this.focused = false;
|
|
5760
|
-
this.stateChanges.next();
|
|
5761
|
-
}
|
|
5762
|
-
registerOnChange(fn) {
|
|
5763
|
-
this._onChange = fn;
|
|
5764
|
-
}
|
|
5765
|
-
registerOnTouched(fn) {
|
|
5766
|
-
this._onTouched = fn;
|
|
5767
|
-
}
|
|
5768
|
-
setDisabledState(isDisabled) {
|
|
5769
|
-
this.disabled = isDisabled;
|
|
5770
|
-
this.initializeOptions();
|
|
5771
|
-
}
|
|
5772
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: MonkeyRadioButtonComponent, deps: [{ token: i0.ChangeDetectorRef }, { token: MonkeyFormFieldComponent, optional: true }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
5773
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "16.1.0", version: "21.2.4", type: MonkeyRadioButtonComponent, isStandalone: true, selector: "monkey-radiobutton", inputs: { tabIndex: "tabIndex", position: "position", size: "size", disabled: ["disabled", "disabled", booleanAttribute], required: ["required", "required", booleanAttribute], value: "value" }, outputs: { onChange: "onChange", onSearch: "onSearch" }, host: { attributes: { "data-testid": "monkey-radiobutton" }, listeners: { "focus": "_onFocus()", "blur": "_onBlur()" }, properties: { "class.mecx-disabled": "disabled", "class.mecx-radiobutton-focused": "focused", "attr.id": "id", "attr.tabindex": "disabled ? -1 : tabIndex", "class": "this.classes" }, classAttribute: "mecx-radiobutton" }, providers: [
|
|
5774
|
-
// eslint-disable-next-line no-use-before-define
|
|
5775
|
-
{ provide: MonkeyFormFieldControl, useExisting: MonkeyRadioButtonComponent }
|
|
5776
|
-
], queries: [{ propertyName: "options", predicate: MonkeyOptionComponent }], ngImport: i0, template: "<ng-content />\r\n", styles: ["monkey-radiobutton{display:inline-flex;width:100%;min-width:0;position:relative;flex-wrap:wrap}monkey-radiobutton:focus-visible,monkey-radiobutton:focus{outline:none}monkey-radiobutton.vertical{flex-direction:column}monkey-radiobutton monkey-option{transition:none!important}monkey-radiobutton.mecx-disabled monkey-option{opacity:.5;pointer-events:none}monkey-radiobutton.mecx-disabled monkey-option:before{background:var(--mecx-color-white);border-color:var(--mecx-color-gray-400)}monkey-radiobutton.mecx-form-field-invalid{background:var(--mecx-color-error-700)}monkey-radiobutton.md monkey-option:before{width:16px;height:16px}monkey-radiobutton.sm monkey-option:before{width:14px;height:14px}\n"], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "ngmodule", type: FormsModule }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
|
|
5777
|
-
}
|
|
5778
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: MonkeyRadioButtonComponent, decorators: [{
|
|
5779
|
-
type: Component,
|
|
5780
|
-
args: [{ selector: 'monkey-radiobutton', imports: [ReactiveFormsModule, FormsModule], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, providers: [
|
|
5781
|
-
// eslint-disable-next-line no-use-before-define
|
|
5782
|
-
{ provide: MonkeyFormFieldControl, useExisting: MonkeyRadioButtonComponent }
|
|
5783
|
-
], host: {
|
|
5784
|
-
'data-testid': 'monkey-radiobutton',
|
|
5785
|
-
class: 'mecx-radiobutton',
|
|
5786
|
-
'[class.mecx-disabled]': 'disabled',
|
|
5787
|
-
'[class.mecx-radiobutton-focused]': 'focused',
|
|
5788
|
-
'[attr.id]': 'id',
|
|
5789
|
-
'[attr.tabindex]': 'disabled ? -1 : tabIndex',
|
|
5790
|
-
'(focus)': '_onFocus()',
|
|
5791
|
-
'(blur)': '_onBlur()'
|
|
5792
|
-
}, template: "<ng-content />\r\n", styles: ["monkey-radiobutton{display:inline-flex;width:100%;min-width:0;position:relative;flex-wrap:wrap}monkey-radiobutton:focus-visible,monkey-radiobutton:focus{outline:none}monkey-radiobutton.vertical{flex-direction:column}monkey-radiobutton monkey-option{transition:none!important}monkey-radiobutton.mecx-disabled monkey-option{opacity:.5;pointer-events:none}monkey-radiobutton.mecx-disabled monkey-option:before{background:var(--mecx-color-white);border-color:var(--mecx-color-gray-400)}monkey-radiobutton.mecx-form-field-invalid{background:var(--mecx-color-error-700)}monkey-radiobutton.md monkey-option:before{width:16px;height:16px}monkey-radiobutton.sm monkey-option:before{width:14px;height:14px}\n"] }]
|
|
5793
|
-
}], ctorParameters: () => [{ type: i0.ChangeDetectorRef }, { type: MonkeyFormFieldComponent, decorators: [{
|
|
5794
|
-
type: Optional
|
|
5795
|
-
}] }], propDecorators: { options: [{
|
|
5796
|
-
type: ContentChildren,
|
|
5797
|
-
args: [MonkeyOptionComponent]
|
|
5798
|
-
}], tabIndex: [{
|
|
5799
|
-
type: Input
|
|
5800
|
-
}], onChange: [{
|
|
5801
|
-
type: Output
|
|
5802
|
-
}], onSearch: [{
|
|
5803
|
-
type: Output
|
|
5804
|
-
}], position: [{
|
|
5805
|
-
type: Input
|
|
5806
|
-
}], size: [{
|
|
5807
|
-
type: Input
|
|
5808
|
-
}], classes: [{
|
|
5809
|
-
type: HostBinding,
|
|
5810
|
-
args: ['class']
|
|
5811
|
-
}], disabled: [{
|
|
5812
|
-
type: Input,
|
|
5813
|
-
args: [{ transform: booleanAttribute }]
|
|
5814
|
-
}], required: [{
|
|
5815
|
-
type: Input,
|
|
5816
|
-
args: [{ transform: booleanAttribute }]
|
|
5817
|
-
}], value: [{
|
|
5818
|
-
type: Input
|
|
5819
|
-
}] } });
|
|
5820
5791
|
|
|
5821
5792
|
/** ************************
|
|
5822
5793
|
* Copyright Monkey Exchange. All Rights Reserved
|
|
5823
5794
|
* This style guide was developed by Monkey Exchange Team
|
|
5824
5795
|
* MIT Licence
|
|
5825
5796
|
************************* */
|
|
5797
|
+
const CONDITIONS = {
|
|
5798
|
+
text: ['LIKE', 'NOT_LIKE', 'STARTS_WITH', 'ENDS_WITH', 'IS_EMPTY'],
|
|
5799
|
+
currency: ['EQ', 'NEQ', 'BETWEEN', 'GT', 'LT'],
|
|
5800
|
+
date: ['EQ', 'NEQ', 'BETWEEN', 'BEFORE', 'AFTER'],
|
|
5801
|
+
status: ['EQ', 'NEQ']
|
|
5802
|
+
};
|
|
5803
|
+
const NO_OPERAND = new Set(['IS_EMPTY']);
|
|
5804
|
+
const TWO_OPERANDS = new Set(['BETWEEN']);
|
|
5805
|
+
function conditionsOf(type) {
|
|
5806
|
+
return CONDITIONS[type] ?? [];
|
|
5807
|
+
}
|
|
5808
|
+
function arityOf(condition) {
|
|
5809
|
+
if (NO_OPERAND.has(condition))
|
|
5810
|
+
return 0;
|
|
5811
|
+
if (TWO_OPERANDS.has(condition))
|
|
5812
|
+
return 2;
|
|
5813
|
+
return 1;
|
|
5814
|
+
}
|
|
5815
|
+
function panelOf(type, condition) {
|
|
5816
|
+
if (!condition || arityOf(condition) === 0)
|
|
5817
|
+
return 'none';
|
|
5818
|
+
switch (type) {
|
|
5819
|
+
case 'status':
|
|
5820
|
+
return 'status';
|
|
5821
|
+
case 'date':
|
|
5822
|
+
return arityOf(condition) === 2 ? 'date-range' : 'date-day';
|
|
5823
|
+
default:
|
|
5824
|
+
return 'field';
|
|
5825
|
+
}
|
|
5826
|
+
}
|
|
5827
|
+
function isComplete(row) {
|
|
5828
|
+
return !!row.condition && row.operands.length === arityOf(row.condition);
|
|
5829
|
+
}
|
|
5830
|
+
function appliedFrom(rows) {
|
|
5831
|
+
return rows.filter(isComplete).map((row) => {
|
|
5832
|
+
return {
|
|
5833
|
+
key: row.key,
|
|
5834
|
+
label: row.label,
|
|
5835
|
+
type: row.type,
|
|
5836
|
+
condition: row.condition,
|
|
5837
|
+
operands: row.operands
|
|
5838
|
+
};
|
|
5839
|
+
});
|
|
5840
|
+
}
|
|
5841
|
+
function withCondition(row, condition) {
|
|
5842
|
+
const sameArity = arityOf(row.condition) === arityOf(condition);
|
|
5843
|
+
if (sameArity)
|
|
5844
|
+
return { ...row, condition };
|
|
5845
|
+
return { ...row, condition, operands: [] };
|
|
5846
|
+
}
|
|
5847
|
+
function withType(row, next) {
|
|
5848
|
+
const condition = conditionsOf(next.type).includes(row.condition)
|
|
5849
|
+
? row.condition
|
|
5850
|
+
: '';
|
|
5851
|
+
return { ...next, condition, operands: [] };
|
|
5852
|
+
}
|
|
5826
5853
|
|
|
5827
5854
|
/** ************************
|
|
5828
5855
|
* Copyright Monkey Exchange. All Rights Reserved
|
|
5829
5856
|
* This style guide was developed by Monkey Exchange Team
|
|
5830
5857
|
* MIT Licence
|
|
5831
5858
|
************************* */
|
|
5832
|
-
|
|
5833
|
-
|
|
5834
|
-
|
|
5835
|
-
|
|
5836
|
-
|
|
5837
|
-
|
|
5838
|
-
|
|
5839
|
-
|
|
5840
|
-
|
|
5841
|
-
|
|
5842
|
-
|
|
5843
|
-
|
|
5844
|
-
|
|
5845
|
-
|
|
5846
|
-
|
|
5847
|
-
|
|
5848
|
-
|
|
5849
|
-
|
|
5850
|
-
|
|
5851
|
-
|
|
5852
|
-
this.dateRange = { startDate: '', endDate: '' };
|
|
5853
|
-
this.showCustomDate = false;
|
|
5854
|
-
this.serviceConfig = computed(() => {
|
|
5855
|
-
const k = this.key();
|
|
5856
|
-
return k ? this._service.getConfig(k) ?? this.config() : undefined;
|
|
5857
|
-
}, ...(ngDevMode ? [{ debugName: "serviceConfig" }] : /* istanbul ignore next */ []));
|
|
5858
|
-
this.activeFilters = computed(() => {
|
|
5859
|
-
const k = this.key();
|
|
5860
|
-
return k ? this._service.getActiveFilters(k) : [];
|
|
5861
|
-
}, ...(ngDevMode ? [{ debugName: "activeFilters" }] : /* istanbul ignore next */ []));
|
|
5862
|
-
this.searchValue = computed(() => {
|
|
5863
|
-
const k = this.key();
|
|
5864
|
-
return k ? this._service.getSearchValue(k) : '';
|
|
5865
|
-
}, ...(ngDevMode ? [{ debugName: "searchValue" }] : /* istanbul ignore next */ []));
|
|
5866
|
-
this.searchPlaceholder = computed(() => this.serviceConfig()?.searchPlaceholder ?? 'Pesquisar...', ...(ngDevMode ? [{ debugName: "searchPlaceholder" }] : /* istanbul ignore next */ []));
|
|
5867
|
-
this.closeFilterMenu = () => {
|
|
5868
|
-
this.showFilterMenu = false;
|
|
5869
|
-
};
|
|
5870
|
-
this.closeDateSubmenu = () => {
|
|
5871
|
-
this.showDateSubmenu = false;
|
|
5872
|
-
};
|
|
5873
|
-
this.closeFilterInput = () => {
|
|
5874
|
-
this.showFilterInput = false;
|
|
5875
|
-
this.showCustomDate = false;
|
|
5876
|
-
this.isEditingFilter = false;
|
|
5877
|
-
this.activeOption.set(null);
|
|
5878
|
-
this._resetInputState();
|
|
5879
|
-
};
|
|
5880
|
-
effect(() => {
|
|
5881
|
-
const k = this.key();
|
|
5882
|
-
const cfg = this.config();
|
|
5883
|
-
if (k && cfg)
|
|
5884
|
-
this._service.setConfig(k, cfg);
|
|
5885
|
-
});
|
|
5886
|
-
}
|
|
5887
|
-
ngOnInit() {
|
|
5888
|
-
const k = this.key();
|
|
5889
|
-
const cfg = this.config();
|
|
5890
|
-
if (k && cfg)
|
|
5891
|
-
this._service.setConfig(k, cfg);
|
|
5892
|
-
}
|
|
5893
|
-
ngOnChanges(changes) {
|
|
5894
|
-
const k = this.key();
|
|
5895
|
-
const cfg = this.config();
|
|
5896
|
-
if (k && cfg && (changes['key'] || changes['config'])) {
|
|
5897
|
-
this._service.setConfig(k, cfg);
|
|
5898
|
-
}
|
|
5899
|
-
}
|
|
5900
|
-
ngOnDestroy() { }
|
|
5901
|
-
availableFilterOptions() {
|
|
5902
|
-
const k = this.key();
|
|
5903
|
-
return k ? this._service.availableFilterOptions(k) : [];
|
|
5904
|
-
}
|
|
5905
|
-
isFilterActive(filterKey) {
|
|
5906
|
-
const k = this.key();
|
|
5907
|
-
return k ? this._service.isFilterActive(k, filterKey) : false;
|
|
5908
|
-
}
|
|
5909
|
-
getOptionId(optionKey) {
|
|
5910
|
-
return `filter-bar-opt-${this.key()}-${optionKey}`;
|
|
5911
|
-
}
|
|
5912
|
-
getActiveFilterId(filterKey) {
|
|
5913
|
-
return `filter-bar-active-${this.key()}-${filterKey}`;
|
|
5914
|
-
}
|
|
5915
|
-
onShowFilterMenu(btn) {
|
|
5916
|
-
this.filterMenuTarget = btn.element;
|
|
5917
|
-
this.showFilterMenu = true;
|
|
5918
|
-
}
|
|
5919
|
-
onSelectOption(option) {
|
|
5920
|
-
if (this.isFilterActive(option.key))
|
|
5921
|
-
return;
|
|
5922
|
-
this.activeOption.set(option);
|
|
5923
|
-
const optEl = document.getElementById(this.getOptionId(option.key));
|
|
5924
|
-
if (!optEl)
|
|
5925
|
-
return;
|
|
5926
|
-
if (option.type === 'date') {
|
|
5927
|
-
this.dateSubmenuTarget = optEl;
|
|
5928
|
-
this.showCustomDate = false;
|
|
5929
|
-
this.showDateSubmenu = true;
|
|
5930
|
-
}
|
|
5931
|
-
else {
|
|
5932
|
-
this.filterInputTarget = optEl;
|
|
5933
|
-
this.isEditingFilter = false;
|
|
5934
|
-
this._resetInputState();
|
|
5935
|
-
this.showFilterInput = true;
|
|
5936
|
-
}
|
|
5937
|
-
}
|
|
5938
|
-
onQuickDate(preset) {
|
|
5939
|
-
const k = this.key();
|
|
5940
|
-
const opt = this.activeOption();
|
|
5941
|
-
if (!k || !opt || opt.type !== 'date')
|
|
5942
|
-
return;
|
|
5943
|
-
const today = new Date();
|
|
5944
|
-
if (preset === 'custom') {
|
|
5945
|
-
this.closeDateSubmenu();
|
|
5946
|
-
this.showCustomDate = true;
|
|
5947
|
-
this.dateRange = { startDate: '', endDate: '' };
|
|
5948
|
-
this.filterInputTarget = this.dateSubmenuTarget;
|
|
5949
|
-
this.showFilterInput = true;
|
|
5950
|
-
return;
|
|
5951
|
-
}
|
|
5952
|
-
let start;
|
|
5953
|
-
let end = today;
|
|
5954
|
-
switch (preset) {
|
|
5955
|
-
case '1-week-after':
|
|
5956
|
-
start = today;
|
|
5957
|
-
end = addDays(today, 7);
|
|
5958
|
-
break;
|
|
5959
|
-
case '1-month-after':
|
|
5960
|
-
start = today;
|
|
5961
|
-
end = addMonths(today, 1);
|
|
5962
|
-
break;
|
|
5963
|
-
case '3-months-after':
|
|
5964
|
-
start = today;
|
|
5965
|
-
end = addMonths(today, 3);
|
|
5966
|
-
break;
|
|
5967
|
-
case '1-week-before':
|
|
5968
|
-
start = subDays(today, 7);
|
|
5969
|
-
break;
|
|
5970
|
-
case '1-month-before':
|
|
5971
|
-
start = subMonths(today, 1);
|
|
5972
|
-
break;
|
|
5973
|
-
case '3-months-before':
|
|
5974
|
-
start = subMonths(today, 3);
|
|
5975
|
-
break;
|
|
5976
|
-
default:
|
|
5977
|
-
return;
|
|
5978
|
-
}
|
|
5979
|
-
const value = {
|
|
5980
|
-
startDate: format(start, 'yyyy-MM-dd'),
|
|
5981
|
-
endDate: format(end, 'yyyy-MM-dd')
|
|
5982
|
-
};
|
|
5983
|
-
this._service.addFilter(k, opt, value);
|
|
5984
|
-
this.closeDateSubmenu();
|
|
5985
|
-
this.closeFilterMenu();
|
|
5986
|
-
this._emit();
|
|
5987
|
-
}
|
|
5988
|
-
onDateChange(event) {
|
|
5989
|
-
this.dateRange = event;
|
|
5990
|
-
if (event.startDate && event.endDate) {
|
|
5991
|
-
setTimeout(() => this.onApply(), 100);
|
|
5992
|
-
}
|
|
5993
|
-
}
|
|
5994
|
-
onStatusChange(val, checked) {
|
|
5995
|
-
if (checked) {
|
|
5996
|
-
if (!this.statusValues.includes(val))
|
|
5997
|
-
this.statusValues = [...this.statusValues, val];
|
|
5998
|
-
}
|
|
5999
|
-
else {
|
|
6000
|
-
this.statusValues = this.statusValues.filter((v) => v !== val);
|
|
6001
|
-
}
|
|
6002
|
-
}
|
|
6003
|
-
onApply() {
|
|
6004
|
-
const k = this.key();
|
|
6005
|
-
const opt = this.activeOption();
|
|
6006
|
-
if (!k || !opt)
|
|
6007
|
-
return;
|
|
6008
|
-
let value;
|
|
6009
|
-
switch (opt.type) {
|
|
6010
|
-
case 'text':
|
|
6011
|
-
if (!this.textValue.trim())
|
|
6012
|
-
return;
|
|
6013
|
-
value = this.textValue.trim();
|
|
6014
|
-
break;
|
|
6015
|
-
case 'date':
|
|
6016
|
-
if (!this.dateRange.startDate || !this.dateRange.endDate)
|
|
6017
|
-
return;
|
|
6018
|
-
value = { startDate: this.dateRange.startDate, endDate: this.dateRange.endDate };
|
|
6019
|
-
break;
|
|
6020
|
-
case 'currency': {
|
|
6021
|
-
const raw = this.currencyValue;
|
|
6022
|
-
if (raw === null || raw === undefined)
|
|
6023
|
-
return;
|
|
6024
|
-
value =
|
|
6025
|
-
this.currencyMode === 'from'
|
|
6026
|
-
? { min: raw, max: undefined }
|
|
6027
|
-
: { min: undefined, max: raw };
|
|
6028
|
-
break;
|
|
6029
|
-
}
|
|
6030
|
-
case 'status':
|
|
6031
|
-
if (this.statusValues.length === 0)
|
|
6032
|
-
return;
|
|
6033
|
-
value = [...this.statusValues];
|
|
6034
|
-
break;
|
|
6035
|
-
default:
|
|
6036
|
-
return;
|
|
6037
|
-
}
|
|
6038
|
-
const isEditing = this._service.isFilterActive(k, opt.key);
|
|
6039
|
-
if (isEditing) {
|
|
6040
|
-
this._service.updateFilter(k, opt.key, opt, value);
|
|
6041
|
-
}
|
|
6042
|
-
else {
|
|
6043
|
-
this._service.addFilter(k, opt, value);
|
|
6044
|
-
}
|
|
6045
|
-
this.closeFilterInput();
|
|
6046
|
-
this.closeFilterMenu();
|
|
6047
|
-
this._emit();
|
|
6048
|
-
}
|
|
6049
|
-
onEditFilter(filter) {
|
|
6050
|
-
const k = this.key();
|
|
6051
|
-
if (!k)
|
|
6052
|
-
return;
|
|
6053
|
-
const cfg = this.serviceConfig();
|
|
6054
|
-
const opt = cfg?.filterOptions.find((o) => o.key === filter.key);
|
|
6055
|
-
if (!opt)
|
|
6056
|
-
return;
|
|
6057
|
-
this.activeOption.set(opt);
|
|
6058
|
-
switch (filter.type) {
|
|
6059
|
-
case 'text':
|
|
6060
|
-
this.textValue = filter.value;
|
|
6061
|
-
break;
|
|
6062
|
-
case 'date': {
|
|
6063
|
-
const dv = filter.value;
|
|
6064
|
-
this.dateRange = { startDate: dv.startDate ?? '', endDate: dv.endDate ?? '' };
|
|
6065
|
-
this.showCustomDate = true;
|
|
6066
|
-
break;
|
|
6067
|
-
}
|
|
6068
|
-
case 'currency': {
|
|
6069
|
-
const cv = filter.value;
|
|
6070
|
-
if (cv.min !== undefined) {
|
|
6071
|
-
this.currencyMode = 'from';
|
|
6072
|
-
this.currencyValue = cv.min;
|
|
6073
|
-
}
|
|
6074
|
-
else if (cv.max !== undefined) {
|
|
6075
|
-
this.currencyMode = 'until';
|
|
6076
|
-
this.currencyValue = cv.max;
|
|
6077
|
-
}
|
|
6078
|
-
break;
|
|
6079
|
-
}
|
|
6080
|
-
case 'status':
|
|
6081
|
-
this.statusValues = [...(filter.value ?? [])];
|
|
6082
|
-
break;
|
|
6083
|
-
}
|
|
6084
|
-
const tagEl = document.getElementById(this.getActiveFilterId(filter.key));
|
|
6085
|
-
if (tagEl) {
|
|
6086
|
-
this.filterInputTarget = tagEl;
|
|
6087
|
-
this.isEditingFilter = true;
|
|
6088
|
-
this.showFilterInput = true;
|
|
6089
|
-
}
|
|
6090
|
-
}
|
|
6091
|
-
onRemoveFilter(filterKey, event) {
|
|
6092
|
-
event.stopPropagation();
|
|
6093
|
-
const k = this.key();
|
|
6094
|
-
if (!k)
|
|
6095
|
-
return;
|
|
6096
|
-
this._service.removeFilter(k, filterKey);
|
|
6097
|
-
this._emit();
|
|
6098
|
-
}
|
|
6099
|
-
onClearAll() {
|
|
6100
|
-
const k = this.key();
|
|
6101
|
-
if (!k)
|
|
6102
|
-
return;
|
|
6103
|
-
this._service.clearAllFilters(k);
|
|
6104
|
-
this._emit();
|
|
6105
|
-
}
|
|
6106
|
-
onSearchChange(value) {
|
|
6107
|
-
const k = this.key();
|
|
6108
|
-
if (!k)
|
|
6109
|
-
return;
|
|
6110
|
-
this._service.setSearchValue(k, value);
|
|
6111
|
-
this.searchChange.emit(value);
|
|
6112
|
-
this._emit();
|
|
6113
|
-
}
|
|
6114
|
-
_resetInputState() {
|
|
6115
|
-
this.textValue = '';
|
|
6116
|
-
this.currencyValue = null;
|
|
6117
|
-
this.currencyMode = 'from';
|
|
6118
|
-
this.statusValues = [];
|
|
6119
|
-
this.dateRange = { startDate: '', endDate: '' };
|
|
6120
|
-
}
|
|
6121
|
-
_emit() {
|
|
6122
|
-
const k = this.key();
|
|
6123
|
-
if (!k)
|
|
6124
|
-
return;
|
|
6125
|
-
const state = this._service.getState(k);
|
|
6126
|
-
this.filtersChange.emit({ search: state.search, filters: state.filters });
|
|
6127
|
-
}
|
|
6128
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: MonkeyFilterBarComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
6129
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.4", type: MonkeyFilterBarComponent, isStandalone: true, selector: "monkey-filter-bar", inputs: { key: { classPropertyName: "key", publicName: "key", isSignal: true, isRequired: true, transformFunction: null }, config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { filtersChange: "filtersChange", searchChange: "searchChange" }, host: { properties: { "attr.data-testid": "'monkey-filter-bar'" }, classAttribute: "mecx-filter-bar" }, usesOnChanges: true, ngImport: i0, template: `
|
|
6130
|
-
<!-- Top action bar -->
|
|
6131
|
-
<div class="filter-bar-top-bar">
|
|
6132
|
-
<monkey-form-field class="filter-bar-search-field" size="sm">
|
|
6133
|
-
<input
|
|
6134
|
-
type="text"
|
|
6135
|
-
monkey-input
|
|
6136
|
-
[placeholder]="searchPlaceholder()"
|
|
6137
|
-
[ngModel]="searchValue()"
|
|
6138
|
-
(ngModelChange)="onSearchChange($event)"
|
|
6139
|
-
/>
|
|
6140
|
-
<monkey-prefix>
|
|
6141
|
-
<i class="mk-i mk-i-search fs-md"></i>
|
|
6142
|
-
</monkey-prefix>
|
|
6143
|
-
</monkey-form-field>
|
|
6144
|
-
|
|
6145
|
-
<monkey-button
|
|
6146
|
-
#addFilterBtn
|
|
6147
|
-
type="secondary"
|
|
6148
|
-
size="sm"
|
|
6149
|
-
(click)="onShowFilterMenu(addFilterBtn)"
|
|
6150
|
-
>
|
|
6151
|
-
<i class="mk-i mk-i-add-plus fs-md" first></i>
|
|
6152
|
-
Adicionar Filtro
|
|
6153
|
-
</monkey-button>
|
|
6154
|
-
|
|
6155
|
-
<div class="filter-bar-extra-actions">
|
|
6156
|
-
<ng-content></ng-content>
|
|
6157
|
-
</div>
|
|
6158
|
-
</div>
|
|
6159
|
-
|
|
6160
|
-
<!-- Filter options popover -->
|
|
6161
|
-
<ng-template
|
|
6162
|
-
[monkeyPopover]="showFilterMenu"
|
|
6163
|
-
[monkeyPopoverTarget]="filterMenuTarget"
|
|
6164
|
-
[monkeyPopoverClosed]="closeFilterMenu"
|
|
6165
|
-
monkeyPopoverDir="ltr"
|
|
6166
|
-
[monkeyPopoverHideHeader]="true"
|
|
6167
|
-
>
|
|
6168
|
-
@for (
|
|
6169
|
-
option of availableFilterOptions();
|
|
6170
|
-
track option.key;
|
|
6171
|
-
let i = $index;
|
|
6172
|
-
let first = $first;
|
|
6173
|
-
let last = $last
|
|
6174
|
-
) {
|
|
6175
|
-
<div
|
|
6176
|
-
[id]="getOptionId(option.key)"
|
|
6177
|
-
class="filter-bar-option-item"
|
|
6178
|
-
[class.first]="first"
|
|
6179
|
-
[class.disabled]="isFilterActive(option.key)"
|
|
6180
|
-
(click)="onSelectOption(option)"
|
|
6181
|
-
>
|
|
6182
|
-
@if (option.icon) {
|
|
6183
|
-
<i [class]="'mk-i mk-i-' + option.icon + ' fs-md'"></i>
|
|
6184
|
-
}
|
|
6185
|
-
<span>{{ option.label }}</span>
|
|
6186
|
-
@if (isFilterActive(option.key)) {
|
|
6187
|
-
<i class="mk-i mk-i-check fs-sm filter-bar-active-check"></i>
|
|
6188
|
-
}
|
|
6189
|
-
</div>
|
|
6190
|
-
@if (!last && availableFilterOptions()[i + 1]?.type !== option.type) {
|
|
6191
|
-
<monkey-divider />
|
|
6192
|
-
}
|
|
6193
|
-
}
|
|
6194
|
-
</ng-template>
|
|
6195
|
-
|
|
6196
|
-
<!-- Date quick-pick submenu popover -->
|
|
6197
|
-
<ng-template
|
|
6198
|
-
[monkeyPopover]="showDateSubmenu"
|
|
6199
|
-
[monkeyPopoverTarget]="dateSubmenuTarget"
|
|
6200
|
-
[monkeyPopoverClosed]="closeDateSubmenu"
|
|
6201
|
-
monkeyPopoverDir="rt"
|
|
6202
|
-
[monkeyPopoverHideHeader]="true"
|
|
6203
|
-
>
|
|
6204
|
-
<div class="filter-bar-filter-panel">
|
|
6205
|
-
<div class="filter-bar-filter-header">
|
|
6206
|
-
@if (activeOption()?.icon) {
|
|
6207
|
-
<i [class]="'mk-i mk-i-' + activeOption()!.icon + ' fs-md'"></i>
|
|
6208
|
-
}
|
|
6209
|
-
<span>{{ activeOption()?.label }}</span>
|
|
6210
|
-
</div>
|
|
6211
|
-
|
|
6212
|
-
<div class="filter-bar-option-item first" (click)="onQuickDate('1-week-after')">
|
|
6213
|
-
1 semana a partir de hoje
|
|
6214
|
-
</div>
|
|
6215
|
-
<div class="filter-bar-option-item" (click)="onQuickDate('1-month-after')">
|
|
6216
|
-
1 mês a partir de hoje
|
|
6217
|
-
</div>
|
|
6218
|
-
<div class="filter-bar-option-item" (click)="onQuickDate('3-months-after')">
|
|
6219
|
-
3 meses a partir de hoje
|
|
6220
|
-
</div>
|
|
6221
|
-
<div class="filter-bar-option-item" (click)="onQuickDate('1-week-before')">
|
|
6222
|
-
1 semana antes de hoje
|
|
6223
|
-
</div>
|
|
6224
|
-
<div class="filter-bar-option-item" (click)="onQuickDate('1-month-before')">
|
|
6225
|
-
1 mês antes de hoje
|
|
6226
|
-
</div>
|
|
6227
|
-
<div class="filter-bar-option-item" (click)="onQuickDate('3-months-before')">
|
|
6228
|
-
3 meses antes de hoje
|
|
6229
|
-
</div>
|
|
6230
|
-
<div class="filter-bar-option-item" (click)="onQuickDate('custom')">Personalizado</div>
|
|
6231
|
-
</div>
|
|
6232
|
-
</ng-template>
|
|
6233
|
-
|
|
6234
|
-
<!-- Filter input popover (text / date / currency / status) -->
|
|
6235
|
-
<ng-template
|
|
6236
|
-
[monkeyPopover]="showFilterInput"
|
|
6237
|
-
[monkeyPopoverTarget]="filterInputTarget"
|
|
6238
|
-
[monkeyPopoverClosed]="closeFilterInput"
|
|
6239
|
-
[monkeyPopoverDir]="isEditingFilter ? 'ltr' : 'rt'"
|
|
6240
|
-
[monkeyPopoverHideHeader]="true"
|
|
6241
|
-
>
|
|
6242
|
-
<div class="filter-bar-filter-panel">
|
|
6243
|
-
<div class="filter-bar-filter-header">
|
|
6244
|
-
@if (activeOption()?.icon) {
|
|
6245
|
-
<i [class]="'mk-i mk-i-' + activeOption()!.icon + ' fs-md'"></i>
|
|
6246
|
-
}
|
|
6247
|
-
<span>{{ activeOption()?.label }}</span>
|
|
6248
|
-
</div>
|
|
6249
|
-
|
|
6250
|
-
@if (activeOption(); as opt) {
|
|
6251
|
-
@if (opt.type === 'text') {
|
|
6252
|
-
<div class="filter-bar-filter-body">
|
|
6253
|
-
<monkey-form-field size="sm">
|
|
6254
|
-
<input
|
|
6255
|
-
type="text"
|
|
6256
|
-
monkey-input
|
|
6257
|
-
[placeholder]="opt.placeholder || 'Digite o valor'"
|
|
6258
|
-
[(ngModel)]="textValue"
|
|
6259
|
-
(keyup.enter)="onApply()"
|
|
6260
|
-
/>
|
|
6261
|
-
</monkey-form-field>
|
|
6262
|
-
</div>
|
|
6263
|
-
}
|
|
6264
|
-
|
|
6265
|
-
@if (opt.type === 'date' && showCustomDate) {
|
|
6266
|
-
<monkey-date-range
|
|
6267
|
-
[startDate]="dateRange.startDate"
|
|
6268
|
-
[endDate]="dateRange.endDate"
|
|
6269
|
-
(onDate)="onDateChange($event)"
|
|
6270
|
-
></monkey-date-range>
|
|
6271
|
-
}
|
|
6272
|
-
|
|
6273
|
-
@if (opt.type === 'currency') {
|
|
6274
|
-
<div class="filter-bar-currency-body">
|
|
6275
|
-
<monkey-radiobutton [(ngModel)]="currencyMode" position="vertical" size="sm">
|
|
6276
|
-
<monkey-option [value]="'from'">De</monkey-option>
|
|
6277
|
-
<monkey-option [value]="'until'">Até</monkey-option>
|
|
6278
|
-
</monkey-radiobutton>
|
|
6279
|
-
<monkey-form-field size="sm">
|
|
6280
|
-
<input
|
|
6281
|
-
type="text"
|
|
6282
|
-
monkey-input-currency
|
|
6283
|
-
[placeholder]="currencyMode === 'from' ? 'Valor mínimo' : 'Valor máximo'"
|
|
6284
|
-
[(ngModel)]="currencyValue"
|
|
6285
|
-
(keyup.enter)="onApply()"
|
|
6286
|
-
/>
|
|
6287
|
-
</monkey-form-field>
|
|
6288
|
-
</div>
|
|
6289
|
-
}
|
|
6290
|
-
|
|
6291
|
-
@if (opt.type === 'status' && opt.statusOptions) {
|
|
6292
|
-
<div class="filter-bar-status-body">
|
|
6293
|
-
@for (s of opt.statusOptions; track s.value) {
|
|
6294
|
-
<monkey-checkbox
|
|
6295
|
-
[value]="statusValues.includes(s.value)"
|
|
6296
|
-
(onChange)="onStatusChange(s.value, $event)"
|
|
6297
|
-
size="sm"
|
|
6298
|
-
>
|
|
6299
|
-
{{ s.description }}
|
|
6300
|
-
</monkey-checkbox>
|
|
6301
|
-
}
|
|
6302
|
-
</div>
|
|
6303
|
-
}
|
|
6304
|
-
|
|
6305
|
-
@if (opt.type !== 'date') {
|
|
6306
|
-
<div class="filter-bar-filter-actions">
|
|
6307
|
-
<monkey-button size="sm" type="secondary" (click)="closeFilterInput()">
|
|
6308
|
-
Cancelar
|
|
6309
|
-
</monkey-button>
|
|
6310
|
-
<monkey-button size="sm" type="primary" (click)="onApply()">
|
|
6311
|
-
Aplicar
|
|
6312
|
-
</monkey-button>
|
|
6313
|
-
</div>
|
|
6314
|
-
}
|
|
6315
|
-
}
|
|
6316
|
-
</div>
|
|
6317
|
-
</ng-template>
|
|
6318
|
-
|
|
6319
|
-
<!-- Active filters row -->
|
|
6320
|
-
@if (activeFilters().length > 0) {
|
|
6321
|
-
<div class="filter-bar-active-bar">
|
|
6322
|
-
<monkey-icon-button
|
|
6323
|
-
type="secondary"
|
|
6324
|
-
size="sm"
|
|
6325
|
-
icon="trash"
|
|
6326
|
-
(click)="onClearAll()"
|
|
6327
|
-
></monkey-icon-button>
|
|
6328
|
-
|
|
6329
|
-
<div class="filter-bar-active-scroll">
|
|
6330
|
-
@for (f of activeFilters(); track f.key) {
|
|
6331
|
-
<div
|
|
6332
|
-
class="filter-bar-filter-tag"
|
|
6333
|
-
[id]="getActiveFilterId(f.key)"
|
|
6334
|
-
(click)="onEditFilter(f)"
|
|
6335
|
-
>
|
|
6336
|
-
@if (f.icon) {
|
|
6337
|
-
<i [class]="'mk-i mk-i-' + f.icon + ' fs-sm'"></i>
|
|
6338
|
-
}
|
|
6339
|
-
<span class="filter-bar-tag-label">{{ f.label }}:</span>
|
|
6340
|
-
<span class="filter-bar-tag-value">{{ f.displayText }}</span>
|
|
6341
|
-
<div class="filter-bar-tag-remove">
|
|
6342
|
-
<monkey-icon-button
|
|
6343
|
-
type="tertiary"
|
|
6344
|
-
color="error"
|
|
6345
|
-
size="sm"
|
|
6346
|
-
icon="close"
|
|
6347
|
-
(click)="onRemoveFilter(f.key, $event)"
|
|
6348
|
-
></monkey-icon-button>
|
|
6349
|
-
</div>
|
|
6350
|
-
</div>
|
|
6351
|
-
}
|
|
6352
|
-
</div>
|
|
6353
|
-
</div>
|
|
6354
|
-
}
|
|
6355
|
-
`, isInline: true, styles: [":host{width:100%;display:flex;flex-direction:column}:host .filter-bar-top-bar{display:flex;gap:8px;width:100%}:host .filter-bar-top-bar monkey-button{flex-shrink:0;max-height:32px}:host .filter-bar-top-bar .filter-bar-search-field{flex:1;min-width:0;max-width:400px;display:unset}:host .filter-bar-top-bar .filter-bar-extra-actions{margin-left:auto}:host .filter-bar-active-bar{display:flex;align-items:center;gap:8px;width:100%;overflow:hidden}:host .filter-bar-active-bar monkey-icon-button{flex-shrink:0}:host .filter-bar-active-bar .filter-bar-active-scroll{display:flex;align-items:center;gap:8px;flex:1;min-width:0;overflow:auto hidden;scrollbar-width:thin;scrollbar-color:var(--mecx-color-gray-300) transparent}:host .filter-bar-active-bar .filter-bar-active-scroll::-webkit-scrollbar{height:4px}:host .filter-bar-active-bar .filter-bar-active-scroll::-webkit-scrollbar-track{background:transparent}:host .filter-bar-active-bar .filter-bar-active-scroll::-webkit-scrollbar-thumb{background:var(--mecx-color-gray-300);border-radius:2px}:host .filter-bar-active-bar .filter-bar-active-scroll .filter-bar-filter-tag{display:inline-flex;align-items:center;gap:6px;padding:0 0 0 10px;background:var(--mecx-color-gray-100);border-radius:8px;white-space:nowrap;flex-shrink:0;cursor:pointer;transition:background-color .2s ease;height:32px}:host .filter-bar-active-bar .filter-bar-active-scroll .filter-bar-filter-tag:hover{background:var(--mecx-color-gray-200)}:host .filter-bar-active-bar .filter-bar-active-scroll .filter-bar-filter-tag i{color:var(--mecx-color-gray-600);flex-shrink:0}:host .filter-bar-active-bar .filter-bar-active-scroll .filter-bar-filter-tag .filter-bar-tag-label{font-size:13px;font-weight:600;color:var(--mecx-color-gray-700);flex-shrink:0}:host .filter-bar-active-bar .filter-bar-active-scroll .filter-bar-filter-tag .filter-bar-tag-value{font-size:13px;color:var(--mecx-color-gray-900);max-width:180px;overflow:hidden;text-overflow:ellipsis}:host .filter-bar-active-bar .filter-bar-active-scroll .filter-bar-filter-tag .filter-bar-tag-remove{border-left:1px solid var(--mecx-color-gray-300);display:flex;align-items:center;height:100%}.filter-bar-option-item{cursor:pointer;display:flex;align-items:center;gap:8px;padding:8px 16px;color:var(--mecx-color-gray-900);font-size:14px;font-weight:400;line-height:24px;letter-spacing:.14px;-webkit-user-select:none;user-select:none}.filter-bar-option-item.first{border-top-left-radius:6px;border-top-right-radius:6px}.filter-bar-option-item:hover:not(.disabled){background-color:var(--mecx-color-gray-100)}.filter-bar-option-item.disabled{opacity:.5;cursor:not-allowed;pointer-events:none}.filter-bar-option-item .filter-bar-active-check{margin-left:auto;color:var(--mecx-color-primary-500, var(--mecx-color-gray-700))}.filter-bar-filter-panel{display:flex;flex-direction:column;min-width:260px}.filter-bar-filter-panel .filter-bar-filter-header{display:flex;align-items:center;gap:6px;padding:8px 12px;border-bottom:1px solid var(--mecx-color-gray-200);font-size:14px;font-weight:600;line-height:24px;letter-spacing:.14px;color:var(--mecx-color-gray-700)}.filter-bar-filter-panel .filter-bar-filter-body{padding:8px 12px}.filter-bar-filter-panel .filter-bar-currency-body{display:flex;flex-direction:column;gap:8px;padding:8px 12px}.filter-bar-filter-panel .filter-bar-status-body{display:flex;flex-direction:column;align-items:flex-start;justify-content:flex-start;gap:10px;padding:12px 16px}.filter-bar-filter-panel monkey-date-range{border:unset;border-radius:unset}.filter-bar-filter-panel .filter-bar-filter-actions{display:flex;justify-content:space-between;gap:8px;padding:8px 12px;border-top:1px solid var(--mecx-color-gray-200)}.mk-i{display:flex}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "ngmodule", type: MonkeyFormFieldModule }, { kind: "component", type: MonkeyFormFieldComponent, selector: "monkey-form-field", inputs: ["id", "hideAction", "enableClear", "size", "noFooterSpace", "displayOnly"], outputs: ["onDisplayOnlyChange"], exportAs: ["monkeyFormField"] }, { kind: "ngmodule", type: MonkeyInputModule }, { kind: "directive", type: MonkeyInputDirective, selector: "input[monkey-input],textarea[monkey-input]", inputs: ["name", "disabled", "id", "required", "type", "min", "max", "percent"], exportAs: ["monkeyInput"] }, { kind: "directive", type: MonkeyInputCurrencyDirective, selector: "input[monkey-input-currency]", inputs: ["name", "disabled", "id", "required", "type"], exportAs: ["monkeyInput"] }, { kind: "component", type: MonkeyButtonComponent, selector: "monkey-button", inputs: ["disabled", "color", "size", "type", "loading", "id"] }, { kind: "component", type: MonkeyOptionComponent, selector: "monkey-option", inputs: ["value", "disabled", "type", "selected"] }, { kind: "directive", type: MonkeyPopoverDirective, selector: "[monkeyPopover]", inputs: ["monkeyPopover", "monkeyPopoverClosed", "monkeyPopoverTarget", "monkeyPopoverMinwidth", "monkeyPopoverBackdrop", "monkeyPopoverWatch", "monkeyPopoverDir", "monkeyPopoverContextmenu", "monkeyPopoverHeight", "monkeyPopoverTitle", "monkeyPopoverActions", "monkeyPopoverHideClose", "monkeyPopoverHideHeader", "monkeyPopoverHideActions", "monkeyPopoverEnableAutofocus"] }, { kind: "component", type: MonkeyDateRangeComponent, selector: "monkey-date-range", inputs: ["startDate", "endDate", "hideQuickAction", "hideHeader", "hideActions", "hideSecondCalendar", "allowFastActionOnHeader", "minDate", "maxDate", "id"], outputs: ["onCancel", "onDate"] }, { kind: "component", type: MonkeyDividerComponent, selector: "monkey-divider", inputs: ["size", "vertical", "id"] }, { kind: "component", type: MonkeyRadioButtonComponent, selector: "monkey-radiobutton", inputs: ["tabIndex", "position", "size", "disabled", "required", "value"], outputs: ["onChange", "onSearch"] }, { kind: "component", type: MonkeyIconButtonComponent, selector: "monkey-icon-button", inputs: ["type", "size", "disabled", "icon", "loading", "color", "id"] }, { kind: "directive", type: MonkeyPrefixDirective, selector: "monkey-prefix" }, { kind: "component", type: MonkeyCheckboxComponent, selector: "monkey-checkbox", inputs: ["disabled", "indeterminate", "required", "showFooter", "size", "value"], outputs: ["onChange"] }] }); }
|
|
6356
|
-
}
|
|
6357
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: MonkeyFilterBarComponent, decorators: [{
|
|
6358
|
-
type: Component,
|
|
6359
|
-
args: [{ selector: 'monkey-filter-bar', imports: [
|
|
6360
|
-
CommonModule,
|
|
6361
|
-
FormsModule,
|
|
6362
|
-
ReactiveFormsModule,
|
|
6363
|
-
MonkeyFormFieldModule,
|
|
6364
|
-
MonkeyInputModule,
|
|
6365
|
-
MonkeyButtonComponent,
|
|
6366
|
-
MonkeyOptionComponent,
|
|
6367
|
-
MonkeyPopoverDirective,
|
|
6368
|
-
MonkeyDateRangeComponent,
|
|
6369
|
-
MonkeyBadgeComponent,
|
|
6370
|
-
MonkeyLabelDirective,
|
|
6371
|
-
MonkeyDividerComponent,
|
|
6372
|
-
MonkeyRadioButtonComponent,
|
|
6373
|
-
MonkeyIconButtonComponent,
|
|
6374
|
-
MonkeyPrefixDirective,
|
|
6375
|
-
MonkeyCheckboxComponent
|
|
6376
|
-
], template: `
|
|
6377
|
-
<!-- Top action bar -->
|
|
6378
|
-
<div class="filter-bar-top-bar">
|
|
6379
|
-
<monkey-form-field class="filter-bar-search-field" size="sm">
|
|
6380
|
-
<input
|
|
6381
|
-
type="text"
|
|
6382
|
-
monkey-input
|
|
6383
|
-
[placeholder]="searchPlaceholder()"
|
|
6384
|
-
[ngModel]="searchValue()"
|
|
6385
|
-
(ngModelChange)="onSearchChange($event)"
|
|
6386
|
-
/>
|
|
6387
|
-
<monkey-prefix>
|
|
6388
|
-
<i class="mk-i mk-i-search fs-md"></i>
|
|
6389
|
-
</monkey-prefix>
|
|
6390
|
-
</monkey-form-field>
|
|
6391
|
-
|
|
6392
|
-
<monkey-button
|
|
6393
|
-
#addFilterBtn
|
|
6394
|
-
type="secondary"
|
|
6395
|
-
size="sm"
|
|
6396
|
-
(click)="onShowFilterMenu(addFilterBtn)"
|
|
6397
|
-
>
|
|
6398
|
-
<i class="mk-i mk-i-add-plus fs-md" first></i>
|
|
6399
|
-
Adicionar Filtro
|
|
6400
|
-
</monkey-button>
|
|
6401
|
-
|
|
6402
|
-
<div class="filter-bar-extra-actions">
|
|
6403
|
-
<ng-content></ng-content>
|
|
6404
|
-
</div>
|
|
6405
|
-
</div>
|
|
6406
|
-
|
|
6407
|
-
<!-- Filter options popover -->
|
|
6408
|
-
<ng-template
|
|
6409
|
-
[monkeyPopover]="showFilterMenu"
|
|
6410
|
-
[monkeyPopoverTarget]="filterMenuTarget"
|
|
6411
|
-
[monkeyPopoverClosed]="closeFilterMenu"
|
|
6412
|
-
monkeyPopoverDir="ltr"
|
|
6413
|
-
[monkeyPopoverHideHeader]="true"
|
|
6414
|
-
>
|
|
6415
|
-
@for (
|
|
6416
|
-
option of availableFilterOptions();
|
|
6417
|
-
track option.key;
|
|
6418
|
-
let i = $index;
|
|
6419
|
-
let first = $first;
|
|
6420
|
-
let last = $last
|
|
6421
|
-
) {
|
|
6422
|
-
<div
|
|
6423
|
-
[id]="getOptionId(option.key)"
|
|
6424
|
-
class="filter-bar-option-item"
|
|
6425
|
-
[class.first]="first"
|
|
6426
|
-
[class.disabled]="isFilterActive(option.key)"
|
|
6427
|
-
(click)="onSelectOption(option)"
|
|
6428
|
-
>
|
|
6429
|
-
@if (option.icon) {
|
|
6430
|
-
<i [class]="'mk-i mk-i-' + option.icon + ' fs-md'"></i>
|
|
6431
|
-
}
|
|
6432
|
-
<span>{{ option.label }}</span>
|
|
6433
|
-
@if (isFilterActive(option.key)) {
|
|
6434
|
-
<i class="mk-i mk-i-check fs-sm filter-bar-active-check"></i>
|
|
6435
|
-
}
|
|
6436
|
-
</div>
|
|
6437
|
-
@if (!last && availableFilterOptions()[i + 1]?.type !== option.type) {
|
|
6438
|
-
<monkey-divider />
|
|
6439
|
-
}
|
|
6440
|
-
}
|
|
6441
|
-
</ng-template>
|
|
6442
|
-
|
|
6443
|
-
<!-- Date quick-pick submenu popover -->
|
|
6444
|
-
<ng-template
|
|
6445
|
-
[monkeyPopover]="showDateSubmenu"
|
|
6446
|
-
[monkeyPopoverTarget]="dateSubmenuTarget"
|
|
6447
|
-
[monkeyPopoverClosed]="closeDateSubmenu"
|
|
6448
|
-
monkeyPopoverDir="rt"
|
|
6449
|
-
[monkeyPopoverHideHeader]="true"
|
|
6450
|
-
>
|
|
6451
|
-
<div class="filter-bar-filter-panel">
|
|
6452
|
-
<div class="filter-bar-filter-header">
|
|
6453
|
-
@if (activeOption()?.icon) {
|
|
6454
|
-
<i [class]="'mk-i mk-i-' + activeOption()!.icon + ' fs-md'"></i>
|
|
6455
|
-
}
|
|
6456
|
-
<span>{{ activeOption()?.label }}</span>
|
|
6457
|
-
</div>
|
|
6458
|
-
|
|
6459
|
-
<div class="filter-bar-option-item first" (click)="onQuickDate('1-week-after')">
|
|
6460
|
-
1 semana a partir de hoje
|
|
6461
|
-
</div>
|
|
6462
|
-
<div class="filter-bar-option-item" (click)="onQuickDate('1-month-after')">
|
|
6463
|
-
1 mês a partir de hoje
|
|
6464
|
-
</div>
|
|
6465
|
-
<div class="filter-bar-option-item" (click)="onQuickDate('3-months-after')">
|
|
6466
|
-
3 meses a partir de hoje
|
|
6467
|
-
</div>
|
|
6468
|
-
<div class="filter-bar-option-item" (click)="onQuickDate('1-week-before')">
|
|
6469
|
-
1 semana antes de hoje
|
|
6470
|
-
</div>
|
|
6471
|
-
<div class="filter-bar-option-item" (click)="onQuickDate('1-month-before')">
|
|
6472
|
-
1 mês antes de hoje
|
|
6473
|
-
</div>
|
|
6474
|
-
<div class="filter-bar-option-item" (click)="onQuickDate('3-months-before')">
|
|
6475
|
-
3 meses antes de hoje
|
|
6476
|
-
</div>
|
|
6477
|
-
<div class="filter-bar-option-item" (click)="onQuickDate('custom')">Personalizado</div>
|
|
6478
|
-
</div>
|
|
6479
|
-
</ng-template>
|
|
6480
|
-
|
|
6481
|
-
<!-- Filter input popover (text / date / currency / status) -->
|
|
6482
|
-
<ng-template
|
|
6483
|
-
[monkeyPopover]="showFilterInput"
|
|
6484
|
-
[monkeyPopoverTarget]="filterInputTarget"
|
|
6485
|
-
[monkeyPopoverClosed]="closeFilterInput"
|
|
6486
|
-
[monkeyPopoverDir]="isEditingFilter ? 'ltr' : 'rt'"
|
|
6487
|
-
[monkeyPopoverHideHeader]="true"
|
|
6488
|
-
>
|
|
6489
|
-
<div class="filter-bar-filter-panel">
|
|
6490
|
-
<div class="filter-bar-filter-header">
|
|
6491
|
-
@if (activeOption()?.icon) {
|
|
6492
|
-
<i [class]="'mk-i mk-i-' + activeOption()!.icon + ' fs-md'"></i>
|
|
6493
|
-
}
|
|
6494
|
-
<span>{{ activeOption()?.label }}</span>
|
|
6495
|
-
</div>
|
|
6496
|
-
|
|
6497
|
-
@if (activeOption(); as opt) {
|
|
6498
|
-
@if (opt.type === 'text') {
|
|
6499
|
-
<div class="filter-bar-filter-body">
|
|
6500
|
-
<monkey-form-field size="sm">
|
|
6501
|
-
<input
|
|
6502
|
-
type="text"
|
|
6503
|
-
monkey-input
|
|
6504
|
-
[placeholder]="opt.placeholder || 'Digite o valor'"
|
|
6505
|
-
[(ngModel)]="textValue"
|
|
6506
|
-
(keyup.enter)="onApply()"
|
|
6507
|
-
/>
|
|
6508
|
-
</monkey-form-field>
|
|
6509
|
-
</div>
|
|
6510
|
-
}
|
|
6511
|
-
|
|
6512
|
-
@if (opt.type === 'date' && showCustomDate) {
|
|
6513
|
-
<monkey-date-range
|
|
6514
|
-
[startDate]="dateRange.startDate"
|
|
6515
|
-
[endDate]="dateRange.endDate"
|
|
6516
|
-
(onDate)="onDateChange($event)"
|
|
6517
|
-
></monkey-date-range>
|
|
6518
|
-
}
|
|
6519
|
-
|
|
6520
|
-
@if (opt.type === 'currency') {
|
|
6521
|
-
<div class="filter-bar-currency-body">
|
|
6522
|
-
<monkey-radiobutton [(ngModel)]="currencyMode" position="vertical" size="sm">
|
|
6523
|
-
<monkey-option [value]="'from'">De</monkey-option>
|
|
6524
|
-
<monkey-option [value]="'until'">Até</monkey-option>
|
|
6525
|
-
</monkey-radiobutton>
|
|
6526
|
-
<monkey-form-field size="sm">
|
|
6527
|
-
<input
|
|
6528
|
-
type="text"
|
|
6529
|
-
monkey-input-currency
|
|
6530
|
-
[placeholder]="currencyMode === 'from' ? 'Valor mínimo' : 'Valor máximo'"
|
|
6531
|
-
[(ngModel)]="currencyValue"
|
|
6532
|
-
(keyup.enter)="onApply()"
|
|
6533
|
-
/>
|
|
6534
|
-
</monkey-form-field>
|
|
6535
|
-
</div>
|
|
6536
|
-
}
|
|
6537
|
-
|
|
6538
|
-
@if (opt.type === 'status' && opt.statusOptions) {
|
|
6539
|
-
<div class="filter-bar-status-body">
|
|
6540
|
-
@for (s of opt.statusOptions; track s.value) {
|
|
6541
|
-
<monkey-checkbox
|
|
6542
|
-
[value]="statusValues.includes(s.value)"
|
|
6543
|
-
(onChange)="onStatusChange(s.value, $event)"
|
|
6544
|
-
size="sm"
|
|
6545
|
-
>
|
|
6546
|
-
{{ s.description }}
|
|
6547
|
-
</monkey-checkbox>
|
|
6548
|
-
}
|
|
6549
|
-
</div>
|
|
6550
|
-
}
|
|
6551
|
-
|
|
6552
|
-
@if (opt.type !== 'date') {
|
|
6553
|
-
<div class="filter-bar-filter-actions">
|
|
6554
|
-
<monkey-button size="sm" type="secondary" (click)="closeFilterInput()">
|
|
6555
|
-
Cancelar
|
|
6556
|
-
</monkey-button>
|
|
6557
|
-
<monkey-button size="sm" type="primary" (click)="onApply()">
|
|
6558
|
-
Aplicar
|
|
6559
|
-
</monkey-button>
|
|
6560
|
-
</div>
|
|
6561
|
-
}
|
|
6562
|
-
}
|
|
6563
|
-
</div>
|
|
6564
|
-
</ng-template>
|
|
6565
|
-
|
|
6566
|
-
<!-- Active filters row -->
|
|
6567
|
-
@if (activeFilters().length > 0) {
|
|
6568
|
-
<div class="filter-bar-active-bar">
|
|
6569
|
-
<monkey-icon-button
|
|
6570
|
-
type="secondary"
|
|
6571
|
-
size="sm"
|
|
6572
|
-
icon="trash"
|
|
6573
|
-
(click)="onClearAll()"
|
|
6574
|
-
></monkey-icon-button>
|
|
6575
|
-
|
|
6576
|
-
<div class="filter-bar-active-scroll">
|
|
6577
|
-
@for (f of activeFilters(); track f.key) {
|
|
6578
|
-
<div
|
|
6579
|
-
class="filter-bar-filter-tag"
|
|
6580
|
-
[id]="getActiveFilterId(f.key)"
|
|
6581
|
-
(click)="onEditFilter(f)"
|
|
6582
|
-
>
|
|
6583
|
-
@if (f.icon) {
|
|
6584
|
-
<i [class]="'mk-i mk-i-' + f.icon + ' fs-sm'"></i>
|
|
6585
|
-
}
|
|
6586
|
-
<span class="filter-bar-tag-label">{{ f.label }}:</span>
|
|
6587
|
-
<span class="filter-bar-tag-value">{{ f.displayText }}</span>
|
|
6588
|
-
<div class="filter-bar-tag-remove">
|
|
6589
|
-
<monkey-icon-button
|
|
6590
|
-
type="tertiary"
|
|
6591
|
-
color="error"
|
|
6592
|
-
size="sm"
|
|
6593
|
-
icon="close"
|
|
6594
|
-
(click)="onRemoveFilter(f.key, $event)"
|
|
6595
|
-
></monkey-icon-button>
|
|
6596
|
-
</div>
|
|
6597
|
-
</div>
|
|
6598
|
-
}
|
|
6599
|
-
</div>
|
|
6600
|
-
</div>
|
|
6601
|
-
}
|
|
6602
|
-
`, host: {
|
|
6603
|
-
'[attr.data-testid]': "'monkey-filter-bar'",
|
|
6604
|
-
class: 'mecx-filter-bar'
|
|
6605
|
-
}, styles: [":host{width:100%;display:flex;flex-direction:column}:host .filter-bar-top-bar{display:flex;gap:8px;width:100%}:host .filter-bar-top-bar monkey-button{flex-shrink:0;max-height:32px}:host .filter-bar-top-bar .filter-bar-search-field{flex:1;min-width:0;max-width:400px;display:unset}:host .filter-bar-top-bar .filter-bar-extra-actions{margin-left:auto}:host .filter-bar-active-bar{display:flex;align-items:center;gap:8px;width:100%;overflow:hidden}:host .filter-bar-active-bar monkey-icon-button{flex-shrink:0}:host .filter-bar-active-bar .filter-bar-active-scroll{display:flex;align-items:center;gap:8px;flex:1;min-width:0;overflow:auto hidden;scrollbar-width:thin;scrollbar-color:var(--mecx-color-gray-300) transparent}:host .filter-bar-active-bar .filter-bar-active-scroll::-webkit-scrollbar{height:4px}:host .filter-bar-active-bar .filter-bar-active-scroll::-webkit-scrollbar-track{background:transparent}:host .filter-bar-active-bar .filter-bar-active-scroll::-webkit-scrollbar-thumb{background:var(--mecx-color-gray-300);border-radius:2px}:host .filter-bar-active-bar .filter-bar-active-scroll .filter-bar-filter-tag{display:inline-flex;align-items:center;gap:6px;padding:0 0 0 10px;background:var(--mecx-color-gray-100);border-radius:8px;white-space:nowrap;flex-shrink:0;cursor:pointer;transition:background-color .2s ease;height:32px}:host .filter-bar-active-bar .filter-bar-active-scroll .filter-bar-filter-tag:hover{background:var(--mecx-color-gray-200)}:host .filter-bar-active-bar .filter-bar-active-scroll .filter-bar-filter-tag i{color:var(--mecx-color-gray-600);flex-shrink:0}:host .filter-bar-active-bar .filter-bar-active-scroll .filter-bar-filter-tag .filter-bar-tag-label{font-size:13px;font-weight:600;color:var(--mecx-color-gray-700);flex-shrink:0}:host .filter-bar-active-bar .filter-bar-active-scroll .filter-bar-filter-tag .filter-bar-tag-value{font-size:13px;color:var(--mecx-color-gray-900);max-width:180px;overflow:hidden;text-overflow:ellipsis}:host .filter-bar-active-bar .filter-bar-active-scroll .filter-bar-filter-tag .filter-bar-tag-remove{border-left:1px solid var(--mecx-color-gray-300);display:flex;align-items:center;height:100%}.filter-bar-option-item{cursor:pointer;display:flex;align-items:center;gap:8px;padding:8px 16px;color:var(--mecx-color-gray-900);font-size:14px;font-weight:400;line-height:24px;letter-spacing:.14px;-webkit-user-select:none;user-select:none}.filter-bar-option-item.first{border-top-left-radius:6px;border-top-right-radius:6px}.filter-bar-option-item:hover:not(.disabled){background-color:var(--mecx-color-gray-100)}.filter-bar-option-item.disabled{opacity:.5;cursor:not-allowed;pointer-events:none}.filter-bar-option-item .filter-bar-active-check{margin-left:auto;color:var(--mecx-color-primary-500, var(--mecx-color-gray-700))}.filter-bar-filter-panel{display:flex;flex-direction:column;min-width:260px}.filter-bar-filter-panel .filter-bar-filter-header{display:flex;align-items:center;gap:6px;padding:8px 12px;border-bottom:1px solid var(--mecx-color-gray-200);font-size:14px;font-weight:600;line-height:24px;letter-spacing:.14px;color:var(--mecx-color-gray-700)}.filter-bar-filter-panel .filter-bar-filter-body{padding:8px 12px}.filter-bar-filter-panel .filter-bar-currency-body{display:flex;flex-direction:column;gap:8px;padding:8px 12px}.filter-bar-filter-panel .filter-bar-status-body{display:flex;flex-direction:column;align-items:flex-start;justify-content:flex-start;gap:10px;padding:12px 16px}.filter-bar-filter-panel monkey-date-range{border:unset;border-radius:unset}.filter-bar-filter-panel .filter-bar-filter-actions{display:flex;justify-content:space-between;gap:8px;padding:8px 12px;border-top:1px solid var(--mecx-color-gray-200)}.mk-i{display:flex}\n"] }]
|
|
6606
|
-
}], ctorParameters: () => [], propDecorators: { key: [{ type: i0.Input, args: [{ isSignal: true, alias: "key", required: true }] }], config: [{ type: i0.Input, args: [{ isSignal: true, alias: "config", required: false }] }], filtersChange: [{
|
|
6607
|
-
type: Output
|
|
6608
|
-
}], searchChange: [{
|
|
6609
|
-
type: Output
|
|
6610
|
-
}] } });
|
|
6611
|
-
|
|
6612
|
-
/** ************************
|
|
6613
|
-
* Copyright Monkey Exchange. All Rights Reserved
|
|
6614
|
-
* This style guide was developed by Monkey Exchange Team
|
|
6615
|
-
* MIT Licence
|
|
6616
|
-
************************* */
|
|
6617
|
-
|
|
6618
|
-
/** ************************
|
|
6619
|
-
* Copyright Monkey Exchange. All Rights Reserved
|
|
6620
|
-
* This style guide was developed by Monkey Exchange Team
|
|
6621
|
-
* MIT Licence
|
|
6622
|
-
************************* */
|
|
6623
|
-
|
|
6624
|
-
/** ************************
|
|
6625
|
-
* Copyright Monkey Exchange. All Rights Reserved
|
|
6626
|
-
* This style guide was developed by Monkey Exchange Team
|
|
6627
|
-
* MIT Licence
|
|
6628
|
-
************************* */
|
|
6629
|
-
/**
|
|
6630
|
-
* Shortest the thumb may get, in px — matches the `--mecx-spaces-medium`
|
|
6631
|
-
* floor in the stylesheet. A very long list would otherwise give a 2px thumb,
|
|
6632
|
-
* too small to grab.
|
|
6633
|
-
*/
|
|
6634
|
-
const MIN_THUMB = 24;
|
|
6635
|
-
/**
|
|
6636
|
-
* A DRAWN scrollbar, not the native one styled — a native scrollbar can't
|
|
6637
|
-
* live outside the element that scrolls (e.g. below a table's rows, next to
|
|
6638
|
-
* its footer), and cross-browser track styling (radius, border) is
|
|
6639
|
-
* inconsistent enough that matching a design exactly isn't reliable with
|
|
6640
|
-
* `::-webkit-scrollbar`/`scrollbar-color` alone.
|
|
6641
|
-
*
|
|
6642
|
-
* It does NOT replace real scrolling: `target` keeps its own
|
|
6643
|
-
* `overflow: auto`, so keyboard, wheel and trackpad scrolling all keep
|
|
6644
|
-
* working — this is a draggable mirror drawn on top. That's also why it's
|
|
6645
|
-
* `aria-hidden`: a screen reader user scrolls the real region, and a second
|
|
6646
|
-
* widget announcing the same position would only add noise.
|
|
6647
|
-
*/
|
|
6648
|
-
class MonkeyScrollbarComponent {
|
|
5859
|
+
/**
|
|
5860
|
+
* Shortest the thumb may get, in px — matches the `--mecx-spaces-medium`
|
|
5861
|
+
* floor in the stylesheet. A very long list would otherwise give a 2px thumb,
|
|
5862
|
+
* too small to grab.
|
|
5863
|
+
*/
|
|
5864
|
+
const MIN_THUMB = 24;
|
|
5865
|
+
/**
|
|
5866
|
+
* A DRAWN scrollbar, not the native one styled — a native scrollbar can't
|
|
5867
|
+
* live outside the element that scrolls (e.g. below a table's rows, next to
|
|
5868
|
+
* its footer), and cross-browser track styling (radius, border) is
|
|
5869
|
+
* inconsistent enough that matching a design exactly isn't reliable with
|
|
5870
|
+
* `::-webkit-scrollbar`/`scrollbar-color` alone.
|
|
5871
|
+
*
|
|
5872
|
+
* It does NOT replace real scrolling: `target` keeps its own
|
|
5873
|
+
* `overflow: auto`, so keyboard, wheel and trackpad scrolling all keep
|
|
5874
|
+
* working — this is a draggable mirror drawn on top. That's also why it's
|
|
5875
|
+
* `aria-hidden`: a screen reader user scrolls the real region, and a second
|
|
5876
|
+
* widget announcing the same position would only add noise.
|
|
5877
|
+
*/
|
|
5878
|
+
class MonkeyScrollbarComponent {
|
|
6649
5879
|
constructor() {
|
|
6650
5880
|
this._zone = inject(NgZone);
|
|
6651
5881
|
this.orientation = input('horizontal', ...(ngDevMode ? [{ debugName: "orientation" }] : /* istanbul ignore next */ []));
|
|
@@ -6857,80 +6087,41 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImpor
|
|
|
6857
6087
|
* This style guide was developed by Monkey Exchange Team
|
|
6858
6088
|
* MIT Licence
|
|
6859
6089
|
************************* */
|
|
6860
|
-
/**
|
|
6861
|
-
* The segmented row that replaces the trigger once the user has picked a
|
|
6862
|
-
* filter. Two segments and a bin:
|
|
6863
|
-
*
|
|
6864
|
-
* [ icon Data de Emissão | 01/01/2025 - 31/01/2025 | 🗑 ]
|
|
6865
|
-
* category value action
|
|
6866
|
-
*
|
|
6867
|
-
* How many segments there are is the consumer's decision — the value segment
|
|
6868
|
-
* is projected as soon as there is something to answer:
|
|
6869
|
-
*
|
|
6870
|
-
* <monkey-filter-chip (remove)="drop()">
|
|
6871
|
-
* <monkey-filter-segment icon="calendar-box" text="Data" readonlySegment />
|
|
6872
|
-
* <monkey-filter-segment placeholder="Selecione" [(open)]="open" />
|
|
6873
|
-
* </monkey-filter-chip>
|
|
6874
|
-
*
|
|
6875
|
-
* The chip carries NO `overflow: hidden`. It would clip the panels the
|
|
6876
|
-
* segments open right below themselves; the ends are rounded by radius, not by
|
|
6877
|
-
* clipping.
|
|
6878
|
-
*/
|
|
6879
6090
|
class MonkeyFilterChipComponent {
|
|
6880
6091
|
constructor() {
|
|
6881
|
-
/** Icon font name of the remove action, without the `mk-i-` prefix. */
|
|
6882
6092
|
this.removeIcon = input('trash', ...(ngDevMode ? [{ debugName: "removeIcon" }] : /* istanbul ignore next */ []));
|
|
6883
|
-
this.removeLabel = input('
|
|
6884
|
-
this.
|
|
6093
|
+
this.removeLabel = input('', ...(ngDevMode ? [{ debugName: "removeLabel" }] : /* istanbul ignore next */ []));
|
|
6094
|
+
this.disabled = input(false, { ...(ngDevMode ? { debugName: "disabled" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
|
|
6095
|
+
this.onRemove = output();
|
|
6885
6096
|
}
|
|
6886
6097
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: MonkeyFilterChipComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
6887
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.4", type: MonkeyFilterChipComponent, isStandalone: true, selector: "monkey-filter-chip", inputs: { removeIcon: { classPropertyName: "removeIcon", publicName: "removeIcon", isSignal: true, isRequired: false, transformFunction: null }, removeLabel: { classPropertyName: "removeLabel", publicName: "removeLabel", isSignal: true, isRequired: false, transformFunction: null } }, outputs: {
|
|
6098
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.4", type: MonkeyFilterChipComponent, isStandalone: true, selector: "monkey-filter-chip", inputs: { removeIcon: { classPropertyName: "removeIcon", publicName: "removeIcon", isSignal: true, isRequired: false, transformFunction: null }, removeLabel: { classPropertyName: "removeLabel", publicName: "removeLabel", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { onRemove: "onRemove" }, host: { attributes: { "data-testid": "monkey-filter-chip" }, properties: { "class.mecx-filter-chip--disabled": "disabled()" }, classAttribute: "mecx-filter-chip" }, ngImport: i0, template: "<ng-content></ng-content>\n<span class=\"mecx-filter-chip-action\">\n <button\n class=\"mecx-filter-chip-remove\"\n type=\"button\"\n [disabled]=\"disabled() || null\"\n [attr.aria-label]=\"removeLabel()\"\n (click)=\"onRemove.emit()\"\n >\n <i class=\"mk-i mk-i-{{ removeIcon() }}\" aria-hidden=\"true\"></i>\n </button>\n</span>\n", styles: [".mecx-filter-chip{--mecx-filter-bar-duration-state: .15s;--mecx-filter-bar-duration-enter: .2s;--mecx-filter-bar-duration-exit: .15s;--mecx-filter-bar-ease-state: cubic-bezier(.25, .46, .45, .94);--mecx-filter-bar-ease-enter: cubic-bezier(.32, .72, 0, 1);--mecx-filter-bar-ease-exit: cubic-bezier(.4, 0, 1, 1);--mecx-filter-bar-scale-unfold: .94;--mecx-filter-bar-travel-anchored: 4px;--mecx-filter-bar-travel-slide: 16px;--mecx-filter-bar-stagger: 25ms;--mecx-filter-bar-control-height: 32px;--mecx-filter-bar-pointer-target: 40px;--mecx-filter-bar-reach: calc((var(--mecx-filter-bar-control-height) - var(--mecx-filter-bar-pointer-target)) / 2);--mecx-filter-bar-radius: 8px;--mecx-filter-bar-radius-item: 4px;--mecx-filter-bar-fade-width: 48px}@media(prefers-reduced-motion:reduce){.mecx-filter-chip{--mecx-filter-bar-duration-state: 1ms;--mecx-filter-bar-duration-enter: 1ms;--mecx-filter-bar-duration-exit: 1ms;--mecx-filter-bar-scale-unfold: 1;--mecx-filter-bar-travel-anchored: 0px;--mecx-filter-bar-travel-slide: 0px;--mecx-filter-bar-stagger: 0ms}}.mecx-filter-chip{display:inline-flex;align-items:center}.mecx-filter-chip>monkey-filter-segment:first-child .mecx-filter-segment-btn{border-top-left-radius:var(--mecx-filter-bar-radius);border-bottom-left-radius:var(--mecx-filter-bar-radius)}.mecx-filter-chip-action{display:inline-flex;align-items:center;height:var(--mecx-filter-bar-control-height);padding:2px;box-sizing:border-box;background:var(--mecx-color-gray-50);border:1px solid var(--mecx-color-gray-500);border-top-right-radius:var(--mecx-filter-bar-radius);border-bottom-right-radius:var(--mecx-filter-bar-radius)}.mecx-filter-chip--disabled .mecx-filter-chip-action{border-color:var(--mecx-color-gray-400)}.mecx-filter-chip-remove{--mecx-filter-bar-bin: 24px;--mecx-filter-bar-bin-reach: calc((var(--mecx-filter-bar-bin) - var(--mecx-filter-bar-pointer-target)) / 2);position:relative;display:inline-flex;align-items:center;justify-content:center;width:var(--mecx-filter-bar-bin);height:var(--mecx-filter-bar-bin);padding:0;background:transparent;border:none;border-radius:var(--mecx-filter-bar-radius-item);color:var(--mecx-color-gray-700);cursor:pointer;outline:none;transition:background-color var(--mecx-filter-bar-duration-state) var(--mecx-filter-bar-ease-state)}.mecx-filter-chip-remove:after{content:\"\";position:absolute;inset:var(--mecx-filter-bar-bin-reach) var(--mecx-filter-bar-bin-reach) var(--mecx-filter-bar-bin-reach) 0}.mecx-filter-chip-remove .mk-i{display:flex;font-size:16px}.mecx-filter-chip-remove:hover{background-color:var(--mecx-color-gray-200);color:var(--mecx-color-error-main)}.mecx-filter-chip-remove:active{background-color:var(--mecx-color-gray-400)}.mecx-filter-chip-remove:focus-visible{outline:2px solid var(--mecx-color-gray-900);outline-offset:-2px}.mecx-filter-chip-remove:disabled{background-color:transparent;color:var(--mecx-color-gray-400);cursor:not-allowed}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
|
|
6888
6099
|
}
|
|
6889
6100
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: MonkeyFilterChipComponent, decorators: [{
|
|
6890
6101
|
type: Component,
|
|
6891
6102
|
args: [{ selector: 'monkey-filter-chip', changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, host: {
|
|
6892
6103
|
'data-testid': 'monkey-filter-chip',
|
|
6893
|
-
class: 'mecx-filter-chip'
|
|
6894
|
-
|
|
6895
|
-
|
|
6104
|
+
class: 'mecx-filter-chip',
|
|
6105
|
+
'[class.mecx-filter-chip--disabled]': 'disabled()'
|
|
6106
|
+
}, template: "<ng-content></ng-content>\n<span class=\"mecx-filter-chip-action\">\n <button\n class=\"mecx-filter-chip-remove\"\n type=\"button\"\n [disabled]=\"disabled() || null\"\n [attr.aria-label]=\"removeLabel()\"\n (click)=\"onRemove.emit()\"\n >\n <i class=\"mk-i mk-i-{{ removeIcon() }}\" aria-hidden=\"true\"></i>\n </button>\n</span>\n", styles: [".mecx-filter-chip{--mecx-filter-bar-duration-state: .15s;--mecx-filter-bar-duration-enter: .2s;--mecx-filter-bar-duration-exit: .15s;--mecx-filter-bar-ease-state: cubic-bezier(.25, .46, .45, .94);--mecx-filter-bar-ease-enter: cubic-bezier(.32, .72, 0, 1);--mecx-filter-bar-ease-exit: cubic-bezier(.4, 0, 1, 1);--mecx-filter-bar-scale-unfold: .94;--mecx-filter-bar-travel-anchored: 4px;--mecx-filter-bar-travel-slide: 16px;--mecx-filter-bar-stagger: 25ms;--mecx-filter-bar-control-height: 32px;--mecx-filter-bar-pointer-target: 40px;--mecx-filter-bar-reach: calc((var(--mecx-filter-bar-control-height) - var(--mecx-filter-bar-pointer-target)) / 2);--mecx-filter-bar-radius: 8px;--mecx-filter-bar-radius-item: 4px;--mecx-filter-bar-fade-width: 48px}@media(prefers-reduced-motion:reduce){.mecx-filter-chip{--mecx-filter-bar-duration-state: 1ms;--mecx-filter-bar-duration-enter: 1ms;--mecx-filter-bar-duration-exit: 1ms;--mecx-filter-bar-scale-unfold: 1;--mecx-filter-bar-travel-anchored: 0px;--mecx-filter-bar-travel-slide: 0px;--mecx-filter-bar-stagger: 0ms}}.mecx-filter-chip{display:inline-flex;align-items:center}.mecx-filter-chip>monkey-filter-segment:first-child .mecx-filter-segment-btn{border-top-left-radius:var(--mecx-filter-bar-radius);border-bottom-left-radius:var(--mecx-filter-bar-radius)}.mecx-filter-chip-action{display:inline-flex;align-items:center;height:var(--mecx-filter-bar-control-height);padding:2px;box-sizing:border-box;background:var(--mecx-color-gray-50);border:1px solid var(--mecx-color-gray-500);border-top-right-radius:var(--mecx-filter-bar-radius);border-bottom-right-radius:var(--mecx-filter-bar-radius)}.mecx-filter-chip--disabled .mecx-filter-chip-action{border-color:var(--mecx-color-gray-400)}.mecx-filter-chip-remove{--mecx-filter-bar-bin: 24px;--mecx-filter-bar-bin-reach: calc((var(--mecx-filter-bar-bin) - var(--mecx-filter-bar-pointer-target)) / 2);position:relative;display:inline-flex;align-items:center;justify-content:center;width:var(--mecx-filter-bar-bin);height:var(--mecx-filter-bar-bin);padding:0;background:transparent;border:none;border-radius:var(--mecx-filter-bar-radius-item);color:var(--mecx-color-gray-700);cursor:pointer;outline:none;transition:background-color var(--mecx-filter-bar-duration-state) var(--mecx-filter-bar-ease-state)}.mecx-filter-chip-remove:after{content:\"\";position:absolute;inset:var(--mecx-filter-bar-bin-reach) var(--mecx-filter-bar-bin-reach) var(--mecx-filter-bar-bin-reach) 0}.mecx-filter-chip-remove .mk-i{display:flex;font-size:16px}.mecx-filter-chip-remove:hover{background-color:var(--mecx-color-gray-200);color:var(--mecx-color-error-main)}.mecx-filter-chip-remove:active{background-color:var(--mecx-color-gray-400)}.mecx-filter-chip-remove:focus-visible{outline:2px solid var(--mecx-color-gray-900);outline-offset:-2px}.mecx-filter-chip-remove:disabled{background-color:transparent;color:var(--mecx-color-gray-400);cursor:not-allowed}\n"] }]
|
|
6107
|
+
}], propDecorators: { removeIcon: [{ type: i0.Input, args: [{ isSignal: true, alias: "removeIcon", required: false }] }], removeLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "removeLabel", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], onRemove: [{ type: i0.Output, args: ["onRemove"] }] } });
|
|
6896
6108
|
|
|
6897
6109
|
/** ************************
|
|
6898
6110
|
* Copyright Monkey Exchange. All Rights Reserved
|
|
6899
6111
|
* This style guide was developed by Monkey Exchange Team
|
|
6900
6112
|
* MIT Licence
|
|
6901
6113
|
************************* */
|
|
6902
|
-
/**
|
|
6903
|
-
* The panel every dropdown of monkey-filter-bar-v2 opens: a surface with an
|
|
6904
|
-
* optional search field on top and the projected rows below it.
|
|
6905
|
-
*
|
|
6906
|
-
* Only the WIDTH changes from one panel to the next, and it is set from the
|
|
6907
|
-
* bar's own stylesheet through a class on this host — the panel component has
|
|
6908
|
-
* no opinion on how wide a company list should be.
|
|
6909
|
-
*
|
|
6910
|
-
* `width` and not `min-width` on those classes: each panel is a fixed-width
|
|
6911
|
-
* frame in the design and a long label ellipsizes inside it. With a floor the
|
|
6912
|
-
* content would win, and the measurement would turn into a suggestion.
|
|
6913
|
-
*/
|
|
6914
6114
|
class MonkeyFilterMenuComponent {
|
|
6915
6115
|
constructor() {
|
|
6116
|
+
this._zone = inject(NgZone);
|
|
6117
|
+
this._items = viewChild('items', ...(ngDevMode ? [{ debugName: "_items" }] : /* istanbul ignore next */ []));
|
|
6118
|
+
this._overflowing = signal(false, ...(ngDevMode ? [{ debugName: "_overflowing" }] : /* istanbul ignore next */ []));
|
|
6916
6119
|
this.showSearch = input(false, { ...(ngDevMode ? { debugName: "showSearch" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
|
|
6917
|
-
this.searchPlaceholder = input('
|
|
6918
|
-
/** Lets the row list scroll instead of growing past the viewport. */
|
|
6120
|
+
this.searchPlaceholder = input('', ...(ngDevMode ? [{ debugName: "searchPlaceholder" }] : /* istanbul ignore next */ []));
|
|
6919
6121
|
this.showScroll = input(true, { ...(ngDevMode ? { debugName: "showScroll" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
|
|
6920
|
-
/** Ceiling of the scrolling list, in px. */
|
|
6921
6122
|
this.maxHeight = input(240, ...(ngDevMode ? [{ debugName: "maxHeight" }] : /* istanbul ignore next */ []));
|
|
6922
|
-
this.
|
|
6123
|
+
this.onSearchChange = output();
|
|
6923
6124
|
this.searchValue = '';
|
|
6924
|
-
this._zone = inject(NgZone);
|
|
6925
|
-
this._items = viewChild('items', ...(ngDevMode ? [{ debugName: "_items" }] : /* istanbul ignore next */ []));
|
|
6926
|
-
/** Is the list actually overflowing right now? */
|
|
6927
|
-
this._overflowing = signal(false, ...(ngDevMode ? [{ debugName: "_overflowing" }] : /* istanbul ignore next */ []));
|
|
6928
|
-
/**
|
|
6929
|
-
* Draw the track only when the content OVERFLOWS.
|
|
6930
|
-
*
|
|
6931
|
-
* Tied to `showScroll` alone, a three-row panel lost 12px of width to a
|
|
6932
|
-
* track that was never going to appear.
|
|
6933
|
-
*/
|
|
6934
6125
|
this.scrolling = computed(() => {
|
|
6935
6126
|
return this.showScroll() && this._overflowing();
|
|
6936
6127
|
}, ...(ngDevMode ? [{ debugName: "scrolling" }] : /* istanbul ignore next */ []));
|
|
@@ -6938,9 +6129,6 @@ class MonkeyFilterMenuComponent {
|
|
|
6938
6129
|
const items = this._items()?.nativeElement;
|
|
6939
6130
|
if (!items)
|
|
6940
6131
|
return;
|
|
6941
|
-
// Outside the Angular zone: a zone-patched observer costs a global
|
|
6942
|
-
// change-detection pass per callback, and the signal written below
|
|
6943
|
-
// already schedules one by itself when the value actually changes.
|
|
6944
6132
|
this._zone.runOutsideAngular(() => {
|
|
6945
6133
|
this._observer = new ResizeObserver(() => {
|
|
6946
6134
|
this._overflowing.set(items.scrollHeight - items.clientHeight > 1);
|
|
@@ -6951,66 +6139,55 @@ class MonkeyFilterMenuComponent {
|
|
|
6951
6139
|
});
|
|
6952
6140
|
});
|
|
6953
6141
|
onCleanup(() => {
|
|
6954
|
-
return this.
|
|
6142
|
+
return this.disconnect();
|
|
6955
6143
|
});
|
|
6956
6144
|
});
|
|
6957
6145
|
}
|
|
6146
|
+
disconnect() {
|
|
6147
|
+
this._observer?.disconnect();
|
|
6148
|
+
this._observer = undefined;
|
|
6149
|
+
}
|
|
6958
6150
|
ngOnDestroy() {
|
|
6959
|
-
this.
|
|
6151
|
+
this.disconnect();
|
|
6960
6152
|
}
|
|
6961
6153
|
onSearchInput(value) {
|
|
6962
6154
|
this.searchValue = value;
|
|
6963
|
-
this.
|
|
6964
|
-
}
|
|
6965
|
-
_disconnect() {
|
|
6966
|
-
this._observer?.disconnect();
|
|
6967
|
-
this._observer = undefined;
|
|
6155
|
+
this.onSearchChange.emit(value);
|
|
6968
6156
|
}
|
|
6969
6157
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: MonkeyFilterMenuComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
6970
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.4", type: MonkeyFilterMenuComponent, isStandalone: true, selector: "monkey-filter-menu", inputs: { showSearch: { classPropertyName: "showSearch", publicName: "showSearch", isSignal: true, isRequired: false, transformFunction: null }, searchPlaceholder: { classPropertyName: "searchPlaceholder", publicName: "searchPlaceholder", isSignal: true, isRequired: false, transformFunction: null }, showScroll: { classPropertyName: "showScroll", publicName: "showScroll", isSignal: true, isRequired: false, transformFunction: null }, maxHeight: { classPropertyName: "maxHeight", publicName: "maxHeight", isSignal: true, isRequired: false, transformFunction: null } }, outputs: {
|
|
6158
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.4", type: MonkeyFilterMenuComponent, isStandalone: true, selector: "monkey-filter-menu", inputs: { showSearch: { classPropertyName: "showSearch", publicName: "showSearch", isSignal: true, isRequired: false, transformFunction: null }, searchPlaceholder: { classPropertyName: "searchPlaceholder", publicName: "searchPlaceholder", isSignal: true, isRequired: false, transformFunction: null }, showScroll: { classPropertyName: "showScroll", publicName: "showScroll", isSignal: true, isRequired: false, transformFunction: null }, maxHeight: { classPropertyName: "maxHeight", publicName: "maxHeight", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { onSearchChange: "onSearchChange" }, host: { attributes: { "data-testid": "monkey-filter-menu" }, classAttribute: "mecx-filter-menu" }, viewQueries: [{ propertyName: "_items", first: true, predicate: ["items"], descendants: true, isSignal: true }], ngImport: i0, template: "@if (showSearch()) {\n <div class=\"mecx-filter-menu-search\">\n <monkey-form-field size=\"sm\" noFooterSpace>\n <input\n type=\"text\"\n monkey-input\n [placeholder]=\"searchPlaceholder()\"\n [ngModel]=\"searchValue\"\n (ngModelChange)=\"onSearchInput($event)\"\n />\n <monkey-prefix>\n <i class=\"mk-i mk-i-search fs-md\"></i>\n </monkey-prefix>\n </monkey-form-field>\n </div>\n}\n\n<div\n #items\n class=\"mecx-filter-menu-items\"\n [class.mecx-filter-menu-items--scroll]=\"showScroll()\"\n [class.mecx-filter-menu-items--scrolling]=\"scrolling()\"\n [style.max-height.px]=\"showScroll() ? maxHeight() : null\"\n>\n <ng-content></ng-content>\n</div>\n", styles: [".mecx-filter-menu{--mecx-filter-bar-duration-state: .15s;--mecx-filter-bar-duration-enter: .2s;--mecx-filter-bar-duration-exit: .15s;--mecx-filter-bar-ease-state: cubic-bezier(.25, .46, .45, .94);--mecx-filter-bar-ease-enter: cubic-bezier(.32, .72, 0, 1);--mecx-filter-bar-ease-exit: cubic-bezier(.4, 0, 1, 1);--mecx-filter-bar-scale-unfold: .94;--mecx-filter-bar-travel-anchored: 4px;--mecx-filter-bar-travel-slide: 16px;--mecx-filter-bar-stagger: 25ms;--mecx-filter-bar-control-height: 32px;--mecx-filter-bar-pointer-target: 40px;--mecx-filter-bar-reach: calc((var(--mecx-filter-bar-control-height) - var(--mecx-filter-bar-pointer-target)) / 2);--mecx-filter-bar-radius: 8px;--mecx-filter-bar-radius-item: 4px;--mecx-filter-bar-fade-width: 48px}@media(prefers-reduced-motion:reduce){.mecx-filter-menu{--mecx-filter-bar-duration-state: 1ms;--mecx-filter-bar-duration-enter: 1ms;--mecx-filter-bar-duration-exit: 1ms;--mecx-filter-bar-scale-unfold: 1;--mecx-filter-bar-travel-anchored: 0px;--mecx-filter-bar-travel-slide: 0px;--mecx-filter-bar-stagger: 0ms}}.mecx-filter-menu{display:flex;flex-direction:column;min-width:158px;max-width:341px;background:var(--mecx-color-white);border:2px solid var(--mecx-color-gray-200);border-radius:var(--mecx-filter-bar-radius);box-shadow:0 8px 12px -4px var(--mecx-color-box-shadow, rgba(47, 50, 55, .08));overflow:hidden;box-sizing:border-box}.mecx-filter-menu-search{padding:8px;border-bottom:2px solid var(--mecx-color-gray-200);flex-shrink:0}.mecx-filter-menu-search monkey-form-field{width:100%;display:block}.mecx-filter-menu-items{display:flex;flex-direction:column;padding:8px}.mecx-filter-menu-items--scroll{overflow-y:auto}.mecx-filter-menu-items--scrolling{scrollbar-gutter:stable;padding-right:0}.mecx-filter-menu-items--scrolling::-webkit-scrollbar{width:20px}.mecx-filter-menu-items--scrolling::-webkit-scrollbar-track{background:var(--mecx-color-gray-100);background-clip:padding-box;border-left:4px solid transparent;border-right:8px solid transparent;border-radius:8px 12px 12px 8px/4px;box-shadow:inset 0 0 0 1px var(--mecx-color-gray-400);margin:8px 0}.mecx-filter-menu-items--scrolling::-webkit-scrollbar-thumb{background:var(--mecx-color-gray-800);background-clip:padding-box;border-left:5px solid transparent;border-right:9px solid transparent;border-radius:8px 12px 12px 8px/3px}.mecx-filter-menu-items>monkey-divider{margin-block:4px}.mecx-filter-menu-items>*{flex-shrink:0}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: MonkeyFormFieldModule }, { kind: "component", type: MonkeyFormFieldComponent, selector: "monkey-form-field", inputs: ["id", "hideAction", "enableClear", "size", "noFooterSpace", "displayOnly"], outputs: ["onDisplayOnlyChange"], exportAs: ["monkeyFormField"] }, { kind: "ngmodule", type: MonkeyInputModule }, { kind: "directive", type: MonkeyInputDirective, selector: "input[monkey-input],textarea[monkey-input]", inputs: ["name", "disabled", "id", "required", "type", "min", "max", "percent"], exportAs: ["monkeyInput"] }, { kind: "directive", type: MonkeyPrefixDirective, selector: "monkey-prefix" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
|
|
6971
6159
|
}
|
|
6972
6160
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: MonkeyFilterMenuComponent, decorators: [{
|
|
6973
6161
|
type: Component,
|
|
6974
6162
|
args: [{ selector: 'monkey-filter-menu', imports: [FormsModule, MonkeyFormFieldModule, MonkeyInputModule, MonkeyPrefixDirective], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, host: {
|
|
6975
6163
|
'data-testid': 'monkey-filter-menu',
|
|
6976
6164
|
class: 'mecx-filter-menu'
|
|
6977
|
-
}, template: "
|
|
6978
|
-
}], ctorParameters: () => [], propDecorators: { showSearch: [{ type: i0.Input, args: [{ isSignal: true, alias: "showSearch", required: false }] }], searchPlaceholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "searchPlaceholder", required: false }] }], showScroll: [{ type: i0.Input, args: [{ isSignal: true, alias: "showScroll", required: false }] }], maxHeight: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxHeight", required: false }] }],
|
|
6165
|
+
}, template: "@if (showSearch()) {\n <div class=\"mecx-filter-menu-search\">\n <monkey-form-field size=\"sm\" noFooterSpace>\n <input\n type=\"text\"\n monkey-input\n [placeholder]=\"searchPlaceholder()\"\n [ngModel]=\"searchValue\"\n (ngModelChange)=\"onSearchInput($event)\"\n />\n <monkey-prefix>\n <i class=\"mk-i mk-i-search fs-md\"></i>\n </monkey-prefix>\n </monkey-form-field>\n </div>\n}\n\n<div\n #items\n class=\"mecx-filter-menu-items\"\n [class.mecx-filter-menu-items--scroll]=\"showScroll()\"\n [class.mecx-filter-menu-items--scrolling]=\"scrolling()\"\n [style.max-height.px]=\"showScroll() ? maxHeight() : null\"\n>\n <ng-content></ng-content>\n</div>\n", styles: [".mecx-filter-menu{--mecx-filter-bar-duration-state: .15s;--mecx-filter-bar-duration-enter: .2s;--mecx-filter-bar-duration-exit: .15s;--mecx-filter-bar-ease-state: cubic-bezier(.25, .46, .45, .94);--mecx-filter-bar-ease-enter: cubic-bezier(.32, .72, 0, 1);--mecx-filter-bar-ease-exit: cubic-bezier(.4, 0, 1, 1);--mecx-filter-bar-scale-unfold: .94;--mecx-filter-bar-travel-anchored: 4px;--mecx-filter-bar-travel-slide: 16px;--mecx-filter-bar-stagger: 25ms;--mecx-filter-bar-control-height: 32px;--mecx-filter-bar-pointer-target: 40px;--mecx-filter-bar-reach: calc((var(--mecx-filter-bar-control-height) - var(--mecx-filter-bar-pointer-target)) / 2);--mecx-filter-bar-radius: 8px;--mecx-filter-bar-radius-item: 4px;--mecx-filter-bar-fade-width: 48px}@media(prefers-reduced-motion:reduce){.mecx-filter-menu{--mecx-filter-bar-duration-state: 1ms;--mecx-filter-bar-duration-enter: 1ms;--mecx-filter-bar-duration-exit: 1ms;--mecx-filter-bar-scale-unfold: 1;--mecx-filter-bar-travel-anchored: 0px;--mecx-filter-bar-travel-slide: 0px;--mecx-filter-bar-stagger: 0ms}}.mecx-filter-menu{display:flex;flex-direction:column;min-width:158px;max-width:341px;background:var(--mecx-color-white);border:2px solid var(--mecx-color-gray-200);border-radius:var(--mecx-filter-bar-radius);box-shadow:0 8px 12px -4px var(--mecx-color-box-shadow, rgba(47, 50, 55, .08));overflow:hidden;box-sizing:border-box}.mecx-filter-menu-search{padding:8px;border-bottom:2px solid var(--mecx-color-gray-200);flex-shrink:0}.mecx-filter-menu-search monkey-form-field{width:100%;display:block}.mecx-filter-menu-items{display:flex;flex-direction:column;padding:8px}.mecx-filter-menu-items--scroll{overflow-y:auto}.mecx-filter-menu-items--scrolling{scrollbar-gutter:stable;padding-right:0}.mecx-filter-menu-items--scrolling::-webkit-scrollbar{width:20px}.mecx-filter-menu-items--scrolling::-webkit-scrollbar-track{background:var(--mecx-color-gray-100);background-clip:padding-box;border-left:4px solid transparent;border-right:8px solid transparent;border-radius:8px 12px 12px 8px/4px;box-shadow:inset 0 0 0 1px var(--mecx-color-gray-400);margin:8px 0}.mecx-filter-menu-items--scrolling::-webkit-scrollbar-thumb{background:var(--mecx-color-gray-800);background-clip:padding-box;border-left:5px solid transparent;border-right:9px solid transparent;border-radius:8px 12px 12px 8px/3px}.mecx-filter-menu-items>monkey-divider{margin-block:4px}.mecx-filter-menu-items>*{flex-shrink:0}\n"] }]
|
|
6166
|
+
}], ctorParameters: () => [], propDecorators: { _items: [{ type: i0.ViewChild, args: ['items', { isSignal: true }] }], showSearch: [{ type: i0.Input, args: [{ isSignal: true, alias: "showSearch", required: false }] }], searchPlaceholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "searchPlaceholder", required: false }] }], showScroll: [{ type: i0.Input, args: [{ isSignal: true, alias: "showScroll", required: false }] }], maxHeight: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxHeight", required: false }] }], onSearchChange: [{ type: i0.Output, args: ["onSearchChange"] }] } });
|
|
6979
6167
|
|
|
6980
6168
|
/** ************************
|
|
6981
6169
|
* Copyright Monkey Exchange. All Rights Reserved
|
|
6982
6170
|
* This style guide was developed by Monkey Exchange Team
|
|
6983
6171
|
* MIT Licence
|
|
6984
6172
|
************************* */
|
|
6985
|
-
/**
|
|
6986
|
-
* One row of a monkey-filter-menu.
|
|
6987
|
-
*
|
|
6988
|
-
* The ROW is the click target, which is why the checkbox inside it does not
|
|
6989
|
-
* grow one of its own: the boxes sit 18px apart inside rows of 32px that touch
|
|
6990
|
-
* each other, so a 40px floor on each would make two targets OVERLAP by 8px —
|
|
6991
|
-
* inside rows that are already clickable end to end.
|
|
6992
|
-
*/
|
|
6993
6173
|
class MonkeyFilterMenuItemComponent {
|
|
6994
6174
|
constructor() {
|
|
6995
6175
|
this.property = input('text', ...(ngDevMode ? [{ debugName: "property" }] : /* istanbul ignore next */ []));
|
|
6996
|
-
/** Icon font name, without the `mk-i-` prefix. */
|
|
6997
6176
|
this.leadIcon = input(null, ...(ngDevMode ? [{ debugName: "leadIcon" }] : /* istanbul ignore next */ []));
|
|
6998
6177
|
this.label = input('', ...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
|
|
6999
|
-
/** Secondary line under the label — a document number, a key. */
|
|
7000
6178
|
this.description = input(null, ...(ngDevMode ? [{ debugName: "description" }] : /* istanbul ignore next */ []));
|
|
7001
6179
|
this.checked = input(false, { ...(ngDevMode ? { debugName: "checked" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
|
|
7002
|
-
/** Already answered elsewhere: the row shows a check and stops responding. */
|
|
7003
6180
|
this.selected = input(false, { ...(ngDevMode ? { debugName: "selected" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
|
|
7004
6181
|
this.disabled = input(false, { ...(ngDevMode ? { debugName: "disabled" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
|
|
7005
|
-
this.
|
|
6182
|
+
this.onItemClick = output();
|
|
7006
6183
|
}
|
|
7007
6184
|
onClick() {
|
|
7008
6185
|
if (this.disabled())
|
|
7009
6186
|
return;
|
|
7010
|
-
this.
|
|
6187
|
+
this.onItemClick.emit();
|
|
7011
6188
|
}
|
|
7012
6189
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: MonkeyFilterMenuItemComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
7013
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.4", type: MonkeyFilterMenuItemComponent, isStandalone: true, selector: "monkey-filter-menu-item", inputs: { property: { classPropertyName: "property", publicName: "property", isSignal: true, isRequired: false, transformFunction: null }, leadIcon: { classPropertyName: "leadIcon", publicName: "leadIcon", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, description: { classPropertyName: "description", publicName: "description", isSignal: true, isRequired: false, transformFunction: null }, checked: { classPropertyName: "checked", publicName: "checked", isSignal: true, isRequired: false, transformFunction: null }, selected: { classPropertyName: "selected", publicName: "selected", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null } }, outputs: {
|
|
6190
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.4", type: MonkeyFilterMenuItemComponent, isStandalone: true, selector: "monkey-filter-menu-item", inputs: { property: { classPropertyName: "property", publicName: "property", isSignal: true, isRequired: false, transformFunction: null }, leadIcon: { classPropertyName: "leadIcon", publicName: "leadIcon", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, description: { classPropertyName: "description", publicName: "description", isSignal: true, isRequired: false, transformFunction: null }, checked: { classPropertyName: "checked", publicName: "checked", isSignal: true, isRequired: false, transformFunction: null }, selected: { classPropertyName: "selected", publicName: "selected", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { onItemClick: "onItemClick" }, host: { attributes: { "data-testid": "monkey-filter-menu-item", "role": "option" }, listeners: { "click": "onClick()" }, properties: { "class.mecx-filter-menu-item--disabled": "disabled()", "class.mecx-filter-menu-item--selected": "selected()", "attr.aria-selected": "selected() || checked()", "attr.aria-disabled": "disabled() || null" }, classAttribute: "mecx-filter-menu-item" }, ngImport: i0, template: "@if (property() === 'checkbox') {\n <monkey-checkbox\n class=\"mecx-filter-menu-item-checkbox\"\n size=\"sm\"\n [value]=\"checked()\"\n [disabled]=\"disabled()\"\n [showFooter]=\"false\"\n ></monkey-checkbox>\n} @else if (leadIcon()) {\n <i class=\"mk-i mk-i-{{ leadIcon() }} mecx-filter-menu-item-icon\"></i>\n}\n\n<span class=\"mecx-filter-menu-item-text\">\n <span class=\"mecx-filter-menu-item-label\">{{ label() }}</span>\n @if (description()) {\n <span class=\"mecx-filter-menu-item-description\">{{ description() }}</span>\n }\n</span>\n@if (selected()) {\n <i class=\"mk-i mk-i-check mecx-filter-menu-item-check\"></i>\n}\n", styles: [".mecx-filter-menu-item{--mecx-filter-bar-duration-state: .15s;--mecx-filter-bar-duration-enter: .2s;--mecx-filter-bar-duration-exit: .15s;--mecx-filter-bar-ease-state: cubic-bezier(.25, .46, .45, .94);--mecx-filter-bar-ease-enter: cubic-bezier(.32, .72, 0, 1);--mecx-filter-bar-ease-exit: cubic-bezier(.4, 0, 1, 1);--mecx-filter-bar-scale-unfold: .94;--mecx-filter-bar-travel-anchored: 4px;--mecx-filter-bar-travel-slide: 16px;--mecx-filter-bar-stagger: 25ms;--mecx-filter-bar-control-height: 32px;--mecx-filter-bar-pointer-target: 40px;--mecx-filter-bar-reach: calc((var(--mecx-filter-bar-control-height) - var(--mecx-filter-bar-pointer-target)) / 2);--mecx-filter-bar-radius: 8px;--mecx-filter-bar-radius-item: 4px;--mecx-filter-bar-fade-width: 48px}@media(prefers-reduced-motion:reduce){.mecx-filter-menu-item{--mecx-filter-bar-duration-state: 1ms;--mecx-filter-bar-duration-enter: 1ms;--mecx-filter-bar-duration-exit: 1ms;--mecx-filter-bar-scale-unfold: 1;--mecx-filter-bar-travel-anchored: 0px;--mecx-filter-bar-travel-slide: 0px;--mecx-filter-bar-stagger: 0ms}}.mecx-filter-menu-item{display:flex;align-items:center;gap:8px;padding:8px;background:var(--mecx-color-white);border-radius:var(--mecx-filter-bar-radius-item);cursor:pointer;width:100%;box-sizing:border-box;-webkit-user-select:none;user-select:none;transition:background-color var(--mecx-filter-bar-duration-state) var(--mecx-filter-bar-ease-state),scale var(--mecx-filter-bar-duration-state) var(--mecx-filter-bar-ease-state)}.mecx-filter-menu-item:hover:not(.mecx-filter-menu-item--disabled){background-color:var(--mecx-color-gray-100)}.mecx-filter-menu-item:active:not(.mecx-filter-menu-item--disabled){scale:.99}.mecx-filter-menu-item--disabled{cursor:not-allowed}.mecx-filter-menu-item--disabled .mecx-filter-menu-item-label,.mecx-filter-menu-item--disabled .mecx-filter-menu-item-description,.mecx-filter-menu-item--disabled .mecx-filter-menu-item-icon{color:var(--mecx-color-gray-400)}.mecx-filter-menu-item-icon{display:flex;flex-shrink:0;font-size:16px;color:var(--mecx-color-gray-700)}.mecx-filter-menu-item-checkbox{flex-shrink:0;pointer-events:none}.mecx-filter-menu-item-text{display:flex;flex-direction:column;gap:4px;flex:1 0 0;min-width:0}.mecx-filter-menu-item-label{display:block;font-size:13px;font-weight:400;line-height:16px;letter-spacing:.02em;color:var(--mecx-color-gray-900);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.mecx-filter-menu-item-description{display:block;font-size:13px;font-weight:400;line-height:16px;letter-spacing:.02em;color:var(--mecx-color-gray-700)}.mecx-filter-menu-item-check{display:flex;flex-shrink:0;font-size:12px;color:var(--mecx-color-theme-main)}\n"], dependencies: [{ kind: "component", type: MonkeyCheckboxComponent, selector: "monkey-checkbox", inputs: ["disabled", "indeterminate", "required", "showFooter", "size", "value"], outputs: ["onChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
|
|
7014
6191
|
}
|
|
7015
6192
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: MonkeyFilterMenuItemComponent, decorators: [{
|
|
7016
6193
|
type: Component,
|
|
@@ -7023,38 +6200,15 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImpor
|
|
|
7023
6200
|
'[attr.aria-selected]': 'selected() || checked()',
|
|
7024
6201
|
'[attr.aria-disabled]': 'disabled() || null',
|
|
7025
6202
|
'(click)': 'onClick()'
|
|
7026
|
-
}, template: "@if (property() === 'checkbox') {\n <monkey-checkbox\n class=\"mecx-filter-menu-item-checkbox\"\n size=\"sm\"\n [value]=\"checked()\"\n [disabled]=\"disabled()\"\n [showFooter]=\"false\"\n ></monkey-checkbox>\n} @else if (leadIcon()) {\n <i class=\"mk-i mk-i-{{ leadIcon() }} mecx-filter-menu-item-icon\"></i>\n}\n\n<span class=\"mecx-filter-menu-item-text\">\n <span class=\"mecx-filter-menu-item-label\">{{ label() }}</span>\n @if (description()) {\n <span class=\"mecx-filter-menu-item-description\">{{ description() }}</span>\n }\n</span>\n
|
|
7027
|
-
}], propDecorators: { property: [{ type: i0.Input, args: [{ isSignal: true, alias: "property", required: false }] }], leadIcon: [{ type: i0.Input, args: [{ isSignal: true, alias: "leadIcon", required: false }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], description: [{ type: i0.Input, args: [{ isSignal: true, alias: "description", required: false }] }], checked: [{ type: i0.Input, args: [{ isSignal: true, alias: "checked", required: false }] }], selected: [{ type: i0.Input, args: [{ isSignal: true, alias: "selected", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }],
|
|
6203
|
+
}, template: "@if (property() === 'checkbox') {\n <monkey-checkbox\n class=\"mecx-filter-menu-item-checkbox\"\n size=\"sm\"\n [value]=\"checked()\"\n [disabled]=\"disabled()\"\n [showFooter]=\"false\"\n ></monkey-checkbox>\n} @else if (leadIcon()) {\n <i class=\"mk-i mk-i-{{ leadIcon() }} mecx-filter-menu-item-icon\"></i>\n}\n\n<span class=\"mecx-filter-menu-item-text\">\n <span class=\"mecx-filter-menu-item-label\">{{ label() }}</span>\n @if (description()) {\n <span class=\"mecx-filter-menu-item-description\">{{ description() }}</span>\n }\n</span>\n@if (selected()) {\n <i class=\"mk-i mk-i-check mecx-filter-menu-item-check\"></i>\n}\n", styles: [".mecx-filter-menu-item{--mecx-filter-bar-duration-state: .15s;--mecx-filter-bar-duration-enter: .2s;--mecx-filter-bar-duration-exit: .15s;--mecx-filter-bar-ease-state: cubic-bezier(.25, .46, .45, .94);--mecx-filter-bar-ease-enter: cubic-bezier(.32, .72, 0, 1);--mecx-filter-bar-ease-exit: cubic-bezier(.4, 0, 1, 1);--mecx-filter-bar-scale-unfold: .94;--mecx-filter-bar-travel-anchored: 4px;--mecx-filter-bar-travel-slide: 16px;--mecx-filter-bar-stagger: 25ms;--mecx-filter-bar-control-height: 32px;--mecx-filter-bar-pointer-target: 40px;--mecx-filter-bar-reach: calc((var(--mecx-filter-bar-control-height) - var(--mecx-filter-bar-pointer-target)) / 2);--mecx-filter-bar-radius: 8px;--mecx-filter-bar-radius-item: 4px;--mecx-filter-bar-fade-width: 48px}@media(prefers-reduced-motion:reduce){.mecx-filter-menu-item{--mecx-filter-bar-duration-state: 1ms;--mecx-filter-bar-duration-enter: 1ms;--mecx-filter-bar-duration-exit: 1ms;--mecx-filter-bar-scale-unfold: 1;--mecx-filter-bar-travel-anchored: 0px;--mecx-filter-bar-travel-slide: 0px;--mecx-filter-bar-stagger: 0ms}}.mecx-filter-menu-item{display:flex;align-items:center;gap:8px;padding:8px;background:var(--mecx-color-white);border-radius:var(--mecx-filter-bar-radius-item);cursor:pointer;width:100%;box-sizing:border-box;-webkit-user-select:none;user-select:none;transition:background-color var(--mecx-filter-bar-duration-state) var(--mecx-filter-bar-ease-state),scale var(--mecx-filter-bar-duration-state) var(--mecx-filter-bar-ease-state)}.mecx-filter-menu-item:hover:not(.mecx-filter-menu-item--disabled){background-color:var(--mecx-color-gray-100)}.mecx-filter-menu-item:active:not(.mecx-filter-menu-item--disabled){scale:.99}.mecx-filter-menu-item--disabled{cursor:not-allowed}.mecx-filter-menu-item--disabled .mecx-filter-menu-item-label,.mecx-filter-menu-item--disabled .mecx-filter-menu-item-description,.mecx-filter-menu-item--disabled .mecx-filter-menu-item-icon{color:var(--mecx-color-gray-400)}.mecx-filter-menu-item-icon{display:flex;flex-shrink:0;font-size:16px;color:var(--mecx-color-gray-700)}.mecx-filter-menu-item-checkbox{flex-shrink:0;pointer-events:none}.mecx-filter-menu-item-text{display:flex;flex-direction:column;gap:4px;flex:1 0 0;min-width:0}.mecx-filter-menu-item-label{display:block;font-size:13px;font-weight:400;line-height:16px;letter-spacing:.02em;color:var(--mecx-color-gray-900);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.mecx-filter-menu-item-description{display:block;font-size:13px;font-weight:400;line-height:16px;letter-spacing:.02em;color:var(--mecx-color-gray-700)}.mecx-filter-menu-item-check{display:flex;flex-shrink:0;font-size:12px;color:var(--mecx-color-theme-main)}\n"] }]
|
|
6204
|
+
}], propDecorators: { property: [{ type: i0.Input, args: [{ isSignal: true, alias: "property", required: false }] }], leadIcon: [{ type: i0.Input, args: [{ isSignal: true, alias: "leadIcon", required: false }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], description: [{ type: i0.Input, args: [{ isSignal: true, alias: "description", required: false }] }], checked: [{ type: i0.Input, args: [{ isSignal: true, alias: "checked", required: false }] }], selected: [{ type: i0.Input, args: [{ isSignal: true, alias: "selected", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], onItemClick: [{ type: i0.Output, args: ["onItemClick"] }] } });
|
|
7028
6205
|
|
|
7029
6206
|
/** ************************
|
|
7030
6207
|
* Copyright Monkey Exchange. All Rights Reserved
|
|
7031
6208
|
* This style guide was developed by Monkey Exchange Team
|
|
7032
6209
|
* MIT Licence
|
|
7033
6210
|
************************* */
|
|
7034
|
-
/**
|
|
7035
|
-
* Picks the panel's horizontal: align, FLIP, or butt against the edge.
|
|
7036
|
-
*
|
|
7037
|
-
* Three steps, in this order:
|
|
7038
|
-
*
|
|
7039
|
-
* 1. The preferred edge — the one `alignment` asks for.
|
|
7040
|
-
* 2. The OPPOSITE edge, when the preferred one does not fit. Aligned to the
|
|
7041
|
-
* start with no room to the right, the panel flips and ends where the
|
|
7042
|
-
* trigger ends, growing back into the screen.
|
|
7043
|
-
* 3. Clamped to the viewport, when not even flipped fits — i.e. when the
|
|
7044
|
-
* panel is WIDER than the viewport. There is no good position then, and
|
|
7045
|
-
* the fix is a narrower panel, not a better coordinate.
|
|
7046
|
-
*
|
|
7047
|
-
* Step 2 is the one that matters visually: nudging the panel just enough to
|
|
7048
|
-
* fit leaves it misaligned with BOTH edges of the trigger, looking displaced
|
|
7049
|
-
* for no reason. Flipped, it is still anchored to an edge — just the other one.
|
|
7050
|
-
*
|
|
7051
|
-
* A viewport of width 0 returns the preferred value without measuring. That is
|
|
7052
|
-
* not defensive padding: jsdom reports `clientWidth: 0`, and measuring against
|
|
7053
|
-
* zero would send every panel to the left edge.
|
|
7054
|
-
*/
|
|
7055
6211
|
function horizontalOf(target, width, gap, alignment) {
|
|
7056
|
-
// The horizontal gap is the panel's breathing room, not a one-sided border:
|
|
7057
|
-
// aligned to the end it pushes inwards, which is the mirrored gesture.
|
|
7058
6212
|
const atStart = target.left + gap;
|
|
7059
6213
|
const atEnd = target.right - width - gap;
|
|
7060
6214
|
const preferred = alignment === 'end' ? atEnd : atStart;
|
|
@@ -7071,19 +6225,6 @@ function horizontalOf(target, width, gap, alignment) {
|
|
|
7071
6225
|
return opposite;
|
|
7072
6226
|
return Math.max(0, Math.min(preferred, viewport - width));
|
|
7073
6227
|
}
|
|
7074
|
-
/**
|
|
7075
|
-
* The offset the panel is applying to ITSELF.
|
|
7076
|
-
*
|
|
7077
|
-
* `getBoundingClientRect` includes the element's own translate, and the
|
|
7078
|
-
* zero-measurement uses that rect to discover the containing block's origin.
|
|
7079
|
-
* Without subtracting this share, the translate of the ENTRANCE animation is
|
|
7080
|
-
* baked into `top` as if it were origin — and comes back out when the
|
|
7081
|
-
* animation ends, taking the panel with it.
|
|
7082
|
-
*
|
|
7083
|
-
* Only `translate` matters. The `scale` of the same animation does not move
|
|
7084
|
-
* the top edge, because the entrance fixes `transform-origin: top` and scales
|
|
7085
|
-
* X by 1.
|
|
7086
|
-
*/
|
|
7087
6228
|
function ownOffset(menu) {
|
|
7088
6229
|
const raw = getComputedStyle(menu).translate;
|
|
7089
6230
|
if (!raw || raw === 'none')
|
|
@@ -7091,26 +6232,6 @@ function ownOffset(menu) {
|
|
|
7091
6232
|
const [x, y] = raw.split(' ');
|
|
7092
6233
|
return { x: parseFloat(x) || 0, y: parseFloat(y ?? '') || 0 };
|
|
7093
6234
|
}
|
|
7094
|
-
/**
|
|
7095
|
-
* Butts the panel against the requested side of the trigger.
|
|
7096
|
-
*
|
|
7097
|
-
* The breathing room stays in the stylesheet, as the panel's `margin`. It has
|
|
7098
|
-
* to come back into the sum because the measurement ALREADY includes it:
|
|
7099
|
-
* without adding it again the margin would cancel itself out and the panel
|
|
7100
|
-
* would sit glued to the trigger.
|
|
7101
|
-
*
|
|
7102
|
-
* The containing block's origin comes out of the same sum without moving
|
|
7103
|
-
* anything: with `top: T` applied, `rect.top = origin + T + translate`, so
|
|
7104
|
-
* `origin = rect.top - T - translate`. All it takes is for the panel to have a
|
|
7105
|
-
* known inline `top`, which `anchorMenu` guarantees the first time round.
|
|
7106
|
-
*
|
|
7107
|
-
* The earlier way to find the origin was to write `top: 0; left: 0`, measure,
|
|
7108
|
-
* then write the final value. That was a round trip PER scroll event — dozens
|
|
7109
|
-
* a second on an inertial scroll, each one throwing the panel into the corner
|
|
7110
|
-
* and back with a forced layout read in between. The symptom is a panel
|
|
7111
|
-
* flickering between the right place and the top of the window instead of
|
|
7112
|
-
* following its trigger.
|
|
7113
|
-
*/
|
|
7114
6235
|
function place(target, menu, gaps, alignment) {
|
|
7115
6236
|
const own = ownOffset(menu);
|
|
7116
6237
|
const appliedTop = parseFloat(menu.style.top) || 0;
|
|
@@ -7123,7 +6244,6 @@ function place(target, menu, gaps, alignment) {
|
|
|
7123
6244
|
menu.style.top = `${y - originTop}px`;
|
|
7124
6245
|
menu.style.left = `${x - originLeft}px`;
|
|
7125
6246
|
}
|
|
7126
|
-
/** The nearest ancestor that SCROLLS — it is the one clipping the trigger. */
|
|
7127
6247
|
function scrollingAncestor(el) {
|
|
7128
6248
|
let node = el.parentElement;
|
|
7129
6249
|
while (node) {
|
|
@@ -7134,21 +6254,6 @@ function scrollingAncestor(el) {
|
|
|
7134
6254
|
}
|
|
7135
6255
|
return null;
|
|
7136
6256
|
}
|
|
7137
|
-
/**
|
|
7138
|
-
* Has the trigger gone out of sight?
|
|
7139
|
-
*
|
|
7140
|
-
* A panel anchored to a trigger that is no longer on screen is worse than no
|
|
7141
|
-
* panel at all: it hangs in the middle of the content with no visible anchor,
|
|
7142
|
-
* and the user has no way of knowing what those options belong to.
|
|
7143
|
-
*
|
|
7144
|
-
* Two boundaries count: the window, and the CLIP of the ancestor that scrolls.
|
|
7145
|
-
* The second is the one that catches a chip scrolling sideways out of the
|
|
7146
|
-
* filter row — there the trigger's rect is still inside the window, and only
|
|
7147
|
-
* the container knows it is gone.
|
|
7148
|
-
*
|
|
7149
|
-
* With no measurable viewport nothing is hidden: in jsdom `clientWidth` is 0,
|
|
7150
|
-
* and closing every menu because of that would be worse than the defect.
|
|
7151
|
-
*/
|
|
7152
6257
|
function outOfSight(trigger, target) {
|
|
7153
6258
|
const vh = document.documentElement.clientHeight || 0;
|
|
7154
6259
|
const vw = document.documentElement.clientWidth || 0;
|
|
@@ -7176,56 +6281,13 @@ function readGaps(menu) {
|
|
|
7176
6281
|
left: parseFloat(style.marginLeft) || 0
|
|
7177
6282
|
};
|
|
7178
6283
|
}
|
|
7179
|
-
/**
|
|
7180
|
-
* Butts the panel against the trigger and KEEPS it there while anything
|
|
7181
|
-
* scrolls. Returns the function that switches it all off.
|
|
7182
|
-
*
|
|
7183
|
-
* Anchoring and following are one job: a positioned panel that stops following
|
|
7184
|
-
* is already wrong on the first scroll, and one that follows without having
|
|
7185
|
-
* been positioned never reaches the right place.
|
|
7186
|
-
*
|
|
7187
|
-
* `capture: true` is not a detail: an element's `scroll` event does NOT
|
|
7188
|
-
* bubble, so without the capture phase the filter row scrolling under the
|
|
7189
|
-
* panel would go unnoticed and the panel would stay planted at the old spot.
|
|
7190
|
-
*
|
|
7191
|
-
* The margins are read once — they do not change. The ORIGIN does: if the page
|
|
7192
|
-
* scrolls and the containing block is a transformed ancestor, it moves down
|
|
7193
|
-
* with the trigger, and only re-measuring both keeps the sum standing.
|
|
7194
|
-
*
|
|
7195
|
-
* `transitionend` is there for one specific and expensive-to-find reason.
|
|
7196
|
-
* While an ancestor's `translate` is ANIMATING it is a containing block; when
|
|
7197
|
-
* the transition ends, it stops being one. A scroll that lands inside that
|
|
7198
|
-
* window measures the transformed origin, and the sum stays wrong FOREVER —
|
|
7199
|
-
* the panel is born displaced and nothing corrects it. That is exactly what
|
|
7200
|
-
* happens here: the row scrolls to follow the new filter at the same instant
|
|
7201
|
-
* the FLIP translates the slots.
|
|
7202
|
-
*
|
|
7203
|
-
* `animationend` closes the SAME window from the other side. The chip's
|
|
7204
|
-
* entrance is not a transition, it is a `@keyframes` animating `translate`. A
|
|
7205
|
-
* chip born with its panel already open — which is the normal case, because
|
|
7206
|
-
* the value panel opens on its own — has that panel anchored against a slot
|
|
7207
|
-
* that is still a containing block, and when the animation ends the slot stops
|
|
7208
|
-
* being one: the same coordinates now resolve against the viewport and the
|
|
7209
|
-
* panel jumps the slot's whole offset.
|
|
7210
|
-
*
|
|
7211
|
-
* The guard is `target.contains(menu)` rather than the animation's name. Only
|
|
7212
|
-
* an ANCESTOR's animation changes the panel's containing block, so the right
|
|
7213
|
-
* question is one of kinship — and it does not tie this helper to the list of
|
|
7214
|
-
* keyframes used by whoever calls it.
|
|
7215
|
-
*/
|
|
7216
6284
|
function anchorMenu(trigger, menu, alignment = 'start', onOutOfSight) {
|
|
7217
6285
|
const gaps = readGaps(menu);
|
|
7218
|
-
// A KNOWN starting point for the first measurement: with `top: auto` the
|
|
7219
|
-
// panel sits at its static position, and the containing block's origin
|
|
7220
|
-
// cannot be derived from that. Once only, before any paint — from then on
|
|
7221
|
-
// `place` derives from the applied position and never moves the panel just
|
|
7222
|
-
// to measure it.
|
|
7223
6286
|
if (!menu.style.top) {
|
|
7224
6287
|
menu.style.top = '0px';
|
|
7225
6288
|
menu.style.left = '0px';
|
|
7226
6289
|
}
|
|
7227
6290
|
const reposition = () => {
|
|
7228
|
-
// One read of the trigger per event, reused by both sums.
|
|
7229
6291
|
const target = trigger.getBoundingClientRect();
|
|
7230
6292
|
if (onOutOfSight && outOfSight(trigger, target)) {
|
|
7231
6293
|
onOutOfSight();
|
|
@@ -7233,11 +6295,6 @@ function anchorMenu(trigger, menu, alignment = 'start', onOutOfSight) {
|
|
|
7233
6295
|
}
|
|
7234
6296
|
place(target, menu, gaps, alignment);
|
|
7235
6297
|
};
|
|
7236
|
-
// Only `translate` is of interest: it is the property that turns an ancestor
|
|
7237
|
-
// into a containing block. Without the filter, every COLOUR transition in
|
|
7238
|
-
// the document — and each hover on a chip is three — would fire a
|
|
7239
|
-
// reposition with a forced layout read, leaving the panel trembling while
|
|
7240
|
-
// the pointer wanders across the bar.
|
|
7241
6298
|
const onTransitionEnd = (event) => {
|
|
7242
6299
|
if (event.propertyName === 'translate')
|
|
7243
6300
|
reposition();
|
|
@@ -7247,12 +6304,6 @@ function anchorMenu(trigger, menu, alignment = 'start', onOutOfSight) {
|
|
|
7247
6304
|
if (node?.contains(menu))
|
|
7248
6305
|
reposition();
|
|
7249
6306
|
};
|
|
7250
|
-
// The panel's own SIZE feeds the horizontal sum — it is what decides whether
|
|
7251
|
-
// the preferred edge fits. A panel that CHANGES size after being anchored
|
|
7252
|
-
// would otherwise stay at the position that fitted the old size, and that is
|
|
7253
|
-
// not a rare case here: the date panel swaps its content on "Personalizado",
|
|
7254
|
-
// trading a short shortcut list for the full date range, without recreating
|
|
7255
|
-
// the element. Repositioning changes nobody's size, so there is no loop.
|
|
7256
6307
|
const observer = new ResizeObserver(() => {
|
|
7257
6308
|
reposition();
|
|
7258
6309
|
});
|
|
@@ -7276,47 +6327,24 @@ function anchorMenu(trigger, menu, alignment = 'start', onOutOfSight) {
|
|
|
7276
6327
|
* This style guide was developed by Monkey Exchange Team
|
|
7277
6328
|
* MIT Licence
|
|
7278
6329
|
************************* */
|
|
7279
|
-
/**
|
|
7280
|
-
* One segment of a monkey-filter-chip.
|
|
7281
|
-
*
|
|
7282
|
-
* ONE component for the two roles the chip has — the category name and the
|
|
7283
|
-
* answer. Both share the same state table, the same padding, the same
|
|
7284
|
-
* typography and the same height; what changes between them is the content
|
|
7285
|
-
* (the first has an icon) and the rounding of the ends, which belongs to the
|
|
7286
|
-
* chip and not to the segment. Two components would be two copies of the same
|
|
7287
|
-
* stylesheet waiting to drift apart.
|
|
7288
|
-
*
|
|
7289
|
-
* `filled` is not an input: it is `text() !== ''`. Letting the consumer
|
|
7290
|
-
* declare "filled" with an empty text would be a state impossible to draw.
|
|
7291
|
-
*
|
|
7292
|
-
* The projected panel is `position: fixed` and anchored by script — see
|
|
7293
|
-
* `anchored-menu.ts` for why an `absolute` one cannot survive inside a row
|
|
7294
|
-
* that scrolls.
|
|
7295
|
-
*/
|
|
7296
6330
|
class MonkeyFilterSegmentComponent {
|
|
7297
6331
|
constructor() {
|
|
7298
|
-
|
|
6332
|
+
this._hostEl = inject(ElementRef);
|
|
6333
|
+
this._menuEl = viewChild('menu', ...(ngDevMode ? [{ debugName: "_menuEl" }] : /* istanbul ignore next */ []));
|
|
7299
6334
|
this.icon = input(null, ...(ngDevMode ? [{ debugName: "icon" }] : /* istanbul ignore next */ []));
|
|
7300
|
-
/** The chosen value. Empty means the segment is still waiting. */
|
|
7301
6335
|
this.text = input('', ...(ngDevMode ? [{ debugName: "text" }] : /* istanbul ignore next */ []));
|
|
7302
|
-
/** Waiting text, in the complement colour. */
|
|
7303
6336
|
this.placeholder = input('', ...(ngDevMode ? [{ debugName: "placeholder" }] : /* istanbul ignore next */ []));
|
|
7304
|
-
/** A segment with no panel to open. */
|
|
7305
6337
|
this.readonlySegment = input(false, { ...(ngDevMode ? { debugName: "readonlySegment" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
|
|
7306
|
-
this.
|
|
7307
|
-
this.
|
|
6338
|
+
this.disabled = input(false, { ...(ngDevMode ? { debugName: "disabled" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
|
|
6339
|
+
this.open = input(false, { ...(ngDevMode ? { debugName: "open" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
|
|
6340
|
+
this.onOpenChange = output();
|
|
6341
|
+
this.onSegmentClick = output();
|
|
7308
6342
|
this.filled = computed(() => {
|
|
7309
6343
|
return this.text().length > 0;
|
|
7310
6344
|
}, ...(ngDevMode ? [{ debugName: "filled" }] : /* istanbul ignore next */ []));
|
|
7311
|
-
/** What is shown: the value when there is one, the waiting text when not. */
|
|
7312
6345
|
this.label = computed(() => {
|
|
7313
6346
|
return this.filled() ? this.text() : this.placeholder();
|
|
7314
6347
|
}, ...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
|
|
7315
|
-
this._hostEl = inject(ElementRef);
|
|
7316
|
-
this._menuEl = viewChild('menu', ...(ngDevMode ? [{ debugName: "_menuEl" }] : /* istanbul ignore next */ []));
|
|
7317
|
-
// The panel is `fixed` to escape the clip of the row that scrolls, and
|
|
7318
|
-
// `fixed` follows nobody — the position is recomputed on every opening and
|
|
7319
|
-
// kept by the listeners `anchorMenu` installs.
|
|
7320
6348
|
effect((onCleanup) => {
|
|
7321
6349
|
const menu = this._menuEl()?.nativeElement;
|
|
7322
6350
|
if (!menu)
|
|
@@ -7324,47 +6352,37 @@ class MonkeyFilterSegmentComponent {
|
|
|
7324
6352
|
onCleanup(anchorMenu(this._hostEl.nativeElement, menu, 'start'));
|
|
7325
6353
|
});
|
|
7326
6354
|
}
|
|
6355
|
+
focusButton() {
|
|
6356
|
+
this._hostEl.nativeElement.querySelector('.mecx-filter-segment-btn')?.focus();
|
|
6357
|
+
}
|
|
7327
6358
|
toggle() {
|
|
7328
|
-
this.
|
|
6359
|
+
if (this.disabled())
|
|
6360
|
+
return;
|
|
6361
|
+
this.onSegmentClick.emit();
|
|
7329
6362
|
if (this.readonlySegment())
|
|
7330
6363
|
return;
|
|
7331
|
-
this.
|
|
6364
|
+
this.onOpenChange.emit(!this.open());
|
|
7332
6365
|
}
|
|
7333
|
-
/**
|
|
7334
|
-
* A click outside closes. Without it the panel would only close by clicking
|
|
7335
|
-
* the segment again — behaviour no system menu has, and which left two
|
|
7336
|
-
* panels open at once on a row with several chips.
|
|
7337
|
-
*/
|
|
7338
6366
|
onDocumentPointerdown(event) {
|
|
7339
6367
|
if (!this.open())
|
|
7340
6368
|
return;
|
|
7341
6369
|
const target = event.target;
|
|
7342
6370
|
if (target && this._hostEl.nativeElement.contains(target))
|
|
7343
6371
|
return;
|
|
7344
|
-
this.
|
|
6372
|
+
this.onOpenChange.emit(false);
|
|
7345
6373
|
}
|
|
7346
|
-
/**
|
|
7347
|
-
* Escape closes and hands the focus back to the segment's button. Without
|
|
7348
|
-
* the hand-back the focus falls to `<body>` and Tab restarts from the top of
|
|
7349
|
-
* the page: whoever opened the panel from the keyboard loses their place in
|
|
7350
|
-
* the middle of the row.
|
|
7351
|
-
*/
|
|
7352
6374
|
onEscape() {
|
|
7353
6375
|
if (!this.open())
|
|
7354
6376
|
return;
|
|
7355
|
-
this.
|
|
6377
|
+
this.onOpenChange.emit(false);
|
|
7356
6378
|
this.focusButton();
|
|
7357
6379
|
}
|
|
7358
|
-
/** Closes and returns the focus. Public for whoever needs to close from outside. */
|
|
7359
6380
|
closeAndFocus() {
|
|
7360
|
-
this.
|
|
6381
|
+
this.onOpenChange.emit(false);
|
|
7361
6382
|
this.focusButton();
|
|
7362
6383
|
}
|
|
7363
|
-
focusButton() {
|
|
7364
|
-
this._hostEl.nativeElement.querySelector('.mecx-filter-segment-btn')?.focus();
|
|
7365
|
-
}
|
|
7366
6384
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: MonkeyFilterSegmentComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
7367
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.4", type: MonkeyFilterSegmentComponent, isStandalone: true, selector: "monkey-filter-segment", inputs: { icon: { classPropertyName: "icon", publicName: "icon", isSignal: true, isRequired: false, transformFunction: null }, text: { classPropertyName: "text", publicName: "text", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, readonlySegment: { classPropertyName: "readonlySegment", publicName: "readonlySegment", isSignal: true, isRequired: false, transformFunction: null }, open: { classPropertyName: "open", publicName: "open", isSignal: true, isRequired: false, transformFunction: null } }, outputs: {
|
|
6385
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.4", type: MonkeyFilterSegmentComponent, isStandalone: true, selector: "monkey-filter-segment", inputs: { icon: { classPropertyName: "icon", publicName: "icon", isSignal: true, isRequired: false, transformFunction: null }, text: { classPropertyName: "text", publicName: "text", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, readonlySegment: { classPropertyName: "readonlySegment", publicName: "readonlySegment", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, open: { classPropertyName: "open", publicName: "open", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { onOpenChange: "onOpenChange", onSegmentClick: "onSegmentClick" }, host: { attributes: { "data-testid": "monkey-filter-segment" }, listeners: { "document:pointerdown": "onDocumentPointerdown($event)", "document:keydown.escape": "onEscape()" }, properties: { "class.mecx-filter-segment--open": "open()", "class.mecx-filter-segment--filled": "filled()", "class.mecx-filter-segment--disabled": "disabled()" }, classAttribute: "mecx-filter-segment" }, viewQueries: [{ propertyName: "_menuEl", first: true, predicate: ["menu"], descendants: true, isSignal: true }], ngImport: i0, template: "<button\n class=\"mecx-filter-segment-btn\"\n type=\"button\"\n [disabled]=\"disabled() || null\"\n [attr.aria-expanded]=\"readonlySegment() ? null : open()\"\n [attr.aria-haspopup]=\"readonlySegment() ? null : 'listbox'\"\n (click)=\"toggle()\"\n>\n @if (icon()) {\n <i class=\"mk-i mk-i-{{ icon() }} mecx-filter-segment-icon\" aria-hidden=\"true\"></i>\n }\n <span class=\"mecx-filter-segment-label\">{{ label() }}</span>\n</button>\n@if (open()) {\n <div\n #menu\n class=\"mecx-filter-segment-menu\"\n animate.enter=\"mecx-filter-segment-menu--entering\"\n animate.leave=\"mecx-filter-segment-menu--leaving\"\n >\n <ng-content></ng-content>\n </div>\n}\n", styles: ["@keyframes mecx-filter-bar-surface-in{0%{opacity:0;scale:1 var(--mecx-filter-bar-scale-unfold);translate:0 calc(var(--mecx-filter-bar-travel-anchored) * -1)}}@keyframes mecx-filter-bar-surface-out{to{opacity:0;scale:1 var(--mecx-filter-bar-scale-unfold);translate:0 calc(var(--mecx-filter-bar-travel-anchored) * -1)}}@keyframes mecx-filter-bar-surface-item-in{0%{opacity:0;translate:0 calc(var(--mecx-filter-bar-travel-anchored) * -1)}}.mecx-filter-segment{--mecx-filter-bar-duration-state: .15s;--mecx-filter-bar-duration-enter: .2s;--mecx-filter-bar-duration-exit: .15s;--mecx-filter-bar-ease-state: cubic-bezier(.25, .46, .45, .94);--mecx-filter-bar-ease-enter: cubic-bezier(.32, .72, 0, 1);--mecx-filter-bar-ease-exit: cubic-bezier(.4, 0, 1, 1);--mecx-filter-bar-scale-unfold: .94;--mecx-filter-bar-travel-anchored: 4px;--mecx-filter-bar-travel-slide: 16px;--mecx-filter-bar-stagger: 25ms;--mecx-filter-bar-control-height: 32px;--mecx-filter-bar-pointer-target: 40px;--mecx-filter-bar-reach: calc((var(--mecx-filter-bar-control-height) - var(--mecx-filter-bar-pointer-target)) / 2);--mecx-filter-bar-radius: 8px;--mecx-filter-bar-radius-item: 4px;--mecx-filter-bar-fade-width: 48px}@media(prefers-reduced-motion:reduce){.mecx-filter-segment{--mecx-filter-bar-duration-state: 1ms;--mecx-filter-bar-duration-enter: 1ms;--mecx-filter-bar-duration-exit: 1ms;--mecx-filter-bar-scale-unfold: 1;--mecx-filter-bar-travel-anchored: 0px;--mecx-filter-bar-travel-slide: 0px;--mecx-filter-bar-stagger: 0ms}}.mecx-filter-segment{position:relative;display:inline-flex;margin-right:-1px}.mecx-filter-segment-btn{display:inline-flex;align-items:center;gap:4px;height:var(--mecx-filter-bar-control-height);padding-inline:8px;box-sizing:border-box;background:var(--mecx-color-gray-50);border:1px solid var(--mecx-color-gray-500);border-radius:0;color:var(--mecx-color-gray-700);font-family:inherit;cursor:pointer;outline:none;white-space:nowrap;position:relative;transition:background-color var(--mecx-filter-bar-duration-state) var(--mecx-filter-bar-ease-state),border-color var(--mecx-filter-bar-duration-state) var(--mecx-filter-bar-ease-state),color var(--mecx-filter-bar-duration-state) var(--mecx-filter-bar-ease-state)}.mecx-filter-segment-btn:after{content:\"\";position:absolute;inset:var(--mecx-filter-bar-reach) 0}.mecx-filter-segment-btn:hover{background-color:var(--mecx-color-gray-200)}.mecx-filter-segment-btn:active{background-color:var(--mecx-color-gray-400)}.mecx-filter-segment-btn:focus-visible{border-color:var(--mecx-color-gray-900)}.mecx-filter-segment-btn:disabled{background-color:var(--mecx-color-gray-50);color:var(--mecx-color-gray-400);border-color:var(--mecx-color-gray-400);cursor:not-allowed}.mecx-filter-segment-btn:hover,.mecx-filter-segment-btn:focus-visible{z-index:1}.mecx-filter-segment--open{z-index:1}.mecx-filter-segment--open .mecx-filter-segment-btn{background-color:var(--mecx-color-gray-200)}.mecx-filter-segment--filled .mecx-filter-segment-btn{color:var(--mecx-color-gray-900)}.mecx-filter-segment--disabled .mecx-filter-segment-btn,.mecx-filter-segment--filled.mecx-filter-segment--disabled .mecx-filter-segment-btn{color:var(--mecx-color-gray-400)}.mecx-filter-segment-icon{display:inline-flex;flex-shrink:0;font-size:16px;color:var(--mecx-color-gray-600)}.mecx-filter-segment--disabled .mecx-filter-segment-icon{color:var(--mecx-color-gray-400)}.mecx-filter-segment-label{font-size:12px;font-weight:500;line-height:16px;letter-spacing:.02em;color:inherit}.mecx-filter-segment-menu{position:fixed;margin-top:4px;z-index:100}.mecx-filter-segment-menu--entering{transform-origin:top;animation:mecx-filter-bar-surface-in var(--mecx-filter-bar-duration-enter) var(--mecx-filter-bar-ease-enter)}.mecx-filter-segment-menu--entering monkey-filter-menu-item,.mecx-filter-segment-menu--entering monkey-divider{animation:mecx-filter-bar-surface-item-in var(--mecx-filter-bar-duration-enter) var(--mecx-filter-bar-ease-enter) both}.mecx-filter-segment-menu--entering .mecx-filter-menu-items>:nth-child(1){animation-delay:calc(var(--mecx-filter-bar-stagger) * 1)}.mecx-filter-segment-menu--entering .mecx-filter-menu-items>:nth-child(2){animation-delay:calc(var(--mecx-filter-bar-stagger) * 2)}.mecx-filter-segment-menu--entering .mecx-filter-menu-items>:nth-child(3){animation-delay:calc(var(--mecx-filter-bar-stagger) * 3)}.mecx-filter-segment-menu--entering .mecx-filter-menu-items>:nth-child(4){animation-delay:calc(var(--mecx-filter-bar-stagger) * 4)}.mecx-filter-segment-menu--entering .mecx-filter-menu-items>:nth-child(5){animation-delay:calc(var(--mecx-filter-bar-stagger) * 5)}.mecx-filter-segment-menu--entering .mecx-filter-menu-items>:nth-child(6){animation-delay:calc(var(--mecx-filter-bar-stagger) * 6)}.mecx-filter-segment-menu--entering .mecx-filter-menu-items>:nth-child(7){animation-delay:calc(var(--mecx-filter-bar-stagger) * 7)}.mecx-filter-segment-menu--entering .mecx-filter-menu-items>:nth-child(8){animation-delay:calc(var(--mecx-filter-bar-stagger) * 8)}.mecx-filter-segment-menu--entering .mecx-filter-menu-items>:nth-child(n+8){animation-delay:calc(var(--mecx-filter-bar-stagger) * 8)}.mecx-filter-segment-menu--leaving{transform-origin:top;animation:mecx-filter-bar-surface-out var(--mecx-filter-bar-duration-exit) var(--mecx-filter-bar-ease-exit)}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
|
|
7368
6386
|
}
|
|
7369
6387
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: MonkeyFilterSegmentComponent, decorators: [{
|
|
7370
6388
|
type: Component,
|
|
@@ -7373,76 +6391,45 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImpor
|
|
|
7373
6391
|
class: 'mecx-filter-segment',
|
|
7374
6392
|
'[class.mecx-filter-segment--open]': 'open()',
|
|
7375
6393
|
'[class.mecx-filter-segment--filled]': 'filled()',
|
|
6394
|
+
'[class.mecx-filter-segment--disabled]': 'disabled()',
|
|
7376
6395
|
'(document:pointerdown)': 'onDocumentPointerdown($event)',
|
|
7377
6396
|
'(document:keydown.escape)': 'onEscape()'
|
|
7378
|
-
}, template: "<button\n class=\"mecx-filter-segment-btn\"\n type=\"button\"\n [attr.aria-expanded]=\"readonlySegment() ? null : open()\"\n [attr.aria-haspopup]=\"readonlySegment() ? null : 'listbox'\"\n (click)=\"toggle()\"\n>\n @if (icon()) {\n <i class=\"mk-i mk-i-{{ icon() }} mecx-filter-segment-icon\" aria-hidden=\"true\"></i>\n }\n <span class=\"mecx-filter-segment-label\">{{ label() }}</span>\n</button>\n
|
|
7379
|
-
}], ctorParameters: () => [], propDecorators: { icon: [{ type: i0.Input, args: [{ isSignal: true, alias: "icon", required: false }] }], text: [{ type: i0.Input, args: [{ isSignal: true, alias: "text", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], readonlySegment: [{ type: i0.Input, args: [{ isSignal: true, alias: "readonlySegment", required: false }] }],
|
|
6397
|
+
}, template: "<button\n class=\"mecx-filter-segment-btn\"\n type=\"button\"\n [disabled]=\"disabled() || null\"\n [attr.aria-expanded]=\"readonlySegment() ? null : open()\"\n [attr.aria-haspopup]=\"readonlySegment() ? null : 'listbox'\"\n (click)=\"toggle()\"\n>\n @if (icon()) {\n <i class=\"mk-i mk-i-{{ icon() }} mecx-filter-segment-icon\" aria-hidden=\"true\"></i>\n }\n <span class=\"mecx-filter-segment-label\">{{ label() }}</span>\n</button>\n@if (open()) {\n <div\n #menu\n class=\"mecx-filter-segment-menu\"\n animate.enter=\"mecx-filter-segment-menu--entering\"\n animate.leave=\"mecx-filter-segment-menu--leaving\"\n >\n <ng-content></ng-content>\n </div>\n}\n", styles: ["@keyframes mecx-filter-bar-surface-in{0%{opacity:0;scale:1 var(--mecx-filter-bar-scale-unfold);translate:0 calc(var(--mecx-filter-bar-travel-anchored) * -1)}}@keyframes mecx-filter-bar-surface-out{to{opacity:0;scale:1 var(--mecx-filter-bar-scale-unfold);translate:0 calc(var(--mecx-filter-bar-travel-anchored) * -1)}}@keyframes mecx-filter-bar-surface-item-in{0%{opacity:0;translate:0 calc(var(--mecx-filter-bar-travel-anchored) * -1)}}.mecx-filter-segment{--mecx-filter-bar-duration-state: .15s;--mecx-filter-bar-duration-enter: .2s;--mecx-filter-bar-duration-exit: .15s;--mecx-filter-bar-ease-state: cubic-bezier(.25, .46, .45, .94);--mecx-filter-bar-ease-enter: cubic-bezier(.32, .72, 0, 1);--mecx-filter-bar-ease-exit: cubic-bezier(.4, 0, 1, 1);--mecx-filter-bar-scale-unfold: .94;--mecx-filter-bar-travel-anchored: 4px;--mecx-filter-bar-travel-slide: 16px;--mecx-filter-bar-stagger: 25ms;--mecx-filter-bar-control-height: 32px;--mecx-filter-bar-pointer-target: 40px;--mecx-filter-bar-reach: calc((var(--mecx-filter-bar-control-height) - var(--mecx-filter-bar-pointer-target)) / 2);--mecx-filter-bar-radius: 8px;--mecx-filter-bar-radius-item: 4px;--mecx-filter-bar-fade-width: 48px}@media(prefers-reduced-motion:reduce){.mecx-filter-segment{--mecx-filter-bar-duration-state: 1ms;--mecx-filter-bar-duration-enter: 1ms;--mecx-filter-bar-duration-exit: 1ms;--mecx-filter-bar-scale-unfold: 1;--mecx-filter-bar-travel-anchored: 0px;--mecx-filter-bar-travel-slide: 0px;--mecx-filter-bar-stagger: 0ms}}.mecx-filter-segment{position:relative;display:inline-flex;margin-right:-1px}.mecx-filter-segment-btn{display:inline-flex;align-items:center;gap:4px;height:var(--mecx-filter-bar-control-height);padding-inline:8px;box-sizing:border-box;background:var(--mecx-color-gray-50);border:1px solid var(--mecx-color-gray-500);border-radius:0;color:var(--mecx-color-gray-700);font-family:inherit;cursor:pointer;outline:none;white-space:nowrap;position:relative;transition:background-color var(--mecx-filter-bar-duration-state) var(--mecx-filter-bar-ease-state),border-color var(--mecx-filter-bar-duration-state) var(--mecx-filter-bar-ease-state),color var(--mecx-filter-bar-duration-state) var(--mecx-filter-bar-ease-state)}.mecx-filter-segment-btn:after{content:\"\";position:absolute;inset:var(--mecx-filter-bar-reach) 0}.mecx-filter-segment-btn:hover{background-color:var(--mecx-color-gray-200)}.mecx-filter-segment-btn:active{background-color:var(--mecx-color-gray-400)}.mecx-filter-segment-btn:focus-visible{border-color:var(--mecx-color-gray-900)}.mecx-filter-segment-btn:disabled{background-color:var(--mecx-color-gray-50);color:var(--mecx-color-gray-400);border-color:var(--mecx-color-gray-400);cursor:not-allowed}.mecx-filter-segment-btn:hover,.mecx-filter-segment-btn:focus-visible{z-index:1}.mecx-filter-segment--open{z-index:1}.mecx-filter-segment--open .mecx-filter-segment-btn{background-color:var(--mecx-color-gray-200)}.mecx-filter-segment--filled .mecx-filter-segment-btn{color:var(--mecx-color-gray-900)}.mecx-filter-segment--disabled .mecx-filter-segment-btn,.mecx-filter-segment--filled.mecx-filter-segment--disabled .mecx-filter-segment-btn{color:var(--mecx-color-gray-400)}.mecx-filter-segment-icon{display:inline-flex;flex-shrink:0;font-size:16px;color:var(--mecx-color-gray-600)}.mecx-filter-segment--disabled .mecx-filter-segment-icon{color:var(--mecx-color-gray-400)}.mecx-filter-segment-label{font-size:12px;font-weight:500;line-height:16px;letter-spacing:.02em;color:inherit}.mecx-filter-segment-menu{position:fixed;margin-top:4px;z-index:100}.mecx-filter-segment-menu--entering{transform-origin:top;animation:mecx-filter-bar-surface-in var(--mecx-filter-bar-duration-enter) var(--mecx-filter-bar-ease-enter)}.mecx-filter-segment-menu--entering monkey-filter-menu-item,.mecx-filter-segment-menu--entering monkey-divider{animation:mecx-filter-bar-surface-item-in var(--mecx-filter-bar-duration-enter) var(--mecx-filter-bar-ease-enter) both}.mecx-filter-segment-menu--entering .mecx-filter-menu-items>:nth-child(1){animation-delay:calc(var(--mecx-filter-bar-stagger) * 1)}.mecx-filter-segment-menu--entering .mecx-filter-menu-items>:nth-child(2){animation-delay:calc(var(--mecx-filter-bar-stagger) * 2)}.mecx-filter-segment-menu--entering .mecx-filter-menu-items>:nth-child(3){animation-delay:calc(var(--mecx-filter-bar-stagger) * 3)}.mecx-filter-segment-menu--entering .mecx-filter-menu-items>:nth-child(4){animation-delay:calc(var(--mecx-filter-bar-stagger) * 4)}.mecx-filter-segment-menu--entering .mecx-filter-menu-items>:nth-child(5){animation-delay:calc(var(--mecx-filter-bar-stagger) * 5)}.mecx-filter-segment-menu--entering .mecx-filter-menu-items>:nth-child(6){animation-delay:calc(var(--mecx-filter-bar-stagger) * 6)}.mecx-filter-segment-menu--entering .mecx-filter-menu-items>:nth-child(7){animation-delay:calc(var(--mecx-filter-bar-stagger) * 7)}.mecx-filter-segment-menu--entering .mecx-filter-menu-items>:nth-child(8){animation-delay:calc(var(--mecx-filter-bar-stagger) * 8)}.mecx-filter-segment-menu--entering .mecx-filter-menu-items>:nth-child(n+8){animation-delay:calc(var(--mecx-filter-bar-stagger) * 8)}.mecx-filter-segment-menu--leaving{transform-origin:top;animation:mecx-filter-bar-surface-out var(--mecx-filter-bar-duration-exit) var(--mecx-filter-bar-ease-exit)}\n"] }]
|
|
6398
|
+
}], ctorParameters: () => [], propDecorators: { _menuEl: [{ type: i0.ViewChild, args: ['menu', { isSignal: true }] }], icon: [{ type: i0.Input, args: [{ isSignal: true, alias: "icon", required: false }] }], text: [{ type: i0.Input, args: [{ isSignal: true, alias: "text", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], readonlySegment: [{ type: i0.Input, args: [{ isSignal: true, alias: "readonlySegment", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], open: [{ type: i0.Input, args: [{ isSignal: true, alias: "open", required: false }] }], onOpenChange: [{ type: i0.Output, args: ["onOpenChange"] }], onSegmentClick: [{ type: i0.Output, args: ["onSegmentClick"] }] } });
|
|
7380
6399
|
|
|
7381
6400
|
/** ************************
|
|
7382
6401
|
* Copyright Monkey Exchange. All Rights Reserved
|
|
7383
6402
|
* This style guide was developed by Monkey Exchange Team
|
|
7384
6403
|
* MIT Licence
|
|
7385
6404
|
************************* */
|
|
7386
|
-
/**
|
|
7387
|
-
* The button that adds a filter, and the panel of categories it opens.
|
|
7388
|
-
*
|
|
7389
|
-
* It is always the LAST slot of the row. While the bar is empty the trigger is
|
|
7390
|
-
* the CALL to action and earns its label; with filters on screen it becomes
|
|
7391
|
-
* the ADDITION, and a 28px square is enough.
|
|
7392
|
-
*
|
|
7393
|
-
* Both are 28px tall — the same as a chip segment — because the button turns
|
|
7394
|
-
* into a chip in place, and 1px of difference would show up as a jump at the
|
|
7395
|
-
* moment of the swap.
|
|
7396
|
-
*/
|
|
7397
6405
|
class MonkeyFilterTriggerComponent {
|
|
7398
6406
|
constructor() {
|
|
6407
|
+
this._hostEl = inject(ElementRef);
|
|
6408
|
+
this._menuEl = viewChild('menu', ...(ngDevMode ? [{ debugName: "_menuEl" }] : /* istanbul ignore next */ []));
|
|
7399
6409
|
this.variant = input('text', ...(ngDevMode ? [{ debugName: "variant" }] : /* istanbul ignore next */ []));
|
|
7400
|
-
/** Icon font name, without the `mk-i-` prefix. */
|
|
7401
6410
|
this.icon = input('filter', ...(ngDevMode ? [{ debugName: "icon" }] : /* istanbul ignore next */ []));
|
|
7402
|
-
this.text = input('
|
|
7403
|
-
this.ariaLabel = input('
|
|
6411
|
+
this.text = input('', ...(ngDevMode ? [{ debugName: "text" }] : /* istanbul ignore next */ []));
|
|
6412
|
+
this.ariaLabel = input('', ...(ngDevMode ? [{ debugName: "ariaLabel" }] : /* istanbul ignore next */ []));
|
|
7404
6413
|
this.disabled = input(false, { ...(ngDevMode ? { debugName: "disabled" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
|
|
7405
|
-
/**
|
|
7406
|
-
* The panel leaves with no exit animation.
|
|
7407
|
-
*
|
|
7408
|
-
* It exists for ONE case: when the closing goes along with the trigger
|
|
7409
|
-
* itself changing place. The panel is a child of the button, so it travels
|
|
7410
|
-
* with it — and a fade on an element that has just teleported 160px does not
|
|
7411
|
-
* read as an exit, it reads as a glitch. Closing by Escape or by an outside
|
|
7412
|
-
* click is not that case and keeps its fade.
|
|
7413
|
-
*/
|
|
7414
6414
|
this.immediateExit = input(false, { ...(ngDevMode ? { debugName: "immediateExit" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
|
|
7415
|
-
this.open =
|
|
7416
|
-
|
|
7417
|
-
* `aria-label` only on the variant with no visible label. Where there is a
|
|
7418
|
-
* label, an `aria-label` over it would swap the name the user reads for one
|
|
7419
|
-
* they cannot see — breaking voice control and the "Label in Name" criterion.
|
|
7420
|
-
*/
|
|
6415
|
+
this.open = input(false, { ...(ngDevMode ? { debugName: "open" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
|
|
6416
|
+
this.onOpenChange = output();
|
|
7421
6417
|
this.ariaLabelAttr = computed(() => {
|
|
7422
6418
|
return this.variant() === 'icon' ? this.ariaLabel() || null : null;
|
|
7423
6419
|
}, ...(ngDevMode ? [{ debugName: "ariaLabelAttr" }] : /* istanbul ignore next */ []));
|
|
7424
|
-
this._hostEl = inject(ElementRef);
|
|
7425
|
-
this._menuEl = viewChild('menu', ...(ngDevMode ? [{ debugName: "_menuEl" }] : /* istanbul ignore next */ []));
|
|
7426
6420
|
effect((onCleanup) => {
|
|
7427
6421
|
const menu = this._menuEl()?.nativeElement;
|
|
7428
6422
|
if (!menu)
|
|
7429
6423
|
return;
|
|
7430
|
-
// Aligned to the END, so the panel's right edge meets the button's own
|
|
7431
|
-
// however wide the button happens to be — the label and the square are
|
|
7432
|
-
// very different widths and the panel must not jump between them.
|
|
7433
|
-
//
|
|
7434
|
-
// Going out of sight closes: a `fixed` panel anchored to a trigger that
|
|
7435
|
-
// has scrolled away hangs in the middle of the content with no visible
|
|
7436
|
-
// anchor.
|
|
7437
6424
|
onCleanup(anchorMenu(this._hostEl.nativeElement, menu, 'end', () => {
|
|
7438
|
-
return this.
|
|
6425
|
+
return this.onOpenChange.emit(false);
|
|
7439
6426
|
}));
|
|
7440
6427
|
});
|
|
7441
6428
|
}
|
|
7442
6429
|
toggle() {
|
|
7443
6430
|
if (this.disabled())
|
|
7444
6431
|
return;
|
|
7445
|
-
this.
|
|
6432
|
+
this.onOpenChange.emit(!this.open());
|
|
7446
6433
|
}
|
|
7447
6434
|
onDocumentPointerdown(event) {
|
|
7448
6435
|
if (!this.open())
|
|
@@ -7450,16 +6437,16 @@ class MonkeyFilterTriggerComponent {
|
|
|
7450
6437
|
const target = event.target;
|
|
7451
6438
|
if (target && this._hostEl.nativeElement.contains(target))
|
|
7452
6439
|
return;
|
|
7453
|
-
this.
|
|
6440
|
+
this.onOpenChange.emit(false);
|
|
7454
6441
|
}
|
|
7455
6442
|
onEscape() {
|
|
7456
6443
|
if (!this.open())
|
|
7457
6444
|
return;
|
|
7458
|
-
this.
|
|
6445
|
+
this.onOpenChange.emit(false);
|
|
7459
6446
|
this._hostEl.nativeElement.querySelector('.mecx-filter-trigger-btn')?.focus();
|
|
7460
6447
|
}
|
|
7461
6448
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: MonkeyFilterTriggerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
7462
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.4", type: MonkeyFilterTriggerComponent, isStandalone: true, selector: "monkey-filter-trigger", inputs: { variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, icon: { classPropertyName: "icon", publicName: "icon", isSignal: true, isRequired: false, transformFunction: null }, text: { classPropertyName: "text", publicName: "text", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, immediateExit: { classPropertyName: "immediateExit", publicName: "immediateExit", isSignal: true, isRequired: false, transformFunction: null }, open: { classPropertyName: "open", publicName: "open", isSignal: true, isRequired: false, transformFunction: null } }, outputs: {
|
|
6449
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.4", type: MonkeyFilterTriggerComponent, isStandalone: true, selector: "monkey-filter-trigger", inputs: { variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, icon: { classPropertyName: "icon", publicName: "icon", isSignal: true, isRequired: false, transformFunction: null }, text: { classPropertyName: "text", publicName: "text", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, immediateExit: { classPropertyName: "immediateExit", publicName: "immediateExit", isSignal: true, isRequired: false, transformFunction: null }, open: { classPropertyName: "open", publicName: "open", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { onOpenChange: "onOpenChange" }, host: { attributes: { "data-testid": "monkey-filter-trigger" }, listeners: { "document:pointerdown": "onDocumentPointerdown($event)", "document:keydown.escape": "onEscape()" }, properties: { "class.mecx-filter-trigger--text": "variant() === \"text\"", "class.mecx-filter-trigger--icon": "variant() === \"icon\"", "class.mecx-filter-trigger--open": "open()" }, classAttribute: "mecx-filter-trigger" }, viewQueries: [{ propertyName: "_menuEl", first: true, predicate: ["menu"], descendants: true, isSignal: true }], ngImport: i0, template: "<button\n class=\"mecx-filter-trigger-btn\"\n type=\"button\"\n [disabled]=\"disabled() || null\"\n [attr.aria-expanded]=\"open()\"\n [attr.aria-label]=\"ariaLabelAttr()\"\n aria-haspopup=\"listbox\"\n (click)=\"toggle()\"\n>\n <i class=\"mk-i mk-i-{{ icon() }} mecx-filter-trigger-icon\" aria-hidden=\"true\"></i>\n @if (variant() === 'text') {\n <span class=\"mecx-filter-trigger-text\">{{ text() }}</span>\n }\n</button>\n@if (open()) {\n <div\n #menu\n class=\"mecx-filter-trigger-menu\"\n animate.enter=\"mecx-filter-trigger-menu--entering\"\n [animate.leave]=\"immediateExit() ? '' : 'mecx-filter-trigger-menu--leaving'\"\n >\n <ng-content></ng-content>\n </div>\n}\n", styles: ["@keyframes mecx-filter-bar-surface-in{0%{opacity:0;scale:1 var(--mecx-filter-bar-scale-unfold);translate:0 calc(var(--mecx-filter-bar-travel-anchored) * -1)}}@keyframes mecx-filter-bar-surface-out{to{opacity:0;scale:1 var(--mecx-filter-bar-scale-unfold);translate:0 calc(var(--mecx-filter-bar-travel-anchored) * -1)}}@keyframes mecx-filter-bar-surface-item-in{0%{opacity:0;translate:0 calc(var(--mecx-filter-bar-travel-anchored) * -1)}}.mecx-filter-trigger{display:inline-flex;position:relative}.mecx-filter-trigger-btn{display:inline-flex;align-items:center;justify-content:center;gap:4px;height:var(--mecx-filter-bar-control-height);box-sizing:border-box;background-color:var(--mecx-color-white);color:var(--mecx-color-gray-900);border:1px solid var(--mecx-color-gray-500);border-radius:var(--mecx-filter-bar-radius);font-family:inherit;cursor:pointer;outline:none;white-space:nowrap;position:relative;transition:background-color var(--mecx-filter-bar-duration-state) var(--mecx-filter-bar-ease-state),color var(--mecx-filter-bar-duration-state) var(--mecx-filter-bar-ease-state)}.mecx-filter-trigger-btn:after{content:\"\";position:absolute;top:50%;left:50%;translate:-50% -50%;width:max(100%,var(--mecx-filter-bar-pointer-target));height:max(100%,var(--mecx-filter-bar-pointer-target))}.mecx-filter-trigger-btn:hover:not(:disabled){color:var(--mecx-color-theme-main)}.mecx-filter-trigger-btn:focus-visible{outline:2px solid var(--mecx-color-theme-main);outline-offset:1px}.mecx-filter-trigger-btn:disabled{background-color:transparent;border-color:transparent;color:var(--mecx-color-gray-400);cursor:not-allowed}.mecx-filter-trigger--open .mecx-filter-trigger-btn{color:var(--mecx-color-theme-main)}.mecx-filter-trigger--text .mecx-filter-trigger-btn{padding-inline:7px 11px}.mecx-filter-trigger--icon .mecx-filter-trigger-btn{width:var(--mecx-filter-bar-control-height);padding-inline:0}.mecx-filter-trigger-icon{display:inline-flex;flex-shrink:0;font-size:16px}.mecx-filter-trigger-text{font-size:13px;font-weight:500;line-height:16px;letter-spacing:.03em}.mecx-filter-trigger-menu{position:fixed;margin-top:4px;z-index:100}.mecx-filter-trigger-menu--entering{transform-origin:top;animation:mecx-filter-bar-surface-in var(--mecx-filter-bar-duration-enter) var(--mecx-filter-bar-ease-enter)}.mecx-filter-trigger-menu--entering monkey-filter-menu-item,.mecx-filter-trigger-menu--entering monkey-divider{animation:mecx-filter-bar-surface-item-in var(--mecx-filter-bar-duration-enter) var(--mecx-filter-bar-ease-enter) both}.mecx-filter-trigger-menu--entering .mecx-filter-menu-items>:nth-child(1){animation-delay:calc(var(--mecx-filter-bar-stagger) * 1)}.mecx-filter-trigger-menu--entering .mecx-filter-menu-items>:nth-child(2){animation-delay:calc(var(--mecx-filter-bar-stagger) * 2)}.mecx-filter-trigger-menu--entering .mecx-filter-menu-items>:nth-child(3){animation-delay:calc(var(--mecx-filter-bar-stagger) * 3)}.mecx-filter-trigger-menu--entering .mecx-filter-menu-items>:nth-child(4){animation-delay:calc(var(--mecx-filter-bar-stagger) * 4)}.mecx-filter-trigger-menu--entering .mecx-filter-menu-items>:nth-child(5){animation-delay:calc(var(--mecx-filter-bar-stagger) * 5)}.mecx-filter-trigger-menu--entering .mecx-filter-menu-items>:nth-child(6){animation-delay:calc(var(--mecx-filter-bar-stagger) * 6)}.mecx-filter-trigger-menu--entering .mecx-filter-menu-items>:nth-child(7){animation-delay:calc(var(--mecx-filter-bar-stagger) * 7)}.mecx-filter-trigger-menu--entering .mecx-filter-menu-items>:nth-child(8){animation-delay:calc(var(--mecx-filter-bar-stagger) * 8)}.mecx-filter-trigger-menu--entering .mecx-filter-menu-items>:nth-child(n+8){animation-delay:calc(var(--mecx-filter-bar-stagger) * 8)}.mecx-filter-trigger-menu--leaving{transform-origin:top;animation:mecx-filter-bar-surface-out var(--mecx-filter-bar-duration-exit) var(--mecx-filter-bar-ease-exit)}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
|
|
7463
6450
|
}
|
|
7464
6451
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: MonkeyFilterTriggerComponent, decorators: [{
|
|
7465
6452
|
type: Component,
|
|
@@ -7471,44 +6458,15 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImpor
|
|
|
7471
6458
|
'[class.mecx-filter-trigger--open]': 'open()',
|
|
7472
6459
|
'(document:pointerdown)': 'onDocumentPointerdown($event)',
|
|
7473
6460
|
'(document:keydown.escape)': 'onEscape()'
|
|
7474
|
-
}, template: "<button\n class=\"mecx-filter-trigger-btn\"\n type=\"button\"\n [disabled]=\"disabled() || null\"\n [attr.aria-expanded]=\"open()\"\n [attr.aria-label]=\"ariaLabelAttr()\"\n aria-haspopup=\"listbox\"\n (click)=\"toggle()\"\n>\n
|
|
7475
|
-
}], ctorParameters: () => [], propDecorators: { variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], icon: [{ type: i0.Input, args: [{ isSignal: true, alias: "icon", required: false }] }], text: [{ type: i0.Input, args: [{ isSignal: true, alias: "text", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], immediateExit: [{ type: i0.Input, args: [{ isSignal: true, alias: "immediateExit", required: false }] }], open: [{ type: i0.Input, args: [{ isSignal: true, alias: "open", required: false }] }
|
|
7476
|
-
|
|
7477
|
-
/** ************************
|
|
7478
|
-
* Copyright Monkey Exchange. All Rights Reserved
|
|
7479
|
-
* This style guide was developed by Monkey Exchange Team
|
|
7480
|
-
* MIT Licence
|
|
7481
|
-
************************* */
|
|
7482
|
-
// ─── FLIP ───────────────────────────────────────────────────────────────────
|
|
7483
|
-
// First, Last, Invert, Play: measure where the elements were, let the layout
|
|
7484
|
-
// change, then put each one back at its old position with a `translate` and
|
|
7485
|
-
// animate to zero. The result is that EVERYTHING slides from where it was,
|
|
7486
|
-
// even though the browser repositioned all of it in one pass.
|
|
7487
|
-
//
|
|
7488
|
-
// Why it exists: when the bar's trigger turns into a chip, the whole row is
|
|
7489
|
-
// rebuilt — the chip is born where the button was and the new button moves to
|
|
7490
|
-
// the right. Without FLIP the only thing that can be animated is the chip
|
|
7491
|
-
// coming in, and the neighbours jump. With it, the swap reads as a swap of
|
|
7492
|
-
// PLACE.
|
|
7493
|
-
//
|
|
7494
|
-
// Two decisions that are not details:
|
|
7495
|
-
//
|
|
7496
|
-
// • Only `translate`. Transform and opacity compose on the GPU and skip
|
|
7497
|
-
// layout and paint. The duration and the curve stay in the stylesheet, in
|
|
7498
|
-
// `--mecx-fbv2-*` custom properties, and this file reads no motion value
|
|
7499
|
-
// at all — that is how `prefers-reduced-motion` keeps working for free,
|
|
7500
|
-
// because the media query redefines the properties themselves.
|
|
7501
|
-
//
|
|
7502
|
-
// • Forced reflow, NEVER requestAnimationFrame. In a hidden tab rAF does not
|
|
7503
|
-
// fire: the elements would sit at the inverted position until the tab came
|
|
7504
|
-
// back, which is worse than not animating. With the synchronous reflow the
|
|
7505
|
-
// final state is always correct — in a hidden tab the transition simply
|
|
7506
|
-
// does not run and the layout is already right.
|
|
7507
|
-
/** Attribute that gives an element identity across the two measurements. */
|
|
6461
|
+
}, template: "<button\n class=\"mecx-filter-trigger-btn\"\n type=\"button\"\n [disabled]=\"disabled() || null\"\n [attr.aria-expanded]=\"open()\"\n [attr.aria-label]=\"ariaLabelAttr()\"\n aria-haspopup=\"listbox\"\n (click)=\"toggle()\"\n>\n <i class=\"mk-i mk-i-{{ icon() }} mecx-filter-trigger-icon\" aria-hidden=\"true\"></i>\n @if (variant() === 'text') {\n <span class=\"mecx-filter-trigger-text\">{{ text() }}</span>\n }\n</button>\n@if (open()) {\n <div\n #menu\n class=\"mecx-filter-trigger-menu\"\n animate.enter=\"mecx-filter-trigger-menu--entering\"\n [animate.leave]=\"immediateExit() ? '' : 'mecx-filter-trigger-menu--leaving'\"\n >\n <ng-content></ng-content>\n </div>\n}\n", styles: ["@keyframes mecx-filter-bar-surface-in{0%{opacity:0;scale:1 var(--mecx-filter-bar-scale-unfold);translate:0 calc(var(--mecx-filter-bar-travel-anchored) * -1)}}@keyframes mecx-filter-bar-surface-out{to{opacity:0;scale:1 var(--mecx-filter-bar-scale-unfold);translate:0 calc(var(--mecx-filter-bar-travel-anchored) * -1)}}@keyframes mecx-filter-bar-surface-item-in{0%{opacity:0;translate:0 calc(var(--mecx-filter-bar-travel-anchored) * -1)}}.mecx-filter-trigger{display:inline-flex;position:relative}.mecx-filter-trigger-btn{display:inline-flex;align-items:center;justify-content:center;gap:4px;height:var(--mecx-filter-bar-control-height);box-sizing:border-box;background-color:var(--mecx-color-white);color:var(--mecx-color-gray-900);border:1px solid var(--mecx-color-gray-500);border-radius:var(--mecx-filter-bar-radius);font-family:inherit;cursor:pointer;outline:none;white-space:nowrap;position:relative;transition:background-color var(--mecx-filter-bar-duration-state) var(--mecx-filter-bar-ease-state),color var(--mecx-filter-bar-duration-state) var(--mecx-filter-bar-ease-state)}.mecx-filter-trigger-btn:after{content:\"\";position:absolute;top:50%;left:50%;translate:-50% -50%;width:max(100%,var(--mecx-filter-bar-pointer-target));height:max(100%,var(--mecx-filter-bar-pointer-target))}.mecx-filter-trigger-btn:hover:not(:disabled){color:var(--mecx-color-theme-main)}.mecx-filter-trigger-btn:focus-visible{outline:2px solid var(--mecx-color-theme-main);outline-offset:1px}.mecx-filter-trigger-btn:disabled{background-color:transparent;border-color:transparent;color:var(--mecx-color-gray-400);cursor:not-allowed}.mecx-filter-trigger--open .mecx-filter-trigger-btn{color:var(--mecx-color-theme-main)}.mecx-filter-trigger--text .mecx-filter-trigger-btn{padding-inline:7px 11px}.mecx-filter-trigger--icon .mecx-filter-trigger-btn{width:var(--mecx-filter-bar-control-height);padding-inline:0}.mecx-filter-trigger-icon{display:inline-flex;flex-shrink:0;font-size:16px}.mecx-filter-trigger-text{font-size:13px;font-weight:500;line-height:16px;letter-spacing:.03em}.mecx-filter-trigger-menu{position:fixed;margin-top:4px;z-index:100}.mecx-filter-trigger-menu--entering{transform-origin:top;animation:mecx-filter-bar-surface-in var(--mecx-filter-bar-duration-enter) var(--mecx-filter-bar-ease-enter)}.mecx-filter-trigger-menu--entering monkey-filter-menu-item,.mecx-filter-trigger-menu--entering monkey-divider{animation:mecx-filter-bar-surface-item-in var(--mecx-filter-bar-duration-enter) var(--mecx-filter-bar-ease-enter) both}.mecx-filter-trigger-menu--entering .mecx-filter-menu-items>:nth-child(1){animation-delay:calc(var(--mecx-filter-bar-stagger) * 1)}.mecx-filter-trigger-menu--entering .mecx-filter-menu-items>:nth-child(2){animation-delay:calc(var(--mecx-filter-bar-stagger) * 2)}.mecx-filter-trigger-menu--entering .mecx-filter-menu-items>:nth-child(3){animation-delay:calc(var(--mecx-filter-bar-stagger) * 3)}.mecx-filter-trigger-menu--entering .mecx-filter-menu-items>:nth-child(4){animation-delay:calc(var(--mecx-filter-bar-stagger) * 4)}.mecx-filter-trigger-menu--entering .mecx-filter-menu-items>:nth-child(5){animation-delay:calc(var(--mecx-filter-bar-stagger) * 5)}.mecx-filter-trigger-menu--entering .mecx-filter-menu-items>:nth-child(6){animation-delay:calc(var(--mecx-filter-bar-stagger) * 6)}.mecx-filter-trigger-menu--entering .mecx-filter-menu-items>:nth-child(7){animation-delay:calc(var(--mecx-filter-bar-stagger) * 7)}.mecx-filter-trigger-menu--entering .mecx-filter-menu-items>:nth-child(8){animation-delay:calc(var(--mecx-filter-bar-stagger) * 8)}.mecx-filter-trigger-menu--entering .mecx-filter-menu-items>:nth-child(n+8){animation-delay:calc(var(--mecx-filter-bar-stagger) * 8)}.mecx-filter-trigger-menu--leaving{transform-origin:top;animation:mecx-filter-bar-surface-out var(--mecx-filter-bar-duration-exit) var(--mecx-filter-bar-ease-exit)}\n"] }]
|
|
6462
|
+
}], ctorParameters: () => [], propDecorators: { _menuEl: [{ type: i0.ViewChild, args: ['menu', { isSignal: true }] }], variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], icon: [{ type: i0.Input, args: [{ isSignal: true, alias: "icon", required: false }] }], text: [{ type: i0.Input, args: [{ isSignal: true, alias: "text", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], immediateExit: [{ type: i0.Input, args: [{ isSignal: true, alias: "immediateExit", required: false }] }], open: [{ type: i0.Input, args: [{ isSignal: true, alias: "open", required: false }] }], onOpenChange: [{ type: i0.Output, args: ["onOpenChange"] }] } });
|
|
6463
|
+
|
|
6464
|
+
/** ************************
|
|
6465
|
+
* Copyright Monkey Exchange. All Rights Reserved
|
|
6466
|
+
* This style guide was developed by Monkey Exchange Team
|
|
6467
|
+
* MIT Licence
|
|
6468
|
+
************************* */
|
|
7508
6469
|
const FLIP_ATTR = 'data-flip-id';
|
|
7509
|
-
/**
|
|
7510
|
-
* Where each identified element is RIGHT NOW. Call before changing the state.
|
|
7511
|
-
*/
|
|
7512
6470
|
function measureFlip(container) {
|
|
7513
6471
|
const before = new Map();
|
|
7514
6472
|
container.querySelectorAll(`[${FLIP_ATTR}]`).forEach((el) => {
|
|
@@ -7518,12 +6476,6 @@ function measureFlip(container) {
|
|
|
7518
6476
|
});
|
|
7519
6477
|
return before;
|
|
7520
6478
|
}
|
|
7521
|
-
/**
|
|
7522
|
-
* Puts every element back at the measured position and releases the
|
|
7523
|
-
* transition. Call AFTER the DOM already reflects the new state.
|
|
7524
|
-
*
|
|
7525
|
-
* @param frozenClass class that zeroes the transition on the inverted frame
|
|
7526
|
-
*/
|
|
7527
6479
|
function animateFlip(container, before, frozenClass) {
|
|
7528
6480
|
const moved = [];
|
|
7529
6481
|
container.querySelectorAll(`[${FLIP_ATTR}]`).forEach((el) => {
|
|
@@ -7531,9 +6483,6 @@ function animateFlip(container, before, frozenClass) {
|
|
|
7531
6483
|
if (!id)
|
|
7532
6484
|
return;
|
|
7533
6485
|
const from = before.get(id);
|
|
7534
|
-
// No previous measurement means the element was BORN just now. It does not
|
|
7535
|
-
// slide from anywhere — it comes in through its own entrance animation,
|
|
7536
|
-
// which is a different movement.
|
|
7537
6486
|
if (!from)
|
|
7538
6487
|
return;
|
|
7539
6488
|
const to = el.getBoundingClientRect();
|
|
@@ -7547,11 +6496,6 @@ function animateFlip(container, before, frozenClass) {
|
|
|
7547
6496
|
});
|
|
7548
6497
|
if (moved.length === 0)
|
|
7549
6498
|
return;
|
|
7550
|
-
// This read is mandatory and is not a hack: it forces the browser to compute
|
|
7551
|
-
// style with the inverted translate ALREADY applied. Without it the two
|
|
7552
|
-
// writes (invert and release) collapse into the same pass and nothing
|
|
7553
|
-
// animates.
|
|
7554
|
-
// eslint-disable-next-line no-void
|
|
7555
6499
|
void container.offsetWidth;
|
|
7556
6500
|
moved.forEach((el) => {
|
|
7557
6501
|
el.classList.remove(frozenClass);
|
|
@@ -7564,29 +6508,7 @@ function animateFlip(container, before, frozenClass) {
|
|
|
7564
6508
|
* This style guide was developed by Monkey Exchange Team
|
|
7565
6509
|
* MIT Licence
|
|
7566
6510
|
************************* */
|
|
7567
|
-
// ─── "Has the app painted yet?" ─────────────────────────────────────────────
|
|
7568
|
-
// A single shared boolean, so that components which animate on ENTERING the
|
|
7569
|
-
// DOM do not animate when they were already there at the first paint.
|
|
7570
|
-
//
|
|
7571
|
-
// Why it exists: `animate.enter` fires on the initial render of the view, not
|
|
7572
|
-
// only when the consumer mounts the component later. A filter bar that opens
|
|
7573
|
-
// with filters already seeded by the consumer would replay the whole row's
|
|
7574
|
-
// entrance on every page load and on every F5, for chips that were always
|
|
7575
|
-
// there. Users read that as the page still assembling itself.
|
|
7576
|
-
//
|
|
7577
|
-
// Why it cannot be solved inside the component: a per-instance signal does not
|
|
7578
|
-
// work. `animate.enter` is evaluated at the moment of INSERTION, and at that
|
|
7579
|
-
// moment the instance has just been created — any flag of its own is still
|
|
7580
|
-
// false, so the chip would simply never animate. "Has painted" is a notion of
|
|
7581
|
-
// the PAGE, not of the component.
|
|
7582
|
-
//
|
|
7583
|
-
// The double rAF is the usual pattern: the first frame schedules, the second
|
|
7584
|
-
// runs after the browser has painted.
|
|
7585
|
-
/** False until the browser paints the first frame. Read-only for consumers. */
|
|
7586
6511
|
let painted = false;
|
|
7587
|
-
// There is no `requestAnimationFrame` under SSR — and no animation to suppress
|
|
7588
|
-
// either, because the server does not paint. It stays false, and the client
|
|
7589
|
-
// reschedules on hydration.
|
|
7590
6512
|
if (typeof requestAnimationFrame === 'function') {
|
|
7591
6513
|
requestAnimationFrame(() => {
|
|
7592
6514
|
requestAnimationFrame(() => {
|
|
@@ -7594,16 +6516,6 @@ if (typeof requestAnimationFrame === 'function') {
|
|
|
7594
6516
|
});
|
|
7595
6517
|
});
|
|
7596
6518
|
}
|
|
7597
|
-
/**
|
|
7598
|
-
* Has the page painted its first frame?
|
|
7599
|
-
*
|
|
7600
|
-
* Use it to decide whether an `animate.enter` should apply:
|
|
7601
|
-
*
|
|
7602
|
-
* [animate.enter]="appPainted() ? 'mecx-x--entering' : ''"
|
|
7603
|
-
*
|
|
7604
|
-
* A component already on screen at the first paint comes in without animation;
|
|
7605
|
-
* one the consumer mounts later animates normally.
|
|
7606
|
-
*/
|
|
7607
6519
|
function appPainted() {
|
|
7608
6520
|
return painted;
|
|
7609
6521
|
}
|
|
@@ -7613,710 +6525,572 @@ function appPainted() {
|
|
|
7613
6525
|
* This style guide was developed by Monkey Exchange Team
|
|
7614
6526
|
* MIT Licence
|
|
7615
6527
|
************************* */
|
|
7616
|
-
|
|
7617
|
-
|
|
7618
|
-
|
|
7619
|
-
|
|
7620
|
-
|
|
7621
|
-
|
|
7622
|
-
|
|
7623
|
-
|
|
7624
|
-
|
|
7625
|
-
|
|
7626
|
-
|
|
7627
|
-
|
|
7628
|
-
// answers for each: date shortcuts and a custom range, currency as a
|
|
7629
|
-
// from/until with one amount, status as a multiple choice
|
|
7630
|
-
// · nothing is written to the service until the answer is CONFIRMED, except
|
|
7631
|
-
// for the date shortcuts, where the click on the row already is the answer
|
|
7632
|
-
//
|
|
7633
|
-
// WHAT CHANGES is the drawing and the movement:
|
|
7634
|
-
//
|
|
7635
|
-
// · the active filter becomes a two-segment CHIP instead of a tag. The
|
|
7636
|
-
// second segment is the edit affordance the tag used to be, and clicking
|
|
7637
|
-
// it reopens exactly the panel that filled it.
|
|
7638
|
-
// · the add-filter button lives at the END of the row and swaps variants:
|
|
7639
|
-
// while the bar is empty it is the CALL to action and carries the label;
|
|
7640
|
-
// with filters on screen it becomes a 28px `+`, because then it no longer
|
|
7641
|
-
// opens "the filters", it ADDS one more.
|
|
7642
|
-
// · the row SCROLLS horizontally instead of wrapping. Wrapping would push
|
|
7643
|
-
// everything below the bar down by one line on every filter added;
|
|
7644
|
-
// scrolling keeps the height stable.
|
|
7645
|
-
// · every change of the row is animated by FLIP (see flip.ts). Each step
|
|
7646
|
-
// changes the width of the whole row, and without FLIP only the new piece
|
|
7647
|
-
// would move while everything else jumped.
|
|
7648
|
-
//
|
|
7649
|
-
// The bar OWNS the state and the animation. The pieces below it —
|
|
7650
|
-
// monkey-filter-chip, monkey-filter-segment, monkey-filter-trigger,
|
|
7651
|
-
// monkey-filter-menu — know nothing about the progression: each one only draws
|
|
7652
|
-
// what it is given.
|
|
7653
|
-
/** Class that freezes the transition on the FLIP's inverted frame. */
|
|
7654
|
-
const FROZEN = 'mecx-filter-bar-v2-slot--frozen';
|
|
7655
|
-
class MonkeyFilterBarV2Component {
|
|
6528
|
+
const DATE_SHORTCUTS = [
|
|
6529
|
+
{ key: 'WEEK-AFTER', resolve: (t) => ({ start: t, end: addDays(t, 7) }) },
|
|
6530
|
+
{ key: 'MONTH-AFTER', resolve: (t) => ({ start: t, end: addMonths(t, 1) }) },
|
|
6531
|
+
{ key: 'QUARTER-AFTER', resolve: (t) => ({ start: t, end: addMonths(t, 3) }) },
|
|
6532
|
+
{ key: 'WEEK-BEFORE', resolve: (t) => ({ start: subDays(t, 7), end: t }) },
|
|
6533
|
+
{ key: 'MONTH-BEFORE', resolve: (t) => ({ start: subMonths(t, 1), end: t }) },
|
|
6534
|
+
{ key: 'QUARTER-BEFORE', resolve: (t) => ({ start: subMonths(t, 3), end: t }) }
|
|
6535
|
+
];
|
|
6536
|
+
const FROZEN = 'mecx-filter-bar-slot--frozen';
|
|
6537
|
+
const OPERAND_DATE_FORMAT = 'yyyy-MM-dd';
|
|
6538
|
+
const DEFAULT_DISPLAY_FORMAT = 'MM/dd/yyyy';
|
|
6539
|
+
class MonkeyFilterBarComponent {
|
|
7656
6540
|
constructor() {
|
|
7657
|
-
this._service = inject(MonkeyFilterBarService);
|
|
7658
6541
|
this._hostEl = inject(ElementRef);
|
|
7659
6542
|
this._injector = inject(Injector);
|
|
7660
|
-
|
|
7661
|
-
this.
|
|
6543
|
+
this._text = toSignal(inject(MonkeyDictionaryService).get('FILTER-BAR'));
|
|
6544
|
+
this._commitTimer = null;
|
|
6545
|
+
this._reported = signal([], ...(ngDevMode ? [{ debugName: "_reported" }] : /* istanbul ignore next */ []));
|
|
7662
6546
|
this.config = input(...(ngDevMode ? [undefined, { debugName: "config" }] : /* istanbul ignore next */ []));
|
|
7663
|
-
|
|
7664
|
-
this.
|
|
7665
|
-
this.
|
|
7666
|
-
this.
|
|
7667
|
-
this.
|
|
7668
|
-
/** A chip seeded by the consumer does not animate; one the user made does. */
|
|
6547
|
+
this.filters = input([], ...(ngDevMode ? [{ debugName: "filters" }] : /* istanbul ignore next */ []));
|
|
6548
|
+
this.onFiltersChange = output();
|
|
6549
|
+
this.dateFormat = input(DEFAULT_DISPLAY_FORMAT, ...(ngDevMode ? [{ debugName: "dateFormat" }] : /* istanbul ignore next */ []));
|
|
6550
|
+
this.disabled = input(false, { ...(ngDevMode ? { debugName: "disabled" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
|
|
6551
|
+
this.debounce = input(0, ...(ngDevMode ? [{ debugName: "debounce" }] : /* istanbul ignore next */ []));
|
|
7669
6552
|
this.appPainted = appPainted;
|
|
7670
|
-
|
|
7671
|
-
/**
|
|
7672
|
-
* The filter being built — chosen from the trigger, not yet confirmed, so
|
|
7673
|
-
* not yet in the service.
|
|
7674
|
-
*
|
|
7675
|
-
* It exists so the chip can be BORN where the trigger was, which is the
|
|
7676
|
-
* whole point of the row's animation, without the bar reporting a filter
|
|
7677
|
-
* that has no answer. Closing the panel without confirming drops it again:
|
|
7678
|
-
* monkey-filter-bar has no half-filled state and neither does this one.
|
|
7679
|
-
*/
|
|
7680
|
-
this.pending = signal(null, ...(ngDevMode ? [{ debugName: "pending" }] : /* istanbul ignore next */ []));
|
|
6553
|
+
this.rows = signal([], ...(ngDevMode ? [{ debugName: "rows" }] : /* istanbul ignore next */ []));
|
|
7681
6554
|
this.openPanel = signal(null, ...(ngDevMode ? [{ debugName: "openPanel" }] : /* istanbul ignore next */ []));
|
|
7682
6555
|
this.triggerOpen = signal(false, ...(ngDevMode ? [{ debugName: "triggerOpen" }] : /* istanbul ignore next */ []));
|
|
7683
|
-
/**
|
|
7684
|
-
* The filter whose date panel is showing the CALENDAR instead of the
|
|
7685
|
-
* shortcuts, or `null`.
|
|
7686
|
-
*
|
|
7687
|
-
* It is the same panel, anchored to the same segment — "Personalizado" only
|
|
7688
|
-
* swaps its content. No modal: the dialog would be almost all frame around a
|
|
7689
|
-
* calendar, and frame is not an answer to anything.
|
|
7690
|
-
*/
|
|
7691
6556
|
this.calendarOpen = signal(null, ...(ngDevMode ? [{ debugName: "calendarOpen" }] : /* istanbul ignore next */ []));
|
|
7692
|
-
/** Search of the category panel. */
|
|
7693
6557
|
this.categorySearch = signal('', ...(ngDevMode ? [{ debugName: "categorySearch" }] : /* istanbul ignore next */ []));
|
|
7694
|
-
/**
|
|
7695
|
-
* Turns off the fade on the trigger's panel. It is written BEFORE the
|
|
7696
|
-
* mutation on purpose: `animate.leave` is read the instant the node leaves,
|
|
7697
|
-
* and turning it on afterwards would arrive too late.
|
|
7698
|
-
*/
|
|
7699
6558
|
this.immediateTriggerExit = signal(false, ...(ngDevMode ? [{ debugName: "immediateTriggerExit" }] : /* istanbul ignore next */ []));
|
|
7700
|
-
// Draft answers of the open panel. They are plain fields and not signals:
|
|
7701
|
-
// they are bound with `[(ngModel)]`, so the template writes them directly,
|
|
7702
|
-
// and nothing else in the view is derived from them.
|
|
7703
6559
|
this.textValue = '';
|
|
6560
|
+
this.textValue2 = '';
|
|
7704
6561
|
this.currencyValue = null;
|
|
7705
|
-
this.
|
|
6562
|
+
this.currencyValue2 = null;
|
|
7706
6563
|
this.statusValues = [];
|
|
7707
6564
|
this.dateRange = { startDate: '', endDate: '' };
|
|
7708
|
-
|
|
7709
|
-
this.
|
|
7710
|
-
|
|
7711
|
-
|
|
7712
|
-
|
|
7713
|
-
|
|
7714
|
-
|
|
7715
|
-
|
|
7716
|
-
|
|
7717
|
-
|
|
7718
|
-
|
|
7719
|
-
|
|
7720
|
-
|
|
7721
|
-
|
|
7722
|
-
|
|
7723
|
-
|
|
7724
|
-
|
|
7725
|
-
this.
|
|
7726
|
-
const
|
|
7727
|
-
|
|
7728
|
-
|
|
7729
|
-
label: f.label,
|
|
7730
|
-
icon: f.icon,
|
|
7731
|
-
type: f.type,
|
|
7732
|
-
value: f.displayText,
|
|
7733
|
-
pending: false
|
|
7734
|
-
};
|
|
6565
|
+
this.dayValue = '';
|
|
6566
|
+
this.options = computed(() => this.config()?.filterOptions ?? [], ...(ngDevMode ? [{ debugName: "options" }] : /* istanbul ignore next */ []));
|
|
6567
|
+
this.labels = computed(() => {
|
|
6568
|
+
const text = this._text();
|
|
6569
|
+
return {
|
|
6570
|
+
add: text?.ADD ?? '',
|
|
6571
|
+
addAria: text?.['ADD-ARIA'] ?? '',
|
|
6572
|
+
clear: text?.CLEAR ?? '',
|
|
6573
|
+
search: text?.SEARCH ?? '',
|
|
6574
|
+
selectCondition: text?.['SELECT-CONDITION'] ?? '',
|
|
6575
|
+
select: text?.SELECT ?? '',
|
|
6576
|
+
confirm: text?.CONFIRM ?? '',
|
|
6577
|
+
rangeFrom: text?.['RANGE-FROM'] ?? '',
|
|
6578
|
+
rangeTo: text?.['RANGE-TO'] ?? '',
|
|
6579
|
+
remove: text?.REMOVE ?? ''
|
|
6580
|
+
};
|
|
6581
|
+
}, ...(ngDevMode ? [{ debugName: "labels" }] : /* istanbul ignore next */ []));
|
|
6582
|
+
this.dateShortcuts = computed(() => {
|
|
6583
|
+
const date = this._text()?.DATE ?? {};
|
|
6584
|
+
return [...DATE_SHORTCUTS.map((shortcut) => shortcut.key), 'CUSTOM'].map((key) => {
|
|
6585
|
+
return { key, label: date[key] ?? '' };
|
|
7735
6586
|
});
|
|
7736
|
-
|
|
7737
|
-
if (!draft)
|
|
7738
|
-
return confirmed;
|
|
7739
|
-
return [
|
|
7740
|
-
...confirmed,
|
|
7741
|
-
{
|
|
7742
|
-
key: draft.key,
|
|
7743
|
-
label: draft.label,
|
|
7744
|
-
icon: draft.icon,
|
|
7745
|
-
type: draft.type,
|
|
7746
|
-
value: '',
|
|
7747
|
-
pending: true
|
|
7748
|
-
}
|
|
7749
|
-
];
|
|
7750
|
-
}, ...(ngDevMode ? [{ debugName: "rows" }] : /* istanbul ignore next */ []));
|
|
7751
|
-
/**
|
|
7752
|
-
* What the TRIGGER offers: only what can still be added.
|
|
7753
|
-
*
|
|
7754
|
-
* This is monkey-filter-bar's rule — a filter already on the row is not on
|
|
7755
|
-
* offer, because the bar holds one filter per key.
|
|
7756
|
-
*/
|
|
6587
|
+
}, ...(ngDevMode ? [{ debugName: "dateShortcuts" }] : /* istanbul ignore next */ []));
|
|
7757
6588
|
this.addOptions = computed(() => {
|
|
7758
|
-
const
|
|
7759
|
-
|
|
7760
|
-
return this._matchingSearch(available);
|
|
6589
|
+
const taken = new Set(this.rows().map((row) => row.key));
|
|
6590
|
+
return this.matchingSearch(this.options().filter((option) => !taken.has(option.key)));
|
|
7761
6591
|
}, ...(ngDevMode ? [{ debugName: "addOptions" }] : /* istanbul ignore next */ []));
|
|
7762
|
-
|
|
7763
|
-
|
|
7764
|
-
|
|
7765
|
-
|
|
7766
|
-
|
|
7767
|
-
* is the one carrying the check — and the other filters already on the row
|
|
7768
|
-
* are shown greyed out rather than hidden, which is what tells the user the
|
|
7769
|
-
* category they were looking for is already in use.
|
|
7770
|
-
*/
|
|
7771
|
-
this.changeOptions = computed(() => {
|
|
7772
|
-
return this._matchingSearch(this.serviceConfig()?.filterOptions ?? []);
|
|
7773
|
-
}, ...(ngDevMode ? [{ debugName: "changeOptions" }] : /* istanbul ignore next */ []));
|
|
7774
|
-
/**
|
|
7775
|
-
* While the bar is empty the trigger is the CALL and earns the label. With
|
|
7776
|
-
* filters on screen a 28px square is enough.
|
|
7777
|
-
*/
|
|
6592
|
+
this.canAddFilter = computed(() => {
|
|
6593
|
+
const taken = new Set(this.rows().map((row) => row.key));
|
|
6594
|
+
return this.options().some((option) => !taken.has(option.key));
|
|
6595
|
+
}, ...(ngDevMode ? [{ debugName: "canAddFilter" }] : /* istanbul ignore next */ []));
|
|
6596
|
+
this.changeOptions = computed(() => this.matchingSearch(this.options()), ...(ngDevMode ? [{ debugName: "changeOptions" }] : /* istanbul ignore next */ []));
|
|
7778
6597
|
this.triggerVariant = computed(() => {
|
|
7779
6598
|
return this.rows().length === 0 ? 'text' : 'icon';
|
|
7780
6599
|
}, ...(ngDevMode ? [{ debugName: "triggerVariant" }] : /* istanbul ignore next */ []));
|
|
7781
|
-
/**
|
|
7782
|
-
* The glyph of the collapsed trigger is a `+`, not the funnel.
|
|
7783
|
-
*
|
|
7784
|
-
* The variant says what the button IS; the glyph says what it DOES. With
|
|
7785
|
-
* filters already on screen the button does not open "the filters", it ADDS
|
|
7786
|
-
* one more — and a funnel there reads as the wrong thing. With the bar empty
|
|
7787
|
-
* the funnel is exact.
|
|
7788
|
-
*/
|
|
7789
6600
|
this.triggerIcon = computed(() => {
|
|
7790
6601
|
return this.rows().length === 0 ? 'filter' : 'add-plus';
|
|
7791
6602
|
}, ...(ngDevMode ? [{ debugName: "triggerIcon" }] : /* istanbul ignore next */ []));
|
|
7792
|
-
/**
|
|
7793
|
-
* The FLIP identity changes along with the variant, and that is the fix: the
|
|
7794
|
-
* text trigger is REMOVED and the icon one is BORN in its place, instead of
|
|
7795
|
-
* one button sliding to the right. Before this, the button dragged along the
|
|
7796
|
-
* panel that was closing — the list vanished travelling sideways.
|
|
7797
|
-
*
|
|
7798
|
-
* From the second filter on the identity holds, and then the `+` really does
|
|
7799
|
-
* slide: that movement is what says "the row grew".
|
|
7800
|
-
*/
|
|
7801
6603
|
this.triggerFlipId = computed(() => {
|
|
7802
6604
|
return this.rows().length === 0 ? 'trigger-text' : 'trigger-icon';
|
|
7803
6605
|
}, ...(ngDevMode ? [{ debugName: "triggerFlipId" }] : /* istanbul ignore next */ []));
|
|
7804
|
-
// The config is registered in the service by the same key the state uses,
|
|
7805
|
-
// so any other consumer of the service sees the same option list. An
|
|
7806
|
-
// effect and not ngOnInit/ngOnChanges: `key` and `config` are signal
|
|
7807
|
-
// inputs, so one reactive registration covers the first value and every
|
|
7808
|
-
// one after it.
|
|
7809
6606
|
effect(() => {
|
|
7810
|
-
const
|
|
7811
|
-
|
|
7812
|
-
|
|
7813
|
-
|
|
6607
|
+
const incoming = this.filters();
|
|
6608
|
+
untracked(() => {
|
|
6609
|
+
if (this.sameAsRows(incoming))
|
|
6610
|
+
return;
|
|
6611
|
+
this._reported.set(incoming);
|
|
6612
|
+
this.rows.set(incoming.map((filter) => {
|
|
6613
|
+
const option = this.options().find((item) => item.key === filter.key);
|
|
6614
|
+
return {
|
|
6615
|
+
key: filter.key,
|
|
6616
|
+
label: filter.label,
|
|
6617
|
+
icon: option?.icon,
|
|
6618
|
+
type: filter.type,
|
|
6619
|
+
condition: filter.condition,
|
|
6620
|
+
operands: filter.operands
|
|
6621
|
+
};
|
|
6622
|
+
}));
|
|
6623
|
+
});
|
|
6624
|
+
});
|
|
6625
|
+
effect(() => {
|
|
6626
|
+
if (!this.disabled())
|
|
6627
|
+
return;
|
|
6628
|
+
untracked(() => {
|
|
6629
|
+
this.triggerOpen.set(false);
|
|
6630
|
+
this.closePanel();
|
|
6631
|
+
});
|
|
6632
|
+
});
|
|
6633
|
+
inject(DestroyRef).onDestroy(() => this.cancelCommit());
|
|
6634
|
+
}
|
|
6635
|
+
askForAnswer(row) {
|
|
6636
|
+
if (isComplete(row)) {
|
|
6637
|
+
this.resetDraft();
|
|
6638
|
+
this.openPanel.set(null);
|
|
6639
|
+
return;
|
|
6640
|
+
}
|
|
6641
|
+
this.seedDraft(row);
|
|
6642
|
+
this.openPanel.set({ key: row.key, part: 'value' });
|
|
6643
|
+
}
|
|
6644
|
+
seedDraft(row) {
|
|
6645
|
+
this.resetDraft();
|
|
6646
|
+
this.calendarOpen.set(null);
|
|
6647
|
+
const [first, second] = row.operands;
|
|
6648
|
+
switch (this.panelFor(row)) {
|
|
6649
|
+
case 'status':
|
|
6650
|
+
this.statusValues = first?.kind === 'selection' ? [...first.values] : [];
|
|
6651
|
+
break;
|
|
6652
|
+
case 'field':
|
|
6653
|
+
if (row.type === 'currency') {
|
|
6654
|
+
this.currencyValue = first?.kind === 'number' ? first.value : null;
|
|
6655
|
+
this.currencyValue2 = second?.kind === 'number' ? second.value : null;
|
|
6656
|
+
}
|
|
6657
|
+
else {
|
|
6658
|
+
this.textValue = first?.kind === 'text' ? first.value : '';
|
|
6659
|
+
this.textValue2 = second?.kind === 'text' ? second.value : '';
|
|
6660
|
+
}
|
|
6661
|
+
break;
|
|
6662
|
+
case 'date-day':
|
|
6663
|
+
this.dayValue = first?.kind === 'date' ? first.value : '';
|
|
6664
|
+
break;
|
|
6665
|
+
case 'date-range':
|
|
6666
|
+
this.dateRange = {
|
|
6667
|
+
startDate: first?.kind === 'date' ? first.value : '',
|
|
6668
|
+
endDate: second?.kind === 'date' ? second.value : ''
|
|
6669
|
+
};
|
|
6670
|
+
if (this.dateRange.startDate)
|
|
6671
|
+
this.calendarOpen.set(row.key);
|
|
6672
|
+
break;
|
|
6673
|
+
default:
|
|
6674
|
+
break;
|
|
6675
|
+
}
|
|
6676
|
+
}
|
|
6677
|
+
readDraft(row) {
|
|
6678
|
+
const range = this.isRange(row);
|
|
6679
|
+
switch (this.panelFor(row)) {
|
|
6680
|
+
case 'status': {
|
|
6681
|
+
if (this.statusValues.length === 0)
|
|
6682
|
+
return null;
|
|
6683
|
+
return [{ kind: 'selection', values: [...this.statusValues] }];
|
|
6684
|
+
}
|
|
6685
|
+
case 'field': {
|
|
6686
|
+
if (row.type === 'currency') {
|
|
6687
|
+
const from = this.currencyValue;
|
|
6688
|
+
if (from === null || from === undefined)
|
|
6689
|
+
return null;
|
|
6690
|
+
if (!range)
|
|
6691
|
+
return [{ kind: 'number', value: from }];
|
|
6692
|
+
const to = this.currencyValue2;
|
|
6693
|
+
if (to === null || to === undefined)
|
|
6694
|
+
return null;
|
|
6695
|
+
const [low, high] = from <= to ? [from, to] : [to, from];
|
|
6696
|
+
return [
|
|
6697
|
+
{ kind: 'number', value: low },
|
|
6698
|
+
{ kind: 'number', value: high }
|
|
6699
|
+
];
|
|
6700
|
+
}
|
|
6701
|
+
const text = this.textValue.trim();
|
|
6702
|
+
if (!text)
|
|
6703
|
+
return null;
|
|
6704
|
+
if (!range)
|
|
6705
|
+
return [{ kind: 'text', value: text }];
|
|
6706
|
+
const text2 = this.textValue2.trim();
|
|
6707
|
+
if (!text2)
|
|
6708
|
+
return null;
|
|
6709
|
+
return [
|
|
6710
|
+
{ kind: 'text', value: text },
|
|
6711
|
+
{ kind: 'text', value: text2 }
|
|
6712
|
+
];
|
|
6713
|
+
}
|
|
6714
|
+
case 'date-day': {
|
|
6715
|
+
if (!this.dayValue)
|
|
6716
|
+
return null;
|
|
6717
|
+
return [{ kind: 'date', value: this.dayValue }];
|
|
6718
|
+
}
|
|
6719
|
+
case 'date-range': {
|
|
6720
|
+
const { startDate, endDate } = this.dateRange;
|
|
6721
|
+
if (!startDate || !endDate)
|
|
6722
|
+
return null;
|
|
6723
|
+
return [
|
|
6724
|
+
{ kind: 'date', value: startDate },
|
|
6725
|
+
{ kind: 'date', value: endDate }
|
|
6726
|
+
];
|
|
6727
|
+
}
|
|
6728
|
+
default:
|
|
6729
|
+
return null;
|
|
6730
|
+
}
|
|
6731
|
+
}
|
|
6732
|
+
money(value) {
|
|
6733
|
+
return value.toLocaleString('pt-BR', { style: 'currency', currency: 'BRL' });
|
|
6734
|
+
}
|
|
6735
|
+
showDate(iso) {
|
|
6736
|
+
if (!iso)
|
|
6737
|
+
return '';
|
|
6738
|
+
const parsed = parseISO(iso);
|
|
6739
|
+
if (Number.isNaN(parsed.getTime()))
|
|
6740
|
+
return iso;
|
|
6741
|
+
return format(parsed, this.dateFormat() || DEFAULT_DISPLAY_FORMAT);
|
|
6742
|
+
}
|
|
6743
|
+
open(key, part) {
|
|
6744
|
+
this.openPanel.set({ key, part });
|
|
6745
|
+
}
|
|
6746
|
+
closePanel() {
|
|
6747
|
+
this.openPanel.set(null);
|
|
6748
|
+
this.calendarOpen.set(null);
|
|
6749
|
+
this.resetDraft();
|
|
6750
|
+
}
|
|
6751
|
+
optionFor(optionKey) {
|
|
6752
|
+
return this.options().find((option) => option.key === optionKey);
|
|
6753
|
+
}
|
|
6754
|
+
matchingSearch(options) {
|
|
6755
|
+
const term = this.categorySearch().trim().toLowerCase();
|
|
6756
|
+
if (!term)
|
|
6757
|
+
return [...options];
|
|
6758
|
+
return options.filter((option) => option.label.toLowerCase().includes(term));
|
|
6759
|
+
}
|
|
6760
|
+
resetDraft() {
|
|
6761
|
+
this.textValue = '';
|
|
6762
|
+
this.textValue2 = '';
|
|
6763
|
+
this.currencyValue = null;
|
|
6764
|
+
this.currencyValue2 = null;
|
|
6765
|
+
this.statusValues = [];
|
|
6766
|
+
this.dateRange = { startDate: '', endDate: '' };
|
|
6767
|
+
this.dayValue = '';
|
|
6768
|
+
}
|
|
6769
|
+
sameAsRows(incoming) {
|
|
6770
|
+
const current = appliedFrom(this.rows());
|
|
6771
|
+
if (current.length !== incoming.length)
|
|
6772
|
+
return false;
|
|
6773
|
+
return current.every((filter, index) => {
|
|
6774
|
+
const other = incoming[index];
|
|
6775
|
+
return (filter.key === other.key &&
|
|
6776
|
+
filter.condition === other.condition &&
|
|
6777
|
+
JSON.stringify(filter.operands) === JSON.stringify(other.operands));
|
|
6778
|
+
});
|
|
6779
|
+
}
|
|
6780
|
+
commit() {
|
|
6781
|
+
this.cancelCommit();
|
|
6782
|
+
if (this.sameAsRows(this._reported()))
|
|
6783
|
+
return;
|
|
6784
|
+
const wait = this.debounce();
|
|
6785
|
+
if (wait <= 0) {
|
|
6786
|
+
this.publish();
|
|
6787
|
+
return;
|
|
6788
|
+
}
|
|
6789
|
+
this._commitTimer = setTimeout(() => {
|
|
6790
|
+
this._commitTimer = null;
|
|
6791
|
+
this.publish();
|
|
6792
|
+
}, wait);
|
|
6793
|
+
}
|
|
6794
|
+
publish() {
|
|
6795
|
+
const applied = appliedFrom(this.rows());
|
|
6796
|
+
this._reported.set(applied);
|
|
6797
|
+
this.onFiltersChange.emit(applied);
|
|
6798
|
+
}
|
|
6799
|
+
cancelCommit() {
|
|
6800
|
+
if (this._commitTimer === null)
|
|
6801
|
+
return;
|
|
6802
|
+
clearTimeout(this._commitTimer);
|
|
6803
|
+
this._commitTimer = null;
|
|
6804
|
+
}
|
|
6805
|
+
releaseFromFlow(container, leaving) {
|
|
6806
|
+
leaving.forEach((id) => {
|
|
6807
|
+
const slot = container.querySelector(`[${FLIP_ATTR}="${id}"]`);
|
|
6808
|
+
if (!slot)
|
|
6809
|
+
return;
|
|
6810
|
+
slot.style.left = `${slot.offsetLeft}px`;
|
|
6811
|
+
slot.style.top = `${slot.offsetTop}px`;
|
|
6812
|
+
slot.style.position = 'absolute';
|
|
7814
6813
|
});
|
|
7815
6814
|
}
|
|
7816
|
-
|
|
6815
|
+
followEnd(container) {
|
|
6816
|
+
const row = container.querySelector('.mecx-filter-bar-row');
|
|
6817
|
+
if (!row)
|
|
6818
|
+
return;
|
|
6819
|
+
const last = this.lastMovingSlot(row);
|
|
6820
|
+
if (!last)
|
|
6821
|
+
return;
|
|
6822
|
+
const room = parseFloat(getComputedStyle(row).paddingInlineEnd) || 0;
|
|
6823
|
+
const excess = last.getBoundingClientRect().right + room - row.getBoundingClientRect().right;
|
|
6824
|
+
if (excess <= 0)
|
|
6825
|
+
return;
|
|
6826
|
+
row.scrollLeft += excess;
|
|
6827
|
+
}
|
|
6828
|
+
lastMovingSlot(row) {
|
|
6829
|
+
const slots = Array.from(row.querySelectorAll(`[${FLIP_ATTR}]`));
|
|
6830
|
+
for (let index = slots.length - 1; index >= 0; index -= 1) {
|
|
6831
|
+
if (getComputedStyle(slots[index]).position !== 'sticky')
|
|
6832
|
+
return slots[index];
|
|
6833
|
+
}
|
|
6834
|
+
return null;
|
|
6835
|
+
}
|
|
6836
|
+
withFlip(mutate, options = {}) {
|
|
6837
|
+
const { leaving = [], follow = true } = options;
|
|
6838
|
+
const container = this._hostEl.nativeElement;
|
|
6839
|
+
const before = measureFlip(container);
|
|
6840
|
+
this.releaseFromFlow(container, leaving);
|
|
6841
|
+
mutate();
|
|
6842
|
+
afterNextRender(() => {
|
|
6843
|
+
if (follow)
|
|
6844
|
+
this.followEnd(container);
|
|
6845
|
+
animateFlip(container, before, FROZEN);
|
|
6846
|
+
this.immediateTriggerExit.set(false);
|
|
6847
|
+
}, { injector: this._injector });
|
|
6848
|
+
}
|
|
6849
|
+
operatorLabel(operator) {
|
|
6850
|
+
if (!operator)
|
|
6851
|
+
return '';
|
|
6852
|
+
return this._text()?.OPERATOR?.[operator] ?? '';
|
|
6853
|
+
}
|
|
7817
6854
|
isOpen(rowKey, part) {
|
|
7818
6855
|
const panel = this.openPanel();
|
|
7819
6856
|
return !!panel && panel.key === rowKey && panel.part === part;
|
|
7820
6857
|
}
|
|
7821
6858
|
isFilterActive(optionKey) {
|
|
7822
|
-
|
|
7823
|
-
return k ? this._service.isFilterActive(k, optionKey) : false;
|
|
6859
|
+
return this.rows().some((row) => row.key === optionKey);
|
|
7824
6860
|
}
|
|
7825
|
-
/** A divider goes where the type changes relative to the row above. */
|
|
7826
6861
|
needsDivider(options, index) {
|
|
7827
6862
|
return index > 0 && options[index].type !== options[index - 1].type;
|
|
7828
6863
|
}
|
|
6864
|
+
conditionsFor(row) {
|
|
6865
|
+
return conditionsOf(row.type);
|
|
6866
|
+
}
|
|
6867
|
+
panelFor(row) {
|
|
6868
|
+
return panelOf(row.type, row.condition);
|
|
6869
|
+
}
|
|
6870
|
+
hasValueSegment(row) {
|
|
6871
|
+
return this.panelFor(row) !== 'none';
|
|
6872
|
+
}
|
|
6873
|
+
isRange(row) {
|
|
6874
|
+
return arityOf(row.condition) === 2;
|
|
6875
|
+
}
|
|
6876
|
+
displayOf(row) {
|
|
6877
|
+
const [first, second] = row.operands;
|
|
6878
|
+
switch (this.panelFor(row)) {
|
|
6879
|
+
case 'status': {
|
|
6880
|
+
if (first?.kind !== 'selection' || first.values.length === 0)
|
|
6881
|
+
return '';
|
|
6882
|
+
if (first.values.length > 1) {
|
|
6883
|
+
return (this._text()?.SELECTED ?? '').replace('{count}', String(first.values.length));
|
|
6884
|
+
}
|
|
6885
|
+
const option = this.statusOptionsOf(row).find((item) => item.value === first.values[0]);
|
|
6886
|
+
return option?.description ?? first.values[0];
|
|
6887
|
+
}
|
|
6888
|
+
case 'field': {
|
|
6889
|
+
const write = (operand) => {
|
|
6890
|
+
if (operand?.kind === 'number')
|
|
6891
|
+
return this.money(operand.value);
|
|
6892
|
+
if (operand?.kind === 'text')
|
|
6893
|
+
return operand.value;
|
|
6894
|
+
return '';
|
|
6895
|
+
};
|
|
6896
|
+
if (!this.isRange(row))
|
|
6897
|
+
return write(first);
|
|
6898
|
+
return `${write(first)} – ${write(second)}`;
|
|
6899
|
+
}
|
|
6900
|
+
case 'date-day':
|
|
6901
|
+
return first?.kind === 'date' ? this.showDate(first.value) : '';
|
|
6902
|
+
case 'date-range': {
|
|
6903
|
+
if (first?.kind !== 'date' || second?.kind !== 'date')
|
|
6904
|
+
return '';
|
|
6905
|
+
return `${this.showDate(first.value)} – ${this.showDate(second.value)}`;
|
|
6906
|
+
}
|
|
6907
|
+
default:
|
|
6908
|
+
return '';
|
|
6909
|
+
}
|
|
6910
|
+
}
|
|
7829
6911
|
valuePlaceholder(row) {
|
|
7830
|
-
return this.
|
|
6912
|
+
return this.optionFor(row.key)?.placeholder ?? this.labels().select;
|
|
7831
6913
|
}
|
|
7832
6914
|
statusOptionsOf(row) {
|
|
7833
|
-
return this.
|
|
6915
|
+
return this.optionFor(row.key)?.statusOptions ?? [];
|
|
7834
6916
|
}
|
|
7835
6917
|
minDateOf(row) {
|
|
7836
|
-
return this.
|
|
6918
|
+
return this.optionFor(row.key)?.minDate ?? '';
|
|
7837
6919
|
}
|
|
7838
6920
|
maxDateOf(row) {
|
|
7839
|
-
return this.
|
|
6921
|
+
return this.optionFor(row.key)?.maxDate ?? '';
|
|
7840
6922
|
}
|
|
7841
|
-
// ── Progression ──────────────────────────────────────────────────────────
|
|
7842
|
-
/**
|
|
7843
|
-
* `index` is the position in the list the template walked — the one the
|
|
7844
|
-
* search filtered. Indexing the full list would pick the wrong option.
|
|
7845
|
-
*/
|
|
7846
6923
|
onSelectCategory(index) {
|
|
7847
6924
|
const option = this.addOptions()[index];
|
|
7848
6925
|
if (!option)
|
|
7849
6926
|
return;
|
|
7850
|
-
// Choosing a category swaps the trigger's VARIANT (text → icon) and with
|
|
7851
|
-
// it its place in the row. The panel is a child of the button and would
|
|
7852
|
-
// travel along.
|
|
7853
6927
|
this.immediateTriggerExit.set(true);
|
|
7854
|
-
this.
|
|
6928
|
+
this.withFlip(() => {
|
|
7855
6929
|
this.triggerOpen.set(false);
|
|
7856
6930
|
this.categorySearch.set('');
|
|
7857
|
-
this.
|
|
6931
|
+
this.resetDraft();
|
|
7858
6932
|
this.calendarOpen.set(null);
|
|
7859
|
-
this.
|
|
7860
|
-
|
|
7861
|
-
|
|
7862
|
-
|
|
7863
|
-
|
|
6933
|
+
this.rows.update((rows) => [
|
|
6934
|
+
...rows,
|
|
6935
|
+
{
|
|
6936
|
+
key: option.key,
|
|
6937
|
+
label: option.label,
|
|
6938
|
+
icon: option.icon,
|
|
6939
|
+
type: option.type,
|
|
6940
|
+
condition: '',
|
|
6941
|
+
operands: []
|
|
6942
|
+
}
|
|
6943
|
+
]);
|
|
6944
|
+
this.openPanel.set({ key: option.key, part: 'condition' });
|
|
7864
6945
|
});
|
|
7865
6946
|
}
|
|
7866
|
-
/**
|
|
7867
|
-
* Swaps the category of a chip that already exists, from its first segment.
|
|
7868
|
-
*
|
|
7869
|
-
* The answer always falls: it belongs to the old category's domain — a list
|
|
7870
|
-
* of statuses means nothing inside a date range — so the chip goes back to
|
|
7871
|
-
* waiting, with its value panel open.
|
|
7872
|
-
*/
|
|
7873
6947
|
onChangeCategory(row, index) {
|
|
7874
6948
|
const option = this.changeOptions()[index];
|
|
7875
6949
|
if (!option)
|
|
7876
6950
|
return;
|
|
7877
|
-
// The same category: nothing to swap, so the click just moves on to the
|
|
7878
|
-
// answer, which is the only thing left to change.
|
|
7879
6951
|
if (option.key === row.key) {
|
|
7880
|
-
this.
|
|
6952
|
+
this.open(row.key, 'condition');
|
|
7881
6953
|
return;
|
|
7882
6954
|
}
|
|
7883
6955
|
if (this.isFilterActive(option.key))
|
|
7884
6956
|
return;
|
|
7885
|
-
this.
|
|
7886
|
-
|
|
7887
|
-
if (k && !row.pending)
|
|
7888
|
-
this._service.removeFilter(k, row.key);
|
|
7889
|
-
this._resetDraft();
|
|
6957
|
+
this.withFlip(() => {
|
|
6958
|
+
this.resetDraft();
|
|
7890
6959
|
this.calendarOpen.set(null);
|
|
7891
6960
|
this.categorySearch.set('');
|
|
7892
|
-
|
|
7893
|
-
|
|
7894
|
-
|
|
7895
|
-
|
|
7896
|
-
|
|
7897
|
-
|
|
7898
|
-
|
|
7899
|
-
|
|
6961
|
+
const next = withType(row, {
|
|
6962
|
+
key: option.key,
|
|
6963
|
+
label: option.label,
|
|
6964
|
+
icon: option.icon,
|
|
6965
|
+
type: option.type
|
|
6966
|
+
});
|
|
6967
|
+
this.rows.update((rows) => rows.map((item) => (item.key === row.key ? next : item)));
|
|
6968
|
+
if (next.condition)
|
|
6969
|
+
this.askForAnswer(next);
|
|
6970
|
+
else
|
|
6971
|
+
this.openPanel.set({ key: next.key, part: 'condition' });
|
|
6972
|
+
}, { leaving: [row.key], follow: false });
|
|
6973
|
+
this.commit();
|
|
6974
|
+
}
|
|
6975
|
+
onSelectCondition(row, condition) {
|
|
6976
|
+
const next = withCondition(row, condition);
|
|
6977
|
+
this.withFlip(() => {
|
|
6978
|
+
this.rows.update((rows) => rows.map((item) => (item.key === row.key ? next : item)));
|
|
6979
|
+
this.calendarOpen.set(null);
|
|
6980
|
+
this.askForAnswer(next);
|
|
6981
|
+
});
|
|
6982
|
+
this.commit();
|
|
7900
6983
|
}
|
|
7901
|
-
/**
|
|
7902
|
-
* Opening the trigger closes whatever chip panel was open: only one panel is
|
|
7903
|
-
* ever on screen, and a draft chip whose panel was abandoned goes with it.
|
|
7904
|
-
*/
|
|
7905
6984
|
onTriggerOpenChange(open) {
|
|
7906
6985
|
this.categorySearch.set('');
|
|
7907
6986
|
this.triggerOpen.set(open);
|
|
7908
6987
|
if (!open)
|
|
7909
6988
|
return;
|
|
7910
|
-
if (this.pending()) {
|
|
7911
|
-
this._dropPending();
|
|
7912
|
-
return;
|
|
7913
|
-
}
|
|
7914
6989
|
this.openPanel.set(null);
|
|
7915
6990
|
this.calendarOpen.set(null);
|
|
7916
|
-
this.
|
|
6991
|
+
this.resetDraft();
|
|
7917
6992
|
}
|
|
7918
6993
|
onCategoryOpenChange(row, open) {
|
|
7919
6994
|
this.categorySearch.set('');
|
|
7920
6995
|
if (!open) {
|
|
7921
|
-
this.
|
|
6996
|
+
this.closePanel();
|
|
6997
|
+
return;
|
|
6998
|
+
}
|
|
6999
|
+
this.triggerOpen.set(false);
|
|
7000
|
+
this.open(row.key, 'category');
|
|
7001
|
+
}
|
|
7002
|
+
onConditionOpenChange(row, open) {
|
|
7003
|
+
if (!open) {
|
|
7004
|
+
this.closePanel();
|
|
7922
7005
|
return;
|
|
7923
7006
|
}
|
|
7924
7007
|
this.triggerOpen.set(false);
|
|
7925
|
-
this.
|
|
7008
|
+
this.open(row.key, 'condition');
|
|
7926
7009
|
}
|
|
7927
7010
|
onValueOpenChange(row, open) {
|
|
7928
7011
|
if (!open) {
|
|
7929
|
-
this.
|
|
7012
|
+
this.closePanel();
|
|
7930
7013
|
return;
|
|
7931
7014
|
}
|
|
7932
7015
|
this.triggerOpen.set(false);
|
|
7933
|
-
this.
|
|
7016
|
+
this.seedDraft(row);
|
|
7017
|
+
this.open(row.key, 'value');
|
|
7934
7018
|
}
|
|
7935
|
-
|
|
7936
|
-
|
|
7937
|
-
* The same shortcuts monkey-filter-bar offers. "Personalizado" is the only
|
|
7938
|
-
* one that does not resolve the interval on its own: it swaps the panel's
|
|
7939
|
-
* content for the calendar, in the same place.
|
|
7940
|
-
*/
|
|
7941
|
-
onQuickDate(row, preset) {
|
|
7942
|
-
const option = this._optionFor(row.key);
|
|
7943
|
-
if (!option || option.type !== 'date')
|
|
7019
|
+
onQuickDate(row, key) {
|
|
7020
|
+
if (row.type !== 'date')
|
|
7944
7021
|
return;
|
|
7945
|
-
if (
|
|
7022
|
+
if (key === 'CUSTOM') {
|
|
7946
7023
|
this.dateRange = { startDate: '', endDate: '' };
|
|
7947
7024
|
this.calendarOpen.set(row.key);
|
|
7948
7025
|
return;
|
|
7949
7026
|
}
|
|
7950
|
-
const
|
|
7951
|
-
|
|
7952
|
-
|
|
7953
|
-
|
|
7954
|
-
case '1-week-after':
|
|
7955
|
-
end = addDays(today, 7);
|
|
7956
|
-
break;
|
|
7957
|
-
case '1-month-after':
|
|
7958
|
-
end = addMonths(today, 1);
|
|
7959
|
-
break;
|
|
7960
|
-
case '3-months-after':
|
|
7961
|
-
end = addMonths(today, 3);
|
|
7962
|
-
break;
|
|
7963
|
-
case '1-week-before':
|
|
7964
|
-
start = subDays(today, 7);
|
|
7965
|
-
break;
|
|
7966
|
-
case '1-month-before':
|
|
7967
|
-
start = subMonths(today, 1);
|
|
7968
|
-
break;
|
|
7969
|
-
case '3-months-before':
|
|
7970
|
-
start = subMonths(today, 3);
|
|
7971
|
-
break;
|
|
7972
|
-
default:
|
|
7973
|
-
return;
|
|
7974
|
-
}
|
|
7027
|
+
const shortcut = DATE_SHORTCUTS.find((item) => item.key === key);
|
|
7028
|
+
if (!shortcut)
|
|
7029
|
+
return;
|
|
7030
|
+
const { start, end } = shortcut.resolve(new Date());
|
|
7975
7031
|
this.dateRange = {
|
|
7976
|
-
startDate: format(start,
|
|
7977
|
-
endDate: format(end,
|
|
7032
|
+
startDate: format(start, OPERAND_DATE_FORMAT),
|
|
7033
|
+
endDate: format(end, OPERAND_DATE_FORMAT)
|
|
7978
7034
|
};
|
|
7979
7035
|
this.onApply(row);
|
|
7980
7036
|
}
|
|
7981
7037
|
onDateChange(row, event) {
|
|
7982
7038
|
this.dateRange = event;
|
|
7983
7039
|
if (event.startDate && event.endDate) {
|
|
7984
|
-
|
|
7985
|
-
|
|
7986
|
-
// close the panel from under it.
|
|
7987
|
-
setTimeout(() => {
|
|
7988
|
-
return this.onApply(row);
|
|
7989
|
-
}, 100);
|
|
7990
|
-
}
|
|
7991
|
-
}
|
|
7992
|
-
/** Cancel inside the calendar goes back to the shortcuts, panel still open. */
|
|
7993
|
-
onBackToShortcuts() {
|
|
7994
|
-
this.calendarOpen.set(null);
|
|
7995
|
-
}
|
|
7996
|
-
// ── Answers ──────────────────────────────────────────────────────────────
|
|
7997
|
-
onStatusChange(value, checked) {
|
|
7998
|
-
if (checked) {
|
|
7999
|
-
if (!this.statusValues.includes(value))
|
|
8000
|
-
this.statusValues = [...this.statusValues, value];
|
|
8001
|
-
return;
|
|
8002
|
-
}
|
|
8003
|
-
this.statusValues = this.statusValues.filter((v) => {
|
|
8004
|
-
return v !== value;
|
|
8005
|
-
});
|
|
8006
|
-
}
|
|
8007
|
-
onToggleStatus(value) {
|
|
8008
|
-
this.onStatusChange(value, !this.statusValues.includes(value));
|
|
8009
|
-
}
|
|
8010
|
-
/**
|
|
8011
|
-
* The one place where an answer is written. Same validation as
|
|
8012
|
-
* monkey-filter-bar: an empty answer is not an answer, and the panel stays
|
|
8013
|
-
* open instead of writing a filter with nothing in it.
|
|
8014
|
-
*/
|
|
8015
|
-
onApply(row) {
|
|
8016
|
-
const k = this.key();
|
|
8017
|
-
const option = this._optionFor(row.key);
|
|
8018
|
-
if (!k || !option)
|
|
8019
|
-
return;
|
|
8020
|
-
let value;
|
|
8021
|
-
switch (option.type) {
|
|
8022
|
-
case 'text':
|
|
8023
|
-
if (!this.textValue.trim())
|
|
8024
|
-
return;
|
|
8025
|
-
value = this.textValue.trim();
|
|
8026
|
-
break;
|
|
8027
|
-
case 'date':
|
|
8028
|
-
if (!this.dateRange.startDate || !this.dateRange.endDate)
|
|
8029
|
-
return;
|
|
8030
|
-
value = { startDate: this.dateRange.startDate, endDate: this.dateRange.endDate };
|
|
8031
|
-
break;
|
|
8032
|
-
case 'currency': {
|
|
8033
|
-
const raw = this.currencyValue;
|
|
8034
|
-
if (raw === null || raw === undefined)
|
|
8035
|
-
return;
|
|
8036
|
-
value = this.currencyMode === 'from' ? { min: raw } : { max: raw };
|
|
8037
|
-
break;
|
|
8038
|
-
}
|
|
8039
|
-
case 'status':
|
|
8040
|
-
if (this.statusValues.length === 0)
|
|
8041
|
-
return;
|
|
8042
|
-
value = [...this.statusValues];
|
|
8043
|
-
break;
|
|
8044
|
-
default:
|
|
8045
|
-
return;
|
|
8046
|
-
}
|
|
8047
|
-
this._withFlip(() => {
|
|
8048
|
-
if (this._service.isFilterActive(k, option.key)) {
|
|
8049
|
-
this._service.updateFilter(k, option.key, option, value);
|
|
8050
|
-
}
|
|
8051
|
-
else {
|
|
8052
|
-
this._service.addFilter(k, option, value);
|
|
8053
|
-
}
|
|
8054
|
-
this.pending.set(null);
|
|
8055
|
-
this.openPanel.set(null);
|
|
8056
|
-
this.calendarOpen.set(null);
|
|
8057
|
-
this._resetDraft();
|
|
8058
|
-
});
|
|
8059
|
-
this._emit();
|
|
8060
|
-
}
|
|
8061
|
-
onRemove(row) {
|
|
8062
|
-
const k = this.key();
|
|
8063
|
-
if (!k)
|
|
8064
|
-
return;
|
|
8065
|
-
// Does not follow the end: the row shrank, and jumping to the end after
|
|
8066
|
-
// deleting something is disorienting — the eye is on the hole that was
|
|
8067
|
-
// left, not on the queue.
|
|
8068
|
-
this._withFlip(() => {
|
|
8069
|
-
if (row.pending) {
|
|
8070
|
-
this.pending.set(null);
|
|
8071
|
-
}
|
|
8072
|
-
else {
|
|
8073
|
-
this._service.removeFilter(k, row.key);
|
|
8074
|
-
}
|
|
8075
|
-
if (this.openPanel()?.key === row.key)
|
|
8076
|
-
this.openPanel.set(null);
|
|
8077
|
-
if (this.calendarOpen() === row.key)
|
|
8078
|
-
this.calendarOpen.set(null);
|
|
8079
|
-
this._resetDraft();
|
|
8080
|
-
}, { leaving: [row.key], follow: false });
|
|
8081
|
-
if (!row.pending)
|
|
8082
|
-
this._emit();
|
|
8083
|
-
}
|
|
8084
|
-
/** Zeroes the whole bar. The trigger goes back to being the call with a label. */
|
|
8085
|
-
onClearAll() {
|
|
8086
|
-
const k = this.key();
|
|
8087
|
-
if (!k)
|
|
8088
|
-
return;
|
|
8089
|
-
const leaving = this.rows().map((row) => {
|
|
8090
|
-
return row.key;
|
|
8091
|
-
});
|
|
8092
|
-
this._withFlip(() => {
|
|
8093
|
-
this._service.clearAllFilters(k);
|
|
8094
|
-
this.pending.set(null);
|
|
8095
|
-
this.openPanel.set(null);
|
|
8096
|
-
this.calendarOpen.set(null);
|
|
8097
|
-
this._resetDraft();
|
|
8098
|
-
}, { leaving, follow: false });
|
|
8099
|
-
this._emit();
|
|
8100
|
-
}
|
|
8101
|
-
onSearchChange(value) {
|
|
8102
|
-
const k = this.key();
|
|
8103
|
-
if (!k)
|
|
8104
|
-
return;
|
|
8105
|
-
this._service.setSearchValue(k, value);
|
|
8106
|
-
this.searchChange.emit(value);
|
|
8107
|
-
this._emit();
|
|
8108
|
-
}
|
|
8109
|
-
// ── Panel bookkeeping ────────────────────────────────────────────────────
|
|
8110
|
-
/**
|
|
8111
|
-
* Opens a chip's answer panel, pre-filled with the answer it already holds —
|
|
8112
|
-
* this is the edit path the active-filter tag used to be.
|
|
8113
|
-
*/
|
|
8114
|
-
_openValuePanel(row) {
|
|
8115
|
-
this._resetDraft();
|
|
8116
|
-
this.calendarOpen.set(null);
|
|
8117
|
-
const k = this.key();
|
|
8118
|
-
const filter = k
|
|
8119
|
-
? this._service.getActiveFilters(k).find((f) => {
|
|
8120
|
-
return f.key === row.key;
|
|
8121
|
-
})
|
|
8122
|
-
: undefined;
|
|
8123
|
-
if (filter) {
|
|
8124
|
-
switch (filter.type) {
|
|
8125
|
-
case 'text':
|
|
8126
|
-
this.textValue = filter.value;
|
|
8127
|
-
break;
|
|
8128
|
-
case 'date': {
|
|
8129
|
-
const range = filter.value;
|
|
8130
|
-
this.dateRange = { startDate: range.startDate ?? '', endDate: range.endDate ?? '' };
|
|
8131
|
-
// Editing a date goes straight to the calendar: the shortcuts are the
|
|
8132
|
-
// way IN, and there is nothing to pick from them once an interval
|
|
8133
|
-
// already exists.
|
|
8134
|
-
this.calendarOpen.set(row.key);
|
|
8135
|
-
break;
|
|
8136
|
-
}
|
|
8137
|
-
case 'currency': {
|
|
8138
|
-
const amount = filter.value;
|
|
8139
|
-
if (amount.min !== undefined) {
|
|
8140
|
-
this.currencyMode = 'from';
|
|
8141
|
-
this.currencyValue = amount.min;
|
|
8142
|
-
}
|
|
8143
|
-
else if (amount.max !== undefined) {
|
|
8144
|
-
this.currencyMode = 'until';
|
|
8145
|
-
this.currencyValue = amount.max;
|
|
8146
|
-
}
|
|
8147
|
-
break;
|
|
8148
|
-
}
|
|
8149
|
-
case 'status':
|
|
8150
|
-
this.statusValues = [...(filter.value ?? [])];
|
|
8151
|
-
break;
|
|
8152
|
-
default:
|
|
8153
|
-
break;
|
|
8154
|
-
}
|
|
8155
|
-
}
|
|
8156
|
-
this.openPanel.set({ key: row.key, part: 'value' });
|
|
8157
|
-
}
|
|
8158
|
-
/**
|
|
8159
|
-
* Closing the value panel of a chip that was never confirmed drops the chip:
|
|
8160
|
-
* monkey-filter-bar adds nothing until Apply, and a chip left on the row
|
|
8161
|
-
* with no answer would be a state it does not have.
|
|
8162
|
-
*
|
|
8163
|
-
* Closing the panel of a CONFIRMED chip changes no width — the segment shows
|
|
8164
|
-
* the same text it did before — so that path needs no FLIP.
|
|
8165
|
-
*/
|
|
8166
|
-
_closePanel(row) {
|
|
8167
|
-
if (!this.isOpen(row.key, 'category') && !this.isOpen(row.key, 'value'))
|
|
8168
|
-
return;
|
|
8169
|
-
if (row.pending) {
|
|
8170
|
-
this._dropPending();
|
|
8171
|
-
return;
|
|
8172
|
-
}
|
|
8173
|
-
this.openPanel.set(null);
|
|
8174
|
-
this.calendarOpen.set(null);
|
|
8175
|
-
this._resetDraft();
|
|
8176
|
-
}
|
|
8177
|
-
/** Takes the draft chip off the row, ghost and all. */
|
|
8178
|
-
_dropPending() {
|
|
8179
|
-
const draft = this.pending();
|
|
8180
|
-
if (!draft)
|
|
8181
|
-
return;
|
|
8182
|
-
this._withFlip(() => {
|
|
8183
|
-
this.pending.set(null);
|
|
8184
|
-
this.openPanel.set(null);
|
|
8185
|
-
this.calendarOpen.set(null);
|
|
8186
|
-
this._resetDraft();
|
|
8187
|
-
}, { leaving: [draft.key], follow: false });
|
|
8188
|
-
}
|
|
8189
|
-
_optionFor(optionKey) {
|
|
8190
|
-
return this.serviceConfig()?.filterOptions.find((o) => {
|
|
8191
|
-
return o.key === optionKey;
|
|
8192
|
-
});
|
|
8193
|
-
}
|
|
8194
|
-
_matchingSearch(options) {
|
|
8195
|
-
const term = this.categorySearch().trim().toLowerCase();
|
|
8196
|
-
if (!term)
|
|
8197
|
-
return [...options];
|
|
8198
|
-
return options.filter((o) => {
|
|
8199
|
-
return o.label.toLowerCase().includes(term);
|
|
8200
|
-
});
|
|
7040
|
+
setTimeout(() => this.onApply(row), 100);
|
|
7041
|
+
}
|
|
8201
7042
|
}
|
|
8202
|
-
|
|
8203
|
-
this.
|
|
8204
|
-
this.currencyValue = null;
|
|
8205
|
-
this.currencyMode = 'from';
|
|
8206
|
-
this.statusValues = [];
|
|
8207
|
-
this.dateRange = { startDate: '', endDate: '' };
|
|
7043
|
+
onBackToShortcuts() {
|
|
7044
|
+
this.calendarOpen.set(null);
|
|
8208
7045
|
}
|
|
8209
|
-
|
|
8210
|
-
|
|
8211
|
-
|
|
8212
|
-
|
|
8213
|
-
const state = this._service.getState(k);
|
|
8214
|
-
this.filtersChange.emit({ search: state.search, filters: state.filters });
|
|
7046
|
+
onToggleStatus(value) {
|
|
7047
|
+
this.statusValues = this.statusValues.includes(value)
|
|
7048
|
+
? this.statusValues.filter((item) => item !== value)
|
|
7049
|
+
: [...this.statusValues, value];
|
|
8215
7050
|
}
|
|
8216
|
-
|
|
8217
|
-
|
|
8218
|
-
|
|
8219
|
-
|
|
8220
|
-
|
|
8221
|
-
|
|
8222
|
-
|
|
8223
|
-
|
|
8224
|
-
|
|
8225
|
-
|
|
8226
|
-
|
|
8227
|
-
* not.
|
|
8228
|
-
*
|
|
8229
|
-
* Released from the flow BEFORE the mutation, the row collapses in the same
|
|
8230
|
-
* pass: the FLIP measures a real before and a real after, and the ghost
|
|
8231
|
-
* fades out on top, in place. Explicit `left`/`top` are mandatory — the
|
|
8232
|
-
* static position of an absolute element inside a flex container is the
|
|
8233
|
-
* container's corner, not where the element was.
|
|
8234
|
-
*/
|
|
8235
|
-
_releaseFromFlow(container, leaving) {
|
|
8236
|
-
leaving.forEach((id) => {
|
|
8237
|
-
const slot = container.querySelector(`[${FLIP_ATTR}="${id}"]`);
|
|
8238
|
-
if (!slot)
|
|
8239
|
-
return;
|
|
8240
|
-
slot.style.left = `${slot.offsetLeft}px`;
|
|
8241
|
-
slot.style.top = `${slot.offsetTop}px`;
|
|
8242
|
-
slot.style.position = 'absolute';
|
|
7051
|
+
onApply(row) {
|
|
7052
|
+
const operands = this.readDraft(row);
|
|
7053
|
+
if (!operands)
|
|
7054
|
+
return;
|
|
7055
|
+
this.withFlip(() => {
|
|
7056
|
+
this.rows.update((rows) => {
|
|
7057
|
+
return rows.map((item) => (item.key === row.key ? { ...item, operands } : item));
|
|
7058
|
+
});
|
|
7059
|
+
this.openPanel.set(null);
|
|
7060
|
+
this.calendarOpen.set(null);
|
|
7061
|
+
this.resetDraft();
|
|
8243
7062
|
});
|
|
7063
|
+
this.commit();
|
|
8244
7064
|
}
|
|
8245
|
-
|
|
8246
|
-
|
|
8247
|
-
|
|
8248
|
-
|
|
8249
|
-
|
|
8250
|
-
|
|
8251
|
-
|
|
8252
|
-
|
|
8253
|
-
|
|
8254
|
-
|
|
8255
|
-
* token, guarantees nothing under reduced motion, and stalls in a throttled
|
|
8256
|
-
* tab.
|
|
8257
|
-
*
|
|
8258
|
-
* The sum comes from the LAST SLOT, never from `scrollWidth`. `scrollWidth`
|
|
8259
|
-
* at this instant is a poisoned measurement: the chip that has just been
|
|
8260
|
-
* born brings its answer panel already open, and the panel has not been
|
|
8261
|
-
* anchored yet — it is at its static position, far ahead, and counts as
|
|
8262
|
-
* overflow. The scroll would go hundreds of pixels chasing a ghost, the FLIP
|
|
8263
|
-
* would animate the whole row that distance, and the browser would clamp the
|
|
8264
|
-
* scroll back when the panel got anchored — a hard jump with no animation,
|
|
8265
|
-
* right in the middle of the chip's entrance.
|
|
8266
|
-
*
|
|
8267
|
-
* The slots do not have that problem: they are flow content, already at
|
|
8268
|
-
* their final position on the first render, and none of them is `fixed`.
|
|
8269
|
-
*/
|
|
8270
|
-
_followEnd(container) {
|
|
8271
|
-
const row = container.querySelector('.mecx-filter-bar-v2-row');
|
|
8272
|
-
if (!row)
|
|
8273
|
-
return;
|
|
8274
|
-
const slots = row.querySelectorAll(`[${FLIP_ATTR}]`);
|
|
8275
|
-
const last = slots[slots.length - 1];
|
|
8276
|
-
if (!last)
|
|
8277
|
-
return;
|
|
8278
|
-
// The breathing room at the end is padding INSIDE the row's box, so the
|
|
8279
|
-
// usable right edge sits before it. Without discounting it, the trigger
|
|
8280
|
-
// comes to rest exactly where the gradient dilutes it.
|
|
8281
|
-
const room = parseFloat(getComputedStyle(row).paddingInlineEnd) || 0;
|
|
8282
|
-
const excess = last.getBoundingClientRect().right + room - row.getBoundingClientRect().right;
|
|
8283
|
-
// Only ever forward. With no overflow this is inert, and going backwards
|
|
8284
|
-
// would drag the eye back at the moment the queue grew.
|
|
8285
|
-
if (excess <= 0)
|
|
8286
|
-
return;
|
|
8287
|
-
row.scrollLeft += excess;
|
|
7065
|
+
onRemove(row) {
|
|
7066
|
+
this.withFlip(() => {
|
|
7067
|
+
this.rows.update((rows) => rows.filter((item) => item.key !== row.key));
|
|
7068
|
+
if (this.openPanel()?.key === row.key)
|
|
7069
|
+
this.openPanel.set(null);
|
|
7070
|
+
if (this.calendarOpen() === row.key)
|
|
7071
|
+
this.calendarOpen.set(null);
|
|
7072
|
+
this.resetDraft();
|
|
7073
|
+
}, { leaving: [row.key], follow: false });
|
|
7074
|
+
this.commit();
|
|
8288
7075
|
}
|
|
8289
|
-
|
|
8290
|
-
|
|
8291
|
-
|
|
8292
|
-
|
|
8293
|
-
|
|
8294
|
-
|
|
8295
|
-
|
|
8296
|
-
|
|
8297
|
-
|
|
8298
|
-
const { leaving = [], follow = true } = options;
|
|
8299
|
-
const container = this._hostEl.nativeElement;
|
|
8300
|
-
const before = measureFlip(container);
|
|
8301
|
-
this._releaseFromFlow(container, leaving);
|
|
8302
|
-
mutate();
|
|
8303
|
-
afterNextRender(() => {
|
|
8304
|
-
if (follow)
|
|
8305
|
-
this._followEnd(container);
|
|
8306
|
-
animateFlip(container, before, FROZEN);
|
|
8307
|
-
// The panel is gone; the next close goes back to a normal fade.
|
|
8308
|
-
this.immediateTriggerExit.set(false);
|
|
8309
|
-
}, { injector: this._injector });
|
|
7076
|
+
onClearAll() {
|
|
7077
|
+
const leaving = this.rows().map((row) => row.key);
|
|
7078
|
+
this.withFlip(() => {
|
|
7079
|
+
this.rows.set([]);
|
|
7080
|
+
this.openPanel.set(null);
|
|
7081
|
+
this.calendarOpen.set(null);
|
|
7082
|
+
this.resetDraft();
|
|
7083
|
+
}, { leaving, follow: false });
|
|
7084
|
+
this.commit();
|
|
8310
7085
|
}
|
|
8311
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type:
|
|
8312
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.4", type: MonkeyFilterBarV2Component, isStandalone: true, selector: "monkey-filter-bar-v2", inputs: { key: { classPropertyName: "key", publicName: "key", isSignal: true, isRequired: true, transformFunction: null }, config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: false, transformFunction: null }, addFilterLabel: { classPropertyName: "addFilterLabel", publicName: "addFilterLabel", isSignal: true, isRequired: false, transformFunction: null }, clearAllLabel: { classPropertyName: "clearAllLabel", publicName: "clearAllLabel", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { filtersChange: "filtersChange", searchChange: "searchChange" }, host: { attributes: { "data-testid": "monkey-filter-bar-v2" }, classAttribute: "mecx-filter-bar-v2" }, ngImport: i0, template: "<!-- Top row: the free-text search and whatever the consumer projects. Kept\n from monkey-filter-bar \u2014 the search is part of this bar's contract\n (`searchChange`), not of the chip row. -->\n<div class=\"mecx-filter-bar-v2-top\">\n <monkey-form-field class=\"mecx-filter-bar-v2-search\" size=\"sm\">\n <input\n type=\"text\"\n monkey-input\n [placeholder]=\"searchPlaceholder()\"\n [ngModel]=\"searchValue()\"\n (ngModelChange)=\"onSearchChange($event)\"\n />\n <monkey-prefix>\n <i class=\"mk-i mk-i-search fs-md\"></i>\n </monkey-prefix>\n </monkey-form-field>\n\n <div class=\"mecx-filter-bar-v2-extra\">\n <ng-content></ng-content>\n </div>\n</div>\n\n<div class=\"mecx-filter-bar-v2-line\">\n <div #rowEl class=\"mecx-filter-bar-v2-row\">\n @for (f of rows(); track f.key) {\n <span\n class=\"mecx-filter-bar-v2-slot\"\n [attr.data-flip-id]=\"f.key\"\n [animate.enter]=\"appPainted() ? 'mecx-filter-bar-v2-slot--entering' : ''\"\n animate.leave=\"mecx-filter-bar-v2-slot--leaving\"\n >\n <monkey-filter-chip (remove)=\"onRemove(f)\">\n <!-- 1 \u00B7 Category \u2014 opens the same list as the trigger, so the user\n can move a filter to another field without deleting it and\n starting over.\n\n The list is repeated here and further down on purpose, and it\n should NOT become a shared <ng-template>: the two differ in what\n they offer (only what can be added, vs. the whole list), in what\n counts as selected, and in what the click does. Sharing the\n markup would mean threading three parameters through a context\n object to save fifteen lines. -->\n <monkey-filter-segment\n [icon]=\"f.icon ?? null\"\n [text]=\"f.label\"\n [open]=\"isOpen(f.key, 'category')\"\n (openChange)=\"onCategoryOpenChange(f, $event)\"\n >\n <!-- Guarded by the same condition the segment uses to show its\n panel. Projected content is created with the view that\n DECLARES it, not with the one that renders it, so without this\n every chip would build both of its panels \u2014 menus, rows,\n fields and all \u2014 and keep them alive while closed. -->\n @if (isOpen(f.key, 'category')) {\n <monkey-filter-menu\n class=\"mecx-filter-bar-v2-menu-categories\"\n [showSearch]=\"true\"\n searchPlaceholder=\"Buscar filtro\"\n (searchChange)=\"categorySearch.set($event)\"\n >\n @for (opt of changeOptions(); track opt.key; let i = $index) {\n @if (needsDivider(changeOptions(), i)) {\n <monkey-divider />\n }\n <monkey-filter-menu-item\n [leadIcon]=\"opt.icon ?? null\"\n [label]=\"opt.label\"\n [selected]=\"opt.key === f.key\"\n [disabled]=\"opt.key !== f.key && isFilterActive(opt.key)\"\n (itemClick)=\"onChangeCategory(f, i)\"\n />\n }\n </monkey-filter-menu>\n }\n </monkey-filter-segment>\n\n <!-- 2 \u00B7 Value \u2014 the panel it opens is decided by the filter type,\n and it is the same panel that the chip's answer came from. That\n is what makes clicking a chip an EDIT instead of a restart. -->\n <monkey-filter-segment\n [placeholder]=\"valuePlaceholder(f)\"\n [text]=\"f.value\"\n [open]=\"isOpen(f.key, 'value')\"\n (openChange)=\"onValueOpenChange(f, $event)\"\n >\n @if (isOpen(f.key, 'value')) {\n @switch (f.type) {\n <!-- status \u2014 a multiple choice, so the answer is only written\n on Confirmar. Ticking a box is not yet a decision. -->\n @case ('status') {\n <monkey-filter-menu class=\"mecx-filter-bar-v2-menu-status\" [showSearch]=\"false\">\n @for (s of statusOptionsOf(f); track s.value) {\n <monkey-filter-menu-item\n property=\"checkbox\"\n [label]=\"s.description\"\n [checked]=\"statusValues.includes(s.value)\"\n (itemClick)=\"onToggleStatus(s.value)\"\n />\n }\n <div class=\"mecx-filter-bar-v2-panel-actions\">\n <monkey-button type=\"secondary\" size=\"sm\" (click)=\"onApply(f)\">\n Confirmar\n </monkey-button>\n </div>\n </monkey-filter-menu>\n }\n\n <!-- date \u2014 the shortcuts are the way in and the calendar is\n the detour. \"Personalizado\" swaps the CONTENT of this\n panel, which stays anchored to the same segment: no modal,\n because the dialog was almost all frame around a calendar\n and the segment already knows how to hang anything. The\n footer here is the date range's own, and Cancelar goes\n back to the shortcuts. -->\n @case ('date') {\n @if (calendarOpen() === f.key) {\n <monkey-date-range\n class=\"mecx-filter-bar-v2-calendar\"\n [startDate]=\"dateRange.startDate\"\n [endDate]=\"dateRange.endDate\"\n [minDate]=\"minDateOf(f)\"\n [maxDate]=\"maxDateOf(f)\"\n (onDate)=\"onDateChange(f, $event)\"\n (onCancel)=\"onBackToShortcuts()\"\n ></monkey-date-range>\n } @else {\n <monkey-filter-menu [showSearch]=\"false\">\n <monkey-filter-menu-item\n label=\"1 semana a partir de hoje\"\n (itemClick)=\"onQuickDate(f, '1-week-after')\"\n />\n <monkey-filter-menu-item\n label=\"1 m\u00EAs a partir de hoje\"\n (itemClick)=\"onQuickDate(f, '1-month-after')\"\n />\n <monkey-filter-menu-item\n label=\"3 meses a partir de hoje\"\n (itemClick)=\"onQuickDate(f, '3-months-after')\"\n />\n <monkey-filter-menu-item\n label=\"1 semana antes de hoje\"\n (itemClick)=\"onQuickDate(f, '1-week-before')\"\n />\n <monkey-filter-menu-item\n label=\"1 m\u00EAs antes de hoje\"\n (itemClick)=\"onQuickDate(f, '1-month-before')\"\n />\n <monkey-filter-menu-item\n label=\"3 meses antes de hoje\"\n (itemClick)=\"onQuickDate(f, '3-months-before')\"\n />\n <monkey-filter-menu-item\n label=\"Personalizado\"\n (itemClick)=\"onQuickDate(f, 'custom')\"\n />\n </monkey-filter-menu>\n }\n }\n\n <!-- currency \u2014 one amount and the side it applies to. The\n label lives inside the field, which is what lets the panel\n close in 238px instead of spending a line on a title. -->\n @case ('currency') {\n <monkey-filter-menu class=\"mecx-filter-bar-v2-menu-field\" [showSearch]=\"false\">\n <div class=\"mecx-filter-bar-v2-field\">\n <monkey-radiobutton [(ngModel)]=\"currencyMode\" position=\"vertical\" size=\"sm\">\n <monkey-option [value]=\"'from'\">De</monkey-option>\n <monkey-option [value]=\"'until'\">At\u00E9</monkey-option>\n </monkey-radiobutton>\n\n <monkey-form-field size=\"sm\">\n <monkey-label>{{ f.label }}</monkey-label>\n <input\n type=\"text\"\n monkey-input-currency\n [placeholder]=\"currencyMode === 'from' ? 'Valor m\u00EDnimo' : 'Valor m\u00E1ximo'\"\n [(ngModel)]=\"currencyValue\"\n (keyup.enter)=\"onApply(f)\"\n />\n </monkey-form-field>\n\n <monkey-button type=\"secondary\" size=\"sm\" (click)=\"onApply(f)\">\n Confirmar\n </monkey-button>\n </div>\n </monkey-filter-menu>\n }\n\n <!-- text \u2014 a single field, so the answer is the text itself. -->\n @default {\n <monkey-filter-menu class=\"mecx-filter-bar-v2-menu-field\" [showSearch]=\"false\">\n <div class=\"mecx-filter-bar-v2-field\">\n <monkey-form-field size=\"sm\">\n <monkey-label>{{ f.label }}</monkey-label>\n <input\n type=\"text\"\n monkey-input\n [placeholder]=\"valuePlaceholder(f)\"\n [(ngModel)]=\"textValue\"\n (keyup.enter)=\"onApply(f)\"\n />\n </monkey-form-field>\n\n <monkey-button type=\"secondary\" size=\"sm\" (click)=\"onApply(f)\">\n Confirmar\n </monkey-button>\n </div>\n </monkey-filter-menu>\n }\n }\n }\n </monkey-filter-segment>\n </monkey-filter-chip>\n </span>\n }\n\n <!-- The trigger is the last slot of the row. Its FLIP identity changes\n along with the variant (see triggerFlipId): with the bar empty it is\n the labelled \"Filtro\" and it goes away with the first filter; the \"+\"\n that takes its place inherits no position, so there is no button\n sliding along and dragging the panel that is closing. -->\n <span class=\"mecx-filter-bar-v2-slot\" [attr.data-flip-id]=\"triggerFlipId()\">\n <monkey-filter-trigger\n [variant]=\"triggerVariant()\"\n [icon]=\"triggerIcon()\"\n [text]=\"addFilterLabel()\"\n [immediateExit]=\"immediateTriggerExit()\"\n [open]=\"triggerOpen()\"\n (openChange)=\"onTriggerOpenChange($event)\"\n >\n @if (triggerOpen()) {\n <monkey-filter-menu\n class=\"mecx-filter-bar-v2-menu-categories\"\n [showSearch]=\"true\"\n searchPlaceholder=\"Buscar filtro\"\n (searchChange)=\"categorySearch.set($event)\"\n >\n @for (opt of addOptions(); track opt.key; let i = $index) {\n @if (needsDivider(addOptions(), i)) {\n <monkey-divider />\n }\n <monkey-filter-menu-item\n [leadIcon]=\"opt.icon ?? null\"\n [label]=\"opt.label\"\n (itemClick)=\"onSelectCategory(i)\"\n />\n }\n </monkey-filter-menu>\n }\n </monkey-filter-trigger>\n </span>\n </div>\n\n <!-- Gradient plus action. The gradient exists so the chips FADE OUT as they\n pass underneath instead of being cut off hard by the edge of what\n scrolls. -->\n @if (rows().length > 0) {\n <div class=\"mecx-filter-bar-v2-actions\">\n <monkey-button type=\"tertiary\" size=\"sm\" (click)=\"onClearAll()\">\n {{ clearAllLabel() }}\n </monkey-button>\n </div>\n }\n</div>\n\n<!-- Drawn bar plus divider. The bar hides itself when there is nothing to\n scroll, so filters existing is enough for it to be mounted. -->\n@if (rows().length > 0) {\n <monkey-scrollbar orientation=\"horizontal\" size=\"small\" [target]=\"rowEl\" />\n <monkey-divider />\n}\n", styles: ["@charset \"UTF-8\";.mecx-filter-bar-v2{--mecx-fbv2-duration-state: .15s;--mecx-fbv2-duration-enter: .2s;--mecx-fbv2-duration-exit: .15s;--mecx-fbv2-ease-state: cubic-bezier(.25, .46, .45, .94);--mecx-fbv2-ease-enter: cubic-bezier(.32, .72, 0, 1);--mecx-fbv2-ease-exit: cubic-bezier(.4, 0, 1, 1);--mecx-fbv2-scale-unfold: .94;--mecx-fbv2-travel-anchored: 4px;--mecx-fbv2-travel-slide: 16px;--mecx-fbv2-stagger: 25ms;--mecx-fbv2-control-height: 28px;--mecx-fbv2-pointer-target: 40px;--mecx-fbv2-radius: 8px;--mecx-fbv2-radius-item: 4px;--mecx-fbv2-fade-width: 48px}@media(prefers-reduced-motion:reduce){.mecx-filter-bar-v2{--mecx-fbv2-duration-state: 1ms;--mecx-fbv2-duration-enter: 1ms;--mecx-fbv2-duration-exit: 1ms;--mecx-fbv2-scale-unfold: 1;--mecx-fbv2-travel-anchored: 0px;--mecx-fbv2-travel-slide: 0px;--mecx-fbv2-stagger: 0ms}}.mecx-filter-bar-v2{display:flex;flex-direction:column;gap:8px;width:100%;background:var(--mecx-color-white)}.mecx-filter-bar-v2-top{display:flex;align-items:center;gap:8px;width:100%}.mecx-filter-bar-v2-search{flex:1;min-width:0;max-width:400px;display:block}.mecx-filter-bar-v2-extra{margin-left:auto;display:flex;align-items:center;gap:8px}.mecx-filter-bar-v2-line{display:flex;align-items:center;width:100%}.mecx-filter-bar-v2-row{display:flex;align-items:center;gap:8px;flex:1 0 0;min-width:0;overflow-x:auto;position:relative;min-height:var(--mecx-fbv2-pointer-target);padding-inline-end:var(--mecx-fbv2-fade-width);scrollbar-width:none;-ms-overflow-style:none}.mecx-filter-bar-v2-row::-webkit-scrollbar{width:0;height:0}.mecx-filter-bar-v2-actions{position:relative;display:flex;align-items:center;justify-content:flex-end;align-self:stretch;flex-shrink:0;padding-left:var(--mecx-fbv2-fade-width);background:var(--mecx-color-white)}.mecx-filter-bar-v2-actions:before{content:\"\";position:absolute;inset-block:0;right:100%;width:var(--mecx-fbv2-fade-width);background:linear-gradient(to right,transparent,var(--mecx-color-white));pointer-events:none}.mecx-filter-bar-v2-slot{display:inline-flex;flex-shrink:0;transition:translate var(--mecx-fbv2-duration-enter) var(--mecx-fbv2-ease-enter)}.mecx-filter-bar-v2-slot--frozen{transition-duration:0s}@keyframes mecx-filter-bar-v2-slot-in{0%{opacity:0;translate:calc(var(--mecx-fbv2-travel-slide) * -1) 0}}@keyframes mecx-filter-bar-v2-slot-out{to{opacity:0;translate:calc(var(--mecx-fbv2-travel-slide) * -1) 0}}.mecx-filter-bar-v2-slot--leaving{position:absolute;pointer-events:none;animation:mecx-filter-bar-v2-slot-out var(--mecx-fbv2-duration-exit) var(--mecx-fbv2-ease-exit) both}.mecx-filter-bar-v2-slot--entering{animation:mecx-filter-bar-v2-slot-in var(--mecx-fbv2-duration-enter) var(--mecx-fbv2-ease-enter);position:relative;z-index:1}.mecx-filter-menu.mecx-filter-bar-v2-menu-categories{width:198px}.mecx-filter-menu.mecx-filter-bar-v2-menu-status{width:225px}.mecx-filter-menu.mecx-filter-bar-v2-menu-field{width:238px}.mecx-filter-bar-v2-field{display:flex;flex-direction:column;gap:8px;width:100%;box-sizing:border-box}.mecx-filter-bar-v2-field monkey-form-field{display:block;width:100%}.mecx-filter-bar-v2-field monkey-button,.mecx-filter-bar-v2-field monkey-button .mecx-button{width:100%}.mecx-filter-bar-v2-panel-actions{display:flex;margin-top:8px;padding-top:8px;border-top:1px solid var(--mecx-color-gray-200)}.mecx-filter-bar-v2-panel-actions monkey-button,.mecx-filter-bar-v2-panel-actions monkey-button .mecx-button{width:100%}.mecx-filter-bar-v2-calendar{display:block;background:var(--mecx-color-white);border-radius:var(--mecx-fbv2-radius);box-shadow:0 8px 12px -4px var(--mecx-color-box-shadow, rgba(47, 50, 55, .08))}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: MonkeyButtonComponent, selector: "monkey-button", inputs: ["disabled", "color", "size", "type", "loading", "id"] }, { kind: "component", type: MonkeyDateRangeComponent, selector: "monkey-date-range", inputs: ["startDate", "endDate", "hideQuickAction", "hideHeader", "hideActions", "hideSecondCalendar", "allowFastActionOnHeader", "minDate", "maxDate", "id"], outputs: ["onCancel", "onDate"] }, { kind: "component", type: MonkeyDividerComponent, selector: "monkey-divider", inputs: ["size", "vertical", "id"] }, { kind: "component", type: MonkeyFilterChipComponent, selector: "monkey-filter-chip", inputs: ["removeIcon", "removeLabel"], outputs: ["remove"] }, { kind: "component", type: MonkeyFilterMenuComponent, selector: "monkey-filter-menu", inputs: ["showSearch", "searchPlaceholder", "showScroll", "maxHeight"], outputs: ["searchChange"] }, { kind: "component", type: MonkeyFilterMenuItemComponent, selector: "monkey-filter-menu-item", inputs: ["property", "leadIcon", "label", "description", "checked", "selected", "disabled"], outputs: ["itemClick"] }, { kind: "component", type: MonkeyFilterSegmentComponent, selector: "monkey-filter-segment", inputs: ["icon", "text", "placeholder", "readonlySegment", "open"], outputs: ["openChange", "segmentClick"] }, { kind: "component", type: MonkeyFilterTriggerComponent, selector: "monkey-filter-trigger", inputs: ["variant", "icon", "text", "ariaLabel", "disabled", "immediateExit", "open"], outputs: ["openChange"] }, { kind: "ngmodule", type: MonkeyFormFieldModule }, { kind: "component", type: MonkeyFormFieldComponent, selector: "monkey-form-field", inputs: ["id", "hideAction", "enableClear", "size", "noFooterSpace", "displayOnly"], outputs: ["onDisplayOnlyChange"], exportAs: ["monkeyFormField"] }, { kind: "ngmodule", type: MonkeyInputModule }, { kind: "directive", type: MonkeyInputDirective, selector: "input[monkey-input],textarea[monkey-input]", inputs: ["name", "disabled", "id", "required", "type", "min", "max", "percent"], exportAs: ["monkeyInput"] }, { kind: "directive", type: MonkeyInputCurrencyDirective, selector: "input[monkey-input-currency]", inputs: ["name", "disabled", "id", "required", "type"], exportAs: ["monkeyInput"] }, { kind: "directive", type: MonkeyLabelDirective, selector: "monkey-label" }, { kind: "component", type: MonkeyOptionComponent, selector: "monkey-option", inputs: ["value", "disabled", "type", "selected"] }, { kind: "directive", type: MonkeyPrefixDirective, selector: "monkey-prefix" }, { kind: "component", type: MonkeyRadioButtonComponent, selector: "monkey-radiobutton", inputs: ["tabIndex", "position", "size", "disabled", "required", "value"], outputs: ["onChange", "onSearch"] }, { kind: "component", type: MonkeyScrollbarComponent, selector: "monkey-scrollbar", inputs: ["orientation", "size", "target"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
|
|
7086
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: MonkeyFilterBarComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
7087
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.4", type: MonkeyFilterBarComponent, isStandalone: true, selector: "monkey-filter-bar", inputs: { config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: false, transformFunction: null }, filters: { classPropertyName: "filters", publicName: "filters", isSignal: true, isRequired: false, transformFunction: null }, dateFormat: { classPropertyName: "dateFormat", publicName: "dateFormat", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, debounce: { classPropertyName: "debounce", publicName: "debounce", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { onFiltersChange: "onFiltersChange" }, host: { attributes: { "data-testid": "monkey-filter-bar" }, properties: { "class.mecx-filter-bar--disabled": "disabled()" }, classAttribute: "mecx-filter-bar" }, ngImport: i0, template: "<div class=\"mecx-filter-bar-line\">\n <div #rowEl class=\"mecx-filter-bar-row\">\n @for (f of rows(); track f.key) {\n <span\n class=\"mecx-filter-bar-slot\"\n [attr.data-flip-id]=\"f.key\"\n [animate.enter]=\"appPainted() ? 'mecx-filter-bar-slot--entering' : ''\"\n animate.leave=\"mecx-filter-bar-slot--leaving\"\n >\n <monkey-filter-chip\n [removeLabel]=\"labels().remove\"\n [disabled]=\"disabled()\"\n (onRemove)=\"onRemove(f)\"\n >\n <monkey-filter-segment\n [icon]=\"f.icon ?? null\"\n [text]=\"f.label\"\n [disabled]=\"disabled()\"\n [open]=\"isOpen(f.key, 'category')\"\n (onOpenChange)=\"onCategoryOpenChange(f, $event)\"\n >\n @if (isOpen(f.key, 'category')) {\n <monkey-filter-menu\n class=\"mecx-filter-bar-menu-categories\"\n [showSearch]=\"true\"\n [searchPlaceholder]=\"labels().search\"\n (onSearchChange)=\"categorySearch.set($event)\"\n >\n @for (opt of changeOptions(); track opt.key; let i = $index) {\n @if (needsDivider(changeOptions(), i)) {\n <monkey-divider />\n }\n <monkey-filter-menu-item\n [leadIcon]=\"opt.icon ?? null\"\n [label]=\"opt.label\"\n [selected]=\"opt.key === f.key\"\n [disabled]=\"opt.key !== f.key && isFilterActive(opt.key)\"\n (onItemClick)=\"onChangeCategory(f, i)\"\n />\n }\n </monkey-filter-menu>\n }\n </monkey-filter-segment>\n <monkey-filter-segment\n [placeholder]=\"labels().selectCondition\"\n [text]=\"operatorLabel(f.condition)\"\n [disabled]=\"disabled()\"\n [open]=\"isOpen(f.key, 'condition')\"\n (onOpenChange)=\"onConditionOpenChange(f, $event)\"\n >\n @if (isOpen(f.key, 'condition')) {\n <monkey-filter-menu class=\"mecx-filter-bar-menu-conditions\" [showSearch]=\"false\">\n @for (c of conditionsFor(f); track c) {\n <monkey-filter-menu-item\n [label]=\"operatorLabel(c)\"\n [selected]=\"c === f.condition\"\n (onItemClick)=\"onSelectCondition(f, c)\"\n />\n }\n </monkey-filter-menu>\n }\n </monkey-filter-segment>\n @if (hasValueSegment(f)) {\n <monkey-filter-segment\n [placeholder]=\"valuePlaceholder(f)\"\n [text]=\"displayOf(f)\"\n [disabled]=\"disabled()\"\n [open]=\"isOpen(f.key, 'value')\"\n (onOpenChange)=\"onValueOpenChange(f, $event)\"\n >\n @if (isOpen(f.key, 'value')) {\n @switch (panelFor(f)) {\n @case ('status') {\n <monkey-filter-menu class=\"mecx-filter-bar-menu-status\" [showSearch]=\"false\">\n @for (s of statusOptionsOf(f); track s.value) {\n <monkey-filter-menu-item\n property=\"checkbox\"\n [label]=\"s.description\"\n [checked]=\"statusValues.includes(s.value)\"\n (onItemClick)=\"onToggleStatus(s.value)\"\n />\n }\n <div class=\"mecx-filter-bar-panel-actions\">\n <monkey-button type=\"secondary\" size=\"sm\" (click)=\"onApply(f)\">\n {{ labels().confirm }}\n </monkey-button>\n </div>\n </monkey-filter-menu>\n }\n\n @case ('date-day') {\n <monkey-filter-menu class=\"mecx-filter-bar-menu-field\" [showSearch]=\"false\">\n <div class=\"mecx-filter-bar-field\">\n <label class=\"mecx-filter-bar-field-row\">\n <span class=\"mecx-filter-bar-field-label\">{{ f.label }}</span>\n <monkey-form-field size=\"sm\" noFooterSpace>\n <input\n type=\"date\"\n monkey-input\n [(ngModel)]=\"dayValue\"\n (keyup.enter)=\"onApply(f)\"\n />\n </monkey-form-field>\n </label>\n <monkey-button type=\"secondary\" size=\"sm\" (click)=\"onApply(f)\">\n {{ labels().confirm }}\n </monkey-button>\n </div>\n </monkey-filter-menu>\n }\n\n @case ('date-range') {\n @if (calendarOpen() === f.key) {\n <monkey-date-range\n class=\"mecx-filter-bar-calendar\"\n [startDate]=\"dateRange.startDate\"\n [endDate]=\"dateRange.endDate\"\n [minDate]=\"minDateOf(f)\"\n [maxDate]=\"maxDateOf(f)\"\n (onDate)=\"onDateChange(f, $event)\"\n (onCancel)=\"onBackToShortcuts()\"\n ></monkey-date-range>\n } @else {\n <monkey-filter-menu [showSearch]=\"false\">\n @for (shortcut of dateShortcuts(); track shortcut.key) {\n <monkey-filter-menu-item\n [label]=\"shortcut.label\"\n (onItemClick)=\"onQuickDate(f, shortcut.key)\"\n />\n }\n </monkey-filter-menu>\n }\n }\n\n @default {\n <monkey-filter-menu class=\"mecx-filter-bar-menu-field\" [showSearch]=\"false\">\n <div class=\"mecx-filter-bar-field\">\n @if (f.type === 'currency') {\n <label class=\"mecx-filter-bar-field-row\">\n <span class=\"mecx-filter-bar-field-label\">\n {{ isRange(f) ? labels().rangeFrom : f.label }}\n </span>\n <monkey-form-field size=\"sm\" noFooterSpace>\n <input\n type=\"text\"\n monkey-input-currency\n [(ngModel)]=\"currencyValue\"\n (keyup.enter)=\"onApply(f)\"\n />\n </monkey-form-field>\n </label>\n @if (isRange(f)) {\n <label class=\"mecx-filter-bar-field-row\">\n <span class=\"mecx-filter-bar-field-label\">{{ labels().rangeTo }}</span>\n <monkey-form-field size=\"sm\" noFooterSpace>\n <input\n type=\"text\"\n monkey-input-currency\n [(ngModel)]=\"currencyValue2\"\n (keyup.enter)=\"onApply(f)\"\n />\n </monkey-form-field>\n </label>\n }\n } @else {\n <label class=\"mecx-filter-bar-field-row\">\n <span class=\"mecx-filter-bar-field-label\">\n {{ isRange(f) ? labels().rangeFrom : f.label }}\n </span>\n <monkey-form-field size=\"sm\" noFooterSpace>\n <input\n type=\"text\"\n monkey-input\n [placeholder]=\"valuePlaceholder(f)\"\n [(ngModel)]=\"textValue\"\n (keyup.enter)=\"onApply(f)\"\n />\n </monkey-form-field>\n </label>\n @if (isRange(f)) {\n <label class=\"mecx-filter-bar-field-row\">\n <span class=\"mecx-filter-bar-field-label\">{{ labels().rangeTo }}</span>\n <monkey-form-field size=\"sm\" noFooterSpace>\n <input\n type=\"text\"\n monkey-input\n [(ngModel)]=\"textValue2\"\n (keyup.enter)=\"onApply(f)\"\n />\n </monkey-form-field>\n </label>\n }\n }\n\n <monkey-button type=\"secondary\" size=\"sm\" (click)=\"onApply(f)\">\n {{ labels().confirm }}\n </monkey-button>\n </div>\n </monkey-filter-menu>\n }\n }\n }\n </monkey-filter-segment>\n }\n </monkey-filter-chip>\n </span>\n }\n\n @if (canAddFilter()) {\n <span\n class=\"mecx-filter-bar-slot mecx-filter-bar-slot--trigger\"\n [attr.data-flip-id]=\"triggerFlipId()\"\n >\n <monkey-filter-trigger\n [variant]=\"triggerVariant()\"\n [icon]=\"triggerIcon()\"\n [text]=\"labels().add\"\n [ariaLabel]=\"labels().addAria\"\n [disabled]=\"disabled()\"\n [immediateExit]=\"immediateTriggerExit()\"\n [open]=\"triggerOpen()\"\n (onOpenChange)=\"onTriggerOpenChange($event)\"\n >\n @if (triggerOpen()) {\n <monkey-filter-menu\n class=\"mecx-filter-bar-menu-categories\"\n [showSearch]=\"true\"\n [searchPlaceholder]=\"labels().search\"\n (onSearchChange)=\"categorySearch.set($event)\"\n >\n @for (opt of addOptions(); track opt.key; let i = $index) {\n @if (needsDivider(addOptions(), i)) {\n <monkey-divider />\n }\n <monkey-filter-menu-item\n [leadIcon]=\"opt.icon ?? null\"\n [label]=\"opt.label\"\n (onItemClick)=\"onSelectCategory(i)\"\n />\n }\n </monkey-filter-menu>\n }\n </monkey-filter-trigger>\n </span>\n }\n </div>\n @if (rows().length > 0) {\n <monkey-scrollbar\n class=\"mecx-filter-bar-bar\"\n orientation=\"horizontal\"\n size=\"small\"\n [target]=\"rowEl\"\n />\n }\n\n <div class=\"mecx-filter-bar-tail\">\n @if (rows().length > 0) {\n <div class=\"mecx-filter-bar-actions\">\n <monkey-button type=\"tertiary\" size=\"sm\" [disabled]=\"disabled()\" (click)=\"onClearAll()\">\n {{ labels().clear }}\n </monkey-button>\n </div>\n }\n\n <div class=\"mecx-filter-bar-extra\">\n <ng-content></ng-content>\n </div>\n </div>\n</div>\n@if (rows().length > 0) {\n <monkey-divider />\n}\n", styles: [".mecx-filter-bar{--mecx-filter-bar-duration-state: .15s;--mecx-filter-bar-duration-enter: .2s;--mecx-filter-bar-duration-exit: .15s;--mecx-filter-bar-ease-state: cubic-bezier(.25, .46, .45, .94);--mecx-filter-bar-ease-enter: cubic-bezier(.32, .72, 0, 1);--mecx-filter-bar-ease-exit: cubic-bezier(.4, 0, 1, 1);--mecx-filter-bar-scale-unfold: .94;--mecx-filter-bar-travel-anchored: 4px;--mecx-filter-bar-travel-slide: 16px;--mecx-filter-bar-stagger: 25ms;--mecx-filter-bar-control-height: 32px;--mecx-filter-bar-pointer-target: 40px;--mecx-filter-bar-reach: calc((var(--mecx-filter-bar-control-height) - var(--mecx-filter-bar-pointer-target)) / 2);--mecx-filter-bar-radius: 8px;--mecx-filter-bar-radius-item: 4px;--mecx-filter-bar-fade-width: 48px}@media(prefers-reduced-motion:reduce){.mecx-filter-bar{--mecx-filter-bar-duration-state: 1ms;--mecx-filter-bar-duration-enter: 1ms;--mecx-filter-bar-duration-exit: 1ms;--mecx-filter-bar-scale-unfold: 1;--mecx-filter-bar-travel-anchored: 0px;--mecx-filter-bar-travel-slide: 0px;--mecx-filter-bar-stagger: 0ms}}.mecx-filter-bar{display:flex;flex-direction:column;gap:8px;width:100%;background:var(--mecx-color-white)}.mecx-filter-bar-top{display:flex;align-items:center;gap:8px;width:100%}.mecx-filter-bar-search{flex:1;min-width:0;max-width:400px;display:block}.mecx-filter-bar-extra{margin-left:auto;display:flex;align-items:center;flex-wrap:wrap;gap:8px}.mecx-filter-bar-extra:empty{display:none}.mecx-filter-bar-line{display:grid;grid-template-columns:minmax(0,1fr) auto;grid-template-areas:\"row tail\" \"bar bar\";align-items:center;row-gap:8px;width:100%}.mecx-filter-bar-bar{grid-area:bar;min-width:0}.mecx-filter-bar-tail{grid-area:tail;display:flex;align-items:center;min-width:0}.mecx-filter-bar-row{grid-area:row;display:flex;align-items:center;gap:8px;min-width:0;overflow-x:auto;position:relative;min-height:var(--mecx-filter-bar-pointer-target);padding-inline-end:var(--mecx-filter-bar-fade-width);scrollbar-width:none;-ms-overflow-style:none}.mecx-filter-bar-row::-webkit-scrollbar{width:0;height:0}.mecx-filter-bar--disabled .mecx-filter-bar-row{cursor:default}.mecx-filter-bar-actions{position:relative;display:flex;align-items:center;justify-content:flex-end;align-self:stretch;flex-shrink:0;padding-left:var(--mecx-filter-bar-fade-width);background:var(--mecx-color-white)}.mecx-filter-bar-actions:before{content:\"\";position:absolute;inset-block:0;right:100%;width:var(--mecx-filter-bar-fade-width);background:linear-gradient(to right,transparent,var(--mecx-color-white));pointer-events:none}.mecx-filter-bar-slot{display:inline-flex;flex-shrink:0;transition:translate var(--mecx-filter-bar-duration-enter) var(--mecx-filter-bar-ease-enter)}.mecx-filter-bar-slot--frozen{transition-duration:0s}@keyframes mecx-filter-bar-slot-in{0%{opacity:0;translate:calc(var(--mecx-filter-bar-travel-slide) * -1) 0}}@keyframes mecx-filter-bar-slot-out{to{opacity:0;translate:calc(var(--mecx-filter-bar-travel-slide) * -1) 0}}.mecx-filter-bar-slot--leaving{position:absolute;pointer-events:none;animation:mecx-filter-bar-slot-out var(--mecx-filter-bar-duration-exit) var(--mecx-filter-bar-ease-exit) both}.mecx-filter-bar-slot--entering{animation:mecx-filter-bar-slot-in var(--mecx-filter-bar-duration-enter) var(--mecx-filter-bar-ease-enter);position:relative;z-index:1}.mecx-filter-menu.mecx-filter-bar-menu-categories{width:220px}.mecx-filter-menu.mecx-filter-bar-menu-status{width:225px}.mecx-filter-menu.mecx-filter-bar-menu-field{width:238px}.mecx-filter-bar-field{display:flex;flex-direction:column;gap:8px;width:100%;box-sizing:border-box}.mecx-filter-bar-field monkey-form-field{display:block;width:100%}.mecx-filter-bar-field monkey-button,.mecx-filter-bar-field monkey-button .mecx-button{width:100%}.mecx-filter-bar-field-row{display:flex;flex-direction:column;gap:4px;width:100%;cursor:pointer}.mecx-filter-bar-field-label{color:var(--mecx-color-gray-900);font-size:14px;font-weight:400;line-height:24px;letter-spacing:.14px}.mecx-filter-bar-panel-actions{display:flex;margin-top:8px;padding-top:8px;border-top:1px solid var(--mecx-color-gray-200)}.mecx-filter-bar-panel-actions monkey-button,.mecx-filter-bar-panel-actions monkey-button .mecx-button{width:100%}.mecx-filter-bar-calendar{display:block;background:var(--mecx-color-white);border-radius:var(--mecx-filter-bar-radius);box-shadow:0 8px 12px -4px var(--mecx-color-box-shadow, rgba(47, 50, 55, .08))}@media(max-width:767.98px){.mecx-filter-bar-line{grid-template-columns:minmax(0,1fr);grid-template-areas:\"row\" \"bar\" \"tail\";position:relative}.mecx-filter-bar-slot--trigger{position:sticky;right:0;z-index:2}.mecx-filter-bar-row{padding-inline-end:0}.mecx-filter-bar-actions{padding-left:0;align-self:auto;background:none;position:static}.mecx-filter-bar-actions:before{right:var(--mecx-filter-bar-control-height);bottom:auto;height:var(--mecx-filter-bar-pointer-target)}}\n/*!\n* Bootstrap Grid v5.3.7 (https://getbootstrap.com/)\n* Copyright 2011-2025 The Bootstrap Authors\n* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n*/\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: MonkeyButtonComponent, selector: "monkey-button", inputs: ["disabled", "color", "size", "type", "loading", "id"] }, { kind: "component", type: MonkeyDateRangeComponent, selector: "monkey-date-range", inputs: ["startDate", "endDate", "hideQuickAction", "hideHeader", "hideActions", "hideSecondCalendar", "allowFastActionOnHeader", "minDate", "maxDate", "id"], outputs: ["onCancel", "onDate"] }, { kind: "component", type: MonkeyDividerComponent, selector: "monkey-divider", inputs: ["size", "vertical", "id"] }, { kind: "component", type: MonkeyFilterChipComponent, selector: "monkey-filter-chip", inputs: ["removeIcon", "removeLabel", "disabled"], outputs: ["onRemove"] }, { kind: "component", type: MonkeyFilterMenuComponent, selector: "monkey-filter-menu", inputs: ["showSearch", "searchPlaceholder", "showScroll", "maxHeight"], outputs: ["onSearchChange"] }, { kind: "component", type: MonkeyFilterMenuItemComponent, selector: "monkey-filter-menu-item", inputs: ["property", "leadIcon", "label", "description", "checked", "selected", "disabled"], outputs: ["onItemClick"] }, { kind: "component", type: MonkeyFilterSegmentComponent, selector: "monkey-filter-segment", inputs: ["icon", "text", "placeholder", "readonlySegment", "disabled", "open"], outputs: ["onOpenChange", "onSegmentClick"] }, { kind: "component", type: MonkeyFilterTriggerComponent, selector: "monkey-filter-trigger", inputs: ["variant", "icon", "text", "ariaLabel", "disabled", "immediateExit", "open"], outputs: ["onOpenChange"] }, { kind: "ngmodule", type: MonkeyFormFieldModule }, { kind: "component", type: MonkeyFormFieldComponent, selector: "monkey-form-field", inputs: ["id", "hideAction", "enableClear", "size", "noFooterSpace", "displayOnly"], outputs: ["onDisplayOnlyChange"], exportAs: ["monkeyFormField"] }, { kind: "ngmodule", type: MonkeyInputModule }, { kind: "directive", type: MonkeyInputDirective, selector: "input[monkey-input],textarea[monkey-input]", inputs: ["name", "disabled", "id", "required", "type", "min", "max", "percent"], exportAs: ["monkeyInput"] }, { kind: "directive", type: MonkeyInputCurrencyDirective, selector: "input[monkey-input-currency]", inputs: ["name", "disabled", "id", "required", "type"], exportAs: ["monkeyInput"] }, { kind: "component", type: MonkeyScrollbarComponent, selector: "monkey-scrollbar", inputs: ["orientation", "size", "target"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
|
|
8313
7088
|
}
|
|
8314
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type:
|
|
7089
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: MonkeyFilterBarComponent, decorators: [{
|
|
8315
7090
|
type: Component,
|
|
8316
|
-
args: [{ selector: 'monkey-filter-bar
|
|
7091
|
+
args: [{ selector: 'monkey-filter-bar', imports: [
|
|
8317
7092
|
FormsModule,
|
|
8318
7093
|
MonkeyButtonComponent,
|
|
8319
|
-
MonkeyCheckboxComponent,
|
|
8320
7094
|
MonkeyDateRangeComponent,
|
|
8321
7095
|
MonkeyDividerComponent,
|
|
8322
7096
|
MonkeyFilterChipComponent,
|
|
@@ -8326,16 +7100,13 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImpor
|
|
|
8326
7100
|
MonkeyFilterTriggerComponent,
|
|
8327
7101
|
MonkeyFormFieldModule,
|
|
8328
7102
|
MonkeyInputModule,
|
|
8329
|
-
MonkeyLabelDirective,
|
|
8330
|
-
MonkeyOptionComponent,
|
|
8331
|
-
MonkeyPrefixDirective,
|
|
8332
|
-
MonkeyRadioButtonComponent,
|
|
8333
7103
|
MonkeyScrollbarComponent
|
|
8334
7104
|
], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, host: {
|
|
8335
|
-
'data-testid': 'monkey-filter-bar
|
|
8336
|
-
class: 'mecx-filter-bar
|
|
8337
|
-
}, template: "<!-- Top row: the free-text search and whatever the consumer projects. Kept\n from monkey-filter-bar \u2014 the search is part of this bar's contract\n (`searchChange`), not of the chip row. -->\n<div class=\"mecx-filter-bar-v2-top\">\n <monkey-form-field class=\"mecx-filter-bar-v2-search\" size=\"sm\">\n <input\n type=\"text\"\n monkey-input\n [placeholder]=\"searchPlaceholder()\"\n [ngModel]=\"searchValue()\"\n (ngModelChange)=\"onSearchChange($event)\"\n />\n <monkey-prefix>\n <i class=\"mk-i mk-i-search fs-md\"></i>\n </monkey-prefix>\n </monkey-form-field>\n\n <div class=\"mecx-filter-bar-v2-extra\">\n <ng-content></ng-content>\n </div>\n</div>\n\n<div class=\"mecx-filter-bar-v2-line\">\n <div #rowEl class=\"mecx-filter-bar-v2-row\">\n @for (f of rows(); track f.key) {\n <span\n class=\"mecx-filter-bar-v2-slot\"\n [attr.data-flip-id]=\"f.key\"\n [animate.enter]=\"appPainted() ? 'mecx-filter-bar-v2-slot--entering' : ''\"\n animate.leave=\"mecx-filter-bar-v2-slot--leaving\"\n >\n <monkey-filter-chip (remove)=\"onRemove(f)\">\n <!-- 1 \u00B7 Category \u2014 opens the same list as the trigger, so the user\n can move a filter to another field without deleting it and\n starting over.\n\n The list is repeated here and further down on purpose, and it\n should NOT become a shared <ng-template>: the two differ in what\n they offer (only what can be added, vs. the whole list), in what\n counts as selected, and in what the click does. Sharing the\n markup would mean threading three parameters through a context\n object to save fifteen lines. -->\n <monkey-filter-segment\n [icon]=\"f.icon ?? null\"\n [text]=\"f.label\"\n [open]=\"isOpen(f.key, 'category')\"\n (openChange)=\"onCategoryOpenChange(f, $event)\"\n >\n <!-- Guarded by the same condition the segment uses to show its\n panel. Projected content is created with the view that\n DECLARES it, not with the one that renders it, so without this\n every chip would build both of its panels \u2014 menus, rows,\n fields and all \u2014 and keep them alive while closed. -->\n @if (isOpen(f.key, 'category')) {\n <monkey-filter-menu\n class=\"mecx-filter-bar-v2-menu-categories\"\n [showSearch]=\"true\"\n searchPlaceholder=\"Buscar filtro\"\n (searchChange)=\"categorySearch.set($event)\"\n >\n @for (opt of changeOptions(); track opt.key; let i = $index) {\n @if (needsDivider(changeOptions(), i)) {\n <monkey-divider />\n }\n <monkey-filter-menu-item\n [leadIcon]=\"opt.icon ?? null\"\n [label]=\"opt.label\"\n [selected]=\"opt.key === f.key\"\n [disabled]=\"opt.key !== f.key && isFilterActive(opt.key)\"\n (itemClick)=\"onChangeCategory(f, i)\"\n />\n }\n </monkey-filter-menu>\n }\n </monkey-filter-segment>\n\n <!-- 2 \u00B7 Value \u2014 the panel it opens is decided by the filter type,\n and it is the same panel that the chip's answer came from. That\n is what makes clicking a chip an EDIT instead of a restart. -->\n <monkey-filter-segment\n [placeholder]=\"valuePlaceholder(f)\"\n [text]=\"f.value\"\n [open]=\"isOpen(f.key, 'value')\"\n (openChange)=\"onValueOpenChange(f, $event)\"\n >\n @if (isOpen(f.key, 'value')) {\n @switch (f.type) {\n <!-- status \u2014 a multiple choice, so the answer is only written\n on Confirmar. Ticking a box is not yet a decision. -->\n @case ('status') {\n <monkey-filter-menu class=\"mecx-filter-bar-v2-menu-status\" [showSearch]=\"false\">\n @for (s of statusOptionsOf(f); track s.value) {\n <monkey-filter-menu-item\n property=\"checkbox\"\n [label]=\"s.description\"\n [checked]=\"statusValues.includes(s.value)\"\n (itemClick)=\"onToggleStatus(s.value)\"\n />\n }\n <div class=\"mecx-filter-bar-v2-panel-actions\">\n <monkey-button type=\"secondary\" size=\"sm\" (click)=\"onApply(f)\">\n Confirmar\n </monkey-button>\n </div>\n </monkey-filter-menu>\n }\n\n <!-- date \u2014 the shortcuts are the way in and the calendar is\n the detour. \"Personalizado\" swaps the CONTENT of this\n panel, which stays anchored to the same segment: no modal,\n because the dialog was almost all frame around a calendar\n and the segment already knows how to hang anything. The\n footer here is the date range's own, and Cancelar goes\n back to the shortcuts. -->\n @case ('date') {\n @if (calendarOpen() === f.key) {\n <monkey-date-range\n class=\"mecx-filter-bar-v2-calendar\"\n [startDate]=\"dateRange.startDate\"\n [endDate]=\"dateRange.endDate\"\n [minDate]=\"minDateOf(f)\"\n [maxDate]=\"maxDateOf(f)\"\n (onDate)=\"onDateChange(f, $event)\"\n (onCancel)=\"onBackToShortcuts()\"\n ></monkey-date-range>\n } @else {\n <monkey-filter-menu [showSearch]=\"false\">\n <monkey-filter-menu-item\n label=\"1 semana a partir de hoje\"\n (itemClick)=\"onQuickDate(f, '1-week-after')\"\n />\n <monkey-filter-menu-item\n label=\"1 m\u00EAs a partir de hoje\"\n (itemClick)=\"onQuickDate(f, '1-month-after')\"\n />\n <monkey-filter-menu-item\n label=\"3 meses a partir de hoje\"\n (itemClick)=\"onQuickDate(f, '3-months-after')\"\n />\n <monkey-filter-menu-item\n label=\"1 semana antes de hoje\"\n (itemClick)=\"onQuickDate(f, '1-week-before')\"\n />\n <monkey-filter-menu-item\n label=\"1 m\u00EAs antes de hoje\"\n (itemClick)=\"onQuickDate(f, '1-month-before')\"\n />\n <monkey-filter-menu-item\n label=\"3 meses antes de hoje\"\n (itemClick)=\"onQuickDate(f, '3-months-before')\"\n />\n <monkey-filter-menu-item\n label=\"Personalizado\"\n (itemClick)=\"onQuickDate(f, 'custom')\"\n />\n </monkey-filter-menu>\n }\n }\n\n <!-- currency \u2014 one amount and the side it applies to. The\n label lives inside the field, which is what lets the panel\n close in 238px instead of spending a line on a title. -->\n @case ('currency') {\n <monkey-filter-menu class=\"mecx-filter-bar-v2-menu-field\" [showSearch]=\"false\">\n <div class=\"mecx-filter-bar-v2-field\">\n <monkey-radiobutton [(ngModel)]=\"currencyMode\" position=\"vertical\" size=\"sm\">\n <monkey-option [value]=\"'from'\">De</monkey-option>\n <monkey-option [value]=\"'until'\">At\u00E9</monkey-option>\n </monkey-radiobutton>\n\n <monkey-form-field size=\"sm\">\n <monkey-label>{{ f.label }}</monkey-label>\n <input\n type=\"text\"\n monkey-input-currency\n [placeholder]=\"currencyMode === 'from' ? 'Valor m\u00EDnimo' : 'Valor m\u00E1ximo'\"\n [(ngModel)]=\"currencyValue\"\n (keyup.enter)=\"onApply(f)\"\n />\n </monkey-form-field>\n\n <monkey-button type=\"secondary\" size=\"sm\" (click)=\"onApply(f)\">\n Confirmar\n </monkey-button>\n </div>\n </monkey-filter-menu>\n }\n\n <!-- text \u2014 a single field, so the answer is the text itself. -->\n @default {\n <monkey-filter-menu class=\"mecx-filter-bar-v2-menu-field\" [showSearch]=\"false\">\n <div class=\"mecx-filter-bar-v2-field\">\n <monkey-form-field size=\"sm\">\n <monkey-label>{{ f.label }}</monkey-label>\n <input\n type=\"text\"\n monkey-input\n [placeholder]=\"valuePlaceholder(f)\"\n [(ngModel)]=\"textValue\"\n (keyup.enter)=\"onApply(f)\"\n />\n </monkey-form-field>\n\n <monkey-button type=\"secondary\" size=\"sm\" (click)=\"onApply(f)\">\n Confirmar\n </monkey-button>\n </div>\n </monkey-filter-menu>\n }\n }\n }\n </monkey-filter-segment>\n </monkey-filter-chip>\n </span>\n }\n\n <!-- The trigger is the last slot of the row. Its FLIP identity changes\n along with the variant (see triggerFlipId): with the bar empty it is\n the labelled \"Filtro\" and it goes away with the first filter; the \"+\"\n that takes its place inherits no position, so there is no button\n sliding along and dragging the panel that is closing. -->\n <span class=\"mecx-filter-bar-v2-slot\" [attr.data-flip-id]=\"triggerFlipId()\">\n <monkey-filter-trigger\n [variant]=\"triggerVariant()\"\n [icon]=\"triggerIcon()\"\n [text]=\"addFilterLabel()\"\n [immediateExit]=\"immediateTriggerExit()\"\n [open]=\"triggerOpen()\"\n (openChange)=\"onTriggerOpenChange($event)\"\n >\n @if (triggerOpen()) {\n <monkey-filter-menu\n class=\"mecx-filter-bar-v2-menu-categories\"\n [showSearch]=\"true\"\n searchPlaceholder=\"Buscar filtro\"\n (searchChange)=\"categorySearch.set($event)\"\n >\n @for (opt of addOptions(); track opt.key; let i = $index) {\n @if (needsDivider(addOptions(), i)) {\n <monkey-divider />\n }\n <monkey-filter-menu-item\n [leadIcon]=\"opt.icon ?? null\"\n [label]=\"opt.label\"\n (itemClick)=\"onSelectCategory(i)\"\n />\n }\n </monkey-filter-menu>\n }\n </monkey-filter-trigger>\n </span>\n </div>\n\n <!-- Gradient plus action. The gradient exists so the chips FADE OUT as they\n pass underneath instead of being cut off hard by the edge of what\n scrolls. -->\n @if (rows().length > 0) {\n <div class=\"mecx-filter-bar-v2-actions\">\n <monkey-button type=\"tertiary\" size=\"sm\" (click)=\"onClearAll()\">\n {{ clearAllLabel() }}\n </monkey-button>\n </div>\n }\n</div>\n\n<!-- Drawn bar plus divider. The bar hides itself when there is nothing to\n scroll, so filters existing is enough for it to be mounted. -->\n@if (rows().length > 0) {\n <monkey-scrollbar orientation=\"horizontal\" size=\"small\" [target]=\"rowEl\" />\n <monkey-divider />\n}\n", styles: ["@charset \"UTF-8\";.mecx-filter-bar-v2{--mecx-fbv2-duration-state: .15s;--mecx-fbv2-duration-enter: .2s;--mecx-fbv2-duration-exit: .15s;--mecx-fbv2-ease-state: cubic-bezier(.25, .46, .45, .94);--mecx-fbv2-ease-enter: cubic-bezier(.32, .72, 0, 1);--mecx-fbv2-ease-exit: cubic-bezier(.4, 0, 1, 1);--mecx-fbv2-scale-unfold: .94;--mecx-fbv2-travel-anchored: 4px;--mecx-fbv2-travel-slide: 16px;--mecx-fbv2-stagger: 25ms;--mecx-fbv2-control-height: 28px;--mecx-fbv2-pointer-target: 40px;--mecx-fbv2-radius: 8px;--mecx-fbv2-radius-item: 4px;--mecx-fbv2-fade-width: 48px}@media(prefers-reduced-motion:reduce){.mecx-filter-bar-v2{--mecx-fbv2-duration-state: 1ms;--mecx-fbv2-duration-enter: 1ms;--mecx-fbv2-duration-exit: 1ms;--mecx-fbv2-scale-unfold: 1;--mecx-fbv2-travel-anchored: 0px;--mecx-fbv2-travel-slide: 0px;--mecx-fbv2-stagger: 0ms}}.mecx-filter-bar-v2{display:flex;flex-direction:column;gap:8px;width:100%;background:var(--mecx-color-white)}.mecx-filter-bar-v2-top{display:flex;align-items:center;gap:8px;width:100%}.mecx-filter-bar-v2-search{flex:1;min-width:0;max-width:400px;display:block}.mecx-filter-bar-v2-extra{margin-left:auto;display:flex;align-items:center;gap:8px}.mecx-filter-bar-v2-line{display:flex;align-items:center;width:100%}.mecx-filter-bar-v2-row{display:flex;align-items:center;gap:8px;flex:1 0 0;min-width:0;overflow-x:auto;position:relative;min-height:var(--mecx-fbv2-pointer-target);padding-inline-end:var(--mecx-fbv2-fade-width);scrollbar-width:none;-ms-overflow-style:none}.mecx-filter-bar-v2-row::-webkit-scrollbar{width:0;height:0}.mecx-filter-bar-v2-actions{position:relative;display:flex;align-items:center;justify-content:flex-end;align-self:stretch;flex-shrink:0;padding-left:var(--mecx-fbv2-fade-width);background:var(--mecx-color-white)}.mecx-filter-bar-v2-actions:before{content:\"\";position:absolute;inset-block:0;right:100%;width:var(--mecx-fbv2-fade-width);background:linear-gradient(to right,transparent,var(--mecx-color-white));pointer-events:none}.mecx-filter-bar-v2-slot{display:inline-flex;flex-shrink:0;transition:translate var(--mecx-fbv2-duration-enter) var(--mecx-fbv2-ease-enter)}.mecx-filter-bar-v2-slot--frozen{transition-duration:0s}@keyframes mecx-filter-bar-v2-slot-in{0%{opacity:0;translate:calc(var(--mecx-fbv2-travel-slide) * -1) 0}}@keyframes mecx-filter-bar-v2-slot-out{to{opacity:0;translate:calc(var(--mecx-fbv2-travel-slide) * -1) 0}}.mecx-filter-bar-v2-slot--leaving{position:absolute;pointer-events:none;animation:mecx-filter-bar-v2-slot-out var(--mecx-fbv2-duration-exit) var(--mecx-fbv2-ease-exit) both}.mecx-filter-bar-v2-slot--entering{animation:mecx-filter-bar-v2-slot-in var(--mecx-fbv2-duration-enter) var(--mecx-fbv2-ease-enter);position:relative;z-index:1}.mecx-filter-menu.mecx-filter-bar-v2-menu-categories{width:198px}.mecx-filter-menu.mecx-filter-bar-v2-menu-status{width:225px}.mecx-filter-menu.mecx-filter-bar-v2-menu-field{width:238px}.mecx-filter-bar-v2-field{display:flex;flex-direction:column;gap:8px;width:100%;box-sizing:border-box}.mecx-filter-bar-v2-field monkey-form-field{display:block;width:100%}.mecx-filter-bar-v2-field monkey-button,.mecx-filter-bar-v2-field monkey-button .mecx-button{width:100%}.mecx-filter-bar-v2-panel-actions{display:flex;margin-top:8px;padding-top:8px;border-top:1px solid var(--mecx-color-gray-200)}.mecx-filter-bar-v2-panel-actions monkey-button,.mecx-filter-bar-v2-panel-actions monkey-button .mecx-button{width:100%}.mecx-filter-bar-v2-calendar{display:block;background:var(--mecx-color-white);border-radius:var(--mecx-fbv2-radius);box-shadow:0 8px 12px -4px var(--mecx-color-box-shadow, rgba(47, 50, 55, .08))}\n"] }]
|
|
8338
|
-
}], ctorParameters: () => [], propDecorators: { key: [{ type: i0.Input, args: [{ isSignal: true, alias: "key", required: true }] }], config: [{ type: i0.Input, args: [{ isSignal: true, alias: "config", required: false }] }], addFilterLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "addFilterLabel", required: false }] }], clearAllLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "clearAllLabel", required: false }] }], filtersChange: [{ type: i0.Output, args: ["filtersChange"] }], searchChange: [{ type: i0.Output, args: ["searchChange"] }] } });
|
|
7105
|
+
'data-testid': 'monkey-filter-bar',
|
|
7106
|
+
class: 'mecx-filter-bar',
|
|
7107
|
+
'[class.mecx-filter-bar--disabled]': 'disabled()'
|
|
7108
|
+
}, template: "<div class=\"mecx-filter-bar-line\">\n <div #rowEl class=\"mecx-filter-bar-row\">\n @for (f of rows(); track f.key) {\n <span\n class=\"mecx-filter-bar-slot\"\n [attr.data-flip-id]=\"f.key\"\n [animate.enter]=\"appPainted() ? 'mecx-filter-bar-slot--entering' : ''\"\n animate.leave=\"mecx-filter-bar-slot--leaving\"\n >\n <monkey-filter-chip\n [removeLabel]=\"labels().remove\"\n [disabled]=\"disabled()\"\n (onRemove)=\"onRemove(f)\"\n >\n <monkey-filter-segment\n [icon]=\"f.icon ?? null\"\n [text]=\"f.label\"\n [disabled]=\"disabled()\"\n [open]=\"isOpen(f.key, 'category')\"\n (onOpenChange)=\"onCategoryOpenChange(f, $event)\"\n >\n @if (isOpen(f.key, 'category')) {\n <monkey-filter-menu\n class=\"mecx-filter-bar-menu-categories\"\n [showSearch]=\"true\"\n [searchPlaceholder]=\"labels().search\"\n (onSearchChange)=\"categorySearch.set($event)\"\n >\n @for (opt of changeOptions(); track opt.key; let i = $index) {\n @if (needsDivider(changeOptions(), i)) {\n <monkey-divider />\n }\n <monkey-filter-menu-item\n [leadIcon]=\"opt.icon ?? null\"\n [label]=\"opt.label\"\n [selected]=\"opt.key === f.key\"\n [disabled]=\"opt.key !== f.key && isFilterActive(opt.key)\"\n (onItemClick)=\"onChangeCategory(f, i)\"\n />\n }\n </monkey-filter-menu>\n }\n </monkey-filter-segment>\n <monkey-filter-segment\n [placeholder]=\"labels().selectCondition\"\n [text]=\"operatorLabel(f.condition)\"\n [disabled]=\"disabled()\"\n [open]=\"isOpen(f.key, 'condition')\"\n (onOpenChange)=\"onConditionOpenChange(f, $event)\"\n >\n @if (isOpen(f.key, 'condition')) {\n <monkey-filter-menu class=\"mecx-filter-bar-menu-conditions\" [showSearch]=\"false\">\n @for (c of conditionsFor(f); track c) {\n <monkey-filter-menu-item\n [label]=\"operatorLabel(c)\"\n [selected]=\"c === f.condition\"\n (onItemClick)=\"onSelectCondition(f, c)\"\n />\n }\n </monkey-filter-menu>\n }\n </monkey-filter-segment>\n @if (hasValueSegment(f)) {\n <monkey-filter-segment\n [placeholder]=\"valuePlaceholder(f)\"\n [text]=\"displayOf(f)\"\n [disabled]=\"disabled()\"\n [open]=\"isOpen(f.key, 'value')\"\n (onOpenChange)=\"onValueOpenChange(f, $event)\"\n >\n @if (isOpen(f.key, 'value')) {\n @switch (panelFor(f)) {\n @case ('status') {\n <monkey-filter-menu class=\"mecx-filter-bar-menu-status\" [showSearch]=\"false\">\n @for (s of statusOptionsOf(f); track s.value) {\n <monkey-filter-menu-item\n property=\"checkbox\"\n [label]=\"s.description\"\n [checked]=\"statusValues.includes(s.value)\"\n (onItemClick)=\"onToggleStatus(s.value)\"\n />\n }\n <div class=\"mecx-filter-bar-panel-actions\">\n <monkey-button type=\"secondary\" size=\"sm\" (click)=\"onApply(f)\">\n {{ labels().confirm }}\n </monkey-button>\n </div>\n </monkey-filter-menu>\n }\n\n @case ('date-day') {\n <monkey-filter-menu class=\"mecx-filter-bar-menu-field\" [showSearch]=\"false\">\n <div class=\"mecx-filter-bar-field\">\n <label class=\"mecx-filter-bar-field-row\">\n <span class=\"mecx-filter-bar-field-label\">{{ f.label }}</span>\n <monkey-form-field size=\"sm\" noFooterSpace>\n <input\n type=\"date\"\n monkey-input\n [(ngModel)]=\"dayValue\"\n (keyup.enter)=\"onApply(f)\"\n />\n </monkey-form-field>\n </label>\n <monkey-button type=\"secondary\" size=\"sm\" (click)=\"onApply(f)\">\n {{ labels().confirm }}\n </monkey-button>\n </div>\n </monkey-filter-menu>\n }\n\n @case ('date-range') {\n @if (calendarOpen() === f.key) {\n <monkey-date-range\n class=\"mecx-filter-bar-calendar\"\n [startDate]=\"dateRange.startDate\"\n [endDate]=\"dateRange.endDate\"\n [minDate]=\"minDateOf(f)\"\n [maxDate]=\"maxDateOf(f)\"\n (onDate)=\"onDateChange(f, $event)\"\n (onCancel)=\"onBackToShortcuts()\"\n ></monkey-date-range>\n } @else {\n <monkey-filter-menu [showSearch]=\"false\">\n @for (shortcut of dateShortcuts(); track shortcut.key) {\n <monkey-filter-menu-item\n [label]=\"shortcut.label\"\n (onItemClick)=\"onQuickDate(f, shortcut.key)\"\n />\n }\n </monkey-filter-menu>\n }\n }\n\n @default {\n <monkey-filter-menu class=\"mecx-filter-bar-menu-field\" [showSearch]=\"false\">\n <div class=\"mecx-filter-bar-field\">\n @if (f.type === 'currency') {\n <label class=\"mecx-filter-bar-field-row\">\n <span class=\"mecx-filter-bar-field-label\">\n {{ isRange(f) ? labels().rangeFrom : f.label }}\n </span>\n <monkey-form-field size=\"sm\" noFooterSpace>\n <input\n type=\"text\"\n monkey-input-currency\n [(ngModel)]=\"currencyValue\"\n (keyup.enter)=\"onApply(f)\"\n />\n </monkey-form-field>\n </label>\n @if (isRange(f)) {\n <label class=\"mecx-filter-bar-field-row\">\n <span class=\"mecx-filter-bar-field-label\">{{ labels().rangeTo }}</span>\n <monkey-form-field size=\"sm\" noFooterSpace>\n <input\n type=\"text\"\n monkey-input-currency\n [(ngModel)]=\"currencyValue2\"\n (keyup.enter)=\"onApply(f)\"\n />\n </monkey-form-field>\n </label>\n }\n } @else {\n <label class=\"mecx-filter-bar-field-row\">\n <span class=\"mecx-filter-bar-field-label\">\n {{ isRange(f) ? labels().rangeFrom : f.label }}\n </span>\n <monkey-form-field size=\"sm\" noFooterSpace>\n <input\n type=\"text\"\n monkey-input\n [placeholder]=\"valuePlaceholder(f)\"\n [(ngModel)]=\"textValue\"\n (keyup.enter)=\"onApply(f)\"\n />\n </monkey-form-field>\n </label>\n @if (isRange(f)) {\n <label class=\"mecx-filter-bar-field-row\">\n <span class=\"mecx-filter-bar-field-label\">{{ labels().rangeTo }}</span>\n <monkey-form-field size=\"sm\" noFooterSpace>\n <input\n type=\"text\"\n monkey-input\n [(ngModel)]=\"textValue2\"\n (keyup.enter)=\"onApply(f)\"\n />\n </monkey-form-field>\n </label>\n }\n }\n\n <monkey-button type=\"secondary\" size=\"sm\" (click)=\"onApply(f)\">\n {{ labels().confirm }}\n </monkey-button>\n </div>\n </monkey-filter-menu>\n }\n }\n }\n </monkey-filter-segment>\n }\n </monkey-filter-chip>\n </span>\n }\n\n @if (canAddFilter()) {\n <span\n class=\"mecx-filter-bar-slot mecx-filter-bar-slot--trigger\"\n [attr.data-flip-id]=\"triggerFlipId()\"\n >\n <monkey-filter-trigger\n [variant]=\"triggerVariant()\"\n [icon]=\"triggerIcon()\"\n [text]=\"labels().add\"\n [ariaLabel]=\"labels().addAria\"\n [disabled]=\"disabled()\"\n [immediateExit]=\"immediateTriggerExit()\"\n [open]=\"triggerOpen()\"\n (onOpenChange)=\"onTriggerOpenChange($event)\"\n >\n @if (triggerOpen()) {\n <monkey-filter-menu\n class=\"mecx-filter-bar-menu-categories\"\n [showSearch]=\"true\"\n [searchPlaceholder]=\"labels().search\"\n (onSearchChange)=\"categorySearch.set($event)\"\n >\n @for (opt of addOptions(); track opt.key; let i = $index) {\n @if (needsDivider(addOptions(), i)) {\n <monkey-divider />\n }\n <monkey-filter-menu-item\n [leadIcon]=\"opt.icon ?? null\"\n [label]=\"opt.label\"\n (onItemClick)=\"onSelectCategory(i)\"\n />\n }\n </monkey-filter-menu>\n }\n </monkey-filter-trigger>\n </span>\n }\n </div>\n @if (rows().length > 0) {\n <monkey-scrollbar\n class=\"mecx-filter-bar-bar\"\n orientation=\"horizontal\"\n size=\"small\"\n [target]=\"rowEl\"\n />\n }\n\n <div class=\"mecx-filter-bar-tail\">\n @if (rows().length > 0) {\n <div class=\"mecx-filter-bar-actions\">\n <monkey-button type=\"tertiary\" size=\"sm\" [disabled]=\"disabled()\" (click)=\"onClearAll()\">\n {{ labels().clear }}\n </monkey-button>\n </div>\n }\n\n <div class=\"mecx-filter-bar-extra\">\n <ng-content></ng-content>\n </div>\n </div>\n</div>\n@if (rows().length > 0) {\n <monkey-divider />\n}\n", styles: [".mecx-filter-bar{--mecx-filter-bar-duration-state: .15s;--mecx-filter-bar-duration-enter: .2s;--mecx-filter-bar-duration-exit: .15s;--mecx-filter-bar-ease-state: cubic-bezier(.25, .46, .45, .94);--mecx-filter-bar-ease-enter: cubic-bezier(.32, .72, 0, 1);--mecx-filter-bar-ease-exit: cubic-bezier(.4, 0, 1, 1);--mecx-filter-bar-scale-unfold: .94;--mecx-filter-bar-travel-anchored: 4px;--mecx-filter-bar-travel-slide: 16px;--mecx-filter-bar-stagger: 25ms;--mecx-filter-bar-control-height: 32px;--mecx-filter-bar-pointer-target: 40px;--mecx-filter-bar-reach: calc((var(--mecx-filter-bar-control-height) - var(--mecx-filter-bar-pointer-target)) / 2);--mecx-filter-bar-radius: 8px;--mecx-filter-bar-radius-item: 4px;--mecx-filter-bar-fade-width: 48px}@media(prefers-reduced-motion:reduce){.mecx-filter-bar{--mecx-filter-bar-duration-state: 1ms;--mecx-filter-bar-duration-enter: 1ms;--mecx-filter-bar-duration-exit: 1ms;--mecx-filter-bar-scale-unfold: 1;--mecx-filter-bar-travel-anchored: 0px;--mecx-filter-bar-travel-slide: 0px;--mecx-filter-bar-stagger: 0ms}}.mecx-filter-bar{display:flex;flex-direction:column;gap:8px;width:100%;background:var(--mecx-color-white)}.mecx-filter-bar-top{display:flex;align-items:center;gap:8px;width:100%}.mecx-filter-bar-search{flex:1;min-width:0;max-width:400px;display:block}.mecx-filter-bar-extra{margin-left:auto;display:flex;align-items:center;flex-wrap:wrap;gap:8px}.mecx-filter-bar-extra:empty{display:none}.mecx-filter-bar-line{display:grid;grid-template-columns:minmax(0,1fr) auto;grid-template-areas:\"row tail\" \"bar bar\";align-items:center;row-gap:8px;width:100%}.mecx-filter-bar-bar{grid-area:bar;min-width:0}.mecx-filter-bar-tail{grid-area:tail;display:flex;align-items:center;min-width:0}.mecx-filter-bar-row{grid-area:row;display:flex;align-items:center;gap:8px;min-width:0;overflow-x:auto;position:relative;min-height:var(--mecx-filter-bar-pointer-target);padding-inline-end:var(--mecx-filter-bar-fade-width);scrollbar-width:none;-ms-overflow-style:none}.mecx-filter-bar-row::-webkit-scrollbar{width:0;height:0}.mecx-filter-bar--disabled .mecx-filter-bar-row{cursor:default}.mecx-filter-bar-actions{position:relative;display:flex;align-items:center;justify-content:flex-end;align-self:stretch;flex-shrink:0;padding-left:var(--mecx-filter-bar-fade-width);background:var(--mecx-color-white)}.mecx-filter-bar-actions:before{content:\"\";position:absolute;inset-block:0;right:100%;width:var(--mecx-filter-bar-fade-width);background:linear-gradient(to right,transparent,var(--mecx-color-white));pointer-events:none}.mecx-filter-bar-slot{display:inline-flex;flex-shrink:0;transition:translate var(--mecx-filter-bar-duration-enter) var(--mecx-filter-bar-ease-enter)}.mecx-filter-bar-slot--frozen{transition-duration:0s}@keyframes mecx-filter-bar-slot-in{0%{opacity:0;translate:calc(var(--mecx-filter-bar-travel-slide) * -1) 0}}@keyframes mecx-filter-bar-slot-out{to{opacity:0;translate:calc(var(--mecx-filter-bar-travel-slide) * -1) 0}}.mecx-filter-bar-slot--leaving{position:absolute;pointer-events:none;animation:mecx-filter-bar-slot-out var(--mecx-filter-bar-duration-exit) var(--mecx-filter-bar-ease-exit) both}.mecx-filter-bar-slot--entering{animation:mecx-filter-bar-slot-in var(--mecx-filter-bar-duration-enter) var(--mecx-filter-bar-ease-enter);position:relative;z-index:1}.mecx-filter-menu.mecx-filter-bar-menu-categories{width:220px}.mecx-filter-menu.mecx-filter-bar-menu-status{width:225px}.mecx-filter-menu.mecx-filter-bar-menu-field{width:238px}.mecx-filter-bar-field{display:flex;flex-direction:column;gap:8px;width:100%;box-sizing:border-box}.mecx-filter-bar-field monkey-form-field{display:block;width:100%}.mecx-filter-bar-field monkey-button,.mecx-filter-bar-field monkey-button .mecx-button{width:100%}.mecx-filter-bar-field-row{display:flex;flex-direction:column;gap:4px;width:100%;cursor:pointer}.mecx-filter-bar-field-label{color:var(--mecx-color-gray-900);font-size:14px;font-weight:400;line-height:24px;letter-spacing:.14px}.mecx-filter-bar-panel-actions{display:flex;margin-top:8px;padding-top:8px;border-top:1px solid var(--mecx-color-gray-200)}.mecx-filter-bar-panel-actions monkey-button,.mecx-filter-bar-panel-actions monkey-button .mecx-button{width:100%}.mecx-filter-bar-calendar{display:block;background:var(--mecx-color-white);border-radius:var(--mecx-filter-bar-radius);box-shadow:0 8px 12px -4px var(--mecx-color-box-shadow, rgba(47, 50, 55, .08))}@media(max-width:767.98px){.mecx-filter-bar-line{grid-template-columns:minmax(0,1fr);grid-template-areas:\"row\" \"bar\" \"tail\";position:relative}.mecx-filter-bar-slot--trigger{position:sticky;right:0;z-index:2}.mecx-filter-bar-row{padding-inline-end:0}.mecx-filter-bar-actions{padding-left:0;align-self:auto;background:none;position:static}.mecx-filter-bar-actions:before{right:var(--mecx-filter-bar-control-height);bottom:auto;height:var(--mecx-filter-bar-pointer-target)}}\n/*!\n* Bootstrap Grid v5.3.7 (https://getbootstrap.com/)\n* Copyright 2011-2025 The Bootstrap Authors\n* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n*/\n"] }]
|
|
7109
|
+
}], ctorParameters: () => [], propDecorators: { config: [{ type: i0.Input, args: [{ isSignal: true, alias: "config", required: false }] }], filters: [{ type: i0.Input, args: [{ isSignal: true, alias: "filters", required: false }] }], onFiltersChange: [{ type: i0.Output, args: ["onFiltersChange"] }], dateFormat: [{ type: i0.Input, args: [{ isSignal: true, alias: "dateFormat", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], debounce: [{ type: i0.Input, args: [{ isSignal: true, alias: "debounce", required: false }] }] } });
|
|
8339
7110
|
|
|
8340
7111
|
/** ************************
|
|
8341
7112
|
* Copyright Monkey Exchange. All Rights Reserved
|
|
@@ -10735,6 +9506,191 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImpor
|
|
|
10735
9506
|
* MIT Licence
|
|
10736
9507
|
************************* */
|
|
10737
9508
|
|
|
9509
|
+
/** ************************
|
|
9510
|
+
* Copyright Monkey Exchange. All Rights Reserved
|
|
9511
|
+
* This style guide was developed by Monkey Exchange Team
|
|
9512
|
+
* MIT Licence
|
|
9513
|
+
************************* */
|
|
9514
|
+
class MonkeyRadioButtonComponent {
|
|
9515
|
+
get classes() {
|
|
9516
|
+
return `${this.position} ${this.size}`;
|
|
9517
|
+
}
|
|
9518
|
+
get disabled() {
|
|
9519
|
+
if (this.ngControl && this.ngControl.disabled !== null) {
|
|
9520
|
+
return this.ngControl.disabled;
|
|
9521
|
+
}
|
|
9522
|
+
return this._disabled;
|
|
9523
|
+
}
|
|
9524
|
+
set disabled(value) {
|
|
9525
|
+
this._disabled = value;
|
|
9526
|
+
if (this.focused) {
|
|
9527
|
+
this.focused = false;
|
|
9528
|
+
this.stateChanges.next();
|
|
9529
|
+
}
|
|
9530
|
+
}
|
|
9531
|
+
get required() {
|
|
9532
|
+
return this._required ?? this.ngControl?.control?.hasValidator(Validators.required) ?? false;
|
|
9533
|
+
}
|
|
9534
|
+
set required(value) {
|
|
9535
|
+
this._required = value;
|
|
9536
|
+
this.stateChanges.next();
|
|
9537
|
+
}
|
|
9538
|
+
set value(value) {
|
|
9539
|
+
if (this._value !== value) {
|
|
9540
|
+
this._value = value;
|
|
9541
|
+
this._onChange(value);
|
|
9542
|
+
}
|
|
9543
|
+
}
|
|
9544
|
+
get value() {
|
|
9545
|
+
return this._value;
|
|
9546
|
+
}
|
|
9547
|
+
constructor(changeDetectorRef, formField) {
|
|
9548
|
+
this.changeDetectorRef = changeDetectorRef;
|
|
9549
|
+
this.formField = formField;
|
|
9550
|
+
this.tabIndex = 0;
|
|
9551
|
+
this.onChange = new EventEmitter();
|
|
9552
|
+
this.onSearch = new EventEmitter();
|
|
9553
|
+
this.position = 'horizontal';
|
|
9554
|
+
this.size = 'lg';
|
|
9555
|
+
this._value = null;
|
|
9556
|
+
this._destroyRef = inject(DestroyRef);
|
|
9557
|
+
this.idGenerator = inject(IdGenerator);
|
|
9558
|
+
this.ngControl = inject(NgControl, { self: true, optional: true });
|
|
9559
|
+
this._elementRef = inject(ElementRef);
|
|
9560
|
+
this.focused = false;
|
|
9561
|
+
this._disabled = false;
|
|
9562
|
+
this.id = this.idGenerator.getId('monkey-radiobutton-');
|
|
9563
|
+
this.stateChanges = new Subject();
|
|
9564
|
+
this.type = 'radio-button';
|
|
9565
|
+
this._onChange = () => { };
|
|
9566
|
+
this._onTouched = () => { };
|
|
9567
|
+
if (this.ngControl) {
|
|
9568
|
+
this.ngControl.valueAccessor = this;
|
|
9569
|
+
}
|
|
9570
|
+
}
|
|
9571
|
+
changeSelected() {
|
|
9572
|
+
setTimeout(() => {
|
|
9573
|
+
if (this.options) {
|
|
9574
|
+
this.options.forEach((opt) => {
|
|
9575
|
+
opt.onSelect(opt.value() === this.value);
|
|
9576
|
+
});
|
|
9577
|
+
}
|
|
9578
|
+
this.changeDetectorRef.markForCheck();
|
|
9579
|
+
});
|
|
9580
|
+
}
|
|
9581
|
+
initializeOptions() {
|
|
9582
|
+
setTimeout(() => {
|
|
9583
|
+
this.options?.forEach((option) => {
|
|
9584
|
+
option.type = 'radio';
|
|
9585
|
+
if (!option.action) {
|
|
9586
|
+
option.action = this.selectOption.bind(this, option);
|
|
9587
|
+
}
|
|
9588
|
+
});
|
|
9589
|
+
this.changeDetectorRef.markForCheck();
|
|
9590
|
+
}, 0);
|
|
9591
|
+
}
|
|
9592
|
+
ngAfterContentInit() {
|
|
9593
|
+
this.initializeOptions();
|
|
9594
|
+
this.options.changes.pipe(takeUntilDestroyed(this._destroyRef)).subscribe(() => {
|
|
9595
|
+
this.initializeOptions();
|
|
9596
|
+
this.changeSelected();
|
|
9597
|
+
});
|
|
9598
|
+
}
|
|
9599
|
+
selectOption(option) {
|
|
9600
|
+
if (!option.disabled && !this.disabled) {
|
|
9601
|
+
this.value = option.value();
|
|
9602
|
+
this._onChange(this.value);
|
|
9603
|
+
this.onChange.emit(this.value);
|
|
9604
|
+
this.options.forEach((opt) => {
|
|
9605
|
+
opt.onSelect(opt.value() === this.value);
|
|
9606
|
+
});
|
|
9607
|
+
}
|
|
9608
|
+
}
|
|
9609
|
+
writeValue(value) {
|
|
9610
|
+
this.value = value;
|
|
9611
|
+
this.changeSelected();
|
|
9612
|
+
}
|
|
9613
|
+
onContainerClick(event) {
|
|
9614
|
+
if (this.disabled)
|
|
9615
|
+
return;
|
|
9616
|
+
this._elementRef.nativeElement.focus();
|
|
9617
|
+
}
|
|
9618
|
+
_onFocus() {
|
|
9619
|
+
if (!this.disabled) {
|
|
9620
|
+
this.focused = true;
|
|
9621
|
+
this._onTouched();
|
|
9622
|
+
this.stateChanges.next();
|
|
9623
|
+
}
|
|
9624
|
+
}
|
|
9625
|
+
_onBlur() {
|
|
9626
|
+
this.focused = false;
|
|
9627
|
+
this.stateChanges.next();
|
|
9628
|
+
}
|
|
9629
|
+
registerOnChange(fn) {
|
|
9630
|
+
this._onChange = fn;
|
|
9631
|
+
}
|
|
9632
|
+
registerOnTouched(fn) {
|
|
9633
|
+
this._onTouched = fn;
|
|
9634
|
+
}
|
|
9635
|
+
setDisabledState(isDisabled) {
|
|
9636
|
+
this.disabled = isDisabled;
|
|
9637
|
+
this.initializeOptions();
|
|
9638
|
+
}
|
|
9639
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: MonkeyRadioButtonComponent, deps: [{ token: i0.ChangeDetectorRef }, { token: MonkeyFormFieldComponent, optional: true }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
9640
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "16.1.0", version: "21.2.4", type: MonkeyRadioButtonComponent, isStandalone: true, selector: "monkey-radiobutton", inputs: { tabIndex: "tabIndex", position: "position", size: "size", disabled: ["disabled", "disabled", booleanAttribute], required: ["required", "required", booleanAttribute], value: "value" }, outputs: { onChange: "onChange", onSearch: "onSearch" }, host: { attributes: { "data-testid": "monkey-radiobutton" }, listeners: { "focus": "_onFocus()", "blur": "_onBlur()" }, properties: { "class.mecx-disabled": "disabled", "class.mecx-radiobutton-focused": "focused", "attr.id": "id", "attr.tabindex": "disabled ? -1 : tabIndex", "class": "this.classes" }, classAttribute: "mecx-radiobutton" }, providers: [
|
|
9641
|
+
// eslint-disable-next-line no-use-before-define
|
|
9642
|
+
{ provide: MonkeyFormFieldControl, useExisting: MonkeyRadioButtonComponent }
|
|
9643
|
+
], queries: [{ propertyName: "options", predicate: MonkeyOptionComponent }], ngImport: i0, template: "<ng-content />\r\n", styles: ["monkey-radiobutton{display:inline-flex;width:100%;min-width:0;position:relative;flex-wrap:wrap}monkey-radiobutton:focus-visible,monkey-radiobutton:focus{outline:none}monkey-radiobutton.vertical{flex-direction:column}monkey-radiobutton monkey-option{transition:none!important}monkey-radiobutton.mecx-disabled monkey-option{opacity:.5;pointer-events:none}monkey-radiobutton.mecx-disabled monkey-option:before{background:var(--mecx-color-white);border-color:var(--mecx-color-gray-400)}monkey-radiobutton.mecx-form-field-invalid{background:var(--mecx-color-error-700)}monkey-radiobutton.md monkey-option:before{width:16px;height:16px}monkey-radiobutton.sm monkey-option:before{width:14px;height:14px}\n"], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "ngmodule", type: FormsModule }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
|
|
9644
|
+
}
|
|
9645
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: MonkeyRadioButtonComponent, decorators: [{
|
|
9646
|
+
type: Component,
|
|
9647
|
+
args: [{ selector: 'monkey-radiobutton', imports: [ReactiveFormsModule, FormsModule], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, providers: [
|
|
9648
|
+
// eslint-disable-next-line no-use-before-define
|
|
9649
|
+
{ provide: MonkeyFormFieldControl, useExisting: MonkeyRadioButtonComponent }
|
|
9650
|
+
], host: {
|
|
9651
|
+
'data-testid': 'monkey-radiobutton',
|
|
9652
|
+
class: 'mecx-radiobutton',
|
|
9653
|
+
'[class.mecx-disabled]': 'disabled',
|
|
9654
|
+
'[class.mecx-radiobutton-focused]': 'focused',
|
|
9655
|
+
'[attr.id]': 'id',
|
|
9656
|
+
'[attr.tabindex]': 'disabled ? -1 : tabIndex',
|
|
9657
|
+
'(focus)': '_onFocus()',
|
|
9658
|
+
'(blur)': '_onBlur()'
|
|
9659
|
+
}, template: "<ng-content />\r\n", styles: ["monkey-radiobutton{display:inline-flex;width:100%;min-width:0;position:relative;flex-wrap:wrap}monkey-radiobutton:focus-visible,monkey-radiobutton:focus{outline:none}monkey-radiobutton.vertical{flex-direction:column}monkey-radiobutton monkey-option{transition:none!important}monkey-radiobutton.mecx-disabled monkey-option{opacity:.5;pointer-events:none}monkey-radiobutton.mecx-disabled monkey-option:before{background:var(--mecx-color-white);border-color:var(--mecx-color-gray-400)}monkey-radiobutton.mecx-form-field-invalid{background:var(--mecx-color-error-700)}monkey-radiobutton.md monkey-option:before{width:16px;height:16px}monkey-radiobutton.sm monkey-option:before{width:14px;height:14px}\n"] }]
|
|
9660
|
+
}], ctorParameters: () => [{ type: i0.ChangeDetectorRef }, { type: MonkeyFormFieldComponent, decorators: [{
|
|
9661
|
+
type: Optional
|
|
9662
|
+
}] }], propDecorators: { options: [{
|
|
9663
|
+
type: ContentChildren,
|
|
9664
|
+
args: [MonkeyOptionComponent]
|
|
9665
|
+
}], tabIndex: [{
|
|
9666
|
+
type: Input
|
|
9667
|
+
}], onChange: [{
|
|
9668
|
+
type: Output
|
|
9669
|
+
}], onSearch: [{
|
|
9670
|
+
type: Output
|
|
9671
|
+
}], position: [{
|
|
9672
|
+
type: Input
|
|
9673
|
+
}], size: [{
|
|
9674
|
+
type: Input
|
|
9675
|
+
}], classes: [{
|
|
9676
|
+
type: HostBinding,
|
|
9677
|
+
args: ['class']
|
|
9678
|
+
}], disabled: [{
|
|
9679
|
+
type: Input,
|
|
9680
|
+
args: [{ transform: booleanAttribute }]
|
|
9681
|
+
}], required: [{
|
|
9682
|
+
type: Input,
|
|
9683
|
+
args: [{ transform: booleanAttribute }]
|
|
9684
|
+
}], value: [{
|
|
9685
|
+
type: Input
|
|
9686
|
+
}] } });
|
|
9687
|
+
|
|
9688
|
+
/** ************************
|
|
9689
|
+
* Copyright Monkey Exchange. All Rights Reserved
|
|
9690
|
+
* This style guide was developed by Monkey Exchange Team
|
|
9691
|
+
* MIT Licence
|
|
9692
|
+
************************* */
|
|
9693
|
+
|
|
10738
9694
|
/** ************************
|
|
10739
9695
|
* Copyright Monkey Exchange. All Rights Reserved
|
|
10740
9696
|
* This style guide was developed by Monkey Exchange Team
|
|
@@ -11448,7 +10404,6 @@ const DEFAULT_ROW_HEIGHT = 65;
|
|
|
11448
10404
|
const DEFAULT_MAX_VISIBLE_ROWS = 20;
|
|
11449
10405
|
const DEFAULT_SKELETON_ROWS = 5;
|
|
11450
10406
|
const WINDOW_BUFFER = 6;
|
|
11451
|
-
const VIRTUAL_SCREENFULS = 3;
|
|
11452
10407
|
const VIRTUAL_MIN_ROWS = 19;
|
|
11453
10408
|
class MonkeyTableComponent {
|
|
11454
10409
|
constructor() {
|
|
@@ -11583,7 +10538,7 @@ class MonkeyTableComponent {
|
|
|
11583
10538
|
this.virtual = computed(() => {
|
|
11584
10539
|
if (this.virtualScroll() === 'off' || !this.bounded() || this.loading())
|
|
11585
10540
|
return false;
|
|
11586
|
-
const threshold = Math.max(this._rowCap()
|
|
10541
|
+
const threshold = Math.max(this._rowCap(), VIRTUAL_MIN_ROWS);
|
|
11587
10542
|
return this.rowViews().length > threshold;
|
|
11588
10543
|
}, ...(ngDevMode ? [{ debugName: "virtual" }] : /* istanbul ignore next */ []));
|
|
11589
10544
|
this.effectiveHeight = computed(() => {
|
|
@@ -13021,5 +11976,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImpor
|
|
|
13021
11976
|
* Generated bundle index. Do not edit.
|
|
13022
11977
|
*/
|
|
13023
11978
|
|
|
13024
|
-
export { MECX_COUNTRY_ISO_CODE, MECX_GOOGLE_API_KEY, MECX_I18N_WRAPPER, MECX_MODAL_DATA, MECX_MODAL_DEFAULT_CONFIG, MECX_POPOVER_OPTIONS, MonkeyAccordionComponent, MonkeyActionBarComponent, MonkeyAlertComponent, MonkeyAutocompleteAddressComponent, MonkeyAutocompleteComponent, MonkeyAvatarComponent, MonkeyBadgeComponent, MonkeyBadgeDirective, MonkeyBreadcrumbComponent, MonkeyButtonComponent, MonkeyCheckboxComponent, MonkeyComplexFilterBarComponent, MonkeyDateRangeComponent, MonkeyDictionaryService, MonkeyDisplayDirective, MonkeyDividerComponent, MonkeyDownloadButtonComponent, MonkeyEcxAddressService, MonkeyErrorDirective, MonkeyFilterBarComponent, MonkeyFilterBarService,
|
|
11979
|
+
export { MECX_COUNTRY_ISO_CODE, MECX_GOOGLE_API_KEY, MECX_I18N_WRAPPER, MECX_MODAL_DATA, MECX_MODAL_DEFAULT_CONFIG, MECX_POPOVER_OPTIONS, MonkeyAccordionComponent, MonkeyActionBarComponent, MonkeyAlertComponent, MonkeyAutocompleteAddressComponent, MonkeyAutocompleteComponent, MonkeyAvatarComponent, MonkeyBadgeComponent, MonkeyBadgeDirective, MonkeyBreadcrumbComponent, MonkeyButtonComponent, MonkeyCheckboxComponent, MonkeyComplexFilterBarComponent, MonkeyDateRangeComponent, MonkeyDictionaryService, MonkeyDisplayDirective, MonkeyDividerComponent, MonkeyDownloadButtonComponent, MonkeyEcxAddressService, MonkeyErrorDirective, MonkeyFilterBarComponent, MonkeyFilterBarService, MonkeyFilterChipComponent, MonkeyFilterMenuComponent, MonkeyFilterMenuItemComponent, MonkeyFilterSegmentComponent, MonkeyFilterTriggerComponent, MonkeyFormDirective, MonkeyFormFieldComponent, MonkeyFormFieldControl, MonkeyFormFieldModule, MonkeyHelperDirective, MonkeyIconButtonComponent, MonkeyInfoDirective, MonkeyInputCodeComponent, MonkeyInputCurrencyDirective, MonkeyInputDateRangeComponent, MonkeyInputDirective, MonkeyInputModule, MonkeyInputPhoneComponent, MonkeyInputUploadComponent, MonkeyLabelDirective, MonkeyModalActionsDirective, MonkeyModalComponent, MonkeyModalConfig, MonkeyModalContentDirective, MonkeyModalModule, MonkeyModalRef, MonkeyModalService, MonkeyModalSubtitleDirective, MonkeyModalTitleDirective, MonkeyOptionComponent, MonkeyPaginationActionComponent, MonkeyPaginationLabelComponent, MonkeyPaginationSizeComponent, MonkeyPassNumberComponent, MonkeyPassSecretNumberComponent, MonkeyPopoverContentComponent, MonkeyPopoverDirective, MonkeyPrefixDirective, MonkeyRadioButtonComponent, MonkeyScrollbarComponent, MonkeySecurityLevelComponent, MonkeySelectComponent, MonkeyStatusComponent, MonkeyStepComponent, MonkeyStepperComponent, MonkeyStepperModule, MonkeyStepperService, MonkeySuffixDirective, MonkeyTabComponent, MonkeyTabLinkDirective, MonkeyTableCellDirective, MonkeyTableColumnDirective, MonkeyTableComponent, MonkeyTableEmptyDirective, MonkeyTableHeaderCellDirective, MonkeyTableLoadingDirective, MonkeyTableRowDetailDirective, MonkeyTabsComponent, MonkeyTabsModule, MonkeyToastComponent, MonkeyToastRef, MonkeyToastService, MonkeyToggleComponent, MonkeyToggleLineButtonComponent, MonkeyToggleLineComponent, MonkeyTooltipComponent, MonkeyTooltipDirective, MonkeyUserProfileButtonComponent, MonkeyUserProfileComponent, addKeys, appliedFrom, ariaSortOf, arityOf, conditionsOf, getCurrencySymbol, indexAtOffset, injectTokenWithWarning, interpolate, isComplete, mergeOrder, offsetOfIndex, panelOf, removeKeys, sameColumnState, selectionState, sortByOrder, toPx, toggleKey, totalHeight, withCondition, withType };
|
|
13025
11980
|
//# sourceMappingURL=monkey-style-guide.mjs.map
|