@miso.ai/client-sdk-ui 1.12.1-beta.1 → 1.12.1-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 (53) hide show
  1. package/dist/cjs/actor/fields.js +0 -4
  2. package/dist/cjs/actor/view.js +28 -29
  3. package/dist/cjs/actor/views.js +2 -14
  4. package/dist/cjs/affiliation/index.js +17 -2
  5. package/dist/cjs/defaults/ask/templates.js +30 -12
  6. package/dist/cjs/defaults/common/templates.js +2 -0
  7. package/dist/cjs/element/container/miso-container.js +8 -2
  8. package/dist/cjs/element/role/index.js +6 -6
  9. package/dist/cjs/element/util/index.js +3 -3
  10. package/dist/cjs/element/util/miso-stub.js +81 -0
  11. package/dist/cjs/element/utils.js +0 -10
  12. package/dist/cjs/layout/input/option-list.js +2 -9
  13. package/dist/cjs/layout/templates.js +7 -2
  14. package/dist/cjs/layout/text/typewriter/index.js +1 -1
  15. package/dist/cjs/plugin.js +5 -4
  16. package/dist/cjs/trait/collapsible.js +57 -0
  17. package/dist/cjs/trait/helpers.js +65 -0
  18. package/dist/cjs/trait/index.js +13 -0
  19. package/dist/cjs/version.js +1 -1
  20. package/dist/cjs/workflow/ask.js +28 -32
  21. package/dist/cjs/workflow/base.js +1 -2
  22. package/dist/cjs/workflow/hybrid-search-views.js +0 -1
  23. package/dist/cjs/workflow/processors.js +20 -9
  24. package/package.json +2 -2
  25. package/src/actor/fields.js +0 -4
  26. package/src/actor/view.js +28 -25
  27. package/src/actor/views.js +2 -12
  28. package/src/affiliation/index.js +18 -2
  29. package/src/defaults/ask/templates.js +36 -23
  30. package/src/defaults/common/templates.js +2 -2
  31. package/src/element/container/miso-container.js +10 -2
  32. package/src/element/role/index.js +1 -1
  33. package/src/element/util/index.js +1 -1
  34. package/src/element/util/miso-stub.js +85 -0
  35. package/src/element/utils.js +0 -10
  36. package/src/layout/input/option-list.js +1 -8
  37. package/src/layout/templates.js +8 -2
  38. package/src/layout/text/typewriter/index.js +1 -1
  39. package/src/plugin.js +4 -4
  40. package/src/trait/collapsible.js +51 -0
  41. package/src/trait/helpers.js +48 -0
  42. package/src/trait/index.js +1 -0
  43. package/src/version.js +1 -1
  44. package/src/workflow/ask.js +28 -21
  45. package/src/workflow/base.js +2 -2
  46. package/src/workflow/hybrid-search-views.js +0 -1
  47. package/src/workflow/processors.js +16 -9
  48. package/dist/cjs/element/util/miso-collapsible.js +0 -52
  49. package/dist/cjs/element/util/miso-utility.js +0 -83
  50. package/dist/cjs/element/util/utils.js +0 -12
  51. package/src/element/util/miso-collapsible.js +0 -49
  52. package/src/element/util/miso-utility.js +0 -69
  53. package/src/element/util/utils.js +0 -3
@@ -14,15 +14,11 @@ exports.query = query;
14
14
  exports.request = request;
15
15
  exports.response = response;
16
16
  exports.session = session;
17
- exports.suggestions = suggestions;
18
17
  exports.tracker = tracker;
19
18
  exports.view = view;
20
19
  function session() {
21
20
  return 'session';
22
21
  }
23
- function suggestions() {
24
- return 'suggestions';
25
- }
26
22
  function completions() {
27
23
  return 'completions';
28
24
  }
@@ -9,7 +9,6 @@ var _constants = require("../constants.js");
9
9
  var fields = _interopRequireWildcard(require("./fields.js"));
10
10
  var _proxy = _interopRequireDefault(require("../util/proxy.js"));
11
11
  var _tracker = _interopRequireDefault(require("./tracker.js"));
12
- var _utils = require("../element/util/utils.js");
13
12
  const _excluded = ["value", "error", "status", "meta"];
14
13
  function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
15
14
  function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
