yukit-web 0.2.1 → 0.2.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.
@@ -1,2 +1,2 @@
1
1
 
2
- 73156870f087abb5a501996bd729e4209ae8993a {"key":"make-fetch-happen:request-cache:https://registry.npmjs.org/yukit-web","integrity":"sha512-uelFM9HXvD6YmCd91rMh6ubuogoSm9GMpjVfIRryARKFLVu7ExOYHI3BzlMqaYujEc7UyNK+5TgfWtdGphaMDQ==","time":1790932554123,"size":404684,"metadata":{"time":1790932554108,"url":"https://registry.npmjs.org/yukit-web","reqHeaders":{"accept":"application/json"},"resHeaders":{"cache-control":"public, max-age=300","content-encoding":"gzip","content-type":"application/json","date":"Fri, 02 Oct 2026 09:15:54 GMT","etag":"W/\"350e8ae7ac80104bec4de38ae2cd6cc7\"","last-modified":"Fri, 02 Oct 2026 08:40:33 GMT","vary":"accept-encoding, accept"},"options":{"compress":true}}}
2
+ 6af72865710cb6579780a2d92b5ddf2f7dd108b1 {"key":"make-fetch-happen:request-cache:https://registry.npmjs.org/yukit-web","integrity":"sha512-WwUmvyHjDKW4ry1w+KImJdk1k3Ado2q+FEmUPA+AChb6TU9iTAASxHT7VNcufHhmgODM5bue56xFGEc4PsdnPQ==","time":1790954640812,"size":423486,"metadata":{"time":1790954640794,"url":"https://registry.npmjs.org/yukit-web","reqHeaders":{"accept":"application/json"},"resHeaders":{"cache-control":"public, max-age=300","content-encoding":"gzip","content-type":"application/json","date":"Fri, 02 Oct 2026 15:24:00 GMT","etag":"W/\"bc1192cab9710288042dd212db05b3e0\"","last-modified":"Fri, 02 Oct 2026 13:58:20 GMT","vary":"accept-encoding, accept"},"options":{"compress":true}}}
@@ -5,24 +5,24 @@
5
5
  4 silly config load:file:/builds/yurest/yurest-ui/dist/yukit-web/.npmrc
6
6
  5 silly config load:file:/root/.npmrc
7
7
  6 silly config load:file:/usr/local/etc/npmrc
8
- 7 verbose title npm view yukit-web@0.2.1 version
9
- 8 verbose argv "view" "yukit-web@0.2.1" "version"
10
- 9 verbose logfile logs-max:10 dir:/builds/yurest/yurest-ui/dist/yukit-web/.npm/_logs/2026-10-02T09_15_53_709Z-
11
- 10 verbose logfile /builds/yurest/yurest-ui/dist/yukit-web/.npm/_logs/2026-10-02T09_15_53_709Z-debug-0.log
8
+ 7 verbose title npm view yukit-web@0.2.3 version
9
+ 8 verbose argv "view" "yukit-web@0.2.3" "version"
10
+ 9 verbose logfile logs-max:10 dir:/builds/yurest/yurest-ui/dist/yukit-web/.npm/_logs/2026-10-02T15_24_00_394Z-
11
+ 10 verbose logfile /builds/yurest/yurest-ui/dist/yukit-web/.npm/_logs/2026-10-02T15_24_00_394Z-debug-0.log
12
12
  11 silly logfile done cleaning log files
13
- 12 http fetch GET 200 https://registry.npmjs.org/yukit-web 217ms (cache miss)
14
- 13 verbose stack Error: No match found for version 0.2.1
13
+ 12 http fetch GET 200 https://registry.npmjs.org/yukit-web 182ms (cache miss)
14
+ 13 verbose stack Error: No match found for version 0.2.3
15
15
  13 verbose stack at #getData (/usr/local/lib/node_modules/npm/lib/commands/view.js:192:27)
16
16
  13 verbose stack at async #viewPackage (/usr/local/lib/node_modules/npm/lib/commands/view.js:112:28)
17
17
  13 verbose stack at async View.exec (/usr/local/lib/node_modules/npm/lib/commands/view.js:70:5)
18
18
  13 verbose stack at async Npm.exec (/usr/local/lib/node_modules/npm/lib/npm.js:207:9)
19
19
  13 verbose stack at async module.exports (/usr/local/lib/node_modules/npm/lib/cli/entry.js:74:5)
20
20
  14 verbose statusCode 404
21
- 15 verbose pkgid yukit-web@0.2.1
21
+ 15 verbose pkgid yukit-web@0.2.3
22
22
  16 error code E404
23
- 17 error 404 No match found for version 0.2.1
23
+ 17 error 404 No match found for version 0.2.3
24
24
  18 error 404
25
- 19 error 404 'yukit-web@0.2.1' is not in this registry.
25
+ 19 error 404 'yukit-web@0.2.3' is not in this registry.
26
26
  20 error 404
27
27
  21 error 404 Note that you can also install from a
28
28
  22 error 404 tarball, folder, http url, or git url.
@@ -32,4 +32,4 @@
32
32
  26 verbose npm v10.9.9
33
33
  27 verbose exit 1
34
34
  28 verbose code 1
35
- 29 error A complete log of this run can be found in: /builds/yurest/yurest-ui/dist/yukit-web/.npm/_logs/2026-10-02T09_15_53_709Z-debug-0.log
35
+ 29 error A complete log of this run can be found in: /builds/yurest/yurest-ui/dist/yukit-web/.npm/_logs/2026-10-02T15_24_00_394Z-debug-0.log
@@ -7,8 +7,8 @@
7
7
  6 silly config load:file:/usr/local/etc/npmrc
8
8
  7 verbose title npm publish
9
9
  8 verbose argv "publish" "--access" "public"
10
- 9 verbose logfile logs-max:10 dir:/builds/yurest/yurest-ui/dist/yukit-web/.npm/_logs/2026-10-02T09_15_54_206Z-
11
- 10 verbose logfile /builds/yurest/yurest-ui/dist/yukit-web/.npm/_logs/2026-10-02T09_15_54_206Z-debug-0.log
10
+ 9 verbose logfile logs-max:10 dir:/builds/yurest/yurest-ui/dist/yukit-web/.npm/_logs/2026-10-02T15_24_00_918Z-
11
+ 10 verbose logfile /builds/yurest/yurest-ui/dist/yukit-web/.npm/_logs/2026-10-02T15_24_00_918Z-debug-0.log
12
12
  11 silly logfile done cleaning log files
13
13
  12 verbose publish [ '.' ]
14
14
  13 silly packumentCache heap:2197815296 maxSize:549453824 maxEntrySize:274726912
@@ -15,7 +15,7 @@ import * as i1 from '@spartan-ng/brain/tooltip';
15
15
  import { provideBrnTooltipDefaultOptions, BrnTooltip } from '@spartan-ng/brain/tooltip';
16
16
  import { tooltipPositionVariants, DEFAULT_TOOLTIP_CONTENT_CLASSES, DEFAULT_TOOLTIP_SVG_CLASS } from 'yukit-web/helm/tooltip';
17
17
  import { NgIcon, provideIcons } from '@ng-icons/core';
18
- import { lucideX, lucideChevronRight, lucideChevronLeft, lucideArrowLeft, lucidePlus, lucideSearch, lucideEyeOff, lucideEye, lucideSettings2, lucideDownload, lucideTrash2, lucideStar, lucideEllipsis, lucideChevronDown, lucideChevronsUpDown, lucideChevronUp, lucidePencil } from '@ng-icons/lucide';
18
+ import { lucideX, lucideChevronRight, lucideChevronLeft, lucideArrowLeft, lucidePlus, lucideSearch, lucideEyeOff, lucideEye, lucideSettings2, lucideDownload, lucideTrash2, lucidePencil, lucideEllipsis, lucideStar, lucideFilter, lucideChevronsUpDown, lucideChevronUp, lucideChevronDown } from '@ng-icons/lucide';
19
19
  import * as i1$1 from 'yukit-web/helm/badge';
20
20
  import { HlmBadge } from 'yukit-web/helm/badge';
21
21
  import * as i1$2 from 'yukit-web/helm/breadcrumb';
@@ -3740,38 +3740,93 @@ class YuwListToolbarFilterSetFormComponent {
3740
3740
  }
3741
3741
  }
