@atomm-developer/generator-workbench 0.1.0 → 0.1.1
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/README.md +9 -2
- package/dist/index.d.ts +31 -6
- package/dist/index.es.js +805 -290
- package/dist/index.umd.js +1 -1
- package/package.json +3 -2
package/dist/index.es.js
CHANGED
|
@@ -21,6 +21,22 @@ function createAuthController(args) {
|
|
|
21
21
|
}
|
|
22
22
|
function createExportController(args) {
|
|
23
23
|
const { sdk, runtime, config, element } = args;
|
|
24
|
+
async function ensureLoggedIn() {
|
|
25
|
+
if (sdk.auth.getStatus().isLogin) {
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
await sdk.auth.login();
|
|
29
|
+
if (!sdk.auth.getStatus().isLogin) {
|
|
30
|
+
throw new Error("[generator-workbench] login is required before export");
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
async function consumeBilling() {
|
|
34
|
+
var _a;
|
|
35
|
+
if (!((_a = sdk.billing) == null ? void 0 : _a.consume)) {
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
await sdk.billing.consume();
|
|
39
|
+
}
|
|
24
40
|
return {
|
|
25
41
|
async exportSvg() {
|
|
26
42
|
var _a;
|
|
@@ -29,6 +45,8 @@ function createExportController(args) {
|
|
|
29
45
|
runtime,
|
|
30
46
|
element
|
|
31
47
|
}));
|
|
48
|
+
await ensureLoggedIn();
|
|
49
|
+
await consumeBilling();
|
|
32
50
|
return sdk.export.download({ format: "svg" });
|
|
33
51
|
},
|
|
34
52
|
async openInStudio() {
|
|
@@ -38,6 +56,8 @@ function createExportController(args) {
|
|
|
38
56
|
runtime,
|
|
39
57
|
element
|
|
40
58
|
}));
|
|
59
|
+
await ensureLoggedIn();
|
|
60
|
+
await consumeBilling();
|
|
41
61
|
return sdk.export.openInStudio({ format: "svg" });
|
|
42
62
|
}
|
|
43
63
|
};
|
|
@@ -151,6 +171,8 @@ function createInitialWorkbenchState() {
|
|
|
151
171
|
isLogin: false,
|
|
152
172
|
userInfo: null
|
|
153
173
|
},
|
|
174
|
+
creditsBalance: 0,
|
|
175
|
+
billingUsage: null,
|
|
154
176
|
busy: {
|
|
155
177
|
login: false,
|
|
156
178
|
importTemplate: false,
|
|
@@ -185,264 +207,693 @@ function queryRequired(root, selector) {
|
|
|
185
207
|
function collectWorkbenchRefs(root) {
|
|
186
208
|
return {
|
|
187
209
|
root,
|
|
188
|
-
topbar: queryRequired(root, ".topbar"),
|
|
189
210
|
workspace: queryRequired(root, '[data-role="workspace"]'),
|
|
190
211
|
logoArea: queryRequired(root, '[data-role="logo-area"]'),
|
|
191
|
-
importTemplateBtn: queryRequired(root, '[data-role="import-template"]'),
|
|
192
|
-
exportTemplateBtn: queryRequired(root, '[data-role="export-template"]'),
|
|
193
|
-
loginBtn: queryRequired(root, '[data-role="login"]'),
|
|
194
|
-
avatarButton: queryRequired(root, '[data-role="avatar-button"]'),
|
|
195
|
-
avatarImage: queryRequired(root, '[data-role="avatar-image"]'),
|
|
196
|
-
avatarMenu: queryRequired(root, '[data-role="avatar-menu"]'),
|
|
197
|
-
logoutBtn: queryRequired(root, '[data-role="logout"]'),
|
|
198
|
-
panelSidebar: queryRequired(root, '[data-role="panel-sidebar"]'),
|
|
199
|
-
panelHost: queryRequired(root, '[data-role="panel-host"]'),
|
|
200
|
-
panelActions: queryRequired(root, '[data-role="panel-actions"]'),
|
|
201
212
|
canvasHost: queryRequired(root, '[data-role="canvas-host"]'),
|
|
202
|
-
|
|
203
|
-
fabMenu: queryRequired(root, '[data-role="fab-menu"]'),
|
|
204
|
-
exportSvgBtn: queryRequired(root, '[data-role="export-svg"]'),
|
|
205
|
-
openInStudioBtn: queryRequired(root, '[data-role="open-in-studio"]'),
|
|
213
|
+
panelHost: queryRequired(root, '[data-role="panel-host"]'),
|
|
206
214
|
templateFileInput: queryRequired(root, '[data-role="template-file-input"]')
|
|
207
215
|
};
|
|
208
216
|
}
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
:
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
|
|
225
|
-
}
|
|
217
|
+
const ATOMM_UI_CDN_CSS_URL = "https://minio-download.makeblock.com/resource/atomm-ui-umd/dist-browser/atomm-ui.min.css";
|
|
218
|
+
const CREDIT_ICON_DATA_URI = "data:image/svg+xml,%3csvg%20width='24'%20height='24'%20viewBox='0%200%2024%2024'%20fill='none'%20xmlns='http://www.w3.org/2000/svg'%3e%3ccircle%20cx='12'%20cy='12'%20r='9'%20fill='url(%23paint0_linear_503_69253)'/%3e%3cg%20filter='url(%23filter0_d_503_69253)'%3e%3crect%20x='7.75781'%20y='12'%20width='6'%20height='6'%20rx='1'%20transform='rotate(-45%207.75781%2012)'%20fill='url(%23paint1_linear_503_69253)'/%3e%3c/g%3e%3cdefs%3e%3cfilter%20id='filter0_d_503_69253'%20x='2.17188'%20y='4.17188'%20width='19.6572'%20height='19.6562'%20filterUnits='userSpaceOnUse'%20color-interpolation-filters='sRGB'%3e%3cfeFlood%20flood-opacity='0'%20result='BackgroundImageFix'/%3e%3cfeColorMatrix%20in='SourceAlpha'%20type='matrix'%20values='0%200%200%200%200%200%200%200%200%200%200%200%200%200%200%200%200%200%20127%200'%20result='hardAlpha'/%3e%3cfeOffset%20dy='2'/%3e%3cfeGaussianBlur%20stdDeviation='3'/%3e%3cfeComposite%20in2='hardAlpha'%20operator='out'/%3e%3cfeColorMatrix%20type='matrix'%20values='0%200%200%200%201%200%200%200%200%200.206957%200%200%200%200%200.0670085%200%200%200%201%200'/%3e%3cfeBlend%20mode='normal'%20in2='BackgroundImageFix'%20result='effect1_dropShadow_503_69253'/%3e%3cfeBlend%20mode='normal'%20in='SourceGraphic'%20in2='effect1_dropShadow_503_69253'%20result='shape'/%3e%3c/filter%3e%3clinearGradient%20id='paint0_linear_503_69253'%20x1='12'%20y1='3'%20x2='12'%20y2='21'%20gradientUnits='userSpaceOnUse'%3e%3cstop%20stop-color='%23FFA346'/%3e%3cstop%20offset='1'%20stop-color='%23FF7C23'/%3e%3c/linearGradient%3e%3clinearGradient%20id='paint1_linear_503_69253'%20x1='13.2327'%20y1='12.5252'%20x2='8.63652'%20y2='18.5356'%20gradientUnits='userSpaceOnUse'%3e%3cstop%20stop-color='white'/%3e%3cstop%20offset='1'%20stop-color='%23FFD3B5'/%3e%3c/linearGradient%3e%3c/defs%3e%3c/svg%3e";
|
|
219
|
+
const EXPORT_ICON_DATA_URI = "data:image/svg+xml,%3Csvg%20viewBox%3D'0%200%201088%201024'%20xmlns%3D'http%3A//www.w3.org/2000/svg'%3E%3Cpath%20d%3D'M416%20128v85.312h-128A42.688%2042.688%200%200%200%20245.312%20256v512c0%2023.552%2019.136%2042.688%2042.688%2042.688h512a42.688%2042.688%200%200%200%2042.688-42.688V597.312H928V768a128%20128%200%200%201-128%20128h-512a128%20128%200%200%201-128-128V256a128%20128%200%200%201%20128-128h128z'%20fill%3D'%23ffffff'/%3E%3Cpath%20d%3D'M723.52%20520.832L924.352%20320l-200.832-200.832-60.352%2060.352%2097.856%2097.792h-67.712A298.688%20298.688%200%200%200%20394.688%20576v85.312H480V576a213.312%20213.312%200%200%201%20213.312-213.312h67.712l-97.856%2097.792%2060.352%2060.352z'%20fill%3D'%23ffffff'/%3E%3C/svg%3E";
|
|
220
|
+
const WORKBENCH_SHELL_STYLES = `
|
|
221
|
+
:host {
|
|
222
|
+
display: block;
|
|
223
|
+
height: 100%;
|
|
224
|
+
color: #111827;
|
|
225
|
+
font-family: Inter, "Montserrat", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
|
|
226
|
+
--bg-soft: #f3f4f6;
|
|
227
|
+
--border-default: #e5e7eb;
|
|
228
|
+
--text-primary: #111827;
|
|
229
|
+
--text-secondary: #4b5563;
|
|
230
|
+
--text-muted: #9ca3af;
|
|
231
|
+
}
|
|
226
232
|
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
233
|
+
* {
|
|
234
|
+
box-sizing: border-box;
|
|
235
|
+
}
|
|
230
236
|
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
flex-direction: column;
|
|
235
|
-
background: #f5f7fb;
|
|
236
|
-
}
|
|
237
|
+
[data-workbench-vue-root] {
|
|
238
|
+
height: 100%;
|
|
239
|
+
}
|
|
237
240
|
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
}
|
|
241
|
+
.shell {
|
|
242
|
+
height: 100%;
|
|
243
|
+
display: flex;
|
|
244
|
+
flex-direction: column;
|
|
245
|
+
background:
|
|
246
|
+
radial-gradient(rgba(17, 24, 39, 0.06) 1px, transparent 1px),
|
|
247
|
+
linear-gradient(180deg, rgba(255, 255, 255, 0.7), rgba(249, 250, 251, 0.96));
|
|
248
|
+
background-size: 20px 20px, auto;
|
|
249
|
+
}
|
|
248
250
|
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
251
|
+
.topbar,
|
|
252
|
+
.app-topbar {
|
|
253
|
+
height: 64px;
|
|
254
|
+
display: flex;
|
|
255
|
+
align-items: center;
|
|
256
|
+
justify-content: space-between;
|
|
257
|
+
gap: 12px;
|
|
258
|
+
padding: 0 24px;
|
|
259
|
+
background: rgba(255, 255, 255, 0.92);
|
|
260
|
+
border-bottom: 1px solid var(--border-default);
|
|
261
|
+
backdrop-filter: blur(12px);
|
|
262
|
+
position: relative;
|
|
263
|
+
z-index: 20;
|
|
264
|
+
}
|
|
252
265
|
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
266
|
+
.logo-area,
|
|
267
|
+
.app-topbar-main {
|
|
268
|
+
display: flex;
|
|
269
|
+
align-items: center;
|
|
270
|
+
gap: 18px;
|
|
271
|
+
min-width: 0;
|
|
272
|
+
flex: 1;
|
|
273
|
+
}
|
|
258
274
|
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
275
|
+
.app-topbar-nav {
|
|
276
|
+
display: flex;
|
|
277
|
+
align-items: center;
|
|
278
|
+
gap: 10px;
|
|
279
|
+
flex-wrap: wrap;
|
|
280
|
+
}
|
|
265
281
|
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
282
|
+
.workspace {
|
|
283
|
+
flex: 1;
|
|
284
|
+
min-height: 0;
|
|
285
|
+
display: grid;
|
|
286
|
+
grid-template-columns: minmax(0, 1fr) 320px;
|
|
287
|
+
}
|
|
269
288
|
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
289
|
+
.workspace.panel-left {
|
|
290
|
+
grid-template-columns: 320px minmax(0, 1fr);
|
|
291
|
+
}
|
|
273
292
|
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
293
|
+
.workspace.panel-right .canvas-host {
|
|
294
|
+
grid-column: 1;
|
|
295
|
+
}
|
|
277
296
|
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
297
|
+
.workspace.panel-right .panel-sidebar {
|
|
298
|
+
grid-column: 2;
|
|
299
|
+
}
|
|
281
300
|
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
301
|
+
.workspace.panel-left .panel-sidebar {
|
|
302
|
+
grid-column: 1;
|
|
303
|
+
}
|
|
285
304
|
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
flex-direction: column;
|
|
290
|
-
background: #fff;
|
|
291
|
-
}
|
|
305
|
+
.workspace.panel-left .canvas-host {
|
|
306
|
+
grid-column: 2;
|
|
307
|
+
}
|
|
292
308
|
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
309
|
+
.panel-sidebar {
|
|
310
|
+
min-height: 0;
|
|
311
|
+
display: flex;
|
|
312
|
+
flex-direction: column;
|
|
313
|
+
background: #ffffff;
|
|
314
|
+
}
|
|
298
315
|
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
place-items: center;
|
|
305
|
-
}
|
|
316
|
+
.panel-host {
|
|
317
|
+
flex: 1;
|
|
318
|
+
min-height: 0;
|
|
319
|
+
overflow: auto;
|
|
320
|
+
}
|
|
306
321
|
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
color: #fff;
|
|
314
|
-
font: inherit;
|
|
315
|
-
}
|
|
322
|
+
.canvas-host {
|
|
323
|
+
position: relative;
|
|
324
|
+
min-height: 480px;
|
|
325
|
+
display: grid;
|
|
326
|
+
place-items: center;
|
|
327
|
+
}
|
|
316
328
|
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
329
|
+
.brand-logo {
|
|
330
|
+
height: 32px;
|
|
331
|
+
width: 92px;
|
|
332
|
+
display: block;
|
|
333
|
+
cursor: pointer;
|
|
334
|
+
flex: 0 0 auto;
|
|
335
|
+
}
|
|
321
336
|
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
337
|
+
.app-topbar-auth {
|
|
338
|
+
display: flex;
|
|
339
|
+
align-items: center;
|
|
340
|
+
justify-content: flex-end;
|
|
341
|
+
gap: 12px;
|
|
342
|
+
flex: 0 0 auto;
|
|
343
|
+
}
|
|
326
344
|
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
345
|
+
.topbar-credits-badge {
|
|
346
|
+
display: inline-flex;
|
|
347
|
+
align-items: center;
|
|
348
|
+
gap: 4px;
|
|
349
|
+
padding: 0;
|
|
350
|
+
color: #2d3541;
|
|
351
|
+
font-size: 14px;
|
|
352
|
+
font-weight: 500;
|
|
353
|
+
line-height: 1;
|
|
354
|
+
white-space: nowrap;
|
|
355
|
+
cursor: default;
|
|
356
|
+
}
|
|
332
357
|
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
gap: 8px;
|
|
337
|
-
background: transparent;
|
|
338
|
-
color: #111827;
|
|
339
|
-
padding: 0;
|
|
340
|
-
}
|
|
358
|
+
.topbar-credits-value {
|
|
359
|
+
font-variant-numeric: tabular-nums;
|
|
360
|
+
}
|
|
341
361
|
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
362
|
+
.credits-token-icon {
|
|
363
|
+
width: 20px;
|
|
364
|
+
height: 20px;
|
|
365
|
+
flex: 0 0 16px;
|
|
366
|
+
user-select: none;
|
|
367
|
+
-webkit-user-drag: none;
|
|
368
|
+
}
|
|
349
369
|
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
padding: 8px;
|
|
356
|
-
display: none;
|
|
357
|
-
background: #fff;
|
|
358
|
-
border: 1px solid #e5e7eb;
|
|
359
|
-
border-radius: 12px;
|
|
360
|
-
box-shadow: 0 12px 32px rgba(15, 23, 42, 0.08);
|
|
361
|
-
}
|
|
370
|
+
.credits-token-icon--sm {
|
|
371
|
+
width: 16px;
|
|
372
|
+
height: 16px;
|
|
373
|
+
flex-basis: 16px;
|
|
374
|
+
}
|
|
362
375
|
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
376
|
+
.auth-avatar-trigger {
|
|
377
|
+
display: inline-flex;
|
|
378
|
+
align-items: center;
|
|
379
|
+
gap: 6px;
|
|
380
|
+
padding: 4px 8px 4px 4px;
|
|
381
|
+
border-radius: 999px;
|
|
382
|
+
cursor: pointer;
|
|
383
|
+
transition: background 150ms ease;
|
|
384
|
+
}
|
|
367
385
|
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
}
|
|
386
|
+
.auth-avatar-trigger:hover {
|
|
387
|
+
background: var(--bg-soft);
|
|
388
|
+
}
|
|
372
389
|
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
390
|
+
.auth-avatar {
|
|
391
|
+
width: 40px;
|
|
392
|
+
height: 40px;
|
|
393
|
+
border-radius: 50%;
|
|
394
|
+
display: grid;
|
|
395
|
+
place-items: center;
|
|
396
|
+
overflow: hidden;
|
|
397
|
+
flex: 0 0 auto;
|
|
398
|
+
background: #f3f4f6;
|
|
399
|
+
color: var(--text-secondary);
|
|
400
|
+
font-size: 14px;
|
|
401
|
+
font-weight: 600;
|
|
402
|
+
}
|
|
377
403
|
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
404
|
+
.auth-avatar--lg {
|
|
405
|
+
width: 40px;
|
|
406
|
+
height: 40px;
|
|
407
|
+
font-size: 14px;
|
|
408
|
+
}
|
|
381
409
|
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
410
|
+
.auth-avatar img {
|
|
411
|
+
width: 100%;
|
|
412
|
+
height: 100%;
|
|
413
|
+
object-fit: cover;
|
|
414
|
+
display: block;
|
|
415
|
+
}
|
|
385
416
|
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
gap: 8px;
|
|
391
|
-
width: 100%;
|
|
392
|
-
}
|
|
417
|
+
.auth-popover-body {
|
|
418
|
+
min-width: 200px;
|
|
419
|
+
padding: 4px 0;
|
|
420
|
+
}
|
|
393
421
|
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
border-radius: 12px;
|
|
401
|
-
box-shadow: 0 16px 40px rgba(15, 23, 42, 0.12);
|
|
402
|
-
}
|
|
422
|
+
.auth-popover-header {
|
|
423
|
+
display: flex;
|
|
424
|
+
align-items: center;
|
|
425
|
+
gap: 12px;
|
|
426
|
+
padding: 12px 16px;
|
|
427
|
+
}
|
|
403
428
|
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
429
|
+
.auth-popover-user-text {
|
|
430
|
+
min-width: 0;
|
|
431
|
+
flex: 1;
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
.auth-popover-name {
|
|
435
|
+
display: block;
|
|
436
|
+
font-size: 14px;
|
|
437
|
+
font-weight: 600;
|
|
438
|
+
color: var(--text-primary);
|
|
439
|
+
overflow: hidden;
|
|
440
|
+
text-overflow: ellipsis;
|
|
441
|
+
white-space: nowrap;
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
.auth-popover-sub {
|
|
445
|
+
display: block;
|
|
446
|
+
margin-top: 2px;
|
|
447
|
+
font-size: 12px;
|
|
448
|
+
color: var(--text-secondary);
|
|
449
|
+
overflow: hidden;
|
|
450
|
+
text-overflow: ellipsis;
|
|
451
|
+
white-space: nowrap;
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
.auth-popover-divider {
|
|
455
|
+
height: 1px;
|
|
456
|
+
background: var(--border-default);
|
|
457
|
+
margin: 4px 0;
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
.auth-popover-action {
|
|
461
|
+
display: flex;
|
|
462
|
+
align-items: center;
|
|
463
|
+
gap: 8px;
|
|
464
|
+
padding: 8px 16px;
|
|
465
|
+
font-size: 13px;
|
|
466
|
+
color: var(--text-secondary);
|
|
467
|
+
cursor: pointer;
|
|
468
|
+
transition: all 150ms ease;
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
.auth-popover-action:hover {
|
|
472
|
+
background: var(--bg-soft);
|
|
473
|
+
color: var(--text-primary);
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
.auth-hover-card {
|
|
477
|
+
position: relative;
|
|
478
|
+
display: inline-flex;
|
|
479
|
+
align-items: center;
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
.auth-hover-panel {
|
|
483
|
+
position: absolute;
|
|
484
|
+
top: calc(100% + 8px);
|
|
485
|
+
right: 0;
|
|
486
|
+
z-index: 40;
|
|
487
|
+
min-width: 200px;
|
|
488
|
+
background: #fff;
|
|
489
|
+
border: 1px solid var(--border-default);
|
|
490
|
+
border-radius: 12px;
|
|
491
|
+
box-shadow: 0 8px 28px rgba(17, 24, 39, 0.12);
|
|
492
|
+
opacity: 0;
|
|
493
|
+
transform: translateY(4px);
|
|
494
|
+
pointer-events: none;
|
|
495
|
+
transition: opacity 150ms ease, transform 150ms ease;
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
.auth-hover-card:hover .auth-hover-panel,
|
|
499
|
+
.auth-hover-card:focus-within .auth-hover-panel {
|
|
500
|
+
opacity: 1;
|
|
501
|
+
transform: translateY(0);
|
|
502
|
+
pointer-events: auto;
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
.panel-actions,
|
|
506
|
+
#sidebar-footer {
|
|
507
|
+
flex-shrink: 0;
|
|
508
|
+
padding: 14px 24px;
|
|
509
|
+
border-top: 1px solid var(--border-default);
|
|
510
|
+
background: #ffffff;
|
|
511
|
+
display: flex;
|
|
512
|
+
align-items: center;
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
.sidebar-footer-export {
|
|
516
|
+
width: 100%;
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
.sidebar-footer-export .sidebar-export-trigger-btn,
|
|
520
|
+
.sidebar-footer-export .sidebar-export-trigger-btn-wrap,
|
|
521
|
+
.sidebar-export-trigger-btn-wrap {
|
|
522
|
+
width: 100%;
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
.sidebar-export-dropdown-menu {
|
|
526
|
+
width: 268px;
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
.sidebar-export-trigger-btn img {
|
|
530
|
+
margin-right: 4px;
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
.export-credits-hint {
|
|
534
|
+
display: inline-flex;
|
|
535
|
+
align-items: center;
|
|
536
|
+
justify-content: center;
|
|
537
|
+
gap: 2px;
|
|
538
|
+
padding: 0;
|
|
539
|
+
font-size: 12px;
|
|
540
|
+
font-weight: 600;
|
|
541
|
+
line-height: 1;
|
|
542
|
+
color: #ff7c23;
|
|
543
|
+
margin-left: 10px;
|
|
544
|
+
white-space: nowrap;
|
|
545
|
+
}
|
|
546
|
+
|
|
547
|
+
.export-credits-hint-value {
|
|
548
|
+
color: white;
|
|
549
|
+
font-size: 13px;
|
|
550
|
+
font-weight: 700;
|
|
551
|
+
font-variant-numeric: tabular-nums;
|
|
552
|
+
}
|
|
553
|
+
|
|
554
|
+
.export-overlay-menu,
|
|
555
|
+
.fab-menu-content {
|
|
556
|
+
padding: 4px;
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
.export-overlay-item {
|
|
560
|
+
display: flex;
|
|
561
|
+
align-items: center;
|
|
562
|
+
gap: 8px;
|
|
563
|
+
padding: 8px 12px;
|
|
564
|
+
border-radius: 6px;
|
|
565
|
+
font-size: 14px;
|
|
566
|
+
color: var(--text-primary);
|
|
567
|
+
cursor: pointer;
|
|
568
|
+
transition: background 120ms ease;
|
|
569
|
+
user-select: none;
|
|
570
|
+
}
|
|
571
|
+
|
|
572
|
+
.export-overlay-item:hover {
|
|
573
|
+
background: var(--bg-soft);
|
|
574
|
+
}
|
|
575
|
+
|
|
576
|
+
.export-overlay-item-icon {
|
|
577
|
+
width: 16px;
|
|
578
|
+
height: 16px;
|
|
579
|
+
border-radius: 4px;
|
|
580
|
+
background: #cbd5e1;
|
|
581
|
+
display: inline-block;
|
|
582
|
+
flex: 0 0 auto;
|
|
583
|
+
}
|
|
584
|
+
|
|
585
|
+
.export-overlay-item-icon--svg {
|
|
586
|
+
background: linear-gradient(180deg, #94a3b8, #64748b);
|
|
587
|
+
}
|
|
588
|
+
|
|
589
|
+
.export-overlay-item-icon--studio {
|
|
590
|
+
background: linear-gradient(180deg, #cbd5e1, #94a3b8);
|
|
591
|
+
}
|
|
592
|
+
|
|
593
|
+
.workspace.panel-right .panel-sidebar {
|
|
594
|
+
border-left: 1px solid var(--border-default);
|
|
595
|
+
}
|
|
596
|
+
|
|
597
|
+
.workspace.panel-left .panel-sidebar {
|
|
598
|
+
border-right: 1px solid var(--border-default);
|
|
599
|
+
}
|
|
600
|
+
`;
|
|
601
|
+
const WORKBENCH_VUE_TEMPLATE = `
|
|
408
602
|
<div class="shell">
|
|
409
|
-
<header class="topbar">
|
|
410
|
-
<div class="logo-area" data-role="logo-area"
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
<
|
|
420
|
-
|
|
603
|
+
<header class="topbar app-topbar">
|
|
604
|
+
<div class="logo-area app-topbar-main" data-role="logo-area">
|
|
605
|
+
<img
|
|
606
|
+
:src="state.logoSrc"
|
|
607
|
+
:alt="state.logoText || 'Atomm'"
|
|
608
|
+
class="brand-logo"
|
|
609
|
+
data-role="brand-logo"
|
|
610
|
+
draggable="false"
|
|
611
|
+
/>
|
|
612
|
+
<div class="app-topbar-nav">
|
|
613
|
+
<xt-button
|
|
614
|
+
v-show="state.templateEnabled"
|
|
615
|
+
type="secondary"
|
|
616
|
+
size="small"
|
|
617
|
+
data-role="import-template"
|
|
618
|
+
@click="callbacks.onImportTemplate()"
|
|
619
|
+
>导入模板</xt-button>
|
|
620
|
+
<xt-button
|
|
621
|
+
v-show="state.templateEnabled"
|
|
622
|
+
type="secondary"
|
|
623
|
+
size="small"
|
|
624
|
+
data-role="export-template"
|
|
625
|
+
@click="callbacks.onExportTemplate()"
|
|
626
|
+
>生成模板</xt-button>
|
|
627
|
+
</div>
|
|
628
|
+
</div>
|
|
629
|
+
<div class="app-topbar-auth">
|
|
630
|
+
<div
|
|
631
|
+
v-if="state.isLogin"
|
|
632
|
+
class="topbar-credits-badge"
|
|
633
|
+
data-role="topbar-credits"
|
|
634
|
+
title="Remaining credits"
|
|
635
|
+
>
|
|
636
|
+
<img src="${CREDIT_ICON_DATA_URI}" alt="" class="credits-token-icon" draggable="false" />
|
|
637
|
+
<span class="topbar-credits-value" data-role="topbar-credits-value">{{ state.creditsBalance }}</span>
|
|
638
|
+
</div>
|
|
639
|
+
|
|
640
|
+
<div
|
|
641
|
+
v-if="state.isLogin && state.avatarMenuTrigger === 'hover'"
|
|
642
|
+
class="auth-hover-card"
|
|
643
|
+
>
|
|
644
|
+
<div class="auth-avatar-trigger" data-role="avatar-button" tabindex="0">
|
|
645
|
+
<div class="auth-avatar">
|
|
646
|
+
<img
|
|
647
|
+
v-if="state.avatarSrc"
|
|
648
|
+
:src="state.avatarSrc"
|
|
649
|
+
alt="Avatar"
|
|
650
|
+
data-role="avatar-image"
|
|
651
|
+
/>
|
|
652
|
+
<span v-else data-role="avatar-image">{{ state.avatarText }}</span>
|
|
653
|
+
</div>
|
|
654
|
+
</div>
|
|
655
|
+
<div class="auth-hover-panel">
|
|
656
|
+
<div class="auth-popover-body" data-role="avatar-menu">
|
|
657
|
+
<div class="auth-popover-header">
|
|
658
|
+
<div class="auth-avatar auth-avatar--lg">
|
|
659
|
+
<img v-if="state.avatarSrc" :src="state.avatarSrc" alt="Avatar" />
|
|
660
|
+
<span v-else>{{ state.avatarText }}</span>
|
|
661
|
+
</div>
|
|
662
|
+
<div class="auth-popover-user-text">
|
|
663
|
+
<span class="auth-popover-name">{{ state.authDisplayName }}</span>
|
|
664
|
+
<span class="auth-popover-sub">{{ state.authSubline }}</span>
|
|
665
|
+
</div>
|
|
666
|
+
</div>
|
|
667
|
+
<div class="auth-popover-divider"></div>
|
|
668
|
+
<div class="auth-popover-action" data-role="logout" @click="callbacks.onLogout()">
|
|
669
|
+
Logout
|
|
670
|
+
</div>
|
|
671
|
+
</div>
|
|
421
672
|
</div>
|
|
422
673
|
</div>
|
|
674
|
+
|
|
675
|
+
<xt-dropdown-menu
|
|
676
|
+
v-else-if="state.isLogin"
|
|
677
|
+
trigger="click"
|
|
678
|
+
:portal-disabled="true"
|
|
679
|
+
placement="bottomRight"
|
|
680
|
+
>
|
|
681
|
+
<template #trigger>
|
|
682
|
+
<div class="auth-avatar-trigger" data-role="avatar-button">
|
|
683
|
+
<div class="auth-avatar">
|
|
684
|
+
<img
|
|
685
|
+
v-if="state.avatarSrc"
|
|
686
|
+
:src="state.avatarSrc"
|
|
687
|
+
alt="Avatar"
|
|
688
|
+
data-role="avatar-image"
|
|
689
|
+
/>
|
|
690
|
+
<span v-else data-role="avatar-image">{{ state.avatarText }}</span>
|
|
691
|
+
</div>
|
|
692
|
+
</div>
|
|
693
|
+
</template>
|
|
694
|
+
<template #overlay>
|
|
695
|
+
<div class="auth-popover-body" data-role="avatar-menu">
|
|
696
|
+
<div class="auth-popover-header">
|
|
697
|
+
<div class="auth-avatar auth-avatar--lg">
|
|
698
|
+
<img v-if="state.avatarSrc" :src="state.avatarSrc" alt="Avatar" />
|
|
699
|
+
<span v-else>{{ state.avatarText }}</span>
|
|
700
|
+
</div>
|
|
701
|
+
<div class="auth-popover-user-text">
|
|
702
|
+
<span class="auth-popover-name">{{ state.authDisplayName }}</span>
|
|
703
|
+
<span class="auth-popover-sub">{{ state.authSubline }}</span>
|
|
704
|
+
</div>
|
|
705
|
+
</div>
|
|
706
|
+
<div class="auth-popover-divider"></div>
|
|
707
|
+
<div class="auth-popover-action" data-role="logout" @click="callbacks.onLogout()">
|
|
708
|
+
Logout
|
|
709
|
+
</div>
|
|
710
|
+
</div>
|
|
711
|
+
</template>
|
|
712
|
+
</xt-dropdown-menu>
|
|
713
|
+
|
|
714
|
+
<xt-button
|
|
715
|
+
size="small"
|
|
716
|
+
type="secondary"
|
|
717
|
+
data-role="login"
|
|
718
|
+
:loading="state.loginLoading"
|
|
719
|
+
v-if="!state.isLogin"
|
|
720
|
+
@click="callbacks.onLogin()"
|
|
721
|
+
>Login</xt-button>
|
|
423
722
|
</div>
|
|
424
723
|
</header>
|
|
425
|
-
|
|
724
|
+
|
|
725
|
+
<div
|
|
726
|
+
class="workspace"
|
|
727
|
+
:class="state.panelTarget === 'left' ? 'panel-left' : 'panel-right'"
|
|
728
|
+
data-role="workspace"
|
|
729
|
+
>
|
|
426
730
|
<main class="canvas-host" data-role="canvas-host"></main>
|
|
427
731
|
<aside class="panel-sidebar" data-role="panel-sidebar">
|
|
428
732
|
<div class="panel-host" data-role="panel-host"></div>
|
|
429
|
-
<div class="panel-actions" data-role="panel-actions">
|
|
430
|
-
<
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
733
|
+
<div id="sidebar-footer" class="sidebar-footer-export panel-actions" data-role="panel-actions">
|
|
734
|
+
<xt-dropdown-menu
|
|
735
|
+
trigger="click"
|
|
736
|
+
:portal-disabled="true"
|
|
737
|
+
placement="topLeft"
|
|
738
|
+
domTriggerClass="sidebar-export-trigger-btn-wrap"
|
|
739
|
+
:show-trigger-icon="false"
|
|
740
|
+
domContentClass="sidebar-export-dropdown-menu"
|
|
741
|
+
>
|
|
742
|
+
<template #trigger>
|
|
743
|
+
<xt-button class="sidebar-export-trigger-btn" block data-role="fab-trigger">
|
|
744
|
+
<template #icon>
|
|
745
|
+
<img
|
|
746
|
+
src="${EXPORT_ICON_DATA_URI}"
|
|
747
|
+
alt=""
|
|
748
|
+
width="16"
|
|
749
|
+
height="16"
|
|
750
|
+
draggable="false"
|
|
751
|
+
/>
|
|
752
|
+
</template>
|
|
753
|
+
Export SVG
|
|
754
|
+
<template #append-icon>
|
|
755
|
+
<div v-if="state.isLogin" class="export-credits-hint">
|
|
756
|
+
<img src="${CREDIT_ICON_DATA_URI}" alt="" class="credits-token-icon credits-token-icon--sm" draggable="false" />
|
|
757
|
+
<span class="export-credits-hint-value" data-role="export-credits-value">{{ state.exportCreditsCost }}</span>
|
|
758
|
+
</div>
|
|
759
|
+
</template>
|
|
760
|
+
</xt-button>
|
|
761
|
+
</template>
|
|
762
|
+
<template #overlay>
|
|
763
|
+
<div class="export-overlay-menu fab-menu-content" data-role="fab-menu">
|
|
764
|
+
<div
|
|
765
|
+
v-show="state.exportEnabled"
|
|
766
|
+
class="export-overlay-item"
|
|
767
|
+
data-role="export-svg"
|
|
768
|
+
@click="callbacks.onExportSvg()"
|
|
769
|
+
>
|
|
770
|
+
<span class="export-overlay-item-icon export-overlay-item-icon--svg"></span>
|
|
771
|
+
Export SVG
|
|
772
|
+
</div>
|
|
773
|
+
<div
|
|
774
|
+
v-show="state.studioEnabled"
|
|
775
|
+
class="export-overlay-item"
|
|
776
|
+
data-role="open-in-studio"
|
|
777
|
+
@click="callbacks.onOpenInStudio()"
|
|
778
|
+
>
|
|
779
|
+
<span class="export-overlay-item-icon export-overlay-item-icon--studio"></span>
|
|
780
|
+
Open in Studio
|
|
781
|
+
</div>
|
|
782
|
+
</div>
|
|
783
|
+
</template>
|
|
784
|
+
</xt-dropdown-menu>
|
|
437
785
|
</div>
|
|
438
786
|
</aside>
|
|
439
787
|
</div>
|
|
440
|
-
|
|
788
|
+
|
|
789
|
+
<input
|
|
790
|
+
data-role="template-file-input"
|
|
791
|
+
type="file"
|
|
792
|
+
accept="application/json"
|
|
793
|
+
style="display:none"
|
|
794
|
+
@change="callbacks.onFileChange($event)"
|
|
795
|
+
/>
|
|
441
796
|
</div>
|
|
442
797
|
`;
|
|
443
|
-
function
|
|
444
|
-
|
|
445
|
-
|
|
798
|
+
function requireVue() {
|
|
799
|
+
const Vue = globalThis.Vue;
|
|
800
|
+
if (!Vue || typeof Vue.createApp !== "function") {
|
|
801
|
+
throw new Error(
|
|
802
|
+
'[generator-workbench] Vue 3 is required. Load it via CDN: <script src="https://unpkg.com/vue@3/dist/vue.global.js"><\/script>'
|
|
803
|
+
);
|
|
804
|
+
}
|
|
805
|
+
return Vue;
|
|
806
|
+
}
|
|
807
|
+
function injectStyles(root, cdnCssUrl) {
|
|
808
|
+
const link = document.createElement("link");
|
|
809
|
+
link.rel = "stylesheet";
|
|
810
|
+
link.href = cdnCssUrl || ATOMM_UI_CDN_CSS_URL;
|
|
811
|
+
root.appendChild(link);
|
|
812
|
+
const style = document.createElement("style");
|
|
813
|
+
style.textContent = WORKBENCH_SHELL_STYLES;
|
|
814
|
+
root.appendChild(style);
|
|
815
|
+
}
|
|
816
|
+
function stateFromConfig(vue, config) {
|
|
817
|
+
return vue.reactive({
|
|
818
|
+
logoText: config.logoText || config.title,
|
|
819
|
+
logoSrc: config.logoUrl || "https://storage-us.atomm.com/resource/xart/static/agent/imgs/atomm-logo.svg",
|
|
820
|
+
panelTarget: config.panelTarget || "right",
|
|
821
|
+
avatarMenuTrigger: config.avatarMenuTrigger || "hover",
|
|
822
|
+
templateEnabled: config.templateEnabled !== false,
|
|
823
|
+
exportEnabled: config.exportEnabled !== false,
|
|
824
|
+
studioEnabled: config.studioEnabled !== false,
|
|
825
|
+
isLogin: false,
|
|
826
|
+
avatarSrc: "",
|
|
827
|
+
avatarText: "U",
|
|
828
|
+
authDisplayName: "",
|
|
829
|
+
authSubline: "",
|
|
830
|
+
creditsBalance: 0,
|
|
831
|
+
exportCreditsCost: 1,
|
|
832
|
+
loginLoading: false
|
|
833
|
+
});
|
|
834
|
+
}
|
|
835
|
+
function createNoopCallbacks() {
|
|
836
|
+
return {
|
|
837
|
+
onLogin: () => {
|
|
838
|
+
},
|
|
839
|
+
onLogout: () => {
|
|
840
|
+
},
|
|
841
|
+
onImportTemplate: () => {
|
|
842
|
+
},
|
|
843
|
+
onExportTemplate: () => {
|
|
844
|
+
},
|
|
845
|
+
onExportSvg: () => {
|
|
846
|
+
},
|
|
847
|
+
onOpenInStudio: () => {
|
|
848
|
+
},
|
|
849
|
+
onFileChange: () => {
|
|
850
|
+
}
|
|
851
|
+
};
|
|
852
|
+
}
|
|
853
|
+
function registerFallbackComponents(app) {
|
|
854
|
+
app.component("xt-button", {
|
|
855
|
+
inheritAttrs: true,
|
|
856
|
+
template: '<button v-bind="$attrs"><slot name="icon" /><slot /><slot name="append-icon" /></button>'
|
|
857
|
+
});
|
|
858
|
+
app.component("xt-avatar", {
|
|
859
|
+
inheritAttrs: true,
|
|
860
|
+
template: '<span v-bind="$attrs"><slot /></span>'
|
|
861
|
+
});
|
|
862
|
+
app.component("xt-dropdown-menu", {
|
|
863
|
+
inheritAttrs: true,
|
|
864
|
+
template: '<div v-bind="$attrs"><slot name="trigger" /><slot name="overlay" /><slot /></div>'
|
|
865
|
+
});
|
|
866
|
+
app.component("xt-hover-card", {
|
|
867
|
+
inheritAttrs: true,
|
|
868
|
+
template: '<div v-bind="$attrs"><slot name="trigger" /><slot name="content" /></div>'
|
|
869
|
+
});
|
|
870
|
+
}
|
|
871
|
+
function renderWorkbenchShell(root, config) {
|
|
872
|
+
const vue = requireVue();
|
|
873
|
+
injectStyles(root, config.atommUiCssUrl);
|
|
874
|
+
const state = stateFromConfig(vue, config);
|
|
875
|
+
const callbacks = createNoopCallbacks();
|
|
876
|
+
const container = document.createElement("div");
|
|
877
|
+
container.setAttribute("data-workbench-vue-root", "");
|
|
878
|
+
root.appendChild(container);
|
|
879
|
+
const AtommUI = globalThis.AtommUI;
|
|
880
|
+
const app = vue.createApp({
|
|
881
|
+
setup() {
|
|
882
|
+
return { state, callbacks };
|
|
883
|
+
},
|
|
884
|
+
template: WORKBENCH_VUE_TEMPLATE
|
|
885
|
+
});
|
|
886
|
+
if (AtommUI) {
|
|
887
|
+
app.use(AtommUI);
|
|
888
|
+
} else {
|
|
889
|
+
registerFallbackComponents(app);
|
|
890
|
+
}
|
|
891
|
+
app.mount(container);
|
|
892
|
+
const refs = collectWorkbenchRefs(root);
|
|
893
|
+
return { state, callbacks, app, refs };
|
|
894
|
+
}
|
|
895
|
+
function unmountWorkbenchShell(context) {
|
|
896
|
+
context.app.unmount();
|
|
446
897
|
}
|
|
447
898
|
const DEFAULT_CONFIG = {
|
|
448
899
|
title: "",
|
|
@@ -465,14 +916,16 @@ class GeneratorWorkbenchElement extends HTMLElement {
|
|
|
465
916
|
__publicField(this, "_sdk", null);
|
|
466
917
|
__publicField(this, "_runtime", null);
|
|
467
918
|
__publicField(this, "_config", { ...DEFAULT_CONFIG });
|
|
468
|
-
__publicField(this, "_refs", null);
|
|
469
919
|
__publicField(this, "_mounted", false);
|
|
470
920
|
__publicField(this, "_state", createInitialWorkbenchState());
|
|
471
921
|
__publicField(this, "_cleanupAuth");
|
|
922
|
+
__publicField(this, "_cleanupCredits");
|
|
923
|
+
__publicField(this, "_cleanupBilling");
|
|
472
924
|
__publicField(this, "_authController");
|
|
473
925
|
__publicField(this, "_templateController");
|
|
474
926
|
__publicField(this, "_exportController");
|
|
475
927
|
__publicField(this, "_runtimeController");
|
|
928
|
+
__publicField(this, "_shellContext");
|
|
476
929
|
this.attachShadow({ mode: "open" });
|
|
477
930
|
}
|
|
478
931
|
get sdk() {
|
|
@@ -520,11 +973,13 @@ class GeneratorWorkbenchElement extends HTMLElement {
|
|
|
520
973
|
}
|
|
521
974
|
this.render();
|
|
522
975
|
this.bindControllers();
|
|
523
|
-
this.
|
|
976
|
+
this.bindShellCallbacks();
|
|
524
977
|
this.bindAuthState();
|
|
525
|
-
await
|
|
978
|
+
await this.syncBillingState();
|
|
979
|
+
const refs = this.requireRefs();
|
|
980
|
+
await ((_a = this._runtimeController) == null ? void 0 : _a.mountCanvas(refs.canvasHost));
|
|
526
981
|
await ((_b = this._runtimeController) == null ? void 0 : _b.mountPanel(
|
|
527
|
-
|
|
982
|
+
refs.panelHost,
|
|
528
983
|
this._state.activePanelFilter
|
|
529
984
|
));
|
|
530
985
|
this._mounted = true;
|
|
@@ -534,10 +989,18 @@ class GeneratorWorkbenchElement extends HTMLElement {
|
|
|
534
989
|
});
|
|
535
990
|
}
|
|
536
991
|
async unmount() {
|
|
537
|
-
var _a, _b;
|
|
992
|
+
var _a, _b, _c, _d;
|
|
538
993
|
(_a = this._cleanupAuth) == null ? void 0 : _a.call(this);
|
|
539
994
|
this._cleanupAuth = void 0;
|
|
540
|
-
|
|
995
|
+
(_b = this._cleanupCredits) == null ? void 0 : _b.call(this);
|
|
996
|
+
this._cleanupCredits = void 0;
|
|
997
|
+
(_c = this._cleanupBilling) == null ? void 0 : _c.call(this);
|
|
998
|
+
this._cleanupBilling = void 0;
|
|
999
|
+
await ((_d = this._runtimeController) == null ? void 0 : _d.unmountAll());
|
|
1000
|
+
if (this._shellContext) {
|
|
1001
|
+
unmountWorkbenchShell(this._shellContext);
|
|
1002
|
+
this._shellContext = void 0;
|
|
1003
|
+
}
|
|
541
1004
|
this._mounted = false;
|
|
542
1005
|
}
|
|
543
1006
|
refreshLayout() {
|
|
@@ -546,9 +1009,10 @@ class GeneratorWorkbenchElement extends HTMLElement {
|
|
|
546
1009
|
try {
|
|
547
1010
|
const result = await this.requireTemplateController().importTemplate(file);
|
|
548
1011
|
this._state.activePanelFilter = result.panelFilter;
|
|
549
|
-
|
|
1012
|
+
const refs = this.requireRefs();
|
|
1013
|
+
if (this._runtimeController) {
|
|
550
1014
|
await this._runtimeController.remountPanel(
|
|
551
|
-
|
|
1015
|
+
refs.panelHost,
|
|
552
1016
|
result.panelFilter
|
|
553
1017
|
);
|
|
554
1018
|
}
|
|
@@ -583,9 +1047,13 @@ class GeneratorWorkbenchElement extends HTMLElement {
|
|
|
583
1047
|
}
|
|
584
1048
|
render() {
|
|
585
1049
|
if (!this.shadowRoot) return;
|
|
586
|
-
|
|
587
|
-
|
|
1050
|
+
if (this._shellContext) {
|
|
1051
|
+
unmountWorkbenchShell(this._shellContext);
|
|
1052
|
+
this.shadowRoot.innerHTML = "";
|
|
1053
|
+
}
|
|
1054
|
+
this._shellContext = renderWorkbenchShell(this.shadowRoot, this._config);
|
|
588
1055
|
this.syncAuthUI();
|
|
1056
|
+
this.syncBillingUI();
|
|
589
1057
|
}
|
|
590
1058
|
bindControllers() {
|
|
591
1059
|
if (!this._sdk || !this._runtime) return;
|
|
@@ -605,47 +1073,35 @@ class GeneratorWorkbenchElement extends HTMLElement {
|
|
|
605
1073
|
runtime: this._runtime
|
|
606
1074
|
});
|
|
607
1075
|
}
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
1076
|
+
bindShellCallbacks() {
|
|
1077
|
+
if (!this._shellContext) return;
|
|
1078
|
+
const { callbacks } = this._shellContext;
|
|
1079
|
+
callbacks.onLogin = () => {
|
|
611
1080
|
void this.handleLogin();
|
|
612
|
-
}
|
|
613
|
-
|
|
1081
|
+
};
|
|
1082
|
+
callbacks.onLogout = () => {
|
|
614
1083
|
void this.handleLogout();
|
|
615
|
-
}
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
}
|
|
619
|
-
|
|
1084
|
+
};
|
|
1085
|
+
callbacks.onImportTemplate = () => {
|
|
1086
|
+
this.requireRefs().templateFileInput.click();
|
|
1087
|
+
};
|
|
1088
|
+
callbacks.onExportTemplate = () => {
|
|
620
1089
|
void this.exportTemplate();
|
|
621
|
-
}
|
|
622
|
-
|
|
1090
|
+
};
|
|
1091
|
+
callbacks.onExportSvg = () => {
|
|
1092
|
+
void this.exportSvg();
|
|
1093
|
+
};
|
|
1094
|
+
callbacks.onOpenInStudio = () => {
|
|
1095
|
+
void this.openInStudio();
|
|
1096
|
+
};
|
|
1097
|
+
callbacks.onFileChange = (event) => {
|
|
623
1098
|
var _a;
|
|
624
|
-
const
|
|
1099
|
+
const input = event.target;
|
|
1100
|
+
const file = (_a = input.files) == null ? void 0 : _a[0];
|
|
625
1101
|
if (!file) return;
|
|
626
1102
|
void this.importTemplate(file);
|
|
627
|
-
|
|
628
|
-
}
|
|
629
|
-
refs.fabTrigger.addEventListener("click", () => {
|
|
630
|
-
this.toggleFabMenu();
|
|
631
|
-
});
|
|
632
|
-
refs.exportSvgBtn.addEventListener("click", () => {
|
|
633
|
-
void this.exportSvg();
|
|
634
|
-
});
|
|
635
|
-
refs.openInStudioBtn.addEventListener("click", () => {
|
|
636
|
-
void this.openInStudio();
|
|
637
|
-
});
|
|
638
|
-
refs.avatarButton.addEventListener("click", () => {
|
|
639
|
-
this.toggleAvatarMenu();
|
|
640
|
-
});
|
|
641
|
-
if (this._config.avatarMenuTrigger === "hover") {
|
|
642
|
-
refs.avatarButton.addEventListener("mouseenter", () => {
|
|
643
|
-
this.setAvatarMenuOpen(true);
|
|
644
|
-
});
|
|
645
|
-
refs.avatarMenu.addEventListener("mouseleave", () => {
|
|
646
|
-
this.setAvatarMenuOpen(false);
|
|
647
|
-
});
|
|
648
|
-
}
|
|
1103
|
+
input.value = "";
|
|
1104
|
+
};
|
|
649
1105
|
}
|
|
650
1106
|
bindAuthState() {
|
|
651
1107
|
var _a;
|
|
@@ -654,52 +1110,111 @@ class GeneratorWorkbenchElement extends HTMLElement {
|
|
|
654
1110
|
this._cleanupAuth = controller.subscribe((status) => {
|
|
655
1111
|
this._state.authStatus = status;
|
|
656
1112
|
this.syncAuthUI();
|
|
1113
|
+
void this.syncBillingState(status);
|
|
657
1114
|
dispatchWorkbenchEvent(this, "auth-change", status);
|
|
658
1115
|
});
|
|
1116
|
+
this.bindBillingSubscriptions();
|
|
1117
|
+
}
|
|
1118
|
+
bindBillingSubscriptions() {
|
|
1119
|
+
var _a, _b, _c, _d;
|
|
1120
|
+
(_a = this._cleanupCredits) == null ? void 0 : _a.call(this);
|
|
1121
|
+
this._cleanupCredits = void 0;
|
|
1122
|
+
(_b = this._cleanupBilling) == null ? void 0 : _b.call(this);
|
|
1123
|
+
this._cleanupBilling = void 0;
|
|
1124
|
+
const creditsModule = (_c = this._sdk) == null ? void 0 : _c.credits;
|
|
1125
|
+
if (typeof (creditsModule == null ? void 0 : creditsModule.onChange) === "function") {
|
|
1126
|
+
this._cleanupCredits = creditsModule.onChange((balance) => {
|
|
1127
|
+
this._state.creditsBalance = Number(balance) || 0;
|
|
1128
|
+
this.syncBillingUI();
|
|
1129
|
+
});
|
|
1130
|
+
}
|
|
1131
|
+
const billingModule = (_d = this._sdk) == null ? void 0 : _d.billing;
|
|
1132
|
+
if (typeof (billingModule == null ? void 0 : billingModule.onChange) === "function") {
|
|
1133
|
+
this._cleanupBilling = billingModule.onChange((usage) => {
|
|
1134
|
+
this.applyBillingUsage(usage);
|
|
1135
|
+
});
|
|
1136
|
+
}
|
|
659
1137
|
}
|
|
660
1138
|
syncAuthUI() {
|
|
661
|
-
|
|
662
|
-
|
|
1139
|
+
var _a, _b, _c, _d;
|
|
1140
|
+
if (!this._shellContext) return;
|
|
1141
|
+
const { state } = this._shellContext;
|
|
663
1142
|
const { isLogin, userInfo } = this._state.authStatus;
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
this.
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
this.
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
this.
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
1143
|
+
const displayName = ((_a = userInfo == null ? void 0 : userInfo.userName) == null ? void 0 : _a.trim()) || ((_b = userInfo == null ? void 0 : userInfo.email) == null ? void 0 : _b.trim()) || ((_c = userInfo == null ? void 0 : userInfo.phoneNumber) == null ? void 0 : _c.trim()) || "";
|
|
1144
|
+
const avatarText = displayName ? displayName.charAt(0).toUpperCase() : "U";
|
|
1145
|
+
const authSubline = ((_d = userInfo == null ? void 0 : userInfo.email) == null ? void 0 : _d.trim()) || ((userInfo == null ? void 0 : userInfo.phoneNumber) ? `${userInfo.phoneZone || ""}${userInfo.phoneNumber}` : "Connected to Generator SDK");
|
|
1146
|
+
state.isLogin = isLogin;
|
|
1147
|
+
state.avatarSrc = isLogin ? (userInfo == null ? void 0 : userInfo.headpic) || "" : "";
|
|
1148
|
+
state.avatarText = avatarText;
|
|
1149
|
+
state.authDisplayName = displayName;
|
|
1150
|
+
state.authSubline = isLogin ? authSubline : "";
|
|
1151
|
+
}
|
|
1152
|
+
syncBillingUI() {
|
|
1153
|
+
if (!this._shellContext) return;
|
|
1154
|
+
const { state } = this._shellContext;
|
|
1155
|
+
const usage = this._state.billingUsage;
|
|
1156
|
+
state.creditsBalance = this._state.creditsBalance;
|
|
1157
|
+
state.exportCreditsCost = (usage == null ? void 0 : usage.creditsPerUse) ?? (usage && "unitPrice" in usage ? Number(usage.unitPrice) || 1 : 1);
|
|
1158
|
+
}
|
|
1159
|
+
applyBillingUsage(usage) {
|
|
1160
|
+
this._state.billingUsage = usage || null;
|
|
1161
|
+
if (usage && typeof usage.creditsBalance === "number") {
|
|
1162
|
+
this._state.creditsBalance = usage.creditsBalance;
|
|
1163
|
+
}
|
|
1164
|
+
this.syncBillingUI();
|
|
1165
|
+
}
|
|
1166
|
+
resetBillingState() {
|
|
1167
|
+
this._state.creditsBalance = 0;
|
|
1168
|
+
this._state.billingUsage = null;
|
|
1169
|
+
this.syncBillingUI();
|
|
1170
|
+
}
|
|
1171
|
+
async syncBillingState(status = this._state.authStatus) {
|
|
1172
|
+
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
1173
|
+
if (!status.isLogin || !this._sdk) {
|
|
1174
|
+
this.resetBillingState();
|
|
1175
|
+
return;
|
|
1176
|
+
}
|
|
1177
|
+
const cachedBalance = (_b = (_a = this._sdk.credits) == null ? void 0 : _a.getCachedBalance) == null ? void 0 : _b.call(_a);
|
|
1178
|
+
if (typeof cachedBalance === "number") {
|
|
1179
|
+
this._state.creditsBalance = cachedBalance;
|
|
1180
|
+
}
|
|
1181
|
+
const cachedUsage = (_d = (_c = this._sdk.billing) == null ? void 0 : _c.getCachedUsage) == null ? void 0 : _d.call(_c);
|
|
1182
|
+
if (cachedUsage) {
|
|
1183
|
+
this.applyBillingUsage(cachedUsage);
|
|
1184
|
+
} else {
|
|
1185
|
+
this.syncBillingUI();
|
|
1186
|
+
}
|
|
1187
|
+
try {
|
|
1188
|
+
const [creditsResult, usage] = await Promise.all([
|
|
1189
|
+
(_f = (_e = this._sdk.credits) == null ? void 0 : _e.getBalance) == null ? void 0 : _f.call(_e),
|
|
1190
|
+
(_h = (_g = this._sdk.billing) == null ? void 0 : _g.getUsage) == null ? void 0 : _h.call(_g)
|
|
1191
|
+
]);
|
|
1192
|
+
if (typeof (creditsResult == null ? void 0 : creditsResult.quota) === "number") {
|
|
1193
|
+
this._state.creditsBalance = creditsResult.quota;
|
|
1194
|
+
}
|
|
1195
|
+
if (usage) {
|
|
1196
|
+
this.applyBillingUsage(usage);
|
|
1197
|
+
return;
|
|
1198
|
+
}
|
|
1199
|
+
this.syncBillingUI();
|
|
1200
|
+
} catch (error) {
|
|
1201
|
+
this.handleError("auth", error);
|
|
1202
|
+
}
|
|
694
1203
|
}
|
|
695
1204
|
async handleLogin() {
|
|
696
1205
|
try {
|
|
697
1206
|
this._state.busy.login = true;
|
|
1207
|
+
if (this._shellContext) {
|
|
1208
|
+
this._shellContext.state.loginLoading = true;
|
|
1209
|
+
}
|
|
698
1210
|
await this.requireAuthController().login();
|
|
699
1211
|
} catch (error) {
|
|
700
1212
|
this.handleError("auth", error);
|
|
701
1213
|
} finally {
|
|
702
1214
|
this._state.busy.login = false;
|
|
1215
|
+
if (this._shellContext) {
|
|
1216
|
+
this._shellContext.state.loginLoading = false;
|
|
1217
|
+
}
|
|
703
1218
|
}
|
|
704
1219
|
}
|
|
705
1220
|
async handleLogout() {
|
|
@@ -719,10 +1234,10 @@ class GeneratorWorkbenchElement extends HTMLElement {
|
|
|
719
1234
|
});
|
|
720
1235
|
}
|
|
721
1236
|
requireRefs() {
|
|
722
|
-
if (!this.
|
|
723
|
-
throw new Error("[generator-workbench]
|
|
1237
|
+
if (!this._shellContext) {
|
|
1238
|
+
throw new Error("[generator-workbench] shell context is not ready");
|
|
724
1239
|
}
|
|
725
|
-
return this.
|
|
1240
|
+
return this._shellContext.refs;
|
|
726
1241
|
}
|
|
727
1242
|
requireAuthController() {
|
|
728
1243
|
if (!this._authController) {
|