@empathyco/x-components 3.0.0-alpha.30 → 3.0.0-alpha.31

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.
Files changed (137) hide show
  1. package/CHANGELOG.md +37 -0
  2. package/core/index.js.map +1 -1
  3. package/design-system/default-theme.css +6 -1
  4. package/design-system/full-theme.css +6 -1
  5. package/design-system/list-default.css +3 -0
  6. package/design-system/suggestion-default.css +3 -1
  7. package/docs/API-reference/api/x-components.identifierresultsactions.md +0 -1
  8. package/docs/API-reference/api/x-components.identifierresultsmutations.md +1 -0
  9. package/docs/API-reference/api/x-components.identifierresultsmutations.setparams.md +24 -0
  10. package/docs/API-reference/api/x-components.identifierresultsstate.md +1 -0
  11. package/docs/API-reference/api/x-components.identifierresultsstate.params.md +13 -0
  12. package/docs/API-reference/api/x-components.md +3 -0
  13. package/docs/API-reference/api/x-components.setconsent.md +1 -1
  14. package/docs/API-reference/api/x-components.setidentifierresultsextraparams.md +13 -0
  15. package/docs/API-reference/api/x-components.setquerytaggingdebounce.md +1 -1
  16. package/docs/API-reference/api/x-components.setsessionduration.md +1 -1
  17. package/docs/API-reference/api/x-components.taggingactions.md +7 -0
  18. package/docs/API-reference/api/x-components.taggingactions.track.md +24 -0
  19. package/docs/API-reference/api/x-components.track.md +13 -0
  20. package/docs/API-reference/api/x-components.trackwire.md +13 -0
  21. package/docs/build-search-ui/README.md +113 -0
  22. package/docs/build-search-ui/web-archetype-integration-guide.md +183 -0
  23. package/docs/build-search-ui/web-use-x-components-guide.md +170 -0
  24. package/docs/build-search-ui/web-x-components-integration-guide.md +197 -0
  25. package/docs/build-search-ui/x-architecture/README.md +133 -0
  26. package/docs/sidebar.json +1 -1
  27. package/identifier-results/index.js +1 -1
  28. package/js/index.js +3 -2
  29. package/js/index.js.map +1 -1
  30. package/js/x-modules/history-queries/components/history-query.vue.js +1 -1
  31. package/js/x-modules/history-queries/components/history-query.vue.js.map +1 -1
  32. package/js/x-modules/history-queries/components/history-query.vue_rollup-plugin-vue=script.js.map +1 -1
  33. package/js/x-modules/identifier-results/store/actions/save-query.action.js +4 -0
  34. package/js/x-modules/identifier-results/store/actions/save-query.action.js.map +1 -1
  35. package/js/x-modules/identifier-results/store/getters/identifier-results-request.getter.js +4 -8
  36. package/js/x-modules/identifier-results/store/getters/identifier-results-request.getter.js.map +1 -1
  37. package/js/x-modules/identifier-results/store/module.js +5 -3
  38. package/js/x-modules/identifier-results/store/module.js.map +1 -1
  39. package/js/x-modules/identifier-results/wiring.js +14 -2
  40. package/js/x-modules/identifier-results/wiring.js.map +1 -1
  41. package/js/x-modules/next-queries/components/next-query.vue.js +2 -1
  42. package/js/x-modules/next-queries/components/next-query.vue.js.map +1 -1
  43. package/js/x-modules/next-queries/components/next-query.vue_rollup-plugin-vue=script.js.map +1 -1
  44. package/js/x-modules/popular-searches/components/popular-search.vue.js +2 -1
  45. package/js/x-modules/popular-searches/components/popular-search.vue.js.map +1 -1
  46. package/js/x-modules/popular-searches/components/popular-search.vue_rollup-plugin-vue=script.js.map +1 -1
  47. package/js/x-modules/query-suggestions/components/query-suggestion.vue.js +2 -1
  48. package/js/x-modules/query-suggestions/components/query-suggestion.vue.js.map +1 -1
  49. package/js/x-modules/query-suggestions/components/query-suggestion.vue_rollup-plugin-vue=script.js.map +1 -1
  50. package/js/x-modules/related-tags/components/related-tag.vue.js +2 -2
  51. package/js/x-modules/related-tags/components/related-tag.vue.js.map +1 -1
  52. package/js/x-modules/related-tags/components/related-tag.vue_rollup-plugin-vue=script.js +15 -7
  53. package/js/x-modules/related-tags/components/related-tag.vue_rollup-plugin-vue=script.js.map +1 -1
  54. package/js/x-modules/search/components/partial-query-button.vue.js.map +1 -1
  55. package/js/x-modules/search/components/partial-query-button.vue_rollup-plugin-vue=script.js +14 -6
  56. package/js/x-modules/search/components/partial-query-button.vue_rollup-plugin-vue=script.js.map +1 -1
  57. package/js/x-modules/search/components/spellcheck-button.vue.js.map +1 -1
  58. package/js/x-modules/search/components/spellcheck-button.vue_rollup-plugin-vue=script.js +14 -6
  59. package/js/x-modules/search/components/spellcheck-button.vue_rollup-plugin-vue=script.js.map +1 -1
  60. package/js/x-modules/search/store/emitters.js +8 -1
  61. package/js/x-modules/search/store/emitters.js.map +1 -1
  62. package/js/x-modules/search-box/components/search-button.vue.js.map +1 -1
  63. package/js/x-modules/search-box/components/search-button.vue_rollup-plugin-vue=script.js +14 -6
  64. package/js/x-modules/search-box/components/search-button.vue_rollup-plugin-vue=script.js.map +1 -1
  65. package/js/x-modules/search-box/components/search-input.vue.js +2 -2
  66. package/js/x-modules/search-box/components/search-input.vue.js.map +1 -1
  67. package/js/x-modules/search-box/components/search-input.vue_rollup-plugin-vue=script.js +10 -9
  68. package/js/x-modules/search-box/components/search-input.vue_rollup-plugin-vue=script.js.map +1 -1
  69. package/js/x-modules/tagging/store/actions/track.action.js +43 -0
  70. package/js/x-modules/tagging/store/actions/track.action.js.map +1 -0
  71. package/js/x-modules/tagging/store/module.js +6 -2
  72. package/js/x-modules/tagging/store/module.js.map +1 -1
  73. package/js/x-modules/tagging/wiring.js +26 -2
  74. package/js/x-modules/tagging/wiring.js.map +1 -1
  75. package/js/x-modules/url/components/url-handler.vue.js.map +1 -1
  76. package/js/x-modules/url/components/url-handler.vue_rollup-plugin-vue=script.js +2 -2
  77. package/js/x-modules/url/components/url-handler.vue_rollup-plugin-vue=script.js.map +1 -1
  78. package/package.json +2 -2
  79. package/report/x-components.api.json +234 -49
  80. package/report/x-components.api.md +34 -6
  81. package/tagging/index.js +2 -1
  82. package/types/adapter/mocked-adapter.d.ts.map +1 -1
  83. package/types/x-modules/history-queries/components/history-query.vue.d.ts.map +1 -1
  84. package/types/x-modules/identifier-results/store/actions/save-query.action.d.ts.map +1 -1
  85. package/types/x-modules/identifier-results/store/getters/identifier-results-request.getter.d.ts.map +1 -1
  86. package/types/x-modules/identifier-results/store/module.d.ts.map +1 -1
  87. package/types/x-modules/identifier-results/store/types.d.ts +9 -7
  88. package/types/x-modules/identifier-results/store/types.d.ts.map +1 -1
  89. package/types/x-modules/identifier-results/wiring.d.ts +10 -1
  90. package/types/x-modules/identifier-results/wiring.d.ts.map +1 -1
  91. package/types/x-modules/next-queries/components/next-query.vue.d.ts.map +1 -1
  92. package/types/x-modules/popular-searches/components/popular-search.vue.d.ts.map +1 -1
  93. package/types/x-modules/query-suggestions/components/query-suggestion.vue.d.ts.map +1 -1
  94. package/types/x-modules/related-tags/components/related-tag.vue.d.ts +8 -0
  95. package/types/x-modules/related-tags/components/related-tag.vue.d.ts.map +1 -1
  96. package/types/x-modules/search/components/partial-query-button.vue.d.ts +8 -0
  97. package/types/x-modules/search/components/partial-query-button.vue.d.ts.map +1 -1
  98. package/types/x-modules/search/components/spellcheck-button.vue.d.ts +8 -0
  99. package/types/x-modules/search/components/spellcheck-button.vue.d.ts.map +1 -1
  100. package/types/x-modules/search/store/emitters.d.ts +4 -1
  101. package/types/x-modules/search/store/emitters.d.ts.map +1 -1
  102. package/types/x-modules/search-box/components/search-button.vue.d.ts +8 -0
  103. package/types/x-modules/search-box/components/search-button.vue.d.ts.map +1 -1
  104. package/types/x-modules/search-box/components/search-input.vue.d.ts +1 -1
  105. package/types/x-modules/search-box/components/search-input.vue.d.ts.map +1 -1
  106. package/types/x-modules/tagging/store/actions/index.d.ts +2 -0
  107. package/types/x-modules/tagging/store/actions/index.d.ts.map +1 -0
  108. package/types/x-modules/tagging/store/actions/track.action.d.ts +12 -0
  109. package/types/x-modules/tagging/store/actions/track.action.d.ts.map +1 -0
  110. package/types/x-modules/tagging/store/index.d.ts +1 -0
  111. package/types/x-modules/tagging/store/index.d.ts.map +1 -1
  112. package/types/x-modules/tagging/store/module.d.ts.map +1 -1
  113. package/types/x-modules/tagging/store/types.d.ts +7 -0
  114. package/types/x-modules/tagging/store/types.d.ts.map +1 -1
  115. package/types/x-modules/tagging/wiring.d.ts +17 -7
  116. package/types/x-modules/tagging/wiring.d.ts.map +1 -1
  117. package/docs/API-reference/api/x-components.identifierresultsactions.seturlparams.md +0 -24
  118. package/docs/css/global.scss +0 -1
  119. package/docs/css/utils/utils.scss +0 -35
  120. package/docs/css/xcomponents/clear-search-input.scss +0 -9
  121. package/docs/css/xcomponents/index.scss +0 -16
  122. package/docs/css/xcomponents/search-input.scss +0 -10
  123. package/docs/css/xcomponents/suggestions.scss +0 -19
  124. package/docs/guide/getting-started/components/clear-search-input.md +0 -98
  125. package/docs/guide/getting-started/components/live-examples.md +0 -100
  126. package/docs/guide/getting-started/components/query-suggestions.md +0 -76
  127. package/docs/guide/getting-started/components/search-button.md +0 -98
  128. package/docs/guide/getting-started/components/search-input.md +0 -105
  129. package/docs/guide/getting-started/install-xplugin.md +0 -72
  130. package/docs/guide/getting-started/use-components.md +0 -75
  131. package/docs/guide/install.md +0 -30
  132. package/docs/react-components/ReactComponents.jsx +0 -46
  133. package/docs/react-components/Utils.jsx +0 -34
  134. package/js/x-modules/identifier-results/store/actions/set-url-params.action.js +0 -17
  135. package/js/x-modules/identifier-results/store/actions/set-url-params.action.js.map +0 -1
  136. package/types/x-modules/identifier-results/store/actions/set-url-params.action.d.ts +0 -12
  137. package/types/x-modules/identifier-results/store/actions/set-url-params.action.d.ts.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"spellcheck-button.vue_rollup-plugin-vue=script.js","sources":["../../../../../src/x-modules/search/components/spellcheck-button.vue?rollup-plugin-vue=script.ts"],"sourcesContent":["\n\n\n\n\n\n\n\n\n\n\n\nimport Vue from 'vue';\nimport { Component } from 'vue-property-decorator';\nimport { State } from '../../../components/decorators/store.decorators';\nimport { xComponentMixin } from '../../../components/x-component.mixin';\nimport { searchXModule } from '../x-module';\n/**\n * A button that when pressed emits the {@link XEventsTypes.UserAcceptedAQuery}\n * and {@link XEventsTypes.UserAcceptedSpellcheckQuery} events, expressing the user\n * intention to set the spellchecked query.\n *\n * @public\n */\n@Component({\n mixins: [xComponentMixin(searchXModule)]\n})\nexport default class SpellcheckButton extends Vue {\n /**\n * The spellcheckedQuery from the search state.\n *\n * @public\n */\n @State('search', 'spellcheckedQuery')\n public spellcheckedQuery!: string;\n\n /**\n * Emits events when the button is clicked.\n *\n * @public\n */\n protected emitEvents(): void {\n this.$x.emit('UserAcceptedAQuery', this.spellcheckedQuery, {\n target: this.$el as HTMLElement\n });\n this.$x.emit('UserAcceptedSpellcheckQuery', this.spellcheckedQuery, {\n target: this.$el as HTMLElement\n });\n }\n}\n"],"names":[],"mappings":";;;;;;;AAiBA;;;;;;;AAUA;IAA8C,oCAAG;IAAjD;;KAsBC;;;;;;IARW,qCAAU,GAApB;QACE,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,oBAAoB,EAAE,IAAI,CAAC,iBAAiB,EAAE;YACzD,MAAM,EAAE,IAAI,CAAC,GAAkB;SAChC,CAAC,CAAC;QACH,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,6BAA6B,EAAE,IAAI,CAAC,iBAAiB,EAAE;YAClE,MAAM,EAAE,IAAI,CAAC,GAAkB;SAChC,CAAC,CAAC;KACJ;IAdD;QADC,KAAK,CAAC,QAAQ,EAAE,mBAAmB,CAAC;+DACH;IAPf,gBAAgB;QAHpC,SAAS,CAAC;YACT,MAAM,EAAE,CAAC,eAAe,CAAC,aAAa,CAAC,CAAC;SACzC,CAAC;OACmB,gBAAgB,CAsBpC;IAAD,uBAAC;CAAA,CAtB6C,GAAG;;;;"}
