@exmg/exm-search 0.0.2-alpha.0

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.
package/README.md ADDED
@@ -0,0 +1,60 @@
1
+ # `<exm-search>` [![Published on npm](https://img.shields.io/npm/v/@exmg/exm-search.svg)](https://www.npmjs.com/package/@exmg/exm-search)
2
+
3
+ # exm-search
4
+
5
+ Exmg search provides an search input in material 3 style
6
+
7
+ ## Installation
8
+
9
+ ```sh
10
+ npm install @exmg/exm-search
11
+ ```
12
+
13
+ ## Example Usage
14
+
15
+ ```html
16
+ <exm-search placeHolder="Filter table.." @search-value-change="${() => console.log('update')}"></exm-search>
17
+ ```
18
+
19
+ ## API
20
+
21
+ ### Properties/Attributes
22
+
23
+ | Name | Type | Default | Description |
24
+ | ------------- | --------- | -------- | ----------------------------------------------- |
25
+ | `bubbles` | `boolean` | _false_ | Whether or not the change events need to bubble |
26
+ | `placeHolder` | `string` | `Search` | Default value for placeholder |
27
+
28
+ ## Styles
29
+
30
+ | Custom property | Description | Default |
31
+ | ------------------------------------- | ---------------------- | -------------------------------------------- |
32
+ | `--exm-search-outline-color` | outline color | `--md-outlined-field-hover-outline-width`; |
33
+ | `--exm-search-outline-width` | outline width | `1px`; |
34
+ | `--exm-search-container-shape` | container shape | `4px`; |
35
+ | `--exm-search-focus-input-text-color` | focus input text color | `--md-sys-color-on-surface`; |
36
+ | `--exm-search-focus-label-text-color` | focus label text color | `--md-sys-color-primary`; |
37
+ | `--exm-search-focus-icon-color` | focus icon color | `--md-sys-color-on-surface-variant`; |
38
+ | `--exm-search-focus-outline-color` | focus outline color | `--md-sys-color-primary`; |
39
+ | `--exm-search-focus-outline-width` | focus outline width | `1px`; |
40
+ | `--exm-search-hover-input-text-color` | hover input text color | `--md-sys-color-on-surface`; |
41
+ | `--exm-search-hover-label-text-color` | hover label text color | `--md-sys-color-on-surface`; |
42
+ | `--exm-search-hover-outline-color` | hover outline color | `--md-sys-color-on-surface` |
43
+ | `--exm-search-input-text-color` | input text color | `--md-sys-color-on-surface`; |
44
+ | `--exm-search-input-text-font` | input text font | `--md-sys-typescale-body-large-font`; |
45
+ | `--exm-search-input-text-line-height` | input text line height | `--md-sys-typescale-body-large-line-height`; |
46
+ | `--exm-search-input-text-size` | input text size | `--md-sys-typescale-body-large-size`; |
47
+ | `--exm-search-input-text-weight` | input text weight | `--md-sys-typescale-body-large-weight`; |
48
+ | `--exm-search-label-text-color` | label text color | `md-sys-color-on-surface-variant`; |
49
+ | `--exm-search-label-text-font` | label text font | `--md-sys-typescale-body-large-font`; |
50
+ | `--exm-search-label-text-line-height` | label line height | `--md-sys-typescale-body-large-line-height`; |
51
+ | `--exm-search-label-text-size` | label text size | `--md-sys-typescale-body-large-size`; |
52
+ | `--exm-search-label-text-weight` | label weight | `--md-sys-typescale-body-large-weight`; |
53
+ | `--exm-search-icon-color` | icon color | `--md-sys-color-on-surface-variant`; |
54
+ | `--exm-search-icon-size` | icon size | `24px`; |
55
+ | `--exm-search-outline-color` | outline color | `--md-sys-color-outline`; |
56
+ | `--exm-search-outline-width` | outline color width | `1px`; |
57
+
58
+ ## Additional references
59
+
60
+ - [Demo](https://exmg.github.io/exmachina-web-components/demo/?el=exm-search)
@@ -0,0 +1,22 @@
1
+ import { ExmgElement } from '@exmg/lit-base';
2
+ import { PropertyValues } from 'lit';
3
+ export declare class ExmSearchBase extends ExmgElement {
4
+ bubbles: boolean;
5
+ _hasFocus: boolean;
6
+ filterValue?: string | null;
7
+ placeHolder: string;
8
+ search?: HTMLInputElement;
9
+ detectOutsideBind?: (e: Event) => void;
10
+ constructor();
11
+ protected fire<T>(eventName: string, detail?: T, bubbles?: boolean): void;
12
+ focus(): void;
13
+ protected firstUpdated(_changedProperties: PropertyValues): void;
14
+ disconnectedCallback(): void;
15
+ detectOutsideClick(e: Event): void;
16
+ render(): import("lit-html").TemplateResult<1>;
17
+ _getValue(): string;
18
+ _notifyChange(): void;
19
+ _handleClear(e: Event): void;
20
+ _handleKeyUp(e: KeyboardEvent): void;
21
+ updated(changedProperties: Map<string, any>): void;
22
+ }
@@ -0,0 +1,129 @@
1
+ import { __decorate } from "tslib";
2
+ import { ExmgElement } from '@exmg/lit-base';
3
+ import { html, nothing } from 'lit';
4
+ import { property, query, state } from 'lit/decorators.js';
5
+ import { classMap } from 'lit/directives/class-map.js';
6
+ export class ExmSearchBase extends ExmgElement {
7
+ constructor() {
8
+ super();
9
+ this.bubbles = false;
10
+ this._hasFocus = true;
11
+ this.placeHolder = 'Search';
12
+ // Set default tabindex to 0
13
+ const tabindex = this.getAttribute('tabindex');
14
+ this.setAttribute('tabindex', tabindex || '0');
15
+ }
16
+ fire(eventName, detail, bubbles) {
17
+ this.dispatchEvent(new CustomEvent(eventName, {
18
+ bubbles: bubbles || this.bubbles,
19
+ composed: true,
20
+ detail,
21
+ }));
22
+ }
23
+ focus() {
24
+ this._hasFocus = true;
25
+ }
26
+ firstUpdated(_changedProperties) {
27
+ this.detectOutsideBind = this.detectOutsideClick.bind(this);
28
+ document.addEventListener('click', this.detectOutsideBind);
29
+ }
30
+ disconnectedCallback() {
31
+ this.detectOutsideBind && document.removeEventListener('click', this.detectOutsideBind);
32
+ super.disconnectedCallback();
33
+ }
34
+ detectOutsideClick(e) {
35
+ const path = e.composedPath();
36
+ if (path.length > 0) {
37
+ // @ts-ignore
38
+ const container = path.find((el) => el.id === 'clickbox');
39
+ // const container = actualTarget.closest('#clickbox');
40
+ if (!container) {
41
+ // Clicked outside the box
42
+ this._hasFocus = false;
43
+ }
44
+ }
45
+ }
46
+ render() {
47
+ const classMapValues = {
48
+ search: true,
49
+ hasFocus: this._hasFocus,
50
+ };
51
+ return html `
52
+ <div id="clickbox" class=${classMap(classMapValues)}>
53
+ <div class="mode-input">
54
+ <md-focus-ring for="searchInput" inward></md-focus-ring>
55
+ <md-icon class="search">search</md-icon>
56
+ <input
57
+ id="searchInput"
58
+ placeholder=${this.placeHolder}
59
+ value=${this.filterValue ? this.filterValue : ''}
60
+ onfocus="let value = this.value; this.value = null; this.value = value"
61
+ @keyup=${this._handleKeyUp}
62
+ />
63
+ ${this.filterValue
64
+ ? html `
65
+ <md-icon-button class="clear" @click=${this._handleClear}><md-icon>clear</md-icon></md-icon-button>
66
+ `
67
+ : nothing}
68
+ </div>
69
+ <div class="mode-default" @click=${() => this.focus()}>
70
+ <md-icon class="search">search</md-icon>
71
+ <span class="interactive-content">${this._getValue()}</span>
72
+ ${this.filterValue
73
+ ? html `
74
+ <md-icon-button class="clear" @click=${this._handleClear}><md-icon>clear</md-icon></md-icon-button>
75
+ `
76
+ : nothing}
77
+ </div>
78
+ </div>
79
+ `;
80
+ }
81
+ _getValue() {
82
+ return this.filterValue || this.placeHolder;
83
+ }
84
+ _notifyChange() {
85
+ this.fire('search-value-change', { value: this.filterValue }, this.bubbles);
86
+ }
87
+ _handleClear(e) {
88
+ var _a;
89
+ e.stopPropagation();
90
+ e.preventDefault();
91
+ this.filterValue = null;
92
+ if (this.search) {
93
+ this.search.value = '';
94
+ }
95
+ this._notifyChange();
96
+ (_a = this.search) === null || _a === void 0 ? void 0 : _a.focus();
97
+ }
98
+ _handleKeyUp(e) {
99
+ const input = e.target;
100
+ if (this.filterValue !== input.value) {
101
+ this.filterValue = input.value;
102
+ this._notifyChange();
103
+ }
104
+ if (e.key === 'Escape') {
105
+ this._hasFocus = false;
106
+ }
107
+ }
108
+ updated(changedProperties) {
109
+ if (changedProperties.has('_hasFocus')) {
110
+ // after _hasFocus changed to true, focus the input
111
+ if (this._hasFocus) {
112
+ this.shadowRoot.querySelector('#searchInput').focus();
113
+ }
114
+ }
115
+ }
116
+ }
117
+ __decorate([
118
+ state()
119
+ ], ExmSearchBase.prototype, "_hasFocus", void 0);
120
+ __decorate([
121
+ property({ type: String })
122
+ ], ExmSearchBase.prototype, "filterValue", void 0);
123
+ __decorate([
124
+ property({ type: String })
125
+ ], ExmSearchBase.prototype, "placeHolder", void 0);
126
+ __decorate([
127
+ query('#searchInput')
128
+ ], ExmSearchBase.prototype, "search", void 0);
129
+ //# sourceMappingURL=exm-search-base.js.map
@@ -0,0 +1,10 @@
1
+ import '@material/web/progress/circular-progress.js';
2
+ import { ExmSearchBase } from './exm-search-base.js';
3
+ export declare class ExmSearch extends ExmSearchBase {
4
+ static styles: import("lit").CSSResult[];
5
+ }
6
+ declare global {
7
+ interface HTMLElementTagNameMap {
8
+ 'exm-search': ExmSearch;
9
+ }
10
+ }
@@ -0,0 +1,13 @@
1
+ import { __decorate } from "tslib";
2
+ import { customElement } from 'lit/decorators/custom-element.js';
3
+ import '@material/web/progress/circular-progress.js';
4
+ import { ExmSearchBase } from './exm-search-base.js';
5
+ import { style } from './styles/exm-search-css.js';
6
+ let ExmSearch = class ExmSearch extends ExmSearchBase {
7
+ };
8
+ ExmSearch.styles = [style];
9
+ ExmSearch = __decorate([
10
+ customElement('exm-search')
11
+ ], ExmSearch);
12
+ export { ExmSearch };
13
+ //# sourceMappingURL=exm-search.js.map
@@ -0,0 +1,3 @@
1
+ export { ExmSearch } from './exm-search.js';
2
+ export { ExmSearchBase } from './exm-search-base.js';
3
+ export { style as exmgSearchStyles } from './styles/exm-search-css.js';
package/dist/index.js ADDED
@@ -0,0 +1,4 @@
1
+ export { ExmSearch } from './exm-search.js';
2
+ export { ExmSearchBase } from './exm-search-base.js';
3
+ export { style as exmgSearchStyles } from './styles/exm-search-css.js';
4
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ export declare const style: import("lit").CSSResult;
@@ -0,0 +1,178 @@
1
+ import { css } from 'lit';
2
+ export const style = css `
3
+ :host {
4
+ display: block;
5
+ --_hover-outline-color: var(--exm-search-hover-outline-color, var(--md-sys-color-on-surface, #1d1b20));
6
+ --_outline-width: var(--exm-search-outline-width, 1px);
7
+ --_outline-color: var(--exm-search-outline-color, var(--md-outlined-field-hover-outline-width, 1px));
8
+ --_container-shape: var(--exm-search-container-shape, 4px);
9
+ --_focus-input-text-color: var(--exm-search-focus-input-text-color, var(--md-sys-color-on-surface, #1d1b20));
10
+ --_focus-label-text-color: var(--exm-search-focus-label-text-color, var(--md-sys-color-primary, #6750a4));
11
+ --_focus-icon-color: var(--exm-search-focus-icon-color, var(--md-sys-color-on-surface-variant, #49454f));
12
+ --_focus-outline-color: var(--exm-search-focus-outline-color, var(--md-sys-color-primary, #6750a4));
13
+ --_focus-outline-width: var(--exm-search-focus-outline-width, 1px);
14
+ --_hover-input-text-color: var(--exm-search-hover-input-text-color, var(--md-sys-color-on-surface, #1d1b20));
15
+ --_hover-label-text-color: var(--exm-search-hover-label-text-color, var(--md-sys-color-on-surface, #1d1b20));
16
+ --_hover-icon-color: var(--exm-search-hover-icon-color, var(--md-sys-color-on-surface-variant, #49454f));
17
+ --_hover-outline-color: var(--exm-search-hover-outline-color, var(--md-sys-color-on-surface, #1d1b20));
18
+ --_input-text-color: var(--exm-search-input-text-color, var(--md-sys-color-on-surface, #1d1b20));
19
+ --_input-text-font: var(
20
+ --exm-search-input-text-font,
21
+ var(--md-sys-typescale-body-large-font, var(--md-ref-typeface-plain, Roboto))
22
+ );
23
+ --_input-text-line-height: var(
24
+ --exm-search-input-text-line-height,
25
+ var(--md-sys-typescale-body-large-line-height, 1.5rem)
26
+ );
27
+ --_input-text-size: var(--exm-search-input-text-size, var(--md-sys-typescale-body-large-size, 1rem));
28
+ --_input-text-weight: var(
29
+ --exm-search-input-text-weight,
30
+ var(--md-sys-typescale-body-large-weight, var(--md-ref-typeface-weight-regular, 400))
31
+ );
32
+ --_label-text-color: var(--exm-search-label-text-color, var(--md-sys-color-on-surface-variant, #49454f));
33
+ --_label-text-font: var(
34
+ --exm-search-label-text-font,
35
+ var(--md-sys-typescale-body-large-font, var(--md-ref-typeface-plain, Roboto))
36
+ );
37
+ --_label-text-line-height: var(
38
+ --exm-search-label-text-line-height,
39
+ var(--md-sys-typescale-body-large-line-height, 1.5rem)
40
+ );
41
+ --_label-text-size: var(--exm-search-label-text-size, var(--md-sys-typescale-body-large-size, 1rem));
42
+ --_label-text-weight: var(
43
+ --exm-search-label-text-weight,
44
+ var(--md-sys-typescale-body-large-weight, var(--md-ref-typeface-weight-regular, 400))
45
+ );
46
+ --_icon-color: var(--exm-search-icon-color, var(--md-sys-color-on-surface-variant, #49454f));
47
+ --_icon-size: var(--exm-search-icon-size, 24px);
48
+ --_outline-color: var(--exm-search-outline-color, var(--md-sys-color-outline, #79747e));
49
+ --_outline-width: var(--exm-search-outline-width, 1px);
50
+ --md-focus-ring-shape: var(--_container-shape);
51
+ color: var(--_label-text-color);
52
+ background-color: var(--md-sys-color-surface-container-low);
53
+ border-radius: var(--_container-shape);
54
+ border-width: var(--_outline-width);
55
+ border-color: var(--_outline-color);
56
+ border-style: solid;
57
+ }
58
+
59
+ :host(:hover) {
60
+ border-color: var(--_hover-outline-color);
61
+ color: var(--_hover-label-text-color);
62
+ }
63
+
64
+ :host(:focus) {
65
+ border-color: var(--_focus-outline-color);
66
+ color: var(--_focus-label-text-color);
67
+ border-width: var(--_focus-outline-width);
68
+ }
69
+
70
+ :host > div {
71
+ display: flex;
72
+ flex-direction: row;
73
+ justify-content: center;
74
+ align-items: center;
75
+ height: 48px;
76
+ }
77
+
78
+ h2 {
79
+ max-width: 936px;
80
+ width: 100%;
81
+ margin: 20px auto;
82
+ }
83
+
84
+ input {
85
+ width: 100%;
86
+ caret-color: var(--md-sys-color-on-surface);
87
+ color: var(--md-sys-color-on-surface);
88
+ }
89
+
90
+ :host(:hover) input {
91
+ color: var(--_hover-input-text-color);
92
+ }
93
+
94
+ :host(:focus) input {
95
+ color: var(--_focus-input-text-color);
96
+ }
97
+
98
+ md-icon {
99
+ fill: var(--_icon-color);
100
+ }
101
+
102
+ md-icon.search {
103
+ margin: 0 0.5rem 0 1rem;
104
+ }
105
+
106
+ :host(:hover) md-icon {
107
+ fill: var(--_hover-icon-color);
108
+ }
109
+
110
+ :host(:focus) md-icon {
111
+ fill: var(--_focus-icon-color);
112
+ }
113
+
114
+ md-icon-button.clear {
115
+ margin-right: 0.5rem;
116
+ min-width: 40px;
117
+ }
118
+
119
+ :host > div > svg {
120
+ margin-right: 10px;
121
+ }
122
+
123
+ span.interactive-content {
124
+ white-space: nowrap;
125
+ overflow: hidden;
126
+ font-size: var(--_label-text-size);
127
+ text-overflow: ellipsis;
128
+ letter-spacing: 0.005em;
129
+ box-sizing: border-box;
130
+ line-height: var(--_label-text-line-height);
131
+ font-weight: var(--_label-text-weight);
132
+ cursor: text;
133
+ flex: 1;
134
+ }
135
+
136
+ .search {
137
+ display: absolute;
138
+ background: none;
139
+ }
140
+
141
+ .search > div {
142
+ width: 100%;
143
+ position: relative;
144
+ align-items: center;
145
+ }
146
+
147
+ .search input {
148
+ font-size: var(--_label-text-size);
149
+ height: inherit;
150
+ padding: 2px;
151
+ border: 0px;
152
+ width: 100%;
153
+ letter-spacing: 0.005em;
154
+ line-height: var(--_label-text-line-height);
155
+ font-weight: var(--_label-text-weight);
156
+ outline: none;
157
+ background: none;
158
+ box-sizing: border-box;
159
+ }
160
+
161
+ .mode-default {
162
+ display: flex;
163
+ }
164
+
165
+ .mode-input {
166
+ display: none;
167
+ height: inherit;
168
+ }
169
+
170
+ .search.hasFocus .mode-default {
171
+ display: none;
172
+ }
173
+
174
+ .search.hasFocus .mode-input {
175
+ display: flex;
176
+ }
177
+ `;
178
+ //# sourceMappingURL=exm-search-css.js.map
package/package.json ADDED
@@ -0,0 +1,40 @@
1
+ {
2
+ "name": "@exmg/exm-search",
3
+ "version": "0.0.2-alpha.0+df24e0c",
4
+ "type": "module",
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
7
+ "module": "dist/index.js",
8
+ "exports": {
9
+ ".": "./dist/index.js",
10
+ "./exm-search.js": "./dist/exm-search.js"
11
+ },
12
+ "peerDependencies": {
13
+ "@exmg/lit-base": "^3.0.3",
14
+ "@material/web": "^2.2.0",
15
+ "lit": "^3.2.1",
16
+ "tslib": "^2.6.2"
17
+ },
18
+ "keywords": [
19
+ "web-components",
20
+ "lit",
21
+ "search"
22
+ ],
23
+ "files": [
24
+ "**/*.scss",
25
+ "**/*.js",
26
+ "**/*.d.ts"
27
+ ],
28
+ "homepage": "https://bitbucket.org/exmachina/exm-web-components",
29
+ "repository": {
30
+ "type": "git",
31
+ "url": "git@bitbucket.org:exmachina/exm-web-components.git",
32
+ "directory": "packages/exm-search"
33
+ },
34
+ "license": "MIT",
35
+ "scripts": {},
36
+ "publishConfig": {
37
+ "access": "public"
38
+ },
39
+ "gitHead": "df24e0c74a76a7e1c258f69386036e24e7860256"
40
+ }