@xsmusices/ui 1.44.8 → 1.44.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/fesm2022/{xsmusices-ui-xs-buttons-group.xsstory-H1pcuFtx.mjs → xsmusices-ui-xs-buttons-group.xsstory-Cgmflzcs.mjs} +27 -5
- package/fesm2022/xsmusices-ui-xs-buttons-group.xsstory-Cgmflzcs.mjs.map +1 -0
- package/fesm2022/xsmusices-ui.mjs +20 -39
- package/fesm2022/xsmusices-ui.mjs.map +1 -1
- package/index.d.ts +1 -9
- package/package.json +1 -1
- package/fesm2022/xsmusices-ui-xs-buttons-group.xsstory-H1pcuFtx.mjs.map +0 -1
|
@@ -69,6 +69,28 @@ const story = {
|
|
|
69
69
|
],
|
|
70
70
|
},
|
|
71
71
|
},
|
|
72
|
+
{
|
|
73
|
+
name: 'Control segmentado',
|
|
74
|
+
description: 'Un botón marcado como selected queda activo y no emite clic, como en un conmutador de vistas',
|
|
75
|
+
inputs: {
|
|
76
|
+
buttonsInput: [
|
|
77
|
+
{ label: 'Lista', selected: true },
|
|
78
|
+
{ label: 'Stats' },
|
|
79
|
+
{ label: 'Opciones' },
|
|
80
|
+
],
|
|
81
|
+
},
|
|
82
|
+
},
|
|
83
|
+
{
|
|
84
|
+
name: 'Control segmentado con iconos',
|
|
85
|
+
description: 'Sin label el layout cae a iconOnly automáticamente',
|
|
86
|
+
inputs: {
|
|
87
|
+
buttonsInput: [
|
|
88
|
+
{ icon: { name: 'list' }, selected: true },
|
|
89
|
+
{ icon: { name: 'chart-simple' } },
|
|
90
|
+
{ icon: { name: 'gear' } },
|
|
91
|
+
],
|
|
92
|
+
},
|
|
93
|
+
},
|
|
72
94
|
],
|
|
73
95
|
multilanguage: false,
|
|
74
96
|
notes: [
|
|
@@ -86,12 +108,12 @@ const story = {
|
|
|
86
108
|
},
|
|
87
109
|
],
|
|
88
110
|
coverage: {
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
111
|
+
statements: 97,
|
|
112
|
+
branches: 100,
|
|
113
|
+
functions: 92,
|
|
114
|
+
lines: 97,
|
|
93
115
|
},
|
|
94
116
|
};
|
|
95
117
|
|
|
96
118
|
export { story };
|
|
97
|
-
//# sourceMappingURL=xsmusices-ui-xs-buttons-group.xsstory-
|
|
119
|
+
//# sourceMappingURL=xsmusices-ui-xs-buttons-group.xsstory-Cgmflzcs.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"xsmusices-ui-xs-buttons-group.xsstory-Cgmflzcs.mjs","sources":["../../../projects/xs-ui/src/lib/components/base/buttons-group/xs-buttons-group.xsstory.ts"],"sourcesContent":["import { StoryMeta } from '../../../story.types';\nimport { XSButtonsGroupComponent } from './xs-buttons-group.component';\n\nexport const story: StoryMeta = {\n id: 'buttons-group',\n name: 'Buttons Group',\n type: 'component',\n subtype: 'Base',\n status: 'active',\n usage: [],\n updated: '2026-01-16T11:57:36.415Z',\n created: '2025-08-15T21:04:25.954Z',\n description:\n 'Componente contenedor para crear grupos de botones con estilos conectados. Facilita la creación de barras de herramientas y controles segmentados.',\n component: XSButtonsGroupComponent,\n selector: 'xs-buttons-group',\n inputs: [\n {\n key: 'buttonsInput',\n label: 'Botones (Array)',\n type: 'json',\n default: [],\n },\n {\n key: 'buttonClick',\n label: 'Función de Click',\n type: 'json',\n default: undefined,\n },\n ],\n examples: [\n {\n name: 'Grupo Básico con Array',\n description:\n 'Grupo de botones creado desde un array de configuración',\n inputs: {\n buttonsInput: [\n { label: 'Guardar', variant: 'success' },\n { label: 'Cancelar', variant: 'secondary' },\n { label: 'Eliminar', variant: 'error' },\n ],\n },\n },\n {\n name: 'Grupo con Iconos',\n description: 'Botones agrupados con iconos FontAwesome',\n inputs: {\n buttonsInput: [\n { label: 'Editar', icon: { name: 'edit' } },\n { label: 'Copiar', icon: { name: 'copy' } },\n {\n label: 'Eliminar',\n icon: { name: 'trash' },\n variant: 'error',\n },\n ],\n },\n },\n {\n name: 'Grupo con Contenido Proyectado',\n description:\n 'Usando ng-content para botones personalizados',\n inputs: {},\n },\n {\n name: 'Grupo con Estados',\n description:\n 'Botones con diferentes estados (disabled, loading)',\n inputs: {\n buttonsInput: [\n { label: 'Activo' },\n { label: 'Cargando', loading: true },\n { label: 'Deshabilitado', disabled: true },\n ],\n },\n },\n {\n name: 'Control segmentado',\n description:\n 'Un botón marcado como selected queda activo y no emite clic, como en un conmutador de vistas',\n inputs: {\n buttonsInput: [\n { label: 'Lista', selected: true },\n { label: 'Stats' },\n { label: 'Opciones' },\n ],\n },\n },\n {\n name: 'Control segmentado con iconos',\n description:\n 'Sin label el layout cae a iconOnly automáticamente',\n inputs: {\n buttonsInput: [\n { icon: { name: 'list' }, selected: true },\n { icon: { name: 'chart-simple' } },\n { icon: { name: 'gear' } },\n ],\n },\n },\n ],\n multilanguage: false,\n notes: [\n {\n text: 'Los botones se conectan automáticamente con bordes y radios apropiados.',\n type: 'info',\n },\n {\n text: 'Soporta tanto configuración declarativa (buttonsInput) como proyección de contenido (ng-content).',\n type: 'info',\n },\n {\n text: 'Para eventos de click, usa buttonClickOutput o configura buttonClick.',\n type: 'info',\n },\n ],\n coverage: {\n statements: 97,\n branches: 100,\n functions: 92,\n lines: 97,\n },\n};\n"],"names":[],"mappings":";;AAGO,MAAM,KAAK,GAAc;AAC9B,IAAA,EAAE,EAAE,eAAe;AACnB,IAAA,IAAI,EAAE,eAAe;AACrB,IAAA,IAAI,EAAE,WAAW;AACjB,IAAA,OAAO,EAAE,MAAM;AACf,IAAA,MAAM,EAAE,QAAQ;AAChB,IAAA,KAAK,EAAE,EAAE;AACT,IAAA,OAAO,EAAE,0BAA0B;AACnC,IAAA,OAAO,EAAE,0BAA0B;AACnC,IAAA,WAAW,EACT,oJAAoJ;AACtJ,IAAA,SAAS,EAAE,uBAAuB;AAClC,IAAA,QAAQ,EAAE,kBAAkB;AAC5B,IAAA,MAAM,EAAE;AACN,QAAA;AACE,YAAA,GAAG,EAAE,cAAc;AACnB,YAAA,KAAK,EAAE,iBAAiB;AACxB,YAAA,IAAI,EAAE,MAAM;AACZ,YAAA,OAAO,EAAE,EAAE;AACZ,SAAA;AACD,QAAA;AACE,YAAA,GAAG,EAAE,aAAa;AAClB,YAAA,KAAK,EAAE,kBAAkB;AACzB,YAAA,IAAI,EAAE,MAAM;AACZ,YAAA,OAAO,EAAE,SAAS;AACnB,SAAA;AACF,KAAA;AACD,IAAA,QAAQ,EAAE;AACR,QAAA;AACE,YAAA,IAAI,EAAE,wBAAwB;AAC9B,YAAA,WAAW,EACT,yDAAyD;AAC3D,YAAA,MAAM,EAAE;AACN,gBAAA,YAAY,EAAE;AACZ,oBAAA,EAAE,KAAK,EAAE,SAAS,EAAE,OAAO,EAAE,SAAS,EAAE;AACxC,oBAAA,EAAE,KAAK,EAAE,UAAU,EAAE,OAAO,EAAE,WAAW,EAAE;AAC3C,oBAAA,EAAE,KAAK,EAAE,UAAU,EAAE,OAAO,EAAE,OAAO,EAAE;AACxC,iBAAA;AACF,aAAA;AACF,SAAA;AACD,QAAA;AACE,YAAA,IAAI,EAAE,kBAAkB;AACxB,YAAA,WAAW,EAAE,0CAA0C;AACvD,YAAA,MAAM,EAAE;AACN,gBAAA,YAAY,EAAE;oBACZ,EAAE,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE;oBAC3C,EAAE,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE;AAC3C,oBAAA;AACE,wBAAA,KAAK,EAAE,UAAU;AACjB,wBAAA,IAAI,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE;AACvB,wBAAA,OAAO,EAAE,OAAO;AACjB,qBAAA;AACF,iBAAA;AACF,aAAA;AACF,SAAA;AACD,QAAA;AACE,YAAA,IAAI,EAAE,gCAAgC;AACtC,YAAA,WAAW,EACT,+CAA+C;AACjD,YAAA,MAAM,EAAE,EAAE;AACX,SAAA;AACD,QAAA;AACE,YAAA,IAAI,EAAE,mBAAmB;AACzB,YAAA,WAAW,EACT,oDAAoD;AACtD,YAAA,MAAM,EAAE;AACN,gBAAA,YAAY,EAAE;oBACZ,EAAE,KAAK,EAAE,QAAQ,EAAE;AACnB,oBAAA,EAAE,KAAK,EAAE,UAAU,EAAE,OAAO,EAAE,IAAI,EAAE;AACpC,oBAAA,EAAE,KAAK,EAAE,eAAe,EAAE,QAAQ,EAAE,IAAI,EAAE;AAC3C,iBAAA;AACF,aAAA;AACF,SAAA;AACD,QAAA;AACE,YAAA,IAAI,EAAE,oBAAoB;AAC1B,YAAA,WAAW,EACT,8FAA8F;AAChG,YAAA,MAAM,EAAE;AACN,gBAAA,YAAY,EAAE;AACZ,oBAAA,EAAE,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE;oBAClC,EAAE,KAAK,EAAE,OAAO,EAAE;oBAClB,EAAE,KAAK,EAAE,UAAU,EAAE;AACtB,iBAAA;AACF,aAAA;AACF,SAAA;AACD,QAAA;AACE,YAAA,IAAI,EAAE,+BAA+B;AACrC,YAAA,WAAW,EACT,oDAAoD;AACtD,YAAA,MAAM,EAAE;AACN,gBAAA,YAAY,EAAE;oBACZ,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE;AAC1C,oBAAA,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,cAAc,EAAE,EAAE;AAClC,oBAAA,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE;AAC3B,iBAAA;AACF,aAAA;AACF,SAAA;AACF,KAAA;AACD,IAAA,aAAa,EAAE,KAAK;AACpB,IAAA,KAAK,EAAE;AACL,QAAA;AACE,YAAA,IAAI,EAAE,yEAAyE;AAC/E,YAAA,IAAI,EAAE,MAAM;AACb,SAAA;AACD,QAAA;AACE,YAAA,IAAI,EAAE,mGAAmG;AACzG,YAAA,IAAI,EAAE,MAAM;AACb,SAAA;AACD,QAAA;AACE,YAAA,IAAI,EAAE,uEAAuE;AAC7E,YAAA,IAAI,EAAE,MAAM;AACb,SAAA;AACF,KAAA;AACD,IAAA,QAAQ,EAAE;AACR,QAAA,UAAU,EAAE,EAAE;AACd,QAAA,QAAQ,EAAE,GAAG;AACb,QAAA,SAAS,EAAE,EAAE;AACb,QAAA,KAAK,EAAE,EAAE;AACV,KAAA;;;;;"}
|
|
@@ -13379,14 +13379,6 @@ var en$e = {
|
|
|
13379
13379
|
class XSFilterPanelComponent {
|
|
13380
13380
|
scrollContainer = viewChild('scrollContainer', ...(ngDevMode ? [{ debugName: "scrollContainer" }] : []));
|
|
13381
13381
|
show = model(false, ...(ngDevMode ? [{ debugName: "show" }] : []));
|
|
13382
|
-
/**
|
|
13383
|
-
* Modo embebido (Fase 1 App): el panel se presenta como contenido dentro
|
|
13384
|
-
* de un XSModal y NO pinta su propio overlay, hoja, cabecera ni gestiona
|
|
13385
|
-
* Escape/foco (lo hace el modal anfitrión). La lógica de grupos, tipos de
|
|
13386
|
-
* filtro y eventos se conserva intacta. Por defecto false: comportamiento
|
|
13387
|
-
* histórico sin cambios.
|
|
13388
|
-
*/
|
|
13389
|
-
embedded = input(false, ...(ngDevMode ? [{ debugName: "embedded" }] : []));
|
|
13390
13382
|
externalTranslateService = input(...(ngDevMode ? [undefined, { debugName: "externalTranslateService" }] : []));
|
|
13391
13383
|
_demoItems = signal([], ...(ngDevMode ? [{ debugName: "_demoItems" }] : []));
|
|
13392
13384
|
_data = signal([], ...(ngDevMode ? [{ debugName: "_data" }] : []));
|
|
@@ -13416,7 +13408,7 @@ class XSFilterPanelComponent {
|
|
|
13416
13408
|
effect(() => this._data.set(this.data() ?? []));
|
|
13417
13409
|
if (isPlatformBrowser(this.platformId)) {
|
|
13418
13410
|
effect(() => {
|
|
13419
|
-
if (
|
|
13411
|
+
if (this.show()) {
|
|
13420
13412
|
setTimeout(() => {
|
|
13421
13413
|
const el = document.querySelector('[role="dialog"]');
|
|
13422
13414
|
el?.focus();
|
|
@@ -13427,7 +13419,6 @@ class XSFilterPanelComponent {
|
|
|
13427
13419
|
.pipe(takeUntilDestroyed(this.destroyRef))
|
|
13428
13420
|
.subscribe((event) => {
|
|
13429
13421
|
if (event.key === 'Escape' &&
|
|
13430
|
-
!this.embedded() &&
|
|
13431
13422
|
this.show()) {
|
|
13432
13423
|
this.handleClose();
|
|
13433
13424
|
}
|
|
@@ -13498,12 +13489,8 @@ class XSFilterPanelComponent {
|
|
|
13498
13489
|
}
|
|
13499
13490
|
scrollToGroup(groupId) {
|
|
13500
13491
|
setTimeout(() => {
|
|
13501
|
-
if (!isPlatformBrowser(this.platformId))
|
|
13502
|
-
return;
|
|
13503
|
-
if (!this.show() && !this.embedded())
|
|
13504
|
-
return;
|
|
13505
13492
|
const el = document.getElementById(`group-${groupId}`);
|
|
13506
|
-
if (el) {
|
|
13493
|
+
if (el && this.scrollContainer()) {
|
|
13507
13494
|
el.scrollIntoView({
|
|
13508
13495
|
behavior: 'smooth',
|
|
13509
13496
|
block: 'nearest',
|
|
@@ -13777,12 +13764,12 @@ class XSFilterPanelComponent {
|
|
|
13777
13764
|
this.applied.emit();
|
|
13778
13765
|
}
|
|
13779
13766
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.33", ngImport: i0, type: XSFilterPanelComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
13780
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.33", type: XSFilterPanelComponent, isStandalone: true, selector: "xs-filter-panel", inputs: { show: { classPropertyName: "show", publicName: "show", isSignal: true, isRequired: false, transformFunction: null }, embedded: { classPropertyName: "embedded", publicName: "embedded", isSignal: true, isRequired: false, transformFunction: null }, externalTranslateService: { classPropertyName: "externalTranslateService", publicName: "externalTranslateService", isSignal: true, isRequired: false, transformFunction: null }, demoItems: { classPropertyName: "demoItems", publicName: "demoItems", isSignal: true, isRequired: false, transformFunction: null }, data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: false, transformFunction: null }, activeFiltersCount: { classPropertyName: "activeFiltersCount", publicName: "activeFiltersCount", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { show: "showChange", panelClose: "panelClose", applied: "applied", filterChange: "filterChange", clear: "clear" }, viewQueries: [{ propertyName: "scrollContainer", first: true, predicate: ["scrollContainer"], descendants: true, isSignal: true }], ngImport: i0, template: "@if (!embedded() && _demoItems().length > 0) {\n <div\n class=\"p-4 mb-4 rounded-xl bg-zinc-900/50 flex justify-between items-center\"\n >\n <div>\n <p class=\"text-white font-bold text-sm\">\n {{ t('DEMO_TITLE') }}\n </p>\n <p class=\"text-zinc-500 text-xs\">\n {{ t('DEMO_DESCRIPTION') }}\n </p>\n </div>\n <xs-button\n (onClick)=\"show.set(true)\"\n [label]=\"t('OPEN_FILTERS')\"\n variant=\"custom\"\n customClass=\"px-4 py-2 bg-blue-600 text-white text-sm font-semibold rounded-xl active:scale-95\"\n />\n </div>\n}\n\n@if (show() || embedded()) {\n @if (show() && !embedded()) {\n <div\n class=\"fixed inset-0 z-[9000] bg-black/60 backdrop-blur-sm overlay-fade-in cursor-default\"\n (click)=\"handleClose()\"\n role=\"presentation\"\n ></div>\n <div class=\"fixed inset-0 z-[9000] flex items-end justify-center pointer-events-none\">\n <section\n role=\"dialog\"\n aria-modal=\"true\"\n [attr.aria-label]=\"t('FILTERS')\"\n tabindex=\"-1\"\n class=\"relative w-full max-w-md mx-auto overflow-hidden bg-black shadow-2xl rounded-t-[2.5rem] sheet-slide-up max-h-[85vh] flex flex-col cursor-auto pointer-events-auto outline-none\"\n (click)=\"$event.stopPropagation()\"\n (keydown)=\"$event.stopPropagation()\"\n >\n <div class=\"flex justify-center pt-4 pb-2\">\n <div class=\"w-12 h-1.5 bg-zinc-800 rounded-full\"></div>\n </div>\n\n <div class=\"px-6 py-2 flex justify-between items-center\">\n <h2\n class=\"text-xl font-bold text-white tracking-tight uppercase\"\n >\n {{ t('FILTERS') }}\n </h2>\n <div class=\"flex items-center gap-2\">\n @if (activeFiltersCount() > 0) {\n <xs-button\n (onClick)=\"clear.emit()\"\n [label]=\"capitalize(t('CLEAR'))\"\n layout=\"mini\"\n variant=\"custom\"\n customClass=\"text-zinc-400 hover:text-white text-sm font-medium p-2 uppercase\"\n />\n }\n <xs-button\n (onClick)=\"handleApply()\"\n [label]=\"t('DONE')\"\n layout=\"mini\"\n variant=\"custom\"\n customClass=\"text-zinc-400 hover:text-white text-sm font-medium p-2 uppercase\"\n />\n </div>\n </div>\n <ng-container *ngTemplateOutlet=\"groupsTpl\" />\n </section>\n </div>\n } @else if (embedded()) {\n <ng-container *ngTemplateOutlet=\"groupsTpl\" />\n }\n}\n\n<ng-template #groupsTpl>\n <div\n #scrollContainer\n [class.flex-1]=\"!embedded()\"\n [class.overflow-y-auto]=\"!embedded()\"\n [class.no-scrollbar]=\"!embedded()\"\n class=\"px-4 pt-4 pb-12 space-y-3\"\n >\n @for (group of filteredData(); track group.id) {\n <div\n [id]=\"'group-' + group.id\"\n class=\"overflow-hidden rounded-[2.5rem] bg-zinc-900/50 transition-all duration-300 filter-group-item border-none\"\n >\n <button\n (click)=\"toggleGroup(group.id)\"\n type=\"button\"\n [attr.aria-expanded]=\"activeGroupId() === group.id\"\n [attr.aria-controls]=\"'group-content-' + group.id\"\n class=\"w-full flex items-center justify-between px-6 py-4 transition-colors border-none\"\n [class]=\"\n activeGroupId() === group.id\n ? 'bg-zinc-900/50'\n : 'bg-transparent hover:bg-black/40 active:bg-black/20'\n \"\n >\n <div\n class=\"flex-1 flex flex-col text-left justify-center h-full\"\n >\n <span\n class=\"text-[10px] font-bold text-zinc-500 uppercase tracking-[0.15em] leading-none mb-2\"\n >\n {{ t(group.title) }}\n </span>\n <span\n class=\"text-base font-semibold leading-tight\"\n [class.text-white]=\"\n group.selectedId ||\n (group.type === 'dateRange' &&\n (group.dateFrom || group.dateTo))\n \"\n >\n {{\n getSelectedLabel(group) || t('NOT_SELECTED')\n }}\n </span>\n </div>\n <div class=\"flex items-center justify-center pl-4\">\n <div\n class=\"chevron opacity-40\"\n [class.open]=\"activeGroupId() === group.id\"\n ></div>\n </div>\n </button>\n\n <div\n [id]=\"'group-content-' + group.id\"\n class=\"collapsible-content\"\n [class.open]=\"activeGroupId() === group.id\"\n role=\"region\"\n [attr.aria-label]=\"t(group.title)\"\n >\n <div class=\"collapsible-inner\">\n <div class=\"px-2 pb-3 bg-zinc-900/50\">\n <div\n class=\"bg-zinc-900/50 rounded-[1.8rem] overflow-hidden inner-panel shadow-2xl border-none\"\n >\n @if (activeGroupType() !== 'searchSelect' && activeGroupType() !== 'dateRange') {\n <div class=\"p-3 bg-zinc-900/50\">\n <div class=\"relative\">\n <input\n type=\"text\"\n [ngModel]=\"searchQuery()\"\n (ngModelChange)=\"\n searchQuery.set($event)\n \"\n [placeholder]=\"capitalize(t('SEARCH')) + '...'\"\n [attr.aria-label]=\"capitalize(t('SEARCH'))\"\n class=\"w-full bg-zinc-900/50 rounded-xl py-3 pl-10 pr-4 text-sm text-white focus:ring-0 placeholder:text-zinc-500 transition-all outline-none border-none\"\n />\n <span\n class=\"absolute left-3 top-3 opacity-40 text-sm\"\n aria-hidden=\"true\"\n >\uD83D\uDD0D</span\n >\n </div>\n </div>\n }\n\n <div class=\"flex flex-col\">\n @if (\n group.type === 'select' ||\n group.type === undefined ||\n group.type === 'searchSelect'\n ) {\n @for (\n opt of group.options;\n track $index\n ) {\n <button\n (click)=\"\n onSelectOption(group.id, opt.id)\n \"\n type=\"button\"\n class=\"w-full flex items-center justify-between px-6 py-4 text-sm border-none bg-transparent transition-all hover:bg-zinc-900/50 active:bg-zinc-900/50 group/opt\"\n >\n <span\n class=\"transition-colors duration-200\"\n [class.text-white]=\"\n group.selectedId === opt.id\n \"\n [class.font-bold]=\"\n group.selectedId === opt.id\n \"\n [class.text-zinc-500]=\"\n group.selectedId !== opt.id\n \"\n >\n {{ capitalize(t(opt.label)) }}\n </span>\n <div\n class=\"flex items-center justify-center w-5 h-5\"\n >\n <div\n [class.opacity-0]=\"\n group.selectedId !== opt.id\n \"\n [class.opacity-100]=\"\n group.selectedId === opt.id\n \"\n class=\"w-2.5 h-2.5 rounded-full bg-red-500 transition-opacity duration-200\"\n ></div>\n </div>\n </button>\n }\n }\n\n @if (group.type === 'multiSelect') {\n @for (\n opt of group.options;\n track $index\n ) {\n <button\n (click)=\"\n onMultiSelectOption(\n group.id,\n opt.id\n )\n \"\n type=\"button\"\n class=\"w-full flex items-center justify-between px-6 py-4 text-sm border-none bg-transparent transition-all hover:bg-zinc-900/50 active:bg-zinc-900/50 group/opt\"\n >\n <span\n class=\"transition-colors duration-200\"\n [class.text-white]=\"\n group.selectedIds?.includes(\n opt.id\n )\n \"\n [class.font-bold]=\"\n group.selectedIds?.includes(\n opt.id\n )\n \"\n [class.text-zinc-500]=\"\n !group.selectedIds?.includes(\n opt.id\n )\n \"\n >\n {{ capitalize(t(opt.label)) }}\n </span>\n <div\n class=\"flex items-center justify-center w-5 h-5\"\n >\n <div\n [class.opacity-0]=\"\n !group.selectedIds?.includes(\n opt.id\n )\n \"\n [class.opacity-100]=\"\n group.selectedIds?.includes(\n opt.id\n )\n \"\n class=\"w-2.5 h-2.5 rounded-full bg-red-500 transition-opacity duration-200\"\n ></div>\n </div>\n </button>\n }\n }\n\n @if (group.type === 'boolean') {\n <button\n (click)=\"\n onBooleanToggle(group.id, true)\n \"\n type=\"button\"\n class=\"w-full flex items-center justify-between px-6 py-4 text-sm border-none bg-transparent transition-all hover:bg-zinc-900/50 active:bg-zinc-900/50\"\n >\n <span\n class=\"transition-colors duration-200\"\n [class.text-white]=\"\n group.selectedBoolean === true\n \"\n [class.font-bold]=\"\n group.selectedBoolean === true\n \"\n [class.text-zinc-500]=\"\n group.selectedBoolean !== true\n \"\n >{{ capitalize(t('YES')) }}</span\n >\n <div\n class=\"flex items-center justify-center w-5 h-5\"\n >\n <div\n [class.opacity-0]=\"\n group.selectedBoolean !== true\n \"\n [class.opacity-100]=\"\n group.selectedBoolean === true\n \"\n class=\"w-2.5 h-2.5 rounded-full bg-red-500 transition-opacity duration-200\"\n ></div>\n </div>\n </button>\n <button\n (click)=\"\n onBooleanToggle(group.id, false)\n \"\n type=\"button\"\n class=\"w-full flex items-center justify-between px-6 py-4 text-sm border-none bg-transparent transition-all hover:bg-zinc-900/50 active:bg-zinc-900/50\"\n >\n <span\n class=\"transition-colors duration-200\"\n [class.text-white]=\"\n group.selectedBoolean === false\n \"\n [class.font-bold]=\"\n group.selectedBoolean === false\n \"\n [class.text-zinc-500]=\"\n group.selectedBoolean !== false\n \"\n >{{ capitalize(t('NO')) }}</span\n >\n <div\n class=\"flex items-center justify-center w-5 h-5\"\n >\n <div\n [class.opacity-0]=\"\n group.selectedBoolean !== false\n \"\n [class.opacity-100]=\"\n group.selectedBoolean === false\n \"\n class=\"w-2.5 h-2.5 rounded-full bg-red-500 transition-opacity duration-200\"\n ></div>\n </div>\n </button>\n }\n\n @if (group.type === 'range') {\n <div\n class=\"px-6 py-4 space-y-4 bg-zinc-900/50\"\n >\n <div class=\"space-y-2\">\n <label\n class=\"text-[10px] font-bold text-zinc-500 uppercase tracking-widest pl-1\"\n >\n {{ t('MIN_VALUE') }}\n </label>\n <input\n type=\"number\"\n [value]=\"\n group.selectedMin ||\n group.minValue ||\n ''\n \"\n (input)=\"\n onRangeChange(\n group.id,\n 'min',\n $event\n )\n \"\n [min]=\"group.minValue\"\n [max]=\"group.maxValue\"\n class=\"w-full bg-zinc-900/50 border-none rounded-xl py-3 px-4 text-sm text-white outline-none focus:ring-0 transition-all\"\n />\n </div>\n <div class=\"space-y-2\">\n <label\n class=\"text-[10px] font-bold text-zinc-500 uppercase tracking-widest pl-1\"\n >\n {{ t('MAX_VALUE') }}\n </label>\n <input\n type=\"number\"\n [value]=\"\n group.selectedMax ||\n group.maxValue ||\n ''\n \"\n (input)=\"\n onRangeChange(\n group.id,\n 'max',\n $event\n )\n \"\n [min]=\"group.minValue\"\n [max]=\"group.maxValue\"\n class=\"w-full bg-zinc-900/50 border-none rounded-xl py-3 px-4 text-sm text-white outline-none focus:ring-0 transition-all\"\n />\n </div>\n </div>\n }\n\n @if (group.type === 'searchSelect') {\n <div class=\"px-6 py-4 bg-zinc-900/50\">\n <input\n type=\"text\"\n [value]=\"\n group.selectedSearchValue || ''\n \"\n (input)=\"\n onSearchChange(group.id, $event)\n \"\n [placeholder]=\"\n group.searchPlaceholder ||\n capitalize(t('SEARCH'))\n \"\n [attr.aria-label]=\"group.searchPlaceholder || capitalize(t('SEARCH'))\"\n class=\"w-full bg-zinc-900/50 border-none rounded-xl py-3 px-4 text-sm text-white outline-none focus:ring-0 transition-all\"\n />\n </div>\n }\n\n @if (group.type === 'dateRange') {\n <div\n class=\"px-6 py-4 space-y-4 bg-zinc-900/50\"\n >\n <div class=\"space-y-2\">\n <label\n class=\"text-[10px] font-bold text-zinc-500 uppercase tracking-widest pl-1\"\n >{{ t('FROM_DATE') }}</label\n >\n <input\n type=\"date\"\n [value]=\"group.dateFrom || ''\"\n (change)=\"\n onDateChange(\n group.id,\n 'from',\n $event\n )\n \"\n class=\"w-full bg-zinc-900/50 border-none rounded-xl py-3 px-4 text-sm text-white outline-none focus:ring-0 transition-all\"\n />\n </div>\n <div class=\"space-y-2\">\n <label\n class=\"text-[10px] font-bold text-zinc-500 uppercase tracking-widest pl-1\"\n >{{ t('TO_DATE') }}</label\n >\n <input\n type=\"date\"\n [value]=\"group.dateTo || ''\"\n (change)=\"\n onDateChange(\n group.id,\n 'to',\n $event\n )\n \"\n class=\"w-full bg-zinc-900/50 border-none rounded-xl py-3 px-4 text-sm text-white outline-none focus:ring-0 transition-all\"\n />\n </div>\n </div>\n }\n </div>\n </div>\n </div>\n </div>\n </div>\n </div>\n }\n </div>\n</ng-template>\n", styles: [".overlay-fade-in{animation:fadeIn .25s ease-out forwards}.sheet-slide-up{will-change:transform;animation:slideUp .4s cubic-bezier(.32,.72,0,1) forwards}@keyframes fadeIn{0%{opacity:0}to{opacity:1}}@keyframes slideUp{0%{transform:translateY(100%)}to{transform:translateY(0)}}.no-scrollbar::-webkit-scrollbar{display:none}.no-scrollbar{-ms-overflow-style:none;scrollbar-width:none}.chevron{height:.5rem;width:.5rem;border-right-width:2px;border-bottom-width:2px;--tw-border-opacity: 1;border-color:rgb(82 82 91 / var(--tw-border-opacity, 1));transition:transform .4s cubic-bezier(.33,1,.68,1),border-color .3s ease;transform:rotate(45deg)}.chevron.open{transform:rotate(225deg) translateY(-1px) translate(-1px)}.filter-group-item:has(.collapsible-content.open){border-color:#3f3f4699;box-shadow:0 10px 30px -10px #00000080}.collapsible-content{display:grid;grid-template-rows:0fr;transition:grid-template-rows .4s cubic-bezier(.33,1,.68,1),opacity .3s ease,visibility .3s;visibility:hidden;opacity:0;overflow:hidden}.collapsible-content.open{grid-template-rows:1fr;visibility:visible;opacity:1}.collapsible-inner{min-height:0}.inner-panel{transform:scale(.98) translateY(-5px);transition:transform .4s cubic-bezier(.33,1,.68,1),opacity .4s ease;opacity:0}.collapsible-content.open .inner-panel{transform:scale(1) translateY(0);opacity:1}@media(hover:hover){.active\\:bg-zinc-800\\/50:hover{background-color:#3f3f464d}.active\\:bg-zinc-900\\/40:hover{background-color:#24242780}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$2.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$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: XSButtonComponent, selector: "xs-button", inputs: ["id", "label", "type", "icon", "action", "customClass", "variant", "layout", "badgeCount", "isFull", "disabled", "loading", "title", "ariaLabel", "borderRadius", "isGrouped", "groupPosition"], outputs: ["isGroupedChange", "groupPositionChange", "click", "onClick"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
13767
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.33", type: XSFilterPanelComponent, isStandalone: true, selector: "xs-filter-panel", inputs: { show: { classPropertyName: "show", publicName: "show", isSignal: true, isRequired: false, transformFunction: null }, externalTranslateService: { classPropertyName: "externalTranslateService", publicName: "externalTranslateService", isSignal: true, isRequired: false, transformFunction: null }, demoItems: { classPropertyName: "demoItems", publicName: "demoItems", isSignal: true, isRequired: false, transformFunction: null }, data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: false, transformFunction: null }, activeFiltersCount: { classPropertyName: "activeFiltersCount", publicName: "activeFiltersCount", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { show: "showChange", panelClose: "panelClose", applied: "applied", filterChange: "filterChange", clear: "clear" }, viewQueries: [{ propertyName: "scrollContainer", first: true, predicate: ["scrollContainer"], descendants: true, isSignal: true }], ngImport: i0, template: "@if (_demoItems().length > 0) {\n <div\n class=\"p-4 mb-4 rounded-xl bg-zinc-900/50 flex justify-between items-center\"\n >\n <div>\n <p class=\"text-white font-bold text-sm\">\n {{ t('DEMO_TITLE') }}\n </p>\n <p class=\"text-zinc-500 text-xs\">\n {{ t('DEMO_DESCRIPTION') }}\n </p>\n </div>\n <xs-button\n (onClick)=\"show.set(true)\"\n [label]=\"t('OPEN_FILTERS')\"\n variant=\"custom\"\n customClass=\"px-4 py-2 bg-blue-600 text-white text-sm font-semibold rounded-xl active:scale-95\"\n />\n </div>\n}\n\n@if (show()) {\n <div\n class=\"fixed inset-0 z-[9000] bg-black/60 backdrop-blur-sm overlay-fade-in cursor-default\"\n (click)=\"handleClose()\"\n role=\"presentation\"\n ></div>\n <div class=\"fixed inset-0 z-[9000] flex items-end justify-center pointer-events-none\">\n <section\n role=\"dialog\"\n aria-modal=\"true\"\n [attr.aria-label]=\"t('FILTERS')\"\n tabindex=\"-1\"\n class=\"relative w-full max-w-md mx-auto overflow-hidden bg-black shadow-2xl rounded-t-[2.5rem] sheet-slide-up max-h-[85vh] flex flex-col cursor-auto pointer-events-auto outline-none\"\n (click)=\"$event.stopPropagation()\"\n (keydown)=\"$event.stopPropagation()\"\n >\n <div class=\"flex justify-center pt-4 pb-2\">\n <div class=\"w-12 h-1.5 bg-zinc-800 rounded-full\"></div>\n </div>\n\n <div class=\"px-6 py-2 flex justify-between items-center\">\n <h2\n class=\"text-xl font-bold text-white tracking-tight uppercase\"\n >\n {{ t('FILTERS') }}\n </h2>\n <div class=\"flex items-center gap-2\">\n @if (activeFiltersCount() > 0) {\n <xs-button\n (onClick)=\"clear.emit()\"\n [label]=\"capitalize(t('CLEAR'))\"\n layout=\"mini\"\n variant=\"custom\"\n customClass=\"text-zinc-400 hover:text-white text-sm font-medium p-2 uppercase\"\n />\n }\n <xs-button\n (onClick)=\"handleApply()\"\n [label]=\"t('DONE')\"\n layout=\"mini\"\n variant=\"custom\"\n customClass=\"text-zinc-400 hover:text-white text-sm font-medium p-2 uppercase\"\n />\n </div>\n </div>\n\n <div\n #scrollContainer\n class=\"flex-1 overflow-y-auto no-scrollbar px-4 pt-4 pb-12 space-y-3\"\n >\n @for (group of filteredData(); track group.id) {\n <div\n [id]=\"'group-' + group.id\"\n class=\"overflow-hidden rounded-[2.5rem] bg-zinc-900/50 transition-all duration-300 filter-group-item border-none\"\n >\n <button\n (click)=\"toggleGroup(group.id)\"\n type=\"button\"\n [attr.aria-expanded]=\"activeGroupId() === group.id\"\n [attr.aria-controls]=\"'group-content-' + group.id\"\n class=\"w-full flex items-center justify-between px-6 py-4 transition-colors border-none\"\n [class]=\"\n activeGroupId() === group.id\n ? 'bg-zinc-900/50'\n : 'bg-transparent hover:bg-black/40 active:bg-black/20'\n \"\n >\n <div\n class=\"flex-1 flex flex-col text-left justify-center h-full\"\n >\n <span\n class=\"text-[10px] font-bold text-zinc-500 uppercase tracking-[0.15em] leading-none mb-2\"\n >\n {{ t(group.title) }}\n </span>\n <span\n class=\"text-base font-semibold leading-tight\"\n [class.text-white]=\"\n group.selectedId ||\n (group.type === 'dateRange' &&\n (group.dateFrom || group.dateTo))\n \"\n >\n {{\n getSelectedLabel(group) || t('NOT_SELECTED')\n }}\n </span>\n </div>\n <div class=\"flex items-center justify-center pl-4\">\n <div\n class=\"chevron opacity-40\"\n [class.open]=\"activeGroupId() === group.id\"\n ></div>\n </div>\n </button>\n\n <div\n [id]=\"'group-content-' + group.id\"\n class=\"collapsible-content\"\n [class.open]=\"activeGroupId() === group.id\"\n role=\"region\"\n [attr.aria-label]=\"t(group.title)\"\n >\n <div class=\"collapsible-inner\">\n <div class=\"px-2 pb-3 bg-zinc-900/50\">\n <div\n class=\"bg-zinc-900/50 rounded-[1.8rem] overflow-hidden inner-panel shadow-2xl border-none\"\n >\n @if (activeGroupType() !== 'searchSelect' && activeGroupType() !== 'dateRange') {\n <div class=\"p-3 bg-zinc-900/50\">\n <div class=\"relative\">\n <input\n type=\"text\"\n [ngModel]=\"searchQuery()\"\n (ngModelChange)=\"\n searchQuery.set($event)\n \"\n [placeholder]=\"capitalize(t('SEARCH')) + '...'\"\n [attr.aria-label]=\"capitalize(t('SEARCH'))\"\n class=\"w-full bg-zinc-900/50 rounded-xl py-3 pl-10 pr-4 text-sm text-white focus:ring-0 placeholder:text-zinc-500 transition-all outline-none border-none\"\n />\n <span\n class=\"absolute left-3 top-3 opacity-40 text-sm\"\n aria-hidden=\"true\"\n >\uD83D\uDD0D</span\n >\n </div>\n </div>\n }\n\n <div class=\"flex flex-col\">\n @if (\n group.type === 'select' ||\n group.type === undefined ||\n group.type === 'searchSelect'\n ) {\n @for (\n opt of group.options;\n track $index\n ) {\n <button\n (click)=\"\n onSelectOption(group.id, opt.id)\n \"\n type=\"button\"\n class=\"w-full flex items-center justify-between px-6 py-4 text-sm border-none bg-transparent transition-all hover:bg-zinc-900/50 active:bg-zinc-900/50 group/opt\"\n >\n <span\n class=\"transition-colors duration-200\"\n [class.text-white]=\"\n group.selectedId === opt.id\n \"\n [class.font-bold]=\"\n group.selectedId === opt.id\n \"\n [class.text-zinc-500]=\"\n group.selectedId !== opt.id\n \"\n >\n {{ capitalize(t(opt.label)) }}\n </span>\n <div\n class=\"flex items-center justify-center w-5 h-5\"\n >\n <div\n [class.opacity-0]=\"\n group.selectedId !== opt.id\n \"\n [class.opacity-100]=\"\n group.selectedId === opt.id\n \"\n class=\"w-2.5 h-2.5 rounded-full bg-red-500 transition-opacity duration-200\"\n ></div>\n </div>\n </button>\n }\n }\n\n @if (group.type === 'multiSelect') {\n @for (\n opt of group.options;\n track $index\n ) {\n <button\n (click)=\"\n onMultiSelectOption(\n group.id,\n opt.id\n )\n \"\n type=\"button\"\n class=\"w-full flex items-center justify-between px-6 py-4 text-sm border-none bg-transparent transition-all hover:bg-zinc-900/50 active:bg-zinc-900/50 group/opt\"\n >\n <span\n class=\"transition-colors duration-200\"\n [class.text-white]=\"\n group.selectedIds?.includes(\n opt.id\n )\n \"\n [class.font-bold]=\"\n group.selectedIds?.includes(\n opt.id\n )\n \"\n [class.text-zinc-500]=\"\n !group.selectedIds?.includes(\n opt.id\n )\n \"\n >\n {{ capitalize(t(opt.label)) }}\n </span>\n <div\n class=\"flex items-center justify-center w-5 h-5\"\n >\n <div\n [class.opacity-0]=\"\n !group.selectedIds?.includes(\n opt.id\n )\n \"\n [class.opacity-100]=\"\n group.selectedIds?.includes(\n opt.id\n )\n \"\n class=\"w-2.5 h-2.5 rounded-full bg-red-500 transition-opacity duration-200\"\n ></div>\n </div>\n </button>\n }\n }\n\n @if (group.type === 'boolean') {\n <button\n (click)=\"\n onBooleanToggle(group.id, true)\n \"\n type=\"button\"\n class=\"w-full flex items-center justify-between px-6 py-4 text-sm border-none bg-transparent transition-all hover:bg-zinc-900/50 active:bg-zinc-900/50\"\n >\n <span\n class=\"transition-colors duration-200\"\n [class.text-white]=\"\n group.selectedBoolean === true\n \"\n [class.font-bold]=\"\n group.selectedBoolean === true\n \"\n [class.text-zinc-500]=\"\n group.selectedBoolean !== true\n \"\n >{{ capitalize(t('YES')) }}</span\n >\n <div\n class=\"flex items-center justify-center w-5 h-5\"\n >\n <div\n [class.opacity-0]=\"\n group.selectedBoolean !== true\n \"\n [class.opacity-100]=\"\n group.selectedBoolean === true\n \"\n class=\"w-2.5 h-2.5 rounded-full bg-red-500 transition-opacity duration-200\"\n ></div>\n </div>\n </button>\n <button\n (click)=\"\n onBooleanToggle(group.id, false)\n \"\n type=\"button\"\n class=\"w-full flex items-center justify-between px-6 py-4 text-sm border-none bg-transparent transition-all hover:bg-zinc-900/50 active:bg-zinc-900/50\"\n >\n <span\n class=\"transition-colors duration-200\"\n [class.text-white]=\"\n group.selectedBoolean === false\n \"\n [class.font-bold]=\"\n group.selectedBoolean === false\n \"\n [class.text-zinc-500]=\"\n group.selectedBoolean !== false\n \"\n >{{ capitalize(t('NO')) }}</span\n >\n <div\n class=\"flex items-center justify-center w-5 h-5\"\n >\n <div\n [class.opacity-0]=\"\n group.selectedBoolean !== false\n \"\n [class.opacity-100]=\"\n group.selectedBoolean === false\n \"\n class=\"w-2.5 h-2.5 rounded-full bg-red-500 transition-opacity duration-200\"\n ></div>\n </div>\n </button>\n }\n\n @if (group.type === 'range') {\n <div\n class=\"px-6 py-4 space-y-4 bg-zinc-900/50\"\n >\n <div class=\"space-y-2\">\n <label\n class=\"text-[10px] font-bold text-zinc-500 uppercase tracking-widest pl-1\"\n >\n {{ t('MIN_VALUE') }}\n </label>\n <input\n type=\"number\"\n [value]=\"\n group.selectedMin ||\n group.minValue ||\n ''\n \"\n (input)=\"\n onRangeChange(\n group.id,\n 'min',\n $event\n )\n \"\n [min]=\"group.minValue\"\n [max]=\"group.maxValue\"\n class=\"w-full bg-zinc-900/50 border-none rounded-xl py-3 px-4 text-sm text-white outline-none focus:ring-0 transition-all\"\n />\n </div>\n <div class=\"space-y-2\">\n <label\n class=\"text-[10px] font-bold text-zinc-500 uppercase tracking-widest pl-1\"\n >\n {{ t('MAX_VALUE') }}\n </label>\n <input\n type=\"number\"\n [value]=\"\n group.selectedMax ||\n group.maxValue ||\n ''\n \"\n (input)=\"\n onRangeChange(\n group.id,\n 'max',\n $event\n )\n \"\n [min]=\"group.minValue\"\n [max]=\"group.maxValue\"\n class=\"w-full bg-zinc-900/50 border-none rounded-xl py-3 px-4 text-sm text-white outline-none focus:ring-0 transition-all\"\n />\n </div>\n </div>\n }\n\n @if (group.type === 'searchSelect') {\n <div class=\"px-6 py-4 bg-zinc-900/50\">\n <input\n type=\"text\"\n [value]=\"\n group.selectedSearchValue || ''\n \"\n (input)=\"\n onSearchChange(group.id, $event)\n \"\n [placeholder]=\"\n group.searchPlaceholder ||\n capitalize(t('SEARCH'))\n \"\n [attr.aria-label]=\"group.searchPlaceholder || capitalize(t('SEARCH'))\"\n class=\"w-full bg-zinc-900/50 border-none rounded-xl py-3 px-4 text-sm text-white outline-none focus:ring-0 transition-all\"\n />\n </div>\n }\n\n @if (group.type === 'dateRange') {\n <div\n class=\"px-6 py-4 space-y-4 bg-zinc-900/50\"\n >\n <div class=\"space-y-2\">\n <label\n class=\"text-[10px] font-bold text-zinc-500 uppercase tracking-widest pl-1\"\n >{{ t('FROM_DATE') }}</label\n >\n <input\n type=\"date\"\n [value]=\"group.dateFrom || ''\"\n (change)=\"\n onDateChange(\n group.id,\n 'from',\n $event\n )\n \"\n class=\"w-full bg-zinc-900/50 border-none rounded-xl py-3 px-4 text-sm text-white outline-none focus:ring-0 transition-all\"\n />\n </div>\n <div class=\"space-y-2\">\n <label\n class=\"text-[10px] font-bold text-zinc-500 uppercase tracking-widest pl-1\"\n >{{ t('TO_DATE') }}</label\n >\n <input\n type=\"date\"\n [value]=\"group.dateTo || ''\"\n (change)=\"\n onDateChange(\n group.id,\n 'to',\n $event\n )\n \"\n class=\"w-full bg-zinc-900/50 border-none rounded-xl py-3 px-4 text-sm text-white outline-none focus:ring-0 transition-all\"\n />\n </div>\n </div>\n }\n </div>\n </div>\n </div>\n </div>\n </div>\n </div>\n }\n </div>\n </section>\n </div>\n}\n", styles: [".overlay-fade-in{animation:fadeIn .25s ease-out forwards}.sheet-slide-up{will-change:transform;animation:slideUp .4s cubic-bezier(.32,.72,0,1) forwards}@keyframes fadeIn{0%{opacity:0}to{opacity:1}}@keyframes slideUp{0%{transform:translateY(100%)}to{transform:translateY(0)}}.no-scrollbar::-webkit-scrollbar{display:none}.no-scrollbar{-ms-overflow-style:none;scrollbar-width:none}.chevron{height:.5rem;width:.5rem;border-right-width:2px;border-bottom-width:2px;--tw-border-opacity: 1;border-color:rgb(82 82 91 / var(--tw-border-opacity, 1));transition:transform .4s cubic-bezier(.33,1,.68,1),border-color .3s ease;transform:rotate(45deg)}.chevron.open{transform:rotate(225deg) translateY(-1px) translate(-1px)}.filter-group-item:has(.collapsible-content.open){border-color:#3f3f4699;box-shadow:0 10px 30px -10px #00000080}.collapsible-content{display:grid;grid-template-rows:0fr;transition:grid-template-rows .4s cubic-bezier(.33,1,.68,1),opacity .3s ease,visibility .3s;visibility:hidden;opacity:0;overflow:hidden}.collapsible-content.open{grid-template-rows:1fr;visibility:visible;opacity:1}.collapsible-inner{min-height:0}.inner-panel{transform:scale(.98) translateY(-5px);transition:transform .4s cubic-bezier(.33,1,.68,1),opacity .4s ease;opacity:0}.collapsible-content.open .inner-panel{transform:scale(1) translateY(0);opacity:1}@media(hover:hover){.active\\:bg-zinc-800\\/50:hover{background-color:#3f3f464d}.active\\:bg-zinc-900\\/40:hover{background-color:#24242780}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$2.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$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: XSButtonComponent, selector: "xs-button", inputs: ["id", "label", "type", "icon", "action", "customClass", "variant", "layout", "badgeCount", "isFull", "disabled", "loading", "title", "ariaLabel", "borderRadius", "isGrouped", "groupPosition"], outputs: ["isGroupedChange", "groupPositionChange", "click", "onClick"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
13781
13768
|
}
|
|
13782
13769
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.33", ngImport: i0, type: XSFilterPanelComponent, decorators: [{
|
|
13783
13770
|
type: Component,
|
|
13784
|
-
args: [{ selector: 'xs-filter-panel', standalone: true, imports: [CommonModule, FormsModule, XSButtonComponent], changeDetection: ChangeDetectionStrategy.OnPush, template: "@if (!embedded() && _demoItems().length > 0) {\n <div\n class=\"p-4 mb-4 rounded-xl bg-zinc-900/50 flex justify-between items-center\"\n >\n <div>\n <p class=\"text-white font-bold text-sm\">\n {{ t('DEMO_TITLE') }}\n </p>\n <p class=\"text-zinc-500 text-xs\">\n {{ t('DEMO_DESCRIPTION') }}\n </p>\n </div>\n <xs-button\n (onClick)=\"show.set(true)\"\n [label]=\"t('OPEN_FILTERS')\"\n variant=\"custom\"\n customClass=\"px-4 py-2 bg-blue-600 text-white text-sm font-semibold rounded-xl active:scale-95\"\n />\n </div>\n}\n\n@if (show() || embedded()) {\n @if (show() && !embedded()) {\n <div\n class=\"fixed inset-0 z-[9000] bg-black/60 backdrop-blur-sm overlay-fade-in cursor-default\"\n (click)=\"handleClose()\"\n role=\"presentation\"\n ></div>\n <div class=\"fixed inset-0 z-[9000] flex items-end justify-center pointer-events-none\">\n <section\n role=\"dialog\"\n aria-modal=\"true\"\n [attr.aria-label]=\"t('FILTERS')\"\n tabindex=\"-1\"\n class=\"relative w-full max-w-md mx-auto overflow-hidden bg-black shadow-2xl rounded-t-[2.5rem] sheet-slide-up max-h-[85vh] flex flex-col cursor-auto pointer-events-auto outline-none\"\n (click)=\"$event.stopPropagation()\"\n (keydown)=\"$event.stopPropagation()\"\n >\n <div class=\"flex justify-center pt-4 pb-2\">\n <div class=\"w-12 h-1.5 bg-zinc-800 rounded-full\"></div>\n </div>\n\n <div class=\"px-6 py-2 flex justify-between items-center\">\n <h2\n class=\"text-xl font-bold text-white tracking-tight uppercase\"\n >\n {{ t('FILTERS') }}\n </h2>\n <div class=\"flex items-center gap-2\">\n @if (activeFiltersCount() > 0) {\n <xs-button\n (onClick)=\"clear.emit()\"\n [label]=\"capitalize(t('CLEAR'))\"\n layout=\"mini\"\n variant=\"custom\"\n customClass=\"text-zinc-400 hover:text-white text-sm font-medium p-2 uppercase\"\n />\n }\n <xs-button\n (onClick)=\"handleApply()\"\n [label]=\"t('DONE')\"\n layout=\"mini\"\n variant=\"custom\"\n customClass=\"text-zinc-400 hover:text-white text-sm font-medium p-2 uppercase\"\n />\n </div>\n </div>\n <ng-container *ngTemplateOutlet=\"groupsTpl\" />\n </section>\n </div>\n } @else if (embedded()) {\n <ng-container *ngTemplateOutlet=\"groupsTpl\" />\n }\n}\n\n<ng-template #groupsTpl>\n <div\n #scrollContainer\n [class.flex-1]=\"!embedded()\"\n [class.overflow-y-auto]=\"!embedded()\"\n [class.no-scrollbar]=\"!embedded()\"\n class=\"px-4 pt-4 pb-12 space-y-3\"\n >\n @for (group of filteredData(); track group.id) {\n <div\n [id]=\"'group-' + group.id\"\n class=\"overflow-hidden rounded-[2.5rem] bg-zinc-900/50 transition-all duration-300 filter-group-item border-none\"\n >\n <button\n (click)=\"toggleGroup(group.id)\"\n type=\"button\"\n [attr.aria-expanded]=\"activeGroupId() === group.id\"\n [attr.aria-controls]=\"'group-content-' + group.id\"\n class=\"w-full flex items-center justify-between px-6 py-4 transition-colors border-none\"\n [class]=\"\n activeGroupId() === group.id\n ? 'bg-zinc-900/50'\n : 'bg-transparent hover:bg-black/40 active:bg-black/20'\n \"\n >\n <div\n class=\"flex-1 flex flex-col text-left justify-center h-full\"\n >\n <span\n class=\"text-[10px] font-bold text-zinc-500 uppercase tracking-[0.15em] leading-none mb-2\"\n >\n {{ t(group.title) }}\n </span>\n <span\n class=\"text-base font-semibold leading-tight\"\n [class.text-white]=\"\n group.selectedId ||\n (group.type === 'dateRange' &&\n (group.dateFrom || group.dateTo))\n \"\n >\n {{\n getSelectedLabel(group) || t('NOT_SELECTED')\n }}\n </span>\n </div>\n <div class=\"flex items-center justify-center pl-4\">\n <div\n class=\"chevron opacity-40\"\n [class.open]=\"activeGroupId() === group.id\"\n ></div>\n </div>\n </button>\n\n <div\n [id]=\"'group-content-' + group.id\"\n class=\"collapsible-content\"\n [class.open]=\"activeGroupId() === group.id\"\n role=\"region\"\n [attr.aria-label]=\"t(group.title)\"\n >\n <div class=\"collapsible-inner\">\n <div class=\"px-2 pb-3 bg-zinc-900/50\">\n <div\n class=\"bg-zinc-900/50 rounded-[1.8rem] overflow-hidden inner-panel shadow-2xl border-none\"\n >\n @if (activeGroupType() !== 'searchSelect' && activeGroupType() !== 'dateRange') {\n <div class=\"p-3 bg-zinc-900/50\">\n <div class=\"relative\">\n <input\n type=\"text\"\n [ngModel]=\"searchQuery()\"\n (ngModelChange)=\"\n searchQuery.set($event)\n \"\n [placeholder]=\"capitalize(t('SEARCH')) + '...'\"\n [attr.aria-label]=\"capitalize(t('SEARCH'))\"\n class=\"w-full bg-zinc-900/50 rounded-xl py-3 pl-10 pr-4 text-sm text-white focus:ring-0 placeholder:text-zinc-500 transition-all outline-none border-none\"\n />\n <span\n class=\"absolute left-3 top-3 opacity-40 text-sm\"\n aria-hidden=\"true\"\n >\uD83D\uDD0D</span\n >\n </div>\n </div>\n }\n\n <div class=\"flex flex-col\">\n @if (\n group.type === 'select' ||\n group.type === undefined ||\n group.type === 'searchSelect'\n ) {\n @for (\n opt of group.options;\n track $index\n ) {\n <button\n (click)=\"\n onSelectOption(group.id, opt.id)\n \"\n type=\"button\"\n class=\"w-full flex items-center justify-between px-6 py-4 text-sm border-none bg-transparent transition-all hover:bg-zinc-900/50 active:bg-zinc-900/50 group/opt\"\n >\n <span\n class=\"transition-colors duration-200\"\n [class.text-white]=\"\n group.selectedId === opt.id\n \"\n [class.font-bold]=\"\n group.selectedId === opt.id\n \"\n [class.text-zinc-500]=\"\n group.selectedId !== opt.id\n \"\n >\n {{ capitalize(t(opt.label)) }}\n </span>\n <div\n class=\"flex items-center justify-center w-5 h-5\"\n >\n <div\n [class.opacity-0]=\"\n group.selectedId !== opt.id\n \"\n [class.opacity-100]=\"\n group.selectedId === opt.id\n \"\n class=\"w-2.5 h-2.5 rounded-full bg-red-500 transition-opacity duration-200\"\n ></div>\n </div>\n </button>\n }\n }\n\n @if (group.type === 'multiSelect') {\n @for (\n opt of group.options;\n track $index\n ) {\n <button\n (click)=\"\n onMultiSelectOption(\n group.id,\n opt.id\n )\n \"\n type=\"button\"\n class=\"w-full flex items-center justify-between px-6 py-4 text-sm border-none bg-transparent transition-all hover:bg-zinc-900/50 active:bg-zinc-900/50 group/opt\"\n >\n <span\n class=\"transition-colors duration-200\"\n [class.text-white]=\"\n group.selectedIds?.includes(\n opt.id\n )\n \"\n [class.font-bold]=\"\n group.selectedIds?.includes(\n opt.id\n )\n \"\n [class.text-zinc-500]=\"\n !group.selectedIds?.includes(\n opt.id\n )\n \"\n >\n {{ capitalize(t(opt.label)) }}\n </span>\n <div\n class=\"flex items-center justify-center w-5 h-5\"\n >\n <div\n [class.opacity-0]=\"\n !group.selectedIds?.includes(\n opt.id\n )\n \"\n [class.opacity-100]=\"\n group.selectedIds?.includes(\n opt.id\n )\n \"\n class=\"w-2.5 h-2.5 rounded-full bg-red-500 transition-opacity duration-200\"\n ></div>\n </div>\n </button>\n }\n }\n\n @if (group.type === 'boolean') {\n <button\n (click)=\"\n onBooleanToggle(group.id, true)\n \"\n type=\"button\"\n class=\"w-full flex items-center justify-between px-6 py-4 text-sm border-none bg-transparent transition-all hover:bg-zinc-900/50 active:bg-zinc-900/50\"\n >\n <span\n class=\"transition-colors duration-200\"\n [class.text-white]=\"\n group.selectedBoolean === true\n \"\n [class.font-bold]=\"\n group.selectedBoolean === true\n \"\n [class.text-zinc-500]=\"\n group.selectedBoolean !== true\n \"\n >{{ capitalize(t('YES')) }}</span\n >\n <div\n class=\"flex items-center justify-center w-5 h-5\"\n >\n <div\n [class.opacity-0]=\"\n group.selectedBoolean !== true\n \"\n [class.opacity-100]=\"\n group.selectedBoolean === true\n \"\n class=\"w-2.5 h-2.5 rounded-full bg-red-500 transition-opacity duration-200\"\n ></div>\n </div>\n </button>\n <button\n (click)=\"\n onBooleanToggle(group.id, false)\n \"\n type=\"button\"\n class=\"w-full flex items-center justify-between px-6 py-4 text-sm border-none bg-transparent transition-all hover:bg-zinc-900/50 active:bg-zinc-900/50\"\n >\n <span\n class=\"transition-colors duration-200\"\n [class.text-white]=\"\n group.selectedBoolean === false\n \"\n [class.font-bold]=\"\n group.selectedBoolean === false\n \"\n [class.text-zinc-500]=\"\n group.selectedBoolean !== false\n \"\n >{{ capitalize(t('NO')) }}</span\n >\n <div\n class=\"flex items-center justify-center w-5 h-5\"\n >\n <div\n [class.opacity-0]=\"\n group.selectedBoolean !== false\n \"\n [class.opacity-100]=\"\n group.selectedBoolean === false\n \"\n class=\"w-2.5 h-2.5 rounded-full bg-red-500 transition-opacity duration-200\"\n ></div>\n </div>\n </button>\n }\n\n @if (group.type === 'range') {\n <div\n class=\"px-6 py-4 space-y-4 bg-zinc-900/50\"\n >\n <div class=\"space-y-2\">\n <label\n class=\"text-[10px] font-bold text-zinc-500 uppercase tracking-widest pl-1\"\n >\n {{ t('MIN_VALUE') }}\n </label>\n <input\n type=\"number\"\n [value]=\"\n group.selectedMin ||\n group.minValue ||\n ''\n \"\n (input)=\"\n onRangeChange(\n group.id,\n 'min',\n $event\n )\n \"\n [min]=\"group.minValue\"\n [max]=\"group.maxValue\"\n class=\"w-full bg-zinc-900/50 border-none rounded-xl py-3 px-4 text-sm text-white outline-none focus:ring-0 transition-all\"\n />\n </div>\n <div class=\"space-y-2\">\n <label\n class=\"text-[10px] font-bold text-zinc-500 uppercase tracking-widest pl-1\"\n >\n {{ t('MAX_VALUE') }}\n </label>\n <input\n type=\"number\"\n [value]=\"\n group.selectedMax ||\n group.maxValue ||\n ''\n \"\n (input)=\"\n onRangeChange(\n group.id,\n 'max',\n $event\n )\n \"\n [min]=\"group.minValue\"\n [max]=\"group.maxValue\"\n class=\"w-full bg-zinc-900/50 border-none rounded-xl py-3 px-4 text-sm text-white outline-none focus:ring-0 transition-all\"\n />\n </div>\n </div>\n }\n\n @if (group.type === 'searchSelect') {\n <div class=\"px-6 py-4 bg-zinc-900/50\">\n <input\n type=\"text\"\n [value]=\"\n group.selectedSearchValue || ''\n \"\n (input)=\"\n onSearchChange(group.id, $event)\n \"\n [placeholder]=\"\n group.searchPlaceholder ||\n capitalize(t('SEARCH'))\n \"\n [attr.aria-label]=\"group.searchPlaceholder || capitalize(t('SEARCH'))\"\n class=\"w-full bg-zinc-900/50 border-none rounded-xl py-3 px-4 text-sm text-white outline-none focus:ring-0 transition-all\"\n />\n </div>\n }\n\n @if (group.type === 'dateRange') {\n <div\n class=\"px-6 py-4 space-y-4 bg-zinc-900/50\"\n >\n <div class=\"space-y-2\">\n <label\n class=\"text-[10px] font-bold text-zinc-500 uppercase tracking-widest pl-1\"\n >{{ t('FROM_DATE') }}</label\n >\n <input\n type=\"date\"\n [value]=\"group.dateFrom || ''\"\n (change)=\"\n onDateChange(\n group.id,\n 'from',\n $event\n )\n \"\n class=\"w-full bg-zinc-900/50 border-none rounded-xl py-3 px-4 text-sm text-white outline-none focus:ring-0 transition-all\"\n />\n </div>\n <div class=\"space-y-2\">\n <label\n class=\"text-[10px] font-bold text-zinc-500 uppercase tracking-widest pl-1\"\n >{{ t('TO_DATE') }}</label\n >\n <input\n type=\"date\"\n [value]=\"group.dateTo || ''\"\n (change)=\"\n onDateChange(\n group.id,\n 'to',\n $event\n )\n \"\n class=\"w-full bg-zinc-900/50 border-none rounded-xl py-3 px-4 text-sm text-white outline-none focus:ring-0 transition-all\"\n />\n </div>\n </div>\n }\n </div>\n </div>\n </div>\n </div>\n </div>\n </div>\n }\n </div>\n</ng-template>\n", styles: [".overlay-fade-in{animation:fadeIn .25s ease-out forwards}.sheet-slide-up{will-change:transform;animation:slideUp .4s cubic-bezier(.32,.72,0,1) forwards}@keyframes fadeIn{0%{opacity:0}to{opacity:1}}@keyframes slideUp{0%{transform:translateY(100%)}to{transform:translateY(0)}}.no-scrollbar::-webkit-scrollbar{display:none}.no-scrollbar{-ms-overflow-style:none;scrollbar-width:none}.chevron{height:.5rem;width:.5rem;border-right-width:2px;border-bottom-width:2px;--tw-border-opacity: 1;border-color:rgb(82 82 91 / var(--tw-border-opacity, 1));transition:transform .4s cubic-bezier(.33,1,.68,1),border-color .3s ease;transform:rotate(45deg)}.chevron.open{transform:rotate(225deg) translateY(-1px) translate(-1px)}.filter-group-item:has(.collapsible-content.open){border-color:#3f3f4699;box-shadow:0 10px 30px -10px #00000080}.collapsible-content{display:grid;grid-template-rows:0fr;transition:grid-template-rows .4s cubic-bezier(.33,1,.68,1),opacity .3s ease,visibility .3s;visibility:hidden;opacity:0;overflow:hidden}.collapsible-content.open{grid-template-rows:1fr;visibility:visible;opacity:1}.collapsible-inner{min-height:0}.inner-panel{transform:scale(.98) translateY(-5px);transition:transform .4s cubic-bezier(.33,1,.68,1),opacity .4s ease;opacity:0}.collapsible-content.open .inner-panel{transform:scale(1) translateY(0);opacity:1}@media(hover:hover){.active\\:bg-zinc-800\\/50:hover{background-color:#3f3f464d}.active\\:bg-zinc-900\\/40:hover{background-color:#24242780}}\n"] }]
|
|
13785
|
-
}], ctorParameters: () => [], propDecorators: { scrollContainer: [{ type: i0.ViewChild, args: ['scrollContainer', { isSignal: true }] }], show: [{ type: i0.Input, args: [{ isSignal: true, alias: "show", required: false }] }, { type: i0.Output, args: ["showChange"] }],
|
|
13771
|
+
args: [{ selector: 'xs-filter-panel', standalone: true, imports: [CommonModule, FormsModule, XSButtonComponent], changeDetection: ChangeDetectionStrategy.OnPush, template: "@if (_demoItems().length > 0) {\n <div\n class=\"p-4 mb-4 rounded-xl bg-zinc-900/50 flex justify-between items-center\"\n >\n <div>\n <p class=\"text-white font-bold text-sm\">\n {{ t('DEMO_TITLE') }}\n </p>\n <p class=\"text-zinc-500 text-xs\">\n {{ t('DEMO_DESCRIPTION') }}\n </p>\n </div>\n <xs-button\n (onClick)=\"show.set(true)\"\n [label]=\"t('OPEN_FILTERS')\"\n variant=\"custom\"\n customClass=\"px-4 py-2 bg-blue-600 text-white text-sm font-semibold rounded-xl active:scale-95\"\n />\n </div>\n}\n\n@if (show()) {\n <div\n class=\"fixed inset-0 z-[9000] bg-black/60 backdrop-blur-sm overlay-fade-in cursor-default\"\n (click)=\"handleClose()\"\n role=\"presentation\"\n ></div>\n <div class=\"fixed inset-0 z-[9000] flex items-end justify-center pointer-events-none\">\n <section\n role=\"dialog\"\n aria-modal=\"true\"\n [attr.aria-label]=\"t('FILTERS')\"\n tabindex=\"-1\"\n class=\"relative w-full max-w-md mx-auto overflow-hidden bg-black shadow-2xl rounded-t-[2.5rem] sheet-slide-up max-h-[85vh] flex flex-col cursor-auto pointer-events-auto outline-none\"\n (click)=\"$event.stopPropagation()\"\n (keydown)=\"$event.stopPropagation()\"\n >\n <div class=\"flex justify-center pt-4 pb-2\">\n <div class=\"w-12 h-1.5 bg-zinc-800 rounded-full\"></div>\n </div>\n\n <div class=\"px-6 py-2 flex justify-between items-center\">\n <h2\n class=\"text-xl font-bold text-white tracking-tight uppercase\"\n >\n {{ t('FILTERS') }}\n </h2>\n <div class=\"flex items-center gap-2\">\n @if (activeFiltersCount() > 0) {\n <xs-button\n (onClick)=\"clear.emit()\"\n [label]=\"capitalize(t('CLEAR'))\"\n layout=\"mini\"\n variant=\"custom\"\n customClass=\"text-zinc-400 hover:text-white text-sm font-medium p-2 uppercase\"\n />\n }\n <xs-button\n (onClick)=\"handleApply()\"\n [label]=\"t('DONE')\"\n layout=\"mini\"\n variant=\"custom\"\n customClass=\"text-zinc-400 hover:text-white text-sm font-medium p-2 uppercase\"\n />\n </div>\n </div>\n\n <div\n #scrollContainer\n class=\"flex-1 overflow-y-auto no-scrollbar px-4 pt-4 pb-12 space-y-3\"\n >\n @for (group of filteredData(); track group.id) {\n <div\n [id]=\"'group-' + group.id\"\n class=\"overflow-hidden rounded-[2.5rem] bg-zinc-900/50 transition-all duration-300 filter-group-item border-none\"\n >\n <button\n (click)=\"toggleGroup(group.id)\"\n type=\"button\"\n [attr.aria-expanded]=\"activeGroupId() === group.id\"\n [attr.aria-controls]=\"'group-content-' + group.id\"\n class=\"w-full flex items-center justify-between px-6 py-4 transition-colors border-none\"\n [class]=\"\n activeGroupId() === group.id\n ? 'bg-zinc-900/50'\n : 'bg-transparent hover:bg-black/40 active:bg-black/20'\n \"\n >\n <div\n class=\"flex-1 flex flex-col text-left justify-center h-full\"\n >\n <span\n class=\"text-[10px] font-bold text-zinc-500 uppercase tracking-[0.15em] leading-none mb-2\"\n >\n {{ t(group.title) }}\n </span>\n <span\n class=\"text-base font-semibold leading-tight\"\n [class.text-white]=\"\n group.selectedId ||\n (group.type === 'dateRange' &&\n (group.dateFrom || group.dateTo))\n \"\n >\n {{\n getSelectedLabel(group) || t('NOT_SELECTED')\n }}\n </span>\n </div>\n <div class=\"flex items-center justify-center pl-4\">\n <div\n class=\"chevron opacity-40\"\n [class.open]=\"activeGroupId() === group.id\"\n ></div>\n </div>\n </button>\n\n <div\n [id]=\"'group-content-' + group.id\"\n class=\"collapsible-content\"\n [class.open]=\"activeGroupId() === group.id\"\n role=\"region\"\n [attr.aria-label]=\"t(group.title)\"\n >\n <div class=\"collapsible-inner\">\n <div class=\"px-2 pb-3 bg-zinc-900/50\">\n <div\n class=\"bg-zinc-900/50 rounded-[1.8rem] overflow-hidden inner-panel shadow-2xl border-none\"\n >\n @if (activeGroupType() !== 'searchSelect' && activeGroupType() !== 'dateRange') {\n <div class=\"p-3 bg-zinc-900/50\">\n <div class=\"relative\">\n <input\n type=\"text\"\n [ngModel]=\"searchQuery()\"\n (ngModelChange)=\"\n searchQuery.set($event)\n \"\n [placeholder]=\"capitalize(t('SEARCH')) + '...'\"\n [attr.aria-label]=\"capitalize(t('SEARCH'))\"\n class=\"w-full bg-zinc-900/50 rounded-xl py-3 pl-10 pr-4 text-sm text-white focus:ring-0 placeholder:text-zinc-500 transition-all outline-none border-none\"\n />\n <span\n class=\"absolute left-3 top-3 opacity-40 text-sm\"\n aria-hidden=\"true\"\n >\uD83D\uDD0D</span\n >\n </div>\n </div>\n }\n\n <div class=\"flex flex-col\">\n @if (\n group.type === 'select' ||\n group.type === undefined ||\n group.type === 'searchSelect'\n ) {\n @for (\n opt of group.options;\n track $index\n ) {\n <button\n (click)=\"\n onSelectOption(group.id, opt.id)\n \"\n type=\"button\"\n class=\"w-full flex items-center justify-between px-6 py-4 text-sm border-none bg-transparent transition-all hover:bg-zinc-900/50 active:bg-zinc-900/50 group/opt\"\n >\n <span\n class=\"transition-colors duration-200\"\n [class.text-white]=\"\n group.selectedId === opt.id\n \"\n [class.font-bold]=\"\n group.selectedId === opt.id\n \"\n [class.text-zinc-500]=\"\n group.selectedId !== opt.id\n \"\n >\n {{ capitalize(t(opt.label)) }}\n </span>\n <div\n class=\"flex items-center justify-center w-5 h-5\"\n >\n <div\n [class.opacity-0]=\"\n group.selectedId !== opt.id\n \"\n [class.opacity-100]=\"\n group.selectedId === opt.id\n \"\n class=\"w-2.5 h-2.5 rounded-full bg-red-500 transition-opacity duration-200\"\n ></div>\n </div>\n </button>\n }\n }\n\n @if (group.type === 'multiSelect') {\n @for (\n opt of group.options;\n track $index\n ) {\n <button\n (click)=\"\n onMultiSelectOption(\n group.id,\n opt.id\n )\n \"\n type=\"button\"\n class=\"w-full flex items-center justify-between px-6 py-4 text-sm border-none bg-transparent transition-all hover:bg-zinc-900/50 active:bg-zinc-900/50 group/opt\"\n >\n <span\n class=\"transition-colors duration-200\"\n [class.text-white]=\"\n group.selectedIds?.includes(\n opt.id\n )\n \"\n [class.font-bold]=\"\n group.selectedIds?.includes(\n opt.id\n )\n \"\n [class.text-zinc-500]=\"\n !group.selectedIds?.includes(\n opt.id\n )\n \"\n >\n {{ capitalize(t(opt.label)) }}\n </span>\n <div\n class=\"flex items-center justify-center w-5 h-5\"\n >\n <div\n [class.opacity-0]=\"\n !group.selectedIds?.includes(\n opt.id\n )\n \"\n [class.opacity-100]=\"\n group.selectedIds?.includes(\n opt.id\n )\n \"\n class=\"w-2.5 h-2.5 rounded-full bg-red-500 transition-opacity duration-200\"\n ></div>\n </div>\n </button>\n }\n }\n\n @if (group.type === 'boolean') {\n <button\n (click)=\"\n onBooleanToggle(group.id, true)\n \"\n type=\"button\"\n class=\"w-full flex items-center justify-between px-6 py-4 text-sm border-none bg-transparent transition-all hover:bg-zinc-900/50 active:bg-zinc-900/50\"\n >\n <span\n class=\"transition-colors duration-200\"\n [class.text-white]=\"\n group.selectedBoolean === true\n \"\n [class.font-bold]=\"\n group.selectedBoolean === true\n \"\n [class.text-zinc-500]=\"\n group.selectedBoolean !== true\n \"\n >{{ capitalize(t('YES')) }}</span\n >\n <div\n class=\"flex items-center justify-center w-5 h-5\"\n >\n <div\n [class.opacity-0]=\"\n group.selectedBoolean !== true\n \"\n [class.opacity-100]=\"\n group.selectedBoolean === true\n \"\n class=\"w-2.5 h-2.5 rounded-full bg-red-500 transition-opacity duration-200\"\n ></div>\n </div>\n </button>\n <button\n (click)=\"\n onBooleanToggle(group.id, false)\n \"\n type=\"button\"\n class=\"w-full flex items-center justify-between px-6 py-4 text-sm border-none bg-transparent transition-all hover:bg-zinc-900/50 active:bg-zinc-900/50\"\n >\n <span\n class=\"transition-colors duration-200\"\n [class.text-white]=\"\n group.selectedBoolean === false\n \"\n [class.font-bold]=\"\n group.selectedBoolean === false\n \"\n [class.text-zinc-500]=\"\n group.selectedBoolean !== false\n \"\n >{{ capitalize(t('NO')) }}</span\n >\n <div\n class=\"flex items-center justify-center w-5 h-5\"\n >\n <div\n [class.opacity-0]=\"\n group.selectedBoolean !== false\n \"\n [class.opacity-100]=\"\n group.selectedBoolean === false\n \"\n class=\"w-2.5 h-2.5 rounded-full bg-red-500 transition-opacity duration-200\"\n ></div>\n </div>\n </button>\n }\n\n @if (group.type === 'range') {\n <div\n class=\"px-6 py-4 space-y-4 bg-zinc-900/50\"\n >\n <div class=\"space-y-2\">\n <label\n class=\"text-[10px] font-bold text-zinc-500 uppercase tracking-widest pl-1\"\n >\n {{ t('MIN_VALUE') }}\n </label>\n <input\n type=\"number\"\n [value]=\"\n group.selectedMin ||\n group.minValue ||\n ''\n \"\n (input)=\"\n onRangeChange(\n group.id,\n 'min',\n $event\n )\n \"\n [min]=\"group.minValue\"\n [max]=\"group.maxValue\"\n class=\"w-full bg-zinc-900/50 border-none rounded-xl py-3 px-4 text-sm text-white outline-none focus:ring-0 transition-all\"\n />\n </div>\n <div class=\"space-y-2\">\n <label\n class=\"text-[10px] font-bold text-zinc-500 uppercase tracking-widest pl-1\"\n >\n {{ t('MAX_VALUE') }}\n </label>\n <input\n type=\"number\"\n [value]=\"\n group.selectedMax ||\n group.maxValue ||\n ''\n \"\n (input)=\"\n onRangeChange(\n group.id,\n 'max',\n $event\n )\n \"\n [min]=\"group.minValue\"\n [max]=\"group.maxValue\"\n class=\"w-full bg-zinc-900/50 border-none rounded-xl py-3 px-4 text-sm text-white outline-none focus:ring-0 transition-all\"\n />\n </div>\n </div>\n }\n\n @if (group.type === 'searchSelect') {\n <div class=\"px-6 py-4 bg-zinc-900/50\">\n <input\n type=\"text\"\n [value]=\"\n group.selectedSearchValue || ''\n \"\n (input)=\"\n onSearchChange(group.id, $event)\n \"\n [placeholder]=\"\n group.searchPlaceholder ||\n capitalize(t('SEARCH'))\n \"\n [attr.aria-label]=\"group.searchPlaceholder || capitalize(t('SEARCH'))\"\n class=\"w-full bg-zinc-900/50 border-none rounded-xl py-3 px-4 text-sm text-white outline-none focus:ring-0 transition-all\"\n />\n </div>\n }\n\n @if (group.type === 'dateRange') {\n <div\n class=\"px-6 py-4 space-y-4 bg-zinc-900/50\"\n >\n <div class=\"space-y-2\">\n <label\n class=\"text-[10px] font-bold text-zinc-500 uppercase tracking-widest pl-1\"\n >{{ t('FROM_DATE') }}</label\n >\n <input\n type=\"date\"\n [value]=\"group.dateFrom || ''\"\n (change)=\"\n onDateChange(\n group.id,\n 'from',\n $event\n )\n \"\n class=\"w-full bg-zinc-900/50 border-none rounded-xl py-3 px-4 text-sm text-white outline-none focus:ring-0 transition-all\"\n />\n </div>\n <div class=\"space-y-2\">\n <label\n class=\"text-[10px] font-bold text-zinc-500 uppercase tracking-widest pl-1\"\n >{{ t('TO_DATE') }}</label\n >\n <input\n type=\"date\"\n [value]=\"group.dateTo || ''\"\n (change)=\"\n onDateChange(\n group.id,\n 'to',\n $event\n )\n \"\n class=\"w-full bg-zinc-900/50 border-none rounded-xl py-3 px-4 text-sm text-white outline-none focus:ring-0 transition-all\"\n />\n </div>\n </div>\n }\n </div>\n </div>\n </div>\n </div>\n </div>\n </div>\n }\n </div>\n </section>\n </div>\n}\n", styles: [".overlay-fade-in{animation:fadeIn .25s ease-out forwards}.sheet-slide-up{will-change:transform;animation:slideUp .4s cubic-bezier(.32,.72,0,1) forwards}@keyframes fadeIn{0%{opacity:0}to{opacity:1}}@keyframes slideUp{0%{transform:translateY(100%)}to{transform:translateY(0)}}.no-scrollbar::-webkit-scrollbar{display:none}.no-scrollbar{-ms-overflow-style:none;scrollbar-width:none}.chevron{height:.5rem;width:.5rem;border-right-width:2px;border-bottom-width:2px;--tw-border-opacity: 1;border-color:rgb(82 82 91 / var(--tw-border-opacity, 1));transition:transform .4s cubic-bezier(.33,1,.68,1),border-color .3s ease;transform:rotate(45deg)}.chevron.open{transform:rotate(225deg) translateY(-1px) translate(-1px)}.filter-group-item:has(.collapsible-content.open){border-color:#3f3f4699;box-shadow:0 10px 30px -10px #00000080}.collapsible-content{display:grid;grid-template-rows:0fr;transition:grid-template-rows .4s cubic-bezier(.33,1,.68,1),opacity .3s ease,visibility .3s;visibility:hidden;opacity:0;overflow:hidden}.collapsible-content.open{grid-template-rows:1fr;visibility:visible;opacity:1}.collapsible-inner{min-height:0}.inner-panel{transform:scale(.98) translateY(-5px);transition:transform .4s cubic-bezier(.33,1,.68,1),opacity .4s ease;opacity:0}.collapsible-content.open .inner-panel{transform:scale(1) translateY(0);opacity:1}@media(hover:hover){.active\\:bg-zinc-800\\/50:hover{background-color:#3f3f464d}.active\\:bg-zinc-900\\/40:hover{background-color:#24242780}}\n"] }]
|
|
13772
|
+
}], ctorParameters: () => [], propDecorators: { scrollContainer: [{ type: i0.ViewChild, args: ['scrollContainer', { isSignal: true }] }], show: [{ type: i0.Input, args: [{ isSignal: true, alias: "show", required: false }] }, { type: i0.Output, args: ["showChange"] }], externalTranslateService: [{ type: i0.Input, args: [{ isSignal: true, alias: "externalTranslateService", required: false }] }], demoItems: [{ type: i0.Input, args: [{ isSignal: true, alias: "demoItems", required: false }] }], data: [{ type: i0.Input, args: [{ isSignal: true, alias: "data", required: false }] }], activeFiltersCount: [{ type: i0.Input, args: [{ isSignal: true, alias: "activeFiltersCount", required: false }] }], panelClose: [{ type: i0.Output, args: ["panelClose"] }], applied: [{ type: i0.Output, args: ["applied"] }], filterChange: [{ type: i0.Output, args: ["filterChange"] }], clear: [{ type: i0.Output, args: ["clear"] }] } });
|
|
13786
13773
|
|
|
13787
13774
|
var MENU_LABEL$1 = "Menú";
|
|
13788
13775
|
var es$d = {
|
|
@@ -15792,12 +15779,22 @@ class XSButtonsGroupComponent {
|
|
|
15792
15779
|
return button.icon ?? null;
|
|
15793
15780
|
}
|
|
15794
15781
|
getButtonVariant(button) {
|
|
15795
|
-
|
|
15782
|
+
if (button.variant)
|
|
15783
|
+
return button.variant;
|
|
15784
|
+
if (button.selected)
|
|
15785
|
+
return 'tertiary';
|
|
15786
|
+
return 'primary';
|
|
15796
15787
|
}
|
|
15797
15788
|
getButtonLayout(button) {
|
|
15798
|
-
|
|
15789
|
+
if (button.layout)
|
|
15790
|
+
return button.layout;
|
|
15791
|
+
if (button.icon && !button.label)
|
|
15792
|
+
return 'iconOnly';
|
|
15793
|
+
return 'base';
|
|
15799
15794
|
}
|
|
15800
15795
|
onButtonClick(button, index) {
|
|
15796
|
+
if (button.selected || button.disabled)
|
|
15797
|
+
return;
|
|
15801
15798
|
const callback = this.buttonClick();
|
|
15802
15799
|
if (callback) {
|
|
15803
15800
|
callback(button, index);
|
|
@@ -15815,29 +15812,13 @@ class XSButtonsGroupComponent {
|
|
|
15815
15812
|
else {
|
|
15816
15813
|
button.groupPosition.set('middle');
|
|
15817
15814
|
}
|
|
15818
|
-
const buttonElement = button.elementRef
|
|
15819
|
-
.nativeElement;
|
|
15820
|
-
buttonElement.classList.add('button-grouped');
|
|
15821
|
-
buttonElement.classList.remove('border-l', 'border-zinc-700');
|
|
15822
|
-
if (index > 0) {
|
|
15823
|
-
buttonElement.classList.add('border-l', 'border-zinc-700');
|
|
15824
|
-
}
|
|
15825
|
-
if (index === 0) {
|
|
15826
|
-
buttonElement.style.borderRadius = '0.5rem 0 0 0.5rem';
|
|
15827
|
-
}
|
|
15828
|
-
else if (index === totalButtons - 1) {
|
|
15829
|
-
buttonElement.style.borderRadius = '0 0.5rem 0.5rem 0';
|
|
15830
|
-
}
|
|
15831
|
-
else {
|
|
15832
|
-
buttonElement.style.borderRadius = '0';
|
|
15833
|
-
}
|
|
15834
15815
|
}
|
|
15835
15816
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.33", ngImport: i0, type: XSButtonsGroupComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
15836
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.33", type: XSButtonsGroupComponent, isStandalone: true, selector: "xs-buttons-group", inputs: { buttonsInput: { classPropertyName: "buttonsInput", publicName: "buttonsInput", isSignal: true, isRequired: false, transformFunction: null }, buttonClick: { classPropertyName: "buttonClick", publicName: "buttonClick", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { buttonClickOutput: "buttonClickOutput" }, host: { attributes: { "xs-buttons-group-host": "" } }, queries: [{ propertyName: "contentButtons", predicate: XSButtonComponent, isSignal: true }], viewQueries: [{ propertyName: "viewButtons", predicate: XSButtonComponent, descendants: true, isSignal: true }], ngImport: i0, template: "<div class=\"inline-flex w-full\">\n @for (\n button of buttonsInput();\n track $index\n ) {\n <xs-button\n [label]=\"button.label || ''\"\n [icon]=\"getButtonIcon(button)\"\n [variant]=\"getButtonVariant(button)\"\n [layout]=\"getButtonLayout(button)\"\n [disabled]=\"button.disabled || false\"\n [loading]=\"button.loading || false\"\n [customClass]=\"button.customClass || ''\"\n (click)=\"onButtonClick(button, $index)\"\n (keydown.enter)=\"onButtonClick(button, $index)\"\n ></xs-button>\n }\n\n @if (buttonsInput().length === 0) {\n <ng-content></ng-content>\n }\n</div>\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: XSButtonComponent, selector: "xs-button", inputs: ["id", "label", "type", "icon", "action", "customClass", "variant", "layout", "badgeCount", "isFull", "disabled", "loading", "title", "ariaLabel", "borderRadius", "isGrouped", "groupPosition"], outputs: ["isGroupedChange", "groupPositionChange", "click", "onClick"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
15817
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.33", type: XSButtonsGroupComponent, isStandalone: true, selector: "xs-buttons-group", inputs: { buttonsInput: { classPropertyName: "buttonsInput", publicName: "buttonsInput", isSignal: true, isRequired: false, transformFunction: null }, buttonClick: { classPropertyName: "buttonClick", publicName: "buttonClick", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { buttonClickOutput: "buttonClickOutput" }, host: { attributes: { "xs-buttons-group-host": "" } }, queries: [{ propertyName: "contentButtons", predicate: XSButtonComponent, isSignal: true }], viewQueries: [{ propertyName: "viewButtons", predicate: XSButtonComponent, descendants: true, isSignal: true }], ngImport: i0, template: "<div class=\"inline-flex w-full gap-1\">\n @for (\n button of buttonsInput();\n track $index\n ) {\n <xs-button\n [label]=\"button.label || ''\"\n [icon]=\"getButtonIcon(button)\"\n [variant]=\"getButtonVariant(button)\"\n [layout]=\"getButtonLayout(button)\"\n [disabled]=\"button.disabled || false\"\n [loading]=\"button.loading || false\"\n [customClass]=\"button.customClass || ''\"\n (click)=\"onButtonClick(button, $index)\"\n (keydown.enter)=\"onButtonClick(button, $index)\"\n ></xs-button>\n }\n\n @if (buttonsInput().length === 0) {\n <ng-content></ng-content>\n }\n</div>\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: XSButtonComponent, selector: "xs-button", inputs: ["id", "label", "type", "icon", "action", "customClass", "variant", "layout", "badgeCount", "isFull", "disabled", "loading", "title", "ariaLabel", "borderRadius", "isGrouped", "groupPosition"], outputs: ["isGroupedChange", "groupPositionChange", "click", "onClick"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
15837
15818
|
}
|
|
15838
15819
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.33", ngImport: i0, type: XSButtonsGroupComponent, decorators: [{
|
|
15839
15820
|
type: Component,
|
|
15840
|
-
args: [{ selector: 'xs-buttons-group', standalone: true, imports: [CommonModule, XSButtonComponent], host: { 'xs-buttons-group-host': '' }, changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"inline-flex w-full\">\n @for (\n button of buttonsInput();\n track $index\n ) {\n <xs-button\n [label]=\"button.label || ''\"\n [icon]=\"getButtonIcon(button)\"\n [variant]=\"getButtonVariant(button)\"\n [layout]=\"getButtonLayout(button)\"\n [disabled]=\"button.disabled || false\"\n [loading]=\"button.loading || false\"\n [customClass]=\"button.customClass || ''\"\n (click)=\"onButtonClick(button, $index)\"\n (keydown.enter)=\"onButtonClick(button, $index)\"\n ></xs-button>\n }\n\n @if (buttonsInput().length === 0) {\n <ng-content></ng-content>\n }\n</div>\n" }]
|
|
15821
|
+
args: [{ selector: 'xs-buttons-group', standalone: true, imports: [CommonModule, XSButtonComponent], host: { 'xs-buttons-group-host': '' }, changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"inline-flex w-full gap-1\">\n @for (\n button of buttonsInput();\n track $index\n ) {\n <xs-button\n [label]=\"button.label || ''\"\n [icon]=\"getButtonIcon(button)\"\n [variant]=\"getButtonVariant(button)\"\n [layout]=\"getButtonLayout(button)\"\n [disabled]=\"button.disabled || false\"\n [loading]=\"button.loading || false\"\n [customClass]=\"button.customClass || ''\"\n (click)=\"onButtonClick(button, $index)\"\n (keydown.enter)=\"onButtonClick(button, $index)\"\n ></xs-button>\n }\n\n @if (buttonsInput().length === 0) {\n <ng-content></ng-content>\n }\n</div>\n" }]
|
|
15841
15822
|
}], ctorParameters: () => [], propDecorators: { buttonsInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "buttonsInput", required: false }] }], buttonClick: [{ type: i0.Input, args: [{ isSignal: true, alias: "buttonClick", required: false }] }], buttonClickOutput: [{ type: i0.Output, args: ["buttonClickOutput"] }], contentButtons: [{ type: i0.ContentChildren, args: [i0.forwardRef(() => XSButtonComponent), { isSignal: true }] }], viewButtons: [{ type: i0.ViewChildren, args: [i0.forwardRef(() => XSButtonComponent), { isSignal: true }] }] } });
|
|
15842
15823
|
|
|
15843
15824
|
class XSButtonGroupService {
|
|
@@ -23233,7 +23214,7 @@ const LIB_STORIES = [
|
|
|
23233
23214
|
() => import('./xsmusices-ui-xs-action-sheet.xsstory-CBpZBlfx.mjs').then((m) => m.story),
|
|
23234
23215
|
() => import('./xsmusices-ui-xs-block.xsstory-GXV6UFJo.mjs').then((m) => m.story),
|
|
23235
23216
|
() => import('./xsmusices-ui-xs-button.xsstory-DqECZuZF.mjs').then((m) => m.story),
|
|
23236
|
-
() => import('./xsmusices-ui-xs-buttons-group.xsstory-
|
|
23217
|
+
() => import('./xsmusices-ui-xs-buttons-group.xsstory-Cgmflzcs.mjs').then((m) => m.story),
|
|
23237
23218
|
() => import('./xsmusices-ui-xs-chart.xsstory--iUHj7bv.mjs').then((m) => m.story),
|
|
23238
23219
|
() => import('./xsmusices-ui-xs-formly.xsstory-Bjne7mpZ.mjs').then((m) => m.story),
|
|
23239
23220
|
() => import('./xsmusices-ui-xs-empty-state.xsstory-CCOJ4b9_.mjs').then((m) => m.story),
|