1
+ {"version":3,"file":"spellcheck-button.vue_rollup-plugin-vue=script.js","sources":["../../../../../src/x-modules/search/components/spellcheck-button.vue?rollup-plugin-vue=script.ts"],"sourcesContent":["\n\n\n\n\n\n\n\n\n\n\n\nimport Vue from 'vue';\nimport { Component } from 'vue-property-decorator';\nimport { State } from '../../../components/decorators/store.decorators';\nimport { xComponentMixin } from '../../../components/x-component.mixin';\nimport { WireMetadata } from '../../../wiring/wiring.types';\nimport { searchXModule } from '../x-module';\n/**\n * A button that when pressed emits the {@link XEventsTypes.UserAcceptedAQuery}\n * and {@link XEventsTypes.UserAcceptedSpellcheckQuery} events, expressing the user\n * intention to set the spellchecked query.\n *\n * @public\n */\n@Component({\n mixins: [xComponentMixin(searchXModule)]\n})\nexport default class SpellcheckButton extends Vue {\n /**\n * The spellcheckedQuery from the search state.\n *\n * @public\n */\n @State('search', 'spellcheckedQuery')\n public spellcheckedQuery!: string;\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.$el as HTMLElement,\n feature: 'spellcheck'\n };\n }\n\n /**\n * Emits events when the button is clicked.\n *\n * @public\n */\n protected emitEvents(): void {\n this.$x.emit('UserAcceptedAQuery', this.spellcheckedQuery, this.createEventMetadata());\n this.$x.emit(\n 'UserAcceptedSpellcheckQuery',\n this.spellcheckedQuery,\n this.createEventMetadata()\n );\n }\n}\n"],"names":[],"mappings":";;;;;;;AAkBA;;;;;;;AAUA;IAA8C,oCAAG;IAAjD;;KAmCC;;;;;;;IApBW,8CAAmB,GAA7B;QACE,OAAO;YACL,MAAM,EAAE,IAAI,CAAC,GAAkB;YAC/B,OAAO,EAAE,YAAY;SACtB,CAAC;KACH;;;;;;IAOS,qCAAU,GAApB;QACE,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,oBAAoB,EAAE,IAAI,CAAC,iBAAiB,EAAE,IAAI,CAAC,mBAAmB,EAAE,CAAC,CAAC;QACvF,IAAI,CAAC,EAAE,CAAC,IAAI,CACV,6BAA6B,EAC7B,IAAI,CAAC,iBAAiB,EACtB,IAAI,CAAC,mBAAmB,EAAE,CAC3B,CAAC;KACH;IA3BD;QADC,KAAK,CAAC,QAAQ,EAAE,mBAAmB,CAAC;+DACH;IAPf,gBAAgB;QAHpC,SAAS,CAAC;YACT,MAAM,EAAE,CAAC,eAAe,CAAC,aAAa,CAAC,CAAC;SACzC,CAAC;OACmB,gBAAgB,CAmCpC;IAAD,uBAAC;CAAA,CAnC6C,GAAG;;;;"}
@@ -1,3 +1,4 @@
1
+ import { isStringEmpty } from '../../../utils/string.js';
1
2
  import '../../../store/x.module.js';
2
3
  import '../../../store/utils/fetch-and-save-action.utils.js';
3
4
  import '../../../store/utils/status-store.utils.js';
@@ -19,7 +20,13 @@ var searchEmitters = createStoreEmitters(searchXStoreModule, {
19
20
  PageChanged: function (state) { return state.page; },
20
21
  ResultsChanged: function (state) { return state.results; },
21
22
  SearchRequestChanged: function (_, getters) { return getters.request; },
22
- SearchTaggingChanged: function (state) { return state.queryTagging; },
23
+ SearchTaggingChanged: {
24
+ selector: function (state) { return state.queryTagging; },
25
+ filter: function (_a) {
26
+ var url = _a.url;
27
+ return !isStringEmpty(url);
28
+ }
29
+ },
23
30
  SpellcheckChanged: function (state) { return state.spellcheckedQuery; },
24
31
  SortChanged: function (state) { return state.sort; }
25
32
  });
