@widgetic/creator 0.3.50 → 0.3.51
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 +917 -272
- package/dist/CreatorApp.svelte.d.ts +1 -0
- package/dist/components/WidgetDetails.svelte +188 -41
- package/dist/creator-types.d.ts +6 -0
- package/package.json +1 -1
|
@@ -25,6 +25,7 @@ declare const CreatorApp: $$__sveltets_2_IsomorphicComponent<{
|
|
|
25
25
|
apiUrl?: CreatorAppProps["apiUrl"];
|
|
26
26
|
widgetBuilderUrl?: CreatorAppProps["widgetBuilderUrl"];
|
|
27
27
|
initialDebugMode?: CreatorAppProps["initialDebugMode"];
|
|
28
|
+
initialAdvancedFeatures?: CreatorAppProps["initialAdvancedFeatures"];
|
|
28
29
|
defaultCoderModelId?: CreatorAppProps["defaultCoderModelId"];
|
|
29
30
|
defaultPlannerModelId?: CreatorAppProps["defaultPlannerModelId"];
|
|
30
31
|
showWidgetsList?: CreatorAppProps["showWidgetsList"];
|
|
@@ -868,6 +868,8 @@
|
|
|
868
868
|
const LEFT_COL_DEFAULT_PERCENT = 58;
|
|
869
869
|
const LEFT_COL_MIN_PERCENT = 32;
|
|
870
870
|
const LEFT_COL_MAX_PERCENT = 72;
|
|
871
|
+
const COL_RESIZER_PX = 10;
|
|
872
|
+
const PREVIEW_COL_MIN_PX = 240;
|
|
871
873
|
/** Chat-first layout: preview column starts collapsed and opens on generate. */
|
|
872
874
|
let previewColumnCollapsed = true;
|
|
873
875
|
let lastAutoExpandForGenerating = false;
|
|
@@ -891,6 +893,23 @@
|
|
|
891
893
|
expandPreviewColumn();
|
|
892
894
|
}
|
|
893
895
|
|
|
896
|
+
function maxLeftColPercent(): number {
|
|
897
|
+
const twoCol =
|
|
898
|
+
typeof document !== 'undefined'
|
|
899
|
+
? (document.querySelector('.widget-details-two-col') as HTMLElement | null)
|
|
900
|
+
: null;
|
|
901
|
+
const width = twoCol?.clientWidth || detailsPanelWidth || DETAILS_PANEL_DEFAULT_WIDTH;
|
|
902
|
+
if (width <= 0) return LEFT_COL_MAX_PERCENT;
|
|
903
|
+
const maxLeftPx = Math.max(160, width - COL_RESIZER_PX - PREVIEW_COL_MIN_PX);
|
|
904
|
+
return Math.min(LEFT_COL_MAX_PERCENT, (maxLeftPx / width) * 100);
|
|
905
|
+
}
|
|
906
|
+
|
|
907
|
+
function clampLeftColPercent(percent: number): number {
|
|
908
|
+
const maxP = maxLeftColPercent();
|
|
909
|
+
const minP = Math.min(LEFT_COL_MIN_PERCENT, maxP);
|
|
910
|
+
return Math.min(maxP, Math.max(minP, percent));
|
|
911
|
+
}
|
|
912
|
+
|
|
894
913
|
function collapsePreviewColumn() {
|
|
895
914
|
previewColumnCollapsed = true;
|
|
896
915
|
if (widthBeforePreviewExpand > 0) {
|
|
@@ -911,10 +930,7 @@
|
|
|
911
930
|
const fittedWidth = Math.min(expandedWidth, Math.max(widthBeforePreviewExpand, maxRight - detailsPanelX));
|
|
912
931
|
detailsPanelWidth = Math.max(widthBeforePreviewExpand, fittedWidth);
|
|
913
932
|
const usable = Math.max(1, detailsPanelWidth);
|
|
914
|
-
leftColPercent =
|
|
915
|
-
LEFT_COL_MAX_PERCENT,
|
|
916
|
-
Math.max(LEFT_COL_MIN_PERCENT, (widthBeforePreviewExpand / usable) * 100),
|
|
917
|
-
);
|
|
933
|
+
leftColPercent = clampLeftColPercent((widthBeforePreviewExpand / usable) * 100);
|
|
918
934
|
console.log('[WidgetDetails] Preview column expanded', {
|
|
919
935
|
from: widthBeforePreviewExpand,
|
|
920
936
|
to: detailsPanelWidth,
|
|
@@ -1461,7 +1477,9 @@
|
|
|
1461
1477
|
}
|
|
1462
1478
|
|
|
1463
1479
|
export function hasValidPreview(): boolean {
|
|
1464
|
-
|
|
1480
|
+
// Iframe can already show a compiled preview while `previewLoading`/`previewError`
|
|
1481
|
+
// still lag (e.g. iteration rebuild). Screenshot only needs a live contentWindow.
|
|
1482
|
+
return !!previewIframe?.contentWindow;
|
|
1465
1483
|
}
|
|
1466
1484
|
|
|
1467
1485
|
export function getPreviewIframe(): HTMLIFrameElement | null {
|
|
@@ -1590,19 +1608,65 @@
|
|
|
1590
1608
|
notifyPreviewCompileErrorChanged();
|
|
1591
1609
|
}
|
|
1592
1610
|
flushPendingPreviewMessages();
|
|
1593
|
-
|
|
1594
|
-
dispatch('previewLoaded', { step: currentStep });
|
|
1595
|
-
}
|
|
1611
|
+
dispatch('previewLoaded', { step: currentStep });
|
|
1596
1612
|
// Emit previewReady so the parent app can clear the "…loading preview…" status.
|
|
1597
1613
|
dispatch('previewReady', { widgetId: selectedWidgetId, step: currentStep });
|
|
1598
1614
|
// Fill available preview area once the widget confirms it is ready.
|
|
1599
1615
|
scheduleFitPreviewToArea();
|
|
1600
1616
|
}
|
|
1601
1617
|
|
|
1618
|
+
function looksLikeHtmlMarkup(value: unknown): value is string {
|
|
1619
|
+
return typeof value === 'string' && /<[a-z][\s\S]*>/i.test(value);
|
|
1620
|
+
}
|
|
1621
|
+
|
|
1622
|
+
/** Same-origin preview iframes (Vite /__widget_builder__ proxy): restore bold/italic after widgets set textContent. */
|
|
1623
|
+
function applyRichTextInPreviewIframe(message: Record<string, unknown>): void {
|
|
1624
|
+
if (message.type !== 'widgetic:update') return;
|
|
1625
|
+
const doc = previewIframe?.contentDocument;
|
|
1626
|
+
if (!doc) return;
|
|
1627
|
+
const apply = () => {
|
|
1628
|
+
try {
|
|
1629
|
+
const content = message.content as Record<string, unknown> | undefined;
|
|
1630
|
+
if (content) {
|
|
1631
|
+
for (const [key, value] of Object.entries(content)) {
|
|
1632
|
+
if (!looksLikeHtmlMarkup(value)) continue;
|
|
1633
|
+
doc.querySelectorAll(`[data-content="${CSS.escape(key)}"]`).forEach((el) => {
|
|
1634
|
+
if (el instanceof HTMLImageElement || el instanceof HTMLInputElement) return;
|
|
1635
|
+
el.innerHTML = value;
|
|
1636
|
+
});
|
|
1637
|
+
}
|
|
1638
|
+
}
|
|
1639
|
+
const items = message.contentItems as Array<Record<string, unknown>> | undefined;
|
|
1640
|
+
if (Array.isArray(items)) {
|
|
1641
|
+
for (const item of items) {
|
|
1642
|
+
const itemEl = item?.id
|
|
1643
|
+
? doc.querySelector(`[data-content-item="${CSS.escape(String(item.id))}"]`)
|
|
1644
|
+
: null;
|
|
1645
|
+
const scope = itemEl || doc;
|
|
1646
|
+
for (const [key, value] of Object.entries(item || {})) {
|
|
1647
|
+
if (key === 'id' || !looksLikeHtmlMarkup(value)) continue;
|
|
1648
|
+
scope.querySelectorAll(`[data-content="${CSS.escape(key)}"]`).forEach((el) => {
|
|
1649
|
+
if (el instanceof HTMLImageElement || el instanceof HTMLInputElement) return;
|
|
1650
|
+
el.innerHTML = value;
|
|
1651
|
+
});
|
|
1652
|
+
}
|
|
1653
|
+
}
|
|
1654
|
+
}
|
|
1655
|
+
} catch (error) {
|
|
1656
|
+
console.warn('[WidgetDetails] Rich-text preview overlay skipped:', error);
|
|
1657
|
+
}
|
|
1658
|
+
};
|
|
1659
|
+
requestAnimationFrame(() => {
|
|
1660
|
+
apply();
|
|
1661
|
+
setTimeout(apply, 50);
|
|
1662
|
+
});
|
|
1663
|
+
}
|
|
1664
|
+
|
|
1602
1665
|
/** Send a postMessage to the widget preview iframe (for live property editing) */
|
|
1603
1666
|
export function sendMessageToPreview(message: Record<string, unknown>): void {
|
|
1604
1667
|
if (previewWidgetReady && previewIframe?.contentWindow) {
|
|
1605
1668
|
previewIframe.contentWindow.postMessage(message, '*');
|
|
1669
|
+
applyRichTextInPreviewIframe(message);
|
|
1606
1670
|
return;
|
|
1607
1671
|
}
|
|
1608
1672
|
pendingPreviewMessages.push(message);
|
|
@@ -1944,9 +2008,15 @@
|
|
|
1944
2008
|
}
|
|
1945
2009
|
} else {
|
|
1946
2010
|
previewHydrating = false;
|
|
1947
|
-
previewWidgetReady = true;
|
|
1948
2011
|
dispatch('previewReady', { widgetId: selectedWidgetId, step: currentStep });
|
|
1949
|
-
// Create
|
|
2012
|
+
// Create: wait for widgetic:ready so contentItems overlay is not sent before the widget listens.
|
|
2013
|
+
if (!previewWidgetReady) {
|
|
2014
|
+
if (previewReadyFallbackTimeout) clearTimeout(previewReadyFallbackTimeout);
|
|
2015
|
+
previewReadyFallbackTimeout = setTimeout(() => {
|
|
2016
|
+
console.warn('[WidgetDetails] Create step widgetic:ready fallback — applying overlay');
|
|
2017
|
+
markPreviewWidgetReady();
|
|
2018
|
+
}, 1500);
|
|
2019
|
+
}
|
|
1950
2020
|
scheduleFitPreviewToArea();
|
|
1951
2021
|
}
|
|
1952
2022
|
}
|
|
@@ -2273,10 +2343,7 @@
|
|
|
2273
2343
|
const width = twoCol?.clientWidth || detailsPanelWidth || DETAILS_PANEL_DEFAULT_WIDTH;
|
|
2274
2344
|
if (width <= 0) return;
|
|
2275
2345
|
const deltaPercent = ((e.clientX - columnResizeStartX) / width) * 100;
|
|
2276
|
-
leftColPercent =
|
|
2277
|
-
LEFT_COL_MAX_PERCENT,
|
|
2278
|
-
Math.max(LEFT_COL_MIN_PERCENT, columnResizeStartPercent + deltaPercent)
|
|
2279
|
-
);
|
|
2346
|
+
leftColPercent = clampLeftColPercent(columnResizeStartPercent + deltaPercent);
|
|
2280
2347
|
// Keep preview iframe inside the shrinking right column (avoid clipped "cut off" widgets).
|
|
2281
2348
|
requestAnimationFrame(() => {
|
|
2282
2349
|
clampPreviewToArea();
|
|
@@ -2363,15 +2430,27 @@
|
|
|
2363
2430
|
window.removeEventListener('blur', stopFn);
|
|
2364
2431
|
}
|
|
2365
2432
|
|
|
2366
|
-
|
|
2433
|
+
let detailsResizeEdge: 'se' | 'sw' | 'e' | 'w' | 's' = 'se';
|
|
2434
|
+
let detailsResizeStartPanelX = 0;
|
|
2435
|
+
let detailsResizeStartPanelY = 0;
|
|
2436
|
+
|
|
2437
|
+
function startDetailsResize(e: MouseEvent, edge: 'se' | 'sw' | 'e' | 'w' | 's' = 'se') {
|
|
2367
2438
|
e.preventDefault();
|
|
2368
2439
|
e.stopPropagation();
|
|
2369
2440
|
isResizingDetails = true;
|
|
2441
|
+
detailsResizeEdge = edge;
|
|
2370
2442
|
detailsResizeStartX = e.clientX;
|
|
2371
2443
|
detailsResizeStartY = e.clientY;
|
|
2372
2444
|
detailsResizeStartWidth = detailsPanelWidth;
|
|
2373
2445
|
detailsResizeStartHeight = detailsPanelHeight || getDefaultDetailsPanelHeight();
|
|
2374
|
-
|
|
2446
|
+
detailsResizeStartPanelX = detailsPanelX;
|
|
2447
|
+
detailsResizeStartPanelY = detailsPanelY;
|
|
2448
|
+
const cursor =
|
|
2449
|
+
edge === 'e' || edge === 'w' ? 'ew-resize'
|
|
2450
|
+
: edge === 's' ? 'ns-resize'
|
|
2451
|
+
: edge === 'sw' ? 'nesw-resize'
|
|
2452
|
+
: 'nwse-resize';
|
|
2453
|
+
document.body.style.cursor = cursor;
|
|
2375
2454
|
document.body.style.userSelect = 'none';
|
|
2376
2455
|
window.addEventListener('mousemove', onDetailsResize);
|
|
2377
2456
|
addGlobalStopListeners(stopDetailsResize);
|
|
@@ -2381,10 +2460,46 @@
|
|
|
2381
2460
|
if (!isResizingDetails) return;
|
|
2382
2461
|
const deltaX = e.clientX - detailsResizeStartX;
|
|
2383
2462
|
const deltaY = e.clientY - detailsResizeStartY;
|
|
2384
|
-
const
|
|
2385
|
-
const
|
|
2386
|
-
|
|
2387
|
-
|
|
2463
|
+
const minW = DETAILS_PANEL_MIN_WIDTH;
|
|
2464
|
+
const minH = DETAILS_PANEL_MIN_HEIGHT;
|
|
2465
|
+
const maxRight = window.innerWidth - 8;
|
|
2466
|
+
const maxBottom = window.innerHeight - 8;
|
|
2467
|
+
|
|
2468
|
+
let nextW = detailsResizeStartWidth;
|
|
2469
|
+
let nextH = detailsResizeStartHeight;
|
|
2470
|
+
let nextX = detailsResizeStartPanelX;
|
|
2471
|
+
let nextY = detailsResizeStartPanelY;
|
|
2472
|
+
|
|
2473
|
+
if (detailsResizeEdge === 'e' || detailsResizeEdge === 'se') {
|
|
2474
|
+
nextW = detailsResizeStartWidth + deltaX;
|
|
2475
|
+
}
|
|
2476
|
+
if (detailsResizeEdge === 'w' || detailsResizeEdge === 'sw') {
|
|
2477
|
+
nextW = detailsResizeStartWidth - deltaX;
|
|
2478
|
+
nextX = detailsResizeStartPanelX + deltaX;
|
|
2479
|
+
}
|
|
2480
|
+
if (detailsResizeEdge === 's' || detailsResizeEdge === 'se' || detailsResizeEdge === 'sw') {
|
|
2481
|
+
nextH = detailsResizeStartHeight + deltaY;
|
|
2482
|
+
}
|
|
2483
|
+
|
|
2484
|
+
nextW = Math.max(minW, nextW);
|
|
2485
|
+
nextH = Math.max(minH, nextH);
|
|
2486
|
+
if (detailsResizeEdge === 'w' || detailsResizeEdge === 'sw') {
|
|
2487
|
+
nextX = detailsResizeStartPanelX + (detailsResizeStartWidth - nextW);
|
|
2488
|
+
if (nextX < 8) {
|
|
2489
|
+
nextW -= (8 - nextX);
|
|
2490
|
+
nextX = 8;
|
|
2491
|
+
}
|
|
2492
|
+
}
|
|
2493
|
+
if (nextX + nextW > maxRight) nextW = maxRight - nextX;
|
|
2494
|
+
if (nextY + nextH > maxBottom) nextH = maxBottom - nextY;
|
|
2495
|
+
|
|
2496
|
+
detailsPanelWidth = nextW;
|
|
2497
|
+
detailsPanelHeight = nextH;
|
|
2498
|
+
detailsPanelX = nextX;
|
|
2499
|
+
detailsPanelY = nextY;
|
|
2500
|
+
if (!previewColumnCollapsed) {
|
|
2501
|
+
leftColPercent = clampLeftColPercent(leftColPercent);
|
|
2502
|
+
}
|
|
2388
2503
|
}
|
|
2389
2504
|
|
|
2390
2505
|
function stopDetailsResize() {
|
|
@@ -2847,11 +2962,11 @@
|
|
|
2847
2962
|
{#if selectedWidgetId}
|
|
2848
2963
|
<!-- svelte-ignore a11y-no-static-element-interactions -->
|
|
2849
2964
|
<div
|
|
2850
|
-
class="widget-details-floating-panel pointer-events-auto fixed
|
|
2965
|
+
class="widget-details-floating-panel pointer-events-auto fixed
|
|
2851
2966
|
{showWidgetDetails ? 'flex flex-col' : 'hidden'}
|
|
2852
2967
|
{fillViewport
|
|
2853
|
-
? 'bg-white rounded-none border-x border-b border-t-0 ring-0 shadow-none'
|
|
2854
|
-
: 'bg-white/95 backdrop-blur-sm shadow-2xl rounded-xl border'}
|
|
2968
|
+
? 'bg-white rounded-none border-x border-b border-t-0 ring-0 shadow-none overflow-hidden'
|
|
2969
|
+
: 'bg-white/95 backdrop-blur-sm shadow-2xl rounded-xl border overflow-visible'}
|
|
2855
2970
|
{isFocusedPanel
|
|
2856
2971
|
? (fillViewport ? 'border-blue-400' : 'border-blue-400 ring-2 ring-blue-200/80')
|
|
2857
2972
|
: 'border-gray-300 opacity-[0.97]'}"
|
|
@@ -2866,7 +2981,7 @@
|
|
|
2866
2981
|
onpointerdown={startDetailsDrag}
|
|
2867
2982
|
>
|
|
2868
2983
|
<span
|
|
2869
|
-
class="widget-details-name pointer-events-none absolute left-3 top-1/2 -translate-y-1/2 max-w-[
|
|
2984
|
+
class="widget-details-name pointer-events-none absolute left-3 top-1/2 -translate-y-1/2 max-w-[28%] truncate text-sm font-bold text-gray-800"
|
|
2870
2985
|
title={selectedWidget?.name || ''}
|
|
2871
2986
|
>
|
|
2872
2987
|
{selectedWidget?.name || (isDraftConvertPanel ? 'Widget Draft' : 'Widget')}
|
|
@@ -2925,7 +3040,7 @@
|
|
|
2925
3040
|
</div>
|
|
2926
3041
|
</div>
|
|
2927
3042
|
|
|
2928
|
-
<div class="widget-details-debug-buttons flex items-center gap-1.5 shrink-0">
|
|
3043
|
+
<div class="widget-details-debug-buttons flex items-center gap-1.5 shrink-0 pr-1">
|
|
2929
3044
|
<button
|
|
2930
3045
|
type="button"
|
|
2931
3046
|
onclick={() => previewColumnCollapsed ? expandPreviewColumn() : collapsePreviewColumn()}
|
|
@@ -2939,23 +3054,24 @@
|
|
|
2939
3054
|
>
|
|
2940
3055
|
{previewColumnCollapsed ? 'Open Preview' : 'Close Preview'}
|
|
2941
3056
|
</button>
|
|
2942
|
-
<button
|
|
2943
|
-
type="button"
|
|
2944
|
-
onclick={handleCloseButtonClick}
|
|
2945
|
-
onmousedown={(e) => e.stopPropagation()}
|
|
2946
|
-
onpointerdown={(e) => e.stopPropagation()}
|
|
2947
|
-
class="widget-details-close-bt w-6 h-6 flex items-center justify-center rounded-lg hover:bg-gray-200 text-gray-500 hover:text-gray-700 cursor-pointer transition-colors text-sm"
|
|
2948
|
-
title="Close widget details"
|
|
2949
|
-
>
|
|
2950
|
-
✕
|
|
2951
|
-
</button>
|
|
2952
3057
|
</div>
|
|
2953
3058
|
</div>
|
|
2954
3059
|
</div>
|
|
2955
3060
|
|
|
3061
|
+
<button
|
|
3062
|
+
type="button"
|
|
3063
|
+
onclick={handleCloseButtonClick}
|
|
3064
|
+
onmousedown={(e) => e.stopPropagation()}
|
|
3065
|
+
onpointerdown={(e) => e.stopPropagation()}
|
|
3066
|
+
class="widget-details-close-bt absolute -top-2.5 -right-2.5 z-30 w-7 h-7 flex items-center justify-center rounded-full bg-white border border-gray-300 shadow-md hover:bg-red-50 hover:border-red-300 hover:text-red-600 text-gray-500 cursor-pointer transition-colors text-sm"
|
|
3067
|
+
title="Close widget details"
|
|
3068
|
+
>
|
|
3069
|
+
✕
|
|
3070
|
+
</button>
|
|
3071
|
+
|
|
2956
3072
|
<!-- Widget Details Content: Two-column layout -->
|
|
2957
|
-
<div class="widget-details-content-wrapper relative m-2.5 min-w-0 min-h-0 flex-1">
|
|
2958
|
-
<div class="widget-details-two-col flex h-full min-h-0 gap-0">
|
|
3073
|
+
<div class="widget-details-content-wrapper relative m-2.5 min-w-0 min-h-0 flex-1 overflow-x-hidden">
|
|
3074
|
+
<div class="widget-details-two-col flex h-full min-h-0 min-w-0 gap-0 overflow-x-hidden">
|
|
2959
3075
|
|
|
2960
3076
|
<!-- ═══ LEFT COLUMN: Step Content (scrollable) ═══ -->
|
|
2961
3077
|
<div
|
|
@@ -2995,17 +3111,17 @@
|
|
|
2995
3111
|
|
|
2996
3112
|
<!-- Scrollable step content -->
|
|
2997
3113
|
<div
|
|
2998
|
-
class="widget-details-left-content flex flex-col flex-1 min-h-0 relative rounded-b-lg
|
|
3114
|
+
class="widget-details-left-content flex flex-col flex-1 min-h-0 relative rounded-b-lg overflow-hidden overflow-x-hidden"
|
|
2999
3115
|
bind:this={contentContainerEl}
|
|
3000
3116
|
>
|
|
3001
3117
|
<div class="actions-panel widget-details-actions-panel relative flex flex-col flex-1 min-h-0">
|
|
3002
3118
|
|
|
3003
3119
|
<!-- Keep all steps mounted — switching tabs must not destroy chat / PropsEditor state -->
|
|
3004
|
-
<div class="widget-details-create-step flex flex-col flex-1 min-h-0 overflow-hidden gap-2 p-2 {currentStep === 'create' ? '' : 'hidden'}">
|
|
3120
|
+
<div class="widget-details-create-step flex flex-col flex-1 min-h-0 justify-start overflow-y-auto overflow-x-hidden scrollbar-thin gap-2 p-2 {currentStep === 'create' ? '' : 'hidden'}">
|
|
3005
3121
|
<slot name="code-generation" />
|
|
3006
3122
|
<slot name="publish-widget" />
|
|
3007
3123
|
</div>
|
|
3008
|
-
<div class="widget-details-edit-step flex flex-col h-full min-h-0 overflow-hidden {currentStep === 'edit' ? '' : 'hidden'}">
|
|
3124
|
+
<div class="widget-details-edit-step flex flex-col h-full min-h-0 overflow-y-auto overflow-x-hidden scrollbar-thin {currentStep === 'edit' ? '' : 'hidden'}">
|
|
3009
3125
|
<slot name="composition-editor" />
|
|
3010
3126
|
</div>
|
|
3011
3127
|
<div class="widget-details-embed-step flex flex-col gap-2 p-2 {currentStep === 'embed' ? '' : 'hidden'}">
|
|
@@ -3139,6 +3255,7 @@
|
|
|
3139
3255
|
{#if isGeneratingCode || previewLoading}
|
|
3140
3256
|
<GenerateLoader
|
|
3141
3257
|
title={isGeneratingCode ? 'Generating code…' : 'Building preview…'}
|
|
3258
|
+
subtitle=""
|
|
3142
3259
|
size="md"
|
|
3143
3260
|
/>
|
|
3144
3261
|
{:else if previewError === 'DRAFT_PANEL'}
|
|
@@ -3190,6 +3307,17 @@
|
|
|
3190
3307
|
</div>
|
|
3191
3308
|
{/if}
|
|
3192
3309
|
</div>
|
|
3310
|
+
{:else if lastGenerationFailed}
|
|
3311
|
+
<div class="widget-preview-generation-error flex flex-col items-center justify-center text-center p-4">
|
|
3312
|
+
<div class="text-3xl mb-2">⚠️</div>
|
|
3313
|
+
<div class="font-medium text-sm text-red-600 mb-1">Code generation failed</div>
|
|
3314
|
+
<div class="text-xs max-w-[220px] text-gray-600 mb-3">{lastGenerationError || 'Fix the prompt or attachments, then retry.'}</div>
|
|
3315
|
+
<button
|
|
3316
|
+
type="button"
|
|
3317
|
+
onclick={() => { dispatch('generateNow', { widgetId: selectedWidgetId }); }}
|
|
3318
|
+
class="generate-now-btn px-3 py-1.5 text-xs rounded border border-green-500 text-green-700 bg-white hover:bg-green-50 cursor-pointer font-medium"
|
|
3319
|
+
>▶ Retry</button>
|
|
3320
|
+
</div>
|
|
3193
3321
|
{:else if isLoadingDirectPreviewUrl || previewLoading}
|
|
3194
3322
|
<GenerateLoader title="Building Preview…" subtitle="Compiling widget code…" size="md" />
|
|
3195
3323
|
{:else}
|
|
@@ -3252,7 +3380,7 @@
|
|
|
3252
3380
|
</div> <!-- end of widget-details-content-wrapper -->
|
|
3253
3381
|
|
|
3254
3382
|
<!-- svelte-ignore a11y-no-static-element-interactions -->
|
|
3255
|
-
<div class="absolute bottom-0 right-0 w-4 h-4 cursor-nwse-resize z-
|
|
3383
|
+
<div class="widget-details-resize-se absolute bottom-0 right-0 w-4 h-4 cursor-nwse-resize z-20 group" onmousedown={(e) => startDetailsResize(e, 'se')} title="Resize panel">
|
|
3256
3384
|
<svg class="w-3 h-3 absolute bottom-0.5 right-0.5 text-gray-400 group-hover:text-gray-600 transition-colors" viewBox="0 0 6 6" fill="currentColor">
|
|
3257
3385
|
<circle cx="5" cy="1" r="0.7"/>
|
|
3258
3386
|
<circle cx="3" cy="3" r="0.7"/>
|
|
@@ -3262,6 +3390,25 @@
|
|
|
3262
3390
|
<circle cx="5" cy="5" r="0.7"/>
|
|
3263
3391
|
</svg>
|
|
3264
3392
|
</div>
|
|
3393
|
+
{#if !fillViewport}
|
|
3394
|
+
<!-- svelte-ignore a11y-no-static-element-interactions -->
|
|
3395
|
+
<div class="widget-details-resize-sw absolute bottom-0 left-0 w-4 h-4 cursor-nesw-resize z-20 group" onmousedown={(e) => startDetailsResize(e, 'sw')} title="Resize panel">
|
|
3396
|
+
<svg class="w-3 h-3 absolute bottom-0.5 left-0.5 text-gray-400 group-hover:text-gray-600 transition-colors rotate-90" viewBox="0 0 6 6" fill="currentColor">
|
|
3397
|
+
<circle cx="5" cy="1" r="0.7"/>
|
|
3398
|
+
<circle cx="3" cy="3" r="0.7"/>
|
|
3399
|
+
<circle cx="5" cy="3" r="0.7"/>
|
|
3400
|
+
<circle cx="1" cy="5" r="0.7"/>
|
|
3401
|
+
<circle cx="3" cy="5" r="0.7"/>
|
|
3402
|
+
<circle cx="5" cy="5" r="0.7"/>
|
|
3403
|
+
</svg>
|
|
3404
|
+
</div>
|
|
3405
|
+
<!-- svelte-ignore a11y-no-static-element-interactions -->
|
|
3406
|
+
<div class="widget-details-resize-e absolute top-8 bottom-4 right-0 w-1.5 cursor-ew-resize z-20 hover:bg-blue-400/30" onmousedown={(e) => startDetailsResize(e, 'e')} title="Resize width"></div>
|
|
3407
|
+
<!-- svelte-ignore a11y-no-static-element-interactions -->
|
|
3408
|
+
<div class="widget-details-resize-w absolute top-8 bottom-4 left-0 w-1.5 cursor-ew-resize z-20 hover:bg-blue-400/30" onmousedown={(e) => startDetailsResize(e, 'w')} title="Resize width"></div>
|
|
3409
|
+
<!-- svelte-ignore a11y-no-static-element-interactions -->
|
|
3410
|
+
<div class="widget-details-resize-s absolute bottom-0 left-4 right-4 h-1.5 cursor-ns-resize z-20 hover:bg-blue-400/30" onmousedown={(e) => startDetailsResize(e, 's')} title="Resize height"></div>
|
|
3411
|
+
{/if}
|
|
3265
3412
|
</div>
|
|
3266
3413
|
{/if}
|
|
3267
3414
|
|
package/dist/creator-types.d.ts
CHANGED
|
@@ -32,6 +32,12 @@ export interface CreatorAppProps {
|
|
|
32
32
|
* Omit for standalone widget-creator (falls back to VITE_DEBUG_MODE / dev).
|
|
33
33
|
*/
|
|
34
34
|
initialDebugMode?: boolean;
|
|
35
|
+
/**
|
|
36
|
+
* Extra canvas tools (undo/frame/image/library, zoom 1:1/fit/shortcuts).
|
|
37
|
+
* Independent of debugMode — Debug is staging-only UI.
|
|
38
|
+
* Site owns the header toggle; embed uses CustomEvent after mount.
|
|
39
|
+
*/
|
|
40
|
+
initialAdvancedFeatures?: boolean;
|
|
35
41
|
/**
|
|
36
42
|
* Host-controlled default coder model id (e.g. `deepseek-v4-flash`).
|
|
37
43
|
* Site reads its own env and passes this — no creator-app.js rebuild, no API-gateway default for the UI.
|