@@ -17,17 +16,23 @@ function _objectWithoutPropertiesLoose(r, e) { if (null == r) return {}; var t =
17
16
  function statesEqual(a, b) {
18
17
  return a === b || a && b && a.status === b.status && a.error === b.error && a.value === b.value &&
19
18
  // skip deep equals
20
- a.ongoing === b.ongoing && sessionEquals(a.session, b.session);
19
+ a.ongoing === b.ongoing && stateEmptyness(a) === stateEmptyness(b) &&
20
+ // TODO: ad-hoc
21
+ sessionEquals(a.session, b.session);
21
22
  }
22
23
  function sessionEquals(a, b) {
23
24
  return a === b || a && b && a.uuid === b.uuid;
24
25
  }
26
+ function stateEmptyness(data) {
27
+ return data && data.meta && data.meta.empty;
28
+ }
25
29
  class ViewActor {
26
30
  constructor(views, role) {
27
31
  this._events = new _commons.EventEmitter({
28
32
  target: this
29
33
  });
30
34
  this._views = views;
35
+ // TODO: we should pull this up to views, for the results are also used in judging container emptyness
31
36
  this._mapping = asMappingFunction((views._roles.mappings || {})[role] || role);
32
37
  (0, _commons.defineValues)(this, {
33
38
  role,
@@ -113,6 +118,9 @@ class ViewActor {
113
118
  }
114
119
  return this._tracker;
115
120
  }
121
+ get workflow() {
122
+ return this._views._workflow;
123
+ }
116
124
  get workflowOptions() {
117
125
  return this._views._options.resolved;
118
126
  }
@@ -162,7 +170,7 @@ class ViewActor {
162
170
  request,
163
171
  meta,
164
172
  data: value
165
- }, getDataEmptyness(data));
173
+ }, getDataEmptyness(this.role, data));
166
174
 
167
175
  // render
168
176
  const notifyUpdate = (state = {}, options) => {
@@ -194,15 +202,6 @@ class ViewActor {
194
202
  silent
195
203
  });
196
204
  }
