@atomm-developer/generator-workbench 0.1.7 → 0.1.9

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 CHANGED
@@ -5,7 +5,7 @@
5
5
  V1 provides:
6
6
 
7
7
  - Web Component shell
8
- - login / avatar / logout entry
8
+ - guest avatar / login / avatar / logout entry
9
9
  - credits badge and export credit hint
10
10
  - built-in invitation action backed by `@atomm/atomm-pro` `InvitationModal`
11
11
  - local template import entry and template publish modal
@@ -82,7 +82,7 @@ workbench.config = {
82
82
 
83
83
  ## Invitation Modal
84
84
 
85
- By default, the shell adds an `Earn Credits` button to the left of the top-bar credits badge after login.
85
+ By default, the shell adds an `Earn Credits` button to the left of the top-bar credits badge. When the user is logged out, the top bar also shows a 40x40 guest avatar instead of a text `Login` button.
86
86
 
87
87
  ```js
88
88
  workbench.config = {
@@ -92,11 +92,10 @@ workbench.config = {
92
92
  }
93
93
  ```
94
94
 
95
- `generator-workbench` will then auto-load `Pinia`, `Vue Router`, `Vue I18n`, and the bundled `atomm-pro` browser assets, mount `XtAtommProContext` inside the shell, and call `InvitationModal.open({ configKey })` when the user clicks the button.
95
+ `generator-workbench` will then auto-load `Pinia`, `Vue Router`, `Vue I18n`, and the bundled `atomm-pro` browser assets, mount `XtAtommProContext` inside the shell, and call `InvitationModal.open({ configKey })` when the user clicks the button. If the user is still logged out, the shell first calls `sdk.auth.login()` and opens the invitation/share modal right after login completes.
96
96
 
97
97
  Notes:
98
98
 
99
- - `InvitationModal` depends on a real login token, so the button is only shown after `sdk.auth` reports `isLogin = true`.
100
99
  - If you need to hide the invite entry, explicitly pass `invitationEnabled: false`.
101
100
  - If `invitationConfigKey` is omitted, the shell defaults it to `generator_${sdk.getAppKey()}`.
102
101
  - If you still need a custom referral/share key, you can explicitly pass `invitationConfigKey`.
@@ -108,6 +107,38 @@ Notes:
108
107
  - `mode: 'full'` keeps the classic shell with the top bar plus the built-in right sidebar layout for separate canvas / panel mounting.
109
108
  - `mode: 'template'` hides the top bar, keeps `#sidebar-footer`, and is useful when the host page already owns branding and login UI.
110
109
 
110
+ The shell layout mode above is different from the route capability mode. When the page URL contains `?mode=embed`, `generator-workbench` keeps the current layout mode but force-disables shell integrations for:
111
+
112
+ - cloud save
113
+ - history
114
+ - credits badge / export credits hint
115
+ - billing-backed export consumption
116
+ - invitation / earn credits entry
117
+
118
+ This is useful when the host site embeds a generator inside an `iframe` and wants a lighter shell surface. If the route omits `mode` or uses `mode=full`, the existing shell behavior stays unchanged.
119
+
120
+ In this embed route, the shell also removes the top bar and `#sidebar-footer` export container from the DOM entirely. The underlying workbench methods and bridge actions still exist, but the shell chrome is no longer rendered inside the iframe.
121
+
122
+ When `?mode=embed` is active, the workbench also boots an iframe bridge compatible with the main-site generator protocol:
123
+
124
+ - outgoing ready signal: `generator_pageLoaded`
125
+ - incoming host commands: `generator_loadTemplateData`, `generator_setGeneratorData`, `generator_getTemplateData`, `generator_getGeneratorData`, `generator_getFile`
126
+ - outgoing result events: `generator_toTemplateLoaded`, `generator_toTemplateData`, `generator_toGeneratorData`, `generator_toFile`, `generator_toFileError`, `generator_toTemplateError`
127
+
128
+ Default bridge mappings:
129
+
130
+ - `generator_loadTemplateData` applies the incoming template through `sdk.template.applyToRuntime(...)`
131
+ - `generator_setGeneratorData` restores `data.info` back into `runtime.setState(...)`
132
+ - `generator_getTemplateData` builds a fresh template from the current runtime state and returns `{ template, info, cover, originImageUrl }`
133
+ - `generator_getFile` reads export data from `config.embedBridge.getExportData(...)` first, then falls back to the SDK export provider registered through `sdk.export.register(...)`
134
+
135
+ If the host needs stricter control, pass `config.embedBridge`:
136
+
137
+ - `targetOrigin`: override the default `postMessage(..., '*')`
138
+ - `validateOrigin(origin, event)`: filter incoming parent messages
139
+ - `getExportData(action, context)`: provide bridge export data explicitly
140
+ - `getOriginImageUrl(context)`: return the origin image URL stored by the host/runtime
141
+
111
142
  In `template` mode, the host shell can pass an external token into the workbench:
112
143
 
113
144
  ```js
@@ -120,7 +151,8 @@ This writes the token to `localStorage` using the SDK app key and then syncs the
120
151
 
121
152
  - When `sdk.credits` and `sdk.billing` are available, the top bar shows the current credits balance after login.
122
153
  - The export trigger reads `sdk.billing.getUsage()` and hides the hint completely when `usage.isEnabled = false`.
123
- - When billing is enabled, the hint switches between `free N`, `creditsPerUse`, and the `30s` free-period countdown.
154
+ - When billing is enabled, the hint switches between `freeRemaining/freeTotal`, `creditsPerUse`, and the `30s` free-period countdown.
155
+ - When free quota remains, the export hint hides the credits token icon and only shows the `remaining/total` text.
124
156
  - When free quota is exhausted, `exportSvg()` and `openInStudio()` compare `usage.creditsPerUse` with `usage.creditsBalance`; if balance is insufficient, they open the `@atomm/atomm-pro` credits purchase modal before retrying the export path.
125
157
  - `exportSvg()` and `openInStudio()` export first, then call `sdk.billing.consume()` on success; the credits path also calls `sdk.billing.refreshCredits()`.
126
158
 
@@ -144,6 +176,8 @@ When `cloudEnabled` is on, the workbench now also supports a route-based bootstr
144
176
  - if the page URL contains `?gid=<id>`, mount will call `sdk.cloud.restore(id)` and write the restored snapshot back through `runtime.setState(...)`
145
177
  - if `gid` is missing, mount will call `sdk.cloud.save(...)` once and write the returned id back into the current route as `gid`
146
178
 
179
+ If the page route contains `?mode=embed`, this cloud bootstrap flow is skipped even when `cloudEnabled` was set by the host config.
180
+
147
181
  Cloud/history events are also emitted as DOM custom events:
148
182
 
149
183
  - `cloud-save-start`
package/dist/index.d.ts CHANGED
@@ -5,6 +5,7 @@ import { BillingConsumeResult } from '@atomm-developer/generator-sdk';
5
5
  import { CloudRecord } from '@atomm-developer/generator-sdk';
6
6
  import { CloudSaveOptions } from '@atomm-developer/generator-sdk';
7
7
  import { CloudSaveResult } from '@atomm-developer/generator-sdk';
8
+ import { ExportData } from '@atomm-developer/generator-sdk';
8
9
  import { ExportDownloadResult } from '@atomm-developer/generator-sdk';
9
10
  import { ExportOpenInStudioResult } from '@atomm-developer/generator-sdk';
10
11
  import { GeneratorTemplateDefinition } from '@atomm-developer/generator-sdk';
@@ -137,6 +138,7 @@ export declare interface GeneratorWorkbenchConfig {
137
138
  autoMount?: boolean;
138
139
  panelTarget?: 'left' | 'right';
139
140
  avatarMenuTrigger?: 'hover' | 'click';
141
+ embedBridge?: GeneratorWorkbenchEmbedBridgeConfig;
140
142
  /** Override the default Vue 3 CDN script URL auto-loaded when window.Vue is absent */
141
143
  vueScriptUrl?: string;
142
144
  /** Override the default Vue Router CDN script URL auto-loaded for invitation modal support */
@@ -188,6 +190,7 @@ export declare class GeneratorWorkbenchElement extends HTMLElement {
188
190
  private _historyController?;
189
191
  private _runtimeController?;
190
192
  private _shellContext?;
193
+ private _iframeBridge?;
191
194
  constructor();
192
195
  get sdk(): GeneratorSDKLike | null;
193
196
  set sdk(value: GeneratorSDKLike | null);
@@ -221,7 +224,10 @@ export declare class GeneratorWorkbenchElement extends HTMLElement {
221
224
  private openHistoryDialog;
222
225
  private closeHistoryDialog;
223
226
  private toggleTemplateExportField;
227
+ private applyTemplatePayload;
228
+ private tryResolveIframeBridgeFile;
224
229
  private bindAuthState;
230
+ private bindIframeBridge;
225
231
  private bindAutoSave;
226
232
  private bindRuntimeCloudSaveEvent;
227
233
  private readonly handleRuntimeCloudSaveRequest;
@@ -243,7 +249,10 @@ export declare class GeneratorWorkbenchElement extends HTMLElement {
243
249
  private clearBillingCountdownTimer;
244
250
  private syncBillingCountdown;
245
251
  private syncBillingState;
252
+ private getEffectiveConfig;
253
+ private getEffectiveSdk;
246
254
  private handleLogin;
255
+ private handleInvitationEntry;
247
256
  private handleLogout;
248
257
  private handleError;
249
258
  private requireRefs;
@@ -254,6 +263,15 @@ export declare class GeneratorWorkbenchElement extends HTMLElement {
254
263
  private requireHistoryController;
255
264
  }
256
265
 
266
+ export declare interface GeneratorWorkbenchEmbedBridgeConfig {
267
+ targetOrigin?: string;
268
+ validateOrigin?: (origin: string, event: MessageEvent) => boolean;
269
+ getOriginImageUrl?: (context: GeneratorWorkbenchActionHookContext) => Promise<string> | string;
270
+ getExportData?: (action: GeneratorWorkbenchEmbedBridgeFileAction, context: GeneratorWorkbenchActionHookContext) => Promise<ExportData | null> | ExportData | null;
271
+ }
272
+
273
+ export declare type GeneratorWorkbenchEmbedBridgeFileAction = 'download' | 'openInStudio' | 'cover';
274
+
257
275
  declare interface GeneratorWorkbenchHistoryContext extends GeneratorWorkbenchActionHookContext {
258
276
  itemId: number;
259
277
  }