@oneteme/jquery-organizer 0.0.2 → 0.0.3

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.
@@ -83,32 +83,22 @@ function resolveMatchingTemplateId(templates, state, config) {
83
83
  return sameOrganizerState(templateState, normalizedState);
84
84
  })?.id;
85
85
  }
86
- function normalizeTemplateToComparableState(template, baseState, config) {
87
- const normalizedY = normalizeYSelection(template.yField, template.yAggregate, config.yFields, baseState);
86
+ function normalizeStateCore(selectedX, selectedY, selectedYAggregate, selectedGroupBy, selectedSlices, config, originalState) {
87
+ const normalizedY = normalizeYSelection(selectedY, selectedYAggregate, config.yFields, originalState);
88
88
  return {
89
- ...baseState,
90
- selectedX: hasOption(config.xFields, template.xField) ? template.xField : baseState.selectedX,
89
+ selectedX: hasOption(config.xFields, selectedX) ? selectedX : undefined,
91
90
  selectedY: normalizedY.selectedY,
92
91
  selectedYAggregate: normalizedY.selectedYAggregate,
93
- selectedGroupBy: hasOption(config.groups, template.groupBy) ? template.groupBy : baseState.selectedGroupBy,
94
- selectedSlices: template.selectedSlices
95
- ? template.selectedSlices.filter(sliceId => hasOption(config.slices, sliceId))
96
- : (baseState.selectedSlices || []),
97
- selectedTemplate: undefined,
92
+ selectedGroupBy: hasOption(config.groups, selectedGroupBy) ? selectedGroupBy : undefined,
93
+ selectedSlices: (selectedSlices || []).filter(sliceId => hasOption(config.slices, sliceId)),
98
94
  };
99
95
  }
96
+ function normalizeTemplateToComparableState(template, baseState, config) {
97
+ return normalizeStateCore(template.xField, template.yField, template.yAggregate, template.groupBy, template.selectedSlices, config, baseState);
98
+ }
100
99
  function normalizeStateWithoutTemplate(state, config) {
101
100
  const base = state || {};
102
- const normalizedY = normalizeYSelection(base.selectedY, base.selectedYAggregate, config.yFields);
103
- return {
104
- ...base,
105
- selectedX: hasOption(config.xFields, base.selectedX) ? base.selectedX : undefined,
106
- selectedY: normalizedY.selectedY,
107
- selectedYAggregate: normalizedY.selectedYAggregate,
108
- selectedGroupBy: hasOption(config.groups, base.selectedGroupBy) ? base.selectedGroupBy : undefined,
109
- selectedSlices: (base.selectedSlices || []).filter(sliceId => hasOption(config.slices, sliceId)),
110
- selectedTemplate: undefined,
111
- };
101
+ return normalizeStateCore(base.selectedX, base.selectedY, base.selectedYAggregate, base.selectedGroupBy, base.selectedSlices, config, base);
112
102
  }
113
103
  function normalizeYSelection(selectedY, selectedYAggregate, yFields, fallbackState) {
114
104
  if (!selectedY) {
@@ -179,7 +169,13 @@ class OrganizerButtonComponent {
179
169
  this.fieldDataCache = new Map();
180
170
  this.destroy$ = new Subject();
181
171
  }
182
- ngOnInit() { }
172
+ ngOnInit() {
173
+ console.debug('[OrganizerButton] Initialized', {
174
+ configFields: this.config?.fields?.length ?? 0,
175
+ hasState: !!this.state,
176
+ hideMenuValues: this.hideMenuValues
177
+ });
178
+ }
183
179
  ngOnDestroy() {
184
180
  this.destroy$.next();
185
181
  this.destroy$.complete();
@@ -197,6 +193,7 @@ class OrganizerButtonComponent {
197
193
  return `${visible}/${total}`;
198
194
  }
199
195
  onFieldToggle(fieldId, visible) {
196
+ console.debug('[OrganizerButton] Field toggled', { fieldId, visible });
200
197
  const visibleFields = this.state?.visibleFields || [];
201
198
  const updated = visible
202
199
  ? [...visibleFields, fieldId]
@@ -204,25 +201,45 @@ class OrganizerButtonComponent {
204
201
  this.emitChange('fieldToggled', { visibleFields: updated });
205
202
  }
206
203
  onXFieldSelect(fieldId) {
204
+ console.debug('[OrganizerButton] X field selected', { fieldId, current: this.state?.selectedX });
205
+ // Évite une requête inutile si le X est déjà sélectionné
206
+ if (this.state?.selectedX === fieldId) {
207
+ console.debug('[OrganizerButton] X field already selected, skipping emit');
208
+ return;
209
+ }
207
210
  this.emitChange('xSelected', { selectedX: fieldId });
208
211
  }
209
212
  onYFieldSelect(fieldId) {
213
+ console.debug('[OrganizerButton] Y field selected', { fieldId, current: this.state?.selectedY });
214
+ // Évite une requête inutile si le Y est déjà sélectionné
215
+ if (this.state?.selectedY === fieldId) {
216
+ console.debug('[OrganizerButton] Y field already selected, skipping emit');
217
+ return;
218
+ }
210
219
  this.emitChange('ySelected', {
211
220
  selectedY: fieldId,
212
221
  selectedYAggregate: undefined
213
222
  });
214
223
  }
215
224
  onYAggregateSelect(yFieldId, aggregateId) {
225
+ console.debug('[OrganizerButton] Y aggregate selected', { yFieldId, aggregateId, current: this.state?.selectedYAggregate });
226
+ // Évite une requête inutile si l'aggregate est déjà sélectionné
227
+ if (this.state?.selectedYAggregate === aggregateId && this.state?.selectedY === yFieldId) {
228
+ console.debug('[OrganizerButton] Y aggregate already selected, skipping emit');
229
+ return;
230
+ }
216
231
  this.emitChange('ySelected', {
217
232
  selectedY: yFieldId,
218
233
  selectedYAggregate: aggregateId
219
234
  });
220
235
  }
221
236
  onGroupBySelect(groupId) {
237
+ console.debug('[OrganizerButton] Group by selected', { groupId });
222
238
  const current = this.state.selectedGroupBy;
223
239
  this.emitChange('groupBySelected', { selectedGroupBy: current === groupId ? undefined : groupId });
224
240
  }
225
241
  onTemplateSelect(templateId) {
242
+ console.debug('[OrganizerButton] Template selected', { templateId });
226
243
  if (!this.config.templates?.length)
227
244
  return;
228
245
  const template = this.config.templates?.find(t => t.id === templateId);
@@ -233,6 +250,7 @@ class OrganizerButtonComponent {
233
250
  this.syncSliceState(newState.selectedSlices);
234
251
  }
235
252
  onSliceClick(sliceId) {
253
+ console.debug('[OrganizerButton] Slice clicked', { sliceId });
236
254
  if (this.config.onSliceClick) {
237
255
  this.config.onSliceClick();
238
256
  }
@@ -270,7 +288,8 @@ class OrganizerButtonComponent {
270
288
  const handleData = (tasks) => {
271
289
  this.sliceStateChange.emit({
272
290
  sliceConfigs: [{ title: slice.label ?? sliceId, columnKey: sliceId }],
273
- tasks
291
+ tasks,
292
+ filterApplied: false // Panel vient d'être ouvert, pas de filtre sélectionné encore
274
293
  });
275
294
  onLoaded?.();
276
295
  };
@@ -848,11 +867,11 @@ class SlicePanelComponent {
848
867
  }, 50);
849
868
  }
850
869
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: SlicePanelComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
851
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: SlicePanelComponent, isStandalone: true, selector: "slice-panel", inputs: { sliceConfigs: "sliceConfigs", columns: "columns", data: "data", lazyData: "lazyData", lazyStatus: "lazyStatus", showToggle: "showToggle", showCounts: "showCounts", collapsedByDefault: "collapsedByDefault", alwaysShow: "alwaysShow" }, outputs: { filterChange: "filterChange", activeKeysChange: "activeKeysChange", dynamicSliceKeysChange: "dynamicSliceKeysChange", collapsedChange: "collapsedChange" }, host: { properties: { "class.collapsed": "this.hostCollapsed" } }, viewQueries: [{ propertyName: "slicePanelBodyRef", first: true, predicate: ["slicePanelBody"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div class=\"slice-panel-wrapper\" [class.collapsed]=\"isCollapsed\">\n <aside class=\"slice-panel\" [class.collapsed]=\"isCollapsed\">\n <div class=\"slice-panel-header\">\n <span *ngIf=\"!isCollapsed\" class=\"slice-panel-title\">\n {{ i18n.filterPanelTitle(slices.length) }}\n </span>\n <button\n *ngIf=\"showToggle\"\n type=\"button\"\n class=\"slice-toggle\"\n [attr.aria-label]=\"isCollapsed ? i18n.expandFilterTitle : i18n.collapseFilterTitle\"\n (click)=\"togglePanel()\"\n >\n <mat-icon class=\"slice-toggle-mat-icon\">{{ isCollapsed ? 'filter_list' : 'filter_list_off' }}</mat-icon>\n </button>\n </div>\n\n <div class=\"slice-panel-body\" *ngIf=\"!isCollapsed\" #slicePanelBody>\n <ng-container *ngFor=\"let slice of slices; let si = index; trackBy: trackBySliceIndex\">\n <div class=\"slice-title-row\" [attr.data-slice-index]=\"si\" (click)=\"toggleSliceCollapse(si)\">\n <span class=\"slice-title-chevron\" [class.expanded]=\"!isSliceCollapsed(si)\">\u203A</span>\n <mat-icon *ngIf=\"getSliceIcon(slice)\" class=\"slice-title-icon\">{{ getSliceIcon(slice) }}</mat-icon>\n <p class=\"slice-title\">{{ slice.title || i18n.filterBlockDefaultTitle }}</p>\n <button\n *ngIf=\"isSliceDynamic(si)\"\n type=\"button\"\n class=\"slice-remove-btn\"\n (click)=\"$event.stopPropagation(); removeDynamicSlice(si)\"\n >\u00D7</button>\n </div>\n\n <div class=\"slice-section-items\" *ngIf=\"!isSliceCollapsed(si)\">\n <ng-container *ngIf=\"isSliceLoading(si); else sliceContent\">\n <div class=\"slice-lazy-loading\">\n <span class=\"lazy-skeleton\"></span>\n <span class=\"lazy-skeleton\"></span>\n <span class=\"lazy-skeleton\"></span>\n </div>\n </ng-container>\n <ng-template #sliceContent>\n <ng-container *ngFor=\"let category of slice.categories; trackBy: trackByCategoryKey\">\n <button\n *ngIf=\"sliceCategoryCount(si, category.key) > 0\"\n class=\"slice-item\"\n type=\"button\"\n [class.active]=\"isSliceCategoryActive(si, category.key)\"\n [attr.data-category-key]=\"category.key\"\n [title]=\"category.label\"\n (click)=\"onSliceCategorySelected(si, category.key)\"\n >\n <span>{{ category.label }}</span>\n <span *ngIf=\"showCounts\">{{ sliceCategoryCount(si, category.key) }}</span>\n </button>\n </ng-container>\n <div *ngIf=\"isSliceEmpty(si)\" class=\"slice-empty-state\">{{ i18n.filterEmptyState }}</div>\n </ng-template>\n </div>\n\n <hr *ngIf=\"si < slices.length - 1\" class=\"slice-divider\" />\n </ng-container>\n </div>\n </aside>\n</div>\n", styles: [":host{display:block;height:100%;min-height:0;box-sizing:border-box}.slice-panel-wrapper{height:100%;max-height:100%;overflow-y:auto;box-sizing:border-box}.slice-panel{margin-top:0;border:1px solid var(--jqt-border-color);border-radius:10px;background:var(--jqt-surface-color);display:flex;flex-direction:column;min-width:0;height:100%;overflow:hidden;box-sizing:border-box}.slice-panel-header{flex-shrink:0;display:flex;justify-content:flex-end;align-items:center;height:34px;padding:0 8px;margin-bottom:8px}.slice-panel-header:has(.slice-panel-title){justify-content:space-between;padding-left:12px}.slice-panel-body{flex:1 1 0;min-height:0;overflow-y:auto;display:flex;flex-direction:column;gap:4px;padding:4px 10px 10px;scrollbar-width:thin;scrollbar-color:var(--jqt-border-color) transparent}.slice-panel-body::-webkit-scrollbar{width:2px}.slice-panel-body::-webkit-scrollbar-thumb{background:var(--jqt-primary-color);border-radius:4px}.slice-panel-title{margin:0;padding-top:2px;font-size:11px;font-weight:700;line-height:1;text-transform:uppercase;letter-spacing:.08em;color:var(--jqt-text-color);-webkit-user-select:none;user-select:none;align-self:center;display:inline-flex;align-items:center;gap:5px}.slice-panel-title .slice-panel-title-icon{font-size:16px;width:16px;height:16px;line-height:1;flex-shrink:0}.slice-section-items{display:flex;flex-direction:column;gap:2px;flex:0 0 auto;scrollbar-width:thin;scrollbar-color:var(--jqt-border-color) transparent}.slice-section-items::-webkit-scrollbar{width:2px}.slice-section-items .slice-empty-state{padding:8px 10px;font-size:12px;color:var(--jqt-text-muted, #9ca3af);font-style:italic;text-align:center}.slice-section-items::-webkit-scrollbar-thumb{background:var(--jqt-border-color);border-radius:4px}.slice-toggle{border:0;background:var(--jqt-surface-color);color:var(--jqt-text-color);border-radius:6px;width:22px;height:22px;padding:0;font-size:14px;text-align:center;cursor:pointer;display:inline-flex;align-items:center;justify-content:center;line-height:1}.slice-toggle-mat-icon{font-size:16px;width:16px;height:16px;line-height:1}.slice-panel.collapsed{border-color:transparent;background:transparent;overflow:visible}.slice-panel.collapsed .slice-panel-header{height:34px;padding:0;justify-content:center;align-items:center}.slice-panel.collapsed .slice-toggle{width:34px;height:34px;border:1px solid var(--jqt-border-color);background:var(--jqt-surface-color);border-radius:8px}.slice-panel.collapsed .slice-toggle:hover{border-color:var(--jqt-text-muted)}.slice-panel.collapsed .slice-toggle .slice-toggle-mat-icon{font-size:18px;width:18px;height:18px}.slice-title-row{display:flex;align-items:center;justify-content:space-between;gap:6px;margin:4px 0 6px;cursor:pointer;-webkit-user-select:none;user-select:none}.slice-title-row:hover .slice-title{color:var(--jqt-text-color)}.slice-title-row:hover .slice-title-chevron{color:var(--jqt-text-secondary)}.slice-title-row:first-of-type .slice-title{margin-top:0}.slice-title-chevron{flex-shrink:0;display:inline-flex;align-items:center;justify-content:center;font-size:16px;line-height:1;color:var(--jqt-text-muted);transition:transform .15s ease;transform:rotate(0);position:relative;top:-1px}.slice-title-chevron.expanded{transform:rotate(90deg)}.slice-title{flex:1 1 auto;margin:0;font-size:14px;font-weight:600;color:var(--jqt-title-color)}.slice-title-icon{flex-shrink:0;font-size:14px!important;width:14px!important;height:14px!important;color:var(--jqt-title-color)}.slice-remove-btn{background:none;border:none;cursor:pointer;color:var(--jqt-border-color);font-size:12px;padding:0 2px;line-height:1;flex-shrink:0;opacity:.5;transition:opacity .15s,color .15s}.slice-remove-btn:hover{color:var(--jqt-text-secondary);opacity:1}.slice-title-row:hover .slice-remove-btn{opacity:.8}.slice-item{display:flex;justify-content:space-between;align-items:center;text-align:left;width:100%;padding:5px 10px 5px 16px;background:transparent;border:0;cursor:pointer;border-radius:8px;color:var(--jqt-text-color);box-sizing:border-box;min-width:0;gap:8px}.slice-item.active{background:var(--jqt-row-hover-bg);font-weight:600}.slice-item.slice-multi{padding-left:6px}.slice-item span:first-child{flex:1 1 auto;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.slice-item span:last-child{flex:0 0 auto;min-width:1.2em;text-align:right}.slice-check-box{flex:0 0 16px;width:16px;height:16px;border:1.5px solid var(--jqt-text-muted);border-radius:4px;background:var(--jqt-surface-color);display:inline-flex;align-items:center;justify-content:center;box-sizing:border-box;transition:background .15s,border-color .15s}.slice-check-box.checked{background:var(--jqt-text-secondary);border-color:var(--jqt-text-secondary)}.slice-check-box.checked:after{content:\"\";display:block;width:9px;height:5px;border-left:2px solid #fff;border-bottom:2px solid #fff;transform:rotate(-45deg) translateY(-1px)}.slice-divider{border:none;border-top:1px solid var(--jqt-border-color);margin:6px 0}.lazy-skeleton{display:block;height:12px;width:70%;border-radius:4px;background:linear-gradient(90deg,var(--jqt-border-color) 25%,var(--jqt-surface-alt-color) 50%,var(--jqt-border-color) 75%);background-size:200% 100%;animation:lazy-shimmer 1.4s ease-in-out infinite}.slice-lazy-loading{display:flex;flex-direction:column;gap:8px;padding:8px 10px}.slice-lazy-loading .lazy-skeleton{width:80%}.slice-lazy-loading .lazy-skeleton:nth-child(2){width:60%}.slice-lazy-loading .lazy-skeleton:nth-child(3){width:45%}@keyframes lazy-shimmer{0%{background-position:200% 0}to{background-position:-200% 0}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
870
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: SlicePanelComponent, isStandalone: true, selector: "slice-panel", inputs: { sliceConfigs: "sliceConfigs", columns: "columns", data: "data", lazyData: "lazyData", lazyStatus: "lazyStatus", showToggle: "showToggle", showCounts: "showCounts", collapsedByDefault: "collapsedByDefault", alwaysShow: "alwaysShow" }, outputs: { filterChange: "filterChange", activeKeysChange: "activeKeysChange", dynamicSliceKeysChange: "dynamicSliceKeysChange", collapsedChange: "collapsedChange" }, host: { properties: { "class.collapsed": "this.hostCollapsed" } }, viewQueries: [{ propertyName: "slicePanelBodyRef", first: true, predicate: ["slicePanelBody"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div class=\"slice-panel-wrapper\" [class.collapsed]=\"isCollapsed\">\n <aside class=\"slice-panel\" [class.collapsed]=\"isCollapsed\">\n <div class=\"slice-panel-header\">\n <span *ngIf=\"!isCollapsed\" class=\"slice-panel-title\">\n {{ i18n.filterPanelTitle(slices.length) }}\n </span>\n <button\n *ngIf=\"showToggle\"\n type=\"button\"\n class=\"slice-toggle\"\n [attr.aria-label]=\"isCollapsed ? i18n.expandFilterTitle : i18n.collapseFilterTitle\"\n (click)=\"togglePanel()\"\n >\n <mat-icon class=\"slice-toggle-mat-icon\">{{ isCollapsed ? 'filter_list' : 'filter_list_off' }}</mat-icon>\n </button>\n </div>\n\n <div class=\"slice-panel-body\" *ngIf=\"!isCollapsed\" #slicePanelBody>\n <ng-container *ngFor=\"let slice of slices; let si = index; trackBy: trackBySliceIndex\">\n <div class=\"slice-title-row\" [attr.data-slice-index]=\"si\" (click)=\"toggleSliceCollapse(si)\">\n <span class=\"slice-title-chevron\" [class.expanded]=\"!isSliceCollapsed(si)\">\u203A</span>\n <mat-icon *ngIf=\"getSliceIcon(slice)\" class=\"slice-title-icon\">{{ getSliceIcon(slice) }}</mat-icon>\n <p class=\"slice-title\">{{ slice.title || i18n.filterBlockDefaultTitle }}</p>\n <button\n *ngIf=\"isSliceDynamic(si)\"\n type=\"button\"\n class=\"slice-remove-btn\"\n (click)=\"$event.stopPropagation(); removeDynamicSlice(si)\"\n >\u00D7</button>\n </div>\n\n <div class=\"slice-section-items\" *ngIf=\"!isSliceCollapsed(si)\">\n <ng-container *ngIf=\"isSliceLoading(si); else sliceContent\">\n <div class=\"slice-lazy-loading\">\n <span class=\"lazy-skeleton\"></span>\n <span class=\"lazy-skeleton\"></span>\n <span class=\"lazy-skeleton\"></span>\n </div>\n </ng-container>\n <ng-template #sliceContent>\n <ng-container *ngFor=\"let category of slice.categories; trackBy: trackByCategoryKey\">\n <button\n *ngIf=\"sliceCategoryCount(si, category.key) > 0\"\n class=\"slice-item\"\n type=\"button\"\n [class.active]=\"isSliceCategoryActive(si, category.key)\"\n [attr.data-category-key]=\"category.key\"\n [title]=\"category.label\"\n (click)=\"onSliceCategorySelected(si, category.key)\"\n >\n <span>{{ category.label }}</span>\n <span *ngIf=\"showCounts\">{{ sliceCategoryCount(si, category.key) }}</span>\n </button>\n </ng-container>\n <div *ngIf=\"isSliceEmpty(si)\" class=\"slice-empty-state\">{{ i18n.filterEmptyState }}</div>\n </ng-template>\n </div>\n\n <hr *ngIf=\"si < slices.length - 1\" class=\"slice-divider\" />\n </ng-container>\n </div>\n </aside>\n</div>\n", styles: ["@keyframes slideInLeft{0%{opacity:0;transform:translate(-24px)}to{opacity:1;transform:translate(0)}}:host{display:block;height:100%;min-height:0;box-sizing:border-box;animation:slideInLeft .3s cubic-bezier(.34,1.56,.64,1) forwards}.slice-panel-wrapper{height:100%;max-height:100%;overflow-y:auto;box-sizing:border-box}.slice-panel{margin-top:0;border:1px solid var(--jqt-border-color);border-radius:10px;background:var(--jqt-surface-color);display:flex;flex-direction:column;min-width:0;height:100%;overflow:hidden;box-sizing:border-box}.slice-panel-header{flex-shrink:0;display:flex;justify-content:flex-end;align-items:center;height:34px;padding:0 8px;margin-bottom:8px}.slice-panel-header:has(.slice-panel-title){justify-content:space-between;padding-left:12px}.slice-panel-body{flex:1 1 0;min-height:0;overflow-y:auto;display:flex;flex-direction:column;gap:4px;padding:4px 10px 10px;scrollbar-width:thin;scrollbar-color:var(--jqt-border-color) transparent}.slice-panel-body::-webkit-scrollbar{width:2px}.slice-panel-body::-webkit-scrollbar-thumb{background:var(--jqt-primary-color);border-radius:4px}.slice-panel-title{margin:0;padding-top:2px;font-size:11px;font-weight:700;line-height:1;text-transform:uppercase;letter-spacing:.08em;color:var(--jqt-text-color);-webkit-user-select:none;user-select:none;align-self:center;display:inline-flex;align-items:center;gap:5px}.slice-panel-title .slice-panel-title-icon{font-size:16px;width:16px;height:16px;line-height:1;flex-shrink:0}.slice-section-items{display:flex;flex-direction:column;gap:2px;flex:0 0 auto;scrollbar-width:thin;scrollbar-color:var(--jqt-border-color) transparent}.slice-section-items::-webkit-scrollbar{width:2px}.slice-section-items .slice-empty-state{padding:8px 10px;font-size:12px;color:var(--jqt-text-muted, #9ca3af);font-style:italic;text-align:center}.slice-section-items::-webkit-scrollbar-thumb{background:var(--jqt-border-color);border-radius:4px}.slice-toggle{border:0;background:var(--jqt-surface-color);color:var(--jqt-text-color);border-radius:6px;width:22px;height:22px;padding:0;font-size:14px;text-align:center;cursor:pointer;display:inline-flex;align-items:center;justify-content:center;line-height:1}.slice-toggle-mat-icon{font-size:16px;width:16px;height:16px;line-height:1}.slice-panel.collapsed{border-color:transparent;background:transparent;overflow:visible}.slice-panel.collapsed .slice-panel-header{height:34px;padding:0;justify-content:center;align-items:center}.slice-panel.collapsed .slice-toggle{width:34px;height:34px;border:1px solid var(--jqt-border-color);background:var(--jqt-surface-color);border-radius:8px}.slice-panel.collapsed .slice-toggle:hover{border-color:var(--jqt-text-muted)}.slice-panel.collapsed .slice-toggle .slice-toggle-mat-icon{font-size:18px;width:18px;height:18px}.slice-title-row{display:flex;align-items:center;justify-content:space-between;gap:6px;margin:4px 0 6px;cursor:pointer;-webkit-user-select:none;user-select:none}.slice-title-row:hover .slice-title{color:var(--jqt-text-color)}.slice-title-row:hover .slice-title-chevron{color:var(--jqt-text-secondary)}.slice-title-row:first-of-type .slice-title{margin-top:0}.slice-title-chevron{flex-shrink:0;display:inline-flex;align-items:center;justify-content:center;font-size:16px;line-height:1;color:var(--jqt-text-muted);transition:transform .15s ease;transform:rotate(0);position:relative;top:-1px}.slice-title-chevron.expanded{transform:rotate(90deg)}.slice-title{flex:1 1 auto;margin:0;font-size:14px;font-weight:600;color:var(--jqt-title-color)}.slice-title-icon{flex-shrink:0;font-size:14px!important;width:14px!important;height:14px!important;color:var(--jqt-title-color)}.slice-remove-btn{background:none;border:none;cursor:pointer;color:var(--jqt-border-color);font-size:12px;padding:0 2px;line-height:1;flex-shrink:0;opacity:.5;transition:opacity .15s,color .15s}.slice-remove-btn:hover{color:var(--jqt-text-secondary);opacity:1}.slice-title-row:hover .slice-remove-btn{opacity:.8}.slice-item{display:flex;justify-content:space-between;align-items:center;text-align:left;width:100%;padding:5px 10px 5px 16px;background:transparent;border:0;cursor:pointer;border-radius:8px;color:var(--jqt-text-color);box-sizing:border-box;min-width:0;gap:8px}.slice-item.active{background:var(--jqt-row-hover-bg);font-weight:600}.slice-item.slice-multi{padding-left:6px}.slice-item span:first-child{flex:1 1 auto;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.slice-item span:last-child{flex:0 0 auto;min-width:1.2em;text-align:right}.slice-check-box{flex:0 0 16px;width:16px;height:16px;border:1.5px solid var(--jqt-text-muted);border-radius:4px;background:var(--jqt-surface-color);display:inline-flex;align-items:center;justify-content:center;box-sizing:border-box;transition:background .15s,border-color .15s}.slice-check-box.checked{background:var(--jqt-text-secondary);border-color:var(--jqt-text-secondary)}.slice-check-box.checked:after{content:\"\";display:block;width:9px;height:5px;border-left:2px solid #fff;border-bottom:2px solid #fff;transform:rotate(-45deg) translateY(-1px)}.slice-divider{border:none;border-top:1px solid var(--jqt-border-color);margin:6px 0}.lazy-skeleton{display:block;height:12px;width:70%;border-radius:4px;background:linear-gradient(90deg,var(--jqt-border-color) 25%,var(--jqt-surface-alt-color) 50%,var(--jqt-border-color) 75%);background-size:200% 100%;animation:lazy-shimmer 1.4s ease-in-out infinite}.slice-lazy-loading{display:flex;flex-direction:column;gap:8px;padding:8px 10px}.slice-lazy-loading .lazy-skeleton{width:80%}.slice-lazy-loading .lazy-skeleton:nth-child(2){width:60%}.slice-lazy-loading .lazy-skeleton:nth-child(3){width:45%}@keyframes lazy-shimmer{0%{background-position:200% 0}to{background-position:-200% 0}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
852
871
  }
853
872
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: SlicePanelComponent, decorators: [{
854
873
  type: Component,
855
- args: [{ standalone: true, selector: 'slice-panel', imports: [CommonModule, MatIconModule], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"slice-panel-wrapper\" [class.collapsed]=\"isCollapsed\">\n <aside class=\"slice-panel\" [class.collapsed]=\"isCollapsed\">\n <div class=\"slice-panel-header\">\n <span *ngIf=\"!isCollapsed\" class=\"slice-panel-title\">\n {{ i18n.filterPanelTitle(slices.length) }}\n </span>\n <button\n *ngIf=\"showToggle\"\n type=\"button\"\n class=\"slice-toggle\"\n [attr.aria-label]=\"isCollapsed ? i18n.expandFilterTitle : i18n.collapseFilterTitle\"\n (click)=\"togglePanel()\"\n >\n <mat-icon class=\"slice-toggle-mat-icon\">{{ isCollapsed ? 'filter_list' : 'filter_list_off' }}</mat-icon>\n </button>\n </div>\n\n <div class=\"slice-panel-body\" *ngIf=\"!isCollapsed\" #slicePanelBody>\n <ng-container *ngFor=\"let slice of slices; let si = index; trackBy: trackBySliceIndex\">\n <div class=\"slice-title-row\" [attr.data-slice-index]=\"si\" (click)=\"toggleSliceCollapse(si)\">\n <span class=\"slice-title-chevron\" [class.expanded]=\"!isSliceCollapsed(si)\">\u203A</span>\n <mat-icon *ngIf=\"getSliceIcon(slice)\" class=\"slice-title-icon\">{{ getSliceIcon(slice) }}</mat-icon>\n <p class=\"slice-title\">{{ slice.title || i18n.filterBlockDefaultTitle }}</p>\n <button\n *ngIf=\"isSliceDynamic(si)\"\n type=\"button\"\n class=\"slice-remove-btn\"\n (click)=\"$event.stopPropagation(); removeDynamicSlice(si)\"\n >\u00D7</button>\n </div>\n\n <div class=\"slice-section-items\" *ngIf=\"!isSliceCollapsed(si)\">\n <ng-container *ngIf=\"isSliceLoading(si); else sliceContent\">\n <div class=\"slice-lazy-loading\">\n <span class=\"lazy-skeleton\"></span>\n <span class=\"lazy-skeleton\"></span>\n <span class=\"lazy-skeleton\"></span>\n </div>\n </ng-container>\n <ng-template #sliceContent>\n <ng-container *ngFor=\"let category of slice.categories; trackBy: trackByCategoryKey\">\n <button\n *ngIf=\"sliceCategoryCount(si, category.key) > 0\"\n class=\"slice-item\"\n type=\"button\"\n [class.active]=\"isSliceCategoryActive(si, category.key)\"\n [attr.data-category-key]=\"category.key\"\n [title]=\"category.label\"\n (click)=\"onSliceCategorySelected(si, category.key)\"\n >\n <span>{{ category.label }}</span>\n <span *ngIf=\"showCounts\">{{ sliceCategoryCount(si, category.key) }}</span>\n </button>\n </ng-container>\n <div *ngIf=\"isSliceEmpty(si)\" class=\"slice-empty-state\">{{ i18n.filterEmptyState }}</div>\n </ng-template>\n </div>\n\n <hr *ngIf=\"si < slices.length - 1\" class=\"slice-divider\" />\n </ng-container>\n </div>\n </aside>\n</div>\n", styles: [":host{display:block;height:100%;min-height:0;box-sizing:border-box}.slice-panel-wrapper{height:100%;max-height:100%;overflow-y:auto;box-sizing:border-box}.slice-panel{margin-top:0;border:1px solid var(--jqt-border-color);border-radius:10px;background:var(--jqt-surface-color);display:flex;flex-direction:column;min-width:0;height:100%;overflow:hidden;box-sizing:border-box}.slice-panel-header{flex-shrink:0;display:flex;justify-content:flex-end;align-items:center;height:34px;padding:0 8px;margin-bottom:8px}.slice-panel-header:has(.slice-panel-title){justify-content:space-between;padding-left:12px}.slice-panel-body{flex:1 1 0;min-height:0;overflow-y:auto;display:flex;flex-direction:column;gap:4px;padding:4px 10px 10px;scrollbar-width:thin;scrollbar-color:var(--jqt-border-color) transparent}.slice-panel-body::-webkit-scrollbar{width:2px}.slice-panel-body::-webkit-scrollbar-thumb{background:var(--jqt-primary-color);border-radius:4px}.slice-panel-title{margin:0;padding-top:2px;font-size:11px;font-weight:700;line-height:1;text-transform:uppercase;letter-spacing:.08em;color:var(--jqt-text-color);-webkit-user-select:none;user-select:none;align-self:center;display:inline-flex;align-items:center;gap:5px}.slice-panel-title .slice-panel-title-icon{font-size:16px;width:16px;height:16px;line-height:1;flex-shrink:0}.slice-section-items{display:flex;flex-direction:column;gap:2px;flex:0 0 auto;scrollbar-width:thin;scrollbar-color:var(--jqt-border-color) transparent}.slice-section-items::-webkit-scrollbar{width:2px}.slice-section-items .slice-empty-state{padding:8px 10px;font-size:12px;color:var(--jqt-text-muted, #9ca3af);font-style:italic;text-align:center}.slice-section-items::-webkit-scrollbar-thumb{background:var(--jqt-border-color);border-radius:4px}.slice-toggle{border:0;background:var(--jqt-surface-color);color:var(--jqt-text-color);border-radius:6px;width:22px;height:22px;padding:0;font-size:14px;text-align:center;cursor:pointer;display:inline-flex;align-items:center;justify-content:center;line-height:1}.slice-toggle-mat-icon{font-size:16px;width:16px;height:16px;line-height:1}.slice-panel.collapsed{border-color:transparent;background:transparent;overflow:visible}.slice-panel.collapsed .slice-panel-header{height:34px;padding:0;justify-content:center;align-items:center}.slice-panel.collapsed .slice-toggle{width:34px;height:34px;border:1px solid var(--jqt-border-color);background:var(--jqt-surface-color);border-radius:8px}.slice-panel.collapsed .slice-toggle:hover{border-color:var(--jqt-text-muted)}.slice-panel.collapsed .slice-toggle .slice-toggle-mat-icon{font-size:18px;width:18px;height:18px}.slice-title-row{display:flex;align-items:center;justify-content:space-between;gap:6px;margin:4px 0 6px;cursor:pointer;-webkit-user-select:none;user-select:none}.slice-title-row:hover .slice-title{color:var(--jqt-text-color)}.slice-title-row:hover .slice-title-chevron{color:var(--jqt-text-secondary)}.slice-title-row:first-of-type .slice-title{margin-top:0}.slice-title-chevron{flex-shrink:0;display:inline-flex;align-items:center;justify-content:center;font-size:16px;line-height:1;color:var(--jqt-text-muted);transition:transform .15s ease;transform:rotate(0);position:relative;top:-1px}.slice-title-chevron.expanded{transform:rotate(90deg)}.slice-title{flex:1 1 auto;margin:0;font-size:14px;font-weight:600;color:var(--jqt-title-color)}.slice-title-icon{flex-shrink:0;font-size:14px!important;width:14px!important;height:14px!important;color:var(--jqt-title-color)}.slice-remove-btn{background:none;border:none;cursor:pointer;color:var(--jqt-border-color);font-size:12px;padding:0 2px;line-height:1;flex-shrink:0;opacity:.5;transition:opacity .15s,color .15s}.slice-remove-btn:hover{color:var(--jqt-text-secondary);opacity:1}.slice-title-row:hover .slice-remove-btn{opacity:.8}.slice-item{display:flex;justify-content:space-between;align-items:center;text-align:left;width:100%;padding:5px 10px 5px 16px;background:transparent;border:0;cursor:pointer;border-radius:8px;color:var(--jqt-text-color);box-sizing:border-box;min-width:0;gap:8px}.slice-item.active{background:var(--jqt-row-hover-bg);font-weight:600}.slice-item.slice-multi{padding-left:6px}.slice-item span:first-child{flex:1 1 auto;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.slice-item span:last-child{flex:0 0 auto;min-width:1.2em;text-align:right}.slice-check-box{flex:0 0 16px;width:16px;height:16px;border:1.5px solid var(--jqt-text-muted);border-radius:4px;background:var(--jqt-surface-color);display:inline-flex;align-items:center;justify-content:center;box-sizing:border-box;transition:background .15s,border-color .15s}.slice-check-box.checked{background:var(--jqt-text-secondary);border-color:var(--jqt-text-secondary)}.slice-check-box.checked:after{content:\"\";display:block;width:9px;height:5px;border-left:2px solid #fff;border-bottom:2px solid #fff;transform:rotate(-45deg) translateY(-1px)}.slice-divider{border:none;border-top:1px solid var(--jqt-border-color);margin:6px 0}.lazy-skeleton{display:block;height:12px;width:70%;border-radius:4px;background:linear-gradient(90deg,var(--jqt-border-color) 25%,var(--jqt-surface-alt-color) 50%,var(--jqt-border-color) 75%);background-size:200% 100%;animation:lazy-shimmer 1.4s ease-in-out infinite}.slice-lazy-loading{display:flex;flex-direction:column;gap:8px;padding:8px 10px}.slice-lazy-loading .lazy-skeleton{width:80%}.slice-lazy-loading .lazy-skeleton:nth-child(2){width:60%}.slice-lazy-loading .lazy-skeleton:nth-child(3){width:45%}@keyframes lazy-shimmer{0%{background-position:200% 0}to{background-position:-200% 0}}\n"] }]
874
+ args: [{ standalone: true, selector: 'slice-panel', imports: [CommonModule, MatIconModule], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"slice-panel-wrapper\" [class.collapsed]=\"isCollapsed\">\n <aside class=\"slice-panel\" [class.collapsed]=\"isCollapsed\">\n <div class=\"slice-panel-header\">\n <span *ngIf=\"!isCollapsed\" class=\"slice-panel-title\">\n {{ i18n.filterPanelTitle(slices.length) }}\n </span>\n <button\n *ngIf=\"showToggle\"\n type=\"button\"\n class=\"slice-toggle\"\n [attr.aria-label]=\"isCollapsed ? i18n.expandFilterTitle : i18n.collapseFilterTitle\"\n (click)=\"togglePanel()\"\n >\n <mat-icon class=\"slice-toggle-mat-icon\">{{ isCollapsed ? 'filter_list' : 'filter_list_off' }}</mat-icon>\n </button>\n </div>\n\n <div class=\"slice-panel-body\" *ngIf=\"!isCollapsed\" #slicePanelBody>\n <ng-container *ngFor=\"let slice of slices; let si = index; trackBy: trackBySliceIndex\">\n <div class=\"slice-title-row\" [attr.data-slice-index]=\"si\" (click)=\"toggleSliceCollapse(si)\">\n <span class=\"slice-title-chevron\" [class.expanded]=\"!isSliceCollapsed(si)\">\u203A</span>\n <mat-icon *ngIf=\"getSliceIcon(slice)\" class=\"slice-title-icon\">{{ getSliceIcon(slice) }}</mat-icon>\n <p class=\"slice-title\">{{ slice.title || i18n.filterBlockDefaultTitle }}</p>\n <button\n *ngIf=\"isSliceDynamic(si)\"\n type=\"button\"\n class=\"slice-remove-btn\"\n (click)=\"$event.stopPropagation(); removeDynamicSlice(si)\"\n >\u00D7</button>\n </div>\n\n <div class=\"slice-section-items\" *ngIf=\"!isSliceCollapsed(si)\">\n <ng-container *ngIf=\"isSliceLoading(si); else sliceContent\">\n <div class=\"slice-lazy-loading\">\n <span class=\"lazy-skeleton\"></span>\n <span class=\"lazy-skeleton\"></span>\n <span class=\"lazy-skeleton\"></span>\n </div>\n </ng-container>\n <ng-template #sliceContent>\n <ng-container *ngFor=\"let category of slice.categories; trackBy: trackByCategoryKey\">\n <button\n *ngIf=\"sliceCategoryCount(si, category.key) > 0\"\n class=\"slice-item\"\n type=\"button\"\n [class.active]=\"isSliceCategoryActive(si, category.key)\"\n [attr.data-category-key]=\"category.key\"\n [title]=\"category.label\"\n (click)=\"onSliceCategorySelected(si, category.key)\"\n >\n <span>{{ category.label }}</span>\n <span *ngIf=\"showCounts\">{{ sliceCategoryCount(si, category.key) }}</span>\n </button>\n </ng-container>\n <div *ngIf=\"isSliceEmpty(si)\" class=\"slice-empty-state\">{{ i18n.filterEmptyState }}</div>\n </ng-template>\n </div>\n\n <hr *ngIf=\"si < slices.length - 1\" class=\"slice-divider\" />\n </ng-container>\n </div>\n </aside>\n</div>\n", styles: ["@keyframes slideInLeft{0%{opacity:0;transform:translate(-24px)}to{opacity:1;transform:translate(0)}}:host{display:block;height:100%;min-height:0;box-sizing:border-box;animation:slideInLeft .3s cubic-bezier(.34,1.56,.64,1) forwards}.slice-panel-wrapper{height:100%;max-height:100%;overflow-y:auto;box-sizing:border-box}.slice-panel{margin-top:0;border:1px solid var(--jqt-border-color);border-radius:10px;background:var(--jqt-surface-color);display:flex;flex-direction:column;min-width:0;height:100%;overflow:hidden;box-sizing:border-box}.slice-panel-header{flex-shrink:0;display:flex;justify-content:flex-end;align-items:center;height:34px;padding:0 8px;margin-bottom:8px}.slice-panel-header:has(.slice-panel-title){justify-content:space-between;padding-left:12px}.slice-panel-body{flex:1 1 0;min-height:0;overflow-y:auto;display:flex;flex-direction:column;gap:4px;padding:4px 10px 10px;scrollbar-width:thin;scrollbar-color:var(--jqt-border-color) transparent}.slice-panel-body::-webkit-scrollbar{width:2px}.slice-panel-body::-webkit-scrollbar-thumb{background:var(--jqt-primary-color);border-radius:4px}.slice-panel-title{margin:0;padding-top:2px;font-size:11px;font-weight:700;line-height:1;text-transform:uppercase;letter-spacing:.08em;color:var(--jqt-text-color);-webkit-user-select:none;user-select:none;align-self:center;display:inline-flex;align-items:center;gap:5px}.slice-panel-title .slice-panel-title-icon{font-size:16px;width:16px;height:16px;line-height:1;flex-shrink:0}.slice-section-items{display:flex;flex-direction:column;gap:2px;flex:0 0 auto;scrollbar-width:thin;scrollbar-color:var(--jqt-border-color) transparent}.slice-section-items::-webkit-scrollbar{width:2px}.slice-section-items .slice-empty-state{padding:8px 10px;font-size:12px;color:var(--jqt-text-muted, #9ca3af);font-style:italic;text-align:center}.slice-section-items::-webkit-scrollbar-thumb{background:var(--jqt-border-color);border-radius:4px}.slice-toggle{border:0;background:var(--jqt-surface-color);color:var(--jqt-text-color);border-radius:6px;width:22px;height:22px;padding:0;font-size:14px;text-align:center;cursor:pointer;display:inline-flex;align-items:center;justify-content:center;line-height:1}.slice-toggle-mat-icon{font-size:16px;width:16px;height:16px;line-height:1}.slice-panel.collapsed{border-color:transparent;background:transparent;overflow:visible}.slice-panel.collapsed .slice-panel-header{height:34px;padding:0;justify-content:center;align-items:center}.slice-panel.collapsed .slice-toggle{width:34px;height:34px;border:1px solid var(--jqt-border-color);background:var(--jqt-surface-color);border-radius:8px}.slice-panel.collapsed .slice-toggle:hover{border-color:var(--jqt-text-muted)}.slice-panel.collapsed .slice-toggle .slice-toggle-mat-icon{font-size:18px;width:18px;height:18px}.slice-title-row{display:flex;align-items:center;justify-content:space-between;gap:6px;margin:4px 0 6px;cursor:pointer;-webkit-user-select:none;user-select:none}.slice-title-row:hover .slice-title{color:var(--jqt-text-color)}.slice-title-row:hover .slice-title-chevron{color:var(--jqt-text-secondary)}.slice-title-row:first-of-type .slice-title{margin-top:0}.slice-title-chevron{flex-shrink:0;display:inline-flex;align-items:center;justify-content:center;font-size:16px;line-height:1;color:var(--jqt-text-muted);transition:transform .15s ease;transform:rotate(0);position:relative;top:-1px}.slice-title-chevron.expanded{transform:rotate(90deg)}.slice-title{flex:1 1 auto;margin:0;font-size:14px;font-weight:600;color:var(--jqt-title-color)}.slice-title-icon{flex-shrink:0;font-size:14px!important;width:14px!important;height:14px!important;color:var(--jqt-title-color)}.slice-remove-btn{background:none;border:none;cursor:pointer;color:var(--jqt-border-color);font-size:12px;padding:0 2px;line-height:1;flex-shrink:0;opacity:.5;transition:opacity .15s,color .15s}.slice-remove-btn:hover{color:var(--jqt-text-secondary);opacity:1}.slice-title-row:hover .slice-remove-btn{opacity:.8}.slice-item{display:flex;justify-content:space-between;align-items:center;text-align:left;width:100%;padding:5px 10px 5px 16px;background:transparent;border:0;cursor:pointer;border-radius:8px;color:var(--jqt-text-color);box-sizing:border-box;min-width:0;gap:8px}.slice-item.active{background:var(--jqt-row-hover-bg);font-weight:600}.slice-item.slice-multi{padding-left:6px}.slice-item span:first-child{flex:1 1 auto;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.slice-item span:last-child{flex:0 0 auto;min-width:1.2em;text-align:right}.slice-check-box{flex:0 0 16px;width:16px;height:16px;border:1.5px solid var(--jqt-text-muted);border-radius:4px;background:var(--jqt-surface-color);display:inline-flex;align-items:center;justify-content:center;box-sizing:border-box;transition:background .15s,border-color .15s}.slice-check-box.checked{background:var(--jqt-text-secondary);border-color:var(--jqt-text-secondary)}.slice-check-box.checked:after{content:\"\";display:block;width:9px;height:5px;border-left:2px solid #fff;border-bottom:2px solid #fff;transform:rotate(-45deg) translateY(-1px)}.slice-divider{border:none;border-top:1px solid var(--jqt-border-color);margin:6px 0}.lazy-skeleton{display:block;height:12px;width:70%;border-radius:4px;background:linear-gradient(90deg,var(--jqt-border-color) 25%,var(--jqt-surface-alt-color) 50%,var(--jqt-border-color) 75%);background-size:200% 100%;animation:lazy-shimmer 1.4s ease-in-out infinite}.slice-lazy-loading{display:flex;flex-direction:column;gap:8px;padding:8px 10px}.slice-lazy-loading .lazy-skeleton{width:80%}.slice-lazy-loading .lazy-skeleton:nth-child(2){width:60%}.slice-lazy-loading .lazy-skeleton:nth-child(3){width:45%}@keyframes lazy-shimmer{0%{background-position:200% 0}to{background-position:-200% 0}}\n"] }]
856
875
  }], propDecorators: { sliceConfigs: [{
857
876
  type: Input
858
877
  }], columns: [{
@@ -917,16 +936,61 @@ const DEFAULT_MENU_ICONS = {
917
936
  'custom': 'settings'
918
937
  };
919
938
 
939
+ var SyntheticItemKeys;
940
+ (function (SyntheticItemKeys) {
941
+ SyntheticItemKeys["EMPTY"] = "__empty__";
942
+ SyntheticItemKeys["SYNTHETIC_MARKER"] = "__synthetic__";
943
+ })(SyntheticItemKeys || (SyntheticItemKeys = {}));
944
+ var SlicePanelI18nKeys;
945
+ (function (SlicePanelI18nKeys) {
946
+ SlicePanelI18nKeys["EXPAND_FILTER"] = "expandFilterTitle";
947
+ SlicePanelI18nKeys["COLLAPSE_FILTER"] = "collapseFilterTitle";
948
+ SlicePanelI18nKeys["FILTER_PANEL_TITLE_SINGLE"] = "filterPanelTitleSingle";
949
+ SlicePanelI18nKeys["FILTER_PANEL_TITLE_PLURAL"] = "filterPanelTitlePlural";
950
+ SlicePanelI18nKeys["FILTER_BLOCK_DEFAULT_TITLE"] = "filterBlockDefaultTitle";
951
+ SlicePanelI18nKeys["FILTER_EMPTY_STATE"] = "filterEmptyState";
952
+ })(SlicePanelI18nKeys || (SlicePanelI18nKeys = {}));
953
+ var OrganizerButtonEventType;
954
+ (function (OrganizerButtonEventType) {
955
+ OrganizerButtonEventType["FIELD_TOGGLED"] = "fieldToggled";
956
+ OrganizerButtonEventType["X_SELECTED"] = "xSelected";
957
+ OrganizerButtonEventType["Y_SELECTED"] = "ySelected";
958
+ OrganizerButtonEventType["GROUP_BY_SELECTED"] = "groupBySelected";
959
+ OrganizerButtonEventType["TEMPLATE_SELECTED"] = "templateSelected";
960
+ OrganizerButtonEventType["SLICE_SELECTED"] = "sliceSelected";
961
+ OrganizerButtonEventType["VIEW_SWITCHED"] = "viewSwitched";
962
+ })(OrganizerButtonEventType || (OrganizerButtonEventType = {}));
963
+ function getGroupItems(config) {
964
+ return config?.groups?.items ?? [];
965
+ }
966
+ function getIndicatorItems(config) {
967
+ return config?.indicators?.items ?? [];
968
+ }
969
+ function getFilterItems(config) {
970
+ return config?.filters?.items ?? [];
971
+ }
972
+ function getStackItems(indicator) {
973
+ return indicator?.extra?.stacks?.items ?? [];
974
+ }
975
+
920
976
  function chartConfigToOrganizer(chartConfig, options = {}) {
921
- if (!chartConfig)
977
+ if (!chartConfig) {
978
+ console.debug('[OrganizerChartAdapter] Empty chart config, returning empty organizer config');
922
979
  return {};
980
+ }
981
+ console.debug('[OrganizerChartAdapter] Converting chart config to organizer', {
982
+ hasGroups: !!chartConfig.groups,
983
+ indicatorCount: chartConfig.indicators?.items?.length ?? 0,
984
+ filterCount: chartConfig.filters?.items?.length ?? 0
985
+ });
923
986
  const { onFetchSliceData, onExportVisual, onExportData, switchView } = options;
924
- const activeIndicator = chartConfig.indicators?.items?.find(i => i.selected);
925
- const baseXFields = (chartConfig.groups?.items || [])
987
+ const indicators = getIndicatorItems(chartConfig);
988
+ const activeIndicator = indicators.find(i => i.selected);
989
+ const baseXFields = getGroupItems(chartConfig)
926
990
  .filter(g => !_isSynthetic(g))
927
991
  .map(g => ({ id: g.key, label: g.menu.label || g.key }));
928
- const yFields = buildYFields((chartConfig.indicators?.items || []).map(i => ({ id: i.key, label: i.menu.label || i.key, group: i.group })));
929
- const stackFields = (activeIndicator?.extra?.stacks?.items || [])
992
+ const yFields = buildYFields(indicators.map(i => ({ id: i.key, label: i.menu.label || i.key, group: i.group })));
993
+ const stackFields = getStackItems(activeIndicator)
930
994
  .filter((s) => !_isSynthetic(s))
931
995
  .map((s) => ({ id: s.key, label: s.menu.label || s.key }));
932
996
  const seenKeys = new Set();
@@ -940,7 +1004,7 @@ function chartConfigToOrganizer(chartConfig, options = {}) {
940
1004
  xFields: mergedGroupFields,
941
1005
  yFields,
942
1006
  groups: mergedGroupFields,
943
- slices: (chartConfig.filters?.items || []).map(f => ({ id: f.key, label: f.menu.label || f.key })),
1007
+ slices: getFilterItems(chartConfig).map(f => ({ id: f.key, label: f.menu.label || f.key })),
944
1008
  templates: chartConfig.templates,
945
1009
  showReset: false,
946
1010
  onFetchSliceData,
@@ -951,13 +1015,22 @@ function chartConfigToOrganizer(chartConfig, options = {}) {
951
1015
  };
952
1016
  }
953
1017
  function chartConfigToState(chartConfig) {
954
- if (!chartConfig)
1018
+ if (!chartConfig) {
1019
+ console.debug('[OrganizerChartAdapter] Empty chart config for state conversion');
955
1020
  return {};
956
- const activeIndicator = chartConfig.indicators?.items?.find(i => i.selected);
957
- const activeStack = (activeIndicator?.extra?.stacks?.items || []).find((s) => s.selected);
958
- const activeGroup = chartConfig.groups?.items?.find(g => g.selected);
959
- const activeSlices = (chartConfig.filters?.items || []).filter(f => f.selected);
1021
+ }
1022
+ const indicators = getIndicatorItems(chartConfig);
1023
+ const activeIndicator = indicators.find(i => i.selected);
1024
+ const activeStack = getStackItems(activeIndicator).find((s) => s.selected);
1025
+ const activeGroup = getGroupItems(chartConfig).find(g => g.selected);
1026
+ const activeSlices = getFilterItems(chartConfig).filter(f => f.selected);
960
1027
  const indicatorGroup = activeIndicator?.group;
1028
+ console.debug('[OrganizerChartAdapter] Current chart state', {
1029
+ activeGroup: activeGroup?.key,
1030
+ activeIndicator: activeIndicator?.key,
1031
+ activeStack: activeStack?.key,
1032
+ sliceCount: activeSlices.length
1033
+ });
961
1034
  const state = {
962
1035
  selectedX: activeGroup?.key,
963
1036
  selectedY: indicatorGroup ?? activeIndicator?.key,
@@ -986,8 +1059,11 @@ function chartConfigToUnifiedState(chartConfig, viewMode = 'chart') {
986
1059
  };
987
1060
  }
988
1061
  function applyOrganizerEventToChart(event, chartConfig) {
989
- if (!chartConfig)
1062
+ if (!chartConfig) {
1063
+ console.debug('[OrganizerChartAdapter] Cannot apply event to empty chart config');
990
1064
  return;
1065
+ }
1066
+ console.debug('[OrganizerChartAdapter] Applying organizer event', { eventType: event.type, state: event.state });
991
1067
  const state = event.state;
992
1068
  _cleanSynthetics(chartConfig);
993
1069
  if (state.selectedX !== undefined)
@@ -1001,6 +1077,7 @@ function applyOrganizerEventToChart(event, chartConfig) {
1001
1077
  event.resolvedYUnit = resolveYUnit(chartConfig, event.state.selectedY, event.state.selectedYAggregate);
1002
1078
  }
1003
1079
  function handleOrganizerChartEvent(event, chartConfig, currentBinding, options = {}) {
1080
+ console.debug('[OrganizerChartAdapter] Handling organizer event', { eventType: event.type });
1004
1081
  if (event.type === 'viewSwitched') {
1005
1082
  return {
1006
1083
  binding: {
@@ -1029,7 +1106,7 @@ function resolveYUnit(chartConfig, selectedY, selectedYAggregate) {
1029
1106
  if (!chartConfig || !selectedY)
1030
1107
  return undefined;
1031
1108
  const actualKey = resolveYKey(selectedY, selectedYAggregate);
1032
- return chartConfig.indicators?.items?.find(i => i.key === actualKey)?.unit;
1109
+ return getIndicatorItems(chartConfig).find(i => i.key === actualKey)?.unit;
1033
1110
  }
1034
1111
  const _syntheticItems = new WeakSet();
1035
1112
  function _makeSynthetic(item) {
@@ -1040,24 +1117,30 @@ function _isSynthetic(item) {
1040
1117
  return _syntheticItems.has(item);
1041
1118
  }
1042
1119
  function _cleanSynthetics(chartConfig) {
1043
- chartConfig.groups.items = chartConfig.groups.items.filter(g => !_isSynthetic(g));
1044
- chartConfig.indicators.items.forEach(ind => {
1045
- if (ind.extra?.stacks?.items) {
1046
- ind.extra.stacks.items = ind.extra.stacks.items.filter((s) => !_isSynthetic(s));
1047
- }
1048
- });
1120
+ if (chartConfig.groups?.items) {
1121
+ chartConfig.groups.items = chartConfig.groups.items.filter(g => !_isSynthetic(g));
1122
+ }
1123
+ if (chartConfig.indicators?.items) {
1124
+ chartConfig.indicators.items.forEach(ind => {
1125
+ if (ind.extra?.stacks?.items) {
1126
+ ind.extra.stacks.items = ind.extra.stacks.items.filter((s) => !_isSynthetic(s));
1127
+ }
1128
+ });
1129
+ }
1049
1130
  }
1050
1131
  function _applyXSelection(selectedX, chartConfig) {
1051
- const isGroupItem = chartConfig.groups.items.some(g => g.key === selectedX);
1132
+ const groupItems = getGroupItems(chartConfig);
1133
+ const isGroupItem = groupItems.some(g => g.key === selectedX);
1052
1134
  if (isGroupItem) {
1053
- chartConfig.groups.items.forEach(g => { g.selected = g.key === selectedX; });
1135
+ groupItems.forEach(g => { g.selected = g.key === selectedX; });
1054
1136
  return;
1055
1137
  }
1056
- const allStacks = chartConfig.indicators.items.flatMap(i => i.extra?.stacks?.items ?? []);
1138
+ const indicators = getIndicatorItems(chartConfig);
1139
+ const allStacks = indicators.flatMap(i => getStackItems(i));
1057
1140
  const stackItem = allStacks.find(s => s.key === selectedX);
1058
1141
  if (stackItem) {
1059
- chartConfig.groups.items.forEach(g => { g.selected = false; });
1060
- chartConfig.groups.items.push(_makeSynthetic({
1142
+ groupItems.forEach(g => { g.selected = false; });
1143
+ groupItems.push(_makeSynthetic({
1061
1144
  key: stackItem.key,
1062
1145
  selected: true,
1063
1146
  menu: stackItem.menu,
@@ -1069,14 +1152,15 @@ function _applyXSelection(selectedX, chartConfig) {
1069
1152
  }
1070
1153
  function _applyYSelection(selectedY, selectedYAggregate, chartConfig) {
1071
1154
  const actualKey = resolveYKey(selectedY, selectedYAggregate);
1072
- chartConfig.indicators.items.forEach(i => { i.selected = i.key === actualKey; });
1073
- chartConfig.indicators.items.forEach(i => {
1074
- i.extra?.stacks?.items?.forEach((s) => { s.selected = false; });
1155
+ const indicators = getIndicatorItems(chartConfig);
1156
+ indicators.forEach(i => { i.selected = i.key === actualKey; });
1157
+ indicators.forEach(i => {
1158
+ getStackItems(i).forEach((s) => { s.selected = false; });
1075
1159
  });
1076
1160
  }
1077
1161
  function _applyGroupBySelection(effectiveGroupBy, chartConfig) {
1078
- const activeIndicator = chartConfig.indicators.items.find(i => i.selected);
1079
- const stackItems = activeIndicator?.extra?.stacks?.items ?? [];
1162
+ const activeIndicator = getIndicatorItems(chartConfig).find(i => i.selected);
1163
+ const stackItems = getStackItems(activeIndicator);
1080
1164
  if (effectiveGroupBy === undefined) {
1081
1165
  stackItems.forEach(s => { s.selected = false; });
1082
1166
  return;
@@ -1086,7 +1170,7 @@ function _applyGroupBySelection(effectiveGroupBy, chartConfig) {
1086
1170
  stackItems.forEach(s => { s.selected = s.key === effectiveGroupBy; });
1087
1171
  return;
1088
1172
  }
1089
- const groupItem = chartConfig.groups.items.find(g => g.key === effectiveGroupBy);
1173
+ const groupItem = getGroupItems(chartConfig).find(g => g.key === effectiveGroupBy);
1090
1174
  if (groupItem && activeIndicator) {
1091
1175
  stackItems.forEach(s => { s.selected = false; });
1092
1176
  if (!activeIndicator.extra) {
@@ -1111,7 +1195,7 @@ function _applyGroupBySelection(effectiveGroupBy, chartConfig) {
1111
1195
  }
1112
1196
  }
1113
1197
  function _applySliceSelection(selectedSlices, chartConfig) {
1114
- chartConfig.filters?.items?.forEach(f => { f.selected = selectedSlices.includes(f.key); });
1198
+ getFilterItems(chartConfig).forEach(f => { f.selected = selectedSlices.includes(f.key); });
1115
1199
  }
1116
1200
 
1117
1201
  function humanizeKey(key) {