@atomm-developer/generator-workbench 0.1.7 → 0.1.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.es.js CHANGED
@@ -166,7 +166,11 @@ function createExportController(args) {
166
166
  element
167
167
  }));
168
168
  await ensureLoggedIn();
169
- const usage = await ensureUsageAllowsExport(await getBillingUsage());
169
+ const initialUsage = await getBillingUsage();
170
+ const usage = await ensureUsageAllowsExport(initialUsage);
171
+ if (!initialUsage) {
172
+ return sdk.export.download({ format: "svg" });
173
+ }
170
174
  if (!usage) {
171
175
  return {
172
176
  success: false,
@@ -185,7 +189,11 @@ function createExportController(args) {
185
189
  element
186
190
  }));
187
191
  await ensureLoggedIn();
188
- const usage = await ensureUsageAllowsExport(await getBillingUsage());
192
+ const initialUsage = await getBillingUsage();
193
+ const usage = await ensureUsageAllowsExport(initialUsage);
194
+ if (!initialUsage) {
195
+ return sdk.export.openInStudio({ format: "svg" });
196
+ }
189
197
  if (!usage) {
190
198
  return {
191
199
  success: false
@@ -470,7 +478,7 @@ function createTemplateController(args) {
470
478
  };
471
479
  },
472
480
  prepareTemplateExport,
473
- async exportTemplate(selectedFieldPaths) {
481
+ buildTemplate(selectedFieldPaths) {
474
482
  var _a;
475
483
  const prepared = prepareTemplateExport();
476
484
  const finalSelectedFieldPaths = (selectedFieldPaths == null ? void 0 : selectedFieldPaths.length) ? collectPanelFieldPaths(prepared.panelSchema, selectedFieldPaths) : prepared.selectedFieldPaths;
@@ -485,6 +493,10 @@ function createTemplateController(args) {
485
493
  selectedFieldPaths: finalSelectedFieldPaths,
486
494
  templateMeta: (_a = config.getTemplateMeta) == null ? void 0 : _a.call(config)
487
495
  });
496
+ return template;
497
+ },
498
+ async exportTemplate(selectedFieldPaths) {
499
+ const template = this.buildTemplate(selectedFieldPaths);
488
500
  sdk.template.download(template);
489
501
  return { template };
490
502
  }
@@ -578,6 +590,7 @@ const ATOMM_UI_CDN_SCRIPT_URL = "https://minio-download.makeblock.com/resource/a
578
590
  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";
579
591
  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";
580
592
  const INVITATION_ICON_URL = "https://storage-us.atomm.com/resource/static/atomm/icon/Vector.svg";
593
+ const NO_LOGIN_AVATAR_URL = "https://storage-us.atomm.com/resource/xart/static/agent/imgs/no-login.png";
581
594
  const WORKBENCH_SHELL_STYLES = `
582
595
  :host {
583
596
  display: block;
@@ -801,6 +814,22 @@ const WORKBENCH_SHELL_STYLES = `
801
814
  transition: background 150ms ease;
802
815
  }
803
816
 
817
+ .auth-avatar-button {
818
+ appearance: none;
819
+ border: 0;
820
+ background: transparent;
821
+ cursor: pointer;
822
+ }
823
+
824
+ .auth-avatar-button--guest {
825
+ padding: 0;
826
+ display: inline-flex;
827
+ align-items: center;
828
+ justify-content: center;
829
+ width: 40px;
830
+ height: 40px;
831
+ }
832
+
804
833
 
805
834
  .auth-avatar {
806
835
  width: 40px;
@@ -822,6 +851,10 @@ const WORKBENCH_SHELL_STYLES = `
822
851
  font-size: 14px;
823
852
  }
824
853
 
854
+ .auth-avatar--guest {
855
+ background: transparent;
856
+ }
857
+
825
858
  .auth-avatar img {
826
859
  width: 100%;
827
860
  height: 100%;
@@ -991,10 +1024,19 @@ const WORKBENCH_SHELL_STYLES = `
991
1024
  }
992
1025
 
