@miso.ai/client-sdk-ui 1.13.2-beta.1 → 1.14.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.
- package/dist/cjs/asset/svgs.js +17 -4
- package/dist/cjs/combo/ask/index.js +2 -2
- package/dist/cjs/constants.js +120 -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 +259 -0
- package/dist/cjs/element/container/index.js +28 -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-message-item.js +91 -0
- package/dist/cjs/element/container/miso-recommendation.js +1 -1
- package/dist/cjs/element/container/miso-search.js +1 -1
- package/dist/cjs/element/container/miso-thread-item.js +91 -0
- package/dist/cjs/element/context/miso-follow-ups.js +1 -1
- package/dist/cjs/element/role/index.js +49 -0
- package/dist/cjs/element/role/miso-delete.js +20 -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 +170 -0
- package/dist/cjs/layout/button/checkbox.js +116 -0
- package/dist/cjs/layout/button/more-button.js +3 -3
- package/dist/cjs/layout/container/container.js +1 -1
- package/dist/cjs/layout/container/item-container.js +99 -0
- package/dist/cjs/layout/error/error.js +2 -1
- package/dist/cjs/layout/index.js +42 -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 +50 -12
- 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 +13 -1
- 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 +359 -0
- package/dist/cjs/layout/list/threads.js +199 -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 +97 -0
- package/dist/cjs/layout/text/question.js +71 -0
- package/dist/cjs/layout/text/text.js +2 -1
- package/dist/cjs/layout/text/typewriter/index.js +18 -23
- package/dist/cjs/plugin.js +43 -104
- package/dist/cjs/util/confirm.js +33 -0
- package/dist/cjs/util/dom.js +21 -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 +51 -104
- package/src/asset/svgs.js +16 -3
- package/src/combo/ask/index.js +2 -2
- package/src/constants.js +39 -147
- package/src/defaults/ask/controls.js +1 -1
- package/src/defaults/hybrid-search/answer-box.js +2 -2
- package/src/defaults.js +174 -0
- package/src/element/container/index.js +4 -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-message-item.js +94 -0
- package/src/element/container/miso-recommendation.js +1 -1
- package/src/element/container/miso-search.js +1 -1
- package/src/element/container/miso-thread-item.js +94 -0
- package/src/element/context/miso-follow-ups.js +1 -1
- package/src/element/role/index.js +7 -0
- package/src/element/role/miso-delete.js +16 -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 +152 -0
- package/src/layout/button/checkbox.js +92 -0
- package/src/layout/button/more-button.js +3 -3
- package/src/layout/container/container.js +2 -2
- package/src/layout/container/item-container.js +99 -0
- package/src/layout/error/error.js +2 -1
- package/src/layout/index.js +6 -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 +45 -8
- 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 +15 -2
- 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 +316 -0
- package/src/layout/list/threads.js +166 -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 +97 -0
- package/src/layout/text/question.js +58 -0
- package/src/layout/text/text.js +2 -1
- package/src/layout/text/typewriter/index.js +15 -18
- package/src/plugin.js +31 -117
- package/src/util/confirm.js +28 -0
- package/src/util/dom.js +16 -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
package/dist/cjs/plugin.js
CHANGED
|
@@ -5,15 +5,18 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
5
5
|
});
|
|
6
6
|
exports.default = void 0;
|
|
7
7
|
var _commons = require("@miso.ai/commons");
|
|
8
|
-
var
|
|
9
|
-
var
|
|
8
|
+
var _clientSdkWorkflow = require("@miso.ai/client-sdk-workflow");
|
|
9
|
+
var _defaults = require("./defaults.js");
|
|
10
|
+
var _index = require("./combo/index.js");
|
|
10
11
|
var _layouts = _interopRequireDefault(require("./layouts.js"));
|
|
11
12
|
var elements = _interopRequireWildcard(require("./element/index.js"));
|
|
12
13
|
var layouts = _interopRequireWildcard(require("./layout/index.js"));
|
|
13
|
-
var sources = _interopRequireWildcard(require("./source.js"));
|
|
14
14
|
var defaults = _interopRequireWildcard(require("./defaults/index.js"));
|
|
15
|
+
var _templates = require("./defaults/ask/templates.js");
|
|
15
16
|
var traits = _interopRequireWildcard(require("./trait/index.js"));
|
|
16
17
|
var _styles = require("./styles.js");
|
|
18
|
+
var _confirm = _interopRequireDefault(require("./util/confirm.js"));
|
|
19
|
+
var _prompt = _interopRequireDefault(require("./util/prompt.js"));
|
|
17
20
|
var _misoContainer = _interopRequireDefault(require("./element/container/miso-container.js"));
|
|
18
21
|
var _misoContext = _interopRequireDefault(require("./element/context/miso-context.js"));
|
|
19
22
|
var _misoCombo = _interopRequireDefault(require("./element/combo/miso-combo.js"));
|
|
@@ -29,23 +32,29 @@ class UiPlugin extends _commons.Component {
|
|
|
29
32
|
constructor() {
|
|
30
33
|
super('ui');
|
|
31
34
|
this.layouts = new _layouts.default(this);
|
|
32
|
-
this._recommendations = new WeakMap();
|
|
33
|
-
this._explores = new WeakMap();
|
|
34
|
-
this._asks = new WeakMap();
|
|
35
|
-
this._extensions = new WeakMap();
|
|
36
35
|
this._ready = new _commons.Resolution();
|
|
37
36
|
}
|
|
38
|
-
async install(MisoClient, {
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
37
|
+
async install(MisoClient, context) {
|
|
38
|
+
const {
|
|
39
|
+
addSubtree,
|
|
40
|
+
addExtensionPoints
|
|
41
|
+
} = context;
|
|
42
|
+
this._pluginContext = context;
|
|
42
43
|
addSubtree(this);
|
|
44
|
+
|
|
45
|
+
// make sure the workflow plugin is installed, then provide the layout
|
|
46
|
+
// registry and seed the default layout options
|
|
47
|
+
MisoClient.plugins.use(_clientSdkWorkflow.WorkflowPlugin);
|
|
48
|
+
context.workflows.plugin.setLayouts(this.layouts);
|
|
49
|
+
this._seedWorkflowDefaults(context.workflows.defaults);
|
|
43
50
|
MisoClient.on('create', this._injectClient.bind(this));
|
|
44
51
|
|
|
45
52
|
// the UI interface for MisoClient
|
|
46
53
|
const ui = {
|
|
47
54
|
defaults,
|
|
48
|
-
traits
|
|
55
|
+
traits,
|
|
56
|
+
confirm: _confirm.default,
|
|
57
|
+
prompt: _prompt.default
|
|
49
58
|
};
|
|
50
59
|
(0, _commons.delegateGetters)(ui, this, ['layouts', 'ready']);
|
|
51
60
|
(0, _commons.defineValues)(this, {
|
|
@@ -96,70 +105,33 @@ class UiPlugin extends _commons.Component {
|
|
|
96
105
|
await (0, _styles.loadStylesIfNecessary)();
|
|
97
106
|
this._ready.resolve();
|
|
98
107
|
}
|
|
99
|
-
async requireExtension(name) {
|
|
100
|
-
switch (name) {
|
|
101
|
-
case 'markdown':
|
|
102
|
-
return await this.MisoClient.plugins.install('std:ui-markdown');
|
|
103
|
-
default:
|
|
104
|
-
throw new Error(`Unknown extension: ${name}`);
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
108
|
get ready() {
|
|
108
109
|
return this._ready.promise;
|
|
109
110
|
}
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Seed the workflow plugin's defaults store with the presentational default
|
|
114
|
+
* options: layouts of each workflow, plus UI templates.
|
|
115
|
+
*/
|
|
116
|
+
_seedWorkflowDefaults(workflowDefaults) {
|
|
117
|
+
for (const [name, layouts] of Object.entries(_defaults.defaultLayouts)) {
|
|
118
|
+
workflowDefaults.set(name, {
|
|
119
|
+
layouts
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
workflowDefaults.set('ask', {
|
|
123
|
+
templates: {
|
|
124
|
+
followUp: _templates.followUp
|
|
125
|
+
}
|
|
126
|
+
});
|
|
127
|
+
}
|
|
110
128
|
_injectClient(client) {
|
|
111
129
|
(0, _commons.defineValues)(client, {
|
|
112
130
|
ui: new Ui(this, client)
|
|
113
131
|
});
|
|
114
132
|
}
|
|
115
|
-
_getExtensions(client) {
|
|
116
|
-
if (this._extensions.has(client)) {
|
|
117
|
-
return this._extensions.get(client);
|
|
118
|
-
}
|
|
119
|
-
const extensions = new Extensions(this, client);
|
|
120
|
-
this._extensions.set(client, extensions);
|
|
121
|
-
return extensions;
|
|
122
|
-
}
|
|
123
|
-
_getRecommendations(client) {
|
|
124
|
-
let recommendations = this._recommendations.get(client);
|
|
125
|
-
if (!recommendations) {
|
|
126
|
-
this._recommendations.set(client, recommendations = new _index.Recommendations(this, client));
|
|
127
|
-
}
|
|
128
|
-
return recommendations;
|
|
129
|
-
}
|
|
130
|
-
_getExplores(client) {
|
|
131
|
-
let explores = this._explores.get(client);
|
|
132
|
-
if (!explores) {
|
|
133
|
-
this._explores.set(client, explores = new _index.Explores(this, client));
|
|
134
|
-
}
|
|
135
|
-
return explores;
|
|
136
|
-
}
|
|
137
|
-
_getAsks(client) {
|
|
138
|
-
let asks = this._asks.get(client);
|
|
139
|
-
if (!asks) {
|
|
140
|
-
this._asks.set(client, asks = new _index.Asks(this, client));
|
|
141
|
-
}
|
|
142
|
-
return asks;
|
|
143
|
-
}
|
|
144
133
|
}
|
|
145
|
-
|
|
146
|
-
// TODO: are we able to eliminate the concept of extension, just use plugins?
|
|
147
134
|
exports.default = UiPlugin;
|
|
148
|
-
class Extensions {
|
|
149
|
-
constructor(plugin, client) {
|
|
150
|
-
this._plugin = plugin;
|
|
151
|
-
this._client = client;
|
|
152
|
-
this._contexts = {};
|
|
153
|
-
}
|
|
154
|
-
async require(name) {
|
|
155
|
-
if (this._contexts[name]) {
|
|
156
|
-
return this._contexts[name];
|
|
157
|
-
}
|
|
158
|
-
const plugin = await this._plugin.requireExtension(name);
|
|
159
|
-
const context = this._contexts[name] = plugin.getContext(this._client);
|
|
160
|
-
return context;
|
|
161
|
-
}
|
|
162
|
-
}
|
|
163
135
|
function createUiPluginContext(plugin, ui, MisoClient) {
|
|
164
136
|
async function addElementClasses(...ElementClasses) {
|
|
165
137
|
for (const ElementClass of ElementClasses) {
|
|
@@ -187,6 +159,9 @@ function createUiPluginContext(plugin, ui, MisoClient) {
|
|
|
187
159
|
};
|
|
188
160
|
}
|
|
189
161
|
|
|
162
|
+
// workflow accessors delegated to client.workflows for backward compatibility
|
|
163
|
+
const WORKFLOW_ACCESSORS = ['search', 'hybridSearch', 'asks', 'ask', 'explores', 'explore', 'recommendations', 'recommendation', 'sources'];
|
|
164
|
+
|
|
190
165
|
/**
|
|
191
166
|
* The UI interface for the client.
|
|
192
167
|
*/
|
|
@@ -194,43 +169,7 @@ class Ui {
|
|
|
194
169
|
constructor(plugin, client) {
|
|
195
170
|
this._plugin = plugin;
|
|
196
171
|
this._client = client;
|
|
197
|
-
(0, _commons.
|
|
198
|
-
sources: {
|
|
199
|
-
api: sources.api(client)
|
|
200
|
-
}
|
|
201
|
-
});
|
|
202
|
-
}
|
|
203
|
-
get recommendations() {
|
|
204
|
-
return this._recommendations || (this._recommendations = this._plugin._getRecommendations(this._client));
|
|
205
|
-
}
|
|
206
|
-
get recommendation() {
|
|
207
|
-
return this.recommendations.get(); // get default recommendation unit
|
|
208
|
-
}
|
|
209
|
-
get search() {
|
|
210
|
-
if (!this._search) {
|
|
211
|
-
this._search = new _index.Search(this._plugin, this._client);
|
|
212
|
-
this._client._events.emit('postworkflow', this._search);
|
|
213
|
-
}
|
|
214
|
-
return this._search;
|
|
215
|
-
}
|
|
216
|
-
get asks() {
|
|
217
|
-
return this._asks || (this._asks = this._plugin._getAsks(this._client));
|
|
218
|
-
}
|
|
219
|
-
get ask() {
|
|
220
|
-
return this.asks.root;
|
|
221
|
-
}
|
|
222
|
-
get hybridSearch() {
|
|
223
|
-
if (!this._hybridSearch) {
|
|
224
|
-
this._hybridSearch = new _index.HybridSearch(this._plugin, this._client);
|
|
225
|
-
this._client._events.emit('postworkflow', this._hybridSearch);
|
|
226
|
-
}
|
|
227
|
-
return this._hybridSearch;
|
|
228
|
-
}
|
|
229
|
-
get explores() {
|
|
230
|
-
return this._explores || (this._explores = this._plugin._getExplores(this._client));
|
|
231
|
-
}
|
|
232
|
-
get explore() {
|
|
233
|
-
return this.explores.get(); // get default explore unit
|
|
172
|
+
(0, _commons.delegateGetters)(this, client.workflows, WORKFLOW_ACCESSORS);
|
|
234
173
|
}
|
|
235
174
|
get ready() {
|
|
236
175
|
return this._plugin.ready;
|
|
@@ -242,6 +181,6 @@ class Combo {
|
|
|
242
181
|
this._MisoClient = MisoClient;
|
|
243
182
|
}
|
|
244
183
|
get ask() {
|
|
245
|
-
return this._ask || (this._ask = new
|
|
184
|
+
return this._ask || (this._ask = new _index.AskCombo(this._plugin, this._MisoClient));
|
|
246
185
|
}
|
|
247
186
|
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.default = confirm;
|
|
7
|
+
var _modal = require("./modal.js");
|
|
8
|
+
const DEFAULT_CLASSNAME = 'miso-confirm';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Show a modal confirmation dialog (a native <dialog>), resolving to whether
|
|
12
|
+
* the user confirmed. Cancel button, backdrop click, and the Escape key all
|
|
13
|
+
* resolve to false. Exposed as `MisoClient.ui.confirm()`.
|
|
14
|
+
*/
|
|
15
|
+
function confirm({
|
|
16
|
+
title,
|
|
17
|
+
message,
|
|
18
|
+
confirmText = 'Confirm',
|
|
19
|
+
cancelText = 'Cancel',
|
|
20
|
+
danger = false,
|
|
21
|
+
className = DEFAULT_CLASSNAME
|
|
22
|
+
} = {}) {
|
|
23
|
+
return (0, _modal.openModal)({
|
|
24
|
+
className,
|
|
25
|
+
title,
|
|
26
|
+
message,
|
|
27
|
+
confirmText,
|
|
28
|
+
cancelText,
|
|
29
|
+
danger,
|
|
30
|
+
result: () => true,
|
|
31
|
+
cancelValue: false
|
|
32
|
+
});
|
|
33
|
+
}
|
package/dist/cjs/util/dom.js
CHANGED
|
@@ -5,8 +5,29 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
5
5
|
});
|
|
6
6
|
exports.addOrRemoveClass = addOrRemoveClass;
|
|
7
7
|
exports.cssAspectRatio = cssAspectRatio;
|
|
8
|
+
exports.dumpElementAttributes = dumpElementAttributes;
|
|
8
9
|
exports.resolveCssLength = resolveCssLength;
|
|
9
10
|
exports.setOrRemoveAttribute = setOrRemoveAttribute;
|
|
11
|
+
// data-* attributes of an element as a JSON string, for click interactions
|
|
12
|
+
function dumpElementAttributes(element) {
|
|
13
|
+
const {
|
|
14
|
+
attributes
|
|
15
|
+
} = element;
|
|
16
|
+
const attrs = {};
|
|
17
|
+
for (const {
|
|
18
|
+
name,
|
|
19
|
+
value
|
|
20
|
+
} of attributes) {
|
|
21
|
+
if (name.startsWith('data-')) {
|
|
22
|
+
attrs[name] = value;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
try {
|
|
26
|
+
return JSON.stringify(attrs);
|
|
27
|
+
} catch (e) {
|
|
28
|
+
return '{}';
|
|
29
|
+
}
|
|
30
|
+
}
|
|
10
31
|
function setOrRemoveAttribute(element, name, value) {
|
|
11
32
|
if (value === undefined) {
|
|
12
33
|
element.removeAttribute(name);
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.openModal = openModal;
|
|
7
|
+
var _commons = require("@miso.ai/commons");
|
|
8
|
+
/**
|
|
9
|
+
* The shared modal dialog core of confirm() and prompt(): a native <dialog>
|
|
10
|
+
* with title, message, an optional body, and cancel/confirm actions. Resolves
|
|
11
|
+
* with `result(dialog)` when confirmed; the cancel button, a backdrop click,
|
|
12
|
+
* and the Escape key all resolve with `cancelValue`.
|
|
13
|
+
*/
|
|
14
|
+
function openModal({
|
|
15
|
+
className,
|
|
16
|
+
title,
|
|
17
|
+
message,
|
|
18
|
+
body = '',
|
|
19
|
+
confirmText = 'Confirm',
|
|
20
|
+
cancelText = 'Cancel',
|
|
21
|
+
danger = false,
|
|
22
|
+
onOpen,
|
|
23
|
+
result = () => true,
|
|
24
|
+
cancelValue
|
|
25
|
+
} = {}) {
|
|
26
|
+
return new Promise(resolve => {
|
|
27
|
+
const dialog = document.createElement('dialog');
|
|
28
|
+
dialog.className = className;
|
|
29
|
+
dialog.innerHTML = [title ? `<div class="${className}__title">${(0, _commons.escapeHtml)(title)}</div>` : '', message ? `<div class="${className}__message">${(0, _commons.escapeHtml)(message)}</div>` : '', body, `<div class="${className}__actions">`, `<button type="button" class="${className}__button ${className}__cancel-button" data-role="cancel">${(0, _commons.escapeHtml)(cancelText)}</button>`, `<button type="button" class="${className}__button ${className}__confirm-button${danger ? ` ${className}__confirm-button--danger` : ''}" data-role="confirm">${(0, _commons.escapeHtml)(confirmText)}</button>`, `</div>`].join('');
|
|
30
|
+
dialog.addEventListener('click', event => {
|
|
31
|
+
if (event.target.closest('[data-role="confirm"]')) {
|
|
32
|
+
dialog.close('confirm');
|
|
33
|
+
} else if (event.target.closest('[data-role="cancel"]') || event.target === dialog) {
|
|
34
|
+
dialog.close(); // cancel button or backdrop click
|
|
35
|
+
}
|
|
36
|
+
});
|
|
37
|
+
dialog.addEventListener('close', () => {
|
|
38
|
+
const value = dialog.returnValue === 'confirm' ? result(dialog) : cancelValue;
|
|
39
|
+
dialog.remove();
|
|
40
|
+
resolve(value);
|
|
41
|
+
}, {
|
|
42
|
+
once: true
|
|
43
|
+
});
|
|
44
|
+
document.body.appendChild(dialog);
|
|
45
|
+
dialog.showModal();
|
|
46
|
+
onOpen && onOpen(dialog);
|
|
47
|
+
});
|
|
48
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.default = prompt;
|
|
7
|
+
var _commons = require("@miso.ai/commons");
|
|
8
|
+
var _modal = require("./modal.js");
|
|
9
|
+
const DEFAULT_CLASSNAME = 'miso-prompt';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Show a modal input dialog (a native <dialog>), resolving to the entered
|
|
13
|
+
* (trimmed) text when confirmed. Cancel button, backdrop click, and the
|
|
14
|
+
* Escape key all resolve to undefined. The Enter key confirms. Exposed as
|
|
15
|
+
* `MisoClient.ui.prompt()`.
|
|
16
|
+
*/
|
|
17
|
+
function prompt({
|
|
18
|
+
title,
|
|
19
|
+
message,
|
|
20
|
+
value = '',
|
|
21
|
+
placeholder,
|
|
22
|
+
confirmText = 'Confirm',
|
|
23
|
+
cancelText = 'Cancel',
|
|
24
|
+
className = DEFAULT_CLASSNAME
|
|
25
|
+
} = {}) {
|
|
26
|
+
return (0, _modal.openModal)({
|
|
27
|
+
className,
|
|
28
|
+
title,
|
|
29
|
+
message,
|
|
30
|
+
body: `<input class="${className}__input" type="text" data-role="input" value="${(0, _commons.escapeHtml)(value)}"${placeholder ? ` placeholder="${(0, _commons.escapeHtml)(placeholder)}"` : ''}>`,
|
|
31
|
+
confirmText,
|
|
32
|
+
cancelText,
|
|
33
|
+
onOpen: dialog => {
|
|
34
|
+
const input = dialog.querySelector('[data-role="input"]');
|
|
35
|
+
input.addEventListener('keydown', event => {
|
|
36
|
+
if (event.key === 'Enter') {
|
|
37
|
+
event.preventDefault();
|
|
38
|
+
dialog.close('confirm');
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
input.focus();
|
|
42
|
+
input.select();
|
|
43
|
+
},
|
|
44
|
+
result: dialog => dialog.querySelector('[data-role="input"]').value.trim(),
|
|
45
|
+
cancelValue: undefined
|
|
46
|
+
});
|
|
47
|
+
}
|
package/dist/cjs/version.js
CHANGED
package/package.json
CHANGED
|
@@ -12,8 +12,8 @@
|
|
|
12
12
|
"access": "public"
|
|
13
13
|
},
|
|
14
14
|
"scripts": {
|
|
15
|
-
"build:clean": "
|
|
16
|
-
"build:cjs": "BABEL_ENV=cjs
|
|
15
|
+
"build:clean": "rimraf dist",
|
|
16
|
+
"build:cjs": "BABEL_ENV=cjs babel src --root-mode upward --out-dir dist/cjs",
|
|
17
17
|
"build": "npm run build:clean && npm run build:cjs"
|
|
18
18
|
},
|
|
19
19
|
"repository": {
|
|
@@ -30,7 +30,8 @@
|
|
|
30
30
|
"url": "https://github.com/MisoAI/miso-client-js-sdk/issues"
|
|
31
31
|
},
|
|
32
32
|
"dependencies": {
|
|
33
|
-
"@miso.ai/commons": "1.
|
|
33
|
+
"@miso.ai/commons": "1.14.0-beta.3",
|
|
34
|
+
"@miso.ai/client-sdk-workflow": "1.14.0-beta.3"
|
|
34
35
|
},
|
|
35
|
-
"version": "1.
|
|
36
|
+
"version": "1.14.0-beta.3"
|
|
36
37
|
}
|
package/src/CLAUDE.md
CHANGED
|
@@ -1,112 +1,64 @@
|
|
|
1
1
|
# Client SDK UI
|
|
2
2
|
|
|
3
|
-
The UI package (`std:ui` plugin) provides the presentation layer for Miso SDK
|
|
3
|
+
The UI package (`std:ui` plugin) provides the presentation layer for Miso SDK: custom elements, layouts, and rendering infrastructure.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
The workflow layer (workflow classes, actors, hub, default-options store) lives in `@miso.ai/client-sdk-workflow` — see `packages/client-sdk-workflow/CLAUDE.md` for the hub-and-spoke architecture, workflow class hierarchy, roles/status model, and the end-to-end data flow. This package plugs elements and layouts into those workflows.
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
## Architecture Overview
|
|
8
8
|
|
|
9
9
|
```
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
│
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
|
|
20
|
-
│ Workflows │ │ Elements │ │ Layouts │
|
|
21
|
-
│ │◄────►│ │◄────►│ │
|
|
22
|
-
│ (Logic) │ │ (Custom El) │ │ (Rendering) │
|
|
23
|
-
└─────────────┘ └─────────────┘ └─────────────┘
|
|
24
|
-
│
|
|
25
|
-
▼
|
|
26
|
-
┌─────────────┐
|
|
27
|
-
│ Actors │
|
|
28
|
-
│ (Hub I/O) │
|
|
29
|
-
└─────────────┘
|
|
10
|
+
UiPlugin ('std:ui', singleton)
|
|
11
|
+
├─ ensures WorkflowPlugin ('std:workflow') is installed
|
|
12
|
+
├─ provides its Layouts registry to the workflow plugin (setLayouts)
|
|
13
|
+
├─ seeds default layout options (defaults.js) + ask followUp template
|
|
14
|
+
│ into the workflow plugin's defaults store
|
|
15
|
+
├─ Layouts registry (layout classes, keyed by type)
|
|
16
|
+
├─ defines <miso-*> custom elements
|
|
17
|
+
└─ injects client.ui on each MisoClient instance; its workflow accessors
|
|
18
|
+
(search, asks, ...) delegate to client.workflows for backward compatibility
|
|
30
19
|
```
|
|
31
20
|
|
|
32
|
-
|
|
21
|
+
Key points that are easy to get wrong:
|
|
33
22
|
|
|
34
|
-
|
|
23
|
+
- **Elements render nothing.** A container element (e.g. `<miso-ask>`) locates its workflow on `connectedCallback()` and registers itself; child role elements register through their container. The workflow's `ViewsActor` then creates one `ViewActor` per element, pairing it with a **layout instance** for that role. The layout writes DOM into the element.
|
|
24
|
+
- Layouts are **instances created per view** from classes registered in the plugin's `Layouts` registry (`layout.type` → class), chosen by the workflow's `layouts` options. They are not templates.
|
|
25
|
+
- Default layout options per workflow live in `src/defaults.js`, keyed by workflow name, and are seeded into the workflow plugin's defaults store at install — they are not baked into the workflow classes.
|
|
26
|
+
|
|
27
|
+
## Core Directories
|
|
35
28
|
|
|
36
29
|
| Directory | Purpose |
|
|
37
30
|
|-----------|---------|
|
|
38
|
-
| `
|
|
39
|
-
| `
|
|
40
|
-
| `
|
|
41
|
-
| `
|
|
42
|
-
| `
|
|
43
|
-
| `
|
|
44
|
-
| `
|
|
45
|
-
|
|
46
|
-
## Key Concepts
|
|
47
|
-
|
|
48
|
-
### Workflows (`workflow/`)
|
|
49
|
-
|
|
50
|
-
// TODO: wrong concept
|
|
51
|
-
|
|
52
|
-
State machines that orchestrate API calls and UI updates. Each workflow manages:
|
|
53
|
-
- Session lifecycle (restart, query, response)
|
|
54
|
-
- Data flow via Hub
|
|
55
|
-
- View state synchronization
|
|
56
|
-
- Interaction tracking
|
|
57
|
-
|
|
58
|
-
**Available workflows**: `Ask`, `Search`, `HybridSearch`, `Explore`, `Recommendation`
|
|
31
|
+
| `element/` | Custom HTML elements (`<miso-*>`): thin, render-free DOM anchors that bind themselves to workflows |
|
|
32
|
+
| `layout/` | Layout classes (rendering logic), registered by `type` in the plugin's registry, instantiated per view |
|
|
33
|
+
| `combo/` | `AskCombo`: programmatic pre-built ask UI (deprecated) |
|
|
34
|
+
| `trait/` | Reusable behaviors exposed as `MisoClient.ui.traits` (e.g. `CollapsibleTrait`) |
|
|
35
|
+
| `defaults/` | Default templates/phrases/controls for ask and hybrid-search UIs, exposed as `MisoClient.ui.defaults` |
|
|
36
|
+
| `defaults.js` | Default layout options of each workflow, seeded into the workflow plugin's store |
|
|
37
|
+
| `constants.js` | UI-only constants (`LAYOUT_TYPE`, data attributes); re-exports workflow constants (`ROLE`, `STATUS`, ...) for convenience |
|
|
59
38
|
|
|
60
|
-
|
|
39
|
+
## Elements (`element/`)
|
|
61
40
|
|
|
62
|
-
Web Components
|
|
41
|
+
Web Components (`<miso-*>`). They contain **no rendering or data logic** — they only establish the DOM binding:
|
|
63
42
|
|
|
64
|
-
- **Containers
|
|
65
|
-
- `<miso-ask
|
|
43
|
+
- **Containers** (`element/container/`): own the workflow binding for their subtree.
|
|
44
|
+
- `<miso-ask>` — binds by `parent-question-id` attribute (absent = root ask), or `workflow="active"` to follow `asks.active`
|
|
45
|
+
- `<miso-search>`, `<miso-hybrid-search>` — bind to `client.ui.search` / `.hybridSearch`
|
|
46
|
+
- `<miso-explore>`, `<miso-recommendation>` — bind by `unit-id` attribute
|
|
47
|
+
- `<miso-history>`, `<miso-conversation>` — bind to `client.workflows.history` / `.conversation`, forming the chat history interface (thread list + conversation panel); their role elements are `<miso-threads>`, `<miso-new-thread>`, `<miso-messages>`, `<miso-title>`, `<miso-rename>`, `<miso-delete>` and `<miso-subscription>`. The new-thread button is its own component (`<miso-new-thread>`, role `new_thread`), *not* part of the thread list, so it renders regardless of the list state (loading, empty, erroneous); it uses the generic `button` layout — an icon and a label, both configurable (`icon`, `text`), emitting a `submit` view event when clicked — which History answers by clearing the selection and resetting the conversation panel to new-thread mode. The thread list uses the `threads` layout as a **shell**, like the conversation's `messages` layout: each `thread` item is a `<miso-thread-item>` container element (`data-role="item"`, carrying the thread id and the state attributes) hosting the thread item subworkflow, with the title and the context menu's rename/subscription/delete controls as role elements inside rendering through that workflow's own generic layouts; selection is part of the data — `selectedThreadId` lives in the workflow's committed value and each record carries its `selected` flag right in the data layer (stamped by the workflow's default data pass, preserving the identity of records whose flag doesn't flip, so only the affected items' subworkflows see a commit; the role mapping is a plain slice) — and the list renders incrementally: fresh items land at either end — a newly created thread renders as a prepend (the list is newest-first), an older page fetched by the more flow as appends — told apart by which boundary the already-rendered records line up with (anything else re-renders in full), while in-place state changes on existing items (selected/unread, the thread id of a settled placeholder) are applied by an attribute-sync pass after each render, reading fresh values off the item bindings, and the item contents follow the record down each thread workflow's own data path — no item re-render either way. The list **pages by infinite scroll**, through the collection layout's stock machinery (the `data-role="trigger"` div after the list + the triggerable mixin, enabled by the threads layout's `infiniteScroll` option and the workflow's `'history'` pagination defaults): the trigger scrolling into view fires the `more` hub field, History appends the next page (`start`/`rows` against the user history list API, exhaustion from the response's own `has_more`), and the page size is set via `history.useApi('threads/list', { rows: N })`; the conversation uses the `messages` layout as a **shell**: each `message` item is a `<miso-message-item>` container element (question/answer/feedback/sources role elements inside, in that order — the feedback buttons right below the answer via the standard feedback layout, the sources as the hybrid-search-style compact horizontal cards under an h3 "Sources" heading (`messageSourcesBlock`, overridable — the block is `visible-when="nonempty"`, so the heading appears only once the item carries content, and a `:has()` rule hides the whole block again when there are zero source cards; a browser without `:has()` degrades to showing the heading, hybrid-search-parity); the item element carries `miso-circled-citation-index`, covering the answer's citation links and the source cards' indexes alike, as the hybrid-search UI scopes it; a message record without its answer body presents as workflow status `loading`, stamped on the element by its container layout as the standard `status` attribute — there is deliberately no per-message loading icon: the answer typewriter's blinking caret is the loading indication, as in ask (hidden at `initial` and at `done` by the stock typewriter CSS); a message whose content fetch failed for good presents as status `erroneous` and swaps its content out wholesale for the item template's muted notice (`messageErrorBlock`, `visible-when="erroneous"` — `miso-message-item` is in the visible-when container list, so the notice keys off the item's own status attribute) — the regular role elements are packed in a `__content` wrapper hidden by a class rule at erroneous status (a wrapper cannot be visible-when-driven itself: the mechanism forces `display: block !important` and only negates combined with positive terms) — and the messages layout's `ongoing` computation skips an errored last message so the composer is not held), rendered incrementally — fresh items land at either end: a posted follow-up appends at the bottom, an older page fetched by the more flow prepends at the top (told apart by which boundary the already-rendered records line up with; anything else re-renders in full) — the content itself renders through each message's own item subworkflow. The panel **pages by infinite scroll, chat-style from the bottom**: the messages layout's own root template places the stock `data-role="trigger"` div **above** the list, so scrolling up fires the `more` hub field (enabled by the layout's `infiniteScroll` option + the workflow's `'conversation'` pagination defaults) and the Conversation workflow prepends the previous page of messages. The post-render sync pass (`_syncWorkflows`) does one thing: assign each `<miso-message-item>` its workflow off the item binding (`element.workflow = conversation._getMessageWorkflow(record)` — implicit binding, item identity keyed by question id falling back to the posted record's local `placeholder_id`, so the element and workflow survive the settle). Item elements of a nested collection do not leak into the outer one: a message hosts its own source-card items (`data-role="item"` too), so `CollectionLayout._getItemElements` keeps only elements whose closest `[data-role="list"]` is the layout's own list — bindings zip values to elements by index, so a stray nested item would shift every binding after it. The question bubble is the **`question` layout** (the message workflow's default for the question role, whose mapping passes the whole record): it renders the question text and stamps the authorship as data attributes on its host element — `data-author` (the label text, configurable via the layout's `author` option; by default 'Written by Miso' for questions whose `metadata.miso_generated_by` is `answer_update_monitor`, per `isUpdateMessage`; it renders as a CSS `attr()` badge overlapping the bubble's top-left border, and monitor-generated bubbles take a distinct background) and `data-generated-by` — and hides its host while there is no question text. The shell also owns the panel-level behaviors: scroll pinning (following content growth via a ResizeObserver on the list, since answers type out through their own workflows outside the shell's render cycle), scroll anchoring while scrolled up — a prepend keeps the reading position by anchoring on the previously-first item: everything prepended, including its contents rendering in later through the item workflows, sits above the anchor, so holding the anchor stationary (at insert time and on every growth event while unpinned, the anchor's offset re-recorded as the user scrolls) holds the view, while growth below it (a streaming answer) needs no compensation; done by hand, since not every engine provides native scroll anchoring — and the `ongoing` view state read off the data — the last message's answer absent or unfinished — which e.g. disables the search box. The conversation's header roles come from the open thread's record: `<miso-title>` (role `title`) renders its title with the generic `text` layout, `<miso-rename>` (role `rename`) renders a pencil button with the generic `button` layout whose **`prompt` option** turns the click into ask-then-submit: the shared prompt dialog opens pre-filled with the control's current value — the role's mapped data value, read off the latest rendered state (`_currentValue()`; `RafLayout` retains it per element) — and the `submit` view event carries the confirmed text as `value`, which Conversation answers with `rename(value)` — `<miso-delete>` (role `delete`, placed right of the rename button) renders a red bin button with the button layout's `confirm` option (the dialog's message interpolates the mapped title), whose confirmed `submit` Conversation answers with `delete()` (the deletion fact then resets the panel to new-thread mode) — and `<miso-subscription>` (role `subscription`) renders the answer-updates toggle with the **`checkbox` layout** — a button-layout subclass; a checkbox that looks like a button (`<button role="switch" aria-checked>` with `data-checked`, an icon and label per state via `icon`/`text` and `checkedIcon`/`checkedText`). Its checked state comes from the data, so a click emits a `change` view event carrying only the requested state (`{ checked }`), read off the rendered element; the Conversation workflow answers it with `subscribe()`/`unsubscribe()` and the new state arrives back down the data path. Note the `visible-when` mechanism forces `display: block !important` on the element it toggles, so a page that lays such an element out as a flex row needs an inner wrapper (as the history demo pages do for the header). A `<miso-query>` (search-box layout) inside `<miso-conversation>` submits questions as the `submit` view event, which Conversation routes to `send()` — follow-ups, or the first question of a new thread (the conversation starts in new-thread mode). With `messages`/`threads` registered as data roles, `<miso-conversation>` carries the `empty`/`nonempty` content status, which pages use to center the composer in the empty (new-thread) state. A click on a thread item is a navigation action, not a content-engagement click: the `threads` layout overrides `_onClick` to emit a `select` view event (no click tracking), which the History workflow handles with `select()` — item selection stays list-level, while everything inside the item belongs to its thread workflow. Each item also carries a context menu (vertical dots, revealed on hover): its markup comes from the item template (`threadMenuBlock`), and its open/close behavior is driven by the thread workflow's **`item-container` layout** (`ItemContainerLayout`, the container-layout subclass for collection item subworkflows) **by contract** — the template marks the toggle button `data-role="item-menu-button"` and the popup `data-role="item-menu"`, and the layout toggles on the button and closes on any other click on the item or outside it (per-item document listeners, which is also how opening one item's menu closes another's); the shell only keeps clicks carrying those data-roles from selecting. The menu items are the thread workflow's own controls, each a generic `button` layout going through a shared modal dialog util (promise-returning native `<dialog>`s on a common core, `util/modal.js`): `<miso-rename>` (role `rename`) uses the button layout's `prompt` option (`util/prompt.js`, a modal text input pre-filled with the current title — Enter confirms, resolving to the trimmed text, or undefined on cancel; exposed as `MisoClient.ui.prompt`), and `<miso-delete>` (role `delete`) its **`confirm` option** (`util/confirm.js`, exposed as `MisoClient.ui.confirm`; the option's `message` may be a function of the control's current value — the mapped title); the confirmed `submit` view events fire the operation requests on the thread workflow's own hub, their facts riding onto the shared thread events emitter. Between the two sits `<miso-subscription>` (role `subscription`), the `checkbox` layout as a plain menu item: text only, labeled by the action a click takes ('Subscribe' / 'Unsubscribe' via `text`/`checkedText` in the `'history'` defaults — unlike the conversation header's state-labeled bell pill), its `change` view event answered by the thread workflow with `history.subscribe()`/`unsubscribe()`.
|
|
48
|
+
- `<miso-message-item>` — a **container element inside another container element** (`<miso-conversation>`), hosting the `message-item` workflow — an answer-based workflow that posts and streams its own content when live (ask-style), and is otherwise fed by the conversation via `updateData()` with its data actor off. Normally **bound implicitly**: the messages layout renders one per item and assigns `element.workflow` off the item binding (which also covers a just-posted message with no question id yet); a `question-id` attribute binds explicitly through the parent container's workflow instead (`conversation._getMessageWorkflow`). Its role children (`<miso-question>`, `<miso-answer>`, `<miso-sources>`, `<miso-feedback>`, ...) bind to the message workflow as usual (`getContainer` resolves to the closest container ancestor) and render one message via the standard answer-based layouts (the message workflow shares the conversation's options, whose `'conversation'` defaults hold the message roles too — omitting the query role, turning the container logo off, and giving the answer typewriter `instant: true` — already-finished answers render in one shot); citation/link clicks and feedback go out as message-level interactions, deduplicated per message.
|
|
49
|
+
- `<miso-thread-item>` — the thread list's analogue of `<miso-message-item>`: a container element inside `<miso-history>`, hosting the `thread-item` workflow — data actor off, fed by History via `updateData()` with only the records that actually changed (record identity is the change signal). Normally **bound implicitly**: the threads layout renders one per item and assigns `element.workflow` off the item binding; a `thread-id` attribute binds explicitly through the parent container's workflow instead (`history._getThreadWorkflow`). Its role children — `<miso-title>` (generic `text` layout, with an 'Untitled' fallback via a `content` template), `<miso-rename>`/`<miso-delete>` (generic `button` layout with the `prompt`/`confirm` dialog options), and `<miso-subscription>` (the `checkbox` layout, the context menu's toggle) — bind to the thread workflow as usual; title and subscription map dot-paths into the record (`'title'`, `'subscribed'`), while rename and delete map the whole record — their button layouts derive the dialog text via the `value` option and render disabled (the `disabled` option) until the record carries a thread id, so a thread being created is inert in the UI too. Its container role uses the `item-container` layout, which drives the context menu found in the item's markup via the `item-menu` data-role contract (a custom body without menu markup simply has nothing to drive).
|
|
50
|
+
- **Role components** (`element/role/`): register with their ancestor container; the role determines which slice of data they display. Either dedicated tags (`<miso-answer>`, `<miso-sources>`, `<miso-products>`, `<miso-query>`, ...) or generic `<miso-component role="...">`. `<miso-results>` is deprecated in favor of `<miso-products>`.
|
|
51
|
+
- **Combos** (`element/combo/`): pre-configured composite `<miso-ask-combo>` (deprecated).
|
|
66
52
|
|
|
67
|
-
|
|
68
|
-
- Query: `<miso-query>`
|
|
69
|
-
- Results: `<miso-answer>`, `<miso-sources>`, `<miso-products>`, `<miso-results>`
|
|
70
|
-
- Navigation: `<miso-follow-up-questions>`, `<miso-related-questions>`
|
|
71
|
-
- Utility: `<miso-feedback>`, `<miso-error>`, `<miso-facets>`, `<miso-total>`
|
|
53
|
+
Connecting an element to the DOM is what triggers view creation: container `connectedCallback` → `workflow._views.addContainer/addComponent` → `ViewActor` created with a layout instance → rendered as soon as data exists.
|
|
72
54
|
|
|
73
|
-
|
|
74
|
-
- `<miso-ask-combo>`
|
|
55
|
+
## Layouts (`layout/`)
|
|
75
56
|
|
|
76
|
-
|
|
57
|
+
Rendering strategies. A layout class has a static `type` (e.g. `'list'`, `'typewriter'`, `'search-box'`) and is registered in the plugin registry; workflows pick layouts per role via options (`useLayouts({ answer: ['typewriter', {...}] })`). `ViewsActor` instantiates one layout object per view.
|
|
77
58
|
|
|
78
|
-
|
|
79
|
-
- `DataActor` - Fetches data from API based on requests
|
|
80
|
-
- `ViewsActor` - Manages view state for each role
|
|
81
|
-
- `TrackersActor` - Handles impression/click/viewable tracking
|
|
82
|
-
- `InteractionsActor` - Sends interaction events to API
|
|
83
|
-
- `SessionMaker` - Manages session lifecycle
|
|
59
|
+
Contract: `render(element, data, { notifyUpdate })` is mandatory; `initialize(view)`, `unrender(element)`, `syncSize(element)`, `destroy()` are optional. `notifyUpdate(state)` is how a layout reports its view state back (published to `view:<role>` on the hub) — this drives workflow lifecycle events. A layout submits user actions as **view events**, like the buttons do: `SearchBoxLayout` emits `submit` (`{ session, value }`) on the query role, which each query-hosting workflow subscribes to and routes itself (`_onQuerySubmit` → `query()` in the answer-based, search-based and explore workflows; Conversation routes to `send()`) — layouts never write the query field or call workflow methods directly.
|
|
84
60
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
Central pub/sub state manager connecting workflows and actors. Fields include:
|
|
88
|
-
- `session` - Current session object
|
|
89
|
-
- `request` - API request parameters
|
|
90
|
-
- `data` - Response data
|
|
91
|
-
- `view(role)` - View state per role
|
|
92
|
-
- `tracker(role, event)` - Tracking state
|
|
93
|
-
|
|
94
|
-
### Layouts (`layout/`)
|
|
95
|
-
|
|
96
|
-
Rendering strategies for each role. Registered via `plugin.layouts.register()`.
|
|
97
|
-
|
|
98
|
-
Types: `input`, `list`, `text`, `container`, `error`, `button`, etc.
|
|
99
|
-
|
|
100
|
-
### Roles & Status
|
|
101
|
-
|
|
102
|
-
**Roles** (from `constants.js`): Define what data a view displays
|
|
103
|
-
- Content: `answer`, `question`, `sources`, `products`, `results`
|
|
104
|
-
- Navigation: `follow_up_questions`, `related_questions`, `query_suggestions`
|
|
105
|
-
- Meta: `feedback`, `error`, `total`, `facets`
|
|
106
|
-
|
|
107
|
-
**Status**: Workflow/view lifecycle states
|
|
108
|
-
- `initial` → `loading` → `ready` / `erroneous`
|
|
109
|
-
- `ongoing` (streaming) → `done`
|
|
61
|
+
A layout root stamps its view role as a `data-role` attribute — the role name verbatim, snake_case included (`data-role="new_thread"`) — and CSS binds to layout className + role (`.miso-text[data-role="question"]`), never to the host element tag: `<miso-rename>` and `<miso-component role="rename">` style alike; element tags appear only in `_container.scss` for structural rules (display, box-sizing, `visible-when`).
|
|
110
62
|
|
|
111
63
|
## Entry Point
|
|
112
64
|
|
|
@@ -115,20 +67,15 @@ Types: `input`, `list`, `text`, `container`, `error`, `button`, etc.
|
|
|
115
67
|
// Installed automatically with full SDK, or manually:
|
|
116
68
|
MisoClient.plugins.use('std:ui');
|
|
117
69
|
|
|
118
|
-
// Access via client instance:
|
|
70
|
+
// Access via client instance (canonical, injected by std:workflow):
|
|
119
71
|
const client = new MisoClient({ apiKey });
|
|
120
|
-
client.
|
|
121
|
-
client.
|
|
122
|
-
client.
|
|
72
|
+
client.workflows.ask; // root Ask workflow (=== client.workflows.asks.root)
|
|
73
|
+
client.workflows.asks; // Asks context (follow-up chain, .active, .root)
|
|
74
|
+
client.workflows.search; // Search workflow
|
|
75
|
+
client.workflows.hybridSearch; // HybridSearch workflow
|
|
76
|
+
client.workflows.recommendations.get(unitId); // Recommendation workflow per unit
|
|
77
|
+
client.workflows.explores.get(unitId); // Explore workflow per unit
|
|
78
|
+
|
|
79
|
+
// client.ui.search, client.ui.asks, client.ui.sources, ... delegate to
|
|
80
|
+
// client.workflows for backward compatibility; client.ui's own surface is only `ready`.
|
|
123
81
|
```
|
|
124
|
-
|
|
125
|
-
## Event Flow
|
|
126
|
-
|
|
127
|
-
1. User interacts with `<miso-query>` element (ask, hybrid-search, search, etc.), or start by calling `start()` on the workflow instance (explore, recommendations).
|
|
128
|
-
2. Container element triggers workflow request
|
|
129
|
-
3. Workflow publishes request to Hub
|
|
130
|
-
4. `DataActor` fetches from API, publishes response
|
|
131
|
-
5. `ViewsActor` updates view states per role
|
|
132
|
-
6. Layout renders updated content in elements
|
|
133
|
-
7. `TrackersActor` observes visibility, triggers interactions
|
|
134
|
-
8. `InteractionsActor` sends tracking data to API
|