@miso.ai/client-sdk-ui 1.11.0-beta.1 → 1.11.0-beta.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/actor/data.js +6 -7
- package/dist/cjs/actor/feedback.js +6 -39
- package/dist/cjs/actor/fields.js +14 -6
- package/dist/cjs/actor/hub.js +1 -2
- package/dist/cjs/actor/index.js +0 -7
- package/dist/cjs/actor/interactions.js +4 -15
- package/dist/cjs/actor/sessions.js +2 -33
- package/dist/cjs/actor/tracker.js +25 -26
- package/dist/cjs/actor/utils.js +0 -49
- package/dist/cjs/actor/view.js +40 -40
- package/dist/cjs/actor/views.js +32 -8
- package/dist/cjs/asset/svgs.js +18 -8
- package/dist/cjs/constants.js +18 -19
- package/dist/cjs/defaults/hybrid-search/answer-box.js +19 -3
- package/dist/cjs/defaults/hybrid-search/phrases.js +5 -5
- package/dist/cjs/defaults/hybrid-search/templates.js +37 -9
- package/dist/cjs/element/role/index.js +12 -5
- package/dist/cjs/element/role/{miso-hits.js → miso-more.js} +4 -4
- package/dist/cjs/element/role/miso-total.js +20 -0
- package/dist/cjs/layout/affiliation/affiliation.js +0 -3
- package/dist/cjs/layout/banner/banner.js +0 -4
- package/dist/cjs/layout/button/more-button.js +73 -0
- package/dist/cjs/layout/container/container.js +0 -3
- package/dist/cjs/layout/error/error.js +0 -4
- package/dist/cjs/layout/index.js +7 -0
- package/dist/cjs/layout/input/facets.js +5 -5
- package/dist/cjs/layout/input/option-list.js +0 -4
- package/dist/cjs/layout/input/search-box.js +33 -12
- package/dist/cjs/layout/list/cards.js +0 -3
- package/dist/cjs/layout/list/carousel.js +0 -3
- package/dist/cjs/layout/list/collection.js +25 -7
- package/dist/cjs/layout/list/list.js +0 -3
- package/dist/cjs/layout/radio/feedback.js +0 -3
- package/dist/cjs/layout/radio/radio.js +0 -4
- package/dist/cjs/layout/raf.js +4 -2
- package/dist/cjs/layout/text/text.js +0 -4
- package/dist/cjs/layout/text/typewriter/index.js +0 -3
- package/dist/cjs/layout/triggerable.js +79 -0
- package/dist/cjs/util/states.js +0 -15
- package/dist/cjs/version.js +1 -1
- package/dist/cjs/workflow/answer-based.js +109 -111
- package/dist/cjs/workflow/ask.js +35 -27
- package/dist/cjs/workflow/asks.js +1 -1
- package/dist/cjs/workflow/autocompletable.js +33 -0
- package/dist/cjs/workflow/autocomplete.js +122 -0
- package/dist/cjs/workflow/base.js +169 -102
- package/dist/cjs/workflow/explore.js +26 -19
- package/dist/cjs/workflow/hybrid-search-answer.js +99 -0
- package/dist/cjs/workflow/hybrid-search-results.js +70 -0
- package/dist/cjs/workflow/hybrid-search-views.js +122 -0
- package/dist/cjs/workflow/hybrid-search.js +98 -103
- package/dist/cjs/workflow/options.js +32 -17
- package/dist/cjs/workflow/processors.js +185 -17
- package/dist/cjs/workflow/recommendation.js +36 -49
- package/dist/cjs/workflow/search-based.js +186 -0
- package/dist/cjs/workflow/search.js +21 -68
- package/package.json +2 -2
- package/src/actor/data.js +2 -4
- package/src/actor/feedback.js +6 -23
- package/src/actor/fields.js +14 -6
- package/src/actor/hub.js +1 -2
- package/src/actor/index.js +0 -1
- package/src/actor/interactions.js +4 -10
- package/src/actor/sessions.js +3 -30
- package/src/actor/tracker.js +25 -19
- package/src/actor/utils.js +0 -47
- package/src/actor/view.js +27 -15
- package/src/actor/views.js +36 -8
- package/src/asset/svgs.js +19 -7
- package/src/constants.js +25 -16
- package/src/defaults/hybrid-search/answer-box.js +17 -5
- package/src/defaults/hybrid-search/phrases.js +4 -4
- package/src/defaults/hybrid-search/templates.js +25 -9
- package/src/element/role/index.js +2 -1
- package/src/element/role/{miso-hits.js → miso-more.js} +3 -3
- package/src/element/role/miso-total.js +16 -0
- package/src/layout/affiliation/affiliation.js +1 -5
- package/src/layout/banner/banner.js +0 -5
- package/src/layout/button/more-button.js +69 -0
- package/src/layout/container/container.js +1 -5
- package/src/layout/error/error.js +0 -5
- package/src/layout/index.js +2 -1
- package/src/layout/input/facets.js +5 -6
- package/src/layout/input/option-list.js +0 -5
- package/src/layout/input/search-box.js +27 -14
- package/src/layout/list/cards.js +0 -4
- package/src/layout/list/carousel.js +0 -4
- package/src/layout/list/collection.js +22 -9
- package/src/layout/list/list.js +0 -4
- package/src/layout/radio/feedback.js +0 -4
- package/src/layout/radio/radio.js +0 -5
- package/src/layout/raf.js +2 -2
- package/src/layout/text/text.js +0 -5
- package/src/layout/text/typewriter/index.js +1 -5
- package/src/layout/trackable.js +1 -1
- package/src/layout/triggerable.js +76 -0
- package/src/util/states.js +0 -14
- package/src/version.js +1 -1
- package/src/workflow/answer-based.js +101 -77
- package/src/workflow/ask.js +33 -25
- package/src/workflow/asks.js +1 -1
- package/src/workflow/autocompletable.js +29 -0
- package/src/workflow/autocomplete.js +113 -0
- package/src/workflow/base.js +147 -93
- package/src/workflow/explore.js +23 -8
- package/src/workflow/hybrid-search-answer.js +92 -0
- package/src/workflow/hybrid-search-results.js +63 -0
- package/src/workflow/hybrid-search-views.js +124 -0
- package/src/workflow/hybrid-search.js +102 -73
- package/src/workflow/options.js +26 -11
- package/src/workflow/processors.js +165 -14
- package/src/workflow/recommendation.js +32 -33
- package/src/workflow/search-based.js +183 -0
- package/src/workflow/search.js +21 -65
- package/dist/cjs/actor/autocomplete.js +0 -160
- package/dist/cjs/workflow/utils.js +0 -42
- package/src/actor/autocomplete.js +0 -133
- package/src/workflow/utils.js +0 -29
package/src/asset/svgs.js
CHANGED
|
@@ -10,12 +10,18 @@ function trianglePath(r) {
|
|
|
10
10
|
const PREFIX = 'miso-ui-icon';
|
|
11
11
|
const ID = `${PREFIX}-svg-${version.replaceAll('.', '_')}`;
|
|
12
12
|
|
|
13
|
+
const ICON_NAME = {
|
|
14
|
+
SEND: 'send',
|
|
15
|
+
SEARCH: 'search',
|
|
16
|
+
TRIANGLE: 'triangle',
|
|
17
|
+
};
|
|
18
|
+
|
|
13
19
|
// CC0 SVGs
|
|
14
|
-
const ICON_SEND = `<symbol id="${PREFIX}
|
|
15
|
-
const ICON_SEARCH = `<symbol id="${PREFIX}
|
|
20
|
+
const ICON_SEND = `<symbol id="${PREFIX}-${ICON_NAME.SEND}" viewBox="0 0 32 32"><path fill="currentColor" d="M11.499,19.173l5.801,-5.849c0.389,-0.392 1.022,-0.394 1.414,-0.006c0.392,0.389 0.395,1.022 0.006,1.414l-5.798,5.847l5.306,8.002c0.207,0.313 0.572,0.483 0.945,0.441c0.373,-0.042 0.691,-0.289 0.824,-0.64l9.024,-23.904c0.138,-0.366 0.05,-0.78 -0.226,-1.058c-0.276,-0.278 -0.689,-0.369 -1.057,-0.233l-24.004,8.892c-0.353,0.13 -0.602,0.448 -0.646,0.821c-0.044,0.373 0.125,0.74 0.438,0.948l7.973,5.325Z"/></symbol>`;
|
|
21
|
+
const ICON_SEARCH = `<symbol id="${PREFIX}-${ICON_NAME.SEARCH}" viewBox="0 0 24 24"><path fill="currentColor" d="M4 11C4 7.13401 7.13401 4 11 4C14.866 4 18 7.13401 18 11C18 14.866 14.866 18 11 18C7.13401 18 4 14.866 4 11ZM11 2C6.02944 2 2 6.02944 2 11C2 15.9706 6.02944 20 11 20C13.125 20 15.078 19.2635 16.6177 18.0319L20.2929 21.7071C20.6834 22.0976 21.3166 22.0976 21.7071 21.7071C22.0976 21.3166 22.0976 20.6834 21.7071 20.2929L18.0319 16.6177C19.2635 15.078 20 13.125 20 11C20 6.02944 15.9706 2 11 2Z"/></symbol>`;
|
|
16
22
|
|
|
17
23
|
// Custom SVGs
|
|
18
|
-
const ICON_TRIANGLE = `<symbol id="${PREFIX}
|
|
24
|
+
const ICON_TRIANGLE = `<symbol id="${PREFIX}-${ICON_NAME.TRIANGLE}" viewBox="-5 -5 105 105"><path d="${trianglePath(5)}"/></symbol>`;
|
|
19
25
|
|
|
20
26
|
const ICONS = [ICON_SEND, ICON_SEARCH, ICON_TRIANGLE];
|
|
21
27
|
|
|
@@ -33,10 +39,16 @@ function loadSvgSprites() {
|
|
|
33
39
|
|
|
34
40
|
loadSvgSprites();
|
|
35
41
|
|
|
36
|
-
function
|
|
42
|
+
function _icon(name) {
|
|
37
43
|
return `<svg class="miso-ui-icon miso-ui-icon-${name}"><use href="#${PREFIX}-${name}"></use></svg>`;
|
|
38
44
|
}
|
|
39
45
|
|
|
40
|
-
export const
|
|
41
|
-
|
|
42
|
-
export
|
|
46
|
+
export const ICON_NAMES = new Set(Object.values(ICON_NAME));
|
|
47
|
+
|
|
48
|
+
export function getIcon(name) {
|
|
49
|
+
return ICON_NAMES.has(name) ? _icon(name) : '';
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export const SEND = _icon(ICON_NAME.SEND);
|
|
53
|
+
export const SEARCH = _icon(ICON_NAME.SEARCH);
|
|
54
|
+
export const TRIANGLE = _icon(ICON_NAME.TRIANGLE);
|
package/src/constants.js
CHANGED
|
@@ -22,7 +22,8 @@ export const ROLE = Object.freeze({
|
|
|
22
22
|
AFFILIATION: 'affiliation',
|
|
23
23
|
KEYWORDS: 'keywords',
|
|
24
24
|
FACETS: 'facets',
|
|
25
|
-
|
|
25
|
+
TOTAL: 'total',
|
|
26
|
+
MORE: 'more',
|
|
26
27
|
ERROR: 'error',
|
|
27
28
|
});
|
|
28
29
|
|
|
@@ -40,34 +41,29 @@ const DATA_ROLE_SET = new Set([
|
|
|
40
41
|
ROLE.RELATED_QUESTIONS,
|
|
41
42
|
ROLE.AFFILIATION,
|
|
42
43
|
ROLE.FACETS,
|
|
43
|
-
ROLE.
|
|
44
|
+
ROLE.TOTAL,
|
|
44
45
|
]);
|
|
45
46
|
|
|
46
47
|
export function isDataRole(role) {
|
|
47
48
|
return DATA_ROLE_SET.has(role);
|
|
48
49
|
}
|
|
49
50
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
51
|
+
const PRODUCT_ROLE_SET = new Set([
|
|
52
|
+
ROLE.PRODUCTS,
|
|
53
|
+
ROLE.SOURCES,
|
|
54
|
+
ROLE.RELATED_RESOURCES,
|
|
55
|
+
]);
|
|
53
56
|
|
|
54
|
-
export
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
LIST: 'list',
|
|
58
|
-
QUERY: 'query',
|
|
59
|
-
RADIO: 'radio',
|
|
60
|
-
FILTERS: 'filters',
|
|
61
|
-
TEXT: 'text',
|
|
62
|
-
AFFILIATION: 'affiliation',
|
|
63
|
-
ERROR: 'error',
|
|
64
|
-
});
|
|
57
|
+
export function isProductRole(role) {
|
|
58
|
+
return PRODUCT_ROLE_SET.has(role);
|
|
59
|
+
}
|
|
65
60
|
|
|
66
61
|
export const EVENT_TYPE = Object.freeze({
|
|
67
62
|
IMPRESSION: 'impression',
|
|
68
63
|
VIEWABLE: 'viewable',
|
|
69
64
|
CLICK: 'click',
|
|
70
65
|
SUBMIT: 'submit',
|
|
66
|
+
FEEDBACK: 'feedback',
|
|
71
67
|
});
|
|
72
68
|
|
|
73
69
|
export const TRACKING_EVENT_TYPES = [
|
|
@@ -75,8 +71,21 @@ export const TRACKING_EVENT_TYPES = [
|
|
|
75
71
|
EVENT_TYPE.VIEWABLE,
|
|
76
72
|
EVENT_TYPE.CLICK,
|
|
77
73
|
EVENT_TYPE.SUBMIT,
|
|
74
|
+
EVENT_TYPE.FEEDBACK,
|
|
75
|
+
];
|
|
76
|
+
|
|
77
|
+
export const PERFORMANCE_EVENT_TYPES = [
|
|
78
|
+
EVENT_TYPE.IMPRESSION,
|
|
79
|
+
EVENT_TYPE.VIEWABLE,
|
|
80
|
+
EVENT_TYPE.CLICK,
|
|
78
81
|
];
|
|
79
82
|
|
|
83
|
+
const PERFORMANCE_EVENT_TYPE_SET = new Set(PERFORMANCE_EVENT_TYPES);
|
|
84
|
+
|
|
85
|
+
export function isPerformanceEventType(type) {
|
|
86
|
+
return PERFORMANCE_EVENT_TYPE_SET.has(type);
|
|
87
|
+
}
|
|
88
|
+
|
|
80
89
|
export const TRACKING_STATUS = Object.freeze({
|
|
81
90
|
UNTRACKED: 'untracked',
|
|
82
91
|
TRACKING: 'tracking',
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { CLASS_PREFIX } from './constants.js';
|
|
2
2
|
import { STATUS } from '../../constants.js';
|
|
3
|
+
import { fields } from '../../actor/index.js';
|
|
3
4
|
import { showMore as DEFAULT_PHRASE_SHOW_MORE, showLess as DEFAULT_PHRASE_SHOW_LESS } from './phrases.js';
|
|
4
5
|
|
|
5
6
|
const CLASS_OPEN = 'answer-box-open';
|
|
@@ -23,7 +24,12 @@ export default class AnswerBox {
|
|
|
23
24
|
|
|
24
25
|
// expose widget API
|
|
25
26
|
workflow.answerBox = this;
|
|
26
|
-
workflow._unsubscribes.push(() =>
|
|
27
|
+
workflow._unsubscribes.push(() => {
|
|
28
|
+
if (workflow.answerBox === this) {
|
|
29
|
+
this.destroy();
|
|
30
|
+
workflow.answerBox = undefined;
|
|
31
|
+
}
|
|
32
|
+
});
|
|
27
33
|
|
|
28
34
|
// handle toggle button clicks
|
|
29
35
|
const callback = event => this._handleClick(event);
|
|
@@ -35,9 +41,8 @@ export default class AnswerBox {
|
|
|
35
41
|
|
|
36
42
|
this._unsubscribes = [
|
|
37
43
|
() => element.removeEventListener('click', callback),
|
|
38
|
-
|
|
39
|
-
workflow.on(
|
|
40
|
-
workflow.on('ready', () => this.show()),
|
|
44
|
+
// cling to data rather than view, as we may miss view event when tab is inactive due to raf
|
|
45
|
+
workflow._answer._hub.on(fields.data(), () => this._syncWofkflowStatus()),
|
|
41
46
|
];
|
|
42
47
|
}
|
|
43
48
|
|
|
@@ -52,7 +57,7 @@ export default class AnswerBox {
|
|
|
52
57
|
}
|
|
53
58
|
|
|
54
59
|
_syncWofkflowStatus() {
|
|
55
|
-
const { status } = this._workflow;
|
|
60
|
+
const { status } = this._workflow._answer;
|
|
56
61
|
switch (status) {
|
|
57
62
|
case STATUS.ERRONEOUS:
|
|
58
63
|
case STATUS.READY:
|
|
@@ -74,6 +79,12 @@ export default class AnswerBox {
|
|
|
74
79
|
}
|
|
75
80
|
}
|
|
76
81
|
|
|
82
|
+
_syncScroll() {
|
|
83
|
+
if (!this.isOpen) {
|
|
84
|
+
this._element.scrollIntoView({ behavior: 'smooth' });
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
77
88
|
destroy() {
|
|
78
89
|
for (const unsubscribe of this._unsubscribes) {
|
|
79
90
|
unsubscribe();
|
|
@@ -113,6 +124,7 @@ for (const [method, [action, className]] of Object.entries(METHODS)) {
|
|
|
113
124
|
this._updateBoxStatus(action, className);
|
|
114
125
|
if (className === CLASS_OPEN) {
|
|
115
126
|
this._syncButtonText();
|
|
127
|
+
this._syncScroll();
|
|
116
128
|
}
|
|
117
129
|
};
|
|
118
130
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* The phrase
|
|
2
|
+
* The phrase to display <miso-question>
|
|
3
3
|
*/
|
|
4
|
-
export const question = 'You asked
|
|
4
|
+
export const question = 'You asked “${value}”';
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* The phrase displayed right before <miso-sources>
|
|
@@ -14,9 +14,9 @@ export const sources = 'Sources';
|
|
|
14
14
|
export const keywords = 'You searched for “${value}”';
|
|
15
15
|
|
|
16
16
|
/**
|
|
17
|
-
* The phrase to display <miso-
|
|
17
|
+
* The phrase to display <miso-total>
|
|
18
18
|
*/
|
|
19
|
-
export const
|
|
19
|
+
export const total = '${value} Results';
|
|
20
20
|
|
|
21
21
|
export const showMore = 'Show more';
|
|
22
22
|
export const showLess = 'Show less';
|
|
@@ -18,6 +18,11 @@ class Sections extends _Sections {
|
|
|
18
18
|
]);
|
|
19
19
|
}
|
|
20
20
|
|
|
21
|
+
question(options) {
|
|
22
|
+
const { phrase } = this._helpers;
|
|
23
|
+
return phrase(options, { name: 'question', tag: 'div' }).replaceAll('${value}', '<miso-question></miso-question>');
|
|
24
|
+
}
|
|
25
|
+
|
|
21
26
|
answerBoxToggle(options) {
|
|
22
27
|
const { element } = this._helpers;
|
|
23
28
|
const { classPrefix } = options;
|
|
@@ -28,10 +33,11 @@ class Sections extends _Sections {
|
|
|
28
33
|
|
|
29
34
|
searchResultsGroup(options) {
|
|
30
35
|
const { container } = this._helpers;
|
|
31
|
-
return container(options, { name: 'search-results', visibleWhen: 'ready' }, [
|
|
36
|
+
return container(options, { name: 'search-results', visibleWhen: 'loading ready' }, [
|
|
32
37
|
this.searchResultsInfoGroup(options),
|
|
33
38
|
this.searchResultsFilters(options),
|
|
34
39
|
'<miso-products></miso-products>',
|
|
40
|
+
this.more(options),
|
|
35
41
|
]);
|
|
36
42
|
}
|
|
37
43
|
|
|
@@ -40,7 +46,7 @@ class Sections extends _Sections {
|
|
|
40
46
|
const { classPrefix } = options;
|
|
41
47
|
return element('div', { classes: [`${classPrefix}__search-results-info`] }, [
|
|
42
48
|
this.keywords(options),
|
|
43
|
-
this.
|
|
49
|
+
this.total(options),
|
|
44
50
|
]);
|
|
45
51
|
}
|
|
46
52
|
|
|
@@ -57,9 +63,20 @@ class Sections extends _Sections {
|
|
|
57
63
|
return phrase(options, { name: 'keywords', tag: 'div', inline: true }).replaceAll('${value}', '<miso-keywords></miso-keywords>');
|
|
58
64
|
}
|
|
59
65
|
|
|
60
|
-
|
|
66
|
+
total(options) {
|
|
61
67
|
const { phrase } = this._helpers;
|
|
62
|
-
return phrase(options, { name: '
|
|
68
|
+
return phrase(options, { name: 'total', tag: 'div', inline: true }).replaceAll('${value}', '<miso-total></miso-total>');
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
more(options) {
|
|
72
|
+
if (!options.moreButton) {
|
|
73
|
+
return '';
|
|
74
|
+
}
|
|
75
|
+
const { element } = this._helpers;
|
|
76
|
+
const { classPrefix } = options;
|
|
77
|
+
return element('div', { classes: [`${classPrefix}__search-results-more-container`] }, [
|
|
78
|
+
'<miso-more></miso-more>',
|
|
79
|
+
]);
|
|
63
80
|
}
|
|
64
81
|
|
|
65
82
|
}
|
|
@@ -70,14 +87,13 @@ export const sections = externalize(new Sections({ helpers }));
|
|
|
70
87
|
export function root(options = {}) {
|
|
71
88
|
const { normalizeOptions, section, container } = helpers;
|
|
72
89
|
options = normalizeOptions(options);
|
|
73
|
-
const { answerBox } = sections;
|
|
90
|
+
const { answerBox, answerGroup, searchResultsGroup } = sections;
|
|
91
|
+
const { answerBox: answerBoxOptions = true } = options;
|
|
74
92
|
return [
|
|
75
93
|
section(options, { name: 'question' }, [
|
|
76
94
|
container(options, { name: 'query' }, '<miso-query></miso-query>'),
|
|
77
95
|
]),
|
|
78
|
-
section(options, { name: 'answer' }, [
|
|
79
|
-
|
|
80
|
-
]),
|
|
81
|
-
section(options, { name: 'search-results' }, sections.searchResultsGroup(options)),
|
|
96
|
+
section(options, { name: 'answer' }, answerBoxOptions ? [ answerBox(options) ] : answerGroup(options)),
|
|
97
|
+
section(options, { name: 'search-results' }, searchResultsGroup(options)),
|
|
82
98
|
].join('');
|
|
83
99
|
};
|
|
@@ -11,6 +11,7 @@ export { default as MisoRelatedResourcesElement } from './miso-related-resources
|
|
|
11
11
|
export { default as MisoRelatedQuestionsElement } from './miso-related-questions.js';
|
|
12
12
|
export { default as MisoSovrnAffiliationElement } from './miso-affiliation.js';
|
|
13
13
|
export { default as MisoKeywordsElement } from './miso-keywords.js';
|
|
14
|
-
export { default as
|
|
14
|
+
export { default as MisoTotalElement } from './miso-total.js';
|
|
15
15
|
export { default as MisoFacetsElement } from './miso-facets.js';
|
|
16
|
+
export { default as MisoMoreElement } from './miso-more.js';
|
|
16
17
|
export { default as MisoErrorElement } from './miso-error.js';
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
import MisoComponentElement from './miso-component.js';
|
|
2
2
|
import { ROLE } from '../../constants.js';
|
|
3
3
|
|
|
4
|
-
export default class
|
|
4
|
+
export default class MisoMoreElement extends MisoComponentElement {
|
|
5
5
|
|
|
6
6
|
constructor() {
|
|
7
7
|
super({
|
|
8
|
-
role: ROLE.
|
|
8
|
+
role: ROLE.MORE,
|
|
9
9
|
});
|
|
10
10
|
}
|
|
11
11
|
|
|
12
12
|
static get tagName() {
|
|
13
|
-
return 'miso-
|
|
13
|
+
return 'miso-more';
|
|
14
14
|
}
|
|
15
15
|
|
|
16
16
|
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import MisoComponentElement from './miso-component.js';
|
|
2
|
+
import { ROLE } from '../../constants.js';
|
|
3
|
+
|
|
4
|
+
export default class MisoTotalElement extends MisoComponentElement {
|
|
5
|
+
|
|
6
|
+
constructor() {
|
|
7
|
+
super({
|
|
8
|
+
role: ROLE.TOTAL,
|
|
9
|
+
});
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
static get tagName() {
|
|
13
|
+
return 'miso-total';
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { CarouselItemViewabilityObserver, requestAnimationFrame as raf } from '@miso.ai/commons';
|
|
2
|
-
import { STATUS
|
|
2
|
+
import { STATUS } from '../../constants.js';
|
|
3
3
|
import CollectionLayout from '../list/collection.js';
|
|
4
4
|
import { affiliation, helpers } from '../templates.js';
|
|
5
5
|
import { TRIANGLE } from '../../asset/svgs.js';
|
|
@@ -136,10 +136,6 @@ function autoplayOptionsEquals(a, b) {
|
|
|
136
136
|
|
|
137
137
|
export default class AffiliationLayout extends CollectionLayout {
|
|
138
138
|
|
|
139
|
-
static get category() {
|
|
140
|
-
return LAYOUT_CATEGORY.AFFILIATION;
|
|
141
|
-
}
|
|
142
|
-
|
|
143
139
|
static get type() {
|
|
144
140
|
return TYPE;
|
|
145
141
|
}
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { LAYOUT_CATEGORY } from '../../constants.js';
|
|
2
1
|
import TemplateBasedLayout from '../template.js';
|
|
3
2
|
import { LOGO } from '../svgs.js';
|
|
4
3
|
|
|
@@ -19,10 +18,6 @@ const DEFAULT_TEMPLATES = Object.freeze({
|
|
|
19
18
|
|
|
20
19
|
export default class BannerLayout extends TemplateBasedLayout {
|
|
21
20
|
|
|
22
|
-
static get category() {
|
|
23
|
-
return LAYOUT_CATEGORY.BANNER;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
21
|
static get type() {
|
|
27
22
|
return TYPE;
|
|
28
23
|
}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { STATUS } from '../../constants.js';
|
|
2
|
+
import { fields } from '../../actor/index.js';
|
|
3
|
+
import TemplateBasedLayout from '../template.js';
|
|
4
|
+
|
|
5
|
+
const TYPE = 'more-button';
|
|
6
|
+
const DEFAULT_CLASSNAME = 'miso-more-button';
|
|
7
|
+
|
|
8
|
+
function root(layout, state) {
|
|
9
|
+
const { className, role, templates } = layout;
|
|
10
|
+
const roleAttr = role ? ` data-role="${role}"` : '';
|
|
11
|
+
const disabledAttr = state.status !== STATUS.READY ? ' disabled' : '';
|
|
12
|
+
return `
|
|
13
|
+
<div class="${className}"${roleAttr}${disabledAttr}>
|
|
14
|
+
${templates.text(layout)}
|
|
15
|
+
</div>
|
|
16
|
+
`;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const DEFAULT_TEMPLATES = Object.freeze({
|
|
20
|
+
root,
|
|
21
|
+
text,
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
function text(layout) {
|
|
25
|
+
return 'More';
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export default class MoreButtonLayout extends TemplateBasedLayout {
|
|
29
|
+
|
|
30
|
+
static get type() {
|
|
31
|
+
return TYPE;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
static get defaultTemplates() {
|
|
35
|
+
return DEFAULT_TEMPLATES;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
static get defaultClassName() {
|
|
39
|
+
return DEFAULT_CLASSNAME;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
constructor({ className = DEFAULT_CLASSNAME, templates, ...options } = {}) {
|
|
43
|
+
super({
|
|
44
|
+
className,
|
|
45
|
+
templates: { ...DEFAULT_TEMPLATES, ...templates },
|
|
46
|
+
...options,
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
initialize(view) {
|
|
51
|
+
this._unsubscribes = [
|
|
52
|
+
...this._unsubscribes,
|
|
53
|
+
view.proxyElement.on('click', (e) => this._handleClick(e)),
|
|
54
|
+
];
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
_handleClick(event) {
|
|
58
|
+
// only left click
|
|
59
|
+
if (event.button !== 0) {
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
const button = event.target.closest('data-role="more"');
|
|
63
|
+
if (!button || button.disabled) {
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
this._view.hub.trigger(fields.more());
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ROLE, STATUS
|
|
1
|
+
import { ROLE, STATUS } from '../../constants.js';
|
|
2
2
|
import RafLayout from '../raf.js';
|
|
3
3
|
import MisoBannerElement from '../../element/miso-banner.js';
|
|
4
4
|
import Viewables from '../../util/viewables.js';
|
|
@@ -7,10 +7,6 @@ const TYPE = 'container';
|
|
|
7
7
|
|
|
8
8
|
export default class ContainerLayout extends RafLayout {
|
|
9
9
|
|
|
10
|
-
static get category() {
|
|
11
|
-
return LAYOUT_CATEGORY.CONTAINER;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
10
|
static get type() {
|
|
15
11
|
return TYPE;
|
|
16
12
|
}
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { LAYOUT_CATEGORY } from '../../constants.js';
|
|
2
1
|
import TemplateBasedLayout from '../template.js';
|
|
3
2
|
|
|
4
3
|
const TYPE = 'error';
|
|
@@ -24,10 +23,6 @@ const DEFAULT_TEMPLATES = Object.freeze({
|
|
|
24
23
|
|
|
25
24
|
export default class ErrorLayout extends TemplateBasedLayout {
|
|
26
25
|
|
|
27
|
-
static get category() {
|
|
28
|
-
return LAYOUT_CATEGORY.ERROR;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
26
|
static get type() {
|
|
32
27
|
return TYPE;
|
|
33
28
|
}
|
package/src/layout/index.js
CHANGED
|
@@ -12,4 +12,5 @@ export { default as FeedbackLayout } from './radio/feedback.js';
|
|
|
12
12
|
export { default as TextLayout } from './text/text.js';
|
|
13
13
|
export { default as TypewriterLayout } from './text/typewriter/index.js';
|
|
14
14
|
export { default as AffiliationLayout } from './affiliation/affiliation.js';
|
|
15
|
-
export { default as FacetsLayout } from './input/facets.js';
|
|
15
|
+
export { default as FacetsLayout } from './input/facets.js';
|
|
16
|
+
export { default as MoreButtonLayout } from './button/more-button.js';
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { escapeHtml } from '@miso.ai/commons';
|
|
2
|
-
import { LAYOUT_CATEGORY } from '../../constants.js';
|
|
3
2
|
import TemplateBasedLayout from '../template.js';
|
|
4
3
|
import Bindings from '../../util/bindings.js';
|
|
5
4
|
|
|
@@ -88,10 +87,6 @@ function getSelectedValues(facets) {
|
|
|
88
87
|
|
|
89
88
|
export default class FacetsLayout extends TemplateBasedLayout {
|
|
90
89
|
|
|
91
|
-
static get category() {
|
|
92
|
-
return LAYOUT_CATEGORY.FILTERS;
|
|
93
|
-
}
|
|
94
|
-
|
|
95
90
|
static get type() {
|
|
96
91
|
return TYPE;
|
|
97
92
|
}
|
|
@@ -125,11 +120,11 @@ export default class FacetsLayout extends TemplateBasedLayout {
|
|
|
125
120
|
|
|
126
121
|
_render(element, data, controls) {
|
|
127
122
|
super._render(element, data, controls);
|
|
128
|
-
this._syncSelections();
|
|
129
123
|
}
|
|
130
124
|
|
|
131
125
|
_afterRender(element, state) {
|
|
132
126
|
this._syncBindings(element, state);
|
|
127
|
+
this._syncSelections();
|
|
133
128
|
}
|
|
134
129
|
|
|
135
130
|
_unrender() {
|
|
@@ -220,6 +215,10 @@ export default class FacetsLayout extends TemplateBasedLayout {
|
|
|
220
215
|
}
|
|
221
216
|
|
|
222
217
|
_handleClick(event) {
|
|
218
|
+
// only left click
|
|
219
|
+
if (event.button !== 0) {
|
|
220
|
+
return;
|
|
221
|
+
}
|
|
223
222
|
const element = event.target.closest(`[data-role="option"]`);
|
|
224
223
|
if (!element) {
|
|
225
224
|
return;
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { escapeHtml } from '@miso.ai/commons';
|
|
2
|
-
import { LAYOUT_CATEGORY } from '../../constants.js';
|
|
3
2
|
import { fields } from '../../actor/index.js';
|
|
4
3
|
import TemplateBasedLayout from '../template.js';
|
|
5
4
|
import { makeTrackable } from '../trackable.js';
|
|
@@ -41,10 +40,6 @@ const DEFAULT_TEMPLATES = Object.freeze({
|
|
|
41
40
|
|
|
42
41
|
export default class OptionListLayout extends TemplateBasedLayout {
|
|
43
42
|
|
|
44
|
-
static get category() {
|
|
45
|
-
return LAYOUT_CATEGORY.QUERY;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
43
|
static get type() {
|
|
49
44
|
return TYPE;
|
|
50
45
|
}
|
|
@@ -1,29 +1,39 @@
|
|
|
1
1
|
import { defineValues, escapeHtml, findInAncestors, debounce } from '@miso.ai/commons';
|
|
2
|
-
import {
|
|
2
|
+
import { STATUS, EVENT_TYPE } from '../../constants.js';
|
|
3
3
|
import { fields } from '../../actor/index.js';
|
|
4
4
|
import TemplateBasedLayout from '../template.js';
|
|
5
5
|
import { imageBlock, productInfoBlock } from '../templates.js';
|
|
6
|
-
import {
|
|
6
|
+
import { getIcon } from '../../asset/svgs.js';
|
|
7
7
|
|
|
8
8
|
const TYPE = 'search-box';
|
|
9
9
|
const DEFAULT_CLASSNAME = 'miso-search-box';
|
|
10
10
|
const DEFAULT_AUTOCOMPLETE_CLASSNAME = 'miso-autocomplete';
|
|
11
11
|
|
|
12
12
|
function root(layout) {
|
|
13
|
-
const { className, role, options,
|
|
14
|
-
const { placeholder
|
|
13
|
+
const { className, templates, role, options, autocomplete } = layout;
|
|
14
|
+
const { placeholder } = options;
|
|
15
15
|
const roleAttr = role ? `data-role="${role}"` : '';
|
|
16
|
-
const buttonContent = buttonText || workflow === 'search' ? SEARCH : SEND;
|
|
17
16
|
return `
|
|
18
17
|
<div class="${className}" ${roleAttr}>
|
|
19
18
|
<div class="${className}__input-group">
|
|
20
19
|
<input class="${className}__input" type="text" data-role="input" ${placeholder ? `placeholder="${placeholder}"` : ''}>
|
|
21
|
-
<button class="${className}__button" type="submit" data-role="submit">${buttonContent}</button>
|
|
20
|
+
<button class="${className}__button" type="submit" data-role="submit">${templates.buttonContent(layout)}</button>
|
|
22
21
|
</div>
|
|
23
22
|
<div class="${autocomplete.className}" data-role="autocomplete"></div>
|
|
24
23
|
</div>`.trim();
|
|
25
24
|
}
|
|
26
25
|
|
|
26
|
+
function buttonContent(layout) {
|
|
27
|
+
const { templates, options } = layout;
|
|
28
|
+
if (options.buttonText) {
|
|
29
|
+
return options.buttonText; // legacy
|
|
30
|
+
}
|
|
31
|
+
const { buttonText, buttonIcon } = templates;
|
|
32
|
+
const text = typeof buttonText === 'function' ? buttonText(layout) : `${buttonText}`;
|
|
33
|
+
const icon = typeof buttonIcon === 'function' ? buttonIcon(layout) : (getIcon(buttonIcon) || `${buttonIcon}`);
|
|
34
|
+
return text + icon;
|
|
35
|
+
}
|
|
36
|
+
|
|
27
37
|
function completions(layout, items) {
|
|
28
38
|
const { templates, workflow, autocomplete } = layout;
|
|
29
39
|
// use options under layout.autocomplete from now on
|
|
@@ -84,6 +94,9 @@ function completionItem(layout, type, item) {
|
|
|
84
94
|
|
|
85
95
|
const DEFAULT_TEMPLATES = Object.freeze({
|
|
86
96
|
root,
|
|
97
|
+
buttonContent,
|
|
98
|
+
buttonText: '',
|
|
99
|
+
buttonIcon: 'search',
|
|
87
100
|
completions,
|
|
88
101
|
completionList,
|
|
89
102
|
completionItem,
|
|
@@ -102,10 +115,6 @@ const DEFAULT_AUTOCOMPLETE_OPTIONS = Object.freeze({
|
|
|
102
115
|
|
|
103
116
|
export default class SearchBoxLayout extends TemplateBasedLayout {
|
|
104
117
|
|
|
105
|
-
static get category() {
|
|
106
|
-
return LAYOUT_CATEGORY.QUERY;
|
|
107
|
-
}
|
|
108
|
-
|
|
109
118
|
static get type() {
|
|
110
119
|
return TYPE;
|
|
111
120
|
}
|
|
@@ -141,7 +150,7 @@ export default class SearchBoxLayout extends TemplateBasedLayout {
|
|
|
141
150
|
proxyElement.on('click', (e) => this._handleClick(e)),
|
|
142
151
|
proxyElement.on('focusin', (e) => this._handleFocusIn(e)),
|
|
143
152
|
proxyElement.on('focusout', (e) => this._handleFocusOut(e)),
|
|
144
|
-
hub.on(fields.
|
|
153
|
+
hub.on(fields.completions(), () => view.refresh({ force: true })),
|
|
145
154
|
];
|
|
146
155
|
}
|
|
147
156
|
|
|
@@ -175,7 +184,7 @@ export default class SearchBoxLayout extends TemplateBasedLayout {
|
|
|
175
184
|
state = super._preprocess({ state });
|
|
176
185
|
return {
|
|
177
186
|
...state,
|
|
178
|
-
completions: this._view.hub.states[fields.
|
|
187
|
+
completions: this._view.hub.states[fields.completions()],
|
|
179
188
|
};
|
|
180
189
|
}
|
|
181
190
|
|
|
@@ -185,6 +194,9 @@ export default class SearchBoxLayout extends TemplateBasedLayout {
|
|
|
185
194
|
super._render(element, data, controls);
|
|
186
195
|
}
|
|
187
196
|
this._updateCompletions(element, data, controls);
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
_afterRender(element, state) {
|
|
188
200
|
this._fullfillFocusRequest(element);
|
|
189
201
|
this._fullfillValueRequest(element);
|
|
190
202
|
}
|
|
@@ -193,7 +205,8 @@ export default class SearchBoxLayout extends TemplateBasedLayout {
|
|
|
193
205
|
if (!state.completions) {
|
|
194
206
|
return;
|
|
195
207
|
}
|
|
196
|
-
const { status = STATUS.INITIAL,
|
|
208
|
+
const { status = STATUS.INITIAL, session, value: completions } = state.completions;
|
|
209
|
+
const { index } = session;
|
|
197
210
|
if (rendered && rendered.completions.index === index && rendered.completions.status === status) {
|
|
198
211
|
return;
|
|
199
212
|
}
|
|
@@ -332,7 +345,7 @@ export default class SearchBoxLayout extends TemplateBasedLayout {
|
|
|
332
345
|
if (!options) {
|
|
333
346
|
return;
|
|
334
347
|
}
|
|
335
|
-
this._view.tracker.submit(value);
|
|
348
|
+
this._view.tracker.submit({ value }); // not array
|
|
336
349
|
}
|
|
337
350
|
|
|
338
351
|
}
|
package/src/layout/list/cards.js
CHANGED