@@ -1 +1 @@
1
- {"version":3,"file":"emitters.js","sources":["../../../../../src/x-modules/search/store/emitters.ts"],"sourcesContent":["import { createStoreEmitters } from '../../../store';\nimport { searchXStoreModule } from './module';\n\n/**\n * {@link StoreEmitters} For the search module.\n *\n * @internal\n */\nexport const searchEmitters = createStoreEmitters(searchXStoreModule, {\n FacetsChanged: {\n selector: state => state.facets,\n filter(newValue, oldValue): boolean {\n return newValue.length !== 0 || oldValue.length !== 0;\n }\n },\n PageChanged: state => state.page,\n ResultsChanged: state => state.results,\n SearchRequestChanged: (_, getters) => getters.request,\n SearchTaggingChanged: state => state.queryTagging,\n SpellcheckChanged: state => state.spellcheckedQuery,\n SortChanged: state => state.sort\n});\n"],"names":[],"mappings":";;;;;;AAGA;;;;;IAKa,cAAc,GAAG,mBAAmB,CAAC,kBAAkB,EAAE;IACpE,aAAa,EAAE;QACb,QAAQ,EAAE,UAAA,KAAK,IAAI,OAAA,KAAK,CAAC,MAAM,GAAA;QAC/B,MAAM,EAAN,UAAO,QAAQ,EAAE,QAAQ;YACvB,OAAO,QAAQ,CAAC,MAAM,KAAK,CAAC,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,CAAC;SACvD;KACF;IACD,WAAW,EAAE,UAAA,KAAK,IAAI,OAAA,KAAK,CAAC,IAAI,GAAA;IAChC,cAAc,EAAE,UAAA,KAAK,IAAI,OAAA,KAAK,CAAC,OAAO,GAAA;IACtC,oBAAoB,EAAE,UAAC,CAAC,EAAE,OAAO,IAAK,OAAA,OAAO,CAAC,OAAO,GAAA;IACrD,oBAAoB,EAAE,UAAA,KAAK,IAAI,OAAA,KAAK,CAAC,YAAY,GAAA;IACjD,iBAAiB,EAAE,UAAA,KAAK,IAAI,OAAA,KAAK,CAAC,iBAAiB,GAAA;IACnD,WAAW,EAAE,UAAA,KAAK,IAAI,OAAA,KAAK,CAAC,IAAI,GAAA;CACjC;;;;"}
1
+ {"version":3,"file":"emitters.js","sources":["../../../../../src/x-modules/search/store/emitters.ts"],"sourcesContent":["import { createStoreEmitters } from '../../../store';\nimport { isStringEmpty } from '../../../utils/string';\nimport { searchXStoreModule } from './module';\n\n/**\n * {@link StoreEmitters} For the search module.\n *\n * @internal\n */\nexport const searchEmitters = createStoreEmitters(searchXStoreModule, {\n FacetsChanged: {\n selector: state => state.facets,\n filter(newValue, oldValue): boolean {\n return newValue.length !== 0 || oldValue.length !== 0;\n }\n },\n PageChanged: state => state.page,\n ResultsChanged: state => state.results,\n SearchRequestChanged: (_, getters) => getters.request,\n SearchTaggingChanged: {\n selector: state => state.queryTagging,\n filter: ({ url }) => !isStringEmpty(url)\n },\n SpellcheckChanged: state => state.spellcheckedQuery,\n SortChanged: state => state.sort\n});\n"],"names":[],"mappings":";;;;;;;AAIA;;;;;IAKa,cAAc,GAAG,mBAAmB,CAAC,kBAAkB,EAAE;IACpE,aAAa,EAAE;QACb,QAAQ,EAAE,UAAA,KAAK,IAAI,OAAA,KAAK,CAAC,MAAM,GAAA;QAC/B,MAAM,EAAN,UAAO,QAAQ,EAAE,QAAQ;YACvB,OAAO,QAAQ,CAAC,MAAM,KAAK,CAAC,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,CAAC;SACvD;KACF;IACD,WAAW,EAAE,UAAA,KAAK,IAAI,OAAA,KAAK,CAAC,IAAI,GAAA;IAChC,cAAc,EAAE,UAAA,KAAK,IAAI,OAAA,KAAK,CAAC,OAAO,GAAA;IACtC,oBAAoB,EAAE,UAAC,CAAC,EAAE,OAAO,IAAK,OAAA,OAAO,CAAC,OAAO,GAAA;IACrD,oBAAoB,EAAE;QACpB,QAAQ,EAAE,UAAA,KAAK,IAAI,OAAA,KAAK,CAAC,YAAY,GAAA;QACrC,MAAM,EAAE,UAAC,EAAO;gBAAL,GAAG,SAAA;YAAO,OAAA,CAAC,aAAa,CAAC,GAAG,CAAC;SAAA;KACzC;IACD,iBAAiB,EAAE,UAAA,KAAK,IAAI,OAAA,KAAK,CAAC,iBAAiB,GAAA;IACnD,WAAW,EAAE,UAAA,KAAK,IAAI,OAAA,KAAK,CAAC,IAAI,GAAA;CACjC;;;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"search-button.vue.js","sources":["../../../../../src/x-modules/search-box/components/search-button.vue"],"sourcesContent":["<template>\n <button\n @click=\"emitEvents\"\n class=\"x-button x-search-button\"\n :class=\"dynamicClasses\"\n data-test=\"search-button\"\n >\n <!-- @slot _Required_. Button content (text, icon, or both) -->\n <slot><span class=\"x-icon\">⌕</span></slot>\n </button>\n</template>\n\n<script lang=\"ts\">\n import Vue from 'vue';\n import { Component } from 'vue-property-decorator';\n import { State } from '../../../components/decorators/store.decorators';\n import { xComponentMixin } from '../../../components/x-component.mixin';\n import { VueCSSClasses } from '../../../utils/types';\n import { searchBoxXModule } from '../x-module';\n\n /**\n * This component renders a button to submit the query.\n *\n * @remarks\n * If query is not empty, it emits {@link XEventsTypes.UserAcceptedAQuery} and\n * {@link SearchBoxXEvents.UserPressedSearchButton} events with the query as payload.\n * It also adds `x-search-button--has-empty-query` as class when there is no query.\n *\n * @public\n */\n @Component({\n mixins: [xComponentMixin(searchBoxXModule)]\n })\n export default class SearchButton extends Vue {\n @State('searchBox', 'query')\n public query!: string;\n\n protected get isQueryEmpty(): boolean {\n return this.query.length === 0;\n }\n\n /**\n * Emits events when the button is clicked.\n *\n * @public\n */\n protected emitEvents(): void {\n if (!this.isQueryEmpty) {\n this.$x.emit('UserAcceptedAQuery', this.query, {\n target: this.$el as HTMLElement\n });\n this.$x.emit('UserPressedSearchButton', this.query, {\n target: this.$el as HTMLElement\n });\n }\n }\n\n protected get dynamicClasses(): VueCSSClasses {\n return {\n 'x-search-button--has-empty-query': this.isQueryEmpty\n };\n }\n }\n</script>\n\n<docs lang=\"mdx\">\n## Events\n\nThis component emits the following events:\n\n- [`UserAcceptedAQuery`](./../../api/x-components.xeventstypes.md)\n- [`UserPressedSearchButton`](./../../api/x-components.searchboxxevents.md)\n\n<!-- prettier-ignore-start -->\n:::warning\nNote that no events are emitted if the query is empty.\n:::\n<!-- prettier-ignore-end -->\n\n## Dynamic classes\n\n`SearchButton` uses the `x-search-button--has-empty-query` dynamic CSS class to modify the HTML\nbutton style when the query is empty.\n\n## See it in action\n\nIn this example, a clickable button is rendered.\n\n_Click the Search button to try it out!_\n\n```vue\n<template>\n <SearchButton />\n</template>\n\n<script>\n import { SearchButton } from '@empathyco/x-components/search-box';\n\n export default {\n name: 'SearchButtonDemo',\n components: {\n SearchButton\n }\n };\n</script>\n```\n\n### Play with default slot\n\nHere an icon is passed in the default slot instead of text to customize the button content.\n\n_Click the icon button to try it out!_\n\n```vue\n<template>\n <SearchButton>Search</SearchButton>\n</template>\n\n<script>\n import { SearchButton } from '@empathyco/x-components/search-box';\n\n export default {\n name: 'SearchButtonDemo',\n components: {\n SearchButton\n }\n };\n</script>\n```\n\n### Play with events\n\nIn this example, the `UserPressedSearchButton` event has been implemented so that when you enter a\nsearch term and click the Search button, the search term is displayed as a message.\n\n_Type any term in the input field and then click the Search button to try it out!_\n\n```vue\n<template>\n <SearchButton\n @UserPressedSearchButton=\"\n query => {\n message = query;\n }\n \"\n />\n</template>\n\n<script>\n import { SearchButton } from '@empathyco/x-components/search-box';\n\n export default {\n name: 'SearchButtonDemo',\n components: {\n SearchButton\n }\n };\n</script>\n```\n\n## Extending the component\n\nComponents can be combined and communicate with each other. Commonly, the `SearchButton` component\ncommunicates with the [`SearchInput`](./search-input.md) to submit the query. In this example, when\nyou enter a search term and click the Search button, the “Looking for results” message is displayed.\n\n_Type any term in the input field and then click the Search button to try it out!_\n\n```vue\n<template>\n <SearchInput />\n <SearchButton @UserAcceptedAQuery=\"message = 'looking for results'\">Search</SearchButton>\n</template>\n\n<script>\n import { SearchButton, SearchInput } from '@empathyco/x-components/search-box';\n\n export default {\n name: 'SearchButtonDemo',\n components: {\n SearchButton,\n SearchInput\n }\n };\n</script>\n```\n</docs>\n"],"names":["const"],"mappings":";;;;AAEAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"search-button.vue.js","sources":["../../../../../src/x-modules/search-box/components/search-button.vue"],"sourcesContent":["<template>\n <button\n @click=\"emitEvents\"\n class=\"x-button x-search-button\"\n :class=\"dynamicClasses\"\n data-test=\"search-button\"\n >\n <!-- @slot _Required_. Button content (text, icon, or both) -->\n <slot><span class=\"x-icon\">⌕</span></slot>\n </button>\n</template>\n\n<script lang=\"ts\">\n import Vue from 'vue';\n import { Component } from 'vue-property-decorator';\n import { State } from '../../../components/decorators/store.decorators';\n import { xComponentMixin } from '../../../components/x-component.mixin';\n import { VueCSSClasses } from '../../../utils/types';\n import { WireMetadata } from '../../../wiring/wiring.types';\n import { searchBoxXModule } from '../x-module';\n\n /**\n * This component renders a button to submit the query.\n *\n * @remarks\n * If query is not empty, it emits {@link XEventsTypes.UserAcceptedAQuery} and\n * {@link SearchBoxXEvents.UserPressedSearchButton} events with the query as payload.\n * It also adds `x-search-button--has-empty-query` as class when there is no query.\n *\n * @public\n */\n @Component({\n mixins: [xComponentMixin(searchBoxXModule)]\n })\n export default class SearchButton extends Vue {\n @State('searchBox', 'query')\n public query!: string;\n\n protected get isQueryEmpty(): boolean {\n return this.query.length === 0;\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.$el as HTMLElement,\n feature: 'search_box'\n };\n }\n\n /**\n * Emits events when the button is clicked.\n *\n * @public\n */\n protected emitEvents(): void {\n if (!this.isQueryEmpty) {\n this.$x.emit('UserAcceptedAQuery', this.query, this.createEventMetadata());\n this.$x.emit('UserPressedSearchButton', this.query, this.createEventMetadata());\n }\n }\n\n protected get dynamicClasses(): VueCSSClasses {\n return {\n 'x-search-button--has-empty-query': this.isQueryEmpty\n };\n }\n }\n</script>\n\n<docs lang=\"mdx\">\n## Events\n\nThis component emits the following events:\n\n- [`UserAcceptedAQuery`](./../../api/x-components.xeventstypes.md)\n- [`UserPressedSearchButton`](./../../api/x-components.searchboxxevents.md)\n\n<!-- prettier-ignore-start -->\n:::warning\nNote that no events are emitted if the query is empty.\n:::\n<!-- prettier-ignore-end -->\n\n## Dynamic classes\n\n`SearchButton` uses the `x-search-button--has-empty-query` dynamic CSS class to modify the HTML\nbutton style when the query is empty.\n\n## See it in action\n\nIn this example, a clickable button is rendered.\n\n_Click the Search button to try it out!_\n\n```vue\n<template>\n <SearchButton />\n</template>\n\n<script>\n import { SearchButton } from '@empathyco/x-components/search-box';\n\n export default {\n name: 'SearchButtonDemo',\n components: {\n SearchButton\n }\n };\n</script>\n```\n\n### Play with default slot\n\nHere an icon is passed in the default slot instead of text to customize the button content.\n\n_Click the icon button to try it out!_\n\n```vue\n<template>\n <SearchButton>Search</SearchButton>\n</template>\n\n<script>\n import { SearchButton } from '@empathyco/x-components/search-box';\n\n export default {\n name: 'SearchButtonDemo',\n components: {\n SearchButton\n }\n };\n</script>\n```\n\n### Play with events\n\nIn this example, the `UserPressedSearchButton` event has been implemented so that when you enter a\nsearch term and click the Search button, the search term is displayed as a message.\n\n_Type any term in the input field and then click the Search button to try it out!_\n\n```vue\n<template>\n <SearchButton\n @UserPressedSearchButton=\"\n query => {\n message = query;\n }\n \"\n />\n</template>\n\n<script>\n import { SearchButton } from '@empathyco/x-components/search-box';\n\n export default {\n name: 'SearchButtonDemo',\n components: {\n SearchButton\n }\n };\n</script>\n```\n\n## Extending the component\n\nComponents can be combined and communicate with each other. Commonly, the `SearchButton` component\ncommunicates with the [`SearchInput`](./search-input.md) to submit the query. In this example, when\nyou enter a search term and click the Search button, the “Looking for results” message is displayed.\n\n_Type any term in the input field and then click the Search button to try it out!_\n\n```vue\n<template>\n <SearchInput />\n <SearchButton @UserAcceptedAQuery=\"message = 'looking for results'\">Search</SearchButton>\n</template>\n\n<script>\n import { SearchButton, SearchInput } from '@empathyco/x-components/search-box';\n\n export default {\n name: 'SearchButtonDemo',\n components: {\n SearchButton,\n SearchInput\n }\n };\n</script>\n```\n</docs>\n"],"names":["const"],"mappings":";;;;AAEAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -27,6 +27,18 @@ var SearchButton = /** @class */ (function (_super) {
27
27
  enumerable: false,
28
28
  configurable: true
29
29
  });
