Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions packages/components-dev/username/module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { UsernameExamplesModule } from '../../docs-examples/components/username'
<username-overview-example />
<username-playground-example />
<username-custom-example />
<username-compact-example />
<username-as-link-example />
<username-search-example />
<username-filter-bar-option-example />
Expand Down
2 changes: 2 additions & 0 deletions packages/components/username/username.en.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ Displaying the username means showing a set of attributes from the internal syst

`isCompact` renders everything as a single line: the name if the profile has one, the login otherwise — never both. Use it where the row has no space for two parts, such as a select trigger.

<Example id="username-compact" />

### Custom template

If flexible layout is required and the default template doesn’t meet your needs, project a `<kbq-username-custom-view>`; it composes with any `mode` and `type`, so consistency with the design system is maintained.
Expand Down
2 changes: 2 additions & 0 deletions packages/components/username/username.ru.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@

`isCompact` выводит всё одной строкой: имя, если оно есть в профиле, иначе логин, но не оба сразу. Используйте этот режим там, где на две части нет места, например в триггере селекта.

<Example id="username-compact" />

### Пользовательский шаблон

Если стандартного шаблона недостаточно, спроецируйте `<kbq-username-custom-view>`: он сочетается с любыми `mode` и `type` и сохраняет согласованность с дизайн-системой.
Expand Down
3 changes: 3 additions & 0 deletions packages/docs-examples/components/username/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { NgModule } from '@angular/core';
import { UsernameAsLinkExample } from './username-as-link/username-as-link-example';
import { UsernameCompactExample } from './username-compact/username-compact-example';
import { UsernameCustomExample } from './username-custom/username-custom-example';
import { UsernameFilterBarOptionExample } from './username-filter-bar-option/username-filter-bar-option-example';
import { UsernameOverviewExample } from './username-overview/username-overview-example';
Expand All @@ -8,6 +9,7 @@ import { UsernameSearchExample } from './username-search/username-search-example