3742
3742
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.22", ngImport: i0, type: YuwListToolbarFilterSetFormComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
3743
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.22", type: YuwListToolbarFilterSetFormComponent, isStandalone: true, selector: "yuw-list-toolbar-filter-set-form", inputs: { labels: { classPropertyName: "labels", publicName: "labels", isSignal: true, isRequired: true, transformFunction: null }, mode: { classPropertyName: "mode", publicName: "mode", isSignal: true, isRequired: true, transformFunction: null }, name: { classPropertyName: "name", publicName: "name", isSignal: true, isRequired: false, transformFunction: null }, titleHidden: { classPropertyName: "titleHidden", publicName: "titleHidden", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { cancelled: "cancelled", confirmed: "confirmed", deleteRequested: "deleteRequested" }, host: { listeners: { "keydown.enter": "onConfirm()" }, classAttribute: "flex max-w-full flex-col gap-3" }, providers: [provideIcons({ lucideTrash2 })], viewQueries: [{ propertyName: "_nameInput", first: true, predicate: YuwInputComponent, descendants: true, isSignal: true }], ngImport: i0, template: "@if (!titleHidden()) {\n <p class=\"text-sm font-medium\">{{ title() }}</p>\n}\n\n@if (isDelete()) {\n <p class=\"text-sm text-muted-foreground\">{{ deleteMessage() }}</p>\n} @else {\n <div class=\"flex flex-col gap-2\">\n <label class=\"text-sm\" for=\"yuw-filter-set-name\">{{ labels().nameLabel }}</label>\n <yuw-input inputId=\"yuw-filter-set-name\" [maxlength]=\"nameMaxLength\" [(value)]=\"draftName\" />\n </div>\n}\n\n<div class=\"flex flex-wrap items-center gap-1\" [class.justify-between]=\"canDelete()\" [class.justify-end]=\"!canDelete()\">\n @if (canDelete()) {\n <yuw-button variant=\"ghost\" color=\"destructive\" size=\"sm\" class=\"gap-1\" (clicked)=\"deleteRequested.emit()\">\n <ng-icon name=\"lucideTrash2\" size=\"16\" />\n {{ labels().delete }}\n </yuw-button>\n }\n\n <span class=\"flex gap-1\">\n <yuw-button variant=\"outline\" size=\"sm\" (clicked)=\"cancelled.emit()\">{{ labels().cancel }}</yuw-button>\n <yuw-button\n size=\"sm\"\n [color]=\"isDelete() ? 'destructive' : 'neutral'\"\n [disabled]=\"!canConfirm()\"\n (clicked)=\"onConfirm()\"\n >\n {{ isDelete() ? labels().delete : labels().confirm }}\n </yuw-button>\n </span>\n</div>\n", dependencies: [{ kind: "component", type: NgIcon, selector: "ng-icon", inputs: ["name", "svg", "size", "strokeWidth", "color"] }, { kind: "component", type: YuwButtonComponent, selector: "yuw-button", inputs: ["animationDisabled", "ariaLabel", "color", "disabled", "href", "size", "target", "transparent", "type", "class", "variant", "yuwDropdownMenuTrigger"], outputs: ["clicked"] }, { kind: "component", type: YuwInputComponent, selector: "yuw-input", inputs: ["inputmode", "maxlength", "size", "type"], outputs: ["enterPressed"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
3743
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.22", type: YuwListToolbarFilterSetFormComponent, isStandalone: true, selector: "yuw-list-toolbar-filter-set-form", inputs: { labels: { classPropertyName: "labels", publicName: "labels", isSignal: true, isRequired: true, transformFunction: null }, mode: { classPropertyName: "mode", publicName: "mode", isSignal: true, isRequired: true, transformFunction: null }, name: { classPropertyName: "name", publicName: "name", isSignal: true, isRequired: false, transformFunction: null }, titleHidden: { classPropertyName: "titleHidden", publicName: "titleHidden", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { cancelled: "cancelled", confirmed: "confirmed", deleteRequested: "deleteRequested" }, host: { listeners: { "keydown.enter": "onConfirm()" }, classAttribute: "flex max-w-full flex-col gap-3" }, providers: [provideIcons({ lucideTrash2 })], viewQueries: [{ propertyName: "_nameInput", first: true, predicate: YuwInputComponent, descendants: true, isSignal: true }], ngImport: i0, template: "@if (!titleHidden()) {\n <p class=\"text-sm font-medium\">{{ title() }}</p>\n}\n\n@if (isDelete()) {\n <p class=\"text-sm text-muted-foreground\">{{ deleteMessage() }}</p>\n} @else {\n <div class=\"flex flex-col gap-2\">\n <label class=\"text-sm\" for=\"yuw-filter-set-name\">{{ labels().nameLabel }}</label>\n <yuw-input inputId=\"yuw-filter-set-name\" [maxlength]=\"nameMaxLength\" [(value)]=\"draftName\" />\n </div>\n}\n\n<div\n class=\"flex min-w-0 flex-wrap items-center gap-1\"\n [class.justify-between]=\"canDelete()\"\n [class.justify-end]=\"!canDelete()\"\n>\n @if (canDelete()) {\n <yuw-button\n variant=\"ghost\"\n color=\"destructive\"\n size=\"sm\"\n class=\"max-w-full min-w-0 gap-1\"\n (clicked)=\"deleteRequested.emit()\"\n >\n <ng-icon name=\"lucideTrash2\" size=\"16\" class=\"shrink-0\" />\n <span class=\"truncate\">{{ labels().delete }}</span>\n </yuw-button>\n }\n\n <span class=\"flex min-w-0 max-w-full gap-1\">\n <yuw-button variant=\"outline\" size=\"sm\" class=\"min-w-0\" (clicked)=\"cancelled.emit()\">\n <span class=\"truncate\">{{ labels().cancel }}</span>\n </yuw-button>\n <yuw-button\n size=\"sm\"\n class=\"min-w-0\"\n [color]=\"isDelete() ? 'destructive' : 'neutral'\"\n [disabled]=\"!canConfirm()\"\n (clicked)=\"onConfirm()\"\n >\n <span class=\"truncate\">{{ isDelete() ? labels().delete : labels().confirm }}</span>\n </yuw-button>\n </span>\n</div>\n", dependencies: [{ kind: "component", type: NgIcon, selector: "ng-icon", inputs: ["name", "svg", "size", "strokeWidth", "color"] }, { kind: "component", type: YuwButtonComponent, selector: "yuw-button", inputs: ["animationDisabled", "ariaLabel", "color", "disabled", "href", "size", "target", "transparent", "type", "class", "variant", "yuwDropdownMenuTrigger"], outputs: ["clicked"] }, { kind: "component", type: YuwInputComponent, selector: "yuw-input", inputs: ["inputmode", "maxlength", "size", "type"], outputs: ["enterPressed"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
3744
3744
  }
3745
3745
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.22", ngImport: i0, type: YuwListToolbarFilterSetFormComponent, decorators: [{
3746
3746
  type: Component,
3747
- args: [{ selector: 'yuw-list-toolbar-filter-set-form', changeDetection: ChangeDetectionStrategy.OnPush, imports: [NgIcon, YuwButtonComponent, YuwInputComponent], providers: [provideIcons({ lucideTrash2 })], host: { class: 'flex max-w-full flex-col gap-3', '(keydown.enter)': 'onConfirm()' }, template: "@if (!titleHidden()) {\n <p class=\"text-sm font-medium\">{{ title() }}</p>\n}\n\n@if (isDelete()) {\n <p class=\"text-sm text-muted-foreground\">{{ deleteMessage() }}</p>\n} @else {\n <div class=\"flex flex-col gap-2\">\n <label class=\"text-sm\" for=\"yuw-filter-set-name\">{{ labels().nameLabel }}</label>\n <yuw-input inputId=\"yuw-filter-set-name\" [maxlength]=\"nameMaxLength\" [(value)]=\"draftName\" />\n </div>\n}\n\n<div class=\"flex flex-wrap items-center gap-1\" [class.justify-between]=\"canDelete()\" [class.justify-end]=\"!canDelete()\">\n @if (canDelete()) {\n <yuw-button variant=\"ghost\" color=\"destructive\" size=\"sm\" class=\"gap-1\" (clicked)=\"deleteRequested.emit()\">\n <ng-icon name=\"lucideTrash2\" size=\"16\" />\n {{ labels().delete }}\n </yuw-button>\n }\n\n <span class=\"flex gap-1\">\n <yuw-button variant=\"outline\" size=\"sm\" (clicked)=\"cancelled.emit()\">{{ labels().cancel }}</yuw-button>\n <yuw-button\n size=\"sm\"\n [color]=\"isDelete() ? 'destructive' : 'neutral'\"\n [disabled]=\"!canConfirm()\"\n (clicked)=\"onConfirm()\"\n >\n {{ isDelete() ? labels().delete : labels().confirm }}\n </yuw-button>\n </span>\n</div>\n" }]
3747
+ args: [{ selector: 'yuw-list-toolbar-filter-set-form', changeDetection: ChangeDetectionStrategy.OnPush, imports: [NgIcon, YuwButtonComponent, YuwInputComponent], providers: [provideIcons({ lucideTrash2 })], host: { class: 'flex max-w-full flex-col gap-3', '(keydown.enter)': 'onConfirm()' }, template: "@if (!titleHidden()) {\n <p class=\"text-sm font-medium\">{{ title() }}</p>\n}\n\n@if (isDelete()) {\n <p class=\"text-sm text-muted-foreground\">{{ deleteMessage() }}</p>\n} @else {\n <div class=\"flex flex-col gap-2\">\n <label class=\"text-sm\" for=\"yuw-filter-set-name\">{{ labels().nameLabel }}</label>\n <yuw-input inputId=\"yuw-filter-set-name\" [maxlength]=\"nameMaxLength\" [(value)]=\"draftName\" />\n </div>\n}\n\n<div\n class=\"flex min-w-0 flex-wrap items-center gap-1\"\n [class.justify-between]=\"canDelete()\"\n [class.justify-end]=\"!canDelete()\"\n>\n @if (canDelete()) {\n <yuw-button\n variant=\"ghost\"\n color=\"destructive\"\n size=\"sm\"\n class=\"max-w-full min-w-0 gap-1\"\n (clicked)=\"deleteRequested.emit()\"\n >\n <ng-icon name=\"lucideTrash2\" size=\"16\" class=\"shrink-0\" />\n <span class=\"truncate\">{{ labels().delete }}</span>\n </yuw-button>\n }\n\n <span class=\"flex min-w-0 max-w-full gap-1\">\n <yuw-button variant=\"outline\" size=\"sm\" class=\"min-w-0\" (clicked)=\"cancelled.emit()\">\n <span class=\"truncate\">{{ labels().cancel }}</span>\n </yuw-button>\n <yuw-button\n size=\"sm\"\n class=\"min-w-0\"\n [color]=\"isDelete() ? 'destructive' : 'neutral'\"\n [disabled]=\"!canConfirm()\"\n (clicked)=\"onConfirm()\"\n >\n <span class=\"truncate\">{{ isDelete() ? labels().delete : labels().confirm }}</span>\n </yuw-button>\n </span>\n</div>\n" }]
3748
3748
  }], ctorParameters: () => [], propDecorators: { _nameInput: [{ type: i0.ViewChild, args: [i0.forwardRef(() => YuwInputComponent), { isSignal: true }] }], labels: [{ type: i0.Input, args: [{ isSignal: true, alias: "labels", required: true }] }], mode: [{ type: i0.Input, args: [{ isSignal: true, alias: "mode", required: true }] }], name: [{ type: i0.Input, args: [{ isSignal: true, alias: "name", required: false }] }], titleHidden: [{ type: i0.Input, args: [{ isSignal: true, alias: "titleHidden", required: false }] }], cancelled: [{ type: i0.Output, args: ["cancelled"] }], confirmed: [{ type: i0.Output, args: ["confirmed"] }], deleteRequested: [{ type: i0.Output, args: ["deleteRequested"] }] } });
3749
3749
 
3750
- const NO_SET = '__yuw_no_set__';
3750
+ const NO_FILTER_SET = '__yuw_no_set__';
3751
+ const STRETCHED_CELL = 'min-w-0 flex-1 [&>yuw-button]:flex [&>yuw-button]:w-full';
3751
3752
  /**
3752
- * Filter control of `yuw-list-toolbar`. From `md` up the editor is a two-pane panel in a popover;
3753
- * below it, one tab per group in a bottom sheet.
3754
- *
3755
- * Each layout keeps its own trigger: the popover anchors to the element holding
3756
- * `yuwPopoverTrigger`, so it cannot come from a shared `ng-template`. `activeCount` reads the
3757
- * applied selection, not the draft. Opening the editor discards unapplied draft changes.
3758
- *
3759
- * Saved sets are on when both `sets` and `labels.sets` are given. A star left of the title saves the
3760
- * applied selection under a name. While that exact selection is already a set the star is filled and
3761
- * opens that set's rename view, which also offers delete. Once
3762
- * there are sets, a select applies one. Choosing "none" restores the selection held before the first
3763
- * set was applied, but only while a set is the one applied, so it never discards hand-picked filters.
3764
- * Below `md` the sets select collapses to an icon button that opens it, so the toolbar keeps one
3765
- * line; the select stays mounted but invisible, right-aligned under the button, so its list has an
3766
- * anchor and a usable width.
3767
- * Naming, renaming and deleting a set replace the editor inside the same popover or sheet. The view
3768
- * is reset when the panel opens, not when it closes, so it does not flash back while closing. A change
3769
- * of layout closes the panel, since a popover opened from a sheet has no anchor to position against.
3753
+ * Sets view of the filters panel: a select with the saved sets and the action that fits the applied
3754
+ * selection. `canSave` offers to save it as a new set, `canEdit` to edit or delete the set it
3755
+ * matches; with neither it is just the list.
3756
+ *
3757
+ * Every option but "none" shows a three-dots button on hover or keyboard highlight, which closes the
3758
+ * list and emits `itemEditRequested` with that set's id. The component owns no state: choosing an
3759
+ * option emits `picked` and the host applies it. `titleHidden` drops the heading when the host
3760
+ * already shows it. `stretchActions` makes edit and delete share the row 50/50 with no gap; without
3761
+ * it they keep their natural width. Button texts are consumer data, so they are cropped, not wrapped.
3762
+ */
3763
+ class YuwListToolbarFilterSetsComponent {
3764
+ constructor() {
3765
+ this._combobox = viewChild(YuwComboboxComponent, ...(ngDevMode ? [{ debugName: "_combobox" }] : /* istanbul ignore next */ []));
3766
+ this.canEdit = input(false, ...(ngDevMode ? [{ debugName: "canEdit" }] : /* istanbul ignore next */ []));
3767
+ this.canSave = input(false, ...(ngDevMode ? [{ debugName: "canSave" }] : /* istanbul ignore next */ []));
3768
+ this.labels = input.required(...(ngDevMode ? [{ debugName: "labels" }] : /* istanbul ignore next */ []));
3769
+ this.selectedId = input(NO_FILTER_SET, ...(ngDevMode ? [{ debugName: "selectedId" }] : /* istanbul ignore next */ []));
3770
+ this.sets = input.required(...(ngDevMode ? [{ debugName: "sets" }] : /* istanbul ignore next */ []));
3771
+ this.stretchActions = input(false, ...(ngDevMode ? [{ debugName: "stretchActions" }] : /* istanbul ignore next */ []));
3772
+ this.titleHidden = input(false, ...(ngDevMode ? [{ debugName: "titleHidden" }] : /* istanbul ignore next */ []));
3773
+ this.deleteRequested = output();
3774
+ this.editRequested = output();
3775
+ this.itemEditRequested = output();
3776
+ this.picked = output();
3777
+ this.saveRequested = output();
3778
+ this.stretchedCell = STRETCHED_CELL;
3779
+ this.options = computed(() => {
3780
+ const sets = this.sets();
3781
+ return sets.length > 0
3782
+ ? [
3783
+ { value: NO_FILTER_SET, label: this.labels().none, data: false },
3784
+ ...sets.map((set) => ({ value: set.id, label: set.name, data: true })),
3785
+ ]
3786
+ : [];
3787
+ }, ...(ngDevMode ? [{ debugName: "options" }] : /* istanbul ignore next */ []));
3788
+ }
3789
+ onItemEdit(id) {
3790
+ this._combobox()?.close();
3791
+ this.itemEditRequested.emit(id);
3792
+ }
3793
+ onPick(value) {
3794
+ if (typeof value === 'string') {
3795
+ this.picked.emit(value);
3796
+ }
3797
+ }
3798
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.22", ngImport: i0, type: YuwListToolbarFilterSetsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
3799
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.22", type: YuwListToolbarFilterSetsComponent, isStandalone: true, selector: "yuw-list-toolbar-filter-sets", inputs: { canEdit: { classPropertyName: "canEdit", publicName: "canEdit", isSignal: true, isRequired: false, transformFunction: null }, canSave: { classPropertyName: "canSave", publicName: "canSave", isSignal: true, isRequired: false, transformFunction: null }, labels: { classPropertyName: "labels", publicName: "labels", isSignal: true, isRequired: true, transformFunction: null }, selectedId: { classPropertyName: "selectedId", publicName: "selectedId", isSignal: true, isRequired: false, transformFunction: null }, sets: { classPropertyName: "sets", publicName: "sets", isSignal: true, isRequired: true, transformFunction: null }, stretchActions: { classPropertyName: "stretchActions", publicName: "stretchActions", isSignal: true, isRequired: false, transformFunction: null }, titleHidden: { classPropertyName: "titleHidden", publicName: "titleHidden", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { deleteRequested: "deleteRequested", editRequested: "editRequested", itemEditRequested: "itemEditRequested", picked: "picked", saveRequested: "saveRequested" }, host: { classAttribute: "flex max-w-full flex-col gap-3" }, providers: [provideIcons({ lucideEllipsis, lucidePencil, lucideTrash2 })], viewQueries: [{ propertyName: "_combobox", first: true, predicate: YuwComboboxComponent, descendants: true, isSignal: true }], ngImport: i0, template: "@if (!titleHidden()) {\n <p class=\"text-sm font-medium\">{{ labels().title }}</p>\n}\n\n<yuw-combobox\n readonlyTrigger\n [options]=\"options()\"\n [value]=\"options().length > 0 ? selectedId() : undefined\"\n [placeholder]=\"labels().select\"\n [emptyText]=\"labels().empty\"\n [triggerAriaLabel]=\"labels().select\"\n (valueChange)=\"onPick($event)\"\n>\n <ng-template yuwComboboxItem let-option>\n <span class=\"min-w-0 flex-1 truncate\">{{ option.label }}</span>\n\n @if (option.data) {\n <span\n class=\"inline-flex opacity-0 transition-opacity duration-150 focus-within:opacity-100 [[data-highlighted]_&]:opacity-100\"\n (click)=\"$event.stopPropagation()\"\n >\n <yuw-button variant=\"ghost\" size=\"icon-sm\" [ariaLabel]=\"labels().edit\" (clicked)=\"onItemEdit(option.value)\">\n <ng-icon name=\"lucideEllipsis\" size=\"14\" />\n </yuw-button>\n </span>\n }\n </ng-template>\n</yuw-combobox>\n\n@if (canSave()) {\n <yuw-button variant=\"outline\" size=\"sm\" class=\"max-w-full min-w-0\" (clicked)=\"saveRequested.emit()\">\n <span class=\"truncate\">{{ labels().save }}</span>\n </yuw-button>\n}\n\n@if (canEdit()) {\n <div class=\"flex min-w-0 max-w-full\" [class.gap-1]=\"!stretchActions()\">\n <div [class]=\"stretchActions() ? stretchedCell : 'min-w-0'\">\n <yuw-button\n variant=\"outline\"\n size=\"sm\"\n [class]=\"stretchActions() ? 'w-full min-w-0 gap-1' : 'max-w-full min-w-0 gap-1'\"\n (clicked)=\"editRequested.emit()\"\n >\n <ng-icon name=\"lucidePencil\" size=\"16\" class=\"shrink-0\" />\n <span class=\"truncate\">{{ labels().edit }}</span>\n </yuw-button>\n </div>\n <div [class]=\"stretchActions() ? stretchedCell : 'min-w-0'\">\n <yuw-button\n variant=\"ghost\"\n color=\"destructive\"\n size=\"sm\"\n [class]=\"stretchActions() ? 'w-full min-w-0 gap-1' : 'max-w-full min-w-0 gap-1'\"\n (clicked)=\"deleteRequested.emit()\"\n >\n <ng-icon name=\"lucideTrash2\" size=\"16\" class=\"shrink-0\" />\n <span class=\"truncate\">{{ labels().delete }}</span>\n </yuw-button>\n </div>\n </div>\n}\n", dependencies: [{ kind: "component", type: NgIcon, selector: "ng-icon", inputs: ["name", "svg", "size", "strokeWidth", "color"] }, { kind: "component", type: YuwButtonComponent, selector: "yuw-button", inputs: ["animationDisabled", "ariaLabel", "color", "disabled", "href", "size", "target", "transparent", "type", "class", "variant", "yuwDropdownMenuTrigger"], outputs: ["clicked"] }, { kind: "component", type: YuwComboboxComponent, selector: "yuw-combobox", inputs: ["clearAriaLabel", "emptyText", "inputId", "invalid", "keepValueOnEscape", "multiple", "options", "placeholder", "readonlyTrigger", "search", "searchPlaceholder", "size", "triggerAriaLabel", "value"], outputs: ["searchChange", "valueChange"] }, { kind: "directive", type: YuwComboboxItemDirective, selector: "[yuwComboboxItem]", inputs: ["yuwComboboxItemTypeOf"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
3800
+ }
3801
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.22", ngImport: i0, type: YuwListToolbarFilterSetsComponent, decorators: [{
3802
+ type: Component,
3803
+ args: [{ selector: 'yuw-list-toolbar-filter-sets', changeDetection: ChangeDetectionStrategy.OnPush, imports: [NgIcon, YuwButtonComponent, YuwComboboxComponent, YuwComboboxItemDirective], providers: [provideIcons({ lucideEllipsis, lucidePencil, lucideTrash2 })], host: { class: 'flex max-w-full flex-col gap-3' }, template: "@if (!titleHidden()) {\n <p class=\"text-sm font-medium\">{{ labels().title }}</p>\n}\n\n<yuw-combobox\n readonlyTrigger\n [options]=\"options()\"\n [value]=\"options().length > 0 ? selectedId() : undefined\"\n [placeholder]=\"labels().select\"\n [emptyText]=\"labels().empty\"\n [triggerAriaLabel]=\"labels().select\"\n (valueChange)=\"onPick($event)\"\n>\n <ng-template yuwComboboxItem let-option>\n <span class=\"min-w-0 flex-1 truncate\">{{ option.label }}</span>\n\n @if (option.data) {\n <span\n class=\"inline-flex opacity-0 transition-opacity duration-150 focus-within:opacity-100 [[data-highlighted]_&]:opacity-100\"\n (click)=\"$event.stopPropagation()\"\n >\n <yuw-button variant=\"ghost\" size=\"icon-sm\" [ariaLabel]=\"labels().edit\" (clicked)=\"onItemEdit(option.value)\">\n <ng-icon name=\"lucideEllipsis\" size=\"14\" />\n </yuw-button>\n </span>\n }\n </ng-template>\n</yuw-combobox>\n\n@if (canSave()) {\n <yuw-button variant=\"outline\" size=\"sm\" class=\"max-w-full min-w-0\" (clicked)=\"saveRequested.emit()\">\n <span class=\"truncate\">{{ labels().save }}</span>\n </yuw-button>\n}\n\n@if (canEdit()) {\n <div class=\"flex min-w-0 max-w-full\" [class.gap-1]=\"!stretchActions()\">\n <div [class]=\"stretchActions() ? stretchedCell : 'min-w-0'\">\n <yuw-button\n variant=\"outline\"\n size=\"sm\"\n [class]=\"stretchActions() ? 'w-full min-w-0 gap-1' : 'max-w-full min-w-0 gap-1'\"\n (clicked)=\"editRequested.emit()\"\n >\n <ng-icon name=\"lucidePencil\" size=\"16\" class=\"shrink-0\" />\n <span class=\"truncate\">{{ labels().edit }}</span>\n </yuw-button>\n </div>\n <div [class]=\"stretchActions() ? stretchedCell : 'min-w-0'\">\n <yuw-button\n variant=\"ghost\"\n color=\"destructive\"\n size=\"sm\"\n [class]=\"stretchActions() ? 'w-full min-w-0 gap-1' : 'max-w-full min-w-0 gap-1'\"\n (clicked)=\"deleteRequested.emit()\"\n >\n <ng-icon name=\"lucideTrash2\" size=\"16\" class=\"shrink-0\" />\n <span class=\"truncate\">{{ labels().delete }}</span>\n </yuw-button>\n </div>\n </div>\n}\n" }]
3804
+ }], propDecorators: { _combobox: [{ type: i0.ViewChild, args: [i0.forwardRef(() => YuwComboboxComponent), { isSignal: true }] }], canEdit: [{ type: i0.Input, args: [{ isSignal: true, alias: "canEdit", required: false }] }], canSave: [{ type: i0.Input, args: [{ isSignal: true, alias: "canSave", required: false }] }], labels: [{ type: i0.Input, args: [{ isSignal: true, alias: "labels", required: true }] }], selectedId: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectedId", required: false }] }], sets: [{ type: i0.Input, args: [{ isSignal: true, alias: "sets", required: true }] }], stretchActions: [{ type: i0.Input, args: [{ isSignal: true, alias: "stretchActions", required: false }] }], titleHidden: [{ type: i0.Input, args: [{ isSignal: true, alias: "titleHidden", required: false }] }], deleteRequested: [{ type: i0.Output, args: ["deleteRequested"] }], editRequested: [{ type: i0.Output, args: ["editRequested"] }], itemEditRequested: [{ type: i0.Output, args: ["itemEditRequested"] }], picked: [{ type: i0.Output, args: ["picked"] }], saveRequested: [{ type: i0.Output, args: ["saveRequested"] }] } });
3805
+
3806
+ const FORM_VIEWS = new Set(['save', 'rename', 'delete']);
3807
+ /**
3808
+ * Filter control of `yuw-list-toolbar`: one welded group of buttons that opens a single panel, a
3809
+ * popover from `md` up and a bottom sheet below it. The panel shows one view at a time: the filter
3810
+ * editor (two panes in the popover, one tab per group in the sheet), the saved sets, or the form
3811
+ * that names, renames or deletes a set.
3812
+ *
3813
+ * The group reads: star (sets) followed by the name of the set that matches the applied selection,
3814
+ * filter icon with the count of applied values, and a clear button. Every button swaps the panel view itself
3815
+ * and stops the click, so the popover trigger never double-toggles; pressing the button of the
3816
+ * view already showing closes the panel. `activeCount` reads the applied selection, not the draft,
3817
+ * and opening the panel discards unapplied draft changes.
3818
+ *
3819
+ * Saved sets are on when both `sets` and `labels.sets` are given; without them the star is not
3820
+ * rendered. The star is never disabled. The sets view lists the sets and offers what fits the
3821
+ * applied selection: save it when it matches no set, edit or delete when it matches one. Choosing
3822
+ * "none" restores the selection held before the first set was applied, but only while a set is the
3823
+ * one applied, so it never discards hand-picked filters. The view is reset when the panel is
3824
+ * opened from a button, not when it closes, so it does not flash back while closing. A change of
3825
+ * layout closes the panel, since a popover opened from a sheet has no anchor to position against.
3770
3826
  * Persisting is the consumer's job: this component only emits `setSaved`, `setRenamed`, `setDeleted`.
3771
3827
  */
3772
3828
  class YuwListToolbarFiltersComponent {
3773
3829
  constructor() {
3774
- this._setsCombobox = viewChild(YuwComboboxComponent, ...(ngDevMode ? [{ debugName: "_setsCombobox" }] : /* istanbul ignore next */ []));
3775
3830
  this.disabled = input(false, { ...(ngDevMode ? { debugName: "disabled" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
3776
3831
  this.groups = input.required(...(ngDevMode ? [{ debugName: "groups" }] : /* istanbul ignore next */ []));
3777
3832
  this.idleColor = input.required(...(ngDevMode ? [{ debugName: "idleColor" }] : /* istanbul ignore next */ []));
@@ -3785,10 +3840,9 @@ class YuwListToolbarFiltersComponent {
3785
3840
  this._activeGroupId = signal(null, ...(ngDevMode ? [{ debugName: "_activeGroupId" }] : /* istanbul ignore next */ []));
3786
3841
  this._selectionBeforeSet = signal(undefined, ...(ngDevMode ? [{ debugName: "_selectionBeforeSet" }] : /* istanbul ignore next */ []));
3787
3842
  this._setPanelId = signal(undefined, ...(ngDevMode ? [{ debugName: "_setPanelId" }] : /* istanbul ignore next */ []));
3788
- this._setPanelRequested = false;
3789
3843
  this.draft = new YuwFilterDraft(this.selection);
3790
3844
  this.open = signal(false, ...(ngDevMode ? [{ debugName: "open" }] : /* istanbul ignore next */ []));
3791
- this.setPanelMode = signal(null, ...(ngDevMode ? [{ debugName: "setPanelMode" }] : /* istanbul ignore next */ []));
3845
+ this.panelView = signal('filters', ...(ngDevMode ? [{ debugName: "panelView" }] : /* istanbul ignore next */ []));
3792
3846
  this.activeCount = computed(() => countSelectedValues(this.selection()), ...(ngDevMode ? [{ debugName: "activeCount" }] : /* istanbul ignore next */ []));
3793
3847
  this.activeGroup = computed(() => {
3794
3848
  const groups = this.groups();
@@ -3802,57 +3856,49 @@ class YuwListToolbarFiltersComponent {
3802
3856
  }, ...(ngDevMode ? [{ debugName: "matchingSet" }] : /* istanbul ignore next */ []));
3803
3857
  this.setLabels = computed(() => (this.sets() ? this.labels().sets : undefined), ...(ngDevMode ? [{ debugName: "setLabels" }] : /* istanbul ignore next */ []));
3804
3858
  this.buttons = computed(() => {
3805
- const active = this.hasActive();
3859
+ const variant = this.hasActive() ? 'secondary' : 'outline';
3806
3860
  const disabled = this.disabled();
3807
3861
  const { title, clearAll } = this.labels();
3808
3862
  const setLabels = this.setLabels();
3809
- const matching = this.matchingSet();
3810
3863
  const entries = [
3811
- {
3812
- id: 'filters',
3813
- label: active ? `${title} : ${this.activeCount()}` : title,
3814
- variant: active ? 'secondary' : 'outline',
3815
- disabled,
3816
- },
3864
+ { id: 'filters', ariaLabel: title, tooltip: title, size: 'icon', variant, disabled },
3817
3865
  ];
3818
3866
  if (setLabels) {
3819
3867
  entries.unshift({
3820
- id: 'save',
3821
- ariaLabel: setLabels.save,
3822
- tooltip: matching ? setLabels.edit : setLabels.save,
3823
- variant: active ? 'secondary' : 'outline',
3824
- size: 'icon',
3825
- disabled: disabled || !active,
3868
+ id: 'sets',
3869
+ ariaLabel: setLabels.title,
3870
+ tooltip: setLabels.title,
3871
+ size: this.matchingSet() ? 'default' : 'icon',
3872
+ variant,
3873
+ disabled,
3826
3874
  });
3827
3875
  }
3828
- if (active) {
3876
+ if (this.hasActive()) {
3829
3877
  entries.push({ id: 'clear', ariaLabel: clearAll, size: 'icon', disabled });
3830
3878
  }
3831
3879
  return entries;
3832
3880
  }, ...(ngDevMode ? [{ debugName: "buttons" }] : /* istanbul ignore next */ []));
3833
3881
  this.buttonsColor = computed(() => (this.hasActive() ? 'secondary' : this.idleColor()), ...(ngDevMode ? [{ debugName: "buttonsColor" }] : /* istanbul ignore next */ []));
3834
- this.selectedSetId = computed(() => this.matchingSet()?.id ?? NO_SET, ...(ngDevMode ? [{ debugName: "selectedSetId" }] : /* istanbul ignore next */ []));
3882
+ this.canSaveSet = computed(() => this.hasActive() && !this.matchingSet(), ...(ngDevMode ? [{ debugName: "canSaveSet" }] : /* istanbul ignore next */ []));
3883
+ this.selectedSetId = computed(() => this.matchingSet()?.id ?? NO_FILTER_SET, ...(ngDevMode ? [{ debugName: "selectedSetId" }] : /* istanbul ignore next */ []));
3835
3884
  this.selectedText = computed(() => this.labels().selected(this.draft.selectedCount()), ...(ngDevMode ? [{ debugName: "selectedText" }] : /* istanbul ignore next */ []));
3836
- this.setOptions = computed(() => {
3837
- const labels = this.setLabels();
3838
- const sets = this.sets() ?? [];
3839
- return labels && sets.length > 0
3840
- ? [
3841
- { value: NO_SET, label: labels.none, data: false },
3842
- ...sets.map((set) => ({ value: set.id, label: set.name, data: true })),
3843
- ]
3844
- : [];
3845
- }, ...(ngDevMode ? [{ debugName: "setOptions" }] : /* istanbul ignore next */ []));
3885
+ this.setPanelMode = computed(() => {
3886
+ const view = this.panelView();
3887
+ return FORM_VIEWS.has(view) ? view : null;
3888
+ }, ...(ngDevMode ? [{ debugName: "setPanelMode" }] : /* istanbul ignore next */ []));
3846
3889
  this.setPanelName = computed(() => this.sets()?.find((set) => set.id === this._setPanelId())?.name ?? '', ...(ngDevMode ? [{ debugName: "setPanelName" }] : /* istanbul ignore next */ []));
3847
3890
  this.sheetTitle = computed(() => {
3848
3891
  const mode = this.setPanelMode();
3849
- const labels = this.setLabels();
3850
- return mode && labels ? filterSetFormTitle(mode, labels) : this.labels().title;
3892
+ const setLabels = this.setLabels();
3893
+ if (mode && setLabels) {
3894
+ return filterSetFormTitle(mode, setLabels);
3895
+ }
3896
+ return this.panelView() === 'sets' && setLabels ? setLabels.title : this.labels().title;
3851
3897
  }, ...(ngDevMode ? [{ debugName: "sheetTitle" }] : /* istanbul ignore next */ []));
3852
3898
  this.tabs = computed(() => this.groups().map((group) => ({ id: group.id, label: group.label })), ...(ngDevMode ? [{ debugName: "tabs" }] : /* istanbul ignore next */ []));
3853
3899
  effect(() => {
3854
3900
  if (this.open()) {
3855
- untracked(() => this._onOpened());
3901
+ untracked(() => this.draft.reset());
3856
3902
  }
3857
3903
  });
3858
3904
  effect(() => {
@@ -3864,28 +3910,19 @@ class YuwListToolbarFiltersComponent {
3864
3910
  this.commit(this.draft.snapshot());
3865
3911
  }
3866
3912
  onButtonClicked({ id, event }) {
3867
- if (id === 'save') {
3868
- event.stopPropagation();
3869
- event.preventDefault();
3870
- const matching = this.matchingSet();
3871
- this.openSetPanel(matching ? 'rename' : 'save', matching?.id);
3872
- return;
3873
- }
3913
+ event.stopPropagation();
3914
+ event.preventDefault();
3874
3915
  if (id === 'clear') {
3875
- event.stopPropagation();
3876
- event.preventDefault();
3877
3916
  this.commit({});
3878
3917
  return;
3879
3918
  }
3880
- if (this.isMobile()) {
3881
- this.open.set(true);
3882
- }
3919
+ this.togglePanel(id === 'filters' ? 'filters' : 'sets');
3883
3920
  }
3884
3921
  onOptionChange(group, value, checked) {
3885
3922
  this.draft.toggle(group, value, checked);
3886
3923
  }
3887
3924
  onSetDeleteRequested() {
3888
- this.setPanelMode.set('delete');
3925
+ this.panelView.set('delete');
3889
3926
  }
3890
3927
  onSetFormConfirmed(name) {
3891
3928
  const mode = this.setPanelMode();
@@ -3901,10 +3938,10 @@ class YuwListToolbarFiltersComponent {
3901
3938
  this.open.set(false);
3902
3939
  }
3903
3940
  onSetPicked(value) {
3904
- if (typeof value !== 'string' || value === this.selectedSetId()) {
3941
+ if (value === this.selectedSetId()) {
3905
3942
  return;
3906
3943
  }
3907
- if (value === NO_SET) {
3944
+ if (value === NO_FILTER_SET) {
3908
3945
  this.selection.set(this._selectionBeforeSet() ?? {});
3909
3946
  this._selectionBeforeSet.set(undefined);
3910
3947
  return;
@@ -3919,34 +3956,27 @@ class YuwListToolbarFiltersComponent {
3919
3956
  this.selection.set(set.selection);
3920
3957
  }
3921
3958
  openSetPanel(mode, setId) {
3922
- this._setPanelRequested = !this.open();
3923
- this.setPanelMode.set(mode);
3924
3959
  this._setPanelId.set(setId);
3960
+ this.panelView.set(mode);
3925
3961
  this.open.set(true);
3926
3962
  }
3927
- openSetPanelFromList(mode, setId) {
3928
- this._setsCombobox()?.close();
3929
- requestAnimationFrame(() => this.openSetPanel(mode, setId));
3930
- }
3931
- openSetsList() {
3932
- this._setsCombobox()?.open();
3933
- }
3934
3963
  selectGroup(groupId) {
3935
3964
  this._activeGroupId.set(groupId);
3936
3965
  }
3937
- _onOpened() {
3938
- this.draft.reset();
3939
- if (!this._setPanelRequested) {
3940
- this.setPanelMode.set(null);
3941
- }
3942
- this._setPanelRequested = false;
3943
- }
3944
3966
  commit(selection) {
3945
3967
  this.selection.set(selection);
3946
3968
  this.open.set(false);
3947
3969
  }
3970
+ togglePanel(view) {
3971
+ if (this.open() && this.panelView() === view) {
3972
+ this.open.set(false);
3973
+ return;
3974
+ }
3975
+ this.panelView.set(view);
3976
+ this.open.set(true);
3977
+ }
3948
3978
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.22", ngImport: i0, type: YuwListToolbarFiltersComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
3949
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.22", type: YuwListToolbarFiltersComponent, isStandalone: true, selector: "yuw-list-toolbar-filters", inputs: { disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, groups: { classPropertyName: "groups", publicName: "groups", isSignal: true, isRequired: true, transformFunction: null }, idleColor: { classPropertyName: "idleColor", publicName: "idleColor", isSignal: true, isRequired: true, transformFunction: null }, isMobile: { classPropertyName: "isMobile", publicName: "isMobile", isSignal: true, isRequired: true, transformFunction: null }, labels: { classPropertyName: "labels", publicName: "labels", isSignal: true, isRequired: true, transformFunction: null }, selection: { classPropertyName: "selection", publicName: "selection", isSignal: true, isRequired: false, transformFunction: null }, sets: { classPropertyName: "sets", publicName: "sets", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { selection: "selectionChange", setDeleted: "setDeleted", setRenamed: "setRenamed", setSaved: "setSaved" }, host: { classAttribute: "flex min-w-0 max-w-full items-center gap-1" }, providers: [provideIcons({ lucideChevronDown, lucideEllipsis, lucideStar, lucideX })], viewQueries: [{ propertyName: "_setsCombobox", first: true, predicate: YuwComboboxComponent, descendants: true, isSignal: true }], ngImport: i0, template: "<ng-template #options let-group>\n <ul class=\"flex flex-col gap-1\" [attr.aria-label]=\"group.label\">\n @for (option of group.options; track option.value) {\n <li>\n <label\n class=\"flex cursor-pointer items-center justify-between gap-3 rounded-md px-3 py-1 text-sm transition-colors hover:bg-accent/45\"\n [for]=\"`${group.id}-option-${option.value}`\"\n >\n <span class=\"min-w-0 truncate\">{{ option.label }}</span>\n\n <yuw-checkbox\n [inputId]=\"`${group.id}-option-${option.value}`\"\n [checked]=\"draft.checkedValues()[group.id]?.has(option.value) ?? false\"\n [disabled]=\"option.disabled ?? false\"\n [ariaLabel]=\"option.label\"\n (checkedChange)=\"onOptionChange(group, option.value, $event)\"\n />\n </label>\n </li>\n }\n </ul>\n</ng-template>\n\n<ng-template #starIcon>\n <ng-icon name=\"lucideStar\" size=\"16\" [class]=\"matchingSet() ? '[&_svg]:fill-current' : ''\" />\n</ng-template>\n\n<ng-template #setForm let-sheet>\n @if (setPanelMode(); as mode) {\n <yuw-list-toolbar-filter-set-form\n [class]=\"sheet ? 'w-full pb-3' : 'w-64 p-1'\"\n [titleHidden]=\"sheet\"\n [labels]=\"setLabels()!\"\n [mode]=\"mode\"\n [name]=\"setPanelName()\"\n (cancelled)=\"open.set(false)\"\n (confirmed)=\"onSetFormConfirmed($event)\"\n (deleteRequested)=\"onSetDeleteRequested()\"\n />\n }\n</ng-template>\n\n<ng-template #commitRow>\n @if (selectedText(); as text) {\n <p class=\"text-end text-xs text-muted-foreground pr-2\">{{ text }}</p>\n }\n\n <div class=\"flex justify-end gap-2 pt-3\">\n <yuw-button variant=\"outline\" (clicked)=\"draft.clear()\">\n {{ labels().clear }}\n </yuw-button>\n\n <yuw-button (clicked)=\"onApply()\">\n {{ labels().apply }}\n </yuw-button>\n </div>\n</ng-template>\n\n@if (isMobile()) {\n <yuw-button-group\n variant=\"secondary\"\n [buttons]=\"buttons()\"\n [color]=\"buttonsColor()\"\n [ariaLabel]=\"labels().title\"\n (buttonClicked)=\"onButtonClicked($event)\"\n >\n <ng-template yuwButtonGroupContent=\"save\">\n <ng-container [ngTemplateOutlet]=\"starIcon\" />\n </ng-template>\n <ng-template yuwButtonGroupContent=\"clear\">\n <ng-icon name=\"lucideX\" size=\"16\" />\n </ng-template>\n </yuw-button-group>\n\n <yuw-sheet\n side=\"bottom\"\n panelClass=\"max-h-[85svh] overflow-y-auto\"\n [showTrigger]=\"false\"\n [title]=\"sheetTitle()\"\n [closeLabel]=\"labels().close\"\n [(open)]=\"open\"\n >\n @if (setPanelMode()) {\n <ng-container [ngTemplateOutlet]=\"setForm\" [ngTemplateOutletContext]=\"{ $implicit: true }\" />\n } @else {\n <div class=\"flex min-h-0 flex-col gap-3\">\n <yuw-tabs\n class=\"max-w-full justify-start overflow-x-auto overflow-y-hidden scrollbar-none [&::-webkit-scrollbar]:hidden scroll-fade-x\"\n [tabs]=\"tabs()\"\n [activeTab]=\"activeGroup()?.id ?? ''\"\n (activeTabChange)=\"selectGroup($event)\"\n >\n @for (group of groups(); track group.id) {\n <ng-template [yuwTabContent]=\"group.id\">\n <span class=\"flex items-center gap-1.5 whitespace-nowrap\">\n {{ group.label }}\n\n @if (draft.pendingGroupIds().has(group.id)) {\n <yuw-badge\n dot\n color=\"secondary\"\n style=\"width: 0.5rem; height: 0.5rem\"\n [attr.aria-label]=\"labels().pending\"\n [attr.title]=\"labels().pending\"\n />\n }\n </span>\n </ng-template>\n\n <ng-template [yuwTabPanel]=\"group.id\">\n <div class=\"max-h-[45svh] overflow-y-auto pt-2\">\n <ng-container [ngTemplateOutlet]=\"options\" [ngTemplateOutletContext]=\"{ $implicit: group }\" />\n </div>\n </ng-template>\n }\n </yuw-tabs>\n\n <div class=\"pb-3\">\n <ng-container [ngTemplateOutlet]=\"commitRow\" />\n </div>\n </div>\n }\n </yuw-sheet>\n} @else {\n <yuw-popover align=\"start\" panelClass=\"w-auto p-2 dark:border\" triggerClass=\"px-0\" triggerTransparent [(open)]=\"open\">\n <yuw-button-group\n yuwPopoverTrigger\n variant=\"secondary\"\n [buttons]=\"buttons()\"\n [color]=\"buttonsColor()\"\n [ariaLabel]=\"labels().title\"\n (buttonClicked)=\"onButtonClicked($event)\"\n >\n <ng-template yuwButtonGroupContent=\"save\">\n <ng-container [ngTemplateOutlet]=\"starIcon\" />\n </ng-template>\n <ng-template yuwButtonGroupContent=\"clear\">\n <ng-icon name=\"lucideX\" size=\"16\" />\n </ng-template>\n </yuw-button-group>\n @if (setPanelMode()) {\n <ng-container [ngTemplateOutlet]=\"setForm\" [ngTemplateOutletContext]=\"{ $implicit: false }\" />\n } @else {\n <div class=\"flex min-w-0\">\n <ul class=\"flex w-44 shrink-0 flex-col gap-1 pe-2\">\n @for (group of groups(); track group.id) {\n <li>\n <button\n type=\"button\"\n class=\"flex w-full items-center gap-2 rounded-md px-3 py-2 text-start text-sm transition-colors hover:bg-accent/45\"\n [class.bg-accent/45]=\"activeGroup()?.id === group.id\"\n [attr.aria-current]=\"activeGroup()?.id === group.id ? 'true' : null\"\n (click)=\"selectGroup(group.id)\"\n >\n <span class=\"min-w-0 flex-1 truncate\">{{ group.label }}</span>\n\n @if (draft.pendingGroupIds().has(group.id)) {\n <yuw-badge\n dot\n color=\"secondary\"\n style=\"width: 0.5rem; height: 0.5rem\"\n [attr.aria-label]=\"labels().pending\"\n [attr.title]=\"labels().pending\"\n />\n }\n </button>\n </li>\n }\n </ul>\n\n @if (activeGroup(); as group) {\n <div class=\"flex min-w-0 flex-1 flex-col gap-3 border-s p-3\">\n <ng-container [ngTemplateOutlet]=\"options\" [ngTemplateOutletContext]=\"{ $implicit: group }\" />\n <ng-container [ngTemplateOutlet]=\"commitRow\" />\n </div>\n }\n </div>\n }\n </yuw-popover>\n}\n\n@if (setLabels(); as labels) {\n @if (setOptions().length > 0) {\n <div [class]=\"isMobile() ? 'relative inline-flex' : 'w-full max-w-52.5'\">\n @if (isMobile()) {\n <yuw-button variant=\"outline\" size=\"icon\" [ariaLabel]=\"labels.select\" (clicked)=\"openSetsList()\">\n <ng-icon name=\"lucideChevronDown\" size=\"16\" />\n </yuw-button>\n }\n\n <div [class]=\"isMobile() ? 'pointer-events-none absolute top-0 right-0 h-full w-52 opacity-0' : 'contents'\">\n <yuw-combobox\n readonlyTrigger\n [options]=\"setOptions()\"\n [value]=\"selectedSetId()\"\n [triggerAriaLabel]=\"labels.select\"\n [placeholder]=\"labels.select\"\n (valueChange)=\"onSetPicked($event)\"\n >\n <ng-template yuwComboboxItem let-option>\n <span class=\"min-w-0 flex-1 truncate\">{{ option.label }}</span>\n\n @if (option.data) {\n <span class=\"inline-flex\" (click)=\"$event.stopPropagation()\">\n <yuw-button\n variant=\"ghost\"\n size=\"icon-sm\"\n [ariaLabel]=\"labels.edit\"\n (clicked)=\"openSetPanelFromList('rename', option.value)\"\n >\n <ng-icon name=\"lucideEllipsis\" size=\"14\" />\n </yuw-button>\n </span>\n }\n </ng-template>\n </yuw-combobox>\n </div>\n </div>\n }\n}\n", styles: [".scrollbar-none{scrollbar-width:none}\n"], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: NgIcon, selector: "ng-icon", inputs: ["name", "svg", "size", "strokeWidth", "color"] }, { kind: "component", type: YuwBadgeComponent, selector: "yuw-badge", inputs: ["color", "dot", "removeLabel", "variant"], outputs: ["removed"] }, { kind: "component", type: YuwButtonComponent, selector: "yuw-button", inputs: ["animationDisabled", "ariaLabel", "color", "disabled", "href", "size", "target", "transparent", "type", "class", "variant", "yuwDropdownMenuTrigger"], outputs: ["clicked"] }, { kind: "component", type: YuwButtonGroupComponent, selector: "yuw-button-group", inputs: ["ariaLabel", "buttons", "color", "orientation", "selectedColor", "selectedVariant", "size", "variant"], outputs: ["buttonClicked"] }, { kind: "directive", type: YuwButtonGroupContentDirective, selector: "ng-template[yuwButtonGroupContent]", inputs: ["yuwButtonGroupContent"] }, { kind: "component", type: YuwCheckboxComponent, selector: "yuw-checkbox", inputs: ["ariaDescribedby", "ariaLabel", "ariaLabelledby", "indeterminate", "inputId", "invalid", "name", "primary", "required", "checked"], outputs: ["indeterminateChange", "checkedChange"] }, { kind: "component", type: YuwComboboxComponent, selector: "yuw-combobox", inputs: ["clearAriaLabel", "emptyText", "inputId", "invalid", "keepValueOnEscape", "multiple", "options", "placeholder", "readonlyTrigger", "search", "searchPlaceholder", "size", "triggerAriaLabel", "value"], outputs: ["searchChange", "valueChange"] }, { kind: "directive", type: YuwComboboxItemDirective, selector: "[yuwComboboxItem]", inputs: ["yuwComboboxItemTypeOf"] }, { kind: "component", type: YuwListToolbarFilterSetFormComponent, selector: "yuw-list-toolbar-filter-set-form", inputs: ["labels", "mode", "name", "titleHidden"], outputs: ["cancelled", "confirmed", "deleteRequested"] }, { kind: "component", type: YuwPopoverComponent, selector: "yuw-popover", inputs: ["align", "description", "offsetX", "open", "panelClass", "showTrigger", "sideOffset", "title", "triggerClass", "triggerColor", "triggerSize", "triggerTransparent", "triggerVariant"], outputs: ["openChange"] }, { kind: "component", type: YuwSheetComponent, selector: "yuw-sheet", inputs: ["ariaLabel", "ariaModal", "closeLabel", "closeOnOutsidePointerEvents", "description", "open", "overlayClass", "panelClass", "scrollStrategy", "showTrigger", "side", "title", "triggerSize", "triggerVariant"], outputs: ["openChange"] }, { kind: "directive", type: YuwTabContentDirective, selector: "ng-template[yuwTabContent]", inputs: ["yuwTabContent"] }, { kind: "directive", type: YuwTabPanelDirective, selector: "ng-template[yuwTabPanel]", inputs: ["yuwTabPanel"] }, { kind: "component", type: YuwTabsComponent, selector: "yuw-tabs", inputs: ["activationMode", "activeTab", "orientation", "size", "tabs", "class", "variant"], outputs: ["activeTabChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
3979
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.22", type: YuwListToolbarFiltersComponent, isStandalone: true, selector: "yuw-list-toolbar-filters", inputs: { disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, groups: { classPropertyName: "groups", publicName: "groups", isSignal: true, isRequired: true, transformFunction: null }, idleColor: { classPropertyName: "idleColor", publicName: "idleColor", isSignal: true, isRequired: true, transformFunction: null }, isMobile: { classPropertyName: "isMobile", publicName: "isMobile", isSignal: true, isRequired: true, transformFunction: null }, labels: { classPropertyName: "labels", publicName: "labels", isSignal: true, isRequired: true, transformFunction: null }, selection: { classPropertyName: "selection", publicName: "selection", isSignal: true, isRequired: false, transformFunction: null }, sets: { classPropertyName: "sets", publicName: "sets", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { selection: "selectionChange", setDeleted: "setDeleted", setRenamed: "setRenamed", setSaved: "setSaved" }, host: { classAttribute: "flex min-w-0 max-w-full items-center gap-1" }, providers: [provideIcons({ lucideFilter, lucideStar, lucideX })], ngImport: i0, template: "<ng-template #options let-group>\n <ul class=\"flex flex-col gap-1\" [attr.aria-label]=\"group.label\">\n @for (option of group.options; track option.value) {\n <li>\n <label\n class=\"flex cursor-pointer items-center justify-between gap-3 rounded-md px-3 py-1 text-sm transition-colors hover:bg-accent/45\"\n [for]=\"`${group.id}-option-${option.value}`\"\n >\n <span class=\"min-w-0 truncate\">{{ option.label }}</span>\n\n <yuw-checkbox\n [inputId]=\"`${group.id}-option-${option.value}`\"\n [checked]=\"draft.checkedValues()[group.id]?.has(option.value) ?? false\"\n [disabled]=\"option.disabled ?? false\"\n [ariaLabel]=\"option.label\"\n (checkedChange)=\"onOptionChange(group, option.value, $event)\"\n />\n </label>\n </li>\n }\n </ul>\n</ng-template>\n\n<ng-template #starIcon>\n <ng-icon name=\"lucideStar\" size=\"16\" [class]=\"matchingSet() ? '[&_svg]:fill-current' : ''\" />\n\n @if (matchingSet(); as set) {\n <span class=\"block max-w-[25ch] truncate\">{{ set.name }}</span>\n }\n</ng-template>\n\n<ng-template #filterIcon>\n <span class=\"relative inline-flex\">\n <ng-icon name=\"lucideFilter\" size=\"16\" />\n\n @if (hasActive()) {\n <yuw-badge\n color=\"destructive\"\n class=\"absolute -top-2.5 -right-2.5 h-4 min-w-4 justify-center px-1 text-[10px] leading-none\"\n data-testid=\"active-filters-count\"\n >\n {{ activeCount() }}\n </yuw-badge>\n }\n </span>\n</ng-template>\n\n<ng-template #setForm let-sheet>\n @if (setPanelMode(); as mode) {\n <yuw-list-toolbar-filter-set-form\n [class]=\"sheet ? 'w-full pb-3' : 'w-64 p-1'\"\n [titleHidden]=\"sheet\"\n [labels]=\"setLabels()!\"\n [mode]=\"mode\"\n [name]=\"setPanelName()\"\n (cancelled)=\"open.set(false)\"\n (confirmed)=\"onSetFormConfirmed($event)\"\n (deleteRequested)=\"onSetDeleteRequested()\"\n />\n }\n</ng-template>\n\n<ng-template #setsView let-sheet>\n <yuw-list-toolbar-filter-sets\n [class]=\"sheet ? 'w-full pb-3' : 'w-64 p-1'\"\n [titleHidden]=\"sheet\"\n [stretchActions]=\"!sheet\"\n [labels]=\"setLabels()!\"\n [sets]=\"sets() ?? []\"\n [selectedId]=\"selectedSetId()\"\n [canSave]=\"canSaveSet()\"\n [canEdit]=\"!!matchingSet()\"\n (picked)=\"onSetPicked($event)\"\n (itemEditRequested)=\"openSetPanel('rename', $event)\"\n (saveRequested)=\"openSetPanel('save')\"\n (editRequested)=\"openSetPanel('rename', matchingSet()?.id)\"\n (deleteRequested)=\"openSetPanel('delete', matchingSet()?.id)\"\n />\n</ng-template>\n\n<ng-template #commitRow>\n @if (selectedText(); as text) {\n <p class=\"text-end text-xs text-muted-foreground pr-2\">{{ text }}</p>\n }\n\n <div class=\"flex justify-end gap-2 pt-3\">\n <yuw-button variant=\"outline\" (clicked)=\"draft.clear()\">\n {{ labels().clear }}\n </yuw-button>\n\n <yuw-button (clicked)=\"onApply()\">\n {{ labels().apply }}\n </yuw-button>\n </div>\n</ng-template>\n\n@if (isMobile()) {\n <yuw-button-group\n variant=\"secondary\"\n [buttons]=\"buttons()\"\n [color]=\"buttonsColor()\"\n [ariaLabel]=\"labels().title\"\n (buttonClicked)=\"onButtonClicked($event)\"\n >\n <ng-template yuwButtonGroupContent=\"sets\">\n <ng-container [ngTemplateOutlet]=\"starIcon\" />\n </ng-template>\n <ng-template yuwButtonGroupContent=\"filters\">\n <ng-container [ngTemplateOutlet]=\"filterIcon\" />\n </ng-template>\n <ng-template yuwButtonGroupContent=\"clear\">\n <ng-icon name=\"lucideX\" size=\"16\" />\n </ng-template>\n </yuw-button-group>\n\n <yuw-sheet\n side=\"bottom\"\n panelClass=\"max-h-[85svh] overflow-y-auto\"\n [showTrigger]=\"false\"\n [title]=\"sheetTitle()\"\n [closeLabel]=\"labels().close\"\n [(open)]=\"open\"\n >\n @switch (panelView()) {\n @case ('filters') {\n <div class=\"flex min-h-0 flex-col gap-3\">\n <yuw-tabs\n class=\"max-w-full justify-start overflow-x-auto overflow-y-hidden scrollbar-none [&::-webkit-scrollbar]:hidden scroll-fade-x\"\n [tabs]=\"tabs()\"\n [activeTab]=\"activeGroup()?.id ?? ''\"\n (activeTabChange)=\"selectGroup($event)\"\n >\n @for (group of groups(); track group.id) {\n <ng-template [yuwTabContent]=\"group.id\">\n <span class=\"flex items-center gap-1.5 whitespace-nowrap\">\n {{ group.label }}\n\n @if (draft.pendingGroupIds().has(group.id)) {\n <yuw-badge\n dot\n color=\"secondary\"\n style=\"width: 0.5rem; height: 0.5rem\"\n [attr.aria-label]=\"labels().pending\"\n [attr.title]=\"labels().pending\"\n />\n }\n </span>\n </ng-template>\n\n <ng-template [yuwTabPanel]=\"group.id\">\n <div class=\"max-h-[45svh] overflow-y-auto pt-2\">\n <ng-container [ngTemplateOutlet]=\"options\" [ngTemplateOutletContext]=\"{ $implicit: group }\" />\n </div>\n </ng-template>\n }\n </yuw-tabs>\n\n <div class=\"pb-3\">\n <ng-container [ngTemplateOutlet]=\"commitRow\" />\n </div>\n </div>\n }\n @case ('sets') {\n <ng-container [ngTemplateOutlet]=\"setsView\" [ngTemplateOutletContext]=\"{ $implicit: true }\" />\n }\n @default {\n <ng-container [ngTemplateOutlet]=\"setForm\" [ngTemplateOutletContext]=\"{ $implicit: true }\" />\n }\n }\n </yuw-sheet>\n} @else {\n <yuw-popover align=\"start\" panelClass=\"w-auto p-2 dark:border\" triggerClass=\"px-0\" triggerTransparent [(open)]=\"open\">\n <yuw-button-group\n yuwPopoverTrigger\n variant=\"secondary\"\n [buttons]=\"buttons()\"\n [color]=\"buttonsColor()\"\n [ariaLabel]=\"labels().title\"\n (buttonClicked)=\"onButtonClicked($event)\"\n >\n <ng-template yuwButtonGroupContent=\"sets\">\n <ng-container [ngTemplateOutlet]=\"starIcon\" />\n </ng-template>\n <ng-template yuwButtonGroupContent=\"filters\">\n <ng-container [ngTemplateOutlet]=\"filterIcon\" />\n </ng-template>\n <ng-template yuwButtonGroupContent=\"clear\">\n <ng-icon name=\"lucideX\" size=\"16\" />\n </ng-template>\n </yuw-button-group>\n\n @switch (panelView()) {\n @case ('filters') {\n <div class=\"flex min-w-0\">\n <ul class=\"flex w-44 shrink-0 flex-col gap-1 pe-2\">\n @for (group of groups(); track group.id) {\n <li>\n <button\n type=\"button\"\n class=\"flex w-full items-center gap-2 rounded-md px-3 py-2 text-start text-sm transition-colors hover:bg-accent/45\"\n [class.bg-accent/45]=\"activeGroup()?.id === group.id\"\n [attr.aria-current]=\"activeGroup()?.id === group.id ? 'true' : null\"\n (click)=\"selectGroup(group.id)\"\n >\n <span class=\"min-w-0 flex-1 truncate\">{{ group.label }}</span>\n\n @if (draft.pendingGroupIds().has(group.id)) {\n <yuw-badge\n dot\n color=\"secondary\"\n style=\"width: 0.5rem; height: 0.5rem\"\n [attr.aria-label]=\"labels().pending\"\n [attr.title]=\"labels().pending\"\n />\n }\n </button>\n </li>\n }\n </ul>\n\n @if (activeGroup(); as group) {\n <div class=\"flex min-w-0 flex-1 flex-col gap-3 border-s p-3\">\n <ng-container [ngTemplateOutlet]=\"options\" [ngTemplateOutletContext]=\"{ $implicit: group }\" />\n <ng-container [ngTemplateOutlet]=\"commitRow\" />\n </div>\n }\n </div>\n }\n @case ('sets') {\n <ng-container [ngTemplateOutlet]=\"setsView\" [ngTemplateOutletContext]=\"{ $implicit: false }\" />\n }\n @default {\n <ng-container [ngTemplateOutlet]=\"setForm\" [ngTemplateOutletContext]=\"{ $implicit: false }\" />\n }\n }\n </yuw-popover>\n}\n", styles: [".scrollbar-none{scrollbar-width:none}\n"], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: NgIcon, selector: "ng-icon", inputs: ["name", "svg", "size", "strokeWidth", "color"] }, { kind: "component", type: YuwBadgeComponent, selector: "yuw-badge", inputs: ["color", "dot", "removeLabel", "variant"], outputs: ["removed"] }, { kind: "component", type: YuwButtonComponent, selector: "yuw-button", inputs: ["animationDisabled", "ariaLabel", "color", "disabled", "href", "size", "target", "transparent", "type", "class", "variant", "yuwDropdownMenuTrigger"], outputs: ["clicked"] }, { kind: "component", type: YuwButtonGroupComponent, selector: "yuw-button-group", inputs: ["ariaLabel", "buttons", "color", "orientation", "selectedColor", "selectedVariant", "size", "variant"], outputs: ["buttonClicked"] }, { kind: "directive", type: YuwButtonGroupContentDirective, selector: "ng-template[yuwButtonGroupContent]", inputs: ["yuwButtonGroupContent"] }, { kind: "component", type: YuwCheckboxComponent, selector: "yuw-checkbox", inputs: ["ariaDescribedby", "ariaLabel", "ariaLabelledby", "indeterminate", "inputId", "invalid", "name", "primary", "required", "checked"], outputs: ["indeterminateChange", "checkedChange"] }, { kind: "component", type: YuwListToolbarFilterSetFormComponent, selector: "yuw-list-toolbar-filter-set-form", inputs: ["labels", "mode", "name", "titleHidden"], outputs: ["cancelled", "confirmed", "deleteRequested"] }, { kind: "component", type: YuwListToolbarFilterSetsComponent, selector: "yuw-list-toolbar-filter-sets", inputs: ["canEdit", "canSave", "labels", "selectedId", "sets", "stretchActions", "titleHidden"], outputs: ["deleteRequested", "editRequested", "itemEditRequested", "picked", "saveRequested"] }, { kind: "component", type: YuwPopoverComponent, selector: "yuw-popover", inputs: ["align", "description", "offsetX", "open", "panelClass", "showTrigger", "sideOffset", "title", "triggerClass", "triggerColor", "triggerSize", "triggerTransparent", "triggerVariant"], outputs: ["openChange"] }, { kind: "component", type: YuwSheetComponent, selector: "yuw-sheet", inputs: ["ariaLabel", "ariaModal", "closeLabel", "closeOnOutsidePointerEvents", "description", "open", "overlayClass", "panelClass", "scrollStrategy", "showTrigger", "side", "title", "triggerSize", "triggerVariant"], outputs: ["openChange"] }, { kind: "directive", type: YuwTabContentDirective, selector: "ng-template[yuwTabContent]", inputs: ["yuwTabContent"] }, { kind: "directive", type: YuwTabPanelDirective, selector: "ng-template[yuwTabPanel]", inputs: ["yuwTabPanel"] }, { kind: "component", type: YuwTabsComponent, selector: "yuw-tabs", inputs: ["activationMode", "activeTab", "orientation", "size", "tabs", "class", "variant"], outputs: ["activeTabChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
3950
3980
  }
3951
3981
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.22", ngImport: i0, type: YuwListToolbarFiltersComponent, decorators: [{
3952
3982
  type: Component,
@@ -3958,16 +3988,15 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.22", ngImpo
3958
3988
  YuwButtonGroupComponent,
3959
3989
  YuwButtonGroupContentDirective,
3960
3990
  YuwCheckboxComponent,
3961
- YuwComboboxComponent,
3962
- YuwComboboxItemDirective,
3963
3991
  YuwListToolbarFilterSetFormComponent,
3992
+ YuwListToolbarFilterSetsComponent,
3964
3993
  YuwPopoverComponent,
3965
3994
  YuwSheetComponent,
3966
3995
  YuwTabContentDirective,
3967
3996
  YuwTabPanelDirective,
3968
3997
  YuwTabsComponent,
3969
- ], providers: [provideIcons({ lucideChevronDown, lucideEllipsis, lucideStar, lucideX })], host: { class: 'flex min-w-0 max-w-full items-center gap-1' }, template: "<ng-template #options let-group>\n <ul class=\"flex flex-col gap-1\" [attr.aria-label]=\"group.label\">\n @for (option of group.options; track option.value) {\n <li>\n <label\n class=\"flex cursor-pointer items-center justify-between gap-3 rounded-md px-3 py-1 text-sm transition-colors hover:bg-accent/45\"\n [for]=\"`${group.id}-option-${option.value}`\"\n >\n <span class=\"min-w-0 truncate\">{{ option.label }}</span>\n\n <yuw-checkbox\n [inputId]=\"`${group.id}-option-${option.value}`\"\n [checked]=\"draft.checkedValues()[group.id]?.has(option.value) ?? false\"\n [disabled]=\"option.disabled ?? false\"\n [ariaLabel]=\"option.label\"\n (checkedChange)=\"onOptionChange(group, option.value, $event)\"\n />\n </label>\n </li>\n }\n </ul>\n</ng-template>\n\n<ng-template #starIcon>\n <ng-icon name=\"lucideStar\" size=\"16\" [class]=\"matchingSet() ? '[&_svg]:fill-current' : ''\" />\n</ng-template>\n\n<ng-template #setForm let-sheet>\n @if (setPanelMode(); as mode) {\n <yuw-list-toolbar-filter-set-form\n [class]=\"sheet ? 'w-full pb-3' : 'w-64 p-1'\"\n [titleHidden]=\"sheet\"\n [labels]=\"setLabels()!\"\n [mode]=\"mode\"\n [name]=\"setPanelName()\"\n (cancelled)=\"open.set(false)\"\n (confirmed)=\"onSetFormConfirmed($event)\"\n (deleteRequested)=\"onSetDeleteRequested()\"\n />\n }\n</ng-template>\n\n<ng-template #commitRow>\n @if (selectedText(); as text) {\n <p class=\"text-end text-xs text-muted-foreground pr-2\">{{ text }}</p>\n }\n\n <div class=\"flex justify-end gap-2 pt-3\">\n <yuw-button variant=\"outline\" (clicked)=\"draft.clear()\">\n {{ labels().clear }}\n </yuw-button>\n\n <yuw-button (clicked)=\"onApply()\">\n {{ labels().apply }}\n </yuw-button>\n </div>\n</ng-template>\n\n@if (isMobile()) {\n <yuw-button-group\n variant=\"secondary\"\n [buttons]=\"buttons()\"\n [color]=\"buttonsColor()\"\n [ariaLabel]=\"labels().title\"\n (buttonClicked)=\"onButtonClicked($event)\"\n >\n <ng-template yuwButtonGroupContent=\"save\">\n <ng-container [ngTemplateOutlet]=\"starIcon\" />\n </ng-template>\n <ng-template yuwButtonGroupContent=\"clear\">\n <ng-icon name=\"lucideX\" size=\"16\" />\n </ng-template>\n </yuw-button-group>\n\n <yuw-sheet\n side=\"bottom\"\n panelClass=\"max-h-[85svh] overflow-y-auto\"\n [showTrigger]=\"false\"\n [title]=\"sheetTitle()\"\n [closeLabel]=\"labels().close\"\n [(open)]=\"open\"\n >\n @if (setPanelMode()) {\n <ng-container [ngTemplateOutlet]=\"setForm\" [ngTemplateOutletContext]=\"{ $implicit: true }\" />\n } @else {\n <div class=\"flex min-h-0 flex-col gap-3\">\n <yuw-tabs\n class=\"max-w-full justify-start overflow-x-auto overflow-y-hidden scrollbar-none [&::-webkit-scrollbar]:hidden scroll-fade-x\"\n [tabs]=\"tabs()\"\n [activeTab]=\"activeGroup()?.id ?? ''\"\n (activeTabChange)=\"selectGroup($event)\"\n >\n @for (group of groups(); track group.id) {\n <ng-template [yuwTabContent]=\"group.id\">\n <span class=\"flex items-center gap-1.5 whitespace-nowrap\">\n {{ group.label }}\n\n @if (draft.pendingGroupIds().has(group.id)) {\n <yuw-badge\n dot\n color=\"secondary\"\n style=\"width: 0.5rem; height: 0.5rem\"\n [attr.aria-label]=\"labels().pending\"\n [attr.title]=\"labels().pending\"\n />\n }\n </span>\n </ng-template>\n\n <ng-template [yuwTabPanel]=\"group.id\">\n <div class=\"max-h-[45svh] overflow-y-auto pt-2\">\n <ng-container [ngTemplateOutlet]=\"options\" [ngTemplateOutletContext]=\"{ $implicit: group }\" />\n </div>\n </ng-template>\n }\n </yuw-tabs>\n\n <div class=\"pb-3\">\n <ng-container [ngTemplateOutlet]=\"commitRow\" />\n </div>\n </div>\n }\n </yuw-sheet>\n} @else {\n <yuw-popover align=\"start\" panelClass=\"w-auto p-2 dark:border\" triggerClass=\"px-0\" triggerTransparent [(open)]=\"open\">\n <yuw-button-group\n yuwPopoverTrigger\n variant=\"secondary\"\n [buttons]=\"buttons()\"\n [color]=\"buttonsColor()\"\n [ariaLabel]=\"labels().title\"\n (buttonClicked)=\"onButtonClicked($event)\"\n >\n <ng-template yuwButtonGroupContent=\"save\">\n <ng-container [ngTemplateOutlet]=\"starIcon\" />\n </ng-template>\n <ng-template yuwButtonGroupContent=\"clear\">\n <ng-icon name=\"lucideX\" size=\"16\" />\n </ng-template>\n </yuw-button-group>\n @if (setPanelMode()) {\n <ng-container [ngTemplateOutlet]=\"setForm\" [ngTemplateOutletContext]=\"{ $implicit: false }\" />\n } @else {\n <div class=\"flex min-w-0\">\n <ul class=\"flex w-44 shrink-0 flex-col gap-1 pe-2\">\n @for (group of groups(); track group.id) {\n <li>\n <button\n type=\"button\"\n class=\"flex w-full items-center gap-2 rounded-md px-3 py-2 text-start text-sm transition-colors hover:bg-accent/45\"\n [class.bg-accent/45]=\"activeGroup()?.id === group.id\"\n [attr.aria-current]=\"activeGroup()?.id === group.id ? 'true' : null\"\n (click)=\"selectGroup(group.id)\"\n >\n <span class=\"min-w-0 flex-1 truncate\">{{ group.label }}</span>\n\n @if (draft.pendingGroupIds().has(group.id)) {\n <yuw-badge\n dot\n color=\"secondary\"\n style=\"width: 0.5rem; height: 0.5rem\"\n [attr.aria-label]=\"labels().pending\"\n [attr.title]=\"labels().pending\"\n />\n }\n </button>\n </li>\n }\n </ul>\n\n @if (activeGroup(); as group) {\n <div class=\"flex min-w-0 flex-1 flex-col gap-3 border-s p-3\">\n <ng-container [ngTemplateOutlet]=\"options\" [ngTemplateOutletContext]=\"{ $implicit: group }\" />\n <ng-container [ngTemplateOutlet]=\"commitRow\" />\n </div>\n }\n </div>\n }\n </yuw-popover>\n}\n\n@if (setLabels(); as labels) {\n @if (setOptions().length > 0) {\n <div [class]=\"isMobile() ? 'relative inline-flex' : 'w-full max-w-52.5'\">\n @if (isMobile()) {\n <yuw-button variant=\"outline\" size=\"icon\" [ariaLabel]=\"labels.select\" (clicked)=\"openSetsList()\">\n <ng-icon name=\"lucideChevronDown\" size=\"16\" />\n </yuw-button>\n }\n\n <div [class]=\"isMobile() ? 'pointer-events-none absolute top-0 right-0 h-full w-52 opacity-0' : 'contents'\">\n <yuw-combobox\n readonlyTrigger\n [options]=\"setOptions()\"\n [value]=\"selectedSetId()\"\n [triggerAriaLabel]=\"labels.select\"\n [placeholder]=\"labels.select\"\n (valueChange)=\"onSetPicked($event)\"\n >\n <ng-template yuwComboboxItem let-option>\n <span class=\"min-w-0 flex-1 truncate\">{{ option.label }}</span>\n\n @if (option.data) {\n <span class=\"inline-flex\" (click)=\"$event.stopPropagation()\">\n <yuw-button\n variant=\"ghost\"\n size=\"icon-sm\"\n [ariaLabel]=\"labels.edit\"\n (clicked)=\"openSetPanelFromList('rename', option.value)\"\n >\n <ng-icon name=\"lucideEllipsis\" size=\"14\" />\n </yuw-button>\n </span>\n }\n </ng-template>\n </yuw-combobox>\n </div>\n </div>\n }\n}\n", styles: [".scrollbar-none{scrollbar-width:none}\n"] }]
3970
- }], ctorParameters: () => [], propDecorators: { _setsCombobox: [{ type: i0.ViewChild, args: [i0.forwardRef(() => YuwComboboxComponent), { isSignal: true }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], groups: [{ type: i0.Input, args: [{ isSignal: true, alias: "groups", required: true }] }], idleColor: [{ type: i0.Input, args: [{ isSignal: true, alias: "idleColor", required: true }] }], isMobile: [{ type: i0.Input, args: [{ isSignal: true, alias: "isMobile", required: true }] }], labels: [{ type: i0.Input, args: [{ isSignal: true, alias: "labels", required: true }] }], selection: [{ type: i0.Input, args: [{ isSignal: true, alias: "selection", required: false }] }, { type: i0.Output, args: ["selectionChange"] }], sets: [{ type: i0.Input, args: [{ isSignal: true, alias: "sets", required: false }] }], setDeleted: [{ type: i0.Output, args: ["setDeleted"] }], setRenamed: [{ type: i0.Output, args: ["setRenamed"] }], setSaved: [{ type: i0.Output, args: ["setSaved"] }] } });
3998
+ ], providers: [provideIcons({ lucideFilter, lucideStar, lucideX })], host: { class: 'flex min-w-0 max-w-full items-center gap-1' }, template: "<ng-template #options let-group>\n <ul class=\"flex flex-col gap-1\" [attr.aria-label]=\"group.label\">\n @for (option of group.options; track option.value) {\n <li>\n <label\n class=\"flex cursor-pointer items-center justify-between gap-3 rounded-md px-3 py-1 text-sm transition-colors hover:bg-accent/45\"\n [for]=\"`${group.id}-option-${option.value}`\"\n >\n <span class=\"min-w-0 truncate\">{{ option.label }}</span>\n\n <yuw-checkbox\n [inputId]=\"`${group.id}-option-${option.value}`\"\n [checked]=\"draft.checkedValues()[group.id]?.has(option.value) ?? false\"\n [disabled]=\"option.disabled ?? false\"\n [ariaLabel]=\"option.label\"\n (checkedChange)=\"onOptionChange(group, option.value, $event)\"\n />\n </label>\n </li>\n }\n </ul>\n</ng-template>\n\n<ng-template #starIcon>\n <ng-icon name=\"lucideStar\" size=\"16\" [class]=\"matchingSet() ? '[&_svg]:fill-current' : ''\" />\n\n @if (matchingSet(); as set) {\n <span class=\"block max-w-[25ch] truncate\">{{ set.name }}</span>\n }\n</ng-template>\n\n<ng-template #filterIcon>\n <span class=\"relative inline-flex\">\n <ng-icon name=\"lucideFilter\" size=\"16\" />\n\n @if (hasActive()) {\n <yuw-badge\n color=\"destructive\"\n class=\"absolute -top-2.5 -right-2.5 h-4 min-w-4 justify-center px-1 text-[10px] leading-none\"\n data-testid=\"active-filters-count\"\n >\n {{ activeCount() }}\n </yuw-badge>\n }\n </span>\n</ng-template>\n\n<ng-template #setForm let-sheet>\n @if (setPanelMode(); as mode) {\n <yuw-list-toolbar-filter-set-form\n [class]=\"sheet ? 'w-full pb-3' : 'w-64 p-1'\"\n [titleHidden]=\"sheet\"\n [labels]=\"setLabels()!\"\n [mode]=\"mode\"\n [name]=\"setPanelName()\"\n (cancelled)=\"open.set(false)\"\n (confirmed)=\"onSetFormConfirmed($event)\"\n (deleteRequested)=\"onSetDeleteRequested()\"\n />\n }\n</ng-template>\n\n<ng-template #setsView let-sheet>\n <yuw-list-toolbar-filter-sets\n [class]=\"sheet ? 'w-full pb-3' : 'w-64 p-1'\"\n [titleHidden]=\"sheet\"\n [stretchActions]=\"!sheet\"\n [labels]=\"setLabels()!\"\n [sets]=\"sets() ?? []\"\n [selectedId]=\"selectedSetId()\"\n [canSave]=\"canSaveSet()\"\n [canEdit]=\"!!matchingSet()\"\n (picked)=\"onSetPicked($event)\"\n (itemEditRequested)=\"openSetPanel('rename', $event)\"\n (saveRequested)=\"openSetPanel('save')\"\n (editRequested)=\"openSetPanel('rename', matchingSet()?.id)\"\n (deleteRequested)=\"openSetPanel('delete', matchingSet()?.id)\"\n />\n</ng-template>\n\n<ng-template #commitRow>\n @if (selectedText(); as text) {\n <p class=\"text-end text-xs text-muted-foreground pr-2\">{{ text }}</p>\n }\n\n <div class=\"flex justify-end gap-2 pt-3\">\n <yuw-button variant=\"outline\" (clicked)=\"draft.clear()\">\n {{ labels().clear }}\n </yuw-button>\n\n <yuw-button (clicked)=\"onApply()\">\n {{ labels().apply }}\n </yuw-button>\n </div>\n</ng-template>\n\n@if (isMobile()) {\n <yuw-button-group\n variant=\"secondary\"\n [buttons]=\"buttons()\"\n [color]=\"buttonsColor()\"\n [ariaLabel]=\"labels().title\"\n (buttonClicked)=\"onButtonClicked($event)\"\n >\n <ng-template yuwButtonGroupContent=\"sets\">\n <ng-container [ngTemplateOutlet]=\"starIcon\" />\n </ng-template>\n <ng-template yuwButtonGroupContent=\"filters\">\n <ng-container [ngTemplateOutlet]=\"filterIcon\" />\n </ng-template>\n <ng-template yuwButtonGroupContent=\"clear\">\n <ng-icon name=\"lucideX\" size=\"16\" />\n </ng-template>\n </yuw-button-group>\n\n <yuw-sheet\n side=\"bottom\"\n panelClass=\"max-h-[85svh] overflow-y-auto\"\n [showTrigger]=\"false\"\n [title]=\"sheetTitle()\"\n [closeLabel]=\"labels().close\"\n [(open)]=\"open\"\n >\n @switch (panelView()) {\n @case ('filters') {\n <div class=\"flex min-h-0 flex-col gap-3\">\n <yuw-tabs\n class=\"max-w-full justify-start overflow-x-auto overflow-y-hidden scrollbar-none [&::-webkit-scrollbar]:hidden scroll-fade-x\"\n [tabs]=\"tabs()\"\n [activeTab]=\"activeGroup()?.id ?? ''\"\n (activeTabChange)=\"selectGroup($event)\"\n >\n @for (group of groups(); track group.id) {\n <ng-template [yuwTabContent]=\"group.id\">\n <span class=\"flex items-center gap-1.5 whitespace-nowrap\">\n {{ group.label }}\n\n @if (draft.pendingGroupIds().has(group.id)) {\n <yuw-badge\n dot\n color=\"secondary\"\n style=\"width: 0.5rem; height: 0.5rem\"\n [attr.aria-label]=\"labels().pending\"\n [attr.title]=\"labels().pending\"\n />\n }\n </span>\n </ng-template>\n\n <ng-template [yuwTabPanel]=\"group.id\">\n <div class=\"max-h-[45svh] overflow-y-auto pt-2\">\n <ng-container [ngTemplateOutlet]=\"options\" [ngTemplateOutletContext]=\"{ $implicit: group }\" />\n </div>\n </ng-template>\n }\n </yuw-tabs>\n\n <div class=\"pb-3\">\n <ng-container [ngTemplateOutlet]=\"commitRow\" />\n </div>\n </div>\n }\n @case ('sets') {\n <ng-container [ngTemplateOutlet]=\"setsView\" [ngTemplateOutletContext]=\"{ $implicit: true }\" />\n }\n @default {\n <ng-container [ngTemplateOutlet]=\"setForm\" [ngTemplateOutletContext]=\"{ $implicit: true }\" />\n }\n }\n </yuw-sheet>\n} @else {\n <yuw-popover align=\"start\" panelClass=\"w-auto p-2 dark:border\" triggerClass=\"px-0\" triggerTransparent [(open)]=\"open\">\n <yuw-button-group\n yuwPopoverTrigger\n variant=\"secondary\"\n [buttons]=\"buttons()\"\n [color]=\"buttonsColor()\"\n [ariaLabel]=\"labels().title\"\n (buttonClicked)=\"onButtonClicked($event)\"\n >\n <ng-template yuwButtonGroupContent=\"sets\">\n <ng-container [ngTemplateOutlet]=\"starIcon\" />\n </ng-template>\n <ng-template yuwButtonGroupContent=\"filters\">\n <ng-container [ngTemplateOutlet]=\"filterIcon\" />\n </ng-template>\n <ng-template yuwButtonGroupContent=\"clear\">\n <ng-icon name=\"lucideX\" size=\"16\" />\n </ng-template>\n </yuw-button-group>\n\n @switch (panelView()) {\n @case ('filters') {\n <div class=\"flex min-w-0\">\n <ul class=\"flex w-44 shrink-0 flex-col gap-1 pe-2\">\n @for (group of groups(); track group.id) {\n <li>\n <button\n type=\"button\"\n class=\"flex w-full items-center gap-2 rounded-md px-3 py-2 text-start text-sm transition-colors hover:bg-accent/45\"\n [class.bg-accent/45]=\"activeGroup()?.id === group.id\"\n [attr.aria-current]=\"activeGroup()?.id === group.id ? 'true' : null\"\n (click)=\"selectGroup(group.id)\"\n >\n <span class=\"min-w-0 flex-1 truncate\">{{ group.label }}</span>\n\n @if (draft.pendingGroupIds().has(group.id)) {\n <yuw-badge\n dot\n color=\"secondary\"\n style=\"width: 0.5rem; height: 0.5rem\"\n [attr.aria-label]=\"labels().pending\"\n [attr.title]=\"labels().pending\"\n />\n }\n </button>\n </li>\n }\n </ul>\n\n @if (activeGroup(); as group) {\n <div class=\"flex min-w-0 flex-1 flex-col gap-3 border-s p-3\">\n <ng-container [ngTemplateOutlet]=\"options\" [ngTemplateOutletContext]=\"{ $implicit: group }\" />\n <ng-container [ngTemplateOutlet]=\"commitRow\" />\n </div>\n }\n </div>\n }\n @case ('sets') {\n <ng-container [ngTemplateOutlet]=\"setsView\" [ngTemplateOutletContext]=\"{ $implicit: false }\" />\n }\n @default {\n <ng-container [ngTemplateOutlet]=\"setForm\" [ngTemplateOutletContext]=\"{ $implicit: false }\" />\n }\n }\n </yuw-popover>\n}\n", styles: [".scrollbar-none{scrollbar-width:none}\n"] }]
3999
+ }], ctorParameters: () => [], propDecorators: { disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], groups: [{ type: i0.Input, args: [{ isSignal: true, alias: "groups", required: true }] }], idleColor: [{ type: i0.Input, args: [{ isSignal: true, alias: "idleColor", required: true }] }], isMobile: [{ type: i0.Input, args: [{ isSignal: true, alias: "isMobile", required: true }] }], labels: [{ type: i0.Input, args: [{ isSignal: true, alias: "labels", required: true }] }], selection: [{ type: i0.Input, args: [{ isSignal: true, alias: "selection", required: false }] }, { type: i0.Output, args: ["selectionChange"] }], sets: [{ type: i0.Input, args: [{ isSignal: true, alias: "sets", required: false }] }], setDeleted: [{ type: i0.Output, args: ["setDeleted"] }], setRenamed: [{ type: i0.Output, args: ["setRenamed"] }], setSaved: [{ type: i0.Output, args: ["setSaved"] }] } });
3971
4000
 
3972
4001
  /**
3973
4002
  * Toolbar of a list page: filters on the leading edge, search, export and column visibility on the