@widgetic/creator 0.3.68 → 0.3.69
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
CHANGED
|
@@ -5672,6 +5672,52 @@
|
|
|
5672
5672
|
}
|
|
5673
5673
|
|
|
5674
5674
|
// ─── Create new canvas ───────────────────────────────────────────────────────
|
|
5675
|
+
/** New-widget opens on a local canvas. The DB row is created on the first real edit. */
|
|
5676
|
+
let canvasRowDeferred = false;
|
|
5677
|
+
let canvasRowCreatePromise: Promise<string | null> | null = null;
|
|
5678
|
+
|
|
5679
|
+
async function ensureCanvasRowForFirstEdit(): Promise<string | null> {
|
|
5680
|
+
const existingId = typeof canvasId === 'string' ? canvasId.trim() : '';
|
|
5681
|
+
if (existingId) return existingId;
|
|
5682
|
+
if (canvasRowCreatePromise) return canvasRowCreatePromise;
|
|
5683
|
+
canvasRowCreatePromise = (async () => {
|
|
5684
|
+
if (!canvasesClient || !$userSession.user) {
|
|
5685
|
+
console.warn('[CreatorApp] First edit not persisted — canvas client is not ready');
|
|
5686
|
+
return null;
|
|
5687
|
+
}
|
|
5688
|
+
try {
|
|
5689
|
+
const usedNames = new Set(userCanvases.map((c) => (c.name || '').trim()).filter(Boolean));
|
|
5690
|
+
let canvasIndex = userCanvases.length + 1;
|
|
5691
|
+
let newName = `Canvas ${canvasIndex}`;
|
|
5692
|
+
while (usedNames.has(newName)) {
|
|
5693
|
+
canvasIndex += 1;
|
|
5694
|
+
newName = `Canvas ${canvasIndex}`;
|
|
5695
|
+
}
|
|
5696
|
+
const createdRaw = await canvasesClient.createCanvas({
|
|
5697
|
+
createCanvasRequest: { persistenceKey: newName }
|
|
5698
|
+
});
|
|
5699
|
+
const createdId = unwrapCreatedCanvasId(createdRaw);
|
|
5700
|
+
if (!createdId) {
|
|
5701
|
+
console.warn('[CreatorApp] First-edit canvas create response missing id');
|
|
5702
|
+
return null;
|
|
5703
|
+
}
|
|
5704
|
+
userCanvases = [{ id: createdId, name: newName, hasContent: true }, ...userCanvases];
|
|
5705
|
+
rememberCanvasId(createdId);
|
|
5706
|
+
activeCanvasName = newName;
|
|
5707
|
+
canvasRowDeferred = false;
|
|
5708
|
+
syncEmbeddedCanvasUrl(createdId);
|
|
5709
|
+
console.log('[CreatorApp] Canvas row created on first edit', createdId);
|
|
5710
|
+
return createdId;
|
|
5711
|
+
} catch (err) {
|
|
5712
|
+
console.error('[CreatorApp] Failed to create canvas on first edit:', err);
|
|
5713
|
+
return null;
|
|
5714
|
+
} finally {
|
|
5715
|
+
canvasRowCreatePromise = null;
|
|
5716
|
+
}
|
|
5717
|
+
})();
|
|
5718
|
+
return canvasRowCreatePromise;
|
|
5719
|
+
}
|
|
5720
|
+
|
|
5675
5721
|
async function createNewCanvas(options: { skipSaveCurrent?: boolean } = {}): Promise<string | null> {
|
|
5676
5722
|
if (!canvasesClient || !$userSession.user) {
|
|
5677
5723
|
console.warn('[WidgetCreator] createNewCanvas skipped — missing client or user');
|
|
@@ -5776,24 +5822,10 @@
|
|
|
5776
5822
|
selectedWidgetId = null;
|
|
5777
5823
|
selectedWidget = null;
|
|
5778
5824
|
beginBlankCanvasSession('site New widget');
|
|
5779
|
-
|
|
5780
|
-
|
|
5781
|
-
|
|
5782
|
-
|
|
5783
|
-
} else {
|
|
5784
|
-
const newCanvasId = await createNewCanvas({ skipSaveCurrent: true });
|
|
5785
|
-
if (!newCanvasId) {
|
|
5786
|
-
showToast('error', 'Could not create a blank canvas', {
|
|
5787
|
-
description: 'Try reloading the page to get a fresh canvas.',
|
|
5788
|
-
duration: 8000
|
|
5789
|
-
});
|
|
5790
|
-
} else {
|
|
5791
|
-
// Replace `new_widget=1` with the concrete canvas_id so a page refresh
|
|
5792
|
-
// reloads THIS canvas (and its sketch) instead of re-running the
|
|
5793
|
-
// new-widget bootstrap and creating yet another blank canvas row.
|
|
5794
|
-
syncEmbeddedCanvasUrl(newCanvasId);
|
|
5795
|
-
}
|
|
5796
|
-
}
|
|
5825
|
+
rememberCanvasId(null);
|
|
5826
|
+
canvasRowDeferred = true;
|
|
5827
|
+
// No DB row yet. Autosave creates one on the first edit that has shapes.
|
|
5828
|
+
// An untouched new-widget refresh stays on new_widget=1 and writes nothing.
|
|
5797
5829
|
// F3: New-widget flow starts with an EMPTY canvas — no widget record, no
|
|
5798
5830
|
// WidgetShape, no auto-opened Widget Details. The widget record is created
|
|
5799
5831
|
// only when the user sketches something and clicks "Convert to Widget".
|
|
@@ -7229,6 +7261,7 @@
|
|
|
7229
7261
|
typeof crypto !== 'undefined' && crypto.randomUUID
|
|
7230
7262
|
? crypto.randomUUID()
|
|
7231
7263
|
: `${Date.now()}-new-widget`;
|
|
7264
|
+
if (!canvasId) await ensureCanvasRowForFirstEdit();
|
|
7232
7265
|
const response = await widgetsClient.createWidget(
|
|
7233
7266
|
{
|
|
7234
7267
|
newWidget: {
|
|
@@ -13923,6 +13956,13 @@ $: if (codeGenerationPrompt && selectedWidgetId && promptLoadedForWidgetId === s
|
|
|
13923
13956
|
});
|
|
13924
13957
|
}
|
|
13925
13958
|
|
|
13959
|
+
// A new-widget session has no row until the user actually adds something.
|
|
13960
|
+
// Empty autosaves (open, refresh, unmount of a blank canvas) stay local.
|
|
13961
|
+
if (canvasRowDeferred && !canvasId && objectCount > 0) {
|
|
13962
|
+
await ensureCanvasRowForFirstEdit();
|
|
13963
|
+
if (canvasId) saveCanvasState(canvasId, json);
|
|
13964
|
+
}
|
|
13965
|
+
|
|
13926
13966
|
// Save to API via SDK with sequence race protection
|
|
13927
13967
|
if (canvasId && canvasesClient) {
|
|
13928
13968
|
const currentSeq = ++autosaveSequence;
|
|
@@ -14123,6 +14163,7 @@ $: if (codeGenerationPrompt && selectedWidgetId && promptLoadedForWidgetId === s
|
|
|
14123
14163
|
?? `ConvertedW-${Date.now()}`;
|
|
14124
14164
|
|
|
14125
14165
|
authStatus = 'Creating widget from design...';
|
|
14166
|
+
if (!canvasId) await ensureCanvasRowForFirstEdit();
|
|
14126
14167
|
const idempotencyKey = crypto?.randomUUID?.() ?? `${Date.now()}-convert`;
|
|
14127
14168
|
const response = await widgetsClient.createWidget(
|
|
14128
14169
|
{
|
|
@@ -146,20 +146,6 @@
|
|
|
146
146
|
const VERSION_MENU_PAD_REM = 0.6;
|
|
147
147
|
/** Menu shows at most 5 rows before scrolling. */
|
|
148
148
|
const VERSION_MENU_MAX_ROWS = 5;
|
|
149
|
-
/** Fabric corner handles sit on the shape corners and must stay clickable through the bar. */
|
|
150
|
-
const HANDLE_NOTCH_PX = 14;
|
|
151
|
-
|
|
152
|
-
function headerNotchClip(barWidth: number, shapeWidth: number): string {
|
|
153
|
-
const notch = HANDLE_NOTCH_PX;
|
|
154
|
-
const height = DRAG_BAR_H;
|
|
155
|
-
const y = height - notch;
|
|
156
|
-
const shapeRight = Math.min(barWidth, Math.max(shapeWidth, notch * 2));
|
|
157
|
-
if (shapeRight >= barWidth - 1) {
|
|
158
|
-
return `polygon(0px 0px, ${barWidth}px 0px, ${barWidth}px ${y}px, ${barWidth - notch}px ${y}px, ${barWidth - notch}px ${height}px, ${notch}px ${height}px, ${notch}px ${y}px, 0px ${y}px)`;
|
|
159
|
-
}
|
|
160
|
-
const rightInner = Math.max(notch + 1, shapeRight - notch);
|
|
161
|
-
return `polygon(0px 0px, ${barWidth}px 0px, ${barWidth}px ${height}px, ${shapeRight}px ${height}px, ${shapeRight}px ${y}px, ${rightInner}px ${y}px, ${rightInner}px ${height}px, ${notch}px ${height}px, ${notch}px ${y}px, 0px ${y}px)`;
|
|
162
|
-
}
|
|
163
149
|
|
|
164
150
|
type ShapeRect = {
|
|
165
151
|
widgetId: string;
|
|
@@ -701,14 +687,14 @@
|
|
|
701
687
|
<div
|
|
702
688
|
class="widget-shape-drag-bar pointer-events-auto absolute left-0 right-0 top-0 z-10 flex items-center gap-1 rounded-t-md border border-b-0 px-1.5 shadow-sm select-none [&_button:focus]:outline-none [&_button:focus]:shadow-none [&_button:focus-visible]:outline-none [&_button:focus-visible]:shadow-none
|
|
703
689
|
{isPrimary ? 'bg-red-100' : 'bg-white'} {isSelected ? 'border-blue-400' : 'border-gray-300'}"
|
|
704
|
-
style="height: {DRAG_BAR_H}px; cursor: grab; min-width: {showExpandedChrome ? MIN_EXPANDED_CHROME_WIDTH : 0}px;
|
|
690
|
+
style="height: {DRAG_BAR_H}px; cursor: grab; min-width: {showExpandedChrome ? MIN_EXPANDED_CHROME_WIDTH : 0}px;"
|
|
705
691
|
title="Drag widget"
|
|
706
692
|
onpointerdown={(e) => startShapeDrag(e, overlay.widgetId)}
|
|
707
693
|
>
|
|
708
694
|
{#if isPrimary}
|
|
709
695
|
<div
|
|
710
696
|
class="widget-shape-primary-stroke pointer-events-none absolute z-20 bg-[#DC2626]"
|
|
711
|
-
style="left: 0; width: {overlay.width}px; top: {DRAG_BAR_H - IFRAME_INSET_PX - 1}px; height: 2px;
|
|
697
|
+
style="left: 0; width: {overlay.width}px; top: {DRAG_BAR_H - IFRAME_INSET_PX - 1}px; height: 2px;"
|
|
712
698
|
></div>
|
|
713
699
|
{/if}
|
|
714
700
|
<span class="widget-shape-drag-grip shrink-0 text-xs leading-none text-gray-400" aria-hidden="true">⠿</span>
|