@1agh/maude 0.27.0 → 0.28.1
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/cli/commands/design-link.test.mjs +46 -0
- package/cli/commands/design.mjs +69 -3
- package/cli/commands/design.test.mjs +97 -1
- package/cli/commands/doctor.mjs +110 -5
- package/cli/commands/doctor.test.mjs +52 -0
- package/cli/lib/cache.mjs +1 -1
- package/cli/lib/config-lint.mjs +1 -1
- package/cli/lib/copy-tree.mjs +1 -1
- package/cli/lib/design-link.mjs +39 -9
- package/cli/lib/flow-design-integration.test.mjs +1 -1
- package/cli/lib/gitignore-block.test.mjs +2 -2
- package/cli/lib/stack-detect.mjs +1 -1
- package/package.json +9 -9
- package/plugins/design/dev-server/activity.ts +256 -0
- package/plugins/design/dev-server/ai-banner.tsx +4 -0
- package/plugins/design/dev-server/annotations-context-toolbar.tsx +1 -1
- package/plugins/design/dev-server/annotations-layer.tsx +3 -3
- package/plugins/design/dev-server/api.ts +1 -1
- package/plugins/design/dev-server/artboard-activity-overlay.tsx +67 -0
- package/plugins/design/dev-server/bin/scenario-report.mjs +1 -1
- package/plugins/design/dev-server/bin/server-up.sh +102 -9
- package/plugins/design/dev-server/bin/visual-sanity.sh +19 -3
- package/plugins/design/dev-server/canvas-comment-mount.tsx +165 -10
- package/plugins/design/dev-server/canvas-cursors.ts +1 -1
- package/plugins/design/dev-server/canvas-lib.tsx +72 -36
- package/plugins/design/dev-server/canvas-shell.tsx +1 -1
- package/plugins/design/dev-server/collab/awareness-bridge.ts +1 -1
- package/plugins/design/dev-server/collab/index.ts +4 -4
- package/plugins/design/dev-server/collab/persistence.ts +1 -1
- package/plugins/design/dev-server/config.schema.json +2 -1
- package/plugins/design/dev-server/context-menu.tsx +1 -1
- package/plugins/design/dev-server/dist/client.bundle.js +19 -19
- package/plugins/design/dev-server/dist/comment-mount.js +84 -6
- package/plugins/design/dev-server/dist/runtime/lib0_decoding.js +1 -620
- package/plugins/design/dev-server/dist/runtime/lib0_encoding.js +1 -604
- package/plugins/design/dev-server/dist/runtime/motion.js +4 -4944
- package/plugins/design/dev-server/dist/runtime/motion_react.js +10 -10054
- package/plugins/design/dev-server/dist/runtime/pixi-js.js +2775 -52482
- package/plugins/design/dev-server/dist/runtime/react-dom.js +1 -231
- package/plugins/design/dev-server/dist/runtime/react-dom_client.js +9 -10357
- package/plugins/design/dev-server/dist/runtime/react.js +1 -535
- package/plugins/design/dev-server/dist/runtime/react_jsx-dev-runtime.js +1 -60
- package/plugins/design/dev-server/dist/runtime/react_jsx-runtime.js +1 -85
- package/plugins/design/dev-server/dist/runtime/y-protocols_awareness.js +1 -376
- package/plugins/design/dev-server/dist/runtime/y-protocols_sync.js +1 -100
- package/plugins/design/dev-server/dist/runtime/yjs.js +5 -6687
- package/plugins/design/dev-server/draw/brush.ts +3 -3
- package/plugins/design/dev-server/draw/index.ts +5 -5
- package/plugins/design/dev-server/draw/layout.ts +1 -1
- package/plugins/design/dev-server/draw/test/geometry.test.ts +1 -1
- package/plugins/design/dev-server/draw/test/layout.test.ts +1 -1
- package/plugins/design/dev-server/draw/test/primitives.test.ts +1 -1
- package/plugins/design/dev-server/draw/test/serialize.test.ts +1 -1
- package/plugins/design/dev-server/equal-spacing-handles.tsx +1 -1
- package/plugins/design/dev-server/examples/perf-100-artboards.tsx +1 -2
- package/plugins/design/dev-server/export-dialog.tsx +1 -1
- package/plugins/design/dev-server/exporters/html.ts +1 -1
- package/plugins/design/dev-server/exporters/index.ts +2 -2
- package/plugins/design/dev-server/exporters/pdf.ts +1 -1
- package/plugins/design/dev-server/exporters/png.ts +1 -1
- package/plugins/design/dev-server/exporters/pptx.ts +1 -1
- package/plugins/design/dev-server/exporters/svg.ts +1 -1
- package/plugins/design/dev-server/http.ts +1 -1
- package/plugins/design/dev-server/inspect.ts +31 -1
- package/plugins/design/dev-server/marquee-overlay.tsx +1 -1
- package/plugins/design/dev-server/participants-chrome.tsx +86 -1
- package/plugins/design/dev-server/server.ts +11 -2
- package/plugins/design/dev-server/sync/agent.ts +1 -1
- package/plugins/design/dev-server/sync/index.ts +29 -24
- package/plugins/design/dev-server/sync/materialize.ts +2 -2
- package/plugins/design/dev-server/sync/migrate-seed.ts +1 -1
- package/plugins/design/dev-server/sync/projection.ts +3 -3
- package/plugins/design/dev-server/test/activity.test.ts +195 -0
- package/plugins/design/dev-server/test/ai-activity.test.ts +1 -1
- package/plugins/design/dev-server/test/annotations-api.test.ts +1 -2
- package/plugins/design/dev-server/test/annotations-draw-modifiers.test.ts +2 -2
- package/plugins/design/dev-server/test/annotations-layer.test.ts +6 -6
- package/plugins/design/dev-server/test/annotations-roundtrip.test.ts +1 -1
- package/plugins/design/dev-server/test/artboard-activity-overlay.test.tsx +56 -0
- package/plugins/design/dev-server/test/boot-self-heal.test.ts +1 -1
- package/plugins/design/dev-server/test/canvas-cursors.test.ts +1 -1
- package/plugins/design/dev-server/test/canvas-edit.test.ts +1 -1
- package/plugins/design/dev-server/test/canvas-header.test.ts +1 -1
- package/plugins/design/dev-server/test/canvas-hmr-runtime.test.tsx +114 -0
- package/plugins/design/dev-server/test/canvas-lib-inline.test.ts +1 -1
- package/plugins/design/dev-server/test/canvas-lib-resolver.test.ts +1 -2
- package/plugins/design/dev-server/test/canvas-meta-api.test.ts +1 -2
- package/plugins/design/dev-server/test/canvas-origin-gate.test.ts +1 -2
- package/plugins/design/dev-server/test/collab-annotations-bridge.test.ts +1 -1
- package/plugins/design/dev-server/test/collab-bridge.test.ts +1 -1
- package/plugins/design/dev-server/test/collab-protocol.test.ts +2 -2
- package/plugins/design/dev-server/test/collab-room.test.ts +1 -1
- package/plugins/design/dev-server/test/collab-stress.test.ts +1 -1
- package/plugins/design/dev-server/test/comments-api.test.ts +1 -2
- package/plugins/design/dev-server/test/compile-entry.test.ts +1 -2
- package/plugins/design/dev-server/test/exporters/canva.test.ts +1 -2
- package/plugins/design/dev-server/test/exporters/history.test.ts +1 -2
- package/plugins/design/dev-server/test/exporters/pw-launch.test.ts +1 -1
- package/plugins/design/dev-server/test/exporters/scope.test.ts +1 -2
- package/plugins/design/dev-server/test/exporters/zip.test.ts +1 -2
- package/plugins/design/dev-server/test/git-lifecycle.test.ts +1 -2
- package/plugins/design/dev-server/test/handoff-static-frames.test.ts +1 -1
- package/plugins/design/dev-server/test/handoff.test.ts +1 -1
- package/plugins/design/dev-server/test/hmr-broadcast.test.ts +1 -1
- package/plugins/design/dev-server/test/input-router.test.ts +2 -2
- package/plugins/design/dev-server/test/locator.test.ts +1 -1
- package/plugins/design/dev-server/test/runtime-bundle.test.ts +1 -1
- package/plugins/design/dev-server/test/shared-doc-convergence.test.ts +1 -1
- package/plugins/design/dev-server/test/shared-doc-migrate.test.ts +2 -3
- package/plugins/design/dev-server/test/shared-doc-projection.test.ts +1 -1
- package/plugins/design/dev-server/test/snap-distance-pill.test.ts +1 -1
- package/plugins/design/dev-server/test/sync-agent.test.ts +2 -3
- package/plugins/design/dev-server/test/sync-atomic-write.test.ts +2 -3
- package/plugins/design/dev-server/test/sync-codec.test.ts +1 -1
- package/plugins/design/dev-server/test/sync-connection-state.test.ts +1 -1
- package/plugins/design/dev-server/test/sync-echo-guard.test.ts +1 -1
- package/plugins/design/dev-server/test/sync-fs-mirror.test.ts +1 -2
- package/plugins/design/dev-server/test/sync-hardening.test.ts +4 -5
- package/plugins/design/dev-server/test/sync-hubs-config.test.ts +1 -2
- package/plugins/design/dev-server/test/sync-meta-codec.test.ts +1 -1
- package/plugins/design/dev-server/test/sync-runtime.test.ts +37 -14
- package/plugins/design/dev-server/test/sync-status.test.ts +1 -1
- package/plugins/design/dev-server/test/sync-untrusted.test.ts +1 -2
- package/plugins/design/dev-server/test/undo-stack.test.ts +2 -2
- package/plugins/design/dev-server/test/use-agent-presence.test.tsx +117 -0
- package/plugins/design/dev-server/test/use-artboard-drag.test.ts +3 -3
- package/plugins/design/dev-server/test/use-canvas-activity.test.tsx +206 -0
- package/plugins/design/dev-server/test/use-selection-set.test.tsx +1 -1
- package/plugins/design/dev-server/test/use-snap-guides.test.ts +1 -1
- package/plugins/design/dev-server/test/use-undo-stack.test.tsx +2 -2
- package/plugins/design/dev-server/use-agent-presence.tsx +244 -0
- package/plugins/design/dev-server/use-annotation-resize.tsx +1 -5
- package/plugins/design/dev-server/use-annotation-selection.tsx +2 -6
- package/plugins/design/dev-server/use-annotations-visibility.tsx +1 -1
- package/plugins/design/dev-server/use-artboard-drag.tsx +1 -1
- package/plugins/design/dev-server/use-canvas-activity.tsx +252 -0
- package/plugins/design/dev-server/use-collab.tsx +3 -4
- package/plugins/design/dev-server/use-selection-set.tsx +1 -1
- package/plugins/design/dev-server/use-tool-mode.tsx +1 -1
- package/plugins/design/dev-server/use-undo-stack.tsx +4 -5
- package/plugins/design/dev-server/ws.ts +21 -2
- package/plugins/design/templates/_shell.html +108 -3
- package/plugins/design/templates/design-system-inspiration/SUB-AGENT-PROMPTS.md +18 -3
|
@@ -27,9 +27,12 @@
|
|
|
27
27
|
*/
|
|
28
28
|
|
|
29
29
|
import {
|
|
30
|
+
Component,
|
|
30
31
|
type ComponentType,
|
|
31
|
-
type ReactNode,
|
|
32
32
|
createElement,
|
|
33
|
+
Fragment,
|
|
34
|
+
type ReactNode,
|
|
35
|
+
useCallback,
|
|
33
36
|
useEffect,
|
|
34
37
|
useMemo,
|
|
35
38
|
useRef,
|
|
@@ -347,6 +350,27 @@ export interface MountCanvasOptions {
|
|
|
347
350
|
commentsEnabled: boolean;
|
|
348
351
|
}
|
|
349
352
|
|
|
353
|
+
// The lite provider tree wrapping a canvas component (tool + selection +
|
|
354
|
+
// comment layer). Pulled out so both the live render and the error-fallback
|
|
355
|
+
// render build the identical envelope.
|
|
356
|
+
//
|
|
357
|
+
// NB: the CanvasActivityProvider (Phase 13 / DDR-029) is NOT mounted here — it
|
|
358
|
+
// lives inside `DesignCanvas` (canvas-lib). comment-mount.js and canvas-lib are
|
|
359
|
+
// SEPARATE bundles, so a context provided here would be a different instance
|
|
360
|
+
// from the one DCArtboard (canvas-lib) consumes. Same reasoning the real
|
|
361
|
+
// ToolProvider lives in DesignCanvas, not in this layer's MaybeToolProvider.
|
|
362
|
+
function buildCanvasTree(Canvas: ComponentType, file: string | undefined): ReactNode {
|
|
363
|
+
return createElement(
|
|
364
|
+
MaybeToolProvider,
|
|
365
|
+
null,
|
|
366
|
+
createElement(
|
|
367
|
+
MaybeSelectionSetProvider,
|
|
368
|
+
null,
|
|
369
|
+
createElement(CommentHost, { file }, createElement(Canvas))
|
|
370
|
+
)
|
|
371
|
+
);
|
|
372
|
+
}
|
|
373
|
+
|
|
350
374
|
export function mountCanvas(Canvas: ComponentType, opts: MountCanvasOptions): void {
|
|
351
375
|
const root = createRoot(opts.rootEl);
|
|
352
376
|
if (!opts.commentsEnabled) {
|
|
@@ -354,15 +378,146 @@ export function mountCanvas(Canvas: ComponentType, opts: MountCanvasOptions): vo
|
|
|
354
378
|
return;
|
|
355
379
|
}
|
|
356
380
|
const file = opts.file ?? deriveFile();
|
|
357
|
-
root.render(
|
|
381
|
+
root.render(createElement(CanvasHmrRuntime, { initialCanvas: Canvas, file }));
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
385
|
+
// Phase 13.1 / DDR-077 — HMR error resilience during agent editing.
|
|
386
|
+
//
|
|
387
|
+
// When an agent (`/design:edit` / `/design:new`) live-edits a canvas, a
|
|
388
|
+
// half-saved file (missing import, undefined symbol, transpile error) used to
|
|
389
|
+
// blank the canvas to white: the shell did `location.reload()` straight into the
|
|
390
|
+
// broken module. The shell now soft-reloads (import-before-swap, see
|
|
391
|
+
// `templates/_shell.html`) so a build/import error never tears down the good
|
|
392
|
+
// render. This runtime closes the remaining gap — a *render-time* throw — by
|
|
393
|
+
// keeping the last good canvas mounted via an error boundary and surfacing a
|
|
394
|
+
// "holding last good" toast instead of a white screen. Strictly gated by the
|
|
395
|
+
// shell on agent-active; manual edits keep the plain reload (so this is inert
|
|
396
|
+
// for solo hand-editing). The runtime exposes its swap/hold API on
|
|
397
|
+
// `window.__maudeCanvasRuntime` (the same window-handshake style the shell
|
|
398
|
+
// already uses for `__canvas_rel__` etc.).
|
|
399
|
+
|
|
400
|
+
export interface CanvasRuntimeApi {
|
|
401
|
+
/** Swap in a freshly-imported canvas module's default export (success path). */
|
|
402
|
+
remount: (next: ComponentType) => void;
|
|
403
|
+
/** Show/hide the "holding last good" toast (build-error path from the shell). */
|
|
404
|
+
setHolding: (on: boolean, message?: string) => void;
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
const RUNTIME_KEY = '__maudeCanvasRuntime';
|
|
408
|
+
|
|
409
|
+
/**
|
|
410
|
+
* Fires `onOk` only when its subtree COMMITS — i.e. renders without throwing. A
|
|
411
|
+
* render-time throw in the canvas unwinds to the boundary before this commits,
|
|
412
|
+
* so `onOk` never runs and `lastGood` is not advanced to a broken module.
|
|
413
|
+
*/
|
|
414
|
+
function OkSignal({
|
|
415
|
+
Canvas,
|
|
416
|
+
file,
|
|
417
|
+
onOk,
|
|
418
|
+
}: {
|
|
419
|
+
Canvas: ComponentType;
|
|
420
|
+
file: string | undefined;
|
|
421
|
+
onOk: () => void;
|
|
422
|
+
}) {
|
|
423
|
+
// biome-ignore lint/correctness/useExhaustiveDependencies: fire once per mount (key=attempt remounts this).
|
|
424
|
+
useEffect(() => {
|
|
425
|
+
onOk();
|
|
426
|
+
}, []);
|
|
427
|
+
return buildCanvasTree(Canvas, file);
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
export class CanvasErrorBoundary extends Component<
|
|
431
|
+
{
|
|
432
|
+
attempt: number;
|
|
433
|
+
onError: () => void;
|
|
434
|
+
fallback: () => ReactNode;
|
|
435
|
+
children: ReactNode;
|
|
436
|
+
},
|
|
437
|
+
{ hasError: boolean }
|
|
438
|
+
> {
|
|
439
|
+
state = { hasError: false };
|
|
440
|
+
static getDerivedStateFromError(): { hasError: boolean } {
|
|
441
|
+
return { hasError: true };
|
|
442
|
+
}
|
|
443
|
+
componentDidCatch(): void {
|
|
444
|
+
this.props.onError();
|
|
445
|
+
}
|
|
446
|
+
componentDidUpdate(prev: { attempt: number }): void {
|
|
447
|
+
// A new canvas (new attempt) arrived → clear the error and try rendering it.
|
|
448
|
+
if (prev.attempt !== this.props.attempt && this.state.hasError) {
|
|
449
|
+
this.setState({ hasError: false });
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
render(): ReactNode {
|
|
453
|
+
if (this.state.hasError) return this.props.fallback();
|
|
454
|
+
return this.props.children;
|
|
455
|
+
}
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
function HmrHoldingToast({ message }: { message?: string }): ReactNode {
|
|
459
|
+
return createElement(
|
|
460
|
+
'div',
|
|
461
|
+
{
|
|
462
|
+
className: 'dc-hmr-holding',
|
|
463
|
+
role: 'status',
|
|
464
|
+
'aria-live': 'polite',
|
|
465
|
+
title: message ? `Holding last working render — ${message}` : 'Holding last working render',
|
|
466
|
+
},
|
|
467
|
+
'⏸ build error — držím poslední funkční verzi'
|
|
468
|
+
);
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
function CanvasHmrRuntime({
|
|
472
|
+
initialCanvas,
|
|
473
|
+
file,
|
|
474
|
+
}: {
|
|
475
|
+
initialCanvas: ComponentType;
|
|
476
|
+
file: string | undefined;
|
|
477
|
+
}): ReactNode {
|
|
478
|
+
const [{ canvas, attempt }, setCanvasState] = useState({ canvas: initialCanvas, attempt: 0 });
|
|
479
|
+
const [holding, setHoldingState] = useState<{ on: boolean; message?: string }>({ on: false });
|
|
480
|
+
const lastGood = useRef<ComponentType | null>(null);
|
|
481
|
+
const canvasRef = useRef(canvas);
|
|
482
|
+
canvasRef.current = canvas;
|
|
483
|
+
|
|
484
|
+
// Publish the runtime API for the shell HMR client.
|
|
485
|
+
useEffect(() => {
|
|
486
|
+
const api: CanvasRuntimeApi = {
|
|
487
|
+
remount: (next) => setCanvasState((s) => ({ canvas: next, attempt: s.attempt + 1 })),
|
|
488
|
+
setHolding: (on, message) => setHoldingState(on ? { on: true, message } : { on: false }),
|
|
489
|
+
};
|
|
490
|
+
(window as unknown as Record<string, unknown>)[RUNTIME_KEY] = api;
|
|
491
|
+
return () => {
|
|
492
|
+
(window as unknown as Record<string, unknown>)[RUNTIME_KEY] = undefined;
|
|
493
|
+
};
|
|
494
|
+
}, []);
|
|
495
|
+
|
|
496
|
+
const handleOk = useCallback(() => {
|
|
497
|
+
lastGood.current = canvasRef.current;
|
|
498
|
+
// The new canvas rendered clean → drop any holding state.
|
|
499
|
+
setHoldingState((h) => (h.on ? { on: false } : h));
|
|
500
|
+
}, []);
|
|
501
|
+
|
|
502
|
+
const handleError = useCallback(() => {
|
|
503
|
+
setHoldingState({ on: true, message: 'render error' });
|
|
504
|
+
}, []);
|
|
505
|
+
|
|
506
|
+
const fallback = useCallback((): ReactNode => {
|
|
507
|
+
const LG = lastGood.current;
|
|
508
|
+
return LG ? buildCanvasTree(LG, file) : null;
|
|
509
|
+
}, [file]);
|
|
510
|
+
|
|
511
|
+
return createElement(
|
|
512
|
+
Fragment,
|
|
513
|
+
null,
|
|
358
514
|
createElement(
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
)
|
|
515
|
+
CanvasErrorBoundary,
|
|
516
|
+
{ attempt, onError: handleError, fallback },
|
|
517
|
+
// key=attempt → each soft-reload remounts a fresh subtree (and resets the
|
|
518
|
+
// boundary's child), matching the clean-slate semantics of a full reload.
|
|
519
|
+
createElement(OkSignal, { key: attempt, Canvas: canvas, file, onOk: handleOk })
|
|
520
|
+
),
|
|
521
|
+
holding.on ? createElement(HmrHoldingToast, { message: holding.message }) : null
|
|
367
522
|
);
|
|
368
523
|
}
|
|
@@ -168,6 +168,6 @@ export const TOOL_CURSORS: Record<Tool, string> = Object.freeze({
|
|
|
168
168
|
*/
|
|
169
169
|
export function resolveToolCursor(token: unknown): string | null {
|
|
170
170
|
if (typeof token !== 'string' || !/^[a-z-]+$/.test(token)) return null;
|
|
171
|
-
if (!Object.
|
|
171
|
+
if (!Object.hasOwn(TOOL_CURSORS, token)) return null;
|
|
172
172
|
return TOOL_CURSORS[token as Tool];
|
|
173
173
|
}
|
|
@@ -67,14 +67,19 @@
|
|
|
67
67
|
* deprecation log at dev-server boot.
|
|
68
68
|
*/
|
|
69
69
|
|
|
70
|
+
import {
|
|
71
|
+
AnimatePresence as _MotionAnimatePresence,
|
|
72
|
+
motion as _motionImpl,
|
|
73
|
+
useReducedMotion as _useReducedMotion,
|
|
74
|
+
} from 'motion/react';
|
|
70
75
|
import {
|
|
71
76
|
type CSSProperties,
|
|
77
|
+
createContext,
|
|
72
78
|
Fragment,
|
|
79
|
+
isValidElement,
|
|
73
80
|
type ReactNode,
|
|
74
81
|
type PointerEvent as ReactPointerEvent,
|
|
75
82
|
type RefObject,
|
|
76
|
-
createContext,
|
|
77
|
-
isValidElement,
|
|
78
83
|
useCallback,
|
|
79
84
|
useContext,
|
|
80
85
|
useEffect,
|
|
@@ -84,18 +89,19 @@ import {
|
|
|
84
89
|
useState,
|
|
85
90
|
} from 'react';
|
|
86
91
|
|
|
87
|
-
import {
|
|
88
|
-
AnimatePresence as _MotionAnimatePresence,
|
|
89
|
-
motion as _motionImpl,
|
|
90
|
-
useReducedMotion as _useReducedMotion,
|
|
91
|
-
} from 'motion/react';
|
|
92
|
-
|
|
92
|
+
import { ArtboardActivityOverlay } from './artboard-activity-overlay.tsx';
|
|
93
93
|
import { CanvasShell } from './canvas-shell.tsx';
|
|
94
94
|
import {
|
|
95
95
|
buildMoveArtboardsRecord,
|
|
96
96
|
diffLayoutPositions,
|
|
97
97
|
} from './commands/move-artboards-command.ts';
|
|
98
|
+
import { AgentPresenceProvider, useAgentPresence } from './use-agent-presence.tsx';
|
|
98
99
|
import { type DragState, useArtboardDrag } from './use-artboard-drag.tsx';
|
|
100
|
+
import {
|
|
101
|
+
CanvasActivityProvider,
|
|
102
|
+
matchesArtboard,
|
|
103
|
+
useCanvasActivity,
|
|
104
|
+
} from './use-canvas-activity.tsx';
|
|
99
105
|
import { CollabProvider, canvasSlugFromPath } from './use-collab.tsx';
|
|
100
106
|
import { useSelectionSetOptional } from './use-selection-set.tsx';
|
|
101
107
|
import { MaybeToolProvider, useToolModeOptional } from './use-tool-mode.tsx';
|
|
@@ -1192,9 +1198,22 @@ export function DesignCanvas(props: DesignCanvasProps) {
|
|
|
1192
1198
|
</MaybeToolProvider>
|
|
1193
1199
|
);
|
|
1194
1200
|
return (
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1201
|
+
// Phase 13 / DDR-029 — the activity context MUST be provided here (canvas-lib
|
|
1202
|
+
// bundle) so DCArtboard's `useCanvasActivity()` reads the SAME context
|
|
1203
|
+
// instance. Providing it from comment-mount.js (a separate bundle) would
|
|
1204
|
+
// create a second ActivityContext the consumer never sees. `canvasFile` is
|
|
1205
|
+
// normalized to the server's design-root-relative activity key inside the
|
|
1206
|
+
// provider (falls back to window.__canvas_rel__).
|
|
1207
|
+
<CanvasActivityProvider file={canvasFile}>
|
|
1208
|
+
{/* Phase 13.2 / DDR-078 — agent presence. Same canvas-lib-bundle rule as
|
|
1209
|
+
the activity context: provided here so DCArtboard + ParticipantsChrome
|
|
1210
|
+
(both canvas-lib) read one context instance. */}
|
|
1211
|
+
<AgentPresenceProvider file={canvasFile}>
|
|
1212
|
+
<UndoStackProvider canvasFile={canvasFile}>
|
|
1213
|
+
{collabSlug ? <CollabProvider slug={collabSlug}>{inner}</CollabProvider> : inner}
|
|
1214
|
+
</UndoStackProvider>
|
|
1215
|
+
</AgentPresenceProvider>
|
|
1216
|
+
</CanvasActivityProvider>
|
|
1198
1217
|
);
|
|
1199
1218
|
}
|
|
1200
1219
|
DesignCanvas.displayName = 'DesignCanvas';
|
|
@@ -1510,6 +1529,12 @@ export function DCArtboard({
|
|
|
1510
1529
|
const toolMode = useToolModeOptional();
|
|
1511
1530
|
const selSet = useSelectionSetOptional();
|
|
1512
1531
|
const dragBus = useDragStateContext();
|
|
1532
|
+
// Phase 13 / DDR-029 — live "agent works here" overlay. Inert (present=false)
|
|
1533
|
+
// outside CanvasActivityProvider, so specimens / legacy mounts never show it.
|
|
1534
|
+
const activity = useCanvasActivity();
|
|
1535
|
+
// Phase 13.2 / DDR-078 — when an agent is the editor, tint the overlay with
|
|
1536
|
+
// its presence color + show its funny name instead of the generic file label.
|
|
1537
|
+
const agent = useAgentPresence();
|
|
1513
1538
|
const rect = ctx ? ctx.rectFor(id) : null;
|
|
1514
1539
|
|
|
1515
1540
|
// Drag hook — always called (hook rules). Inert outside DesignCanvas
|
|
@@ -1583,19 +1608,40 @@ export function DCArtboard({
|
|
|
1583
1608
|
|
|
1584
1609
|
const handleProps = dragHook.bindHandle();
|
|
1585
1610
|
|
|
1611
|
+
// Phase 13 — overlay when THIS canvas is active and the change scope includes
|
|
1612
|
+
// this artboard (null scope = file-level = every artboard). Rendered as a
|
|
1613
|
+
// world-coord sibling of the <article> so it pans/zooms with the artboard.
|
|
1614
|
+
const showActivity = activity.present && matchesArtboard(activity.artboardIds, id);
|
|
1615
|
+
// Agent-driven → funny name + agent color; manual edit → file label + default hue.
|
|
1616
|
+
const activityLabel = agent
|
|
1617
|
+
? agent.name
|
|
1618
|
+
: activity.artboardIds
|
|
1619
|
+
? `${activity.fileLabel}:${label}`
|
|
1620
|
+
: activity.fileLabel;
|
|
1621
|
+
|
|
1586
1622
|
return (
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
{label}
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
|
|
1623
|
+
<>
|
|
1624
|
+
<article
|
|
1625
|
+
className={`dc-artboard dc-positioned${isInDrag ? ' dc-dragging' : ''}`}
|
|
1626
|
+
data-dc-screen={id}
|
|
1627
|
+
aria-current={isActive ? 'true' : undefined}
|
|
1628
|
+
style={{ left: liveX, top: liveY, width: rect.w, height: rect.h }}
|
|
1629
|
+
{...handleProps}
|
|
1630
|
+
>
|
|
1631
|
+
<button type="button" className="dc-artboard-label sku" aria-label={`Artboard ${label}`}>
|
|
1632
|
+
{label}
|
|
1633
|
+
</button>
|
|
1634
|
+
<div className="dc-artboard-body">{children}</div>
|
|
1635
|
+
</article>
|
|
1636
|
+
{showActivity ? (
|
|
1637
|
+
<ArtboardActivityOverlay
|
|
1638
|
+
rect={{ x: liveX, y: liveY, w: rect.w, h: rect.h }}
|
|
1639
|
+
label={activityLabel}
|
|
1640
|
+
active={activity.active}
|
|
1641
|
+
color={agent?.color}
|
|
1642
|
+
/>
|
|
1643
|
+
) : null}
|
|
1644
|
+
</>
|
|
1599
1645
|
);
|
|
1600
1646
|
}
|
|
1601
1647
|
DCArtboard.displayName = 'DCArtboard';
|
|
@@ -2157,11 +2203,7 @@ export function SpecimenHeader({
|
|
|
2157
2203
|
}
|
|
2158
2204
|
|
|
2159
2205
|
/** `<dl class="specimen-meta">` ladder. */
|
|
2160
|
-
export function SpecimenMeta({
|
|
2161
|
-
entries,
|
|
2162
|
-
}: {
|
|
2163
|
-
entries: Array<{ label: string; value: ReactNode }>;
|
|
2164
|
-
}) {
|
|
2206
|
+
export function SpecimenMeta({ entries }: { entries: Array<{ label: string; value: ReactNode }> }) {
|
|
2165
2207
|
return (
|
|
2166
2208
|
<dl className="specimen-meta">
|
|
2167
2209
|
{entries.map(({ label, value }) => (
|
|
@@ -2180,13 +2222,7 @@ export function KbdHint({ children }: { children: ReactNode }) {
|
|
|
2180
2222
|
}
|
|
2181
2223
|
|
|
2182
2224
|
/** Inline `var(--name)` value visualiser — small chip + token name. */
|
|
2183
|
-
export function TokenChip({
|
|
2184
|
-
name,
|
|
2185
|
-
swatch,
|
|
2186
|
-
}: {
|
|
2187
|
-
name: string;
|
|
2188
|
-
swatch?: boolean;
|
|
2189
|
-
}) {
|
|
2225
|
+
export function TokenChip({ name, swatch }: { name: string; swatch?: boolean }) {
|
|
2190
2226
|
return (
|
|
2191
2227
|
<span className="token-chip" data-token={name}>
|
|
2192
2228
|
{swatch ? (
|
|
@@ -2716,7 +2752,7 @@ export function ReducedMotionToggle() {
|
|
|
2716
2752
|
}
|
|
2717
2753
|
|
|
2718
2754
|
export {
|
|
2755
|
+
_MotionAnimatePresence as AnimatePresence,
|
|
2719
2756
|
_motionImpl as motion,
|
|
2720
2757
|
_useReducedMotion as useReducedMotion,
|
|
2721
|
-
_MotionAnimatePresence as AnimatePresence,
|
|
2722
2758
|
};
|
|
@@ -42,10 +42,10 @@ import { ArtboardMarqueeOverlay } from './artboard-marquee.tsx';
|
|
|
42
42
|
import {
|
|
43
43
|
type ArtboardRect,
|
|
44
44
|
SnapGuideOverlay,
|
|
45
|
-
type ViewportControllerHandle,
|
|
46
45
|
useArtboardsContext,
|
|
47
46
|
useDragStateContext,
|
|
48
47
|
useViewportControllerContext,
|
|
48
|
+
type ViewportControllerHandle,
|
|
49
49
|
} from './canvas-lib.tsx';
|
|
50
50
|
import { type AlignMode, alignLabel, equalSpacingLabel } from './commands/equal-spacing-command.ts';
|
|
51
51
|
import {
|
|
@@ -27,8 +27,8 @@
|
|
|
27
27
|
// originating clientID — the random 32-bit ids make local↔remote collisions
|
|
28
28
|
// negligible.
|
|
29
29
|
|
|
30
|
-
import { applyAwarenessUpdate, encodeAwarenessUpdate } from 'y-protocols/awareness';
|
|
31
30
|
import type { Awareness } from 'y-protocols/awareness';
|
|
31
|
+
import { applyAwarenessUpdate, encodeAwarenessUpdate } from 'y-protocols/awareness';
|
|
32
32
|
|
|
33
33
|
interface AwarenessChange {
|
|
34
34
|
added: number[];
|
|
@@ -7,13 +7,13 @@ import path from 'node:path';
|
|
|
7
7
|
import type { Api } from '../api.ts';
|
|
8
8
|
import type { Context } from '../context.ts';
|
|
9
9
|
|
|
10
|
-
import {
|
|
11
|
-
import { type Registry
|
|
10
|
+
import { createPersistence, Y_TYPES } from './persistence.ts';
|
|
11
|
+
import { createRegistry, type Registry } from './registry.ts';
|
|
12
12
|
|
|
13
|
-
export {
|
|
13
|
+
export type { CollabConn } from './protocol.ts';
|
|
14
14
|
export type { Registry } from './registry.ts';
|
|
15
15
|
export type { Room, RoomConn } from './room.ts';
|
|
16
|
-
export
|
|
16
|
+
export { Y_TYPES };
|
|
17
17
|
|
|
18
18
|
export interface Collab {
|
|
19
19
|
registry: Registry;
|
|
@@ -8,7 +8,7 @@ import * as Y from 'yjs';
|
|
|
8
8
|
|
|
9
9
|
import type { Api } from '../api.ts';
|
|
10
10
|
import type { Context } from '../context.ts';
|
|
11
|
-
import { type RoomCallbacks
|
|
11
|
+
import { ensureStateDir, type RoomCallbacks } from './room.ts';
|
|
12
12
|
|
|
13
13
|
/**
|
|
14
14
|
* Y.Doc shared-type names. Frozen on Task 1 so client + server agree even
|
|
@@ -206,7 +206,8 @@
|
|
|
206
206
|
},
|
|
207
207
|
"syncTsx": {
|
|
208
208
|
"type": "boolean",
|
|
209
|
-
"
|
|
209
|
+
"default": true,
|
|
210
|
+
"description": "DDR-079 (supersedes DDR-072) — project-level TSX sync, ON BY DEFAULT. Omit the field to sync ALL .tsx canvases to this hub (the common case: a linked teammate sees the project's TSX without a hidden opt-in). Set false to opt the whole project OUT. A per-canvas .meta.json \"syncable\": false still excludes one canvas (the sidecar always wins). Inert unless the cross-origin sandbox is active (MAUDE_CANVAS_ORIGIN_SPLIT != 0) — the DDR-060 Lock-2 coupling is preserved. TSX bodies execute, so syncing broadens a WebRTC/self-nav exfil residual to every synced canvas — link only hubs you operate or trust; the dev-server prints a loud boot banner against non-loopback hubs."
|
|
210
211
|
}
|
|
211
212
|
},
|
|
212
213
|
"additionalProperties": false
|