zerochat 7.3.0__py3-none-any.whl
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.
- zerochat-7.3.0.dist-info/METADATA +70 -0
- zerochat-7.3.0.dist-info/RECORD +130 -0
- zerochat-7.3.0.dist-info/WHEEL +5 -0
- zerochat-7.3.0.dist-info/entry_points.txt +2 -0
- zerochat-7.3.0.dist-info/licenses/LICENSE +34 -0
- zerochat-7.3.0.dist-info/top_level.txt +2 -0
- zerochat.py +2004 -0
- zerochat_runtime/__init__.py +1 -0
- zerochat_runtime/assets/css/base.css +199 -0
- zerochat_runtime/assets/css/components/composer.css +1258 -0
- zerochat_runtime/assets/css/components/debug.css +777 -0
- zerochat_runtime/assets/css/components/header.css +97 -0
- zerochat_runtime/assets/css/components/icons.css +39 -0
- zerochat_runtime/assets/css/components/markdown.css +685 -0
- zerochat_runtime/assets/css/components/messages.css +473 -0
- zerochat_runtime/assets/css/components/modals.css +1319 -0
- zerochat_runtime/assets/css/components/sidebar.css +622 -0
- zerochat_runtime/assets/css/components/tools.css +1223 -0
- zerochat_runtime/assets/css/layout.css +171 -0
- zerochat_runtime/assets/css/print.css +120 -0
- zerochat_runtime/assets/css/styles.css +18 -0
- zerochat_runtime/assets/css/theme-overrides.css +555 -0
- zerochat_runtime/assets/css/tokens.css +165 -0
- zerochat_runtime/assets/help/architecture.html +247 -0
- zerochat_runtime/assets/help/composer.html +134 -0
- zerochat_runtime/assets/help/conversations.html +105 -0
- zerochat_runtime/assets/help/debug.html +108 -0
- zerochat_runtime/assets/help/en/architecture.html +247 -0
- zerochat_runtime/assets/help/en/composer.html +134 -0
- zerochat_runtime/assets/help/en/conversations.html +104 -0
- zerochat_runtime/assets/help/en/debug.html +105 -0
- zerochat_runtime/assets/help/en/gemini-free.html +39 -0
- zerochat_runtime/assets/help/en/index.html +191 -0
- zerochat_runtime/assets/help/en/learning.html +71 -0
- zerochat_runtime/assets/help/en/mcp.html +143 -0
- zerochat_runtime/assets/help/en/openrouter-free.html +39 -0
- zerochat_runtime/assets/help/en/profiles.html +173 -0
- zerochat_runtime/assets/help/en/rag.html +130 -0
- zerochat_runtime/assets/help/en/reasoning-telemetry.html +108 -0
- zerochat_runtime/assets/help/en/tools-agent.html +133 -0
- zerochat_runtime/assets/help/en/webllm.html +355 -0
- zerochat_runtime/assets/help/gemini-free.html +39 -0
- zerochat_runtime/assets/help/help.css +604 -0
- zerochat_runtime/assets/help/help.js +51 -0
- zerochat_runtime/assets/help/index.html +194 -0
- zerochat_runtime/assets/help/learning.html +71 -0
- zerochat_runtime/assets/help/mcp.html +143 -0
- zerochat_runtime/assets/help/openrouter-free.html +39 -0
- zerochat_runtime/assets/help/profiles.html +174 -0
- zerochat_runtime/assets/help/rag.html +130 -0
- zerochat_runtime/assets/help/reasoning-telemetry.html +111 -0
- zerochat_runtime/assets/help/tools-agent.html +133 -0
- zerochat_runtime/assets/help/webllm.html +359 -0
- zerochat_runtime/assets/js/agent-core.js +1553 -0
- zerochat_runtime/assets/js/api.js +844 -0
- zerochat_runtime/assets/js/app.js +2558 -0
- zerochat_runtime/assets/js/attachments.js +220 -0
- zerochat_runtime/assets/js/charts.js +338 -0
- zerochat_runtime/assets/js/chat-engine.js +566 -0
- zerochat_runtime/assets/js/config-store.js +207 -0
- zerochat_runtime/assets/js/context-manager.js +584 -0
- zerochat_runtime/assets/js/conversation-service.js +484 -0
- zerochat_runtime/assets/js/cookies.js +688 -0
- zerochat_runtime/assets/js/data-reset-service.js +136 -0
- zerochat_runtime/assets/js/debug.js +508 -0
- zerochat_runtime/assets/js/defaults.js +16 -0
- zerochat_runtime/assets/js/export.js +179 -0
- zerochat_runtime/assets/js/file-parser.js +2088 -0
- zerochat_runtime/assets/js/generation-controller.js +417 -0
- zerochat_runtime/assets/js/i18n.js +1483 -0
- zerochat_runtime/assets/js/icons.js +156 -0
- zerochat_runtime/assets/js/ingestionEngine.js +436 -0
- zerochat_runtime/assets/js/markdown.js +588 -0
- zerochat_runtime/assets/js/mcp.js +1271 -0
- zerochat_runtime/assets/js/message-turns.js +62 -0
- zerochat_runtime/assets/js/profile-backup.js +118 -0
- zerochat_runtime/assets/js/profile-export-bundle.js +481 -0
- zerochat_runtime/assets/js/profile-repository.js +213 -0
- zerochat_runtime/assets/js/providers-webllm.js +486 -0
- zerochat_runtime/assets/js/providers.js +1560 -0
- zerochat_runtime/assets/js/rag-index.js +295 -0
- zerochat_runtime/assets/js/rag-service.js +530 -0
- zerochat_runtime/assets/js/rag-ui.js +997 -0
- zerochat_runtime/assets/js/ragStorage.js +676 -0
- zerochat_runtime/assets/js/sandbox.js +449 -0
- zerochat_runtime/assets/js/state.js +704 -0
- zerochat_runtime/assets/js/storage-db.js +144 -0
- zerochat_runtime/assets/js/tool-cards.js +330 -0
- zerochat_runtime/assets/js/tool-security.js +653 -0
- zerochat_runtime/assets/js/tools/README.md +50 -0
- zerochat_runtime/assets/js/tools/builtin/agent-checkpoint.tool.js +212 -0
- zerochat_runtime/assets/js/tools/builtin/download-pdf.tool.js +111 -0
- zerochat_runtime/assets/js/tools/builtin/execute-javascript.tool.js +219 -0
- zerochat_runtime/assets/js/tools/builtin/fetch-web-page.tool.js +112 -0
- zerochat_runtime/assets/js/tools/builtin/list-documents.tool.js +117 -0
- zerochat_runtime/assets/js/tools/builtin/read-knowledge-chunk.tool.js +129 -0
- zerochat_runtime/assets/js/tools/builtin/read-knowledge-image.tool.js +95 -0
- zerochat_runtime/assets/js/tools/builtin/render-chart.tool.js +90 -0
- zerochat_runtime/assets/js/tools/builtin/search-knowledge-base.tool.js +124 -0
- zerochat_runtime/assets/js/tools/builtin/search-web.tool.js +125 -0
- zerochat_runtime/assets/js/tools/tool-manifest.js +53 -0
- zerochat_runtime/assets/js/tools/tool-runtime.js +77 -0
- zerochat_runtime/assets/js/ui-composer.js +319 -0
- zerochat_runtime/assets/js/ui-conversation.js +655 -0
- zerochat_runtime/assets/js/ui-dialogs.js +132 -0
- zerochat_runtime/assets/js/ui-generation-status.js +119 -0
- zerochat_runtime/assets/js/ui-inspector.js +804 -0
- zerochat_runtime/assets/js/ui-mcp.js +604 -0
- zerochat_runtime/assets/js/ui-profiles.js +824 -0
- zerochat_runtime/assets/js/ui-reasoning.js +146 -0
- zerochat_runtime/assets/js/ui-settings.js +825 -0
- zerochat_runtime/assets/js/ui-shell.js +215 -0
- zerochat_runtime/assets/js/ui-sidebar.js +429 -0
- zerochat_runtime/assets/js/ui-telemetry.js +404 -0
- zerochat_runtime/assets/js/ui-transfer.js +262 -0
- zerochat_runtime/assets/js/utils.js +216 -0
- zerochat_runtime/assets/js/vendor/orama.browser.js +11 -0
- zerochat_runtime/assets/js/web-browser.js +569 -0
- zerochat_runtime/assets/js/web-search.js +519 -0
- zerochat_runtime/assets/manifest.webmanifest +20 -0
- zerochat_runtime/assets/services/dummy_mcp/dummy_mcp_server.py +47 -0
- zerochat_runtime/assets/services/dummy_mcp/service.json +22 -0
- zerochat_runtime/assets/services/lsp/installer.json +9 -0
- zerochat_runtime/assets/services/lsp/service.json +22 -0
- zerochat_runtime/assets/services/memory/installer.json +9 -0
- zerochat_runtime/assets/services/memory/service.json +24 -0
- zerochat_runtime/assets/services/playwright/installer.json +10 -0
- zerochat_runtime/assets/services/playwright/service.json +39 -0
- zerochat_runtime/assets/sw.js +164 -0
- zerochat_runtime/assets/zerochat.html +671 -0
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
(function (root, factory) {
|
|
2
|
+
if (typeof exports === 'object' && typeof module !== 'undefined') module.exports = factory();
|
|
3
|
+
else root.ChatDialogs = factory(root.ChatState, root.ChatI18n, root.document);
|
|
4
|
+
})(typeof self !== 'undefined' ? self : this, function (state, i18n, document) {
|
|
5
|
+
'use strict';
|
|
6
|
+
|
|
7
|
+
function create(store, translations, doc) {
|
|
8
|
+
const dialog = doc.getElementById('notice-dialog');
|
|
9
|
+
const title = doc.getElementById('notice-title');
|
|
10
|
+
const message = doc.getElementById('notice-message');
|
|
11
|
+
const accept = doc.getElementById('notice-accept');
|
|
12
|
+
const cancel = doc.getElementById('notice-cancel');
|
|
13
|
+
const input = doc.getElementById('notice-input');
|
|
14
|
+
const checkboxContainer = doc.getElementById('notice-checkbox-container');
|
|
15
|
+
const checkbox = doc.getElementById('notice-checkbox');
|
|
16
|
+
const checkboxText = doc.getElementById('notice-checkbox-text');
|
|
17
|
+
let activeId = null;
|
|
18
|
+
let previousFocus = null;
|
|
19
|
+
|
|
20
|
+
function render() {
|
|
21
|
+
const notice = (store.get('ui').notices || [])[0];
|
|
22
|
+
if (notice?.id === activeId) return;
|
|
23
|
+
activeId = notice?.id || null;
|
|
24
|
+
if (!notice) {
|
|
25
|
+
input.value = '';
|
|
26
|
+
if (checkbox) checkbox.checked = false;
|
|
27
|
+
if (checkboxContainer) checkboxContainer.hidden = true;
|
|
28
|
+
accept.setAttribute('data-i18n', 'notice_accept');
|
|
29
|
+
accept.textContent = translations.t('notice_accept');
|
|
30
|
+
cancel.setAttribute('data-i18n', 'notice_cancel');
|
|
31
|
+
cancel.textContent = translations.t('notice_cancel');
|
|
32
|
+
if (dialog.open) dialog.close();
|
|
33
|
+
if (previousFocus?.isConnected) previousFocus.focus();
|
|
34
|
+
previousFocus = null;
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
title.textContent = notice.title;
|
|
38
|
+
message.textContent = notice.message;
|
|
39
|
+
if (notice.acceptText) {
|
|
40
|
+
accept.removeAttribute('data-i18n');
|
|
41
|
+
accept.textContent = notice.acceptText;
|
|
42
|
+
} else {
|
|
43
|
+
accept.setAttribute('data-i18n', 'notice_accept');
|
|
44
|
+
accept.textContent = translations.t('notice_accept');
|
|
45
|
+
}
|
|
46
|
+
if (notice.cancelText) {
|
|
47
|
+
cancel.removeAttribute('data-i18n');
|
|
48
|
+
cancel.textContent = notice.cancelText;
|
|
49
|
+
} else {
|
|
50
|
+
cancel.setAttribute('data-i18n', 'notice_cancel');
|
|
51
|
+
cancel.textContent = translations.t('notice_cancel');
|
|
52
|
+
}
|
|
53
|
+
cancel.hidden = notice.mode === 'alert';
|
|
54
|
+
input.hidden = notice.mode !== 'prompt';
|
|
55
|
+
input.value = notice.mode === 'prompt' ? notice.value : '';
|
|
56
|
+
if (checkboxContainer) {
|
|
57
|
+
checkboxContainer.hidden = !notice.checkbox;
|
|
58
|
+
if (checkboxText) checkboxText.textContent = notice.checkbox || '';
|
|
59
|
+
if (checkbox) checkbox.checked = Boolean(notice.checkboxDefault);
|
|
60
|
+
}
|
|
61
|
+
dialog.dataset.type = notice.type;
|
|
62
|
+
if (!dialog.open) {
|
|
63
|
+
previousFocus = doc.activeElement;
|
|
64
|
+
dialog.showModal();
|
|
65
|
+
}
|
|
66
|
+
(notice.mode === 'prompt' ? input : notice.mode === 'confirm' ? cancel : accept).focus();
|
|
67
|
+
if (notice.mode === 'prompt') input.select();
|
|
68
|
+
}
|
|
69
|
+
function dismiss(accepted = false) {
|
|
70
|
+
if (activeId !== null) {
|
|
71
|
+
const isChecked = Boolean(checkbox && checkbox.checked);
|
|
72
|
+
store.dismissNotice(activeId, accepted, input.value, isChecked);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
input.addEventListener('keydown', event => {
|
|
76
|
+
if (event.key === 'Enter' && !event.isComposing) {
|
|
77
|
+
event.preventDefault();
|
|
78
|
+
event.stopPropagation();
|
|
79
|
+
dismiss(true);
|
|
80
|
+
}
|
|
81
|
+
});
|
|
82
|
+
accept.addEventListener('click', () => dismiss(true));
|
|
83
|
+
cancel.addEventListener('click', () => dismiss(false));
|
|
84
|
+
dialog.addEventListener('cancel', event => { event.preventDefault(); dismiss(); });
|
|
85
|
+
dialog.addEventListener('close', () => { if (!dialog.open) dismiss(); });
|
|
86
|
+
store.subscribe(s => JSON.stringify(s.ui.notices || []), render);
|
|
87
|
+
render();
|
|
88
|
+
|
|
89
|
+
function enqueue(message, options, mode, value) {
|
|
90
|
+
const type = options.type || 'info';
|
|
91
|
+
const id = store.enqueueNotice({
|
|
92
|
+
message: String(message ?? ''),
|
|
93
|
+
title: String(options.title ?? translations.t(mode === 'prompt' ? 'notice_prompt' : mode === 'confirm' ? 'notice_confirm' : 'notice_' + type)),
|
|
94
|
+
type,
|
|
95
|
+
mode,
|
|
96
|
+
value,
|
|
97
|
+
acceptText: options.acceptText,
|
|
98
|
+
cancelText: options.cancelText,
|
|
99
|
+
checkbox: options.checkbox,
|
|
100
|
+
checkboxDefault: options.checkboxDefault
|
|
101
|
+
});
|
|
102
|
+
return new Promise(resolve => {
|
|
103
|
+
const unsubscribe = store.subscribe(s => (s.ui.notices || []).some(item => item.id === id), present => {
|
|
104
|
+
if (!present) {
|
|
105
|
+
unsubscribe();
|
|
106
|
+
const result = store.get('ui').noticeResult;
|
|
107
|
+
const accepted = result?.id === id && result.accepted === true;
|
|
108
|
+
const checkboxChecked = Boolean(result?.id === id && result.checkboxChecked === true);
|
|
109
|
+
if (options.checkbox !== undefined || options.returnDetails) {
|
|
110
|
+
resolve({ accepted, applyToAll: checkboxChecked, checkboxChecked, value: result?.value ?? null });
|
|
111
|
+
} else {
|
|
112
|
+
resolve(mode === 'prompt' ? (accepted ? result.value : null) : mode === 'confirm' ? accepted : undefined);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
});
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
return {
|
|
119
|
+
alert: (message, options = {}) => enqueue(message, options, 'alert'),
|
|
120
|
+
confirm: (message, options = {}) => enqueue(message, options, 'confirm'),
|
|
121
|
+
prompt: (message, defaultValue = '', options = {}) => enqueue(message, options, 'prompt', defaultValue),
|
|
122
|
+
askDuplicate: (message, options = {}) => enqueue(message, {
|
|
123
|
+
...options,
|
|
124
|
+
type: options.type || 'info',
|
|
125
|
+
acceptText: options.acceptText || translations.t('rag_btn_replace'),
|
|
126
|
+
cancelText: options.cancelText || translations.t('rag_btn_ignore'),
|
|
127
|
+
checkbox: options.checkbox || translations.t('rag_duplicate_apply_all')
|
|
128
|
+
}, 'confirm')
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
return document ? create(state, i18n, document) : { create };
|
|
132
|
+
});
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* General-purpose progress status indicator for the composer.
|
|
3
|
+
* Displays brief, non-sensitive progress messages announced by any module
|
|
4
|
+
* (providers, RAG, tools, MCP, agent loop) during an active chat cycle.
|
|
5
|
+
*/
|
|
6
|
+
(function (root, factory) {
|
|
7
|
+
if (typeof exports === 'object' && typeof module !== 'undefined') module.exports = factory();
|
|
8
|
+
else root.ChatUIGenerationStatus = factory();
|
|
9
|
+
}(typeof self !== 'undefined' ? self : this, function () {
|
|
10
|
+
'use strict';
|
|
11
|
+
|
|
12
|
+
let elapsedTimer = null;
|
|
13
|
+
|
|
14
|
+
function resolveI18n() {
|
|
15
|
+
if (typeof window !== 'undefined') return window.ChatI18n;
|
|
16
|
+
if (typeof require !== 'undefined') { try { return require('./i18n.js'); } catch (_) {} }
|
|
17
|
+
return null;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function t(key, params) {
|
|
21
|
+
return resolveI18n()?.t?.(key, params) || key;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function getViewModel(status = {}, now = Date.now()) {
|
|
25
|
+
const raw = typeof status === 'string' ? { text: status } : (status || {});
|
|
26
|
+
const phase = String(raw.phase || (raw.text || raw.message ? 'custom' : 'idle'));
|
|
27
|
+
const percent = raw.percent != null && raw.percent !== '' && Number.isFinite(Number(raw.percent))
|
|
28
|
+
? Math.round(Math.max(0, Math.min(100, Number(raw.percent))))
|
|
29
|
+
: null;
|
|
30
|
+
const elapsed = phase === 'thinking' && raw.startedAt != null && raw.startedAt !== '' && Number.isFinite(Number(raw.startedAt))
|
|
31
|
+
? Math.max(0, Math.floor((now - Number(raw.startedAt)) / 1000)) : null;
|
|
32
|
+
const labels = {
|
|
33
|
+
connecting: t('generation_status_connecting'),
|
|
34
|
+
preparing: t('generation_status_preparing'),
|
|
35
|
+
loading: t('generation_status_loading'),
|
|
36
|
+
compiling: t('generation_status_compiling'),
|
|
37
|
+
ready: t('generation_status_generating'),
|
|
38
|
+
thinking: t('generation_status_thinking'),
|
|
39
|
+
generating: t('generation_status_generating'),
|
|
40
|
+
rag: t('generation_status_rag')
|
|
41
|
+
};
|
|
42
|
+
let text = raw.text || raw.message || labels[phase] || (phase !== 'idle' ? t('generation_status_generating') : '');
|
|
43
|
+
if (phase === 'idle') text = '';
|
|
44
|
+
if (text && percent !== null) text = t('generation_status_percent', { text, percent });
|
|
45
|
+
if (text && elapsed !== null) text = t('generation_status_elapsed', { text, seconds: elapsed });
|
|
46
|
+
const active = Boolean(text) && phase !== 'idle';
|
|
47
|
+
return { active, phase, percent, text };
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function render(element, status) {
|
|
51
|
+
if (!element) return;
|
|
52
|
+
const view = getViewModel(status);
|
|
53
|
+
element.hidden = !view.active;
|
|
54
|
+
if (!view.active) {
|
|
55
|
+
if (elapsedTimer) clearInterval(elapsedTimer);
|
|
56
|
+
elapsedTimer = null;
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
element.dataset.phase = view.phase;
|
|
60
|
+
const text = element.querySelector?.('.generation-status-text');
|
|
61
|
+
if (text) text.textContent = view.text;
|
|
62
|
+
const progress = element.querySelector?.('.generation-status-progress');
|
|
63
|
+
if (progress) {
|
|
64
|
+
progress.hidden = view.percent === null;
|
|
65
|
+
if (view.percent !== null) progress.value = view.percent;
|
|
66
|
+
}
|
|
67
|
+
if (elapsedTimer) clearInterval(elapsedTimer);
|
|
68
|
+
elapsedTimer = null;
|
|
69
|
+
if (view.phase === 'thinking') {
|
|
70
|
+
elapsedTimer = setInterval(() => render(element, status), 1000);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function resolveState() {
|
|
75
|
+
if (typeof window !== 'undefined' && window.ChatState) return window.ChatState;
|
|
76
|
+
if (typeof globalThis !== 'undefined' && globalThis.ChatState) return globalThis.ChatState;
|
|
77
|
+
if (typeof require !== 'undefined') { try { return require('./state.js'); } catch (_) {} }
|
|
78
|
+
return null;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
function setStatus(element, update = {}) {
|
|
82
|
+
const State = resolveState();
|
|
83
|
+
const raw = typeof update === 'string' ? { text: update } : (update || {});
|
|
84
|
+
const isGenerating = Boolean(State?.get?.('streaming')?.isGenerating);
|
|
85
|
+
const phase = String(raw.phase || (raw.text || raw.message ? 'custom' : 'idle'));
|
|
86
|
+
// Si no se está procesando un ciclo de chat, el indicador permanece invisible y no se reactiva.
|
|
87
|
+
if (!isGenerating && phase !== 'idle') return;
|
|
88
|
+
|
|
89
|
+
let next;
|
|
90
|
+
if (State?.setGenerationStatus) {
|
|
91
|
+
next = State.setGenerationStatus(raw);
|
|
92
|
+
} else if (State?.get && State?.set) {
|
|
93
|
+
const ui = State.get('ui') || {};
|
|
94
|
+
const current = ui.generationStatus || { phase: 'idle', percent: null, startedAt: null };
|
|
95
|
+
const phaseChanged = phase !== current.phase;
|
|
96
|
+
next = phaseChanged
|
|
97
|
+
? { text: '', message: '', detail: '', percent: null, ...raw, phase, startedAt: Date.now() }
|
|
98
|
+
: { ...current, ...raw, phase, startedAt: current.startedAt || Date.now() };
|
|
99
|
+
State.set('ui', { ...ui, generationStatus: next });
|
|
100
|
+
} else {
|
|
101
|
+
next = { ...raw, phase, startedAt: Date.now() };
|
|
102
|
+
}
|
|
103
|
+
render(element, next);
|
|
104
|
+
return next;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
function clearStatus(element) {
|
|
108
|
+
const State = resolveState();
|
|
109
|
+
if (State?.clearGenerationStatus) {
|
|
110
|
+
State.clearGenerationStatus();
|
|
111
|
+
} else if (State?.get && State?.set) {
|
|
112
|
+
const ui = State.get('ui') || {};
|
|
113
|
+
State.set('ui', { ...ui, generationStatus: { phase: 'idle', percent: null, text: '', message: '', detail: '', startedAt: null } });
|
|
114
|
+
}
|
|
115
|
+
render(element, { phase: 'idle' });
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
return { getViewModel, render, setStatus, clearStatus };
|
|
119
|
+
}));
|