yukit-web 0.0.27 → 0.0.29

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
- 77dc06cf0c5ba39ea98787da2a9e5bc545ccc8c5 {"key":"make-fetch-happen:request-cache:https://registry.npmjs.org/yukit-web","integrity":"sha512-u8hiTHwngrJcvZXAmprAAi837ZVBeuPoNQPY4m6CGH3r0JJAdiCOLLKWdIF/m5LLY0MH3kD+evEFXCHrhPop6g==","time":1790758297418,"size":310641,"metadata":{"time":1790758297405,"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":"Wed, 30 Sep 2026 08:51:37 GMT","etag":"W/\"712569c98b5be63987a3b7a3d67aaadf\"","last-modified":"Tue, 29 Sep 2026 09:41:12 GMT","vary":"accept-encoding, accept"},"options":{"compress":true}}}
2
+ 5ed0793cdc917fcecfdc96b1c9647b824e2a3aba {"key":"make-fetch-happen:request-cache:https://registry.npmjs.org/yukit-web","integrity":"sha512-7xi7GNr6qSazltbwq7235gXGE/C4cZ3chyNAVewFISVMRJBuk3+vdSGB6V2my94E0E/PQJ7qNSLhR947v9NcKg==","time":1790771894777,"size":329455,"metadata":{"time":1790771894768,"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":"Wed, 30 Sep 2026 12:38:14 GMT","etag":"W/\"824696d09472effdca1839fd3142422d\"","last-modified":"Wed, 30 Sep 2026 09:52:28 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.0.27 version
9
- 8 verbose argv "view" "yukit-web@0.0.27" "version"
10
- 9 verbose logfile logs-max:10 dir:/builds/yurest/yurest-ui/dist/yukit-web/.npm/_logs/2026-09-30T08_51_37_007Z-
11
- 10 verbose logfile /builds/yurest/yurest-ui/dist/yukit-web/.npm/_logs/2026-09-30T08_51_37_007Z-debug-0.log
8
+ 7 verbose title npm view yukit-web@0.0.29 version
9
+ 8 verbose argv "view" "yukit-web@0.0.29" "version"
10
+ 9 verbose logfile logs-max:10 dir:/builds/yurest/yurest-ui/dist/yukit-web/.npm/_logs/2026-09-30T12_38_14_404Z-
11
+ 10 verbose logfile /builds/yurest/yurest-ui/dist/yukit-web/.npm/_logs/2026-09-30T12_38_14_404Z-debug-0.log
12
12
  11 silly logfile done cleaning log files
13
- 12 http fetch GET 200 https://registry.npmjs.org/yukit-web 218ms (cache miss)
14
- 13 verbose stack Error: No match found for version 0.0.27
13
+ 12 http fetch GET 200 https://registry.npmjs.org/yukit-web 232ms (cache miss)
14
+ 13 verbose stack Error: No match found for version 0.0.29
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.0.27
21
+ 15 verbose pkgid yukit-web@0.0.29
22
22
  16 error code E404
23
- 17 error 404 No match found for version 0.0.27
23
+ 17 error 404 No match found for version 0.0.29
24
24
  18 error 404
25
- 19 error 404 'yukit-web@0.0.27' is not in this registry.
25
+ 19 error 404 'yukit-web@0.0.29' 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-09-30T08_51_37_007Z-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-09-30T12_38_14_404Z-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-09-30T08_51_37_498Z-
11
- 10 verbose logfile /builds/yurest/yurest-ui/dist/yukit-web/.npm/_logs/2026-09-30T08_51_37_498Z-debug-0.log
10
+ 9 verbose logfile logs-max:10 dir:/builds/yurest/yurest-ui/dist/yukit-web/.npm/_logs/2026-09-30T12_38_14_836Z-
11
+ 10 verbose logfile /builds/yurest/yurest-ui/dist/yukit-web/.npm/_logs/2026-09-30T12_38_14_836Z-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
@@ -1,7 +1,7 @@
1
1
  import { clsx } from 'clsx';
2
2
  import { twMerge } from 'tailwind-merge';
3
3
  import * as i0 from '@angular/core';
4
- import { input, Directive, forwardRef, inject, ElementRef, booleanAttribute, signal, computed, model, output, linkedSignal, effect, untracked, ChangeDetectionStrategy, Component, TemplateRef, contentChildren, Injectable, viewChild, contentChild, Injector, afterNextRender, numberAttribute, runInInjectionContext, DestroyRef } from '@angular/core';
4
+ import { input, Directive, forwardRef, inject, ElementRef, booleanAttribute, signal, computed, model, output, linkedSignal, effect, untracked, ChangeDetectionStrategy, Component, TemplateRef, contentChildren, Injectable, viewChild, contentChild, Injector, afterNextRender, numberAttribute, DOCUMENT, runInInjectionContext, DestroyRef } from '@angular/core';
5
5
  import { classes, hlm } from 'yukit-web/helm/utils';
6
6
  import { NG_VALUE_ACCESSOR } from '@angular/forms';
7
7
  import { toSignal, toObservable, outputFromObservable } from '@angular/core/rxjs-interop';
@@ -19,6 +19,7 @@ import * as i1$1 from 'yukit-web/helm/breadcrumb';
19
19
  import { HlmBreadcrumbImports } from 'yukit-web/helm/breadcrumb';
20
20
  import { Router, NavigationEnd, isActive, RouterLink, RouterLinkActive } from '@angular/router';
21
21
  import { HlmPagination, HlmPaginationContent, HlmPaginationItem, HlmPaginationEllipsis } from 'yukit-web/helm/pagination';
22
+ import { BrnComboboxMultiple, BrnCombobox } from '@spartan-ng/brain/combobox';
22
23
  import * as i1$2 from 'yukit-web/helm/combobox';
23
24
  import { HlmComboboxContent, HlmComboboxImports } from 'yukit-web/helm/combobox';
24
25
  import { BreakpointObserver } from '@angular/cdk/layout';
@@ -662,7 +663,7 @@ class YuwBadgeComponent {
662
663
  this.removeLabel = input(undefined, ...(ngDevMode ? [{ debugName: "removeLabel" }] : /* istanbul ignore next */ []));
663
664
  this.variant = input('default', ...(ngDevMode ? [{ debugName: "variant" }] : /* istanbul ignore next */ []));
664
665
  this.removed = output();
665
- this.dotClass = computed(() => (this.dot() ? 'size-4 p-0' : ''), ...(ngDevMode ? [{ debugName: "dotClass" }] : /* istanbul ignore next */ []));
666
+ this.dotClass = computed(() => (this.dot() ? 'size-4 p-0!' : ''), ...(ngDevMode ? [{ debugName: "dotClass" }] : /* istanbul ignore next */ []));
666
667
  this.removeClass = computed(() => REMOVE_TEXT_CLASS[this.variant() ?? 'default'], ...(ngDevMode ? [{ debugName: "removeClass" }] : /* istanbul ignore next */ []));
667
668
  }
668
669
  onRemoveClick(event) {
@@ -914,6 +915,8 @@ let nextUniqueId$2 = 0;
914
915
  * - `clearAriaLabel`: When set, the clear button is shown on the single-selection control and
915
916
  * this is its accessible name; when absent, there is no clear button. One input, one source of
916
917
  * truth. User-facing text — the consuming app is responsible for providing it translated.
918
+ * - `keepValueOnEscape`: Stops Escape from clearing the selection when the list is closed, so a
919
+ * filter picker keeps its choices and Escape only dismisses.
917
920
  * - `inputId`: HTML `id` for the focusable control (the search input, or the trigger button when
918
921
  * `readonlyTrigger` is set), enabling external `<label for="...">` association.
919
922
  * - `readonlyTrigger`: Renders control as a button showing selected label, placing search input inside popover.
@@ -932,13 +935,17 @@ let nextUniqueId$2 = 0;
932
935
  */
933
936
  class YuwComboboxComponent extends YuwValueAccessorBase {
934
937
  constructor() {
935
- super(...arguments);
938
+ super();
939
+ this._element = inject(ElementRef);
940
+ this._multipleBox = viewChild(BrnComboboxMultiple, ...(ngDevMode ? [{ debugName: "_multipleBox" }] : /* istanbul ignore next */ []));
936
941
  this._panel = viewChild(HlmComboboxContent, { ...(ngDevMode ? { debugName: "_panel" } : /* istanbul ignore next */ {}), read: ElementRef });
942
+ this._singleBox = viewChild(BrnCombobox, ...(ngDevMode ? [{ debugName: "_singleBox" }] : /* istanbul ignore next */ []));
937
943
  this.itemTemplate = contentChild(YuwComboboxItemDirective, ...(ngDevMode ? [{ debugName: "itemTemplate" }] : /* istanbul ignore next */ []));
938
944
  this.clearAriaLabel = input(undefined, ...(ngDevMode ? [{ debugName: "clearAriaLabel" }] : /* istanbul ignore next */ []));
939
945
  this.emptyText = input(undefined, ...(ngDevMode ? [{ debugName: "emptyText" }] : /* istanbul ignore next */ []));
940
946
  this.inputId = input(undefined, ...(ngDevMode ? [{ debugName: "inputId" }] : /* istanbul ignore next */ []));
941
947
  this.invalid = input(false, { ...(ngDevMode ? { debugName: "invalid" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
948
+ this.keepValueOnEscape = input(false, { ...(ngDevMode ? { debugName: "keepValueOnEscape" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
942
949
  this.multiple = input(false, { ...(ngDevMode ? { debugName: "multiple" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
943
950
  this.options = input.required(...(ngDevMode ? [{ debugName: "options" }] : /* istanbul ignore next */ []));
944
951
  this.placeholder = input(undefined, ...(ngDevMode ? [{ debugName: "placeholder" }] : /* istanbul ignore next */ []));
@@ -973,6 +980,15 @@ class YuwComboboxComponent extends YuwValueAccessorBase {
973
980
  return Array.isArray(value) ? value[0] : value;
974
981
  }, ...(ngDevMode ? [{ debugName: "_singleValue" }] : /* istanbul ignore next */ []));
975
982
  this._triggerClass = computed(() => yuwButtonVariants({ size: this.size() }), ...(ngDevMode ? [{ debugName: "_triggerClass" }] : /* istanbul ignore next */ []));
983
+ effect((onCleanup) => onCleanup(this._guardEscape() ?? (() => undefined)));
984
+ }
985
+ /**
986
+ * Focuses the field and opens its option list. For a combobox living inside a popover or sheet:
987
+ * the container calls it when it opens, so the user sees the options without a second click.
988
+ */
989
+ open() {
990
+ this.focus();
991
+ (this._multipleBox() ?? this._singleBox())?.open();
976
992
  }
977
993
  _emptyValue() {
978
994
  return this.multiple() ? [] : undefined;
@@ -993,15 +1009,41 @@ class YuwComboboxComponent extends YuwValueAccessorBase {
993
1009
  onValueChange(next) {
994
1010
  this._commit(next ?? this._emptyValue());
995
1011
  }
996
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.22", ngImport: i0, type: YuwComboboxComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
997
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.22", type: YuwComboboxComponent, isStandalone: true, selector: "yuw-combobox", inputs: { clearAriaLabel: { classPropertyName: "clearAriaLabel", publicName: "clearAriaLabel", isSignal: true, isRequired: false, transformFunction: null }, emptyText: { classPropertyName: "emptyText", publicName: "emptyText", isSignal: true, isRequired: false, transformFunction: null }, inputId: { classPropertyName: "inputId", publicName: "inputId", isSignal: true, isRequired: false, transformFunction: null }, invalid: { classPropertyName: "invalid", publicName: "invalid", isSignal: true, isRequired: false, transformFunction: null }, multiple: { classPropertyName: "multiple", publicName: "multiple", isSignal: true, isRequired: false, transformFunction: null }, options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: true, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, readonlyTrigger: { classPropertyName: "readonlyTrigger", publicName: "readonlyTrigger", isSignal: true, isRequired: false, transformFunction: null }, search: { classPropertyName: "search", publicName: "search", isSignal: true, isRequired: false, transformFunction: null }, searchPlaceholder: { classPropertyName: "searchPlaceholder", publicName: "searchPlaceholder", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, triggerAriaLabel: { classPropertyName: "triggerAriaLabel", publicName: "triggerAriaLabel", isSignal: true, isRequired: true, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { search: "searchChange", value: "valueChange" }, host: { classAttribute: "contents" }, providers: [provideValueAccessor(YuwComboboxComponent)], queries: [{ propertyName: "itemTemplate", first: true, predicate: YuwComboboxItemDirective, descendants: true, isSignal: true }], viewQueries: [{ propertyName: "_panel", first: true, predicate: HlmComboboxContent, descendants: true, read: ElementRef, isSignal: true }], usesInheritance: true, ngImport: i0, template: "<ng-template #itemContent let-option>\n @if (itemTemplate(); as custom) {\n <ng-container\n [ngTemplateOutlet]=\"custom.templateRef\"\n [ngTemplateOutletContext]=\"{\n $implicit: option,\n option: option,\n selected: _selectedValues().has(option.value),\n }\"\n />\n } @else {\n {{ option.label }}\n }\n</ng-template>\n\n@if (multiple()) {\n <hlm-combobox-multiple\n [disabled]=\"_disabled()\"\n [value]=\"_multipleValue()\"\n (valueChange)=\"onValueChange($event)\"\n [(search)]=\"search\"\n [itemToString]=\"_itemToString\"\n (focusout)=\"_onFocusOut($event)\"\n >\n <hlm-combobox-chips [forceInvalid]=\"invalid()\" [class]=\"_chipsClass()\">\n @for (chip of _selectedChips(); track chip.value) {\n <hlm-combobox-chip [value]=\"chip.value\">{{ chip.label }}</hlm-combobox-chip>\n }\n <input hlmComboboxChipInput [id]=\"_controlId()\" [placeholder]=\"placeholder() ?? ''\" />\n </hlm-combobox-chips>\n\n <hlm-combobox-content *hlmComboboxPortal>\n <div hlmComboboxList>\n @for (option of options(); track option.value) {\n <hlm-combobox-item [value]=\"option.value\" [disabled]=\"option.disabled ?? false\">\n <ng-container [ngTemplateOutlet]=\"itemContent\" [ngTemplateOutletContext]=\"{ $implicit: option }\" />\n </hlm-combobox-item>\n }\n </div>\n <hlm-combobox-empty>{{ emptyText() ?? '' }}</hlm-combobox-empty>\n </hlm-combobox-content>\n </hlm-combobox-multiple>\n} @else {\n <hlm-combobox\n [disabled]=\"_disabled()\"\n [value]=\"_singleValue()\"\n (valueChange)=\"onValueChange($event)\"\n [(search)]=\"search\"\n [itemToString]=\"_itemToString\"\n (focusout)=\"_onFocusOut($event)\"\n >\n @if (readonlyTrigger()) {\n <hlm-combobox-trigger\n [buttonId]=\"_controlId()\"\n [forceInvalid]=\"invalid()\"\n [class]=\"_triggerClass()\"\n class=\"w-full justify-between items-center\"\n >\n <hlm-combobox-value [placeholder]=\"placeholder() ?? ''\" />\n </hlm-combobox-trigger>\n } @else {\n <hlm-combobox-input\n [inputId]=\"_controlId()\"\n [placeholder]=\"placeholder() ?? ''\"\n [showClear]=\"_clearVisible()\"\n [clearAriaLabel]=\"clearAriaLabel() ?? ''\"\n [triggerAriaLabel]=\"triggerAriaLabel()\"\n [forceInvalid]=\"invalid()\"\n [class]=\"_fieldClass()\"\n />\n }\n\n <hlm-combobox-content *hlmComboboxPortal>\n @if (readonlyTrigger()) {\n <hlm-combobox-input\n [placeholder]=\"searchPlaceholder() ?? ''\"\n [showClear]=\"_clearVisible()\"\n [clearAriaLabel]=\"clearAriaLabel() ?? ''\"\n [triggerAriaLabel]=\"triggerAriaLabel()\"\n [showTrigger]=\"false\"\n />\n }\n <div hlmComboboxList>\n @for (option of options(); track option.value) {\n <hlm-combobox-item [value]=\"option.value\" [disabled]=\"option.disabled ?? false\">\n <ng-container [ngTemplateOutlet]=\"itemContent\" [ngTemplateOutletContext]=\"{ $implicit: option }\" />\n </hlm-combobox-item>\n }\n </div>\n <hlm-combobox-empty>{{ emptyText() ?? '' }}</hlm-combobox-empty>\n </hlm-combobox-content>\n </hlm-combobox>\n}\n", dependencies: [{ kind: "directive", type: i1$2.HlmCombobox, selector: "[hlmCombobox],hlm-combobox" }, { kind: "component", type: i1$2.HlmComboboxChip, selector: "hlm-combobox-chip", inputs: ["showRemove"] }, { kind: "directive", type: i1$2.HlmComboboxChipInput, selector: "input[hlmComboboxChipInput]" }, { kind: "directive", type: i1$2.HlmComboboxChips, selector: "[hlmComboboxChips],hlm-combobox-chips", inputs: ["forceInvalid"] }, { kind: "directive", type: i1$2.HlmComboboxContent, selector: "[hlmComboboxContent],hlm-combobox-content" }, { kind: "directive", type: i1$2.HlmComboboxEmpty, selector: "[hlmComboboxEmpty],hlm-combobox-empty" }, { kind: "component", type: i1$2.HlmComboboxInput, selector: "hlm-combobox-input", inputs: ["inputId", "placeholder", "showTrigger", "showClear", "forceInvalid", "triggerAriaLabel", "clearAriaLabel", "aria-invalid"] }, { kind: "component", type: i1$2.HlmComboboxItem, selector: "hlm-combobox-item" }, { kind: "directive", type: i1$2.HlmComboboxList, selector: "[hlmComboboxList]" }, { kind: "directive", type: i1$2.HlmComboboxMultiple, selector: "[hlmComboboxMultiple],hlm-combobox-multiple" }, { kind: "directive", type: i1$2.HlmComboboxPortal, selector: "[hlmComboboxPortal]" }, { kind: "component", type: i1$2.HlmComboboxTrigger, selector: "hlm-combobox-trigger", inputs: ["class", "buttonId", "variant", "forceInvalid"] }, { kind: "directive", type: i1$2.HlmComboboxValue, selector: "[hlmComboboxValue],hlm-combobox-value" }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
1012
+ /**
1013
+ * The brain clears the whole selection when Escape is pressed with the list closed. While
1014
+ * `keepValueOnEscape` is on, that reset is skipped for the duration of the Escape keydown only,
1015
+ * so the clear button and programmatic resets still work and the event keeps propagating (an
1016
+ * enclosing popover can still close on it). Nothing is registered while the input is off, and
1017
+ * the returned function undoes it all.
1018
+ */
1019
+ _guardEscape() {
1020
+ const box = this._multipleBox() ?? this._singleBox();
1021
+ if (!this.keepValueOnEscape() || !box) {
1022
+ return undefined;
1023
+ }
1024
+ const host = this._element.nativeElement;
1025
+ const reset = box.resetValue.bind(box);
1026
+ let escaping = false;
1027
+ const start = (event) => (escaping = event.key === 'Escape');
1028
+ const stop = () => (escaping = false);
1029
+ box.resetValue = () => (escaping ? undefined : reset());
1030
+ host.addEventListener('keydown', start, true);
1031
+ host.addEventListener('keydown', stop);
1032
+ return () => {
1033
+ Reflect.deleteProperty(box, 'resetValue');
1034
+ host.removeEventListener('keydown', start, true);
1035
+ host.removeEventListener('keydown', stop);
1036
+ };
1037
+ }
1038
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.22", ngImport: i0, type: YuwComboboxComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
1039
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.22", type: YuwComboboxComponent, isStandalone: true, selector: "yuw-combobox", inputs: { clearAriaLabel: { classPropertyName: "clearAriaLabel", publicName: "clearAriaLabel", isSignal: true, isRequired: false, transformFunction: null }, emptyText: { classPropertyName: "emptyText", publicName: "emptyText", isSignal: true, isRequired: false, transformFunction: null }, inputId: { classPropertyName: "inputId", publicName: "inputId", isSignal: true, isRequired: false, transformFunction: null }, invalid: { classPropertyName: "invalid", publicName: "invalid", isSignal: true, isRequired: false, transformFunction: null }, keepValueOnEscape: { classPropertyName: "keepValueOnEscape", publicName: "keepValueOnEscape", isSignal: true, isRequired: false, transformFunction: null }, multiple: { classPropertyName: "multiple", publicName: "multiple", isSignal: true, isRequired: false, transformFunction: null }, options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: true, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, readonlyTrigger: { classPropertyName: "readonlyTrigger", publicName: "readonlyTrigger", isSignal: true, isRequired: false, transformFunction: null }, search: { classPropertyName: "search", publicName: "search", isSignal: true, isRequired: false, transformFunction: null }, searchPlaceholder: { classPropertyName: "searchPlaceholder", publicName: "searchPlaceholder", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, triggerAriaLabel: { classPropertyName: "triggerAriaLabel", publicName: "triggerAriaLabel", isSignal: true, isRequired: true, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { search: "searchChange", value: "valueChange" }, host: { classAttribute: "contents" }, providers: [provideValueAccessor(YuwComboboxComponent)], queries: [{ propertyName: "itemTemplate", first: true, predicate: YuwComboboxItemDirective, descendants: true, isSignal: true }], viewQueries: [{ propertyName: "_multipleBox", first: true, predicate: BrnComboboxMultiple, descendants: true, isSignal: true }, { propertyName: "_panel", first: true, predicate: HlmComboboxContent, descendants: true, read: ElementRef, isSignal: true }, { propertyName: "_singleBox", first: true, predicate: BrnCombobox, descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: "<ng-template #itemContent let-option>\n @if (itemTemplate(); as custom) {\n <ng-container\n [ngTemplateOutlet]=\"custom.templateRef\"\n [ngTemplateOutletContext]=\"{\n $implicit: option,\n option: option,\n selected: _selectedValues().has(option.value),\n }\"\n />\n } @else {\n {{ option.label }}\n }\n</ng-template>\n\n@if (multiple()) {\n <hlm-combobox-multiple\n [disabled]=\"_disabled()\"\n [value]=\"_multipleValue()\"\n (valueChange)=\"onValueChange($event)\"\n [(search)]=\"search\"\n [itemToString]=\"_itemToString\"\n (focusout)=\"_onFocusOut($event)\"\n >\n <hlm-combobox-chips [forceInvalid]=\"invalid()\" [class]=\"_chipsClass()\">\n @for (chip of _selectedChips(); track chip.value) {\n <hlm-combobox-chip [value]=\"chip.value\">{{ chip.label }}</hlm-combobox-chip>\n }\n <input hlmComboboxChipInput [id]=\"_controlId()\" [placeholder]=\"placeholder() ?? ''\" />\n </hlm-combobox-chips>\n\n <hlm-combobox-content *hlmComboboxPortal>\n <div hlmComboboxList>\n @for (option of options(); track option.value) {\n <hlm-combobox-item [value]=\"option.value\" [disabled]=\"option.disabled ?? false\">\n <ng-container [ngTemplateOutlet]=\"itemContent\" [ngTemplateOutletContext]=\"{ $implicit: option }\" />\n </hlm-combobox-item>\n }\n </div>\n <hlm-combobox-empty>{{ emptyText() ?? '' }}</hlm-combobox-empty>\n </hlm-combobox-content>\n </hlm-combobox-multiple>\n} @else {\n <hlm-combobox\n [disabled]=\"_disabled()\"\n [value]=\"_singleValue()\"\n (valueChange)=\"onValueChange($event)\"\n [(search)]=\"search\"\n [itemToString]=\"_itemToString\"\n (focusout)=\"_onFocusOut($event)\"\n >\n @if (readonlyTrigger()) {\n <hlm-combobox-trigger\n [buttonId]=\"_controlId()\"\n [forceInvalid]=\"invalid()\"\n [class]=\"_triggerClass()\"\n class=\"w-full justify-between items-center\"\n >\n <hlm-combobox-value [placeholder]=\"placeholder() ?? ''\" />\n </hlm-combobox-trigger>\n } @else {\n <hlm-combobox-input\n [inputId]=\"_controlId()\"\n [placeholder]=\"placeholder() ?? ''\"\n [showClear]=\"_clearVisible()\"\n [clearAriaLabel]=\"clearAriaLabel() ?? ''\"\n [triggerAriaLabel]=\"triggerAriaLabel()\"\n [forceInvalid]=\"invalid()\"\n [class]=\"_fieldClass()\"\n />\n }\n\n <hlm-combobox-content *hlmComboboxPortal>\n @if (readonlyTrigger()) {\n <hlm-combobox-input\n [placeholder]=\"searchPlaceholder() ?? ''\"\n [showClear]=\"_clearVisible()\"\n [clearAriaLabel]=\"clearAriaLabel() ?? ''\"\n [triggerAriaLabel]=\"triggerAriaLabel()\"\n [showTrigger]=\"false\"\n />\n }\n <div hlmComboboxList>\n @for (option of options(); track option.value) {\n <hlm-combobox-item [value]=\"option.value\" [disabled]=\"option.disabled ?? false\">\n <ng-container [ngTemplateOutlet]=\"itemContent\" [ngTemplateOutletContext]=\"{ $implicit: option }\" />\n </hlm-combobox-item>\n }\n </div>\n <hlm-combobox-empty>{{ emptyText() ?? '' }}</hlm-combobox-empty>\n </hlm-combobox-content>\n </hlm-combobox>\n}\n", dependencies: [{ kind: "directive", type: i1$2.HlmCombobox, selector: "[hlmCombobox],hlm-combobox" }, { kind: "component", type: i1$2.HlmComboboxChip, selector: "hlm-combobox-chip", inputs: ["showRemove"] }, { kind: "directive", type: i1$2.HlmComboboxChipInput, selector: "input[hlmComboboxChipInput]" }, { kind: "directive", type: i1$2.HlmComboboxChips, selector: "[hlmComboboxChips],hlm-combobox-chips", inputs: ["forceInvalid"] }, { kind: "directive", type: i1$2.HlmComboboxContent, selector: "[hlmComboboxContent],hlm-combobox-content" }, { kind: "directive", type: i1$2.HlmComboboxEmpty, selector: "[hlmComboboxEmpty],hlm-combobox-empty" }, { kind: "component", type: i1$2.HlmComboboxInput, selector: "hlm-combobox-input", inputs: ["inputId", "placeholder", "showTrigger", "showClear", "forceInvalid", "triggerAriaLabel", "clearAriaLabel", "aria-invalid"] }, { kind: "component", type: i1$2.HlmComboboxItem, selector: "hlm-combobox-item" }, { kind: "directive", type: i1$2.HlmComboboxList, selector: "[hlmComboboxList]" }, { kind: "directive", type: i1$2.HlmComboboxMultiple, selector: "[hlmComboboxMultiple],hlm-combobox-multiple" }, { kind: "directive", type: i1$2.HlmComboboxPortal, selector: "[hlmComboboxPortal]" }, { kind: "component", type: i1$2.HlmComboboxTrigger, selector: "hlm-combobox-trigger", inputs: ["class", "buttonId", "variant", "forceInvalid"] }, { kind: "directive", type: i1$2.HlmComboboxValue, selector: "[hlmComboboxValue],hlm-combobox-value" }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
998
1040
  }
999
1041
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.22", ngImport: i0, type: YuwComboboxComponent, decorators: [{
1000
1042
  type: Component,
1001
1043
  args: [{ selector: 'yuw-combobox', imports: [...HlmComboboxImports, NgTemplateOutlet], providers: [provideValueAccessor(YuwComboboxComponent)], host: {
1002
1044
  class: 'contents',
1003
1045
  }, changeDetection: ChangeDetectionStrategy.OnPush, template: "<ng-template #itemContent let-option>\n @if (itemTemplate(); as custom) {\n <ng-container\n [ngTemplateOutlet]=\"custom.templateRef\"\n [ngTemplateOutletContext]=\"{\n $implicit: option,\n option: option,\n selected: _selectedValues().has(option.value),\n }\"\n />\n } @else {\n {{ option.label }}\n }\n</ng-template>\n\n@if (multiple()) {\n <hlm-combobox-multiple\n [disabled]=\"_disabled()\"\n [value]=\"_multipleValue()\"\n (valueChange)=\"onValueChange($event)\"\n [(search)]=\"search\"\n [itemToString]=\"_itemToString\"\n (focusout)=\"_onFocusOut($event)\"\n >\n <hlm-combobox-chips [forceInvalid]=\"invalid()\" [class]=\"_chipsClass()\">\n @for (chip of _selectedChips(); track chip.value) {\n <hlm-combobox-chip [value]=\"chip.value\">{{ chip.label }}</hlm-combobox-chip>\n }\n <input hlmComboboxChipInput [id]=\"_controlId()\" [placeholder]=\"placeholder() ?? ''\" />\n </hlm-combobox-chips>\n\n <hlm-combobox-content *hlmComboboxPortal>\n <div hlmComboboxList>\n @for (option of options(); track option.value) {\n <hlm-combobox-item [value]=\"option.value\" [disabled]=\"option.disabled ?? false\">\n <ng-container [ngTemplateOutlet]=\"itemContent\" [ngTemplateOutletContext]=\"{ $implicit: option }\" />\n </hlm-combobox-item>\n }\n </div>\n <hlm-combobox-empty>{{ emptyText() ?? '' }}</hlm-combobox-empty>\n </hlm-combobox-content>\n </hlm-combobox-multiple>\n} @else {\n <hlm-combobox\n [disabled]=\"_disabled()\"\n [value]=\"_singleValue()\"\n (valueChange)=\"onValueChange($event)\"\n [(search)]=\"search\"\n [itemToString]=\"_itemToString\"\n (focusout)=\"_onFocusOut($event)\"\n >\n @if (readonlyTrigger()) {\n <hlm-combobox-trigger\n [buttonId]=\"_controlId()\"\n [forceInvalid]=\"invalid()\"\n [class]=\"_triggerClass()\"\n class=\"w-full justify-between items-center\"\n >\n <hlm-combobox-value [placeholder]=\"placeholder() ?? ''\" />\n </hlm-combobox-trigger>\n } @else {\n <hlm-combobox-input\n [inputId]=\"_controlId()\"\n [placeholder]=\"placeholder() ?? ''\"\n [showClear]=\"_clearVisible()\"\n [clearAriaLabel]=\"clearAriaLabel() ?? ''\"\n [triggerAriaLabel]=\"triggerAriaLabel()\"\n [forceInvalid]=\"invalid()\"\n [class]=\"_fieldClass()\"\n />\n }\n\n <hlm-combobox-content *hlmComboboxPortal>\n @if (readonlyTrigger()) {\n <hlm-combobox-input\n [placeholder]=\"searchPlaceholder() ?? ''\"\n [showClear]=\"_clearVisible()\"\n [clearAriaLabel]=\"clearAriaLabel() ?? ''\"\n [triggerAriaLabel]=\"triggerAriaLabel()\"\n [showTrigger]=\"false\"\n />\n }\n <div hlmComboboxList>\n @for (option of options(); track option.value) {\n <hlm-combobox-item [value]=\"option.value\" [disabled]=\"option.disabled ?? false\">\n <ng-container [ngTemplateOutlet]=\"itemContent\" [ngTemplateOutletContext]=\"{ $implicit: option }\" />\n </hlm-combobox-item>\n }\n </div>\n <hlm-combobox-empty>{{ emptyText() ?? '' }}</hlm-combobox-empty>\n </hlm-combobox-content>\n </hlm-combobox>\n}\n" }]
1004
- }], propDecorators: { _panel: [{ type: i0.ViewChild, args: [i0.forwardRef(() => HlmComboboxContent), { ...{ read: ElementRef }, isSignal: true }] }], itemTemplate: [{ type: i0.ContentChild, args: [i0.forwardRef(() => YuwComboboxItemDirective), { isSignal: true }] }], clearAriaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "clearAriaLabel", required: false }] }], emptyText: [{ type: i0.Input, args: [{ isSignal: true, alias: "emptyText", required: false }] }], inputId: [{ type: i0.Input, args: [{ isSignal: true, alias: "inputId", required: false }] }], invalid: [{ type: i0.Input, args: [{ isSignal: true, alias: "invalid", required: false }] }], multiple: [{ type: i0.Input, args: [{ isSignal: true, alias: "multiple", required: false }] }], options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: true }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], readonlyTrigger: [{ type: i0.Input, args: [{ isSignal: true, alias: "readonlyTrigger", required: false }] }], search: [{ type: i0.Input, args: [{ isSignal: true, alias: "search", required: false }] }, { type: i0.Output, args: ["searchChange"] }], searchPlaceholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "searchPlaceholder", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], triggerAriaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "triggerAriaLabel", required: true }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }] } });
1046
+ }], ctorParameters: () => [], propDecorators: { _multipleBox: [{ type: i0.ViewChild, args: [i0.forwardRef(() => BrnComboboxMultiple), { isSignal: true }] }], _panel: [{ type: i0.ViewChild, args: [i0.forwardRef(() => HlmComboboxContent), { ...{ read: ElementRef }, isSignal: true }] }], _singleBox: [{ type: i0.ViewChild, args: [i0.forwardRef(() => BrnCombobox), { isSignal: true }] }], itemTemplate: [{ type: i0.ContentChild, args: [i0.forwardRef(() => YuwComboboxItemDirective), { isSignal: true }] }], clearAriaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "clearAriaLabel", required: false }] }], emptyText: [{ type: i0.Input, args: [{ isSignal: true, alias: "emptyText", required: false }] }], inputId: [{ type: i0.Input, args: [{ isSignal: true, alias: "inputId", required: false }] }], invalid: [{ type: i0.Input, args: [{ isSignal: true, alias: "invalid", required: false }] }], keepValueOnEscape: [{ type: i0.Input, args: [{ isSignal: true, alias: "keepValueOnEscape", required: false }] }], multiple: [{ type: i0.Input, args: [{ isSignal: true, alias: "multiple", required: false }] }], options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: true }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], readonlyTrigger: [{ type: i0.Input, args: [{ isSignal: true, alias: "readonlyTrigger", required: false }] }], search: [{ type: i0.Input, args: [{ isSignal: true, alias: "search", required: false }] }, { type: i0.Output, args: ["searchChange"] }], searchPlaceholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "searchPlaceholder", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], triggerAriaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "triggerAriaLabel", required: true }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }] } });
1005
1047
 
