dynim-core 1.0.9 → 1.0.11

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.
@@ -32,6 +32,10 @@ export interface Builder {
32
32
  enter: () => void;
33
33
  exit: () => void;
34
34
  isActive: () => boolean;
35
+ isPreviewMode: () => boolean;
36
+ togglePreview: () => void;
37
+ enterPreviewMode: () => void;
38
+ exitPreviewMode: () => void;
35
39
  getEditorState: () => unknown;
36
40
  getTreeState: () => unknown;
37
41
  destroy: () => void;
@@ -1 +1 @@
1
- {"version":3,"file":"builder.d.ts","sourceRoot":"","sources":["../../src/builder/builder.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAA6B,KAAK,YAAY,EAAE,MAAM,UAAU,CAAC;AAQxE,OAAO,EAAoB,KAAK,UAAU,EAAE,MAAM,eAAe,CAAC;AAIlE,MAAM,WAAW,aAAa;IAC5B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,8DAA8D;IAC9D,WAAW,CAAC,EAAE,MAAM,IAAI,CAAC;IACzB,UAAU,CAAC,EAAE,YAAY,CAAC;IAC1B,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,uCAAuC;IACvC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,wCAAwC;IACxC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,qCAAqC;IACrC,UAAU,CAAC,EAAE,MAAM,OAAO,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,YAAY,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACrE,+FAA+F;IAC/F,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,mEAAmE;IACnE,UAAU,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACnD;AAED,MAAM,WAAW,OAAO;IACtB,KAAK,EAAE,MAAM,IAAI,CAAC;IAClB,IAAI,EAAE,MAAM,IAAI,CAAC;IACjB,QAAQ,EAAE,MAAM,OAAO,CAAC;IACxB,cAAc,EAAE,MAAM,OAAO,CAAC;IAC9B,YAAY,EAAE,MAAM,OAAO,CAAC;IAC5B,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB;AAED,wBAAgB,aAAa,CAAC,MAAM,GAAE,aAAkB,GAAG,OAAO,CAyejE;;;;AAMD,wBAAyC"}
1
+ {"version":3,"file":"builder.d.ts","sourceRoot":"","sources":["../../src/builder/builder.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAA6B,KAAK,YAAY,EAAE,MAAM,UAAU,CAAC;AAQxE,OAAO,EAAoB,KAAK,UAAU,EAAE,MAAM,eAAe,CAAC;AAIlE,MAAM,WAAW,aAAa;IAC5B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,8DAA8D;IAC9D,WAAW,CAAC,EAAE,MAAM,IAAI,CAAC;IACzB,UAAU,CAAC,EAAE,YAAY,CAAC;IAC1B,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,uCAAuC;IACvC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,wCAAwC;IACxC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,qCAAqC;IACrC,UAAU,CAAC,EAAE,MAAM,OAAO,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,YAAY,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACrE,+FAA+F;IAC/F,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,mEAAmE;IACnE,UAAU,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACnD;AAED,MAAM,WAAW,OAAO;IACtB,KAAK,EAAE,MAAM,IAAI,CAAC;IAClB,IAAI,EAAE,MAAM,IAAI,CAAC;IACjB,QAAQ,EAAE,MAAM,OAAO,CAAC;IACxB,aAAa,EAAE,MAAM,OAAO,CAAC;IAC7B,aAAa,EAAE,MAAM,IAAI,CAAC;IAC1B,gBAAgB,EAAE,MAAM,IAAI,CAAC;IAC7B,eAAe,EAAE,MAAM,IAAI,CAAC;IAC5B,cAAc,EAAE,MAAM,OAAO,CAAC;IAC9B,YAAY,EAAE,MAAM,OAAO,CAAC;IAC5B,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB;AAED,wBAAgB,aAAa,CAAC,MAAM,GAAE,aAAkB,GAAG,OAAO,CA0kBjE;;;;AAMD,wBAAyC"}
@@ -17,6 +17,7 @@ import { buildElementIdentifier, getRelevantStyles } from './element-utils';
17
17
  export function createBuilder(config = {}) {
18
18
  const { logo = 'Builder', onExit, onEnter, onExitStart, chatConfig = {}, contentRoot = document.body, pageId = window.location.pathname, apiBase = 'http://localhost:8080', sessionToken, refreshToken, getSession, codeClient: externalCodeClient, loadBundle } = config;
19
19
  let isActive = false;
20
+ let isPreviewMode = false;
20
21
  let chatWidget = null;
21
22
  let state = null;
22
23
  let client = null;
@@ -37,6 +38,12 @@ export function createBuilder(config = {}) {
37
38
  <span>${logo}</span>
38
39
  </div>
39
40
  <div class="builder-bar__divider"></div>
41
+ <span class="builder-bar__preview-badge" style="display: none;">
42
+ <svg viewBox="0 0 24 24" width="14" height="14" fill="currentColor">
43
+ <path d="M12 4.5C7 4.5 2.73 7.61 1 12c1.73 4.39 6 7.5 11 7.5s9.27-3.11 11-7.5c-1.73-4.39-6-7.5-11-7.5zM12 17c-2.76 0-5-2.24-5-5s2.24-5 5-5 5 2.24 5 5-2.24 5-5 5zm0-8c-1.66 0-3 1.34-3 3s1.34 3 3 3 3-1.34 3-3-1.34-3-3-3z"/>
44
+ </svg>
45
+ PREVIEWING
46
+ </span>
40
47
  <div class="builder-bar__actions">
41
48
  <button class="builder-bar__btn builder-bar__btn--preview">
42
49
  <svg viewBox="0 0 24 24" width="14" height="14" fill="currentColor">
@@ -318,6 +325,11 @@ export function createBuilder(config = {}) {
318
325
  async function exit() {
319
326
  if (!isActive)
320
327
  return;
328
+ // Exit preview mode first if active
329
+ if (isPreviewMode) {
330
+ isPreviewMode = false;
331
+ updateBarForPreviewMode(false);
332
+ }
321
333
  isActive = false;
322
334
  // Notify IMMEDIATELY before any async work
323
335
  // This allows BuilderProvider to set isExitingRef before streaming events can interfere
@@ -404,6 +416,71 @@ export function createBuilder(config = {}) {
404
416
  console.error('[Builder] Save failed:', error);
405
417
  }
406
418
  }
419
+ function updateBarForPreviewMode(isPreviewing) {
420
+ const previewBtn = root.querySelector('.builder-bar__btn--preview');
421
+ const previewBadge = root.querySelector('.builder-bar__preview-badge');
422
+ if (previewBtn) {
423
+ // Update button text while preserving the icon
424
+ const textNode = Array.from(previewBtn.childNodes).find(node => node.nodeType === Node.TEXT_NODE);
425
+ if (textNode) {
426
+ textNode.textContent = isPreviewing ? 'Edit' : 'Preview';
427
+ }
428
+ else {
429
+ // Fallback: append text if no text node found
430
+ previewBtn.appendChild(document.createTextNode(isPreviewing ? 'Edit' : 'Preview'));
431
+ }
432
+ }
433
+ if (previewBadge) {
434
+ previewBadge.style.display = isPreviewing ? 'flex' : 'none';
435
+ }
436
+ // Add/remove preview mode class for styling
437
+ root.classList.toggle('builder-bar--preview-mode', isPreviewing);
438
+ }
439
+ function enterPreviewMode() {
440
+ if (!isActive || isPreviewMode)
441
+ return;
442
+ isPreviewMode = true;
443
+ console.log('[Builder] Entering preview mode');
444
+ // Hide editing UI
445
+ freezeOverlay?.unmount();
446
+ overlays?.hideAll();
447
+ interactionEngine?.detach();
448
+ aiPromptPopover?.unmount();
449
+ // Hide chat
450
+ chatWidget?.close();
451
+ if (chatWidget?.root) {
452
+ chatWidget.root.style.display = 'none';
453
+ }
454
+ // Clear any selection
455
+ editorState?.clearSelection();
456
+ // Update bar UI
457
+ updateBarForPreviewMode(true);
458
+ }
459
+ function exitPreviewMode() {
460
+ if (!isActive || !isPreviewMode)
461
+ return;
462
+ isPreviewMode = false;
463
+ console.log('[Builder] Exiting preview mode');
464
+ // Restore editing UI
465
+ freezeOverlay?.mount();
466
+ overlays?.mount();
467
+ interactionEngine?.attach();
468
+ aiPromptPopover?.mount();
469
+ // Show chat
470
+ if (chatWidget?.root) {
471
+ chatWidget.root.style.display = '';
472
+ }
473
+ // Update bar UI
474
+ updateBarForPreviewMode(false);
475
+ }
476
+ function togglePreview() {
477
+ if (isPreviewMode) {
478
+ exitPreviewMode();
479
+ }
480
+ else {
481
+ enterPreviewMode();
482
+ }
483
+ }
407
484
  root.addEventListener('click', (e) => {
408
485
  const target = e.target;
409
486
  if (target.closest('.builder-bar__btn--exit')) {
@@ -413,7 +490,7 @@ export function createBuilder(config = {}) {
413
490
  }
414
491
  if (target.closest('.builder-bar__btn--preview')) {
415
492
  e.stopPropagation();
416
- handlePreview();
493
+ togglePreview();
417
494
  return;
418
495
  }
419
496
  if (target.closest('.builder-bar__btn--save')) {
@@ -435,6 +512,10 @@ export function createBuilder(config = {}) {
435
512
  enter,
436
513
  exit,
437
514
  isActive: () => isActive,
515
+ isPreviewMode: () => isPreviewMode,
516
+ togglePreview,
517
+ enterPreviewMode,
518
+ exitPreviewMode,
438
519
  getEditorState: () => editorState?.getState(),
439
520
  getTreeState: () => treeState?.getState(),
440
521
  destroy: () => {
@@ -88,6 +88,8 @@ export interface CodeClient {
88
88
  getEdits: () => Promise<CodeEdit[]>;
89
89
  /** Pre-warm the file cache for faster code requests - projectId comes from JWT */
90
90
  warmCache: () => Promise<void>;
91
+ /** Abort any active streaming request */
92
+ abort: () => void;
91
93
  /** Set/update the session token */
92
94
  setSessionToken: (token: string, refreshToken?: string) => void;
93
95
  /** Check if authenticated */
@@ -1 +1 @@
1
- {"version":3,"file":"code-client.d.ts","sourceRoot":"","sources":["../../src/builder/code-client.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"code-client.d.ts","sourceRoot":"","sources":["../../src/builder/code-client.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAIH,MAAM,WAAW,gBAAgB;IAC/B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,2CAA2C;IAC3C,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,mDAAmD;IACnD,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,+DAA+D;IAC/D,UAAU,CAAC,EAAE,MAAM,OAAO,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,YAAY,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACrE,+DAA+D;IAC/D,eAAe,CAAC,EAAE,CAAC,OAAO,EAAE,WAAW,KAAK,IAAI,CAAC;IACjD,iEAAiE;IACjE,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE,SAAS,KAAK,IAAI,CAAC;IACxC,8CAA8C;IAC9C,SAAS,CAAC,EAAE,CAAC,KAAK,EAAE,SAAS,KAAK,IAAI,CAAC;IACvC,sCAAsC;IACtC,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,QAAQ,KAAK,IAAI,CAAC;IAClC,uBAAuB;IACvB,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;IACjC,mCAAmC;IACnC,aAAa,CAAC,EAAE,MAAM,IAAI,CAAC;IAC3B,iCAAiC;IACjC,WAAW,CAAC,EAAE,MAAM,IAAI,CAAC;IACzB,uCAAuC;IACvC,gBAAgB,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAC3C,uCAAuC;IACvC,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;CACtC;AAED,qEAAqE;AACrE,MAAM,WAAW,WAAW;IAC1B,6CAA6C;IAC7C,QAAQ,EAAE,MAAM,CAAC;IACjB,gCAAgC;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,0BAA0B;IAC1B,KAAK,EAAE,QAAQ,EAAE,CAAC;IAClB,qBAAqB;IACrB,MAAM,EAAE,MAAM,GAAG,WAAW,GAAG,SAAS,GAAG,MAAM,GAAG,OAAO,CAAC;IAC5D,yCAAyC;IACzC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,yCAAyC;IACzC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,iBAAiB;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,8CAA8C;IAC9C,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,8DAA8D;IAC9D,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,sCAAsC;IACtC,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,GAAG,UAAU,GAAG,MAAM,GAAG,UAAU,GAAG,MAAM,GAAG,OAAO,GAAG,iBAAiB,GAAG,WAAW,GAAG,cAAc,GAAG,cAAc,CAAC;IACvI,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,QAAQ,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,QAAQ;IACvB,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,QAAQ,GAAG,SAAS,GAAG,QAAQ,CAAC;IACtC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,UAAU;IACzB,kFAAkF;IAClF,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3C,0EAA0E;IAC1E,QAAQ,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9B,8EAA8E;IAC9E,WAAW,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IACjC,2DAA2D;IAC3D,QAAQ,EAAE,MAAM,OAAO,CAAC,QAAQ,EAAE,CAAC,CAAC;IACpC,kFAAkF;IAClF,SAAS,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/B,yCAAyC;IACzC,KAAK,EAAE,MAAM,IAAI,CAAC;IAClB,mCAAmC;IACnC,eAAe,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,YAAY,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IAChE,6BAA6B;IAC7B,eAAe,EAAE,MAAM,OAAO,CAAC;IAC/B,gCAAgC;IAChC,UAAU,EAAE,MAAM,WAAW,CAAC;IAC9B,0BAA0B;IAC1B,YAAY,EAAE,MAAM,IAAI,CAAC;IACzB,kEAAkE;IAClE,SAAS,EAAE,CAAC,QAAQ,EAAE,CAAC,OAAO,EAAE,WAAW,KAAK,IAAI,KAAK,MAAM,IAAI,CAAC;CACrE;AAcD,wBAAgB,gBAAgB,CAAC,MAAM,GAAE,gBAAqB,GAAG,UAAU,CA6f1E"}
@@ -36,6 +36,8 @@ export function createCodeClient(config = {}) {
36
36
  let needsTextBreak = false;
37
37
  // Additional message listeners (for sharing client between components)
38
38
  const messageListeners = new Set();
39
+ // AbortController for canceling active streams
40
+ let currentAbortController = null;
39
41
  /** Notify all listeners of message update */
40
42
  function notifyListeners() {
41
43
  onMessageUpdate?.(currentMessage);
@@ -164,6 +166,11 @@ export function createCodeClient(config = {}) {
164
166
  onAuthError?.(new Error('Not authenticated'));
165
167
  return;
166
168
  }
169
+ // Abort any existing stream before starting a new one
170
+ if (currentAbortController) {
171
+ currentAbortController.abort();
172
+ }
173
+ currentAbortController = new AbortController();
167
174
  // Reset message state for new request
168
175
  currentMessage = createEmptyMessage();
169
176
  needsTextBreak = false;
@@ -183,7 +190,8 @@ export function createCodeClient(config = {}) {
183
190
  'Content-Type': 'application/json',
184
191
  'Accept': 'text/event-stream'
185
192
  },
186
- body
193
+ body,
194
+ signal: currentAbortController.signal
187
195
  });
188
196
  if (!response.ok) {
189
197
  if (response.status === 401 || response.status === 403) {
@@ -285,10 +293,29 @@ export function createCodeClient(config = {}) {
285
293
  }
286
294
  }
287
295
  catch (error) {
296
+ // Don't log abort errors as they're intentional
297
+ if (error.name === 'AbortError') {
298
+ console.log('[CodeClient] Stream aborted');
299
+ return;
300
+ }
288
301
  console.error('[CodeClient] Code request error:', error);
289
302
  updateMessage({ status: 'error', error: error.message });
290
303
  onError?.(error);
291
304
  }
305
+ finally {
306
+ currentAbortController = null;
307
+ }
308
+ }
309
+ /**
310
+ * Abort any active streaming request
311
+ * Used when exiting builder to prevent race conditions
312
+ */
313
+ function abort() {
314
+ if (currentAbortController) {
315
+ console.log('[CodeClient] Aborting active stream');
316
+ currentAbortController.abort();
317
+ currentAbortController = null;
318
+ }
292
319
  }
293
320
  /**
294
321
  * Save pending edits (commit temp changes)
@@ -413,6 +440,7 @@ export function createCodeClient(config = {}) {
413
440
  abandonCode,
414
441
  getEdits,
415
442
  warmCache,
443
+ abort,
416
444
  setSessionToken,
417
445
  isAuthenticated: () => !!currentSessionToken,
418
446
  getMessage: () => currentMessage,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dynim-core",
3
- "version": "1.0.9",
3
+ "version": "1.0.11",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",
@@ -70,6 +70,32 @@
70
70
  margin: 0 4px;
71
71
  }
72
72
 
73
+ /* Preview badge */
74
+ .builder-bar__preview-badge {
75
+ display: flex;
76
+ align-items: center;
77
+ gap: 6px;
78
+ padding: 4px 12px;
79
+ background: #3b82f6;
80
+ color: white;
81
+ border-radius: 4px;
82
+ font-size: 12px;
83
+ font-weight: 600;
84
+ text-transform: uppercase;
85
+ letter-spacing: 0.5px;
86
+ }
87
+
88
+ .builder-bar__preview-badge svg {
89
+ width: 14px;
90
+ height: 14px;
91
+ }
92
+
93
+ /* Preview mode bar styling */
94
+ .builder-bar--preview-mode .builder-bar {
95
+ background: linear-gradient(to right, rgba(30, 41, 59, 0.95), rgba(15, 23, 42, 0.95));
96
+ border-bottom: 2px solid #3b82f6;
97
+ }
98
+
73
99
  /* Actions section */
74
100
  .builder-bar__actions {
75
101
  display: flex;