30
+ /**
31
+ * Generates the {@link WireMetadata | event metadata} object omitting the moduleName.
32
+ *
33
+ * @returns The {@link WireMetadata} object omitting the moduleName.
34
+ * @internal
35
+ */
36
+ SearchButton.prototype.createEventMetadata = function () {
37
+ return {
38
+ target: this.$el,
39
+ feature: 'search_box'
40
+ };
41
+ };
30
42
  /**
31
43
  * Emits events when the button is clicked.
32
44
  *
@@ -34,12 +46,8 @@ var SearchButton = /** @class */ (function (_super) {
34
46
  */
35
47
  SearchButton.prototype.emitEvents = function () {
36
48
  if (!this.isQueryEmpty) {
37
- this.$x.emit('UserAcceptedAQuery', this.query, {
38
- target: this.$el
39
- });
40
- this.$x.emit('UserPressedSearchButton', this.query, {
41
- target: this.$el
42
- });
49
+ this.$x.emit('UserAcceptedAQuery', this.query, this.createEventMetadata());
50
+ this.$x.emit('UserPressedSearchButton', this.query, this.createEventMetadata());
43
51
  }
44
52
  };
45
53
  Object.defineProperty(SearchButton.prototype, "dynamicClasses", {
@@ -1 +1 @@
1
- {"version":3,"file":"search-button.vue_rollup-plugin-vue=script.js","sources":["../../../../../src/x-modules/search-box/components/search-button.vue?rollup-plugin-vue=script.ts"],"sourcesContent":["\n\n\n\n\n\n\n\n\n\n\n\n\nimport Vue from 'vue';\nimport { Component } from 'vue-property-decorator';\nimport { State } from '../../../components/decorators/store.decorators';\nimport { xComponentMixin } from '../../../components/x-component.mixin';\nimport { VueCSSClasses } from '../../../utils/types';\nimport { searchBoxXModule } from '../x-module';\n\n/**\n * This component renders a button to submit the query.\n *\n * @remarks\n * If query is not empty, it emits {@link XEventsTypes.UserAcceptedAQuery} and\n * {@link SearchBoxXEvents.UserPressedSearchButton} events with the query as payload.\n * It also adds `x-search-button--has-empty-query` as class when there is no query.\n *\n * @public\n */\n@Component({\n mixins: [xComponentMixin(searchBoxXModule)]\n})\nexport default class SearchButton extends Vue {\n @State('searchBox', 'query')\n public query!: string;\n\n protected get isQueryEmpty(): boolean {\n return this.query.length === 0;\n }\n\n /**\n * Emits events when the button is clicked.\n *\n * @public\n */\n protected emitEvents(): void {\n if (!this.isQueryEmpty) {\n this.$x.emit('UserAcceptedAQuery', this.query, {\n target: this.$el as HTMLElement\n });\n this.$x.emit('UserPressedSearchButton', this.query, {\n target: this.$el as HTMLElement\n });\n }\n }\n\n protected get dynamicClasses(): VueCSSClasses {\n return {\n 'x-search-button--has-empty-query': this.isQueryEmpty\n };\n }\n}\n"],"names":[],"mappings":";;;;;;;AAoBA;;;;;;;;;;AAaA;IAA0C,gCAAG;IAA7C;;KA6BC;IAzBC,sBAAc,sCAAY;aAA1B;YACE,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC,CAAC;SAChC;;;OAAA;;;;;;IAOS,iCAAU,GAApB;QACE,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE;YACtB,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,oBAAoB,EAAE,IAAI,CAAC,KAAK,EAAE;gBAC7C,MAAM,EAAE,IAAI,CAAC,GAAkB;aAChC,CAAC,CAAC;YACH,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,yBAAyB,EAAE,IAAI,CAAC,KAAK,EAAE;gBAClD,MAAM,EAAE,IAAI,CAAC,GAAkB;aAChC,CAAC,CAAC;SACJ;KACF;IAED,sBAAc,wCAAc;aAA5B;YACE,OAAO;gBACL,kCAAkC,EAAE,IAAI,CAAC,YAAY;aACtD,CAAC;SACH;;;OAAA;IA1BD;QADC,KAAK,CAAC,WAAW,EAAE,OAAO,CAAC;+CACN;IAFH,YAAY;QAHhC,SAAS,CAAC;YACT,MAAM,EAAE,CAAC,eAAe,CAAC,gBAAgB,CAAC,CAAC;SAC5C,CAAC;OACmB,YAAY,CA6BhC;IAAD,mBAAC;CAAA,CA7ByC,GAAG;;;;"}
1
+ {"version":3,"file":"search-button.vue_rollup-plugin-vue=script.js","sources":["../../../../../src/x-modules/search-box/components/search-button.vue?rollup-plugin-vue=script.ts"],"sourcesContent":["\n\n\n\n\n\n\n\n\n\n\n\n\nimport Vue from 'vue';\nimport { Component } from 'vue-property-decorator';\nimport { State } from '../../../components/decorators/store.decorators';\nimport { xComponentMixin } from '../../../components/x-component.mixin';\nimport { VueCSSClasses } from '../../../utils/types';\nimport { WireMetadata } from '../../../wiring/wiring.types';\nimport { searchBoxXModule } from '../x-module';\n\n/**\n * This component renders a button to submit the query.\n *\n * @remarks\n * If query is not empty, it emits {@link XEventsTypes.UserAcceptedAQuery} and\n * {@link SearchBoxXEvents.UserPressedSearchButton} events with the query as payload.\n * It also adds `x-search-button--has-empty-query` as class when there is no query.\n *\n * @public\n */\n@Component({\n mixins: [xComponentMixin(searchBoxXModule)]\n})\nexport default class SearchButton extends Vue {\n @State('searchBox', 'query')\n public query!: string;\n\n protected get isQueryEmpty(): boolean {\n return this.query.length === 0;\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.$el as HTMLElement,\n feature: 'search_box'\n };\n }\n\n /**\n * Emits events when the button is clicked.\n *\n * @public\n */\n protected emitEvents(): void {\n if (!this.isQueryEmpty) {\n this.$x.emit('UserAcceptedAQuery', this.query, this.createEventMetadata());\n this.$x.emit('UserPressedSearchButton', this.query, this.createEventMetadata());\n }\n }\n\n protected get dynamicClasses(): VueCSSClasses {\n return {\n 'x-search-button--has-empty-query': this.isQueryEmpty\n };\n }\n}\n"],"names":[],"mappings":";;;;;;;AAqBA;;;;;;;;;;AAaA;IAA0C,gCAAG;IAA7C;;KAsCC;IAlCC,sBAAc,sCAAY;aAA1B;YACE,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC,CAAC;SAChC;;;OAAA;;;;;;;IAQS,0CAAmB,GAA7B;QACE,OAAO;YACL,MAAM,EAAE,IAAI,CAAC,GAAkB;YAC/B,OAAO,EAAE,YAAY;SACtB,CAAC;KACH;;;;;;IAOS,iCAAU,GAApB;QACE,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE;YACtB,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,oBAAoB,EAAE,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,mBAAmB,EAAE,CAAC,CAAC;YAC3E,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,yBAAyB,EAAE,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,mBAAmB,EAAE,CAAC,CAAC;SACjF;KACF;IAED,sBAAc,wCAAc;aAA5B;YACE,OAAO;gBACL,kCAAkC,EAAE,IAAI,CAAC,YAAY;aACtD,CAAC;SACH;;;OAAA;IAnCD;QADC,KAAK,CAAC,WAAW,EAAE,OAAO,CAAC;+CACN;IAFH,YAAY;QAHhC,SAAS,CAAC;YACT,MAAM,EAAE,CAAC,eAAe,CAAC,gBAAgB,CAAC,CAAC;SAC5C,CAAC;OACmB,YAAY,CAsChC;IAAD,mBAAC;CAAA,CAtCyC,GAAG;;;;"}
@@ -61,11 +61,11 @@ __vue_render__._withStripped = true;
61
61
  /* style */
62
62
  var __vue_inject_styles__ = function (inject) {
63
63
  if (!inject) { return }
64
- inject("data-v-3d804b23_0", { source: ".x-search-input[data-v-3d804b23]::-webkit-search-decoration,\n.x-search-input[data-v-3d804b23]::-webkit-search-cancel-button,\n.x-search-input[data-v-3d804b23]::-webkit-search-results-button,\n.x-search-input[data-v-3d804b23]::-webkit-search-results-decoration {\n -webkit-appearance: none;\n}", map: undefined, media: undefined });
64
+ inject("data-v-32b99e91_0", { source: ".x-search-input[data-v-32b99e91]::-webkit-search-decoration,\n.x-search-input[data-v-32b99e91]::-webkit-search-cancel-button,\n.x-search-input[data-v-32b99e91]::-webkit-search-results-button,\n.x-search-input[data-v-32b99e91]::-webkit-search-results-decoration {\n -webkit-appearance: none;\n}", map: undefined, media: undefined });
65
65
 
66
66
  };
67
67
  /* scoped */
68
- var __vue_scope_id__ = "data-v-3d804b23";
68
+ var __vue_scope_id__ = "data-v-32b99e91";
69
69
  /* module identifier */
70
70
  var __vue_module_identifier__ = undefined;
71
71
  /* 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 :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 />\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 /**\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 * Focus search input when the user navigates to the search input.\n *\n * @internal\n */\n @XOn('UserReachedEmpathizeTop')\n focusInput(): void {\n this.$refs.input?.focus();\n }\n\n protected debouncedUserAcceptedAQuery!: DebouncedFunction<[string]>;\n\n /**\n * When event {@link XEventsTypes.UserAcceptedAQuery} is emitted the pending debounced emit\n * {@link XEvent} `UserAcceptedAQuery` is canceled.\n *\n * @internal\n */\n @XOn('UserAcceptedAQuery')\n @XOn('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 eventMetadata(): Omit<WireMetadata, 'moduleName'> {\n return {\n target: this.$refs.input\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, this.eventMetadata());\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, this.eventMetadata());\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, this.eventMetadata());\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, this.eventMetadata());\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.eventMetadata());\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.eventMetadata());\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.eventMetadata());\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\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\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\n<template>\n <SearchInput\n @UserPressedEnterKey=\"logUserPressedEnter\"\n @UserFocusedSearchBox=\"hasFocus = true\"\n @UserBlurredSearchBox=\"hasFocus = false\"\n @UserIsTypingAQuery=\"value = 'focus'\"\n />\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 methods: {\n logUserPressedEnter() {\n console.log('User pressed enter');\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 “puzzle” or another toy in the input field and then click the clear icon to try it out!_\n\n```vue\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 {\n SearchInput,\n ClearSearchInput,\n ClearSearchButton\n } 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 ClearSearchButton,\n QuerySuggestions\n }\n };\n</script>\n```\n</docs>\n"],"names":["const"],"mappings":";;;;;AAEAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
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 :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 />\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 /**\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 * Focus search input when the user navigates to the search input.\n *\n * @internal\n */\n @XOn('UserReachedEmpathizeTop')\n focusInput(): void {\n this.$refs.input?.focus();\n }\n\n protected debouncedUserAcceptedAQuery!: DebouncedFunction<[string]>;\n\n /**\n * When event {@link XEventsTypes.UserAcceptedAQuery} is emitted the pending debounced emit\n * {@link XEvent} `UserAcceptedAQuery` is canceled.\n *\n * @internal\n */\n @XOn('UserAcceptedAQuery')\n @XOn('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\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\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\n<template>\n <SearchInput\n @UserPressedEnterKey=\"logUserPressedEnter\"\n @UserFocusedSearchBox=\"hasFocus = true\"\n @UserBlurredSearchBox=\"hasFocus = false\"\n @UserIsTypingAQuery=\"value = 'focus'\"\n />\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 methods: {\n logUserPressedEnter() {\n console.log('User pressed enter');\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 “puzzle” or another toy in the input field and then click the clear icon to try it out!_\n\n```vue\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 {\n SearchInput,\n ClearSearchInput,\n ClearSearchButton\n } 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 ClearSearchButton,\n QuerySuggestions\n }\n };\n</script>\n```\n</docs>\n"],"names":["const"],"mappings":";;;;;AAEAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -63,9 +63,10 @@ var SearchInput = /** @class */ (function (_super) {
63
63
  * @returns The {@link WireMetadata} object omitting the moduleName.
64
64
  * @internal
65
65
  */
66
- SearchInput.prototype.eventMetadata = function () {
66
+ SearchInput.prototype.createEventMetadata = function () {
67
67
  return {
68
- target: this.$refs.input
68
+ target: this.$refs.input,
69
+ feature: 'search_box'
69
70
  };
70
71
  };
71
72
  /**
@@ -74,7 +75,7 @@ var SearchInput = /** @class */ (function (_super) {
74
75
  * @internal
75
76
  */
76
77
  SearchInput.prototype.emitUserBlurredSearchBox = function () {
77
- this.$x.emit('UserBlurredSearchBox', undefined, this.eventMetadata());
78
+ this.$x.emit('UserBlurredSearchBox', undefined, { target: this.$refs.input });
78
79
  };
79
80
  /**
80
81
  * Emits event {@link SearchBoxXEvents.UserClickedSearchBox} when user clicks the search input.
@@ -82,7 +83,7 @@ var SearchInput = /** @class */ (function (_super) {
82
83
  * @internal
83
84
  */
84
85
  SearchInput.prototype.emitUserClickedSearchBox = function () {
85
- this.$x.emit('UserClickedSearchBox', undefined, this.eventMetadata());
86
+ this.$x.emit('UserClickedSearchBox', undefined, { target: this.$refs.input });
86
87
  };
87
88
  /**
88
89
  * Emits event {@link SearchBoxXEvents.UserFocusedSearchBox} when search box gains focus.
@@ -90,7 +91,7 @@ var SearchInput = /** @class */ (function (_super) {
90
91
  * @internal
91
92
  */
92
93
  SearchInput.prototype.emitUserFocusedSearchBox = function () {
93
- this.$x.emit('UserFocusedSearchBox', undefined, this.eventMetadata());
94
+ this.$x.emit('UserFocusedSearchBox', undefined, { target: this.$refs.input });
94
95
  };
95
96
  /**
96
97
  * Emits event {@link SearchBoxXEvents.UserIsTypingAQuery} when the user typed/pasted something
@@ -101,7 +102,7 @@ var SearchInput = /** @class */ (function (_super) {
101
102
  */
102
103
  SearchInput.prototype.emitUserIsTypingAQueryEvents = function () {
103
104
  var query = this.$refs.input.value;
104
- this.$x.emit('UserIsTypingAQuery', query, this.eventMetadata());
105
+ this.$x.emit('UserIsTypingAQuery', query, { target: this.$refs.input });
105
106
  if (query.trim()) {
106
107
  this.emitDebouncedUserAcceptedAQuery(query);
107
108
  }
@@ -116,7 +117,7 @@ var SearchInput = /** @class */ (function (_super) {
116
117
  * @internal
117
118
  */
118
119
  SearchInput.prototype.emitUserPressedArrowKey = function (event) {
119
- this.$x.emit('UserPressedArrowKey', event.key, this.eventMetadata());
120
+ this.$x.emit('UserPressedArrowKey', event.key, this.createEventMetadata());
120
121
  };
121
122
  /**
122
123
  * Emits multiple events when the user pressed the enter key.
@@ -132,7 +133,7 @@ var SearchInput = /** @class */ (function (_super) {
132
133
  var _a;
133
134
  var query = this.$refs.input.value.trim();
134
135
  if (query.length > 0) {
135
- this.$x.emit('UserPressedEnterKey', query, this.eventMetadata());
136
+ this.$x.emit('UserPressedEnterKey', query, this.createEventMetadata());
136
137
  this.emitUserAcceptedAQuery(query);
137
138
  }
138
139
  (_a = this.$refs.input) === null || _a === void 0 ? void 0 : _a.blur();
@@ -146,7 +147,7 @@ var SearchInput = /** @class */ (function (_super) {
146
147
  * @param query - The query that will be emitted.
147
148
  */
148
149
  SearchInput.prototype.emitUserAcceptedAQuery = function (query) {
149
- this.$x.emit('UserAcceptedAQuery', query, this.eventMetadata());
150
+ this.$x.emit('UserAcceptedAQuery', query, this.createEventMetadata());
150
151
  };
151
152
  __decorate([
152
153
  Prop({ default: 64 })
@@ -1 +1 @@
1
- {"version":3,"file":"search-input.vue_rollup-plugin-vue=script.js","sources":["../../../../../src/x-modules/search-box/components/search-input.vue?rollup-plugin-vue=script.ts"],"sourcesContent":["\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nimport { Suggestion } from '@empathyco/x-types';\nimport Vue from 'vue';\nimport { Component, Prop } from 'vue-property-decorator';\nimport { XOn } from '../../../components/decorators/bus.decorators';\nimport { State } from '../../../components/decorators/store.decorators';\nimport { xComponentMixin } from '../../../components/x-component.mixin';\nimport { ArrowKey, PropsWithType } from '../../../utils';\nimport { debounce } from '../../../utils/debounce';\nimport { DebouncedFunction } from '../../../utils/types';\nimport { XEventsTypes } from '../../../wiring/events.types';\nimport { WireMetadata } from '../../../wiring/wiring.types';\nimport { 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})\nexport default class SearchInput extends Vue {\n public $refs!: { input: HTMLInputElement };\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 * Focus search input when the user navigates to the search input.\n *\n * @internal\n */\n @XOn('UserReachedEmpathizeTop')\n focusInput(): void {\n this.$refs.input?.focus();\n }\n\n protected debouncedUserAcceptedAQuery!: DebouncedFunction<[string]>;\n\n /**\n * When event {@link XEventsTypes.UserAcceptedAQuery} is emitted the pending debounced emit\n * {@link XEvent} `UserAcceptedAQuery` is canceled.\n *\n * @internal\n */\n @XOn('UserAcceptedAQuery')\n @XOn('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 eventMetadata(): Omit<WireMetadata, 'moduleName'> {\n return {\n target: this.$refs.input\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, this.eventMetadata());\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, this.eventMetadata());\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, this.eventMetadata());\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, this.eventMetadata());\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.eventMetadata());\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.eventMetadata());\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.eventMetadata());\n }\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"search-input.vue_rollup-plugin-vue=script.js","sources":["../../../../../src/x-modules/search-box/components/search-input.vue?rollup-plugin-vue=script.ts"],"sourcesContent":["\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nimport { Suggestion } from '@empathyco/x-types';\nimport Vue from 'vue';\nimport { Component, Prop } from 'vue-property-decorator';\nimport { XOn } from '../../../components/decorators/bus.decorators';\nimport { State } from '../../../components/decorators/store.decorators';\nimport { xComponentMixin } from '../../../components/x-component.mixin';\nimport { ArrowKey, PropsWithType } from '../../../utils';\nimport { debounce } from '../../../utils/debounce';\nimport { DebouncedFunction } from '../../../utils/types';\nimport { XEventsTypes } from '../../../wiring/events.types';\nimport { WireMetadata } from '../../../wiring/wiring.types';\nimport { 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})\nexport default class SearchInput extends Vue {\n public $refs!: { input: HTMLInputElement };\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 * Focus search input when the user navigates to the search input.\n *\n * @internal\n */\n @XOn('UserReachedEmpathizeTop')\n focusInput(): void {\n this.$refs.input?.focus();\n }\n\n protected debouncedUserAcceptedAQuery!: DebouncedFunction<[string]>;\n\n /**\n * When event {@link XEventsTypes.UserAcceptedAQuery} is emitted the pending debounced emit\n * {@link XEvent} `UserAcceptedAQuery` is canceled.\n *\n * @internal\n */\n @XOn('UserAcceptedAQuery')\n @XOn('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"],"names":[],"mappings":"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"}
@@ -0,0 +1,43 @@
1
+ import { __assign } from 'tslib';
2
+ import { XPlugin } from '../../../../plugins/x-plugin.js';
3
+ import { DefaultSessionService } from '../../service/session.service.js';
4
+
5
+ /**
6
+ * Default implementation for the {@link TaggingActions.track}.
7
+ *
8
+ * @param context - The {@link https://vuex.vuejs.org/guide/actions.html | context} of the actions,
9
+ * provided by Vuex.
10
+ * @param taggingInfo - The information of the event to track.
11
+ *
12
+ * @public
13
+ */
14
+ var track = function (_a, taggingInfo) {
15
+ var state = _a.state;
16
+ var consent = state.consent;
17
+ var tagging = Array.isArray(taggingInfo) ? taggingInfo : [taggingInfo];
18
+ var sessionId = getSessionId(consent);
19
+ // TODO EX-5061 - Remove this validation when the adapter ignores undefined values.
20
+ var session = sessionId && { session: sessionId };
21
+ tagging.forEach(function (_a) {
22
+ var url = _a.url, params = _a.params;
23
+ XPlugin.adapter.track({
24
+ url: url,
25
+ params: __assign(__assign({}, params), session)
26
+ });
27
+ });
28
+ };
29
+ /**
30
+ * Returns the session id if the consent is true.
31
+ *
32
+ * @param consent - User consent to retrieve the session id.
33
+ *
34
+ * @returns The user session id or undefined.
35
+ *
36
+ * @internal
37
+ */
38
+ function getSessionId(consent) {
39
+ return consent ? DefaultSessionService.instance.getSessionId() : undefined;
40
+ }
41
+
42
+ export { track };
43
+ //# sourceMappingURL=track.action.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"track.action.js","sources":["../../../../../../src/x-modules/tagging/store/actions/track.action.ts"],"sourcesContent":["import { TaggingInfo } from '@empathyco/x-types';\nimport { XPlugin } from '../../../../plugins/x-plugin';\nimport { DefaultSessionService } from '../../service';\nimport { TaggingXStoreModule } from '../types';\n\n/**\n * Default implementation for the {@link TaggingActions.track}.\n *\n * @param context - The {@link https://vuex.vuejs.org/guide/actions.html | context} of the actions,\n * provided by Vuex.\n * @param taggingInfo - The information of the event to track.\n *\n * @public\n */\nexport const track: TaggingXStoreModule['actions']['track'] = ({ state }, taggingInfo) => {\n const { consent } = state;\n const tagging = Array.isArray(taggingInfo) ? taggingInfo : [taggingInfo];\n const sessionId = getSessionId(consent);\n // TODO EX-5061 - Remove this validation when the adapter ignores undefined values.\n const session = sessionId && { session: sessionId };\n\n tagging.forEach(({ url, params }: TaggingInfo) => {\n XPlugin.adapter.track({\n url,\n params: {\n ...params,\n ...session\n }\n });\n });\n};\n\n/**\n * Returns the session id if the consent is true.\n *\n * @param consent - User consent to retrieve the session id.\n *\n * @returns The user session id or undefined.\n *\n * @internal\n */\nfunction getSessionId(consent: boolean | null): string | undefined {\n return consent ? DefaultSessionService.instance.getSessionId() : undefined;\n}\n"],"names":[],"mappings":";;;;AAKA;;;;;;;;;IASa,KAAK,GAA4C,UAAC,EAAS,EAAE,WAAW;QAApB,KAAK,WAAA;IAC5D,IAAA,OAAO,GAAK,KAAK,QAAV,CAAW;IAC1B,IAAM,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC,WAAW,CAAC,GAAG,WAAW,GAAG,CAAC,WAAW,CAAC,CAAC;IACzE,IAAM,SAAS,GAAG,YAAY,CAAC,OAAO,CAAC,CAAC;;IAExC,IAAM,OAAO,GAAG,SAAS,IAAI,EAAE,OAAO,EAAE,SAAS,EAAE,CAAC;IAEpD,OAAO,CAAC,OAAO,CAAC,UAAC,EAA4B;YAA1B,GAAG,SAAA,EAAE,MAAM,YAAA;QAC5B,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC;YACpB,GAAG,KAAA;YACH,MAAM,wBACD,MAAM,GACN,OAAO,CACX;SACF,CAAC,CAAC;KACJ,CAAC,CAAC;AACL,EAAE;AAEF;;;;;;;;;AASA,SAAS,YAAY,CAAC,OAAuB;IAC3C,OAAO,OAAO,GAAG,qBAAqB,CAAC,QAAQ,CAAC,YAAY,EAAE,GAAG,SAAS,CAAC;AAC7E;;;;"}
@@ -1,3 +1,5 @@
1
+ import { track } from './actions/track.action.js';
2
+
1
3
  /**
2
4
  * {@link XStoreModule} For the tagging module.
3
5
  *
@@ -7,7 +9,7 @@ var taggingXStoreModule = {
7
9
  state: function () { return ({
8
10
  config: {
9
11
  sessionTTLMs: 30 * 60 * 1000,
10
- queryTaggingDebounceMs: 200
12
+ queryTaggingDebounceMs: 2000
11
13
  },
12
14
  consent: null
13
15
  }); },
@@ -23,7 +25,9 @@ var taggingXStoreModule = {
23
25
  state.consent = consent;
24
26
  }
25
27
  },
26
- actions: {}
28
+ actions: {
29
+ track: track
30
+ }
27
31
  };
28
32
 
29
33
  export { taggingXStoreModule };
@@ -1 +1 @@
1
- {"version":3,"file":"module.js","sources":["../../../../../src/x-modules/tagging/store/module.ts"],"sourcesContent":["import { TaggingXStoreModule } from './types';\n\n/**\n * {@link XStoreModule} For the tagging module.\n *\n * @internal\n */\nexport const taggingXStoreModule: TaggingXStoreModule = {\n state: () => ({\n config: {\n sessionTTLMs: 30 * 60 * 1000,\n queryTaggingDebounceMs: 200\n },\n consent: null\n }),\n getters: {},\n mutations: {\n setSessionDuration(state, sessionTTLMs) {\n state.config.sessionTTLMs = sessionTTLMs;\n },\n setQueryTaggingDebounce(state, queryTaggingDebounceMs) {\n state.config.queryTaggingDebounceMs = queryTaggingDebounceMs;\n },\n setConsent(state, consent) {\n state.consent = consent;\n }\n },\n actions: {}\n};\n"],"names":[],"mappings":"AAEA;;;;;IAKa,mBAAmB,GAAwB;IACtD,KAAK,EAAE,cAAM,QAAC;QACZ,MAAM,EAAE;YACN,YAAY,EAAE,EAAE,GAAG,EAAE,GAAG,IAAI;YAC5B,sBAAsB,EAAE,GAAG;SAC5B;QACD,OAAO,EAAE,IAAI;KACd,IAAC;IACF,OAAO,EAAE,EAAE;IACX,SAAS,EAAE;QACT,kBAAkB,YAAC,KAAK,EAAE,YAAY;YACpC,KAAK,CAAC,MAAM,CAAC,YAAY,GAAG,YAAY,CAAC;SAC1C;QACD,uBAAuB,YAAC,KAAK,EAAE,sBAAsB;YACnD,KAAK,CAAC,MAAM,CAAC,sBAAsB,GAAG,sBAAsB,CAAC;SAC9D;QACD,UAAU,YAAC,KAAK,EAAE,OAAO;YACvB,KAAK,CAAC,OAAO,GAAG,OAAO,CAAC;SACzB;KACF;IACD,OAAO,EAAE,EAAE;;;;;"}
1
+ {"version":3,"file":"module.js","sources":["../../../../../src/x-modules/tagging/store/module.ts"],"sourcesContent":["import { track } from './actions/track.action';\nimport { TaggingXStoreModule } from './types';\n\n/**\n * {@link XStoreModule} For the tagging module.\n *\n * @internal\n */\nexport const taggingXStoreModule: TaggingXStoreModule = {\n state: () => ({\n config: {\n sessionTTLMs: 30 * 60 * 1000,\n queryTaggingDebounceMs: 2000\n },\n consent: null\n }),\n getters: {},\n mutations: {\n setSessionDuration(state, sessionTTLMs) {\n state.config.sessionTTLMs = sessionTTLMs;\n },\n setQueryTaggingDebounce(state, queryTaggingDebounceMs) {\n state.config.queryTaggingDebounceMs = queryTaggingDebounceMs;\n },\n setConsent(state, consent) {\n state.consent = consent;\n }\n },\n actions: {\n track\n }\n};\n"],"names":[],"mappings":";;AAGA;;;;;IAKa,mBAAmB,GAAwB;IACtD,KAAK,EAAE,cAAM,QAAC;QACZ,MAAM,EAAE;YACN,YAAY,EAAE,EAAE,GAAG,EAAE,GAAG,IAAI;YAC5B,sBAAsB,EAAE,IAAI;SAC7B;QACD,OAAO,EAAE,IAAI;KACd,IAAC;IACF,OAAO,EAAE,EAAE;IACX,SAAS,EAAE;QACT,kBAAkB,YAAC,KAAK,EAAE,YAAY;YACpC,KAAK,CAAC,MAAM,CAAC,YAAY,GAAG,YAAY,CAAC;SAC1C;QACD,uBAAuB,YAAC,KAAK,EAAE,sBAAsB;YACnD,KAAK,CAAC,MAAM,CAAC,sBAAsB,GAAG,sBAAsB,CAAC;SAC9D;QACD,UAAU,YAAC,KAAK,EAAE,OAAO;YACvB,KAAK,CAAC,OAAO,GAAG,OAAO,CAAC;SACzB;KACF;IACD,OAAO,EAAE;QACP,KAAK,OAAA;KACN;;;;;"}
@@ -1,7 +1,8 @@
1
1
  import { wireServiceWithoutPayload } from '../../wiring/wires.factory.js';
2
2
  import { createWiring } from '../../wiring/wiring.utils.js';
3
- import { namespacedWireCommit } from '../../wiring/namespaced-wires.factory.js';
3
+ import { namespacedWireCommit, namespacedWireDispatch } from '../../wiring/namespaced-wires.factory.js';
4
4
  import { filter } from '../../wiring/wires.operators.js';
5
+ import { namespacedDebounce } from '../../wiring/namespaced-wires.operators.js';
5
6
  import { DefaultSessionService } from './service/session.service.js';
6
7
 
7
8
  /**
@@ -10,12 +11,22 @@ import { DefaultSessionService } from './service/session.service.js';
10
11
  * @internal
11
12
  */
12
13
  var moduleName = 'tagging';
14
+ /**
15
+ * Debounce function for the module.
16
+ */
17
+ var moduleDebounce = namespacedDebounce(moduleName);
13
18
  /**
14
19
  * WireCommit for {@link TaggingXModule}.
15
20
  *
16
21
  * @internal
17
22
  */
18
23
  var wireCommit = namespacedWireCommit(moduleName);
24
+ /**
25
+ * WireDispatch for {@link TaggingXModule}.
26
+ *
27
+ * @internal
28
+ */
29
+ var wireDispatch = namespacedWireDispatch(moduleName);
19
30
  /**
20
31
  * Wires without payload factory for {@link DefaultSessionService}.
21
32
  */
@@ -44,6 +55,16 @@ var setQueryTaggingDebounce = wireCommit('setQueryTaggingDebounce');
44
55
  * @public
45
56
  */
46
57
  var setSessionDuration = wireCommit('setSessionDuration');
58
+ /**
59
+ * Tracks the tagging of the query using a debounce which ends if the user
60
+ * accepts a query.
61
+ *
62
+ * @public
63
+ */
64
+ var trackWire = moduleDebounce(wireDispatch('track'), function (_a) {
65
+ var state = _a.state;
66
+ return state.config.queryTaggingDebounceMs;
67
+ }, 'UserClearedQuery');
47
68
  /**
48
69
  * Wiring configuration for the {@link TaggingXModule | tagging module}.
49
70
  *
@@ -61,8 +82,11 @@ var taggingWiring = createWiring({
61
82
  },
62
83
  QueryTaggingDebounceProvided: {
63
84
  setQueryTaggingDebounce: setQueryTaggingDebounce
85
+ },
86
+ SearchTaggingChanged: {
87
+ trackWire: trackWire
64
88
  }
65
89
  });
66
90
 
67
- export { setConsent, setQueryTaggingDebounce, setSessionDuration, taggingWiring };
91
+ export { setConsent, setQueryTaggingDebounce, setSessionDuration, taggingWiring, trackWire };
68
92
  //# sourceMappingURL=wiring.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"wiring.js","sources":["../../../../src/x-modules/tagging/wiring.ts"],"sourcesContent":["import { namespacedWireCommit } from '../../wiring/namespaced-wires.factory';\nimport { wireServiceWithoutPayload } from '../../wiring/wires.factory';\nimport { filter } from '../../wiring/wires.operators';\nimport { createWiring } from '../../wiring/wiring.utils';\nimport { DefaultSessionService } from './service/session.service';\n\n/**\n * `tagging` {@link XModuleName | XModule name}.\n *\n * @internal\n */\nconst moduleName = 'tagging';\n\n/**\n * WireCommit for {@link TaggingXModule}.\n *\n * @internal\n */\nconst wireCommit = namespacedWireCommit(moduleName);\n\n/**\n * Wires without payload factory for {@link DefaultSessionService}.\n */\nconst wireSessionServiceWithoutPayload = wireServiceWithoutPayload(DefaultSessionService.instance);\n\n/**\n * Clears the session id.\n *\n * @public\n */\nconst clearSessionWire = filter(\n wireSessionServiceWithoutPayload('clearSessionId'),\n consent => !consent\n);\n\n/**\n * Sets the tagging state `consent`.\n *\n * @public\n */\nexport const setConsent = wireCommit('setConsent');\n\n/**\n * Sets the tagging state config `queryTaggingDebounceMs`.\n *\n * @public\n */\nexport const setQueryTaggingDebounce = wireCommit('setQueryTaggingDebounce');\n\n/**\n * Sets the tagging state `sessionTTLMs`.\n *\n * @public\n */\nexport const setSessionDuration = wireCommit('setSessionDuration');\n\n/**\n * Wiring configuration for the {@link TaggingXModule | tagging module}.\n *\n * @internal\n */\nexport const taggingWiring = createWiring({\n ConsentProvided: {\n setConsent\n },\n ConsentChanged: {\n clearSessionWire\n },\n SessionDurationProvided: {\n setSessionDuration\n },\n QueryTaggingDebounceProvided: {\n setQueryTaggingDebounce\n }\n});\n"],"names":[],"mappings":";;;;;;AAMA;;;;;AAKA,IAAM,UAAU,GAAG,SAAS,CAAC;AAE7B;;;;;AAKA,IAAM,UAAU,GAAG,oBAAoB,CAAC,UAAU,CAAC,CAAC;AAEpD;;;AAGA,IAAM,gCAAgC,GAAG,yBAAyB,CAAC,qBAAqB,CAAC,QAAQ,CAAC,CAAC;AAEnG;;;;;AAKA,IAAM,gBAAgB,GAAG,MAAM,CAC7B,gCAAgC,CAAC,gBAAgB,CAAC,EAClD,UAAA,OAAO,IAAI,OAAA,CAAC,OAAO,GAAA,CACpB,CAAC;AAEF;;;;;IAKa,UAAU,GAAG,UAAU,CAAC,YAAY,EAAE;AAEnD;;;;;IAKa,uBAAuB,GAAG,UAAU,CAAC,yBAAyB,EAAE;AAE7E;;;;;IAKa,kBAAkB,GAAG,UAAU,CAAC,oBAAoB,EAAE;AAEnE;;;;;IAKa,aAAa,GAAG,YAAY,CAAC;IACxC,eAAe,EAAE;QACf,UAAU,YAAA;KACX;IACD,cAAc,EAAE;QACd,gBAAgB,kBAAA;KACjB;IACD,uBAAuB,EAAE;QACvB,kBAAkB,oBAAA;KACnB;IACD,4BAA4B,EAAE;QAC5B,uBAAuB,yBAAA;KACxB;CACF;;;;"}
1
+ {"version":3,"file":"wiring.js","sources":["../../../../src/x-modules/tagging/wiring.ts"],"sourcesContent":["import { namespacedDebounce } from '../../wiring';\nimport {\n namespacedWireCommit,\n namespacedWireDispatch\n} from '../../wiring/namespaced-wires.factory';\nimport { wireServiceWithoutPayload } from '../../wiring/wires.factory';\nimport { filter } from '../../wiring/wires.operators';\nimport { createWiring } from '../../wiring/wiring.utils';\nimport { DefaultSessionService } from './service/session.service';\n\n/**\n * `tagging` {@link XModuleName | XModule name}.\n *\n * @internal\n */\nconst moduleName = 'tagging';\n\n/**\n * Debounce function for the module.\n */\nconst moduleDebounce = namespacedDebounce(moduleName);\n\n/**\n * WireCommit for {@link TaggingXModule}.\n *\n * @internal\n */\nconst wireCommit = namespacedWireCommit(moduleName);\n\n/**\n * WireDispatch for {@link TaggingXModule}.\n *\n * @internal\n */\nconst wireDispatch = namespacedWireDispatch(moduleName);\n\n/**\n * Wires without payload factory for {@link DefaultSessionService}.\n */\nconst wireSessionServiceWithoutPayload = wireServiceWithoutPayload(DefaultSessionService.instance);\n\n/**\n * Clears the session id.\n *\n * @public\n */\nconst clearSessionWire = filter(\n wireSessionServiceWithoutPayload('clearSessionId'),\n consent => !consent\n);\n\n/**\n * Sets the tagging state `consent`.\n *\n * @public\n */\nexport const setConsent = wireCommit('setConsent');\n\n/**\n * Sets the tagging state config `queryTaggingDebounceMs`.\n *\n * @public\n */\nexport const setQueryTaggingDebounce = wireCommit('setQueryTaggingDebounce');\n\n/**\n * Sets the tagging state `sessionTTLMs`.\n *\n * @public\n */\nexport const setSessionDuration = wireCommit('setSessionDuration');\n\n/**\n * Tracks the tagging of the query using a debounce which ends if the user\n * accepts a query.\n *\n * @public\n */\nexport const trackWire = moduleDebounce(\n wireDispatch('track'),\n ({ state }) => state.config.queryTaggingDebounceMs,\n 'UserClearedQuery'\n);\n\n/**\n * Wiring configuration for the {@link TaggingXModule | tagging module}.\n *\n * @internal\n */\nexport const taggingWiring = createWiring({\n ConsentProvided: {\n setConsent\n },\n ConsentChanged: {\n clearSessionWire\n },\n SessionDurationProvided: {\n setSessionDuration\n },\n QueryTaggingDebounceProvided: {\n setQueryTaggingDebounce\n },\n SearchTaggingChanged: {\n trackWire\n }\n});\n"],"names":[],"mappings":";;;;;;;AAUA;;;;;AAKA,IAAM,UAAU,GAAG,SAAS,CAAC;AAE7B;;;AAGA,IAAM,cAAc,GAAG,kBAAkB,CAAC,UAAU,CAAC,CAAC;AAEtD;;;;;AAKA,IAAM,UAAU,GAAG,oBAAoB,CAAC,UAAU,CAAC,CAAC;AAEpD;;;;;AAKA,IAAM,YAAY,GAAG,sBAAsB,CAAC,UAAU,CAAC,CAAC;AAExD;;;AAGA,IAAM,gCAAgC,GAAG,yBAAyB,CAAC,qBAAqB,CAAC,QAAQ,CAAC,CAAC;AAEnG;;;;;AAKA,IAAM,gBAAgB,GAAG,MAAM,CAC7B,gCAAgC,CAAC,gBAAgB,CAAC,EAClD,UAAA,OAAO,IAAI,OAAA,CAAC,OAAO,GAAA,CACpB,CAAC;AAEF;;;;;IAKa,UAAU,GAAG,UAAU,CAAC,YAAY,EAAE;AAEnD;;;;;IAKa,uBAAuB,GAAG,UAAU,CAAC,yBAAyB,EAAE;AAE7E;;;;;IAKa,kBAAkB,GAAG,UAAU,CAAC,oBAAoB,EAAE;AAEnE;;;;;;IAMa,SAAS,GAAG,cAAc,CACrC,YAAY,CAAC,OAAO,CAAC,EACrB,UAAC,EAAS;QAAP,KAAK,WAAA;IAAO,OAAA,KAAK,CAAC,MAAM,CAAC,sBAAsB;AAAnC,CAAmC,EAClD,kBAAkB,EAClB;AAEF;;;;;IAKa,aAAa,GAAG,YAAY,CAAC;IACxC,eAAe,EAAE;QACf,UAAU,YAAA;KACX;IACD,cAAc,EAAE;QACd,gBAAgB,kBAAA;KACjB;IACD,uBAAuB,EAAE;QACvB,kBAAkB,oBAAA;KACnB;IACD,4BAA4B,EAAE;QAC5B,uBAAuB,yBAAA;KACxB;IACD,oBAAoB,EAAE;QACpB,SAAS,WAAA;KACV;CACF;;;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"url-handler.vue.js","sources":["../../../../../src/x-modules/url/components/url-handler.vue"],"sourcesContent":["<template>\n <GlobalEvents @popstate=\"emitEvents\" target=\"window\" />\n</template>\n\n<script lang=\"ts\">\n import Vue from 'vue';\n import GlobalEvents from 'vue-global-events';\n import { Component } from 'vue-property-decorator';\n import { XOn } from '../../../components/decorators/bus.decorators';\n import { xComponentMixin } from '../../../components/x-component.mixin';\n import { UrlParams } from '../../../types/url-params';\n import { objectFilter } from '../../../utils/object';\n import { Dictionary } from '../../../utils/types';\n import { initialUrlState } from '../store/initial-state';\n import { UrlParamValue } from '../store/types';\n import { urlXModule } from '../x-module';\n\n interface ParsedUrlParams {\n all: UrlParams;\n extra: Dictionary<unknown>;\n }\n\n /**\n * This component manage the browser URL parameters to perserve them through reloads and browser\n * history navigation. It allow to configure the default url parameter names using its attributes.\n * This component doesn't render elements to the DOM.\n *\n * @public\n */\n @Component({\n components: {\n GlobalEvents\n },\n mixins: [xComponentMixin(urlXModule)]\n })\n export default class UrlHandler extends Vue {\n /**\n * Computed to know which params we must get from URL. It gets the params names from the initial\n * state, to get all default params names, and also from the `$attrs` to get the extra params\n * names to take into account.\n *\n * @returns An array with the name of the params.\n *\n * @internal\n */\n protected get managedParamsNames(): string[] {\n return Object.keys({ ...initialUrlState, ...this.$attrs });\n }\n\n /**\n * Returns the mapping of the param keys used in the URL is configured through $attrs. This way\n * we can support any param and extra param, no matters its name.\n *\n * @param paramName - The param name to get the Url key.\n * @returns The key used in the URL for the `paramName` passed.\n *\n * @internal\n */\n protected getUrlKey(paramName: string): string {\n return this.$attrs[paramName] ?? paramName;\n }\n\n /**\n * Flag to know if the params were already loaded from the URL.\n *\n * @internal\n */\n protected urlLoaded = false;\n\n /**\n * To emit the Url events just when the URL is load, and before the components mounted events\n * and state changes, we do it in the created of this component.\n */\n created(): void {\n this.emitEvents();\n }\n\n /**\n * Updates the browser URL with the new {@link UrlParams} using the history `pushState` method.\n *\n * @param newUrlParams - The new params to update browser URL.\n */\n @XOn('PushableUrlStateChanged')\n updateUrlWithPush(newUrlParams: UrlParams): void {\n this.updateUrl(newUrlParams, window.history.pushState.bind(window.history));\n }\n\n /**\n * Updates the browser URL with the new {@link UrlParams} using the history `replaceState`\n * method.\n *\n * @param newUrlParams - The new params to update browser URL.\n */\n @XOn('ReplaceableUrlStateChanged')\n updateUrlWithReplace(newUrlParams: UrlParams): void {\n this.updateUrl(newUrlParams, window.history.replaceState.bind(window.history));\n }\n\n /**\n * Emits the {@link UrlXEvents.ParamsLoadedFromUrl} XEvent,\n * the {@link UrlXEvents.ExtraParamsLoadedFromUrl} XEvent and, if there is query, also emits\n * the {@link XEventsTypes.UserOpenXProgrammatically}.\n *\n * @internal\n */\n protected emitEvents(): void {\n const { all, extra } = this.parseUrlParams();\n this.$x.emit('ParamsLoadedFromUrl', all);\n this.$x.emit('ExtraParamsLoadedFromUrl', extra);\n // TODO: Move this logic from here.\n if (all.query) {\n this.$x.emit('UserOpenXProgrammatically');\n }\n this.urlLoaded = true;\n }\n\n /**\n * Gets the {@link UrlParams} from the URL, including only the params defined by `paramsNames`.\n *\n * @returns ParsedUrlParams obtained from URL.\n * @internal\n */\n\n protected parseUrlParams(): ParsedUrlParams {\n const urlSearchParams = new URL(window.location.href).searchParams;\n return this.managedParamsNames.reduce<ParsedUrlParams>(\n (params, name) => {\n const urlKey = this.getUrlKey(name);\n if (urlSearchParams.has(urlKey)) {\n if (name in initialUrlState) {\n const urlValue = urlSearchParams.getAll(urlKey);\n params.all[name] = this.parseUrlParam(name, urlValue);\n } else {\n params.all[name] = params.extra[name] = urlSearchParams.get(urlKey);\n }\n }\n return params;\n },\n { all: { ...initialUrlState }, extra: {} }\n );\n }\n\n /**\n * Updates the browser URL with the passed `newUrlParams` and using the browser history method\n * passed as `historyMethod`. It only updates the browser history if the new URL is different\n * from the current.\n *\n * @param newUrlParams - The new params to add to the browser URL.\n * @param historyMethod - The browser history method used to add the new URL.\n *\n * @internal\n */\n protected updateUrl(\n newUrlParams: UrlParams,\n historyMethod: History['pushState'] | History['replaceState']\n ): void {\n if (this.urlLoaded) {\n const url = new URL(window.location.href);\n this.deleteUrlParameters(url);\n this.setUrlParameters(url, newUrlParams);\n if (url.href.replace(/\\+/g, '%20') !== window.location.href) {\n historyMethod({ ...window.history.state }, document.title, url.href);\n }\n }\n }\n\n /**\n * Deletes all the parameters in the passed URL.\n *\n * @param url - The URL to remove parameters from.\n * @internal\n * **/\n protected deleteUrlParameters(url: URL): void {\n this.managedParamsNames.forEach(paramName =>\n url.searchParams.delete(this.getUrlKey(paramName))\n );\n }\n\n /**\n * Set all the provided parameters to the url with the mapped key.\n *\n * @param url - The current URL.\n * @param urlParams - The list of parameters to add.\n * @remarks The params are filtered because there maybe received extra params which will not be\n * managed by URL. This is defined by the `managedParamsNames` computed. Also, the parameters\n * are sorted Alphabetically to produce always the same URL with the same parameters.This is\n * important for SEO purposes.\n *\n * @internal\n * **/\n protected setUrlParameters(url: URL, urlParams: UrlParams): void {\n const filteredParams = objectFilter(urlParams, paramName =>\n this.managedParamsNames.includes(paramName as string)\n );\n const sortedParameters = this.sortParams(filteredParams);\n sortedParameters.forEach(([paramName, paramValue]) => {\n const urlParamKey = this.getUrlKey(paramName);\n if (Array.isArray(paramValue)) {\n paramValue.forEach(value => {\n url.searchParams.append(urlParamKey, String(value));\n });\n } else {\n url.searchParams.set(urlParamKey, String(paramValue));\n }\n });\n }\n\n /**\n * Sorts the params in a tuple array [key,value] to generate always the same URL with the params\n * in the same order.\n *\n * @param urlParams - The {@link UrlParams} to sort.\n * @returns An array of tuples with the key-value of each paramter, sorted by key.\n * @internal\n */\n protected sortParams(urlParams: UrlParams): Array<[string, unknown]> {\n return Object.entries(urlParams).sort(([param1], [param2]) => {\n return param1 < param2 ? -1 : 1;\n });\n }\n\n /**\n * Returns the URL param value parsed depending on its type in the initial store state. As we\n * can not know what type can have an extra param, all extra params are parsed as strings. We\n * know if it is an extra param because it is not in the initial state.\n *\n * @param name - The name of the param in {@link UrlParams}.\n * @param value - The `URLSearchParams` value as an arry of strings.\n * @returns The parsed value.\n *\n * @internal\n */\n protected parseUrlParam(name: string, value: string[]): UrlParamValue {\n switch (typeof initialUrlState[name]) {\n case 'number':\n return Number(value[0]);\n case 'boolean':\n return value[0].toLowerCase() === 'true';\n case 'string':\n return value[0];\n default:\n // array\n return value;\n }\n }\n }\n</script>\n\n<docs lang=\"mdx\">\n## Events\n\nThis component emits the following events:\n\n- [`ParamsLoadedFromUrl`](./../../api/x-components.urlxevents.paramsloadedfromurl.md)\n- [`ExtraParamsLoadedFromUrl`](./../../api/x-components.urlxevents.extraparamsloadedfromurl.md)\n- [`UserOpenXProgrammatically`](./../../api/x-components.xeventstypes.useropenxprogrammatically.md)\n\n## See it in action\n\nThis component manages the browser URL parameters to preserve them through reloads and browser\nhistory navigation. It allow to configure the default url parameter names using its attributes. This\ncomponent doesn't render elements to the DOM.\n\n_Try to make some requests and take a look to the url!_\n\n```vue\n<template>\n <UrlHandler />\n</template>\n\n<script>\n import { UrlHandler } from '@empathyco/x-components/url-handler';\n\n export default {\n name: 'UrlHandlerDemo',\n components: {\n UrlHandler\n }\n };\n</script>\n```\n\n### Play with props\n\nIn this example, the `UrlHandler` component changes the following query parameter names:\n\n- `query` to be `q`.\n- `page` to be `p`.\n- `filter` to be `f`\n- `sort` to be `s`\n\n_Try to make some requests and take a look to the url!_\n\n```vue\n<template>\n <UrlHandler query=\"q\" page=\"p\" filter=\"f\" sort=\"s\" />\n</template>\n\n<script>\n import { UrlHandler } from '@empathyco/x-components/url-handler';\n\n export default {\n name: 'UrlHandlerDemo',\n components: {\n UrlHandler\n }\n };\n</script>\n```\n\n### Play with events\n\nThe `UrlHandler` will emit the `ParamsLoadedFromUrl` when the page is loaded.\n\nThe `UrlHandler` will emit the `ExtraParamsLoadedFromUrl` when the page is loaded with an extra\nparam configured and with a value in URL.\n\nThe `UrlHandler` will emit the `UserOpenXProgrammatically` when the page is loaded with a query in\nthe URL.\n</docs>\n"],"names":["const"],"mappings":";;;;AAEAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"url-handler.vue.js","sources":["../../../../../src/x-modules/url/components/url-handler.vue"],"sourcesContent":["<template>\n <GlobalEvents @popstate=\"emitEvents\" target=\"window\" />\n</template>\n\n<script lang=\"ts\">\n import Vue from 'vue';\n import GlobalEvents from 'vue-global-events';\n import { Component } from 'vue-property-decorator';\n import { XOn } from '../../../components/decorators/bus.decorators';\n import { xComponentMixin } from '../../../components/x-component.mixin';\n import { UrlParams } from '../../../types/url-params';\n import { objectFilter } from '../../../utils/object';\n import { Dictionary } from '../../../utils/types';\n import { initialUrlState } from '../store/initial-state';\n import { UrlParamValue } from '../store/types';\n import { urlXModule } from '../x-module';\n\n interface ParsedUrlParams {\n all: UrlParams;\n extra: Dictionary<unknown>;\n }\n\n /**\n * This component manage the browser URL parameters to perserve them through reloads and browser\n * history navigation. It allow to configure the default url parameter names using its attributes.\n * This component doesn't render elements to the DOM.\n *\n * @public\n */\n @Component({\n components: {\n GlobalEvents\n },\n mixins: [xComponentMixin(urlXModule)]\n })\n export default class UrlHandler extends Vue {\n /**\n * Computed to know which params we must get from URL. It gets the params names from the initial\n * state, to get all default params names, and also from the `$attrs` to get the extra params\n * names to take into account.\n *\n * @returns An array with the name of the params.\n *\n * @internal\n */\n protected get managedParamsNames(): string[] {\n return Object.keys({ ...initialUrlState, ...this.$attrs });\n }\n\n /**\n * Returns the mapping of the param keys used in the URL is configured through $attrs. This way\n * we can support any param and extra param, no matters its name.\n *\n * @param paramName - The param name to get the Url key.\n * @returns The key used in the URL for the `paramName` passed.\n *\n * @internal\n */\n protected getUrlKey(paramName: string): string {\n return this.$attrs[paramName] ?? paramName;\n }\n\n /**\n * Flag to know if the params were already loaded from the URL.\n *\n * @internal\n */\n protected urlLoaded = false;\n\n /**\n * To emit the Url events just when the URL is load, and before the components mounted events\n * and state changes, we do it in the created of this component.\n */\n created(): void {\n this.emitEvents();\n }\n\n /**\n * Updates the browser URL with the new {@link UrlParams} using the history `pushState` method.\n *\n * @param newUrlParams - The new params to update browser URL.\n */\n @XOn('PushableUrlStateChanged')\n updateUrlWithPush(newUrlParams: UrlParams): void {\n this.updateUrl(newUrlParams, window.history.pushState.bind(window.history));\n }\n\n /**\n * Updates the browser URL with the new {@link UrlParams} using the history `replaceState`\n * method.\n *\n * @param newUrlParams - The new params to update browser URL.\n */\n @XOn('ReplaceableUrlStateChanged')\n updateUrlWithReplace(newUrlParams: UrlParams): void {\n this.updateUrl(newUrlParams, window.history.replaceState.bind(window.history));\n }\n\n /**\n * Emits the {@link UrlXEvents.ParamsLoadedFromUrl} XEvent,\n * the {@link UrlXEvents.ExtraParamsLoadedFromUrl} XEvent and, if there is query, also emits\n * the {@link XEventsTypes.UserOpenXProgrammatically}.\n *\n * @internal\n */\n protected emitEvents(): void {\n const { all, extra } = this.parseUrlParams();\n this.$x.emit('ParamsLoadedFromUrl', all, { feature: 'url' });\n this.$x.emit('ExtraParamsLoadedFromUrl', extra, { feature: 'url' });\n // TODO: Move this logic from here.\n if (all.query) {\n this.$x.emit('UserOpenXProgrammatically');\n }\n this.urlLoaded = true;\n }\n\n /**\n * Gets the {@link UrlParams} from the URL, including only the params defined by `paramsNames`.\n *\n * @returns ParsedUrlParams obtained from URL.\n * @internal\n */\n\n protected parseUrlParams(): ParsedUrlParams {\n const urlSearchParams = new URL(window.location.href).searchParams;\n return this.managedParamsNames.reduce<ParsedUrlParams>(\n (params, name) => {\n const urlKey = this.getUrlKey(name);\n if (urlSearchParams.has(urlKey)) {\n if (name in initialUrlState) {\n const urlValue = urlSearchParams.getAll(urlKey);\n params.all[name] = this.parseUrlParam(name, urlValue);\n } else {\n params.all[name] = params.extra[name] = urlSearchParams.get(urlKey);\n }\n }\n return params;\n },\n { all: { ...initialUrlState }, extra: {} }\n );\n }\n\n /**\n * Updates the browser URL with the passed `newUrlParams` and using the browser history method\n * passed as `historyMethod`. It only updates the browser history if the new URL is different\n * from the current.\n *\n * @param newUrlParams - The new params to add to the browser URL.\n * @param historyMethod - The browser history method used to add the new URL.\n *\n * @internal\n */\n protected updateUrl(\n newUrlParams: UrlParams,\n historyMethod: History['pushState'] | History['replaceState']\n ): void {\n if (this.urlLoaded) {\n const url = new URL(window.location.href);\n this.deleteUrlParameters(url);\n this.setUrlParameters(url, newUrlParams);\n if (url.href.replace(/\\+/g, '%20') !== window.location.href) {\n historyMethod({ ...window.history.state }, document.title, url.href);\n }\n }\n }\n\n /**\n * Deletes all the parameters in the passed URL.\n *\n * @param url - The URL to remove parameters from.\n * @internal\n * **/\n protected deleteUrlParameters(url: URL): void {\n this.managedParamsNames.forEach(paramName =>\n url.searchParams.delete(this.getUrlKey(paramName))\n );\n }\n\n /**\n * Set all the provided parameters to the url with the mapped key.\n *\n * @param url - The current URL.\n * @param urlParams - The list of parameters to add.\n * @remarks The params are filtered because there maybe received extra params which will not be\n * managed by URL. This is defined by the `managedParamsNames` computed. Also, the parameters\n * are sorted Alphabetically to produce always the same URL with the same parameters.This is\n * important for SEO purposes.\n *\n * @internal\n * **/\n protected setUrlParameters(url: URL, urlParams: UrlParams): void {\n const filteredParams = objectFilter(urlParams, paramName =>\n this.managedParamsNames.includes(paramName as string)\n );\n const sortedParameters = this.sortParams(filteredParams);\n sortedParameters.forEach(([paramName, paramValue]) => {\n const urlParamKey = this.getUrlKey(paramName);\n if (Array.isArray(paramValue)) {\n paramValue.forEach(value => {\n url.searchParams.append(urlParamKey, String(value));\n });\n } else {\n url.searchParams.set(urlParamKey, String(paramValue));\n }\n });\n }\n\n /**\n * Sorts the params in a tuple array [key,value] to generate always the same URL with the params\n * in the same order.\n *\n * @param urlParams - The {@link UrlParams} to sort.\n * @returns An array of tuples with the key-value of each paramter, sorted by key.\n * @internal\n */\n protected sortParams(urlParams: UrlParams): Array<[string, unknown]> {\n return Object.entries(urlParams).sort(([param1], [param2]) => {\n return param1 < param2 ? -1 : 1;\n });\n }\n\n /**\n * Returns the URL param value parsed depending on its type in the initial store state. As we\n * can not know what type can have an extra param, all extra params are parsed as strings. We\n * know if it is an extra param because it is not in the initial state.\n *\n * @param name - The name of the param in {@link UrlParams}.\n * @param value - The `URLSearchParams` value as an arry of strings.\n * @returns The parsed value.\n *\n * @internal\n */\n protected parseUrlParam(name: string, value: string[]): UrlParamValue {\n switch (typeof initialUrlState[name]) {\n case 'number':\n return Number(value[0]);\n case 'boolean':\n return value[0].toLowerCase() === 'true';\n case 'string':\n return value[0];\n default:\n // array\n return value;\n }\n }\n }\n</script>\n\n<docs lang=\"mdx\">\n## Events\n\nThis component emits the following events:\n\n- [`ParamsLoadedFromUrl`](./../../api/x-components.urlxevents.paramsloadedfromurl.md)\n- [`ExtraParamsLoadedFromUrl`](./../../api/x-components.urlxevents.extraparamsloadedfromurl.md)\n- [`UserOpenXProgrammatically`](./../../api/x-components.xeventstypes.useropenxprogrammatically.md)\n\n## See it in action\n\nThis component manages the browser URL parameters to preserve them through reloads and browser\nhistory navigation. It allow to configure the default url parameter names using its attributes. This\ncomponent doesn't render elements to the DOM.\n\n_Try to make some requests and take a look to the url!_\n\n```vue\n<template>\n <UrlHandler />\n</template>\n\n<script>\n import { UrlHandler } from '@empathyco/x-components/url-handler';\n\n export default {\n name: 'UrlHandlerDemo',\n components: {\n UrlHandler\n }\n };\n</script>\n```\n\n### Play with props\n\nIn this example, the `UrlHandler` component changes the following query parameter names:\n\n- `query` to be `q`.\n- `page` to be `p`.\n- `filter` to be `f`\n- `sort` to be `s`\n\n_Try to make some requests and take a look to the url!_\n\n```vue\n<template>\n <UrlHandler query=\"q\" page=\"p\" filter=\"f\" sort=\"s\" />\n</template>\n\n<script>\n import { UrlHandler } from '@empathyco/x-components/url-handler';\n\n export default {\n name: 'UrlHandlerDemo',\n components: {\n UrlHandler\n }\n };\n</script>\n```\n\n### Play with events\n\nThe `UrlHandler` will emit the `ParamsLoadedFromUrl` when the page is loaded.\n\nThe `UrlHandler` will emit the `ExtraParamsLoadedFromUrl` when the page is loaded with an extra\nparam configured and with a value in URL.\n\nThe `UrlHandler` will emit the `UserOpenXProgrammatically` when the page is loaded with a query in\nthe URL.\n</docs>\n"],"names":["const"],"mappings":";;;;AAEAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -89,8 +89,8 @@ var UrlHandler = /** @class */ (function (_super) {
89
89
  */
90
90
  UrlHandler.prototype.emitEvents = function () {
91
91
  var _a = this.parseUrlParams(), all = _a.all, extra = _a.extra;
92
- this.$x.emit('ParamsLoadedFromUrl', all);
93
- this.$x.emit('ExtraParamsLoadedFromUrl', extra);
92
+ this.$x.emit('ParamsLoadedFromUrl', all, { feature: 'url' });
93
+ this.$x.emit('ExtraParamsLoadedFromUrl', extra, { feature: 'url' });
94
94
  // TODO: Move this logic from here.
95
95
  if (all.query) {
96
96
  this.$x.emit('UserOpenXProgrammatically');