export {
UsernameAsLinkExample,
UsernameCompactExample,
UsernameCustomExample,
UsernameFilterBarOptionExample,
UsernameOverviewExample,
Expand All @@ -16,6 +18,7 @@ export {
};

const EXAMPLES = [
UsernameCompactExample,
UsernameCustomExample,
UsernameOverviewExample,
UsernamePlaygroundExample,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { ChangeDetectionStrategy, Component } from '@angular/core';
import { KbqUserInfo, KbqUsername } from '@koobiq/components/username';

/**
* @title Username compact
*/
@Component({
selector: 'username-compact-example',
imports: [KbqUsername],
template: `
@for (user of users; track user) {
<kbq-username isCompact [userInfo]="user" />
}
`,
changeDetection: ChangeDetectionStrategy.OnPush,
host: {
class: 'layout-column layout-gap-s layout-padding-m'
}
})
export class UsernameCompactExample {
protected readonly users: KbqUserInfo[] = [
{ firstName: 'Maxwell', middleName: 'Alan', lastName: 'Root', login: 'mroot', site: 'corp' },
{ firstName: 'Madonna', login: 'madonna' },
{ login: 'efox', site: 'dev' }
];
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@
{ 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' }
{ firstName: 'Elena', middleName: 'Vera', lastName: 'Fox', login: 'efox' },
{ firstName: 'Madonna', login: 'madonna', site: 'corp' }
];

/**
Expand All @@ -29,18 +30,23 @@
</kbq-filter-bar>

<ng-template #userOption let-pipe let-option="option">
@let searchText = pipe.searchControl.value;
@let keywords = splitSearch(pipe.searchControl.value);

<kbq-username>
<kbq-username-custom-view>
@let fullName = option.value | kbqUsername;
<span kbqUsernamePrimary [innerHTML]="fullName | kbqHighlightBackground: searchText"></span>
<span kbqUsernamePrimary [innerHTML]="fullName | kbqHighlightBackground: keywords"></span>

@if (option.value?.login) {
<span
kbqUsernameSecondary
[innerHTML]="option.value.login | kbqHighlightBackground: searchText"
></span>
<span kbqUsernameSecondary>
<span [innerHTML]="option.value.login | kbqHighlightBackground: keywords"></span>
@if (option.value.site) {
<span
kbqUsernameSecondaryHint
[innerHTML]="' (' + option.value.site + ')' | kbqHighlightBackground: keywords"

Check failure on line 46 in packages/docs-examples/components/username/username-filter-bar-option/username-filter-bar-option-example.ts

View workflow job for this annotation

GitHub Actions / linters

Irregular whitespace not allowed
></span>
}
</span>
}
</kbq-username-custom-view>
</kbq-username>
Expand Down Expand Up @@ -73,6 +79,11 @@

pipeTemplates: KbqPipeTemplate[] = [];

// The name, the login and the site are rendered in separate elements, so each word of the query is highlighted on its own.
protected splitSearch(text: string | null): string[] {
return (text ?? '').split(/\s+/).filter(Boolean);
}

ngAfterViewInit(): void {
this.pipeTemplates = [
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,16 +38,18 @@
<kbq-username>
<kbq-username-custom-view>
@let fullName = user | kbqUsername;
<span
kbqUsernamePrimary
[innerHTML]="fullName | kbqHighlightBackground: searchControl.value.trim()"
></span>
<span kbqUsernamePrimary [innerHTML]="fullName | kbqHighlightBackground: keywords()"></span>

@if (user.login) {
<span
kbqUsernameSecondary
[innerHTML]="user.login | kbqHighlightBackground: searchControl.value.trim()"
></span>
<span kbqUsernameSecondary>
<span [innerHTML]="user.login | kbqHighlightBackground: keywords()"></span>
@if (user.site) {
<span
kbqUsernameSecondaryHint
[innerHTML]="' (' + user.site + ')' | kbqHighlightBackground: keywords()"

Check failure on line 49 in packages/docs-examples/components/username/username-search/username-search-example.ts

View workflow job for this annotation

GitHub Actions / linters

Irregular whitespace not allowed
></span>
}
</span>
}
</kbq-username-custom-view>
</kbq-username>
Expand Down Expand Up @@ -79,21 +81,25 @@
{ 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' }
{ firstName: 'Elena', middleName: 'Vera', lastName: 'Fox', login: 'efox' },
{ firstName: 'Madonna', login: 'madonna', site: 'corp' }
];

// The name, the login and the site are rendered in separate elements, so each word of the query is highlighted on its own.
protected readonly keywords = computed(() => (this.searchText() ?? '').split(/\s+/).filter(Boolean));

protected readonly filteredUsers = computed(() => {
const query = (this.searchText() ?? '').toLowerCase().trim();
const keywords = this.keywords().map((word) => word.toLowerCase());

if (!query) return this.users;
if (!keywords.length) return this.users;

return this.users.filter((user) =>
kbqBuildUsernameText(
return this.users.filter((user) => {
const text = kbqBuildUsernameText(
{ name: this.formatUsername(user), login: user.login, site: user.site },
{ formatSite: (s) => s }
)
.toLowerCase()
.includes(query)
);
).toLowerCase();

return keywords.every((word) => text.includes(word));
});
});
}
13 changes: 13 additions & 0 deletions packages/docs-examples/example-module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7621,6 +7621,18 @@ export const EXAMPLE_COMPONENTS: {[id: string]: LiveExample} = {
"primaryFile": "username-as-link-example.ts",
"importPath": "components/username"
},
"username-compact": {
"packagePath": "components/username/username-compact",
"title": "Username compact",
"componentName": "UsernameCompactExample",
"files": [
"username-compact-example.ts"
],
"localImportFiles": [],
"selector": "username-compact-example",
"primaryFile": "username-compact-example.ts",
"importPath": "components/username"
},
"username-custom": {
"packagePath": "components/username/username-custom",
"title": "Username custom",
Expand Down Expand Up @@ -8518,6 +8530,7 @@ export type LiveExampleId =
| 'tree-state-saving'
| 'tree-toggle-on-click'
| 'username-as-link'
| 'username-compact'
| 'username-custom'
| 'username-filter-bar-option'
| 'username-overview'
Expand Down
2 changes: 2 additions & 0 deletions packages/docs-examples/loader/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1241,6 +1241,8 @@ export async function loadExampleComponent(id: string): Promise<Type<unknown> |
return import('@koobiq/docs-examples/components/tree').then((m) => m.TreeToggleOnClickExample);
case 'username-as-link':
return import('@koobiq/docs-examples/components/username').then((m) => m.UsernameAsLinkExample);
case 'username-compact':
return import('@koobiq/docs-examples/components/username').then((m) => m.UsernameCompactExample);
case 'username-custom':
return import('@koobiq/docs-examples/components/username').then((m) => m.UsernameCustomExample);
case 'username-filter-bar-option':
Expand Down
Loading