@miso.ai/client-sdk-ui 1.10.0-beta.1 → 1.10.0-beta.3

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 (51) hide show
  1. package/dist/cjs/actor/data.js +1 -1
  2. package/dist/cjs/actor/tracker.js +1 -1
  3. package/dist/cjs/actor/view.js +1 -1
  4. package/dist/cjs/affiliation/index.js +99 -0
  5. package/dist/cjs/combo/ask/options.js +1 -1
  6. package/dist/cjs/combo/base.js +1 -1
  7. package/dist/cjs/constants.js +3 -1
  8. package/dist/cjs/defaults/ask/controls.js +1 -1
  9. package/dist/cjs/defaults/ask/templates.js +14 -4
  10. package/dist/cjs/element/role/index.js +7 -0
  11. package/dist/cjs/element/role/miso-affiliation.js +20 -0
  12. package/dist/cjs/layout/affiliation/affiliation.js +109 -0
  13. package/dist/cjs/layout/banner/banner.js +1 -1
  14. package/dist/cjs/layout/container/container.js +1 -1
  15. package/dist/cjs/layout/error/error.js +1 -1
  16. package/dist/cjs/layout/index.js +7 -0
  17. package/dist/cjs/layout/input/option-list.js +1 -1
  18. package/dist/cjs/layout/input/search-box.js +17 -5
  19. package/dist/cjs/layout/list/cards.js +1 -1
  20. package/dist/cjs/layout/list/carousel.js +1 -1
  21. package/dist/cjs/layout/list/collection.js +7 -1
  22. package/dist/cjs/layout/list/list.js +1 -1
  23. package/dist/cjs/layout/radio/feedback.js +1 -1
  24. package/dist/cjs/layout/radio/radio.js +1 -1
  25. package/dist/cjs/layout/raf.js +1 -1
  26. package/dist/cjs/layout/template.js +1 -1
  27. package/dist/cjs/layout/templates.js +123 -44
  28. package/dist/cjs/layout/text/text.js +1 -1
  29. package/dist/cjs/layout/text/typewriter/index.js +1 -1
  30. package/dist/cjs/plugin.js +1 -1
  31. package/dist/cjs/util/tracker.js +1 -1
  32. package/dist/cjs/version.js +1 -1
  33. package/dist/cjs/workflow/ask.js +12 -2
  34. package/dist/cjs/workflow/asks.js +1 -1
  35. package/dist/cjs/workflow/base.js +1 -1
  36. package/dist/cjs/workflow/explore.js +1 -1
  37. package/dist/cjs/workflow/options.js +6 -1
  38. package/package.json +2 -2
  39. package/src/affiliation/index.js +83 -0
  40. package/src/constants.js +3 -0
  41. package/src/defaults/ask/templates.js +14 -2
  42. package/src/element/role/index.js +1 -0
  43. package/src/element/role/miso-affiliation.js +16 -0
  44. package/src/layout/affiliation/affiliation.js +84 -0
  45. package/src/layout/index.js +1 -0
  46. package/src/layout/input/search-box.js +7 -2
  47. package/src/layout/list/collection.js +7 -1
  48. package/src/layout/templates.js +92 -26
  49. package/src/version.js +1 -1
  50. package/src/workflow/ask.js +6 -1
  51. package/src/workflow/options.js +5 -1
@@ -285,7 +285,8 @@ export default class SearchBoxLayout extends TemplateBasedLayout {
285
285
  // TODO: select completion items with arrow keys
286
286
  }
287
287
 
