@miso.ai/client-sdk-ui 1.13.2-beta.0 → 1.14.0-beta.2
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/asset/svgs.js +15 -4
- package/dist/cjs/combo/ask/index.js +2 -2
- package/dist/cjs/constants.js +118 -98
- package/dist/cjs/defaults/ask/controls.js +1 -1
- package/dist/cjs/defaults/hybrid-search/answer-box.js +4 -4
- package/dist/cjs/defaults.js +169 -0
- package/dist/cjs/element/container/index.js +14 -0
- package/dist/cjs/element/container/miso-ask.js +3 -3
- package/dist/cjs/element/container/miso-conversation.js +21 -0
- package/dist/cjs/element/container/miso-explore.js +1 -1
- package/dist/cjs/element/container/miso-history.js +21 -0
- package/dist/cjs/element/container/miso-hybrid-search.js +1 -1
- package/dist/cjs/element/container/miso-recommendation.js +1 -1
- package/dist/cjs/element/container/miso-search.js +1 -1
- package/dist/cjs/element/context/miso-follow-ups.js +1 -1
- package/dist/cjs/element/role/index.js +42 -0
- package/dist/cjs/element/role/miso-messages.js +20 -0
- package/dist/cjs/element/role/miso-new-thread.js +20 -0
- package/dist/cjs/element/role/miso-rename.js +20 -0
- package/dist/cjs/element/role/miso-subscription.js +20 -0
- package/dist/cjs/element/role/miso-threads.js +20 -0
- package/dist/cjs/element/role/miso-title.js +20 -0
- package/dist/cjs/layout/affiliation/affiliation.js +1 -1
- package/dist/cjs/layout/banner/banner.js +2 -1
- package/dist/cjs/layout/button/button.js +130 -0
- package/dist/cjs/layout/button/checkbox.js +115 -0
- package/dist/cjs/layout/button/more-button.js +3 -3
- package/dist/cjs/layout/container/container.js +1 -1
- package/dist/cjs/layout/error/error.js +2 -1
- package/dist/cjs/layout/index.js +28 -0
- package/dist/cjs/layout/input/facets.js +4 -3
- package/dist/cjs/layout/input/option-list.js +3 -2
- package/dist/cjs/layout/input/search-box.js +42 -9
- package/dist/cjs/layout/input/select.js +2 -1
- package/dist/cjs/layout/list/cards.js +2 -1
- package/dist/cjs/layout/list/carousel.js +2 -1
- package/dist/cjs/layout/list/collection.js +5 -0
- package/dist/cjs/layout/list/gallery.js +2 -1
- package/dist/cjs/layout/list/horizontal.js +2 -1
- package/dist/cjs/layout/list/list.js +2 -1
- package/dist/cjs/layout/list/messages.js +346 -0
- package/dist/cjs/layout/list/threads.js +257 -0
- package/dist/cjs/layout/mixin/trackable.js +4 -5
- package/dist/cjs/layout/mixin/triggerable.js +2 -2
- package/dist/cjs/layout/radio/feedback.js +4 -3
- package/dist/cjs/layout/templates.js +70 -0
- package/dist/cjs/layout/text/text.js +2 -1
- package/dist/cjs/layout/text/typewriter/index.js +4 -2
- package/dist/cjs/plugin.js +43 -104
- package/dist/cjs/util/confirm.js +33 -0
- package/dist/cjs/util/modal.js +48 -0
- package/dist/cjs/util/prompt.js +47 -0
- package/dist/cjs/version.js +1 -1
- package/package.json +5 -4
- package/src/CLAUDE.md +48 -105
- package/src/asset/svgs.js +14 -3
- package/src/combo/ask/index.js +2 -2
- package/src/constants.js +37 -147
- package/src/defaults/ask/controls.js +1 -1
- package/src/defaults/hybrid-search/answer-box.js +2 -2
- package/src/defaults.js +107 -0
- package/src/element/container/index.js +2 -0
- package/src/element/container/miso-ask.js +3 -3
- package/src/element/container/miso-conversation.js +19 -0
- package/src/element/container/miso-explore.js +1 -1
- package/src/element/container/miso-history.js +19 -0
- package/src/element/container/miso-hybrid-search.js +1 -1
- package/src/element/container/miso-recommendation.js +1 -1
- package/src/element/container/miso-search.js +1 -1
- package/src/element/context/miso-follow-ups.js +1 -1
- package/src/element/role/index.js +6 -0
- package/src/element/role/miso-messages.js +16 -0
- package/src/element/role/miso-new-thread.js +16 -0
- package/src/element/role/miso-rename.js +16 -0
- package/src/element/role/miso-subscription.js +16 -0
- package/src/element/role/miso-threads.js +16 -0
- package/src/element/role/miso-title.js +16 -0
- package/src/layout/affiliation/affiliation.js +2 -2
- package/src/layout/banner/banner.js +2 -1
- package/src/layout/button/button.js +116 -0
- package/src/layout/button/checkbox.js +91 -0
- package/src/layout/button/more-button.js +3 -3
- package/src/layout/container/container.js +2 -2
- package/src/layout/error/error.js +2 -1
- package/src/layout/index.js +4 -0
- package/src/layout/input/facets.js +3 -2
- package/src/layout/input/option-list.js +3 -2
- package/src/layout/input/search-box.js +41 -6
- package/src/layout/input/select.js +2 -1
- package/src/layout/list/cards.js +2 -1
- package/src/layout/list/carousel.js +2 -1
- package/src/layout/list/collection.js +6 -1
- package/src/layout/list/gallery.js +2 -1
- package/src/layout/list/horizontal.js +2 -1
- package/src/layout/list/list.js +2 -1
- package/src/layout/list/messages.js +318 -0
- package/src/layout/list/threads.js +206 -0
- package/src/layout/mixin/trackable.js +2 -3
- package/src/layout/mixin/triggerable.js +1 -1
- package/src/layout/radio/feedback.js +3 -2
- package/src/layout/templates.js +62 -0
- package/src/layout/text/text.js +2 -1
- package/src/layout/text/typewriter/index.js +5 -3
- package/src/plugin.js +31 -117
- package/src/util/confirm.js +28 -0
- package/src/util/modal.js +49 -0
- package/src/util/prompt.js +42 -0
- package/src/version.js +1 -1
- package/dist/cjs/actor/data.js +0 -132
- package/dist/cjs/actor/feedback.js +0 -29
- package/dist/cjs/actor/fields.js +0 -57
- package/dist/cjs/actor/filters.js +0 -161
- package/dist/cjs/actor/hub.js +0 -57
- package/dist/cjs/actor/index.js +0 -73
- package/dist/cjs/actor/interactions.js +0 -36
- package/dist/cjs/actor/sessions.js +0 -25
- package/dist/cjs/actor/tracker-states.js +0 -61
- package/dist/cjs/actor/tracker.js +0 -109
- package/dist/cjs/actor/trackers.js +0 -52
- package/dist/cjs/actor/utils.js +0 -15
- package/dist/cjs/actor/view.js +0 -294
- package/dist/cjs/actor/views.js +0 -209
- package/dist/cjs/source.js +0 -27
- package/dist/cjs/util/proxy.js +0 -88
- package/dist/cjs/util/trackers.js +0 -88
- package/dist/cjs/workflow/affiliations.js +0 -140
- package/dist/cjs/workflow/answer-based.js +0 -337
- package/dist/cjs/workflow/ask.js +0 -319
- package/dist/cjs/workflow/asks.js +0 -150
- package/dist/cjs/workflow/autocompletable.js +0 -63
- package/dist/cjs/workflow/autocomplete.js +0 -120
- package/dist/cjs/workflow/base.js +0 -418
- package/dist/cjs/workflow/context.js +0 -19
- package/dist/cjs/workflow/explore.js +0 -210
- package/dist/cjs/workflow/explores.js +0 -21
- package/dist/cjs/workflow/hybrid-search-answer.js +0 -88
- package/dist/cjs/workflow/hybrid-search-views.js +0 -109
- package/dist/cjs/workflow/hybrid-search.js +0 -213
- package/dist/cjs/workflow/index.js +0 -41
- package/dist/cjs/workflow/options/api.js +0 -41
- package/dist/cjs/workflow/options/auto-query.js +0 -97
- package/dist/cjs/workflow/options/configurable.js +0 -45
- package/dist/cjs/workflow/options/data-processor.js +0 -20
- package/dist/cjs/workflow/options/filters.js +0 -15
- package/dist/cjs/workflow/options/index.js +0 -126
- package/dist/cjs/workflow/options/interactions.js +0 -41
- package/dist/cjs/workflow/options/layouts.js +0 -79
- package/dist/cjs/workflow/options/options.js +0 -156
- package/dist/cjs/workflow/options/pagination.js +0 -25
- package/dist/cjs/workflow/options/roles.js +0 -15
- package/dist/cjs/workflow/options/templates.js +0 -30
- package/dist/cjs/workflow/options/trackers.js +0 -83
- package/dist/cjs/workflow/options/utils.js +0 -33
- package/dist/cjs/workflow/processors.js +0 -607
- package/dist/cjs/workflow/recommendation.js +0 -57
- package/dist/cjs/workflow/recommendations.js +0 -18
- package/dist/cjs/workflow/search-based.js +0 -337
- package/dist/cjs/workflow/search.js +0 -64
- package/dist/cjs/workflow/unit.js +0 -57
- package/dist/cjs/workflow/units.js +0 -42
- package/dist/cjs/workflow/use-link.js +0 -49
- package/src/actor/data.js +0 -106
- package/src/actor/feedback.js +0 -28
- package/src/actor/fields.js +0 -51
- package/src/actor/filters.js +0 -149
- package/src/actor/hub.js +0 -47
- package/src/actor/index.js +0 -10
- package/src/actor/interactions.js +0 -32
- package/src/actor/sessions.js +0 -21
- package/src/actor/tracker-states.js +0 -57
- package/src/actor/tracker.js +0 -104
- package/src/actor/trackers.js +0 -45
- package/src/actor/utils.js +0 -7
- package/src/actor/view.js +0 -272
- package/src/actor/views.js +0 -224
- package/src/source.js +0 -17
- package/src/util/proxy.js +0 -81
- package/src/util/trackers.js +0 -84
- package/src/workflow/affiliations.js +0 -121
- package/src/workflow/answer-based.js +0 -312
- package/src/workflow/ask.js +0 -284
- package/src/workflow/asks.js +0 -143
- package/src/workflow/autocompletable.js +0 -67
- package/src/workflow/autocomplete.js +0 -114
- package/src/workflow/base.js +0 -396
- package/src/workflow/context.js +0 -16
- package/src/workflow/explore.js +0 -194
- package/src/workflow/explores.js +0 -18
- package/src/workflow/hybrid-search-answer.js +0 -73
- package/src/workflow/hybrid-search-views.js +0 -116
- package/src/workflow/hybrid-search.js +0 -230
- package/src/workflow/index.js +0 -5
- package/src/workflow/options/api.js +0 -31
- package/src/workflow/options/auto-query.js +0 -70
- package/src/workflow/options/configurable.js +0 -48
- package/src/workflow/options/data-processor.js +0 -15
- package/src/workflow/options/filters.js +0 -10
- package/src/workflow/options/index.js +0 -11
- package/src/workflow/options/interactions.js +0 -36
- package/src/workflow/options/layouts.js +0 -73
- package/src/workflow/options/options.js +0 -175
- package/src/workflow/options/pagination.js +0 -18
- package/src/workflow/options/roles.js +0 -12
- package/src/workflow/options/templates.js +0 -27
- package/src/workflow/options/trackers.js +0 -80
- package/src/workflow/options/utils.js +0 -26
- package/src/workflow/processors.js +0 -490
- package/src/workflow/recommendation.js +0 -63
- package/src/workflow/recommendations.js +0 -14
- package/src/workflow/search-based.js +0 -329
- package/src/workflow/search.js +0 -73
- package/src/workflow/unit.js +0 -51
- package/src/workflow/units.js +0 -43
- package/src/workflow/use-link.js +0 -41
|
@@ -6,7 +6,7 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
6
6
|
exports.default = void 0;
|
|
7
7
|
var _commons = require("@miso.ai/commons");
|
|
8
8
|
var _constants = require("../../constants.js");
|
|
9
|
-
var
|
|
9
|
+
var _clientSdkWorkflow = require("@miso.ai/client-sdk-workflow");
|
|
10
10
|
var _template = _interopRequireDefault(require("../template.js"));
|
|
11
11
|
var _templates = require("../templates.js");
|
|
12
12
|
var _svgs = require("../../asset/svgs.js");
|
|
@@ -14,7 +14,7 @@ var _dom = require("../../util/dom.js");
|
|
|
14
14
|
const _excluded = ["className", "templates", "autocomplete"];
|
|
15
15
|
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
16
16
|
function _objectWithoutPropertiesLoose(r, e) { if (null == r) return {}; var t = {}; for (var n in r) if ({}.hasOwnProperty.call(r, n)) { if (-1 !== e.indexOf(n)) continue; t[n] = r[n]; } return t; }
|
|
17
|
-
const TYPE =
|
|
17
|
+
const TYPE = _constants.LAYOUT_TYPE.SEARCH_BOX;
|
|
18
18
|
const DEFAULT_CLASSNAME = 'miso-search-box';
|
|
19
19
|
const DEFAULT_AUTOCOMPLETE_CLASSNAME = 'miso-autocomplete';
|
|
20
20
|
function root(layout) {
|
|
@@ -170,9 +170,31 @@ class SearchBoxLayout extends _template.default {
|
|
|
170
170
|
proxyElement,
|
|
171
171
|
hub
|
|
172
172
|
} = view;
|
|
173
|
-
this._unsubscribes = [...this._unsubscribes, proxyElement.on('input', e => this._syncInput(e)), proxyElement.on('keydown', e => this._handleKeyDown(e)), proxyElement.on('click', e => this._handleClick(e)), proxyElement.on('focusin', e => this._handleFocusIn(e)), proxyElement.on('focusout', e => this._handleFocusOut(e)), hub.on(
|
|
173
|
+
this._unsubscribes = [...this._unsubscribes, proxyElement.on('input', e => this._syncInput(e)), proxyElement.on('keydown', e => this._handleKeyDown(e)), proxyElement.on('click', e => this._handleClick(e)), proxyElement.on('focusin', e => this._handleFocusIn(e)), proxyElement.on('focusout', e => this._handleFocusOut(e)), hub.on(_clientSdkWorkflow.fields.completions(), () => view.refresh({
|
|
174
174
|
force: true
|
|
175
175
|
}))];
|
|
176
|
+
if (this.options.disableWhenOngoing) {
|
|
177
|
+
// disable submission while the main view is still displaying an answer
|
|
178
|
+
const mainRole = view.workflow._roles && view.workflow._roles.main;
|
|
179
|
+
if (mainRole) {
|
|
180
|
+
this._unsubscribes.push(hub.on(_clientSdkWorkflow.fields.view(mainRole), state => this._syncDisabled(!!state.ongoing)));
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
_syncDisabled(disabled) {
|
|
185
|
+
if (this._disabled === disabled) {
|
|
186
|
+
return;
|
|
187
|
+
}
|
|
188
|
+
this._disabled = disabled;
|
|
189
|
+
this._syncDisabledAttributes();
|
|
190
|
+
}
|
|
191
|
+
_syncDisabledAttributes() {
|
|
192
|
+
// the user can keep typing; only submission is disabled
|
|
193
|
+
const element = this._element;
|
|
194
|
+
const button = element && element.querySelector(`[data-role="submit"]`);
|
|
195
|
+
if (button) {
|
|
196
|
+
button.disabled = !!this._disabled;
|
|
197
|
+
}
|
|
176
198
|
}
|
|
177
199
|
focus() {
|
|
178
200
|
// TODO: support blur as well
|
|
@@ -203,7 +225,7 @@ class SearchBoxLayout extends _template.default {
|
|
|
203
225
|
state
|
|
204
226
|
});
|
|
205
227
|
return Object.assign({}, state, {
|
|
206
|
-
completions: this._view.hub.states[
|
|
228
|
+
completions: this._view.hub.states[_clientSdkWorkflow.fields.completions()]
|
|
207
229
|
});
|
|
208
230
|
}
|
|
209
231
|
_render(element, data, controls) {
|
|
@@ -216,6 +238,7 @@ class SearchBoxLayout extends _template.default {
|
|
|
216
238
|
_afterRender(element, state) {
|
|
217
239
|
this._fullfillFocusRequest(element);
|
|
218
240
|
this._fullfillValueRequest(element);
|
|
241
|
+
this._syncDisabledAttributes(); // a re-render replaces the input element
|
|
219
242
|
}
|
|
220
243
|
_updateCompletions(element, {
|
|
221
244
|
state,
|
|
@@ -293,7 +316,7 @@ class SearchBoxLayout extends _template.default {
|
|
|
293
316
|
}
|
|
294
317
|
this._prevInput = value;
|
|
295
318
|
const self = this;
|
|
296
|
-
this._debounce(() => self._view.hub.update(
|
|
319
|
+
this._debounce(() => self._view.hub.update(_clientSdkWorkflow.fields.input(), {
|
|
297
320
|
value
|
|
298
321
|
}));
|
|
299
322
|
}
|
|
@@ -325,7 +348,9 @@ class SearchBoxLayout extends _template.default {
|
|
|
325
348
|
}) {
|
|
326
349
|
if (!isComposing && key === 'Enter' && target.matches('[data-role="input"]')) {
|
|
327
350
|
this._submit(target.value);
|
|
328
|
-
|
|
351
|
+
if (this.options.blurOnSubmit !== false) {
|
|
352
|
+
target.blur();
|
|
353
|
+
}
|
|
329
354
|
}
|
|
330
355
|
// TODO: select completion items with arrow keys
|
|
331
356
|
}
|
|
@@ -339,7 +364,9 @@ class SearchBoxLayout extends _template.default {
|
|
|
339
364
|
for (let element = target; element && element !== this._element; element = element.parentElement) {
|
|
340
365
|
if (element.matches('[data-role="submit"]') || element.matches('[data-role="button"]') || element.matches('[type="submit"]')) {
|
|
341
366
|
if (inputElement) {
|
|
342
|
-
|
|
367
|
+
if (this.options.blurOnSubmit !== false) {
|
|
368
|
+
inputElement.blur();
|
|
369
|
+
}
|
|
343
370
|
this._submit(inputElement.value);
|
|
344
371
|
}
|
|
345
372
|
return;
|
|
@@ -375,14 +402,20 @@ class SearchBoxLayout extends _template.default {
|
|
|
375
402
|
}
|
|
376
403
|
}
|
|
377
404
|
async _submit(value) {
|
|
378
|
-
if (!value || !value.trim()) {
|
|
405
|
+
if (this._disabled || !value || !value.trim()) {
|
|
379
406
|
return;
|
|
380
407
|
}
|
|
381
408
|
this.close();
|
|
382
409
|
// TODO: q -> value
|
|
383
|
-
this._view.hub.update(
|
|
410
|
+
this._view.hub.update(_clientSdkWorkflow.fields.query(), {
|
|
384
411
|
q: value
|
|
385
412
|
});
|
|
413
|
+
if (this.options.clearOnSubmit) {
|
|
414
|
+
const inputElement = this._element && this._element.querySelector(`[data-role="input"]`);
|
|
415
|
+
if (inputElement) {
|
|
416
|
+
inputElement.value = '';
|
|
417
|
+
}
|
|
418
|
+
}
|
|
386
419
|
this._trackSubmit(value);
|
|
387
420
|
}
|
|
388
421
|
_trackSubmit(value) {
|
|
@@ -4,13 +4,14 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
6
|
exports.default = void 0;
|
|
7
|
+
var _constants = require("../../constants.js");
|
|
7
8
|
var _commons = require("@miso.ai/commons");
|
|
8
9
|
var _template = _interopRequireDefault(require("../template.js"));
|
|
9
10
|
var _trackable = require("../mixin/trackable.js");
|
|
10
11
|
const _excluded = ["className", "templates"];
|
|
11
12
|
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
12
13
|
function _objectWithoutPropertiesLoose(r, e) { if (null == r) return {}; var t = {}; for (var n in r) if ({}.hasOwnProperty.call(r, n)) { if (-1 !== e.indexOf(n)) continue; t[n] = r[n]; } return t; }
|
|
13
|
-
const TYPE =
|
|
14
|
+
const TYPE = _constants.LAYOUT_TYPE.SELECT;
|
|
14
15
|
const DEFAULT_CLASSNAME = 'miso-select';
|
|
15
16
|
function root(layout, state) {
|
|
16
17
|
const {
|
|
@@ -4,11 +4,12 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
6
|
exports.default = void 0;
|
|
7
|
+
var _constants = require("../../constants.js");
|
|
7
8
|
var _collection = _interopRequireDefault(require("./collection.js"));
|
|
8
9
|
const _excluded = ["className"];
|
|
9
10
|
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
10
11
|
function _objectWithoutPropertiesLoose(r, e) { if (null == r) return {}; var t = {}; for (var n in r) if ({}.hasOwnProperty.call(r, n)) { if (-1 !== e.indexOf(n)) continue; t[n] = r[n]; } return t; }
|
|
11
|
-
const TYPE =
|
|
12
|
+
const TYPE = _constants.LAYOUT_TYPE.CARDS;
|
|
12
13
|
const DEFAULT_CLASSNAME = 'miso-cards';
|
|
13
14
|
class CardsLayout extends _collection.default {
|
|
14
15
|
static get type() {
|
|
@@ -4,13 +4,14 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
6
|
exports.default = void 0;
|
|
7
|
+
var _constants = require("../../constants.js");
|
|
7
8
|
var _collection = _interopRequireDefault(require("./collection.js"));
|
|
8
9
|
var _swipeable = require("../mixin/swipeable.js");
|
|
9
10
|
var _svgs = require("../../asset/svgs.js");
|
|
10
11
|
const _excluded = ["className", "templates"];
|
|
11
12
|
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
12
13
|
function _objectWithoutPropertiesLoose(r, e) { if (null == r) return {}; var t = {}; for (var n in r) if ({}.hasOwnProperty.call(r, n)) { if (-1 !== e.indexOf(n)) continue; t[n] = r[n]; } return t; }
|
|
13
|
-
const TYPE =
|
|
14
|
+
const TYPE = _constants.LAYOUT_TYPE.CAROUSEL;
|
|
14
15
|
const DEFAULT_CLASSNAME = 'miso-carousel';
|
|
15
16
|
const DEFAULT_TEMPLATES = Object.freeze({
|
|
16
17
|
body,
|
|
@@ -95,6 +95,11 @@ const DEFAULT_TEMPLATES = Object.freeze({
|
|
|
95
95
|
compactArticle: _templates.compactArticle,
|
|
96
96
|
image: _templates.image,
|
|
97
97
|
question: _templates.question,
|
|
98
|
+
thread: _templates.thread,
|
|
99
|
+
threadMenuBlock: _templates.threadMenuBlock,
|
|
100
|
+
message: _templates.message,
|
|
101
|
+
messageQuestionBlock: _templates.messageQuestionBlock,
|
|
102
|
+
messageAnswerBlock: _templates.messageAnswerBlock,
|
|
98
103
|
root,
|
|
99
104
|
[_constants.STATUS.READY]: ready,
|
|
100
105
|
empty: () => ``,
|
|
@@ -4,6 +4,7 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
6
|
exports.default = void 0;
|
|
7
|
+
var _constants = require("../../constants.js");
|
|
7
8
|
var _commons = require("@miso.ai/commons");
|
|
8
9
|
var _collection = _interopRequireDefault(require("./collection.js"));
|
|
9
10
|
var _dom = require("../../util/dom.js");
|
|
@@ -43,7 +44,7 @@ const DEFAULT_HEIGHT = '16rem';
|
|
|
43
44
|
const DEFAULT_TEMPLATES = Object.freeze(Object.assign({}, _collection.default.defaultTemplates, {
|
|
44
45
|
item
|
|
45
46
|
}));
|
|
46
|
-
const TYPE =
|
|
47
|
+
const TYPE = _constants.LAYOUT_TYPE.GALLERY;
|
|
47
48
|
const DEFAULT_CLASSNAME = 'miso-gallery';
|
|
48
49
|
class GalleryLayout extends _collection.default {
|
|
49
50
|
static get type() {
|
|
@@ -4,11 +4,12 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
6
|
exports.default = void 0;
|
|
7
|
+
var _constants = require("../../constants.js");
|
|
7
8
|
var _collection = _interopRequireDefault(require("./collection.js"));
|
|
8
9
|
const _excluded = ["className"];
|
|
9
10
|
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
10
11
|
function _objectWithoutPropertiesLoose(r, e) { if (null == r) return {}; var t = {}; for (var n in r) if ({}.hasOwnProperty.call(r, n)) { if (-1 !== e.indexOf(n)) continue; t[n] = r[n]; } return t; }
|
|
11
|
-
const TYPE =
|
|
12
|
+
const TYPE = _constants.LAYOUT_TYPE.HORIZONTAL;
|
|
12
13
|
const DEFAULT_CLASSNAME = 'miso-horizontal';
|
|
13
14
|
class HorizontalLayout extends _collection.default {
|
|
14
15
|
static get type() {
|
|
@@ -4,11 +4,12 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
6
|
exports.default = void 0;
|
|
7
|
+
var _constants = require("../../constants.js");
|
|
7
8
|
var _collection = _interopRequireDefault(require("./collection.js"));
|
|
8
9
|
const _excluded = ["className"];
|
|
9
10
|
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
10
11
|
function _objectWithoutPropertiesLoose(r, e) { if (null == r) return {}; var t = {}; for (var n in r) if ({}.hasOwnProperty.call(r, n)) { if (-1 !== e.indexOf(n)) continue; t[n] = r[n]; } return t; }
|
|
11
|
-
const TYPE =
|
|
12
|
+
const TYPE = _constants.LAYOUT_TYPE.LIST;
|
|
12
13
|
const DEFAULT_CLASSNAME = 'miso-list';
|
|
13
14
|
class ListLayout extends _collection.default {
|
|
14
15
|
static get type() {
|
|
@@ -0,0 +1,346 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.default = void 0;
|
|
7
|
+
var _commons = require("@miso.ai/commons");
|
|
8
|
+
var _clientSdkWorkflow = require("@miso.ai/client-sdk-workflow");
|
|
9
|
+
var _constants = require("../../constants.js");
|
|
10
|
+
var _collection = _interopRequireDefault(require("./collection.js"));
|
|
11
|
+
var _utils = require("../text/typewriter/utils.js");
|
|
12
|
+
var _templates = require("../templates.js");
|
|
13
|
+
var _dom = require("../../util/dom.js");
|
|
14
|
+
const _excluded = ["className"];
|
|
15
|
+
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
16
|
+
function _objectWithoutPropertiesLoose(r, e) { if (null == r) return {}; var t = {}; for (var n in r) if ({}.hasOwnProperty.call(r, n)) { if (-1 !== e.indexOf(n)) continue; t[n] = r[n]; } return t; }
|
|
17
|
+
const TYPE = _constants.LAYOUT_TYPE.MESSAGES;
|
|
18
|
+
const DEFAULT_CLASSNAME = 'miso-messages';
|
|
19
|
+
const TYPEWRITER_CLASSNAME = 'miso-typewriter';
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* The conversation panel of the chat history interface: a list of `message`
|
|
23
|
+
* items (question bubble + answer body), rendered incrementally — appended
|
|
24
|
+
* messages (e.g. a posted follow-up question) render as new items, while
|
|
25
|
+
* in-place changes are applied to existing items by a post-render pass
|
|
26
|
+
* (`_syncMessages`):
|
|
27
|
+
*
|
|
28
|
+
* - question texts are filled in when they arrive (the head request carries
|
|
29
|
+
* question ids only)
|
|
30
|
+
* - a finished answer body is transformed from markdown to HTML in one shot
|
|
31
|
+
* through the `std:ui-markdown` plugin
|
|
32
|
+
* - a streaming answer (a follow-up being generated, `finished: false`) is
|
|
33
|
+
* driven by a per-message typewriter: a progressive markdown renderer with
|
|
34
|
+
* a paced cursor, like the typewriter layout of the ask workflow
|
|
35
|
+
*/
|
|
36
|
+
class MessagesLayout extends _collection.default {
|
|
37
|
+
static get type() {
|
|
38
|
+
return TYPE;
|
|
39
|
+
}
|
|
40
|
+
static get defaultClassName() {
|
|
41
|
+
return DEFAULT_CLASSNAME;
|
|
42
|
+
}
|
|
43
|
+
constructor(_ref = {}) {
|
|
44
|
+
let {
|
|
45
|
+
className = DEFAULT_CLASSNAME
|
|
46
|
+
} = _ref,
|
|
47
|
+
options = _objectWithoutPropertiesLoose(_ref, _excluded);
|
|
48
|
+
super(Object.assign({
|
|
49
|
+
className
|
|
50
|
+
}, options));
|
|
51
|
+
this._renderedAnswers = new WeakMap(); // answer element -> rendered markdown
|
|
52
|
+
this._typewriters = new WeakMap(); // answer element -> MessageTypewriter
|
|
53
|
+
this._readiness = new _commons.Resolution();
|
|
54
|
+
this._pinned = true; // whether the view sticks to the bottom on updates
|
|
55
|
+
this._displaying = false; // whether a typewriter is still displaying an answer
|
|
56
|
+
// kick off sooner
|
|
57
|
+
MessagesLayout.MisoClient.plugins.install('std:ui-markdown');
|
|
58
|
+
}
|
|
59
|
+
initialize(view) {
|
|
60
|
+
super.initialize(view);
|
|
61
|
+
this._setup();
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// setup //
|
|
65
|
+
async _setup() {
|
|
66
|
+
try {
|
|
67
|
+
const plugin = await MessagesLayout.MisoClient.plugins.install('std:ui-markdown');
|
|
68
|
+
if (!this._view) {
|
|
69
|
+
return; // destroyed
|
|
70
|
+
}
|
|
71
|
+
this._markdown = plugin.getContext(this._view.workflow._client);
|
|
72
|
+
this._readiness.resolve();
|
|
73
|
+
} catch (e) {
|
|
74
|
+
this._readiness.reject(e);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
async _ready() {
|
|
78
|
+
return this._readiness.promise;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// render //
|
|
82
|
+
async render(element, state, controls = {}) {
|
|
83
|
+
// capture the view state callback, so the typewriter can report the
|
|
84
|
+
// `ongoing` state outside the render cycle
|
|
85
|
+
this._notifyUpdate = controls.notifyUpdate;
|
|
86
|
+
await super.render(element, state, controls);
|
|
87
|
+
}
|
|
88
|
+
_afterRender(element, state) {
|
|
89
|
+
super._afterRender(element, state); // syncs bindings to the latest values
|
|
90
|
+
if (!state.incremental) {
|
|
91
|
+
this._displaying = false; // a fresh render (thread load) drops any ongoing typewriter
|
|
92
|
+
}
|
|
93
|
+
if (!state.incremental || state.html) {
|
|
94
|
+
// a fresh render (thread load) or appended items (posted follow-up):
|
|
95
|
+
// jump to the bottom
|
|
96
|
+
this._scrollToBottom({
|
|
97
|
+
force: true
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
this._syncMessages(element).catch(error => console.error(error));
|
|
101
|
+
}
|
|
102
|
+
async _syncMessages(element) {
|
|
103
|
+
await this._ready();
|
|
104
|
+
const items = this._getItemElements(element);
|
|
105
|
+
let displaying = false;
|
|
106
|
+
for (let i = 0; i < items.length; i++) {
|
|
107
|
+
const item = items[i];
|
|
108
|
+
const binding = this._bindings.get(item);
|
|
109
|
+
if (!binding) {
|
|
110
|
+
continue;
|
|
111
|
+
}
|
|
112
|
+
const message = binding.value;
|
|
113
|
+
const last = i === items.length - 1;
|
|
114
|
+
this._syncQuestion(item, message);
|
|
115
|
+
this._syncAnswer(item, message, {
|
|
116
|
+
last
|
|
117
|
+
});
|
|
118
|
+
if (last) {
|
|
119
|
+
displaying = this._isDisplaying(item, message);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
this._setDisplaying(displaying);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// whether the (last) message pair is still being displayed: its answer is
|
|
126
|
+
// pending, streaming, or still being typed — live (posted in this session)
|
|
127
|
+
// or not: an answer still generating is picked up by the answers polling
|
|
128
|
+
// even after switching away from the thread and back, and must keep
|
|
129
|
+
// blocking submission all the same
|
|
130
|
+
_isDisplaying(item, message) {
|
|
131
|
+
if (!(0, _clientSdkWorkflow.hasAnswer)(message)) {
|
|
132
|
+
return true; // waiting for the answer body
|
|
133
|
+
}
|
|
134
|
+
const answerElement = item.querySelector('[data-role="answer"]');
|
|
135
|
+
const typewriter = answerElement && this._typewriters.get(answerElement);
|
|
136
|
+
return typewriter ? !typewriter.done : message.finished === false;
|
|
137
|
+
}
|
|
138
|
+
_syncQuestion(item, message) {
|
|
139
|
+
const questionElement = item.querySelector('[data-role="question"]');
|
|
140
|
+
if (!questionElement) {
|
|
141
|
+
return;
|
|
142
|
+
}
|
|
143
|
+
// the authorship arrives with the answers response, after the stub render
|
|
144
|
+
(0, _dom.setOrRemoveAttribute)(questionElement, 'data-author', (0, _templates.messageAuthor)(message));
|
|
145
|
+
(0, _dom.setOrRemoveAttribute)(questionElement, 'data-generated-by', (0, _clientSdkWorkflow.getGeneratedBy)(message));
|
|
146
|
+
const {
|
|
147
|
+
question
|
|
148
|
+
} = message;
|
|
149
|
+
if (!question || questionElement.textContent === question) {
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
152
|
+
questionElement.textContent = question;
|
|
153
|
+
questionElement.hidden = false;
|
|
154
|
+
}
|
|
155
|
+
_syncAnswer(item, message, {
|
|
156
|
+
last = false
|
|
157
|
+
} = {}) {
|
|
158
|
+
const answerElement = item.querySelector('[data-role="answer"]');
|
|
159
|
+
if (!answerElement) {
|
|
160
|
+
return;
|
|
161
|
+
}
|
|
162
|
+
// an ongoing typewriter keeps consuming updates until it finishes typing
|
|
163
|
+
const typewriter = this._typewriters.get(answerElement);
|
|
164
|
+
if (typewriter) {
|
|
165
|
+
typewriter.update(message);
|
|
166
|
+
return;
|
|
167
|
+
}
|
|
168
|
+
if (!(0, _clientSdkWorkflow.hasAnswer)(message)) {
|
|
169
|
+
return; // still loading; the spinner stays
|
|
170
|
+
}
|
|
171
|
+
if (message.live || message.finished === false) {
|
|
172
|
+
// an answer being generated live in this session: drive it with a
|
|
173
|
+
// typewriter (even if the data arrived complete in one shot)
|
|
174
|
+
const typewriter = new MessageTypewriter(this._markdown, answerElement, {
|
|
175
|
+
onUpdate: () => this._scrollToBottom(),
|
|
176
|
+
// keep pinned to the bottom while typing
|
|
177
|
+
onDone: () => this._setDisplaying(false)
|
|
178
|
+
});
|
|
179
|
+
this._typewriters.set(answerElement, typewriter);
|
|
180
|
+
typewriter.update(message);
|
|
181
|
+
return;
|
|
182
|
+
}
|
|
183
|
+
// a finished answer: transform in one shot
|
|
184
|
+
if (this._renderedAnswers.get(answerElement) === message.answer) {
|
|
185
|
+
return; // already rendered
|
|
186
|
+
}
|
|
187
|
+
this._renderedAnswers.set(answerElement, message.answer);
|
|
188
|
+
this._transform(answerElement, message).then(() => {
|
|
189
|
+
last && this._scrollToBottom();
|
|
190
|
+
}).catch(error => {
|
|
191
|
+
this._renderedAnswers.delete(answerElement);
|
|
192
|
+
console.error(error);
|
|
193
|
+
});
|
|
194
|
+
}
|
|
195
|
+
async _transform(answerElement, {
|
|
196
|
+
answer,
|
|
197
|
+
sources
|
|
198
|
+
}) {
|
|
199
|
+
answerElement.innerHTML = await this._markdown.transform(answer, sources);
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
// whether the last answer is still being displayed (typed); reported as
|
|
203
|
+
// the `ongoing` view state, e.g. for the search box to disable submission
|
|
204
|
+
_setDisplaying(displaying) {
|
|
205
|
+
if (this._displaying === displaying) {
|
|
206
|
+
return;
|
|
207
|
+
}
|
|
208
|
+
this._displaying = displaying;
|
|
209
|
+
this._notifyUpdate && this._notifyUpdate({
|
|
210
|
+
ongoing: displaying
|
|
211
|
+
});
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
// scrolling //
|
|
215
|
+
/**
|
|
216
|
+
* Scroll the containing scrollable to the bottom. Unless forced, only
|
|
217
|
+
* applies while the user is pinned to the bottom — scrolling up to read
|
|
218
|
+
* releases the pin, scrolling back down restores it.
|
|
219
|
+
*/
|
|
220
|
+
_scrollToBottom({
|
|
221
|
+
force = false
|
|
222
|
+
} = {}) {
|
|
223
|
+
const scrollable = this._getScrollable();
|
|
224
|
+
if (!scrollable || !(force || this._pinned)) {
|
|
225
|
+
return;
|
|
226
|
+
}
|
|
227
|
+
scrollable.scrollTop = scrollable.scrollHeight;
|
|
228
|
+
this._pinned = true;
|
|
229
|
+
}
|
|
230
|
+
_getScrollable() {
|
|
231
|
+
const element = this._element;
|
|
232
|
+
if (!element || typeof getComputedStyle === 'undefined') {
|
|
233
|
+
return undefined;
|
|
234
|
+
}
|
|
235
|
+
for (let el = element; el && el.nodeType === 1 && el !== document.body; el = el.parentElement) {
|
|
236
|
+
const {
|
|
237
|
+
overflowY
|
|
238
|
+
} = getComputedStyle(el);
|
|
239
|
+
if (overflowY === 'auto' || overflowY === 'scroll') {
|
|
240
|
+
this._watchScroll(el);
|
|
241
|
+
return el;
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
return undefined;
|
|
245
|
+
}
|
|
246
|
+
_watchScroll(scrollable) {
|
|
247
|
+
if (this._watchedScrollable === scrollable) {
|
|
248
|
+
return;
|
|
249
|
+
}
|
|
250
|
+
this._unwatchScroll && this._unwatchScroll();
|
|
251
|
+
const onScroll = () => {
|
|
252
|
+
this._pinned = scrollable.scrollHeight - scrollable.scrollTop - scrollable.clientHeight < 40;
|
|
253
|
+
};
|
|
254
|
+
scrollable.addEventListener('scroll', onScroll, {
|
|
255
|
+
passive: true
|
|
256
|
+
});
|
|
257
|
+
this._watchedScrollable = scrollable;
|
|
258
|
+
const unwatch = this._unwatchScroll = () => {
|
|
259
|
+
scrollable.removeEventListener('scroll', onScroll);
|
|
260
|
+
this._watchedScrollable = undefined;
|
|
261
|
+
this._unwatchScroll = undefined;
|
|
262
|
+
};
|
|
263
|
+
this._unsubscribes.push(() => this._unwatchScroll === unwatch && unwatch());
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
// TODO: can't we just use Controller?
|
|
268
|
+
/**
|
|
269
|
+
* Types a streaming answer into an element: a progressive markdown renderer
|
|
270
|
+
* fed by data updates, advanced by a paced cursor on animation frames — the
|
|
271
|
+
* typewriting effect, without the full typewriter layout machinery.
|
|
272
|
+
*/
|
|
273
|
+
exports.default = MessagesLayout;
|
|
274
|
+
class MessageTypewriter {
|
|
275
|
+
constructor(markdown, element, {
|
|
276
|
+
onUpdate,
|
|
277
|
+
onDone
|
|
278
|
+
} = {}) {
|
|
279
|
+
this._element = element;
|
|
280
|
+
this._onUpdate = onUpdate;
|
|
281
|
+
this._onDone = onDone;
|
|
282
|
+
// the element acts as a typewriter container: it starts as the caret ref
|
|
283
|
+
// (the cursor class moves into the content as it types), and the preset
|
|
284
|
+
// stamps the `done` class on finish, which hides the caret via CSS
|
|
285
|
+
element.classList.add(TYPEWRITER_CLASSNAME, (0, _utils.cursorClassName)(TYPEWRITER_CLASSNAME));
|
|
286
|
+
this._renderer = markdown.createRenderer({
|
|
287
|
+
cursorClass: (0, _utils.cursorClassName)(TYPEWRITER_CLASSNAME),
|
|
288
|
+
getSource: index => (this._sources || [])[index]
|
|
289
|
+
});
|
|
290
|
+
this._getNextCursor = (0, _commons.pacer)();
|
|
291
|
+
this._rendered = this._renderer.clear(element);
|
|
292
|
+
this._timestamp = undefined;
|
|
293
|
+
this._value = '';
|
|
294
|
+
this._sources = undefined;
|
|
295
|
+
this._dataDone = false;
|
|
296
|
+
this._doneAt = undefined;
|
|
297
|
+
this._requested = false;
|
|
298
|
+
}
|
|
299
|
+
get done() {
|
|
300
|
+
return this._rendered.done;
|
|
301
|
+
}
|
|
302
|
+
update({
|
|
303
|
+
answer = '',
|
|
304
|
+
finished,
|
|
305
|
+
sources
|
|
306
|
+
}) {
|
|
307
|
+
this._value = answer;
|
|
308
|
+
this._sources = sources;
|
|
309
|
+
this._dataDone = finished !== false;
|
|
310
|
+
this._requestFrame();
|
|
311
|
+
}
|
|
312
|
+
_requestFrame() {
|
|
313
|
+
if (this._requested || this._rendered.done) {
|
|
314
|
+
return;
|
|
315
|
+
}
|
|
316
|
+
this._requested = true;
|
|
317
|
+
(0, _commons.requestAnimationFrame)(timestamp => this._frame(timestamp));
|
|
318
|
+
}
|
|
319
|
+
_frame(timestamp) {
|
|
320
|
+
this._requested = false;
|
|
321
|
+
if (!this._element.isConnected) {
|
|
322
|
+
// the element is gone (re-render, thread switch); stop typing
|
|
323
|
+
this._onDone && this._onDone();
|
|
324
|
+
return;
|
|
325
|
+
}
|
|
326
|
+
const prev = this._rendered;
|
|
327
|
+
const prevTimestamp = this._timestamp !== undefined ? this._timestamp : timestamp;
|
|
328
|
+
if (this._dataDone && this._doneAt === undefined) {
|
|
329
|
+
this._doneAt = timestamp;
|
|
330
|
+
}
|
|
331
|
+
const cursor = this._getNextCursor(prev.cursor, this._doneAt, prevTimestamp, timestamp);
|
|
332
|
+
this._rendered = this._renderer.update(this._element, prev, {
|
|
333
|
+
value: this._value,
|
|
334
|
+
cursor,
|
|
335
|
+
timestamp,
|
|
336
|
+
done: this._dataDone
|
|
337
|
+
});
|
|
338
|
+
this._timestamp = timestamp;
|
|
339
|
+
this._onUpdate && this._onUpdate();
|
|
340
|
+
if (!this._rendered.done) {
|
|
341
|
+
this._requestFrame();
|
|
342
|
+
} else {
|
|
343
|
+
this._onDone && this._onDone();
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
}
|