mirror of
https://github.com/bitwarden/browser.git
synced 2024-11-26 12:25:20 +01:00
[EC-623] Reusable Search Input Component (#4082)
* [EC-623] Introduce shared organization module and search input component * [EC-623] Add search input story * [EC-623] Rename search input component tag prefix from bit->app
This commit is contained in:
parent
750ff736cd
commit
c002573581
@ -1,11 +1,10 @@
|
||||
import { NgModule } from "@angular/core";
|
||||
|
||||
import { SharedModule } from "../shared";
|
||||
|
||||
import { AccessSelectorModule } from "./components/access-selector";
|
||||
import { OrganizationsRoutingModule } from "./organization-routing.module";
|
||||
import { SharedOrganizationModule } from "./shared";
|
||||
|
||||
@NgModule({
|
||||
imports: [SharedModule, AccessSelectorModule, OrganizationsRoutingModule],
|
||||
imports: [SharedOrganizationModule, AccessSelectorModule, OrganizationsRoutingModule],
|
||||
})
|
||||
export class OrganizationModule {}
|
||||
|
@ -0,0 +1,21 @@
|
||||
<label class="tw-sr-only" [for]="id">{{ "search" | i18n }}</label>
|
||||
<div class="tw-relative tw-flex tw-items-center">
|
||||
<label
|
||||
[for]="id"
|
||||
aria-hidden="true"
|
||||
class="tw-absolute tw-left-2 tw-z-20 !tw-mb-0 tw-cursor-text"
|
||||
>
|
||||
<i class="bwi bwi-search bwi-fw tw-text-muted"></i>
|
||||
</label>
|
||||
<input
|
||||
bitInput
|
||||
type="search"
|
||||
[id]="id"
|
||||
[placeholder]="placeholder ?? ('search' | i18n)"
|
||||
class="tw-rounded-l tw-pl-9"
|
||||
[ngModel]="searchText"
|
||||
(ngModelChange)="onChange($event)"
|
||||
(blur)="onTouch()"
|
||||
[disabled]="disabled"
|
||||
/>
|
||||
</div>
|
@ -0,0 +1,54 @@
|
||||
import { Component, Input } from "@angular/core";
|
||||
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from "@angular/forms";
|
||||
|
||||
let nextId = 0;
|
||||
|
||||
@Component({
|
||||
selector: "app-search-input",
|
||||
templateUrl: "./search-input.component.html",
|
||||
providers: [
|
||||
{
|
||||
provide: NG_VALUE_ACCESSOR,
|
||||
multi: true,
|
||||
useExisting: SearchInputComponent,
|
||||
},
|
||||
],
|
||||
})
|
||||
export class SearchInputComponent implements ControlValueAccessor {
|
||||
private notifyOnChange: (v: string) => void;
|
||||
private notifyOnTouch: () => void;
|
||||
|
||||
protected id = `search-id-${nextId++}`;
|
||||
protected searchText: string;
|
||||
|
||||
@Input() disabled: boolean;
|
||||
@Input() placeholder: string;
|
||||
|
||||
onChange(searchText: string) {
|
||||
if (this.notifyOnChange != undefined) {
|
||||
this.notifyOnChange(searchText);
|
||||
}
|
||||
}
|
||||
|
||||
onTouch() {
|
||||
if (this.notifyOnTouch != undefined) {
|
||||
this.notifyOnTouch();
|
||||
}
|
||||
}
|
||||
|
||||
registerOnChange(fn: (v: string) => void): void {
|
||||
this.notifyOnChange = fn;
|
||||
}
|
||||
|
||||
registerOnTouched(fn: () => void): void {
|
||||
this.notifyOnTouch = fn;
|
||||
}
|
||||
|
||||
writeValue(searchText: string): void {
|
||||
this.searchText = searchText;
|
||||
}
|
||||
|
||||
setDisabledState(isDisabled: boolean) {
|
||||
this.disabled = isDisabled;
|
||||
}
|
||||
}
|
@ -0,0 +1,36 @@
|
||||
import { FormsModule, ReactiveFormsModule } from "@angular/forms";
|
||||
import { Meta, moduleMetadata, Story } from "@storybook/angular";
|
||||
|
||||
import { JslibModule } from "@bitwarden/angular/jslib.module";
|
||||
import { InputModule } from "@bitwarden/components/src/input/input.module";
|
||||
|
||||
import { PreloadedEnglishI18nModule } from "../../../../tests/preloaded-english-i18n.module";
|
||||
|
||||
import { SearchInputComponent } from "./search-input.component";
|
||||
|
||||
export default {
|
||||
title: "Web/Organizations/Search Input",
|
||||
component: SearchInputComponent,
|
||||
decorators: [
|
||||
moduleMetadata({
|
||||
imports: [
|
||||
InputModule,
|
||||
FormsModule,
|
||||
ReactiveFormsModule,
|
||||
PreloadedEnglishI18nModule,
|
||||
JslibModule,
|
||||
],
|
||||
providers: [],
|
||||
}),
|
||||
],
|
||||
} as Meta;
|
||||
|
||||
const Template: Story<SearchInputComponent> = (args: SearchInputComponent) => ({
|
||||
props: args,
|
||||
template: `
|
||||
<app-search-input [(ngModel)]="searchText" [placeholder]="placeholder" [disabled]="disabled"></app-search-input>
|
||||
`,
|
||||
});
|
||||
|
||||
export const Default = Template.bind({});
|
||||
Default.args = {};
|
1
apps/web/src/app/organizations/shared/index.ts
Normal file
1
apps/web/src/app/organizations/shared/index.ts
Normal file
@ -0,0 +1 @@
|
||||
export * from "./shared-organization.module";
|
@ -0,0 +1,12 @@
|
||||
import { NgModule } from "@angular/core";
|
||||
|
||||
import { SharedModule } from "../../shared";
|
||||
|
||||
import { SearchInputComponent } from "./components/search-input/search-input.component";
|
||||
|
||||
@NgModule({
|
||||
imports: [SharedModule],
|
||||
declarations: [SearchInputComponent],
|
||||
exports: [SharedModule, SearchInputComponent],
|
||||
})
|
||||
export class SharedOrganizationModule {}
|
Loading…
Reference in New Issue
Block a user