993
1026
  .export-credits-hint-value {
994
- color: white;
995
- font-size: 13px;
996
- font-weight: 700;
997
- font-variant-numeric: tabular-nums;
1027
+ width: 100%;
1028
+ background: linear-gradient(90deg, #fce1bf, #ecb678 67.02%, #f9c991);
1029
+ border-radius: 4px;
1030
+ gap: 2px;
1031
+ height: 16px;
1032
+ padding: 2px 4px;
1033
+ font-size: 10px;
1034
+ font-weight: 600;
1035
+ line-height: 16px;
1036
+ color: #581e06;
1037
+ display: flex;
1038
+ justify-content: center;
1039
+ align-items: center;
998
1040
  }
999
1041
 
1000
1042
  .export-overlay-menu,
@@ -1201,12 +1243,11 @@ const WORKBENCH_VUE_TEMPLATE = `
1201
1243
  </div>
1202
1244
  <div class="app-topbar-auth">
1203
1245
  <button
1204
- v-if="state.isLogin && state.invitationEnabled"
1246
+ v-if="state.invitationEnabled"
1205
1247
  type="button"
1206
1248
  class="invite-entry"
1207
1249
  data-role="open-invitation"
1208
- :disabled="!state.invitationReady"
1209
- @click="openInvitationModal()"
1250
+ @click="callbacks.onOpenInvitation()"
1210
1251
  >
1211
1252
  <img
1212
1253
  src="${INVITATION_ICON_URL}"
@@ -1217,7 +1258,7 @@ const WORKBENCH_VUE_TEMPLATE = `
1217
1258
  <span class="invite-entry-text">{{ state.invitationButtonText }}</span>
1218
1259
  </button>
1219
1260
  <div
1220
- v-if="state.isLogin"
1261
+ v-if="state.isLogin && state.creditsEnabled"
1221
1262
  class="topbar-credits-badge"
1222
1263
  data-role="topbar-credits"
1223
1264
  title="Remaining credits"
@@ -1300,14 +1341,22 @@ const WORKBENCH_VUE_TEMPLATE = `
1300
1341
  </template>
1301
1342
  </xt-dropdown-menu>
1302
1343
 
1303
- <xt-button
1304
- size="small"
1305
- type="secondary"
1344
+ <button
1345
+ type="button"
1346
+ class="auth-avatar-button auth-avatar-button--guest"
1306
1347
  data-role="login"
1307
- :loading="state.loginLoading"
1308
1348
  v-if="!state.isLogin"
1309
1349
  @click="callbacks.onLogin()"
1310
- >Login</xt-button>
1350
+ >
1351
+ <div class="auth-avatar auth-avatar--guest">
1352
+ <img
1353
+ src="${NO_LOGIN_AVATAR_URL}"
1354
+ alt="Login"
1355
+ data-role="guest-avatar-image"
1356
+ draggable="false"
1357
+ />
1358
+ </div>
1359
+ </button>
1311
1360
  </div>
1312
1361
  </header>
1313
1362
 
@@ -1814,6 +1863,7 @@ function stateFromConfig(vue, config, invitationReady) {
1814
1863
  panelTarget: config.panelTarget || "right",
1815
1864
  avatarMenuTrigger: config.avatarMenuTrigger || "hover",
1816
1865
  templateEnabled: config.templateEnabled !== false,
1866
+ creditsEnabled: config.creditsEnabled !== false,
1817
1867
  invitationEnabled: isInvitationEnabled(config),
1818
1868
  invitationReady,
1819
1869
  invitationConfigKey: ((_a = config.invitationConfigKey) == null ? void 0 : _a.trim()) || "",
@@ -1855,6 +1905,8 @@ function createNoopCallbacks() {
1855
1905
  return {
1856
1906
  onLogin: () => {
1857
1907
  },
1908
+ onOpenInvitation: () => {
1909
+ },
1858
1910
  onLogout: () => {
1859
1911
  },
1860
1912
  onImportTemplate: () => {
@@ -2120,6 +2172,15 @@ async function renderWorkbenchShell(root, config) {
2120
2172
  const state = stateFromConfig(vue, config, invitationRuntime !== null);
2121
2173
  const callbacks = createNoopCallbacks();
2122
2174
  const invitationModalRef = vue.ref(null);
2175
+ const triggerInvitationModal = () => {
2176
+ var _a2, _b2;
2177
+ const modalInstance = invitationModalRef.value;
2178
+ const open = (modalInstance == null ? void 0 : modalInstance.open) || ((_b2 = (_a2 = modalInstance == null ? void 0 : modalInstance.$) == null ? void 0 : _a2.exposed) == null ? void 0 : _b2.open);
2179
+ open == null ? void 0 : open({
2180
+ configKey: state.invitationConfigKey || "default",
2181
+ showDetail: false
2182
+ });
2183
+ };
2123
2184
  const container = document.createElement("div");
2124
2185
  container.setAttribute("data-workbench-vue-root", "");
2125
2186
  root.appendChild(container);
@@ -2142,18 +2203,10 @@ async function renderWorkbenchShell(root, config) {
2142
2203
  }) : null;
2143
2204
  const app = vue.createApp({
2144
2205
  setup() {
2145
- const openInvitationModal = () => {
2146
- var _a2, _b2;
2147
- (_b2 = (_a2 = invitationModalRef.value) == null ? void 0 : _a2.open) == null ? void 0 : _b2.call(_a2, {
2148
- configKey: state.invitationConfigKey || "default",
2149
- showDetail: false
2150
- });
2151
- };
2152
2206
  return {
2153
2207
  state,
2154
2208
  callbacks,
2155
- invitationModalRef,
2156
- openInvitationModal
2209
+ invitationModalRef
2157
2210
  };
2158
2211
  },
2159
2212
  template: WORKBENCH_VUE_TEMPLATE
@@ -2184,6 +2237,7 @@ async function renderWorkbenchShell(root, config) {
2184
2237
  callbacks,
2185
2238
  app,
2186
2239
  refs,
2240
+ openInvitationModal: triggerInvitationModal,
2187
2241
  requestCreditsPurchase: async (options) => {
2188
2242
  if (!purchaseBridge) {
2189
2243
  await injectStyleSheetIntoDocumentHead(
@@ -2215,6 +2269,295 @@ function unmountWorkbenchShell(context) {
2215
2269
  context.disposeCreditsPurchaseBridge();
2216
2270
  context.app.unmount();
2217
2271
  }
2272
+ function createIframeBridge(args) {
2273
+ const {
2274
+ targetWindow = window,
2275
+ parentWindow = window.parent,
2276
+ targetOrigin = "*",
2277
+ validateOrigin,
2278
+ handlers
2279
+ } = args;
2280
+ let disposed = false;
2281
+ const post = (type, data) => {
2282
+ if (disposed) return;
2283
+ logBridge("outgoing", {
2284
+ type,
2285
+ data,
2286
+ targetOrigin
2287
+ });
2288
+ parentWindow.postMessage(
2289
+ {
2290
+ type,
2291
+ data
2292
+ },
2293
+ targetOrigin
2294
+ );
2295
+ };
2296
+ const postTemplateError = (action, error) => {
2297
+ logBridge("error", {
2298
+ type: "generator_toTemplateError",
2299
+ action,
2300
+ message: toErrorMessage(error)
2301
+ });
2302
+ post("generator_toTemplateError", {
2303
+ action,
2304
+ message: toErrorMessage(error)
2305
+ });
2306
+ };
2307
+ const postFileError = (action, error) => {
2308
+ logBridge("error", {
2309
+ type: "generator_toFileError",
2310
+ action,
2311
+ message: toErrorMessage(error)
2312
+ });
2313
+ post("generator_toFileError", {
2314
+ action,
2315
+ message: toErrorMessage(error)
2316
+ });
2317
+ };
2318
+ const onMessage = (event) => {
2319
+ if (disposed) return;
2320
+ if (validateOrigin && !validateOrigin(event.origin, event)) {
2321
+ return;
2322
+ }
2323
+ const message = event.data;
2324
+ if (!message || typeof message !== "object") {
2325
+ return;
2326
+ }
2327
+ const type = "type" in message && typeof message.type === "string" ? message.type : "";
2328
+ const data = "data" in message ? message.data : void 0;
2329
+ logBridge("incoming", {
2330
+ type,
2331
+ data,
2332
+ origin: event.origin
2333
+ });
2334
+ switch (type) {
2335
+ case "generator_getGeneratorData":
2336
+ void handlers.getGeneratorData().then((payload) => {
2337
+ post("generator_toGeneratorData", payload);
2338
+ }).catch((error) => {
2339
+ postTemplateError("getGeneratorData", error);
2340
+ });
2341
+ return;
2342
+ case "generator_setGeneratorData":
2343
+ void Promise.resolve(handlers.setGeneratorData(data || {}));
2344
+ return;
2345
+ case "generator_loadTemplateData":
2346
+ void handlers.loadTemplateData(data || {}).then((payload) => {
2347
+ post("generator_toTemplateLoaded", {
2348
+ template: (payload == null ? void 0 : payload.template) || (data && "template" in data ? data.template : data) || null
2349
+ });
2350
+ }).catch((error) => {
2351
+ postTemplateError("loadTemplateData", error);
2352
+ });
2353
+ return;
2354
+ case "generator_getTemplateData":
2355
+ void handlers.getTemplateData().then((payload) => {
2356
+ post("generator_toTemplateData", payload);
2357
+ }).catch((error) => {
2358
+ postTemplateError("getTemplateData", error);
2359
+ });
2360
+ return;
2361
+ case "generator_getFile": {
2362
+ const action = normalizeFileAction(data == null ? void 0 : data.action);
2363
+ void handlers.getFile(action).then((payload) => {
2364
+ post("generator_toFile", payload);
2365
+ }).catch((error) => {
2366
+ postFileError(action, error);
2367
+ });
2368
+ return;
2369
+ }
2370
+ case "generator_getTemplateFieldOptions":
2371
+ postTemplateError(
2372
+ "getTemplateFieldOptions",
2373
+ new Error("Template field options are not supported")
2374
+ );
2375
+ return;
2376
+ case "generator_publishTemplate":
2377
+ postTemplateError(
2378
+ "publishTemplate",
2379
+ new Error("Template publishing is not supported")
2380
+ );
2381
+ return;
2382
+ default:
2383
+ return;
2384
+ }
2385
+ };
2386
+ targetWindow.addEventListener("message", onMessage);
2387
+ post("generator_pageLoaded");
2388
+ return {
2389
+ dispose() {
2390
+ if (disposed) return;
2391
+ logBridge("lifecycle", {
2392
+ type: "dispose"
2393
+ });
2394
+ disposed = true;
2395
+ targetWindow.removeEventListener("message", onMessage);
2396
+ }
2397
+ };
2398
+ }
2399
+ async function resolveIframeBridgeFile(args) {
2400
+ var _a, _b;
2401
+ const { action, sdk, runtime, config, element } = args;
2402
+ const context = {
2403
+ sdk,
2404
+ runtime,
2405
+ element
2406
+ };
2407
+ const configuredExportData = await Promise.resolve(
2408
+ (_b = (_a = config.embedBridge) == null ? void 0 : _a.getExportData) == null ? void 0 : _b.call(_a, action, context)
2409
+ );
2410
+ const exportData = configuredExportData || await resolveSdkExportData(sdk, action);
2411
+ if (!exportData) {
2412
+ throw new Error("No export data available");
2413
+ }
2414
+ return {
2415
+ action,
2416
+ ...await exportDataToBridgeFile(exportData)
2417
+ };
2418
+ }
2419
+ async function resolveIframeBridgeOriginImageUrl(args) {
2420
+ var _a, _b;
2421
+ const { sdk, runtime, config, element } = args;
2422
+ return await Promise.resolve(
2423
+ (_b = (_a = config.embedBridge) == null ? void 0 : _a.getOriginImageUrl) == null ? void 0 : _b.call(_a, {
2424
+ sdk,
2425
+ runtime,
2426
+ element
2427
+ })
2428
+ ) || "";
2429
+ }
2430
+ async function resolveSdkExportData(sdk, action) {
2431
+ const exportModule = sdk.export;
2432
+ const provider = exportModule.provider;
2433
+ if (!provider) {
2434
+ return null;
2435
+ }
2436
+ const purpose = mapActionToExportPurpose(action);
2437
+ const preferredFormat = action === "cover" ? "png" : "svg";
2438
+ if (typeof provider.getExportData === "function") {
2439
+ const data = await Promise.resolve(
2440
+ provider.getExportData(purpose, preferredFormat)
2441
+ );
2442
+ if (data) {
2443
+ return data;
2444
+ }
2445
+ }
2446
+ if (typeof provider.getExportCanvas === "function") {
2447
+ const canvas = await Promise.resolve(provider.getExportCanvas(purpose));
2448
+ if (canvas) {
2449
+ return {
2450
+ type: "canvas",
2451
+ canvas
2452
+ };
2453
+ }
2454
+ }
2455
+ return null;
2456
+ }
2457
+ async function exportDataToBridgeFile(data) {
2458
+ switch (data.type) {
2459
+ case "canvas": {
2460
+ const base64 = data.canvas.toDataURL("image/png");
2461
+ return {
2462
+ base64,
2463
+ mimeType: "image/png",
2464
+ ext: "png"
2465
+ };
2466
+ }
2467
+ case "dataUrl": {
2468
+ const mimeType = readDataUrlMimeType(data.dataUrl);
2469
+ return {
2470
+ base64: data.dataUrl,
2471
+ mimeType,
2472
+ ext: mimeTypeToExtension(mimeType)
2473
+ };
2474
+ }
2475
+ case "svg": {
2476
+ return {
2477
+ base64: svgToDataUrl(data.svgString),
2478
+ mimeType: "image/svg+xml",
2479
+ ext: "svg"
2480
+ };
2481
+ }
2482
+ case "blob": {
2483
+ const dataUrl = await blobToDataUrl(data.blob);
2484
+ const mimeType = data.blob.type || readDataUrlMimeType(dataUrl);
2485
+ return {
2486
+ base64: dataUrl,
2487
+ mimeType,
2488
+ ext: mimeTypeToExtension(mimeType)
2489
+ };
2490
+ }
2491
+ case "url": {
2492
+ const response = await fetch(data.url);
2493
+ if (!response.ok) {
2494
+ throw new Error(`Failed to fetch export URL: ${response.status}`);
2495
+ }
2496
+ const blob = await response.blob();
2497
+ const dataUrl = await blobToDataUrl(blob);
2498
+ const mimeType = blob.type || readDataUrlMimeType(dataUrl);
2499
+ return {
2500
+ base64: dataUrl,
2501
+ mimeType,
2502
+ ext: mimeTypeToExtension(mimeType)
2503
+ };
2504
+ }
2505
+ }
2506
+ }
2507
+ function normalizeFileAction(action) {
2508
+ return action === "openInStudio" || action === "cover" ? action : "download";
2509
+ }
2510
+ function mapActionToExportPurpose(action) {
2511
+ if (action === "openInStudio") {
2512
+ return "studio";
2513
+ }
2514
+ return action;
2515
+ }
2516
+ function toErrorMessage(error) {
2517
+ return error instanceof Error ? error.message : String(error);
2518
+ }
2519
+ function readDataUrlMimeType(dataUrl) {
2520
+ var _a;
2521
+ return ((_a = dataUrl.match(/^data:(image\/[a-zA-Z0-9.+-]+);/)) == null ? void 0 : _a[1]) || "image/png";
2522
+ }
2523
+ function mimeTypeToExtension(mimeType) {
2524
+ var _a;
2525
+ if (mimeType === "image/svg+xml") return "svg";
2526
+ if (mimeType === "image/jpeg") return "jpg";
2527
+ return ((_a = mimeType.split("/")[1]) == null ? void 0 : _a.split("+")[0]) || "png";
2528
+ }
2529
+ function svgToDataUrl(svgString) {
2530
+ const utf8 = encodeURIComponent(svgString).replace(
2531
+ /%([0-9A-F]{2})/g,
2532
+ (_, p1) => String.fromCharCode(Number.parseInt(p1, 16))
2533
+ );
2534
+ return `data:image/svg+xml;base64,${btoa(utf8)}`;
2535
+ }
2536
+ function blobToDataUrl(blob) {
2537
+ return new Promise((resolve, reject) => {
2538
+ const reader = new FileReader();
2539
+ reader.onload = () => {
2540
+ if (typeof reader.result !== "string") {
2541
+ reject(new Error("Failed to read blob as data URL"));
2542
+ return;
2543
+ }
2544
+ resolve(reader.result);
2545
+ };
2546
+ reader.onerror = () => {
2547
+ reject(reader.error || new Error("Failed to read blob as data URL"));
2548
+ };
2549
+ reader.readAsDataURL(blob);
2550
+ });
2551
+ }
2552
+ function logBridge(phase, payload) {
2553
+ if (!isBridgeDebugEnabled()) {
2554
+ return;
2555
+ }
2556
+ console.log(`[generator-workbench][iframe-bridge][${phase}]`, payload);
2557
+ }
2558
+ function isBridgeDebugEnabled() {
2559
+ return new URLSearchParams(window.location.search).get("bridgeDebug") === "1";
2560
+ }
2218
2561
  const DEFAULT_CONFIG = {
2219
2562
  title: "",
2220
2563
  mode: "full",
@@ -2229,6 +2572,9 @@ function isShellMode(config) {
2229
2572
  return config.mode === "shell";
2230
2573
  }
2231
2574
  const TOKEN_STORAGE_KEY_PREFIX = "__atomm_sdk_token__";
2575
+ function getRouteCapabilityMode() {
2576
+ return new URLSearchParams(window.location.search).get("mode") === "embed" ? "embed" : "full";
2577
+ }
2232
2578
  function normalizeWorkbenchConfig(config) {
2233
2579
  return {
2234
2580
  ...DEFAULT_CONFIG,
@@ -2257,6 +2603,7 @@ class GeneratorWorkbenchElement extends HTMLElement {
2257
2603
  __publicField(this, "_historyController");
2258
2604
  __publicField(this, "_runtimeController");
2259
2605
  __publicField(this, "_shellContext");
2606
+ __publicField(this, "_iframeBridge");
2260
2607
  __publicField(this, "handleRuntimeCloudSaveRequest", (event) => {
2261
2608
  if (!event.detail) return;
2262
2609
  if (this._runtimeCloudSaveTimer) {
@@ -2353,6 +2700,7 @@ class GeneratorWorkbenchElement extends HTMLElement {
2353
2700
  this._state.activePanelFilter
2354
2701
  ));
2355
2702
  }
2703
+ this.bindIframeBridge();
2356
2704
  this._mounted = true;
2357
2705
  dispatchWorkbenchEvent(this, "workbench-ready", {
2358
2706
  sdk: this._sdk,
@@ -2360,7 +2708,7 @@ class GeneratorWorkbenchElement extends HTMLElement {
2360
2708
  });
2361
2709
  }
2362
2710
  async unmount() {
2363
- var _a, _b, _c, _d, _e, _f;
2711
+ var _a, _b, _c, _d, _e, _f, _g;
2364
2712
  (_a = this._cleanupAuth) == null ? void 0 : _a.call(this);
2365
2713
  this._cleanupAuth = void 0;
2366
2714
  (_b = this._cleanupCredits) == null ? void 0 : _b.call(this);
@@ -2376,11 +2724,13 @@ class GeneratorWorkbenchElement extends HTMLElement {
2376
2724
  this._runtimeCloudSaveTimer = null;
2377
2725
  }
2378
2726
  this.clearBillingCountdownTimer();
2727
+ (_f = this._iframeBridge) == null ? void 0 : _f.dispose();
2728
+ this._iframeBridge = void 0;
2379
2729
  this.removeEventListener(
2380
2730
  "runtime-cloud-save-request",
2381
2731
  this.handleRuntimeCloudSaveRequest
2382
2732
  );
2383
- await ((_f = this._runtimeController) == null ? void 0 : _f.unmountAll());
2733
+ await ((_g = this._runtimeController) == null ? void 0 : _g.unmountAll());
2384
2734
  if (this._shellContext) {
2385
2735
  unmountWorkbenchShell(this._shellContext);
2386
2736
  this._shellContext = void 0;
@@ -2555,7 +2905,10 @@ class GeneratorWorkbenchElement extends HTMLElement {
2555
2905
  unmountWorkbenchShell(this._shellContext);
2556
2906
  this.shadowRoot.innerHTML = "";
2557
2907
  }
2558
- this._shellContext = await renderWorkbenchShell(this.shadowRoot, this._config);
2908
+ this._shellContext = await renderWorkbenchShell(
2909
+ this.shadowRoot,
2910
+ this.getEffectiveConfig()
2911
+ );
2559
2912
  this.syncAuthUI();
2560
2913
  this.syncBillingUI();
2561
2914
  this.syncInvitationConfigKey();
@@ -2563,32 +2916,34 @@ class GeneratorWorkbenchElement extends HTMLElement {
2563
2916
  }
2564
2917
  bindControllers() {
2565
2918
  var _a;
2566
- if (!this._sdk || !this._runtime) return;
2567
- this._authController = createAuthController({ sdk: this._sdk });
2919
+ const sdk = this.getEffectiveSdk();
2920
+ const config = this.getEffectiveConfig();
2921
+ if (!sdk || !this._runtime) return;
2922
+ this._authController = createAuthController({ sdk });
2568
2923
  this._templateController = createTemplateController({
2569
- sdk: this._sdk,
2924
+ sdk,
2570
2925
  runtime: this._runtime,
2571
- config: this._config
2926
+ config
2572
2927
  });
2573
2928
  this._exportController = createExportController({
2574
- sdk: this._sdk,
2929
+ sdk,
2575
2930
  runtime: this._runtime,
2576
- config: this._config,
2931
+ config,
2577
2932
  element: this,
2578
- requestCreditsPurchase: (_a = this._shellContext) == null ? void 0 : _a.requestCreditsPurchase
2933
+ requestCreditsPurchase: config.creditsEnabled === false ? void 0 : (_a = this._shellContext) == null ? void 0 : _a.requestCreditsPurchase
2579
2934
  });
2580
- this._cloudController = createCloudController({
2581
- sdk: this._sdk,
2935
+ this._cloudController = sdk.cloud ? createCloudController({
2936
+ sdk,
2582
2937
  runtime: this._runtime,
2583
- config: this._config,
2938
+ config,
2584
2939
  element: this
2585
- });
2586
- this._historyController = createHistoryController({
2587
- sdk: this._sdk,
2940
+ }) : void 0;
2941
+ this._historyController = sdk.history ? createHistoryController({
2942
+ sdk,
2588
2943
  runtime: this._runtime,
2589
- config: this._config,
2944
+ config,
2590
2945
  element: this
2591
- });
2946
+ }) : void 0;
2592
2947
  this._runtimeController = createRuntimeController({
2593
2948
  runtime: this._runtime
2594
2949
  });
@@ -2599,6 +2954,9 @@ class GeneratorWorkbenchElement extends HTMLElement {
2599
2954
  callbacks.onLogin = () => {
2600
2955
  void this.handleLogin();
2601
2956
  };
2957
+ callbacks.onOpenInvitation = () => {
2958
+ void this.handleInvitationEntry();
2959
+ };
2602
2960
  callbacks.onLogout = () => {
2603
2961
  void this.handleLogout();
2604
2962
  };
@@ -2701,6 +3059,56 @@ class GeneratorWorkbenchElement extends HTMLElement {
2701
3059
  }
2702
3060
  this._shellContext.state.templateSelectedFieldPaths = Array.from(selected);
2703
3061
  }
3062
+ async applyTemplatePayload(template) {
3063
+ if (!this._runtime) {
3064
+ throw new Error("[generator-workbench] runtime is required for template bridge actions");
3065
+ }
3066
+ if (!this._sdk) {
3067
+ throw new Error("[generator-workbench] sdk is required for template bridge actions");
3068
+ }
3069
+ let capturedPanelFilter;
3070
+ await this._sdk.template.applyToRuntime(
3071
+ this._runtime,
3072
+ template,
3073
+ {
3074
+ onPanelFilter: (panelFilter) => {
3075
+ capturedPanelFilter = panelFilter;
3076
+ }
3077
+ }
3078
+ );
3079
+ if (capturedPanelFilter) {
3080
+ this._state.activePanelFilter = capturedPanelFilter;
3081
+ if (this._runtimeController && !isShellMode(this._config)) {
3082
+ const panelHost = this.requireRefs().panelHost;
3083
+ if (!panelHost) {
3084
+ throw new Error(
3085
+ "[generator-workbench] panel host is required for template bridge actions"
3086
+ );
3087
+ }
3088
+ await this._runtimeController.remountPanel(panelHost, capturedPanelFilter);
3089
+ }
3090
+ }
3091
+ return {
3092
+ template,
3093
+ panelFilter: capturedPanelFilter
3094
+ };
3095
+ }
3096
+ async tryResolveIframeBridgeFile(action, sdk, config) {
3097
+ try {
3098
+ if (!this._runtime) {
3099
+ return void 0;
3100
+ }
3101
+ return await resolveIframeBridgeFile({
3102
+ action,
3103
+ sdk,
3104
+ runtime: this._runtime,
3105
+ config,
3106
+ element: this
3107
+ });
3108
+ } catch {
3109
+ return void 0;
3110
+ }
3111
+ }
2704
3112
  bindAuthState() {
2705
3113
  var _a;
2706
3114
  const controller = this.requireAuthController();
@@ -2713,13 +3121,101 @@ class GeneratorWorkbenchElement extends HTMLElement {
2713
3121
  });
2714
3122
  this.bindBillingSubscriptions();
2715
3123
  }
3124
+ bindIframeBridge() {
3125
+ var _a, _b, _c;
3126
+ (_a = this._iframeBridge) == null ? void 0 : _a.dispose();
3127
+ this._iframeBridge = void 0;
3128
+ if (getRouteCapabilityMode() !== "embed" || !this._runtime) {
3129
+ return;
3130
+ }
3131
+ const sdk = this._sdk;
3132
+ if (!sdk) {
3133
+ return;
3134
+ }
3135
+ const config = this._config;
3136
+ const runtime = this._runtime;
3137
+ this._iframeBridge = createIframeBridge({
3138
+ targetOrigin: ((_b = config.embedBridge) == null ? void 0 : _b.targetOrigin) || "*",
3139
+ validateOrigin: (_c = config.embedBridge) == null ? void 0 : _c.validateOrigin,
3140
+ handlers: {
3141
+ getGeneratorData: async () => {
3142
+ const info = runtime.getState();
3143
+ const originImageUrl = await resolveIframeBridgeOriginImageUrl({
3144
+ sdk,
3145
+ runtime,
3146
+ config,
3147
+ element: this
3148
+ });
3149
+ const coverFile = await this.tryResolveIframeBridgeFile(
3150
+ "cover",
3151
+ sdk,
3152
+ config
3153
+ );
3154
+ return {
3155
+ info,
3156
+ cover: (coverFile == null ? void 0 : coverFile.base64) || "",
3157
+ originImageUrl
3158
+ };
3159
+ },
3160
+ setGeneratorData: async (data) => {
3161
+ const snapshot = data.info && typeof data.info === "object" && !Array.isArray(data.info) ? data.info : data;
3162
+ await runtime.setState(snapshot, {
3163
+ source: "iframe-bridge",
3164
+ originImageUrl: typeof data.originImageUrl === "string" ? data.originImageUrl : ""
3165
+ });
3166
+ },
3167
+ loadTemplateData: async (data) => {
3168
+ const template = data.template && typeof data.template === "object" && !Array.isArray(data.template) ? data.template : data;
3169
+ if (!template || typeof template !== "object" || Array.isArray(template)) {
3170
+ throw new Error("Template payload is empty");
3171
+ }
3172
+ const result = await this.applyTemplatePayload(
3173
+ template
3174
+ );
3175
+ return {
3176
+ template: result.template
3177
+ };
3178
+ },
3179
+ getTemplateData: async () => {
3180
+ const template = this.requireTemplateController().buildTemplate();
3181
+ const info = runtime.getState();
3182
+ const originImageUrl = await resolveIframeBridgeOriginImageUrl({
3183
+ sdk,
3184
+ runtime,
3185
+ config,
3186
+ element: this
3187
+ });
3188
+ const coverFile = await this.tryResolveIframeBridgeFile(
3189
+ "cover",
3190
+ sdk,
3191
+ config
3192
+ );
3193
+ return {
3194
+ template,
3195
+ info,
3196
+ cover: (coverFile == null ? void 0 : coverFile.base64) || "",
3197
+ originImageUrl
3198
+ };
3199
+ },
3200
+ getFile: async (action) => resolveIframeBridgeFile({
3201
+ action,
3202
+ sdk,
3203
+ runtime,
3204
+ config,
3205
+ element: this
3206
+ })
3207
+ }
3208
+ });
3209
+ }
2716
3210
  bindAutoSave() {
2717
- var _a, _b, _c, _d;
3211
+ var _a, _b, _c;
3212
+ const sdk = this.getEffectiveSdk();
3213
+ const config = this.getEffectiveConfig();
2718
3214
  (_a = this._cleanupRuntimeSubscription) == null ? void 0 : _a.call(this);
2719
3215
  this._cleanupRuntimeSubscription = void 0;
2720
3216
  (_b = this._cloudAutoSaveScheduler) == null ? void 0 : _b.dispose();
2721
3217
  this._cloudAutoSaveScheduler = void 0;
2722
- if (!this._config.autoSaveEnabled || !((_c = this._runtime) == null ? void 0 : _c.subscribe) || !((_d = this._sdk) == null ? void 0 : _d.cloud)) {
3218
+ if (!config.autoSaveEnabled || !((_c = this._runtime) == null ? void 0 : _c.subscribe) || !(sdk == null ? void 0 : sdk.cloud)) {
2723
3219
  return;
2724
3220
  }
2725
3221
  this._cloudAutoSaveScheduler = this.requireCloudController().scheduleAutoSave(
@@ -2735,18 +3231,24 @@ class GeneratorWorkbenchElement extends HTMLElement {
2735
3231
  });
2736
3232
  }
2737
3233
  bindRuntimeCloudSaveEvent() {
3234
+ const sdk = this.getEffectiveSdk();
3235
+ const config = this.getEffectiveConfig();
2738
3236
  this.removeEventListener(
2739
3237
  "runtime-cloud-save-request",
2740
3238
  this.handleRuntimeCloudSaveRequest
2741
3239
  );
3240
+ if (!config.cloudEnabled || !(sdk == null ? void 0 : sdk.cloud)) {
3241
+ return;
3242
+ }
2742
3243
  this.addEventListener(
2743
3244
  "runtime-cloud-save-request",
2744
3245
  this.handleRuntimeCloudSaveRequest
2745
3246
  );
2746
3247
  }
2747
3248
  async initializeCloudRecordFromRoute() {
2748
- var _a;
2749
- if (!this._config.cloudEnabled || !((_a = this._sdk) == null ? void 0 : _a.cloud)) {
3249
+ const sdk = this.getEffectiveSdk();
3250
+ const config = this.getEffectiveConfig();
3251
+ if (!config.cloudEnabled || !(sdk == null ? void 0 : sdk.cloud)) {
2750
3252
  return;
2751
3253
  }
2752
3254
  const routeGid = this.getRouteCloudRecordId();
@@ -2813,19 +3315,20 @@ class GeneratorWorkbenchElement extends HTMLElement {
2813
3315
  );
2814
3316
  }
2815
3317
  bindBillingSubscriptions() {
2816
- var _a, _b, _c, _d;
3318
+ var _a, _b;
3319
+ const sdk = this.getEffectiveSdk();
2817
3320
  (_a = this._cleanupCredits) == null ? void 0 : _a.call(this);
2818
3321
  this._cleanupCredits = void 0;
2819
3322
  (_b = this._cleanupBilling) == null ? void 0 : _b.call(this);
2820
3323
  this._cleanupBilling = void 0;
2821
- const creditsModule = (_c = this._sdk) == null ? void 0 : _c.credits;
3324
+ const creditsModule = sdk == null ? void 0 : sdk.credits;
2822
3325
  if (typeof (creditsModule == null ? void 0 : creditsModule.onChange) === "function") {
2823
3326
  this._cleanupCredits = creditsModule.onChange((balance) => {
2824
3327
  this._state.creditsBalance = Number(balance) || 0;
2825
3328
  this.syncBillingUI();
2826
3329
  });
2827
3330
  }
2828
- const billingModule = (_d = this._sdk) == null ? void 0 : _d.billing;
3331
+ const billingModule = sdk == null ? void 0 : sdk.billing;
2829
3332
  if (typeof (billingModule == null ? void 0 : billingModule.onChange) === "function") {
2830
3333
  this._cleanupBilling = billingModule.onChange((usage) => {
2831
3334
  this.applyBillingUsage(usage);
@@ -2864,11 +3367,14 @@ class GeneratorWorkbenchElement extends HTMLElement {
2864
3367
  if (!this._shellContext) return;
2865
3368
  const { state } = this._shellContext;
2866
3369
  const usage = this._state.billingUsage;
3370
+ state.creditsEnabled = this.getEffectiveConfig().creditsEnabled !== false;
2867
3371
  state.creditsBalance = this._state.creditsBalance;
2868
3372
  state.showExportCreditsHint = Boolean(
2869
3373
  this._state.authStatus.isLogin && (usage == null ? void 0 : usage.isEnabled)
2870
3374
  );
2871
- state.showExportCreditsIcon = Boolean(state.showExportCreditsHint && !(usage == null ? void 0 : usage.inFreePeriod));
3375
+ state.showExportCreditsIcon = Boolean(
3376
+ state.showExportCreditsHint && !(usage == null ? void 0 : usage.inFreePeriod) && ((usage == null ? void 0 : usage.freeRemaining) ?? 0) <= 0
3377
+ );
2872
3378
  state.exportCreditsHintText = this.resolveExportCreditsHintText(usage);
2873
3379
  }
2874
3380
  syncInvitationConfigKey() {
@@ -2924,7 +3430,7 @@ class GeneratorWorkbenchElement extends HTMLElement {
2924
3430
  return `${usage.freePeriodRemaining}s`;
2925
3431
  }
2926
3432
  if (usage.freeRemaining > 0) {
2927
- return `free ${usage.freeRemaining}`;
3433
+ return `${usage.freeRemaining}/${usage.freeTotal}`;
2928
3434
  }
2929
3435
  return String(usage.creditsPerUse);
2930
3436
  }
@@ -2974,15 +3480,20 @@ class GeneratorWorkbenchElement extends HTMLElement {
2974
3480
  }
2975
3481
  async syncBillingState(status = this._state.authStatus) {
2976
3482
  var _a, _b, _c, _d, _e, _f, _g, _h;
2977
- if (!status.isLogin || !this._sdk) {
3483
+ const sdk = this.getEffectiveSdk();
3484
+ if (!status.isLogin || !sdk) {
3485
+ this.resetBillingState();
3486
+ return;
3487
+ }
3488
+ if (!sdk.credits && !sdk.billing) {
2978
3489
  this.resetBillingState();
2979
3490
  return;
2980
3491
  }
2981
- const cachedBalance = (_b = (_a = this._sdk.credits) == null ? void 0 : _a.getCachedBalance) == null ? void 0 : _b.call(_a);
3492
+ const cachedBalance = (_b = (_a = sdk.credits) == null ? void 0 : _a.getCachedBalance) == null ? void 0 : _b.call(_a);
2982
3493
  if (typeof cachedBalance === "number") {
2983
3494
  this._state.creditsBalance = cachedBalance;
2984
3495
  }
2985
- const cachedUsage = (_d = (_c = this._sdk.billing) == null ? void 0 : _c.getCachedUsage) == null ? void 0 : _d.call(_c);
3496
+ const cachedUsage = (_d = (_c = sdk.billing) == null ? void 0 : _c.getCachedUsage) == null ? void 0 : _d.call(_c);
2986
3497
  if (cachedUsage) {
2987
3498
  this.applyBillingUsage(cachedUsage);
2988
3499
  } else {
@@ -2990,8 +3501,8 @@ class GeneratorWorkbenchElement extends HTMLElement {
2990
3501
  }
2991
3502
  try {
2992
3503
  const [creditsResult, usage] = await Promise.all([
2993
- (_f = (_e = this._sdk.credits) == null ? void 0 : _e.getBalance) == null ? void 0 : _f.call(_e),
2994
- (_h = (_g = this._sdk.billing) == null ? void 0 : _g.getUsage) == null ? void 0 : _h.call(_g)
3504
+ (_f = (_e = sdk.credits) == null ? void 0 : _e.getBalance) == null ? void 0 : _f.call(_e),
3505
+ (_h = (_g = sdk.billing) == null ? void 0 : _g.getUsage) == null ? void 0 : _h.call(_g)
2995
3506
  ]);
2996
3507
  if (typeof (creditsResult == null ? void 0 : creditsResult.quota) === "number") {
2997
3508
  this._state.creditsBalance = creditsResult.quota;
@@ -3005,6 +3516,34 @@ class GeneratorWorkbenchElement extends HTMLElement {
3005
3516
  this.handleError("auth", error);
3006
3517
  }
3007
3518
  }
3519
+ getEffectiveConfig() {
3520
+ if (getRouteCapabilityMode() !== "embed") {
3521
+ return this._config;
3522
+ }
3523
+ return {
3524
+ ...this._config,
3525
+ invitationEnabled: false,
3526
+ cloudEnabled: false,
3527
+ historyEnabled: false,
3528
+ autoSaveEnabled: false,
3529
+ creditsEnabled: false
3530
+ };
3531
+ }
3532
+ getEffectiveSdk() {
3533
+ if (!this._sdk) {
3534
+ return null;
3535
+ }
3536
+ if (getRouteCapabilityMode() !== "embed") {
3537
+ return this._sdk;
3538
+ }
3539
+ return {
3540
+ ...this._sdk,
3541
+ credits: void 0,
3542
+ billing: void 0,
3543
+ cloud: void 0,
3544
+ history: void 0
3545
+ };
3546
+ }
3008
3547
  async handleLogin() {
3009
3548
  try {
3010
3549
  this._state.busy.login = true;
@@ -3021,6 +3560,26 @@ class GeneratorWorkbenchElement extends HTMLElement {
3021
3560
  }
3022
3561
  }
3023
3562
  }
3563
+ async handleInvitationEntry() {
3564
+ var _a;
3565
+ try {
3566
+ if (!this._state.authStatus.isLogin) {
3567
+ await this.handleLogin();
3568
+ const status = this.requireAuthController().getStatus();
3569
+ if (status.isLogin) {
3570
+ this._state.authStatus = status;
3571
+ this.syncAuthUI();
3572
+ void this.syncBillingState(status);
3573
+ }
3574
+ }
3575
+ if (!this.requireAuthController().getStatus().isLogin) {
3576
+ return;
3577
+ }
3578
+ (_a = this._shellContext) == null ? void 0 : _a.openInvitationModal();
3579
+ } catch (error) {
3580
+ this.handleError("auth", error);
3581
+ }
3582
+ }
3024
3583
  async handleLogout() {
3025
3584
  try {
3026
3585
  await this.requireAuthController().logout();