flexdesk 0.17.18 → 0.18.0
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/CHANGELOG.md +53 -0
- package/README.md +1 -0
- package/css/flexdesk.css +7544 -5916
- package/css/reset.css +1 -1
- package/css/tokens.css +23 -1
- package/dist/charts.js +10 -6
- package/dist/charts.js.map +1 -1
- package/dist/chunk-5W4EEKSK.js +778 -0
- package/dist/chunk-5W4EEKSK.js.map +7 -0
- package/dist/chunk-DNJ3N4T4.js +82 -0
- package/dist/chunk-DNJ3N4T4.js.map +7 -0
- package/dist/{chunk-REJ5HLIM.js → chunk-HYJYYEPK.js} +2 -2
- package/dist/{chunk-7U4IB65H.js → chunk-LLBJ2SJH.js} +5 -3
- package/dist/{chunk-7U4IB65H.js.map → chunk-LLBJ2SJH.js.map} +1 -1
- package/dist/{chunk-7OL6F2AM.js → chunk-P74F6I6P.js} +6 -4
- package/dist/{chunk-7OL6F2AM.js.map → chunk-P74F6I6P.js.map} +1 -1
- package/dist/chunk-PAI2ZUWV.js +260 -0
- package/dist/chunk-PAI2ZUWV.js.map +7 -0
- package/dist/chunk-Q7BALEPX.js +527 -0
- package/dist/chunk-Q7BALEPX.js.map +7 -0
- package/dist/chunk-QXAOTGCC.js +40 -0
- package/dist/chunk-QXAOTGCC.js.map +7 -0
- package/dist/{chunk-XJNADRGR.js → chunk-RKVYIXDC.js} +664 -91
- package/dist/chunk-RKVYIXDC.js.map +7 -0
- package/dist/{chunk-2Z2ENHR3.js → chunk-U5GKJUOC.js} +3 -3
- package/dist/{chunk-2Z2ENHR3.js.map → chunk-U5GKJUOC.js.map} +1 -1
- package/dist/chunk-UKP22RUG.js +219 -0
- package/dist/chunk-UKP22RUG.js.map +7 -0
- package/dist/chunk-VLOAI3HS.js +43 -0
- package/dist/chunk-VLOAI3HS.js.map +7 -0
- package/dist/{chunk-WUFLGETN.js → chunk-WVFGV5FT.js} +2 -39
- package/dist/{chunk-WUFLGETN.js.map → chunk-WVFGV5FT.js.map} +3 -3
- package/dist/{chunk-PGZ4EHSE.js → chunk-ZL3VKINP.js} +41 -390
- package/dist/chunk-ZL3VKINP.js.map +7 -0
- package/dist/editor.js +3 -2
- package/dist/editor.js.map +1 -1
- package/dist/flexdesk.css +7544 -5916
- package/dist/flow.js +29 -97
- package/dist/flow.js.map +3 -3
- package/dist/git.js +1356 -0
- package/dist/git.js.map +7 -0
- package/dist/reset.css +1 -1
- package/dist/tiles.js +20 -15
- package/dist/tiles.js.map +2 -2
- package/dist/tokens.css +23 -1
- package/dist/widgets.js +3967 -1188
- package/dist/widgets.js.map +4 -4
- package/dist/wm.js +120 -32
- package/dist/wm.js.map +2 -2
- package/docs/README.md +9 -4
- package/docs/best-practices.md +2 -2
- package/docs/components/chat-shell.md +198 -0
- package/docs/components/conversation.md +10 -0
- package/docs/components/filter-builder.md +246 -0
- package/docs/components/forms-and-dialogs.md +22 -0
- package/docs/components/git.md +355 -0
- package/docs/components/input-fields.md +167 -2
- package/docs/components/keymap.md +8 -0
- package/docs/components/menus.md +82 -2
- package/docs/components/panels-and-desktops.md +16 -5
- package/docs/components/shell.md +104 -1
- package/docs/components/workspace-picker.md +149 -0
- package/docs/concepts/building-and-packaging.md +2 -2
- package/docs/concepts/packages-and-entry-points.md +14 -13
- package/docs/concepts/state-guard.md +3 -3
- package/docs/quickstart.md +1 -1
- package/git.js +13 -0
- package/package.json +6 -1
- package/src/flow/kit/dom.js +28 -119
- package/src/flow/kit/step_picker.js +1 -1
- package/src/flow/kit/value_picker.js +1 -1
- package/src/flow/outline/menu.js +1 -1
- package/src/git/diff_viewer.js +212 -0
- package/src/git/diff_window.js +51 -0
- package/src/git/git_graph.js +401 -0
- package/src/git/git_ops.js +61 -0
- package/src/git/git_panel.js +755 -0
- package/src/git/index.js +9 -0
- package/src/git/line_diff.js +202 -0
- package/src/tiles/tile_base.js +5 -4
- package/src/tiling/desktops.js +10 -8
- package/src/tiling/keymap.js +6 -5
- package/src/tiling/kind_taxonomy.js +15 -2
- package/src/tiling/shell.js +124 -17
- package/src/tiling/tile_renderer.js +2 -3
- package/src/ui/components/action_dropdown.js +4 -78
- package/src/ui/components/anchored_layer.js +255 -0
- package/src/ui/components/chat_shell.js +920 -0
- package/src/ui/components/chat_state_machine.js +223 -0
- package/src/ui/components/choice_controls.js +45 -2
- package/src/ui/components/color_field.js +3 -2
- package/src/ui/components/color_list_field.js +3 -2
- package/src/ui/components/combobox.js +422 -0
- package/src/ui/components/conversation_view.js +17 -2
- package/src/ui/components/data_table.js +2 -2
- package/src/ui/components/filter_builder.js +766 -0
- package/src/ui/components/filter_model.js +614 -0
- package/src/ui/components/managed_window.js +24 -47
- package/src/ui/components/modal.js +79 -109
- package/src/ui/components/option_list.js +160 -0
- package/src/ui/components/popover.js +94 -0
- package/src/ui/components/recent_items.js +169 -0
- package/src/ui/components/select.js +322 -0
- package/src/ui/components/tag_input.js +77 -8
- package/src/ui/components/workspace_picker.js +1155 -0
- package/src/ui/utils/fire_event.js +17 -0
- package/src/ui/utils/focusable.js +25 -0
- package/src/ui/utils/modal_host.js +27 -0
- package/widgets.js +12 -2
- package/css/base.css +0 -10547
- package/css/overrides.css +0 -2596
- package/dist/chunk-7JI7HHSY.js +0 -107
- package/dist/chunk-7JI7HHSY.js.map +0 -7
- package/dist/chunk-MIW7D6WC.js +0 -526
- package/dist/chunk-MIW7D6WC.js.map +0 -7
- package/dist/chunk-PGZ4EHSE.js.map +0 -7
- package/dist/chunk-XJNADRGR.js.map +0 -7
- /package/dist/{chunk-REJ5HLIM.js.map → chunk-HYJYYEPK.js.map} +0 -0
|
@@ -0,0 +1,778 @@
|
|
|
1
|
+
import {
|
|
2
|
+
openConfirm,
|
|
3
|
+
openForm,
|
|
4
|
+
openModal
|
|
5
|
+
} from "./chunk-RKVYIXDC.js";
|
|
6
|
+
import {
|
|
7
|
+
ManagedWindow
|
|
8
|
+
} from "./chunk-ZL3VKINP.js";
|
|
9
|
+
|
|
10
|
+
// src/ui/components/progress.js
|
|
11
|
+
var PROGRESS_STATES = Object.freeze(["running", "done", "error", "cancelled"]);
|
|
12
|
+
var PROGRESS_ITEM_STATES = Object.freeze(["pending", "running", "done", "failed"]);
|
|
13
|
+
var STEP_STATES = Object.freeze(["pending", "active", "done", "error"]);
|
|
14
|
+
var clamp01 = (x) => x < 0 ? 0 : x > 1 ? 1 : x;
|
|
15
|
+
var isNum = (x) => typeof x === "number" && Number.isFinite(x);
|
|
16
|
+
function formatElapsed(ms) {
|
|
17
|
+
const s = Math.max(0, Math.floor((ms || 0) / 1e3));
|
|
18
|
+
const h = Math.floor(s / 3600);
|
|
19
|
+
const m = Math.floor(s % 3600 / 60);
|
|
20
|
+
const ss = String(s % 60).padStart(2, "0");
|
|
21
|
+
return h ? `${h}:${String(m).padStart(2, "0")}:${ss}` : `${m}:${ss}`;
|
|
22
|
+
}
|
|
23
|
+
function el(tag, className, text) {
|
|
24
|
+
const n = document.createElement(tag);
|
|
25
|
+
if (className) n.className = className;
|
|
26
|
+
if (text !== void 0) n.textContent = text;
|
|
27
|
+
return n;
|
|
28
|
+
}
|
|
29
|
+
function setText(node, text) {
|
|
30
|
+
const t = text == null ? "" : String(text);
|
|
31
|
+
if (node.textContent !== t) node.textContent = t;
|
|
32
|
+
}
|
|
33
|
+
function setWidth(node, fraction) {
|
|
34
|
+
const w = `${(clamp01(fraction) * 100).toFixed(2).replace(/\.?0+$/, "")}%`;
|
|
35
|
+
if (node.style.width !== w) node.style.width = w;
|
|
36
|
+
}
|
|
37
|
+
var ProgressBar = class {
|
|
38
|
+
/**
|
|
39
|
+
* @param {HTMLElement|null} host appended to, if given
|
|
40
|
+
* @param {ProgressBarOptions} [options]
|
|
41
|
+
*/
|
|
42
|
+
constructor(host, options = {}) {
|
|
43
|
+
const {
|
|
44
|
+
value = 0,
|
|
45
|
+
max = null,
|
|
46
|
+
indeterminate = false,
|
|
47
|
+
label = "",
|
|
48
|
+
showPercent = true,
|
|
49
|
+
showCount = null,
|
|
50
|
+
showElapsed = false,
|
|
51
|
+
onCancel = null,
|
|
52
|
+
cancelLabel = "Cancel",
|
|
53
|
+
now = Date.now,
|
|
54
|
+
className = ""
|
|
55
|
+
} = options;
|
|
56
|
+
this._value = isNum(value) ? value : 0;
|
|
57
|
+
this._max = isNum(max) && max > 0 ? max : null;
|
|
58
|
+
this._indeterminate = !!indeterminate;
|
|
59
|
+
this._label = label || "";
|
|
60
|
+
this._showPercent = showPercent !== false;
|
|
61
|
+
this._showCount = showCount;
|
|
62
|
+
this._showElapsed = !!showElapsed;
|
|
63
|
+
this._state = "running";
|
|
64
|
+
this._now = typeof now === "function" ? now : Date.now;
|
|
65
|
+
this._started = this._now();
|
|
66
|
+
this._stopped = null;
|
|
67
|
+
this._timer = null;
|
|
68
|
+
this._onCancel = typeof onCancel === "function" ? onCancel : null;
|
|
69
|
+
const root = el("div", `twm-progress${className ? ` ${className}` : ""}`);
|
|
70
|
+
const head = el("div", "twm-progress__head");
|
|
71
|
+
this._labelEl = el("span", "twm-progress__label");
|
|
72
|
+
this._readoutEl = el("span", "twm-progress__readout");
|
|
73
|
+
head.append(this._labelEl, this._readoutEl);
|
|
74
|
+
if (this._showElapsed) {
|
|
75
|
+
this._elapsedEl = el("span", "twm-progress__elapsed");
|
|
76
|
+
head.appendChild(this._elapsedEl);
|
|
77
|
+
this._startTimer();
|
|
78
|
+
} else {
|
|
79
|
+
this._elapsedEl = null;
|
|
80
|
+
}
|
|
81
|
+
if (this._onCancel) {
|
|
82
|
+
const btn = el("button", "twm-progress__cancel", cancelLabel);
|
|
83
|
+
btn.type = "button";
|
|
84
|
+
btn.addEventListener("click", () => {
|
|
85
|
+
if (btn.disabled || this._state !== "running") return;
|
|
86
|
+
btn.disabled = true;
|
|
87
|
+
this._onCancel();
|
|
88
|
+
});
|
|
89
|
+
this._cancelBtn = btn;
|
|
90
|
+
head.appendChild(btn);
|
|
91
|
+
} else {
|
|
92
|
+
this._cancelBtn = null;
|
|
93
|
+
}
|
|
94
|
+
this._track = el("div", "twm-progress__track");
|
|
95
|
+
this._track.setAttribute("role", "progressbar");
|
|
96
|
+
this._fill = el("div", "twm-progress__fill");
|
|
97
|
+
this._track.appendChild(this._fill);
|
|
98
|
+
root.append(head, this._track);
|
|
99
|
+
this.element = root;
|
|
100
|
+
this._draw();
|
|
101
|
+
if (host) host.appendChild(root);
|
|
102
|
+
}
|
|
103
|
+
/** The bar's fraction 0..1, or null while indeterminate. */
|
|
104
|
+
get fraction() {
|
|
105
|
+
if (this._indeterminate) return null;
|
|
106
|
+
return clamp01(this._max ? this._value / this._max : this._value);
|
|
107
|
+
}
|
|
108
|
+
/** `running`, `done`, `error` or `cancelled`. */
|
|
109
|
+
get state() {
|
|
110
|
+
return this._state;
|
|
111
|
+
}
|
|
112
|
+
/** Milliseconds since construction, frozen at the final state. */
|
|
113
|
+
get elapsed() {
|
|
114
|
+
return (this._stopped ?? this._now()) - this._started;
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Change the bar in place. A number is the new value (a count with `max`,
|
|
118
|
+
* else a fraction); an object may carry `value`, `max`, `label` and
|
|
119
|
+
* `indeterminate`. Ignored once the bar is in a final state.
|
|
120
|
+
*/
|
|
121
|
+
update(next) {
|
|
122
|
+
if (this._state !== "running") return this;
|
|
123
|
+
const o = isNum(next) ? { value: next } : next || {};
|
|
124
|
+
if ("max" in o) this._max = isNum(o.max) && o.max > 0 ? o.max : null;
|
|
125
|
+
if (isNum(o.value)) {
|
|
126
|
+
this._value = o.value;
|
|
127
|
+
if (!("indeterminate" in o)) this._indeterminate = false;
|
|
128
|
+
}
|
|
129
|
+
if ("indeterminate" in o) this._indeterminate = !!o.indeterminate;
|
|
130
|
+
if ("label" in o) this._label = o.label || "";
|
|
131
|
+
this._draw();
|
|
132
|
+
return this;
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Put the bar in a final state (`done`, `error`, `cancelled`) or back to
|
|
136
|
+
* `running`. `done` fills it. A final state stops the elapsed clock and
|
|
137
|
+
* disables Cancel; `running` restarts the clock (still counting from
|
|
138
|
+
* construction) and enables Cancel again. `label` replaces the label when
|
|
139
|
+
* given.
|
|
140
|
+
*/
|
|
141
|
+
setState(state, { label } = {}) {
|
|
142
|
+
if (!PROGRESS_STATES.includes(state)) throw new Error(`ProgressBar: unknown state "${state}"`);
|
|
143
|
+
this._state = state;
|
|
144
|
+
if (label !== void 0) this._label = label || "";
|
|
145
|
+
if (state === "done") {
|
|
146
|
+
this._indeterminate = false;
|
|
147
|
+
this._value = this._max ?? 1;
|
|
148
|
+
}
|
|
149
|
+
if (state === "running") {
|
|
150
|
+
this._stopped = null;
|
|
151
|
+
if (this._showElapsed) this._startTimer();
|
|
152
|
+
} else {
|
|
153
|
+
this._stopped = this._now();
|
|
154
|
+
if (this._timer) {
|
|
155
|
+
clearInterval(this._timer);
|
|
156
|
+
this._timer = null;
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
if (this._cancelBtn) this._cancelBtn.disabled = state !== "running";
|
|
160
|
+
this._draw();
|
|
161
|
+
this._drawElapsed();
|
|
162
|
+
return this;
|
|
163
|
+
}
|
|
164
|
+
/** Tick the elapsed readout once a second, unless it already ticks. */
|
|
165
|
+
_startTimer() {
|
|
166
|
+
if (!this._timer) this._timer = setInterval(() => this._drawElapsed(), 1e3);
|
|
167
|
+
}
|
|
168
|
+
/** Stop the elapsed clock and detach. */
|
|
169
|
+
dispose() {
|
|
170
|
+
this._showElapsed = false;
|
|
171
|
+
if (this._timer) {
|
|
172
|
+
clearInterval(this._timer);
|
|
173
|
+
this._timer = null;
|
|
174
|
+
}
|
|
175
|
+
this.element.remove();
|
|
176
|
+
}
|
|
177
|
+
_draw() {
|
|
178
|
+
const root = this.element;
|
|
179
|
+
for (const s of PROGRESS_STATES) {
|
|
180
|
+
root.classList.toggle(`twm-progress--${s}`, this._state === s);
|
|
181
|
+
}
|
|
182
|
+
root.classList.toggle("twm-progress--indeterminate", this._indeterminate);
|
|
183
|
+
setText(this._labelEl, this._label);
|
|
184
|
+
const f = this.fraction;
|
|
185
|
+
const parts = [];
|
|
186
|
+
if (f !== null) {
|
|
187
|
+
if (this._showPercent) parts.push(`${Math.floor(f * 100)}%`);
|
|
188
|
+
const count = this._showCount ?? !!this._max;
|
|
189
|
+
if (count && this._max) parts.push(`${fmtCount(this._value)} / ${fmtCount(this._max)}`);
|
|
190
|
+
}
|
|
191
|
+
setText(this._readoutEl, parts.join(" \xB7 "));
|
|
192
|
+
if (f === null) {
|
|
193
|
+
if (this._fill.style.width) this._fill.style.width = "";
|
|
194
|
+
this._track.removeAttribute("aria-valuenow");
|
|
195
|
+
} else {
|
|
196
|
+
setWidth(this._fill, f);
|
|
197
|
+
this._track.setAttribute("aria-valuenow", String(Math.round(f * 100)));
|
|
198
|
+
}
|
|
199
|
+
this._track.setAttribute("aria-valuemin", "0");
|
|
200
|
+
this._track.setAttribute("aria-valuemax", "100");
|
|
201
|
+
if (this._label) this._track.setAttribute("aria-label", this._label);
|
|
202
|
+
this._drawElapsed();
|
|
203
|
+
}
|
|
204
|
+
_drawElapsed() {
|
|
205
|
+
if (this._elapsedEl) setText(this._elapsedEl, formatElapsed(this.elapsed));
|
|
206
|
+
}
|
|
207
|
+
};
|
|
208
|
+
function fmtCount(n) {
|
|
209
|
+
return Number.isInteger(n) ? String(n) : String(Math.round(n * 100) / 100);
|
|
210
|
+
}
|
|
211
|
+
var ProgressList = class {
|
|
212
|
+
/**
|
|
213
|
+
* @param {HTMLElement|null} host appended to, if given
|
|
214
|
+
* @param {ProgressListOptions} [options]
|
|
215
|
+
*/
|
|
216
|
+
constructor(host, options = {}) {
|
|
217
|
+
const { items = [], stats = true, pulse = true, emptyText = "", className = "" } = options;
|
|
218
|
+
this._stats = stats;
|
|
219
|
+
this._emptyText = emptyText;
|
|
220
|
+
this._rows = /* @__PURE__ */ new Map();
|
|
221
|
+
this._items = [];
|
|
222
|
+
const root = el("div", `twm-progress-list${pulse ? " twm-progress-list--pulse" : ""}${className ? ` ${className}` : ""}`);
|
|
223
|
+
this._listEl = el("div", "twm-progress-list__rows");
|
|
224
|
+
this._listEl.setAttribute("role", "list");
|
|
225
|
+
this._emptyEl = el("div", "twm-progress-list__empty");
|
|
226
|
+
this._statsEl = el("div", "twm-progress-list__stats");
|
|
227
|
+
root.append(this._listEl, this._emptyEl, this._statsEl);
|
|
228
|
+
this.element = root;
|
|
229
|
+
this.setItems(items);
|
|
230
|
+
if (host) host.appendChild(root);
|
|
231
|
+
}
|
|
232
|
+
/** The items last given, in order. */
|
|
233
|
+
get items() {
|
|
234
|
+
return this._items.slice();
|
|
235
|
+
}
|
|
236
|
+
/**
|
|
237
|
+
* Reconcile the rows with `items` by key: a known key keeps its row and
|
|
238
|
+
* has its text, width and state changed in place; a new key gets a row; a
|
|
239
|
+
* key that is gone loses its row. Rows follow the order given, and a row
|
|
240
|
+
* already in its place is not moved.
|
|
241
|
+
*/
|
|
242
|
+
setItems(items) {
|
|
243
|
+
const list = Array.isArray(items) ? items : [];
|
|
244
|
+
const seen = /* @__PURE__ */ new Set();
|
|
245
|
+
this._items = [];
|
|
246
|
+
for (const it of list) {
|
|
247
|
+
if (!it || it.key == null) continue;
|
|
248
|
+
const k = String(it.key);
|
|
249
|
+
if (seen.has(k)) continue;
|
|
250
|
+
seen.add(k);
|
|
251
|
+
this._items.push(it);
|
|
252
|
+
}
|
|
253
|
+
for (const [k, r] of this._rows) {
|
|
254
|
+
if (!seen.has(k)) {
|
|
255
|
+
r.row.remove();
|
|
256
|
+
this._rows.delete(k);
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
const scale = this._items.reduce((m, it) => {
|
|
260
|
+
const d = isNum(it.total) && it.total > 0 ? it.total : isNum(it.completed) ? it.completed : 0;
|
|
261
|
+
return d > m ? d : m;
|
|
262
|
+
}, 0);
|
|
263
|
+
let prev = null;
|
|
264
|
+
for (const it of this._items) {
|
|
265
|
+
const k = String(it.key);
|
|
266
|
+
let r = this._rows.get(k);
|
|
267
|
+
if (!r) {
|
|
268
|
+
r = this._makeRow();
|
|
269
|
+
this._rows.set(k, r);
|
|
270
|
+
}
|
|
271
|
+
this._drawRow(r, it, scale);
|
|
272
|
+
const want = prev ? prev.nextSibling : this._listEl.firstChild;
|
|
273
|
+
if (want !== r.row) this._listEl.insertBefore(r.row, want);
|
|
274
|
+
prev = r.row;
|
|
275
|
+
}
|
|
276
|
+
this._emptyEl.hidden = this._items.length > 0 || !this._emptyText;
|
|
277
|
+
setText(this._emptyEl, this._emptyText);
|
|
278
|
+
const line = this._statsLine();
|
|
279
|
+
this._statsEl.hidden = !line;
|
|
280
|
+
setText(this._statsEl, line);
|
|
281
|
+
return this;
|
|
282
|
+
}
|
|
283
|
+
/** The row element for `key`, or null. */
|
|
284
|
+
rowFor(key) {
|
|
285
|
+
return this._rows.get(String(key))?.row ?? null;
|
|
286
|
+
}
|
|
287
|
+
dispose() {
|
|
288
|
+
this.element.remove();
|
|
289
|
+
this._rows.clear();
|
|
290
|
+
}
|
|
291
|
+
_makeRow() {
|
|
292
|
+
const row = el("div", "twm-progress-list__row");
|
|
293
|
+
row.setAttribute("role", "listitem");
|
|
294
|
+
const name = el("span", "twm-progress-list__name");
|
|
295
|
+
const track = el("div", "twm-progress-list__track");
|
|
296
|
+
const fill = el("div", "twm-progress-list__fill");
|
|
297
|
+
track.appendChild(fill);
|
|
298
|
+
const count = el("span", "twm-progress-list__count");
|
|
299
|
+
const state = el("span", "twm-progress-list__state");
|
|
300
|
+
row.append(state, name, track, count);
|
|
301
|
+
return { row, name, fill, count, state };
|
|
302
|
+
}
|
|
303
|
+
_drawRow(r, it, scale) {
|
|
304
|
+
const state = PROGRESS_ITEM_STATES.includes(it.state) ? it.state : "pending";
|
|
305
|
+
for (const s of PROGRESS_ITEM_STATES) {
|
|
306
|
+
r.row.classList.toggle(`twm-progress-list__row--${s}`, s === state);
|
|
307
|
+
}
|
|
308
|
+
const done = isNum(it.completed) ? it.completed : 0;
|
|
309
|
+
const hasTotal = isNum(it.total) && it.total > 0;
|
|
310
|
+
const denom = hasTotal ? it.total : scale;
|
|
311
|
+
setWidth(r.fill, denom > 0 ? done / denom : 0);
|
|
312
|
+
setText(r.name, it.name ?? String(it.key));
|
|
313
|
+
const count = hasTotal ? `${fmtCount(done)} / ${fmtCount(it.total)}` : fmtCount(done);
|
|
314
|
+
setText(r.count, it.detail ? `${count} \xB7 ${it.detail}` : count);
|
|
315
|
+
if (r.state.title !== state) r.state.title = state;
|
|
316
|
+
}
|
|
317
|
+
_statsLine() {
|
|
318
|
+
if (this._stats === false) return "";
|
|
319
|
+
if (typeof this._stats === "function") return String(this._stats(this.items) ?? "");
|
|
320
|
+
if (!this._items.length) return "";
|
|
321
|
+
const n = { done: 0, running: 0, failed: 0, pending: 0 };
|
|
322
|
+
let completed = 0;
|
|
323
|
+
for (const it of this._items) {
|
|
324
|
+
n[PROGRESS_ITEM_STATES.includes(it.state) ? it.state : "pending"] += 1;
|
|
325
|
+
if (isNum(it.completed)) completed += it.completed;
|
|
326
|
+
}
|
|
327
|
+
const parts = [`${n.done} / ${this._items.length} done`];
|
|
328
|
+
if (n.running) parts.push(`${n.running} running`);
|
|
329
|
+
if (n.failed) parts.push(`${n.failed} failed`);
|
|
330
|
+
if (n.pending) parts.push(`${n.pending} pending`);
|
|
331
|
+
parts.push(`${fmtCount(completed)} completed`);
|
|
332
|
+
return parts.join(" \xB7 ");
|
|
333
|
+
}
|
|
334
|
+
};
|
|
335
|
+
var StepProgress = class {
|
|
336
|
+
/**
|
|
337
|
+
* @param {HTMLElement|null} host appended to, if given
|
|
338
|
+
* @param {{ steps?: Array<StepDef|string>, className?: string }} [options]
|
|
339
|
+
*/
|
|
340
|
+
constructor(host, options = {}) {
|
|
341
|
+
const { steps = [], className = "" } = options;
|
|
342
|
+
const root = el("ol", `twm-steps${className ? ` ${className}` : ""}`);
|
|
343
|
+
this.element = root;
|
|
344
|
+
this._steps = steps.map((s, i) => {
|
|
345
|
+
const def = typeof s === "string" ? { label: s } : s || {};
|
|
346
|
+
const li = el("li", "twm-steps__step");
|
|
347
|
+
const marker = el("span", "twm-steps__marker");
|
|
348
|
+
const label = el("span", "twm-steps__label", def.label ?? "");
|
|
349
|
+
const pass = el("span", "twm-steps__pass");
|
|
350
|
+
pass.hidden = true;
|
|
351
|
+
li.append(marker, label, pass);
|
|
352
|
+
root.appendChild(li);
|
|
353
|
+
return { key: def.key != null ? String(def.key) : String(i), label: def.label ?? "", state: "pending", pass: null, li, passEl: pass };
|
|
354
|
+
});
|
|
355
|
+
this._draw();
|
|
356
|
+
if (host) host.appendChild(root);
|
|
357
|
+
}
|
|
358
|
+
/** `[{ key, label, state, pass }]`, in order. */
|
|
359
|
+
get steps() {
|
|
360
|
+
return this._steps.map(({ key, label, state, pass }) => ({ key, label, state, pass }));
|
|
361
|
+
}
|
|
362
|
+
/** The index of the active phase, or -1. */
|
|
363
|
+
get activeIndex() {
|
|
364
|
+
return this._steps.findIndex((s) => s.state === "active");
|
|
365
|
+
}
|
|
366
|
+
/**
|
|
367
|
+
* Make one phase active: every phase before it is done, every phase after
|
|
368
|
+
* it pending. `pass` and `passes` read "pass n of m" on it.
|
|
369
|
+
* @param {string|number} which - A key, or an index.
|
|
370
|
+
* @param {{ pass?: number, passes?: number }} [opts]
|
|
371
|
+
*/
|
|
372
|
+
setStep(which, { pass, passes } = {}) {
|
|
373
|
+
const i = this._index(which);
|
|
374
|
+
this._steps.forEach((s, j) => {
|
|
375
|
+
s.state = j < i ? "done" : j === i ? "active" : "pending";
|
|
376
|
+
s.pass = j === i && isNum(pass) ? { n: pass, of: isNum(passes) ? passes : null } : null;
|
|
377
|
+
});
|
|
378
|
+
this._draw();
|
|
379
|
+
return this;
|
|
380
|
+
}
|
|
381
|
+
/** Mark a phase (the active one by default) as failed; phases after it stay pending. */
|
|
382
|
+
fail(which) {
|
|
383
|
+
const i = which === void 0 ? this.activeIndex : this._index(which);
|
|
384
|
+
if (i < 0) return this;
|
|
385
|
+
this._steps.forEach((s, j) => {
|
|
386
|
+
if (j < i) s.state = "done";
|
|
387
|
+
else if (j === i) s.state = "error";
|
|
388
|
+
else s.state = "pending";
|
|
389
|
+
if (j !== i) s.pass = null;
|
|
390
|
+
});
|
|
391
|
+
this._draw();
|
|
392
|
+
return this;
|
|
393
|
+
}
|
|
394
|
+
/** Every phase done. */
|
|
395
|
+
complete() {
|
|
396
|
+
for (const s of this._steps) {
|
|
397
|
+
s.state = "done";
|
|
398
|
+
s.pass = null;
|
|
399
|
+
}
|
|
400
|
+
this._draw();
|
|
401
|
+
return this;
|
|
402
|
+
}
|
|
403
|
+
dispose() {
|
|
404
|
+
this.element.remove();
|
|
405
|
+
}
|
|
406
|
+
_index(which) {
|
|
407
|
+
const i = typeof which === "number" ? which : this._steps.findIndex((s) => s.key === String(which));
|
|
408
|
+
if (!Number.isInteger(i) || i < 0 || i >= this._steps.length) {
|
|
409
|
+
throw new Error(`StepProgress: no step "${which}"`);
|
|
410
|
+
}
|
|
411
|
+
return i;
|
|
412
|
+
}
|
|
413
|
+
_draw() {
|
|
414
|
+
for (const s of this._steps) {
|
|
415
|
+
for (const st of STEP_STATES) s.li.classList.toggle(`twm-steps__step--${st}`, s.state === st);
|
|
416
|
+
if (s.state === "active") s.li.setAttribute("aria-current", "step");
|
|
417
|
+
else s.li.removeAttribute("aria-current");
|
|
418
|
+
const text = s.pass ? s.pass.of ? `pass ${s.pass.n} of ${s.pass.of}` : `pass ${s.pass.n}` : "";
|
|
419
|
+
s.passEl.hidden = !text;
|
|
420
|
+
setText(s.passEl, text);
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
};
|
|
424
|
+
|
|
425
|
+
// src/ui/components/job_progress.js
|
|
426
|
+
function mountJobProgress(parent, { progress = null, steps = null, spinner = null } = {}) {
|
|
427
|
+
const stepper = Array.isArray(steps) && steps.length ? new StepProgress(parent, { steps, className: "twm-job-progress__steps" }) : null;
|
|
428
|
+
let bar = null;
|
|
429
|
+
if (progress) {
|
|
430
|
+
const { onCancel: _ignored, ...rest } = typeof progress === "object" ? progress : {};
|
|
431
|
+
bar = new ProgressBar(parent, { ...rest, className: "twm-job-progress__bar" });
|
|
432
|
+
if (spinner) spinner.hidden = true;
|
|
433
|
+
}
|
|
434
|
+
return {
|
|
435
|
+
get bar() {
|
|
436
|
+
return bar;
|
|
437
|
+
},
|
|
438
|
+
get steps() {
|
|
439
|
+
return stepper;
|
|
440
|
+
},
|
|
441
|
+
/** `bar.update(next)`. */
|
|
442
|
+
setProgress(next) {
|
|
443
|
+
if (!bar) throw new Error("setProgress: this dialog was opened without `progress`");
|
|
444
|
+
bar.update(next);
|
|
445
|
+
},
|
|
446
|
+
/** `steps.setStep(which, opts)`. */
|
|
447
|
+
setStep(which, opts) {
|
|
448
|
+
if (!stepper) throw new Error("setStep: this dialog was opened without `steps`");
|
|
449
|
+
stepper.setStep(which, opts);
|
|
450
|
+
},
|
|
451
|
+
/** Put the bar and the phases in their final state. */
|
|
452
|
+
finish(status) {
|
|
453
|
+
if (status === "done") {
|
|
454
|
+
bar?.setState("done");
|
|
455
|
+
stepper?.complete();
|
|
456
|
+
} else if (status === "error") {
|
|
457
|
+
bar?.setState("error");
|
|
458
|
+
stepper?.fail();
|
|
459
|
+
} else bar?.setState("cancelled");
|
|
460
|
+
}
|
|
461
|
+
};
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
// src/ui/components/confirm_dialog.js
|
|
465
|
+
var dialogIdCounter = 0;
|
|
466
|
+
async function showConfirmDialog(options = {}) {
|
|
467
|
+
const {
|
|
468
|
+
title = "Confirm",
|
|
469
|
+
message = "Are you sure?",
|
|
470
|
+
icon = "warning",
|
|
471
|
+
okLabel = "OK",
|
|
472
|
+
cancelLabel = "Cancel",
|
|
473
|
+
okVariant = "primary"
|
|
474
|
+
} = options;
|
|
475
|
+
return openConfirm({
|
|
476
|
+
title,
|
|
477
|
+
message,
|
|
478
|
+
icon,
|
|
479
|
+
confirmLabel: okLabel,
|
|
480
|
+
cancelLabel,
|
|
481
|
+
danger: okVariant === "danger"
|
|
482
|
+
});
|
|
483
|
+
}
|
|
484
|
+
async function showDeleteConfirmDialog(options = {}) {
|
|
485
|
+
const {
|
|
486
|
+
itemName = "",
|
|
487
|
+
itemType = "item",
|
|
488
|
+
additionalMessage = ""
|
|
489
|
+
} = options;
|
|
490
|
+
let message = `Delete ${itemType}`;
|
|
491
|
+
if (itemName) message += ` "${itemName}"`;
|
|
492
|
+
message += "?";
|
|
493
|
+
if (additionalMessage) message += `
|
|
494
|
+
|
|
495
|
+
${additionalMessage}`;
|
|
496
|
+
return openConfirm({
|
|
497
|
+
title: `Delete ${capitalize(itemType)}`,
|
|
498
|
+
message,
|
|
499
|
+
icon: "delete",
|
|
500
|
+
confirmLabel: "Delete",
|
|
501
|
+
cancelLabel: "Cancel",
|
|
502
|
+
danger: true
|
|
503
|
+
});
|
|
504
|
+
}
|
|
505
|
+
async function showCloseConfirmDialog(options = {}) {
|
|
506
|
+
const {
|
|
507
|
+
itemName = "",
|
|
508
|
+
itemType = "tab"
|
|
509
|
+
} = options;
|
|
510
|
+
let message = `Close ${itemType}`;
|
|
511
|
+
if (itemName) message += ` "${itemName}"`;
|
|
512
|
+
message += "?";
|
|
513
|
+
return openConfirm({
|
|
514
|
+
title: `Close ${capitalize(itemType)}`,
|
|
515
|
+
message,
|
|
516
|
+
icon: "close",
|
|
517
|
+
confirmLabel: "Close",
|
|
518
|
+
cancelLabel: "Cancel"
|
|
519
|
+
});
|
|
520
|
+
}
|
|
521
|
+
async function showChoiceDialog(options = {}) {
|
|
522
|
+
const {
|
|
523
|
+
title = "Choose",
|
|
524
|
+
message = "",
|
|
525
|
+
icon = "warning",
|
|
526
|
+
actions = []
|
|
527
|
+
} = options;
|
|
528
|
+
const content = document.createElement("div");
|
|
529
|
+
content.className = "twm-confirm-dialog__body";
|
|
530
|
+
content.innerHTML = `
|
|
531
|
+
<span class="twm-confirm-dialog__icon material-symbols-outlined">${escapeHtml(icon)}</span>
|
|
532
|
+
<div class="twm-confirm-dialog__message">${escapeHtml(message)}</div>
|
|
533
|
+
`;
|
|
534
|
+
return openModal({
|
|
535
|
+
title,
|
|
536
|
+
icon,
|
|
537
|
+
content,
|
|
538
|
+
width: 480,
|
|
539
|
+
height: 220,
|
|
540
|
+
actions: actions.map((a) => ({
|
|
541
|
+
label: a.label,
|
|
542
|
+
value: a.value,
|
|
543
|
+
primary: a.variant === "primary",
|
|
544
|
+
danger: a.variant === "danger"
|
|
545
|
+
}))
|
|
546
|
+
});
|
|
547
|
+
}
|
|
548
|
+
async function showSelectDialog(options = {}) {
|
|
549
|
+
const {
|
|
550
|
+
title = "Select",
|
|
551
|
+
message = "",
|
|
552
|
+
items = [],
|
|
553
|
+
okLabel = "OK",
|
|
554
|
+
cancelLabel = "Cancel"
|
|
555
|
+
} = options;
|
|
556
|
+
const fields = [];
|
|
557
|
+
if (message) {
|
|
558
|
+
fields.push({ section: message });
|
|
559
|
+
}
|
|
560
|
+
fields.push({
|
|
561
|
+
name: "_choice",
|
|
562
|
+
label: "Choice",
|
|
563
|
+
type: "select",
|
|
564
|
+
default: items[0]?.value || "",
|
|
565
|
+
options: items.map((i) => ({ value: i.value, label: i.label }))
|
|
566
|
+
});
|
|
567
|
+
void cancelLabel;
|
|
568
|
+
const data = await openForm({
|
|
569
|
+
title,
|
|
570
|
+
submitLabel: okLabel,
|
|
571
|
+
fields
|
|
572
|
+
});
|
|
573
|
+
if (!data) return null;
|
|
574
|
+
return data._choice;
|
|
575
|
+
}
|
|
576
|
+
function escapeHtml(str) {
|
|
577
|
+
if (!str) return "";
|
|
578
|
+
return String(str).replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """);
|
|
579
|
+
}
|
|
580
|
+
function capitalize(str) {
|
|
581
|
+
if (!str) return "";
|
|
582
|
+
return str.charAt(0).toUpperCase() + str.slice(1);
|
|
583
|
+
}
|
|
584
|
+
function showRunProgressDialog(options = {}) {
|
|
585
|
+
const {
|
|
586
|
+
title = "Running Pipeline",
|
|
587
|
+
message = "Starting\u2026",
|
|
588
|
+
onCancel,
|
|
589
|
+
progress = null,
|
|
590
|
+
steps = null
|
|
591
|
+
} = options;
|
|
592
|
+
const dialogId = `run-progress-${++dialogIdCounter}`;
|
|
593
|
+
let finished = false;
|
|
594
|
+
let settle;
|
|
595
|
+
const result = new Promise((resolve) => {
|
|
596
|
+
settle = resolve;
|
|
597
|
+
});
|
|
598
|
+
const contentEl = document.createElement("div");
|
|
599
|
+
contentEl.className = "twm-confirm-dialog__content run-progress";
|
|
600
|
+
const bodyEl = document.createElement("div");
|
|
601
|
+
bodyEl.className = "twm-run-progress__body";
|
|
602
|
+
const spinnerEl = document.createElement("div");
|
|
603
|
+
spinnerEl.className = "twm-run-progress__spinner";
|
|
604
|
+
const messageEl = document.createElement("div");
|
|
605
|
+
messageEl.className = "twm-run-progress__message";
|
|
606
|
+
messageEl.textContent = message;
|
|
607
|
+
bodyEl.append(spinnerEl, messageEl);
|
|
608
|
+
contentEl.appendChild(bodyEl);
|
|
609
|
+
const job = mountJobProgress(contentEl, { progress, steps, spinner: spinnerEl });
|
|
610
|
+
let stopBtn = null;
|
|
611
|
+
if (typeof onCancel === "function") {
|
|
612
|
+
const stopActionsEl = document.createElement("div");
|
|
613
|
+
stopActionsEl.className = "twm-confirm-dialog__actions twm-run-progress__stop-actions";
|
|
614
|
+
stopBtn = document.createElement("button");
|
|
615
|
+
stopBtn.type = "button";
|
|
616
|
+
stopBtn.className = "twm-confirm-dialog__btn twm-run-progress__stop-btn";
|
|
617
|
+
stopBtn.innerHTML = '<span class="material-symbols-outlined">stop</span> Stop';
|
|
618
|
+
stopBtn.addEventListener("click", () => {
|
|
619
|
+
stopBtn.disabled = true;
|
|
620
|
+
stopBtn.innerHTML = '<span class="material-symbols-outlined">hourglass_top</span> Stopping\u2026';
|
|
621
|
+
onCancel();
|
|
622
|
+
});
|
|
623
|
+
stopActionsEl.appendChild(stopBtn);
|
|
624
|
+
contentEl.appendChild(stopActionsEl);
|
|
625
|
+
}
|
|
626
|
+
const actionsEl = document.createElement("div");
|
|
627
|
+
actionsEl.className = "twm-confirm-dialog__actions";
|
|
628
|
+
actionsEl.style.display = "none";
|
|
629
|
+
const closeBtn = document.createElement("button");
|
|
630
|
+
closeBtn.type = "button";
|
|
631
|
+
closeBtn.className = "twm-confirm-dialog__btn twm-confirm-dialog__btn--primary";
|
|
632
|
+
closeBtn.textContent = "Close";
|
|
633
|
+
closeBtn.addEventListener("click", () => dialogWindow.close());
|
|
634
|
+
actionsEl.appendChild(closeBtn);
|
|
635
|
+
contentEl.appendChild(actionsEl);
|
|
636
|
+
const finish = (status, text, cls) => {
|
|
637
|
+
finished = true;
|
|
638
|
+
spinnerEl.style.display = "none";
|
|
639
|
+
if (stopBtn) stopBtn.parentElement.style.display = "none";
|
|
640
|
+
messageEl.textContent = text;
|
|
641
|
+
messageEl.className = `twm-run-progress__message ${cls}`;
|
|
642
|
+
job.finish(status);
|
|
643
|
+
actionsEl.style.display = "";
|
|
644
|
+
settle({ status, message: text });
|
|
645
|
+
};
|
|
646
|
+
const dialogWindow = new ManagedWindow({
|
|
647
|
+
id: dialogId,
|
|
648
|
+
title,
|
|
649
|
+
icon: "play_arrow",
|
|
650
|
+
content: contentEl,
|
|
651
|
+
minWidth: 320,
|
|
652
|
+
minHeight: 120,
|
|
653
|
+
defaultWidth: 420,
|
|
654
|
+
defaultHeight: 200 + (job.bar ? 40 : 0) + (job.steps ? 40 : 0),
|
|
655
|
+
canMinimize: false,
|
|
656
|
+
canMaximize: false,
|
|
657
|
+
canResize: false,
|
|
658
|
+
canDrag: false,
|
|
659
|
+
modal: true,
|
|
660
|
+
// BUG-0053. Focus goes to the window, never to Stop or Cancel: a stray
|
|
661
|
+
// Enter or Space would cancel the run.
|
|
662
|
+
focusOnOpen: "window",
|
|
663
|
+
onClose: () => {
|
|
664
|
+
if (finished) return;
|
|
665
|
+
finish("cancelled", "Cancelled.", "is-cancelled");
|
|
666
|
+
}
|
|
667
|
+
});
|
|
668
|
+
dialogWindow.show();
|
|
669
|
+
return {
|
|
670
|
+
result,
|
|
671
|
+
update(msg) {
|
|
672
|
+
if (finished) return;
|
|
673
|
+
messageEl.textContent = msg;
|
|
674
|
+
},
|
|
675
|
+
setProgress(next) {
|
|
676
|
+
if (finished) return;
|
|
677
|
+
job.setProgress(next);
|
|
678
|
+
},
|
|
679
|
+
setStep(which, opts) {
|
|
680
|
+
if (finished) return;
|
|
681
|
+
job.setStep(which, opts);
|
|
682
|
+
},
|
|
683
|
+
complete(res) {
|
|
684
|
+
if (finished) return;
|
|
685
|
+
finish(res?.ok ? "done" : "error", res?.message || "", res?.ok ? "is-ok" : "is-err");
|
|
686
|
+
},
|
|
687
|
+
cancelled(msg) {
|
|
688
|
+
if (finished) return;
|
|
689
|
+
finish("cancelled", msg || "Cancelled.", "is-cancelled");
|
|
690
|
+
},
|
|
691
|
+
close() {
|
|
692
|
+
try {
|
|
693
|
+
dialogWindow.close();
|
|
694
|
+
} catch {
|
|
695
|
+
}
|
|
696
|
+
}
|
|
697
|
+
};
|
|
698
|
+
}
|
|
699
|
+
|
|
700
|
+
// src/ui/components/toast.js
|
|
701
|
+
var toastBus = null;
|
|
702
|
+
function setToastBus(bus) {
|
|
703
|
+
const prev = toastBus;
|
|
704
|
+
toastBus = bus && typeof bus.emit === "function" ? bus : null;
|
|
705
|
+
return prev;
|
|
706
|
+
}
|
|
707
|
+
function getToastBus() {
|
|
708
|
+
return toastBus;
|
|
709
|
+
}
|
|
710
|
+
function _emit(severity, persistent, titleOrMsg, msg) {
|
|
711
|
+
const bus = toastBus;
|
|
712
|
+
const title = msg !== void 0 ? titleOrMsg : null;
|
|
713
|
+
const message = msg !== void 0 ? msg : titleOrMsg;
|
|
714
|
+
if (!bus) {
|
|
715
|
+
(severity === "error" || severity === "warn" ? console.warn : console.info)(
|
|
716
|
+
`[toast/${severity}]`,
|
|
717
|
+
title ? `${title}:` : "",
|
|
718
|
+
message
|
|
719
|
+
);
|
|
720
|
+
return;
|
|
721
|
+
}
|
|
722
|
+
bus.emit("toast:show", {
|
|
723
|
+
title,
|
|
724
|
+
message,
|
|
725
|
+
severity,
|
|
726
|
+
persistent,
|
|
727
|
+
durationMs: persistent ? 0 : 5e3
|
|
728
|
+
});
|
|
729
|
+
}
|
|
730
|
+
function toastError(titleOrMsg, msg) {
|
|
731
|
+
_emit("error", true, titleOrMsg, msg);
|
|
732
|
+
}
|
|
733
|
+
function toastWarn(titleOrMsg, msg) {
|
|
734
|
+
_emit("warn", false, titleOrMsg, msg);
|
|
735
|
+
}
|
|
736
|
+
function toastInfo(titleOrMsg, msg) {
|
|
737
|
+
_emit("info", false, titleOrMsg, msg);
|
|
738
|
+
}
|
|
739
|
+
function toastSuccess(titleOrMsg, msg) {
|
|
740
|
+
_emit("success", false, titleOrMsg, msg);
|
|
741
|
+
}
|
|
742
|
+
function reportBridgeError(opName, resOrErr) {
|
|
743
|
+
if (!resOrErr) return true;
|
|
744
|
+
if (resOrErr instanceof Error) {
|
|
745
|
+
toastError(opName, resOrErr.message || String(resOrErr));
|
|
746
|
+
return false;
|
|
747
|
+
}
|
|
748
|
+
if (resOrErr && resOrErr.ok === false) {
|
|
749
|
+
toastError(opName, resOrErr.error || "operation refused");
|
|
750
|
+
return false;
|
|
751
|
+
}
|
|
752
|
+
return true;
|
|
753
|
+
}
|
|
754
|
+
|
|
755
|
+
export {
|
|
756
|
+
PROGRESS_STATES,
|
|
757
|
+
PROGRESS_ITEM_STATES,
|
|
758
|
+
STEP_STATES,
|
|
759
|
+
formatElapsed,
|
|
760
|
+
ProgressBar,
|
|
761
|
+
ProgressList,
|
|
762
|
+
StepProgress,
|
|
763
|
+
mountJobProgress,
|
|
764
|
+
showConfirmDialog,
|
|
765
|
+
showDeleteConfirmDialog,
|
|
766
|
+
showCloseConfirmDialog,
|
|
767
|
+
showChoiceDialog,
|
|
768
|
+
showSelectDialog,
|
|
769
|
+
showRunProgressDialog,
|
|
770
|
+
setToastBus,
|
|
771
|
+
getToastBus,
|
|
772
|
+
toastError,
|
|
773
|
+
toastWarn,
|
|
774
|
+
toastInfo,
|
|
775
|
+
toastSuccess,
|
|
776
|
+
reportBridgeError
|
|
777
|
+
};
|
|
778
|
+
//# sourceMappingURL=chunk-5W4EEKSK.js.map
|