1006
1048
  /** Page size selector and range message of a `YuwPagedList`; in a datatable it takes the pagination slot. */
1007
1049
  class YuwPageSizeComponent {
@@ -1012,7 +1054,7 @@ class YuwPageSizeComponent {
1012
1054
  this.message = computed(() => this.labels().range(this.list().range()), ...(ngDevMode ? [{ debugName: "message" }] : /* istanbul ignore next */ []));
1013
1055
  }
1014
1056
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.22", ngImport: i0, type: YuwPageSizeComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
1015
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.22", type: YuwPageSizeComponent, isStandalone: true, selector: "yuw-page-size", inputs: { disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, labels: { classPropertyName: "labels", publicName: "labels", isSignal: true, isRequired: true, transformFunction: null }, list: { classPropertyName: "list", publicName: "list", isSignal: true, isRequired: true, transformFunction: null } }, host: { classAttribute: "flex items-center gap-2" }, ngImport: i0, template: "<yuw-combobox\n readonlyTrigger\n class=\"w-32\"\n [disabled]=\"disabled()\"\n [options]=\"list().pageSizeOptions\"\n [triggerAriaLabel]=\"labels().label\"\n [value]=\"list().pageSize()\"\n [emptyText]=\"labels().empty\"\n (valueChange)=\"list().pageSize.set($event)\"\n/>\n<p class=\"text-sm text-muted-foreground\">{{ message() }}</p>\n", dependencies: [{ kind: "component", type: YuwComboboxComponent, selector: "yuw-combobox", inputs: ["clearAriaLabel", "emptyText", "inputId", "invalid", "multiple", "options", "placeholder", "readonlyTrigger", "search", "searchPlaceholder", "size", "triggerAriaLabel", "value"], outputs: ["searchChange", "valueChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
1057
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.22", type: YuwPageSizeComponent, isStandalone: true, selector: "yuw-page-size", inputs: { disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, labels: { classPropertyName: "labels", publicName: "labels", isSignal: true, isRequired: true, transformFunction: null }, list: { classPropertyName: "list", publicName: "list", isSignal: true, isRequired: true, transformFunction: null } }, host: { classAttribute: "flex items-center gap-2" }, ngImport: i0, template: "<yuw-combobox\n readonlyTrigger\n class=\"w-32\"\n [disabled]=\"disabled()\"\n [options]=\"list().pageSizeOptions\"\n [triggerAriaLabel]=\"labels().label\"\n [value]=\"list().pageSize()\"\n [emptyText]=\"labels().empty\"\n (valueChange)=\"list().pageSize.set($event)\"\n/>\n<p class=\"text-sm text-muted-foreground\">{{ message() }}</p>\n", dependencies: [{ 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"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
1016
1058
  }
1017
1059
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.22", ngImport: i0, type: YuwPageSizeComponent, decorators: [{
1018
1060
  type: Component,
@@ -3160,6 +3202,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.22", ngImpo
3160
3202
  }, changeDetection: ChangeDetectionStrategy.OnPush, template: "<div\n hlmPopover\n [state]=\"_popoverState()\"\n [align]=\"align()\"\n [sideOffset]=\"sideOffset()\"\n [offsetX]=\"offsetX()\"\n (stateChanged)=\"onOpenChange($event)\"\n>\n @if (showTrigger()) {\n <yuw-button\n yuwPopoverTriggerButton\n [color]=\"triggerColor()\"\n [variant]=\"triggerVariant()\"\n [size]=\"triggerSize()\"\n [transparent]=\"triggerTransparent()\"\n [class]=\"triggerClass()\"\n >\n <ng-content select=\"[yuwPopoverTrigger]\" />\n </yuw-button>\n }\n\n <hlm-popover-content *hlmPopoverPortal [class]=\"panelClass()\">\n @if (title() || description()) {\n <div hlmPopoverHeader>\n @if (title()) {\n <p hlmPopoverTitle>{{ title() }}</p>\n }\n @if (description()) {\n <p hlmPopoverDescription>{{ description() }}</p>\n }\n </div>\n }\n\n <ng-content />\n </hlm-popover-content>\n</div>\n" }]
3161
3203
  }], propDecorators: { align: [{ type: i0.Input, args: [{ isSignal: true, alias: "align", required: false }] }], description: [{ type: i0.Input, args: [{ isSignal: true, alias: "description", required: false }] }], offsetX: [{ type: i0.Input, args: [{ isSignal: true, alias: "offsetX", required: false }] }], open: [{ type: i0.Input, args: [{ isSignal: true, alias: "open", required: false }] }, { type: i0.Output, args: ["openChange"] }], panelClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "panelClass", required: false }] }], showTrigger: [{ type: i0.Input, args: [{ isSignal: true, alias: "showTrigger", required: false }] }], sideOffset: [{ type: i0.Input, args: [{ isSignal: true, alias: "sideOffset", required: false }] }], title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: false }] }], triggerClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "triggerClass", required: false }] }], triggerColor: [{ type: i0.Input, args: [{ isSignal: true, alias: "triggerColor", required: false }] }], triggerSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "triggerSize", required: false }] }], triggerTransparent: [{ type: i0.Input, args: [{ isSignal: true, alias: "triggerTransparent", required: false }] }], triggerVariant: [{ type: i0.Input, args: [{ isSignal: true, alias: "triggerVariant", required: false }] }] } });
