@1agh/maude 0.45.2 → 0.47.0
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/apps/studio/acp/bootstrap-brief.ts +8 -0
- package/apps/studio/acp/bridge.ts +151 -1
- package/apps/studio/annotations-layer.tsx +42 -0
- package/apps/studio/annotations-snap.ts +50 -10
- package/apps/studio/api.ts +760 -15
- package/apps/studio/artboard-guides-overlay.tsx +270 -0
- package/apps/studio/bin/_agent-browser-safe-config.json +1 -0
- package/apps/studio/bin/_agent-browser-safe.mjs +228 -0
- package/apps/studio/bin/_agent-browser-safe.test.mjs +165 -0
- package/apps/studio/bin/_curl-local.mjs +349 -0
- package/apps/studio/bin/_curl-local.test.mjs +280 -0
- package/apps/studio/bin/_pdf-playwright.mjs +35 -4
- package/apps/studio/bin/_png-playwright.mjs +38 -4
- package/apps/studio/bin/_pw-launch.mjs +52 -0
- package/apps/studio/bin/_pw-launch.test.mjs +90 -0
- package/apps/studio/bin/_smart-frames.mjs +419 -0
- package/apps/studio/bin/_smart-frames.test.mjs +140 -0
- package/apps/studio/bin/agent-browser-safe.sh +29 -0
- package/apps/studio/bin/curl-local.sh +28 -0
- package/apps/studio/bin/smart-frames.sh +30 -0
- package/apps/studio/canvas-cursors.ts +6 -0
- package/apps/studio/canvas-edit.ts +972 -6
- package/apps/studio/canvas-icons.tsx +13 -0
- package/apps/studio/canvas-lib.tsx +206 -11
- package/apps/studio/canvas-shell.tsx +809 -50
- package/apps/studio/client/app.jsx +1554 -206
- package/apps/studio/client/panels/ChatPanel.jsx +92 -3
- package/apps/studio/client/panels/SettingsPanel.jsx +211 -0
- package/apps/studio/client/panels/acp-capabilities.js +11 -0
- package/apps/studio/client/styles/3-shell-maude.css +39 -0
- package/apps/studio/client/styles/6-acp-chat.css +41 -0
- package/apps/studio/contextual-toolbar.tsx +5 -3
- package/apps/studio/dist/client.bundle.js +1627 -1627
- package/apps/studio/dist/comment-mount.js +2 -2
- package/apps/studio/dist/styles.css +1 -1
- package/apps/studio/dom-selection.ts +20 -0
- package/apps/studio/export-dialog.tsx +138 -18
- package/apps/studio/exporters/pdf.ts +332 -18
- package/apps/studio/exporters/png.ts +45 -3
- package/apps/studio/footage/schema.ts +17 -1
- package/apps/studio/generation/gemma-models.ts +224 -0
- package/apps/studio/generation/prefs.ts +43 -0
- package/apps/studio/grid-track-handles.ts +179 -0
- package/apps/studio/handoff.ts +35 -0
- package/apps/studio/http.ts +331 -7
- package/apps/studio/input-router.tsx +73 -17
- package/apps/studio/print/marks.ts +113 -0
- package/apps/studio/print/units.ts +269 -0
- package/apps/studio/print-overlay-content.tsx +132 -0
- package/apps/studio/test/acp-mode-banner.test.ts +45 -0
- package/apps/studio/test/acp-session-allowed-tools.test.ts +187 -0
- package/apps/studio/test/annotations-snap.test.ts +56 -0
- package/apps/studio/test/artboard-guides-overlay.test.tsx +152 -0
- package/apps/studio/test/artboard-kinds.test.tsx +83 -0
- package/apps/studio/test/artboard-selection-attrs.test.ts +69 -0
- package/apps/studio/test/browse-posture.test.tsx +107 -0
- package/apps/studio/test/canvas-hide-chrome.test.ts +58 -0
- package/apps/studio/test/canvas-meta-api.test.ts +237 -0
- package/apps/studio/test/canvas-origin-gate.test.ts +4 -0
- package/apps/studio/test/comment-mount.test.ts +2 -1
- package/apps/studio/test/component-map.test.ts +48 -0
- package/apps/studio/test/convert-to-absolute.test.ts +333 -0
- package/apps/studio/test/detach-component.test.ts +94 -0
- package/apps/studio/test/edit-scope-api.test.ts +8 -4
- package/apps/studio/test/element-structural-api.test.ts +74 -0
- package/apps/studio/test/element-structural-edit.test.ts +363 -0
- package/apps/studio/test/exporters/png.test.ts +49 -1
- package/apps/studio/test/grid-track-handles.test.ts +160 -0
- package/apps/studio/test/handoff.test.ts +48 -0
- package/apps/studio/test/input-router.test.ts +82 -8
- package/apps/studio/test/layers-synthetic-groups.test.ts +96 -0
- package/apps/studio/test/pdf-print-boxes.test.ts +326 -0
- package/apps/studio/test/print-marks.test.ts +113 -0
- package/apps/studio/test/print-units.test.ts +173 -0
- package/apps/studio/test/use-snap-guides.test.ts +81 -0
- package/apps/studio/test/use-tool-mode.test.tsx +10 -2
- package/apps/studio/tool-palette.tsx +3 -1
- package/apps/studio/use-canvas-media-drop.tsx +126 -0
- package/apps/studio/use-chrome-visibility.tsx +19 -0
- package/apps/studio/use-element-resize.tsx +24 -3
- package/apps/studio/use-grid-track-handles.tsx +364 -0
- package/apps/studio/use-keyboard-discipline.tsx +15 -0
- package/apps/studio/use-snap-guides.tsx +73 -5
- package/apps/studio/use-spacing-handles.tsx +9 -5
- package/apps/studio/use-tool-mode.tsx +30 -3
- package/apps/studio/web-overlay-content.tsx +52 -0
- package/apps/studio/whats-new.json +55 -0
- package/cli/commands/design.mjs +25 -1
- package/package.json +8 -8
- package/plugins/design/dependencies.json +35 -0
- package/plugins/design/templates/_shell.html +4 -0
|
@@ -39,6 +39,18 @@ export function IconMove(props: IconProps) {
|
|
|
39
39
|
</Svg>
|
|
40
40
|
);
|
|
41
41
|
}
|
|
42
|
+
// feature-4 (browse/move split) — Browse tool. A pointing-hand ("tap") cursor:
|
|
43
|
+
// the universal "the mock is alive, click it" glyph, deliberately distinct from
|
|
44
|
+
// Move's solid selection arrow.
|
|
45
|
+
export function IconBrowse(props: IconProps) {
|
|
46
|
+
return (
|
|
47
|
+
<Svg {...props}>
|
|
48
|
+
<path d="M10 9V5a1.4 1.4 0 012.8 0v6" />
|
|
49
|
+
<path d="M12.8 10.4V9.6a1.3 1.3 0 012.6 0V12" />
|
|
50
|
+
<path d="M15.4 12.2v-1a1.3 1.3 0 012.6 0V15c0 2.6-1.7 5-5 5-2 0-3.3-.8-4.4-2.2L6 13.4a1.4 1.4 0 012.2-1.7L10 13.6V9" />
|
|
51
|
+
</Svg>
|
|
52
|
+
);
|
|
53
|
+
}
|
|
42
54
|
|
|
43
55
|
export function IconHand(props: IconProps) {
|
|
44
56
|
return (
|
|
@@ -463,6 +475,7 @@ export function IconHighlighter(props: IconProps) {
|
|
|
463
475
|
}
|
|
464
476
|
|
|
465
477
|
export const TOOL_ICONS: Record<string, (p: IconProps) => JSX.Element> = {
|
|
478
|
+
browse: IconBrowse,
|
|
466
479
|
move: IconMove,
|
|
467
480
|
hand: IconHand,
|
|
468
481
|
comment: IconComment,
|
|
@@ -101,7 +101,23 @@ import {
|
|
|
101
101
|
} from 'react';
|
|
102
102
|
|
|
103
103
|
import { ArtboardActivityOverlay } from './artboard-activity-overlay.tsx';
|
|
104
|
+
import {
|
|
105
|
+
ArtboardGuidesOverlay,
|
|
106
|
+
type GuideDefinitions,
|
|
107
|
+
type OverlayVisibility,
|
|
108
|
+
} from './artboard-guides-overlay.tsx';
|
|
104
109
|
import { CanvasShell } from './canvas-shell.tsx';
|
|
110
|
+
import type { ArtboardPrintProp } from './print/units.ts';
|
|
111
|
+
// feature-2-print-artboards T3 — side-effect import: registers the print
|
|
112
|
+
// kind's overlay content (bleed/trim/margin) into artboard-guides-overlay's
|
|
113
|
+
// registry at module load, per that file's own "call registerKindOverlay at
|
|
114
|
+
// module load" contract. Must live in the same module graph every canvas
|
|
115
|
+
// bundle already pulls in (canvas-lib IS that shared graph — DDR-025), so a
|
|
116
|
+
// canvas never renders without the registration having run first.
|
|
117
|
+
import './print-overlay-content.tsx';
|
|
118
|
+
// feature-3-web-artboards T2 — same side-effect-import contract as the print
|
|
119
|
+
// registration above, for the 'web' kind's breakpoint-band chip.
|
|
120
|
+
import './web-overlay-content.tsx';
|
|
105
121
|
import {
|
|
106
122
|
buildMoveArtboardsRecord,
|
|
107
123
|
diffLayoutPositions,
|
|
@@ -299,6 +315,21 @@ const ENGINE_CSS = `
|
|
|
299
315
|
color: var(--fg-1, #4a3f30);
|
|
300
316
|
font-family: var(--font-mono, ui-monospace, SFMono-Regular, Menlo, monospace);
|
|
301
317
|
}
|
|
318
|
+
/* T3 — per-kind chrome. Subtle tint on the header + a small glyph before the
|
|
319
|
+
label text, for any non-digital kind. digital (the default, and every
|
|
320
|
+
unmigrated canvas) renders no chip and no tint — byte-identical chrome. */
|
|
321
|
+
.dc-canvas .dc-artboard[data-dc-kind]:not([data-dc-kind='digital']) .dc-artboard-label {
|
|
322
|
+
background: color-mix(in oklab, var(--accent, var(--fg-2, #4a3f30)) 10%, var(--bg-2, #e8e3d8));
|
|
323
|
+
}
|
|
324
|
+
.dc-canvas .dc-artboard-kind-chip {
|
|
325
|
+
display: inline-flex;
|
|
326
|
+
align-items: center;
|
|
327
|
+
justify-content: center;
|
|
328
|
+
margin-right: 6px;
|
|
329
|
+
color: var(--accent, var(--fg-1, #4a3f30));
|
|
330
|
+
opacity: 0.85;
|
|
331
|
+
vertical-align: -1px;
|
|
332
|
+
}
|
|
302
333
|
.dc-canvas .dc-artboard-body {
|
|
303
334
|
flex: 1;
|
|
304
335
|
position: relative;
|
|
@@ -379,12 +410,25 @@ function ensureEngineStyles(): void {
|
|
|
379
410
|
// world-coord positioning) and by DCSection (which collapses inside the
|
|
380
411
|
// canvas) and by future T3 components (MiniMap, ZoomToolbar).
|
|
381
412
|
|
|
413
|
+
/**
|
|
414
|
+
* What an artboard IS — digital screen / print page / web flow / video comp.
|
|
415
|
+
* Absent JSX prop resolves to `digital` (DDR-027-consistent: JSX is truth,
|
|
416
|
+
* no meta PATCH lane). Drives chrome (T3), the guides overlay content
|
|
417
|
+
* registry (T4), and generation/editing rules downstream (feature-2-print,
|
|
418
|
+
* feature-3-web).
|
|
419
|
+
*/
|
|
420
|
+
export type ArtboardKind = 'digital' | 'print' | 'web' | 'video';
|
|
421
|
+
|
|
382
422
|
export interface ArtboardRect {
|
|
383
423
|
id: string;
|
|
384
424
|
x: number;
|
|
385
425
|
y: number;
|
|
386
426
|
w: number;
|
|
387
427
|
h: number;
|
|
428
|
+
/** Resolved kind (explicit `kind` prop, or `video` fallback via
|
|
429
|
+
* `subtreeHasVideoComp`, or `digital`) — JSX-authoritative, recomputed
|
|
430
|
+
* from `harvestArtboards` every render; never persisted to meta. */
|
|
431
|
+
kind: ArtboardKind;
|
|
388
432
|
}
|
|
389
433
|
|
|
390
434
|
export interface ViewportState {
|
|
@@ -445,8 +489,11 @@ interface ArtboardSeed {
|
|
|
445
489
|
id: string;
|
|
446
490
|
w: number;
|
|
447
491
|
h: number;
|
|
492
|
+
kind: ArtboardKind;
|
|
448
493
|
}
|
|
449
494
|
|
|
495
|
+
const ARTBOARD_KINDS: ReadonlySet<string> = new Set(['digital', 'print', 'web', 'video']);
|
|
496
|
+
|
|
450
497
|
/**
|
|
451
498
|
* Walk a children subtree harvesting DCArtboard descriptors in render order.
|
|
452
499
|
* DCSection (and any other wrapper) is traversed but doesn't appear in the
|
|
@@ -469,11 +516,22 @@ function harvestArtboards(children: ReactNode): ArtboardSeed[] {
|
|
|
469
516
|
(typeof type === 'function' &&
|
|
470
517
|
(type as { displayName?: string }).displayName === 'DCArtboard');
|
|
471
518
|
if (isArtboard) {
|
|
472
|
-
const props = node.props as {
|
|
519
|
+
const props = node.props as {
|
|
520
|
+
id?: string;
|
|
521
|
+
width?: number;
|
|
522
|
+
height?: number;
|
|
523
|
+
kind?: string;
|
|
524
|
+
children?: ReactNode;
|
|
525
|
+
};
|
|
526
|
+
const explicitKind =
|
|
527
|
+
typeof props.kind === 'string' && ARTBOARD_KINDS.has(props.kind)
|
|
528
|
+
? (props.kind as ArtboardKind)
|
|
529
|
+
: undefined;
|
|
473
530
|
out.push({
|
|
474
531
|
id: typeof props.id === 'string' && props.id.length > 0 ? props.id : `__ab_${auto}`,
|
|
475
532
|
w: typeof props.width === 'number' ? props.width : VP_GRID.w,
|
|
476
533
|
h: typeof props.height === 'number' ? props.height : VP_GRID.h,
|
|
534
|
+
kind: explicitKind ?? (subtreeHasVideoComp(props.children) ? 'video' : 'digital'),
|
|
477
535
|
});
|
|
478
536
|
auto++;
|
|
479
537
|
return;
|
|
@@ -529,6 +587,7 @@ function synthDefaultGrid(seeds: ArtboardSeed[]): ArtboardRect[] {
|
|
|
529
587
|
y: row * (cellH + VP_GRID.gutter),
|
|
530
588
|
w: seed.w,
|
|
531
589
|
h: seed.h,
|
|
590
|
+
kind: seed.kind,
|
|
532
591
|
};
|
|
533
592
|
});
|
|
534
593
|
}
|
|
@@ -565,6 +624,9 @@ function readCanvasMeta():
|
|
|
565
624
|
| {
|
|
566
625
|
layout?: { artboards?: ArtboardRect[] };
|
|
567
626
|
viewport?: ViewportState;
|
|
627
|
+
/** T6 — per-user overlay-visibility bag, GET-merged in from view.json
|
|
628
|
+
* server-side (never present in the versioned `.meta.json` itself). */
|
|
629
|
+
overlays?: OverlayVisibility;
|
|
568
630
|
}
|
|
569
631
|
| undefined {
|
|
570
632
|
if (typeof window === 'undefined') return undefined;
|
|
@@ -572,6 +634,7 @@ function readCanvasMeta():
|
|
|
572
634
|
__canvas_meta__?: {
|
|
573
635
|
layout?: { artboards?: ArtboardRect[] };
|
|
574
636
|
viewport?: ViewportState;
|
|
637
|
+
overlays?: OverlayVisibility;
|
|
575
638
|
};
|
|
576
639
|
};
|
|
577
640
|
return w.__canvas_meta__;
|
|
@@ -1487,6 +1550,21 @@ function DesignCanvasInner({ children, controls }: DesignCanvasProps) {
|
|
|
1487
1550
|
const hostRef = useRef<HTMLDivElement | null>(null);
|
|
1488
1551
|
const worldRef = useRef<HTMLDivElement | null>(null);
|
|
1489
1552
|
|
|
1553
|
+
// T6 — self-seed the (per-canvas, persisted) guides visibility into the
|
|
1554
|
+
// shared ChromeVisibilityContext once at mount, from the SAME
|
|
1555
|
+
// window.__canvas_meta__ snapshot the viewport/layout reads above use.
|
|
1556
|
+
// Unlike minimap/zoom/present (global shell prefs pushed in via postMessage
|
|
1557
|
+
// shortly after load), `guides` has no global default to race — it's
|
|
1558
|
+
// read directly out of this canvas's own meta, so there's nothing to wait
|
|
1559
|
+
// for. The shell's View-menu toggle then live-updates it through the same
|
|
1560
|
+
// `dgn:'view-chrome'` channel as the other three flags.
|
|
1561
|
+
// T6 — the per-canvas overlay-visibility self-seed used to live here, but
|
|
1562
|
+
// this component renders CanvasShell as its CHILD and the
|
|
1563
|
+
// ChromeVisibilityProvider mounts INSIDE CanvasShell — so this component's
|
|
1564
|
+
// own useChromeVisibility() was always null and the seed silently never
|
|
1565
|
+
// ran (dead code since the foundation feature). The working seed now lives
|
|
1566
|
+
// in canvas-shell.tsx's CanvasRouter, which sits inside the provider.
|
|
1567
|
+
|
|
1490
1568
|
const seeds = useMemo(() => harvestArtboards(children), [children]);
|
|
1491
1569
|
|
|
1492
1570
|
// Merge JSX-derived defaults with meta-persisted positions. Per DDR-027,
|
|
@@ -1511,6 +1589,10 @@ function DesignCanvasInner({ children, controls }: DesignCanvasProps) {
|
|
|
1511
1589
|
y: Number.isFinite(m.y) ? m.y : d.y,
|
|
1512
1590
|
w: typeof m.w === 'number' && m.w > 0 ? m.w : d.w,
|
|
1513
1591
|
h: typeof m.h === 'number' && m.h > 0 ? m.h : d.h,
|
|
1592
|
+
// kind is JSX-authoritative like w/h (DDR-027) but, unlike w/h, was
|
|
1593
|
+
// never part of the legacy persisted layout shape — always the fresh
|
|
1594
|
+
// seed value, no meta fallback to tolerate.
|
|
1595
|
+
kind: d.kind,
|
|
1514
1596
|
};
|
|
1515
1597
|
});
|
|
1516
1598
|
}, [seeds]);
|
|
@@ -1803,6 +1885,57 @@ export function DCSection({
|
|
|
1803
1885
|
}
|
|
1804
1886
|
DCSection.displayName = 'DCSection';
|
|
1805
1887
|
|
|
1888
|
+
/**
|
|
1889
|
+
* Small monochrome glyph shown in the SKU-strip header for a non-`digital`
|
|
1890
|
+
* artboard (T3). Mirrors the corner video-badge's stroke style (viewBox 16,
|
|
1891
|
+
* `currentColor`, ~1.2px stroke) for chrome consistency. `video` reuses that
|
|
1892
|
+
* exact badge glyph.
|
|
1893
|
+
*/
|
|
1894
|
+
function ArtboardKindIcon({ kind }: { kind: ArtboardKind }) {
|
|
1895
|
+
if (kind === 'print') {
|
|
1896
|
+
return (
|
|
1897
|
+
<svg viewBox="0 0 16 16" width="10" height="10" fill="none" aria-hidden="true">
|
|
1898
|
+
<rect
|
|
1899
|
+
x="3"
|
|
1900
|
+
y="1.5"
|
|
1901
|
+
width="10"
|
|
1902
|
+
height="5"
|
|
1903
|
+
rx="0.5"
|
|
1904
|
+
stroke="currentColor"
|
|
1905
|
+
strokeWidth="1.2"
|
|
1906
|
+
/>
|
|
1907
|
+
<rect x="1.5" y="6" width="13" height="6" rx="1" stroke="currentColor" strokeWidth="1.2" />
|
|
1908
|
+
<rect x="4.5" y="10.5" width="7" height="4" stroke="currentColor" strokeWidth="1.1" />
|
|
1909
|
+
</svg>
|
|
1910
|
+
);
|
|
1911
|
+
}
|
|
1912
|
+
if (kind === 'web') {
|
|
1913
|
+
return (
|
|
1914
|
+
<svg viewBox="0 0 16 16" width="10" height="10" fill="none" aria-hidden="true">
|
|
1915
|
+
<circle cx="8" cy="8" r="6" stroke="currentColor" strokeWidth="1.2" />
|
|
1916
|
+
<path
|
|
1917
|
+
d="M2 8h12M8 2c2 2 2 10 0 12M8 2c-2 2-2 10 0 12"
|
|
1918
|
+
stroke="currentColor"
|
|
1919
|
+
strokeWidth="1.1"
|
|
1920
|
+
/>
|
|
1921
|
+
</svg>
|
|
1922
|
+
);
|
|
1923
|
+
}
|
|
1924
|
+
// video — same glyph as the corner Timeline badge.
|
|
1925
|
+
return (
|
|
1926
|
+
<svg viewBox="0 0 16 16" width="10" height="10" fill="none" aria-hidden="true">
|
|
1927
|
+
<rect x="1.5" y="4.5" width="8" height="7" rx="1.2" stroke="currentColor" strokeWidth="1.3" />
|
|
1928
|
+
<path
|
|
1929
|
+
d="M9.5 7l4-2.3v6.6l-4-2.3"
|
|
1930
|
+
stroke="currentColor"
|
|
1931
|
+
strokeWidth="1.3"
|
|
1932
|
+
strokeLinejoin="round"
|
|
1933
|
+
/>
|
|
1934
|
+
</svg>
|
|
1935
|
+
);
|
|
1936
|
+
}
|
|
1937
|
+
ArtboardKindIcon.displayName = 'ArtboardKindIcon';
|
|
1938
|
+
|
|
1806
1939
|
/**
|
|
1807
1940
|
* Bordered artboard with a SKU-strip header. Inside DesignCanvas its world
|
|
1808
1941
|
* position comes from meta.layout (or the synthesized default grid); the
|
|
@@ -1820,6 +1953,9 @@ export function DCArtboard({
|
|
|
1820
1953
|
padding,
|
|
1821
1954
|
layout,
|
|
1822
1955
|
gap,
|
|
1956
|
+
kind,
|
|
1957
|
+
guides,
|
|
1958
|
+
print,
|
|
1823
1959
|
children,
|
|
1824
1960
|
}: {
|
|
1825
1961
|
id: string;
|
|
@@ -1833,17 +1969,33 @@ export function DCArtboard({
|
|
|
1833
1969
|
fixed?: boolean;
|
|
1834
1970
|
/** `.dc-artboard-body` background (CSS color/token, e.g. "var(--bg-1)"). */
|
|
1835
1971
|
background?: string;
|
|
1836
|
-
/** `.dc-artboard-body` padding
|
|
1837
|
-
|
|
1972
|
+
/** `.dc-artboard-body` padding — px number, or a `var(--token)` string
|
|
1973
|
+
* (space-token binding from the Inspector's artboard panel). */
|
|
1974
|
+
padding?: number | string;
|
|
1838
1975
|
/** `.dc-artboard-body` layout mode. Default = the engine's plain block flow. */
|
|
1839
1976
|
layout?: 'block' | 'flex-col' | 'flex-row' | 'grid';
|
|
1840
|
-
/** `.dc-artboard-body` gap
|
|
1841
|
-
|
|
1977
|
+
/** `.dc-artboard-body` gap — px number or `var(--token)` string; only
|
|
1978
|
+
* visible under flex-col/flex-row/grid. */
|
|
1979
|
+
gap?: number | string;
|
|
1980
|
+
/** What this artboard IS — digital screen / print page / web flow / video
|
|
1981
|
+
* comp. Absent ⇒ `digital` (or `video` when the subtree contains a
|
|
1982
|
+
* `<VideoComp>`, for unmigrated canvases — see `subtreeHasVideoComp`).
|
|
1983
|
+
* An explicit prop always supersedes that structural fallback. */
|
|
1984
|
+
kind?: ArtboardKind;
|
|
1985
|
+
/** Generic layout guides (T5) — Figma-vocabulary columns/rows/grid,
|
|
1986
|
+
* versioned design intent. Kind-agnostic: any artboard can carry these
|
|
1987
|
+
* regardless of `kind`. Visibility is per-user (T6), not this prop. */
|
|
1988
|
+
guides?: GuideDefinitions;
|
|
1989
|
+
/** feature-2-print-artboards T2 — paper/orientation/bleed/margins intent.
|
|
1990
|
+
* Only meaningful when `kind="print"`; the overlay (T3) reads it to draw
|
|
1991
|
+
* bleed/trim/margin guides against THIS artboard's own resolved px size. */
|
|
1992
|
+
print?: ArtboardPrintProp;
|
|
1842
1993
|
children: ReactNode;
|
|
1843
1994
|
}) {
|
|
1844
1995
|
const ctx = useWorldContext();
|
|
1845
1996
|
const _controller = useViewportControllerContext();
|
|
1846
1997
|
const toolMode = useToolModeOptional();
|
|
1998
|
+
const chrome = useChromeVisibility();
|
|
1847
1999
|
const selSet = useSelectionSetOptional();
|
|
1848
2000
|
const dragBus = useDragStateContext();
|
|
1849
2001
|
// Phase 13 / DDR-029 — live "agent works here" overlay. Inert (present=false)
|
|
@@ -1853,10 +2005,15 @@ export function DCArtboard({
|
|
|
1853
2005
|
// its presence color + show its funny name instead of the generic file label.
|
|
1854
2006
|
const agent = useAgentPresence();
|
|
1855
2007
|
const rect = ctx ? ctx.rectFor(id) : null;
|
|
2008
|
+
// T1/T2 — explicit `kind` wins; `subtreeHasVideoComp` is the fallback that
|
|
2009
|
+
// keeps existing unmigrated video canvases badged identically without
|
|
2010
|
+
// requiring a JSX edit (Design Decision 1).
|
|
2011
|
+
const hasVideoContent = useMemo(() => subtreeHasVideoComp(children), [children]);
|
|
2012
|
+
const resolvedKind: ArtboardKind = kind ?? (hasVideoContent ? 'video' : 'digital');
|
|
1856
2013
|
// DDR-148 — badge video artboards in the header; clicking the badge opens
|
|
1857
2014
|
// the timeline panel via the same postMessage the context-menu "Open
|
|
1858
2015
|
// Timeline" entry already sends (canvas-shell.tsx artboardHasVideo/handler).
|
|
1859
|
-
const hasVideo =
|
|
2016
|
+
const hasVideo = resolvedKind === 'video';
|
|
1860
2017
|
const openTimeline = useCallback(
|
|
1861
2018
|
(e: ReactMouseEvent<HTMLButtonElement>) => {
|
|
1862
2019
|
e.stopPropagation();
|
|
@@ -1921,8 +2078,9 @@ export function DCArtboard({
|
|
|
1921
2078
|
const bodyStyle = useMemo<CSSProperties>(() => {
|
|
1922
2079
|
const st: CSSProperties = {};
|
|
1923
2080
|
if (background) st.background = background;
|
|
1924
|
-
|
|
1925
|
-
if (typeof
|
|
2081
|
+
// number → px; string → a var(--token) binding (validated server-side).
|
|
2082
|
+
if (typeof padding === 'number' || typeof padding === 'string') st.padding = padding;
|
|
2083
|
+
if (typeof gap === 'number' || typeof gap === 'string') st.gap = gap;
|
|
1926
2084
|
if (layout === 'flex-col') {
|
|
1927
2085
|
st.display = 'flex';
|
|
1928
2086
|
st.flexDirection = 'column';
|
|
@@ -1943,9 +2101,20 @@ export function DCArtboard({
|
|
|
1943
2101
|
const readBackAttrs = {
|
|
1944
2102
|
'data-dc-fixed': fixed ? 'true' : undefined,
|
|
1945
2103
|
'data-dc-bg': background,
|
|
1946
|
-
'data-dc-padding':
|
|
2104
|
+
'data-dc-padding': padding != null ? String(padding) : undefined,
|
|
1947
2105
|
'data-dc-layout': layout,
|
|
1948
|
-
'data-dc-gap':
|
|
2106
|
+
'data-dc-gap': gap != null ? String(gap) : undefined,
|
|
2107
|
+
// Always present (unlike the optional-override props above) — this is a
|
|
2108
|
+
// resolved classification, not a "no override" style knob. Chrome, the
|
|
2109
|
+
// Inspector kind picker (T8), and canvas-shell's artboardHasVideo gate
|
|
2110
|
+
// (T2) all key off this attribute.
|
|
2111
|
+
'data-dc-kind': resolvedKind,
|
|
2112
|
+
// feature-2-print-artboards T2 — read-back for the Inspector's print
|
|
2113
|
+
// picker (paper/orientation/bleed pre-fill), same "stamp the resolved
|
|
2114
|
+
// prop as JSON, parse it back" shape `guides` would need if it grew an
|
|
2115
|
+
// Inspector editor. Small object (≤ ~150 bytes), so a plain JSON attr is
|
|
2116
|
+
// simpler than adding parallel data-dc-print-* scalar attrs per field.
|
|
2117
|
+
'data-dc-print': print ? JSON.stringify(print) : undefined,
|
|
1949
2118
|
};
|
|
1950
2119
|
|
|
1951
2120
|
if (!ctx || !rect) {
|
|
@@ -2037,7 +2206,22 @@ export function DCArtboard({
|
|
|
2037
2206
|
}}
|
|
2038
2207
|
{...handleProps}
|
|
2039
2208
|
>
|
|
2040
|
-
<button
|
|
2209
|
+
<button
|
|
2210
|
+
type="button"
|
|
2211
|
+
className="dc-artboard-label sku"
|
|
2212
|
+
// a11y-auditor (T3 review) — the kind chip is aria-hidden (decorative,
|
|
2213
|
+
// redundant with the Inspector's Kind picker), so a non-digital kind
|
|
2214
|
+
// must still reach the artboard's own accessible name or it's
|
|
2215
|
+
// invisible to AT users entirely.
|
|
2216
|
+
aria-label={
|
|
2217
|
+
resolvedKind !== 'digital' ? `Artboard ${label}, ${resolvedKind}` : `Artboard ${label}`
|
|
2218
|
+
}
|
|
2219
|
+
>
|
|
2220
|
+
{resolvedKind !== 'digital' ? (
|
|
2221
|
+
<span className="dc-artboard-kind-chip" aria-hidden="true">
|
|
2222
|
+
<ArtboardKindIcon kind={resolvedKind} />
|
|
2223
|
+
</span>
|
|
2224
|
+
) : null}
|
|
2041
2225
|
{label}
|
|
2042
2226
|
</button>
|
|
2043
2227
|
{hasVideo ? (
|
|
@@ -2079,6 +2263,17 @@ export function DCArtboard({
|
|
|
2079
2263
|
color={agent?.color}
|
|
2080
2264
|
/>
|
|
2081
2265
|
) : null}
|
|
2266
|
+
{/* T4 — world-coord sibling, same reasoning as ArtboardActivityOverlay
|
|
2267
|
+
above: must stay OUTSIDE `.dc-artboard`'s contain:paint/
|
|
2268
|
+
content-visibility subtree so guides are never culled/frozen with
|
|
2269
|
+
exported content (they're never exported at all). */}
|
|
2270
|
+
<ArtboardGuidesOverlay
|
|
2271
|
+
rect={{ x: liveX, y: liveY, w: rect.w, h: rect.h }}
|
|
2272
|
+
kind={resolvedKind}
|
|
2273
|
+
guides={guides}
|
|
2274
|
+
print={print}
|
|
2275
|
+
visibility={{ guides: chrome?.guides ?? false, print: chrome?.print ?? false }}
|
|
2276
|
+
/>
|
|
2082
2277
|
</>
|
|
2083
2278
|
);
|
|
2084
2279
|
}
|