>('userOption');
+
+ activeFilter: KbqFilter = {
+ name: '',
+ readonly: false,
+ disabled: false,
+ changed: false,
+ saved: false,
+ pipes: [
+ {
+ name: 'Assignee',
+ type: KbqPipeTypes.Select,
+ value: null,
+ search: true,
+ cleanable: true,
+ removable: false,
+ disabled: false
+ }
+ ]
+ };
+
+ pipeTemplates: KbqPipeTemplate[] = [];
+
+ ngAfterViewInit(): void {
+ this.pipeTemplates = [
+ {
+ name: 'Assignee',
+ type: KbqPipeTypes.Select,
+ values: USERS.map((user) => ({
+ name: kbqBuildUsernameText(
+ { name: this.usernamePipe.transform(user), login: user.login, site: user.site },
+ { formatSite: (s) => s }
+ ),
+ value: user,
+ id: user.login
+ })),
+ valueTemplate: this.userOptionTemplate(),
+ cleanable: true,
+ removable: false,
+ disabled: false
+ }
+ ];
+ }
+}
diff --git a/packages/docs-examples/components/username/username-search/username-search-example.ts b/packages/docs-examples/components/username/username-search/username-search-example.ts
new file mode 100644
index 0000000000..d30b58da95
--- /dev/null
+++ b/packages/docs-examples/components/username/username-search/username-search-example.ts
@@ -0,0 +1,94 @@
+import { ChangeDetectionStrategy, Component, computed, inject } from '@angular/core';
+import { toSignal } from '@angular/core/rxjs-interop';
+import { FormControl, ReactiveFormsModule } from '@angular/forms';
+import { KbqHighlightBackgroundPipe } from '@koobiq/components/core';
+import { KbqFormFieldModule } from '@koobiq/components/form-field';
+import { KbqIconModule } from '@koobiq/components/icon';
+import { KbqInputModule } from '@koobiq/components/input';
+import { kbqBuildUsernameText, KbqUserInfo, KbqUsernameModule, KbqUsernamePipe } from '@koobiq/components/username';
+import { startWith } from 'rxjs';
+
+/**
+ * @title Username search
+ */
+@Component({
+ selector: 'username-search-example',
+ imports: [
+ ReactiveFormsModule,
+ KbqFormFieldModule,
+ KbqInputModule,
+ KbqUsernameModule,
+ KbqIconModule,
+ KbqHighlightBackgroundPipe
+ ],
+ template: `
+
+
+
+
+
+
+
+ @for (user of filteredUsers(); track user) {
+
+
+ @let fullName = user | kbqUsername;
+
+
+ @if (user.login) {
+
+ }
+
+
+ } @empty {
+ Nothing found
+ }
+
+ `,
+ styles: `
+ .example__users-list {
+ display: flex;
+ flex-direction: column;
+ gap: var(--kbq-size-s);
+ }
+ `,
+ changeDetection: ChangeDetectionStrategy.OnPush,
+ host: {
+ class: 'layout-column layout-gap-m layout-padding-m'
+ }
+})
+export class UsernameSearchExample {
+ private readonly usernamePipe = inject(KbqUsernamePipe);
+
+ protected readonly searchControl = new FormControl('', { nonNullable: true });
+
+ private readonly searchText = toSignal(this.searchControl.valueChanges.pipe(startWith('')), { initialValue: '' });
+
+ protected readonly users: KbqUserInfo[] = [
+ { firstName: 'Maxwell', middleName: 'Alan', lastName: 'Root', login: 'mroot', site: 'corp' },
+ { firstName: 'Alice', middleName: 'Marie', lastName: 'Stone', login: 'astone' },
+ { firstName: 'Robert', lastName: 'Green', login: 'rgreen', site: 'dev' },
+ { firstName: 'Elena', middleName: 'Vera', lastName: 'Fox', login: 'efox' }
+ ];
+
+ protected readonly filteredUsers = computed(() => {
+ const query = (this.searchText() ?? '').toLowerCase().trim();
+
+ if (!query) return this.users;
+
+ return this.users.filter((user) =>
+ kbqBuildUsernameText(
+ { name: this.usernamePipe.transform(user), login: user.login, site: user.site },
+ { formatSite: (s) => s }
+ )
+ .toLowerCase()
+ .includes(query)
+ );
+ });
+}
diff --git a/tools/public_api_guard/components/username.api.md b/tools/public_api_guard/components/username.api.md
index 3b4f48174e..a01e755026 100644
--- a/tools/public_api_guard/components/username.api.md
+++ b/tools/public_api_guard/components/username.api.md
@@ -11,6 +11,11 @@ import { PipeTransform } from '@angular/core';
// @public
export const KBQ_PROFILE_MAPPING: InjectionToken;
+// @public
+export function kbqBuildUsernameText(data: {
+ name: string;
+} & Partial>, options?: KbqUsernameTextOptions): string;
+
// @public
export const kbqDefaultFullNameFormat = "lf.m.";
@@ -137,6 +142,12 @@ export class KbqUsernameSecondaryHint {
// @public
export type KbqUsernameStyle = 'default' | 'error' | 'accented' | 'inherit';
+// @public (undocumented)
+export interface KbqUsernameTextOptions {
+ formatLogin?: (login: string) => string;
+ formatSite?: (site: string) => string;
+}
+
// (No @packageDocumentation comment for this package)
```