@empathyco/x-components 3.0.0-alpha.150 → 3.0.0-alpha.151

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/CHANGELOG.md CHANGED
@@ -3,6 +3,19 @@
3
3
  All notable changes to this project will be documented in this file. See
4
4
  [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ ## [3.0.0-alpha.151](https://github.com/empathyco/x/compare/@empathyco/x-components@3.0.0-alpha.150...@empathyco/x-components@3.0.0-alpha.151) (2022-08-09)
7
+
8
+ ### Documentation
9
+
10
+ - clarify how to subscribe to any `XEvent` (#645)
11
+ ([d57941a](https://github.com/empathyco/x/commit/d57941a52d23f56cb7c04ed49b816a252473243f)),
12
+ closes [EX-6816](https://searchbroker.atlassian.net/browse/EX-6816)
13
+
14
+ # Change Log
15
+
16
+ All notable changes to this project will be documented in this file. See
17
+ [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
18
+
6
19
  ## [3.0.0-alpha.150](https://github.com/empathyco/x/compare/@empathyco/x-components@3.0.0-alpha.149...@empathyco/x-components@3.0.0-alpha.150) (2022-08-08)
7
20
 
8
21
  ### Features
@@ -47,16 +47,6 @@
47
47
  .x-badge-container {
48
48
  position: relative;
49
49
  }
50
- :root {
51
- --x-color-background-badge-default: var(--x-color-base-neutral-10);
52
- --x-color-text-badge-default: var(--x-color-base-neutral-100);
53
- --x-color-border-badge-default: var(--x-color-base-neutral-10);
54
- --x-size-border-radius-badge-default: var(--x-size-border-radius-base-pill);
55
- --x-size-border-width-badge-default: 0;
56
- --x-size-width-badge-default: 1.5em;
57
- --x-number-font-weight-badge-default: var(--x-number-font-weight-base-regular);
58
- --x-size-font-badge-default: var(--x-size-font-base-xs);
59
- }
60
50
  :root {
61
51
  --x-color-background-button-default: var(--x-color-base-lead);
62
52
  --x-color-border-button-default: var(--x-color-background-button-default);
@@ -142,6 +132,16 @@
142
132
  margin-right: var(--x-size-gap-button-default);
143
133
  }
144
134
  }
135
+ :root {
136
+ --x-color-background-badge-default: var(--x-color-base-neutral-10);
137
+ --x-color-text-badge-default: var(--x-color-base-neutral-100);
138
+ --x-color-border-badge-default: var(--x-color-base-neutral-10);
139
+ --x-size-border-radius-badge-default: var(--x-size-border-radius-base-pill);
140
+ --x-size-border-width-badge-default: 0;
141
+ --x-size-width-badge-default: 1.5em;
142
+ --x-number-font-weight-badge-default: var(--x-number-font-weight-base-regular);
143
+ --x-size-font-badge-default: var(--x-size-font-base-xs);
144
+ }
145
145
  :root {
146
146
  --x-color-background-button-default: var(--x-color-base-lead);
147
147
  --x-color-border-button-default: var(--x-color-background-button-default);
@@ -114,6 +114,13 @@
114
114
  --x-size-border-radius-bottom-left-button-card
115
115
  );
116
116
  }
117
+ :root {
118
+ --x-size-border-radius-button-card: var(--x-size-border-radius-base-s);
119
+ --x-size-border-radius-top-left-button-card: var(--x-size-border-radius-button-card);
120
+ --x-size-border-radius-top-right-button-card: var(--x-size-border-radius-button-card);
121
+ --x-size-border-radius-bottom-right-button-card: var(--x-size-border-radius-button-card);
122
+ --x-size-border-radius-bottom-left-button-card: var(--x-size-border-radius-button-card);
123
+ }
117
124
  [dir="ltr"] .x-button {
118
125
  padding-right: var(--x-size-padding-right-button-default);
119
126
  }
@@ -7586,11 +7593,3 @@
7586
7593
  .x-normal-case {
7587
7594
  text-transform: none;
7588
7595
  }
7589
-
7590
- :root {
7591
- --x-size-border-radius-button-card: var(--x-size-border-radius-base-s);
7592
- --x-size-border-radius-top-left-button-card: var(--x-size-border-radius-button-card);
7593
- --x-size-border-radius-top-right-button-card: var(--x-size-border-radius-button-card);
7594
- --x-size-border-radius-bottom-right-button-card: var(--x-size-border-radius-button-card);
7595
- --x-size-border-radius-bottom-left-button-card: var(--x-size-border-radius-button-card);
7596
- }
@@ -98,6 +98,16 @@ For example, if you select the search input box, the message “focus” appears
98
98
  enter a search term, the message “typing” appears. If you press Enter after typing a search term,
99
99
  the message “enter” appears.
100
100
 
101
+ <!-- prettier-ignore-start -->
102
+ :::warning X Events are only emitted from the root X Component.
103
+ At the moment, X Events are only emitted from the root X Component. This means that if you wrap
104
+ the `SearchInput` with another component of another module like the `MainScroll`, you should add
105
+ the listeners to the `MainScroll` instead of the `SearchInput`. If you need to subscribe to these
106
+ events, it is recommended to use the [`GlobalXBus`](../common/x-components.global-x-bus.md)
107
+ component instead.
108
+ :::
109
+ <!-- prettier-ignore-end -->
110
+
101
111
  _Type any term in the input field to try it out!_
102
112
 
103
113
  ```vue live
@@ -162,3 +162,40 @@ Next, you want to configure the behavior of the `SearchInput` component. Here yo
162
162
  :autocompleteSuggestionsEvent="'NextQueriesChanged'"
163
163
  />
164
164
  ```
165
+
166
+ **3. Listening to X Events**
167
+
168
+ For advanced use cases you might need to subscribe to certain `XEvent`. The recommended way to do so
169
+ is by using the `GlobalXBus` component.
170
+
171
+ In this example you are subscribing to the `UserAcceptedAQuery` event. This event is emitted both by
172
+ the `SearchInput` component and by the `QuerySuggestions` one.
173
+
174
+ ```vue live
175
+ <template>
176
+ <div>
177
+ <GlobalXBus @UserAcceptedAQuery="logUserAcceptedAQuery" />
178
+ <SearchInput />
179
+ <QuerySuggestions />
180
+ </div>
181
+ </template>
182
+ <script>
183
+ import { GlobalXBus } from '@empathyco/x-components';
184
+ import { SearchInput } from '@empathyco/x-components/search-box';
185
+ import { QuerySuggestions } from '@empathyco/x-components/query-suggestions';
186
+
187
+ export default {
188
+ name: 'Demo',
189
+ components: {
190
+ GlobalXBus,
191
+ SearchInput,
192
+ QuerySuggestions
193
+ },
194
+ methods: {
195
+ logUserAcceptedAQuery(query, metadata) {
196
+ console.log('UserAcceptedAQuery', query, metadata);
197
+ }
198
+ }
199
+ };
200
+ </script>
201
+ ```
@@ -71,11 +71,11 @@ __vue_render__._withStripped = true;
71
71
  /* style */
72
72
  const __vue_inject_styles__ = function (inject) {
73
73
  if (!inject) return
74
- inject("data-v-38b09624_0", { source: ".x-search-input[data-v-38b09624]::-webkit-search-decoration,\n.x-search-input[data-v-38b09624]::-webkit-search-cancel-button,\n.x-search-input[data-v-38b09624]::-webkit-search-results-button,\n.x-search-input[data-v-38b09624]::-webkit-search-results-decoration {\n -webkit-appearance: none;\n}", map: undefined, media: undefined });
74
+ inject("data-v-5d3fc332_0", { source: ".x-search-input[data-v-5d3fc332]::-webkit-search-decoration,\n.x-search-input[data-v-5d3fc332]::-webkit-search-cancel-button,\n.x-search-input[data-v-5d3fc332]::-webkit-search-results-button,\n.x-search-input[data-v-5d3fc332]::-webkit-search-results-decoration {\n -webkit-appearance: none;\n}", map: undefined, media: undefined });
75
75
 
76
76
  };
77
77
  /* scoped */
78
- const __vue_scope_id__ = "data-v-38b09624";
78
+ const __vue_scope_id__ = "data-v-5d3fc332";
79
79
  /* module identifier */
80
80
  const __vue_module_identifier__ = undefined;
81
81
  /* functional template */
@@ -1 +1 @@
1
- {"version":3,"file":"search-input.vue.js","sources":["../../../../../src/x-modules/search-box/components/search-input.vue"],"sourcesContent":["<template>\n <input\n ref=\"input\"\n @blur=\"emitUserBlurredSearchBox\"\n @click=\"emitUserClickedSearchBox\"\n @focus=\"emitUserFocusedSearchBox\"\n @input=\"emitUserIsTypingAQueryEvents\"\n @keydown.enter=\"emitUserPressedEnterKey\"\n @keydown.up.down.prevent=\"emitUserPressedArrowKey\"\n v-on=\"$listeners\"\n :maxlength=\"maxLength\"\n :value=\"query\"\n autocomplete=\"off\"\n class=\"x-input x-search-input\"\n enterkeyhint=\"search\"\n inputmode=\"search\"\n type=\"search\"\n data-test=\"search-input\"\n :aria-label=\"searchInputMessage\"\n />\n</template>\n\n<script lang=\"ts\">\n import { Suggestion } from '@empathyco/x-types';\n import Vue from 'vue';\n import { Component, Prop } from 'vue-property-decorator';\n import { XOn } from '../../../components/decorators/bus.decorators';\n import { State } from '../../../components/decorators/store.decorators';\n import { xComponentMixin } from '../../../components/x-component.mixin';\n import { ArrowKey, PropsWithType } from '../../../utils';\n import { debounce } from '../../../utils/debounce';\n import { DebouncedFunction } from '../../../utils/types';\n import { XEventsTypes } from '../../../wiring/events.types';\n import { WireMetadata } from '../../../wiring/wiring.types';\n import { searchBoxXModule } from '../x-module';\n\n /**\n * This component renders an input field that allows the user to type a query. It also reacts to\n * query changes through event listening.\n *\n * @public\n */\n @Component({\n mixins: [xComponentMixin(searchBoxXModule)]\n })\n export default class SearchInput extends Vue {\n public $refs!: { input: HTMLInputElement };\n\n protected searchInputMessage = 'type your query here';\n\n /**\n * Maximum characters allowed in the input search.\n */\n @Prop({ default: 64 })\n protected maxLength!: number;\n\n /**\n * Allows input autofocus when the search field is rendered.\n */\n @Prop({ default: true })\n protected autofocus!: boolean;\n\n /**\n * Enables the auto-accept query after debounce.\n */\n @Prop({ default: true })\n protected instant!: boolean;\n\n /**\n * Debounce time for the instant.\n */\n @Prop({ default: 500 })\n protected instantDebounceInMs!: number;\n\n /**\n * Keyboard keys to accept the autocomplete suggestion.\n */\n @Prop({ default: () => ['ArrowRight'] })\n protected autocompleteKeyboardKeys!: string[]; // https://keycode.info/\n\n /**\n * Event that retrieves the autocomplete suggestion.\n */\n @Prop({ default: 'QuerySuggestionsChanged' })\n protected autocompleteSuggestionsEvent!: PropsWithType<XEventsTypes, Suggestion[]>;\n\n @State('searchBox', 'query')\n public query!: string;\n\n /**\n * When event {@link XEventsTypes.UserReachedEmpathizeTop} or\n * {@link SearchBoxXEvents.UserPressedClearSearchBoxButton}\n * are emitted the search in put is focused.\n *\n * @internal\n */\n @XOn(['UserReachedEmpathizeTop', 'UserPressedClearSearchBoxButton'])\n focusInput(): void {\n this.$refs.input?.focus();\n }\n\n protected debouncedUserAcceptedAQuery!: DebouncedFunction<[string]>;\n\n /**\n * When event {@link XEventsTypes.UserAcceptedAQuery} or\n * {@link SearchBoxXEvents.UserClearedQuery} are emitted the pending debounced emit\n * {@link XEvent} `UserAcceptedAQuery` is canceled.\n *\n * @internal\n */\n @XOn(['UserAcceptedAQuery', 'UserClearedQuery'])\n cancelDebouncedUserAcceptedAQuery(): void {\n this.debouncedUserAcceptedAQuery?.cancel();\n }\n\n mounted(): void {\n if (this.autofocus) {\n this.focusInput();\n }\n }\n\n /**\n * Emits {@link XEventsTypes.UserAcceptedAQuery} event with a debounce configured in\n * `instantDebounceInMs` prop.\n *\n * @internal\n * @param query - The query that will be emitted.\n */\n emitDebouncedUserAcceptedAQuery(query: string): void {\n if (this.instant) {\n if (!this.debouncedUserAcceptedAQuery) {\n this.debouncedUserAcceptedAQuery = debounce(\n this.emitUserAcceptedAQuery.bind(this),\n this.instantDebounceInMs\n );\n }\n this.debouncedUserAcceptedAQuery(query);\n }\n }\n\n /**\n * Generates the {@link WireMetadata | event metadata} object omitting the moduleName.\n *\n * @returns The {@link WireMetadata} object omitting the moduleName.\n * @internal\n */\n protected createEventMetadata(): Omit<WireMetadata, 'moduleName'> {\n return {\n target: this.$refs.input,\n feature: 'search_box'\n };\n }\n\n /**\n * Emits event {@link SearchBoxXEvents.UserBlurredSearchBox} when search box loses focus.\n *\n * @internal\n */\n protected emitUserBlurredSearchBox(): void {\n this.$x.emit('UserBlurredSearchBox', undefined, { target: this.$refs.input });\n }\n\n /**\n * Emits event {@link SearchBoxXEvents.UserClickedSearchBox} when user clicks the search input.\n *\n * @internal\n */\n protected emitUserClickedSearchBox(): void {\n this.$x.emit('UserClickedSearchBox', undefined, { target: this.$refs.input });\n }\n\n /**\n * Emits event {@link SearchBoxXEvents.UserFocusedSearchBox} when search box gains focus.\n *\n * @internal\n */\n protected emitUserFocusedSearchBox(): void {\n this.$x.emit('UserFocusedSearchBox', undefined, { target: this.$refs.input });\n }\n\n /**\n * Emits event {@link SearchBoxXEvents.UserIsTypingAQuery} when the user typed/pasted something\n * into the search-box. Also emits event {@link SearchBoxXEvents.UserClearedQuery} when the user\n * removes all characters in the search-box.\n *\n * @internal\n */\n protected emitUserIsTypingAQueryEvents(): void {\n const query = this.$refs.input.value;\n this.$x.emit('UserIsTypingAQuery', query, { target: this.$refs.input });\n if (query.trim()) {\n this.emitDebouncedUserAcceptedAQuery(query);\n } else {\n this.cancelDebouncedUserAcceptedAQuery();\n }\n }\n\n /**\n * Emits event {@link XEventsTypes.UserPressedArrowKey} when the user pressed an arrow key.\n *\n * @param event - The keyboard event with the arrow key pressed.\n * @internal\n */\n protected emitUserPressedArrowKey(event: KeyboardEvent): void {\n this.$x.emit('UserPressedArrowKey', event.key as ArrowKey, this.createEventMetadata());\n }\n\n /**\n * Emits multiple events when the user pressed the enter key.\n *\n * @remarks\n * Emitted events are:\n * {@link SearchBoxXEvents.UserPressedEnterKey}\n * {@link XEventsTypes.UserAcceptedAQuery}\n *\n * @internal\n */\n protected emitUserPressedEnterKey(): void {\n const query = this.$refs.input.value.trim();\n if (query.length > 0) {\n this.$x.emit('UserPressedEnterKey', query, this.createEventMetadata());\n this.emitUserAcceptedAQuery(query);\n }\n this.$refs.input?.blur();\n }\n\n /**\n * Emits {@link XEventsTypes.UserAcceptedAQuery} event.\n *\n * @remarks It is necessary in a separated method to use it as the parameter of debounce in\n * emitDebouncedUserAcceptedAQuery method.\n * @internal\n * @param query - The query that will be emitted.\n */\n protected emitUserAcceptedAQuery(query: string): void {\n this.$x.emit('UserAcceptedAQuery', query, this.createEventMetadata());\n }\n }\n</script>\n\n<style lang=\"scss\" scoped>\n .x-search-input::-webkit-search-decoration,\n .x-search-input::-webkit-search-cancel-button,\n .x-search-input::-webkit-search-results-button,\n .x-search-input::-webkit-search-results-decoration {\n -webkit-appearance: none;\n }\n</style>\n\n<docs lang=\"mdx\">\n## Events\n\nThis component emits the following events:\n\n- [`UserClickedSearchBox`](./../../api/x-components.searchboxxevents.md)\n- [`UserBlurredSearchBox`](./../../api/x-components.searchboxxevents.md)\n- [`UserFocusedSearchBox`](./../../api/x-components.searchboxxevents.md)\n- [`UserIsTypingAQuery`](./../../api/x-components.searchboxxevents.md)\n- [`UserPressedEnterKey`](./../../api/x-components.searchboxxevents.md)\n- [`UserPressedArrowKey`](./../../api/x-components.xeventstypes.md)\n- [`UserAcceptedAQuery`](./../../api/x-components.xeventstypes.md)\n\n## See it in action\n\n<!-- prettier-ignore-start -->\n:::warning Backend service required\nTo use this component, the Search service must be implemented.\n:::\n<!-- prettier-ignore-end -->\n\nHere you have a basic example of how the search input is rendered.\n\n_Type any term in the input field to try it out!_\n\n```vue live\n<template>\n <SearchInput />\n</template>\n\n<script>\n import { SearchInput } from '@empathyco/x-components/search-box';\n\n export default {\n name: 'SearchInputDemo',\n components: {\n SearchInput\n }\n };\n</script>\n```\n\n### Play with props\n\nIn this example, the search input has been limited to accept a maximum of 5 characters, including\nspaces, it won't take the focus when it is rendered, and it will emit the `UserAcceptedAQuery` event\nafter 1000 milliseconds without typing.\n\n_Type a term with more than 5 characters to try it out!_\n\n```vue live\n<template>\n <SearchInput :maxLength=\"5\" :autofocus=\"false\" :instant=\"true\" :instantDebounceInMs=\"1000\" />\n</template>\n\n<script>\n import { SearchInput } from '@empathyco/x-components/search-box';\n\n export default {\n name: 'SearchInputDemo',\n components: {\n SearchInput\n }\n };\n</script>\n```\n\n### Play with events\n\nIn this example, a message has been added below the search input to illustrate the action performed.\nFor example, if you select the search input box, the message “focus” appears. When you start to\nenter a search term, the message “typing” appears. If you press Enter after typing a search term,\nthe message “enter” appears.\n\n_Type any term in the input field to try it out!_\n\n```vue live\n<template>\n <div>\n <SearchInput\n @UserPressedEnterKey=\"value = 'enter'\"\n @UserFocusedSearchBox=\"hasFocus = true\"\n @UserBlurredSearchBox=\"hasFocus = false\"\n @UserIsTypingAQuery=\"value = 'typing'\"\n />\n <strong>{{ value }}</strong>\n <span>{{ hasFocus ? 'focused' : 'unfocused' }}</span>\n </div>\n</template>\n\n<script>\n import { SearchInput } from '@empathyco/x-components/search-box';\n\n export default {\n name: 'SearchInputDemo',\n components: {\n SearchInput\n },\n data() {\n return {\n value: '',\n hasFocus: false\n };\n }\n };\n</script>\n```\n\n## Extending the component\n\nComponents can be combined and communicate with each other. Commonly, the `SearchInput` component\ncommunicates with the [`SearchButton`](x-components.search-button.md) and the\n[`ClearSearchInput`](x-components.clear-search-input.md) to offer a full query entry experience.\nFurthermore, you can use it together with the [`QuerySuggestions`](query-suggestions.md) component\nto autocomplete the typed search term.\n\n_Type “trousers” or another fashion term in the input field and then click the clear icon to try it\nout!_\n\n```vue live\n<template>\n <div>\n <div style=\"display: flex; flex-flow: row nowrap;\">\n <SearchInput />\n <ClearSearchInput>\n <img src=\"/assets/icons/cross.svg\" />\n </ClearSearchInput>\n <SearchButton>Search</SearchButton>\n </div>\n <QuerySuggestions />\n </div>\n</template>\n\n<script>\n import { SearchInput, ClearSearchInput, SearchButton } from '@empathyco/x-components/search-box';\n import { QuerySuggestions } from '@empathyco/x-components/query-suggestions';\n\n export default {\n name: 'SearchInputDemo',\n components: {\n SearchInput,\n ClearSearchInput,\n SearchButton,\n QuerySuggestions\n }\n };\n</script>\n```\n</docs>\n"],"names":[],"mappings":";;;;;AAEA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"search-input.vue.js","sources":["../../../../../src/x-modules/search-box/components/search-input.vue"],"sourcesContent":["<template>\n <input\n ref=\"input\"\n @blur=\"emitUserBlurredSearchBox\"\n @click=\"emitUserClickedSearchBox\"\n @focus=\"emitUserFocusedSearchBox\"\n @input=\"emitUserIsTypingAQueryEvents\"\n @keydown.enter=\"emitUserPressedEnterKey\"\n @keydown.up.down.prevent=\"emitUserPressedArrowKey\"\n v-on=\"$listeners\"\n :maxlength=\"maxLength\"\n :value=\"query\"\n autocomplete=\"off\"\n class=\"x-input x-search-input\"\n enterkeyhint=\"search\"\n inputmode=\"search\"\n type=\"search\"\n data-test=\"search-input\"\n :aria-label=\"searchInputMessage\"\n />\n</template>\n\n<script lang=\"ts\">\n import { Suggestion } from '@empathyco/x-types';\n import Vue from 'vue';\n import { Component, Prop } from 'vue-property-decorator';\n import { XOn } from '../../../components/decorators/bus.decorators';\n import { State } from '../../../components/decorators/store.decorators';\n import { xComponentMixin } from '../../../components/x-component.mixin';\n import { ArrowKey, PropsWithType } from '../../../utils';\n import { debounce } from '../../../utils/debounce';\n import { DebouncedFunction } from '../../../utils/types';\n import { XEventsTypes } from '../../../wiring/events.types';\n import { WireMetadata } from '../../../wiring/wiring.types';\n import { searchBoxXModule } from '../x-module';\n\n /**\n * This component renders an input field that allows the user to type a query. It also reacts to\n * query changes through event listening.\n *\n * @public\n */\n @Component({\n mixins: [xComponentMixin(searchBoxXModule)]\n })\n export default class SearchInput extends Vue {\n public $refs!: { input: HTMLInputElement };\n\n protected searchInputMessage = 'type your query here';\n\n /**\n * Maximum characters allowed in the input search.\n */\n @Prop({ default: 64 })\n protected maxLength!: number;\n\n /**\n * Allows input autofocus when the search field is rendered.\n */\n @Prop({ default: true })\n protected autofocus!: boolean;\n\n /**\n * Enables the auto-accept query after debounce.\n */\n @Prop({ default: true })\n protected instant!: boolean;\n\n /**\n * Debounce time for the instant.\n */\n @Prop({ default: 500 })\n protected instantDebounceInMs!: number;\n\n /**\n * Keyboard keys to accept the autocomplete suggestion.\n */\n @Prop({ default: () => ['ArrowRight'] })\n protected autocompleteKeyboardKeys!: string[]; // https://keycode.info/\n\n /**\n * Event that retrieves the autocomplete suggestion.\n */\n @Prop({ default: 'QuerySuggestionsChanged' })\n protected autocompleteSuggestionsEvent!: PropsWithType<XEventsTypes, Suggestion[]>;\n\n @State('searchBox', 'query')\n public query!: string;\n\n /**\n * When event {@link XEventsTypes.UserReachedEmpathizeTop} or\n * {@link SearchBoxXEvents.UserPressedClearSearchBoxButton}\n * are emitted the search in put is focused.\n *\n * @internal\n */\n @XOn(['UserReachedEmpathizeTop', 'UserPressedClearSearchBoxButton'])\n focusInput(): void {\n this.$refs.input?.focus();\n }\n\n protected debouncedUserAcceptedAQuery!: DebouncedFunction<[string]>;\n\n /**\n * When event {@link XEventsTypes.UserAcceptedAQuery} or\n * {@link SearchBoxXEvents.UserClearedQuery} are emitted the pending debounced emit\n * {@link XEvent} `UserAcceptedAQuery` is canceled.\n *\n * @internal\n */\n @XOn(['UserAcceptedAQuery', 'UserClearedQuery'])\n cancelDebouncedUserAcceptedAQuery(): void {\n this.debouncedUserAcceptedAQuery?.cancel();\n }\n\n mounted(): void {\n if (this.autofocus) {\n this.focusInput();\n }\n }\n\n /**\n * Emits {@link XEventsTypes.UserAcceptedAQuery} event with a debounce configured in\n * `instantDebounceInMs` prop.\n *\n * @internal\n * @param query - The query that will be emitted.\n */\n emitDebouncedUserAcceptedAQuery(query: string): void {\n if (this.instant) {\n if (!this.debouncedUserAcceptedAQuery) {\n this.debouncedUserAcceptedAQuery = debounce(\n this.emitUserAcceptedAQuery.bind(this),\n this.instantDebounceInMs\n );\n }\n this.debouncedUserAcceptedAQuery(query);\n }\n }\n\n /**\n * Generates the {@link WireMetadata | event metadata} object omitting the moduleName.\n *\n * @returns The {@link WireMetadata} object omitting the moduleName.\n * @internal\n */\n protected createEventMetadata(): Omit<WireMetadata, 'moduleName'> {\n return {\n target: this.$refs.input,\n feature: 'search_box'\n };\n }\n\n /**\n * Emits event {@link SearchBoxXEvents.UserBlurredSearchBox} when search box loses focus.\n *\n * @internal\n */\n protected emitUserBlurredSearchBox(): void {\n this.$x.emit('UserBlurredSearchBox', undefined, { target: this.$refs.input });\n }\n\n /**\n * Emits event {@link SearchBoxXEvents.UserClickedSearchBox} when user clicks the search input.\n *\n * @internal\n */\n protected emitUserClickedSearchBox(): void {\n this.$x.emit('UserClickedSearchBox', undefined, { target: this.$refs.input });\n }\n\n /**\n * Emits event {@link SearchBoxXEvents.UserFocusedSearchBox} when search box gains focus.\n *\n * @internal\n */\n protected emitUserFocusedSearchBox(): void {\n this.$x.emit('UserFocusedSearchBox', undefined, { target: this.$refs.input });\n }\n\n /**\n * Emits event {@link SearchBoxXEvents.UserIsTypingAQuery} when the user typed/pasted something\n * into the search-box. Also emits event {@link SearchBoxXEvents.UserClearedQuery} when the user\n * removes all characters in the search-box.\n *\n * @internal\n */\n protected emitUserIsTypingAQueryEvents(): void {\n const query = this.$refs.input.value;\n this.$x.emit('UserIsTypingAQuery', query, { target: this.$refs.input });\n if (query.trim()) {\n this.emitDebouncedUserAcceptedAQuery(query);\n } else {\n this.cancelDebouncedUserAcceptedAQuery();\n }\n }\n\n /**\n * Emits event {@link XEventsTypes.UserPressedArrowKey} when the user pressed an arrow key.\n *\n * @param event - The keyboard event with the arrow key pressed.\n * @internal\n */\n protected emitUserPressedArrowKey(event: KeyboardEvent): void {\n this.$x.emit('UserPressedArrowKey', event.key as ArrowKey, this.createEventMetadata());\n }\n\n /**\n * Emits multiple events when the user pressed the enter key.\n *\n * @remarks\n * Emitted events are:\n * {@link SearchBoxXEvents.UserPressedEnterKey}\n * {@link XEventsTypes.UserAcceptedAQuery}\n *\n * @internal\n */\n protected emitUserPressedEnterKey(): void {\n const query = this.$refs.input.value.trim();\n if (query.length > 0) {\n this.$x.emit('UserPressedEnterKey', query, this.createEventMetadata());\n this.emitUserAcceptedAQuery(query);\n }\n this.$refs.input?.blur();\n }\n\n /**\n * Emits {@link XEventsTypes.UserAcceptedAQuery} event.\n *\n * @remarks It is necessary in a separated method to use it as the parameter of debounce in\n * emitDebouncedUserAcceptedAQuery method.\n * @internal\n * @param query - The query that will be emitted.\n */\n protected emitUserAcceptedAQuery(query: string): void {\n this.$x.emit('UserAcceptedAQuery', query, this.createEventMetadata());\n }\n }\n</script>\n\n<style lang=\"scss\" scoped>\n .x-search-input::-webkit-search-decoration,\n .x-search-input::-webkit-search-cancel-button,\n .x-search-input::-webkit-search-results-button,\n .x-search-input::-webkit-search-results-decoration {\n -webkit-appearance: none;\n }\n</style>\n\n<docs lang=\"mdx\">\n## Events\n\nThis component emits the following events:\n\n- [`UserClickedSearchBox`](./../../api/x-components.searchboxxevents.md)\n- [`UserBlurredSearchBox`](./../../api/x-components.searchboxxevents.md)\n- [`UserFocusedSearchBox`](./../../api/x-components.searchboxxevents.md)\n- [`UserIsTypingAQuery`](./../../api/x-components.searchboxxevents.md)\n- [`UserPressedEnterKey`](./../../api/x-components.searchboxxevents.md)\n- [`UserPressedArrowKey`](./../../api/x-components.xeventstypes.md)\n- [`UserAcceptedAQuery`](./../../api/x-components.xeventstypes.md)\n\n## See it in action\n\n<!-- prettier-ignore-start -->\n:::warning Backend service required\nTo use this component, the Search service must be implemented.\n:::\n<!-- prettier-ignore-end -->\n\nHere you have a basic example of how the search input is rendered.\n\n_Type any term in the input field to try it out!_\n\n```vue live\n<template>\n <SearchInput />\n</template>\n\n<script>\n import { SearchInput } from '@empathyco/x-components/search-box';\n\n export default {\n name: 'SearchInputDemo',\n components: {\n SearchInput\n }\n };\n</script>\n```\n\n### Play with props\n\nIn this example, the search input has been limited to accept a maximum of 5 characters, including\nspaces, it won't take the focus when it is rendered, and it will emit the `UserAcceptedAQuery` event\nafter 1000 milliseconds without typing.\n\n_Type a term with more than 5 characters to try it out!_\n\n```vue live\n<template>\n <SearchInput :maxLength=\"5\" :autofocus=\"false\" :instant=\"true\" :instantDebounceInMs=\"1000\" />\n</template>\n\n<script>\n import { SearchInput } from '@empathyco/x-components/search-box';\n\n export default {\n name: 'SearchInputDemo',\n components: {\n SearchInput\n }\n };\n</script>\n```\n\n### Play with events\n\nIn this example, a message has been added below the search input to illustrate the action performed.\nFor example, if you select the search input box, the message “focus” appears. When you start to\nenter a search term, the message “typing” appears. If you press Enter after typing a search term,\nthe message “enter” appears.\n\n<!-- prettier-ignore-start -->\n:::warning X Events are only emitted from the root X Component.\nAt the moment, X Events are only emitted from the root X Component. This means that if you wrap\nthe `SearchInput` with another component of another module like the `MainScroll`, you should add\nthe listeners to the `MainScroll` instead of the `SearchInput`. If you need to subscribe to these\nevents, it is recommended to use the [`GlobalXBus`](../common/x-components.global-x-bus.md)\ncomponent instead.\n:::\n<!-- prettier-ignore-end -->\n\n_Type any term in the input field to try it out!_\n\n```vue live\n<template>\n <div>\n <SearchInput\n @UserPressedEnterKey=\"value = 'enter'\"\n @UserFocusedSearchBox=\"hasFocus = true\"\n @UserBlurredSearchBox=\"hasFocus = false\"\n @UserIsTypingAQuery=\"value = 'typing'\"\n />\n <strong>{{ value }}</strong>\n <span>{{ hasFocus ? 'focused' : 'unfocused' }}</span>\n </div>\n</template>\n\n<script>\n import { SearchInput } from '@empathyco/x-components/search-box';\n\n export default {\n name: 'SearchInputDemo',\n components: {\n SearchInput\n },\n data() {\n return {\n value: '',\n hasFocus: false\n };\n }\n };\n</script>\n```\n\n## Extending the component\n\nComponents can be combined and communicate with each other. Commonly, the `SearchInput` component\ncommunicates with the [`SearchButton`](x-components.search-button.md) and the\n[`ClearSearchInput`](x-components.clear-search-input.md) to offer a full query entry experience.\nFurthermore, you can use it together with the [`QuerySuggestions`](query-suggestions.md) component\nto autocomplete the typed search term.\n\n_Type “trousers” or another fashion term in the input field and then click the clear icon to try it\nout!_\n\n```vue live\n<template>\n <div>\n <div style=\"display: flex; flex-flow: row nowrap;\">\n <SearchInput />\n <ClearSearchInput>\n <img src=\"/assets/icons/cross.svg\" />\n </ClearSearchInput>\n <SearchButton>Search</SearchButton>\n </div>\n <QuerySuggestions />\n </div>\n</template>\n\n<script>\n import { SearchInput, ClearSearchInput, SearchButton } from '@empathyco/x-components/search-box';\n import { QuerySuggestions } from '@empathyco/x-components/query-suggestions';\n\n export default {\n name: 'SearchInputDemo',\n components: {\n SearchInput,\n ClearSearchInput,\n SearchButton,\n QuerySuggestions\n }\n };\n</script>\n```\n</docs>\n"],"names":[],"mappings":";;;;;AAEA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@empathyco/x-components",
3
- "version": "3.0.0-alpha.150",
3
+ "version": "3.0.0-alpha.151",
4
4
  "description": "Empathy X Components",
5
5
  "author": "Empathy Systems Corporation S.L.",
6
6
  "license": "Apache-2.0",
@@ -125,5 +125,5 @@
125
125
  "access": "public",
126
126
  "directory": "dist"
127
127
  },
128
- "gitHead": "1fc14893fef9ae25e2711f30513144055ebe13af"
128
+ "gitHead": "083e19ea7652b512e0cc82553ab98021751cef75"
129
129
  }