3162
3204
 
3205
+ /**
3206
+ * What counts as inside the columns popover: its trigger, its panel and the combobox list, which
3207
+ * renders in its own overlay outside the panel.
3208
+ */
3209
+ const INSIDE_COLUMNS_SELECTOR = '.yuw-columns-trigger, hlm-popover-content, hlm-combobox-content';
3163
3210
  /**
3164
3211
  * Action row of `yuw-list-toolbar`: search, export and column visibility, each rendered only when
3165
3212
  * its input is set. Below `md` the search collapses into a popover; both widths bind the same
@@ -3167,10 +3214,16 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.22", ngImpo
3167
3214
  * holding `yuwPopoverTrigger`.
3168
3215
  *
3169
3216
  * `hiddenColumns` is two-way: the consumer can seed it (a restored preference) and the combobox
3170
- * reflects it. While it is not empty the columns button carries a red dot.
3217
+ * reflects it. While it is not empty the columns button carries a red dot. Opening the columns
3218
+ * popover also opens the combobox list, so the choice is one click away. That list lives in its own
3219
+ * overlay, which swallows the first outside press, so a press outside both closes the popover
3220
+ * directly and one click is enough. Tabbing focus out of the popover closes it the same way.
3171
3221
  */
3172
3222
  class YuwListToolbarActionsComponent {
3173
3223
  constructor() {
3224
+ this._document = inject(DOCUMENT);
3225
+ this._injector = inject(Injector);
3226
+ this._columnsCombobox = viewChild(YuwComboboxComponent, ...(ngDevMode ? [{ debugName: "_columnsCombobox" }] : /* istanbul ignore next */ []));
3174
3227
  this.hiddenColumns = model([], ...(ngDevMode ? [{ debugName: "hiddenColumns" }] : /* istanbul ignore next */ []));
3175
3228
  this.hideableColumns = input(...(ngDevMode ? [undefined, { debugName: "hideableColumns" }] : /* istanbul ignore next */ []));
3176
3229
  this.isMobile = input.required(...(ngDevMode ? [{ debugName: "isMobile" }] : /* istanbul ignore next */ []));
@@ -3183,12 +3236,33 @@ class YuwListToolbarActionsComponent {
3183
3236
  this.searchOpen = signal(false, ...(ngDevMode ? [{ debugName: "searchOpen" }] : /* istanbul ignore next */ []));
3184
3237
  this.settingsOpen = signal(false, ...(ngDevMode ? [{ debugName: "settingsOpen" }] : /* istanbul ignore next */ []));
3185
3238
  this.hasHiddenColumns = computed(() => this.hiddenColumns().length > 0, ...(ngDevMode ? [{ debugName: "hasHiddenColumns" }] : /* istanbul ignore next */ []));
3239
+ effect(() => {
3240
+ if (this.settingsOpen()) {
3241
+ afterNextRender(() => this._columnsCombobox()?.open(), { injector: this._injector });
3242
+ }
3243
+ });
3244
+ effect((onCleanup) => {
3245
+ if (!this.settingsOpen()) {
3246
+ return;
3247
+ }
3248
+ const closeWhenOutside = (event) => {
3249
+ if (event.target instanceof Element && !event.target.closest(INSIDE_COLUMNS_SELECTOR)) {
3250
+ this.settingsOpen.set(false);
3251
+ }
3252
+ };
3253
+ this._document.addEventListener('pointerdown', closeWhenOutside, true);
3254
+ this._document.addEventListener('focusin', closeWhenOutside, true);
3255
+ onCleanup(() => {
3256
+ this._document.removeEventListener('pointerdown', closeWhenOutside, true);
3257
+ this._document.removeEventListener('focusin', closeWhenOutside, true);
3258
+ });
3259
+ });
3186
3260
  }
3187
3261
  onHiddenColumnsChange(value) {
3188
3262
  this.hiddenColumns.set(Array.isArray(value) ? value : value ? [value] : []);
3189
3263
  }
3190
3264
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.22", ngImport: i0, type: YuwListToolbarActionsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
3191
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.22", type: YuwListToolbarActionsComponent, isStandalone: true, selector: "yuw-list-toolbar-actions", inputs: { hiddenColumns: { classPropertyName: "hiddenColumns", publicName: "hiddenColumns", isSignal: true, isRequired: false, transformFunction: null }, hideableColumns: { classPropertyName: "hideableColumns", publicName: "hideableColumns", isSignal: true, isRequired: false, transformFunction: null }, isMobile: { classPropertyName: "isMobile", publicName: "isMobile", isSignal: true, isRequired: true, transformFunction: null }, labels: { classPropertyName: "labels", publicName: "labels", isSignal: true, isRequired: true, transformFunction: null }, search: { classPropertyName: "search", publicName: "search", isSignal: true, isRequired: false, transformFunction: null }, searchPlaceholder: { classPropertyName: "searchPlaceholder", publicName: "searchPlaceholder", isSignal: true, isRequired: false, transformFunction: null }, showExport: { classPropertyName: "showExport", publicName: "showExport", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { hiddenColumns: "hiddenColumnsChange", search: "searchChange", exported: "exported", searched: "searched" }, host: { classAttribute: "flex items-center gap-2" }, providers: [provideIcons({ lucideDownload, lucideSearch, lucideSettings2 })], ngImport: i0, template: "@if (searchPlaceholder(); as placeholder) {\n @if (isMobile()) {\n <yuw-popover\n align=\"center\"\n class=\"mr-5\"\n triggerVariant=\"outline\"\n triggerSize=\"icon\"\n panelClass=\"w-[min(20rem,calc(100vw-2rem))] p-2\"\n [offsetX]=\"-16\"\n [(open)]=\"searchOpen\"\n >\n <span yuwPopoverTrigger class=\"flex items-center\" [attr.aria-label]=\"labels().search.expand\">\n <ng-icon name=\"lucideSearch\" size=\"16\" />\n </span>\n\n <yuw-search-input\n expandedWidth=\"100%\"\n [(value)]=\"search\"\n [placeholder]=\"placeholder\"\n [clearAriaLabel]=\"labels().search.clear\"\n (searched)=\"searched.emit($event)\"\n />\n </yuw-popover>\n } @else {\n <yuw-search-input\n collapseFrom=\"right\"\n expandedWidth=\"18rem\"\n [(value)]=\"search\"\n [placeholder]=\"placeholder\"\n [clearAriaLabel]=\"labels().search.clear\"\n [expandAriaLabel]=\"labels().search.expand\"\n (searched)=\"searched.emit($event)\"\n />\n }\n}\n\n@if (showExport()) {\n <yuw-button variant=\"outline\" class=\"gap-2\" (clicked)=\"exported.emit($event)\">\n <ng-icon name=\"lucideDownload\" size=\"16\" />\n <span class=\"max-md:hidden\">\n {{ labels().export }}\n </span>\n </yuw-button>\n}\n\n@if (hideableColumns(); as columns) {\n <yuw-popover\n align=\"end\"\n panelClass=\"w-auto p-2 dark:border max-w-3xs\"\n triggerVariant=\"outline\"\n triggerSize=\"icon\"\n triggerClass=\"relative\"\n [(open)]=\"settingsOpen\"\n >\n <span yuwPopoverTrigger class=\"flex items-center\" [attr.aria-label]=\"labels().columns.trigger\">\n <ng-icon name=\"lucideSettings2\" size=\"16\" />\n\n @if (hasHiddenColumns()) {\n <yuw-badge\n dot\n color=\"destructive\"\n class=\"absolute -top-1 -right-1\"\n style=\"width: 0.5rem; height: 0.5rem\"\n data-testid=\"hidden-columns-dot\"\n />\n }\n </span>\n\n <div>\n <yuw-combobox\n multiple\n [options]=\"columns\"\n [value]=\"hiddenColumns()\"\n [placeholder]=\"labels().columns.placeholder\"\n [emptyText]=\"labels().columns.empty\"\n [triggerAriaLabel]=\"labels().columns.toggle\"\n (valueChange)=\"onHiddenColumnsChange($event)\"\n />\n </div>\n </yuw-popover>\n}\n", dependencies: [{ 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: YuwComboboxComponent, selector: "yuw-combobox", inputs: ["clearAriaLabel", "emptyText", "inputId", "invalid", "multiple", "options", "placeholder", "readonlyTrigger", "search", "searchPlaceholder", "size", "triggerAriaLabel", "value"], outputs: ["searchChange", "valueChange"] }, { 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: YuwSearchInputComponent, selector: "yuw-search-input", inputs: ["clearAriaLabel", "collapseFrom", "expandAriaLabel", "expandedWidth", "size", "transparent"], outputs: ["searched"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
3265
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.22", type: YuwListToolbarActionsComponent, isStandalone: true, selector: "yuw-list-toolbar-actions", inputs: { hiddenColumns: { classPropertyName: "hiddenColumns", publicName: "hiddenColumns", isSignal: true, isRequired: false, transformFunction: null }, hideableColumns: { classPropertyName: "hideableColumns", publicName: "hideableColumns", isSignal: true, isRequired: false, transformFunction: null }, isMobile: { classPropertyName: "isMobile", publicName: "isMobile", isSignal: true, isRequired: true, transformFunction: null }, labels: { classPropertyName: "labels", publicName: "labels", isSignal: true, isRequired: true, transformFunction: null }, search: { classPropertyName: "search", publicName: "search", isSignal: true, isRequired: false, transformFunction: null }, searchPlaceholder: { classPropertyName: "searchPlaceholder", publicName: "searchPlaceholder", isSignal: true, isRequired: false, transformFunction: null }, showExport: { classPropertyName: "showExport", publicName: "showExport", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { hiddenColumns: "hiddenColumnsChange", search: "searchChange", exported: "exported", searched: "searched" }, host: { classAttribute: "flex items-center gap-2" }, providers: [provideIcons({ lucideDownload, lucideSearch, lucideSettings2 })], viewQueries: [{ propertyName: "_columnsCombobox", first: true, predicate: YuwComboboxComponent, descendants: true, isSignal: true }], ngImport: i0, template: "@if (searchPlaceholder(); as placeholder) {\n @if (isMobile()) {\n <yuw-popover\n align=\"center\"\n class=\"mr-5\"\n triggerVariant=\"outline\"\n triggerSize=\"icon\"\n panelClass=\"w-[min(20rem,calc(100vw-2rem))] p-2\"\n [offsetX]=\"-16\"\n [(open)]=\"searchOpen\"\n >\n <span yuwPopoverTrigger class=\"flex items-center\" [attr.aria-label]=\"labels().search.expand\">\n <ng-icon name=\"lucideSearch\" size=\"16\" />\n </span>\n\n <yuw-search-input\n expandedWidth=\"100%\"\n [(value)]=\"search\"\n [placeholder]=\"placeholder\"\n [clearAriaLabel]=\"labels().search.clear\"\n (searched)=\"searched.emit($event)\"\n />\n </yuw-popover>\n } @else {\n <yuw-search-input\n collapseFrom=\"right\"\n expandedWidth=\"18rem\"\n [(value)]=\"search\"\n [placeholder]=\"placeholder\"\n [clearAriaLabel]=\"labels().search.clear\"\n [expandAriaLabel]=\"labels().search.expand\"\n (searched)=\"searched.emit($event)\"\n />\n }\n}\n\n@if (showExport()) {\n <yuw-button variant=\"outline\" class=\"gap-2\" (clicked)=\"exported.emit($event)\">\n <ng-icon name=\"lucideDownload\" size=\"16\" />\n <span class=\"max-md:hidden\">\n {{ labels().export }}\n </span>\n </yuw-button>\n}\n\n@if (hideableColumns(); as columns) {\n <yuw-popover\n align=\"end\"\n panelClass=\"w-auto p-2 dark:border max-w-3xs\"\n triggerVariant=\"outline\"\n triggerSize=\"icon\"\n triggerClass=\"yuw-columns-trigger relative\"\n [(open)]=\"settingsOpen\"\n >\n <span yuwPopoverTrigger class=\"flex items-center\" [attr.aria-label]=\"labels().columns.trigger\">\n <ng-icon name=\"lucideSettings2\" size=\"16\" />\n\n @if (hasHiddenColumns()) {\n <yuw-badge\n dot\n color=\"destructive\"\n class=\"absolute -top-1 -right-1\"\n style=\"width: 0.5rem; height: 0.5rem\"\n data-testid=\"hidden-columns-dot\"\n />\n }\n </span>\n\n <div>\n <yuw-combobox\n multiple\n keepValueOnEscape\n [options]=\"columns\"\n [value]=\"hiddenColumns()\"\n [placeholder]=\"labels().columns.placeholder\"\n [emptyText]=\"labels().columns.empty\"\n [triggerAriaLabel]=\"labels().columns.toggle\"\n (valueChange)=\"onHiddenColumnsChange($event)\"\n />\n </div>\n </yuw-popover>\n}\n", dependencies: [{ 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: YuwComboboxComponent, selector: "yuw-combobox", inputs: ["clearAriaLabel", "emptyText", "inputId", "invalid", "keepValueOnEscape", "multiple", "options", "placeholder", "readonlyTrigger", "search", "searchPlaceholder", "size", "triggerAriaLabel", "value"], outputs: ["searchChange", "valueChange"] }, { 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: YuwSearchInputComponent, selector: "yuw-search-input", inputs: ["clearAriaLabel", "collapseFrom", "expandAriaLabel", "expandedWidth", "size", "transparent"], outputs: ["searched"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
3192
3266
  }
3193
3267
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.22", ngImport: i0, type: YuwListToolbarActionsComponent, decorators: [{
3194
3268
  type: Component,
@@ -3199,8 +3273,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.22", ngImpo
3199
3273
  YuwComboboxComponent,
3200
3274
  YuwPopoverComponent,
3201
3275
  YuwSearchInputComponent,
3202
- ], providers: [provideIcons({ lucideDownload, lucideSearch, lucideSettings2 })], host: { class: 'flex items-center gap-2' }, template: "@if (searchPlaceholder(); as placeholder) {\n @if (isMobile()) {\n <yuw-popover\n align=\"center\"\n class=\"mr-5\"\n triggerVariant=\"outline\"\n triggerSize=\"icon\"\n panelClass=\"w-[min(20rem,calc(100vw-2rem))] p-2\"\n [offsetX]=\"-16\"\n [(open)]=\"searchOpen\"\n >\n <span yuwPopoverTrigger class=\"flex items-center\" [attr.aria-label]=\"labels().search.expand\">\n <ng-icon name=\"lucideSearch\" size=\"16\" />\n </span>\n\n <yuw-search-input\n expandedWidth=\"100%\"\n [(value)]=\"search\"\n [placeholder]=\"placeholder\"\n [clearAriaLabel]=\"labels().search.clear\"\n (searched)=\"searched.emit($event)\"\n />\n </yuw-popover>\n } @else {\n <yuw-search-input\n collapseFrom=\"right\"\n expandedWidth=\"18rem\"\n [(value)]=\"search\"\n [placeholder]=\"placeholder\"\n [clearAriaLabel]=\"labels().search.clear\"\n [expandAriaLabel]=\"labels().search.expand\"\n (searched)=\"searched.emit($event)\"\n />\n }\n}\n\n@if (showExport()) {\n <yuw-button variant=\"outline\" class=\"gap-2\" (clicked)=\"exported.emit($event)\">\n <ng-icon name=\"lucideDownload\" size=\"16\" />\n <span class=\"max-md:hidden\">\n {{ labels().export }}\n </span>\n </yuw-button>\n}\n\n@if (hideableColumns(); as columns) {\n <yuw-popover\n align=\"end\"\n panelClass=\"w-auto p-2 dark:border max-w-3xs\"\n triggerVariant=\"outline\"\n triggerSize=\"icon\"\n triggerClass=\"relative\"\n [(open)]=\"settingsOpen\"\n >\n <span yuwPopoverTrigger class=\"flex items-center\" [attr.aria-label]=\"labels().columns.trigger\">\n <ng-icon name=\"lucideSettings2\" size=\"16\" />\n\n @if (hasHiddenColumns()) {\n <yuw-badge\n dot\n color=\"destructive\"\n class=\"absolute -top-1 -right-1\"\n style=\"width: 0.5rem; height: 0.5rem\"\n data-testid=\"hidden-columns-dot\"\n />\n }\n </span>\n\n <div>\n <yuw-combobox\n multiple\n [options]=\"columns\"\n [value]=\"hiddenColumns()\"\n [placeholder]=\"labels().columns.placeholder\"\n [emptyText]=\"labels().columns.empty\"\n [triggerAriaLabel]=\"labels().columns.toggle\"\n (valueChange)=\"onHiddenColumnsChange($event)\"\n />\n </div>\n </yuw-popover>\n}\n" }]
3203
- }], propDecorators: { hiddenColumns: [{ type: i0.Input, args: [{ isSignal: true, alias: "hiddenColumns", required: false }] }, { type: i0.Output, args: ["hiddenColumnsChange"] }], hideableColumns: [{ type: i0.Input, args: [{ isSignal: true, alias: "hideableColumns", required: false }] }], isMobile: [{ type: i0.Input, args: [{ isSignal: true, alias: "isMobile", required: true }] }], labels: [{ type: i0.Input, args: [{ isSignal: true, alias: "labels", required: true }] }], search: [{ type: i0.Input, args: [{ isSignal: true, alias: "search", required: false }] }, { type: i0.Output, args: ["searchChange"] }], searchPlaceholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "searchPlaceholder", required: false }] }], showExport: [{ type: i0.Input, args: [{ isSignal: true, alias: "showExport", required: false }] }], exported: [{ type: i0.Output, args: ["exported"] }], searched: [{ type: i0.Output, args: ["searched"] }] } });
3276
+ ], providers: [provideIcons({ lucideDownload, lucideSearch, lucideSettings2 })], host: { class: 'flex items-center gap-2' }, template: "@if (searchPlaceholder(); as placeholder) {\n @if (isMobile()) {\n <yuw-popover\n align=\"center\"\n class=\"mr-5\"\n triggerVariant=\"outline\"\n triggerSize=\"icon\"\n panelClass=\"w-[min(20rem,calc(100vw-2rem))] p-2\"\n [offsetX]=\"-16\"\n [(open)]=\"searchOpen\"\n >\n <span yuwPopoverTrigger class=\"flex items-center\" [attr.aria-label]=\"labels().search.expand\">\n <ng-icon name=\"lucideSearch\" size=\"16\" />\n </span>\n\n <yuw-search-input\n expandedWidth=\"100%\"\n [(value)]=\"search\"\n [placeholder]=\"placeholder\"\n [clearAriaLabel]=\"labels().search.clear\"\n (searched)=\"searched.emit($event)\"\n />\n </yuw-popover>\n } @else {\n <yuw-search-input\n collapseFrom=\"right\"\n expandedWidth=\"18rem\"\n [(value)]=\"search\"\n [placeholder]=\"placeholder\"\n [clearAriaLabel]=\"labels().search.clear\"\n [expandAriaLabel]=\"labels().search.expand\"\n (searched)=\"searched.emit($event)\"\n />\n }\n}\n\n@if (showExport()) {\n <yuw-button variant=\"outline\" class=\"gap-2\" (clicked)=\"exported.emit($event)\">\n <ng-icon name=\"lucideDownload\" size=\"16\" />\n <span class=\"max-md:hidden\">\n {{ labels().export }}\n </span>\n </yuw-button>\n}\n\n@if (hideableColumns(); as columns) {\n <yuw-popover\n align=\"end\"\n panelClass=\"w-auto p-2 dark:border max-w-3xs\"\n triggerVariant=\"outline\"\n triggerSize=\"icon\"\n triggerClass=\"yuw-columns-trigger relative\"\n [(open)]=\"settingsOpen\"\n >\n <span yuwPopoverTrigger class=\"flex items-center\" [attr.aria-label]=\"labels().columns.trigger\">\n <ng-icon name=\"lucideSettings2\" size=\"16\" />\n\n @if (hasHiddenColumns()) {\n <yuw-badge\n dot\n color=\"destructive\"\n class=\"absolute -top-1 -right-1\"\n style=\"width: 0.5rem; height: 0.5rem\"\n data-testid=\"hidden-columns-dot\"\n />\n }\n </span>\n\n <div>\n <yuw-combobox\n multiple\n keepValueOnEscape\n [options]=\"columns\"\n [value]=\"hiddenColumns()\"\n [placeholder]=\"labels().columns.placeholder\"\n [emptyText]=\"labels().columns.empty\"\n [triggerAriaLabel]=\"labels().columns.toggle\"\n (valueChange)=\"onHiddenColumnsChange($event)\"\n />\n </div>\n </yuw-popover>\n}\n" }]
3277
+ }], ctorParameters: () => [], propDecorators: { _columnsCombobox: [{ type: i0.ViewChild, args: [i0.forwardRef(() => YuwComboboxComponent), { isSignal: true }] }], hiddenColumns: [{ type: i0.Input, args: [{ isSignal: true, alias: "hiddenColumns", required: false }] }, { type: i0.Output, args: ["hiddenColumnsChange"] }], hideableColumns: [{ type: i0.Input, args: [{ isSignal: true, alias: "hideableColumns", required: false }] }], isMobile: [{ type: i0.Input, args: [{ isSignal: true, alias: "isMobile", required: true }] }], labels: [{ type: i0.Input, args: [{ isSignal: true, alias: "labels", required: true }] }], search: [{ type: i0.Input, args: [{ isSignal: true, alias: "search", required: false }] }, { type: i0.Output, args: ["searchChange"] }], searchPlaceholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "searchPlaceholder", required: false }] }], showExport: [{ type: i0.Input, args: [{ isSignal: true, alias: "showExport", required: false }] }], exported: [{ type: i0.Output, args: ["exported"] }], searched: [{ type: i0.Output, args: ["searched"] }] } });
3204
3278
 
3205
3279
  /**
3206
3280
  * Makes a `<yuw-button>` the trigger of the surrounding `<yuw-sheet>`.