197
- triggerAction(data) {
198
- const {
199
- element
200
- } = this;
201
- if (!element) {
202
- return;
203
- }
204
- (0, _utils.triggerMisoAction)(element, data);
205
- }
206
205
  _sliceData(data) {
207
206
  const {
208
207
  value,
@@ -219,12 +218,12 @@ class ViewActor {
219
218
  if (this.role === _constants.ROLE.CONTAINER) {
220
219
  // pass empty/nonempty information
221
220
  sliced.meta = Object.assign({}, meta, {
222
- empty: this._isContainerEmpty(value)
221
+ empty: this._isContainerEmpty(data)
223
222
  });
224
223
  }
225
224
  return (0, _commons.trimObj)(sliced);
226
225
  }
227
- _isContainerEmpty(value) {
226
+ _isContainerEmpty(data) {
228
227
  const {
229
228
  element
230
229
  } = this;
@@ -239,14 +238,10 @@ class ViewActor {
239
238
  if (!(0, _constants.isDataRole)(role)) {
240
239
  continue;
241
240
  }
242
- let sliced = value && value[role];
243
- if (role === _constants.ROLE.QUERY_SUGGESTIONS) {
244
- // special case: query suggestions -> look up value from hub
245
- // TODO: adhoc
246
- const data = this.hub.states[fields.suggestions()];
247
- sliced = data && data.value;
248
- }
249
- if (sliced && sliced.length !== 0) {
241
+ // respect data mapping
242
+ const mapping = asMappingFunction((this._views._roles.mappings || {})[role] || role);
243
+ const sliced = mapping(data, this); // TODO: the view passed in should be the view of the role, not container role
244
+ if (!isDateValueEmpty(role, sliced)) {
250
245
  return false;
251
246
  }
252
247
  }
@@ -289,17 +284,21 @@ function asMappingFunction(fn) {
289
284
  throw new Error(`Invalid mapping function: ${fn}`);
290
285
  }
291
286
  }
292
- function getDataEmptyness(data) {
287
+ function getDataEmptyness(role, data) {
293
288
  return isDataStatusRelevantToEmptyness(data) ? {
294
- empty: !!isDateValueEmpty(data)
289
+ empty: !!isDateValueEmpty(role, data && data.value)
295
290
  } : {};
296
291
  }
297
292
  function isDataStatusRelevantToEmptyness(data) {
298
293
  return data.status === _constants.STATUS.READY && !data.ongoing;
299
294
  }
300
- function isDateValueEmpty(data) {
301
- const {
302
- value
303
- } = data;
304
- return value === undefined || (Array.isArray(value) || typeof value === 'string') && !value.length;
295
+ function isDateValueEmpty(role, value) {
296
+ // TODO: ad-hoc
297
+ switch (role) {
298
+ case _constants.ROLE.ANSWER:
299
+ case _constants.ROLE.REASONING:
300
+ return !value || !value.value;
301
+ default:
302
+ return value === undefined || (Array.isArray(value) || typeof value === 'string') && !value.length;
303
+ }
305
304
  }
@@ -22,7 +22,8 @@ class ViewsActor {
22
22
  options
23
23
  }) {
24
24
  this._hub = hub;
25
- this._workflowName = workflow;
25
+ this._workflow = workflow;
26
+ this._workflowName = workflow._name;
26
27
  this._extensions = extensions;
27
28
  this._layoutFactory = layouts;
28
29
  this._options = options;
@@ -189,19 +190,6 @@ class ViewsActor {
189
190
  data = this._getData(data);
190
191
  // container first
191
192
  let views = this._getViews(true);
192
- if (!force && data._inst) {
193
- const {
194
- includes,
195
- excludes
196
- } = data._inst;
197
- if (includes) {
198
- // always include containers
199
- views = views.filter(view => view.role === _constants.ROLE.CONTAINER || includes.includes(view.role));
200
- }
201
- if (excludes) {
202
- views = views.filter(view => !excludes.includes(view.role));
203
- }
204
- }
205
193
  await Promise.all(views.map(view => view.refresh({
206
194
  force,
207
195
  data
@@ -22,6 +22,15 @@ function processData(data) {
22
22
  });
23
23
  }
24
24
  function processValue(value) {
25
+ /*
26
+ if (value.affiliation_products) {
27
+ const { affiliation_products, ...rest } = value;
28
+ value = {
29
+ ...rest,
30
+ affiliation: processMisoData(affiliation_products),
31
+ };
32
+ } else
33
+ */
25
34
  if (value.sovrn_aff) {
26
35
  const {
27
36
  sovrn_aff
@@ -61,14 +70,20 @@ function postProcessValue(value) {
61
70
  })
62
71
  });
63
72
  }
73
+ function processMisoData(products) {
74
+ return {
75
+ channel: 'miso',
76
+ products
77
+ };
78
+ }
64
79
  function processSovrnData(_ref) {
65
80
  let {
66
81
  products
67
82
  } = _ref,
68
- sovrn_aff = _objectWithoutPropertiesLoose(_ref, _excluded2);
83
+ data = _objectWithoutPropertiesLoose(_ref, _excluded2);
69
84
  return Object.assign({
70
85
  channel: 'sovrn'
71
- }, sovrn_aff, {
86
+ }, data, {
72
87
  products: products.map(processSovrnProduct)
73
88
  });
74
89
  }
@@ -23,11 +23,24 @@ class Sections extends _templates.Sections {
23
23
  const {
24
24
  container
25
25
  } = this._helpers;
26
- return [...super.answerGroup(options), container(options, {
26
+ return [this.question(options), this.reasoning(options), this.answer(options), this.affiliation(options), this.sources(options), container(options, {
27
27
  name: 'bottom-spacing',
28
28
  visibleWhen: 'ongoing'
29
29
  })];
30
30
  }
31
+ question(options) {
32
+ const {
33
+ container,
34
+ phrase
35
+ } = this._helpers;
36
+ return container(options, {
37
+ name: 'question',
38
+ visibleWhen: 'ready'
39
+ }, [options.parentQuestionId ? '<hr>' : '', phrase(options, {
40
+ name: 'question',
41
+ tag: 'div'
42
+ }), '<miso-question></miso-question>']);
43
+ }
31
44
  answer(options) {
32
45
  const {
33
46
  container
@@ -35,28 +48,33 @@ class Sections extends _templates.Sections {
35
48
  return container(options, {
36
49
  name: 'answer',
37
50
  visibleWhen: 'ready'
38
- }, [options.parentQuestionId ? '<hr>' : '', ...this.question(options), this.reasoning(options), '<miso-answer></miso-answer>', '<miso-feedback></miso-feedback>']);
51
+ }, ['<miso-answer></miso-answer>', '<miso-feedback></miso-feedback>']);
39
52
  }
40
- reasoning({
41
- phrases,
42
- reasoning: options = {}
43
- } = {}) {
53
+ reasoning(options = {}) {
54
+ const {
55
+ phrases,
56
+ reasoning: reasoningOptions = {}
57
+ } = options;
44
58
  const {
59
+ container,
45
60
  element,
46
61
  phraseText
47
62
  } = this._helpers;
48
63
  const classes = [];
49
- options.hide !== false && classes.push('hidden');
50
- options.expand && classes.push('expanded');
51
- return element('miso-collapsible', {
64
+ reasoningOptions.expand && classes.push('expanded');
65
+ return container(options, {
66
+ name: 'reasoning',
67
+ visibleWhen: 'nonempty'
68
+ }, [element('miso-stub', {
52
69
  classes,
53
- 'data-role': 'reasoning-container'
70
+ trait: 'collapsible',
71
+ 'data-role': 'reasoning-box'
54
72
  }, [element('div', {
55
73
  classes: ['miso-collapsible__header'],
56
74
  'data-role': 'toggle-expand'
57
- }, [`<div class="miso-collapsible__icon">${options.icon || _svgs.BULB}</div>`, `<div class="miso-collapsible__title" data-role="title">${phraseText(phrases, 'thoughts')}</div>`, `<div class="miso-collapsible__toggle">${_svgs.CHEVRON}</div>`]), element('div', {
75
+ }, [`<div class="miso-collapsible__icon">${reasoningOptions.icon || _svgs.BULB}</div>`, `<div class="miso-collapsible__title" data-role="title">${phraseText(phrases, 'thoughts')}</div>`, `<div class="miso-collapsible__toggle">${_svgs.CHEVRON}</div>`]), element('div', {
58
76
  classes: ['miso-collapsible__body']
59
- }, ['<miso-reasoning></miso-reasoning>'])]);
77
+ }, ['<miso-reasoning></miso-reasoning>'])])]);
60
78
  }
61
79
  sources(options) {
62
80
  const {
@@ -167,6 +167,7 @@ class Helpers {
167
167
  }, {
168
168
  name,
169
169
  visibleWhen,
170
+ trait,
170
171
  logo = false
171
172
  }, body) {
172
173
  const classes = [`${classPrefix}__${name}-container`];
@@ -174,6 +175,7 @@ class Helpers {
174
175
  return this.element(this._context.CONAINER_TAG, {
175
176
  classes,
176
177
  visibleWhen,
178
+ trait,
177
179
  logo,
178
180
  parentQuestionId
179
181
  }, body);
@@ -4,10 +4,12 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.default = void 0;
7
+ var _misoStub = _interopRequireDefault(require("../util/miso-stub.js"));
7
8
  var _utils = require("../utils.js");
9
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
8
10
  const ATTR_LOGO = 'logo';
9
11
  const DEFAULT_LOGO_VALUE = 'auto';
10
- const OBSERVED_ATTRIBUTES = Object.freeze([ATTR_LOGO]);
12
+ const OBSERVED_ATTRIBUTES = Object.freeze([..._misoStub.default.observedAttributes, ATTR_LOGO]);
11
13
  function logoAttrToProp(value) {
12
14
  if (!value) {
13
15
  return DEFAULT_LOGO_VALUE;
@@ -33,7 +35,7 @@ function logoPropToAttr(value) {
33
35
  throw new Error(`Invalid logo property value: ${value}.`);
34
36
  }
35
37
  }
36
- class MisoContainerElement extends HTMLElement {
38
+ class MisoContainerElement extends _misoStub.default {
37
39
  static get observedAttributes() {
38
40
  return OBSERVED_ATTRIBUTES;
39
41
  }
@@ -70,6 +72,7 @@ class MisoContainerElement extends HTMLElement {
70
72
 
71
73
  // lifecycle //
72
74
  async connectedCallback() {
75
+ super.connectedCallback();
73
76
  const client = this._client = await (0, _utils.getClient)(MisoContainerElement);
74
77
  if (document.body.contains(this)) {
75
78
  // in case already disconnected
@@ -78,6 +81,7 @@ class MisoContainerElement extends HTMLElement {
78
81
  }
79
82
  disconnectedCallback() {
80
83
  this._setWorkflow(undefined);
84
+ super.disconnectedCallback();
81
85
  }
82
86
  _getWorkflow(client) {
83
87
  throw new Error('Unimplemented');
@@ -99,6 +103,8 @@ class MisoContainerElement extends HTMLElement {
99
103
  case ATTR_LOGO:
100
104
  this._handleLogoUpdate(oldValue, newValue);
101
105
  break;
106
+ default:
107
+ super.attributeChangedCallback(attr, oldValue, newValue);
102
108
  }
103
109
  }
104
110
  _handleLogoUpdate(oldAttrValue, newAttrValue) {
@@ -3,6 +3,12 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
+ Object.defineProperty(exports, "MisoAffiliationElement", {
7
+ enumerable: true,
8
+ get: function () {
9
+ return _misoAffiliation.default;
10
+ }
11
+ });
6
12
  Object.defineProperty(exports, "MisoAnswerElement", {
7
13
  enumerable: true,
8
14
  get: function () {
@@ -111,12 +117,6 @@ Object.defineProperty(exports, "MisoSourcesElement", {
111
117
  return _misoSources.default;
112
118
  }
113
119
  });
114
- Object.defineProperty(exports, "MisoSovrnAffiliationElement", {
115
- enumerable: true,
116
- get: function () {
117
- return _misoAffiliation.default;
118
- }
119
- });
120
120
  Object.defineProperty(exports, "MisoTotalElement", {
121
121
  enumerable: true,
122
122
  get: function () {
@@ -9,12 +9,12 @@ Object.defineProperty(exports, "MisoBannerElement", {
9
9
  return _misoBanner.default;
10
10
  }
11
11
  });
12
- Object.defineProperty(exports, "MisoCollapsibleElement", {
12
+ Object.defineProperty(exports, "MisoStubElement", {
13
13
  enumerable: true,
14
14
  get: function () {
15
- return _misoCollapsible.default;
15
+ return _misoStub.default;
16
16
  }
17
17
  });
18
18
  var _misoBanner = _interopRequireDefault(require("./miso-banner.js"));
19
- var _misoCollapsible = _interopRequireDefault(require("./miso-collapsible.js"));
19
+ var _misoStub = _interopRequireDefault(require("./miso-stub.js"));
20
20
  function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
@@ -0,0 +1,81 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = void 0;
7
+ const TAG_NAME = 'miso-stub';
8
+ const ATTR_TRAIT = 'trait';
9
+ const OBSERVED_ATTRIBUTES = Object.freeze([ATTR_TRAIT]);
10
+ class MisoStubElement extends HTMLElement {
11
+ static get tagName() {
12
+ return TAG_NAME;
13
+ }
14
+ static get observedAttributes() {
15
+ return OBSERVED_ATTRIBUTES;
16
+ }
17
+ constructor() {
18
+ super();
19
+ this._traits = [];
20
+ }
21
+
22
+ // lifecycle //
23
+ connectedCallback() {
24
+ this._syncTraits();
25
+ }
26
+ disconnectedCallback() {
27
+ for (const trait of this._traits) {
28
+ this._destroyTrait(trait);
29
+ }
30
+ this._traits = [];
31
+ }
32
+ attributeChangedCallback(attr) {
33
+ switch (attr) {
34
+ case ATTR_TRAIT:
35
+ this._syncTraits();
36
+ break;
37
+ }
38
+ }
39
+ _syncTraits() {
40
+ const names = (this.getAttribute(ATTR_TRAIT) || '').split(/\s+/).filter(Boolean);
41
+ const traits = [];
42
+ for (const trait of this._traits) {
43
+ if (!names.includes(trait.constructor.traitName)) {
44
+ this._destroyTrait(trait);
45
+ } else {
46
+ traits.push(trait);
47
+ }
48
+ }
49
+ if (names.length > 0) {
50
+ const availableTraits = getAvailableTraits(MisoStubElement.MisoClient);
51
+ for (const name of names) {
52
+ if (this._traits.find(trait => trait.constructor.traitName === name)) {
53
+ continue;
54
+ }
55
+ const TraitClass = availableTraits[name];
56
+ if (!TraitClass) {
57
+ console.warn(`Unknown trait: ${name}`);
58
+ continue;
59
+ }
60
+ const trait = new TraitClass(this);
61
+ traits.push(trait);
62
+ }
63
+ }
64
+ this._traits = traits;
65
+ }
66
+ _destroyTrait(trait) {
67
+ try {
68
+ trait._destroy && trait._destroy();
69
+ } catch (error) {
70
+ console.error(error);
71
+ }
72
+ }
73
+ }
74
+ exports.default = MisoStubElement;
75
+ function getAvailableTraits(MisoClient) {
76
+ const traits = MisoClient.ui && MisoClient.ui.traits || {};
77
+ return Object.values(traits).reduce((traits, trait) => {
78
+ traits[trait.traitName] = trait;
79
+ return traits;
80
+ }, {});
81
+ }
@@ -4,7 +4,6 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.applyCoerce = applyCoerce;
7
- exports.defineStatusGetters = defineStatusGetters;
8
7
  exports.getClient = getClient;
9
8
  exports.getContainer = getContainer;
10
9
  exports.getMisoClient = getMisoClient;
@@ -85,13 +84,4 @@ function coerceDefault(str) {
85
84
  return num;
86
85
  }
87
86
  return str;
88
- }
89
- function defineStatusGetters(prototype, statuses) {
90
- for (const status of statuses) {
91
- Object.defineProperty(prototype, status, {
92
- get() {
93
- return this.classList.contains(status);
94
- }
95
- });
96
- }
97
87
  }
@@ -77,16 +77,9 @@ class OptionListLayout extends _template.default {
77
77
  }
78
78
  initialize(view) {
79
79
  const {
80
- proxyElement,
81
- hub
80
+ proxyElement
82
81
  } = view;
83
- this._unsubscribes = [...this._unsubscribes, proxyElement.on('click', e => this._handleClick(e)), hub.on(_index.fields.suggestions(), () => this._handleInput()) // TODO: use data mapping
84
- ];
85
- }
86
- _preprocess() {
87
- return super._preprocess({
88
- state: this._view.hub.states[_index.fields.suggestions()] // TODO: use data mapping
89
- });
82
+ this._unsubscribes = [...this._unsubscribes, proxyElement.on('click', e => this._handleClick(e))];
90
83
  }
91
84
  _render(element, data, controls) {
92
85
  super._render(element, data, controls);
@@ -128,7 +128,7 @@ function titleBlock({
128
128
  title,
129
129
  _title_with_markups
130
130
  }) {
131
- const text = _title_with_markups || (0, _commons.escapeHtml)(title);
131
+ const text = formatHtmlWithMarkup(_title_with_markups) || (0, _commons.escapeHtml)(title);
132
132
  return text ? `<div class="${className}__item-title">${text}</div>` : '';
133
133
  }
134
134
  function brandBlock({
@@ -149,7 +149,7 @@ function descriptionBlock({
149
149
  snippet,
150
150
  description
151
151
  }) {
152
- return snippet ? `<div class="${className}__item-snippet">${snippet}</div>` : description ? `<div class="${className}__item-desc">${(0, _commons.escapeHtml)(description)}</div>` : '';
152
+ return snippet ? `<div class="${className}__item-snippet">${formatHtmlWithMarkup(snippet)}</div>` : description ? `<div class="${className}__item-desc">${(0, _commons.escapeHtml)(description)}</div>` : '';
153
153
  }
154
154
  function dateBlock({
155
155
  className,
@@ -333,6 +333,10 @@ function formatNumber(number, fn = DEFAULT_NUMBER_OPTIONS) {
333
333
  throw new Error(`Invalid number format: ${fn}`);
334
334
  }
335
335
  }
336
+ function formatHtmlWithMarkup(html) {
337
+ // preserve space between two <mark> elements
338
+ return html && html.replace(/<\/mark>\s+<mark>/g, '</mark>&nbsp;<mark>');
339
+ }
336
340
  function asFunction(template = '') {
337
341
  return typeof template === 'function' ? template : () => template;
338
342
  }
@@ -340,6 +344,7 @@ const helpers = exports.helpers = Object.freeze({
340
344
  tagPair,
341
345
  formatDate,
342
346
  formatNumber,
347
+ formatHtmlWithMarkup,
343
348
  escapeHtml: _commons.escapeHtml,
344
349
  asFunction
345
350
  });
@@ -130,7 +130,7 @@ class TypewriterLayout extends _progressive.default {
130
130
  const sameSession = (0, _utils.fromSameSession)(prev, state);
131
131
  const sameStreak = sameSession && stage === prev.stage;
132
132
  const streak = !prev ? 0 : sameStreak ? prev.streak : prev.streak + 1;
133
- const doneAt = sameSession && prev && prev.doneAt || (status === _constants.STATUS.READY && finished ? Date.now() : undefined);
133
+ const doneAt = sameSession && prev && prev.doneAt || (status === _constants.STATUS.READY && finished ? performance.now() : undefined);
134
134
  const done = doneAt !== undefined;
135
135
  return this._prevState = Object.freeze((0, _commons.trimObj)({
136
136
  session,
@@ -12,6 +12,7 @@ var elements = _interopRequireWildcard(require("./element/index.js"));
12
12
  var layouts = _interopRequireWildcard(require("./layout/index.js"));
13
13
  var sources = _interopRequireWildcard(require("./source.js"));
14
14
  var defaults = _interopRequireWildcard(require("./defaults/index.js"));
15
+ var traits = _interopRequireWildcard(require("./trait/index.js"));
15
16
  var _styles = require("./styles.js");
16
17
  var _misoContainer = _interopRequireDefault(require("./element/container/miso-container.js"));
17
18
  var _misoCombo = _interopRequireDefault(require("./element/combo/miso-combo.js"));
@@ -37,7 +38,8 @@ class UiPlugin extends _commons.Component {
37
38
  context.addSubtree(this);
38
39
  MisoClient.on('create', this._injectClient.bind(this));
39
40
  const ui = {
40
- defaults
41
+ defaults,
42
+ traits
41
43
  };
42
44
  (0, _commons.delegateGetters)(ui, this, ['layouts', 'combo', 'ready']);
43
45
  (0, _commons.defineValues)(this, {
@@ -68,9 +70,8 @@ class UiPlugin extends _commons.Component {
68
70
  others = _objectWithoutPropertiesLoose(elements, _excluded);
69
71
  // containers must go first, so their APIs will be ready before children are defined
70
72
  const ElementClasses = [...Object.values(combos), ...Object.values(containers), ...Object.values(roles), ...Object.values(others)];
71
- _misoContainer.default.MisoClient = MisoClient;
72
- _misoCombo.default.MisoClient = MisoClient;
73
- for (const ElementClass of ElementClasses) {
73
+ const ElementSuperClasses = [_misoContainer.default, _misoCombo.default];
74
+ for (const ElementClass of [...ElementSuperClasses, ...ElementClasses]) {
74
75
  ElementClass.MisoClient = MisoClient; // TODO: find better way
75
76
  }
76
77
 
@@ -0,0 +1,57 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = void 0;
7
+ var _helpers = require("./helpers.js");
8
+ const CLASS_NAME = 'miso-collapsible';
9
+ const STATUS_EXPANDED = 'expanded';
10
+ const ACTIONS = [{
11
+ action: 'expand',
12
+ classAction: 'add',
13
+ className: STATUS_EXPANDED
14
+ }, {
15
+ action: 'collapse',
16
+ classAction: 'remove',
17
+ className: STATUS_EXPANDED
18
+ }];
19
+ const CLICKABLES = [{
20
+ role: 'expand',
21
+ action: 'expand'
22
+ }, {
23
+ role: 'collapse',
24
+ action: 'collapse'
25
+ }, {
26
+ role: 'toggle-expand',
27
+ action: 'toggle'
28
+ }];
29
+ class CollapsibleTrait {
30
+ static get traitName() {
31
+ return 'collapsible';
32
+ }
33
+ constructor(element) {
34
+ this._element = element;
35
+ element.collapsible = this;
36
+ element.classList.add(CLASS_NAME);
37
+ this._unsubscribes = [(0, _helpers.listenToClickables)(this)];
38
+ }
39
+ _destroy() {
40
+ for (const unsubscribe of this._unsubscribes || []) {
41
+ unsubscribe();
42
+ }
43
+ this._unsubscribes = [];
44
+ delete this._element.collapsible;
45
+ this._element.classList.remove(CLASS_NAME);
46
+ this._element = undefined;
47
+ }
48
+
49
+ // api //
50
+ toggle() {
51
+ this.expanded ? this.collapse() : this.expand();
52
+ }
53
+ }
54
+ exports.default = CollapsibleTrait;
55
+ (0, _helpers.defineStatusGetters)(CollapsibleTrait.prototype, [STATUS_EXPANDED]);
56
+ (0, _helpers.defineActions)(CollapsibleTrait.prototype, ACTIONS);
57
+ (0, _helpers.defineClickables)(CollapsibleTrait.prototype, CLICKABLES);