@widgetic/creator 0.3.55 → 0.3.56
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/CreatorApp.svelte +79 -54
- package/dist/components/WidgetDetails.svelte +33 -9
- package/dist/components/WidgetDetails.svelte.d.ts +5 -0
- package/dist/creator-types.d.ts +2 -1
- package/dist/utils/persistWidgetThumbnail.d.ts +5 -0
- package/dist/utils/persistWidgetThumbnail.js +28 -0
- package/package.json +1 -1
package/dist/CreatorApp.svelte
CHANGED
|
@@ -67,6 +67,7 @@
|
|
|
67
67
|
isInfrastructurePreviewError
|
|
68
68
|
} from './pageHelpers.js';
|
|
69
69
|
import { uploadChatFileToWidgeticApi } from './utils/widgeticChatUpload.js';
|
|
70
|
+
import { persistWidgetThumbnail } from './utils/persistWidgetThumbnail.js';
|
|
70
71
|
import { nativeScrollbarPadding } from './utils/nativeScrollbarPadding.js';
|
|
71
72
|
import { streamOperationUpdates } from './utils/operationStream.js';
|
|
72
73
|
import { generateEmbedCode, EMBED_FORMATS, EMBED_FORMAT_LABELS, type EmbedFormat } from './utils/embedCode.js';
|
|
@@ -81,6 +82,14 @@
|
|
|
81
82
|
import { setEnableLocalCache, isLocalCacheEnabled } from './localCacheGate.js';
|
|
82
83
|
import type { CreatorAppProps } from './creator-types.js';
|
|
83
84
|
|
|
85
|
+
function resolveCreatorWorkflowStep(
|
|
86
|
+
step?: CreatorAppProps['initialStep'] | 'create' | 'edit' | 'embed' | null
|
|
87
|
+
): 'create' | 'edit' | 'embed' {
|
|
88
|
+
if (!canvasAdvancedFeatures) return 'create';
|
|
89
|
+
if (step === 'edit' || step === 'embed') return step;
|
|
90
|
+
return 'create';
|
|
91
|
+
}
|
|
92
|
+
|
|
84
93
|
/** Embedded mode props (site integration) */
|
|
85
94
|
export let embedded: CreatorAppProps['embedded'] = false;
|
|
86
95
|
export let canvasId: CreatorAppProps['canvasId'] = null;
|
|
@@ -928,10 +937,6 @@
|
|
|
928
937
|
codegenWidgetId = finalizedWidgetId;
|
|
929
938
|
const newPanelChat = getChatMethodsForWidget(finalizedWidgetId);
|
|
930
939
|
newPanelChat?.setDraftText?.('');
|
|
931
|
-
const hydrateImages = fallbackChatImageAttachments(finalizedWidgetId);
|
|
932
|
-
if (hydrateImages.length > 0) {
|
|
933
|
-
newPanelChat?.updateLastUserMessageAttachments?.(hydrateImages);
|
|
934
|
-
}
|
|
935
940
|
}
|
|
936
941
|
|
|
937
942
|
const panelChat = getChatMethodsForWidget(codegenWidgetId);
|
|
@@ -1251,31 +1256,6 @@
|
|
|
1251
1256
|
* picked, which may differ from convos[0] when several empty conversations
|
|
1252
1257
|
* exist (feedback c: chat looked empty while messages went elsewhere).
|
|
1253
1258
|
*/
|
|
1254
|
-
function userMessageImpliesAttachedFile(content: string): boolean {
|
|
1255
|
-
return /imaginea ata[sș]at[ăa]|attached (reference )?(image|document|file|pdf|video)|reference image|din imagine|ata[sș]at[ăa]?\s+(document|pdf|fi[sș]ier|video)|attached document|starting from the attached image/i.test(
|
|
1256
|
-
content || '',
|
|
1257
|
-
);
|
|
1258
|
-
}
|
|
1259
|
-
|
|
1260
|
-
function fallbackChatImageAttachments(widgetId: string): Array<{
|
|
1261
|
-
id: string;
|
|
1262
|
-
url: string;
|
|
1263
|
-
file_type: string;
|
|
1264
|
-
file_name: string;
|
|
1265
|
-
}> {
|
|
1266
|
-
const urls = uniquePersistImageUrls([
|
|
1267
|
-
...(getPanelState(widgetId).promptImages ?? []),
|
|
1268
|
-
...(widgetId === focusedPanelWidgetId ? promptImages : []),
|
|
1269
|
-
(typeof canvasRef?.getWidgetShapeDataUrl === 'function' ? canvasRef.getWidgetShapeDataUrl(widgetId) : '') || '',
|
|
1270
|
-
]);
|
|
1271
|
-
return urls.map((url, i) => ({
|
|
1272
|
-
id: `hydrate_img_${i}`,
|
|
1273
|
-
url,
|
|
1274
|
-
file_type: guessAttachmentFileType(url, 'design-screenshot.png', 'image/png'),
|
|
1275
|
-
file_name: 'design-screenshot.png',
|
|
1276
|
-
}));
|
|
1277
|
-
}
|
|
1278
|
-
|
|
1279
1259
|
function guessAttachmentFileType(url: string, fileName?: string | null, fallback?: string | null): string {
|
|
1280
1260
|
if (fallback && String(fallback).includes('/')) return String(fallback);
|
|
1281
1261
|
const hint = `${url || ''} ${fileName || ''}`;
|
|
@@ -1297,7 +1277,26 @@
|
|
|
1297
1277
|
else if (url.startsWith('data:image/')) dataUrls.push(url);
|
|
1298
1278
|
}
|
|
1299
1279
|
// Same screenshot often exists as CDN URL + compressed data URL — keep HTTPS only.
|
|
1300
|
-
|
|
1280
|
+
// If only data URLs remain, keep the first one so convert does not triple the bubble.
|
|
1281
|
+
if (httpsUrls.length > 0) return httpsUrls;
|
|
1282
|
+
return dataUrls.slice(0, 1);
|
|
1283
|
+
}
|
|
1284
|
+
|
|
1285
|
+
async function persistWidgetListThumbnail(widgetId: string, imageDataUrl: string): Promise<void> {
|
|
1286
|
+
if (!widgetsClient || !widgetId || !imageDataUrl) return;
|
|
1287
|
+
try {
|
|
1288
|
+
const compact = imageDataUrl.startsWith('data:image/')
|
|
1289
|
+
? await compressImageDataUrlForCodegen(imageDataUrl, 384, 180000)
|
|
1290
|
+
: imageDataUrl;
|
|
1291
|
+
const thumbnailUrl = await persistWidgetThumbnail(widgetsClient, widgetId, compact);
|
|
1292
|
+
if (thumbnailUrl) {
|
|
1293
|
+
widgets = widgets.map((w) =>
|
|
1294
|
+
w.id === widgetId ? { ...w, thumbnailUrl, thumbnail_url: thumbnailUrl } : w
|
|
1295
|
+
);
|
|
1296
|
+
}
|
|
1297
|
+
} catch (error) {
|
|
1298
|
+
console.warn('[CreatorApp] persist list thumbnail failed', widgetId.slice(0, 8), error);
|
|
1299
|
+
}
|
|
1301
1300
|
}
|
|
1302
1301
|
|
|
1303
1302
|
async function ensureCodegenUserMessagePersisted(
|
|
@@ -1400,6 +1399,14 @@
|
|
|
1400
1399
|
.filter((url: string | undefined): url is string => !!url),
|
|
1401
1400
|
);
|
|
1402
1401
|
const existingHasRemoteImage = [...existingUrls].some((url) => /^https?:\/\//i.test(url));
|
|
1402
|
+
// Chat already persisted CDN attachments for this turn — do not merge data URLs/canvas shots.
|
|
1403
|
+
if (targetUser && existingHasRemoteImage) {
|
|
1404
|
+
if (convId !== visibleConversationId) {
|
|
1405
|
+
await panelChat?.selectConversation?.(convId);
|
|
1406
|
+
patchPanelSnapshot(widgetId, { currentChatConversationId: convId });
|
|
1407
|
+
}
|
|
1408
|
+
return;
|
|
1409
|
+
}
|
|
1403
1410
|
const missingPersist = persistAttachments.filter((att) => {
|
|
1404
1411
|
if (att.url && existingUrls.has(att.url)) return false;
|
|
1405
1412
|
if (existingHasRemoteImage && typeof att.url === 'string' && att.url.startsWith('data:')) return false;
|
|
@@ -1627,14 +1634,6 @@
|
|
|
1627
1634
|
created_at: content.created_at || content.createdAt || a.created_at || a.createdAt || new Date().toISOString(),
|
|
1628
1635
|
};
|
|
1629
1636
|
}).filter((a: { url: string }) => !!a.url);
|
|
1630
|
-
if (
|
|
1631
|
-
attachments.length === 0
|
|
1632
|
-
&& (m.message_type || m.messageType || 'user') === 'user'
|
|
1633
|
-
&& userMessageImpliesAttachedFile(m.message_content || m.messageContent || '')
|
|
1634
|
-
&& widgetIdForSync
|
|
1635
|
-
) {
|
|
1636
|
-
attachments = fallbackChatImageAttachments(widgetIdForSync);
|
|
1637
|
-
}
|
|
1638
1637
|
return {
|
|
1639
1638
|
id: m.id,
|
|
1640
1639
|
conversationId: m.conversation_id || m.conversationId || conversationId,
|
|
@@ -3794,8 +3793,17 @@
|
|
|
3794
3793
|
|
|
3795
3794
|
function handleHostToggleAdvancedEvent() {
|
|
3796
3795
|
canvasAdvancedFeatures = !canvasAdvancedFeatures;
|
|
3797
|
-
// console.log('[CreatorApp] Advanced canvas features:', canvasAdvancedFeatures ? 'ON' : 'OFF');
|
|
3798
3796
|
emitCreatorAdvancedChanged();
|
|
3797
|
+
console.log('[CreatorApp] Advanced', canvasAdvancedFeatures ? 'ON' : 'OFF',
|
|
3798
|
+
'— composition steps', canvasAdvancedFeatures ? 'visible' : 'hidden');
|
|
3799
|
+
if (!canvasAdvancedFeatures) {
|
|
3800
|
+
widgetDetailsStep = 'create';
|
|
3801
|
+
for (const panelId of Object.keys(widgetPanelSnapshots || {})) {
|
|
3802
|
+
if (getPanelState(panelId).widgetDetailsStep !== 'create') {
|
|
3803
|
+
patchPanelSnapshot(panelId, { widgetDetailsStep: 'create' });
|
|
3804
|
+
}
|
|
3805
|
+
}
|
|
3806
|
+
}
|
|
3799
3807
|
}
|
|
3800
3808
|
|
|
3801
3809
|
function resolveHostTargetWidgetId(): string | null {
|
|
@@ -5499,7 +5507,7 @@
|
|
|
5499
5507
|
selectedWidgetId === deepLinkWidgetId && !!getWidgetById(deepLinkWidgetId);
|
|
5500
5508
|
if (alreadyLinked) {
|
|
5501
5509
|
if (embeddedInitialStepPending && initialStep) {
|
|
5502
|
-
widgetDetailsStep = initialStep;
|
|
5510
|
+
widgetDetailsStep = resolveCreatorWorkflowStep(initialStep);
|
|
5503
5511
|
embeddedInitialStepPending = false;
|
|
5504
5512
|
}
|
|
5505
5513
|
embeddedDeepLinkAutoOpenDone = true;
|
|
@@ -5550,7 +5558,7 @@
|
|
|
5550
5558
|
canvasRef.selectWidgetShape(target.id);
|
|
5551
5559
|
}
|
|
5552
5560
|
if (embeddedInitialStepPending && initialStep) {
|
|
5553
|
-
widgetDetailsStep = initialStep;
|
|
5561
|
+
widgetDetailsStep = resolveCreatorWorkflowStep(initialStep);
|
|
5554
5562
|
embeddedInitialStepPending = false;
|
|
5555
5563
|
}
|
|
5556
5564
|
|
|
@@ -5988,10 +5996,10 @@
|
|
|
5988
5996
|
}
|
|
5989
5997
|
if (!isGeneratingCode && !_isRestoringCheckpoint) {
|
|
5990
5998
|
if (embeddedInitialStepPending && initialStep) {
|
|
5991
|
-
widgetDetailsStep = initialStep;
|
|
5999
|
+
widgetDetailsStep = resolveCreatorWorkflowStep(initialStep);
|
|
5992
6000
|
embeddedInitialStepPending = false;
|
|
5993
6001
|
} else if (initialStep) {
|
|
5994
|
-
widgetDetailsStep = initialStep;
|
|
6002
|
+
widgetDetailsStep = resolveCreatorWorkflowStep(initialStep);
|
|
5995
6003
|
} else {
|
|
5996
6004
|
widgetDetailsStep = 'create';
|
|
5997
6005
|
}
|
|
@@ -6839,8 +6847,8 @@
|
|
|
6839
6847
|
if (quiet || isConvertOrDraftPanelOpen()) {
|
|
6840
6848
|
const shapeDataUrl = canvasRef?.getWidgetShapeDataUrl?.(widgetId);
|
|
6841
6849
|
if (shapeDataUrl && canvasRef) {
|
|
6842
|
-
// console.log('[handleRefreshScreenshot] Using canvas shape screenshot (panel closed):', widgetId.substring(0, 8));
|
|
6843
6850
|
canvasRef.updateWidgetImage(widgetId, shapeDataUrl);
|
|
6851
|
+
void persistWidgetListThumbnail(widgetId, shapeDataUrl);
|
|
6844
6852
|
} else {
|
|
6845
6853
|
// console.log('[handleRefreshScreenshot] Skip quiet capture — panel closed:', widgetId.substring(0, 8));
|
|
6846
6854
|
}
|
|
@@ -6892,6 +6900,7 @@
|
|
|
6892
6900
|
const json = canvasRef?.saveCanvas();
|
|
6893
6901
|
if (json) handleCanvasAutoSave(json);
|
|
6894
6902
|
}, 500);
|
|
6903
|
+
void persistWidgetListThumbnail(widgetId, result.data);
|
|
6895
6904
|
if (!quiet) {
|
|
6896
6905
|
showToast('success', 'Widget preview updated on canvas', { duration: 2000 });
|
|
6897
6906
|
} else {
|
|
@@ -8080,9 +8089,10 @@ Requirements:
|
|
|
8080
8089
|
selectedWidgetId = initialWidgetId;
|
|
8081
8090
|
saveSelectedWidgetId(initialWidgetId);
|
|
8082
8091
|
}
|
|
8083
|
-
// Site deep-link: Edit widget
|
|
8092
|
+
// Site deep-link: Edit widget / New Composition used to open Edit/Embed in Creator.
|
|
8093
|
+
// Canvas is Create-only now; /composition owns the editor.
|
|
8084
8094
|
if (embedded && initialStep) {
|
|
8085
|
-
widgetDetailsStep = initialStep;
|
|
8095
|
+
widgetDetailsStep = resolveCreatorWorkflowStep(initialStep);
|
|
8086
8096
|
}
|
|
8087
8097
|
if (embedded && projectId) {
|
|
8088
8098
|
// console.log('[CreatorApp] Embedded project context:', {
|
|
@@ -8733,7 +8743,7 @@ Requirements:
|
|
|
8733
8743
|
lastPublishedVersion: publishedVersion,
|
|
8734
8744
|
selectedWidgetJsPath: widget?.jsPath ?? null,
|
|
8735
8745
|
currentRepositoryId: normalizeRepositoryId(widget),
|
|
8736
|
-
widgetDetailsStep: publishedVersion !== null ? 'edit' : 'create',
|
|
8746
|
+
widgetDetailsStep: resolveCreatorWorkflowStep(publishedVersion !== null ? 'edit' : 'create'),
|
|
8737
8747
|
generateCodeStatus: null,
|
|
8738
8748
|
lastGenerationFailed: false,
|
|
8739
8749
|
lastGenerationError: null,
|
|
@@ -8949,12 +8959,18 @@ Requirements:
|
|
|
8949
8959
|
const resolvedVersion = resolvePublishedVersionFromWidget(widget);
|
|
8950
8960
|
const resolvedJsPath = ((widget as { jsPath?: string | null; js_path?: string | null })?.jsPath
|
|
8951
8961
|
?? (widget as { js_path?: string | null })?.js_path) as string | null;
|
|
8952
|
-
if (resolvedVersion !== null &&
|
|
8962
|
+
if (resolvedVersion !== null && snap.lastPublishedVersion === null) {
|
|
8953
8963
|
patchPanelSnapshot(widgetId, {
|
|
8954
8964
|
lastPublishedVersion: resolvedVersion,
|
|
8955
8965
|
selectedWidgetJsPath: snap.selectedWidgetJsPath ?? resolvedJsPath,
|
|
8956
|
-
widgetDetailsStep: 'edit',
|
|
8966
|
+
...(canvasAdvancedFeatures ? { widgetDetailsStep: 'edit' as const } : {}),
|
|
8957
8967
|
});
|
|
8968
|
+
} else if (
|
|
8969
|
+
canvasAdvancedFeatures
|
|
8970
|
+
&& resolvedVersion !== null
|
|
8971
|
+
&& snap.widgetDetailsStep === 'create'
|
|
8972
|
+
) {
|
|
8973
|
+
patchPanelSnapshot(widgetId, { widgetDetailsStep: 'edit' });
|
|
8958
8974
|
}
|
|
8959
8975
|
}
|
|
8960
8976
|
|
|
@@ -11889,6 +11905,10 @@ $: if (codeGenerationPrompt && selectedWidgetId && promptLoadedForWidgetId === s
|
|
|
11889
11905
|
}
|
|
11890
11906
|
}
|
|
11891
11907
|
|
|
11908
|
+
if (screenshot) {
|
|
11909
|
+
void persistWidgetListThumbnail(widgetId, screenshot);
|
|
11910
|
+
}
|
|
11911
|
+
|
|
11892
11912
|
// Auto-create repository so generation can start right away.
|
|
11893
11913
|
try {
|
|
11894
11914
|
const repoId = await ensureWidgetRepository(newWidget, { silent: true });
|
|
@@ -11907,11 +11927,15 @@ $: if (codeGenerationPrompt && selectedWidgetId && promptLoadedForWidgetId === s
|
|
|
11907
11927
|
// panel remounts: the freshly mounted Chat then activates this
|
|
11908
11928
|
// conversation (best-conversation = one with messages) instead of
|
|
11909
11929
|
// starting empty after a close/reopen.
|
|
11910
|
-
await ensureCodegenUserMessagePersisted(
|
|
11911
|
-
|
|
11912
|
-
|
|
11913
|
-
|
|
11914
|
-
|
|
11930
|
+
await ensureCodegenUserMessagePersisted(
|
|
11931
|
+
widgetId,
|
|
11932
|
+
prompt,
|
|
11933
|
+
uniquePersistImageUrls([
|
|
11934
|
+
...extraImageUrls,
|
|
11935
|
+
...(draftPanelState.promptImages ?? []),
|
|
11936
|
+
screenshot,
|
|
11937
|
+
]),
|
|
11938
|
+
);
|
|
11915
11939
|
// NOTE: never copy currentChatConversationId from the draft — the draft
|
|
11916
11940
|
// chat's conversation is a local UUID that doesn't exist in the DB, and
|
|
11917
11941
|
// migrating it would point codegen/summaries at a phantom conversation.
|
|
@@ -12882,6 +12906,7 @@ $: if (codeGenerationPrompt && selectedWidgetId && promptLoadedForWidgetId === s
|
|
|
12882
12906
|
panelTopOffset={widgetsPanelTopOffset}
|
|
12883
12907
|
panelBottomMargin={embedded ? 24 : widgetsPanelBottomMargin}
|
|
12884
12908
|
fillViewport={false}
|
|
12909
|
+
showCompositionSteps={canvasAdvancedFeatures}
|
|
12885
12910
|
currentStep={ps.widgetDetailsStep}
|
|
12886
12911
|
on:focusPanel={() => focusWidgetPanel(panelWidgetId)}
|
|
12887
12912
|
on:stepChange={({ detail }) => {
|
|
@@ -285,6 +285,12 @@
|
|
|
285
285
|
// ═══════════════════════════════════════════════════════════════════════
|
|
286
286
|
type WidgetStep = 'create' | 'edit' | 'embed';
|
|
287
287
|
export let currentStep: WidgetStep = 'create';
|
|
288
|
+
/**
|
|
289
|
+
* Canvas Creator is code-only (chat + preview). Edit/Embed header steps stay
|
|
290
|
+
* off until composition editing lives on /composition. Keep the Edit/Embed
|
|
291
|
+
* panels mounted (CSS-hidden) so we can turn this back on without ripping slots.
|
|
292
|
+
*/
|
|
293
|
+
export let showCompositionSteps: boolean = false;
|
|
288
294
|
/** After Set live, Create preview stays on that published artifact until the next Worker build. */
|
|
289
295
|
let pinnedPublishedPreviewUrl: string | null = null;
|
|
290
296
|
|
|
@@ -308,8 +314,15 @@
|
|
|
308
314
|
previewError = null;
|
|
309
315
|
if (!iframeSrc) previewLoading = true;
|
|
310
316
|
}
|
|
311
|
-
$: canEditStep = lastPublishedVersion !== null && !isGeneratingCode;
|
|
312
|
-
$: canEmbedStep = lastPublishedVersion !== null && !isGeneratingCode;
|
|
317
|
+
$: canEditStep = showCompositionSteps && lastPublishedVersion !== null && !isGeneratingCode;
|
|
318
|
+
$: canEmbedStep = showCompositionSteps && lastPublishedVersion !== null && !isGeneratingCode;
|
|
319
|
+
$: activeWorkflowStep = showCompositionSteps ? currentStep : 'create';
|
|
320
|
+
|
|
321
|
+
$: if (!showCompositionSteps && currentStep !== 'create') {
|
|
322
|
+
currentStep = 'create';
|
|
323
|
+
dispatch('stepChange', { step: 'create' });
|
|
324
|
+
switchPreviewUrlForStep('create');
|
|
325
|
+
}
|
|
313
326
|
|
|
314
327
|
// Auto-switch back to Create when code generation starts
|
|
315
328
|
let _justFinishedGenerating = false;
|
|
@@ -358,6 +371,7 @@
|
|
|
358
371
|
|
|
359
372
|
function canNavigateToStep(step: WidgetStep): boolean {
|
|
360
373
|
if (step === 'create') return true;
|
|
374
|
+
if (!showCompositionSteps) return false;
|
|
361
375
|
if (step === 'edit') return canEditStep;
|
|
362
376
|
if (step === 'embed') return canEmbedStep;
|
|
363
377
|
return false;
|
|
@@ -978,6 +992,7 @@
|
|
|
978
992
|
let detailsDragBarEl: HTMLElement | null = null;
|
|
979
993
|
let widgetDetailsNameCtEl: HTMLElement | null = null;
|
|
980
994
|
let widgetDetailsStepsRowEl: HTMLElement | null = null;
|
|
995
|
+
let widgetDetailsDebugButtonsEl: HTMLElement | null = null;
|
|
981
996
|
let headerNameMaxWidthPx = 96;
|
|
982
997
|
let detailsDragStartX = 0;
|
|
983
998
|
let detailsDragStartY = 0;
|
|
@@ -2818,10 +2833,14 @@
|
|
|
2818
2833
|
}
|
|
2819
2834
|
|
|
2820
2835
|
function updateHeaderNameMaxWidth() {
|
|
2821
|
-
if (!widgetDetailsNameCtEl
|
|
2836
|
+
if (!widgetDetailsNameCtEl) return;
|
|
2822
2837
|
const nameRect = widgetDetailsNameCtEl.getBoundingClientRect();
|
|
2823
|
-
const
|
|
2824
|
-
|
|
2838
|
+
const rightEl = showCompositionSteps && widgetDetailsStepsRowEl
|
|
2839
|
+
? widgetDetailsStepsRowEl
|
|
2840
|
+
: widgetDetailsDebugButtonsEl;
|
|
2841
|
+
if (!rightEl) return;
|
|
2842
|
+
const rightRect = rightEl.getBoundingClientRect();
|
|
2843
|
+
const available = Math.floor(rightRect.left - nameRect.left - HEADER_ELEMENTS_GAP_PX);
|
|
2825
2844
|
const next = Math.max(HEADER_NAME_MIN_WIDTH_PX, available);
|
|
2826
2845
|
if (next !== headerNameMaxWidthPx) {
|
|
2827
2846
|
headerNameMaxWidthPx = next;
|
|
@@ -3359,6 +3378,7 @@
|
|
|
3359
3378
|
}}
|
|
3360
3379
|
/>
|
|
3361
3380
|
</div>
|
|
3381
|
+
{#if showCompositionSteps}
|
|
3362
3382
|
<div
|
|
3363
3383
|
class="widget-details-step-indicator-row pointer-events-none absolute left-1/2 top-1/2 z-0 flex -translate-x-1/2 -translate-y-1/2 justify-center"
|
|
3364
3384
|
bind:this={widgetDetailsStepsRowEl}
|
|
@@ -3421,8 +3441,12 @@
|
|
|
3421
3441
|
</HoverTooltip>
|
|
3422
3442
|
</div>
|
|
3423
3443
|
</div>
|
|
3444
|
+
{/if}
|
|
3424
3445
|
|
|
3425
|
-
<div
|
|
3446
|
+
<div
|
|
3447
|
+
class="widget-details-debug-buttons relative z-[1] ml-auto flex items-center shrink-0"
|
|
3448
|
+
bind:this={widgetDetailsDebugButtonsEl}
|
|
3449
|
+
>
|
|
3426
3450
|
<HoverTooltip text={previewColumnCollapsed ? 'Open live preview' : 'Close live preview'}>
|
|
3427
3451
|
<button
|
|
3428
3452
|
type="button"
|
|
@@ -3505,7 +3529,7 @@
|
|
|
3505
3529
|
<div class="actions-panel widget-details-actions-panel relative flex flex-col flex-1 min-h-0">
|
|
3506
3530
|
|
|
3507
3531
|
<!-- Keep all steps mounted — switching tabs must not destroy chat / PropsEditor state -->
|
|
3508
|
-
<div class="widget-details-create-step flex flex-col flex-1 min-h-0 overflow-hidden overflow-x-hidden {
|
|
3532
|
+
<div class="widget-details-create-step flex flex-col flex-1 min-h-0 overflow-hidden overflow-x-hidden {activeWorkflowStep === 'create' ? '' : 'hidden'}">
|
|
3509
3533
|
<div class="widget-details-create-models-ct shrink-0 empty:hidden">
|
|
3510
3534
|
<slot name="code-generation-models" />
|
|
3511
3535
|
</div>
|
|
@@ -3523,10 +3547,10 @@
|
|
|
3523
3547
|
<slot name="publish-widget" />
|
|
3524
3548
|
</div>
|
|
3525
3549
|
</div>
|
|
3526
|
-
<div class="widget-details-edit-step flex flex-col flex-1 min-h-0 overflow-hidden {
|
|
3550
|
+
<div class="widget-details-edit-step flex flex-col flex-1 min-h-0 overflow-hidden {activeWorkflowStep === 'edit' ? '' : 'hidden'}">
|
|
3527
3551
|
<slot name="composition-editor" />
|
|
3528
3552
|
</div>
|
|
3529
|
-
<div class="widget-details-embed-step flex flex-col flex-1 min-h-0 overflow-y-auto overflow-x-hidden scrollbar-thin gap-2 p-2 {
|
|
3553
|
+
<div class="widget-details-embed-step flex flex-col flex-1 min-h-0 overflow-y-auto overflow-x-hidden scrollbar-thin gap-2 p-2 {activeWorkflowStep === 'embed' ? '' : 'hidden'}">
|
|
3530
3554
|
<slot name="embed-section" />
|
|
3531
3555
|
</div>
|
|
3532
3556
|
|
|
@@ -99,6 +99,11 @@ declare const WidgetDetails: $$__sveltets_2_IsomorphicComponent<{
|
|
|
99
99
|
/** Cascade offset index (0 = centered, 1+ = shifted down-right). */ panelCascadeIndex?: number;
|
|
100
100
|
/** False when another panel has keyboard/chat focus. */ isFocusedPanel?: boolean;
|
|
101
101
|
currentStep?: "embed" | "create" | "edit";
|
|
102
|
+
/**
|
|
103
|
+
* Canvas Creator is code-only (chat + preview). Edit/Embed header steps stay
|
|
104
|
+
* off until composition editing lives on /composition. Keep the Edit/Embed
|
|
105
|
+
* panels mounted (CSS-hidden) so we can turn this back on without ripping slots.
|
|
106
|
+
*/ showCompositionSteps?: boolean;
|
|
102
107
|
beginCompositionHydration?: () => void;
|
|
103
108
|
showPublishedArtifact?: (url: string | null) => void;
|
|
104
109
|
finishCompositionHydration?: () => void;
|
package/dist/creator-types.d.ts
CHANGED
|
@@ -6,7 +6,7 @@ export interface CreatorAppProps {
|
|
|
6
6
|
initialWidgetId?: string | null;
|
|
7
7
|
/** Select this composition when opening Edit step from site. */
|
|
8
8
|
initialCompositionId?: string | null;
|
|
9
|
-
/** Open Widget Details on this step when embedded from site (overrides auto step once). */
|
|
9
|
+
/** Open Widget Details on this step when embedded from site (overrides auto step once). Ignored while Creator composition steps are hidden. */
|
|
10
10
|
initialStep?: 'create' | 'edit' | 'embed';
|
|
11
11
|
/**
|
|
12
12
|
* Site "+ New widget": create an empty canvas + Untitled widget instead of
|
|
@@ -35,6 +35,7 @@ export interface CreatorAppProps {
|
|
|
35
35
|
/**
|
|
36
36
|
* Extra canvas tools (undo/frame/image/library, zoom 1:1/fit/shortcuts).
|
|
37
37
|
* Independent of debugMode — Debug is staging-only UI.
|
|
38
|
+
* Also shows Widget Details Edit/Embed steps while ON (dev testing).
|
|
38
39
|
* Site owns the header toggle; embed uses CustomEvent after mount.
|
|
39
40
|
*/
|
|
40
41
|
initialAdvancedFeatures?: boolean;
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { WidgetsApi } from '@widgetic/api-sdk';
|
|
2
|
+
/**
|
|
3
|
+
* Upload a convert/preview screenshot to widgets.thumbnail_url via the API gateway.
|
|
4
|
+
*/
|
|
5
|
+
export declare function persistWidgetThumbnail(widgetsClient: WidgetsApi | null | undefined, widgetId: string | null | undefined, imageDataUrl: string | null | undefined): Promise<string | null>;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Upload a convert/preview screenshot to widgets.thumbnail_url via the API gateway.
|
|
3
|
+
*/
|
|
4
|
+
export async function persistWidgetThumbnail(widgetsClient, widgetId, imageDataUrl) {
|
|
5
|
+
if (!widgetsClient || !widgetId || typeof imageDataUrl !== 'string')
|
|
6
|
+
return null;
|
|
7
|
+
if (!imageDataUrl.startsWith('data:image/'))
|
|
8
|
+
return null;
|
|
9
|
+
try {
|
|
10
|
+
const response = await widgetsClient.uploadWidgetThumbnailRaw({
|
|
11
|
+
id: widgetId,
|
|
12
|
+
uploadWidgetThumbnailRequest: { imageDataUrl },
|
|
13
|
+
});
|
|
14
|
+
const json = await response.raw.json();
|
|
15
|
+
const thumbnailUrl = json?.data?.thumbnailUrl ||
|
|
16
|
+
json?.data?.thumbnail_url ||
|
|
17
|
+
json?.thumbnailUrl ||
|
|
18
|
+
null;
|
|
19
|
+
if (thumbnailUrl) {
|
|
20
|
+
console.log('[persistWidgetThumbnail] stored', widgetId.slice(0, 8), thumbnailUrl.slice(0, 80));
|
|
21
|
+
}
|
|
22
|
+
return thumbnailUrl;
|
|
23
|
+
}
|
|
24
|
+
catch (error) {
|
|
25
|
+
console.warn('[persistWidgetThumbnail] failed', widgetId?.slice(0, 8), error);
|
|
26
|
+
return null;
|
|
27
|
+
}
|
|
28
|
+
}
|