288
- _handleClick({ target }) {
288
+ _handleClick(event) {
289
+ const { target } = event;
289
290
  const { inputElement } = this._context();
290
291
  for (let element = target; element && element !== this._element; element = element.parentElement) {
291
292
  if (element.matches('[data-role="submit"]') || element.matches('[data-role="button"]') || element.matches('[type="submit"]')) {
@@ -303,12 +304,16 @@ export default class SearchBoxLayout extends TemplateBasedLayout {
303
304
  if (inputElement) {
304
305
  inputElement.value = value;
305
306
  }
306
- this._submit(value);
307
+ this._view._events.emit('select', Object.freeze({ value: item, index, domEvent: event }));
308
+ if (!event.defaultPrevented) {
309
+ this._submit(value);
310
+ }
307
311
  }
308
312
  this.close();
309
313
  return;
310
314
  }
311
315
  if (element.matches('[data-role="product-item"]')) {
316
+ this._view._events.emit('select', Object.freeze({ value: item, index, domEvent: event }));
312
317
  return;
313
318
  }
314
319
  }
@@ -1,7 +1,7 @@
1
1
  import { defineValues } from '@miso.ai/commons';
2
2
  import { STATUS, LAYOUT_CATEGORY } from '../../constants.js';
3
3
  import TemplateBasedLayout from '../template.js';
4
- import { product, article, question, productInfoBlock, articleInfoBlock, imageBlock, indexBlock, helpers } from '../templates.js';
4
+ import { product, article, question, productInfoBlock, articleInfoBlock, titleBlock, brandBlock, descriptionBlock, dateBlock, priceBlock, ctaBlock, cta, imageBlock, indexBlock, helpers } from '../templates.js';
5
5
 
6
6
  const VALUE = Symbol.for('miso.value');
7
7
 
@@ -59,6 +59,12 @@ const DEFAULT_TEMPLATES = Object.freeze({
59
59
  item,
60
60
  productInfoBlock,
61
61
  articleInfoBlock,
62
+ titleBlock,
63
+ descriptionBlock,
64
+ dateBlock,
65
+ priceBlock,
66
+ ctaBlock,
67
+ cta,
62
68
  imageBlock,
63
69
  indexBlock,
64
70
  helpers,
@@ -42,37 +42,86 @@ export function article(layout, state, data, meta) {
42
42
  ].join('');
43
43
  }
44
44
 
45
- export function productInfoBlock({ className }, { title, description, sale_price, original_price }) {
46
- let content = '';
47
- if (title) {
48
- content += `<div class="${className}__item-title">${escapeHtml(title)}</div>`;
49
- }
50
- if (description) {
51
- content += `<div class="${className}__item-desc">${escapeHtml(description)}</div>`;
52
- }
53
- const price = sale_price || original_price;
54
- if (price) {
55
- content += `<hr><div class="${className}__item-price">${price}</div>`;
56
- // TODO: enhance this
45
+ export function affiliation(layout, state, data, meta) {
46
+ const { templates } = layout;
47
+ const [openTag, closeTag] = tagPair(layout, data);
48
+ return [
49
+ openTag,
50
+ (templates.infoBlock || templates.affiliationInfoBlock || affiliationInfoBlock)(layout, data, meta),
51
+ (templates.imageBlock || imageBlock)(layout, data, meta),
52
+ (templates.brandBlock || brandBlock)(layout, data, meta),
53
+ closeTag,
54
+ ].join('');
55
+ }
56
+
57
+ export function affiliationInfoBlock(layout, data, meta) {
58
+ const { className, templates } = layout;
59
+ return `<div class="${className}__item-info-container">${[
60
+ (templates.titleBlock || titleBlock)(layout, data, meta),
61
+ (templates.descriptionBlock || descriptionBlock)(layout, data, meta),
62
+ (templates.priceBlock || priceBlock)(layout, data, meta),
63
+ (templates.ctaBlock || ctaBlock)(layout, data, meta),
64
+ ].join('')}</div>`;
65
+ }
66
+
67
+ export function productInfoBlock(layout, data, meta) {
68
+ const { className, templates } = layout;
69
+ return `<div class="${className}__item-info-container">${[
70
+ (templates.titleBlock || titleBlock)(layout, data, meta),
71
+ (templates.descriptionBlock || descriptionBlock)(layout, data, meta),
72
+ (templates.priceBlock || priceBlock)(layout, data, meta),
73
+ ].join('')}</div>`;
74
+ }
75
+
76
+ export function articleInfoBlock(layout, data, meta) {
77
+ const { className, templates } = layout;
78
+ return `<div class="${className}__item-info-container">${[
79
+ (templates.titleBlock || titleBlock)(layout, data, meta),
80
+ (templates.dateBlock || dateBlock)(layout, data, meta),
81
+ (templates.descriptionBlock || descriptionBlock)(layout, data, meta),
82
+ (templates.ctaBlock || ctaBlock)(layout, data, meta),
83
+ ].join('')}</div>`;
84
+ }
85
+
86
+ export function titleBlock({ className }, { title }) {
87
+ return title ? `<div class="${className}__item-title">${escapeHtml(title)}</div>` : '';
88
+ }
89
+
90
+ export function brandBlock({ className }, { brand, brand_logo }) {
91
+ if (!brand && !brand_logo) {
92
+ return '';
57
93
  }
58
- return `<div class="${className}__item-info-container">${content}</div>`;
94
+ brand_logo = undefined;
95
+ const content = brand_logo ? `<img class="${className}__item-brand-logo" src="${brand_logo}"${brand ? ` alt="${brand}"` : ''}>` : `<div class="${className}__item-brand">${brand}</div>`;
96
+ return `<div class="${className}__item-brand-container">${content}</div>`;
97
+ }
98
+
99
+ export function descriptionBlock({ className }, { snippet, description }) {
100
+ return snippet ? `<div class="${className}__item-snippet">${snippet}</div>` : description ? `<div class="${className}__item-desc">${escapeHtml(description)}</div>` : '';
59
101
  }
60
102
 
61
- export function articleInfoBlock({ className, templates }, { title, snippet, description, created_at, updated_at, published_at }) {
103
+ export function dateBlock({ className, templates }, { created_at, updated_at, published_at }) {
62
104
  const date = published_at || created_at || updated_at;
63
- let content = '';
64
- if (title) {
65
- content += `<div class="${className}__item-title">${escapeHtml(title)}</div>`;
105
+ return date ? `<div class="${className}__item-date">${formatDate(date, templates.date)}</div>` : '';
106
+ }
107
+
108
+ export function priceBlock({ className }, { sale_price, original_price, discount_rate_percent, currency = 'USD' }) {
109
+ const price = sale_price || original_price;
110
+ if (!price) {
111
+ return '';
66
112
  }
67
- if (date) {
68
- content += `<div class="${className}__item-date">${formatDate(date, templates.date)}</div>`;
113
+ const has_price_difference = original_price !== undefined && sale_price !== undefined && sale_price < original_price;
114
+ discount_rate_percent = discount_rate_percent || (has_price_difference ? Math.floor((1 - sale_price / original_price) * 100) : undefined);
115
+
116
+ let content = '';
117
+ if (has_price_difference) {
118
+ content += `<span class="${className}__item-original-price miso-price" data-currency="${currency}">${original_price}</span><br>`;
69
119
  }
70
- if (snippet) {
71
- content += `<div class="${className}__item-snippet">${snippet}</div>`;
72
- } else if (description) {
73
- content += `<div class="${className}__item-desc">${escapeHtml(description)}</div>`;
120
+ content += `<span class="${className}__item-price miso-price" data-currency="${currency}">${price}</span>`;
121
+ if (discount_rate_percent) {
122
+ content += `<span class="${className}__item-discount-rate"> (${discount_rate_percent}% off)</span>`;
74
123
  }
75
- return `<div class="${className}__item-info-container">${content}</div>`;
124
+ return `<div class="${className}__item-price-container">${content}</div>`;
76
125
  }
77
126
 
78
127
  export function imageBlock({ className }, { cover_image }) {
@@ -84,8 +133,25 @@ export function imageBlock({ className }, { cover_image }) {
84
133
  }
85
134
 
86
135
  export function indexBlock({ className }, data, { index }) {
87
- const i = index + 1;
88
- return `<div class="${className}__item-index-container"><span class="${className}__item-index miso-citation-index" data-index="${i}"></span></div>`;
136
+ return `<div class="${className}__item-index-container"><span class="${className}__item-index miso-citation-index" data-index="${index + 1}"></span></div>`;
137
+ }
138
+
139
+ export function ctaBlock(layout, data, meta) {
140
+ const { className, templates } = layout;
141
+ let _cta = templates.cta || cta;
142
+ if (typeof _cta === 'function') {
143
+ _cta = _cta(layout, data, meta);
144
+ }
145
+ return _cta ? `<div class="${className}__item-cta-container">${_cta}</div>` : '';
146
+ }
147
+
148
+ export function cta(layout, data, meta) {
149
+ const { className, templates } = layout;
150
+ let text = templates.ctaText;
151
+ if (typeof text === 'function') {
152
+ text = text(layout, data, meta);
153
+ }
154
+ return text ? `<div class="${className}__item-cta">${text}</div>` : '';
89
155
  }
90
156
 
91
157
  // helpers //
package/src/version.js CHANGED
@@ -1 +1 @@
1
- export default '1.10.0-beta.1';
1
+ export default '1.10.0-beta.3';
@@ -4,8 +4,9 @@ import { mergeApiOptions } from './options.js';
4
4
  import * as sources from '../source/index.js';
5
5
  import { fields, FeedbackActor, AutocompleteActor } from '../actor/index.js';
6
6
  import { ROLE, STATUS, ORGANIC_QUESTION_SOURCE } from '../constants.js';
7
- import { SearchBoxLayout, OptionListLayout, ListLayout, TextLayout, TypewriterLayout, FeedbackLayout } from '../layout/index.js';
7
+ import { SearchBoxLayout, OptionListLayout, ListLayout, TextLayout, TypewriterLayout, FeedbackLayout, AffiliationLayout } from '../layout/index.js';
8
8
  import { makeConfigurable } from './options.js';
9
+ import { processData as processAffiliationData } from '../affiliation/index.js';
9
10
 
10
11
  const DEFAULT_API_OPTIONS = Object.freeze({
11
12
  group: API.GROUP.ASK,
@@ -35,6 +36,7 @@ const DEFAULT_LAYOUTS = Object.freeze({
35
36
  [ROLE.SOURCES]: [ListLayout.type, { incremental: true, itemType: 'article', templates: { ordered: true } }],
36
37
  [ROLE.RELATED_RESOURCES]: [ListLayout.type, { incremental: true, itemType: 'article' }],
37
38
  [ROLE.QUERY_SUGGESTIONS]: OptionListLayout.type,
39
+ [ROLE.AFFILIATION]: [AffiliationLayout.type, { itemType: 'affiliation', link: { rel: 'noopener nofollow' } }],
38
40
  });
39
41
 
40
42
  const DEFAULT_TRACKERS = Object.freeze({
@@ -207,6 +209,9 @@ export default class Ask extends Workflow {
207
209
  }
208
210
  }
209
211
 
212
+ // affiliation
213
+ data = processAffiliationData(data);
214
+
210
215
  // 1. put answer_stage to meta
211
216
  // 2. mark ongoing flag
212
217
  return {
@@ -11,10 +11,14 @@ export function normalizeApiOptions([name, payload] = []) {
11
11
  payload = name;
12
12
  name = undefined;
13
13
  }
14
+ let group = undefined;
15
+ if (name && name.indexOf('/') !== -1) {
16
+ [group, name] = name.split('/');
17
+ }
14
18
  if ((name && typeof name !== 'string') || (payload !== undefined && typeof payload !== 'object')) {
15
19
  throw new Error(`Invalid arguments for useApi(): ${name}, ${payload}`);
16
20
  }
17
- return trimObj({ name, payload });
21
+ return trimObj({ group, name, payload });
18
22
  }
19
23
 
20
24
  export function normalizeLayoutsOptions(options = {}) {